From python-checkins at python.org Wed Apr 1 03:21:29 2015 From: python-checkins at python.org (benjamin.peterson) Date: Wed, 01 Apr 2015 01:21:29 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E4=29=3A_document_what_?= =?utf-8?q?exactly_str=2Esplitlines=28=29_splits_on_=28closes_=2312855=29?= Message-ID: <20150401012128.2053.77937@psf.io> https://hg.python.org/cpython/rev/6244a5dbaf84 changeset: 95337:6244a5dbaf84 branch: 3.4 parent: 95327:5c5eb374e296 user: Benjamin Peterson date: Tue Mar 31 21:20:36 2015 -0400 summary: document what exactly str.splitlines() splits on (closes #12855) Patch by Martin Panter. files: Doc/library/stdtypes.rst | 40 +++++++++++++++++++++++++-- 1 files changed, 36 insertions(+), 4 deletions(-) diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst --- a/Doc/library/stdtypes.rst +++ b/Doc/library/stdtypes.rst @@ -1855,10 +1855,42 @@ .. method:: str.splitlines([keepends]) - Return a list of the lines in the string, breaking at line boundaries. - This method uses the :term:`universal newlines` approach to splitting lines. - Line breaks are not included in the resulting list unless *keepends* is - given and true. + Return a list of the lines in the string, breaking at line boundaries. Line + breaks are not included in the resulting list unless *keepends* is given and + true. + + This method splits on the following line boundaries. In particular, the + boundaries are a superset of :term:`universal newlines`. + + +-----------------------+-----------------------------+ + | Representation | Description | + +=======================+=============================+ + | ``\n`` | Line Feed | + +-----------------------+-----------------------------+ + | ``\r`` | Carriage Return | + +-----------------------+-----------------------------+ + | ``\r\n`` | Carriage Return + Line Feed | + +-----------------------+-----------------------------+ + | ``\v`` or ``\x0b`` | Line Tabulation | + +-----------------------+-----------------------------+ + | ``\f`` or ``\x0c`` | Form Feed | + +-----------------------+-----------------------------+ + | ``\x1c`` | File Separator | + +-----------------------+-----------------------------+ + | ``\x1d`` | Group Separator | + +-----------------------+-----------------------------+ + | ``\x1e`` | Record Separator | + +-----------------------+-----------------------------+ + | ``\x85`` | Next Line (C1 Control Code) | + +-----------------------+-----------------------------+ + | ``\u2028`` | Line Separator | + +-----------------------+-----------------------------+ + | ``\u2029`` | Paragraph Separator | + +-----------------------+-----------------------------+ + + .. versionchanged:: 3.2 + + ``\v`` and ``\f`` added to list of line boundaries. For example:: -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Apr 1 03:21:36 2015 From: python-checkins at python.org (benjamin.peterson) Date: Wed, 01 Apr 2015 01:21:36 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?b?KTogbWVyZ2UgMy40ICgjMTI4NTUp?= Message-ID: <20150401012129.91344.29886@psf.io> https://hg.python.org/cpython/rev/87af6deb5d26 changeset: 95338:87af6deb5d26 parent: 95336:7ed567ad8b4c parent: 95337:6244a5dbaf84 user: Benjamin Peterson date: Tue Mar 31 21:21:09 2015 -0400 summary: merge 3.4 (#12855) files: Doc/library/stdtypes.rst | 40 +++++++++++++++++++++++++-- 1 files changed, 36 insertions(+), 4 deletions(-) diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst --- a/Doc/library/stdtypes.rst +++ b/Doc/library/stdtypes.rst @@ -1855,10 +1855,42 @@ .. method:: str.splitlines([keepends]) - Return a list of the lines in the string, breaking at line boundaries. - This method uses the :term:`universal newlines` approach to splitting lines. - Line breaks are not included in the resulting list unless *keepends* is - given and true. + Return a list of the lines in the string, breaking at line boundaries. Line + breaks are not included in the resulting list unless *keepends* is given and + true. + + This method splits on the following line boundaries. In particular, the + boundaries are a superset of :term:`universal newlines`. + + +-----------------------+-----------------------------+ + | Representation | Description | + +=======================+=============================+ + | ``\n`` | Line Feed | + +-----------------------+-----------------------------+ + | ``\r`` | Carriage Return | + +-----------------------+-----------------------------+ + | ``\r\n`` | Carriage Return + Line Feed | + +-----------------------+-----------------------------+ + | ``\v`` or ``\x0b`` | Line Tabulation | + +-----------------------+-----------------------------+ + | ``\f`` or ``\x0c`` | Form Feed | + +-----------------------+-----------------------------+ + | ``\x1c`` | File Separator | + +-----------------------+-----------------------------+ + | ``\x1d`` | Group Separator | + +-----------------------+-----------------------------+ + | ``\x1e`` | Record Separator | + +-----------------------+-----------------------------+ + | ``\x85`` | Next Line (C1 Control Code) | + +-----------------------+-----------------------------+ + | ``\u2028`` | Line Separator | + +-----------------------+-----------------------------+ + | ``\u2029`` | Paragraph Separator | + +-----------------------+-----------------------------+ + + .. versionchanged:: 3.2 + + ``\v`` and ``\f`` added to list of line boundaries. For example:: -- Repository URL: https://hg.python.org/cpython From solipsis at pitrou.net Wed Apr 1 10:40:37 2015 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Wed, 01 Apr 2015 08:40:37 +0000 Subject: [Python-checkins] Daily reference leaks (87af6deb5d26): sum=141 Message-ID: <20150401084037.2599.52581@psf.io> results for 87af6deb5d26 on branch "default" -------------------------------------------- test_deque leaked [37, 37, 37] references, sum=111 test_deque leaked [9, 9, 9] memory blocks, sum=27 test_functools leaked [0, 0, 3] memory blocks, sum=3 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogHAvN6_', '--timeout', '7200'] From python-checkins at python.org Wed Apr 1 11:10:37 2015 From: python-checkins at python.org (victor.stinner) Date: Wed, 01 Apr 2015 09:10:37 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2323618=3A_Fix_EINT?= =?utf-8?q?R_handling_on_Windows?= Message-ID: <20150401091035.95096.66129@psf.io> https://hg.python.org/cpython/rev/8ec4acfdb851 changeset: 95339:8ec4acfdb851 user: Victor Stinner date: Wed Apr 01 11:09:43 2015 +0200 summary: Issue #23618: Fix EINTR handling on Windows Windows uses WSAEINTR error code, not EINTR, for socket functions. files: Modules/socketmodule.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -2476,7 +2476,7 @@ } err = GET_ERROR; - if (err == EINTR && PyErr_CheckSignals()) + if (CHECK_ERRNO(EINTR) && PyErr_CheckSignals()) return -1; wait_connect = (s->sock_timeout > 0 && err == IN_PROGRESS_ERR @@ -2488,7 +2488,7 @@ if (timeout == -1) { /* select() failed */ err = GET_ERROR; - if (err == EINTR && PyErr_CheckSignals()) + if (CHECK_ERRNO(EINTR) && PyErr_CheckSignals()) return -1; return err; } -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Apr 1 12:07:23 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Wed, 01 Apr 2015 10:07:23 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzIzNzk5?= =?utf-8?q?=3A_Added_test=2Esupport=2Estart=5Fthreads=28=29_for_running_an?= =?utf-8?q?d_cleaning_up?= Message-ID: <20150401100719.65755.92485@psf.io> https://hg.python.org/cpython/rev/8987218adc99 changeset: 95341:8987218adc99 branch: 3.4 parent: 95337:6244a5dbaf84 user: Serhiy Storchaka date: Wed Apr 01 13:01:14 2015 +0300 summary: Issue #23799: Added test.support.start_threads() for running and cleaning up multiple threads. files: Lib/test/support/__init__.py | 39 ++++++++++++++++++- Lib/test/test_bz2.py | 6 +- Lib/test/test_capi.py | 14 ++---- Lib/test/test_gc.py | 12 +---- Lib/test/test_io.py | 30 ++++--------- Lib/test/test_threaded_import.py | 10 ++-- Lib/test/test_threadedtempfile.py | 32 +++----------- Lib/test/test_threading_local.py | 11 +--- Misc/NEWS | 3 + 9 files changed, 77 insertions(+), 80 deletions(-) diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py --- a/Lib/test/support/__init__.py +++ b/Lib/test/support/__init__.py @@ -6,6 +6,7 @@ import collections.abc import contextlib import errno +import faulthandler import fnmatch import functools import gc @@ -96,7 +97,7 @@ # logging "TestHandler", # threads - "threading_setup", "threading_cleanup", + "threading_setup", "threading_cleanup", "reap_threads", "start_threads", # miscellaneous "check_warnings", "EnvironmentVarGuard", "run_with_locale", "swap_item", "swap_attr", "Matcher", "set_memlimit", "SuppressCrashReport", "sortdict", @@ -1941,6 +1942,42 @@ break @contextlib.contextmanager +def start_threads(threads, unlock=None): + threads = list(threads) + started = [] + try: + try: + for t in threads: + t.start() + started.append(t) + except: + if verbose: + print("Can't start %d threads, only %d threads started" % + (len(threads), len(started))) + raise + yield + finally: + try: + if unlock: + unlock() + endtime = starttime = time.time() + for timeout in range(1, 16): + endtime += 60 + for t in started: + t.join(max(endtime - time.time(), 0.01)) + started = [t for t in started if t.isAlive()] + if not started: + break + if verbose: + print('Unable to join %d threads during a period of ' + '%d minutes' % (len(started), timeout)) + finally: + started = [t for t in started if t.isAlive()] + if started: + faulthandler.dump_traceback(sys.stdout) + raise AssertionError('Unable to join %d threads' % len(started)) + + at contextlib.contextmanager def swap_attr(obj, attr, new_val): """Temporary swap out an attribute with a new object. diff --git a/Lib/test/test_bz2.py b/Lib/test/test_bz2.py --- a/Lib/test/test_bz2.py +++ b/Lib/test/test_bz2.py @@ -493,10 +493,8 @@ for i in range(5): f.write(data) threads = [threading.Thread(target=comp) for i in range(nthreads)] - for t in threads: - t.start() - for t in threads: - t.join() + with support.start_threads(threads): + pass def testWithoutThreading(self): module = support.import_fresh_module("bz2", blocked=("threading",)) 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 @@ -202,15 +202,11 @@ context.lock = threading.Lock() context.event = threading.Event() - for i in range(context.nThreads): - t = threading.Thread(target=self.pendingcalls_thread, args = (context,)) - t.start() - threads.append(t) - - self.pendingcalls_wait(context.l, n, context) - - for t in threads: - t.join() + threads = [threading.Thread(target=self.pendingcalls_thread, + args=(context,)) + for i in range(context.nThreads)] + with support.start_threads(threads): + self.pendingcalls_wait(context.l, n, context) def pendingcalls_thread(self, context): try: 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 @@ -1,6 +1,6 @@ import unittest from test.support import (verbose, refcount_test, run_unittest, - strip_python_stderr, cpython_only) + strip_python_stderr, cpython_only, start_threads) from test.script_helper import assert_python_ok, make_script, temp_dir import sys @@ -397,19 +397,13 @@ old_switchinterval = sys.getswitchinterval() sys.setswitchinterval(1e-5) try: - exit = False + exit = [] threads = [] for i in range(N_THREADS): t = threading.Thread(target=run_thread) threads.append(t) - try: - for t in threads: - t.start() - finally: + with start_threads(threads, lambda: exit.append(1)): time.sleep(1.0) - exit = True - for t in threads: - t.join() finally: sys.setswitchinterval(old_switchinterval) gc.collect() diff --git a/Lib/test/test_io.py b/Lib/test/test_io.py --- a/Lib/test/test_io.py +++ b/Lib/test/test_io.py @@ -1070,11 +1070,8 @@ errors.append(e) raise threads = [threading.Thread(target=f) for x in range(20)] - for t in threads: - t.start() - time.sleep(0.02) # yield - for t in threads: - t.join() + with support.start_threads(threads): + time.sleep(0.02) # yield self.assertFalse(errors, "the following exceptions were caught: %r" % errors) s = b''.join(results) @@ -1393,11 +1390,8 @@ errors.append(e) raise threads = [threading.Thread(target=f) for x in range(20)] - for t in threads: - t.start() - time.sleep(0.02) # yield - for t in threads: - t.join() + with support.start_threads(threads): + time.sleep(0.02) # yield self.assertFalse(errors, "the following exceptions were caught: %r" % errors) bufio.close() @@ -2691,14 +2685,10 @@ text = "Thread%03d\n" % n event.wait() f.write(text) - threads = [threading.Thread(target=lambda n=x: run(n)) + threads = [threading.Thread(target=run, args=(x,)) for x in range(20)] - for t in threads: - t.start() - time.sleep(0.02) - event.set() - for t in threads: - t.join() + with support.start_threads(threads, event.set): + time.sleep(0.02) with self.open(support.TESTFN) as f: content = f.read() for n in range(20): @@ -3402,11 +3392,11 @@ # handlers, which in this case will invoke alarm_interrupt(). signal.alarm(1) try: - self.assertRaises(ZeroDivisionError, - wio.write, item * (support.PIPE_MAX_SIZE // len(item) + 1)) + with self.assertRaises(ZeroDivisionError): + wio.write(item * (support.PIPE_MAX_SIZE // len(item) + 1)) finally: signal.alarm(0) - t.join() + t.join() # We got one byte, get another one and check that it isn't a # repeat of the first one. read_results.append(os.read(r, 1)) 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 @@ -14,7 +14,7 @@ import unittest from test.support import ( verbose, import_module, run_unittest, TESTFN, reap_threads, - forget, unlink, rmtree) + forget, unlink, rmtree, start_threads) threading = import_module('threading') def task(N, done, done_tasks, errors): @@ -115,10 +115,10 @@ errors = [] done_tasks = [] done.clear() - for i in range(N): - t = threading.Thread(target=task, - args=(N, done, done_tasks, errors,)) - t.start() + with start_threads(threading.Thread(target=task, + args=(N, done, done_tasks, errors,)) + for i in range(N)): + pass self.assertTrue(done.wait(60)) self.assertFalse(errors) if verbose: diff --git a/Lib/test/test_threadedtempfile.py b/Lib/test/test_threadedtempfile.py --- a/Lib/test/test_threadedtempfile.py +++ b/Lib/test/test_threadedtempfile.py @@ -18,7 +18,7 @@ import tempfile -from test.support import threading_setup, threading_cleanup, run_unittest, import_module +from test.support import start_threads, import_module threading = import_module('threading') import unittest import io @@ -46,33 +46,17 @@ class ThreadedTempFileTest(unittest.TestCase): def test_main(self): - threads = [] - thread_info = threading_setup() - - for i in range(NUM_THREADS): - t = TempFileGreedy() - threads.append(t) - t.start() - - startEvent.set() - - ok = 0 - errors = [] - for t in threads: - t.join() - ok += t.ok_count - if t.error_count: - errors.append(str(t.name) + str(t.errors.getvalue())) - - threading_cleanup(*thread_info) + threads = [TempFileGreedy() for i in range(NUM_THREADS)] + with start_threads(threads, startEvent.set): + pass + ok = sum(t.ok_count for t in threads) + errors = [str(t.name) + str(t.errors.getvalue()) + for t in threads if t.error_count] msg = "Errors: errors %d ok %d\n%s" % (len(errors), ok, '\n'.join(errors)) self.assertEqual(errors, [], msg) self.assertEqual(ok, NUM_THREADS * FILES_PER_THREAD) -def test_main(): - run_unittest(ThreadedTempFileTest) - if __name__ == "__main__": - test_main() + unittest.main() diff --git a/Lib/test/test_threading_local.py b/Lib/test/test_threading_local.py --- a/Lib/test/test_threading_local.py +++ b/Lib/test/test_threading_local.py @@ -64,14 +64,9 @@ # Simply check that the variable is correctly set self.assertEqual(local.x, i) - threads= [] - for i in range(10): - t = threading.Thread(target=f, args=(i,)) - t.start() - threads.append(t) - - for t in threads: - t.join() + with support.start_threads(threading.Thread(target=f, args=(i,)) + for i in range(10)): + pass def test_derived_cycle_dealloc(self): # http://bugs.python.org/issue6990 diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -137,6 +137,9 @@ Tests ----- +- Issue #23799: Added test.support.start_threads() for running and + cleaning up multiple threads. + - Issue #22390: test.regrtest now emits a warning if temporary files or directories are left after running a test. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Apr 1 12:07:23 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Wed, 01 Apr 2015 10:07:23 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzIzNzk5?= =?utf-8?q?=3A_Added_test=2Etest=5Fsupport=2Estart=5Fthreads=28=29_for_run?= =?utf-8?q?ning_and?= Message-ID: <20150401100719.91346.77884@psf.io> https://hg.python.org/cpython/rev/f8358f6e50e7 changeset: 95340:f8358f6e50e7 branch: 2.7 parent: 95311:051cf1aa6288 user: Serhiy Storchaka date: Wed Apr 01 12:56:39 2015 +0300 summary: Issue #23799: Added test.test_support.start_threads() for running and cleaning up multiple threads. files: Lib/test/test_bz2.py | 12 ++--- Lib/test/test_capi.py | 32 +++++++--------- Lib/test/test_gc.py | 12 +---- Lib/test/test_io.py | 32 ++++++---------- Lib/test/test_support.py | 35 ++++++++++++++++++- Lib/test/test_threadedtempfile.py | 27 +++---------- Lib/test/test_threading_local.py | 19 +++------ Misc/NEWS | 3 + 8 files changed, 85 insertions(+), 87 deletions(-) diff --git a/Lib/test/test_bz2.py b/Lib/test/test_bz2.py --- a/Lib/test/test_bz2.py +++ b/Lib/test/test_bz2.py @@ -1,4 +1,4 @@ -from test import test_support +from test import test_support as support from test.test_support import TESTFN, _4G, bigmemtest, import_module, findfile import unittest @@ -306,10 +306,8 @@ for i in range(5): f.write(data) threads = [threading.Thread(target=comp) for i in range(nthreads)] - for t in threads: - t.start() - for t in threads: - t.join() + with support.start_threads(threads): + pass def testMixedIterationReads(self): # Issue #8397: mixed iteration and reads should be forbidden. @@ -482,13 +480,13 @@ self.assertEqual(text.strip("a"), "") def test_main(): - test_support.run_unittest( + support.run_unittest( BZ2FileTest, BZ2CompressorTest, BZ2DecompressorTest, FuncTest ) - test_support.reap_children() + support.reap_children() if __name__ == '__main__': test_main() 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 @@ -6,7 +6,7 @@ import time import random import unittest -from test import test_support +from test import test_support as support try: import thread import threading @@ -14,7 +14,7 @@ thread = None threading = None # Skip this test if the _testcapi module isn't available. -_testcapi = test_support.import_module('_testcapi') +_testcapi = support.import_module('_testcapi') @unittest.skipUnless(threading, 'Threading required for this test.') @@ -42,7 +42,7 @@ #this busy loop is where we expect to be interrupted to #run our callbacks. Note that callbacks are only run on the #main thread - if False and test_support.verbose: + if False and support.verbose: print "(%i)"%(len(l),), for i in xrange(1000): a = i*i @@ -51,7 +51,7 @@ count += 1 self.assertTrue(count < 10000, "timeout waiting for %i callbacks, got %i"%(n, len(l))) - if False and test_support.verbose: + if False and support.verbose: print "(%i)"%(len(l),) def test_pendingcalls_threaded(self): @@ -67,15 +67,11 @@ context.lock = threading.Lock() context.event = threading.Event() - for i in range(context.nThreads): - t = threading.Thread(target=self.pendingcalls_thread, args = (context,)) - t.start() - threads.append(t) - - self.pendingcalls_wait(context.l, n, context) - - for t in threads: - t.join() + threads = [threading.Thread(target=self.pendingcalls_thread, + args=(context,)) + for i in range(context.nThreads)] + with support.start_threads(threads): + self.pendingcalls_wait(context.l, n, context) def pendingcalls_thread(self, context): try: @@ -84,7 +80,7 @@ with context.lock: context.nFinished += 1 nFinished = context.nFinished - if False and test_support.verbose: + if False and support.verbose: print "finished threads: ", nFinished if nFinished == context.nThreads: context.event.set() @@ -103,7 +99,7 @@ @unittest.skipUnless(threading and thread, 'Threading required for this test.') class TestThreadState(unittest.TestCase): - @test_support.reap_threads + @support.reap_threads def test_thread_state(self): # some extra thread-state tests driven via _testcapi def target(): @@ -129,14 +125,14 @@ for name in dir(_testcapi): if name.startswith('test_'): test = getattr(_testcapi, name) - if test_support.verbose: + if support.verbose: print "internal", name try: test() except _testcapi.error: - raise test_support.TestFailed, sys.exc_info()[1] + raise support.TestFailed, sys.exc_info()[1] - test_support.run_unittest(TestPendingCalls, TestThreadState) + support.run_unittest(TestPendingCalls, TestThreadState) if __name__ == "__main__": test_main() 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 @@ -1,5 +1,5 @@ import unittest -from test.test_support import verbose, run_unittest +from test.test_support import verbose, run_unittest, start_threads import sys import time import gc @@ -352,19 +352,13 @@ old_checkinterval = sys.getcheckinterval() sys.setcheckinterval(3) try: - exit = False + exit = [] threads = [] for i in range(N_THREADS): t = threading.Thread(target=run_thread) threads.append(t) - try: - for t in threads: - t.start() - finally: + with start_threads(threads, lambda: exit.append(1)): time.sleep(1.0) - exit = True - for t in threads: - t.join() finally: sys.setcheckinterval(old_checkinterval) gc.collect() diff --git a/Lib/test/test_io.py b/Lib/test/test_io.py --- a/Lib/test/test_io.py +++ b/Lib/test/test_io.py @@ -985,11 +985,8 @@ errors.append(e) raise threads = [threading.Thread(target=f) for x in range(20)] - for t in threads: - t.start() - time.sleep(0.02) # yield - for t in threads: - t.join() + with support.start_threads(threads): + time.sleep(0.02) # yield self.assertFalse(errors, "the following exceptions were caught: %r" % errors) s = b''.join(results) @@ -1299,11 +1296,8 @@ errors.append(e) raise threads = [threading.Thread(target=f) for x in range(20)] - for t in threads: - t.start() - time.sleep(0.02) # yield - for t in threads: - t.join() + with support.start_threads(threads): + time.sleep(0.02) # yield self.assertFalse(errors, "the following exceptions were caught: %r" % errors) bufio.close() @@ -2555,14 +2549,10 @@ text = "Thread%03d\n" % n event.wait() f.write(text) - threads = [threading.Thread(target=lambda n=x: run(n)) + threads = [threading.Thread(target=run, args=(x,)) for x in range(20)] - for t in threads: - t.start() - time.sleep(0.02) - event.set() - for t in threads: - t.join() + with support.start_threads(threads, event.set): + time.sleep(0.02) with self.open(support.TESTFN) as f: content = f.read() for n in range(20): @@ -3042,9 +3032,11 @@ # return with a successful (partial) result rather than an EINTR. # The buffered IO layer must check for pending signal # handlers, which in this case will invoke alarm_interrupt(). - self.assertRaises(ZeroDivisionError, - wio.write, item * (support.PIPE_MAX_SIZE // len(item) + 1)) - t.join() + try: + with self.assertRaises(ZeroDivisionError): + wio.write(item * (support.PIPE_MAX_SIZE // len(item) + 1)) + finally: + t.join() # We got one byte, get another one and check that it isn't a # repeat of the first one. read_results.append(os.read(r, 1)) 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 @@ -37,7 +37,7 @@ "captured_stdout", "TransientResource", "transient_internet", "run_with_locale", "set_memlimit", "bigmemtest", "bigaddrspacetest", "BasicTestRunner", "run_unittest", "run_doctest", "threading_setup", - "threading_cleanup", "reap_children", "cpython_only", + "threading_cleanup", "reap_threads", "start_threads", "cpython_only", "check_impl_detail", "get_attribute", "py3k_bytes", "import_fresh_module", "threading_cleanup", "reap_children", "strip_python_stderr", "IPV6_ENABLED"] @@ -1509,6 +1509,39 @@ break @contextlib.contextmanager +def start_threads(threads, unlock=None): + threads = list(threads) + started = [] + try: + try: + for t in threads: + t.start() + started.append(t) + except: + if verbose: + print("Can't start %d threads, only %d threads started" % + (len(threads), len(started))) + raise + yield + finally: + if unlock: + unlock() + endtime = starttime = time.time() + for timeout in range(1, 16): + endtime += 60 + for t in started: + t.join(max(endtime - time.time(), 0.01)) + started = [t for t in started if t.isAlive()] + if not started: + break + if verbose: + print('Unable to join %d threads during a period of ' + '%d minutes' % (len(started), timeout)) + started = [t for t in started if t.isAlive()] + if started: + raise AssertionError('Unable to join %d threads' % len(started)) + + at contextlib.contextmanager def swap_attr(obj, attr, new_val): """Temporary swap out an attribute with a new object. diff --git a/Lib/test/test_threadedtempfile.py b/Lib/test/test_threadedtempfile.py --- a/Lib/test/test_threadedtempfile.py +++ b/Lib/test/test_threadedtempfile.py @@ -18,7 +18,7 @@ import tempfile -from test.test_support import threading_setup, threading_cleanup, run_unittest, import_module +from test.test_support import start_threads, run_unittest, import_module threading = import_module('threading') import unittest import StringIO @@ -46,25 +46,12 @@ class ThreadedTempFileTest(unittest.TestCase): def test_main(self): - threads = [] - thread_info = threading_setup() - - for i in range(NUM_THREADS): - t = TempFileGreedy() - threads.append(t) - t.start() - - startEvent.set() - - ok = 0 - errors = [] - for t in threads: - t.join() - ok += t.ok_count - if t.error_count: - errors.append(str(t.getName()) + str(t.errors.getvalue())) - - threading_cleanup(*thread_info) + threads = [TempFileGreedy() for i in range(NUM_THREADS)] + with start_threads(threads, startEvent.set): + pass + ok = sum(t.ok_count for t in threads) + errors = [str(t.getName()) + str(t.errors.getvalue()) + for t in threads if t.error_count] msg = "Errors: errors %d ok %d\n%s" % (len(errors), ok, '\n'.join(errors)) diff --git a/Lib/test/test_threading_local.py b/Lib/test/test_threading_local.py --- a/Lib/test/test_threading_local.py +++ b/Lib/test/test_threading_local.py @@ -1,12 +1,12 @@ import unittest from doctest import DocTestSuite -from test import test_support +from test import test_support as support import weakref import gc # Modules under test -_thread = test_support.import_module('thread') -threading = test_support.import_module('threading') +_thread = support.import_module('thread') +threading = support.import_module('threading') import _threading_local @@ -63,14 +63,9 @@ # Simply check that the variable is correctly set self.assertEqual(local.x, i) - threads= [] - for i in range(10): - t = threading.Thread(target=f, args=(i,)) - t.start() - threads.append(t) - - for t in threads: - t.join() + with support.start_threads(threading.Thread(target=f, args=(i,)) + for i in range(10)): + pass def test_derived_cycle_dealloc(self): # http://bugs.python.org/issue6990 @@ -228,7 +223,7 @@ setUp=setUp, tearDown=tearDown) ) - test_support.run_unittest(suite) + support.run_unittest(suite) if __name__ == '__main__': test_main() diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -182,6 +182,9 @@ Tests ----- +- Issue #23799: Added test.test_support.start_threads() for running and + cleaning up multiple threads. + - Issue #22390: test.regrtest now emits a warning if temporary files or directories are left after running a test. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Apr 1 12:07:30 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Wed, 01 Apr 2015 10:07:30 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2323799=3A_Added_test=2Esupport=2Estart=5Fthreads?= =?utf-8?q?=28=29_for_running_and_cleaning_up?= Message-ID: <20150401100720.1897.87551@psf.io> https://hg.python.org/cpython/rev/a2df4baa112b changeset: 95342:a2df4baa112b parent: 95339:8ec4acfdb851 parent: 95341:8987218adc99 user: Serhiy Storchaka date: Wed Apr 01 13:06:18 2015 +0300 summary: Issue #23799: Added test.support.start_threads() for running and cleaning up multiple threads. files: Lib/test/support/__init__.py | 39 ++++++++++++++++++- Lib/test/test_bz2.py | 6 +- Lib/test/test_capi.py | 14 ++---- Lib/test/test_gc.py | 12 +---- Lib/test/test_io.py | 26 +++-------- Lib/test/test_threaded_import.py | 10 ++-- Lib/test/test_threadedtempfile.py | 32 +++----------- Lib/test/test_threading_local.py | 11 +--- Misc/NEWS | 3 + 9 files changed, 75 insertions(+), 78 deletions(-) diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py --- a/Lib/test/support/__init__.py +++ b/Lib/test/support/__init__.py @@ -6,6 +6,7 @@ import collections.abc import contextlib import errno +import faulthandler import fnmatch import functools import gc @@ -96,7 +97,7 @@ # logging "TestHandler", # threads - "threading_setup", "threading_cleanup", + "threading_setup", "threading_cleanup", "reap_threads", "start_threads", # miscellaneous "check_warnings", "EnvironmentVarGuard", "run_with_locale", "swap_item", "swap_attr", "Matcher", "set_memlimit", "SuppressCrashReport", "sortdict", @@ -1942,6 +1943,42 @@ break @contextlib.contextmanager +def start_threads(threads, unlock=None): + threads = list(threads) + started = [] + try: + try: + for t in threads: + t.start() + started.append(t) + except: + if verbose: + print("Can't start %d threads, only %d threads started" % + (len(threads), len(started))) + raise + yield + finally: + try: + if unlock: + unlock() + endtime = starttime = time.time() + for timeout in range(1, 16): + endtime += 60 + for t in started: + t.join(max(endtime - time.time(), 0.01)) + started = [t for t in started if t.isAlive()] + if not started: + break + if verbose: + print('Unable to join %d threads during a period of ' + '%d minutes' % (len(started), timeout)) + finally: + started = [t for t in started if t.isAlive()] + if started: + faulthandler.dump_traceback(sys.stdout) + raise AssertionError('Unable to join %d threads' % len(started)) + + at contextlib.contextmanager def swap_attr(obj, attr, new_val): """Temporary swap out an attribute with a new object. diff --git a/Lib/test/test_bz2.py b/Lib/test/test_bz2.py --- a/Lib/test/test_bz2.py +++ b/Lib/test/test_bz2.py @@ -507,10 +507,8 @@ for i in range(5): f.write(data) threads = [threading.Thread(target=comp) for i in range(nthreads)] - for t in threads: - t.start() - for t in threads: - t.join() + with support.start_threads(threads): + pass def testWithoutThreading(self): module = support.import_fresh_module("bz2", blocked=("threading",)) 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 @@ -284,15 +284,11 @@ context.lock = threading.Lock() context.event = threading.Event() - for i in range(context.nThreads): - t = threading.Thread(target=self.pendingcalls_thread, args = (context,)) - t.start() - threads.append(t) - - self.pendingcalls_wait(context.l, n, context) - - for t in threads: - t.join() + threads = [threading.Thread(target=self.pendingcalls_thread, + args=(context,)) + for i in range(context.nThreads)] + with support.start_threads(threads): + self.pendingcalls_wait(context.l, n, context) def pendingcalls_thread(self, context): try: 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 @@ -1,6 +1,6 @@ import unittest from test.support import (verbose, refcount_test, run_unittest, - strip_python_stderr, cpython_only) + strip_python_stderr, cpython_only, start_threads) from test.script_helper import assert_python_ok, make_script, temp_dir import sys @@ -397,19 +397,13 @@ old_switchinterval = sys.getswitchinterval() sys.setswitchinterval(1e-5) try: - exit = False + exit = [] threads = [] for i in range(N_THREADS): t = threading.Thread(target=run_thread) threads.append(t) - try: - for t in threads: - t.start() - finally: + with start_threads(threads, lambda: exit.append(1)): time.sleep(1.0) - exit = True - for t in threads: - t.join() finally: sys.setswitchinterval(old_switchinterval) gc.collect() diff --git a/Lib/test/test_io.py b/Lib/test/test_io.py --- a/Lib/test/test_io.py +++ b/Lib/test/test_io.py @@ -1131,11 +1131,8 @@ errors.append(e) raise threads = [threading.Thread(target=f) for x in range(20)] - for t in threads: - t.start() - time.sleep(0.02) # yield - for t in threads: - t.join() + with support.start_threads(threads): + time.sleep(0.02) # yield self.assertFalse(errors, "the following exceptions were caught: %r" % errors) s = b''.join(results) @@ -1454,11 +1451,8 @@ errors.append(e) raise threads = [threading.Thread(target=f) for x in range(20)] - for t in threads: - t.start() - time.sleep(0.02) # yield - for t in threads: - t.join() + with support.start_threads(threads): + time.sleep(0.02) # yield self.assertFalse(errors, "the following exceptions were caught: %r" % errors) bufio.close() @@ -2752,14 +2746,10 @@ text = "Thread%03d\n" % n event.wait() f.write(text) - threads = [threading.Thread(target=lambda n=x: run(n)) + threads = [threading.Thread(target=run, args=(x,)) for x in range(20)] - for t in threads: - t.start() - time.sleep(0.02) - event.set() - for t in threads: - t.join() + with support.start_threads(threads, event.set): + time.sleep(0.02) with self.open(support.TESTFN) as f: content = f.read() for n in range(20): @@ -3493,7 +3483,7 @@ self.assertRaises(ZeroDivisionError, wio.write, large_data) finally: signal.alarm(0) - t.join() + t.join() # We got one byte, get another one and check that it isn't a # repeat of the first one. read_results.append(os.read(r, 1)) 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 @@ -14,7 +14,7 @@ import unittest from test.support import ( verbose, import_module, run_unittest, TESTFN, reap_threads, - forget, unlink, rmtree) + forget, unlink, rmtree, start_threads) threading = import_module('threading') def task(N, done, done_tasks, errors): @@ -116,10 +116,10 @@ done_tasks = [] done.clear() t0 = time.monotonic() - for i in range(N): - t = threading.Thread(target=task, - args=(N, done, done_tasks, errors,)) - t.start() + with start_threads(threading.Thread(target=task, + args=(N, done, done_tasks, errors,)) + for i in range(N)): + pass completed = done.wait(10 * 60) dt = time.monotonic() - t0 if verbose: diff --git a/Lib/test/test_threadedtempfile.py b/Lib/test/test_threadedtempfile.py --- a/Lib/test/test_threadedtempfile.py +++ b/Lib/test/test_threadedtempfile.py @@ -18,7 +18,7 @@ import tempfile -from test.support import threading_setup, threading_cleanup, run_unittest, import_module +from test.support import start_threads, import_module threading = import_module('threading') import unittest import io @@ -46,33 +46,17 @@ class ThreadedTempFileTest(unittest.TestCase): def test_main(self): - threads = [] - thread_info = threading_setup() - - for i in range(NUM_THREADS): - t = TempFileGreedy() - threads.append(t) - t.start() - - startEvent.set() - - ok = 0 - errors = [] - for t in threads: - t.join() - ok += t.ok_count - if t.error_count: - errors.append(str(t.name) + str(t.errors.getvalue())) - - threading_cleanup(*thread_info) + threads = [TempFileGreedy() for i in range(NUM_THREADS)] + with start_threads(threads, startEvent.set): + pass + ok = sum(t.ok_count for t in threads) + errors = [str(t.name) + str(t.errors.getvalue()) + for t in threads if t.error_count] msg = "Errors: errors %d ok %d\n%s" % (len(errors), ok, '\n'.join(errors)) self.assertEqual(errors, [], msg) self.assertEqual(ok, NUM_THREADS * FILES_PER_THREAD) -def test_main(): - run_unittest(ThreadedTempFileTest) - if __name__ == "__main__": - test_main() + unittest.main() diff --git a/Lib/test/test_threading_local.py b/Lib/test/test_threading_local.py --- a/Lib/test/test_threading_local.py +++ b/Lib/test/test_threading_local.py @@ -64,14 +64,9 @@ # Simply check that the variable is correctly set self.assertEqual(local.x, i) - threads= [] - for i in range(10): - t = threading.Thread(target=f, args=(i,)) - t.start() - threads.append(t) - - for t in threads: - t.join() + with support.start_threads(threading.Thread(target=f, args=(i,)) + for i in range(10)): + pass def test_derived_cycle_dealloc(self): # http://bugs.python.org/issue6990 diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -230,6 +230,9 @@ Tests ----- +- Issue #23799: Added test.support.start_threads() for running and + cleaning up multiple threads. + - Issue #22390: test.regrtest now emits a warning if temporary files or directories are left after running a test. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Apr 1 15:15:43 2015 From: python-checkins at python.org (r.david.murray) Date: Wed, 01 Apr 2015 13:15:43 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_It_wasn=27t_a_typo=2C_it_i?= =?utf-8?q?s_the_mnemonic_=28AT=3D=40=29=2E?= Message-ID: <20150401131517.1872.36003@psf.io> https://hg.python.org/cpython/rev/f4acf2a31151 changeset: 95343:f4acf2a31151 user: R David Murray date: Wed Apr 01 09:15:02 2015 -0400 summary: It wasn't a typo, it is the mnemonic (AT=@). files: Doc/whatsnew/3.5.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -147,7 +147,7 @@ -------------------------------------------------------------- This PEP proposes a new binary operator to be used for matrix multiplication, -called ``@``. (Mnemonic: ``@`` is ``*`` for matrices.) +called ``@``. (Mnemonic: ``@`` is ``*`` for mATrices.) .. seealso:: -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Apr 1 15:59:07 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Wed, 01 Apr 2015 13:59:07 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2323838=3A_linecache_now_clears_the_cache_and_ret?= =?utf-8?q?urns_an_empty_result_on?= Message-ID: <20150401135907.2017.25077@psf.io> https://hg.python.org/cpython/rev/ab2326c801c2 changeset: 95346:ab2326c801c2 parent: 95343:f4acf2a31151 parent: 95345:88a0e6cd93c3 user: Serhiy Storchaka date: Wed Apr 01 16:56:13 2015 +0300 summary: Issue #23838: linecache now clears the cache and returns an empty result on MemoryError. files: Lib/linecache.py | 11 +++++++---- Lib/test/test_linecache.py | 18 +++++++++++++++--- Misc/NEWS | 3 +++ 3 files changed, 25 insertions(+), 7 deletions(-) diff --git a/Lib/linecache.py b/Lib/linecache.py --- a/Lib/linecache.py +++ b/Lib/linecache.py @@ -40,11 +40,14 @@ if filename in cache: entry = cache[filename] - if len(entry) == 1: - return updatecache(filename, module_globals) - return cache[filename][2] - else: + if len(entry) != 1: + return cache[filename][2] + + try: return updatecache(filename, module_globals) + except MemoryError: + clearcache() + return [] def checkcache(filename=None): diff --git a/Lib/test/test_linecache.py b/Lib/test/test_linecache.py --- a/Lib/test/test_linecache.py +++ b/Lib/test/test_linecache.py @@ -169,9 +169,21 @@ linecache.lazycache(NONEXISTENT_FILENAME, globals())) self.assertEqual(4, len(linecache.cache[NONEXISTENT_FILENAME])) + def test_memoryerror(self): + lines = linecache.getlines(FILENAME) + self.assertTrue(lines) + def raise_memoryerror(*args, **kwargs): + raise MemoryError + with support.swap_attr(linecache, 'updatecache', raise_memoryerror): + lines2 = linecache.getlines(FILENAME) + self.assertEqual(lines2, lines) -def test_main(): - support.run_unittest(LineCacheTests) + linecache.clearcache() + with support.swap_attr(linecache, 'updatecache', raise_memoryerror): + lines3 = linecache.getlines(FILENAME) + self.assertEqual(lines3, []) + self.assertEqual(linecache.getlines(FILENAME), lines) + if __name__ == "__main__": - test_main() + unittest.main() diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -13,6 +13,9 @@ Library ------- +- Issue #23838: linecache now clears the cache and returns an empty result on + MemoryError. + - Issue #10395: Added os.path.commonpath(). Implemented in posixpath and ntpath. Based on patch by Rafik Draoui. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Apr 1 15:59:07 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Wed, 01 Apr 2015 13:59:07 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzIzODM4?= =?utf-8?q?=3A_linecache_now_clears_the_cache_and_returns_an_empty_result_?= =?utf-8?q?on?= Message-ID: <20150401135907.1888.94701@psf.io> https://hg.python.org/cpython/rev/88a0e6cd93c3 changeset: 95345:88a0e6cd93c3 branch: 3.4 parent: 95341:8987218adc99 user: Serhiy Storchaka date: Wed Apr 01 16:54:05 2015 +0300 summary: Issue #23838: linecache now clears the cache and returns an empty result on MemoryError. files: Lib/linecache.py | 6 +++++- Lib/test/test_linecache.py | 19 ++++++++++++++++--- Misc/NEWS | 3 +++ 3 files changed, 24 insertions(+), 4 deletions(-) diff --git a/Lib/linecache.py b/Lib/linecache.py --- a/Lib/linecache.py +++ b/Lib/linecache.py @@ -37,8 +37,12 @@ if filename in cache: return cache[filename][2] - else: + + try: return updatecache(filename, module_globals) + except MemoryError: + clearcache() + return [] def checkcache(filename=None): diff --git a/Lib/test/test_linecache.py b/Lib/test/test_linecache.py --- a/Lib/test/test_linecache.py +++ b/Lib/test/test_linecache.py @@ -126,8 +126,21 @@ self.assertEqual(line, getline(source_name, index + 1)) source_list.append(line) -def test_main(): - support.run_unittest(LineCacheTests) + def test_memoryerror(self): + lines = linecache.getlines(FILENAME) + self.assertTrue(lines) + def raise_memoryerror(*args, **kwargs): + raise MemoryError + with support.swap_attr(linecache, 'updatecache', raise_memoryerror): + lines2 = linecache.getlines(FILENAME) + self.assertEqual(lines2, lines) + + linecache.clearcache() + with support.swap_attr(linecache, 'updatecache', raise_memoryerror): + lines3 = linecache.getlines(FILENAME) + self.assertEqual(lines3, []) + self.assertEqual(linecache.getlines(FILENAME), lines) + if __name__ == "__main__": - test_main() + unittest.main() diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -21,6 +21,9 @@ Library ------- +- Issue #23838: linecache now clears the cache and returns an empty result on + MemoryError. + - Issue #18473: Fixed 2to3 and 3to2 compatible pickle mappings. Fixed ambigious reverse mappings. Added many new mappings. Import mapping is no longer applied to modules already mapped with full name mapping. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Apr 1 15:59:07 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Wed, 01 Apr 2015 13:59:07 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzIzODM4?= =?utf-8?q?=3A_linecache_now_clears_the_cache_and_returns_an_empty_result_?= =?utf-8?q?on?= Message-ID: <20150401135907.113163.31855@psf.io> https://hg.python.org/cpython/rev/d444496e714a changeset: 95344:d444496e714a branch: 2.7 parent: 95340:f8358f6e50e7 user: Serhiy Storchaka date: Wed Apr 01 16:53:53 2015 +0300 summary: Issue #23838: linecache now clears the cache and returns an empty result on MemoryError. files: Lib/linecache.py | 6 +++++- Lib/test/test_linecache.py | 16 ++++++++++++++++ Misc/NEWS | 3 +++ 3 files changed, 24 insertions(+), 1 deletions(-) diff --git a/Lib/linecache.py b/Lib/linecache.py --- a/Lib/linecache.py +++ b/Lib/linecache.py @@ -36,8 +36,12 @@ if filename in cache: return cache[filename][2] - else: + + try: return updatecache(filename, module_globals) + except MemoryError: + clearcache() + return [] def checkcache(filename=None): diff --git a/Lib/test/test_linecache.py b/Lib/test/test_linecache.py --- a/Lib/test/test_linecache.py +++ b/Lib/test/test_linecache.py @@ -124,6 +124,22 @@ self.assertEqual(line, getline(source_name, index + 1)) source_list.append(line) + def test_memoryerror(self): + lines = linecache.getlines(FILENAME) + self.assertTrue(lines) + def raise_memoryerror(*args, **kwargs): + raise MemoryError + with support.swap_attr(linecache, 'updatecache', raise_memoryerror): + lines2 = linecache.getlines(FILENAME) + self.assertEqual(lines2, lines) + + linecache.clearcache() + with support.swap_attr(linecache, 'updatecache', raise_memoryerror): + lines3 = linecache.getlines(FILENAME) + self.assertEqual(lines3, []) + self.assertEqual(linecache.getlines(FILENAME), lines) + + def test_main(): support.run_unittest(LineCacheTests) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -21,6 +21,9 @@ Library ------- +- Issue #23838: linecache now clears the cache and returns an empty result on + MemoryError. + - Issue #23742: ntpath.expandvars() no longer loses unbalanced single quotes. - Issue #21802: The reader in BufferedRWPair now is closed even when closing -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Apr 1 15:59:07 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Wed, 01 Apr 2015 13:59:07 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzIzODIx?= =?utf-8?q?=3A_Fixed_test=5Fpdb_failure_under_-O=2E?= Message-ID: <20150401135907.120002.45052@psf.io> https://hg.python.org/cpython/rev/26778732099d changeset: 95347:26778732099d branch: 3.4 parent: 95345:88a0e6cd93c3 user: Serhiy Storchaka date: Wed Apr 01 16:58:19 2015 +0300 summary: Issue #23821: Fixed test_pdb failure under -O. files: Lib/test/test_pdb.py | 26 +++++++++++++++----------- 1 files changed, 15 insertions(+), 11 deletions(-) diff --git a/Lib/test/test_pdb.py b/Lib/test/test_pdb.py --- a/Lib/test/test_pdb.py +++ b/Lib/test/test_pdb.py @@ -677,10 +677,12 @@ ... import pdb; pdb.Pdb(nosigint=True).set_trace() ... it = test_gen() ... try: - ... assert next(it) == 0 + ... if next(it) != 0: + ... raise AssertionError ... next(it) ... except StopIteration as ex: - ... assert ex.value == 1 + ... if ex.value != 1: + ... raise AssertionError ... print("finished") >>> with PdbTestInput(['step', @@ -699,7 +701,7 @@ -> try: (Pdb) step > (5)test_function() - -> assert next(it) == 0 + -> if next(it) != 0: (Pdb) step --Call-- > (1)test_gen() @@ -716,7 +718,7 @@ -> return 1 (Pdb) step StopIteration: 1 - > (6)test_function() + > (7)test_function() -> next(it) (Pdb) continue finished @@ -735,10 +737,12 @@ ... import pdb; pdb.Pdb(nosigint=True).set_trace() ... it = test_gen() ... try: - ... assert next(it) == 0 + ... if next(it) != 0: + ... raise AssertionError ... next(it) ... except StopIteration as ex: - ... assert ex.value == 1 + ... if ex.value != 1: + ... raise AssertionError ... print("finished") >>> with PdbTestInput(['step', @@ -756,21 +760,21 @@ -> try: (Pdb) step > (5)test_function() - -> assert next(it) == 0 + -> if next(it) != 0: (Pdb) step --Call-- > (1)test_gen() -> def test_gen(): (Pdb) return StopIteration: 1 - > (6)test_function() + > (7)test_function() -> next(it) (Pdb) step - > (7)test_function() + > (8)test_function() -> except StopIteration as ex: (Pdb) step - > (8)test_function() - -> assert ex.value == 1 + > (9)test_function() + -> if ex.value != 1: (Pdb) continue finished """ -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Apr 1 15:59:07 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Wed, 01 Apr 2015 13:59:07 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2323821=3A_Fixed_test=5Fpdb_failure_under_-O=2E?= Message-ID: <20150401135907.91362.99983@psf.io> https://hg.python.org/cpython/rev/23442d957793 changeset: 95348:23442d957793 parent: 95346:ab2326c801c2 parent: 95347:26778732099d user: Serhiy Storchaka date: Wed Apr 01 16:58:39 2015 +0300 summary: Issue #23821: Fixed test_pdb failure under -O. files: Lib/test/test_pdb.py | 26 +++++++++++++++----------- 1 files changed, 15 insertions(+), 11 deletions(-) diff --git a/Lib/test/test_pdb.py b/Lib/test/test_pdb.py --- a/Lib/test/test_pdb.py +++ b/Lib/test/test_pdb.py @@ -677,10 +677,12 @@ ... import pdb; pdb.Pdb(nosigint=True).set_trace() ... it = test_gen() ... try: - ... assert next(it) == 0 + ... if next(it) != 0: + ... raise AssertionError ... next(it) ... except StopIteration as ex: - ... assert ex.value == 1 + ... if ex.value != 1: + ... raise AssertionError ... print("finished") >>> with PdbTestInput(['step', @@ -699,7 +701,7 @@ -> try: (Pdb) step > (5)test_function() - -> assert next(it) == 0 + -> if next(it) != 0: (Pdb) step --Call-- > (1)test_gen() @@ -716,7 +718,7 @@ -> return 1 (Pdb) step StopIteration: 1 - > (6)test_function() + > (7)test_function() -> next(it) (Pdb) continue finished @@ -735,10 +737,12 @@ ... import pdb; pdb.Pdb(nosigint=True).set_trace() ... it = test_gen() ... try: - ... assert next(it) == 0 + ... if next(it) != 0: + ... raise AssertionError ... next(it) ... except StopIteration as ex: - ... assert ex.value == 1 + ... if ex.value != 1: + ... raise AssertionError ... print("finished") >>> with PdbTestInput(['step', @@ -756,21 +760,21 @@ -> try: (Pdb) step > (5)test_function() - -> assert next(it) == 0 + -> if next(it) != 0: (Pdb) step --Call-- > (1)test_gen() -> def test_gen(): (Pdb) return StopIteration: 1 - > (6)test_function() + > (7)test_function() -> next(it) (Pdb) step - > (7)test_function() + > (8)test_function() -> except StopIteration as ex: (Pdb) step - > (8)test_function() - -> assert ex.value == 1 + > (9)test_function() + -> if ex.value != 1: (Pdb) continue finished """ -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Apr 1 16:33:07 2015 From: python-checkins at python.org (victor.stinner) Date: Wed, 01 Apr 2015 14:33:07 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_What=27s_New_in_Python_3?= =?utf-8?q?=2E5=3A_mention_signal=2Eset=5Fwakeup=5Ffd=28=29_enhancement_on?= =?utf-8?q?_Windows?= Message-ID: <20150401143306.95068.35666@psf.io> https://hg.python.org/cpython/rev/0c40e8f559a9 changeset: 95349:0c40e8f559a9 user: Victor Stinner date: Wed Apr 01 16:32:32 2015 +0200 summary: What's New in Python 3.5: mention signal.set_wakeup_fd() enhancement on Windows files: Doc/whatsnew/3.5.rst | 3 +++ 1 files changed, 3 insertions(+), 0 deletions(-) diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -410,6 +410,9 @@ signal ------ +* On Windows, :func:`signal.set_wakeup_fd` now also supports socket handles. + (Contributed by Victor Stinner in :issue:`22018`.) + * Different constants of :mod:`signal` module are now enumeration values using the :mod:`enum` module. This allows meaningful names to be printed during debugging, instead of integer ?magic numbers?. (Contributed by Giampaolo -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Apr 1 17:11:14 2015 From: python-checkins at python.org (raymond.hettinger) Date: Wed, 01 Apr 2015 15:11:14 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Check_deques_against_commo?= =?utf-8?q?n_sequence_tests_=28except_for_slicing=29=2E?= Message-ID: <20150401151114.1901.60002@psf.io> https://hg.python.org/cpython/rev/393189326adb changeset: 95350:393189326adb user: Raymond Hettinger date: Wed Apr 01 08:11:09 2015 -0700 summary: Check deques against common sequence tests (except for slicing). files: Lib/test/test_deque.py | 16 ++++++++++++++++ 1 files changed, 16 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_deque.py b/Lib/test/test_deque.py --- a/Lib/test/test_deque.py +++ b/Lib/test/test_deque.py @@ -843,6 +843,21 @@ # SF bug #1486663 -- this used to erroneously raise a TypeError SubclassWithKwargs(newarg=1) +class TestSequence(seq_tests.CommonTest): + type2test = deque + + def test_getitem(self): + # For now, bypass tests that require slicing + pass + + def test_getslice(self): + # For now, bypass tests that require slicing + pass + + def test_subscript(self): + # For now, bypass tests that require slicing + pass + #============================================================================== libreftest = """ @@ -957,6 +972,7 @@ TestVariousIteratorArgs, TestSubclass, TestSubclassWithKwargs, + TestSequence, ) support.run_unittest(*test_classes) -- Repository URL: https://hg.python.org/cpython From zachary.ware+pydev at gmail.com Wed Apr 1 17:27:54 2015 From: zachary.ware+pydev at gmail.com (Zachary Ware) Date: Wed, 1 Apr 2015 10:27:54 -0500 Subject: [Python-checkins] cpython: Check deques against common sequence tests (except for slicing). In-Reply-To: <20150401151114.1901.60002@psf.io> References: <20150401151114.1901.60002@psf.io> Message-ID: On Wed, Apr 1, 2015 at 10:11 AM, raymond.hettinger wrote: > https://hg.python.org/cpython/rev/393189326adb > changeset: 95350:393189326adb > user: Raymond Hettinger > date: Wed Apr 01 08:11:09 2015 -0700 > summary: > Check deques against common sequence tests (except for slicing). > > files: > Lib/test/test_deque.py | 16 ++++++++++++++++ > 1 files changed, 16 insertions(+), 0 deletions(-) > > > diff --git a/Lib/test/test_deque.py b/Lib/test/test_deque.py > --- a/Lib/test/test_deque.py > +++ b/Lib/test/test_deque.py > @@ -843,6 +843,21 @@ > # SF bug #1486663 -- this used to erroneously raise a TypeError > SubclassWithKwargs(newarg=1) > > +class TestSequence(seq_tests.CommonTest): > + type2test = deque > + > + def test_getitem(self): > + # For now, bypass tests that require slicing > + pass > + > + def test_getslice(self): > + # For now, bypass tests that require slicing > + pass > + > + def test_subscript(self): > + # For now, bypass tests that require slicing > + pass Instead of making these empty passing tests, it's better to set them to 'None' so that unittest doesn't run them (and thus doesn't report success when it hasn't actually tested something). -- Zach From python-checkins at python.org Wed Apr 1 17:51:07 2015 From: python-checkins at python.org (victor.stinner) Date: Wed, 01 Apr 2015 15:51:07 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2322117=2C_issue_?= =?utf-8?q?=2323485=3A_Fix_=5FPyTime=5FAsMilliseconds=28=29_and?= Message-ID: <20150401155107.2041.81158@psf.io> https://hg.python.org/cpython/rev/65ac8e587bb0 changeset: 95351:65ac8e587bb0 user: Victor Stinner date: Wed Apr 01 17:47:07 2015 +0200 summary: Issue #22117, issue #23485: Fix _PyTime_AsMilliseconds() and _PyTime_AsMicroseconds() rounding. Add also unit tests. files: Lib/test/test_time.py | 76 +++++++++++++++++++++++++- Modules/_testcapimodule.c | 38 +++++++++++++ Python/pytime.c | 26 ++++---- 3 files changed, 123 insertions(+), 17 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 @@ -21,6 +21,8 @@ TIME_MAXYEAR = (1 << 8 * SIZEOF_INT - 1) - 1 TIME_MINYEAR = -TIME_MAXYEAR - 1 +US_TO_NS = 10 ** 3 +MS_TO_NS = 10 ** 6 SEC_TO_NS = 10 ** 9 class _PyTime(enum.IntEnum): @@ -867,10 +869,6 @@ # seconds (2 * SEC_TO_NS, (2, 0)), (-3 * SEC_TO_NS, (-3, 0)), - - # seconds + nanoseconds - (1234567000, (1, 234567)), - (-1234567000, (-2, 765433)), ): with self.subTest(nanoseconds=ns, timeval=tv, round=rnd): self.assertEqual(PyTime_AsTimeval(ns, rnd), tv) @@ -914,6 +912,76 @@ with self.subTest(nanoseconds=ns, timespec=ts): self.assertEqual(PyTime_AsTimespec(ns), ts) + def test_milliseconds(self): + from _testcapi import PyTime_AsMilliseconds + for rnd in ALL_ROUNDING_METHODS: + for ns, tv in ( + # milliseconds + (1 * MS_TO_NS, 1), + (-2 * MS_TO_NS, -2), + + # seconds + (2 * SEC_TO_NS, 2000), + (-3 * SEC_TO_NS, -3000), + ): + with self.subTest(nanoseconds=ns, timeval=tv, round=rnd): + self.assertEqual(PyTime_AsMilliseconds(ns, rnd), tv) + + FLOOR = _PyTime.ROUND_FLOOR + CEILING = _PyTime.ROUND_CEILING + for ns, ms, rnd in ( + # nanoseconds + (1, 0, FLOOR), + (1, 1, CEILING), + (-1, 0, FLOOR), + (-1, -1, CEILING), + + # seconds + nanoseconds + (1234 * MS_TO_NS + 1, 1234, FLOOR), + (1234 * MS_TO_NS + 1, 1235, CEILING), + (-1234 * MS_TO_NS - 1, -1234, FLOOR), + (-1234 * MS_TO_NS - 1, -1235, CEILING), + ): + with self.subTest(nanoseconds=ns, milliseconds=ms, round=rnd): + self.assertEqual(PyTime_AsMilliseconds(ns, rnd), ms) + + def test_microseconds(self): + from _testcapi import PyTime_AsMicroseconds + for rnd in ALL_ROUNDING_METHODS: + for ns, tv in ( + # microseconds + (1 * US_TO_NS, 1), + (-2 * US_TO_NS, -2), + + # milliseconds + (1 * MS_TO_NS, 1000), + (-2 * MS_TO_NS, -2000), + + # seconds + (2 * SEC_TO_NS, 2000000), + (-3 * SEC_TO_NS, -3000000), + ): + with self.subTest(nanoseconds=ns, timeval=tv, round=rnd): + self.assertEqual(PyTime_AsMicroseconds(ns, rnd), tv) + + FLOOR = _PyTime.ROUND_FLOOR + CEILING = _PyTime.ROUND_CEILING + for ns, ms, rnd in ( + # nanoseconds + (1, 0, FLOOR), + (1, 1, CEILING), + (-1, 0, FLOOR), + (-1, -1, CEILING), + + # seconds + nanoseconds + (1234 * US_TO_NS + 1, 1234, FLOOR), + (1234 * US_TO_NS + 1, 1235, CEILING), + (-1234 * US_TO_NS - 1, -1234, FLOOR), + (-1234 * US_TO_NS - 1, -1235, CEILING), + ): + with self.subTest(nanoseconds=ns, milliseconds=ms, round=rnd): + self.assertEqual(PyTime_AsMicroseconds(ns, rnd), ms) + if __name__ == "__main__": unittest.main() diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -3452,6 +3452,42 @@ } #endif +static PyObject * +test_PyTime_AsMilliseconds(PyObject *self, PyObject *args) +{ + PY_LONG_LONG ns; + int round; + _PyTime_t t, ms; + + if (!PyArg_ParseTuple(args, "Li", &ns, &round)) + return NULL; + if (check_time_rounding(round) < 0) + return NULL; + t = _PyTime_FromNanoseconds(ns); + ms = _PyTime_AsMilliseconds(t, round); + /* This conversion rely on the fact that _PyTime_t is a number of + nanoseconds */ + return _PyTime_AsNanosecondsObject(ms); +} + +static PyObject * +test_PyTime_AsMicroseconds(PyObject *self, PyObject *args) +{ + PY_LONG_LONG ns; + int round; + _PyTime_t t, ms; + + if (!PyArg_ParseTuple(args, "Li", &ns, &round)) + return NULL; + if (check_time_rounding(round) < 0) + return NULL; + t = _PyTime_FromNanoseconds(ns); + ms = _PyTime_AsMicroseconds(t, round); + /* This conversion rely on the fact that _PyTime_t is a number of + nanoseconds */ + return _PyTime_AsNanosecondsObject(ms); +} + static PyMethodDef TestMethods[] = { {"raise_exception", raise_exception, METH_VARARGS}, @@ -3621,6 +3657,8 @@ #ifdef HAVE_CLOCK_GETTIME {"PyTime_AsTimespec", test_PyTime_AsTimespec, METH_VARARGS}, #endif + {"PyTime_AsMilliseconds", test_PyTime_AsMilliseconds, METH_VARARGS}, + {"PyTime_AsMicroseconds", test_PyTime_AsMicroseconds, METH_VARARGS}, {NULL, NULL} /* sentinel */ }; diff --git a/Python/pytime.c b/Python/pytime.c --- a/Python/pytime.c +++ b/Python/pytime.c @@ -19,6 +19,10 @@ #define MS_TO_NS (MS_TO_US * US_TO_NS) #define SEC_TO_NS (SEC_TO_MS * MS_TO_NS) +/* Conversion from nanoseconds */ +#define NS_TO_MS (1000 * 1000) +#define NS_TO_US (1000) + static void error_time_t_overflow(void) { @@ -288,33 +292,29 @@ } static _PyTime_t -_PyTime_Multiply(_PyTime_t t, unsigned int multiply, _PyTime_round_t round) +_PyTime_Divide(_PyTime_t t, _PyTime_t k, _PyTime_round_t round) { - _PyTime_t k; - if (multiply < SEC_TO_NS) { - k = SEC_TO_NS / multiply; - if (round == _PyTime_ROUND_CEILING) + assert(k > 1); + if (round == _PyTime_ROUND_CEILING) { + if (t >= 0) return (t + k - 1) / k; else - return t / k; + return (t - (k - 1)) / k; } - else { - k = multiply / SEC_TO_NS; - return t * k; - } + else + return t / k; } _PyTime_t _PyTime_AsMilliseconds(_PyTime_t t, _PyTime_round_t round) { - return _PyTime_Multiply(t, 1000, round); + return _PyTime_Divide(t, NS_TO_MS, round); } -/* FIXME: write unit tests */ _PyTime_t _PyTime_AsMicroseconds(_PyTime_t t, _PyTime_round_t round) { - return _PyTime_Multiply(t, 1000 * 1000, round); + return _PyTime_Divide(t, NS_TO_US, round); } static int -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Apr 1 17:55:31 2015 From: python-checkins at python.org (brett.cannon) Date: Wed, 01 Apr 2015 15:55:31 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_Link_to_implementation_for_PE?= =?utf-8?q?P_488?= Message-ID: <20150401155531.2028.93928@psf.io> https://hg.python.org/peps/rev/9ee257fb5abe changeset: 5747:9ee257fb5abe user: Brett Cannon date: Wed Apr 01 11:55:28 2015 -0400 summary: Link to implementation for PEP 488 files: pep-0488.txt | 4 ++++ 1 files changed, 4 insertions(+), 0 deletions(-) diff --git a/pep-0488.txt b/pep-0488.txt --- a/pep-0488.txt +++ b/pep-0488.txt @@ -147,6 +147,8 @@ Implementation ============== +An implementation of this PEP is available [11]_. + importlib --------- @@ -334,6 +336,8 @@ .. [10] The PyPy Project (http://pypy.org/) +.. [11] Implementation of PEP 488 + (http://bugs.python.org/issue23731) Copyright ========= -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Wed Apr 1 18:37:38 2015 From: python-checkins at python.org (benjamin.peterson) Date: Wed, 01 Apr 2015 16:37:38 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E4=29=3A_remove_assignm?= =?utf-8?q?ent_in_conditional?= Message-ID: <20150401163738.1926.25871@psf.io> https://hg.python.org/cpython/rev/47451f6e7e75 changeset: 95352:47451f6e7e75 branch: 3.4 parent: 95347:26778732099d user: Benjamin Peterson date: Wed Apr 01 11:16:40 2015 -0400 summary: remove assignment in conditional files: Modules/socketmodule.c | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -5268,7 +5268,8 @@ goto err; } - if ((all = PyList_New(0)) == NULL) + all = PyList_New(0); + if (all == NULL) goto err; for (res = res0; res; res = res->ai_next) { PyObject *single; -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Apr 1 18:37:52 2015 From: python-checkins at python.org (benjamin.peterson) Date: Wed, 01 Apr 2015 16:37:52 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?b?KTogbWVyZ2UgMy40?= Message-ID: <20150401163738.91342.31532@psf.io> https://hg.python.org/cpython/rev/1eaf53ab4faa changeset: 95354:1eaf53ab4faa parent: 95351:65ac8e587bb0 parent: 95352:47451f6e7e75 user: Benjamin Peterson date: Wed Apr 01 12:37:34 2015 -0400 summary: merge 3.4 files: Modules/socketmodule.c | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -5429,7 +5429,8 @@ goto err; } - if ((all = PyList_New(0)) == NULL) + all = PyList_New(0); + if (all == NULL) goto err; for (res = res0; res; res = res->ai_next) { PyObject *single; -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Apr 1 18:37:52 2015 From: python-checkins at python.org (benjamin.peterson) Date: Wed, 01 Apr 2015 16:37:52 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_remove_assignm?= =?utf-8?q?ent_in_conditional?= Message-ID: <20150401163738.65773.32285@psf.io> https://hg.python.org/cpython/rev/5d88f6531872 changeset: 95353:5d88f6531872 branch: 2.7 parent: 95344:d444496e714a user: Benjamin Peterson date: Wed Apr 01 11:16:40 2015 -0400 summary: remove assignment in conditional files: Modules/socketmodule.c | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -4207,7 +4207,8 @@ goto err; } - if ((all = PyList_New(0)) == NULL) + all = PyList_New(0); + if (all == NULL) goto err; for (res = res0; res; res = res->ai_next) { PyObject *addr = -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Apr 1 18:51:52 2015 From: python-checkins at python.org (victor.stinner) Date: Wed, 01 Apr 2015 16:51:52 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2323836=3A_Document?= =?utf-8?q?_functions_releasing_the_GIL_in_fileutils=2Ec?= Message-ID: <20150401165151.113167.85402@psf.io> https://hg.python.org/cpython/rev/d9b9e2a68e7c changeset: 95356:d9b9e2a68e7c user: Victor Stinner date: Wed Apr 01 18:34:32 2015 +0200 summary: Issue #23836: Document functions releasing the GIL in fileutils.c files: Python/fileutils.c | 8 +++++--- 1 files changed, 5 insertions(+), 3 deletions(-) diff --git a/Python/fileutils.c b/Python/fileutils.c --- a/Python/fileutils.c +++ b/Python/fileutils.c @@ -667,7 +667,8 @@ error on error. On POSIX, set errno on error. Fill status and return 0 on success. - The GIL must be held. */ + Release the GIL to call GetFileType() and GetFileInformationByHandle(), or + to call fstat(). The caller must hold the GIL. */ int _Py_fstat(int fd, struct _Py_stat_struct *status) { @@ -968,7 +969,7 @@ When interrupted by a signal (open() fails with EINTR), retry the syscall, except if the Python signal handler raises an exception. - The GIL must be held. */ + Release the GIL to call open(). The caller must hold the GIL. */ int _Py_open(const char *pathname, int flags) { @@ -1054,7 +1055,8 @@ When interrupted by a signal (open() fails with EINTR), retry the syscall, except if the Python signal handler raises an exception. - The GIL must be held. */ + Release the GIL to call _wfopen() or fopen(). The caller must hold + the GIL. */ FILE* _Py_fopen_obj(PyObject *path, const char *mode) { -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Apr 1 18:51:52 2015 From: python-checkins at python.org (victor.stinner) Date: Wed, 01 Apr 2015 16:51:52 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2323836=3A_Add_=5FP?= =?utf-8?q?y=5Fwrite=5Fnoraise=28=29_function?= Message-ID: <20150401165151.119996.54785@psf.io> https://hg.python.org/cpython/rev/60e001ec141d changeset: 95355:60e001ec141d user: Victor Stinner date: Wed Apr 01 18:34:45 2015 +0200 summary: Issue #23836: Add _Py_write_noraise() function Helper to write() which retries write() if it is interrupted by a signal (fails with EINTR). files: Include/fileutils.h | 5 + Python/fileutils.c | 131 ++++++++++++++++++++----------- 2 files changed, 88 insertions(+), 48 deletions(-) diff --git a/Include/fileutils.h b/Include/fileutils.h --- a/Include/fileutils.h +++ b/Include/fileutils.h @@ -84,6 +84,11 @@ const void *buf, size_t count); +PyAPI_FUNC(Py_ssize_t) _Py_write_noraise( + int fd, + const void *buf, + size_t count); + #ifdef HAVE_READLINK PyAPI_FUNC(int) _Py_wreadlink( const wchar_t *path, diff --git a/Python/fileutils.c b/Python/fileutils.c --- a/Python/fileutils.c +++ b/Python/fileutils.c @@ -1124,18 +1124,18 @@ } /* Read count bytes from fd into buf. - * - * On success, return the number of read bytes, it can be lower than count. - * If the current file offset is at or past the end of file, no bytes are read, - * and read() returns zero. - * - * On error, raise an exception, set errno and return -1. - * - * When interrupted by a signal (read() fails with EINTR), retry the syscall. - * If the Python signal handler raises an exception, the function returns -1 - * (the syscall is not retried). - * - * The GIL must be held. */ + + On success, return the number of read bytes, it can be lower than count. + If the current file offset is at or past the end of file, no bytes are read, + and read() returns zero. + + On error, raise an exception, set errno and return -1. + + When interrupted by a signal (read() fails with EINTR), retry the syscall. + If the Python signal handler raises an exception, the function returns -1 + (the syscall is not retried). + + Release the GIL to call read(). The caller must hold the GIL. */ Py_ssize_t _Py_read(int fd, void *buf, size_t count) { @@ -1200,34 +1200,20 @@ return n; } -/* Write count bytes of buf into fd. - * - * -On success, return the number of written bytes, it can be lower than count - * including 0 - * - On error, raise an exception, set errno and return -1. - * - * When interrupted by a signal (write() fails with EINTR), retry the syscall. - * If the Python signal handler raises an exception, the function returns -1 - * (the syscall is not retried). - * - * The GIL must be held. */ -Py_ssize_t -_Py_write(int fd, const void *buf, size_t count) +static Py_ssize_t +_Py_write_impl(int fd, const void *buf, size_t count, int gil_held) { Py_ssize_t n; int err; int async_err = 0; - /* _Py_write() must not be called with an exception set, otherwise the - * caller may think that write() was interrupted by a signal and the signal - * handler raised an exception. */ - assert(!PyErr_Occurred()); - if (!_PyVerify_fd(fd)) { - /* save/restore errno because PyErr_SetFromErrno() can modify it */ - err = errno; - PyErr_SetFromErrno(PyExc_OSError); - errno = err; + if (gil_held) { + /* save/restore errno because PyErr_SetFromErrno() can modify it */ + err = errno; + PyErr_SetFromErrno(PyExc_OSError); + errno = err; + } return -1; } @@ -1249,30 +1235,45 @@ } #endif - do { - Py_BEGIN_ALLOW_THREADS - errno = 0; + if (gil_held) { + do { + Py_BEGIN_ALLOW_THREADS + errno = 0; #ifdef MS_WINDOWS - n = write(fd, buf, (int)count); + n = write(fd, buf, (int)count); #else - n = write(fd, buf, count); + n = write(fd, buf, count); #endif - /* save/restore errno because PyErr_CheckSignals() - * and PyErr_SetFromErrno() can modify it */ - err = errno; - Py_END_ALLOW_THREADS - } while (n < 0 && errno == EINTR && - !(async_err = PyErr_CheckSignals())); + /* save/restore errno because PyErr_CheckSignals() + * and PyErr_SetFromErrno() can modify it */ + err = errno; + Py_END_ALLOW_THREADS + } while (n < 0 && err == EINTR && + !(async_err = PyErr_CheckSignals())); + } + else { + do { + errno = 0; +#ifdef MS_WINDOWS + n = write(fd, buf, (int)count); +#else + n = write(fd, buf, count); +#endif + err = errno; + } while (n < 0 && err == EINTR); + } if (async_err) { /* write() was interrupted by a signal (failed with EINTR) - * and the Python signal handler raised an exception */ + and the Python signal handler raised an exception (if gil_held is + nonzero). */ errno = err; - assert(errno == EINTR && PyErr_Occurred()); + assert(errno == EINTR && (!gil_held || PyErr_Occurred())); return -1; } if (n < 0) { - PyErr_SetFromErrno(PyExc_OSError); + if (gil_held) + PyErr_SetFromErrno(PyExc_OSError); errno = err; return -1; } @@ -1280,6 +1281,40 @@ return n; } +/* Write count bytes of buf into fd. + + On success, return the number of written bytes, it can be lower than count + including 0. On error, raise an exception, set errno and return -1. + + When interrupted by a signal (write() fails with EINTR), retry the syscall. + If the Python signal handler raises an exception, the function returns -1 + (the syscall is not retried). + + Release the GIL to call write(). The caller must hold the GIL. */ +Py_ssize_t +_Py_write(int fd, const void *buf, size_t count) +{ + /* _Py_write() must not be called with an exception set, otherwise the + * caller may think that write() was interrupted by a signal and the signal + * handler raised an exception. */ + assert(!PyErr_Occurred()); + + return _Py_write_impl(fd, buf, count, 1); +} + +/* Write count bytes of buf into fd. + * + * On success, return the number of written bytes, it can be lower than count + * including 0. On error, set errno and return -1. + * + * When interrupted by a signal (write() fails with EINTR), retry the syscall + * without calling the Python signal handler. */ +Py_ssize_t +_Py_write_noraise(int fd, const void *buf, size_t count) +{ + return _Py_write_impl(fd, buf, count, 0); +} + #ifdef HAVE_READLINK /* Read value of symbolic link. Encode the path to the locale encoding, decode -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Apr 1 18:51:56 2015 From: python-checkins at python.org (victor.stinner) Date: Wed, 01 Apr 2015 16:51:56 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2323836=3A_Use_=5FP?= =?utf-8?q?y=5Fwrite=5Fnoraise=28=29_to_retry_on_EINTR_in_child=5Fexec=28?= =?utf-8?q?=29_of?= Message-ID: <20150401165156.1888.8856@psf.io> https://hg.python.org/cpython/rev/e3c97621d8b4 changeset: 95358:e3c97621d8b4 user: Victor Stinner date: Wed Apr 01 18:35:53 2015 +0200 summary: Issue #23836: Use _Py_write_noraise() to retry on EINTR in child_exec() of _posixsubprocess files: Modules/_posixsubprocess.c | 19 ++++++++++--------- 1 files changed, 10 insertions(+), 9 deletions(-) diff --git a/Modules/_posixsubprocess.c b/Modules/_posixsubprocess.c --- a/Modules/_posixsubprocess.c +++ b/Modules/_posixsubprocess.c @@ -382,7 +382,7 @@ PyObject *preexec_fn, PyObject *preexec_fn_args_tuple) { - int i, saved_errno, unused, reached_preexec = 0; + int i, saved_errno, reached_preexec = 0; PyObject *result; const char* err_msg = ""; /* Buffer large enough to hold a hex integer. We can't malloc. */ @@ -496,28 +496,29 @@ saved_errno = errno; /* Report the posix error to our parent process. */ /* We ignore all write() return values as the total size of our writes is - * less than PIPEBUF and we cannot do anything about an error anyways. */ + less than PIPEBUF and we cannot do anything about an error anyways. + Use _Py_write_noraise() to retry write() if it is interrupted by a + signal (fails with EINTR). */ if (saved_errno) { char *cur; - unused = write(errpipe_write, "OSError:", 8); + _Py_write_noraise(errpipe_write, "OSError:", 8); cur = hex_errno + sizeof(hex_errno); while (saved_errno != 0 && cur > hex_errno) { *--cur = "0123456789ABCDEF"[saved_errno % 16]; saved_errno /= 16; } - unused = write(errpipe_write, cur, hex_errno + sizeof(hex_errno) - cur); - unused = write(errpipe_write, ":", 1); + _Py_write_noraise(errpipe_write, cur, hex_errno + sizeof(hex_errno) - cur); + _Py_write_noraise(errpipe_write, ":", 1); if (!reached_preexec) { /* Indicate to the parent that the error happened before exec(). */ - unused = write(errpipe_write, "noexec", 6); + _Py_write_noraise(errpipe_write, "noexec", 6); } /* We can't call strerror(saved_errno). It is not async signal safe. * The parent process will look the error message up. */ } else { - unused = write(errpipe_write, "SubprocessError:0:", 18); - unused = write(errpipe_write, err_msg, strlen(err_msg)); + _Py_write_noraise(errpipe_write, "SubprocessError:0:", 18); + _Py_write_noraise(errpipe_write, err_msg, strlen(err_msg)); } - if (unused) return; /* silly? yes! avoids gcc compiler warning. */ } -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Apr 1 18:51:56 2015 From: python-checkins at python.org (victor.stinner) Date: Wed, 01 Apr 2015 16:51:56 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2323836=3A_Use_=5FP?= =?utf-8?q?y=5Fwrite=5Fnoraise=28=29_to_retry_on_EINTR_in_=5FPy=5FDumpTrac?= =?utf-8?q?eback=28=29?= Message-ID: <20150401165156.2650.15697@psf.io> https://hg.python.org/cpython/rev/29ab05c5e9dc changeset: 95359:29ab05c5e9dc user: Victor Stinner date: Wed Apr 01 18:38:01 2015 +0200 summary: Issue #23836: Use _Py_write_noraise() to retry on EINTR in _Py_DumpTraceback() and _Py_DumpTracebackThreads(). Document also these functions to explain that the caller is responsible to call PyErr_CheckSignals(). files: Python/traceback.c | 28 ++++++++++++++++++++-------- 1 files changed, 20 insertions(+), 8 deletions(-) diff --git a/Python/traceback.c b/Python/traceback.c --- a/Python/traceback.c +++ b/Python/traceback.c @@ -13,7 +13,7 @@ #define OFF(x) offsetof(PyTracebackObject, x) -#define PUTS(fd, str) write(fd, str, (int)strlen(str)) +#define PUTS(fd, str) _Py_write_noraise(fd, str, (int)strlen(str)) #define MAX_STRING_LENGTH 500 #define MAX_FRAME_DEPTH 100 #define MAX_NTHREADS 100 @@ -512,7 +512,7 @@ len++; } while (value); reverse_string(buffer, len); - write(fd, buffer, len); + _Py_write_noraise(fd, buffer, len); } /* Format an integer in range [0; 0xffffffff] to hexadecimal of 'width' digits, @@ -532,7 +532,7 @@ len++; } while (len < width || value); reverse_string(buffer, len); - write(fd, buffer, len); + _Py_write_noraise(fd, buffer, len); } /* Write an unicode object into the file fd using ascii+backslashreplace. @@ -585,7 +585,7 @@ if (' ' <= ch && ch <= 126) { /* printable ASCII character */ char c = (char)ch; - write(fd, &c, 1); + _Py_write_noraise(fd, &c, 1); } else if (ch <= 0xff) { PUTS(fd, "\\x"); @@ -619,9 +619,9 @@ if (code != NULL && code->co_filename != NULL && PyUnicode_Check(code->co_filename)) { - write(fd, "\"", 1); + PUTS(fd, "\""); dump_ascii(fd, code->co_filename); - write(fd, "\"", 1); + PUTS(fd, "\""); } else { PUTS(fd, "???"); } @@ -638,7 +638,7 @@ else PUTS(fd, "???"); - write(fd, "\n", 1); + PUTS(fd, "\n"); } static void @@ -668,6 +668,12 @@ } } +/* Dump the traceback of a Python thread into fd. Use write() to write the + traceback and retry if write() is interrupted by a signal (failed with + EINTR), but don't call the Python signal handler. + + The caller is responsible to call PyErr_CheckSignals() to call Python signal + handlers if signals were received. */ void _Py_DumpTraceback(int fd, PyThreadState *tstate) { @@ -690,6 +696,12 @@ PUTS(fd, " (most recent call first):\n"); } +/* Dump the traceback of all Python threads into fd. Use write() to write the + traceback and retry if write() is interrupted by a signal (failed with + EINTR), but don't call the Python signal handler. + + The caller is responsible to call PyErr_CheckSignals() to call Python signal + handlers if signals were received. */ const char* _Py_DumpTracebackThreads(int fd, PyInterpreterState *interp, PyThreadState *current_thread) @@ -708,7 +720,7 @@ do { if (nthreads != 0) - write(fd, "\n", 1); + PUTS(fd, "\n"); if (nthreads >= MAX_NTHREADS) { PUTS(fd, "...\n"); break; -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Apr 1 18:51:56 2015 From: python-checkins at python.org (victor.stinner) Date: Wed, 01 Apr 2015 16:51:56 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2323836=3A_Use_=5FP?= =?utf-8?q?y=5Fwrite=5Fnoraise=28=29_to_retry_on_EINTR_in_trip=5Fsignal=28?= =?utf-8?q?=29_of?= Message-ID: <20150401165156.1918.344@psf.io> https://hg.python.org/cpython/rev/12e065efc821 changeset: 95357:12e065efc821 user: Victor Stinner date: Wed Apr 01 18:35:22 2015 +0200 summary: Issue #23836: Use _Py_write_noraise() to retry on EINTR in trip_signal() of signalmodule.c files: Modules/signalmodule.c | 7 ++++--- 1 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Modules/signalmodule.c b/Modules/signalmodule.c --- a/Modules/signalmodule.c +++ b/Modules/signalmodule.c @@ -263,9 +263,10 @@ #endif { byte = (unsigned char)sig_num; - do { - rc = write(fd, &byte, 1); - } while (rc < 0 && errno == EINTR); + + /* _Py_write_noraise() retries write() if write() is interrupted by + a signal (fails with EINTR). */ + rc = _Py_write_noraise(fd, &byte, 1); if (rc < 0) { Py_AddPendingCall(report_wakeup_write_error, -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Apr 1 18:51:56 2015 From: python-checkins at python.org (victor.stinner) Date: Wed, 01 Apr 2015 16:51:56 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2323836=3A_Fix_the_?= =?utf-8?q?faulthandler_module_to_handle_reentrant_calls?= Message-ID: <20150401165156.1908.53736@psf.io> https://hg.python.org/cpython/rev/f07b855afbb2 changeset: 95360:f07b855afbb2 user: Victor Stinner date: Wed Apr 01 18:48:58 2015 +0200 summary: Issue #23836: Fix the faulthandler module to handle reentrant calls to its signal handlers. Use also _Py_write_noraise() instead of write() to retry write() if it is interrupted by a signal (fail with EINTR). faulthandler.dump_traceback() also calls PyErr_CheckSignals() to call the Python signal handler if a signal was received. files: Misc/NEWS | 3 + Modules/faulthandler.c | 85 +++++++++++++++-------------- 2 files changed, 48 insertions(+), 40 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -13,6 +13,9 @@ Library ------- +- Issue #23836: Fix the faulthandler module to handle reentrant calls to + its signal handlers. + - Issue #23838: linecache now clears the cache and returns an empty result on MemoryError. diff --git a/Modules/faulthandler.c b/Modules/faulthandler.c --- a/Modules/faulthandler.c +++ b/Modules/faulthandler.c @@ -28,9 +28,7 @@ # define FAULTHANDLER_USER #endif -/* cast size_t to int because write() takes an int on Windows - (anyway, the length is smaller than 30 characters) */ -#define PUTS(fd, str) write(fd, str, (int)strlen(str)) +#define PUTS(fd, str) _Py_write_noraise(fd, str, strlen(str)) _Py_IDENTIFIER(enable); _Py_IDENTIFIER(fileno); @@ -213,6 +211,42 @@ return tstate; } +static void +faulthandler_dump_traceback(int fd, int all_threads, + PyInterpreterState *interp) +{ + static volatile int reentrant = 0; + PyThreadState *tstate; + + if (reentrant) + return; + + reentrant = 1; + +#ifdef WITH_THREAD + /* SIGSEGV, SIGFPE, SIGABRT, SIGBUS and SIGILL are synchronous signals and + are thus delivered to the thread that caused the fault. Get the Python + thread state of the current thread. + + PyThreadState_Get() doesn't give the state of the thread that caused the + fault if the thread released the GIL, and so this function cannot be + used. Read the thread local storage (TLS) instead: call + PyGILState_GetThisThreadState(). */ + tstate = PyGILState_GetThisThreadState(); +#else + tstate = PyThreadState_Get(); +#endif + + if (all_threads) + _Py_DumpTracebackThreads(fd, interp, tstate); + else { + if (tstate != NULL) + _Py_DumpTraceback(fd, tstate); + } + + reentrant = 0; +} + static PyObject* faulthandler_dump_traceback_py(PyObject *self, PyObject *args, PyObject *kwargs) @@ -247,6 +281,10 @@ else { _Py_DumpTraceback(fd, tstate); } + + if (PyErr_CheckSignals()) + return NULL; + Py_RETURN_NONE; } @@ -270,7 +308,6 @@ const int fd = fatal_error.fd; unsigned int i; fault_handler_t *handler = NULL; - PyThreadState *tstate; int save_errno = errno; if (!fatal_error.enabled) @@ -298,26 +335,8 @@ PUTS(fd, handler->name); PUTS(fd, "\n\n"); -#ifdef WITH_THREAD - /* SIGSEGV, SIGFPE, SIGABRT, SIGBUS and SIGILL are synchronous signals and - are thus delivered to the thread that caused the fault. Get the Python - thread state of the current thread. - - PyThreadState_Get() doesn't give the state of the thread that caused the - fault if the thread released the GIL, and so this function cannot be - used. Read the thread local storage (TLS) instead: call - PyGILState_GetThisThreadState(). */ - tstate = PyGILState_GetThisThreadState(); -#else - tstate = PyThreadState_Get(); -#endif - - if (fatal_error.all_threads) - _Py_DumpTracebackThreads(fd, fatal_error.interp, tstate); - else { - if (tstate != NULL) - _Py_DumpTraceback(fd, tstate); - } + faulthandler_dump_traceback(fd, fatal_error.all_threads, + fatal_error.interp); errno = save_errno; #ifdef MS_WINDOWS @@ -474,7 +493,7 @@ /* get the thread holding the GIL, NULL if no thread hold the GIL */ current = (PyThreadState*)_Py_atomic_load_relaxed(&_PyThreadState_Current); - write(thread.fd, thread.header, (int)thread.header_len); + _Py_write_noraise(thread.fd, thread.header, (int)thread.header_len); errmsg = _Py_DumpTracebackThreads(thread.fd, thread.interp, current); ok = (errmsg == NULL); @@ -660,28 +679,14 @@ faulthandler_user(int signum) { user_signal_t *user; - PyThreadState *tstate; int save_errno = errno; user = &user_signals[signum]; if (!user->enabled) return; -#ifdef WITH_THREAD - /* PyThreadState_Get() doesn't give the state of the current thread if - the thread doesn't hold the GIL. Read the thread local storage (TLS) - instead: call PyGILState_GetThisThreadState(). */ - tstate = PyGILState_GetThisThreadState(); -#else - tstate = PyThreadState_Get(); -#endif + faulthandler_dump_traceback(user->fd, user->all_threads, user->interp); - if (user->all_threads) - _Py_DumpTracebackThreads(user->fd, user->interp, tstate); - else { - if (tstate != NULL) - _Py_DumpTraceback(user->fd, tstate); - } #ifdef HAVE_SIGACTION if (user->chain) { (void)sigaction(signum, &user->previous, NULL); -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Apr 1 22:14:49 2015 From: python-checkins at python.org (victor.stinner) Date: Wed, 01 Apr 2015 20:14:49 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2323834=3A_Add_sock?= =?utf-8?q?=5Fcall=28=29_helper_function?= Message-ID: <20150401201449.15197.57123@psf.io> https://hg.python.org/cpython/rev/358a2bcd0d0b changeset: 95361:358a2bcd0d0b user: Victor Stinner date: Wed Apr 01 21:57:09 2015 +0200 summary: Issue #23834: Add sock_call() helper function The BEGIN_SELECT_LOOP and END_SELECT_LOOP macros of socketmodule.c don't handle EINTR. Functions using these macros use an inner loop to handle EINTR, but they don't recompute the timeout. This changes replaces the two macros with a new sock_call() function which takes a function as a parameter. sock_call() recomputes the timeout, handle false positive and handle EINTR. files: Modules/socketmodule.c | 593 ++++++++++++++++------------ 1 files changed, 330 insertions(+), 263 deletions(-) diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -683,45 +683,113 @@ return internal_select_impl(s, 1, s->sock_timeout, 1); } -/* - Two macros for automatic retry of select() in case of false positives - (for example, select() could indicate a socket is ready for reading - but the data then discarded by the OS because of a wrong checksum). - Here is an example of use: - - BEGIN_SELECT_LOOP(s) - - timeout = internal_select(s, 0, interval); - - if (!timeout) { - Py_BEGIN_ALLOW_THREADS - outlen = recv(s->sock_fd, cbuf, len, flags); - Py_END_ALLOW_THREADS - } - if (timeout == 1) { - PyErr_SetString(socket_timeout, "timed out"); +/* Call a socket function. + + Raise an exception and return -1 on error, return 0 on success. + + If the socket has a timeout, wait until the socket is ready before calling + the function: wait until the socket is writable if writing is nonzero, wait + until the socket received data otherwise. + + If the function func is interrupted by a signal (failed with EINTR): retry + the function, except if the signal handler raised an exception (PEP 475). + + When the function is retried, recompute the timeout using a monotonic clock. + + sock_call() must be called with the GIL held. The function func is called + with the GIL released. */ +static int +sock_call(PySocketSockObject *s, + int writing, + int (*func) (PySocketSockObject *s, void *data), + void *data) +{ + int has_timeout = (s->sock_timeout > 0); + _PyTime_t deadline = 0; + int deadline_initialized = 0; + int res; + + /* sock_call() must be called with the GIL held. */ + assert(PyGILState_Check()); + + /* outer loop to retry select() when select() is interrupted by a signal + or to retry select()+func() on false positive (see above) */ + while (1) { + if (has_timeout) { + _PyTime_t interval; + + if (deadline_initialized) { + /* recompute the timeout */ + interval = deadline - _PyTime_GetMonotonicClock(); + } + else { + deadline = _PyTime_GetMonotonicClock() + s->sock_timeout; + interval = s->sock_timeout; + } + + res = internal_select(s, writing, interval); + if (res == -1) { + if (CHECK_ERRNO(EINTR)) { + /* select() was interrupted by a signal */ + if (PyErr_CheckSignals()) + return -1; + + /* retry select() */ + continue; + } + + /* select() failed */ + s->errorhandler(); + return -1; + } + + if (res == 1) { + PyErr_SetString(socket_timeout, "timed out"); + return -1; + } + + /* the socket is ready */ + } + + /* inner loop to retry func() when func() is interrupted by a signal */ + while (1) { + Py_BEGIN_ALLOW_THREADS + res = func(s, data); + Py_END_ALLOW_THREADS + + if (res) { + /* func() succeeded */ + return 0; + } + + if (!CHECK_ERRNO(EINTR)) + break; + + /* func() was interrupted by a signal */ + if (PyErr_CheckSignals()) + return -1; + + /* retry func() */ + } + + if (s->sock_timeout > 0 + && (CHECK_ERRNO(EWOULDBLOCK) || CHECK_ERRNO(EAGAIN))) { + /* False positive: func() failed with EWOULDBLOCK or EAGAIN. + + For example, select() could indicate a socket is ready for + reading, but the data then discarded by the OS because of a + wrong checksum. + + Loop on select() to recheck for socket readyness. */ + continue; + } + + /* func() failed */ + s->errorhandler(); return -1; } - END_SELECT_LOOP(s) -*/ - -#define BEGIN_SELECT_LOOP(s) \ - { \ - _PyTime_t deadline = 0; \ - _PyTime_t interval = s->sock_timeout; \ - int has_timeout = (s->sock_timeout > 0); \ - if (has_timeout) \ - deadline = _PyTime_GetMonotonicClock() + interval; \ - while (1) { \ - errno = 0; \ - -#define END_SELECT_LOOP(s) \ - if (!has_timeout || \ - (!CHECK_ERRNO(EWOULDBLOCK) && !CHECK_ERRNO(EAGAIN))) \ - break; \ - interval = deadline - _PyTime_GetMonotonicClock(); \ - } \ - } \ +} + /* Initialize a new socket object. */ @@ -2061,23 +2129,51 @@ #endif /* CMSG_LEN */ +struct sock_accept { + socklen_t *addrlen; + sock_addr_t *addrbuf; + SOCKET_T result; +}; + +#if defined(HAVE_ACCEPT4) && defined(SOCK_CLOEXEC) +/* accept4() is available on Linux 2.6.28+ and glibc 2.10 */ +static int accept4_works = -1; +#endif + +static int +sock_accept_impl(PySocketSockObject *s, void *data) +{ + struct sock_accept *ctx = data; + +#if defined(HAVE_ACCEPT4) && defined(SOCK_CLOEXEC) + if (accept4_works != 0) { + ctx->result = accept4(s->sock_fd, SAS2SA(ctx->addrbuf), ctx->addrlen, + SOCK_CLOEXEC); + if (ctx->result == INVALID_SOCKET && accept4_works == -1) { + /* On Linux older than 2.6.28, accept4() fails with ENOSYS */ + accept4_works = (errno != ENOSYS); + } + } + if (accept4_works == 0) + ctx->result = accept(s->sock_fd, SAS2SA(ctx->addrbuf), ctx->addrlen); +#else + ctx->result = accept(s->sock_fd, SAS2SA(ctx->addrbuf), ctx->addrlen); +#endif + return (ctx->result >= 0); +} + /* s._accept() -> (fd, address) */ static PyObject * sock_accept(PySocketSockObject *s) { sock_addr_t addrbuf; - SOCKET_T newfd = INVALID_SOCKET; + SOCKET_T newfd; socklen_t addrlen; PyObject *sock = NULL; PyObject *addr = NULL; PyObject *res = NULL; - int timeout; - int async_err = 0; -#if defined(HAVE_ACCEPT4) && defined(SOCK_CLOEXEC) - /* accept4() is available on Linux 2.6.28+ and glibc 2.10 */ - static int accept4_works = -1; -#endif + struct sock_accept ctx; if (!getsockaddrlen(s, &addrlen)) return NULL; @@ -2086,37 +2182,11 @@ if (!IS_SELECTABLE(s)) return select_error(); - BEGIN_SELECT_LOOP(s) - do { - timeout = internal_select(s, 0, interval); - - if (!timeout) { - Py_BEGIN_ALLOW_THREADS -#if defined(HAVE_ACCEPT4) && defined(SOCK_CLOEXEC) - if (accept4_works != 0) { - newfd = accept4(s->sock_fd, SAS2SA(&addrbuf), &addrlen, - SOCK_CLOEXEC); - if (newfd == INVALID_SOCKET && accept4_works == -1) { - /* On Linux older than 2.6.28, accept4() fails with ENOSYS */ - accept4_works = (errno != ENOSYS); - } - } - if (accept4_works == 0) - newfd = accept(s->sock_fd, SAS2SA(&addrbuf), &addrlen); -#else - newfd = accept(s->sock_fd, SAS2SA(&addrbuf), &addrlen); -#endif - Py_END_ALLOW_THREADS - } - } while (newfd < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); - if (timeout == 1) { - PyErr_SetString(socket_timeout, "timed out"); + ctx.addrlen = &addrlen; + ctx.addrbuf = &addrbuf; + if (sock_call(s, 0, sock_accept_impl, &ctx) < 0) return NULL; - } - END_SELECT_LOOP(s) - - if (newfd == INVALID_SOCKET) - return (!async_err) ? s->errorhandler() : NULL; + newfd = ctx.result; #ifdef MS_WINDOWS if (!SetHandleInformation((HANDLE)newfd, HANDLE_FLAG_INHERIT, 0)) { @@ -2690,6 +2760,28 @@ unaccepted connections that the system will allow before refusing new\n\ connections. If not specified, a default reasonable value is chosen."); +struct sock_recv { + char *cbuf; + Py_ssize_t len; + int flags; + Py_ssize_t result; +}; + +static int +sock_recv_impl(PySocketSockObject *s, void *data) +{ + struct sock_recv *ctx = data; + +#ifdef MS_WINDOWS + if (ctx->len > INT_MAX) + ctx->len = INT_MAX; + ctx->result = recv(s->sock_fd, ctx->cbuf, (int)ctx->len, ctx->flags); +#else + ctx->result = recv(s->sock_fd, ctx->cbuf, ctx->len, ctx->flags); +#endif + return (ctx->result >= 0); +} + /* * This is the guts of the recv() and recv_into() methods, which reads into a @@ -2703,9 +2795,7 @@ static Py_ssize_t sock_recv_guts(PySocketSockObject *s, char* cbuf, Py_ssize_t len, int flags) { - Py_ssize_t outlen = -1; - int timeout; - int async_err = 0; + struct sock_recv ctx; if (!IS_SELECTABLE(s)) { select_error(); @@ -2716,36 +2806,13 @@ return 0; } - BEGIN_SELECT_LOOP(s) - do { - timeout = internal_select(s, 0, interval); - - if (!timeout) { - Py_BEGIN_ALLOW_THREADS -#ifdef MS_WINDOWS - if (len > INT_MAX) - len = INT_MAX; - outlen = recv(s->sock_fd, cbuf, (int)len, flags); -#else - outlen = recv(s->sock_fd, cbuf, len, flags); -#endif - Py_END_ALLOW_THREADS - } - } while (outlen < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); - - if (timeout == 1) { - PyErr_SetString(socket_timeout, "timed out"); + ctx.cbuf = cbuf; + ctx.len = len; + ctx.flags = flags; + if (sock_call(s, 0, sock_recv_impl, &ctx) < 0) return -1; - } - END_SELECT_LOOP(s) - if (outlen < 0) { - /* Note: the call to errorhandler() ALWAYS indirectly returned - NULL, so ignore its return value */ - if (!async_err) - s->errorhandler(); - return -1; - } - return outlen; + + return ctx.result; } @@ -2859,6 +2926,34 @@ \n\ See recv() for documentation about the flags."); +struct sock_recvfrom { + char* cbuf; + Py_ssize_t len; + int flags; + socklen_t *addrlen; + sock_addr_t *addrbuf; + Py_ssize_t result; +}; + +static int +sock_recvfrom_impl(PySocketSockObject *s, void *data) +{ + struct sock_recvfrom *ctx = data; + + memset(ctx->addrbuf, 0, *ctx->addrlen); + +#ifdef MS_WINDOWS + if (ctx->len > INT_MAX) + ctx->len = INT_MAX; + ctx->result = recvfrom(s->sock_fd, ctx->cbuf, (int)ctx->len, ctx->flags, + SAS2SA(ctx->addrbuf), ctx->addrlen); +#else + ctx->result = recvfrom(s->sock_fd, ctx->cbuf, ctx->len, ctx->flags, + SAS2SA(ctx->addrbuf), ctx->addrlen); +#endif + return (ctx->result >= 0); +} + /* * This is the guts of the recvfrom() and recvfrom_into() methods, which reads @@ -2876,10 +2971,8 @@ PyObject** addr) { sock_addr_t addrbuf; - int timeout; - Py_ssize_t n = -1; socklen_t addrlen; - int async_err = 0; + struct sock_recvfrom ctx; *addr = NULL; @@ -2891,42 +2984,20 @@ return -1; } - BEGIN_SELECT_LOOP(s) - do { - memset(&addrbuf, 0, addrlen); - timeout = internal_select(s, 0, interval); - - if (!timeout) { - Py_BEGIN_ALLOW_THREADS -#ifdef MS_WINDOWS - if (len > INT_MAX) - len = INT_MAX; - n = recvfrom(s->sock_fd, cbuf, (int)len, flags, - (void *) &addrbuf, &addrlen); -#else - n = recvfrom(s->sock_fd, cbuf, len, flags, - SAS2SA(&addrbuf), &addrlen); -#endif - Py_END_ALLOW_THREADS - } - } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); - - if (timeout == 1) { - PyErr_SetString(socket_timeout, "timed out"); + ctx.cbuf = cbuf; + ctx.len = len; + ctx.flags = flags; + ctx.addrbuf = &addrbuf; + ctx.addrlen = &addrlen; + if (sock_call(s, 0, sock_recvfrom_impl, &ctx) < 0) return -1; - } - END_SELECT_LOOP(s) - if (n < 0) { - if (!async_err) - s->errorhandler(); + + *addr = makesockaddr(s->sock_fd, SAS2SA(&addrbuf), addrlen, + s->sock_proto); + if (*addr == NULL) return -1; - } - - if (!(*addr = makesockaddr(s->sock_fd, SAS2SA(&addrbuf), - addrlen, s->sock_proto))) - return -1; - - return n; + + return ctx.result; } /* s.recvfrom(nbytes [,flags]) method */ @@ -3037,6 +3108,21 @@ \n\ Like recv_into(buffer[, nbytes[, flags]]) but also return the sender's address info."); +struct sock_recvmsg { + struct msghdr *msg; + int flags; + ssize_t result; +}; + +static int +sock_recvmsg_impl(PySocketSockObject *s, void *data) +{ + struct sock_recvmsg *ctx = data; + + ctx->result = recvmsg(s->sock_fd, ctx->msg, ctx->flags); + return (ctx->result >= 0); +} + /* The sendmsg() and recvmsg[_into]() methods require a working CMSG_LEN(). See the comment near get_CMSG_LEN(). */ @@ -3056,9 +3142,6 @@ int flags, Py_ssize_t controllen, PyObject *(*makeval)(ssize_t, void *), void *makeval_data) { - ssize_t bytes_received = -1; - int timeout; - int async_err = 0; sock_addr_t addrbuf; socklen_t addrbuflen; struct msghdr msg = {0}; @@ -3067,6 +3150,7 @@ struct cmsghdr *cmsgh; size_t cmsgdatalen = 0; int cmsg_status; + struct sock_recvmsg ctx; /* XXX: POSIX says that msg_name and msg_namelen "shall be ignored" when the socket is connected (Linux fills them in @@ -3093,35 +3177,17 @@ goto finally; } - BEGIN_SELECT_LOOP(s) - do { - msg.msg_name = SAS2SA(&addrbuf); - msg.msg_namelen = addrbuflen; - msg.msg_iov = iov; - msg.msg_iovlen = iovlen; - msg.msg_control = controlbuf; - msg.msg_controllen = controllen; - timeout = internal_select(s, 0, interval); - - if (timeout == 1) { - PyErr_SetString(socket_timeout, "timed out"); - goto finally; - } - - if (!timeout) { - Py_BEGIN_ALLOW_THREADS; - bytes_received = recvmsg(s->sock_fd, &msg, flags); - Py_END_ALLOW_THREADS; - } - } while (bytes_received < 0 && errno == EINTR && - !(async_err = PyErr_CheckSignals())); - END_SELECT_LOOP(s) - - if (bytes_received < 0) { - if (!async_err) - s->errorhandler(); + msg.msg_name = SAS2SA(&addrbuf); + msg.msg_namelen = addrbuflen; + msg.msg_iov = iov; + msg.msg_iovlen = iovlen; + msg.msg_control = controlbuf; + msg.msg_controllen = controllen; + + ctx.msg = &msg; + ctx.flags = flags; + if (sock_call(s, 0, sock_recvmsg_impl, &ctx) < 0) goto finally; - } /* Make list of (level, type, data) tuples from control messages. */ if ((cmsg_list = PyList_New(0)) == NULL) @@ -3163,7 +3229,7 @@ } retval = Py_BuildValue("NOiN", - (*makeval)(bytes_received, makeval_data), + (*makeval)(ctx.result, makeval_data), cmsg_list, (int)msg.msg_flags, makesockaddr(s->sock_fd, SAS2SA(&addrbuf), @@ -3371,16 +3437,36 @@ #endif /* CMSG_LEN */ +struct sock_send { + char *buf; + Py_ssize_t len; + int flags; + Py_ssize_t result; +}; + +static int +sock_send_impl(PySocketSockObject *s, void *data) +{ + struct sock_send *ctx = data; + +#ifdef MS_WINDOWS + if (ctx->len > INT_MAX) + ctx->len = INT_MAX; + ctx->result = send(s->sock_fd, ctx->buf, (int)ctx->len, ctx->flags); +#else + ctx->result = send(s->sock_fd, ctx->buf, ctx->len, ctx->flags); +#endif + return (ctx->result >= 0); +} + /* s.send(data [,flags]) method */ static PyObject * sock_send(PySocketSockObject *s, PyObject *args) { - char *buf; - Py_ssize_t len, n = -1; - int async_err = 0; - int flags = 0, timeout; + int flags = 0; Py_buffer pbuf; + struct sock_send ctx; if (!PyArg_ParseTuple(args, "y*|i:send", &pbuf, &flags)) return NULL; @@ -3389,36 +3475,16 @@ PyBuffer_Release(&pbuf); return select_error(); } - buf = pbuf.buf; - len = pbuf.len; - - BEGIN_SELECT_LOOP(s) - do { - timeout = internal_select(s, 1, interval); - - if (!timeout) { - Py_BEGIN_ALLOW_THREADS -#ifdef MS_WINDOWS - if (len > INT_MAX) - len = INT_MAX; - n = send(s->sock_fd, buf, (int)len, flags); -#else - n = send(s->sock_fd, buf, len, flags); -#endif - Py_END_ALLOW_THREADS - } - } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); - if (timeout == 1) { + ctx.buf = pbuf.buf; + ctx.len = pbuf.len; + ctx.flags = flags; + if (sock_call(s, 1, sock_send_impl, &ctx) < 0) { PyBuffer_Release(&pbuf); - PyErr_SetString(socket_timeout, "timed out"); return NULL; } - END_SELECT_LOOP(s) - PyBuffer_Release(&pbuf); - if (n < 0) - return (!async_err) ? s->errorhandler() : NULL; - return PyLong_FromSsize_t(n); + + return PyLong_FromSsize_t(ctx.result); } PyDoc_STRVAR(send_doc, @@ -3494,6 +3560,32 @@ to tell how much data has been sent."); +struct sock_sendto { + char *buf; + Py_ssize_t len; + int flags; + int addrlen; + sock_addr_t *addrbuf; + Py_ssize_t result; +}; + +static int +sock_sendto_impl(PySocketSockObject *s, void *data) +{ + struct sock_sendto *ctx = data; + +#ifdef MS_WINDOWS + if (ctx->len > INT_MAX) + ctx->len = INT_MAX; + ctx->result = sendto(s->sock_fd, ctx->buf, (int)ctx->len, ctx->flags, + SAS2SA(ctx->addrbuf), ctx->addrlen); +#else + ctx->result = sendto(s->sock_fd, ctx->buf, ctx->len, ctx->flags, + SAS2SA(ctx->addrbuf), ctx->addrlen); +#endif + return (ctx->result >= 0); +} + /* s.sendto(data, [flags,] sockaddr) method */ static PyObject * @@ -3501,11 +3593,10 @@ { Py_buffer pbuf; PyObject *addro; - char *buf; - Py_ssize_t len, arglen; + Py_ssize_t arglen; sock_addr_t addrbuf; - int addrlen, n = -1, flags, timeout; - int async_err = 0; + int addrlen, flags; + struct sock_sendto ctx; flags = 0; arglen = PyTuple_Size(args); @@ -3526,9 +3617,6 @@ if (PyErr_Occurred()) return NULL; - buf = pbuf.buf; - len = pbuf.len; - if (!IS_SELECTABLE(s)) { PyBuffer_Release(&pbuf); return select_error(); @@ -3539,35 +3627,18 @@ return NULL; } - BEGIN_SELECT_LOOP(s) - do { - timeout = internal_select(s, 1, interval); - - if (!timeout) { - Py_BEGIN_ALLOW_THREADS -#ifdef MS_WINDOWS - if (len > INT_MAX) - len = INT_MAX; - n = sendto(s->sock_fd, buf, (int)len, flags, - SAS2SA(&addrbuf), addrlen); -#else - n = sendto(s->sock_fd, buf, len, flags, - SAS2SA(&addrbuf), addrlen); -#endif - Py_END_ALLOW_THREADS - } - } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); - - if (timeout == 1) { + ctx.buf = pbuf.buf; + ctx.len = pbuf.len; + ctx.flags = flags; + ctx.addrlen = addrlen; + ctx.addrbuf = &addrbuf; + if (sock_call(s, 1, sock_sendto_impl, &ctx) < 0) { PyBuffer_Release(&pbuf); - PyErr_SetString(socket_timeout, "timed out"); return NULL; } - END_SELECT_LOOP(s) PyBuffer_Release(&pbuf); - if (n < 0) - return (!async_err) ? s->errorhandler() : NULL; - return PyLong_FromSsize_t(n); + + return PyLong_FromSsize_t(ctx.result); } PyDoc_STRVAR(sendto_doc, @@ -3577,6 +3648,21 @@ For IP sockets, the address is a pair (hostaddr, port)."); +struct sock_sendmsg { + struct msghdr *msg; + int flags; + ssize_t result; +}; + +static int +sock_sendmsg_impl(PySocketSockObject *s, void *data) +{ + struct sock_sendmsg *ctx = data; + + ctx->result = sendmsg(s->sock_fd, ctx->msg, ctx->flags); + return (ctx->result >= 0); +} + /* The sendmsg() and recvmsg[_into]() methods require a working CMSG_LEN(). See the comment near get_CMSG_LEN(). */ #ifdef CMSG_LEN @@ -3597,11 +3683,10 @@ } *cmsgs = NULL; void *controlbuf = NULL; size_t controllen, controllen_last; - ssize_t bytes_sent = -1; - int async_err = 0; - int addrlen, timeout, flags = 0; + int addrlen, flags = 0; PyObject *data_arg, *cmsg_arg = NULL, *addr_arg = NULL, *data_fast = NULL, *cmsg_fast = NULL, *retval = NULL; + struct sock_sendmsg ctx; if (!PyArg_ParseTuple(args, "O|OiO:sendmsg", &data_arg, &cmsg_arg, &flags, &addr_arg)) @@ -3755,30 +3840,12 @@ goto finally; } - BEGIN_SELECT_LOOP(s) - do { - timeout = internal_select(s, 1, interval); - - if (!timeout) { - Py_BEGIN_ALLOW_THREADS; - bytes_sent = sendmsg(s->sock_fd, &msg, flags); - Py_END_ALLOW_THREADS; - } - - if (timeout == 1) { - PyErr_SetString(socket_timeout, "timed out"); - goto finally; - } - } while (bytes_sent < 0 && errno == EINTR && - !(async_err = PyErr_CheckSignals())); - END_SELECT_LOOP(s) - - if (bytes_sent < 0) { - if (!async_err) - s->errorhandler(); + ctx.msg = &msg; + ctx.flags = flags; + if (sock_call(s, 1, sock_sendmsg_impl, &ctx) < 0) goto finally; - } - retval = PyLong_FromSsize_t(bytes_sent); + + retval = PyLong_FromSsize_t(ctx.result); finally: PyMem_Free(controlbuf); -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Apr 1 23:23:21 2015 From: python-checkins at python.org (victor.stinner) Date: Wed, 01 Apr 2015 21:23:21 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2323834=3A_Modify_s?= =?utf-8?q?ocket=2Esendall=28=29_to_reuse_sock=5Fcall=28=29_with?= Message-ID: <20150401212321.59558.40502@psf.io> https://hg.python.org/cpython/rev/b3c7ae99b8e0 changeset: 95362:b3c7ae99b8e0 user: Victor Stinner date: Wed Apr 01 22:53:26 2015 +0200 summary: Issue #23834: Modify socket.sendall() to reuse sock_call() with sock_send_impl() files: Modules/socketmodule.c | 50 ++++++++++++----------------- 1 files changed, 21 insertions(+), 29 deletions(-) diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -3501,10 +3501,10 @@ sock_sendall(PySocketSockObject *s, PyObject *args) { char *buf; - Py_ssize_t len, n = -1; - int async_err = 0; - int flags = 0, timeout; + Py_ssize_t len, n; + int flags = 0; Py_buffer pbuf; + struct sock_send ctx; if (!PyArg_ParseTuple(args, "y*|i:sendall", &pbuf, &flags)) return NULL; @@ -3517,38 +3517,30 @@ } do { - timeout = internal_select(s, 1, s->sock_timeout); - - n = -1; - if (!timeout) { - Py_BEGIN_ALLOW_THREADS -#ifdef MS_WINDOWS - if (len > INT_MAX) - len = INT_MAX; - n = send(s->sock_fd, buf, (int)len, flags); -#else - n = send(s->sock_fd, buf, len, flags); -#endif - Py_END_ALLOW_THREADS - } - if (timeout == 1) { + ctx.buf = buf; + ctx.len = len; + ctx.flags = flags; + if (sock_call(s, 1, sock_send_impl, &ctx) < 0) { PyBuffer_Release(&pbuf); - PyErr_SetString(socket_timeout, "timed out"); return NULL; } - if (n >= 0) { - buf += n; - len -= n; + n = ctx.result; + assert(n >= 0); + + buf += n; + len -= n; + + /* We must run our signal handlers before looping again. + send() can return a successful partial write when it is + interrupted, so we can't restrict ourselves to EINTR. */ + if (PyErr_CheckSignals()) { + PyBuffer_Release(&pbuf); + return NULL; } - } while (len > 0 && (n >= 0 || errno == EINTR) && - !(async_err = PyErr_CheckSignals())); + } while (len > 0); PyBuffer_Release(&pbuf); - if (n < 0 || async_err) - return (!async_err) ? s->errorhandler() : NULL; - - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; } PyDoc_STRVAR(sendall_doc, -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Apr 2 03:23:15 2015 From: python-checkins at python.org (victor.stinner) Date: Thu, 02 Apr 2015 01:23:15 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2323834=3A_Fix_sock?= =?utf-8?q?=5Fcall=28=29=2C_set_deadline=5Finitialized_to_recompute_the_ti?= =?utf-8?q?meout?= Message-ID: <20150402012315.14221.35860@psf.io> https://hg.python.org/cpython/rev/920b700d9509 changeset: 95363:920b700d9509 user: Victor Stinner date: Thu Apr 02 03:22:49 2015 +0200 summary: Issue #23834: Fix sock_call(), set deadline_initialized to recompute the timeout files: Modules/socketmodule.c | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -723,6 +723,7 @@ interval = deadline - _PyTime_GetMonotonicClock(); } else { + deadline_initialized = 1; deadline = _PyTime_GetMonotonicClock() + s->sock_timeout; interval = s->sock_timeout; } -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Apr 2 06:08:23 2015 From: python-checkins at python.org (benjamin.peterson) Date: Thu, 02 Apr 2015 04:08:23 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E4=29=3A_replace_512_bi?= =?utf-8?q?t_dh_key_with_a_2014_bit_one_=28closes_=2323844=29?= Message-ID: <20150402040823.15225.66493@psf.io> https://hg.python.org/cpython/rev/1ad7c0253abe changeset: 95364:1ad7c0253abe branch: 3.4 parent: 95352:47451f6e7e75 user: Benjamin Peterson date: Thu Apr 02 00:04:06 2015 -0400 summary: replace 512 bit dh key with a 2014 bit one (closes #23844) Patch by C?dric Krier. files: Lib/test/dh1024.pem | 7 +++++++ Lib/test/dh512.pem | 9 --------- Lib/test/test_ssl.py | 2 +- 3 files changed, 8 insertions(+), 10 deletions(-) diff --git a/Lib/test/dh1024.pem b/Lib/test/dh1024.pem new file mode 100644 --- /dev/null +++ b/Lib/test/dh1024.pem @@ -0,0 +1,7 @@ +-----BEGIN DH PARAMETERS----- +MIGHAoGBAIbzw1s9CT8SV5yv6L7esdAdZYZjPi3qWFs61CYTFFQnf2s/d09NYaJt +rrvJhIzWavqnue71qXCf83/J3nz3FEwUU/L0mGyheVbsSHiI64wUo3u50wK5Igo0 +RNs/LD0irs7m0icZ//hijafTU+JOBiuA8zMI+oZfU7BGuc9XrUprAgEC +-----END DH PARAMETERS----- + +Generated with: openssl dhparam -out dh1024.pem 1024 diff --git a/Lib/test/dh512.pem b/Lib/test/dh512.pem deleted file mode 100644 --- a/Lib/test/dh512.pem +++ /dev/null @@ -1,9 +0,0 @@ ------BEGIN DH PARAMETERS----- -MEYCQQD1Kv884bEpQBgRjXyEpwpy1obEAxnIByl6ypUM2Zafq9AKUJsCRtMIPWak -XUGfnHy9iUsiGSa6q6Jew1XpKgVfAgEC ------END DH PARAMETERS----- - -These are the 512 bit DH parameters from "Assigned Number for SKIP Protocols" -(http://www.skip-vpn.org/spec/numbers.html). -See there for how they were generated. -Note that g is not a generator, but this is not a problem since p is a safe prime. diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py --- a/Lib/test/test_ssl.py +++ b/Lib/test/test_ssl.py @@ -64,7 +64,7 @@ NOKIACERT = data_file("nokia.pem") NULLBYTECERT = data_file("nullbytecert.pem") -DHFILE = data_file("dh512.pem") +DHFILE = data_file("dh1024.pem") BYTES_DHFILE = os.fsencode(DHFILE) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Apr 2 06:08:23 2015 From: python-checkins at python.org (benjamin.peterson) Date: Thu, 02 Apr 2015 04:08:23 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_replace_512_bi?= =?utf-8?q?t_dh_key_with_a_2014_bit_one_=28closes_=2323844=29?= Message-ID: <20150402040823.16250.46334@psf.io> https://hg.python.org/cpython/rev/4f2391e86643 changeset: 95365:4f2391e86643 branch: 2.7 parent: 95353:5d88f6531872 user: Benjamin Peterson date: Thu Apr 02 00:04:06 2015 -0400 summary: replace 512 bit dh key with a 2014 bit one (closes #23844) Patch by C?dric Krier. files: Lib/test/dh1024.pem | 7 +++++++ Lib/test/dh512.pem | 9 --------- Lib/test/test_ssl.py | 2 +- 3 files changed, 8 insertions(+), 10 deletions(-) diff --git a/Lib/test/dh1024.pem b/Lib/test/dh1024.pem new file mode 100644 --- /dev/null +++ b/Lib/test/dh1024.pem @@ -0,0 +1,7 @@ +-----BEGIN DH PARAMETERS----- +MIGHAoGBAIbzw1s9CT8SV5yv6L7esdAdZYZjPi3qWFs61CYTFFQnf2s/d09NYaJt +rrvJhIzWavqnue71qXCf83/J3nz3FEwUU/L0mGyheVbsSHiI64wUo3u50wK5Igo0 +RNs/LD0irs7m0icZ//hijafTU+JOBiuA8zMI+oZfU7BGuc9XrUprAgEC +-----END DH PARAMETERS----- + +Generated with: openssl dhparam -out dh1024.pem 1024 diff --git a/Lib/test/dh512.pem b/Lib/test/dh512.pem deleted file mode 100644 --- a/Lib/test/dh512.pem +++ /dev/null @@ -1,9 +0,0 @@ ------BEGIN DH PARAMETERS----- -MEYCQQD1Kv884bEpQBgRjXyEpwpy1obEAxnIByl6ypUM2Zafq9AKUJsCRtMIPWak -XUGfnHy9iUsiGSa6q6Jew1XpKgVfAgEC ------END DH PARAMETERS----- - -These are the 512 bit DH parameters from "Assigned Number for SKIP Protocols" -(http://www.skip-vpn.org/spec/numbers.html). -See there for how they were generated. -Note that g is not a generator, but this is not a problem since p is a safe prime. diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py --- a/Lib/test/test_ssl.py +++ b/Lib/test/test_ssl.py @@ -66,7 +66,7 @@ NOKIACERT = data_file("nokia.pem") NULLBYTECERT = data_file("nullbytecert.pem") -DHFILE = data_file("dh512.pem") +DHFILE = data_file("dh1024.pem") BYTES_DHFILE = DHFILE.encode(sys.getfilesystemencoding()) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Apr 2 06:08:37 2015 From: python-checkins at python.org (benjamin.peterson) Date: Thu, 02 Apr 2015 04:08:37 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?b?KTogbWVyZ2UgMy40ICgjMjM4NDQp?= Message-ID: <20150402040824.19530.10159@psf.io> https://hg.python.org/cpython/rev/c27585e43e50 changeset: 95366:c27585e43e50 parent: 95363:920b700d9509 parent: 95364:1ad7c0253abe user: Benjamin Peterson date: Thu Apr 02 00:08:10 2015 -0400 summary: merge 3.4 (#23844) files: Lib/test/dh1024.pem | 7 +++++++ Lib/test/dh512.pem | 9 --------- Lib/test/test_ssl.py | 2 +- 3 files changed, 8 insertions(+), 10 deletions(-) diff --git a/Lib/test/dh1024.pem b/Lib/test/dh1024.pem new file mode 100644 --- /dev/null +++ b/Lib/test/dh1024.pem @@ -0,0 +1,7 @@ +-----BEGIN DH PARAMETERS----- +MIGHAoGBAIbzw1s9CT8SV5yv6L7esdAdZYZjPi3qWFs61CYTFFQnf2s/d09NYaJt +rrvJhIzWavqnue71qXCf83/J3nz3FEwUU/L0mGyheVbsSHiI64wUo3u50wK5Igo0 +RNs/LD0irs7m0icZ//hijafTU+JOBiuA8zMI+oZfU7BGuc9XrUprAgEC +-----END DH PARAMETERS----- + +Generated with: openssl dhparam -out dh1024.pem 1024 diff --git a/Lib/test/dh512.pem b/Lib/test/dh512.pem deleted file mode 100644 --- a/Lib/test/dh512.pem +++ /dev/null @@ -1,9 +0,0 @@ ------BEGIN DH PARAMETERS----- -MEYCQQD1Kv884bEpQBgRjXyEpwpy1obEAxnIByl6ypUM2Zafq9AKUJsCRtMIPWak -XUGfnHy9iUsiGSa6q6Jew1XpKgVfAgEC ------END DH PARAMETERS----- - -These are the 512 bit DH parameters from "Assigned Number for SKIP Protocols" -(http://www.skip-vpn.org/spec/numbers.html). -See there for how they were generated. -Note that g is not a generator, but this is not a problem since p is a safe prime. diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py --- a/Lib/test/test_ssl.py +++ b/Lib/test/test_ssl.py @@ -64,7 +64,7 @@ NOKIACERT = data_file("nokia.pem") NULLBYTECERT = data_file("nullbytecert.pem") -DHFILE = data_file("dh512.pem") +DHFILE = data_file("dh1024.pem") BYTES_DHFILE = os.fsencode(DHFILE) -- Repository URL: https://hg.python.org/cpython From storchaka at gmail.com Thu Apr 2 08:07:38 2015 From: storchaka at gmail.com (Serhiy Storchaka) Date: Thu, 02 Apr 2015 09:07:38 +0300 Subject: [Python-checkins] cpython: Check deques against common sequence tests (except for slicing). In-Reply-To: References: <20150401151114.1901.60002@psf.io> Message-ID: On 01.04.15 18:27, Zachary Ware wrote: > On Wed, Apr 1, 2015 at 10:11 AM, raymond.hettinger > wrote: >> https://hg.python.org/cpython/rev/393189326adb >> changeset: 95350:393189326adb >> user: Raymond Hettinger >> date: Wed Apr 01 08:11:09 2015 -0700 >> summary: >> Check deques against common sequence tests (except for slicing). >> >> files: >> Lib/test/test_deque.py | 16 ++++++++++++++++ >> 1 files changed, 16 insertions(+), 0 deletions(-) >> >> >> diff --git a/Lib/test/test_deque.py b/Lib/test/test_deque.py >> --- a/Lib/test/test_deque.py >> +++ b/Lib/test/test_deque.py >> @@ -843,6 +843,21 @@ >> # SF bug #1486663 -- this used to erroneously raise a TypeError >> SubclassWithKwargs(newarg=1) >> >> +class TestSequence(seq_tests.CommonTest): >> + type2test = deque >> + >> + def test_getitem(self): >> + # For now, bypass tests that require slicing >> + pass >> + >> + def test_getslice(self): >> + # For now, bypass tests that require slicing >> + pass >> + >> + def test_subscript(self): >> + # For now, bypass tests that require slicing >> + pass > > Instead of making these empty passing tests, it's better to set them > to 'None' so that unittest doesn't run them (and thus doesn't report > success when it hasn't actually tested something). Seconded. From python-checkins at python.org Thu Apr 2 08:50:31 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Thu, 02 Apr 2015 06:50:31 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2322977=3A_Fixed_formatting_Windows_error_message?= =?utf-8?q?s_on_Wine=2E?= Message-ID: <20150402065031.16499.74356@psf.io> https://hg.python.org/cpython/rev/cf0cac11813d changeset: 95368:cf0cac11813d parent: 95366:c27585e43e50 parent: 95367:7907746baa0d user: Serhiy Storchaka date: Thu Apr 02 09:50:06 2015 +0300 summary: Issue #22977: Fixed formatting Windows error messages on Wine. Patch by Martin Panter. files: Lib/test/test_exceptions.py | 10 +++++++++- Misc/NEWS | 3 +++ Python/errors.c | 4 ++-- 3 files changed, 14 insertions(+), 3 deletions(-) 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 @@ -6,10 +6,11 @@ import pickle import weakref import errno +import ctypes from test.support import (TESTFN, captured_output, check_impl_detail, check_warnings, cpython_only, gc_collect, run_unittest, - no_tracing, unlink) + no_tracing, unlink, get_attribute) class NaiveException(Exception): def __init__(self, x): @@ -245,6 +246,13 @@ self.assertEqual(w.strerror, 'foo') self.assertEqual(w.filename, None) + def test_windows_message(self): + """Should fill in unknown error code in Windows error message""" + windll = get_attribute(ctypes, "windll") + code = int.from_bytes(b"\xE0msc", "big") + with self.assertRaisesRegex(OSError, hex(code)): + windll.kernel32.RaiseException(code, 0, 0, None) + def testAttributes(self): # test that exception attributes are happy diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,9 @@ Core and Builtins ----------------- +- Issue #22977: Fixed formatting Windows error messages on Wine. + Patch by Martin Panter. + Library ------- diff --git a/Python/errors.c b/Python/errors.c --- a/Python/errors.c +++ b/Python/errors.c @@ -491,7 +491,7 @@ /* Only ever seen this in out-of-mem situations */ s_buf = NULL; - message = PyUnicode_FromFormat("Windows Error 0x%X", i); + message = PyUnicode_FromFormat("Windows Error 0x%x", i); } else { /* remove trailing cr/lf and dots */ while (len > 0 && (s_buf[len-1] <= L' ' || s_buf[len-1] == L'.')) @@ -600,7 +600,7 @@ NULL); /* no args */ if (len==0) { /* Only seen this in out of mem situations */ - message = PyUnicode_FromFormat("Windows Error 0x%X", err); + message = PyUnicode_FromFormat("Windows Error 0x%x", err); s_buf = NULL; } else { /* remove trailing cr/lf and dots */ -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Apr 2 08:50:31 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Thu, 02 Apr 2015 06:50:31 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzIyOTc3?= =?utf-8?q?=3A_Fixed_formatting_Windows_error_messages_on_Wine=2E?= Message-ID: <20150402065031.29533.56374@psf.io> https://hg.python.org/cpython/rev/7907746baa0d changeset: 95367:7907746baa0d branch: 3.4 parent: 95364:1ad7c0253abe user: Serhiy Storchaka date: Thu Apr 02 09:47:27 2015 +0300 summary: Issue #22977: Fixed formatting Windows error messages on Wine. Patch by Martin Panter. files: Lib/test/test_exceptions.py | 10 +++++++++- Misc/NEWS | 3 +++ Python/errors.c | 4 ++-- 3 files changed, 14 insertions(+), 3 deletions(-) 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 @@ -6,10 +6,11 @@ import pickle import weakref import errno +import ctypes from test.support import (TESTFN, captured_output, check_impl_detail, check_warnings, cpython_only, gc_collect, run_unittest, - no_tracing, unlink) + no_tracing, unlink, get_attribute) class NaiveException(Exception): def __init__(self, x): @@ -245,6 +246,13 @@ self.assertEqual(w.strerror, 'foo') self.assertEqual(w.filename, None) + def test_windows_message(self): + """Should fill in unknown error code in Windows error message""" + windll = get_attribute(ctypes, "windll") + code = int.from_bytes(b"\xE0msc", "big") + with self.assertRaisesRegex(OSError, hex(code)): + windll.kernel32.RaiseException(code, 0, 0, None) + def testAttributes(self): # test that exception attributes are happy diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,9 @@ Core and Builtins ----------------- +- Issue #22977: Fixed formatting Windows error messages on Wine. + Patch by Martin Panter. + - Issue #23803: Fixed str.partition() and str.rpartition() when a separator is wider then partitioned string. diff --git a/Python/errors.c b/Python/errors.c --- a/Python/errors.c +++ b/Python/errors.c @@ -491,7 +491,7 @@ /* Only ever seen this in out-of-mem situations */ s_buf = NULL; - message = PyUnicode_FromFormat("Windows Error 0x%X", i); + message = PyUnicode_FromFormat("Windows Error 0x%x", i); } else { /* remove trailing cr/lf and dots */ while (len > 0 && (s_buf[len-1] <= L' ' || s_buf[len-1] == L'.')) @@ -600,7 +600,7 @@ NULL); /* no args */ if (len==0) { /* Only seen this in out of mem situations */ - message = PyUnicode_FromFormat("Windows Error 0x%X", err); + message = PyUnicode_FromFormat("Windows Error 0x%x", err); s_buf = NULL; } else { /* remove trailing cr/lf and dots */ -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Apr 2 10:02:55 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Thu, 02 Apr 2015 08:02:55 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzIxNTI2?= =?utf-8?q?=3A_Tkinter_now_supports_new_boolean_type_in_Tcl_8=2E5=2E?= Message-ID: <20150402080255.27436.86956@psf.io> https://hg.python.org/cpython/rev/d0554559de53 changeset: 95371:d0554559de53 branch: 2.7 parent: 95365:4f2391e86643 user: Serhiy Storchaka date: Thu Apr 02 10:35:57 2015 +0300 summary: Issue #21526: Tkinter now supports new boolean type in Tcl 8.5. files: Lib/test/test_tcl.py | 15 +++++++++ Misc/NEWS | 2 + Modules/_tkinter.c | 49 ++++++++++++++++++++++--------- 3 files changed, 51 insertions(+), 15 deletions(-) diff --git a/Lib/test/test_tcl.py b/Lib/test/test_tcl.py --- a/Lib/test/test_tcl.py +++ b/Lib/test/test_tcl.py @@ -391,6 +391,21 @@ if tcl_version >= (8, 5): check('2**64', True) + def test_booleans(self): + tcl = self.interp + def check(expr, expected): + result = tcl.call('expr', expr) + self.assertEqual(result, expected) + self.assertIsInstance(result, int) + check('true', True) + check('yes', True) + check('on', True) + check('false', False) + check('no', False) + check('off', False) + check('1 < 2', True) + check('1 > 2', False) + def test_passing_values(self): def passValue(value): return self.interp.call('set', '_', value) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -21,6 +21,8 @@ Library ------- +- Issue #21526: Tkinter now supports new boolean type in Tcl 8.5. + - Issue #23838: linecache now clears the cache and returns an empty result on MemoryError. diff --git a/Modules/_tkinter.c b/Modules/_tkinter.c --- a/Modules/_tkinter.c +++ b/Modules/_tkinter.c @@ -257,13 +257,14 @@ int dispatching; /* We cannot include tclInt.h, as this is internal. So we cache interesting types here. */ - Tcl_ObjType *BooleanType; - Tcl_ObjType *ByteArrayType; - Tcl_ObjType *DoubleType; - Tcl_ObjType *IntType; - Tcl_ObjType *ListType; - Tcl_ObjType *ProcBodyType; - Tcl_ObjType *StringType; + const Tcl_ObjType *OldBooleanType; + const Tcl_ObjType *BooleanType; + const Tcl_ObjType *ByteArrayType; + const Tcl_ObjType *DoubleType; + const Tcl_ObjType *IntType; + const Tcl_ObjType *ListType; + const Tcl_ObjType *ProcBodyType; + const Tcl_ObjType *StringType; } TkappObject; #define Tkapp_Check(v) (Py_TYPE(v) == &Tkapp_Type) @@ -733,7 +734,8 @@ } #endif - v->BooleanType = Tcl_GetObjType("boolean"); + v->OldBooleanType = Tcl_GetObjType("boolean"); + v->BooleanType = Tcl_GetObjType("booleanString"); v->ByteArrayType = Tcl_GetObjType("bytearray"); v->DoubleType = Tcl_GetObjType("double"); v->IntType = Tcl_GetObjType("int"); @@ -1129,21 +1131,30 @@ } } +static PyObject * +fromBoolean(PyObject* tkapp, Tcl_Obj *value) +{ + int boolValue; + if (Tcl_GetBooleanFromObj(Tkapp_Interp(tkapp), value, &boolValue) == TCL_ERROR) + return Tkinter_Error(tkapp); + return PyBool_FromLong(boolValue); +} + static PyObject* FromObj(PyObject* tkapp, Tcl_Obj *value) { PyObject *result = NULL; TkappObject *app = (TkappObject*)tkapp; + Tcl_Interp *interp = Tkapp_Interp(tkapp); if (value->typePtr == NULL) { result = fromTclStringAndSize(value->bytes, value->length); return result; } - if (value->typePtr == app->BooleanType) { - result = value->internalRep.longValue ? Py_True : Py_False; - Py_INCREF(result); - return result; + if (value->typePtr == app->BooleanType || + value->typePtr == app->OldBooleanType) { + return fromBoolean(tkapp, value); } if (value->typePtr == app->ByteArrayType) { @@ -1166,15 +1177,14 @@ PyObject *elem; Tcl_Obj *tcl_elem; - status = Tcl_ListObjLength(Tkapp_Interp(tkapp), value, &size); + status = Tcl_ListObjLength(interp, value, &size); if (status == TCL_ERROR) return Tkinter_Error(tkapp); result = PyTuple_New(size); if (!result) return NULL; for (i = 0; i < size; i++) { - status = Tcl_ListObjIndex(Tkapp_Interp(tkapp), - value, i, &tcl_elem); + status = Tcl_ListObjIndex(interp, value, i, &tcl_elem); if (status == TCL_ERROR) { Py_DECREF(result); return Tkinter_Error(tkapp); @@ -1222,6 +1232,15 @@ #endif } +#if TK_VERSION_HEX >= 0x08050000 + if (app->BooleanType == NULL && + strcmp(value->typePtr->name, "booleanString") == 0) { + /* booleanString type is not registered in Tcl */ + app->BooleanType = value->typePtr; + return fromBoolean(tkapp, value); + } +#endif + return newPyTclObject(value); } -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Apr 2 10:03:07 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Thu, 02 Apr 2015 08:03:07 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2321526=3A_Fixed_support_of_new_boolean_type_in_T?= =?utf-8?q?cl_8=2E5=2E?= Message-ID: <20150402080255.59588.49574@psf.io> https://hg.python.org/cpython/rev/b2413da7516f changeset: 95370:b2413da7516f parent: 95368:cf0cac11813d parent: 95369:de3496cd609e user: Serhiy Storchaka date: Thu Apr 02 10:58:40 2015 +0300 summary: Issue #21526: Fixed support of new boolean type in Tcl 8.5. files: Lib/test/test_tcl.py | 15 +++++++++++++++ Misc/NEWS | 4 ++-- Modules/_tkinter.c | 23 +++++++++++++++++++---- 3 files changed, 36 insertions(+), 6 deletions(-) diff --git a/Lib/test/test_tcl.py b/Lib/test/test_tcl.py --- a/Lib/test/test_tcl.py +++ b/Lib/test/test_tcl.py @@ -378,6 +378,21 @@ if tcl_version >= (8, 5): check('2**64', True) + def test_booleans(self): + tcl = self.interp + def check(expr, expected): + result = tcl.call('expr', expr) + self.assertEqual(result, expected) + self.assertIsInstance(result, int) + check('true', True) + check('yes', True) + check('on', True) + check('false', False) + check('no', False) + check('off', False) + check('1 < 2', True) + check('1 > 2', False) + def test_passing_values(self): def passValue(value): return self.interp.call('set', '_', value) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -16,6 +16,8 @@ Library ------- +- Issue #21526: Tkinter now supports new boolean type in Tcl 8.5. + - Issue #23836: Fix the faulthandler module to handle reentrant calls to its signal handlers. @@ -146,8 +148,6 @@ - Issue #23252: Added support for writing ZIP files to unseekable streams. -- Issue #21526: Tkinter now supports new boolean type in Tcl 8.5. - - Issue #23647: Increase impalib's MAXLINE to accommodate modern mailbox sizes. - Issue #23539: If body is None, http.client.HTTPConnection.request now sets diff --git a/Modules/_tkinter.c b/Modules/_tkinter.c --- a/Modules/_tkinter.c +++ b/Modules/_tkinter.c @@ -998,6 +998,15 @@ } } +static PyObject * +fromBoolean(PyObject* tkapp, Tcl_Obj *value) +{ + int boolValue; + if (Tcl_GetBooleanFromObj(Tkapp_Interp(tkapp), value, &boolValue) == TCL_ERROR) + return Tkinter_Error(tkapp); + return PyBool_FromLong(boolValue); +} + static PyObject* FromObj(PyObject* tkapp, Tcl_Obj *value) { @@ -1011,10 +1020,7 @@ if (value->typePtr == app->BooleanType || value->typePtr == app->OldBooleanType) { - int boolValue; - if (Tcl_GetBooleanFromObj(interp, value, &boolValue) == TCL_ERROR) - return Tkinter_Error(tkapp); - return PyBool_FromLong(boolValue); + return fromBoolean(tkapp, value); } if (value->typePtr == app->ByteArrayType) { @@ -1069,6 +1075,15 @@ Tcl_GetCharLength(value)); } +#if TK_VERSION_HEX >= 0x08050000 + if (app->BooleanType == NULL && + strcmp(value->typePtr->name, "booleanString") == 0) { + /* booleanString type is not registered in Tcl */ + app->BooleanType = value->typePtr; + return fromBoolean(tkapp, value); + } +#endif + return newPyTclObject(value); } -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Apr 2 10:03:07 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Thu, 02 Apr 2015 08:03:07 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzIxNTI2?= =?utf-8?q?=3A_Tkinter_now_supports_new_boolean_type_in_Tcl_8=2E5=2E?= Message-ID: <20150402080254.14213.25613@psf.io> https://hg.python.org/cpython/rev/de3496cd609e changeset: 95369:de3496cd609e branch: 3.4 parent: 95367:7907746baa0d user: Serhiy Storchaka date: Thu Apr 02 10:35:57 2015 +0300 summary: Issue #21526: Tkinter now supports new boolean type in Tcl 8.5. files: Lib/test/test_tcl.py | 15 +++++++++ Misc/NEWS | 2 + Modules/_tkinter.c | 49 ++++++++++++++++++++++--------- 3 files changed, 51 insertions(+), 15 deletions(-) diff --git a/Lib/test/test_tcl.py b/Lib/test/test_tcl.py --- a/Lib/test/test_tcl.py +++ b/Lib/test/test_tcl.py @@ -378,6 +378,21 @@ if tcl_version >= (8, 5): check('2**64', True) + def test_booleans(self): + tcl = self.interp + def check(expr, expected): + result = tcl.call('expr', expr) + self.assertEqual(result, expected) + self.assertIsInstance(result, int) + check('true', True) + check('yes', True) + check('on', True) + check('false', False) + check('no', False) + check('off', False) + check('1 < 2', True) + check('1 > 2', False) + def test_passing_values(self): def passValue(value): return self.interp.call('set', '_', value) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -24,6 +24,8 @@ Library ------- +- Issue #21526: Tkinter now supports new boolean type in Tcl 8.5. + - Issue #23838: linecache now clears the cache and returns an empty result on MemoryError. diff --git a/Modules/_tkinter.c b/Modules/_tkinter.c --- a/Modules/_tkinter.c +++ b/Modules/_tkinter.c @@ -242,13 +242,14 @@ int dispatching; /* We cannot include tclInt.h, as this is internal. So we cache interesting types here. */ - Tcl_ObjType *BooleanType; - Tcl_ObjType *ByteArrayType; - Tcl_ObjType *DoubleType; - Tcl_ObjType *IntType; - Tcl_ObjType *ListType; - Tcl_ObjType *ProcBodyType; - Tcl_ObjType *StringType; + const Tcl_ObjType *OldBooleanType; + const Tcl_ObjType *BooleanType; + const Tcl_ObjType *ByteArrayType; + const Tcl_ObjType *DoubleType; + const Tcl_ObjType *IntType; + const Tcl_ObjType *ListType; + const Tcl_ObjType *ProcBodyType; + const Tcl_ObjType *StringType; } TkappObject; #define Tkapp_Interp(v) (((TkappObject *) (v))->interp) @@ -577,7 +578,8 @@ } #endif - v->BooleanType = Tcl_GetObjType("boolean"); + v->OldBooleanType = Tcl_GetObjType("boolean"); + v->BooleanType = Tcl_GetObjType("booleanString"); v->ByteArrayType = Tcl_GetObjType("bytearray"); v->DoubleType = Tcl_GetObjType("double"); v->IntType = Tcl_GetObjType("int"); @@ -979,20 +981,29 @@ } } +static PyObject * +fromBoolean(PyObject* tkapp, Tcl_Obj *value) +{ + int boolValue; + if (Tcl_GetBooleanFromObj(Tkapp_Interp(tkapp), value, &boolValue) == TCL_ERROR) + return Tkinter_Error(tkapp); + return PyBool_FromLong(boolValue); +} + static PyObject* FromObj(PyObject* tkapp, Tcl_Obj *value) { PyObject *result = NULL; TkappObject *app = (TkappObject*)tkapp; + Tcl_Interp *interp = Tkapp_Interp(tkapp); if (value->typePtr == NULL) { return unicodeFromTclStringAndSize(value->bytes, value->length); } - if (value->typePtr == app->BooleanType) { - result = value->internalRep.longValue ? Py_True : Py_False; - Py_INCREF(result); - return result; + if (value->typePtr == app->BooleanType || + value->typePtr == app->OldBooleanType) { + return fromBoolean(tkapp, value); } if (value->typePtr == app->ByteArrayType) { @@ -1015,15 +1026,14 @@ PyObject *elem; Tcl_Obj *tcl_elem; - status = Tcl_ListObjLength(Tkapp_Interp(tkapp), value, &size); + status = Tcl_ListObjLength(interp, value, &size); if (status == TCL_ERROR) return Tkinter_Error(tkapp); result = PyTuple_New(size); if (!result) return NULL; for (i = 0; i < size; i++) { - status = Tcl_ListObjIndex(Tkapp_Interp(tkapp), - value, i, &tcl_elem); + status = Tcl_ListObjIndex(interp, value, i, &tcl_elem); if (status == TCL_ERROR) { Py_DECREF(result); return Tkinter_Error(tkapp); @@ -1048,6 +1058,15 @@ Tcl_GetCharLength(value)); } +#if TK_VERSION_HEX >= 0x08050000 + if (app->BooleanType == NULL && + strcmp(value->typePtr->name, "booleanString") == 0) { + /* booleanString type is not registered in Tcl */ + app->BooleanType = value->typePtr; + return fromBoolean(tkapp, value); + } +#endif + return newPyTclObject(value); } -- Repository URL: https://hg.python.org/cpython From solipsis at pitrou.net Thu Apr 2 10:37:18 2015 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Thu, 02 Apr 2015 08:37:18 +0000 Subject: [Python-checkins] Daily reference leaks (c27585e43e50): sum=390 Message-ID: <20150402083717.59582.80436@psf.io> results for c27585e43e50 on branch "default" -------------------------------------------- test_collections leaked [-2, -2, 0] references, sum=-4 test_deque leaked [91, 91, 91] references, sum=273 test_deque leaked [21, 21, 21] memory blocks, sum=63 test_functools leaked [0, 0, 3] memory blocks, sum=3 test_multiprocessing_forkserver leaked [0, 0, 38] references, sum=38 test_multiprocessing_forkserver leaked [0, 0, 17] memory blocks, sum=17 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogjfzOkf', '--timeout', '7200'] From python-checkins at python.org Thu Apr 2 10:48:22 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Thu, 02 Apr 2015 08:48:22 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzIxNTI2?= =?utf-8?q?=3A_Fixed_the_test=5Fbooleans_test_for_wantobjects_=3D_0=2E?= Message-ID: <20150402084822.129135.39553@psf.io> https://hg.python.org/cpython/rev/4255ca2f5314 changeset: 95373:4255ca2f5314 branch: 3.4 parent: 95369:de3496cd609e user: Serhiy Storchaka date: Thu Apr 02 11:46:07 2015 +0300 summary: Issue #21526: Fixed the test_booleans test for wantobjects = 0. files: Lib/test/test_tcl.py | 8 ++++++-- 1 files changed, 6 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_tcl.py b/Lib/test/test_tcl.py --- a/Lib/test/test_tcl.py +++ b/Lib/test/test_tcl.py @@ -382,8 +382,12 @@ tcl = self.interp def check(expr, expected): result = tcl.call('expr', expr) - self.assertEqual(result, expected) - self.assertIsInstance(result, int) + if tcl.wantobjects(): + self.assertEqual(result, expected) + self.assertIsInstance(result, int) + else: + self.assertIn(result, (expr, str(int(expected)))) + self.assertIsInstance(result, str) check('true', True) check('yes', True) check('on', True) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Apr 2 10:48:22 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Thu, 02 Apr 2015 08:48:22 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2321526=3A_Fixed_the_test=5Fbooleans_test_for_wan?= =?utf-8?q?tobjects_=3D_0=2E?= Message-ID: <20150402084822.14233.51394@psf.io> https://hg.python.org/cpython/rev/bb0b5b6c13f3 changeset: 95374:bb0b5b6c13f3 parent: 95370:b2413da7516f parent: 95373:4255ca2f5314 user: Serhiy Storchaka date: Thu Apr 02 11:47:51 2015 +0300 summary: Issue #21526: Fixed the test_booleans test for wantobjects = 0. files: Lib/test/test_tcl.py | 8 ++++++-- 1 files changed, 6 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_tcl.py b/Lib/test/test_tcl.py --- a/Lib/test/test_tcl.py +++ b/Lib/test/test_tcl.py @@ -382,8 +382,12 @@ tcl = self.interp def check(expr, expected): result = tcl.call('expr', expr) - self.assertEqual(result, expected) - self.assertIsInstance(result, int) + if tcl.wantobjects(): + self.assertEqual(result, expected) + self.assertIsInstance(result, int) + else: + self.assertIn(result, (expr, str(int(expected)))) + self.assertIsInstance(result, str) check('true', True) check('yes', True) check('on', True) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Apr 2 10:48:22 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Thu, 02 Apr 2015 08:48:22 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzIxNTI2?= =?utf-8?q?=3A_Fixed_the_test=5Fbooleans_test_for_wantobjects_=3D_0=2E?= Message-ID: <20150402084821.14217.97543@psf.io> https://hg.python.org/cpython/rev/954e7e1d85f1 changeset: 95372:954e7e1d85f1 branch: 2.7 user: Serhiy Storchaka date: Thu Apr 02 11:46:07 2015 +0300 summary: Issue #21526: Fixed the test_booleans test for wantobjects = 0. files: Lib/test/test_tcl.py | 8 ++++++-- 1 files changed, 6 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_tcl.py b/Lib/test/test_tcl.py --- a/Lib/test/test_tcl.py +++ b/Lib/test/test_tcl.py @@ -395,8 +395,12 @@ tcl = self.interp def check(expr, expected): result = tcl.call('expr', expr) - self.assertEqual(result, expected) - self.assertIsInstance(result, int) + if tcl.wantobjects(): + self.assertEqual(result, expected) + self.assertIsInstance(result, int) + else: + self.assertIn(result, (expr, str(int(expected)))) + self.assertIsInstance(result, str) check('true', True) check('yes', True) check('on', True) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Apr 2 12:57:52 2015 From: python-checkins at python.org (victor.stinner) Date: Thu, 02 Apr 2015 10:57:52 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2323618=3A_Don=27t_?= =?utf-8?q?declare_recvmsg/sendmsg_helper_functions_on_Windows?= Message-ID: <20150402105752.16242.71964@psf.io> https://hg.python.org/cpython/rev/aad52bfc816f changeset: 95375:aad52bfc816f user: Victor Stinner date: Thu Apr 02 12:28:07 2015 +0200 summary: Issue #23618: Don't declare recvmsg/sendmsg helper functions on Windows files: Modules/socketmodule.c | 13 ++++++------- 1 files changed, 6 insertions(+), 7 deletions(-) diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -3109,6 +3109,9 @@ \n\ Like recv_into(buffer[, nbytes[, flags]]) but also return the sender's address info."); +/* The sendmsg() and recvmsg[_into]() methods require a working + CMSG_LEN(). See the comment near get_CMSG_LEN(). */ +#ifdef CMSG_LEN struct sock_recvmsg { struct msghdr *msg; int flags; @@ -3124,10 +3127,6 @@ return (ctx->result >= 0); } - -/* The sendmsg() and recvmsg[_into]() methods require a working - CMSG_LEN(). See the comment near get_CMSG_LEN(). */ -#ifdef CMSG_LEN /* * Call recvmsg() with the supplied iovec structures, flags, and * ancillary data buffer size (controllen). Returns the tuple return @@ -3641,6 +3640,9 @@ For IP sockets, the address is a pair (hostaddr, port)."); +/* The sendmsg() and recvmsg[_into]() methods require a working + CMSG_LEN(). See the comment near get_CMSG_LEN(). */ +#ifdef CMSG_LEN struct sock_sendmsg { struct msghdr *msg; int flags; @@ -3656,9 +3658,6 @@ return (ctx->result >= 0); } -/* The sendmsg() and recvmsg[_into]() methods require a working - CMSG_LEN(). See the comment near get_CMSG_LEN(). */ -#ifdef CMSG_LEN /* s.sendmsg(buffers[, ancdata[, flags[, address]]]) method */ static PyObject * -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Apr 2 12:57:52 2015 From: python-checkins at python.org (victor.stinner) Date: Thu, 02 Apr 2015 10:57:52 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2323618=3A_Document?= =?utf-8?q?_EINTR_changes_in_socket_documentation?= Message-ID: <20150402105752.29543.58519@psf.io> https://hg.python.org/cpython/rev/f22188acc77d changeset: 95376:f22188acc77d user: Victor Stinner date: Thu Apr 02 11:49:42 2015 +0200 summary: Issue #23618: Document EINTR changes in socket documentation files: Doc/library/functions.rst | 2 +- Doc/library/os.rst | 8 ++-- Doc/library/socket.rst | 40 +++++++++++++++++++++++++++ Doc/whatsnew/3.5.rst | 11 +++++++ 4 files changed, 56 insertions(+), 5 deletions(-) diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst --- a/Doc/library/functions.rst +++ b/Doc/library/functions.rst @@ -1066,7 +1066,7 @@ The ``'U'`` mode. .. versionchanged:: 3.5 - If the system call is interrupted and the signal does not raise an + If the system call is interrupted and the signal handler does not raise an exception, the function now retries the system call instead of raising an :exc:`InterruptedError` exception (see :pep:`475` for the rationale). diff --git a/Doc/library/os.rst b/Doc/library/os.rst --- a/Doc/library/os.rst +++ b/Doc/library/os.rst @@ -906,7 +906,7 @@ The *dir_fd* argument. .. versionchanged:: 3.5 - If the system call is interrupted and the signal does not raise an + If the system call is interrupted and the signal handler does not raise an exception, the function now retries the system call instead of raising an :exc:`InterruptedError` exception (see :pep:`475` for the rationale). @@ -1088,7 +1088,7 @@ :meth:`~file.read` or :meth:`~file.readline` methods. .. versionchanged:: 3.5 - If the system call is interrupted and the signal does not raise an + If the system call is interrupted and the signal handler does not raise an exception, the function now retries the system call instead of raising an :exc:`InterruptedError` exception (see :pep:`475` for the rationale). @@ -1208,7 +1208,7 @@ :meth:`~file.write` method. .. versionchanged:: 3.5 - If the system call is interrupted and the signal does not raise an + If the system call is interrupted and the signal handler does not raise an exception, the function now retries the system call instead of raising an :exc:`InterruptedError` exception (see :pep:`475` for the rationale). @@ -3375,7 +3375,7 @@ functions called with :const:`P_NOWAIT` return suitable process handles. .. versionchanged:: 3.5 - If the system call is interrupted and the signal does not raise an + If the system call is interrupted and the signal handler does not raise an exception, the function now retries the system call instead of raising an :exc:`InterruptedError` exception (see :pep:`475` for the rationale). diff --git a/Doc/library/socket.rst b/Doc/library/socket.rst --- a/Doc/library/socket.rst +++ b/Doc/library/socket.rst @@ -793,6 +793,11 @@ .. versionchanged:: 3.4 The socket is now non-inheritable. + .. versionchanged:: 3.5 + If the system call is interrupted and the signal handler does not raise + an exception, the method now retries the system call instead of raising + an :exc:`InterruptedError` exception (see :pep:`475` for the rationale). + .. method:: socket.bind(address) @@ -966,6 +971,11 @@ For best match with hardware and network realities, the value of *bufsize* should be a relatively small power of 2, for example, 4096. + .. versionchanged:: 3.5 + If the system call is interrupted and the signal handler does not raise + an exception, the method now retries the system call instead of raising + an :exc:`InterruptedError` exception (see :pep:`475` for the rationale). + .. method:: socket.recvfrom(bufsize[, flags]) @@ -975,6 +985,11 @@ :manpage:`recv(2)` for the meaning of the optional argument *flags*; it defaults to zero. (The format of *address* depends on the address family --- see above.) + .. versionchanged:: 3.5 + If the system call is interrupted and the signal handler does not raise + an exception, the method now retries the system call instead of raising + an :exc:`InterruptedError` exception (see :pep:`475` for the rationale). + .. method:: socket.recvmsg(bufsize[, ancbufsize[, flags]]) @@ -1041,6 +1056,11 @@ .. versionadded:: 3.3 + .. versionchanged:: 3.5 + If the system call is interrupted and the signal handler does not raise + an exception, the method now retries the system call instead of raising + an :exc:`InterruptedError` exception (see :pep:`475` for the rationale). + .. method:: socket.recvmsg_into(buffers[, ancbufsize[, flags]]) @@ -1107,6 +1127,11 @@ application needs to attempt delivery of the remaining data. For further information on this topic, consult the :ref:`socket-howto`. + .. versionchanged:: 3.5 + If the system call is interrupted and the signal handler does not raise + an exception, the method now retries the system call instead of raising + an :exc:`InterruptedError` exception (see :pep:`475` for the rationale). + .. method:: socket.sendall(bytes[, flags]) @@ -1117,6 +1142,11 @@ success. On error, an exception is raised, and there is no way to determine how much data, if any, was successfully sent. + .. versionchanged:: 3.5 + If the system call is interrupted and the signal handler does not raise + an exception, the method now retries the system call instead of raising + an :exc:`InterruptedError` exception (see :pep:`475` for the rationale). + .. method:: socket.sendto(bytes, address) socket.sendto(bytes, flags, address) @@ -1127,6 +1157,11 @@ bytes sent. (The format of *address* depends on the address family --- see above.) + .. versionchanged:: 3.5 + If the system call is interrupted and the signal handler does not raise + an exception, the method now retries the system call instead of raising + an :exc:`InterruptedError` exception (see :pep:`475` for the rationale). + .. method:: socket.sendmsg(buffers[, ancdata[, flags[, address]]]) @@ -1163,6 +1198,11 @@ .. versionadded:: 3.3 + .. versionchanged:: 3.5 + If the system call is interrupted and the signal handler does not raise + an exception, the method now retries the system call instead of raising + an :exc:`InterruptedError` exception (see :pep:`475` for the rationale). + .. method:: socket.sendfile(file, offset=0, count=None) Send a file until EOF is reached by using high-performance diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -640,6 +640,17 @@ - :func:`os.read`, :func:`os.write` - :func:`select.select`, :func:`select.poll.poll`, :func:`select.epoll.poll`, :func:`select.kqueue.control`, :func:`select.devpoll.poll` + - :func:`socket.socket` methods: + + * :meth:`~socket.socket.accept` + * :meth:`~socket.socket.recv` + * :meth:`~socket.socket.recvfrom` + * :meth:`~socket.socket.recvmsg` + * :meth:`~socket.socket.send` + * :meth:`~socket.socket.sendall` + * :meth:`~socket.socket.sendmsg` + * :meth:`~socket.socket.sendto` + - :func:`signal.sigtimedwait`, :func:`signal.sigwaitinfo` - :func:`time.sleep` -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Apr 2 13:42:43 2015 From: python-checkins at python.org (victor.stinner) Date: Thu, 02 Apr 2015 11:42:43 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2323618=3A_socket?= =?utf-8?q?=2Esocket=2Econnect=28=29_now_waits_until_the_connection_comple?= =?utf-8?q?tes?= Message-ID: <20150402114243.14205.95572@psf.io> https://hg.python.org/cpython/rev/75fcc7a3738a changeset: 95377:75fcc7a3738a user: Victor Stinner date: Thu Apr 02 11:50:57 2015 +0200 summary: Issue #23618: socket.socket.connect() now waits until the connection completes instead of raising InterruptedError if the connection is interrupted by signals, signal handlers don't raise an exception and the socket is blocking or has a timeout. socket.socket.connect() still raise InterruptedError for non-blocking sockets. files: Doc/library/socket.rst | 13 + Doc/whatsnew/3.5.rst | 1 + Misc/NEWS | 6 + Modules/socketmodule.c | 434 ++++++++++++++++------------ 4 files changed, 264 insertions(+), 190 deletions(-) diff --git a/Doc/library/socket.rst b/Doc/library/socket.rst --- a/Doc/library/socket.rst +++ b/Doc/library/socket.rst @@ -830,6 +830,19 @@ Connect to a remote socket at *address*. (The format of *address* depends on the address family --- see above.) + If the connection is interrupted by a signal, the method waits until the + connection completes, or raise a :exc:`socket.timeout` on timeout, if the + signal handler doesn't raise an exception and the socket is blocking or has + a timeout. For non-blocking sockets, the method raises an + :exc:`InterruptedError` exception if the connection is interrupted by a + signal (or the exception raised by the signal handler). + + .. versionchanged:: 3.5 + The method now waits until the connection completes instead of raising an + :exc:`InterruptedError` exception if the connection is interrupted by a + signal, the signal handler doesn't raise an exception and the socket is + blocking or has a timeout (see the :pep:`475` for the rationale). + .. method:: socket.connect_ex(address) diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -643,6 +643,7 @@ - :func:`socket.socket` methods: * :meth:`~socket.socket.accept` + * :meth:`~socket.socket.connect` (except for non-blocking sockets) * :meth:`~socket.socket.recv` * :meth:`~socket.socket.recvfrom` * :meth:`~socket.socket.recvmsg` diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -16,6 +16,12 @@ Library ------- +- Issue #23618: :meth:`socket.socket.connect` now waits until the connection + completes instead of raising :exc:`InterruptedError` if the connection is + interrupted by signals, signal handlers don't raise an exception and the + socket is blocking or has a timeout. :meth:`socket.socket.connect` still + raise :exc:`InterruptedError` for non-blocking sockets. + - Issue #21526: Tkinter now supports new boolean type in Tcl 8.5. - Issue #23836: Fix the faulthandler module to handle reentrant calls to diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -482,6 +482,19 @@ #endif #ifdef MS_WINDOWS +# define GET_SOCK_ERROR WSAGetLastError() +# define SET_SOCK_ERROR(err) WSASetLastError(err) +# define SOCK_TIMEOUT_ERR WSAEWOULDBLOCK +# define SOCK_INPROGRESS_ERR WSAEWOULDBLOCK +#else +# define GET_SOCK_ERROR errno +# define SET_SOCK_ERROR(err) do { errno = err; } while (0) +# define SOCK_TIMEOUT_ERR EWOULDBLOCK +# define SOCK_INPROGRESS_ERR EINPROGRESS +#endif + + +#ifdef MS_WINDOWS /* Does WSASocket() support the WSA_FLAG_NO_HANDLE_INHERIT flag? */ static int support_wsa_no_inherit = -1; #endif @@ -592,8 +605,8 @@ } static int -internal_select_impl(PySocketSockObject *s, int writing, _PyTime_t interval, - int error) +internal_select(PySocketSockObject *s, int writing, _PyTime_t interval, + int connect) { int n; #ifdef HAVE_POLL @@ -610,43 +623,64 @@ #endif /* Error condition is for output only */ - assert(!(error && !writing)); - - /* Nothing to do unless we're in timeout mode (not non-blocking) */ - if (s->sock_timeout <= 0) - return 0; + assert(!(connect && !writing)); /* Guard against closed socket */ if (s->sock_fd < 0) return 0; - /* Handling this condition here simplifies the select loops */ - if (interval < 0) - return 1; + /* for connect(), we want to poll even if the socket is blocking */ + if (!connect) { + /* Nothing to do unless we're in timeout mode (not non-blocking) */ + if (s->sock_timeout <= 0) + return 0; + + /* Handling this condition here simplifies the select loops */ + if (interval < 0) + return 1; + } /* Prefer poll, if available, since you can poll() any fd * which can't be done with select(). */ #ifdef HAVE_POLL pollfd.fd = s->sock_fd; pollfd.events = writing ? POLLOUT : POLLIN; - if (error) + if (connect) { + /* On Windows, the socket becomes writable on connection success, + but a connection failure is notified as an error. On POSIX, the + socket becomes writable on connection success or on connection + failure. */ pollfd.events |= POLLERR; + } /* s->sock_timeout is in seconds, timeout in ms */ - ms = _PyTime_AsMilliseconds(interval, _PyTime_ROUND_CEILING); + if (interval >= 0) + ms = _PyTime_AsMilliseconds(interval, _PyTime_ROUND_CEILING); + else + ms = -1; assert(ms <= INT_MAX); Py_BEGIN_ALLOW_THREADS; n = poll(&pollfd, 1, (int)ms); Py_END_ALLOW_THREADS; #else - _PyTime_AsTimeval_noraise(interval, &tv, _PyTime_ROUND_CEILING); + if (interval >= 0) + _PyTime_AsTimeval_noraise(interval, &tv, _PyTime_ROUND_CEILING); + else { + tv.tv_sec = -1; + tv.tv_sec = 0; + } FD_ZERO(&fds); FD_SET(s->sock_fd, &fds); FD_ZERO(&efds); - if (error) + if (connect) { + /* On Windows, the socket becomes writable on connection success, + but a connection failure is notified as an error. On POSIX, the + socket becomes writable on connection success or on connection + failure. */ FD_SET(s->sock_fd, &efds); + } /* See if the socket is ready */ Py_BEGIN_ALLOW_THREADS; @@ -666,129 +700,153 @@ return 0; } -/* Do a select()/poll() on the socket, if necessary (sock_timeout > 0). - The argument writing indicates the direction. - This does not raise an exception; we'll let our caller do that - after they've reacquired the interpreter lock. - Returns 1 on timeout, -1 on error, 0 otherwise. */ -static int -internal_select(PySocketSockObject *s, int writing, _PyTime_t interval) -{ - return internal_select_impl(s, writing, interval, 0); -} - -static int -internal_connect_select(PySocketSockObject *s) -{ - return internal_select_impl(s, 1, s->sock_timeout, 1); -} - /* Call a socket function. - Raise an exception and return -1 on error, return 0 on success. + On error, raise an exception and return -1 if err is set, or fill err and + return -1 otherwise. If a signal was received and the signal handler raised + an exception, return -1, and set err to -1 if err is set. + + On success, return 0, and set err to 0 if err is set. If the socket has a timeout, wait until the socket is ready before calling the function: wait until the socket is writable if writing is nonzero, wait until the socket received data otherwise. - If the function func is interrupted by a signal (failed with EINTR): retry + If the socket function is interrupted by a signal (failed with EINTR): retry the function, except if the signal handler raised an exception (PEP 475). When the function is retried, recompute the timeout using a monotonic clock. - sock_call() must be called with the GIL held. The function func is called - with the GIL released. */ + sock_call_ex() must be called with the GIL held. The socket function is + called with the GIL released. */ +static int +sock_call_ex(PySocketSockObject *s, + int writing, + int (*sock_func) (PySocketSockObject *s, void *data), + void *data, + int connect, + int *err) +{ + int has_timeout = (s->sock_timeout > 0); + _PyTime_t deadline = 0; + int deadline_initialized = 0; + int res; + + /* sock_call() must be called with the GIL held. */ + assert(PyGILState_Check()); + + /* outer loop to retry select() when select() is interrupted by a signal + or to retry select()+sock_func() on false positive (see above) */ + while (1) { + /* For connect(), poll even for blocking socket. The connection + runs asynchronously. */ + if (has_timeout || connect) { + _PyTime_t interval; + + if (has_timeout) { + if (deadline_initialized) { + /* recompute the timeout */ + interval = deadline - _PyTime_GetMonotonicClock(); + } + else { + deadline_initialized = 1; + deadline = _PyTime_GetMonotonicClock() + s->sock_timeout; + interval = s->sock_timeout; + } + } + else + interval = -1; + + res = internal_select(s, writing, interval, connect); + if (res == -1) { + if (err) + *err = GET_SOCK_ERROR; + + if (CHECK_ERRNO(EINTR)) { + /* select() was interrupted by a signal */ + if (PyErr_CheckSignals()) { + if (err) + *err = -1; + return -1; + } + + /* retry select() */ + continue; + } + + /* select() failed */ + s->errorhandler(); + return -1; + } + + if (res == 1) { + if (err) + *err = SOCK_TIMEOUT_ERR; + else + PyErr_SetString(socket_timeout, "timed out"); + return -1; + } + + /* the socket is ready */ + } + + /* inner loop to retry sock_func() when sock_func() is interrupted + by a signal */ + while (1) { + Py_BEGIN_ALLOW_THREADS + res = sock_func(s, data); + Py_END_ALLOW_THREADS + + if (res) { + /* sock_func() succeeded */ + if (err) + *err = 0; + return 0; + } + + if (err) + *err = GET_SOCK_ERROR; + + if (!CHECK_ERRNO(EINTR)) + break; + + /* sock_func() was interrupted by a signal */ + if (PyErr_CheckSignals()) { + if (err) + *err = -1; + return -1; + } + + /* retry sock_func() */ + } + + if (s->sock_timeout > 0 + && (CHECK_ERRNO(EWOULDBLOCK) || CHECK_ERRNO(EAGAIN))) { + /* False positive: sock_func() failed with EWOULDBLOCK or EAGAIN. + + For example, select() could indicate a socket is ready for + reading, but the data then discarded by the OS because of a + wrong checksum. + + Loop on select() to recheck for socket readyness. */ + continue; + } + + /* sock_func() failed */ + if (!err) + s->errorhandler(); + /* else: err was already set before */ + return -1; + } +} + static int sock_call(PySocketSockObject *s, int writing, int (*func) (PySocketSockObject *s, void *data), void *data) { - int has_timeout = (s->sock_timeout > 0); - _PyTime_t deadline = 0; - int deadline_initialized = 0; - int res; - - /* sock_call() must be called with the GIL held. */ - assert(PyGILState_Check()); - - /* outer loop to retry select() when select() is interrupted by a signal - or to retry select()+func() on false positive (see above) */ - while (1) { - if (has_timeout) { - _PyTime_t interval; - - if (deadline_initialized) { - /* recompute the timeout */ - interval = deadline - _PyTime_GetMonotonicClock(); - } - else { - deadline_initialized = 1; - deadline = _PyTime_GetMonotonicClock() + s->sock_timeout; - interval = s->sock_timeout; - } - - res = internal_select(s, writing, interval); - if (res == -1) { - if (CHECK_ERRNO(EINTR)) { - /* select() was interrupted by a signal */ - if (PyErr_CheckSignals()) - return -1; - - /* retry select() */ - continue; - } - - /* select() failed */ - s->errorhandler(); - return -1; - } - - if (res == 1) { - PyErr_SetString(socket_timeout, "timed out"); - return -1; - } - - /* the socket is ready */ - } - - /* inner loop to retry func() when func() is interrupted by a signal */ - while (1) { - Py_BEGIN_ALLOW_THREADS - res = func(s, data); - Py_END_ALLOW_THREADS - - if (res) { - /* func() succeeded */ - return 0; - } - - if (!CHECK_ERRNO(EINTR)) - break; - - /* func() was interrupted by a signal */ - if (PyErr_CheckSignals()) - return -1; - - /* retry func() */ - } - - if (s->sock_timeout > 0 - && (CHECK_ERRNO(EWOULDBLOCK) || CHECK_ERRNO(EAGAIN))) { - /* False positive: func() failed with EWOULDBLOCK or EAGAIN. - - For example, select() could indicate a socket is ready for - reading, but the data then discarded by the OS because of a - wrong checksum. - - Loop on select() to recheck for socket readyness. */ - continue; - } - - /* func() failed */ - s->errorhandler(); - return -1; - } + return sock_call_ex(s, writing, func, data, 0, NULL); } @@ -2519,23 +2577,26 @@ can be reused for other purposes. The file descriptor is returned."); static int +sock_connect_impl(PySocketSockObject *s, void* Py_UNUSED(data)) +{ + int err; + socklen_t size = sizeof err; + + if (getsockopt(s->sock_fd, SOL_SOCKET, SO_ERROR, (void *)&err, &size)) { + /* getsockopt() failed */ + return 0; + } + + if (err == EISCONN) + return 1; + return (err == 0); +} + +static int internal_connect(PySocketSockObject *s, struct sockaddr *addr, int addrlen, - int *timeoutp) + int raise) { -#ifdef MS_WINDOWS -# define GET_ERROR WSAGetLastError() -# define IN_PROGRESS_ERR WSAEWOULDBLOCK -# define TIMEOUT_ERR WSAEWOULDBLOCK -#else -# define GET_ERROR errno -# define IN_PROGRESS_ERR EINPROGRESS -# define TIMEOUT_ERR EWOULDBLOCK -#endif - - int res, err, wait_connect, timeout; - socklen_t res_size; - - *timeoutp = 0; + int res, err, wait_connect; Py_BEGIN_ALLOW_THREADS res = connect(s->sock_fd, addr, addrlen); @@ -2546,44 +2607,53 @@ return 0; } - err = GET_ERROR; - if (CHECK_ERRNO(EINTR) && PyErr_CheckSignals()) - return -1; - - wait_connect = (s->sock_timeout > 0 && err == IN_PROGRESS_ERR - && IS_SELECTABLE(s)); - if (!wait_connect) - return err; - - timeout = internal_connect_select(s); - if (timeout == -1) { - /* select() failed */ - err = GET_ERROR; - if (CHECK_ERRNO(EINTR) && PyErr_CheckSignals()) + /* connect() failed */ + + /* save error, PyErr_CheckSignals() can replace it */ + err = GET_SOCK_ERROR; + if (CHECK_ERRNO(EINTR)) { + if (PyErr_CheckSignals()) return -1; - return err; - } - - if (timeout == 1) { - /* select() timed out */ - *timeoutp = 1; - return TIMEOUT_ERR; - } - - res_size = sizeof res; - if (getsockopt(s->sock_fd, SOL_SOCKET, SO_ERROR, - (void *)&res, &res_size)) { - /* getsockopt() failed */ - return GET_ERROR; - } - - if (res == EISCONN) - return 0; - return res; - -#undef GET_ERROR -#undef IN_PROGRESS_ERR -#undef TIMEOUT_ERR + + /* Issue #23618: when connect() fails with EINTR, the connection is + running asynchronously. + + If the socket is blocking or has a timeout, wait until the + connection completes, fails or timed out using select(), and then + get the connection status using getsockopt(SO_ERROR). + + If the socket is non-blocking, raise InterruptedError. The caller is + responsible to wait until the connection completes, fails or timed + out (it's the case in asyncio for example). */ + wait_connect = (s->sock_timeout != 0 && IS_SELECTABLE(s)); + } + else { + wait_connect = (s->sock_timeout > 0 && err == SOCK_INPROGRESS_ERR + && IS_SELECTABLE(s)); + } + + if (!wait_connect) { + if (raise) { + /* restore error, maybe replaced by PyErr_CheckSignals() */ + SET_SOCK_ERROR(err); + s->errorhandler(); + return -1; + } + else + return err; + } + + if (raise) { + /* socket.connect() raises an exception on error */ + if (sock_call_ex(s, 1, sock_connect_impl, NULL, 1, NULL) < 0) + return -1; + } + else { + /* socket.connect_ex() returns the error code on error */ + if (sock_call_ex(s, 1, sock_connect_impl, NULL, 1, &err) < 0) + return err; + } + return 0; } /* s.connect(sockaddr) method */ @@ -2594,29 +2664,14 @@ sock_addr_t addrbuf; int addrlen; int res; - int timeout; if (!getsockaddrarg(s, addro, SAS2SA(&addrbuf), &addrlen)) return NULL; - res = internal_connect(s, SAS2SA(&addrbuf), addrlen, &timeout); + res = internal_connect(s, SAS2SA(&addrbuf), addrlen, 1); if (res < 0) return NULL; - if (timeout == 1) { - PyErr_SetString(socket_timeout, "timed out"); - return NULL; - } - - if (res != 0) { -#ifdef MS_WINDOWS - WSASetLastError(res); -#else - errno = res; -#endif - return s->errorhandler(); - } - Py_RETURN_NONE; } @@ -2635,12 +2690,11 @@ sock_addr_t addrbuf; int addrlen; int res; - int timeout; if (!getsockaddrarg(s, addro, SAS2SA(&addrbuf), &addrlen)) return NULL; - res = internal_connect(s, SAS2SA(&addrbuf), addrlen, &timeout); + res = internal_connect(s, SAS2SA(&addrbuf), addrlen, 0); if (res < 0) return NULL; -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Apr 2 13:56:46 2015 From: python-checkins at python.org (victor.stinner) Date: Thu, 02 Apr 2015 11:56:46 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2323648=3A_Complete?= =?utf-8?q?_the_list_of_modified_functions_for_the_PEP_475?= Message-ID: <20150402115646.29533.39578@psf.io> https://hg.python.org/cpython/rev/66e4ef9a7467 changeset: 95378:66e4ef9a7467 user: Victor Stinner date: Thu Apr 02 13:56:29 2015 +0200 summary: Issue #23648: Complete the list of modified functions for the PEP 475 files: Doc/whatsnew/3.5.rst | 32 +++++++++++++++++++++++++++++++- 1 files changed, 31 insertions(+), 1 deletions(-) diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -637,7 +637,37 @@ raise an exception: - :func:`open`, :func:`os.open`, :func:`io.open` - - :func:`os.read`, :func:`os.write` + - functions of the :mod:`faulthandler` module + - :mod:`os` functions: + + * :func:`os.fchdir` + * :func:`os.fchmod` + * :func:`os.fchown` + * :func:`os.fdatasync` + * :func:`os.fstat` + * :func:`os.fstatvfs` + * :func:`os.fsync` + * :func:`os.ftruncate` + * :func:`os.mkfifo` + * :func:`os.mknod` + * :func:`os.posix_fadvise` + * :func:`os.posix_fallocate` + * :func:`os.pread` + * :func:`os.pwrite` + * :func:`os.read` + * :func:`os.readv` + * :func:`os.sendfile` + * :func:`os.wait3` + * :func:`os.wait4` + * :func:`os.wait` + * :func:`os.waitid` + * :func:`os.waitpid` + * :func:`os.write` + * :func:`os.writev` + * special cases: :func:`os.close` and :func:`os.dup2` now ignore + :py:data:`~errno.EINTR` error, the syscall is not retried (see the PEP + for the rationale) + - :func:`select.select`, :func:`select.poll.poll`, :func:`select.epoll.poll`, :func:`select.kqueue.control`, :func:`select.devpoll.poll` - :func:`socket.socket` methods: -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Apr 2 14:23:07 2015 From: python-checkins at python.org (victor.stinner) Date: Thu, 02 Apr 2015 12:23:07 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzIyOTc3?= =?utf-8?q?=3A_Fix_test=5Fexceptions?= Message-ID: <20150402122307.27438.3911@psf.io> https://hg.python.org/cpython/rev/dafae2b3c257 changeset: 95379:dafae2b3c257 branch: 3.4 parent: 95373:4255ca2f5314 user: Victor Stinner date: Thu Apr 02 14:17:38 2015 +0200 summary: Issue #22977: Fix test_exceptions files: Lib/test/test_exceptions.py | 13 ++++++++----- 1 files changed, 8 insertions(+), 5 deletions(-) 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 @@ -10,7 +10,7 @@ from test.support import (TESTFN, captured_output, check_impl_detail, check_warnings, cpython_only, gc_collect, run_unittest, - no_tracing, unlink, get_attribute) + no_tracing, unlink, import_module) class NaiveException(Exception): def __init__(self, x): @@ -246,12 +246,15 @@ self.assertEqual(w.strerror, 'foo') self.assertEqual(w.filename, None) + @unittest.skipUnless(sys.platform == 'win32', + 'test specific to Windows') def test_windows_message(self): """Should fill in unknown error code in Windows error message""" - windll = get_attribute(ctypes, "windll") - code = int.from_bytes(b"\xE0msc", "big") - with self.assertRaisesRegex(OSError, hex(code)): - windll.kernel32.RaiseException(code, 0, 0, None) + ctypes = import_module('ctypes') + # this error code has no message, Python formats it as hexadecimal + code = 3765269347 + with self.assertRaisesRegex(OSError, 'Windows Error 0x%x' % code): + ctypes.pythonapi.PyErr_SetFromWindowsErr(code) def testAttributes(self): # test that exception attributes are happy -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Apr 2 14:23:07 2015 From: python-checkins at python.org (victor.stinner) Date: Thu, 02 Apr 2015 12:23:07 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?b?KTogTWVyZ2UgMy40ICh0ZXN0X2V4Y2VwdGlvbnMp?= Message-ID: <20150402122307.29541.18208@psf.io> https://hg.python.org/cpython/rev/c4f8b56cb4e3 changeset: 95380:c4f8b56cb4e3 parent: 95378:66e4ef9a7467 parent: 95379:dafae2b3c257 user: Victor Stinner date: Thu Apr 02 14:22:44 2015 +0200 summary: Merge 3.4 (test_exceptions) files: Lib/test/test_exceptions.py | 13 ++++++++----- 1 files changed, 8 insertions(+), 5 deletions(-) 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 @@ -10,7 +10,7 @@ from test.support import (TESTFN, captured_output, check_impl_detail, check_warnings, cpython_only, gc_collect, run_unittest, - no_tracing, unlink, get_attribute) + no_tracing, unlink, import_module) class NaiveException(Exception): def __init__(self, x): @@ -246,12 +246,15 @@ self.assertEqual(w.strerror, 'foo') self.assertEqual(w.filename, None) + @unittest.skipUnless(sys.platform == 'win32', + 'test specific to Windows') def test_windows_message(self): """Should fill in unknown error code in Windows error message""" - windll = get_attribute(ctypes, "windll") - code = int.from_bytes(b"\xE0msc", "big") - with self.assertRaisesRegex(OSError, hex(code)): - windll.kernel32.RaiseException(code, 0, 0, None) + ctypes = import_module('ctypes') + # this error code has no message, Python formats it as hexadecimal + code = 3765269347 + with self.assertRaisesRegex(OSError, 'Windows Error 0x%x' % code): + ctypes.pythonapi.PyErr_SetFromWindowsErr(code) def testAttributes(self): # test that exception attributes are happy -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Apr 2 14:38:11 2015 From: python-checkins at python.org (victor.stinner) Date: Thu, 02 Apr 2015 12:38:11 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2323618=3A_Fix_sock?= =?utf-8?q?=5Fconnect=5Fimpl=28=29=2C_set_the_socket_error_code?= Message-ID: <20150402123811.27446.73453@psf.io> https://hg.python.org/cpython/rev/44adbb5eeb4b changeset: 95381:44adbb5eeb4b user: Victor Stinner date: Thu Apr 02 14:37:20 2015 +0200 summary: Issue #23618: Fix sock_connect_impl(), set the socket error code sock_call_ex() gets the socket error code when the socket function fails. sock_connect_impl() didn't set the error correctly. files: Modules/socketmodule.c | 8 +++++++- 1 files changed, 7 insertions(+), 1 deletions(-) diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -2589,7 +2589,13 @@ if (err == EISCONN) return 1; - return (err == 0); + if (err != 0) { + /* sock_call_ex() uses GET_SOCK_ERROR() to get the error code */ + SET_SOCK_ERROR(err); + abort(); + return 0; + } + return 1; } static int -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Apr 2 15:20:19 2015 From: python-checkins at python.org (victor.stinner) Date: Thu, 02 Apr 2015 13:20:19 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2323618=3A_Ooops=2C?= =?utf-8?q?_remove_abort=28=29_added_for_debug_purpose?= Message-ID: <20150402132019.16248.49120@psf.io> https://hg.python.org/cpython/rev/09a4d5cc6afd changeset: 95382:09a4d5cc6afd user: Victor Stinner date: Thu Apr 02 15:17:12 2015 +0200 summary: Issue #23618: Ooops, remove abort() added for debug purpose files: Modules/socketmodule.c | 1 - 1 files changed, 0 insertions(+), 1 deletions(-) diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -2592,7 +2592,6 @@ if (err != 0) { /* sock_call_ex() uses GET_SOCK_ERROR() to get the error code */ SET_SOCK_ERROR(err); - abort(); return 0; } return 1; -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Apr 2 15:59:21 2015 From: python-checkins at python.org (matthias.klose) Date: Thu, 02 Apr 2015 13:59:21 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogLSBTZXQgUFlfVkVS?= =?utf-8?q?SION_to_=222=2E7=2E10b0=22=2C_PY=5FMICRO=5FVERSION_to_10_and?= Message-ID: <20150402135921.29535.84126@psf.io> https://hg.python.org/cpython/rev/d81d6f274d60 changeset: 95383:d81d6f274d60 branch: 2.7 parent: 95372:954e7e1d85f1 user: doko at ubuntu.com date: Thu Apr 02 15:59:13 2015 +0200 summary: - Set PY_VERSION to "2.7.10b0", PY_MICRO_VERSION to 10 and PY_RELEASE_LEVEL to PY_RELEASE_LEVEL_BETA. files: Include/patchlevel.h | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Include/patchlevel.h b/Include/patchlevel.h --- a/Include/patchlevel.h +++ b/Include/patchlevel.h @@ -22,12 +22,12 @@ /*--start constants--*/ #define PY_MAJOR_VERSION 2 #define PY_MINOR_VERSION 7 -#define PY_MICRO_VERSION 9 -#define PY_RELEASE_LEVEL PY_RELEASE_LEVEL_FINAL +#define PY_MICRO_VERSION 10 +#define PY_RELEASE_LEVEL PY_RELEASE_LEVEL_BETA #define PY_RELEASE_SERIAL 0 /* Version as a string */ -#define PY_VERSION "2.7.9+" +#define PY_VERSION "2.7.10b0" /*--end constants--*/ /* Subversion Revision number of this file (not of the repository). Empty -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Apr 2 16:26:30 2015 From: python-checkins at python.org (victor.stinner) Date: Thu, 02 Apr 2015 14:26:30 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzIzODUx?= =?utf-8?q?=3A_close=28=29_must_not_be_retried_when_it_fails_with_EINTR?= Message-ID: <20150402142630.15209.34920@psf.io> https://hg.python.org/cpython/rev/e54b23d7afa6 changeset: 95384:e54b23d7afa6 branch: 3.4 parent: 95379:dafae2b3c257 user: Victor Stinner date: Thu Apr 02 16:24:46 2015 +0200 summary: Issue #23851: close() must not be retried when it fails with EINTR See the PEP 475 for the rationale. files: Modules/_posixsubprocess.c | 12 ++++++------ 1 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Modules/_posixsubprocess.c b/Modules/_posixsubprocess.c --- a/Modules/_posixsubprocess.c +++ b/Modules/_posixsubprocess.c @@ -207,13 +207,13 @@ if (keep_fd < start_fd) continue; for (fd_num = start_fd; fd_num < keep_fd; ++fd_num) { - while (close(fd_num) < 0 && errno == EINTR); + close(fd_num); } start_fd = keep_fd + 1; } if (start_fd <= end_fd) { for (fd_num = start_fd; fd_num < end_fd; ++fd_num) { - while (close(fd_num) < 0 && errno == EINTR); + close(fd_num); } } } @@ -274,11 +274,11 @@ continue; /* Not a number. */ if (fd != fd_dir_fd && fd >= start_fd && !_is_fd_in_sorted_fd_sequence(fd, py_fds_to_keep)) { - while (close(fd) < 0 && errno == EINTR); + close(fd); } } } - while (close(fd_dir_fd) < 0 && errno == EINTR); + close(fd_dir_fd); } } @@ -312,7 +312,7 @@ * reuse that fd otherwise we might close opendir's file descriptor in * our loop. This trick assumes that fd's are allocated on a lowest * available basis. */ - while (close(start_fd) < 0 && errno == EINTR); + close(start_fd); ++start_fd; #endif @@ -339,7 +339,7 @@ continue; /* Not a number. */ if (fd != fd_used_by_opendir && fd >= start_fd && !_is_fd_in_sorted_fd_sequence(fd, py_fds_to_keep)) { - while (close(fd) < 0 && errno == EINTR); + close(fd); } errno = 0; } -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Apr 2 16:26:30 2015 From: python-checkins at python.org (victor.stinner) Date: Thu, 02 Apr 2015 14:26:30 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Merge_3=2E4_=28=5Fposixsubprocess=29?= Message-ID: <20150402142630.16501.52067@psf.io> https://hg.python.org/cpython/rev/e28221e52d24 changeset: 95385:e28221e52d24 parent: 95382:09a4d5cc6afd parent: 95384:e54b23d7afa6 user: Victor Stinner date: Thu Apr 02 16:25:01 2015 +0200 summary: Merge 3.4 (_posixsubprocess) files: Modules/_posixsubprocess.c | 12 ++++++------ 1 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Modules/_posixsubprocess.c b/Modules/_posixsubprocess.c --- a/Modules/_posixsubprocess.c +++ b/Modules/_posixsubprocess.c @@ -207,13 +207,13 @@ if (keep_fd < start_fd) continue; for (fd_num = start_fd; fd_num < keep_fd; ++fd_num) { - while (close(fd_num) < 0 && errno == EINTR); + close(fd_num); } start_fd = keep_fd + 1; } if (start_fd <= end_fd) { for (fd_num = start_fd; fd_num < end_fd; ++fd_num) { - while (close(fd_num) < 0 && errno == EINTR); + close(fd_num); } } } @@ -274,11 +274,11 @@ continue; /* Not a number. */ if (fd != fd_dir_fd && fd >= start_fd && !_is_fd_in_sorted_fd_sequence(fd, py_fds_to_keep)) { - while (close(fd) < 0 && errno == EINTR); + close(fd); } } } - while (close(fd_dir_fd) < 0 && errno == EINTR); + close(fd_dir_fd); } } @@ -312,7 +312,7 @@ * reuse that fd otherwise we might close opendir's file descriptor in * our loop. This trick assumes that fd's are allocated on a lowest * available basis. */ - while (close(start_fd) < 0 && errno == EINTR); + close(start_fd); ++start_fd; #endif @@ -339,7 +339,7 @@ continue; /* Not a number. */ if (fd != fd_used_by_opendir && fd >= start_fd && !_is_fd_in_sorted_fd_sequence(fd, py_fds_to_keep)) { - while (close(fd) < 0 && errno == EINTR); + close(fd); } errno = 0; } -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Apr 2 17:22:05 2015 From: python-checkins at python.org (victor.stinner) Date: Thu, 02 Apr 2015 15:22:05 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzIzODM0?= =?utf-8?q?=3A_Fix_socket=2Esendto=28=29=2C_use_the_C_Py=5Fssize=5Ft_type_?= =?utf-8?q?to_store_the?= Message-ID: <20150402152205.16517.36055@psf.io> https://hg.python.org/cpython/rev/436bb7ad6349 changeset: 95387:436bb7ad6349 branch: 3.4 parent: 95384:e54b23d7afa6 user: Victor Stinner date: Thu Apr 02 17:16:08 2015 +0200 summary: Issue #23834: Fix socket.sendto(), use the C Py_ssize_t type to store the result of sendto() instead of the C int type. files: Misc/NEWS | 3 +++ Modules/socketmodule.c | 3 ++- 2 files changed, 5 insertions(+), 1 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -24,6 +24,9 @@ Library ------- +- Issue #23834: Fix socket.sendto(), use the C Py_ssize_t type to store the + result of sendto() instead of the C int type. + - Issue #21526: Tkinter now supports new boolean type in Tcl 8.5. - Issue #23838: linecache now clears the cache and returns an empty result on diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -3366,7 +3366,8 @@ char *buf; Py_ssize_t len, arglen; sock_addr_t addrbuf; - int addrlen, n = -1, flags, timeout; + int addrlen, flags, timeout; + Py_ssize_t n = -1; flags = 0; arglen = PyTuple_Size(args); -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Apr 2 17:22:05 2015 From: python-checkins at python.org (victor.stinner) Date: Thu, 02 Apr 2015 15:22:05 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_=28Merge_3=2E4=29_Issue_=2323834=3A_Fix_socket=2Esendto?= =?utf-8?q?=28=29=2C_use_the_C_Py=5Fssize=5Ft_type_to?= Message-ID: <20150402152205.29537.35512@psf.io> https://hg.python.org/cpython/rev/a064abfd436c changeset: 95388:a064abfd436c parent: 95385:e28221e52d24 parent: 95387:436bb7ad6349 user: Victor Stinner date: Thu Apr 02 17:20:48 2015 +0200 summary: (Merge 3.4) Issue #23834: Fix socket.sendto(), use the C Py_ssize_t type to store the result of sendto() instead of the C int type. (The bug was already fixed in the default branch, but differently.) 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 @@ -16,6 +16,9 @@ Library ------- +- Issue #23834: Fix socket.sendto(), use the C Py_ssize_t type to store the + result of sendto() instead of the C int type. + - Issue #23618: :meth:`socket.socket.connect` now waits until the connection completes instead of raising :exc:`InterruptedError` if the connection is interrupted by signals, signal handlers don't raise an exception and the -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Apr 2 17:22:09 2015 From: python-checkins at python.org (victor.stinner) Date: Thu, 02 Apr 2015 15:22:09 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzIzODM0?= =?utf-8?q?=3A_Fix_socket=2Esendto=28=29=2C_use_the_C_long_type_to_store_t?= =?utf-8?q?he_result_of?= Message-ID: <20150402152205.14221.39333@psf.io> https://hg.python.org/cpython/rev/29c32ca46652 changeset: 95386:29c32ca46652 branch: 2.7 parent: 95383:d81d6f274d60 user: Victor Stinner date: Thu Apr 02 17:19:17 2015 +0200 summary: Issue #23834: Fix socket.sendto(), use the C long type to store the result of sendto() instead of the C int type. files: Misc/NEWS | 3 +++ Modules/socketmodule.c | 3 ++- 2 files changed, 5 insertions(+), 1 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -21,6 +21,9 @@ Library ------- +- Issue #23834: Fix socket.sendto(), use the C long type to store the result of + sendto() instead of the C int type. + - Issue #21526: Tkinter now supports new boolean type in Tcl 8.5. - Issue #23838: linecache now clears the cache and returns an empty result on diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -2901,7 +2901,8 @@ char *buf; Py_ssize_t len; sock_addr_t addrbuf; - int addrlen, n = -1, flags, timeout; + int addrlen, flags, timeout; + long n = -1; int arglen; flags = 0; -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Apr 2 17:49:41 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Thu, 02 Apr 2015 15:49:41 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzE2ODQw?= =?utf-8?q?=3A_Tkinter_now_supports_64-bit_integers_added_in_Tcl_8=2E4_and?= Message-ID: <20150402154941.16505.90097@psf.io> https://hg.python.org/cpython/rev/a6f4d8fa7ab8 changeset: 95390:a6f4d8fa7ab8 branch: 3.4 parent: 95387:436bb7ad6349 user: Serhiy Storchaka date: Thu Apr 02 18:46:50 2015 +0300 summary: Issue #16840: Tkinter now supports 64-bit integers added in Tcl 8.4 and arbitrary precision integers added in Tcl 8.5. files: Lib/test/test_tcl.py | 46 +++++- Misc/NEWS | 3 + Modules/_tkinter.c | 222 ++++++++++++++++++++++++++++-- 3 files changed, 248 insertions(+), 23 deletions(-) diff --git a/Lib/test/test_tcl.py b/Lib/test/test_tcl.py --- a/Lib/test/test_tcl.py +++ b/Lib/test/test_tcl.py @@ -133,9 +133,22 @@ tcl = self.interp self.assertRaises(TclError,tcl.unsetvar,'a') + def get_integers(self): + integers = (0, 1, -1, 2**31-1, -2**31) + if tcl_version >= (8, 4): # wideInt was added in Tcl 8.4 + integers += (2**31, -2**31-1, 2**63-1, -2**63) + if tcl_version >= (8, 5): # bignum was added in Tcl 8.5 + integers += (2**63, -2**63-1, 2**1000, -2**1000) + return integers + def test_getint(self): tcl = self.interp.tk - self.assertEqual(tcl.getint(' 42 '), 42) + for i in self.get_integers(): + self.assertEqual(tcl.getint(' %d ' % i), i) + self.assertEqual(tcl.getint(' %#o ' % i), i) + self.assertEqual(tcl.getint(' %#x ' % i), i) + if tcl_version < (8, 5): # bignum was added in Tcl 8.5 + self.assertRaises(TclError, tcl.getint, str(2**1000)) self.assertEqual(tcl.getint(42), 42) self.assertRaises(TypeError, tcl.getint) self.assertRaises(TypeError, tcl.getint, '42', '10') @@ -270,7 +283,7 @@ check('"a\xbd\u20ac"', 'a\xbd\u20ac') check(r'"a\xbd\u20ac"', 'a\xbd\u20ac') check(r'"a\0b"', 'a\x00b') - if tcl_version >= (8, 5): + if tcl_version >= (8, 5): # bignum was added in Tcl 8.5 check('2**64', str(2**64)) def test_exprdouble(self): @@ -302,7 +315,7 @@ check('[string length "a\xbd\u20ac"]', 3.0) check(r'[string length "a\xbd\u20ac"]', 3.0) self.assertRaises(TclError, tcl.exprdouble, '"abc"') - if tcl_version >= (8, 5): + if tcl_version >= (8, 5): # bignum was added in Tcl 8.5 check('2**64', float(2**64)) def test_exprlong(self): @@ -334,7 +347,7 @@ check('[string length "a\xbd\u20ac"]', 3) check(r'[string length "a\xbd\u20ac"]', 3) self.assertRaises(TclError, tcl.exprlong, '"abc"') - if tcl_version >= (8, 5): + if tcl_version >= (8, 5): # bignum was added in Tcl 8.5 self.assertRaises(TclError, tcl.exprlong, '2**64') def test_exprboolean(self): @@ -375,7 +388,7 @@ check('[string length "a\xbd\u20ac"]', True) check(r'[string length "a\xbd\u20ac"]', True) self.assertRaises(TclError, tcl.exprboolean, '"abc"') - if tcl_version >= (8, 5): + if tcl_version >= (8, 5): # bignum was added in Tcl 8.5 check('2**64', True) def test_booleans(self): @@ -397,6 +410,21 @@ check('1 < 2', True) check('1 > 2', False) + def test_expr_bignum(self): + tcl = self.interp + for i in self.get_integers(): + result = tcl.call('expr', str(i)) + if self.wantobjects: + self.assertEqual(result, i) + self.assertIsInstance(result, int) + else: + self.assertEqual(result, str(i)) + self.assertIsInstance(result, str) + if tcl_version < (8, 5): # bignum was added in Tcl 8.5 + result = tcl.call('expr', str(2**1000)) + self.assertEqual(result, str(2**1000)) + self.assertIsInstance(result, str) + def test_passing_values(self): def passValue(value): return self.interp.call('set', '_', value) @@ -414,8 +442,10 @@ b'str\xc0\x80ing' if self.wantobjects else 'str\xc0\x80ing') self.assertEqual(passValue(b'str\xbding'), b'str\xbding' if self.wantobjects else 'str\xbding') - for i in (0, 1, -1, 2**31-1, -2**31): + for i in self.get_integers(): self.assertEqual(passValue(i), i if self.wantobjects else str(i)) + if tcl_version < (8, 5): # bignum was added in Tcl 8.5 + self.assertEqual(passValue(2**1000), str(2**1000)) for f in (0.0, 1.0, -1.0, 1/3, sys.float_info.min, sys.float_info.max, -sys.float_info.min, -sys.float_info.max): @@ -473,8 +503,10 @@ check(b'str\x00ing', 'str\x00ing') check(b'str\xc0\x80ing', 'str\xc0\x80ing') check(b'str\xc0\x80ing\xe2\x82\xac', 'str\xc0\x80ing\xe2\x82\xac') - for i in (0, 1, -1, 2**31-1, -2**31): + for i in self.get_integers(): check(i, str(i)) + if tcl_version < (8, 5): # bignum was added in Tcl 8.5 + check(2**1000, str(2**1000)) for f in (0.0, 1.0, -1.0): check(f, repr(f)) for f in (1/3.0, sys.float_info.min, sys.float_info.max, diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -24,6 +24,9 @@ Library ------- +- Issue #16840: Tkinter now supports 64-bit integers added in Tcl 8.4 and + arbitrary precision integers added in Tcl 8.5. + - Issue #23834: Fix socket.sendto(), use the C Py_ssize_t type to store the result of sendto() instead of the C int type. diff --git a/Modules/_tkinter.c b/Modules/_tkinter.c --- a/Modules/_tkinter.c +++ b/Modules/_tkinter.c @@ -69,6 +69,11 @@ #error "Tk older than 8.3.1 not supported" #endif +#if TK_VERSION_HEX >= 0x08050000 +#define HAVE_LIBTOMMAMTH +#include +#endif + #if !(defined(MS_WINDOWS) || defined(__CYGWIN__)) #define HAVE_CREATEFILEHANDLER #endif @@ -247,6 +252,8 @@ const Tcl_ObjType *ByteArrayType; const Tcl_ObjType *DoubleType; const Tcl_ObjType *IntType; + const Tcl_ObjType *WideIntType; + const Tcl_ObjType *BignumType; const Tcl_ObjType *ListType; const Tcl_ObjType *ProcBodyType; const Tcl_ObjType *StringType; @@ -583,6 +590,8 @@ v->ByteArrayType = Tcl_GetObjType("bytearray"); v->DoubleType = Tcl_GetObjType("double"); v->IntType = Tcl_GetObjType("int"); + v->WideIntType = Tcl_GetObjType("wideInt"); + v->BignumType = Tcl_GetObjType("bignum"); v->ListType = Tcl_GetObjType("list"); v->ProcBodyType = Tcl_GetObjType("procbody"); v->StringType = Tcl_GetObjType("string"); @@ -875,28 +884,92 @@ #define CHECK_STRING_LENGTH(s) #endif +#ifdef HAVE_LIBTOMMAMTH +static Tcl_Obj* +asBignumObj(PyObject *value) +{ + Tcl_Obj *result; + int neg; + PyObject *hexstr; + char *hexchars; + mp_int bigValue; + + neg = Py_SIZE(value) < 0; + hexstr = _PyLong_Format(value, 16); + if (hexstr == NULL) + return NULL; + hexchars = PyUnicode_AsUTF8(hexstr); + if (hexchars == NULL) { + Py_DECREF(hexstr); + return NULL; + } + hexchars += neg + 2; /* skip sign and "0x" */ + mp_init(&bigValue); + if (mp_read_radix(&bigValue, hexchars, 16) != MP_OKAY) { + mp_clear(&bigValue); + Py_DECREF(hexstr); + PyErr_NoMemory(); + return NULL; + } + Py_DECREF(hexstr); + bigValue.sign = neg ? MP_NEG : MP_ZPOS; + result = Tcl_NewBignumObj(&bigValue); + mp_clear(&bigValue); + if (result == NULL) { + PyErr_NoMemory(); + return NULL; + } + return result; +} +#endif + static Tcl_Obj* AsObj(PyObject *value) { Tcl_Obj *result; - long longVal; - int overflow; if (PyBytes_Check(value)) return Tcl_NewByteArrayObj((unsigned char *)PyBytes_AS_STRING(value), PyBytes_GET_SIZE(value)); - else if (PyBool_Check(value)) + + if (PyBool_Check(value)) return Tcl_NewBooleanObj(PyObject_IsTrue(value)); - else if (PyLong_CheckExact(value) && - ((longVal = PyLong_AsLongAndOverflow(value, &overflow)), - !overflow)) { + + if (PyLong_CheckExact(value)) { + int overflow; + long longValue; +#ifdef TCL_WIDE_INT_TYPE + Tcl_WideInt wideValue; +#endif + longValue = PyLong_AsLongAndOverflow(value, &overflow); + if (!overflow) { + return Tcl_NewLongObj(longValue); + } /* If there is an overflow in the long conversion, + fall through to wideInt handling. */ +#ifdef TCL_WIDE_INT_TYPE + if (_PyLong_AsByteArray((PyLongObject *)value, + (unsigned char *)(void *)&wideValue, + sizeof(wideValue), + PY_LITTLE_ENDIAN, + /* signed */ 1) == 0) { + return Tcl_NewWideIntObj(wideValue); + } + PyErr_Clear(); +#endif + /* If there is an overflow in the wideInt conversion, + fall through to bignum handling. */ +#ifdef HAVE_LIBTOMMAMTH + return asBignumObj(value); +#endif + /* If there is no wideInt or bignum support, fall through to default object handling. */ - return Tcl_NewLongObj(longVal); } - else if (PyFloat_Check(value)) + + if (PyFloat_Check(value)) return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value)); - else if (PyTuple_Check(value)) { + + if (PyTuple_Check(value)) { Tcl_Obj **argv; Py_ssize_t size, i; @@ -916,7 +989,8 @@ ckfree(FREECAST argv); return result; } - else if (PyUnicode_Check(value)) { + + if (PyUnicode_Check(value)) { void *inbuf; Py_ssize_t size; int kind; @@ -966,12 +1040,14 @@ ckfree(FREECAST outbuf); return result; } - else if(PyTclObject_Check(value)) { + + if (PyTclObject_Check(value)) { Tcl_Obj *v = ((PyTclObject*)value)->value; Tcl_IncrRefCount(v); return v; } - else { + + { PyObject *v = PyObject_Str(value); if (!v) return 0; @@ -990,6 +1066,62 @@ return PyBool_FromLong(boolValue); } +#ifdef TCL_WIDE_INT_TYPE +static PyObject* +fromWideIntObj(PyObject* tkapp, Tcl_Obj *value) +{ + Tcl_WideInt wideValue; + if (Tcl_GetWideIntFromObj(Tkapp_Interp(tkapp), value, &wideValue) == TCL_OK) { +#ifdef HAVE_LONG_LONG + if (sizeof(wideValue) <= SIZEOF_LONG_LONG) + return PyLong_FromLongLong(wideValue); +#endif + return _PyLong_FromByteArray((unsigned char *)(void *)&wideValue, + sizeof(wideValue), + PY_LITTLE_ENDIAN, + /* signed */ 1); + } + return NULL; +} +#endif + +#ifdef HAVE_LIBTOMMAMTH +static PyObject* +fromBignumObj(PyObject* tkapp, Tcl_Obj *value) +{ + mp_int bigValue; + unsigned long numBytes; + unsigned char *bytes; + PyObject *res; + + if (Tcl_GetBignumFromObj(Tkapp_Interp(tkapp), value, &bigValue) != TCL_OK) + return Tkinter_Error(tkapp); + numBytes = mp_unsigned_bin_size(&bigValue); + bytes = PyMem_Malloc(numBytes); + if (bytes == NULL) { + mp_clear(&bigValue); + return PyErr_NoMemory(); + } + if (mp_to_unsigned_bin_n(&bigValue, bytes, + &numBytes) != MP_OKAY) { + mp_clear(&bigValue); + PyMem_Free(bytes); + return PyErr_NoMemory(); + } + res = _PyLong_FromByteArray(bytes, numBytes, + /* big-endian */ 0, + /* unsigned */ 0); + PyMem_Free(bytes); + if (res != NULL && bigValue.sign == MP_NEG) { + PyObject *res2 = PyNumber_Negative(res); + Py_DECREF(res); + res = res2; + } + mp_clear(&bigValue); + return res; +} +#endif + static PyObject* FromObj(PyObject* tkapp, Tcl_Obj *value) { @@ -1017,9 +1149,33 @@ } if (value->typePtr == app->IntType) { - return PyLong_FromLong(value->internalRep.longValue); + long longValue; + if (Tcl_GetLongFromObj(interp, value, &longValue) == TCL_OK) + return PyLong_FromLong(longValue); + /* If there is an error in the long conversion, + fall through to wideInt handling. */ } +#ifdef TCL_WIDE_INT_TYPE + if (value->typePtr == app->IntType || + value->typePtr == app->WideIntType) { + result = fromWideIntObj(tkapp, value); + if (result != NULL || PyErr_Occurred()) + return result; + Tcl_ResetResult(interp); + /* If there is an error in the wideInt conversion, + fall through to bignum handling. */ + } +#endif + +#ifdef HAVE_LIBTOMMAMTH + if (value->typePtr == app->IntType || + value->typePtr == app->WideIntType || + value->typePtr == app->BignumType) { + return fromBignumObj(tkapp, value); + } +#endif + if (value->typePtr == app->ListType) { int size; int i, status; @@ -1067,6 +1223,15 @@ } #endif +#ifdef HAVE_LIBTOMMAMTH + if (app->BignumType == NULL && + strcmp(value->typePtr->name, "bignum") == 0) { + /* bignum type is not registered in Tcl */ + app->BignumType = value->typePtr; + return fromBignumObj(tkapp, value); + } +#endif + return newPyTclObject(value); } @@ -1700,7 +1865,12 @@ Tkapp_GetInt(PyObject *self, PyObject *args) { char *s; - int v; +#if defined(TCL_WIDE_INT_TYPE) || defined(HAVE_LIBTOMMAMTH) + Tcl_Obj *value; + PyObject *result; +#else + int intValue; +#endif if (PyTuple_Size(args) == 1) { PyObject* o = PyTuple_GetItem(args, 0); @@ -1712,9 +1882,29 @@ if (!PyArg_ParseTuple(args, "s:getint", &s)) return NULL; CHECK_STRING_LENGTH(s); - if (Tcl_GetInt(Tkapp_Interp(self), s, &v) == TCL_ERROR) +#if defined(TCL_WIDE_INT_TYPE) || defined(HAVE_LIBTOMMAMTH) + value = Tcl_NewStringObj(s, -1); + if (value == NULL) return Tkinter_Error(self); - return Py_BuildValue("i", v); + /* Don't use Tcl_GetInt() because it returns ambiguous result for value + in ranges -2**32..-2**31-1 and 2**31..2**32-1 (on 32-bit platform). + + Prefer bignum because Tcl_GetWideIntFromObj returns ambiguous result for + value in ranges -2**64..-2**63-1 and 2**63..2**64-1 (on 32-bit platform). + */ +#ifdef HAVE_LIBTOMMAMTH + result = fromBignumObj(self, value); +#else + result = fromWideIntObj(self, value); +#endif + Tcl_DecrRefCount(value); + if (result != NULL || PyErr_Occurred()) + return result; +#else + if (Tcl_GetInt(Tkapp_Interp(self), s, &intValue) == TCL_OK) + return PyLong_FromLong(intValue); +#endif + return Tkinter_Error(self); } static PyObject * -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Apr 2 17:49:41 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Thu, 02 Apr 2015 15:49:41 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzE2ODQw?= =?utf-8?q?=3A_Tkinter_now_supports_64-bit_integers_added_in_Tcl_8=2E4_and?= Message-ID: <20150402154941.129143.63345@psf.io> https://hg.python.org/cpython/rev/42a6449e577c changeset: 95389:42a6449e577c branch: 2.7 parent: 95386:29c32ca46652 user: Serhiy Storchaka date: Thu Apr 02 18:46:30 2015 +0300 summary: Issue #16840: Tkinter now supports 64-bit integers added in Tcl 8.4 and arbitrary precision integers added in Tcl 8.5. files: Lib/test/test_tcl.py | 49 +++++- Misc/NEWS | 3 + Modules/_tkinter.c | 235 +++++++++++++++++++++++++++++- 3 files changed, 267 insertions(+), 20 deletions(-) diff --git a/Lib/test/test_tcl.py b/Lib/test/test_tcl.py --- a/Lib/test/test_tcl.py +++ b/Lib/test/test_tcl.py @@ -130,9 +130,24 @@ tcl = self.interp self.assertRaises(TclError,tcl.unsetvar,'a') + def get_integers(self): + integers = (0, 1, -1, 2**31-1, -2**31) + if tcl_version >= (8, 4): # wideInt was added in Tcl 8.4 + integers += (2**31, -2**31-1, 2**63-1, -2**63) + if tcl_version >= (8, 5): # bignum was added in Tcl 8.5 + integers += (2**63, -2**63-1, 2**1000, -2**1000) + return integers + def test_getint(self): tcl = self.interp.tk - self.assertEqual(tcl.getint(' 42 '), 42) + for i in self.get_integers(): + result = tcl.getint(' %d ' % i) + self.assertEqual(result, i) + self.assertIsInstance(result, type(int(result))) + self.assertEqual(tcl.getint(' %#o ' % i), i) + self.assertEqual(tcl.getint(' %#x ' % i), i) + if tcl_version < (8, 5): # bignum was added in Tcl 8.5 + self.assertRaises(TclError, tcl.getint, str(2**1000)) self.assertEqual(tcl.getint(42), 42) self.assertRaises(TypeError, tcl.getint) self.assertRaises(TypeError, tcl.getint, '42', '10') @@ -286,7 +301,7 @@ check('"a\xc2\xbd\xe2\x82\xac"', 'a\xc2\xbd\xe2\x82\xac') check(r'"a\xbd\u20ac"', 'a\xc2\xbd\xe2\x82\xac') check(r'"a\0b"', 'a\xc0\x80b') - if tcl_version >= (8, 5): + if tcl_version >= (8, 5): # bignum was added in Tcl 8.5 check('2**64', str(2**64)) def test_exprdouble(self): @@ -317,7 +332,7 @@ check('[string length "a\xc2\xbd\xe2\x82\xac"]', 3.0) check(r'[string length "a\xbd\u20ac"]', 3.0) self.assertRaises(TclError, tcl.exprdouble, '"abc"') - if tcl_version >= (8, 5): + if tcl_version >= (8, 5): # bignum was added in Tcl 8.5 check('2**64', float(2**64)) def test_exprlong(self): @@ -348,7 +363,7 @@ check('[string length "a\xc2\xbd\xe2\x82\xac"]', 3) check(r'[string length "a\xbd\u20ac"]', 3) self.assertRaises(TclError, tcl.exprlong, '"abc"') - if tcl_version >= (8, 5): + if tcl_version >= (8, 5): # bignum was added in Tcl 8.5 self.assertRaises(TclError, tcl.exprlong, '2**64') def test_exprboolean(self): @@ -388,7 +403,7 @@ check('[string length "a\xc2\xbd\xe2\x82\xac"]', True) check(r'[string length "a\xbd\u20ac"]', True) self.assertRaises(TclError, tcl.exprboolean, '"abc"') - if tcl_version >= (8, 5): + if tcl_version >= (8, 5): # bignum was added in Tcl 8.5 check('2**64', True) def test_booleans(self): @@ -410,6 +425,22 @@ check('1 < 2', True) check('1 > 2', False) + def test_expr_bignum(self): + tcl = self.interp + for i in self.get_integers(): + result = tcl.call('expr', str(i)) + if self.wantobjects: + self.assertEqual(result, i) + self.assertIsInstance(result, (int, long)) + self.assertIsInstance(result, type(int(result))) + else: + self.assertEqual(result, str(i)) + self.assertIsInstance(result, str) + if tcl_version < (8, 5): # bignum was added in Tcl 8.5 + result = tcl.call('expr', str(2**1000)) + self.assertEqual(result, str(2**1000)) + self.assertIsInstance(result, str) + def test_passing_values(self): def passValue(value): return self.interp.call('set', '_', value) @@ -427,8 +458,10 @@ self.assertEqual(passValue(u'str\x00ing'), u'str\x00ing') self.assertEqual(passValue(u'str\x00ing\xbd'), u'str\x00ing\xbd') self.assertEqual(passValue(u'str\x00ing\u20ac'), u'str\x00ing\u20ac') - for i in (0, 1, -1, int(2**31-1), int(-2**31)): + for i in self.get_integers(): self.assertEqual(passValue(i), i if self.wantobjects else str(i)) + if tcl_version < (8, 5): # bignum was added in Tcl 8.5 + self.assertEqual(passValue(2**1000), str(2**1000)) for f in (0.0, 1.0, -1.0, 1//3, 1/3.0, sys.float_info.min, sys.float_info.max, -sys.float_info.min, -sys.float_info.max): @@ -484,8 +517,10 @@ check(u'str\x00ing') check(u'str\x00ing\xbd') check(u'str\x00ing\u20ac') - for i in (0, 1, -1, 2**31-1, -2**31): + for i in self.get_integers(): check(i, str(i)) + if tcl_version < (8, 5): # bignum was added in Tcl 8.5 + check(2**1000, str(2**1000)) for f in (0.0, 1.0, -1.0): check(f, repr(f)) for f in (1/3.0, sys.float_info.min, sys.float_info.max, diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -21,6 +21,9 @@ Library ------- +- Issue #16840: Tkinter now supports 64-bit integers added in Tcl 8.4 and + arbitrary precision integers added in Tcl 8.5. + - Issue #23834: Fix socket.sendto(), use the C long type to store the result of sendto() instead of the C int type. diff --git a/Modules/_tkinter.c b/Modules/_tkinter.c --- a/Modules/_tkinter.c +++ b/Modules/_tkinter.c @@ -96,6 +96,11 @@ #error "unsupported Tcl configuration" #endif +#if TK_VERSION_HEX >= 0x08050000 +#define HAVE_LIBTOMMAMTH +#include +#endif + #if !(defined(MS_WINDOWS) || defined(__CYGWIN__)) #define HAVE_CREATEFILEHANDLER #endif @@ -262,6 +267,8 @@ const Tcl_ObjType *ByteArrayType; const Tcl_ObjType *DoubleType; const Tcl_ObjType *IntType; + const Tcl_ObjType *WideIntType; + const Tcl_ObjType *BignumType; const Tcl_ObjType *ListType; const Tcl_ObjType *ProcBodyType; const Tcl_ObjType *StringType; @@ -739,6 +746,8 @@ v->ByteArrayType = Tcl_GetObjType("bytearray"); v->DoubleType = Tcl_GetObjType("double"); v->IntType = Tcl_GetObjType("int"); + v->WideIntType = Tcl_GetObjType("wideInt"); + v->BignumType = Tcl_GetObjType("bignum"); v->ListType = Tcl_GetObjType("list"); v->ProcBodyType = Tcl_GetObjType("procbody"); v->StringType = Tcl_GetObjType("string"); @@ -1035,6 +1044,45 @@ #define CHECK_STRING_LENGTH(s) #endif +#ifdef HAVE_LIBTOMMAMTH +static Tcl_Obj* +asBignumObj(PyObject *value) +{ + Tcl_Obj *result; + int neg; + PyObject *hexstr; + char *hexchars; + mp_int bigValue; + + neg = Py_SIZE(value) < 0; + hexstr = _PyLong_Format(value, 16, 0, 1); + if (hexstr == NULL) + return NULL; + hexchars = PyString_AsString(hexstr); + if (hexchars == NULL) { + Py_DECREF(hexstr); + return NULL; + } + hexchars += neg + 2; /* skip sign and "0x" */ + mp_init(&bigValue); + if (mp_read_radix(&bigValue, hexchars, 16) != MP_OKAY) { + mp_clear(&bigValue); + Py_DECREF(hexstr); + PyErr_NoMemory(); + return NULL; + } + Py_DECREF(hexstr); + bigValue.sign = neg ? MP_NEG : MP_ZPOS; + result = Tcl_NewBignumObj(&bigValue); + mp_clear(&bigValue); + if (result == NULL) { + PyErr_NoMemory(); + return NULL; + } + return result; +} +#endif + static Tcl_Obj* AsObj(PyObject *value) { @@ -1043,13 +1091,52 @@ if (PyString_Check(value)) return Tcl_NewStringObj(PyString_AS_STRING(value), PyString_GET_SIZE(value)); - else if (PyBool_Check(value)) + + if (PyBool_Check(value)) return Tcl_NewBooleanObj(PyObject_IsTrue(value)); - else if (PyInt_Check(value)) + + if (PyInt_Check(value)) return Tcl_NewLongObj(PyInt_AS_LONG(value)); - else if (PyFloat_Check(value)) + + if (PyLong_CheckExact(value)) { + int overflow; + long longValue; +#ifdef TCL_WIDE_INT_TYPE + Tcl_WideInt wideValue; +#endif + longValue = PyLong_AsLongAndOverflow(value, &overflow); + if (!overflow) { + return Tcl_NewLongObj(longValue); + } + /* If there is an overflow in the long conversion, + fall through to wideInt handling. */ +#ifdef TCL_WIDE_INT_TYPE + if (_PyLong_AsByteArray((PyLongObject *)value, + (unsigned char *)(void *)&wideValue, + sizeof(wideValue), +#ifdef WORDS_BIGENDIAN + 0, +#else + 1, +#endif + /* signed */ 1) == 0) { + return Tcl_NewWideIntObj(wideValue); + } + PyErr_Clear(); +#endif + /* If there is an overflow in the wideInt conversion, + fall through to bignum handling. */ +#ifdef HAVE_LIBTOMMAMTH + return asBignumObj(value); +#endif + /* If there is no wideInt or bignum support, + fall through to default object handling. */ + } + + if (PyFloat_Check(value)) return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value)); - else if (PyTuple_Check(value)) { + + if (PyTuple_Check(value)) { Tcl_Obj **argv; Py_ssize_t size, i; @@ -1069,8 +1156,9 @@ ckfree(FREECAST argv); return result; } + #ifdef Py_USING_UNICODE - else if (PyUnicode_Check(value)) { + if (PyUnicode_Check(value)) { Py_UNICODE *inbuf = PyUnicode_AS_UNICODE(value); Py_ssize_t size = PyUnicode_GET_SIZE(value); /* This #ifdef assumes that Tcl uses UCS-2. @@ -1113,15 +1201,16 @@ #else return Tcl_NewUnicodeObj(inbuf, size); #endif - } #endif - else if(PyTclObject_Check(value)) { + + if(PyTclObject_Check(value)) { Tcl_Obj *v = ((PyTclObject*)value)->value; Tcl_IncrRefCount(v); return v; } - else { + + { PyObject *v = PyObject_Str(value); if (!v) return 0; @@ -1140,6 +1229,66 @@ return PyBool_FromLong(boolValue); } +#ifdef TCL_WIDE_INT_TYPE +static PyObject* +fromWideIntObj(PyObject* tkapp, Tcl_Obj *value) +{ + Tcl_WideInt wideValue; + if (Tcl_GetWideIntFromObj(Tkapp_Interp(tkapp), value, &wideValue) == TCL_OK) { +#ifdef HAVE_LONG_LONG + if (sizeof(wideValue) <= SIZEOF_LONG_LONG) + return PyLong_FromLongLong(wideValue); +#endif + return _PyLong_FromByteArray((unsigned char *)(void *)&wideValue, + sizeof(wideValue), +#ifdef WORDS_BIGENDIAN + 0, +#else + 1, +#endif + /* signed */ 1); + } + return NULL; +} +#endif + +#ifdef HAVE_LIBTOMMAMTH +static PyObject* +fromBignumObj(PyObject* tkapp, Tcl_Obj *value) +{ + mp_int bigValue; + unsigned long numBytes; + unsigned char *bytes; + PyObject *res; + + if (Tcl_GetBignumFromObj(Tkapp_Interp(tkapp), value, &bigValue) != TCL_OK) + return Tkinter_Error(tkapp); + numBytes = mp_unsigned_bin_size(&bigValue); + bytes = PyMem_Malloc(numBytes); + if (bytes == NULL) { + mp_clear(&bigValue); + return PyErr_NoMemory(); + } + if (mp_to_unsigned_bin_n(&bigValue, bytes, + &numBytes) != MP_OKAY) { + mp_clear(&bigValue); + PyMem_Free(bytes); + return PyErr_NoMemory(); + } + res = _PyLong_FromByteArray(bytes, numBytes, + /* big-endian */ 0, + /* unsigned */ 0); + PyMem_Free(bytes); + if (res != NULL && bigValue.sign == MP_NEG) { + PyObject *res2 = PyNumber_Negative(res); + Py_DECREF(res); + res = res2; + } + mp_clear(&bigValue); + return res; +} +#endif + static PyObject* FromObj(PyObject* tkapp, Tcl_Obj *value) { @@ -1168,9 +1317,33 @@ } if (value->typePtr == app->IntType) { - return PyInt_FromLong(value->internalRep.longValue); + long longValue; + if (Tcl_GetLongFromObj(interp, value, &longValue) == TCL_OK) + return PyInt_FromLong(longValue); + /* If there is an error in the long conversion, + fall through to wideInt handling. */ } +#ifdef TCL_WIDE_INT_TYPE + if (value->typePtr == app->IntType || + value->typePtr == app->WideIntType) { + result = fromWideIntObj(tkapp, value); + if (result != NULL || PyErr_Occurred()) + return result; + Tcl_ResetResult(interp); + /* If there is an error in the wideInt conversion, + fall through to bignum handling. */ + } +#endif + +#ifdef HAVE_LIBTOMMAMTH + if (value->typePtr == app->IntType || + value->typePtr == app->WideIntType || + value->typePtr == app->BignumType) { + return fromBignumObj(tkapp, value); + } +#endif + if (value->typePtr == app->ListType) { int size; int i, status; @@ -1241,6 +1414,15 @@ } #endif +#ifdef HAVE_LIBTOMMAMTH + if (app->BignumType == NULL && + strcmp(value->typePtr->name, "bignum") == 0) { + /* bignum type is not registered in Tcl */ + app->BignumType = value->typePtr; + return fromBignumObj(tkapp, value); + } +#endif + return newPyTclObject(value); } @@ -1915,11 +2097,16 @@ Tkapp_GetInt(PyObject *self, PyObject *args) { char *s; - int v; +#if defined(TCL_WIDE_INT_TYPE) || defined(HAVE_LIBTOMMAMTH) + Tcl_Obj *value; + PyObject *result; +#else + int intValue; +#endif if (PyTuple_Size(args) == 1) { PyObject* o = PyTuple_GetItem(args, 0); - if (PyInt_Check(o)) { + if (PyInt_Check(o) || PyLong_Check(o)) { Py_INCREF(o); return o; } @@ -1927,9 +2114,31 @@ if (!PyArg_ParseTuple(args, "s:getint", &s)) return NULL; CHECK_STRING_LENGTH(s); - if (Tcl_GetInt(Tkapp_Interp(self), s, &v) == TCL_ERROR) +#if defined(TCL_WIDE_INT_TYPE) || defined(HAVE_LIBTOMMAMTH) + value = Tcl_NewStringObj(s, -1); + if (value == NULL) return Tkinter_Error(self); - return Py_BuildValue("i", v); + /* Don't use Tcl_GetInt() because it returns ambiguous result for value + in ranges -2**32..-2**31-1 and 2**31..2**32-1 (on 32-bit platform). + + Prefer bignum because Tcl_GetWideIntFromObj returns ambiguous result for + value in ranges -2**64..-2**63-1 and 2**63..2**64-1 (on 32-bit platform). + */ +#ifdef HAVE_LIBTOMMAMTH + result = fromBignumObj(self, value); +#else + result = fromWideIntObj(self, value); +#endif + Tcl_DecrRefCount(value); + if (result != NULL) + return PyNumber_Int(result); + if (PyErr_Occurred()) + return NULL; +#else + if (Tcl_GetInt(Tkapp_Interp(self), s, &intValue) == TCL_OK) + return PyInt_FromLong(intValue); +#endif + return Tkinter_Error(self); } static PyObject * -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Apr 2 17:49:41 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Thu, 02 Apr 2015 15:49:41 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2316840=3A_Tkinter_now_supports_64-bit_integers_a?= =?utf-8?q?dded_in_Tcl_8=2E4_and?= Message-ID: <20150402154941.16260.27653@psf.io> https://hg.python.org/cpython/rev/9291b28157e1 changeset: 95391:9291b28157e1 parent: 95388:a064abfd436c parent: 95390:a6f4d8fa7ab8 user: Serhiy Storchaka date: Thu Apr 02 18:49:14 2015 +0300 summary: Issue #16840: Tkinter now supports 64-bit integers added in Tcl 8.4 and arbitrary precision integers added in Tcl 8.5. files: Lib/test/test_tcl.py | 44 +++++- Misc/NEWS | 3 + Modules/_tkinter.c | 209 ++++++++++++++++++++++++++++-- 3 files changed, 233 insertions(+), 23 deletions(-) diff --git a/Lib/test/test_tcl.py b/Lib/test/test_tcl.py --- a/Lib/test/test_tcl.py +++ b/Lib/test/test_tcl.py @@ -133,9 +133,20 @@ tcl = self.interp self.assertRaises(TclError,tcl.unsetvar,'a') + def get_integers(self): + integers = (0, 1, -1, 2**31-1, -2**31, 2**31, -2**31-1, 2**63-1, -2**63) + if tcl_version >= (8, 5): # bignum was added in Tcl 8.5 + integers += (2**63, -2**63-1, 2**1000, -2**1000) + return integers + def test_getint(self): tcl = self.interp.tk - self.assertEqual(tcl.getint(' 42 '), 42) + for i in self.get_integers(): + self.assertEqual(tcl.getint(' %d ' % i), i) + self.assertEqual(tcl.getint(' %#o ' % i), i) + self.assertEqual(tcl.getint(' %#x ' % i), i) + if tcl_version < (8, 5): # bignum was added in Tcl 8.5 + self.assertRaises(TclError, tcl.getint, str(2**1000)) self.assertEqual(tcl.getint(42), 42) self.assertRaises(TypeError, tcl.getint) self.assertRaises(TypeError, tcl.getint, '42', '10') @@ -270,7 +281,7 @@ check('"a\xbd\u20ac"', 'a\xbd\u20ac') check(r'"a\xbd\u20ac"', 'a\xbd\u20ac') check(r'"a\0b"', 'a\x00b') - if tcl_version >= (8, 5): + if tcl_version >= (8, 5): # bignum was added in Tcl 8.5 check('2**64', str(2**64)) def test_exprdouble(self): @@ -302,7 +313,7 @@ check('[string length "a\xbd\u20ac"]', 3.0) check(r'[string length "a\xbd\u20ac"]', 3.0) self.assertRaises(TclError, tcl.exprdouble, '"abc"') - if tcl_version >= (8, 5): + if tcl_version >= (8, 5): # bignum was added in Tcl 8.5 check('2**64', float(2**64)) def test_exprlong(self): @@ -334,7 +345,7 @@ check('[string length "a\xbd\u20ac"]', 3) check(r'[string length "a\xbd\u20ac"]', 3) self.assertRaises(TclError, tcl.exprlong, '"abc"') - if tcl_version >= (8, 5): + if tcl_version >= (8, 5): # bignum was added in Tcl 8.5 self.assertRaises(TclError, tcl.exprlong, '2**64') def test_exprboolean(self): @@ -375,7 +386,7 @@ check('[string length "a\xbd\u20ac"]', True) check(r'[string length "a\xbd\u20ac"]', True) self.assertRaises(TclError, tcl.exprboolean, '"abc"') - if tcl_version >= (8, 5): + if tcl_version >= (8, 5): # bignum was added in Tcl 8.5 check('2**64', True) def test_booleans(self): @@ -397,6 +408,21 @@ check('1 < 2', True) check('1 > 2', False) + def test_expr_bignum(self): + tcl = self.interp + for i in self.get_integers(): + result = tcl.call('expr', str(i)) + if self.wantobjects: + self.assertEqual(result, i) + self.assertIsInstance(result, int) + else: + self.assertEqual(result, str(i)) + self.assertIsInstance(result, str) + if tcl_version < (8, 5): # bignum was added in Tcl 8.5 + result = tcl.call('expr', str(2**1000)) + self.assertEqual(result, str(2**1000)) + self.assertIsInstance(result, str) + def test_passing_values(self): def passValue(value): return self.interp.call('set', '_', value) @@ -414,8 +440,10 @@ b'str\xc0\x80ing' if self.wantobjects else 'str\xc0\x80ing') self.assertEqual(passValue(b'str\xbding'), b'str\xbding' if self.wantobjects else 'str\xbding') - for i in (0, 1, -1, 2**31-1, -2**31): + for i in self.get_integers(): self.assertEqual(passValue(i), i if self.wantobjects else str(i)) + if tcl_version < (8, 5): # bignum was added in Tcl 8.5 + self.assertEqual(passValue(2**1000), str(2**1000)) for f in (0.0, 1.0, -1.0, 1/3, sys.float_info.min, sys.float_info.max, -sys.float_info.min, -sys.float_info.max): @@ -475,8 +503,10 @@ check(b'str\x00ing', 'str\x00ing') check(b'str\xc0\x80ing', 'str\xc0\x80ing') check(b'str\xc0\x80ing\xe2\x82\xac', 'str\xc0\x80ing\xe2\x82\xac') - for i in (0, 1, -1, 2**31-1, -2**31): + for i in self.get_integers(): check(i, str(i)) + if tcl_version < (8, 5): # bignum was added in Tcl 8.5 + check(2**1000, str(2**1000)) for f in (0.0, 1.0, -1.0): check(f, repr(f)) for f in (1/3.0, sys.float_info.min, sys.float_info.max, diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -16,6 +16,9 @@ Library ------- +- Issue #16840: Tkinter now supports 64-bit integers added in Tcl 8.4 and + arbitrary precision integers added in Tcl 8.5. + - Issue #23834: Fix socket.sendto(), use the C Py_ssize_t type to store the result of sendto() instead of the C int type. diff --git a/Modules/_tkinter.c b/Modules/_tkinter.c --- a/Modules/_tkinter.c +++ b/Modules/_tkinter.c @@ -56,6 +56,11 @@ #error "Tk older than 8.4 not supported" #endif +#if TK_VERSION_HEX >= 0x08050000 +#define HAVE_LIBTOMMAMTH +#include +#endif + #if !(defined(MS_WINDOWS) || defined(__CYGWIN__)) #define HAVE_CREATEFILEHANDLER #endif @@ -234,6 +239,8 @@ const Tcl_ObjType *ByteArrayType; const Tcl_ObjType *DoubleType; const Tcl_ObjType *IntType; + const Tcl_ObjType *WideIntType; + const Tcl_ObjType *BignumType; const Tcl_ObjType *ListType; const Tcl_ObjType *ProcBodyType; const Tcl_ObjType *StringType; @@ -591,6 +598,8 @@ v->ByteArrayType = Tcl_GetObjType("bytearray"); v->DoubleType = Tcl_GetObjType("double"); v->IntType = Tcl_GetObjType("int"); + v->WideIntType = Tcl_GetObjType("wideInt"); + v->BignumType = Tcl_GetObjType("bignum"); v->ListType = Tcl_GetObjType("list"); v->ProcBodyType = Tcl_GetObjType("procbody"); v->StringType = Tcl_GetObjType("string"); @@ -883,12 +892,49 @@ #define CHECK_STRING_LENGTH(s) #endif +#ifdef HAVE_LIBTOMMAMTH +static Tcl_Obj* +asBignumObj(PyObject *value) +{ + Tcl_Obj *result; + int neg; + PyObject *hexstr; + char *hexchars; + mp_int bigValue; + + neg = Py_SIZE(value) < 0; + hexstr = _PyLong_Format(value, 16); + if (hexstr == NULL) + return NULL; + hexchars = PyUnicode_AsUTF8(hexstr); + if (hexchars == NULL) { + Py_DECREF(hexstr); + return NULL; + } + hexchars += neg + 2; /* skip sign and "0x" */ + mp_init(&bigValue); + if (mp_read_radix(&bigValue, hexchars, 16) != MP_OKAY) { + mp_clear(&bigValue); + Py_DECREF(hexstr); + PyErr_NoMemory(); + return NULL; + } + Py_DECREF(hexstr); + bigValue.sign = neg ? MP_NEG : MP_ZPOS; + result = Tcl_NewBignumObj(&bigValue); + mp_clear(&bigValue); + if (result == NULL) { + PyErr_NoMemory(); + return NULL; + } + return result; +} +#endif + static Tcl_Obj* AsObj(PyObject *value) { Tcl_Obj *result; - long longVal; - int overflow; if (PyBytes_Check(value)) { if (PyBytes_GET_SIZE(value) >= INT_MAX) { @@ -898,18 +944,45 @@ return Tcl_NewByteArrayObj((unsigned char *)PyBytes_AS_STRING(value), (int)PyBytes_GET_SIZE(value)); } - else if (PyBool_Check(value)) + + if (PyBool_Check(value)) return Tcl_NewBooleanObj(PyObject_IsTrue(value)); - else if (PyLong_CheckExact(value) && - ((longVal = PyLong_AsLongAndOverflow(value, &overflow)), - !overflow)) { + + if (PyLong_CheckExact(value)) { + int overflow; + long longValue; +#ifdef TCL_WIDE_INT_TYPE + Tcl_WideInt wideValue; +#endif + longValue = PyLong_AsLongAndOverflow(value, &overflow); + if (!overflow) { + return Tcl_NewLongObj(longValue); + } /* If there is an overflow in the long conversion, + fall through to wideInt handling. */ +#ifdef TCL_WIDE_INT_TYPE + if (_PyLong_AsByteArray((PyLongObject *)value, + (unsigned char *)(void *)&wideValue, + sizeof(wideValue), + PY_LITTLE_ENDIAN, + /* signed */ 1) == 0) { + return Tcl_NewWideIntObj(wideValue); + } + PyErr_Clear(); +#endif + /* If there is an overflow in the wideInt conversion, + fall through to bignum handling. */ +#ifdef HAVE_LIBTOMMAMTH + return asBignumObj(value); +#endif + /* If there is no wideInt or bignum support, fall through to default object handling. */ - return Tcl_NewLongObj(longVal); } - else if (PyFloat_Check(value)) + + if (PyFloat_Check(value)) return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value)); - else if (PyTuple_Check(value) || PyList_Check(value)) { + + if (PyTuple_Check(value) || PyList_Check(value)) { Tcl_Obj **argv; Py_ssize_t size, i; @@ -933,7 +1006,8 @@ PyMem_Free(argv); return result; } - else if (PyUnicode_Check(value)) { + + if (PyUnicode_Check(value)) { void *inbuf; Py_ssize_t size; int kind; @@ -983,12 +1057,14 @@ PyMem_Free(outbuf); return result; } - else if(PyTclObject_Check(value)) { + + if (PyTclObject_Check(value)) { Tcl_Obj *v = ((PyTclObject*)value)->value; Tcl_IncrRefCount(v); return v; } - else { + + { PyObject *v = PyObject_Str(value); if (!v) return 0; @@ -1008,6 +1084,60 @@ } static PyObject* +fromWideIntObj(PyObject* tkapp, Tcl_Obj *value) +{ + Tcl_WideInt wideValue; + if (Tcl_GetWideIntFromObj(Tkapp_Interp(tkapp), value, &wideValue) == TCL_OK) { +#ifdef HAVE_LONG_LONG + if (sizeof(wideValue) <= SIZEOF_LONG_LONG) + return PyLong_FromLongLong(wideValue); +#endif + return _PyLong_FromByteArray((unsigned char *)(void *)&wideValue, + sizeof(wideValue), + PY_LITTLE_ENDIAN, + /* signed */ 1); + } + return NULL; +} + +#ifdef HAVE_LIBTOMMAMTH +static PyObject* +fromBignumObj(PyObject* tkapp, Tcl_Obj *value) +{ + mp_int bigValue; + unsigned long numBytes; + unsigned char *bytes; + PyObject *res; + + if (Tcl_GetBignumFromObj(Tkapp_Interp(tkapp), value, &bigValue) != TCL_OK) + return Tkinter_Error(tkapp); + numBytes = mp_unsigned_bin_size(&bigValue); + bytes = PyMem_Malloc(numBytes); + if (bytes == NULL) { + mp_clear(&bigValue); + return PyErr_NoMemory(); + } + if (mp_to_unsigned_bin_n(&bigValue, bytes, + &numBytes) != MP_OKAY) { + mp_clear(&bigValue); + PyMem_Free(bytes); + return PyErr_NoMemory(); + } + res = _PyLong_FromByteArray(bytes, numBytes, + /* big-endian */ 0, + /* unsigned */ 0); + PyMem_Free(bytes); + if (res != NULL && bigValue.sign == MP_NEG) { + PyObject *res2 = PyNumber_Negative(res); + Py_DECREF(res); + res = res2; + } + mp_clear(&bigValue); + return res; +} +#endif + +static PyObject* FromObj(PyObject* tkapp, Tcl_Obj *value) { PyObject *result = NULL; @@ -1034,9 +1164,31 @@ } if (value->typePtr == app->IntType) { - return PyLong_FromLong(value->internalRep.longValue); + long longValue; + if (Tcl_GetLongFromObj(interp, value, &longValue) == TCL_OK) + return PyLong_FromLong(longValue); + /* If there is an error in the long conversion, + fall through to wideInt handling. */ } + if (value->typePtr == app->IntType || + value->typePtr == app->WideIntType) { + result = fromWideIntObj(tkapp, value); + if (result != NULL || PyErr_Occurred()) + return result; + Tcl_ResetResult(interp); + /* If there is an error in the wideInt conversion, + fall through to bignum handling. */ + } + +#ifdef HAVE_LIBTOMMAMTH + if (value->typePtr == app->IntType || + value->typePtr == app->WideIntType || + value->typePtr == app->BignumType) { + return fromBignumObj(tkapp, value); + } +#endif + if (value->typePtr == app->ListType) { int size; int i, status; @@ -1084,6 +1236,15 @@ } #endif +#ifdef HAVE_LIBTOMMAMTH + if (app->BignumType == NULL && + strcmp(value->typePtr->name, "bignum") == 0) { + /* bignum type is not registered in Tcl */ + app->BignumType = value->typePtr; + return fromBignumObj(tkapp, value); + } +#endif + return newPyTclObject(value); } @@ -1718,7 +1879,8 @@ Tkapp_GetInt(PyObject *self, PyObject *args) { char *s; - int v; + Tcl_Obj *value; + PyObject *result; if (PyTuple_Size(args) == 1) { PyObject* o = PyTuple_GetItem(args, 0); @@ -1730,9 +1892,24 @@ if (!PyArg_ParseTuple(args, "s:getint", &s)) return NULL; CHECK_STRING_LENGTH(s); - if (Tcl_GetInt(Tkapp_Interp(self), s, &v) == TCL_ERROR) + value = Tcl_NewStringObj(s, -1); + if (value == NULL) return Tkinter_Error(self); - return Py_BuildValue("i", v); + /* Don't use Tcl_GetInt() because it returns ambiguous result for value + in ranges -2**32..-2**31-1 and 2**31..2**32-1 (on 32-bit platform). + + Prefer bignum because Tcl_GetWideIntFromObj returns ambiguous result for + value in ranges -2**64..-2**63-1 and 2**63..2**64-1 (on 32-bit platform). + */ +#ifdef HAVE_LIBTOMMAMTH + result = fromBignumObj(self, value); +#else + result = fromWideIntObj(self, value); +#endif + Tcl_DecrRefCount(value); + if (result != NULL || PyErr_Occurred()) + return result; + return Tkinter_Error(self); } static PyObject * -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Apr 2 19:08:09 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Thu, 02 Apr 2015 17:08:09 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzE2ODQw?= =?utf-8?q?=3A_Fixed_test=5Ftcl_for_Tcl_=3C_8=2E5=2E?= Message-ID: <20150402170809.16248.38359@psf.io> https://hg.python.org/cpython/rev/9905fb0b5885 changeset: 95395:9905fb0b5885 branch: 2.7 parent: 95392:77e5623e22dd user: Serhiy Storchaka date: Thu Apr 02 20:06:48 2015 +0300 summary: Issue #16840: Fixed test_tcl for Tcl < 8.5. files: Lib/test/test_tcl.py | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Lib/test/test_tcl.py b/Lib/test/test_tcl.py --- a/Lib/test/test_tcl.py +++ b/Lib/test/test_tcl.py @@ -144,6 +144,8 @@ result = tcl.getint(' %d ' % i) self.assertEqual(result, i) self.assertIsInstance(result, type(int(result))) + if tcl_version >= (8, 5): + self.assertEqual(tcl.getint(' {:#o} '.format(i)), i) self.assertEqual(tcl.getint(' %#o ' % i), i) self.assertEqual(tcl.getint(' %#x ' % i), i) if tcl_version < (8, 5): # bignum was added in Tcl 8.5 @@ -438,9 +440,7 @@ self.assertEqual(result, str(i)) self.assertIsInstance(result, str) if tcl_version < (8, 5): # bignum was added in Tcl 8.5 - result = tcl.call('expr', str(2**1000)) - self.assertEqual(result, str(2**1000)) - self.assertIsInstance(result, str) + self.assertRaises(TclError, tcl.call, 'expr', str(2**1000)) def test_passing_values(self): def passValue(value): -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Apr 2 19:08:08 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Thu, 02 Apr 2015 17:08:08 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzIxNTI2?= =?utf-8?q?=3A_Skip_test=5Fbooleans_on_Tcl_=3C_8=2E5=2E?= Message-ID: <20150402170808.27430.20711@psf.io> https://hg.python.org/cpython/rev/77e5623e22dd changeset: 95392:77e5623e22dd branch: 2.7 parent: 95389:42a6449e577c user: Serhiy Storchaka date: Thu Apr 02 19:57:52 2015 +0300 summary: Issue #21526: Skip test_booleans on Tcl < 8.5. files: Lib/test/test_tcl.py | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_tcl.py b/Lib/test/test_tcl.py --- a/Lib/test/test_tcl.py +++ b/Lib/test/test_tcl.py @@ -406,6 +406,7 @@ if tcl_version >= (8, 5): # bignum was added in Tcl 8.5 check('2**64', True) + @unittest.skipUnless(tcl_version >= (8, 5), 'requires Tcl version >= 8.5') def test_booleans(self): tcl = self.interp def check(expr, expected): -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Apr 2 19:08:09 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Thu, 02 Apr 2015 17:08:09 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzE2ODQw?= =?utf-8?q?=3A_Fixed_test=5Ftcl_for_Tcl_=3C_8=2E5=2E?= Message-ID: <20150402170809.16260.69234@psf.io> https://hg.python.org/cpython/rev/1d2444273b3d changeset: 95396:1d2444273b3d branch: 3.4 parent: 95393:3b8039c37b37 user: Serhiy Storchaka date: Thu Apr 02 20:07:09 2015 +0300 summary: Issue #16840: Fixed test_tcl for Tcl < 8.5. files: Lib/test/test_tcl.py | 8 ++++---- 1 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Lib/test/test_tcl.py b/Lib/test/test_tcl.py --- a/Lib/test/test_tcl.py +++ b/Lib/test/test_tcl.py @@ -145,7 +145,9 @@ tcl = self.interp.tk for i in self.get_integers(): self.assertEqual(tcl.getint(' %d ' % i), i) - self.assertEqual(tcl.getint(' %#o ' % i), i) + if tcl_version >= (8, 5): + self.assertEqual(tcl.getint(' %#o ' % i), i) + self.assertEqual(tcl.getint((' %#o ' % i).replace('o', '')), i) self.assertEqual(tcl.getint(' %#x ' % i), i) if tcl_version < (8, 5): # bignum was added in Tcl 8.5 self.assertRaises(TclError, tcl.getint, str(2**1000)) @@ -422,9 +424,7 @@ self.assertEqual(result, str(i)) self.assertIsInstance(result, str) if tcl_version < (8, 5): # bignum was added in Tcl 8.5 - result = tcl.call('expr', str(2**1000)) - self.assertEqual(result, str(2**1000)) - self.assertIsInstance(result, str) + self.assertRaises(TclError, tcl.call, 'expr', str(2**1000)) def test_passing_values(self): def passValue(value): -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Apr 2 19:08:10 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Thu, 02 Apr 2015 17:08:10 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2316840=3A_Fixed_test=5Ftcl_for_Tcl_=3C_8=2E5=2E?= Message-ID: <20150402170809.14233.93184@psf.io> https://hg.python.org/cpython/rev/2398dba039f3 changeset: 95397:2398dba039f3 parent: 95394:8ad98ade3f78 parent: 95396:1d2444273b3d user: Serhiy Storchaka date: Thu Apr 02 20:07:24 2015 +0300 summary: Issue #16840: Fixed test_tcl for Tcl < 8.5. files: Lib/test/test_tcl.py | 8 ++++---- 1 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Lib/test/test_tcl.py b/Lib/test/test_tcl.py --- a/Lib/test/test_tcl.py +++ b/Lib/test/test_tcl.py @@ -143,7 +143,9 @@ tcl = self.interp.tk for i in self.get_integers(): self.assertEqual(tcl.getint(' %d ' % i), i) - self.assertEqual(tcl.getint(' %#o ' % i), i) + if tcl_version >= (8, 5): + self.assertEqual(tcl.getint(' %#o ' % i), i) + self.assertEqual(tcl.getint((' %#o ' % i).replace('o', '')), i) self.assertEqual(tcl.getint(' %#x ' % i), i) if tcl_version < (8, 5): # bignum was added in Tcl 8.5 self.assertRaises(TclError, tcl.getint, str(2**1000)) @@ -420,9 +422,7 @@ self.assertEqual(result, str(i)) self.assertIsInstance(result, str) if tcl_version < (8, 5): # bignum was added in Tcl 8.5 - result = tcl.call('expr', str(2**1000)) - self.assertEqual(result, str(2**1000)) - self.assertIsInstance(result, str) + self.assertRaises(TclError, tcl.call, 'expr', str(2**1000)) def test_passing_values(self): def passValue(value): -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Apr 2 19:08:10 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Thu, 02 Apr 2015 17:08:10 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzIxNTI2?= =?utf-8?q?=3A_Skip_test=5Fbooleans_on_Tcl_=3C_8=2E5=2E?= Message-ID: <20150402170808.14221.50106@psf.io> https://hg.python.org/cpython/rev/3b8039c37b37 changeset: 95393:3b8039c37b37 branch: 3.4 parent: 95390:a6f4d8fa7ab8 user: Serhiy Storchaka date: Thu Apr 02 19:57:52 2015 +0300 summary: Issue #21526: Skip test_booleans on Tcl < 8.5. files: Lib/test/test_tcl.py | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_tcl.py b/Lib/test/test_tcl.py --- a/Lib/test/test_tcl.py +++ b/Lib/test/test_tcl.py @@ -391,6 +391,7 @@ if tcl_version >= (8, 5): # bignum was added in Tcl 8.5 check('2**64', True) + @unittest.skipUnless(tcl_version >= (8, 5), 'requires Tcl version >= 8.5') def test_booleans(self): tcl = self.interp def check(expr, expected): -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Apr 2 19:08:10 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Thu, 02 Apr 2015 17:08:10 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2321526=3A_Skip_test=5Fbooleans_on_Tcl_=3C_8=2E5?= =?utf-8?q?=2E?= Message-ID: <20150402170808.129145.97694@psf.io> https://hg.python.org/cpython/rev/8ad98ade3f78 changeset: 95394:8ad98ade3f78 parent: 95391:9291b28157e1 parent: 95393:3b8039c37b37 user: Serhiy Storchaka date: Thu Apr 02 19:59:34 2015 +0300 summary: Issue #21526: Skip test_booleans on Tcl < 8.5. files: Lib/test/test_tcl.py | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_tcl.py b/Lib/test/test_tcl.py --- a/Lib/test/test_tcl.py +++ b/Lib/test/test_tcl.py @@ -389,6 +389,7 @@ if tcl_version >= (8, 5): # bignum was added in Tcl 8.5 check('2**64', True) + @unittest.skipUnless(tcl_version >= (8, 5), 'requires Tcl version >= 8.5') def test_booleans(self): tcl = self.interp def check(expr, expected): -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Apr 2 20:00:59 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Thu, 02 Apr 2015 18:00:59 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Issue_=232175=3A_Added_tests_for_xml=2Esax=2Esaxutils=2E?= =?utf-8?b?cHJlcGFyZV9pbnB1dF9zb3VyY2UoKS4=?= Message-ID: <20150402180058.16495.98321@psf.io> https://hg.python.org/cpython/rev/e0292b3ba245 changeset: 95400:e0292b3ba245 parent: 95397:2398dba039f3 parent: 95399:fa47897e7889 user: Serhiy Storchaka date: Thu Apr 02 20:57:20 2015 +0300 summary: Issue #2175: Added tests for xml.sax.saxutils.prepare_input_source(). Made test XML files non-ASCII. files: Lib/test/test_minidom.py | 10 ++- Lib/test/test_sax.py | 76 +++++++++++++++++- Lib/test/xmltestdata/test.xml | 4 +- Lib/test/xmltestdata/test.xml.out | 2 +- 4 files changed, 82 insertions(+), 10 deletions(-) diff --git a/Lib/test/test_minidom.py b/Lib/test/test_minidom.py --- a/Lib/test/test_minidom.py +++ b/Lib/test/test_minidom.py @@ -49,8 +49,14 @@ t = node.wholeText self.confirm(t == s, "looking for %r, found %r" % (s, t)) - def testParseFromFile(self): - with open(tstfile) as file: + def testParseFromBinaryFile(self): + with open(tstfile, 'rb') as file: + dom = parse(file) + dom.unlink() + self.confirm(isinstance(dom, Document)) + + def testParseFromTextFile(self): + with open(tstfile, 'r', encoding='iso-8859-1') as file: dom = parse(file) dom.unlink() self.confirm(isinstance(dom, Document)) diff --git a/Lib/test/test_sax.py b/Lib/test/test_sax.py --- a/Lib/test/test_sax.py +++ b/Lib/test/test_sax.py @@ -10,7 +10,7 @@ # don't try to test this module if we cannot create a parser raise unittest.SkipTest("no XML parsers available") from xml.sax.saxutils import XMLGenerator, escape, unescape, quoteattr, \ - XMLFilterBase + XMLFilterBase, prepare_input_source from xml.sax.expatreader import create_parser from xml.sax.handler import feature_namespaces from xml.sax.xmlreader import InputSource, AttributesImpl, AttributesNSImpl @@ -172,6 +172,60 @@ p = make_parser(['xml.parsers.no_such_parser']) +class PrepareInputSourceTest(unittest.TestCase): + + def setUp(self): + self.file = support.TESTFN + with open(self.file, "w") as tmp: + tmp.write("This was read from a file.") + + def tearDown(self): + support.unlink(self.file) + + def make_byte_stream(self): + return BytesIO(b"This is a byte stream.") + + def checkContent(self, stream, content): + self.assertIsNotNone(stream) + self.assertEqual(stream.read(), content) + stream.close() + + + def test_byte_stream(self): + # If the source is an InputSource that does not have a character + # stream but does have a byte stream, use the byte stream. + src = InputSource(self.file) + src.setByteStream(self.make_byte_stream()) + prep = prepare_input_source(src) + self.assertIsNone(prep.getCharacterStream()) + self.checkContent(prep.getByteStream(), + b"This is a byte stream.") + + def test_system_id(self): + # If the source is an InputSource that has neither a character + # stream nor a byte stream, open the system ID. + src = InputSource(self.file) + prep = prepare_input_source(src) + self.assertIsNone(prep.getCharacterStream()) + self.checkContent(prep.getByteStream(), + b"This was read from a file.") + + def test_string(self): + # If the source is a string, use it as a system ID and open it. + prep = prepare_input_source(self.file) + self.assertIsNone(prep.getCharacterStream()) + self.checkContent(prep.getByteStream(), + b"This was read from a file.") + + def test_binary_file(self): + # If the source is a binary file-like object, use it as a byte + # stream. + prep = prepare_input_source(self.make_byte_stream()) + self.assertIsNone(prep.getCharacterStream()) + self.checkContent(prep.getByteStream(), + b"This is a byte stream.") + + # ===== XMLGenerator class XmlgenTest: @@ -622,7 +676,7 @@ # ===== XMLReader support - def test_expat_file(self): + def test_expat_binary_file(self): parser = create_parser() result = BytesIO() xmlgen = XMLGenerator(result) @@ -633,8 +687,19 @@ self.assertEqual(result.getvalue(), xml_test_out) + def test_expat_text_file(self): + parser = create_parser() + result = BytesIO() + xmlgen = XMLGenerator(result) + + parser.setContentHandler(xmlgen) + with open(TEST_XMLFILE, 'rt', encoding='iso-8859-1') as f: + parser.parse(f) + + self.assertEqual(result.getvalue(), xml_test_out) + @requires_nonascii_filenames - def test_expat_file_nonascii(self): + def test_expat_binary_file_nonascii(self): fname = support.TESTFN_UNICODE shutil.copyfile(TEST_XMLFILE, fname) self.addCleanup(support.unlink, fname) @@ -644,7 +709,7 @@ xmlgen = XMLGenerator(result) parser.setContentHandler(xmlgen) - parser.parse(open(fname)) + parser.parse(open(fname, 'rb')) self.assertEqual(result.getvalue(), xml_test_out) @@ -826,7 +891,7 @@ self.assertEqual(result.getvalue(), xml_test_out) - def test_expat_inpsource_stream(self): + def test_expat_inpsource_byte_stream(self): parser = create_parser() result = BytesIO() xmlgen = XMLGenerator(result) @@ -1018,6 +1083,7 @@ def test_main(): run_unittest(MakeParserTest, SaxutilsTest, + PrepareInputSourceTest, StringXmlgenTest, BytesXmlgenTest, WriterXmlgenTest, diff --git a/Lib/test/xmltestdata/test.xml b/Lib/test/xmltestdata/test.xml --- a/Lib/test/xmltestdata/test.xml +++ b/Lib/test/xmltestdata/test.xml @@ -1,4 +1,4 @@ - + Introduction to XSL

Introduction to XSL

@@ -110,6 +110,6 @@ - +? diff --git a/Lib/test/xmltestdata/test.xml.out b/Lib/test/xmltestdata/test.xml.out --- a/Lib/test/xmltestdata/test.xml.out +++ b/Lib/test/xmltestdata/test.xml.out @@ -110,6 +110,6 @@ - +? \ No newline at end of file -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Apr 2 20:00:59 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Thu, 02 Apr 2015 18:00:59 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=232175=3A_SAX_parse?= =?utf-8?q?rs_now_support_a_character_stream_of_InputSource_object=2E?= Message-ID: <20150402180058.27448.12210@psf.io> https://hg.python.org/cpython/rev/407883c52bf3 changeset: 95401:407883c52bf3 user: Serhiy Storchaka date: Thu Apr 02 21:00:13 2015 +0300 summary: Issue #2175: SAX parsers now support a character stream of InputSource object. files: Doc/library/xml.sax.reader.rst | 12 ++++---- Doc/whatsnew/3.5.rst | 7 ++++ Lib/test/test_sax.py | 33 ++++++++++++++++++++++ Lib/xml/sax/expatreader.py | 11 +++++-- Lib/xml/sax/saxutils.py | 7 +++- Lib/xml/sax/xmlreader.py | 4 ++- Misc/NEWS | 2 + 7 files changed, 64 insertions(+), 12 deletions(-) diff --git a/Doc/library/xml.sax.reader.rst b/Doc/library/xml.sax.reader.rst --- a/Doc/library/xml.sax.reader.rst +++ b/Doc/library/xml.sax.reader.rst @@ -100,8 +100,10 @@ system identifier (a string identifying the input source -- typically a file name or an URL), a file-like object, or an :class:`InputSource` object. When :meth:`parse` returns, the input is completely processed, and the parser object - can be discarded or reset. As a limitation, the current implementation only - accepts byte streams; processing of character streams is for further study. + can be discarded or reset. + + .. versionchanged:: 3.5 + Added support of character streams. .. method:: XMLReader.getContentHandler() @@ -288,8 +290,7 @@ .. method:: InputSource.setByteStream(bytefile) - Set the byte stream (a Python file-like object which does not perform - byte-to-character conversion) for this input source. + Set the byte stream (a :term:`binary file`) for this input source. The SAX parser will ignore this if there is also a character stream specified, but it will use a byte stream in preference to opening a URI connection itself. @@ -308,8 +309,7 @@ .. method:: InputSource.setCharacterStream(charfile) - Set the character stream for this input source. (The stream must be a Python 1.6 - Unicode-wrapped file-like that performs conversion to strings.) + Set the character stream (a :term:`text file`) for this input source. If there is a character stream specified, the SAX parser will ignore any byte stream and will not attempt to open a URI connection to the system identifier. diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -499,6 +499,13 @@ * :class:`xmlrpc.client.ServerProxy` is now a :term:`context manager`. (Contributed by Claudiu Popa in :issue:`20627`.) +xml.sax +------- + +* SAX parsers now support a character stream of + :class:`~xml.sax.xmlreader.InputSource` object. + (Contributed by Serhiy Storchaka in :issue:`2175`.) + faulthandler ------------ diff --git a/Lib/test/test_sax.py b/Lib/test/test_sax.py --- a/Lib/test/test_sax.py +++ b/Lib/test/test_sax.py @@ -185,12 +185,24 @@ def make_byte_stream(self): return BytesIO(b"This is a byte stream.") + def make_character_stream(self): + return StringIO("This is a character stream.") + def checkContent(self, stream, content): self.assertIsNotNone(stream) self.assertEqual(stream.read(), content) stream.close() + def test_character_stream(self): + # If the source is an InputSource with a character stream, use it. + src = InputSource(self.file) + src.setCharacterStream(self.make_character_stream()) + prep = prepare_input_source(src) + self.assertIsNone(prep.getByteStream()) + self.checkContent(prep.getCharacterStream(), + "This is a character stream.") + def test_byte_stream(self): # If the source is an InputSource that does not have a character # stream but does have a byte stream, use the byte stream. @@ -225,6 +237,14 @@ self.checkContent(prep.getByteStream(), b"This is a byte stream.") + def test_text_file(self): + # If the source is a text file-like object, use it as a character + # stream. + prep = prepare_input_source(self.make_character_stream()) + self.assertIsNone(prep.getByteStream()) + self.checkContent(prep.getCharacterStream(), + "This is a character stream.") + # ===== XMLGenerator @@ -904,6 +924,19 @@ self.assertEqual(result.getvalue(), xml_test_out) + def test_expat_inpsource_character_stream(self): + parser = create_parser() + result = BytesIO() + xmlgen = XMLGenerator(result) + + parser.setContentHandler(xmlgen) + inpsrc = InputSource() + with open(TEST_XMLFILE, 'rt', encoding='iso-8859-1') as f: + inpsrc.setCharacterStream(f) + parser.parse(inpsrc) + + self.assertEqual(result.getvalue(), xml_test_out) + # ===== IncrementalParser support def test_expat_incremental(self): diff --git a/Lib/xml/sax/expatreader.py b/Lib/xml/sax/expatreader.py --- a/Lib/xml/sax/expatreader.py +++ b/Lib/xml/sax/expatreader.py @@ -219,9 +219,14 @@ self._parsing = 0 # break cycle created by expat handlers pointing to our methods self._parser = None - bs = self._source.getByteStream() - if bs is not None: - bs.close() + try: + file = self._source.getCharacterStream() + if file is not None: + file.close() + finally: + file = self._source.getByteStream() + if file is not None: + file.close() def _reset_cont_handler(self): self._parser.ProcessingInstructionHandler = \ diff --git a/Lib/xml/sax/saxutils.py b/Lib/xml/sax/saxutils.py --- a/Lib/xml/sax/saxutils.py +++ b/Lib/xml/sax/saxutils.py @@ -345,11 +345,14 @@ elif hasattr(source, "read"): f = source source = xmlreader.InputSource() - source.setByteStream(f) + if isinstance(f.read(0), str): + source.setCharacterStream(f) + else: + source.setByteStream(f) if hasattr(f, "name") and isinstance(f.name, str): source.setSystemId(f.name) - if source.getByteStream() is None: + if source.getCharacterStream() is None and source.getByteStream() is None: sysid = source.getSystemId() basehead = os.path.dirname(os.path.normpath(base)) sysidfilename = os.path.join(basehead, sysid) diff --git a/Lib/xml/sax/xmlreader.py b/Lib/xml/sax/xmlreader.py --- a/Lib/xml/sax/xmlreader.py +++ b/Lib/xml/sax/xmlreader.py @@ -117,7 +117,9 @@ source = saxutils.prepare_input_source(source) self.prepareParser(source) - file = source.getByteStream() + file = source.getCharacterStream() + if file is None: + file = source.getByteStream() buffer = file.read(self._bufsize) while buffer: self.feed(buffer) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -16,6 +16,8 @@ Library ------- +- Issue #2175: SAX parsers now support a character stream of InputSource object. + - Issue #16840: Tkinter now supports 64-bit integers added in Tcl 8.4 and arbitrary precision integers added in Tcl 8.5. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Apr 2 20:00:59 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Thu, 02 Apr 2015 18:00:59 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzIxNzU6?= =?utf-8?q?_Added_tests_for_xml=2Esax=2Esaxutils=2Eprepare=5Finput=5Fsourc?= =?utf-8?b?ZSgpLg==?= Message-ID: <20150402180058.16248.3102@psf.io> https://hg.python.org/cpython/rev/fa47897e7889 changeset: 95399:fa47897e7889 branch: 3.4 parent: 95396:1d2444273b3d user: Serhiy Storchaka date: Thu Apr 02 20:55:59 2015 +0300 summary: Issue #2175: Added tests for xml.sax.saxutils.prepare_input_source(). Made test XML files non-ASCII. files: Lib/test/test_minidom.py | 10 ++- Lib/test/test_sax.py | 76 +++++++++++++++++- Lib/test/xmltestdata/test.xml | 4 +- Lib/test/xmltestdata/test.xml.out | 2 +- 4 files changed, 82 insertions(+), 10 deletions(-) diff --git a/Lib/test/test_minidom.py b/Lib/test/test_minidom.py --- a/Lib/test/test_minidom.py +++ b/Lib/test/test_minidom.py @@ -49,8 +49,14 @@ t = node.wholeText self.confirm(t == s, "looking for %r, found %r" % (s, t)) - def testParseFromFile(self): - with open(tstfile) as file: + def testParseFromBinaryFile(self): + with open(tstfile, 'rb') as file: + dom = parse(file) + dom.unlink() + self.confirm(isinstance(dom, Document)) + + def testParseFromTextFile(self): + with open(tstfile, 'r', encoding='iso-8859-1') as file: dom = parse(file) dom.unlink() self.confirm(isinstance(dom, Document)) diff --git a/Lib/test/test_sax.py b/Lib/test/test_sax.py --- a/Lib/test/test_sax.py +++ b/Lib/test/test_sax.py @@ -10,7 +10,7 @@ # don't try to test this module if we cannot create a parser raise unittest.SkipTest("no XML parsers available") from xml.sax.saxutils import XMLGenerator, escape, unescape, quoteattr, \ - XMLFilterBase + XMLFilterBase, prepare_input_source from xml.sax.expatreader import create_parser from xml.sax.handler import feature_namespaces from xml.sax.xmlreader import InputSource, AttributesImpl, AttributesNSImpl @@ -172,6 +172,60 @@ p = make_parser(['xml.parsers.no_such_parser']) +class PrepareInputSourceTest(unittest.TestCase): + + def setUp(self): + self.file = support.TESTFN + with open(self.file, "w") as tmp: + tmp.write("This was read from a file.") + + def tearDown(self): + support.unlink(self.file) + + def make_byte_stream(self): + return BytesIO(b"This is a byte stream.") + + def checkContent(self, stream, content): + self.assertIsNotNone(stream) + self.assertEqual(stream.read(), content) + stream.close() + + + def test_byte_stream(self): + # If the source is an InputSource that does not have a character + # stream but does have a byte stream, use the byte stream. + src = InputSource(self.file) + src.setByteStream(self.make_byte_stream()) + prep = prepare_input_source(src) + self.assertIsNone(prep.getCharacterStream()) + self.checkContent(prep.getByteStream(), + b"This is a byte stream.") + + def test_system_id(self): + # If the source is an InputSource that has neither a character + # stream nor a byte stream, open the system ID. + src = InputSource(self.file) + prep = prepare_input_source(src) + self.assertIsNone(prep.getCharacterStream()) + self.checkContent(prep.getByteStream(), + b"This was read from a file.") + + def test_string(self): + # If the source is a string, use it as a system ID and open it. + prep = prepare_input_source(self.file) + self.assertIsNone(prep.getCharacterStream()) + self.checkContent(prep.getByteStream(), + b"This was read from a file.") + + def test_binary_file(self): + # If the source is a binary file-like object, use it as a byte + # stream. + prep = prepare_input_source(self.make_byte_stream()) + self.assertIsNone(prep.getCharacterStream()) + self.checkContent(prep.getByteStream(), + b"This is a byte stream.") + + # ===== XMLGenerator class XmlgenTest: @@ -622,7 +676,7 @@ # ===== XMLReader support - def test_expat_file(self): + def test_expat_binary_file(self): parser = create_parser() result = BytesIO() xmlgen = XMLGenerator(result) @@ -633,8 +687,19 @@ self.assertEqual(result.getvalue(), xml_test_out) + def test_expat_text_file(self): + parser = create_parser() + result = BytesIO() + xmlgen = XMLGenerator(result) + + parser.setContentHandler(xmlgen) + with open(TEST_XMLFILE, 'rt', encoding='iso-8859-1') as f: + parser.parse(f) + + self.assertEqual(result.getvalue(), xml_test_out) + @requires_nonascii_filenames - def test_expat_file_nonascii(self): + def test_expat_binary_file_nonascii(self): fname = support.TESTFN_UNICODE shutil.copyfile(TEST_XMLFILE, fname) self.addCleanup(support.unlink, fname) @@ -644,7 +709,7 @@ xmlgen = XMLGenerator(result) parser.setContentHandler(xmlgen) - parser.parse(open(fname)) + parser.parse(open(fname, 'rb')) self.assertEqual(result.getvalue(), xml_test_out) @@ -826,7 +891,7 @@ self.assertEqual(result.getvalue(), xml_test_out) - def test_expat_inpsource_stream(self): + def test_expat_inpsource_byte_stream(self): parser = create_parser() result = BytesIO() xmlgen = XMLGenerator(result) @@ -1018,6 +1083,7 @@ def test_main(): run_unittest(MakeParserTest, SaxutilsTest, + PrepareInputSourceTest, StringXmlgenTest, BytesXmlgenTest, WriterXmlgenTest, diff --git a/Lib/test/xmltestdata/test.xml b/Lib/test/xmltestdata/test.xml --- a/Lib/test/xmltestdata/test.xml +++ b/Lib/test/xmltestdata/test.xml @@ -1,4 +1,4 @@ - + Introduction to XSL

Introduction to XSL

@@ -110,6 +110,6 @@ - +? diff --git a/Lib/test/xmltestdata/test.xml.out b/Lib/test/xmltestdata/test.xml.out --- a/Lib/test/xmltestdata/test.xml.out +++ b/Lib/test/xmltestdata/test.xml.out @@ -110,6 +110,6 @@ - +? \ No newline at end of file -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Apr 2 20:01:01 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Thu, 02 Apr 2015 18:01:01 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzIxNzU6?= =?utf-8?q?_Added_tests_for_xml=2Esax=2Esaxutils=2Eprepare=5Finput=5Fsourc?= =?utf-8?b?ZSgpLg==?= Message-ID: <20150402180058.59578.89664@psf.io> https://hg.python.org/cpython/rev/84d49ad9109b changeset: 95398:84d49ad9109b branch: 2.7 parent: 95395:9905fb0b5885 user: Serhiy Storchaka date: Thu Apr 02 20:55:46 2015 +0300 summary: Issue #2175: Added tests for xml.sax.saxutils.prepare_input_source(). Made test XML files non-ASCII. files: Lib/test/test_sax.py | 61 ++++++++++++++++++- Lib/test/xmltestdata/test.xml | 4 +- Lib/test/xmltestdata/test.xml.out | 2 +- 3 files changed, 61 insertions(+), 6 deletions(-) diff --git a/Lib/test/test_sax.py b/Lib/test/test_sax.py --- a/Lib/test/test_sax.py +++ b/Lib/test/test_sax.py @@ -9,7 +9,7 @@ # don't try to test this module if we cannot create a parser raise ImportError("no XML parsers available") from xml.sax.saxutils import XMLGenerator, escape, unescape, quoteattr, \ - XMLFilterBase + XMLFilterBase, prepare_input_source from xml.sax.expatreader import create_parser from xml.sax.handler import feature_namespaces from xml.sax.xmlreader import InputSource, AttributesImpl, AttributesNSImpl @@ -167,6 +167,60 @@ p = make_parser(['xml.parsers.no_such_parser']) +class PrepareInputSourceTest(unittest.TestCase): + + def setUp(self): + self.file = support.TESTFN + with open(self.file, "w") as tmp: + tmp.write("This was read from a file.") + + def tearDown(self): + support.unlink(self.file) + + def make_byte_stream(self): + return io.BytesIO(b"This is a byte stream.") + + def checkContent(self, stream, content): + self.assertIsNotNone(stream) + self.assertEqual(stream.read(), content) + stream.close() + + + def test_byte_stream(self): + # If the source is an InputSource that does not have a character + # stream but does have a byte stream, use the byte stream. + src = InputSource(self.file) + src.setByteStream(self.make_byte_stream()) + prep = prepare_input_source(src) + self.assertIsNone(prep.getCharacterStream()) + self.checkContent(prep.getByteStream(), + b"This is a byte stream.") + + def test_system_id(self): + # If the source is an InputSource that has neither a character + # stream nor a byte stream, open the system ID. + src = InputSource(self.file) + prep = prepare_input_source(src) + self.assertIsNone(prep.getCharacterStream()) + self.checkContent(prep.getByteStream(), + b"This was read from a file.") + + def test_string(self): + # If the source is a string, use it as a system ID and open it. + prep = prepare_input_source(self.file) + self.assertIsNone(prep.getCharacterStream()) + self.checkContent(prep.getByteStream(), + b"This was read from a file.") + + def test_binary_file(self): + # If the source is a binary file-like object, use it as a byte + # stream. + prep = prepare_input_source(self.make_byte_stream()) + self.assertIsNone(prep.getCharacterStream()) + self.checkContent(prep.getByteStream(), + b"This is a byte stream.") + + # ===== XMLGenerator start = '\n' @@ -481,7 +535,7 @@ # ===== XMLReader support - def test_expat_file(self): + def test_expat_binary_file(self): parser = create_parser() result = StringIO() xmlgen = XMLGenerator(result) @@ -660,7 +714,7 @@ self.assertEqual(result.getvalue(), xml_test_out) - def test_expat_inpsource_stream(self): + def test_expat_inpsource_byte_stream(self): parser = create_parser() result = StringIO() xmlgen = XMLGenerator(result) @@ -896,6 +950,7 @@ def test_main(): run_unittest(MakeParserTest, SaxutilsTest, + PrepareInputSourceTest, StringXmlgenTest, BytesIOXmlgenTest, WriterXmlgenTest, diff --git a/Lib/test/xmltestdata/test.xml b/Lib/test/xmltestdata/test.xml --- a/Lib/test/xmltestdata/test.xml +++ b/Lib/test/xmltestdata/test.xml @@ -1,4 +1,4 @@ - + Introduction to XSL

Introduction to XSL

@@ -110,6 +110,6 @@ - +? diff --git a/Lib/test/xmltestdata/test.xml.out b/Lib/test/xmltestdata/test.xml.out --- a/Lib/test/xmltestdata/test.xml.out +++ b/Lib/test/xmltestdata/test.xml.out @@ -110,6 +110,6 @@ - +? \ No newline at end of file -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Apr 2 22:22:08 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Thu, 02 Apr 2015 20:22:08 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzEwNTkw?= =?utf-8?q?=3A_Added_tests_for_xml=2Esax=2Eparse=28=29_and_xml=2Esax=2Epar?= =?utf-8?b?c2VTdHJpbmcoKS4=?= Message-ID: <20150402202208.27446.42823@psf.io> https://hg.python.org/cpython/rev/ca8666310eb3 changeset: 95403:ca8666310eb3 branch: 3.4 parent: 95399:fa47897e7889 user: Serhiy Storchaka date: Thu Apr 02 23:05:57 2015 +0300 summary: Issue #10590: Added tests for xml.sax.parse() and xml.sax.parseString(). files: Lib/test/test_sax.py | 124 ++++++++++++++++++++++++++++++- 1 files changed, 123 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_sax.py b/Lib/test/test_sax.py --- a/Lib/test/test_sax.py +++ b/Lib/test/test_sax.py @@ -16,10 +16,11 @@ from xml.sax.xmlreader import InputSource, AttributesImpl, AttributesNSImpl from io import BytesIO, StringIO import codecs +import gc import os.path import shutil from test import support -from test.support import findfile, run_unittest +from test.support import findfile, run_unittest, TESTFN TEST_XMLFILE = findfile("test.xml", subdir="xmltestdata") TEST_XMLFILE_OUT = findfile("test.xml.out", subdir="xmltestdata") @@ -95,6 +96,126 @@ self.assertEqual(attrs["attr"], "val") self.assertEqual(attrs.getQNameByName("attr"), "attr") + +def xml_str(doc, encoding=None): + if encoding is None: + return doc + return '\n%s' % (encoding, doc) + +def xml_bytes(doc, encoding, decl_encoding=...): + if decl_encoding is ...: + decl_encoding = encoding + return xml_str(doc, decl_encoding).encode(encoding, 'xmlcharrefreplace') + +def make_xml_file(doc, encoding, decl_encoding=...): + if decl_encoding is ...: + decl_encoding = encoding + with open(TESTFN, 'w', encoding=encoding, errors='xmlcharrefreplace') as f: + f.write(xml_str(doc, decl_encoding)) + + +class ParseTest(unittest.TestCase): + data = '$\xa3\u20ac\U0001017b' + + def tearDown(self): + support.unlink(TESTFN) + + def check_parse(self, f): + from xml.sax import parse + result = StringIO() + parse(f, XMLGenerator(result, 'utf-8')) + self.assertEqual(result.getvalue(), xml_str(self.data, 'utf-8')) + + def test_parse_text(self): + encodings = ('us-ascii', 'iso-8859-1', 'utf-8', + 'utf-16', 'utf-16le', 'utf-16be') + for encoding in encodings: + self.check_parse(StringIO(xml_str(self.data, encoding))) + make_xml_file(self.data, encoding) + with open(TESTFN, 'r', encoding=encoding) as f: + self.check_parse(f) + self.check_parse(StringIO(self.data)) + make_xml_file(self.data, encoding, None) + with open(TESTFN, 'r', encoding=encoding) as f: + self.check_parse(f) + + def test_parse_bytes(self): + # UTF-8 is default encoding, US-ASCII is compatible with UTF-8, + # UTF-16 is autodetected + encodings = ('us-ascii', 'utf-8', 'utf-16', 'utf-16le', 'utf-16be') + for encoding in encodings: + self.check_parse(BytesIO(xml_bytes(self.data, encoding))) + make_xml_file(self.data, encoding) + self.check_parse(TESTFN) + with open(TESTFN, 'rb') as f: + self.check_parse(f) + self.check_parse(BytesIO(xml_bytes(self.data, encoding, None))) + make_xml_file(self.data, encoding, None) + self.check_parse(TESTFN) + with open(TESTFN, 'rb') as f: + self.check_parse(f) + # accept UTF-8 with BOM + self.check_parse(BytesIO(xml_bytes(self.data, 'utf-8-sig', 'utf-8'))) + make_xml_file(self.data, 'utf-8-sig', 'utf-8') + self.check_parse(TESTFN) + with open(TESTFN, 'rb') as f: + self.check_parse(f) + self.check_parse(BytesIO(xml_bytes(self.data, 'utf-8-sig', None))) + make_xml_file(self.data, 'utf-8-sig', None) + self.check_parse(TESTFN) + with open(TESTFN, 'rb') as f: + self.check_parse(f) + # accept data with declared encoding + self.check_parse(BytesIO(xml_bytes(self.data, 'iso-8859-1'))) + make_xml_file(self.data, 'iso-8859-1') + self.check_parse(TESTFN) + with open(TESTFN, 'rb') as f: + self.check_parse(f) + # fail on non-UTF-8 incompatible data without declared encoding + with self.assertRaises(SAXException): + self.check_parse(BytesIO(xml_bytes(self.data, 'iso-8859-1', None))) + make_xml_file(self.data, 'iso-8859-1', None) + with support.check_warnings(('unclosed file', ResourceWarning)): + # XXX Failed parser leaks an opened file. + with self.assertRaises(SAXException): + self.check_parse(TESTFN) + # Collect leaked file. + gc.collect() + with open(TESTFN, 'rb') as f: + with self.assertRaises(SAXException): + self.check_parse(f) + + def test_parse_InputSource(self): + # accept data without declared but with explicitly specified encoding + make_xml_file(self.data, 'iso-8859-1', None) + with open(TESTFN, 'rb') as f: + input = InputSource() + input.setByteStream(f) + input.setEncoding('iso-8859-1') + self.check_parse(input) + + def check_parseString(self, s): + from xml.sax import parseString + result = StringIO() + parseString(s, XMLGenerator(result, 'utf-8')) + self.assertEqual(result.getvalue(), xml_str(self.data, 'utf-8')) + + def test_parseString_bytes(self): + # UTF-8 is default encoding, US-ASCII is compatible with UTF-8, + # UTF-16 is autodetected + encodings = ('us-ascii', 'utf-8', 'utf-16', 'utf-16le', 'utf-16be') + for encoding in encodings: + self.check_parseString(xml_bytes(self.data, encoding)) + self.check_parseString(xml_bytes(self.data, encoding, None)) + # accept UTF-8 with BOM + self.check_parseString(xml_bytes(self.data, 'utf-8-sig', 'utf-8')) + self.check_parseString(xml_bytes(self.data, 'utf-8-sig', None)) + # accept data with declared encoding + self.check_parseString(xml_bytes(self.data, 'iso-8859-1')) + # fail on non-UTF-8 incompatible data without declared encoding + with self.assertRaises(SAXException): + self.check_parseString(xml_bytes(self.data, 'iso-8859-1', None)) + class MakeParserTest(unittest.TestCase): def test_make_parser2(self): # Creating parsers several times in a row should succeed. @@ -1082,6 +1203,7 @@ def test_main(): run_unittest(MakeParserTest, + ParseTest, SaxutilsTest, PrepareInputSourceTest, StringXmlgenTest, -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Apr 2 22:22:08 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Thu, 02 Apr 2015 20:22:08 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2310590=3A_Added_tests_for_xml=2Esax=2Eparse=28?= =?utf-8?q?=29_and_xml=2Esax=2EparseString=28=29=2E?= Message-ID: <20150402202208.29529.55205@psf.io> https://hg.python.org/cpython/rev/846c165cf643 changeset: 95404:846c165cf643 parent: 95401:407883c52bf3 parent: 95403:ca8666310eb3 user: Serhiy Storchaka date: Thu Apr 02 23:07:19 2015 +0300 summary: Issue #10590: Added tests for xml.sax.parse() and xml.sax.parseString(). files: Lib/test/test_sax.py | 124 ++++++++++++++++++++++++++++++- 1 files changed, 123 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_sax.py b/Lib/test/test_sax.py --- a/Lib/test/test_sax.py +++ b/Lib/test/test_sax.py @@ -16,10 +16,11 @@ from xml.sax.xmlreader import InputSource, AttributesImpl, AttributesNSImpl from io import BytesIO, StringIO import codecs +import gc import os.path import shutil from test import support -from test.support import findfile, run_unittest +from test.support import findfile, run_unittest, TESTFN TEST_XMLFILE = findfile("test.xml", subdir="xmltestdata") TEST_XMLFILE_OUT = findfile("test.xml.out", subdir="xmltestdata") @@ -95,6 +96,126 @@ self.assertEqual(attrs["attr"], "val") self.assertEqual(attrs.getQNameByName("attr"), "attr") + +def xml_str(doc, encoding=None): + if encoding is None: + return doc + return '\n%s' % (encoding, doc) + +def xml_bytes(doc, encoding, decl_encoding=...): + if decl_encoding is ...: + decl_encoding = encoding + return xml_str(doc, decl_encoding).encode(encoding, 'xmlcharrefreplace') + +def make_xml_file(doc, encoding, decl_encoding=...): + if decl_encoding is ...: + decl_encoding = encoding + with open(TESTFN, 'w', encoding=encoding, errors='xmlcharrefreplace') as f: + f.write(xml_str(doc, decl_encoding)) + + +class ParseTest(unittest.TestCase): + data = '$\xa3\u20ac\U0001017b' + + def tearDown(self): + support.unlink(TESTFN) + + def check_parse(self, f): + from xml.sax import parse + result = StringIO() + parse(f, XMLGenerator(result, 'utf-8')) + self.assertEqual(result.getvalue(), xml_str(self.data, 'utf-8')) + + def test_parse_text(self): + encodings = ('us-ascii', 'iso-8859-1', 'utf-8', + 'utf-16', 'utf-16le', 'utf-16be') + for encoding in encodings: + self.check_parse(StringIO(xml_str(self.data, encoding))) + make_xml_file(self.data, encoding) + with open(TESTFN, 'r', encoding=encoding) as f: + self.check_parse(f) + self.check_parse(StringIO(self.data)) + make_xml_file(self.data, encoding, None) + with open(TESTFN, 'r', encoding=encoding) as f: + self.check_parse(f) + + def test_parse_bytes(self): + # UTF-8 is default encoding, US-ASCII is compatible with UTF-8, + # UTF-16 is autodetected + encodings = ('us-ascii', 'utf-8', 'utf-16', 'utf-16le', 'utf-16be') + for encoding in encodings: + self.check_parse(BytesIO(xml_bytes(self.data, encoding))) + make_xml_file(self.data, encoding) + self.check_parse(TESTFN) + with open(TESTFN, 'rb') as f: + self.check_parse(f) + self.check_parse(BytesIO(xml_bytes(self.data, encoding, None))) + make_xml_file(self.data, encoding, None) + self.check_parse(TESTFN) + with open(TESTFN, 'rb') as f: + self.check_parse(f) + # accept UTF-8 with BOM + self.check_parse(BytesIO(xml_bytes(self.data, 'utf-8-sig', 'utf-8'))) + make_xml_file(self.data, 'utf-8-sig', 'utf-8') + self.check_parse(TESTFN) + with open(TESTFN, 'rb') as f: + self.check_parse(f) + self.check_parse(BytesIO(xml_bytes(self.data, 'utf-8-sig', None))) + make_xml_file(self.data, 'utf-8-sig', None) + self.check_parse(TESTFN) + with open(TESTFN, 'rb') as f: + self.check_parse(f) + # accept data with declared encoding + self.check_parse(BytesIO(xml_bytes(self.data, 'iso-8859-1'))) + make_xml_file(self.data, 'iso-8859-1') + self.check_parse(TESTFN) + with open(TESTFN, 'rb') as f: + self.check_parse(f) + # fail on non-UTF-8 incompatible data without declared encoding + with self.assertRaises(SAXException): + self.check_parse(BytesIO(xml_bytes(self.data, 'iso-8859-1', None))) + make_xml_file(self.data, 'iso-8859-1', None) + with support.check_warnings(('unclosed file', ResourceWarning)): + # XXX Failed parser leaks an opened file. + with self.assertRaises(SAXException): + self.check_parse(TESTFN) + # Collect leaked file. + gc.collect() + with open(TESTFN, 'rb') as f: + with self.assertRaises(SAXException): + self.check_parse(f) + + def test_parse_InputSource(self): + # accept data without declared but with explicitly specified encoding + make_xml_file(self.data, 'iso-8859-1', None) + with open(TESTFN, 'rb') as f: + input = InputSource() + input.setByteStream(f) + input.setEncoding('iso-8859-1') + self.check_parse(input) + + def check_parseString(self, s): + from xml.sax import parseString + result = StringIO() + parseString(s, XMLGenerator(result, 'utf-8')) + self.assertEqual(result.getvalue(), xml_str(self.data, 'utf-8')) + + def test_parseString_bytes(self): + # UTF-8 is default encoding, US-ASCII is compatible with UTF-8, + # UTF-16 is autodetected + encodings = ('us-ascii', 'utf-8', 'utf-16', 'utf-16le', 'utf-16be') + for encoding in encodings: + self.check_parseString(xml_bytes(self.data, encoding)) + self.check_parseString(xml_bytes(self.data, encoding, None)) + # accept UTF-8 with BOM + self.check_parseString(xml_bytes(self.data, 'utf-8-sig', 'utf-8')) + self.check_parseString(xml_bytes(self.data, 'utf-8-sig', None)) + # accept data with declared encoding + self.check_parseString(xml_bytes(self.data, 'iso-8859-1')) + # fail on non-UTF-8 incompatible data without declared encoding + with self.assertRaises(SAXException): + self.check_parseString(xml_bytes(self.data, 'iso-8859-1', None)) + class MakeParserTest(unittest.TestCase): def test_make_parser2(self): # Creating parsers several times in a row should succeed. @@ -1115,6 +1236,7 @@ def test_main(): run_unittest(MakeParserTest, + ParseTest, SaxutilsTest, PrepareInputSourceTest, StringXmlgenTest, -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Apr 2 22:22:08 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Thu, 02 Apr 2015 20:22:08 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzEwNTkw?= =?utf-8?q?=3A_Added_tests_for_xml=2Esax=2Eparse=28=29_and_xml=2Esax=2Epar?= =?utf-8?b?c2VTdHJpbmcoKS4=?= Message-ID: <20150402202208.16501.72246@psf.io> https://hg.python.org/cpython/rev/3ac1b21fbb42 changeset: 95402:3ac1b21fbb42 branch: 2.7 parent: 95398:84d49ad9109b user: Serhiy Storchaka date: Thu Apr 02 23:05:23 2015 +0300 summary: Issue #10590: Added tests for xml.sax.parse() and xml.sax.parseString(). files: Lib/test/test_sax.py | 109 ++++++++++++++++++++++++++++++- 1 files changed, 108 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_sax.py b/Lib/test/test_sax.py --- a/Lib/test/test_sax.py +++ b/Lib/test/test_sax.py @@ -15,10 +15,11 @@ from xml.sax.xmlreader import InputSource, AttributesImpl, AttributesNSImpl from cStringIO import StringIO import io +import gc import os.path import shutil import test.test_support as support -from test.test_support import findfile, run_unittest +from test.test_support import findfile, run_unittest, TESTFN import unittest TEST_XMLFILE = findfile("test.xml", subdir="xmltestdata") @@ -90,6 +91,111 @@ self.assertEqual(attrs["attr"], "val") self.assertEqual(attrs.getQNameByName("attr"), "attr") + +def xml_unicode(doc, encoding=None): + if encoding is None: + return doc + return u'\n%s' % (encoding, doc) + +def xml_bytes(doc, encoding, decl_encoding=Ellipsis): + if decl_encoding is Ellipsis: + decl_encoding = encoding + return xml_unicode(doc, decl_encoding).encode(encoding, 'xmlcharrefreplace') + +def make_xml_file(doc, encoding, decl_encoding=Ellipsis): + if decl_encoding is Ellipsis: + decl_encoding = encoding + with io.open(TESTFN, 'w', encoding=encoding, errors='xmlcharrefreplace') as f: + f.write(xml_unicode(doc, decl_encoding)) + + +class ParseTest(unittest.TestCase): + data = support.u(r'' + r'$\xa3\u20ac\U0001017b') + + def tearDown(self): + support.unlink(TESTFN) + + def check_parse(self, f): + from xml.sax import parse + result = StringIO() + parse(f, XMLGenerator(result, 'utf-8')) + self.assertEqual(result.getvalue(), xml_bytes(self.data, 'utf-8')) + + def test_parse_bytes(self): + # UTF-8 is default encoding, US-ASCII is compatible with UTF-8, + # UTF-16 is autodetected + encodings = ('us-ascii', 'utf-8', 'utf-16', 'utf-16le', 'utf-16be') + for encoding in encodings: + self.check_parse(io.BytesIO(xml_bytes(self.data, encoding))) + make_xml_file(self.data, encoding) + self.check_parse(TESTFN) + with io.open(TESTFN, 'rb') as f: + self.check_parse(f) + self.check_parse(io.BytesIO(xml_bytes(self.data, encoding, None))) + make_xml_file(self.data, encoding, None) + self.check_parse(TESTFN) + with io.open(TESTFN, 'rb') as f: + self.check_parse(f) + # accept UTF-8 with BOM + self.check_parse(io.BytesIO(xml_bytes(self.data, 'utf-8-sig', 'utf-8'))) + make_xml_file(self.data, 'utf-8-sig', 'utf-8') + self.check_parse(TESTFN) + with io.open(TESTFN, 'rb') as f: + self.check_parse(f) + self.check_parse(io.BytesIO(xml_bytes(self.data, 'utf-8-sig', None))) + make_xml_file(self.data, 'utf-8-sig', None) + self.check_parse(TESTFN) + with io.open(TESTFN, 'rb') as f: + self.check_parse(f) + # accept data with declared encoding + self.check_parse(io.BytesIO(xml_bytes(self.data, 'iso-8859-1'))) + make_xml_file(self.data, 'iso-8859-1') + self.check_parse(TESTFN) + with io.open(TESTFN, 'rb') as f: + self.check_parse(f) + # fail on non-UTF-8 incompatible data without declared encoding + with self.assertRaises(SAXException): + self.check_parse(io.BytesIO(xml_bytes(self.data, 'iso-8859-1', None))) + make_xml_file(self.data, 'iso-8859-1', None) + with self.assertRaises(SAXException): + self.check_parse(TESTFN) + with io.open(TESTFN, 'rb') as f: + with self.assertRaises(SAXException): + self.check_parse(f) + + def test_parse_InputSource(self): + # accept data without declared but with explicitly specified encoding + make_xml_file(self.data, 'iso-8859-1', None) + with io.open(TESTFN, 'rb') as f: + input = InputSource() + input.setByteStream(f) + input.setEncoding('iso-8859-1') + self.check_parse(input) + + def check_parseString(self, s): + from xml.sax import parseString + result = StringIO() + parseString(s, XMLGenerator(result, 'utf-8')) + self.assertEqual(result.getvalue(), xml_bytes(self.data, 'utf-8')) + + def test_parseString_bytes(self): + # UTF-8 is default encoding, US-ASCII is compatible with UTF-8, + # UTF-16 is autodetected + encodings = ('us-ascii', 'utf-8', 'utf-16', 'utf-16le', 'utf-16be') + for encoding in encodings: + self.check_parseString(xml_bytes(self.data, encoding)) + self.check_parseString(xml_bytes(self.data, encoding, None)) + # accept UTF-8 with BOM + self.check_parseString(xml_bytes(self.data, 'utf-8-sig', 'utf-8')) + self.check_parseString(xml_bytes(self.data, 'utf-8-sig', None)) + # accept data with declared encoding + self.check_parseString(xml_bytes(self.data, 'iso-8859-1')) + # fail on non-UTF-8 incompatible data without declared encoding + with self.assertRaises(SAXException): + self.check_parseString(xml_bytes(self.data, 'iso-8859-1', None)) + + class MakeParserTest(unittest.TestCase): def test_make_parser2(self): # Creating parsers several times in a row should succeed. @@ -949,6 +1055,7 @@ def test_main(): run_unittest(MakeParserTest, + ParseTest, SaxutilsTest, PrepareInputSourceTest, StringXmlgenTest, -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Apr 3 03:36:46 2015 From: python-checkins at python.org (benjamin.peterson) Date: Fri, 03 Apr 2015 01:36:46 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_use_rc_rather_?= =?utf-8?q?than_beta?= Message-ID: <20150403013646.75244.60571@psf.io> https://hg.python.org/cpython/rev/7f9597b44740 changeset: 95405:7f9597b44740 branch: 2.7 parent: 95402:3ac1b21fbb42 user: Benjamin Peterson date: Thu Apr 02 21:36:42 2015 -0400 summary: use rc rather than beta files: Include/patchlevel.h | 4 ++-- 1 files changed, 2 insertions(+), 2 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 10 -#define PY_RELEASE_LEVEL PY_RELEASE_LEVEL_BETA +#define PY_RELEASE_LEVEL PY_RELEASE_LEVEL_GAMMA #define PY_RELEASE_SERIAL 0 /* Version as a string */ -#define PY_VERSION "2.7.10b0" +#define PY_VERSION "2.7.10rc0" /*--end constants--*/ /* Subversion Revision number of this file (not of the repository). Empty -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Apr 3 06:54:26 2015 From: python-checkins at python.org (nick.coghlan) Date: Fri, 03 Apr 2015 04:54:26 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_PEP_474=3A_Document_why_*I*_c?= =?utf-8?q?are_about_this_PEP?= Message-ID: <20150403045426.75258.91638@psf.io> https://hg.python.org/peps/rev/8adee3dfda69 changeset: 5748:8adee3dfda69 user: Nick Coghlan date: Fri Apr 03 14:54:15 2015 +1000 summary: PEP 474: Document why *I* care about this PEP files: pep-0474.txt | 77 +++++++++++++++++++++++++++++++++------ 1 files changed, 65 insertions(+), 12 deletions(-) diff --git a/pep-0474.txt b/pep-0474.txt --- a/pep-0474.txt +++ b/pep-0474.txt @@ -133,8 +133,9 @@ The richer administrative functionality would also make it substantially easier to grant users access to particular repositories for collaboration purposes, without having to grant them general access to the entire -installation. - +installation. This helps lower barriers to entry, as trust can more +readily be granted and earned incrementally, rather than being an +all-or-nothing decision around granting core developer access. Sustaining Engineering Considerations ===================================== @@ -191,8 +192,7 @@ specifically aimed at developers running local VMs for testing purposes. The `Vagrant based development guidelines `__ -for -OpenShift Origin provide an extended example of the kind of workflow this +for OpenShift Origin provide an extended example of the kind of workflow this approach enables. It's also worth noting that Vagrant is one of the options for working with a local build of the `main python.org website `__. @@ -223,6 +223,58 @@ one that I will continue to encourage as best I can. +Personal Motivation +=================== + +As of March 2015, having moved from Boeing Defence Australia (where I had +worked since September 1998) to Red Hat back in June 2011 , I now work for +Red Hat as a software development workflow designer and process architect, +focusing on the open source cross-platform +`Atomic Developer Bundle `__, +which is part of the tooling ecosystem for the +`Project Atomic `__ container hosting platform. +Two of the key pieces of that bundle will be familiar to many readers: +Docker for container management, and Vagrant for cross-platform local +development VM management. + +However, rather than being a developer for the downstream Red Hat Enterprise +Linux Container Development Kit, I work with the development teams for a +range of Red Hat's internal services, encouraging the standardisation of +internal development tooling and processes on the Atomic Developer Bundle, +contributing upstream as required to ensure it meets our needs and +expectations. As with other Red Hat community web service development +projects like `PatternFly `__, this approach +helps enable standardisation across internal services, community projects, +and commercial products, while still leaving individual development teams +with significant scope to appropriately prioritise their process improvement +efforts by focusing on the limitations currently causing the most +difficulties for them and their users. + +In that role, I'll be focusing on effectively integrating the Developer +Bundle with tools and technologies used across Red Hat's project and product +portfolio. As Red Hat is an open source system integrator, that means +touching on a wide range of services and technologies, including GitHub, +GerritHub, standalone Gerrit, GitLab, Bugzilla, JIRA, Jenkins, Docker, +Kubernetes, OpenShift, OpenStack, oVirt, Ansible, Puppet, and more. + +However, as noted above in the section on sustaining engineering +considerations, I've also secured agreement to spend a portion of my work +time on similarly applying these cross platforms tools to improving the +developer experience for the maintenance of Python Software Foundation +infrastructure, starting with this proposal for a Kallithea-based +forge.python.org service. + +Between them, my day job and my personal open source engagement have given +me visibility into a lot of what the popular source code management +services do well and what they do poorly. While Kallithea certainly has +plenty of flaws of its own, it's the one I consider most *fixable* from a +personal perspective, as it allows me to get directly involved in tailoring +it to meet the needs of the CPython core development community in a way that +wouldn't be possible with a proprietary service like GitHub or BitBucket, or +practical with a PHP-based service like Phabricator or a Ruby-based service +like GitLab. + + Technical Concerns and Challenges ================================= @@ -358,8 +410,9 @@ Prior to acceptance, in the absence of transparent interoperability, this PEP should propose specific recommendations for inclusion in the CPython -developer's guide for using git-hg to create pull requests against -forge.python.org hosted Mercurial repositories. +developer's guide section for +`git users `__ for creating +pull requests against forge.python.org hosted Mercurial repositories. Pilot Objectives and Timeline @@ -375,13 +428,13 @@ * May 1: Brett's decision on which proposal to accept * Sep 13: Python 3.5 released, adopting new workflows for Python 3.6 -Prior to the April 8 discussion, it is proposed to have the following aspects -of this PEP completed: +If this proposal is selected for further development, it is proposed to start +with the rollout of the following pilot deployment: * a reference implementation operational at kallithea-pilot.python.org, containing at least the developer guide and PEP repositories. This will be a "throwaway" instance, allowing core developers and other contributors - to experiement freely without worrying about the long term consequences for + to experiment freely without worrying about the long term consequences for the repository history. * read-only live mirrors of the Kallithea hosted repositories on GitHub and BitBucket. As with the pilot service itself, these would be temporary repos, @@ -403,9 +456,9 @@ process to be based on the relocated Mercurial repos The following items would be objectives of the overall workflow improvement -process, but may not be completed before the Python Language summit, and are -also considered "desirable, but not essential" for the initial adoption of -the new service in September (if this proposal is the one selected): +process, but are considered "desirable, but not essential" for the initial +adoption of the new service in September (if this proposal is the one +selected and the proposed pilot deployment is successful): * allowing the use of python-social-auth to authenticate against the PSF hosted Kallithea instance -- Repository URL: https://hg.python.org/peps From solipsis at pitrou.net Fri Apr 3 10:42:58 2015 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Fri, 03 Apr 2015 08:42:58 +0000 Subject: [Python-checkins] Daily reference leaks (846c165cf643): sum=339 Message-ID: <20150403084258.105422.43947@psf.io> results for 846c165cf643 on branch "default" -------------------------------------------- test_deque leaked [91, 91, 91] references, sum=273 test_deque leaked [21, 21, 21] memory blocks, sum=63 test_functools leaked [0, 0, 3] memory blocks, sum=3 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogbs_1oC', '--timeout', '7200'] From python-checkins at python.org Fri Apr 3 11:09:42 2015 From: python-checkins at python.org (victor.stinner) Date: Fri, 03 Apr 2015 09:09:42 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzIyMzUx?= =?utf-8?q?=3A_Fix_test=5Fnntplib_if_the_ssl_module_is_missing?= Message-ID: <20150403090941.16266.39776@psf.io> https://hg.python.org/cpython/rev/c3e7a670dda2 changeset: 95406:c3e7a670dda2 branch: 3.4 parent: 95403:ca8666310eb3 user: Victor Stinner date: Fri Apr 03 11:06:40 2015 +0200 summary: Issue #22351: Fix test_nntplib if the ssl module is missing @unittest.skipUnless(ssl, '...') doesn't work because the class body uses the nntplib.NNTP_SSL attribute which doesn't exist. files: Lib/test/test_nntplib.py | 19 ++++++++++--------- 1 files changed, 10 insertions(+), 9 deletions(-) diff --git a/Lib/test/test_nntplib.py b/Lib/test/test_nntplib.py --- a/Lib/test/test_nntplib.py +++ b/Lib/test/test_nntplib.py @@ -1509,15 +1509,16 @@ Handler, nntplib.NNTPPermanentError, authinfo_response, login, password) - at unittest.skipUnless(ssl, 'requires SSL support') -class MockSslTests(MockSocketTests): - class nntp_class(nntplib.NNTP_SSL): - def __init__(self, *pos, **kw): - class bypass_context: - """Bypass encryption and actual SSL module""" - def wrap_socket(sock, **args): - return sock - return super().__init__(*pos, ssl_context=bypass_context, **kw) +if ssl is not None: + class MockSslTests(MockSocketTests): + class nntp_class(nntplib.NNTP_SSL): + def __init__(self, *pos, **kw): + class bypass_context: + """Bypass encryption and actual SSL module""" + def wrap_socket(sock, **args): + return sock + return super().__init__(*pos, ssl_context=bypass_context, **kw) + if __name__ == "__main__": unittest.main() -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Apr 3 11:09:42 2015 From: python-checkins at python.org (victor.stinner) Date: Fri, 03 Apr 2015 09:09:42 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?b?KTogTWVyZ2UgMy40ICh0ZXN0X25udHBsaWIp?= Message-ID: <20150403090942.64679.58377@psf.io> https://hg.python.org/cpython/rev/f80d5faa60ee changeset: 95407:f80d5faa60ee parent: 95404:846c165cf643 parent: 95406:c3e7a670dda2 user: Victor Stinner date: Fri Apr 03 11:09:08 2015 +0200 summary: Merge 3.4 (test_nntplib) files: Lib/test/test_nntplib.py | 19 ++++++++++--------- 1 files changed, 10 insertions(+), 9 deletions(-) diff --git a/Lib/test/test_nntplib.py b/Lib/test/test_nntplib.py --- a/Lib/test/test_nntplib.py +++ b/Lib/test/test_nntplib.py @@ -1509,15 +1509,16 @@ Handler, nntplib.NNTPPermanentError, authinfo_response, login, password) - at unittest.skipUnless(ssl, 'requires SSL support') -class MockSslTests(MockSocketTests): - class nntp_class(nntplib.NNTP_SSL): - def __init__(self, *pos, **kw): - class bypass_context: - """Bypass encryption and actual SSL module""" - def wrap_socket(sock, **args): - return sock - return super().__init__(*pos, ssl_context=bypass_context, **kw) +if ssl is not None: + class MockSslTests(MockSocketTests): + class nntp_class(nntplib.NNTP_SSL): + def __init__(self, *pos, **kw): + class bypass_context: + """Bypass encryption and actual SSL module""" + def wrap_socket(sock, **args): + return sock + return super().__init__(*pos, ssl_context=bypass_context, **kw) + if __name__ == "__main__": unittest.main() -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Apr 3 13:36:57 2015 From: python-checkins at python.org (victor.stinner) Date: Fri, 03 Apr 2015 11:36:57 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2323834=3A_Simplify?= =?utf-8?q?_timeout_handling?= Message-ID: <20150403113657.16503.46119@psf.io> https://hg.python.org/cpython/rev/7a9c49885cd3 changeset: 95409:7a9c49885cd3 user: Victor Stinner date: Fri Apr 03 13:22:27 2015 +0200 summary: Issue #23834: Simplify timeout handling * Use the new _PyTime_FromSeconds() function to set the timeout to -1 second for socket.settimeout(None). It avoids a special case in internal_select() because of a rounding issue: -1 nanosecond is rounded to 0 millisecond which means non-blocking, instead of blocking. * Check if the interval the negative in sock_call_ex() instead of doing the check in internal_select(). sock_call_ex() remembers if the socket has a timeout or not, which avoids a race condition if the timeout is modified in a different thread. files: Modules/socketmodule.c | 42 ++++++++++-------------------- 1 files changed, 14 insertions(+), 28 deletions(-) diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -629,17 +629,6 @@ if (s->sock_fd < 0) return 0; - /* for connect(), we want to poll even if the socket is blocking */ - if (!connect) { - /* Nothing to do unless we're in timeout mode (not non-blocking) */ - if (s->sock_timeout <= 0) - return 0; - - /* Handling this condition here simplifies the select loops */ - if (interval < 0) - return 1; - } - /* Prefer poll, if available, since you can poll() any fd * which can't be done with select(). */ #ifdef HAVE_POLL @@ -654,22 +643,14 @@ } /* s->sock_timeout is in seconds, timeout in ms */ - if (interval >= 0) - ms = _PyTime_AsMilliseconds(interval, _PyTime_ROUND_CEILING); - else - ms = -1; + ms = _PyTime_AsMilliseconds(interval, _PyTime_ROUND_CEILING); assert(ms <= INT_MAX); Py_BEGIN_ALLOW_THREADS; n = poll(&pollfd, 1, (int)ms); Py_END_ALLOW_THREADS; #else - if (interval >= 0) - _PyTime_AsTimeval_noraise(interval, &tv, _PyTime_ROUND_CEILING); - else { - tv.tv_sec = -1; - tv.tv_sec = 0; - } + _PyTime_AsTimeval_noraise(interval, &tv, _PyTime_ROUND_CEILING); FD_ZERO(&fds); FD_SET(s->sock_fd, &fds); @@ -741,9 +722,9 @@ /* For connect(), poll even for blocking socket. The connection runs asynchronously. */ if (has_timeout || connect) { - _PyTime_t interval; - if (has_timeout) { + _PyTime_t interval; + if (deadline_initialized) { /* recompute the timeout */ interval = deadline - _PyTime_GetMonotonicClock(); @@ -753,11 +734,16 @@ deadline = _PyTime_GetMonotonicClock() + s->sock_timeout; interval = s->sock_timeout; } + + if (interval >= 0) + res = internal_select(s, writing, interval, connect); + else + res = 1; } - else - interval = -1; - - res = internal_select(s, writing, interval, connect); + else { + res = internal_select(s, writing, -1, connect); + } + if (res == -1) { if (err) *err = GET_SOCK_ERROR; @@ -2332,7 +2318,7 @@ int overflow = 0; if (timeout_obj == Py_None) { - *timeout = -1; + *timeout = _PyTime_FromSeconds(-1); return 0; } -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Apr 3 13:36:57 2015 From: python-checkins at python.org (victor.stinner) Date: Fri, 03 Apr 2015 11:36:57 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2322117=3A_Add_a_ne?= =?utf-8?q?w_=5FPyTime=5FFromSeconds=28=29_function?= Message-ID: <20150403113657.98374.24414@psf.io> https://hg.python.org/cpython/rev/d976683671ba changeset: 95408:d976683671ba user: Victor Stinner date: Fri Apr 03 13:10:54 2015 +0200 summary: Issue #22117: Add a new _PyTime_FromSeconds() function Fix also _Py_InitializeEx_Private(): initialize time before initializing import, import_init() uses the _PyTime API (for thread locks). files: Include/pytime.h | 5 ++++- Lib/test/test_time.py | 7 +++++++ Modules/_testcapimodule.c | 13 +++++++++++++ Modules/_threadmodule.c | 2 +- Python/pylifecycle.c | 6 +++--- Python/pytime.c | 17 +++++++++++++++++ 6 files changed, 45 insertions(+), 5 deletions(-) diff --git a/Include/pytime.h b/Include/pytime.h --- a/Include/pytime.h +++ b/Include/pytime.h @@ -66,7 +66,10 @@ _PyTime_round_t); -/* Create a timestamp from a number of nanoseconds (C long). */ +/* Create a timestamp from a number of seconds. */ +PyAPI_FUNC(_PyTime_t) _PyTime_FromSeconds(int ns); + +/* Create a timestamp from a number of nanoseconds. */ PyAPI_FUNC(_PyTime_t) _PyTime_FromNanoseconds(PY_LONG_LONG ns); /* Convert a number of seconds (Python float or int) to a timetamp. 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 @@ -731,6 +731,13 @@ @unittest.skipUnless(_testcapi is not None, 'need the _testcapi module') class TestPyTime_t(unittest.TestCase): + def test_FromSeconds(self): + from _testcapi import PyTime_FromSeconds + for seconds in (0, 3, -456, _testcapi.INT_MAX, _testcapi.INT_MIN): + with self.subTest(seconds=seconds): + self.assertEqual(PyTime_FromSeconds(seconds), + seconds * SEC_TO_NS) + def test_FromSecondsObject(self): from _testcapi import PyTime_FromSecondsObject diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -3383,6 +3383,18 @@ } static PyObject * +test_pytime_fromseconds(PyObject *self, PyObject *args) +{ + int seconds; + _PyTime_t ts; + + if (!PyArg_ParseTuple(args, "i", &seconds)) + return NULL; + ts = _PyTime_FromSeconds(seconds); + return _PyTime_AsNanosecondsObject(ts); +} + +static PyObject * test_pytime_fromsecondsobject(PyObject *self, PyObject *args) { PyObject *obj; @@ -3651,6 +3663,7 @@ return_null_without_error, METH_NOARGS}, {"return_result_with_error", return_result_with_error, METH_NOARGS}, + {"PyTime_FromSeconds", test_pytime_fromseconds, METH_VARARGS}, {"PyTime_FromSecondsObject", test_pytime_fromsecondsobject, METH_VARARGS}, {"PyTime_AsSecondsDouble", test_pytime_assecondsdouble, METH_VARARGS}, {"PyTime_AsTimeval", test_PyTime_AsTimeval, METH_VARARGS}, diff --git a/Modules/_threadmodule.c b/Modules/_threadmodule.c --- a/Modules/_threadmodule.c +++ b/Modules/_threadmodule.c @@ -101,7 +101,7 @@ char *kwlist[] = {"blocking", "timeout", NULL}; int blocking = 1; PyObject *timeout_obj = NULL; - const _PyTime_t unset_timeout = _PyTime_FromNanoseconds(-1000000000); + const _PyTime_t unset_timeout = _PyTime_FromSeconds(-1); *timeout = unset_timeout ; diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -405,15 +405,15 @@ if (!install_importlib) return; + if (_PyTime_Init() < 0) + Py_FatalError("Py_Initialize: can't initialize time"); + import_init(interp, sysmod); /* initialize the faulthandler module */ if (_PyFaulthandler_Init()) Py_FatalError("Py_Initialize: can't initialize faulthandler"); - if (_PyTime_Init() < 0) - Py_FatalError("Py_Initialize: can't initialize time"); - if (initfsencoding(interp) < 0) Py_FatalError("Py_Initialize: unable to load the file system codec"); diff --git a/Python/pytime.c b/Python/pytime.c --- a/Python/pytime.c +++ b/Python/pytime.c @@ -159,6 +159,19 @@ } _PyTime_t +_PyTime_FromSeconds(int seconds) +{ + _PyTime_t t; + /* ensure that integer overflow cannot happen, int type should have 32 + bits, whereas _PyTime_t type has at least 64 bits (SEC_TO_MS takes 30 + bits). */ + assert((seconds >= 0 && seconds <= _PyTime_MAX / SEC_TO_NS) + || (seconds < 0 && seconds >= _PyTime_MIN / SEC_TO_NS)); + t = (_PyTime_t)seconds * SEC_TO_NS; + return t; +} + +_PyTime_t _PyTime_FromNanoseconds(PY_LONG_LONG ns) { _PyTime_t t; @@ -657,5 +670,9 @@ /* ensure that the operating system provides a monotonic clock */ if (_PyTime_GetMonotonicClockWithInfo(&t, NULL) < 0) return -1; + + /* check that _PyTime_FromSeconds() cannot overflow */ + assert(INT_MAX <= _PyTime_MAX / SEC_TO_NS); + assert(INT_MIN >= _PyTime_MIN / SEC_TO_NS); return 0; } -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Apr 3 13:36:57 2015 From: python-checkins at python.org (victor.stinner) Date: Fri, 03 Apr 2015 11:36:57 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2323853=3A_Cleanup_?= =?utf-8?b?X3NzbC5j?= Message-ID: <20150403113657.16509.43710@psf.io> https://hg.python.org/cpython/rev/753233baf27e changeset: 95410:753233baf27e user: Victor Stinner date: Thu Apr 02 21:28:28 2015 +0200 summary: Issue #23853: Cleanup _ssl.c * Rename check_socket_and_wait_for_timeout() to PySSL_select() * PySSL_select() is now clearly splitted betwen poll() and select() * Add empty lines for readability files: Modules/_ssl.c | 99 +++++++++++++++++++------------------ 1 files changed, 52 insertions(+), 47 deletions(-) diff --git a/Modules/_ssl.c b/Modules/_ssl.c --- a/Modules/_ssl.c +++ b/Modules/_ssl.c @@ -223,8 +223,7 @@ static PyObject *PySSL_SSLwrite(PySSLSocket *self, PyObject *args); static PyObject *PySSL_SSLread(PySSLSocket *self, PyObject *args); -static int check_socket_and_wait_for_timeout(PySocketSockObject *s, - int writing); +static int PySSL_select(PySocketSockObject *s, int writing); static PyObject *PySSL_peercert(PySSLSocket *self, PyObject *args); static PyObject *PySSL_cipher(PySSLSocket *self); @@ -588,15 +587,18 @@ ret = SSL_do_handshake(self->ssl); err = SSL_get_error(self->ssl, ret); PySSL_END_ALLOW_THREADS + if (PyErr_CheckSignals()) goto error; + if (err == SSL_ERROR_WANT_READ) { - sockstate = check_socket_and_wait_for_timeout(sock, 0); + sockstate = PySSL_select(sock, 0); } else if (err == SSL_ERROR_WANT_WRITE) { - sockstate = check_socket_and_wait_for_timeout(sock, 1); + sockstate = PySSL_select(sock, 1); } else { sockstate = SOCKET_OPERATION_OK; } + if (sockstate == SOCKET_HAS_TIMED_OUT) { PyErr_SetString(PySocketModule.timeout_error, ERRSTR("The handshake operation timed out")); @@ -1609,11 +1611,17 @@ */ static int -check_socket_and_wait_for_timeout(PySocketSockObject *s, int writing) +PySSL_select(PySocketSockObject *s, int writing) { + int rc; +#ifdef HAVE_POLL + struct pollfd pollfd; + _PyTime_t ms; +#else + int nfds; fd_set fds; struct timeval tv; - int rc; +#endif /* Nothing to do unless we're in timeout mode (not non-blocking) */ if ((s == NULL) || (s->sock_timeout == 0)) @@ -1628,25 +1636,17 @@ /* Prefer poll, if available, since you can poll() any fd * which can't be done with select(). */ #ifdef HAVE_POLL - { - struct pollfd pollfd; - int timeout; - - pollfd.fd = s->sock_fd; - pollfd.events = writing ? POLLOUT : POLLIN; - - /* s->sock_timeout is in seconds, timeout in ms */ - timeout = (int)_PyTime_AsMilliseconds(s->sock_timeout, - _PyTime_ROUND_CEILING); - - PySSL_BEGIN_ALLOW_THREADS - rc = poll(&pollfd, 1, timeout); - PySSL_END_ALLOW_THREADS - - goto normal_return; - } -#endif - + pollfd.fd = s->sock_fd; + pollfd.events = writing ? POLLOUT : POLLIN; + + /* s->sock_timeout is in seconds, timeout in ms */ + ms = (int)_PyTime_AsMilliseconds(s->sock_timeout, _PyTime_ROUND_CEILING); + assert(ms <= INT_MAX); + + PySSL_BEGIN_ALLOW_THREADS + rc = poll(&pollfd, 1, (int)ms); + PySSL_END_ALLOW_THREADS +#else /* Guard against socket too large for select*/ if (!_PyIsSelectable_fd(s->sock_fd)) return SOCKET_TOO_LARGE_FOR_SELECT; @@ -1656,19 +1656,16 @@ FD_ZERO(&fds); FD_SET(s->sock_fd, &fds); - /* See if the socket is ready */ + /* Wait until the socket becomes ready */ PySSL_BEGIN_ALLOW_THREADS + nfds = Py_SAFE_DOWNCAST(s->sock_fd+1, SOCKET_T, int); if (writing) - rc = select(Py_SAFE_DOWNCAST(s->sock_fd+1, SOCKET_T, int), - NULL, &fds, NULL, &tv); + rc = select(nfds, NULL, &fds, NULL, &tv); else - rc = select(Py_SAFE_DOWNCAST(s->sock_fd+1, SOCKET_T, int), - &fds, NULL, NULL, &tv); + rc = select(nfds, &fds, NULL, NULL, &tv); PySSL_END_ALLOW_THREADS - -#ifdef HAVE_POLL -normal_return: #endif + /* Return SOCKET_TIMED_OUT on timeout, SOCKET_OPERATION_OK otherwise (when we are able to write or when there's something to read) */ return rc == 0 ? SOCKET_HAS_TIMED_OUT : SOCKET_OPERATION_OK; @@ -1710,7 +1707,7 @@ BIO_set_nbio(SSL_get_wbio(self->ssl), nonblocking); } - sockstate = check_socket_and_wait_for_timeout(sock, 1); + sockstate = PySSL_select(sock, 1); if (sockstate == SOCKET_HAS_TIMED_OUT) { PyErr_SetString(PySocketModule.timeout_error, "The write operation timed out"); @@ -1724,21 +1721,24 @@ "Underlying socket too large for select()."); goto error; } + do { PySSL_BEGIN_ALLOW_THREADS len = SSL_write(self->ssl, buf.buf, (int)buf.len); err = SSL_get_error(self->ssl, len); PySSL_END_ALLOW_THREADS - if (PyErr_CheckSignals()) { + + if (PyErr_CheckSignals()) goto error; - } + if (err == SSL_ERROR_WANT_READ) { - sockstate = check_socket_and_wait_for_timeout(sock, 0); + sockstate = PySSL_select(sock, 0); } else if (err == SSL_ERROR_WANT_WRITE) { - sockstate = check_socket_and_wait_for_timeout(sock, 1); + sockstate = PySSL_select(sock, 1); } else { sockstate = SOCKET_OPERATION_OK; } + if (sockstate == SOCKET_HAS_TIMED_OUT) { PyErr_SetString(PySocketModule.timeout_error, "The write operation timed out"); @@ -1847,21 +1847,23 @@ count = SSL_read(self->ssl, mem, len); err = SSL_get_error(self->ssl, count); PySSL_END_ALLOW_THREADS + if (PyErr_CheckSignals()) goto error; + if (err == SSL_ERROR_WANT_READ) { - sockstate = check_socket_and_wait_for_timeout(sock, 0); + sockstate = PySSL_select(sock, 0); } else if (err == SSL_ERROR_WANT_WRITE) { - sockstate = check_socket_and_wait_for_timeout(sock, 1); - } else if ((err == SSL_ERROR_ZERO_RETURN) && - (SSL_get_shutdown(self->ssl) == - SSL_RECEIVED_SHUTDOWN)) + sockstate = PySSL_select(sock, 1); + } else if (err == SSL_ERROR_ZERO_RETURN && + SSL_get_shutdown(self->ssl) == SSL_RECEIVED_SHUTDOWN) { count = 0; goto done; - } else { + } + else sockstate = SOCKET_OPERATION_OK; - } + if (sockstate == SOCKET_HAS_TIMED_OUT) { PyErr_SetString(PySocketModule.timeout_error, "The read operation timed out"); @@ -1870,6 +1872,7 @@ break; } } while (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE); + if (count <= 0) { PySSL_SetError(self, count, __FILE__, __LINE__); goto error; @@ -1935,6 +1938,7 @@ SSL_set_read_ahead(self->ssl, 0); err = SSL_shutdown(self->ssl); PySSL_END_ALLOW_THREADS + /* If err == 1, a secure shutdown with SSL_shutdown() is complete */ if (err > 0) break; @@ -1952,11 +1956,12 @@ /* Possibly retry shutdown until timeout or failure */ ssl_err = SSL_get_error(self->ssl, err); if (ssl_err == SSL_ERROR_WANT_READ) - sockstate = check_socket_and_wait_for_timeout(sock, 0); + sockstate = PySSL_select(sock, 0); else if (ssl_err == SSL_ERROR_WANT_WRITE) - sockstate = check_socket_and_wait_for_timeout(sock, 1); + sockstate = PySSL_select(sock, 1); else break; + if (sockstate == SOCKET_HAS_TIMED_OUT) { if (ssl_err == SSL_ERROR_WANT_READ) PyErr_SetString(PySocketModule.timeout_error, -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Apr 3 14:03:00 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Fri, 03 Apr 2015 12:03:00 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2322351=2E_MockSslTests_tests_in_test=5Fnntplib_n?= =?utf-8?q?ow_are_reported_if_skipped=2E?= Message-ID: <20150403120300.27432.48125@psf.io> https://hg.python.org/cpython/rev/c935c1e1d001 changeset: 95412:c935c1e1d001 parent: 95410:753233baf27e parent: 95411:7a91363f31e1 user: Serhiy Storchaka date: Fri Apr 03 15:02:40 2015 +0300 summary: Issue #22351. MockSslTests tests in test_nntplib now are reported if skipped. files: Lib/test/test_nntplib.py | 19 ++++++++++--------- 1 files changed, 10 insertions(+), 9 deletions(-) diff --git a/Lib/test/test_nntplib.py b/Lib/test/test_nntplib.py --- a/Lib/test/test_nntplib.py +++ b/Lib/test/test_nntplib.py @@ -1509,15 +1509,16 @@ Handler, nntplib.NNTPPermanentError, authinfo_response, login, password) -if ssl is not None: - class MockSslTests(MockSocketTests): - class nntp_class(nntplib.NNTP_SSL): - def __init__(self, *pos, **kw): - class bypass_context: - """Bypass encryption and actual SSL module""" - def wrap_socket(sock, **args): - return sock - return super().__init__(*pos, ssl_context=bypass_context, **kw) +class bypass_context: + """Bypass encryption and actual SSL module""" + def wrap_socket(sock, **args): + return sock + + at unittest.skipUnless(ssl, 'requires SSL support') +class MockSslTests(MockSocketTests): + @staticmethod + def nntp_class(*pos, **kw): + return nntplib.NNTP_SSL(*pos, ssl_context=bypass_context, **kw) if __name__ == "__main__": -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Apr 3 14:04:09 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Fri, 03 Apr 2015 12:04:09 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzIyMzUx?= =?utf-8?q?=2E_MockSslTests_tests_in_test=5Fnntplib_now_are_reported_if_sk?= =?utf-8?q?ipped=2E?= Message-ID: <20150403120300.75242.92898@psf.io> https://hg.python.org/cpython/rev/7a91363f31e1 changeset: 95411:7a91363f31e1 branch: 3.4 parent: 95406:c3e7a670dda2 user: Serhiy Storchaka date: Fri Apr 03 15:02:20 2015 +0300 summary: Issue #22351. MockSslTests tests in test_nntplib now are reported if skipped. files: Lib/test/test_nntplib.py | 19 ++++++++++--------- 1 files changed, 10 insertions(+), 9 deletions(-) diff --git a/Lib/test/test_nntplib.py b/Lib/test/test_nntplib.py --- a/Lib/test/test_nntplib.py +++ b/Lib/test/test_nntplib.py @@ -1509,15 +1509,16 @@ Handler, nntplib.NNTPPermanentError, authinfo_response, login, password) -if ssl is not None: - class MockSslTests(MockSocketTests): - class nntp_class(nntplib.NNTP_SSL): - def __init__(self, *pos, **kw): - class bypass_context: - """Bypass encryption and actual SSL module""" - def wrap_socket(sock, **args): - return sock - return super().__init__(*pos, ssl_context=bypass_context, **kw) +class bypass_context: + """Bypass encryption and actual SSL module""" + def wrap_socket(sock, **args): + return sock + + at unittest.skipUnless(ssl, 'requires SSL support') +class MockSslTests(MockSocketTests): + @staticmethod + def nntp_class(*pos, **kw): + return nntplib.NNTP_SSL(*pos, ssl_context=bypass_context, **kw) if __name__ == "__main__": -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Apr 3 14:25:52 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Fri, 03 Apr 2015 12:25:52 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Got_rid_of_warnings_=22sug?= =?utf-8?q?gest_braces_around_empty_body_in_an_=E2=80=98else=E2=80=99?= Message-ID: <20150403122552.75248.43271@psf.io> https://hg.python.org/cpython/rev/5795e7a85aee changeset: 95413:5795e7a85aee user: Serhiy Storchaka date: Fri Apr 03 15:24:33 2015 +0300 summary: Got rid of warnings "suggest braces around empty body in an ?else? statement" in Parser/pgen.c. files: Parser/pgen.c | 5 +++-- 1 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Parser/pgen.c b/Parser/pgen.c --- a/Parser/pgen.c +++ b/Parser/pgen.c @@ -136,11 +136,12 @@ static char REQNFMT[] = "metacompile: less than %d children\n"; -#define REQN(i, count) \ +#define REQN(i, count) do { \ if (i < count) { \ fprintf(stderr, REQNFMT, count); \ Py_FatalError("REQN"); \ - } else + } \ +} while (0) #else #define REQN(i, count) /* empty */ -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Apr 3 17:10:31 2015 From: python-checkins at python.org (victor.stinner) Date: Fri, 03 Apr 2015 15:10:31 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Merge_3=2E4_=28asyncio_doc=29?= Message-ID: <20150403151031.105426.1057@psf.io> https://hg.python.org/cpython/rev/17d9a526394f changeset: 95415:17d9a526394f parent: 95413:5795e7a85aee parent: 95414:c167b9f9aac8 user: Victor Stinner date: Fri Apr 03 17:10:17 2015 +0200 summary: Merge 3.4 (asyncio doc) files: Doc/library/asyncio-task.rst | 5 +++++ 1 files changed, 5 insertions(+), 0 deletions(-) diff --git a/Doc/library/asyncio-task.rst b/Doc/library/asyncio-task.rst --- a/Doc/library/asyncio-task.rst +++ b/Doc/library/asyncio-task.rst @@ -644,7 +644,12 @@ cancels the task and raises :exc:`asyncio.TimeoutError`. To avoid the task cancellation, wrap it in :func:`shield`. + If the wait is cancelled, the future *fut* is also cancelled. + This function is a :ref:`coroutine `, usage:: result = yield from asyncio.wait_for(fut, 60.0) + .. versionchanged:: 3.4.3 + If the wait is cancelled, the future *fut* is now also cancelled. + -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Apr 3 17:10:31 2015 From: python-checkins at python.org (victor.stinner) Date: Fri, 03 Apr 2015 15:10:31 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzIzMjE5?= =?utf-8?q?=3A_Update_asyncio=2Ewait=5Ffor=28=29_documentation?= Message-ID: <20150403151031.98398.81516@psf.io> https://hg.python.org/cpython/rev/c167b9f9aac8 changeset: 95414:c167b9f9aac8 branch: 3.4 parent: 95411:7a91363f31e1 user: Victor Stinner date: Fri Apr 03 17:08:19 2015 +0200 summary: Issue #23219: Update asyncio.wait_for() documentation the wait is cancelled, the future *fut* is now also cancelled. files: Doc/library/asyncio-task.rst | 5 +++++ 1 files changed, 5 insertions(+), 0 deletions(-) diff --git a/Doc/library/asyncio-task.rst b/Doc/library/asyncio-task.rst --- a/Doc/library/asyncio-task.rst +++ b/Doc/library/asyncio-task.rst @@ -644,7 +644,12 @@ cancels the task and raises :exc:`asyncio.TimeoutError`. To avoid the task cancellation, wrap it in :func:`shield`. + If the wait is cancelled, the future *fut* is also cancelled. + This function is a :ref:`coroutine `, usage:: result = yield from asyncio.wait_for(fut, 60.0) + .. versionchanged:: 3.4.3 + If the wait is cancelled, the future *fut* is now also cancelled. + -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Apr 3 17:13:45 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Fri, 03 Apr 2015 15:13:45 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_Escaped_backsl?= =?utf-8?q?ashes_in_docstrings=2E?= Message-ID: <20150403151345.29547.69881@psf.io> https://hg.python.org/cpython/rev/fe34dfea16b0 changeset: 95416:fe34dfea16b0 branch: 2.7 parent: 95405:7f9597b44740 user: Serhiy Storchaka date: Fri Apr 03 18:12:32 2015 +0300 summary: Escaped backslashes in docstrings. files: Lib/codecs.py | 2 +- Lib/idlelib/SearchEngine.py | 2 +- Lib/textwrap.py | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Lib/codecs.py b/Lib/codecs.py --- a/Lib/codecs.py +++ b/Lib/codecs.py @@ -1057,7 +1057,7 @@ during translation. One example where this happens is cp875.py which decodes - multiple character to \u001a. + multiple character to \\u001a. """ m = {} diff --git a/Lib/idlelib/SearchEngine.py b/Lib/idlelib/SearchEngine.py --- a/Lib/idlelib/SearchEngine.py +++ b/Lib/idlelib/SearchEngine.py @@ -191,7 +191,7 @@ This is done by searching forwards until there is no match. Prog: compiled re object with a search method returning a match. - Chars: line of text, without \n. + Chars: line of text, without \\n. Col: stop index for the search; the limit for match.end(). ''' m = prog.search(chars) diff --git a/Lib/textwrap.py b/Lib/textwrap.py --- a/Lib/textwrap.py +++ b/Lib/textwrap.py @@ -147,7 +147,7 @@ """_munge_whitespace(text : string) -> string Munge whitespace in text: expand tabs and convert all other - whitespace characters to spaces. Eg. " foo\tbar\n\nbaz" + whitespace characters to spaces. Eg. " foo\\tbar\\n\\nbaz" becomes " foo bar baz". """ if self.expand_tabs: @@ -193,7 +193,7 @@ """_fix_sentence_endings(chunks : [string]) Correct for sentence endings buried in 'chunks'. Eg. when the - original text contains "... foo.\nBar ...", munge_whitespace() + original text contains "... foo.\\nBar ...", munge_whitespace() and split() will convert that to [..., "foo.", " ", "Bar", ...] which has one too few spaces; this method simply changes the one space to two. @@ -379,7 +379,7 @@ in indented form. Note that tabs and spaces are both treated as whitespace, but they - are not equal: the lines " hello" and "\thello" are + are not equal: the lines " hello" and "\\thello" are considered to have no common leading whitespace. (This behaviour is new in Python 2.5; older versions of this module incorrectly expanded tabs before searching for common leading whitespace.) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Apr 3 17:13:46 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Fri, 03 Apr 2015 15:13:46 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Escaped_backslashes_in_docstrings=2E?= Message-ID: <20150403151346.75250.89199@psf.io> https://hg.python.org/cpython/rev/1b37e4e156e5 changeset: 95418:1b37e4e156e5 parent: 95415:17d9a526394f parent: 95417:e855bde79795 user: Serhiy Storchaka date: Fri Apr 03 18:13:23 2015 +0300 summary: Escaped backslashes in docstrings. files: Lib/base64.py | 4 ++-- Lib/codecs.py | 2 +- Lib/email/_encoded_words.py | 2 +- Lib/idlelib/SearchEngine.py | 2 +- Lib/smtplib.py | 4 ++-- Lib/test/support/__init__.py | 6 +++--- Lib/textwrap.py | 6 +++--- 7 files changed, 13 insertions(+), 13 deletions(-) diff --git a/Lib/base64.py b/Lib/base64.py --- a/Lib/base64.py +++ b/Lib/base64.py @@ -324,7 +324,7 @@ instead of 4 consecutive spaces (ASCII 0x20) as supported by 'btoa'. This feature is not supported by the "standard" Adobe encoding. - wrapcol controls whether the output should have newline ('\n') characters + wrapcol controls whether the output should have newline ('\\n') characters added to it. If this is non-zero, each output line will be at most this many characters long. @@ -434,7 +434,7 @@ def b85encode(b, pad=False): """Encode an ASCII-encoded byte array in base85 format. - If pad is true, the input is padded with "\0" so its length is a multiple of + If pad is true, the input is padded with "\\0" so its length is a multiple of 4 characters before encoding. """ global _b85chars, _b85chars2 diff --git a/Lib/codecs.py b/Lib/codecs.py --- a/Lib/codecs.py +++ b/Lib/codecs.py @@ -1065,7 +1065,7 @@ during translation. One example where this happens is cp875.py which decodes - multiple character to \u001a. + multiple character to \\u001a. """ m = {} diff --git a/Lib/email/_encoded_words.py b/Lib/email/_encoded_words.py --- a/Lib/email/_encoded_words.py +++ b/Lib/email/_encoded_words.py @@ -152,7 +152,7 @@ then from the resulting bytes into unicode using the specified charset. If the cte-decoded string does not successfully decode using the specified character set, a defect is added to the defects list and the unknown octets - are replaced by the unicode 'unknown' character \uFDFF. + are replaced by the unicode 'unknown' character \\uFDFF. The specified charset and language are returned. The default for language, which is rarely if ever encountered, is the empty string. diff --git a/Lib/idlelib/SearchEngine.py b/Lib/idlelib/SearchEngine.py --- a/Lib/idlelib/SearchEngine.py +++ b/Lib/idlelib/SearchEngine.py @@ -191,7 +191,7 @@ This is done by searching forwards until there is no match. Prog: compiled re object with a search method returning a match. - Chars: line of text, without \n. + Chars: line of text, without \\n. Col: stop index for the search; the limit for match.end(). ''' m = prog.search(chars) diff --git a/Lib/smtplib.py b/Lib/smtplib.py --- a/Lib/smtplib.py +++ b/Lib/smtplib.py @@ -518,8 +518,8 @@ Raises SMTPDataError if there is an unexpected reply to the DATA command; the return value from this method is the final response code received when the all data is sent. If msg - is a string, lone '\r' and '\n' characters are converted to - '\r\n' characters. If msg is bytes, it is transmitted as is. + is a string, lone '\\r' and '\\n' characters are converted to + '\\r\\n' characters. If msg is bytes, it is transmitted as is. """ self.putcmd("data") (code, repl) = self.getreply() diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py --- a/Lib/test/support/__init__.py +++ b/Lib/test/support/__init__.py @@ -1380,7 +1380,7 @@ with captured_stdout() as stdout: print("hello") - self.assertEqual(stdout.getvalue(), "hello\n") + self.assertEqual(stdout.getvalue(), "hello\\n") """ return captured_output("stdout") @@ -1389,7 +1389,7 @@ with captured_stderr() as stderr: print("hello", file=sys.stderr) - self.assertEqual(stderr.getvalue(), "hello\n") + self.assertEqual(stderr.getvalue(), "hello\\n") """ return captured_output("stderr") @@ -1397,7 +1397,7 @@ """Capture the input to sys.stdin: with captured_stdin() as stdin: - stdin.write('hello\n') + stdin.write('hello\\n') stdin.seek(0) # call test code that consumes from sys.stdin captured = input() diff --git a/Lib/textwrap.py b/Lib/textwrap.py --- a/Lib/textwrap.py +++ b/Lib/textwrap.py @@ -148,7 +148,7 @@ """_munge_whitespace(text : string) -> string Munge whitespace in text: expand tabs and convert all other - whitespace characters to spaces. Eg. " foo\tbar\n\nbaz" + whitespace characters to spaces. Eg. " foo\\tbar\\n\\nbaz" becomes " foo bar baz". """ if self.expand_tabs: @@ -184,7 +184,7 @@ """_fix_sentence_endings(chunks : [string]) Correct for sentence endings buried in 'chunks'. Eg. when the - original text contains "... foo.\nBar ...", munge_whitespace() + original text contains "... foo.\\nBar ...", munge_whitespace() and split() will convert that to [..., "foo.", " ", "Bar", ...] which has one too few spaces; this method simply changes the one space to two. @@ -420,7 +420,7 @@ in indented form. Note that tabs and spaces are both treated as whitespace, but they - are not equal: the lines " hello" and "\thello" are + are not equal: the lines " hello" and "\\thello" are considered to have no common leading whitespace. (This behaviour is new in Python 2.5; older versions of this module incorrectly expanded tabs before searching for common leading whitespace.) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Apr 3 17:13:46 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Fri, 03 Apr 2015 15:13:46 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E4=29=3A_Escaped_backsl?= =?utf-8?q?ashes_in_docstrings=2E?= Message-ID: <20150403151345.98374.2859@psf.io> https://hg.python.org/cpython/rev/e855bde79795 changeset: 95417:e855bde79795 branch: 3.4 parent: 95414:c167b9f9aac8 user: Serhiy Storchaka date: Fri Apr 03 18:12:41 2015 +0300 summary: Escaped backslashes in docstrings. files: Lib/base64.py | 4 ++-- Lib/codecs.py | 2 +- Lib/email/_encoded_words.py | 2 +- Lib/idlelib/SearchEngine.py | 2 +- Lib/smtplib.py | 4 ++-- Lib/test/support/__init__.py | 6 +++--- Lib/textwrap.py | 6 +++--- 7 files changed, 13 insertions(+), 13 deletions(-) diff --git a/Lib/base64.py b/Lib/base64.py --- a/Lib/base64.py +++ b/Lib/base64.py @@ -324,7 +324,7 @@ instead of 4 consecutive spaces (ASCII 0x20) as supported by 'btoa'. This feature is not supported by the "standard" Adobe encoding. - wrapcol controls whether the output should have newline ('\n') characters + wrapcol controls whether the output should have newline ('\\n') characters added to it. If this is non-zero, each output line will be at most this many characters long. @@ -434,7 +434,7 @@ def b85encode(b, pad=False): """Encode an ASCII-encoded byte array in base85 format. - If pad is true, the input is padded with "\0" so its length is a multiple of + If pad is true, the input is padded with "\\0" so its length is a multiple of 4 characters before encoding. """ global _b85chars, _b85chars2 diff --git a/Lib/codecs.py b/Lib/codecs.py --- a/Lib/codecs.py +++ b/Lib/codecs.py @@ -1061,7 +1061,7 @@ during translation. One example where this happens is cp875.py which decodes - multiple character to \u001a. + multiple character to \\u001a. """ m = {} diff --git a/Lib/email/_encoded_words.py b/Lib/email/_encoded_words.py --- a/Lib/email/_encoded_words.py +++ b/Lib/email/_encoded_words.py @@ -152,7 +152,7 @@ then from the resulting bytes into unicode using the specified charset. If the cte-decoded string does not successfully decode using the specified character set, a defect is added to the defects list and the unknown octets - are replaced by the unicode 'unknown' character \uFDFF. + are replaced by the unicode 'unknown' character \\uFDFF. The specified charset and language are returned. The default for language, which is rarely if ever encountered, is the empty string. diff --git a/Lib/idlelib/SearchEngine.py b/Lib/idlelib/SearchEngine.py --- a/Lib/idlelib/SearchEngine.py +++ b/Lib/idlelib/SearchEngine.py @@ -191,7 +191,7 @@ This is done by searching forwards until there is no match. Prog: compiled re object with a search method returning a match. - Chars: line of text, without \n. + Chars: line of text, without \\n. Col: stop index for the search; the limit for match.end(). ''' m = prog.search(chars) diff --git a/Lib/smtplib.py b/Lib/smtplib.py --- a/Lib/smtplib.py +++ b/Lib/smtplib.py @@ -518,8 +518,8 @@ Raises SMTPDataError if there is an unexpected reply to the DATA command; the return value from this method is the final response code received when the all data is sent. If msg - is a string, lone '\r' and '\n' characters are converted to - '\r\n' characters. If msg is bytes, it is transmitted as is. + is a string, lone '\\r' and '\\n' characters are converted to + '\\r\\n' characters. If msg is bytes, it is transmitted as is. """ self.putcmd("data") (code, repl) = self.getreply() diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py --- a/Lib/test/support/__init__.py +++ b/Lib/test/support/__init__.py @@ -1379,7 +1379,7 @@ with captured_stdout() as stdout: print("hello") - self.assertEqual(stdout.getvalue(), "hello\n") + self.assertEqual(stdout.getvalue(), "hello\\n") """ return captured_output("stdout") @@ -1388,7 +1388,7 @@ with captured_stderr() as stderr: print("hello", file=sys.stderr) - self.assertEqual(stderr.getvalue(), "hello\n") + self.assertEqual(stderr.getvalue(), "hello\\n") """ return captured_output("stderr") @@ -1396,7 +1396,7 @@ """Capture the input to sys.stdin: with captured_stdin() as stdin: - stdin.write('hello\n') + stdin.write('hello\\n') stdin.seek(0) # call test code that consumes from sys.stdin captured = input() diff --git a/Lib/textwrap.py b/Lib/textwrap.py --- a/Lib/textwrap.py +++ b/Lib/textwrap.py @@ -133,7 +133,7 @@ """_munge_whitespace(text : string) -> string Munge whitespace in text: expand tabs and convert all other - whitespace characters to spaces. Eg. " foo\tbar\n\nbaz" + whitespace characters to spaces. Eg. " foo\\tbar\\n\\nbaz" becomes " foo bar baz". """ if self.expand_tabs: @@ -169,7 +169,7 @@ """_fix_sentence_endings(chunks : [string]) Correct for sentence endings buried in 'chunks'. Eg. when the - original text contains "... foo.\nBar ...", munge_whitespace() + original text contains "... foo.\\nBar ...", munge_whitespace() and split() will convert that to [..., "foo.", " ", "Bar", ...] which has one too few spaces; this method simply changes the one space to two. @@ -405,7 +405,7 @@ in indented form. Note that tabs and spaces are both treated as whitespace, but they - are not equal: the lines " hello" and "\thello" are + are not equal: the lines " hello" and "\\thello" are considered to have no common leading whitespace. (This behaviour is new in Python 2.5; older versions of this module incorrectly expanded tabs before searching for common leading whitespace.) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Apr 3 18:42:56 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Fri, 03 Apr 2015 16:42:56 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Removed_trailing_whitespac?= =?utf-8?q?es_in_miscalenous_files=2E?= Message-ID: <20150403164256.16503.71276@psf.io> https://hg.python.org/cpython/rev/60740163085d changeset: 95419:60740163085d user: Serhiy Storchaka date: Fri Apr 03 19:42:32 2015 +0300 summary: Removed trailing whitespaces in miscalenous files. files: Include/methodobject.h | 4 ++-- Mac/Makefile.in | 6 +++--- Modules/ld_so_aix.in | 6 +++--- Parser/Python.asdl | 16 ++++++++-------- Tools/freeze/extensions_win32.ini | 8 ++++---- Tools/scripts/dutree.doc | 6 +++--- 6 files changed, 23 insertions(+), 23 deletions(-) diff --git a/Include/methodobject.h b/Include/methodobject.h --- a/Include/methodobject.h +++ b/Include/methodobject.h @@ -47,7 +47,7 @@ typedef struct PyMethodDef PyMethodDef; #define PyCFunction_New(ML, SELF) PyCFunction_NewEx((ML), (SELF), NULL) -PyAPI_FUNC(PyObject *) PyCFunction_NewEx(PyMethodDef *, PyObject *, +PyAPI_FUNC(PyObject *) PyCFunction_NewEx(PyMethodDef *, PyObject *, PyObject *); /* Flag passed to newmethodobject */ @@ -66,7 +66,7 @@ /* METH_COEXIST allows a method to be entered even though a slot has already filled the entry. When defined, the flag allows a separate - method, "__contains__" for example, to coexist with a defined + method, "__contains__" for example, to coexist with a defined slot like sq_contains. */ #define METH_COEXIST 0x0040 diff --git a/Mac/Makefile.in b/Mac/Makefile.in --- a/Mac/Makefile.in +++ b/Mac/Makefile.in @@ -1,5 +1,5 @@ -# This file can be invoked from the various frameworkinstall... targets in the -# main Makefile. The next couple of variables are overridden on the +# This file can be invoked from the various frameworkinstall... targets in the +# main Makefile. The next couple of variables are overridden on the # commandline in that case. VERSION=@VERSION@ @@ -53,7 +53,7 @@ installapps: install_Python install_PythonLauncher install_IDLE # -# Install unix tools in /usr/local/bin. These are just aliases for the +# Install unix tools in /usr/local/bin. These are just aliases for the # actual installation inside the framework. # installunixtools: diff --git a/Modules/ld_so_aix.in b/Modules/ld_so_aix.in --- a/Modules/ld_so_aix.in +++ b/Modules/ld_so_aix.in @@ -5,7 +5,7 @@ # TYPE: executable, uses makexp_aix # SYSTEM: AIX # -# DESCRIPTION: Creates a shareable .o from a set of pre-compiled +# DESCRIPTION: Creates a shareable .o from a set of pre-compiled # (unshared) .o files # # USAGE: ld_so_aix [CC] [arguments] @@ -46,7 +46,7 @@ # 4. Uncommenting the "echo" lines gives detailed output # about the commands executed in the script. # -# +# # HISTORY: Oct-1996 -- Support added for multiple .o files -- # -- and optional arguments processing. -- # Chris Myers (myers at tc.cornell.edu), Keith Kwok @@ -132,7 +132,7 @@ done if test "$objfile" = "libpython at VERSION@@ABIFLAGS at .so"; then - ldsocoremode="true" + ldsocoremode="true" fi if test -z "$objs"; then diff --git a/Parser/Python.asdl b/Parser/Python.asdl --- a/Parser/Python.asdl +++ b/Parser/Python.asdl @@ -9,9 +9,9 @@ -- not really an actual node but useful in Jython's typesystem. | Suite(stmt* body) - stmt = FunctionDef(identifier name, arguments args, + stmt = FunctionDef(identifier name, arguments args, stmt* body, expr* decorator_list, expr? returns) - | ClassDef(identifier name, + | ClassDef(identifier name, expr* bases, keyword* keywords, expr? starargs, @@ -77,7 +77,7 @@ | Subscript(expr value, slice slice, expr_context ctx) | Starred(expr value, expr_context ctx) | Name(identifier id, expr_context ctx) - | List(expr* elts, expr_context ctx) + | List(expr* elts, expr_context ctx) | Tuple(expr* elts, expr_context ctx) -- col_offset is the byte offset in the utf8 string the parser uses @@ -85,13 +85,13 @@ expr_context = Load | Store | Del | AugLoad | AugStore | Param - slice = Slice(expr? lower, expr? upper, expr? step) - | ExtSlice(slice* dims) - | Index(expr value) + slice = Slice(expr? lower, expr? upper, expr? step) + | ExtSlice(slice* dims) + | Index(expr value) - boolop = And | Or + boolop = And | Or - operator = Add | Sub | Mult | MatMult | Div | Mod | Pow | LShift + operator = Add | Sub | Mult | MatMult | Div | Mod | Pow | LShift | RShift | BitOr | BitXor | BitAnd | FloorDiv unaryop = Invert | Not | UAdd | USub diff --git a/Tools/freeze/extensions_win32.ini b/Tools/freeze/extensions_win32.ini --- a/Tools/freeze/extensions_win32.ini +++ b/Tools/freeze/extensions_win32.ini @@ -6,7 +6,7 @@ ; This is all setup for all the win32 extension modules ; released by Mark Hammond. -; You must ensure that the environment variable PYTHONEX is set +; You must ensure that the environment variable PYTHONEX is set ; to point to the root win32 extensions directory ; PYTHONPREFIX must point to the Python build root directory @@ -49,7 +49,7 @@ [zlib] dsp=%PYTHONPREFIX%\PCBuild\zlib.dsp -cl=/I %PYTHONPREFIX%\..\zlib-1.1.4 /D _WINDOWS /D WIN32 +cl=/I %PYTHONPREFIX%\..\zlib-1.1.4 /D _WINDOWS /D WIN32 libs=%PYTHONPREFIX%\..\zlib-1.1.4\zlib.lib /nodefaultlib:libc [winreg] @@ -95,7 +95,7 @@ cl=/I %PYTHONEX%\win32\src [win32file] -dsp=%PYTHONEX%\win32\win32file.dsp +dsp=%PYTHONEX%\win32\win32file.dsp cl=/I %PYTHONEX%\win32\src [win32net] @@ -108,7 +108,7 @@ cl=/I %PYTHONEX%\win32\src [win32pipe] -dsp=%PYTHONEX%\win32\win32pipe.dsp +dsp=%PYTHONEX%\win32\win32pipe.dsp cl=/I %PYTHONEX%\win32\src [win32security] diff --git a/Tools/scripts/dutree.doc b/Tools/scripts/dutree.doc --- a/Tools/scripts/dutree.doc +++ b/Tools/scripts/dutree.doc @@ -34,13 +34,13 @@ : | 1 sm.bak At first I thought I could just keep one local list around -at once, but this seems inherently recursive. Which means +at once, but this seems inherently recursive. Which means I need an real recursive data structure. Maybe you could do it with one of the %assoc arrays Larry uses in the begat programs, but I broke down and got dirty. I think the hardest -part was matching Felix's desired output exactly. It's not +part was matching Felix's desired output exactly. It's not blazingly fast: I should probably inline the &childof routine, -but it *was* faster to write than I could have written the +but it *was* faster to write than I could have written the equivalent C program. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Apr 3 19:54:08 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Fri, 03 Apr 2015 17:54:08 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2323466=3A_Raised_O?= =?utf-8?q?verflowError_if_=25c_argument_is_out_of_range=2E?= Message-ID: <20150403175408.29533.24922@psf.io> https://hg.python.org/cpython/rev/313fd1c819c5 changeset: 95420:313fd1c819c5 user: Serhiy Storchaka date: Fri Apr 03 20:53:46 2015 +0300 summary: Issue #23466: Raised OverflowError if %c argument is out of range. files: Lib/test/test_format.py | 12 ++++++------ Objects/bytesobject.c | 11 ++++++++--- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/Lib/test/test_format.py b/Lib/test/test_format.py --- a/Lib/test/test_format.py +++ b/Lib/test/test_format.py @@ -358,12 +358,12 @@ "not all arguments converted during bytes formatting") test_exc(b'no format', bytearray(b'1'), TypeError, "not all arguments converted during bytes formatting") - test_exc(b"%c", -1, TypeError, - "%c requires an integer in range(256) or a single byte") - test_exc(b"%c", 256, TypeError, - "%c requires an integer in range(256) or a single byte") - test_exc(b"%c", 2**128, TypeError, - "%c requires an integer in range(256) or a single byte") + test_exc(b"%c", -1, OverflowError, + "%c arg not in range(256)") + test_exc(b"%c", 256, OverflowError, + "%c arg not in range(256)") + test_exc(b"%c", 2**128, OverflowError, + "%c arg not in range(256)") test_exc(b"%c", b"Za", TypeError, "%c requires an integer in range(256) or a single byte") test_exc(b"%c", "Y", TypeError, diff --git a/Objects/bytesobject.c b/Objects/bytesobject.c --- a/Objects/bytesobject.c +++ b/Objects/bytesobject.c @@ -496,10 +496,15 @@ ival = PyLong_AsLongAndOverflow(iobj, &overflow); Py_DECREF(iobj); } - if (!overflow && 0 <= ival && ival <= 255) { - *p = (char)ival; - return 1; + if (!overflow && ival == -1 && PyErr_Occurred()) + goto onError; + if (overflow || !(0 <= ival && ival <= 255)) { + PyErr_SetString(PyExc_OverflowError, + "%c arg not in range(256)"); + return 0; } + *p = (char)ival; + return 1; } onError: PyErr_SetString(PyExc_TypeError, -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Apr 3 21:39:32 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Fri, 03 Apr 2015 19:39:32 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2315582=3A_inspect?= =?utf-8?q?=2Egetdoc=28=29_now_follows_inheritance_chains=2E?= Message-ID: <20150403193932.105420.2583@psf.io> https://hg.python.org/cpython/rev/157b7055bb9d changeset: 95421:157b7055bb9d user: Serhiy Storchaka date: Fri Apr 03 22:38:53 2015 +0300 summary: Issue #15582: inspect.getdoc() now follows inheritance chains. files: Doc/library/inspect.rst | 3 + Lib/inspect.py | 73 ++++++++++++++++++++++++++ Lib/test/inspect_fodder.py | 14 ++++- Lib/test/test_inspect.py | 23 +++++++- Misc/NEWS | 2 + 5 files changed, 112 insertions(+), 3 deletions(-) diff --git a/Doc/library/inspect.rst b/Doc/library/inspect.rst --- a/Doc/library/inspect.rst +++ b/Doc/library/inspect.rst @@ -356,6 +356,9 @@ .. function:: getdoc(object) Get the documentation string for an object, cleaned up with :func:`cleandoc`. + If the documentation string for an object is not provided and the object is + a class, a method, a property or a descriptor, retrieve the documentation + string from the inheritance hierarchy. .. function:: getcomments(object) diff --git a/Lib/inspect.py b/Lib/inspect.py --- a/Lib/inspect.py +++ b/Lib/inspect.py @@ -468,6 +468,74 @@ expline = line.expandtabs() return len(expline) - len(expline.lstrip()) +def _findclass(func): + cls = sys.modules.get(func.__module__) + if cls is None: + return None + for name in func.__qualname__.split('.')[:-1]: + cls = getattr(cls, name) + if not isclass(cls): + return None + return cls + +def _finddoc(obj): + if isclass(obj): + for base in obj.__mro__: + if base is not object: + try: + doc = base.__doc__ + except AttributeError: + continue + if doc is not None: + return doc + return None + + if ismethod(obj): + name = obj.__func__.__name__ + self = obj.__self__ + if (isclass(self) and + getattr(getattr(self, name, None), '__func__') is obj.__func__): + # classmethod + cls = self + else: + cls = self.__class__ + elif isfunction(obj): + name = obj.__name__ + cls = _findclass(obj) + if cls is None or getattr(cls, name) is not obj: + return None + elif isbuiltin(obj): + name = obj.__name__ + self = obj.__self__ + if (isclass(self) and + self.__qualname__ + '.' + name == obj.__qualname__): + # classmethod + cls = self + else: + cls = self.__class__ + elif ismethoddescriptor(obj) or isdatadescriptor(obj): + name = obj.__name__ + cls = obj.__objclass__ + if getattr(cls, name) is not obj: + return None + elif isinstance(obj, property): + func = f.fget + name = func.__name__ + cls = _findclass(func) + if cls is None or getattr(cls, name) is not obj: + return None + else: + return None + + for base in cls.__mro__: + try: + doc = getattr(base, name).__doc__ + except AttributeError: + continue + if doc is not None: + return doc + return None + def getdoc(object): """Get the documentation string for an object. @@ -478,6 +546,11 @@ doc = object.__doc__ except AttributeError: return None + if doc is None: + try: + doc = _finddoc(object) + except (AttributeError, TypeError): + return None if not isinstance(doc, str): return None return cleandoc(doc) diff --git a/Lib/test/inspect_fodder.py b/Lib/test/inspect_fodder.py --- a/Lib/test/inspect_fodder.py +++ b/Lib/test/inspect_fodder.py @@ -45,9 +45,16 @@ self.ex = sys.exc_info() self.tr = inspect.trace() + def contradiction(self): + 'The automatic gainsaying.' + pass + # line 48 class MalodorousPervert(StupidGit): - pass + def abuse(self, a, b, c): + pass + def contradiction(self): + pass Tit = MalodorousPervert @@ -55,4 +62,7 @@ pass class FesteringGob(MalodorousPervert, ParrotDroppings): - pass + def abuse(self, a, b, c): + pass + def contradiction(self): + pass diff --git a/Lib/test/test_inspect.py b/Lib/test/test_inspect.py --- a/Lib/test/test_inspect.py +++ b/Lib/test/test_inspect.py @@ -292,6 +292,27 @@ self.assertEqual(inspect.getdoc(git.abuse), 'Another\n\ndocstring\n\ncontaining\n\ntabs') + @unittest.skipIf(sys.flags.optimize >= 2, + "Docstrings are omitted with -O2 and above") + def test_getdoc_inherited(self): + self.assertEqual(inspect.getdoc(mod.FesteringGob), + 'A longer,\n\nindented\n\ndocstring.') + self.assertEqual(inspect.getdoc(mod.FesteringGob.abuse), + 'Another\n\ndocstring\n\ncontaining\n\ntabs') + self.assertEqual(inspect.getdoc(mod.FesteringGob().abuse), + 'Another\n\ndocstring\n\ncontaining\n\ntabs') + self.assertEqual(inspect.getdoc(mod.FesteringGob.contradiction), + 'The automatic gainsaying.') + + @unittest.skipIf(MISSING_C_DOCSTRINGS, "test requires docstrings") + def test_finddoc(self): + finddoc = inspect._finddoc + self.assertEqual(finddoc(int), int.__doc__) + self.assertEqual(finddoc(int.to_bytes), int.to_bytes.__doc__) + self.assertEqual(finddoc(int().to_bytes), int.to_bytes.__doc__) + self.assertEqual(finddoc(int.from_bytes), int.from_bytes.__doc__) + self.assertEqual(finddoc(int.real), int.real.__doc__) + def test_cleandoc(self): self.assertEqual(inspect.cleandoc('An\n indented\n docstring.'), 'An\nindented\ndocstring.') @@ -316,7 +337,7 @@ def test_getsource(self): self.assertSourceEqual(git.abuse, 29, 39) - self.assertSourceEqual(mod.StupidGit, 21, 46) + self.assertSourceEqual(mod.StupidGit, 21, 50) def test_getsourcefile(self): self.assertEqual(normcase(inspect.getsourcefile(mod.spam)), modfile) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -16,6 +16,8 @@ Library ------- +- Issue #15582: inspect.getdoc() now follows inheritance chains. + - Issue #2175: SAX parsers now support a character stream of InputSource object. - Issue #16840: Tkinter now supports 64-bit integers added in Tcl 8.4 and -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Apr 3 22:09:16 2015 From: python-checkins at python.org (larry.hastings) Date: Fri, 03 Apr 2015 20:09:16 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2323500=3A_Argument?= =?utf-8?q?_Clinic_is_now_smarter_about_generating_the_=22=23ifndef=22?= Message-ID: <20150403200916.27436.36943@psf.io> https://hg.python.org/cpython/rev/25eef0ecb9c1 changeset: 95422:25eef0ecb9c1 user: Larry Hastings date: Fri Apr 03 13:09:02 2015 -0700 summary: Issue #23500: Argument Clinic is now smarter about generating the "#ifndef" (empty) definition of the methoddef macro: it's only generated once, even if Argument Clinic processes the same symbol multiple times, and it's emitted at the end of all processing rather than immediately after the first use. files: Misc/NEWS | 5 + Modules/clinic/spwdmodule.c.h | 10 +- Modules/clinic/zlibmodule.c.h | 14 +- Modules/posixmodule.c | 14 +- Tools/clinic/clinic.py | 168 ++++++++++++--------- 5 files changed, 115 insertions(+), 96 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -268,6 +268,11 @@ Tools/Demos ----------- +- Issue #23500: Argument Clinic is now smarter about generating the "#ifndef" + (empty) definition of the methoddef macro: it's only generated once, even + if Argument Clinic processes the same symbol multiple times, and it's emitted + at the end of all processing rather than immediately after the first use. + - Issue #22826: The result of open() in Tools/freeze/bkfile.py is now better compatible with regular files (in particular it now supports the context management protocol). diff --git a/Modules/clinic/spwdmodule.c.h b/Modules/clinic/spwdmodule.c.h --- a/Modules/clinic/spwdmodule.c.h +++ b/Modules/clinic/spwdmodule.c.h @@ -36,10 +36,6 @@ #endif /* defined(HAVE_GETSPNAM) */ -#ifndef SPWD_GETSPNAM_METHODDEF - #define SPWD_GETSPNAM_METHODDEF -#endif /* !defined(SPWD_GETSPNAM_METHODDEF) */ - #if defined(HAVE_GETSPENT) PyDoc_STRVAR(spwd_getspall__doc__, @@ -64,7 +60,11 @@ #endif /* defined(HAVE_GETSPENT) */ +#ifndef SPWD_GETSPNAM_METHODDEF + #define SPWD_GETSPNAM_METHODDEF +#endif /* !defined(SPWD_GETSPNAM_METHODDEF) */ + #ifndef SPWD_GETSPALL_METHODDEF #define SPWD_GETSPALL_METHODDEF #endif /* !defined(SPWD_GETSPALL_METHODDEF) */ -/*[clinic end generated code: output=41fec4a15b0cd2a0 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=ab16125c5e5f2b1b input=a9049054013a1b77]*/ diff --git a/Modules/clinic/zlibmodule.c.h b/Modules/clinic/zlibmodule.c.h --- a/Modules/clinic/zlibmodule.c.h +++ b/Modules/clinic/zlibmodule.c.h @@ -314,10 +314,6 @@ #endif /* defined(HAVE_ZLIB_COPY) */ -#ifndef ZLIB_COMPRESS_COPY_METHODDEF - #define ZLIB_COMPRESS_COPY_METHODDEF -#endif /* !defined(ZLIB_COMPRESS_COPY_METHODDEF) */ - #if defined(HAVE_ZLIB_COPY) PyDoc_STRVAR(zlib_Decompress_copy__doc__, @@ -340,10 +336,6 @@ #endif /* defined(HAVE_ZLIB_COPY) */ -#ifndef ZLIB_DECOMPRESS_COPY_METHODDEF - #define ZLIB_DECOMPRESS_COPY_METHODDEF -#endif /* !defined(ZLIB_DECOMPRESS_COPY_METHODDEF) */ - PyDoc_STRVAR(zlib_Decompress_flush__doc__, "flush($self, length=zlib.DEF_BUF_SIZE, /)\n" "--\n" @@ -450,4 +442,8 @@ return return_value; } -/*[clinic end generated code: output=bc9473721ca7c962 input=a9049054013a1b77]*/ + +#ifndef ZLIB_COMPRESS_COPY_METHODDEF + #define ZLIB_COMPRESS_COPY_METHODDEF +#endif /* !defined(ZLIB_COMPRESS_COPY_METHODDEF) */ +/*[clinic end generated code: output=901c18189767dc08 input=a9049054013a1b77]*/ diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -17130,10 +17130,6 @@ #define OS_SYSTEM_METHODDEF #endif /* !defined(OS_SYSTEM_METHODDEF) */ -#ifndef OS_SYSTEM_METHODDEF - #define OS_SYSTEM_METHODDEF -#endif /* !defined(OS_SYSTEM_METHODDEF) */ - #ifndef OS_UNAME_METHODDEF #define OS_UNAME_METHODDEF #endif /* !defined(OS_UNAME_METHODDEF) */ @@ -17306,10 +17302,6 @@ #define OS_WAITPID_METHODDEF #endif /* !defined(OS_WAITPID_METHODDEF) */ -#ifndef OS_WAITPID_METHODDEF - #define OS_WAITPID_METHODDEF -#endif /* !defined(OS_WAITPID_METHODDEF) */ - #ifndef OS_WAIT_METHODDEF #define OS_WAIT_METHODDEF #endif /* !defined(OS_WAIT_METHODDEF) */ @@ -17410,10 +17402,6 @@ #define OS_PUTENV_METHODDEF #endif /* !defined(OS_PUTENV_METHODDEF) */ -#ifndef OS_PUTENV_METHODDEF - #define OS_PUTENV_METHODDEF -#endif /* !defined(OS_PUTENV_METHODDEF) */ - #ifndef OS_UNSETENV_METHODDEF #define OS_UNSETENV_METHODDEF #endif /* !defined(OS_UNSETENV_METHODDEF) */ @@ -17521,7 +17509,7 @@ #ifndef OS_SET_HANDLE_INHERITABLE_METHODDEF #define OS_SET_HANDLE_INHERITABLE_METHODDEF #endif /* !defined(OS_SET_HANDLE_INHERITABLE_METHODDEF) */ -/*[clinic end generated code: output=52a6140b0b052ce6 input=524ce2e021e4eba6]*/ +/*[clinic end generated code: output=b788c2d6010113e8 input=524ce2e021e4eba6]*/ static PyMethodDef posix_methods[] = { diff --git a/Tools/clinic/clinic.py b/Tools/clinic/clinic.py --- a/Tools/clinic/clinic.py +++ b/Tools/clinic/clinic.py @@ -67,14 +67,18 @@ unknown = Unknown() +_text_accumulator_nt = collections.namedtuple("_text_accumulator", "text append output") + def _text_accumulator(): text = [] def output(): s = ''.join(text) text.clear() return s - return text, text.append, output - + return _text_accumulator_nt(text, text.append, output) + + +text_accumulator_nt = collections.namedtuple("text_accumulator", "text append") def text_accumulator(): """ @@ -88,7 +92,7 @@ empties the accumulator. """ text, append, output = _text_accumulator() - return append, output + return text_accumulator_nt(append, output) def warn_or_fail(fail=False, *args, filename=None, line_number=None): @@ -820,7 +824,8 @@ cpp_if = "#if " + conditional cpp_endif = "#endif /* " + conditional + " */" - if methoddef_define: + if methoddef_define and f.name not in clinic.ifndef_symbols: + clinic.ifndef_symbols.add(f.name) methoddef_ifndef = normalize_snippet(""" #ifndef {methoddef_name} #define {methoddef_name} @@ -1078,7 +1083,8 @@ if has_option_groups: self.render_option_group_parsing(f, template_dict) - for name, destination in clinic.field_destinations.items(): + # buffers, not destination + for name, destination in clinic.destination_buffers.items(): template = templates[name] if has_option_groups: template = linear_format(template, @@ -1403,12 +1409,48 @@ self.f.write(text) +class BufferSeries: + """ + Behaves like a "defaultlist". + When you ask for an index that doesn't exist yet, + the object grows the list until that item exists. + So o[n] will always work. + + Supports negative indices for actual items. + e.g. o[-1] is an element immediately preceding o[0]. + """ + + def __init__(self): + self._start = 0 + self._array = [] + self._constructor = _text_accumulator + + def __getitem__(self, i): + i -= self._start + if i < 0: + self._start += i + prefix = [self._constructor() for x in range(-i)] + self._array = prefix + self._array + i = 0 + while i >= len(self._array): + self._array.append(self._constructor()) + return self._array[i] + + def clear(self): + for ta in self._array: + ta._text.clear() + + def dump(self): + texts = [ta.output() for ta in self._array] + return "".join(texts) + + class Destination: def __init__(self, name, type, clinic, *args): self.name = name self.type = type self.clinic = clinic - valid_types = ('buffer', 'file', 'suppress', 'two-pass') + valid_types = ('buffer', 'file', 'suppress') if type not in valid_types: fail("Invalid destination type " + repr(type) + " for " + name + " , must be " + ', '.join(valid_types)) extra_arguments = 1 if type == "file" else 0 @@ -1427,10 +1469,8 @@ d['basename'] = basename d['basename_root'], d['basename_extension'] = os.path.splitext(filename) self.filename = args[0].format_map(d) - if type == 'two-pass': - self.id = None - - self.text, self.append, self._dump = _text_accumulator() + + self.buffers = BufferSeries() def __repr__(self): if self.type == 'file': @@ -1442,15 +1482,10 @@ def clear(self): if self.type != 'buffer': fail("Can't clear destination" + self.name + " , it's not of type buffer") - self.text.clear() + self.buffers.clear() def dump(self): - if self.type == 'two-pass': - if self.id is None: - self.id = str(uuid.uuid4()) - return self.id - fail("You can only dump a two-pass buffer exactly once!") - return self._dump() + return self.buffers.dump() # maps strings to Language objects. @@ -1489,49 +1524,44 @@ presets_text = """ preset block everything block +methoddef_ifndef buffer 1 docstring_prototype suppress parser_prototype suppress cpp_if suppress cpp_endif suppress -methoddef_ifndef buffer preset original everything block +methoddef_ifndef buffer 1 docstring_prototype suppress parser_prototype suppress cpp_if suppress cpp_endif suppress -methoddef_ifndef buffer preset file everything file +methoddef_ifndef file 1 docstring_prototype suppress parser_prototype suppress impl_definition block preset buffer everything buffer +methoddef_ifndef buffer 1 +impl_definition block docstring_prototype suppress impl_prototype suppress parser_prototype suppress -impl_definition block preset partial-buffer everything buffer +methoddef_ifndef buffer 1 docstring_prototype block impl_prototype suppress methoddef_define block parser_prototype block impl_definition block -preset two-pass -everything buffer -docstring_prototype two-pass -impl_prototype suppress -methoddef_define two-pass -parser_prototype two-pass -impl_definition block - """ def __init__(self, language, printer=None, *, force=False, verify=True, filename=None): @@ -1555,12 +1585,11 @@ self.add_destination("block", "buffer") self.add_destination("suppress", "suppress") self.add_destination("buffer", "buffer") - self.add_destination("two-pass", "two-pass") if filename: self.add_destination("file", "file", "{dirname}/clinic/{basename}.h") - d = self.destinations.get - self.field_destinations = collections.OrderedDict(( + d = self.get_destination_buffer + self.destination_buffers = collections.OrderedDict(( ('cpp_if', d('suppress')), ('docstring_prototype', d('suppress')), ('docstring_definition', d('block')), @@ -1569,11 +1598,12 @@ ('parser_prototype', d('suppress')), ('parser_definition', d('block')), ('cpp_endif', d('suppress')), - ('methoddef_ifndef', d('buffer')), + ('methoddef_ifndef', d('buffer', 1)), ('impl_definition', d('block')), )) - self.field_destinations_stack = [] + self.destination_buffers_stack = [] + self.ifndef_symbols = set() self.presets = {} preset = None @@ -1581,37 +1611,43 @@ line = line.strip() if not line: continue - name, value = line.split() + name, value, *options = line.split() if name == 'preset': self.presets[value] = preset = collections.OrderedDict() continue - destination = self.get_destination(value) + if len(options): + index = int(options[0]) + else: + index = 0 + buffer = self.get_destination_buffer(value, index) if name == 'everything': - for name in self.field_destinations: - preset[name] = destination + for name in self.destination_buffers: + preset[name] = buffer continue - assert name in self.field_destinations - preset[name] = destination + assert name in self.destination_buffers + preset[name] = buffer global clinic clinic = self - def get_destination(self, name, default=unspecified): - d = self.destinations.get(name) - if not d: - if default is not unspecified: - return default - fail("Destination does not exist: " + repr(name)) - return d - def add_destination(self, name, type, *args): if name in self.destinations: fail("Destination already exists: " + repr(name)) self.destinations[name] = Destination(name, type, self, *args) + def get_destination(self, name): + d = self.destinations.get(name) + if not d: + fail("Destination does not exist: " + repr(name)) + return d + + def get_destination_buffer(self, name, item=0): + d = self.get_destination(name) + return d.buffers[item] + def parse(self, input): printer = self.printer self.block_parser = BlockParser(input, self.language, verify=self.verify) @@ -1631,17 +1667,11 @@ second_pass_replacements = {} + # these are destinations not buffers for name, destination in self.destinations.items(): if destination.type == 'suppress': continue - output = destination._dump() - - if destination.type == 'two-pass': - if destination.id: - second_pass_replacements[destination.id] = output - elif output: - fail("Two-pass buffer " + repr(name) + " not empty at end of file!") - continue + output = destination.dump() if output: @@ -3104,43 +3134,43 @@ fail("unknown destination command", repr(command)) - def directive_output(self, field, destination=''): - fd = self.clinic.field_destinations - - if field == "preset": + def directive_output(self, command_or_name, destination=''): + fd = self.clinic.destination_buffers + + if command_or_name == "preset": preset = self.clinic.presets.get(destination) if not preset: fail("Unknown preset " + repr(destination) + "!") fd.update(preset) return - if field == "push": - self.clinic.field_destinations_stack.append(fd.copy()) + if command_or_name == "push": + self.clinic.destination_buffers_stack.append(fd.copy()) return - if field == "pop": - if not self.clinic.field_destinations_stack: + if command_or_name == "pop": + if not self.clinic.destination_buffers_stack: fail("Can't 'output pop', stack is empty!") - previous_fd = self.clinic.field_destinations_stack.pop() + previous_fd = self.clinic.destination_buffers_stack.pop() fd.update(previous_fd) return # secret command for debugging! - if field == "print": + if command_or_name == "print": self.block.output.append(pprint.pformat(fd)) self.block.output.append('\n') return d = self.clinic.get_destination(destination) - if field == "everything": + if command_or_name == "everything": for name in list(fd): fd[name] = d return - if field not in fd: - fail("Invalid field " + repr(field) + ", must be one of:\n preset push pop print everything " + " ".join(fd)) - fd[field] = d + if command_or_name not in fd: + fail("Invalid command / destination name " + repr(command_or_name) + ", must be one of:\n preset push pop print everything " + " ".join(fd)) + fd[command_or_name] = d def directive_dump(self, name): self.block.output.append(self.clinic.get_destination(name).dump()) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Apr 3 22:54:14 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Fri, 03 Apr 2015 20:54:14 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2323501=3A_Argumen_?= =?utf-8?q?Clinic_now_generates_code_into_separate_files_by_default=2E?= Message-ID: <20150403205413.16244.57389@psf.io> https://hg.python.org/cpython/rev/aa88a18a4aa1 changeset: 95423:aa88a18a4aa1 user: Serhiy Storchaka date: Fri Apr 03 23:53:51 2015 +0300 summary: Issue #23501: Argumen Clinic now generates code into separate files by default. files: Misc/NEWS | 2 + Modules/_bz2module.c | 3 +- Modules/_codecsmodule.c | 31 +- Modules/_cryptmodule.c | 37 +- Modules/_cursesmodule.c | 70 +- Modules/_datetimemodule.c | 38 +- Modules/_dbmmodule.c | 74 +- Modules/_lzmamodule.c | 3 +- Modules/_opcode.c | 37 +- Modules/_pickle.c | 3 +- Modules/_weakref.c | 31 +- Modules/arraymodule.c | 3 +- Modules/audioop.c | 3 +- Modules/binascii.c | 3 +- Modules/cjkcodecs/multibytecodec.c | 7 +- Modules/_codecsmodule.c | 1229 +- Modules/_cryptmodule.c | 64 +- Modules/_cursesmodule.c | 3456 +--- Modules/_datetimemodule.c | 5556 +----- Modules/_dbmmodule.c | 489 +- Modules/_opcode.c | 76 +- Modules/_weakref.c | 131 +- Modules/md5module.c | 608 +- Modules/posixmodule.c | 13317 +------------ Modules/pyexpat.c | 1978 +- Modules/sha1module.c | 580 +- Modules/sha256module.c | 747 +- Modules/sha512module.c | 852 +- Modules/unicodedata.c | 1398 +- Modules/cmathmodule.c | 3 +- Modules/fcntlmodule.c | 3 +- Modules/grpmodule.c | 3 +- Modules/md5module.c | 103 +- Modules/posixmodule.c | 5755 +----- Modules/pwdmodule.c | 3 +- Modules/pyexpat.c | 307 +- Modules/sha1module.c | 103 +- Modules/sha256module.c | 135 +- Modules/sha512module.c | 163 +- Modules/spwdmodule.c | 3 +- Modules/unicodedata.c | 37 +- Modules/zlibmodule.c | 3 +- Objects/bytearrayobject.c | 756 +- Objects/bytesobject.c | 522 +- Objects/bytearrayobject.c | 3271 +--- Objects/bytesobject.c | 3702 +--- Objects/dictobject.c | 3889 +--- Objects/unicodeobject.c | 15439 +-------------- Objects/dictobject.c | 44 +- Objects/unicodeobject.c | 42 +- Python/bltinmodule.c | 715 +- Python/bltinmodule.c | 2694 +-- Python/import.c | 3 +- Tools/clinic/clinic.py | 14 +- 54 files changed, 738 insertions(+), 67800 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -63,6 +63,8 @@ Build ----- +- Issue #23501: Argumen Clinic now generates code into separate files by default. + Tests ----- diff --git a/Modules/_bz2module.c b/Modules/_bz2module.c --- a/Modules/_bz2module.c +++ b/Modules/_bz2module.c @@ -211,12 +211,11 @@ } /*[clinic input] -output preset file module _bz2 class _bz2.BZ2Compressor "BZ2Compressor *" "&BZ2Compressor_Type" class _bz2.BZ2Decompressor "BZ2Decompressor *" "&BZ2Decompressor_Type" [clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=e3b139924f5e18cc]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=dc7d7992a79f9cb7]*/ #include "clinic/_bz2module.c.h" diff --git a/Modules/_codecsmodule.c b/Modules/_codecsmodule.c --- a/Modules/_codecsmodule.c +++ b/Modules/_codecsmodule.c @@ -47,6 +47,7 @@ [clinic start generated code]*/ /*[clinic end generated code: output=da39a3ee5e6b4b0d input=e1390e3da3cb9deb]*/ +#include "clinic/_codecsmodule.c.h" /* --- Registry ----------------------------------------------------------- */ @@ -153,37 +154,9 @@ Purge the named codec from the internal codec lookup cache [clinic start generated code]*/ -PyDoc_STRVAR(_codecs__forget_codec__doc__, -"_forget_codec($module, encoding, /)\n" -"--\n" -"\n" -"Purge the named codec from the internal codec lookup cache"); - -#define _CODECS__FORGET_CODEC_METHODDEF \ - {"_forget_codec", (PyCFunction)_codecs__forget_codec, METH_VARARGS, _codecs__forget_codec__doc__}, - -static PyObject * -_codecs__forget_codec_impl(PyModuleDef *module, const char *encoding); - -static PyObject * -_codecs__forget_codec(PyModuleDef *module, PyObject *args) -{ - PyObject *return_value = NULL; - const char *encoding; - - if (!PyArg_ParseTuple(args, - "s:_forget_codec", - &encoding)) - goto exit; - return_value = _codecs__forget_codec_impl(module, encoding); - -exit: - return return_value; -} - static PyObject * _codecs__forget_codec_impl(PyModuleDef *module, const char *encoding) -/*[clinic end generated code: output=a75e631591702a5c input=18d5d92d0e386c38]*/ +/*[clinic end generated code: output=b56a9b99d2d28080 input=18d5d92d0e386c38]*/ { if (_PyCodec_Forget(encoding) < 0) { return NULL; diff --git a/Modules/_cryptmodule.c b/Modules/_cryptmodule.c --- a/Modules/_cryptmodule.c +++ b/Modules/_cryptmodule.c @@ -12,6 +12,7 @@ [clinic start generated code]*/ /*[clinic end generated code: output=da39a3ee5e6b4b0d input=c6252cf4f2f2ae81]*/ +#include "clinic/_cryptmodule.c.h" /*[clinic input] crypt.crypt @@ -29,43 +30,9 @@ [clinic start generated code]*/ -PyDoc_STRVAR(crypt_crypt__doc__, -"crypt($module, word, salt, /)\n" -"--\n" -"\n" -"Hash a *word* with the given *salt* and return the hashed password.\n" -"\n" -"*word* will usually be a user\'s password. *salt* (either a random 2 or 16\n" -"character string, possibly prefixed with $digit$ to indicate the method)\n" -"will be used to perturb the encryption algorithm and produce distinct\n" -"results for a given *word*."); - -#define CRYPT_CRYPT_METHODDEF \ - {"crypt", (PyCFunction)crypt_crypt, METH_VARARGS, crypt_crypt__doc__}, - -static PyObject * -crypt_crypt_impl(PyModuleDef *module, const char *word, const char *salt); - -static PyObject * -crypt_crypt(PyModuleDef *module, PyObject *args) -{ - PyObject *return_value = NULL; - const char *word; - const char *salt; - - if (!PyArg_ParseTuple(args, - "ss:crypt", - &word, &salt)) - goto exit; - return_value = crypt_crypt_impl(module, word, salt); - -exit: - return return_value; -} - static PyObject * crypt_crypt_impl(PyModuleDef *module, const char *word, const char *salt) -/*[clinic end generated code: output=3eaacdf994a6ff23 input=4d93b6d0f41fbf58]*/ +/*[clinic end generated code: output=995ad1e854d83069 input=4d93b6d0f41fbf58]*/ { /* On some platforms (AtheOS) crypt returns NULL for an invalid salt. Return None in that case. XXX Maybe raise an exception? */ diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c --- a/Modules/_cursesmodule.c +++ b/Modules/_cursesmodule.c @@ -140,6 +140,8 @@ [clinic start generated code]*/ /*[clinic end generated code: output=da39a3ee5e6b4b0d input=88c860abdbb50e0c]*/ +#include "clinic/_cursesmodule.c.h" + /* Definition of exception curses.error */ static PyObject *PyCursesError; @@ -583,75 +585,9 @@ current settings for the window object. [clinic start generated code]*/ -PyDoc_STRVAR(curses_window_addch__doc__, -"addch([y, x,] ch, [attr])\n" -"Paint character ch at (y, x) with attributes attr.\n" -"\n" -" y\n" -" Y-coordinate.\n" -" x\n" -" X-coordinate.\n" -" ch\n" -" Character to add.\n" -" attr\n" -" Attributes for the character.\n" -"\n" -"Paint character ch at (y, x) with attributes attr,\n" -"overwriting any character previously painted at that location.\n" -"By default, the character position and attributes are the\n" -"current settings for the window object."); - -#define CURSES_WINDOW_ADDCH_METHODDEF \ - {"addch", (PyCFunction)curses_window_addch, METH_VARARGS, curses_window_addch__doc__}, - -static PyObject * -curses_window_addch_impl(PyCursesWindowObject *self, int group_left_1, int y, int x, PyObject *ch, int group_right_1, long attr); - -static PyObject * -curses_window_addch(PyCursesWindowObject *self, PyObject *args) -{ - PyObject *return_value = NULL; - int group_left_1 = 0; - int y = 0; - int x = 0; - PyObject *ch; - int group_right_1 = 0; - long attr = 0; - - switch (PyTuple_GET_SIZE(args)) { - case 1: - if (!PyArg_ParseTuple(args, "O:addch", &ch)) - goto exit; - break; - case 2: - if (!PyArg_ParseTuple(args, "Ol:addch", &ch, &attr)) - goto exit; - group_right_1 = 1; - break; - case 3: - if (!PyArg_ParseTuple(args, "iiO:addch", &y, &x, &ch)) - goto exit; - group_left_1 = 1; - break; - case 4: - if (!PyArg_ParseTuple(args, "iiOl:addch", &y, &x, &ch, &attr)) - goto exit; - group_right_1 = 1; - group_left_1 = 1; - break; - default: - PyErr_SetString(PyExc_TypeError, "curses.window.addch requires 1 to 4 arguments"); - goto exit; - } - return_value = curses_window_addch_impl(self, group_left_1, y, x, ch, group_right_1, attr); - -exit: - return return_value; -} - static PyObject * curses_window_addch_impl(PyCursesWindowObject *self, int group_left_1, int y, int x, PyObject *ch, int group_right_1, long attr) -/*[clinic end generated code: output=d4b97cc287010c54 input=5a41efb34a2de338]*/ +/*[clinic end generated code: output=9fa34a5d80151f1a input=5a41efb34a2de338]*/ { PyCursesWindowObject *cwself = (PyCursesWindowObject *)self; int coordinates_group = group_left_1; diff --git a/Modules/_datetimemodule.c b/Modules/_datetimemodule.c --- a/Modules/_datetimemodule.c +++ b/Modules/_datetimemodule.c @@ -26,6 +26,8 @@ [clinic start generated code]*/ /*[clinic end generated code: output=da39a3ee5e6b4b0d input=78142cb64b9e98bc]*/ +#include "clinic/_datetimemodule.c.h" + /* We require that C int be at least 32 bits, and use int virtually * everywhere. In just a few cases we use a temp long, where a Python * API returns a C long. In such cases, we have to ensure that the @@ -4133,43 +4135,9 @@ If no tz is specified, uses local timezone. [clinic start generated code]*/ -PyDoc_STRVAR(datetime_datetime_now__doc__, -"now($type, /, tz=None)\n" -"--\n" -"\n" -"Returns new datetime object representing current time local to tz.\n" -"\n" -" tz\n" -" Timezone object.\n" -"\n" -"If no tz is specified, uses local timezone."); - -#define DATETIME_DATETIME_NOW_METHODDEF \ - {"now", (PyCFunction)datetime_datetime_now, METH_VARARGS|METH_KEYWORDS|METH_CLASS, datetime_datetime_now__doc__}, - -static PyObject * -datetime_datetime_now_impl(PyTypeObject *type, PyObject *tz); - -static PyObject * -datetime_datetime_now(PyTypeObject *type, PyObject *args, PyObject *kwargs) -{ - PyObject *return_value = NULL; - static char *_keywords[] = {"tz", NULL}; - PyObject *tz = Py_None; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "|O:now", _keywords, - &tz)) - goto exit; - return_value = datetime_datetime_now_impl(type, tz); - -exit: - return return_value; -} - static PyObject * datetime_datetime_now_impl(PyTypeObject *type, PyObject *tz) -/*[clinic end generated code: output=583c5637e3c843fa input=80d09869c5267d00]*/ +/*[clinic end generated code: output=b3386e5345e2b47a input=80d09869c5267d00]*/ { PyObject *self; diff --git a/Modules/_dbmmodule.c b/Modules/_dbmmodule.c --- a/Modules/_dbmmodule.c +++ b/Modules/_dbmmodule.c @@ -40,6 +40,8 @@ DBM *di_dbm; } dbmobject; +#include "clinic/_dbmmodule.c.h" + static PyTypeObject Dbmtype; #define is_dbmobject(v) (Py_TYPE(v) == &Dbmtype) @@ -277,39 +279,9 @@ Return the value for key if present, otherwise default. [clinic start generated code]*/ -PyDoc_STRVAR(dbm_dbm_get__doc__, -"get($self, key, default=None, /)\n" -"--\n" -"\n" -"Return the value for key if present, otherwise default."); - -#define DBM_DBM_GET_METHODDEF \ - {"get", (PyCFunction)dbm_dbm_get, METH_VARARGS, dbm_dbm_get__doc__}, - -static PyObject * -dbm_dbm_get_impl(dbmobject *dp, const char *key, Py_ssize_clean_t key_length, PyObject *default_value); - -static PyObject * -dbm_dbm_get(dbmobject *dp, PyObject *args) -{ - PyObject *return_value = NULL; - const char *key; - Py_ssize_clean_t key_length; - PyObject *default_value = Py_None; - - if (!PyArg_ParseTuple(args, - "s#|O:get", - &key, &key_length, &default_value)) - goto exit; - return_value = dbm_dbm_get_impl(dp, key, key_length, default_value); - -exit: - return return_value; -} - static PyObject * dbm_dbm_get_impl(dbmobject *dp, const char *key, Py_ssize_clean_t key_length, PyObject *default_value) -/*[clinic end generated code: output=452ea11394e7e92d input=aecf5efd2f2b1a3b]*/ +/*[clinic end generated code: output=c2bdccaa734ad349 input=aecf5efd2f2b1a3b]*/ { datum dbm_key, val; @@ -449,47 +421,9 @@ [clinic start generated code]*/ -PyDoc_STRVAR(dbmopen__doc__, -"open($module, filename, flags=\'r\', mode=0o666, /)\n" -"--\n" -"\n" -"Return a database object.\n" -"\n" -" filename\n" -" The filename to open.\n" -" flags\n" -" How to open the file. \"r\" for reading, \"w\" for writing, etc.\n" -" mode\n" -" If creating a new file, the mode bits for the new file\n" -" (e.g. os.O_RDWR)."); - -#define DBMOPEN_METHODDEF \ - {"open", (PyCFunction)dbmopen, METH_VARARGS, dbmopen__doc__}, - -static PyObject * -dbmopen_impl(PyModuleDef *module, const char *filename, const char *flags, int mode); - -static PyObject * -dbmopen(PyModuleDef *module, PyObject *args) -{ - PyObject *return_value = NULL; - const char *filename; - const char *flags = "r"; - int mode = 438; - - if (!PyArg_ParseTuple(args, - "s|si:open", - &filename, &flags, &mode)) - goto exit; - return_value = dbmopen_impl(module, filename, flags, mode); - -exit: - return return_value; -} - static PyObject * dbmopen_impl(PyModuleDef *module, const char *filename, const char *flags, int mode) -/*[clinic end generated code: output=9a7b725f9c4dcec2 input=6499ab0fab1333ac]*/ +/*[clinic end generated code: output=8b618fe06b92bf86 input=6499ab0fab1333ac]*/ { int iflags; diff --git a/Modules/_lzmamodule.c b/Modules/_lzmamodule.c --- a/Modules/_lzmamodule.c +++ b/Modules/_lzmamodule.c @@ -478,12 +478,11 @@ /*[clinic input] -output preset file module _lzma class _lzma.LZMACompressor "Compressor *" "&Compressor_type" class _lzma.LZMADecompressor "Decompressor *" "&Decompressor_type" [clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=f17afc786525d6c2]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=2c14bbe05ff0c147]*/ #include "clinic/_lzmamodule.c.h" diff --git a/Modules/_opcode.c b/Modules/_opcode.c --- a/Modules/_opcode.c +++ b/Modules/_opcode.c @@ -6,6 +6,8 @@ [clinic start generated code]*/ /*[clinic end generated code: output=da39a3ee5e6b4b0d input=117442e66eb376e6]*/ +#include "clinic/_opcode.c.h" + /*[clinic input] _opcode.stack_effect -> int @@ -17,42 +19,9 @@ Compute the stack effect of the opcode. [clinic start generated code]*/ -PyDoc_STRVAR(_opcode_stack_effect__doc__, -"stack_effect($module, opcode, oparg=None, /)\n" -"--\n" -"\n" -"Compute the stack effect of the opcode."); - -#define _OPCODE_STACK_EFFECT_METHODDEF \ - {"stack_effect", (PyCFunction)_opcode_stack_effect, METH_VARARGS, _opcode_stack_effect__doc__}, - -static int -_opcode_stack_effect_impl(PyModuleDef *module, int opcode, PyObject *oparg); - -static PyObject * -_opcode_stack_effect(PyModuleDef *module, PyObject *args) -{ - PyObject *return_value = NULL; - int opcode; - PyObject *oparg = Py_None; - int _return_value; - - if (!PyArg_ParseTuple(args, - "i|O:stack_effect", - &opcode, &oparg)) - goto exit; - _return_value = _opcode_stack_effect_impl(module, opcode, oparg); - if ((_return_value == -1) && PyErr_Occurred()) - goto exit; - return_value = PyLong_FromLong((long)_return_value); - -exit: - return return_value; -} - static int _opcode_stack_effect_impl(PyModuleDef *module, int opcode, PyObject *oparg) -/*[clinic end generated code: output=9e1133f8d587bc67 input=2d0a9ee53c0418f5]*/ +/*[clinic end generated code: output=1fcafd5596c6b050 input=2d0a9ee53c0418f5]*/ { int effect; int oparg_int = 0; diff --git a/Modules/_pickle.c b/Modules/_pickle.c --- a/Modules/_pickle.c +++ b/Modules/_pickle.c @@ -5,14 +5,13 @@ "Optimized C implementation for the Python pickle module."); /*[clinic input] -output preset file module _pickle class _pickle.Pickler "PicklerObject *" "&Pickler_Type" class _pickle.PicklerMemoProxy "PicklerMemoProxyObject *" "&PicklerMemoProxyType" class _pickle.Unpickler "UnpicklerObject *" "&Unpickler_Type" class _pickle.UnpicklerMemoProxy "UnpicklerMemoProxyObject *" "&UnpicklerMemoProxyType" [clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=11c45248a41dd3fc]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=4b3e113468a58e6c]*/ /* Bump this when new opcodes are added to the pickle protocol. */ enum { diff --git a/Modules/_weakref.c b/Modules/_weakref.c --- a/Modules/_weakref.c +++ b/Modules/_weakref.c @@ -9,6 +9,8 @@ [clinic start generated code]*/ /*[clinic end generated code: output=da39a3ee5e6b4b0d input=ffec73b85846596d]*/ +#include "clinic/_weakref.c.h" + /*[clinic input] _weakref.getweakrefcount -> Py_ssize_t @@ -19,36 +21,9 @@ Return the number of weak references to 'object'. [clinic start generated code]*/ -PyDoc_STRVAR(_weakref_getweakrefcount__doc__, -"getweakrefcount($module, object, /)\n" -"--\n" -"\n" -"Return the number of weak references to \'object\'."); - -#define _WEAKREF_GETWEAKREFCOUNT_METHODDEF \ - {"getweakrefcount", (PyCFunction)_weakref_getweakrefcount, METH_O, _weakref_getweakrefcount__doc__}, - -static Py_ssize_t -_weakref_getweakrefcount_impl(PyModuleDef *module, PyObject *object); - -static PyObject * -_weakref_getweakrefcount(PyModuleDef *module, PyObject *object) -{ - PyObject *return_value = NULL; - Py_ssize_t _return_value; - - _return_value = _weakref_getweakrefcount_impl(module, object); - if ((_return_value == -1) && PyErr_Occurred()) - goto exit; - return_value = PyLong_FromSsize_t(_return_value); - -exit: - return return_value; -} - static Py_ssize_t _weakref_getweakrefcount_impl(PyModuleDef *module, PyObject *object) -/*[clinic end generated code: output=032eedbfd7d69e10 input=cedb69711b6a2507]*/ +/*[clinic end generated code: output=6a6ad0b98285e468 input=cedb69711b6a2507]*/ { PyWeakReference **list; diff --git a/Modules/arraymodule.c b/Modules/arraymodule.c --- a/Modules/arraymodule.c +++ b/Modules/arraymodule.c @@ -16,10 +16,9 @@ #endif /* !STDC_HEADERS */ /*[clinic input] -output preset file module array [clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=0909c1a148c69931]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=7d1b8d7f5958fd83]*/ struct arrayobject; /* Forward */ diff --git a/Modules/audioop.c b/Modules/audioop.c --- a/Modules/audioop.c +++ b/Modules/audioop.c @@ -391,10 +391,9 @@ } /*[clinic input] -output preset file module audioop [clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=5619f935f269199a]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=8fa8f6611be3591a]*/ /*[clinic input] audioop.getsample diff --git a/Modules/binascii.c b/Modules/binascii.c --- a/Modules/binascii.c +++ b/Modules/binascii.c @@ -184,10 +184,9 @@ }; /*[clinic input] -output preset file module binascii [clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=44c6f840ce708f0c]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=de89fb46bcaf3fec]*/ /*[python input] diff --git a/Modules/cjkcodecs/multibytecodec.c b/Modules/cjkcodecs/multibytecodec.c --- a/Modules/cjkcodecs/multibytecodec.c +++ b/Modules/cjkcodecs/multibytecodec.c @@ -11,15 +11,10 @@ #include "clinic/multibytecodec.c.h" /*[clinic input] -output preset file module _multibytecodec -[clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=e0cf1b7f3c472d17]*/ - -/*[clinic input] class _multibytecodec.MultibyteCodec "MultibyteCodecObject *" "&MultibyteCodec_Type" [clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=d5b1fc1fec8eb003]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=6ad689546cbb5450]*/ typedef struct { PyObject *inobj; diff --git a/Modules/_codecsmodule.c b/Modules/clinic/_codecsmodule.c.h copy from Modules/_codecsmodule.c copy to Modules/clinic/_codecsmodule.c.h --- a/Modules/_codecsmodule.c +++ b/Modules/clinic/_codecsmodule.c.h @@ -1,156 +1,5 @@ -/* ------------------------------------------------------------------------ - - _codecs -- Provides access to the codec registry and the builtin - codecs. - - This module should never be imported directly. The standard library - module "codecs" wraps this builtin module for use within Python. - - The codec registry is accessible via: - - register(search_function) -> None - - lookup(encoding) -> CodecInfo object - - The builtin Unicode codecs use the following interface: - - _encode(Unicode_object[,errors='strict']) -> - (string object, bytes consumed) - - _decode(char_buffer_obj[,errors='strict']) -> - (Unicode object, bytes consumed) - - _encode() interfaces also accept non-Unicode object as - input. The objects are then converted to Unicode using - PyUnicode_FromObject() prior to applying the conversion. - - These s are available: utf_8, unicode_escape, - raw_unicode_escape, unicode_internal, latin_1, ascii (7-bit), - mbcs (on win32). - - -Written by Marc-Andre Lemburg (mal at lemburg.com). - -Copyright (c) Corporation for National Research Initiatives. - - ------------------------------------------------------------------------ */ - -#define PY_SSIZE_T_CLEAN -#include "Python.h" - -#ifdef MS_WINDOWS -#include -#endif - /*[clinic input] -module _codecs -[clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=e1390e3da3cb9deb]*/ - - -/* --- Registry ----------------------------------------------------------- */ - -PyDoc_STRVAR(register__doc__, -"register(search_function)\n\ -\n\ -Register a codec search function. Search functions are expected to take\n\ -one argument, the encoding name in all lower case letters, and either\n\ -return None, or a tuple of functions (encoder, decoder, stream_reader,\n\ -stream_writer) (or a CodecInfo object)."); - -static -PyObject *codec_register(PyObject *self, PyObject *search_function) -{ - if (PyCodec_Register(search_function)) - return NULL; - - Py_RETURN_NONE; -} - -PyDoc_STRVAR(lookup__doc__, -"lookup(encoding) -> CodecInfo\n\ -\n\ -Looks up a codec tuple in the Python codec registry and returns\n\ -a CodecInfo object."); - -static -PyObject *codec_lookup(PyObject *self, PyObject *args) -{ - char *encoding; - - if (!PyArg_ParseTuple(args, "s:lookup", &encoding)) - return NULL; - - return _PyCodec_Lookup(encoding); -} - -PyDoc_STRVAR(encode__doc__, -"encode(obj, [encoding[,errors]]) -> object\n\ -\n\ -Encodes obj using the codec registered for encoding. encoding defaults\n\ -to the default encoding. errors may be given to set a different error\n\ -handling scheme. Default is 'strict' meaning that encoding errors raise\n\ -a ValueError. Other possible values are 'ignore', 'replace' and\n\ -'xmlcharrefreplace' as well as any other name registered with\n\ -codecs.register_error that can handle ValueErrors."); - -static PyObject * -codec_encode(PyObject *self, PyObject *args, PyObject *kwargs) -{ - static char *kwlist[] = {"obj", "encoding", "errors", NULL}; - const char *encoding = NULL; - const char *errors = NULL; - PyObject *v; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|ss:encode", kwlist, - &v, &encoding, &errors)) - return NULL; - - if (encoding == NULL) - encoding = PyUnicode_GetDefaultEncoding(); - - /* Encode via the codec registry */ - return PyCodec_Encode(v, encoding, errors); -} - -PyDoc_STRVAR(decode__doc__, -"decode(obj, [encoding[,errors]]) -> object\n\ -\n\ -Decodes obj using the codec registered for encoding. encoding defaults\n\ -to the default encoding. errors may be given to set a different error\n\ -handling scheme. Default is 'strict' meaning that encoding errors raise\n\ -a ValueError. Other possible values are 'ignore' and 'replace'\n\ -as well as any other name registered with codecs.register_error that is\n\ -able to handle ValueErrors."); - -static PyObject * -codec_decode(PyObject *self, PyObject *args, PyObject *kwargs) -{ - static char *kwlist[] = {"obj", "encoding", "errors", NULL}; - const char *encoding = NULL; - const char *errors = NULL; - PyObject *v; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|ss:decode", kwlist, - &v, &encoding, &errors)) - return NULL; - - if (encoding == NULL) - encoding = PyUnicode_GetDefaultEncoding(); - - /* Decode via the codec registry */ - return PyCodec_Decode(v, encoding, errors); -} - -/* --- Helpers ------------------------------------------------------------ */ - -/*[clinic input] -_codecs._forget_codec - - encoding: str - / - -Purge the named codec from the internal codec lookup cache +preserve [clinic start generated code]*/ PyDoc_STRVAR(_codecs__forget_codec__doc__, @@ -180,1078 +29,4 @@ exit: return return_value; } - -static PyObject * -_codecs__forget_codec_impl(PyModuleDef *module, const char *encoding) -/*[clinic end generated code: output=a75e631591702a5c input=18d5d92d0e386c38]*/ -{ - if (_PyCodec_Forget(encoding) < 0) { - return NULL; - }; - Py_RETURN_NONE; -} - -static -PyObject *codec_tuple(PyObject *unicode, - Py_ssize_t len) -{ - PyObject *v; - if (unicode == NULL) - return NULL; - v = Py_BuildValue("On", unicode, len); - Py_DECREF(unicode); - return v; -} - -/* --- String codecs ------------------------------------------------------ */ -static PyObject * -escape_decode(PyObject *self, - PyObject *args) -{ - Py_buffer pbuf; - const char *errors = NULL; - PyObject *result; - - if (!PyArg_ParseTuple(args, "s*|z:escape_decode", - &pbuf, &errors)) - return NULL; - result = codec_tuple( - PyBytes_DecodeEscape(pbuf.buf, pbuf.len, errors, 0, NULL), - pbuf.len); - PyBuffer_Release(&pbuf); - return result; -} - -static PyObject * -escape_encode(PyObject *self, - PyObject *args) -{ - PyObject *str; - Py_ssize_t size; - Py_ssize_t newsize; - const char *errors = NULL; - PyObject *v; - - if (!PyArg_ParseTuple(args, "O!|z:escape_encode", - &PyBytes_Type, &str, &errors)) - return NULL; - - size = PyBytes_GET_SIZE(str); - if (size > PY_SSIZE_T_MAX / 4) { - PyErr_SetString(PyExc_OverflowError, - "string is too large to encode"); - return NULL; - } - newsize = 4*size; - v = PyBytes_FromStringAndSize(NULL, newsize); - - if (v == NULL) { - return NULL; - } - else { - Py_ssize_t i; - char c; - char *p = PyBytes_AS_STRING(v); - - for (i = 0; i < size; i++) { - /* There's at least enough room for a hex escape */ - assert(newsize - (p - PyBytes_AS_STRING(v)) >= 4); - c = PyBytes_AS_STRING(str)[i]; - if (c == '\'' || c == '\\') - *p++ = '\\', *p++ = c; - else if (c == '\t') - *p++ = '\\', *p++ = 't'; - else if (c == '\n') - *p++ = '\\', *p++ = 'n'; - else if (c == '\r') - *p++ = '\\', *p++ = 'r'; - else if (c < ' ' || c >= 0x7f) { - *p++ = '\\'; - *p++ = 'x'; - *p++ = Py_hexdigits[(c & 0xf0) >> 4]; - *p++ = Py_hexdigits[c & 0xf]; - } - else - *p++ = c; - } - *p = '\0'; - if (_PyBytes_Resize(&v, (p - PyBytes_AS_STRING(v)))) { - return NULL; - } - } - - return codec_tuple(v, size); -} - -/* --- Decoder ------------------------------------------------------------ */ - -static PyObject * -unicode_internal_decode(PyObject *self, - PyObject *args) -{ - PyObject *obj; - const char *errors = NULL; - - if (!PyArg_ParseTuple(args, "O|z:unicode_internal_decode", - &obj, &errors)) - return NULL; - - if (PyUnicode_Check(obj)) { - if (PyUnicode_READY(obj) < 0) - return NULL; - Py_INCREF(obj); - return codec_tuple(obj, PyUnicode_GET_LENGTH(obj)); - } - else { - Py_buffer view; - PyObject *result; - if (PyObject_GetBuffer(obj, &view, PyBUF_SIMPLE) != 0) - return NULL; - - result = codec_tuple( - _PyUnicode_DecodeUnicodeInternal(view.buf, view.len, errors), - view.len); - PyBuffer_Release(&view); - return result; - } -} - -static PyObject * -utf_7_decode(PyObject *self, - PyObject *args) -{ - Py_buffer pbuf; - const char *errors = NULL; - int final = 0; - Py_ssize_t consumed; - PyObject *decoded = NULL; - - if (!PyArg_ParseTuple(args, "y*|zi:utf_7_decode", - &pbuf, &errors, &final)) - return NULL; - consumed = pbuf.len; - - decoded = PyUnicode_DecodeUTF7Stateful(pbuf.buf, pbuf.len, errors, - final ? NULL : &consumed); - PyBuffer_Release(&pbuf); - if (decoded == NULL) - return NULL; - return codec_tuple(decoded, consumed); -} - -static PyObject * -utf_8_decode(PyObject *self, - PyObject *args) -{ - Py_buffer pbuf; - const char *errors = NULL; - int final = 0; - Py_ssize_t consumed; - PyObject *decoded = NULL; - - if (!PyArg_ParseTuple(args, "y*|zi:utf_8_decode", - &pbuf, &errors, &final)) - return NULL; - consumed = pbuf.len; - - decoded = PyUnicode_DecodeUTF8Stateful(pbuf.buf, pbuf.len, errors, - final ? NULL : &consumed); - PyBuffer_Release(&pbuf); - if (decoded == NULL) - return NULL; - return codec_tuple(decoded, consumed); -} - -static PyObject * -utf_16_decode(PyObject *self, - PyObject *args) -{ - Py_buffer pbuf; - const char *errors = NULL; - int byteorder = 0; - int final = 0; - Py_ssize_t consumed; - PyObject *decoded; - - if (!PyArg_ParseTuple(args, "y*|zi:utf_16_decode", - &pbuf, &errors, &final)) - return NULL; - consumed = pbuf.len; /* This is overwritten unless final is true. */ - decoded = PyUnicode_DecodeUTF16Stateful(pbuf.buf, pbuf.len, errors, - &byteorder, final ? NULL : &consumed); - PyBuffer_Release(&pbuf); - if (decoded == NULL) - return NULL; - return codec_tuple(decoded, consumed); -} - -static PyObject * -utf_16_le_decode(PyObject *self, - PyObject *args) -{ - Py_buffer pbuf; - const char *errors = NULL; - int byteorder = -1; - int final = 0; - Py_ssize_t consumed; - PyObject *decoded = NULL; - - if (!PyArg_ParseTuple(args, "y*|zi:utf_16_le_decode", - &pbuf, &errors, &final)) - return NULL; - - consumed = pbuf.len; /* This is overwritten unless final is true. */ - decoded = PyUnicode_DecodeUTF16Stateful(pbuf.buf, pbuf.len, errors, - &byteorder, final ? NULL : &consumed); - PyBuffer_Release(&pbuf); - if (decoded == NULL) - return NULL; - return codec_tuple(decoded, consumed); -} - -static PyObject * -utf_16_be_decode(PyObject *self, - PyObject *args) -{ - Py_buffer pbuf; - const char *errors = NULL; - int byteorder = 1; - int final = 0; - Py_ssize_t consumed; - PyObject *decoded = NULL; - - if (!PyArg_ParseTuple(args, "y*|zi:utf_16_be_decode", - &pbuf, &errors, &final)) - return NULL; - - consumed = pbuf.len; /* This is overwritten unless final is true. */ - decoded = PyUnicode_DecodeUTF16Stateful(pbuf.buf, pbuf.len, errors, - &byteorder, final ? NULL : &consumed); - PyBuffer_Release(&pbuf); - if (decoded == NULL) - return NULL; - return codec_tuple(decoded, consumed); -} - -/* This non-standard version also provides access to the byteorder - parameter of the builtin UTF-16 codec. - - It returns a tuple (unicode, bytesread, byteorder) with byteorder - being the value in effect at the end of data. - -*/ - -static PyObject * -utf_16_ex_decode(PyObject *self, - PyObject *args) -{ - Py_buffer pbuf; - const char *errors = NULL; - int byteorder = 0; - PyObject *unicode, *tuple; - int final = 0; - Py_ssize_t consumed; - - if (!PyArg_ParseTuple(args, "y*|zii:utf_16_ex_decode", - &pbuf, &errors, &byteorder, &final)) - return NULL; - consumed = pbuf.len; /* This is overwritten unless final is true. */ - unicode = PyUnicode_DecodeUTF16Stateful(pbuf.buf, pbuf.len, errors, - &byteorder, final ? NULL : &consumed); - PyBuffer_Release(&pbuf); - if (unicode == NULL) - return NULL; - tuple = Py_BuildValue("Oni", unicode, consumed, byteorder); - Py_DECREF(unicode); - return tuple; -} - -static PyObject * -utf_32_decode(PyObject *self, - PyObject *args) -{ - Py_buffer pbuf; - const char *errors = NULL; - int byteorder = 0; - int final = 0; - Py_ssize_t consumed; - PyObject *decoded; - - if (!PyArg_ParseTuple(args, "y*|zi:utf_32_decode", - &pbuf, &errors, &final)) - return NULL; - consumed = pbuf.len; /* This is overwritten unless final is true. */ - decoded = PyUnicode_DecodeUTF32Stateful(pbuf.buf, pbuf.len, errors, - &byteorder, final ? NULL : &consumed); - PyBuffer_Release(&pbuf); - if (decoded == NULL) - return NULL; - return codec_tuple(decoded, consumed); -} - -static PyObject * -utf_32_le_decode(PyObject *self, - PyObject *args) -{ - Py_buffer pbuf; - const char *errors = NULL; - int byteorder = -1; - int final = 0; - Py_ssize_t consumed; - PyObject *decoded; - - if (!PyArg_ParseTuple(args, "y*|zi:utf_32_le_decode", - &pbuf, &errors, &final)) - return NULL; - consumed = pbuf.len; /* This is overwritten unless final is true. */ - decoded = PyUnicode_DecodeUTF32Stateful(pbuf.buf, pbuf.len, errors, - &byteorder, final ? NULL : &consumed); - PyBuffer_Release(&pbuf); - if (decoded == NULL) - return NULL; - return codec_tuple(decoded, consumed); -} - -static PyObject * -utf_32_be_decode(PyObject *self, - PyObject *args) -{ - Py_buffer pbuf; - const char *errors = NULL; - int byteorder = 1; - int final = 0; - Py_ssize_t consumed; - PyObject *decoded; - - if (!PyArg_ParseTuple(args, "y*|zi:utf_32_be_decode", - &pbuf, &errors, &final)) - return NULL; - consumed = pbuf.len; /* This is overwritten unless final is true. */ - decoded = PyUnicode_DecodeUTF32Stateful(pbuf.buf, pbuf.len, errors, - &byteorder, final ? NULL : &consumed); - PyBuffer_Release(&pbuf); - if (decoded == NULL) - return NULL; - return codec_tuple(decoded, consumed); -} - -/* This non-standard version also provides access to the byteorder - parameter of the builtin UTF-32 codec. - - It returns a tuple (unicode, bytesread, byteorder) with byteorder - being the value in effect at the end of data. - -*/ - -static PyObject * -utf_32_ex_decode(PyObject *self, - PyObject *args) -{ - Py_buffer pbuf; - const char *errors = NULL; - int byteorder = 0; - PyObject *unicode, *tuple; - int final = 0; - Py_ssize_t consumed; - - if (!PyArg_ParseTuple(args, "y*|zii:utf_32_ex_decode", - &pbuf, &errors, &byteorder, &final)) - return NULL; - consumed = pbuf.len; /* This is overwritten unless final is true. */ - unicode = PyUnicode_DecodeUTF32Stateful(pbuf.buf, pbuf.len, errors, - &byteorder, final ? NULL : &consumed); - PyBuffer_Release(&pbuf); - if (unicode == NULL) - return NULL; - tuple = Py_BuildValue("Oni", unicode, consumed, byteorder); - Py_DECREF(unicode); - return tuple; -} - -static PyObject * -unicode_escape_decode(PyObject *self, - PyObject *args) -{ - Py_buffer pbuf; - const char *errors = NULL; - PyObject *unicode; - - if (!PyArg_ParseTuple(args, "s*|z:unicode_escape_decode", - &pbuf, &errors)) - return NULL; - - unicode = PyUnicode_DecodeUnicodeEscape(pbuf.buf, pbuf.len, errors); - PyBuffer_Release(&pbuf); - return codec_tuple(unicode, pbuf.len); -} - -static PyObject * -raw_unicode_escape_decode(PyObject *self, - PyObject *args) -{ - Py_buffer pbuf; - const char *errors = NULL; - PyObject *unicode; - - if (!PyArg_ParseTuple(args, "s*|z:raw_unicode_escape_decode", - &pbuf, &errors)) - return NULL; - - unicode = PyUnicode_DecodeRawUnicodeEscape(pbuf.buf, pbuf.len, errors); - PyBuffer_Release(&pbuf); - return codec_tuple(unicode, pbuf.len); -} - -static PyObject * -latin_1_decode(PyObject *self, - PyObject *args) -{ - Py_buffer pbuf; - PyObject *unicode; - const char *errors = NULL; - - if (!PyArg_ParseTuple(args, "y*|z:latin_1_decode", - &pbuf, &errors)) - return NULL; - - unicode = PyUnicode_DecodeLatin1(pbuf.buf, pbuf.len, errors); - PyBuffer_Release(&pbuf); - return codec_tuple(unicode, pbuf.len); -} - -static PyObject * -ascii_decode(PyObject *self, - PyObject *args) -{ - Py_buffer pbuf; - PyObject *unicode; - const char *errors = NULL; - - if (!PyArg_ParseTuple(args, "y*|z:ascii_decode", - &pbuf, &errors)) - return NULL; - - unicode = PyUnicode_DecodeASCII(pbuf.buf, pbuf.len, errors); - PyBuffer_Release(&pbuf); - return codec_tuple(unicode, pbuf.len); -} - -static PyObject * -charmap_decode(PyObject *self, - PyObject *args) -{ - Py_buffer pbuf; - PyObject *unicode; - const char *errors = NULL; - PyObject *mapping = NULL; - - if (!PyArg_ParseTuple(args, "y*|zO:charmap_decode", - &pbuf, &errors, &mapping)) - return NULL; - if (mapping == Py_None) - mapping = NULL; - - unicode = PyUnicode_DecodeCharmap(pbuf.buf, pbuf.len, mapping, errors); - PyBuffer_Release(&pbuf); - return codec_tuple(unicode, pbuf.len); -} - -#ifdef HAVE_MBCS - -static PyObject * -mbcs_decode(PyObject *self, - PyObject *args) -{ - Py_buffer pbuf; - const char *errors = NULL; - int final = 0; - Py_ssize_t consumed; - PyObject *decoded = NULL; - - if (!PyArg_ParseTuple(args, "y*|zi:mbcs_decode", - &pbuf, &errors, &final)) - return NULL; - consumed = pbuf.len; - - decoded = PyUnicode_DecodeMBCSStateful(pbuf.buf, pbuf.len, errors, - final ? NULL : &consumed); - PyBuffer_Release(&pbuf); - if (decoded == NULL) - return NULL; - return codec_tuple(decoded, consumed); -} - -static PyObject * -code_page_decode(PyObject *self, - PyObject *args) -{ - Py_buffer pbuf; - const char *errors = NULL; - int final = 0; - Py_ssize_t consumed; - PyObject *decoded = NULL; - int code_page; - - if (!PyArg_ParseTuple(args, "iy*|zi:code_page_decode", - &code_page, &pbuf, &errors, &final)) - return NULL; - consumed = pbuf.len; - - decoded = PyUnicode_DecodeCodePageStateful(code_page, - pbuf.buf, pbuf.len, errors, - final ? NULL : &consumed); - PyBuffer_Release(&pbuf); - if (decoded == NULL) - return NULL; - return codec_tuple(decoded, consumed); -} - -#endif /* HAVE_MBCS */ - -/* --- Encoder ------------------------------------------------------------ */ - -static PyObject * -readbuffer_encode(PyObject *self, - PyObject *args) -{ - Py_buffer pdata; - const char *data; - Py_ssize_t size; - const char *errors = NULL; - PyObject *result; - - if (!PyArg_ParseTuple(args, "s*|z:readbuffer_encode", - &pdata, &errors)) - return NULL; - data = pdata.buf; - size = pdata.len; - - result = PyBytes_FromStringAndSize(data, size); - PyBuffer_Release(&pdata); - return codec_tuple(result, size); -} - -static PyObject * -unicode_internal_encode(PyObject *self, - PyObject *args) -{ - PyObject *obj; - const char *errors = NULL; - - if (PyErr_WarnEx(PyExc_DeprecationWarning, - "unicode_internal codec has been deprecated", - 1)) - return NULL; - - if (!PyArg_ParseTuple(args, "O|z:unicode_internal_encode", - &obj, &errors)) - return NULL; - - if (PyUnicode_Check(obj)) { - Py_UNICODE *u; - Py_ssize_t len, size; - - if (PyUnicode_READY(obj) < 0) - return NULL; - - u = PyUnicode_AsUnicodeAndSize(obj, &len); - if (u == NULL) - return NULL; - if ((size_t)len > (size_t)PY_SSIZE_T_MAX / sizeof(Py_UNICODE)) - return PyErr_NoMemory(); - size = len * sizeof(Py_UNICODE); - return codec_tuple(PyBytes_FromStringAndSize((const char*)u, size), - PyUnicode_GET_LENGTH(obj)); - } - else { - Py_buffer view; - PyObject *result; - if (PyObject_GetBuffer(obj, &view, PyBUF_SIMPLE) != 0) - return NULL; - result = codec_tuple(PyBytes_FromStringAndSize(view.buf, view.len), view.len); - PyBuffer_Release(&view); - return result; - } -} - -static PyObject * -utf_7_encode(PyObject *self, - PyObject *args) -{ - PyObject *str, *v; - const char *errors = NULL; - - if (!PyArg_ParseTuple(args, "O|z:utf_7_encode", - &str, &errors)) - return NULL; - - str = PyUnicode_FromObject(str); - if (str == NULL || PyUnicode_READY(str) < 0) { - Py_XDECREF(str); - return NULL; - } - v = codec_tuple(_PyUnicode_EncodeUTF7(str, 0, 0, errors), - PyUnicode_GET_LENGTH(str)); - Py_DECREF(str); - return v; -} - -static PyObject * -utf_8_encode(PyObject *self, - PyObject *args) -{ - PyObject *str, *v; - const char *errors = NULL; - - if (!PyArg_ParseTuple(args, "O|z:utf_8_encode", - &str, &errors)) - return NULL; - - str = PyUnicode_FromObject(str); - if (str == NULL || PyUnicode_READY(str) < 0) { - Py_XDECREF(str); - return NULL; - } - v = codec_tuple(PyUnicode_AsEncodedString(str, "utf-8", errors), - PyUnicode_GET_LENGTH(str)); - Py_DECREF(str); - return v; -} - -/* This version provides access to the byteorder parameter of the - builtin UTF-16 codecs as optional third argument. It defaults to 0 - which means: use the native byte order and prepend the data with a - BOM mark. - -*/ - -static PyObject * -utf_16_encode(PyObject *self, - PyObject *args) -{ - PyObject *str, *v; - const char *errors = NULL; - int byteorder = 0; - - if (!PyArg_ParseTuple(args, "O|zi:utf_16_encode", - &str, &errors, &byteorder)) - return NULL; - - str = PyUnicode_FromObject(str); - if (str == NULL || PyUnicode_READY(str) < 0) { - Py_XDECREF(str); - return NULL; - } - v = codec_tuple(_PyUnicode_EncodeUTF16(str, errors, byteorder), - PyUnicode_GET_LENGTH(str)); - Py_DECREF(str); - return v; -} - -static PyObject * -utf_16_le_encode(PyObject *self, - PyObject *args) -{ - PyObject *str, *v; - const char *errors = NULL; - - if (!PyArg_ParseTuple(args, "O|z:utf_16_le_encode", - &str, &errors)) - return NULL; - - str = PyUnicode_FromObject(str); - if (str == NULL || PyUnicode_READY(str) < 0) { - Py_XDECREF(str); - return NULL; - } - v = codec_tuple(_PyUnicode_EncodeUTF16(str, errors, -1), - PyUnicode_GET_LENGTH(str)); - Py_DECREF(str); - return v; -} - -static PyObject * -utf_16_be_encode(PyObject *self, - PyObject *args) -{ - PyObject *str, *v; - const char *errors = NULL; - - if (!PyArg_ParseTuple(args, "O|z:utf_16_be_encode", - &str, &errors)) - return NULL; - - str = PyUnicode_FromObject(str); - if (str == NULL || PyUnicode_READY(str) < 0) { - Py_XDECREF(str); - return NULL; - } - v = codec_tuple(_PyUnicode_EncodeUTF16(str, errors, +1), - PyUnicode_GET_LENGTH(str)); - Py_DECREF(str); - return v; -} - -/* This version provides access to the byteorder parameter of the - builtin UTF-32 codecs as optional third argument. It defaults to 0 - which means: use the native byte order and prepend the data with a - BOM mark. - -*/ - -static PyObject * -utf_32_encode(PyObject *self, - PyObject *args) -{ - PyObject *str, *v; - const char *errors = NULL; - int byteorder = 0; - - if (!PyArg_ParseTuple(args, "O|zi:utf_32_encode", - &str, &errors, &byteorder)) - return NULL; - - str = PyUnicode_FromObject(str); - if (str == NULL || PyUnicode_READY(str) < 0) { - Py_XDECREF(str); - return NULL; - } - v = codec_tuple(_PyUnicode_EncodeUTF32(str, errors, byteorder), - PyUnicode_GET_LENGTH(str)); - Py_DECREF(str); - return v; -} - -static PyObject * -utf_32_le_encode(PyObject *self, - PyObject *args) -{ - PyObject *str, *v; - const char *errors = NULL; - - if (!PyArg_ParseTuple(args, "O|z:utf_32_le_encode", - &str, &errors)) - return NULL; - - str = PyUnicode_FromObject(str); - if (str == NULL || PyUnicode_READY(str) < 0) { - Py_XDECREF(str); - return NULL; - } - v = codec_tuple(_PyUnicode_EncodeUTF32(str, errors, -1), - PyUnicode_GET_LENGTH(str)); - Py_DECREF(str); - return v; -} - -static PyObject * -utf_32_be_encode(PyObject *self, - PyObject *args) -{ - PyObject *str, *v; - const char *errors = NULL; - - if (!PyArg_ParseTuple(args, "O|z:utf_32_be_encode", - &str, &errors)) - return NULL; - - str = PyUnicode_FromObject(str); - if (str == NULL || PyUnicode_READY(str) < 0) { - Py_XDECREF(str); - return NULL; - } - v = codec_tuple(_PyUnicode_EncodeUTF32(str, errors, +1), - PyUnicode_GET_LENGTH(str)); - Py_DECREF(str); - return v; -} - -static PyObject * -unicode_escape_encode(PyObject *self, - PyObject *args) -{ - PyObject *str, *v; - const char *errors = NULL; - - if (!PyArg_ParseTuple(args, "O|z:unicode_escape_encode", - &str, &errors)) - return NULL; - - str = PyUnicode_FromObject(str); - if (str == NULL || PyUnicode_READY(str) < 0) { - Py_XDECREF(str); - return NULL; - } - v = codec_tuple(PyUnicode_AsUnicodeEscapeString(str), - PyUnicode_GET_LENGTH(str)); - Py_DECREF(str); - return v; -} - -static PyObject * -raw_unicode_escape_encode(PyObject *self, - PyObject *args) -{ - PyObject *str, *v; - const char *errors = NULL; - - if (!PyArg_ParseTuple(args, "O|z:raw_unicode_escape_encode", - &str, &errors)) - return NULL; - - str = PyUnicode_FromObject(str); - if (str == NULL || PyUnicode_READY(str) < 0) { - Py_XDECREF(str); - return NULL; - } - v = codec_tuple(PyUnicode_AsRawUnicodeEscapeString(str), - PyUnicode_GET_LENGTH(str)); - Py_DECREF(str); - return v; -} - -static PyObject * -latin_1_encode(PyObject *self, - PyObject *args) -{ - PyObject *str, *v; - const char *errors = NULL; - - if (!PyArg_ParseTuple(args, "O|z:latin_1_encode", - &str, &errors)) - return NULL; - - str = PyUnicode_FromObject(str); - if (str == NULL || PyUnicode_READY(str) < 0) { - Py_XDECREF(str); - return NULL; - } - v = codec_tuple(_PyUnicode_AsLatin1String(str, errors), - PyUnicode_GET_LENGTH(str)); - Py_DECREF(str); - return v; -} - -static PyObject * -ascii_encode(PyObject *self, - PyObject *args) -{ - PyObject *str, *v; - const char *errors = NULL; - - if (!PyArg_ParseTuple(args, "O|z:ascii_encode", - &str, &errors)) - return NULL; - - str = PyUnicode_FromObject(str); - if (str == NULL || PyUnicode_READY(str) < 0) { - Py_XDECREF(str); - return NULL; - } - v = codec_tuple(_PyUnicode_AsASCIIString(str, errors), - PyUnicode_GET_LENGTH(str)); - Py_DECREF(str); - return v; -} - -static PyObject * -charmap_encode(PyObject *self, - PyObject *args) -{ - PyObject *str, *v; - const char *errors = NULL; - PyObject *mapping = NULL; - - if (!PyArg_ParseTuple(args, "O|zO:charmap_encode", - &str, &errors, &mapping)) - return NULL; - if (mapping == Py_None) - mapping = NULL; - - str = PyUnicode_FromObject(str); - if (str == NULL || PyUnicode_READY(str) < 0) { - Py_XDECREF(str); - return NULL; - } - v = codec_tuple(_PyUnicode_EncodeCharmap(str, mapping, errors), - PyUnicode_GET_LENGTH(str)); - Py_DECREF(str); - return v; -} - -static PyObject* -charmap_build(PyObject *self, PyObject *args) -{ - PyObject *map; - if (!PyArg_ParseTuple(args, "U:charmap_build", &map)) - return NULL; - return PyUnicode_BuildEncodingMap(map); -} - -#ifdef HAVE_MBCS - -static PyObject * -mbcs_encode(PyObject *self, - PyObject *args) -{ - PyObject *str, *v; - const char *errors = NULL; - - if (!PyArg_ParseTuple(args, "O|z:mbcs_encode", - &str, &errors)) - return NULL; - - str = PyUnicode_FromObject(str); - if (str == NULL || PyUnicode_READY(str) < 0) { - Py_XDECREF(str); - return NULL; - } - v = codec_tuple(PyUnicode_EncodeCodePage(CP_ACP, str, errors), - PyUnicode_GET_LENGTH(str)); - Py_DECREF(str); - return v; -} - -static PyObject * -code_page_encode(PyObject *self, - PyObject *args) -{ - PyObject *str, *v; - const char *errors = NULL; - int code_page; - - if (!PyArg_ParseTuple(args, "iO|z:code_page_encode", - &code_page, &str, &errors)) - return NULL; - - str = PyUnicode_FromObject(str); - if (str == NULL || PyUnicode_READY(str) < 0) { - Py_XDECREF(str); - return NULL; - } - v = codec_tuple(PyUnicode_EncodeCodePage(code_page, - str, - errors), - PyUnicode_GET_LENGTH(str)); - Py_DECREF(str); - return v; -} - -#endif /* HAVE_MBCS */ - -/* --- Error handler registry --------------------------------------------- */ - -PyDoc_STRVAR(register_error__doc__, -"register_error(errors, handler)\n\ -\n\ -Register the specified error handler under the name\n\ -errors. handler must be a callable object, that\n\ -will be called with an exception instance containing\n\ -information about the location of the encoding/decoding\n\ -error and must return a (replacement, new position) tuple."); - -static PyObject *register_error(PyObject *self, PyObject *args) -{ - const char *name; - PyObject *handler; - - if (!PyArg_ParseTuple(args, "sO:register_error", - &name, &handler)) - return NULL; - if (PyCodec_RegisterError(name, handler)) - return NULL; - Py_RETURN_NONE; -} - -PyDoc_STRVAR(lookup_error__doc__, -"lookup_error(errors) -> handler\n\ -\n\ -Return the error handler for the specified error handling name\n\ -or raise a LookupError, if no handler exists under this name."); - -static PyObject *lookup_error(PyObject *self, PyObject *args) -{ - const char *name; - - if (!PyArg_ParseTuple(args, "s:lookup_error", - &name)) - return NULL; - return PyCodec_LookupError(name); -} - -/* --- Module API --------------------------------------------------------- */ - -static PyMethodDef _codecs_functions[] = { - {"register", codec_register, METH_O, - register__doc__}, - {"lookup", codec_lookup, METH_VARARGS, - lookup__doc__}, - {"encode", (PyCFunction)codec_encode, METH_VARARGS|METH_KEYWORDS, - encode__doc__}, - {"decode", (PyCFunction)codec_decode, METH_VARARGS|METH_KEYWORDS, - decode__doc__}, - {"escape_encode", escape_encode, METH_VARARGS}, - {"escape_decode", escape_decode, METH_VARARGS}, - {"utf_8_encode", utf_8_encode, METH_VARARGS}, - {"utf_8_decode", utf_8_decode, METH_VARARGS}, - {"utf_7_encode", utf_7_encode, METH_VARARGS}, - {"utf_7_decode", utf_7_decode, METH_VARARGS}, - {"utf_16_encode", utf_16_encode, METH_VARARGS}, - {"utf_16_le_encode", utf_16_le_encode, METH_VARARGS}, - {"utf_16_be_encode", utf_16_be_encode, METH_VARARGS}, - {"utf_16_decode", utf_16_decode, METH_VARARGS}, - {"utf_16_le_decode", utf_16_le_decode, METH_VARARGS}, - {"utf_16_be_decode", utf_16_be_decode, METH_VARARGS}, - {"utf_16_ex_decode", utf_16_ex_decode, METH_VARARGS}, - {"utf_32_encode", utf_32_encode, METH_VARARGS}, - {"utf_32_le_encode", utf_32_le_encode, METH_VARARGS}, - {"utf_32_be_encode", utf_32_be_encode, METH_VARARGS}, - {"utf_32_decode", utf_32_decode, METH_VARARGS}, - {"utf_32_le_decode", utf_32_le_decode, METH_VARARGS}, - {"utf_32_be_decode", utf_32_be_decode, METH_VARARGS}, - {"utf_32_ex_decode", utf_32_ex_decode, METH_VARARGS}, - {"unicode_escape_encode", unicode_escape_encode, METH_VARARGS}, - {"unicode_escape_decode", unicode_escape_decode, METH_VARARGS}, - {"unicode_internal_encode", unicode_internal_encode, METH_VARARGS}, - {"unicode_internal_decode", unicode_internal_decode, METH_VARARGS}, - {"raw_unicode_escape_encode", raw_unicode_escape_encode, METH_VARARGS}, - {"raw_unicode_escape_decode", raw_unicode_escape_decode, METH_VARARGS}, - {"latin_1_encode", latin_1_encode, METH_VARARGS}, - {"latin_1_decode", latin_1_decode, METH_VARARGS}, - {"ascii_encode", ascii_encode, METH_VARARGS}, - {"ascii_decode", ascii_decode, METH_VARARGS}, - {"charmap_encode", charmap_encode, METH_VARARGS}, - {"charmap_decode", charmap_decode, METH_VARARGS}, - {"charmap_build", charmap_build, METH_VARARGS}, - {"readbuffer_encode", readbuffer_encode, METH_VARARGS}, -#ifdef HAVE_MBCS - {"mbcs_encode", mbcs_encode, METH_VARARGS}, - {"mbcs_decode", mbcs_decode, METH_VARARGS}, - {"code_page_encode", code_page_encode, METH_VARARGS}, - {"code_page_decode", code_page_decode, METH_VARARGS}, -#endif - {"register_error", register_error, METH_VARARGS, - register_error__doc__}, - {"lookup_error", lookup_error, METH_VARARGS, - lookup_error__doc__}, - _CODECS__FORGET_CODEC_METHODDEF - {NULL, NULL} /* sentinel */ -}; - -static struct PyModuleDef codecsmodule = { - PyModuleDef_HEAD_INIT, - "_codecs", - NULL, - -1, - _codecs_functions, - NULL, - NULL, - NULL, - NULL -}; - -PyMODINIT_FUNC -PyInit__codecs(void) -{ - return PyModule_Create(&codecsmodule); -} +/*[clinic end generated code: output=cdea83e21d76a900 input=a9049054013a1b77]*/ diff --git a/Modules/_cryptmodule.c b/Modules/clinic/_cryptmodule.c.h copy from Modules/_cryptmodule.c copy to Modules/clinic/_cryptmodule.c.h --- a/Modules/_cryptmodule.c +++ b/Modules/clinic/_cryptmodule.c.h @@ -1,32 +1,5 @@ -/* cryptmodule.c - by Steve Majewski - */ - -#include "Python.h" - -#include - -/* Module crypt */ - /*[clinic input] -module crypt -[clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=c6252cf4f2f2ae81]*/ - - -/*[clinic input] -crypt.crypt - - word: 's' - salt: 's' - / - -Hash a *word* with the given *salt* and return the hashed password. - -*word* will usually be a user's password. *salt* (either a random 2 or 16 -character string, possibly prefixed with $digit$ to indicate the method) -will be used to perturb the encryption algorithm and produce distinct -results for a given *word*. - +preserve [clinic start generated code]*/ PyDoc_STRVAR(crypt_crypt__doc__, @@ -62,37 +35,4 @@ exit: return return_value; } - -static PyObject * -crypt_crypt_impl(PyModuleDef *module, const char *word, const char *salt) -/*[clinic end generated code: output=3eaacdf994a6ff23 input=4d93b6d0f41fbf58]*/ -{ - /* On some platforms (AtheOS) crypt returns NULL for an invalid - salt. Return None in that case. XXX Maybe raise an exception? */ - return Py_BuildValue("s", crypt(word, salt)); -} - - -static PyMethodDef crypt_methods[] = { - CRYPT_CRYPT_METHODDEF - {NULL, NULL} /* sentinel */ -}; - - -static struct PyModuleDef cryptmodule = { - PyModuleDef_HEAD_INIT, - "_crypt", - NULL, - -1, - crypt_methods, - NULL, - NULL, - NULL, - NULL -}; - -PyMODINIT_FUNC -PyInit__crypt(void) -{ - return PyModule_Create(&cryptmodule); -} +/*[clinic end generated code: output=b5b8d977189d19ea input=a9049054013a1b77]*/ diff --git a/Modules/_cursesmodule.c b/Modules/clinic/_cursesmodule.c.h copy from Modules/_cursesmodule.c copy to Modules/clinic/_cursesmodule.c.h --- a/Modules/_cursesmodule.c +++ b/Modules/clinic/_cursesmodule.c.h @@ -1,586 +1,5 @@ -/* - * This is a curses module for Python. - * - * Based on prior work by Lance Ellinghaus and Oliver Andrich - * Version 1.2 of this module: Copyright 1994 by Lance Ellinghouse, - * Cathedral City, California Republic, United States of America. - * - * Version 1.5b1, heavily extended for ncurses by Oliver Andrich: - * Copyright 1996,1997 by Oliver Andrich, Koblenz, Germany. - * - * Tidied for Python 1.6, and currently maintained by . - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this source file to use, copy, modify, merge, or publish it - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or in any new file that contains a substantial portion of - * this file. - * - * THE AUTHOR MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF - * THE SOFTWARE FOR ANY PURPOSE. IT IS PROVIDED "AS IS" WITHOUT - * EXPRESS OR IMPLIED WARRANTY. THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NON-INFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE - * AUTHOR BE LIABLE TO YOU OR ANY OTHER PARTY FOR ANY SPECIAL, - * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER - * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE, STRICT LIABILITY OR - * ANY OTHER ACTION ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ - -/* - - A number of SysV or ncurses functions don't have wrappers yet; if you - need a given function, add it and send a patch. See - http://www.python.org/dev/patches/ for instructions on how to submit - patches to Python. - - Here's a list of currently unsupported functions: - - addchnstr addchstr color_set define_key - del_curterm delscreen dupwin inchnstr inchstr innstr keyok - mcprint mvaddchnstr mvaddchstr mvcur mvinchnstr - mvinchstr mvinnstr mmvwaddchnstr mvwaddchstr - mvwinchnstr mvwinchstr mvwinnstr newterm - restartterm ripoffline scr_dump - scr_init scr_restore scr_set scrl set_curterm set_term setterm - tgetent tgetflag tgetnum tgetstr tgoto timeout tputs - vidattr vidputs waddchnstr waddchstr - wcolor_set winchnstr winchstr winnstr wmouse_trafo wscrl - - Low-priority: - slk_attr slk_attr_off slk_attr_on slk_attr_set slk_attroff - slk_attron slk_attrset slk_clear slk_color slk_init slk_label - slk_noutrefresh slk_refresh slk_restore slk_set slk_touch - - Menu extension (ncurses and probably SYSV): - current_item free_item free_menu item_count item_description - item_index item_init item_name item_opts item_opts_off - item_opts_on item_term item_userptr item_value item_visible - menu_back menu_driver menu_fore menu_format menu_grey - menu_init menu_items menu_mark menu_opts menu_opts_off - menu_opts_on menu_pad menu_pattern menu_request_by_name - menu_request_name menu_spacing menu_sub menu_term menu_userptr - menu_win new_item new_menu pos_menu_cursor post_menu - scale_menu set_current_item set_item_init set_item_opts - set_item_term set_item_userptr set_item_value set_menu_back - set_menu_fore set_menu_format set_menu_grey set_menu_init - set_menu_items set_menu_mark set_menu_opts set_menu_pad - set_menu_pattern set_menu_spacing set_menu_sub set_menu_term - set_menu_userptr set_menu_win set_top_row top_row unpost_menu - - Form extension (ncurses and probably SYSV): - current_field data_ahead data_behind dup_field - dynamic_fieldinfo field_arg field_back field_buffer - field_count field_fore field_index field_info field_init - field_just field_opts field_opts_off field_opts_on field_pad - field_status field_term field_type field_userptr form_driver - form_fields form_init form_opts form_opts_off form_opts_on - form_page form_request_by_name form_request_name form_sub - form_term form_userptr form_win free_field free_form - link_field link_fieldtype move_field new_field new_form - new_page pos_form_cursor post_form scale_form - set_current_field set_field_back set_field_buffer - set_field_fore set_field_init set_field_just set_field_opts - set_field_pad set_field_status set_field_term set_field_type - set_field_userptr set_fieldtype_arg set_fieldtype_choice - set_form_fields set_form_init set_form_opts set_form_page - set_form_sub set_form_term set_form_userptr set_form_win - set_max_field set_new_page unpost_form - - -*/ - -/* Release Number */ - -char *PyCursesVersion = "2.2"; - -/* Includes */ - -#define PY_SSIZE_T_CLEAN - -#include "Python.h" - - -#ifdef __hpux -#define STRICT_SYSV_CURSES -#endif - -#define CURSES_MODULE -#include "py_curses.h" - -/* These prototypes are in , but including this header - #defines many common symbols (such as "lines") which breaks the - curses module in other ways. So the code will just specify - explicit prototypes here. */ -extern int setupterm(char *,int,int *); -#ifdef __sgi -#include -#endif - -#ifdef HAVE_LANGINFO_H -#include -#endif - -#if !defined(HAVE_NCURSES_H) && (defined(sgi) || defined(__sun) || defined(SCO5)) -#define STRICT_SYSV_CURSES /* Don't use ncurses extensions */ -typedef chtype attr_t; /* No attr_t type is available */ -#endif - -#if defined(_AIX) -#define STRICT_SYSV_CURSES -#endif - /*[clinic input] -module curses -class curses.window "PyCursesWindowObject *" "&PyCursesWindow_Type" -[clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=88c860abdbb50e0c]*/ - -/* Definition of exception curses.error */ - -static PyObject *PyCursesError; - -/* Tells whether setupterm() has been called to initialise terminfo. */ -static int initialised_setupterm = FALSE; - -/* Tells whether initscr() has been called to initialise curses. */ -static int initialised = FALSE; - -/* Tells whether start_color() has been called to initialise color usage. */ -static int initialisedcolors = FALSE; - -static char *screen_encoding = NULL; - -/* Utility Macros */ -#define PyCursesSetupTermCalled \ - if (initialised_setupterm != TRUE) { \ - PyErr_SetString(PyCursesError, \ - "must call (at least) setupterm() first"); \ - return 0; } - -#define PyCursesInitialised \ - if (initialised != TRUE) { \ - PyErr_SetString(PyCursesError, \ - "must call initscr() first"); \ - return 0; } - -#define PyCursesInitialisedColor \ - if (initialisedcolors != TRUE) { \ - PyErr_SetString(PyCursesError, \ - "must call start_color() first"); \ - return 0; } - -/* Utility Functions */ - -/* - * Check the return code from a curses function and return None - * or raise an exception as appropriate. These are exported using the - * capsule API. - */ - -static PyObject * -PyCursesCheckERR(int code, const char *fname) -{ - if (code != ERR) { - Py_INCREF(Py_None); - return Py_None; - } else { - if (fname == NULL) { - PyErr_SetString(PyCursesError, catchall_ERR); - } else { - PyErr_Format(PyCursesError, "%s() returned ERR", fname); - } - return NULL; - } -} - -/* Convert an object to a byte (an integer of type chtype): - - - int - - bytes of length 1 - - str of length 1 - - Return 1 on success, 0 on error (invalid type or integer overflow). */ -static int -PyCurses_ConvertToChtype(PyCursesWindowObject *win, PyObject *obj, chtype *ch) -{ - long value; - if(PyBytes_Check(obj) && PyBytes_Size(obj) == 1) { - value = (unsigned char)PyBytes_AsString(obj)[0]; - } - else if (PyUnicode_Check(obj)) { - if (PyUnicode_GetLength(obj) != 1) { - PyErr_Format(PyExc_TypeError, - "expect bytes or str of length 1, or int, " - "got a str of length %zi", - PyUnicode_GET_LENGTH(obj)); - return 0; - } - value = PyUnicode_READ_CHAR(obj, 0); - if (128 < value) { - PyObject *bytes; - const char *encoding; - if (win) - encoding = win->encoding; - else - encoding = screen_encoding; - bytes = PyUnicode_AsEncodedObject(obj, encoding, NULL); - if (bytes == NULL) - return 0; - if (PyBytes_GET_SIZE(bytes) == 1) - value = (unsigned char)PyBytes_AS_STRING(bytes)[0]; - else - value = -1; - Py_DECREF(bytes); - if (value < 0) - goto overflow; - } - } - else if (PyLong_CheckExact(obj)) { - int long_overflow; - value = PyLong_AsLongAndOverflow(obj, &long_overflow); - if (long_overflow) - goto overflow; - } - else { - PyErr_Format(PyExc_TypeError, - "expect bytes or str of length 1, or int, got %s", - Py_TYPE(obj)->tp_name); - return 0; - } - *ch = (chtype)value; - if ((long)*ch != value) - goto overflow; - return 1; - -overflow: - PyErr_SetString(PyExc_OverflowError, - "byte doesn't fit in chtype"); - return 0; -} - -/* Convert an object to a byte (chtype) or a character (cchar_t): - - - int - - bytes of length 1 - - str of length 1 - - Return: - - - 2 if obj is a character (written into *wch) - - 1 if obj is a byte (written into *ch) - - 0 on error: raise an exception */ -static int -PyCurses_ConvertToCchar_t(PyCursesWindowObject *win, PyObject *obj, - chtype *ch -#ifdef HAVE_NCURSESW - , cchar_t *wch -#endif - ) -{ - long value; -#ifdef HAVE_NCURSESW - wchar_t buffer[2]; -#endif - - if (PyUnicode_Check(obj)) { -#ifdef HAVE_NCURSESW - if (PyUnicode_AsWideChar(obj, buffer, 2) != 1) { - PyErr_Format(PyExc_TypeError, - "expect bytes or str of length 1, or int, " - "got a str of length %zi", - PyUnicode_GET_LENGTH(obj)); - return 0; - } - memset(wch->chars, 0, sizeof(wch->chars)); - wch->chars[0] = buffer[0]; - return 2; -#else - return PyCurses_ConvertToChtype(win, obj, ch); -#endif - } - else if(PyBytes_Check(obj) && PyBytes_Size(obj) == 1) { - value = (unsigned char)PyBytes_AsString(obj)[0]; - } - else if (PyLong_CheckExact(obj)) { - int overflow; - value = PyLong_AsLongAndOverflow(obj, &overflow); - if (overflow) { - PyErr_SetString(PyExc_OverflowError, - "int doesn't fit in long"); - return 0; - } - } - else { - PyErr_Format(PyExc_TypeError, - "expect bytes or str of length 1, or int, got %s", - Py_TYPE(obj)->tp_name); - return 0; - } - - *ch = (chtype)value; - if ((long)*ch != value) { - PyErr_Format(PyExc_OverflowError, - "byte doesn't fit in chtype"); - return 0; - } - return 1; -} - -/* Convert an object to a byte string (char*) or a wide character string - (wchar_t*). Return: - - - 2 if obj is a character string (written into *wch) - - 1 if obj is a byte string (written into *bytes) - - 0 on error: raise an exception */ -static int -PyCurses_ConvertToString(PyCursesWindowObject *win, PyObject *obj, - PyObject **bytes, wchar_t **wstr) -{ - if (PyUnicode_Check(obj)) { -#ifdef HAVE_NCURSESW - assert (wstr != NULL); - *wstr = PyUnicode_AsWideCharString(obj, NULL); - if (*wstr == NULL) - return 0; - return 2; -#else - assert (wstr == NULL); - *bytes = PyUnicode_AsEncodedObject(obj, win->encoding, NULL); - if (*bytes == NULL) - return 0; - return 1; -#endif - } - else if (PyBytes_Check(obj)) { - Py_INCREF(obj); - *bytes = obj; - return 1; - } - - PyErr_Format(PyExc_TypeError, "expect bytes or str, got %s", - Py_TYPE(obj)->tp_name); - return 0; -} - -/* Function versions of the 3 functions for testing whether curses has been - initialised or not. */ - -static int func_PyCursesSetupTermCalled(void) -{ - PyCursesSetupTermCalled; - return 1; -} - -static int func_PyCursesInitialised(void) -{ - PyCursesInitialised; - return 1; -} - -static int func_PyCursesInitialisedColor(void) -{ - PyCursesInitialisedColor; - return 1; -} - -/***************************************************************************** - The Window Object -******************************************************************************/ - -/* Definition of the window type */ - -PyTypeObject PyCursesWindow_Type; - -/* Function prototype macros for Window object - - X - function name - TYPE - parameter Type - ERGSTR - format string for construction of the return value - PARSESTR - format string for argument parsing -*/ - -#define Window_NoArgNoReturnFunction(X) \ - static PyObject *PyCursesWindow_ ## X \ - (PyCursesWindowObject *self, PyObject *args) \ - { return PyCursesCheckERR(X(self->win), # X); } - -#define Window_NoArgTrueFalseFunction(X) \ - static PyObject * PyCursesWindow_ ## X \ - (PyCursesWindowObject *self) \ - { \ - if (X (self->win) == FALSE) { Py_INCREF(Py_False); return Py_False; } \ - else { Py_INCREF(Py_True); return Py_True; } } - -#define Window_NoArgNoReturnVoidFunction(X) \ - static PyObject * PyCursesWindow_ ## X \ - (PyCursesWindowObject *self) \ - { \ - X(self->win); Py_INCREF(Py_None); return Py_None; } - -#define Window_NoArg2TupleReturnFunction(X, TYPE, ERGSTR) \ - static PyObject * PyCursesWindow_ ## X \ - (PyCursesWindowObject *self) \ - { \ - TYPE arg1, arg2; \ - X(self->win,arg1,arg2); return Py_BuildValue(ERGSTR, arg1, arg2); } - -#define Window_OneArgNoReturnVoidFunction(X, TYPE, PARSESTR) \ - static PyObject * PyCursesWindow_ ## X \ - (PyCursesWindowObject *self, PyObject *args) \ - { \ - TYPE arg1; \ - if (!PyArg_ParseTuple(args, PARSESTR, &arg1)) return NULL; \ - X(self->win,arg1); Py_INCREF(Py_None); return Py_None; } - -#define Window_OneArgNoReturnFunction(X, TYPE, PARSESTR) \ - static PyObject * PyCursesWindow_ ## X \ - (PyCursesWindowObject *self, PyObject *args) \ - { \ - TYPE arg1; \ - if (!PyArg_ParseTuple(args,PARSESTR, &arg1)) return NULL; \ - return PyCursesCheckERR(X(self->win, arg1), # X); } - -#define Window_TwoArgNoReturnFunction(X, TYPE, PARSESTR) \ - static PyObject * PyCursesWindow_ ## X \ - (PyCursesWindowObject *self, PyObject *args) \ - { \ - TYPE arg1, arg2; \ - if (!PyArg_ParseTuple(args,PARSESTR, &arg1, &arg2)) return NULL; \ - return PyCursesCheckERR(X(self->win, arg1, arg2), # X); } - -/* ------------- WINDOW routines --------------- */ - -Window_NoArgNoReturnFunction(untouchwin) -Window_NoArgNoReturnFunction(touchwin) -Window_NoArgNoReturnFunction(redrawwin) -Window_NoArgNoReturnFunction(winsertln) -Window_NoArgNoReturnFunction(werase) -Window_NoArgNoReturnFunction(wdeleteln) - -Window_NoArgTrueFalseFunction(is_wintouched) - -Window_NoArgNoReturnVoidFunction(wsyncup) -Window_NoArgNoReturnVoidFunction(wsyncdown) -Window_NoArgNoReturnVoidFunction(wstandend) -Window_NoArgNoReturnVoidFunction(wstandout) -Window_NoArgNoReturnVoidFunction(wcursyncup) -Window_NoArgNoReturnVoidFunction(wclrtoeol) -Window_NoArgNoReturnVoidFunction(wclrtobot) -Window_NoArgNoReturnVoidFunction(wclear) - -Window_OneArgNoReturnVoidFunction(idcok, int, "i;True(1) or False(0)") -Window_OneArgNoReturnVoidFunction(immedok, int, "i;True(1) or False(0)") -Window_OneArgNoReturnVoidFunction(wtimeout, int, "i;delay") - -Window_NoArg2TupleReturnFunction(getyx, int, "ii") -Window_NoArg2TupleReturnFunction(getbegyx, int, "ii") -Window_NoArg2TupleReturnFunction(getmaxyx, int, "ii") -Window_NoArg2TupleReturnFunction(getparyx, int, "ii") - -Window_OneArgNoReturnFunction(clearok, int, "i;True(1) or False(0)") -Window_OneArgNoReturnFunction(idlok, int, "i;True(1) or False(0)") -#if defined(__NetBSD__) -Window_OneArgNoReturnVoidFunction(keypad, int, "i;True(1) or False(0)") -#else -Window_OneArgNoReturnFunction(keypad, int, "i;True(1) or False(0)") -#endif -Window_OneArgNoReturnFunction(leaveok, int, "i;True(1) or False(0)") -#if defined(__NetBSD__) -Window_OneArgNoReturnVoidFunction(nodelay, int, "i;True(1) or False(0)") -#else -Window_OneArgNoReturnFunction(nodelay, int, "i;True(1) or False(0)") -#endif -Window_OneArgNoReturnFunction(notimeout, int, "i;True(1) or False(0)") -Window_OneArgNoReturnFunction(scrollok, int, "i;True(1) or False(0)") -Window_OneArgNoReturnFunction(winsdelln, int, "i;nlines") -Window_OneArgNoReturnFunction(syncok, int, "i;True(1) or False(0)") - -Window_TwoArgNoReturnFunction(mvwin, int, "ii;y,x") -Window_TwoArgNoReturnFunction(mvderwin, int, "ii;y,x") -Window_TwoArgNoReturnFunction(wmove, int, "ii;y,x") -#ifndef STRICT_SYSV_CURSES -Window_TwoArgNoReturnFunction(wresize, int, "ii;lines,columns") -#endif - -/* Allocation and deallocation of Window Objects */ - -static PyObject * -PyCursesWindow_New(WINDOW *win, const char *encoding) -{ - PyCursesWindowObject *wo; - - if (encoding == NULL) { -#if defined(MS_WINDOWS) - char *buffer[100]; - UINT cp; - cp = GetConsoleOutputCP(); - if (cp != 0) { - PyOS_snprintf(buffer, sizeof(buffer), "cp%u", cp); - encoding = buffer; - } -#elif defined(CODESET) - const char *codeset = nl_langinfo(CODESET); - if (codeset != NULL && codeset[0] != 0) - encoding = codeset; -#endif - if (encoding == NULL) - encoding = "utf-8"; - } - - wo = PyObject_NEW(PyCursesWindowObject, &PyCursesWindow_Type); - if (wo == NULL) return NULL; - wo->win = win; - wo->encoding = _PyMem_Strdup(encoding); - if (wo->encoding == NULL) { - Py_DECREF(wo); - PyErr_NoMemory(); - return NULL; - } - return (PyObject *)wo; -} - -static void -PyCursesWindow_Dealloc(PyCursesWindowObject *wo) -{ - if (wo->win != stdscr) delwin(wo->win); - if (wo->encoding != NULL) - PyMem_Free(wo->encoding); - PyObject_DEL(wo); -} - -/* Addch, Addstr, Addnstr */ - -/*[clinic input] - -curses.window.addch - - [ - y: int - Y-coordinate. - x: int - X-coordinate. - ] - - ch: object - Character to add. - - [ - attr: long - Attributes for the character. - ] - / - -Paint character ch at (y, x) with attributes attr. - -Paint character ch at (y, x) with attributes attr, -overwriting any character previously painted at that location. -By default, the character position and attributes are the -current settings for the window object. +preserve [clinic start generated code]*/ PyDoc_STRVAR(curses_window_addch__doc__, @@ -648,2875 +67,4 @@ exit: return return_value; } - -static PyObject * -curses_window_addch_impl(PyCursesWindowObject *self, int group_left_1, int y, int x, PyObject *ch, int group_right_1, long attr) -/*[clinic end generated code: output=d4b97cc287010c54 input=5a41efb34a2de338]*/ -{ - PyCursesWindowObject *cwself = (PyCursesWindowObject *)self; - int coordinates_group = group_left_1; - int attr_group = group_right_1; - int rtn; - int type; - chtype cch; -#ifdef HAVE_NCURSESW - cchar_t wch; -#endif - const char *funcname; - - if (!attr_group) - attr = A_NORMAL; - -#ifdef HAVE_NCURSESW - type = PyCurses_ConvertToCchar_t(cwself, ch, &cch, &wch); - if (type == 2) { - funcname = "add_wch"; - wch.attr = attr; - if (coordinates_group) - rtn = mvwadd_wch(cwself->win,y,x, &wch); - else { - rtn = wadd_wch(cwself->win, &wch); - } - } - else -#else - type = PyCurses_ConvertToCchar_t(cwself, ch, &cch); -#endif - if (type == 1) { - funcname = "addch"; - if (coordinates_group) - rtn = mvwaddch(cwself->win,y,x, cch | attr); - else { - rtn = waddch(cwself->win, cch | attr); - } - } - else { - return NULL; - } - return PyCursesCheckERR(rtn, funcname); -} - -static PyObject * -PyCursesWindow_AddStr(PyCursesWindowObject *self, PyObject *args) -{ - int rtn; - int x, y; - int strtype; - PyObject *strobj, *bytesobj = NULL; -#ifdef HAVE_NCURSESW - wchar_t *wstr = NULL; -#endif - attr_t attr = A_NORMAL , attr_old = A_NORMAL; - long lattr; - int use_xy = FALSE, use_attr = FALSE; - const char *funcname; - - switch (PyTuple_Size(args)) { - case 1: - if (!PyArg_ParseTuple(args,"O;str", &strobj)) - return NULL; - break; - case 2: - if (!PyArg_ParseTuple(args,"Ol;str,attr", &strobj, &lattr)) - return NULL; - attr = lattr; - use_attr = TRUE; - break; - case 3: - if (!PyArg_ParseTuple(args,"iiO;int,int,str", &y, &x, &strobj)) - return NULL; - use_xy = TRUE; - break; - case 4: - if (!PyArg_ParseTuple(args,"iiOl;int,int,str,attr", &y, &x, &strobj, &lattr)) - return NULL; - attr = lattr; - use_xy = use_attr = TRUE; - break; - default: - PyErr_SetString(PyExc_TypeError, "addstr requires 1 to 4 arguments"); - return NULL; - } -#ifdef HAVE_NCURSESW - strtype = PyCurses_ConvertToString(self, strobj, &bytesobj, &wstr); -#else - strtype = PyCurses_ConvertToString(self, strobj, &bytesobj, NULL); -#endif - if (strtype == 0) - return NULL; - if (use_attr == TRUE) { - attr_old = getattrs(self->win); - (void)wattrset(self->win,attr); - } -#ifdef HAVE_NCURSESW - if (strtype == 2) { - funcname = "addwstr"; - if (use_xy == TRUE) - rtn = mvwaddwstr(self->win,y,x,wstr); - else - rtn = waddwstr(self->win,wstr); - PyMem_Free(wstr); - } - else -#endif - { - char *str = PyBytes_AS_STRING(bytesobj); - funcname = "addstr"; - if (use_xy == TRUE) - rtn = mvwaddstr(self->win,y,x,str); - else - rtn = waddstr(self->win,str); - Py_DECREF(bytesobj); - } - if (use_attr == TRUE) - (void)wattrset(self->win,attr_old); - return PyCursesCheckERR(rtn, funcname); -} - -static PyObject * -PyCursesWindow_AddNStr(PyCursesWindowObject *self, PyObject *args) -{ - int rtn, x, y, n; - int strtype; - PyObject *strobj, *bytesobj = NULL; -#ifdef HAVE_NCURSESW - wchar_t *wstr = NULL; -#endif - attr_t attr = A_NORMAL , attr_old = A_NORMAL; - long lattr; - int use_xy = FALSE, use_attr = FALSE; - const char *funcname; - - switch (PyTuple_Size(args)) { - case 2: - if (!PyArg_ParseTuple(args,"Oi;str,n", &strobj, &n)) - return NULL; - break; - case 3: - if (!PyArg_ParseTuple(args,"Oil;str,n,attr", &strobj, &n, &lattr)) - return NULL; - attr = lattr; - use_attr = TRUE; - break; - case 4: - if (!PyArg_ParseTuple(args,"iiOi;y,x,str,n", &y, &x, &strobj, &n)) - return NULL; - use_xy = TRUE; - break; - case 5: - if (!PyArg_ParseTuple(args,"iiOil;y,x,str,n,attr", &y, &x, &strobj, &n, &lattr)) - return NULL; - attr = lattr; - use_xy = use_attr = TRUE; - break; - default: - PyErr_SetString(PyExc_TypeError, "addnstr requires 2 to 5 arguments"); - return NULL; - } -#ifdef HAVE_NCURSESW - strtype = PyCurses_ConvertToString(self, strobj, &bytesobj, &wstr); -#else - strtype = PyCurses_ConvertToString(self, strobj, &bytesobj, NULL); -#endif - if (strtype == 0) - return NULL; - - if (use_attr == TRUE) { - attr_old = getattrs(self->win); - (void)wattrset(self->win,attr); - } -#ifdef HAVE_NCURSESW - if (strtype == 2) { - funcname = "addnwstr"; - if (use_xy == TRUE) - rtn = mvwaddnwstr(self->win,y,x,wstr,n); - else - rtn = waddnwstr(self->win,wstr,n); - PyMem_Free(wstr); - } - else -#endif - { - char *str = PyBytes_AS_STRING(bytesobj); - funcname = "addnstr"; - if (use_xy == TRUE) - rtn = mvwaddnstr(self->win,y,x,str,n); - else - rtn = waddnstr(self->win,str,n); - Py_DECREF(bytesobj); - } - if (use_attr == TRUE) - (void)wattrset(self->win,attr_old); - return PyCursesCheckERR(rtn, funcname); -} - -static PyObject * -PyCursesWindow_Bkgd(PyCursesWindowObject *self, PyObject *args) -{ - PyObject *temp; - chtype bkgd; - attr_t attr = A_NORMAL; - long lattr; - - switch (PyTuple_Size(args)) { - case 1: - if (!PyArg_ParseTuple(args, "O;ch or int", &temp)) - return NULL; - break; - case 2: - if (!PyArg_ParseTuple(args,"Ol;ch or int,attr", &temp, &lattr)) - return NULL; - attr = lattr; - break; - default: - PyErr_SetString(PyExc_TypeError, "bkgd requires 1 or 2 arguments"); - return NULL; - } - - if (!PyCurses_ConvertToChtype(self, temp, &bkgd)) - return NULL; - - return PyCursesCheckERR(wbkgd(self->win, bkgd | attr), "bkgd"); -} - -static PyObject * -PyCursesWindow_AttrOff(PyCursesWindowObject *self, PyObject *args) -{ - long lattr; - if (!PyArg_ParseTuple(args,"l;attr", &lattr)) - return NULL; - return PyCursesCheckERR(wattroff(self->win, (attr_t)lattr), "attroff"); -} - -static PyObject * -PyCursesWindow_AttrOn(PyCursesWindowObject *self, PyObject *args) -{ - long lattr; - if (!PyArg_ParseTuple(args,"l;attr", &lattr)) - return NULL; - return PyCursesCheckERR(wattron(self->win, (attr_t)lattr), "attron"); -} - -static PyObject * -PyCursesWindow_AttrSet(PyCursesWindowObject *self, PyObject *args) -{ - long lattr; - if (!PyArg_ParseTuple(args,"l;attr", &lattr)) - return NULL; - return PyCursesCheckERR(wattrset(self->win, (attr_t)lattr), "attrset"); -} - -static PyObject * -PyCursesWindow_BkgdSet(PyCursesWindowObject *self, PyObject *args) -{ - PyObject *temp; - chtype bkgd; - attr_t attr = A_NORMAL; - long lattr; - - switch (PyTuple_Size(args)) { - case 1: - if (!PyArg_ParseTuple(args, "O;ch or int", &temp)) - return NULL; - break; - case 2: - if (!PyArg_ParseTuple(args,"Ol;ch or int,attr", &temp, &lattr)) - return NULL; - attr = lattr; - break; - default: - PyErr_SetString(PyExc_TypeError, "bkgdset requires 1 or 2 arguments"); - return NULL; - } - - if (!PyCurses_ConvertToChtype(self, temp, &bkgd)) - return NULL; - - wbkgdset(self->win, bkgd | attr); - return PyCursesCheckERR(0, "bkgdset"); -} - -static PyObject * -PyCursesWindow_Border(PyCursesWindowObject *self, PyObject *args) -{ - PyObject *temp[8]; - chtype ch[8]; - int i; - - /* Clear the array of parameters */ - for(i=0; i<8; i++) { - temp[i] = NULL; - ch[i] = 0; - } - - if (!PyArg_ParseTuple(args,"|OOOOOOOO;ls,rs,ts,bs,tl,tr,bl,br", - &temp[0], &temp[1], &temp[2], &temp[3], - &temp[4], &temp[5], &temp[6], &temp[7])) - return NULL; - - for(i=0; i<8; i++) { - if (temp[i] != NULL && !PyCurses_ConvertToChtype(self, temp[i], &ch[i])) - return NULL; - } - - wborder(self->win, - ch[0], ch[1], ch[2], ch[3], - ch[4], ch[5], ch[6], ch[7]); - Py_INCREF(Py_None); - return Py_None; -} - -static PyObject * -PyCursesWindow_Box(PyCursesWindowObject *self, PyObject *args) -{ - chtype ch1=0,ch2=0; - switch(PyTuple_Size(args)){ - case 0: break; - default: - if (!PyArg_ParseTuple(args,"ll;vertint,horint", &ch1, &ch2)) - return NULL; - } - box(self->win,ch1,ch2); - Py_INCREF(Py_None); - return Py_None; -} - -#if defined(HAVE_NCURSES_H) || defined(MVWDELCH_IS_EXPRESSION) -#define py_mvwdelch mvwdelch -#else -int py_mvwdelch(WINDOW *w, int y, int x) -{ - mvwdelch(w,y,x); - /* On HP/UX, mvwdelch already returns. On other systems, - we may well run into this return statement. */ - return 0; -} -#endif - -/* chgat, added by Fabian Kreutz */ - -static PyObject * -PyCursesWindow_ChgAt(PyCursesWindowObject *self, PyObject *args) -{ - int rtn; - int x, y; - int num = -1; - short color; - attr_t attr = A_NORMAL; - long lattr; - int use_xy = FALSE; - - switch (PyTuple_Size(args)) { - case 1: - if (!PyArg_ParseTuple(args,"l;attr", &lattr)) - return NULL; - attr = lattr; - break; - case 2: - if (!PyArg_ParseTuple(args,"il;n,attr", &num, &lattr)) - return NULL; - attr = lattr; - break; - case 3: - if (!PyArg_ParseTuple(args,"iil;int,int,attr", &y, &x, &lattr)) - return NULL; - attr = lattr; - use_xy = TRUE; - break; - case 4: - if (!PyArg_ParseTuple(args,"iiil;int,int,n,attr", &y, &x, &num, &lattr)) - return NULL; - attr = lattr; - use_xy = TRUE; - break; - default: - PyErr_SetString(PyExc_TypeError, "chgat requires 1 to 4 arguments"); - return NULL; - } - - color = (short)((attr >> 8) & 0xff); - attr = attr - (color << 8); - - if (use_xy == TRUE) { - rtn = mvwchgat(self->win,y,x,num,attr,color,NULL); - touchline(self->win,y,1); - } else { - getyx(self->win,y,x); - rtn = wchgat(self->win,num,attr,color,NULL); - touchline(self->win,y,1); - } - return PyCursesCheckERR(rtn, "chgat"); -} - - -static PyObject * -PyCursesWindow_DelCh(PyCursesWindowObject *self, PyObject *args) -{ - int rtn; - int x, y; - - switch (PyTuple_Size(args)) { - case 0: - rtn = wdelch(self->win); - break; - case 2: - if (!PyArg_ParseTuple(args,"ii;y,x", &y, &x)) - return NULL; - rtn = py_mvwdelch(self->win,y,x); - break; - default: - PyErr_SetString(PyExc_TypeError, "delch requires 0 or 2 arguments"); - return NULL; - } - return PyCursesCheckERR(rtn, "[mv]wdelch"); -} - -static PyObject * -PyCursesWindow_DerWin(PyCursesWindowObject *self, PyObject *args) -{ - WINDOW *win; - int nlines, ncols, begin_y, begin_x; - - nlines = 0; - ncols = 0; - switch (PyTuple_Size(args)) { - case 2: - if (!PyArg_ParseTuple(args,"ii;begin_y,begin_x",&begin_y,&begin_x)) - return NULL; - break; - case 4: - if (!PyArg_ParseTuple(args, "iiii;nlines,ncols,begin_y,begin_x", - &nlines,&ncols,&begin_y,&begin_x)) - return NULL; - break; - default: - PyErr_SetString(PyExc_TypeError, "derwin requires 2 or 4 arguments"); - return NULL; - } - - win = derwin(self->win,nlines,ncols,begin_y,begin_x); - - if (win == NULL) { - PyErr_SetString(PyCursesError, catchall_NULL); - return NULL; - } - - return (PyObject *)PyCursesWindow_New(win, NULL); -} - -static PyObject * -PyCursesWindow_EchoChar(PyCursesWindowObject *self, PyObject *args) -{ - PyObject *temp; - chtype ch; - attr_t attr = A_NORMAL; - long lattr; - - switch (PyTuple_Size(args)) { - case 1: - if (!PyArg_ParseTuple(args,"O;ch or int", &temp)) - return NULL; - break; - case 2: - if (!PyArg_ParseTuple(args,"Ol;ch or int,attr", &temp, &lattr)) - return NULL; - attr = lattr; - break; - default: - PyErr_SetString(PyExc_TypeError, "echochar requires 1 or 2 arguments"); - - - return NULL; - } - - if (!PyCurses_ConvertToChtype(self, temp, &ch)) - return NULL; - -#ifdef WINDOW_HAS_FLAGS - if (self->win->_flags & _ISPAD) - return PyCursesCheckERR(pechochar(self->win, ch | attr), - "echochar"); - else -#endif - return PyCursesCheckERR(wechochar(self->win, ch | attr), - "echochar"); -} - -#ifdef NCURSES_MOUSE_VERSION -static PyObject * -PyCursesWindow_Enclose(PyCursesWindowObject *self, PyObject *args) -{ - int x, y; - if (!PyArg_ParseTuple(args,"ii;y,x", &y, &x)) - return NULL; - - return PyLong_FromLong( wenclose(self->win,y,x) ); -} -#endif - -static PyObject * -PyCursesWindow_GetBkgd(PyCursesWindowObject *self) -{ - return PyLong_FromLong((long) getbkgd(self->win)); -} - -static PyObject * -PyCursesWindow_GetCh(PyCursesWindowObject *self, PyObject *args) -{ - int x, y; - int rtn; - - switch (PyTuple_Size(args)) { - case 0: - Py_BEGIN_ALLOW_THREADS - rtn = wgetch(self->win); - Py_END_ALLOW_THREADS - break; - case 2: - if (!PyArg_ParseTuple(args,"ii;y,x",&y,&x)) - return NULL; - Py_BEGIN_ALLOW_THREADS - rtn = mvwgetch(self->win,y,x); - Py_END_ALLOW_THREADS - break; - default: - PyErr_SetString(PyExc_TypeError, "getch requires 0 or 2 arguments"); - return NULL; - } - return PyLong_FromLong((long)rtn); -} - -static PyObject * -PyCursesWindow_GetKey(PyCursesWindowObject *self, PyObject *args) -{ - int x, y; - int rtn; - - switch (PyTuple_Size(args)) { - case 0: - Py_BEGIN_ALLOW_THREADS - rtn = wgetch(self->win); - Py_END_ALLOW_THREADS - break; - case 2: - if (!PyArg_ParseTuple(args,"ii;y,x",&y,&x)) - return NULL; - Py_BEGIN_ALLOW_THREADS - rtn = mvwgetch(self->win,y,x); - Py_END_ALLOW_THREADS - break; - default: - PyErr_SetString(PyExc_TypeError, "getkey requires 0 or 2 arguments"); - return NULL; - } - if (rtn == ERR) { - /* getch() returns ERR in nodelay mode */ - PyErr_CheckSignals(); - if (!PyErr_Occurred()) - PyErr_SetString(PyCursesError, "no input"); - return NULL; - } else if (rtn<=255) { - return Py_BuildValue("C", rtn); - } else { - const char *knp; -#if defined(__NetBSD__) - knp = unctrl(rtn); -#else - knp = keyname(rtn); -#endif - return PyUnicode_FromString((knp == NULL) ? "" : knp); - } -} - -#ifdef HAVE_NCURSESW -static PyObject * -PyCursesWindow_Get_WCh(PyCursesWindowObject *self, PyObject *args) -{ - int x, y; - int ct; - wint_t rtn; - - switch (PyTuple_Size(args)) { - case 0: - Py_BEGIN_ALLOW_THREADS - ct = wget_wch(self->win,&rtn); - Py_END_ALLOW_THREADS - break; - case 2: - if (!PyArg_ParseTuple(args,"ii;y,x",&y,&x)) - return NULL; - Py_BEGIN_ALLOW_THREADS - ct = mvwget_wch(self->win,y,x,&rtn); - Py_END_ALLOW_THREADS - break; - default: - PyErr_SetString(PyExc_TypeError, "get_wch requires 0 or 2 arguments"); - return NULL; - } - if (ct == ERR) { - if (PyErr_CheckSignals()) - return NULL; - - /* get_wch() returns ERR in nodelay mode */ - PyErr_SetString(PyCursesError, "no input"); - return NULL; - } - if (ct == KEY_CODE_YES) - return PyLong_FromLong(rtn); - else - return PyUnicode_FromOrdinal(rtn); -} -#endif - -static PyObject * -PyCursesWindow_GetStr(PyCursesWindowObject *self, PyObject *args) -{ - int x, y, n; - char rtn[1024]; /* This should be big enough.. I hope */ - int rtn2; - - switch (PyTuple_Size(args)) { - case 0: - Py_BEGIN_ALLOW_THREADS - rtn2 = wgetnstr(self->win,rtn, 1023); - Py_END_ALLOW_THREADS - break; - case 1: - if (!PyArg_ParseTuple(args,"i;n", &n)) - return NULL; - Py_BEGIN_ALLOW_THREADS - rtn2 = wgetnstr(self->win, rtn, Py_MIN(n, 1023)); - Py_END_ALLOW_THREADS - break; - case 2: - if (!PyArg_ParseTuple(args,"ii;y,x",&y,&x)) - return NULL; - Py_BEGIN_ALLOW_THREADS -#ifdef STRICT_SYSV_CURSES - rtn2 = wmove(self->win,y,x)==ERR ? ERR : wgetnstr(self->win, rtn, 1023); -#else - rtn2 = mvwgetnstr(self->win,y,x,rtn, 1023); -#endif - Py_END_ALLOW_THREADS - break; - case 3: - if (!PyArg_ParseTuple(args,"iii;y,x,n", &y, &x, &n)) - return NULL; -#ifdef STRICT_SYSV_CURSES - Py_BEGIN_ALLOW_THREADS - rtn2 = wmove(self->win,y,x)==ERR ? ERR : - wgetnstr(self->win, rtn, Py_MIN(n, 1023)); - Py_END_ALLOW_THREADS -#else - Py_BEGIN_ALLOW_THREADS - rtn2 = mvwgetnstr(self->win, y, x, rtn, Py_MIN(n, 1023)); - Py_END_ALLOW_THREADS -#endif - break; - default: - PyErr_SetString(PyExc_TypeError, "getstr requires 0 to 3 arguments"); - return NULL; - } - if (rtn2 == ERR) - rtn[0] = 0; - return PyBytes_FromString(rtn); -} - -static PyObject * -PyCursesWindow_Hline(PyCursesWindowObject *self, PyObject *args) -{ - PyObject *temp; - chtype ch; - int n, x, y, code = OK; - attr_t attr = A_NORMAL; - long lattr; - - switch (PyTuple_Size(args)) { - case 2: - if (!PyArg_ParseTuple(args, "Oi;ch or int,n", &temp, &n)) - return NULL; - break; - case 3: - if (!PyArg_ParseTuple(args, "Oil;ch or int,n,attr", &temp, &n, &lattr)) - return NULL; - attr = lattr; - break; - case 4: - if (!PyArg_ParseTuple(args, "iiOi;y,x,ch or int,n", &y, &x, &temp, &n)) - return NULL; - code = wmove(self->win, y, x); - break; - case 5: - if (!PyArg_ParseTuple(args, "iiOil; y,x,ch or int,n,attr", - &y, &x, &temp, &n, &lattr)) - return NULL; - attr = lattr; - code = wmove(self->win, y, x); - break; - default: - PyErr_SetString(PyExc_TypeError, "hline requires 2 to 5 arguments"); - return NULL; - } - - if (code != ERR) { - if (!PyCurses_ConvertToChtype(self, temp, &ch)) - return NULL; - return PyCursesCheckERR(whline(self->win, ch | attr, n), "hline"); - } else - return PyCursesCheckERR(code, "wmove"); -} - -static PyObject * -PyCursesWindow_InsCh(PyCursesWindowObject *self, PyObject *args) -{ - int rtn, x, y, use_xy = FALSE; - PyObject *temp; - chtype ch = 0; - attr_t attr = A_NORMAL; - long lattr; - - switch (PyTuple_Size(args)) { - case 1: - if (!PyArg_ParseTuple(args, "O;ch or int", &temp)) - return NULL; - break; - case 2: - if (!PyArg_ParseTuple(args, "Ol;ch or int,attr", &temp, &lattr)) - return NULL; - attr = lattr; - break; - case 3: - if (!PyArg_ParseTuple(args,"iiO;y,x,ch or int", &y, &x, &temp)) - return NULL; - use_xy = TRUE; - break; - case 4: - if (!PyArg_ParseTuple(args,"iiOl;y,x,ch or int, attr", &y, &x, &temp, &lattr)) - return NULL; - attr = lattr; - use_xy = TRUE; - break; - default: - PyErr_SetString(PyExc_TypeError, "insch requires 1 or 4 arguments"); - return NULL; - } - - if (!PyCurses_ConvertToChtype(self, temp, &ch)) - return NULL; - - if (use_xy == TRUE) - rtn = mvwinsch(self->win,y,x, ch | attr); - else { - rtn = winsch(self->win, ch | attr); - } - return PyCursesCheckERR(rtn, "insch"); -} - -static PyObject * -PyCursesWindow_InCh(PyCursesWindowObject *self, PyObject *args) -{ - int x, y; - unsigned long rtn; - - switch (PyTuple_Size(args)) { - case 0: - rtn = winch(self->win); - break; - case 2: - if (!PyArg_ParseTuple(args,"ii;y,x",&y,&x)) - return NULL; - rtn = mvwinch(self->win,y,x); - break; - default: - PyErr_SetString(PyExc_TypeError, "inch requires 0 or 2 arguments"); - return NULL; - } - return PyLong_FromUnsignedLong(rtn); -} - -static PyObject * -PyCursesWindow_InStr(PyCursesWindowObject *self, PyObject *args) -{ - int x, y, n; - char rtn[1024]; /* This should be big enough.. I hope */ - int rtn2; - - switch (PyTuple_Size(args)) { - case 0: - rtn2 = winnstr(self->win,rtn, 1023); - break; - case 1: - if (!PyArg_ParseTuple(args,"i;n", &n)) - return NULL; - rtn2 = winnstr(self->win, rtn, Py_MIN(n, 1023)); - break; - case 2: - if (!PyArg_ParseTuple(args,"ii;y,x",&y,&x)) - return NULL; - rtn2 = mvwinnstr(self->win,y,x,rtn,1023); - break; - case 3: - if (!PyArg_ParseTuple(args, "iii;y,x,n", &y, &x, &n)) - return NULL; - rtn2 = mvwinnstr(self->win, y, x, rtn, Py_MIN(n,1023)); - break; - default: - PyErr_SetString(PyExc_TypeError, "instr requires 0 or 3 arguments"); - return NULL; - } - if (rtn2 == ERR) - rtn[0] = 0; - return PyBytes_FromString(rtn); -} - -static PyObject * -PyCursesWindow_InsStr(PyCursesWindowObject *self, PyObject *args) -{ - int rtn; - int x, y; - int strtype; - PyObject *strobj, *bytesobj = NULL; -#ifdef HAVE_NCURSESW - wchar_t *wstr = NULL; -#endif - attr_t attr = A_NORMAL , attr_old = A_NORMAL; - long lattr; - int use_xy = FALSE, use_attr = FALSE; - const char *funcname; - - switch (PyTuple_Size(args)) { - case 1: - if (!PyArg_ParseTuple(args,"O;str", &strobj)) - return NULL; - break; - case 2: - if (!PyArg_ParseTuple(args,"Ol;str,attr", &strobj, &lattr)) - return NULL; - attr = lattr; - use_attr = TRUE; - break; - case 3: - if (!PyArg_ParseTuple(args,"iiO;y,x,str", &y, &x, &strobj)) - return NULL; - use_xy = TRUE; - break; - case 4: - if (!PyArg_ParseTuple(args,"iiOl;y,x,str,attr", &y, &x, &strobj, &lattr)) - return NULL; - attr = lattr; - use_xy = use_attr = TRUE; - break; - default: - PyErr_SetString(PyExc_TypeError, "insstr requires 1 to 4 arguments"); - return NULL; - } - -#ifdef HAVE_NCURSESW - strtype = PyCurses_ConvertToString(self, strobj, &bytesobj, &wstr); -#else - strtype = PyCurses_ConvertToString(self, strobj, &bytesobj, NULL); -#endif - if (strtype == 0) - return NULL; - - if (use_attr == TRUE) { - attr_old = getattrs(self->win); - (void)wattrset(self->win,attr); - } -#ifdef HAVE_NCURSESW - if (strtype == 2) { - funcname = "inswstr"; - if (use_xy == TRUE) - rtn = mvwins_wstr(self->win,y,x,wstr); - else - rtn = wins_wstr(self->win,wstr); - PyMem_Free(wstr); - } - else -#endif - { - char *str = PyBytes_AS_STRING(bytesobj); - funcname = "insstr"; - if (use_xy == TRUE) - rtn = mvwinsstr(self->win,y,x,str); - else - rtn = winsstr(self->win,str); - Py_DECREF(bytesobj); - } - if (use_attr == TRUE) - (void)wattrset(self->win,attr_old); - return PyCursesCheckERR(rtn, funcname); -} - -static PyObject * -PyCursesWindow_InsNStr(PyCursesWindowObject *self, PyObject *args) -{ - int rtn, x, y, n; - int strtype; - PyObject *strobj, *bytesobj = NULL; -#ifdef HAVE_NCURSESW - wchar_t *wstr = NULL; -#endif - attr_t attr = A_NORMAL , attr_old = A_NORMAL; - long lattr; - int use_xy = FALSE, use_attr = FALSE; - const char *funcname; - - switch (PyTuple_Size(args)) { - case 2: - if (!PyArg_ParseTuple(args,"Oi;str,n", &strobj, &n)) - return NULL; - break; - case 3: - if (!PyArg_ParseTuple(args,"Oil;str,n,attr", &strobj, &n, &lattr)) - return NULL; - attr = lattr; - use_attr = TRUE; - break; - case 4: - if (!PyArg_ParseTuple(args,"iiOi;y,x,str,n", &y, &x, &strobj, &n)) - return NULL; - use_xy = TRUE; - break; - case 5: - if (!PyArg_ParseTuple(args,"iiOil;y,x,str,n,attr", &y, &x, &strobj, &n, &lattr)) - return NULL; - attr = lattr; - use_xy = use_attr = TRUE; - break; - default: - PyErr_SetString(PyExc_TypeError, "insnstr requires 2 to 5 arguments"); - return NULL; - } - -#ifdef HAVE_NCURSESW - strtype = PyCurses_ConvertToString(self, strobj, &bytesobj, &wstr); -#else - strtype = PyCurses_ConvertToString(self, strobj, &bytesobj, NULL); -#endif - if (strtype == 0) - return NULL; - - if (use_attr == TRUE) { - attr_old = getattrs(self->win); - (void)wattrset(self->win,attr); - } -#ifdef HAVE_NCURSESW - if (strtype == 2) { - funcname = "insn_wstr"; - if (use_xy == TRUE) - rtn = mvwins_nwstr(self->win,y,x,wstr,n); - else - rtn = wins_nwstr(self->win,wstr,n); - PyMem_Free(wstr); - } - else -#endif - { - char *str = PyBytes_AS_STRING(bytesobj); - funcname = "insnstr"; - if (use_xy == TRUE) - rtn = mvwinsnstr(self->win,y,x,str,n); - else - rtn = winsnstr(self->win,str,n); - Py_DECREF(bytesobj); - } - if (use_attr == TRUE) - (void)wattrset(self->win,attr_old); - return PyCursesCheckERR(rtn, funcname); -} - -static PyObject * -PyCursesWindow_Is_LineTouched(PyCursesWindowObject *self, PyObject *args) -{ - int line, erg; - if (!PyArg_ParseTuple(args,"i;line", &line)) - return NULL; - erg = is_linetouched(self->win, line); - if (erg == ERR) { - PyErr_SetString(PyExc_TypeError, - "is_linetouched: line number outside of boundaries"); - return NULL; - } else - if (erg == FALSE) { - Py_INCREF(Py_False); - return Py_False; - } else { - Py_INCREF(Py_True); - return Py_True; - } -} - -static PyObject * -PyCursesWindow_NoOutRefresh(PyCursesWindowObject *self, PyObject *args) -{ - int pminrow,pmincol,sminrow,smincol,smaxrow,smaxcol; - int rtn; - -#ifndef WINDOW_HAS_FLAGS - if (0) -#else - if (self->win->_flags & _ISPAD) -#endif - { - switch(PyTuple_Size(args)) { - case 6: - if (!PyArg_ParseTuple(args, - "iiiiii;" \ - "pminrow,pmincol,sminrow,smincol,smaxrow,smaxcol", - &pminrow, &pmincol, &sminrow, - &smincol, &smaxrow, &smaxcol)) - return NULL; - Py_BEGIN_ALLOW_THREADS - rtn = pnoutrefresh(self->win, - pminrow, pmincol, sminrow, - smincol, smaxrow, smaxcol); - Py_END_ALLOW_THREADS - return PyCursesCheckERR(rtn, "pnoutrefresh"); - default: - PyErr_SetString(PyCursesError, - "noutrefresh() called for a pad " - "requires 6 arguments"); - return NULL; - } - } else { - if (!PyArg_ParseTuple(args, ":noutrefresh")) - return NULL; - - Py_BEGIN_ALLOW_THREADS - rtn = wnoutrefresh(self->win); - Py_END_ALLOW_THREADS - return PyCursesCheckERR(rtn, "wnoutrefresh"); - } -} - -static PyObject * -PyCursesWindow_Overlay(PyCursesWindowObject *self, PyObject *args) -{ - PyCursesWindowObject *temp; - int use_copywin = FALSE; - int sminrow, smincol, dminrow, dmincol, dmaxrow, dmaxcol; - int rtn; - - switch (PyTuple_Size(args)) { - case 1: - if (!PyArg_ParseTuple(args, "O!;window object", - &PyCursesWindow_Type, &temp)) - return NULL; - break; - case 7: - if (!PyArg_ParseTuple(args, "O!iiiiii;window object, int, int, int, int, int, int", - &PyCursesWindow_Type, &temp, &sminrow, &smincol, - &dminrow, &dmincol, &dmaxrow, &dmaxcol)) - return NULL; - use_copywin = TRUE; - break; - default: - PyErr_SetString(PyExc_TypeError, - "overlay requires one or seven arguments"); - return NULL; - } - - if (use_copywin == TRUE) { - rtn = copywin(self->win, temp->win, sminrow, smincol, - dminrow, dmincol, dmaxrow, dmaxcol, TRUE); - return PyCursesCheckERR(rtn, "copywin"); - } - else { - rtn = overlay(self->win, temp->win); - return PyCursesCheckERR(rtn, "overlay"); - } -} - -static PyObject * -PyCursesWindow_Overwrite(PyCursesWindowObject *self, PyObject *args) -{ - PyCursesWindowObject *temp; - int use_copywin = FALSE; - int sminrow, smincol, dminrow, dmincol, dmaxrow, dmaxcol; - int rtn; - - switch (PyTuple_Size(args)) { - case 1: - if (!PyArg_ParseTuple(args, "O!;window object", - &PyCursesWindow_Type, &temp)) - return NULL; - break; - case 7: - if (!PyArg_ParseTuple(args, "O!iiiiii;window object, int, int, int, int, int, int", - &PyCursesWindow_Type, &temp, &sminrow, &smincol, - &dminrow, &dmincol, &dmaxrow, &dmaxcol)) - return NULL; - use_copywin = TRUE; - break; - default: - PyErr_SetString(PyExc_TypeError, - "overwrite requires one or seven arguments"); - return NULL; - } - - if (use_copywin == TRUE) { - rtn = copywin(self->win, temp->win, sminrow, smincol, - dminrow, dmincol, dmaxrow, dmaxcol, FALSE); - return PyCursesCheckERR(rtn, "copywin"); - } - else { - rtn = overwrite(self->win, temp->win); - return PyCursesCheckERR(rtn, "overwrite"); - } -} - -static PyObject * -PyCursesWindow_PutWin(PyCursesWindowObject *self, PyObject *stream) -{ - /* We have to simulate this by writing to a temporary FILE*, - then reading back, then writing to the argument stream. */ - char fn[100]; - int fd = -1; - FILE *fp = NULL; - PyObject *res = NULL; - - strcpy(fn, "/tmp/py.curses.putwin.XXXXXX"); - fd = mkstemp(fn); - if (fd < 0) - return PyErr_SetFromErrnoWithFilename(PyExc_IOError, fn); - if (_Py_set_inheritable(fd, 0, NULL) < 0) - goto exit; - fp = fdopen(fd, "wb+"); - if (fp == NULL) { - PyErr_SetFromErrnoWithFilename(PyExc_IOError, fn); - goto exit; - } - res = PyCursesCheckERR(putwin(self->win, fp), "putwin"); - if (res == NULL) - goto exit; - fseek(fp, 0, 0); - while (1) { - char buf[BUFSIZ]; - Py_ssize_t n = fread(buf, 1, BUFSIZ, fp); - _Py_IDENTIFIER(write); - - if (n <= 0) - break; - Py_DECREF(res); - res = _PyObject_CallMethodId(stream, &PyId_write, "y#", buf, n); - if (res == NULL) - break; - } - -exit: - if (fp != NULL) - fclose(fp); - else if (fd != -1) - close(fd); - remove(fn); - return res; -} - -static PyObject * -PyCursesWindow_RedrawLine(PyCursesWindowObject *self, PyObject *args) -{ - int beg, num; - if (!PyArg_ParseTuple(args, "ii;beg,num", &beg, &num)) - return NULL; - return PyCursesCheckERR(wredrawln(self->win,beg,num), "redrawln"); -} - -static PyObject * -PyCursesWindow_Refresh(PyCursesWindowObject *self, PyObject *args) -{ - int pminrow,pmincol,sminrow,smincol,smaxrow,smaxcol; - int rtn; - -#ifndef WINDOW_HAS_FLAGS - if (0) -#else - if (self->win->_flags & _ISPAD) -#endif - { - switch(PyTuple_Size(args)) { - case 6: - if (!PyArg_ParseTuple(args, - "iiiiii;" \ - "pminrow,pmincol,sminrow,smincol,smaxrow,smaxcol", - &pminrow, &pmincol, &sminrow, - &smincol, &smaxrow, &smaxcol)) - return NULL; - - Py_BEGIN_ALLOW_THREADS - rtn = prefresh(self->win, - pminrow, pmincol, sminrow, - smincol, smaxrow, smaxcol); - Py_END_ALLOW_THREADS - return PyCursesCheckERR(rtn, "prefresh"); - default: - PyErr_SetString(PyCursesError, - "refresh() for a pad requires 6 arguments"); - return NULL; - } - } else { - if (!PyArg_ParseTuple(args, ":refresh")) - return NULL; - Py_BEGIN_ALLOW_THREADS - rtn = wrefresh(self->win); - Py_END_ALLOW_THREADS - return PyCursesCheckERR(rtn, "prefresh"); - } -} - -static PyObject * -PyCursesWindow_SetScrollRegion(PyCursesWindowObject *self, PyObject *args) -{ - int x, y; - if (!PyArg_ParseTuple(args,"ii;top, bottom",&y,&x)) - return NULL; - return PyCursesCheckERR(wsetscrreg(self->win,y,x), "wsetscrreg"); -} - -static PyObject * -PyCursesWindow_SubWin(PyCursesWindowObject *self, PyObject *args) -{ - WINDOW *win; - int nlines, ncols, begin_y, begin_x; - - nlines = 0; - ncols = 0; - switch (PyTuple_Size(args)) { - case 2: - if (!PyArg_ParseTuple(args,"ii;begin_y,begin_x",&begin_y,&begin_x)) - return NULL; - break; - case 4: - if (!PyArg_ParseTuple(args, "iiii;nlines,ncols,begin_y,begin_x", - &nlines,&ncols,&begin_y,&begin_x)) - return NULL; - break; - default: - PyErr_SetString(PyExc_TypeError, "subwin requires 2 or 4 arguments"); - return NULL; - } - - /* printf("Subwin: %i %i %i %i \n", nlines, ncols, begin_y, begin_x); */ -#ifdef WINDOW_HAS_FLAGS - if (self->win->_flags & _ISPAD) - win = subpad(self->win, nlines, ncols, begin_y, begin_x); - else -#endif - win = subwin(self->win, nlines, ncols, begin_y, begin_x); - - if (win == NULL) { - PyErr_SetString(PyCursesError, catchall_NULL); - return NULL; - } - - return (PyObject *)PyCursesWindow_New(win, self->encoding); -} - -static PyObject * -PyCursesWindow_Scroll(PyCursesWindowObject *self, PyObject *args) -{ - int nlines; - switch(PyTuple_Size(args)) { - case 0: - return PyCursesCheckERR(scroll(self->win), "scroll"); - case 1: - if (!PyArg_ParseTuple(args, "i;nlines", &nlines)) - return NULL; - return PyCursesCheckERR(wscrl(self->win, nlines), "scroll"); - default: - PyErr_SetString(PyExc_TypeError, "scroll requires 0 or 1 arguments"); - return NULL; - } -} - -static PyObject * -PyCursesWindow_TouchLine(PyCursesWindowObject *self, PyObject *args) -{ - int st, cnt, val; - switch (PyTuple_Size(args)) { - case 2: - if (!PyArg_ParseTuple(args,"ii;start,count",&st,&cnt)) - return NULL; - return PyCursesCheckERR(touchline(self->win,st,cnt), "touchline"); - case 3: - if (!PyArg_ParseTuple(args, "iii;start,count,val", &st, &cnt, &val)) - return NULL; - return PyCursesCheckERR(wtouchln(self->win, st, cnt, val), "touchline"); - default: - PyErr_SetString(PyExc_TypeError, "touchline requires 2 or 3 arguments"); - return NULL; - } -} - -static PyObject * -PyCursesWindow_Vline(PyCursesWindowObject *self, PyObject *args) -{ - PyObject *temp; - chtype ch; - int n, x, y, code = OK; - attr_t attr = A_NORMAL; - long lattr; - - switch (PyTuple_Size(args)) { - case 2: - if (!PyArg_ParseTuple(args, "Oi;ch or int,n", &temp, &n)) - return NULL; - break; - case 3: - if (!PyArg_ParseTuple(args, "Oil;ch or int,n,attr", &temp, &n, &lattr)) - return NULL; - attr = lattr; - break; - case 4: - if (!PyArg_ParseTuple(args, "iiOi;y,x,ch or int,n", &y, &x, &temp, &n)) - return NULL; - code = wmove(self->win, y, x); - break; - case 5: - if (!PyArg_ParseTuple(args, "iiOil; y,x,ch or int,n,attr", - &y, &x, &temp, &n, &lattr)) - return NULL; - attr = lattr; - code = wmove(self->win, y, x); - break; - default: - PyErr_SetString(PyExc_TypeError, "vline requires 2 to 5 arguments"); - return NULL; - } - - if (code != ERR) { - if (!PyCurses_ConvertToChtype(self, temp, &ch)) - return NULL; - return PyCursesCheckERR(wvline(self->win, ch | attr, n), "vline"); - } else - return PyCursesCheckERR(code, "wmove"); -} - -static PyObject * -PyCursesWindow_get_encoding(PyCursesWindowObject *self, void *closure) -{ - return PyUnicode_FromString(self->encoding); -} - -static int -PyCursesWindow_set_encoding(PyCursesWindowObject *self, PyObject *value) -{ - PyObject *ascii; - char *encoding; - - /* It is illegal to del win.encoding */ - if (value == NULL) { - PyErr_SetString(PyExc_TypeError, - "encoding may not be deleted"); - return -1; - } - - if (!PyUnicode_Check(value)) { - PyErr_SetString(PyExc_TypeError, - "setting encoding to a non-string"); - return -1; - } - ascii = PyUnicode_AsASCIIString(value); - if (ascii == NULL) - return -1; - encoding = _PyMem_Strdup(PyBytes_AS_STRING(ascii)); - Py_DECREF(ascii); - if (encoding == NULL) { - PyErr_NoMemory(); - return -1; - } - PyMem_Free(self->encoding); - self->encoding = encoding; - return 0; -} - - -static PyMethodDef PyCursesWindow_Methods[] = { - CURSES_WINDOW_ADDCH_METHODDEF - {"addnstr", (PyCFunction)PyCursesWindow_AddNStr, METH_VARARGS}, - {"addstr", (PyCFunction)PyCursesWindow_AddStr, METH_VARARGS}, - {"attroff", (PyCFunction)PyCursesWindow_AttrOff, METH_VARARGS}, - {"attron", (PyCFunction)PyCursesWindow_AttrOn, METH_VARARGS}, - {"attrset", (PyCFunction)PyCursesWindow_AttrSet, METH_VARARGS}, - {"bkgd", (PyCFunction)PyCursesWindow_Bkgd, METH_VARARGS}, - {"chgat", (PyCFunction)PyCursesWindow_ChgAt, METH_VARARGS}, - {"bkgdset", (PyCFunction)PyCursesWindow_BkgdSet, METH_VARARGS}, - {"border", (PyCFunction)PyCursesWindow_Border, METH_VARARGS}, - {"box", (PyCFunction)PyCursesWindow_Box, METH_VARARGS}, - {"clear", (PyCFunction)PyCursesWindow_wclear, METH_NOARGS}, - {"clearok", (PyCFunction)PyCursesWindow_clearok, METH_VARARGS}, - {"clrtobot", (PyCFunction)PyCursesWindow_wclrtobot, METH_NOARGS}, - {"clrtoeol", (PyCFunction)PyCursesWindow_wclrtoeol, METH_NOARGS}, - {"cursyncup", (PyCFunction)PyCursesWindow_wcursyncup, METH_NOARGS}, - {"delch", (PyCFunction)PyCursesWindow_DelCh, METH_VARARGS}, - {"deleteln", (PyCFunction)PyCursesWindow_wdeleteln, METH_NOARGS}, - {"derwin", (PyCFunction)PyCursesWindow_DerWin, METH_VARARGS}, - {"echochar", (PyCFunction)PyCursesWindow_EchoChar, METH_VARARGS}, -#ifdef NCURSES_MOUSE_VERSION - {"enclose", (PyCFunction)PyCursesWindow_Enclose, METH_VARARGS}, -#endif - {"erase", (PyCFunction)PyCursesWindow_werase, METH_NOARGS}, - {"getbegyx", (PyCFunction)PyCursesWindow_getbegyx, METH_NOARGS}, - {"getbkgd", (PyCFunction)PyCursesWindow_GetBkgd, METH_NOARGS}, - {"getch", (PyCFunction)PyCursesWindow_GetCh, METH_VARARGS}, - {"getkey", (PyCFunction)PyCursesWindow_GetKey, METH_VARARGS}, -#ifdef HAVE_NCURSESW - {"get_wch", (PyCFunction)PyCursesWindow_Get_WCh, METH_VARARGS}, -#endif - {"getmaxyx", (PyCFunction)PyCursesWindow_getmaxyx, METH_NOARGS}, - {"getparyx", (PyCFunction)PyCursesWindow_getparyx, METH_NOARGS}, - {"getstr", (PyCFunction)PyCursesWindow_GetStr, METH_VARARGS}, - {"getyx", (PyCFunction)PyCursesWindow_getyx, METH_NOARGS}, - {"hline", (PyCFunction)PyCursesWindow_Hline, METH_VARARGS}, - {"idcok", (PyCFunction)PyCursesWindow_idcok, METH_VARARGS}, - {"idlok", (PyCFunction)PyCursesWindow_idlok, METH_VARARGS}, - {"immedok", (PyCFunction)PyCursesWindow_immedok, METH_VARARGS}, - {"inch", (PyCFunction)PyCursesWindow_InCh, METH_VARARGS}, - {"insch", (PyCFunction)PyCursesWindow_InsCh, METH_VARARGS}, - {"insdelln", (PyCFunction)PyCursesWindow_winsdelln, METH_VARARGS}, - {"insertln", (PyCFunction)PyCursesWindow_winsertln, METH_NOARGS}, - {"insnstr", (PyCFunction)PyCursesWindow_InsNStr, METH_VARARGS}, - {"insstr", (PyCFunction)PyCursesWindow_InsStr, METH_VARARGS}, - {"instr", (PyCFunction)PyCursesWindow_InStr, METH_VARARGS}, - {"is_linetouched", (PyCFunction)PyCursesWindow_Is_LineTouched, METH_VARARGS}, - {"is_wintouched", (PyCFunction)PyCursesWindow_is_wintouched, METH_NOARGS}, - {"keypad", (PyCFunction)PyCursesWindow_keypad, METH_VARARGS}, - {"leaveok", (PyCFunction)PyCursesWindow_leaveok, METH_VARARGS}, - {"move", (PyCFunction)PyCursesWindow_wmove, METH_VARARGS}, - {"mvderwin", (PyCFunction)PyCursesWindow_mvderwin, METH_VARARGS}, - {"mvwin", (PyCFunction)PyCursesWindow_mvwin, METH_VARARGS}, - {"nodelay", (PyCFunction)PyCursesWindow_nodelay, METH_VARARGS}, - {"notimeout", (PyCFunction)PyCursesWindow_notimeout, METH_VARARGS}, - {"noutrefresh", (PyCFunction)PyCursesWindow_NoOutRefresh, METH_VARARGS}, - {"overlay", (PyCFunction)PyCursesWindow_Overlay, METH_VARARGS}, - {"overwrite", (PyCFunction)PyCursesWindow_Overwrite, - METH_VARARGS}, - {"putwin", (PyCFunction)PyCursesWindow_PutWin, METH_O}, - {"redrawln", (PyCFunction)PyCursesWindow_RedrawLine, METH_VARARGS}, - {"redrawwin", (PyCFunction)PyCursesWindow_redrawwin, METH_NOARGS}, - {"refresh", (PyCFunction)PyCursesWindow_Refresh, METH_VARARGS}, -#ifndef STRICT_SYSV_CURSES - {"resize", (PyCFunction)PyCursesWindow_wresize, METH_VARARGS}, -#endif - {"scroll", (PyCFunction)PyCursesWindow_Scroll, METH_VARARGS}, - {"scrollok", (PyCFunction)PyCursesWindow_scrollok, METH_VARARGS}, - {"setscrreg", (PyCFunction)PyCursesWindow_SetScrollRegion, METH_VARARGS}, - {"standend", (PyCFunction)PyCursesWindow_wstandend, METH_NOARGS}, - {"standout", (PyCFunction)PyCursesWindow_wstandout, METH_NOARGS}, - {"subpad", (PyCFunction)PyCursesWindow_SubWin, METH_VARARGS}, - {"subwin", (PyCFunction)PyCursesWindow_SubWin, METH_VARARGS}, - {"syncdown", (PyCFunction)PyCursesWindow_wsyncdown, METH_NOARGS}, - {"syncok", (PyCFunction)PyCursesWindow_syncok, METH_VARARGS}, - {"syncup", (PyCFunction)PyCursesWindow_wsyncup, METH_NOARGS}, - {"timeout", (PyCFunction)PyCursesWindow_wtimeout, METH_VARARGS}, - {"touchline", (PyCFunction)PyCursesWindow_TouchLine, METH_VARARGS}, - {"touchwin", (PyCFunction)PyCursesWindow_touchwin, METH_NOARGS}, - {"untouchwin", (PyCFunction)PyCursesWindow_untouchwin, METH_NOARGS}, - {"vline", (PyCFunction)PyCursesWindow_Vline, METH_VARARGS}, - {NULL, NULL} /* sentinel */ -}; - -static PyGetSetDef PyCursesWindow_getsets[] = { - {"encoding", - (getter)PyCursesWindow_get_encoding, - (setter)PyCursesWindow_set_encoding, - "the typecode character used to create the array"}, - {NULL, NULL, NULL, NULL } /* sentinel */ -}; - -/* -------------------------------------------------------*/ - -PyTypeObject PyCursesWindow_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "_curses.curses window", /*tp_name*/ - sizeof(PyCursesWindowObject), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - /* methods */ - (destructor)PyCursesWindow_Dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ - (getattrfunc)0, /*tp_getattr*/ - (setattrfunc)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*/ - 0, /*tp_doc*/ - 0, /*tp_traverse*/ - 0, /*tp_clear*/ - 0, /*tp_richcompare*/ - 0, /*tp_weaklistoffset*/ - 0, /*tp_iter*/ - 0, /*tp_iternext*/ - PyCursesWindow_Methods, /*tp_methods*/ - 0, /* tp_members */ - PyCursesWindow_getsets, /* tp_getset */ -}; - -/********************************************************************* - Global Functions -**********************************************************************/ - -NoArgNoReturnFunction(beep) -NoArgNoReturnFunction(def_prog_mode) -NoArgNoReturnFunction(def_shell_mode) -NoArgNoReturnFunction(doupdate) -NoArgNoReturnFunction(endwin) -NoArgNoReturnFunction(flash) -NoArgNoReturnFunction(nocbreak) -NoArgNoReturnFunction(noecho) -NoArgNoReturnFunction(nonl) -NoArgNoReturnFunction(noraw) -NoArgNoReturnFunction(reset_prog_mode) -NoArgNoReturnFunction(reset_shell_mode) -NoArgNoReturnFunction(resetty) -NoArgNoReturnFunction(savetty) - -NoArgOrFlagNoReturnFunction(cbreak) -NoArgOrFlagNoReturnFunction(echo) -NoArgOrFlagNoReturnFunction(nl) -NoArgOrFlagNoReturnFunction(raw) - -NoArgReturnIntFunction(baudrate) -NoArgReturnIntFunction(termattrs) - -NoArgReturnStringFunction(termname) -NoArgReturnStringFunction(longname) - -NoArgTrueFalseFunction(can_change_color) -NoArgTrueFalseFunction(has_colors) -NoArgTrueFalseFunction(has_ic) -NoArgTrueFalseFunction(has_il) -NoArgTrueFalseFunction(isendwin) -NoArgNoReturnVoidFunction(flushinp) -NoArgNoReturnVoidFunction(noqiflush) - -static PyObject * -PyCurses_filter(PyObject *self) -{ - /* not checking for PyCursesInitialised here since filter() must - be called before initscr() */ - filter(); - Py_INCREF(Py_None); - return Py_None; -} - -static PyObject * -PyCurses_Color_Content(PyObject *self, PyObject *args) -{ - short color,r,g,b; - - PyCursesInitialised; - PyCursesInitialisedColor; - - if (!PyArg_ParseTuple(args, "h:color_content", &color)) return NULL; - - if (color_content(color, &r, &g, &b) != ERR) - return Py_BuildValue("(iii)", r, g, b); - else { - PyErr_SetString(PyCursesError, - "Argument 1 was out of range. Check value of COLORS."); - return NULL; - } -} - -static PyObject * -PyCurses_color_pair(PyObject *self, PyObject *args) -{ - int n; - - PyCursesInitialised; - PyCursesInitialisedColor; - - if (!PyArg_ParseTuple(args, "i:color_pair", &n)) return NULL; - return PyLong_FromLong((long) (n << 8)); -} - -static PyObject * -PyCurses_Curs_Set(PyObject *self, PyObject *args) -{ - int vis,erg; - - PyCursesInitialised; - - if (!PyArg_ParseTuple(args, "i:curs_set", &vis)) return NULL; - - erg = curs_set(vis); - if (erg == ERR) return PyCursesCheckERR(erg, "curs_set"); - - return PyLong_FromLong((long) erg); -} - -static PyObject * -PyCurses_Delay_Output(PyObject *self, PyObject *args) -{ - int ms; - - PyCursesInitialised; - - if (!PyArg_ParseTuple(args, "i:delay_output", &ms)) return NULL; - - return PyCursesCheckERR(delay_output(ms), "delay_output"); -} - -static PyObject * -PyCurses_EraseChar(PyObject *self) -{ - char ch; - - PyCursesInitialised; - - ch = erasechar(); - - return PyBytes_FromStringAndSize(&ch, 1); -} - -static PyObject * -PyCurses_getsyx(PyObject *self) -{ - int x = 0; - int y = 0; - - PyCursesInitialised; - - getsyx(y, x); - - return Py_BuildValue("(ii)", y, x); -} - -#ifdef NCURSES_MOUSE_VERSION -static PyObject * -PyCurses_GetMouse(PyObject *self) -{ - int rtn; - MEVENT event; - - PyCursesInitialised; - - rtn = getmouse( &event ); - if (rtn == ERR) { - PyErr_SetString(PyCursesError, "getmouse() returned ERR"); - return NULL; - } - return Py_BuildValue("(hiiil)", - (short)event.id, - event.x, event.y, event.z, - (long) event.bstate); -} - -static PyObject * -PyCurses_UngetMouse(PyObject *self, PyObject *args) -{ - MEVENT event; - - PyCursesInitialised; - if (!PyArg_ParseTuple(args, "hiiil", - &event.id, - &event.x, &event.y, &event.z, - (int *) &event.bstate)) - return NULL; - - return PyCursesCheckERR(ungetmouse(&event), "ungetmouse"); -} -#endif - -static PyObject * -PyCurses_GetWin(PyCursesWindowObject *self, PyObject *stream) -{ - char fn[100]; - int fd = -1; - FILE *fp = NULL; - PyObject *data; - size_t datalen; - WINDOW *win; - _Py_IDENTIFIER(read); - PyObject *res = NULL; - - PyCursesInitialised; - - strcpy(fn, "/tmp/py.curses.getwin.XXXXXX"); - fd = mkstemp(fn); - if (fd < 0) - return PyErr_SetFromErrnoWithFilename(PyExc_IOError, fn); - if (_Py_set_inheritable(fd, 0, NULL) < 0) - goto error; - fp = fdopen(fd, "wb+"); - if (fp == NULL) { - PyErr_SetFromErrnoWithFilename(PyExc_IOError, fn); - goto error; - } - - data = _PyObject_CallMethodId(stream, &PyId_read, ""); - if (data == NULL) - goto error; - if (!PyBytes_Check(data)) { - PyErr_Format(PyExc_TypeError, - "f.read() returned %.100s instead of bytes", - data->ob_type->tp_name); - Py_DECREF(data); - goto error; - } - datalen = PyBytes_GET_SIZE(data); - if (fwrite(PyBytes_AS_STRING(data), 1, datalen, fp) != datalen) { - Py_DECREF(data); - PyErr_SetFromErrnoWithFilename(PyExc_IOError, fn); - goto error; - } - Py_DECREF(data); - - fseek(fp, 0, 0); - win = getwin(fp); - if (win == NULL) { - PyErr_SetString(PyCursesError, catchall_NULL); - goto error; - } - res = PyCursesWindow_New(win, NULL); - -error: - if (fp != NULL) - fclose(fp); - else if (fd != -1) - close(fd); - remove(fn); - return res; -} - -static PyObject * -PyCurses_HalfDelay(PyObject *self, PyObject *args) -{ - unsigned char tenths; - - PyCursesInitialised; - - if (!PyArg_ParseTuple(args, "b:halfdelay", &tenths)) return NULL; - - return PyCursesCheckERR(halfdelay(tenths), "halfdelay"); -} - -#ifndef STRICT_SYSV_CURSES -/* No has_key! */ -static PyObject * PyCurses_has_key(PyObject *self, PyObject *args) -{ - int ch; - - PyCursesInitialised; - - if (!PyArg_ParseTuple(args,"i",&ch)) return NULL; - - if (has_key(ch) == FALSE) { - Py_INCREF(Py_False); - return Py_False; - } - Py_INCREF(Py_True); - return Py_True; -} -#endif /* STRICT_SYSV_CURSES */ - -static PyObject * -PyCurses_Init_Color(PyObject *self, PyObject *args) -{ - short color, r, g, b; - - PyCursesInitialised; - PyCursesInitialisedColor; - - switch(PyTuple_Size(args)) { - case 4: - if (!PyArg_ParseTuple(args, "hhhh;color,r,g,b", &color, &r, &g, &b)) return NULL; - break; - default: - PyErr_SetString(PyExc_TypeError, "init_color requires 4 arguments"); - return NULL; - } - - return PyCursesCheckERR(init_color(color, r, g, b), "init_color"); -} - -static PyObject * -PyCurses_Init_Pair(PyObject *self, PyObject *args) -{ - short pair, f, b; - - PyCursesInitialised; - PyCursesInitialisedColor; - - if (PyTuple_Size(args) != 3) { - PyErr_SetString(PyExc_TypeError, "init_pair requires 3 arguments"); - return NULL; - } - - if (!PyArg_ParseTuple(args, "hhh;pair, f, b", &pair, &f, &b)) return NULL; - - return PyCursesCheckERR(init_pair(pair, f, b), "init_pair"); -} - -static PyObject *ModDict; - -static PyObject * -PyCurses_InitScr(PyObject *self) -{ - WINDOW *win; - PyCursesWindowObject *winobj; - - if (initialised == TRUE) { - wrefresh(stdscr); - return (PyObject *)PyCursesWindow_New(stdscr, NULL); - } - - win = initscr(); - - if (win == NULL) { - PyErr_SetString(PyCursesError, catchall_NULL); - return NULL; - } - - initialised = initialised_setupterm = TRUE; - -/* This was moved from initcurses() because it core dumped on SGI, - where they're not defined until you've called initscr() */ -#define SetDictInt(string,ch) \ - do { \ - PyObject *o = PyLong_FromLong((long) (ch)); \ - if (o && PyDict_SetItemString(ModDict, string, o) == 0) { \ - Py_DECREF(o); \ - } \ - } while (0) - - /* Here are some graphic symbols you can use */ - SetDictInt("ACS_ULCORNER", (ACS_ULCORNER)); - SetDictInt("ACS_LLCORNER", (ACS_LLCORNER)); - SetDictInt("ACS_URCORNER", (ACS_URCORNER)); - SetDictInt("ACS_LRCORNER", (ACS_LRCORNER)); - SetDictInt("ACS_LTEE", (ACS_LTEE)); - SetDictInt("ACS_RTEE", (ACS_RTEE)); - SetDictInt("ACS_BTEE", (ACS_BTEE)); - SetDictInt("ACS_TTEE", (ACS_TTEE)); - SetDictInt("ACS_HLINE", (ACS_HLINE)); - SetDictInt("ACS_VLINE", (ACS_VLINE)); - SetDictInt("ACS_PLUS", (ACS_PLUS)); -#if !defined(__hpux) || defined(HAVE_NCURSES_H) - /* On HP/UX 11, these are of type cchar_t, which is not an - integral type. If this is a problem on more platforms, a - configure test should be added to determine whether ACS_S1 - is of integral type. */ - SetDictInt("ACS_S1", (ACS_S1)); - SetDictInt("ACS_S9", (ACS_S9)); - SetDictInt("ACS_DIAMOND", (ACS_DIAMOND)); - SetDictInt("ACS_CKBOARD", (ACS_CKBOARD)); - SetDictInt("ACS_DEGREE", (ACS_DEGREE)); - SetDictInt("ACS_PLMINUS", (ACS_PLMINUS)); - SetDictInt("ACS_BULLET", (ACS_BULLET)); - SetDictInt("ACS_LARROW", (ACS_LARROW)); - SetDictInt("ACS_RARROW", (ACS_RARROW)); - SetDictInt("ACS_DARROW", (ACS_DARROW)); - SetDictInt("ACS_UARROW", (ACS_UARROW)); - SetDictInt("ACS_BOARD", (ACS_BOARD)); - SetDictInt("ACS_LANTERN", (ACS_LANTERN)); - SetDictInt("ACS_BLOCK", (ACS_BLOCK)); -#endif - SetDictInt("ACS_BSSB", (ACS_ULCORNER)); - SetDictInt("ACS_SSBB", (ACS_LLCORNER)); - SetDictInt("ACS_BBSS", (ACS_URCORNER)); - SetDictInt("ACS_SBBS", (ACS_LRCORNER)); - SetDictInt("ACS_SBSS", (ACS_RTEE)); - SetDictInt("ACS_SSSB", (ACS_LTEE)); - SetDictInt("ACS_SSBS", (ACS_BTEE)); - SetDictInt("ACS_BSSS", (ACS_TTEE)); - SetDictInt("ACS_BSBS", (ACS_HLINE)); - SetDictInt("ACS_SBSB", (ACS_VLINE)); - SetDictInt("ACS_SSSS", (ACS_PLUS)); - - /* The following are never available with strict SYSV curses */ -#ifdef ACS_S3 - SetDictInt("ACS_S3", (ACS_S3)); -#endif -#ifdef ACS_S7 - SetDictInt("ACS_S7", (ACS_S7)); -#endif -#ifdef ACS_LEQUAL - SetDictInt("ACS_LEQUAL", (ACS_LEQUAL)); -#endif -#ifdef ACS_GEQUAL - SetDictInt("ACS_GEQUAL", (ACS_GEQUAL)); -#endif -#ifdef ACS_PI - SetDictInt("ACS_PI", (ACS_PI)); -#endif -#ifdef ACS_NEQUAL - SetDictInt("ACS_NEQUAL", (ACS_NEQUAL)); -#endif -#ifdef ACS_STERLING - SetDictInt("ACS_STERLING", (ACS_STERLING)); -#endif - - SetDictInt("LINES", LINES); - SetDictInt("COLS", COLS); - - winobj = (PyCursesWindowObject *)PyCursesWindow_New(win, NULL); - screen_encoding = winobj->encoding; - return (PyObject *)winobj; -} - -static PyObject * -PyCurses_setupterm(PyObject* self, PyObject *args, PyObject* keywds) -{ - int fd = -1; - int err; - char* termstr = NULL; - - static char *kwlist[] = {"term", "fd", NULL}; - - if (!PyArg_ParseTupleAndKeywords( - args, keywds, "|zi:setupterm", kwlist, &termstr, &fd)) { - return NULL; - } - - if (fd == -1) { - PyObject* sys_stdout; - - sys_stdout = PySys_GetObject("stdout"); - - if (sys_stdout == NULL || sys_stdout == Py_None) { - PyErr_SetString( - PyCursesError, - "lost sys.stdout"); - return NULL; - } - - fd = PyObject_AsFileDescriptor(sys_stdout); - - if (fd == -1) { - return NULL; - } - } - - if (!initialised_setupterm && setupterm(termstr,fd,&err) == ERR) { - char* s = "setupterm: unknown error"; - - if (err == 0) { - s = "setupterm: could not find terminal"; - } else if (err == -1) { - s = "setupterm: could not find terminfo database"; - } - - PyErr_SetString(PyCursesError,s); - return NULL; - } - - initialised_setupterm = TRUE; - - Py_INCREF(Py_None); - return Py_None; -} - -static PyObject * -PyCurses_IntrFlush(PyObject *self, PyObject *args) -{ - int ch; - - PyCursesInitialised; - - switch(PyTuple_Size(args)) { - case 1: - if (!PyArg_ParseTuple(args,"i;True(1), False(0)",&ch)) return NULL; - break; - default: - PyErr_SetString(PyExc_TypeError, "intrflush requires 1 argument"); - return NULL; - } - - return PyCursesCheckERR(intrflush(NULL,ch), "intrflush"); -} - -#ifdef HAVE_CURSES_IS_TERM_RESIZED -static PyObject * -PyCurses_Is_Term_Resized(PyObject *self, PyObject *args) -{ - int lines; - int columns; - int result; - - PyCursesInitialised; - - if (!PyArg_ParseTuple(args,"ii:is_term_resized", &lines, &columns)) - return NULL; - result = is_term_resized(lines, columns); - if (result == TRUE) { - Py_INCREF(Py_True); - return Py_True; - } else { - Py_INCREF(Py_False); - return Py_False; - } -} -#endif /* HAVE_CURSES_IS_TERM_RESIZED */ - -#if !defined(__NetBSD__) -static PyObject * -PyCurses_KeyName(PyObject *self, PyObject *args) -{ - const char *knp; - int ch; - - PyCursesInitialised; - - if (!PyArg_ParseTuple(args,"i",&ch)) return NULL; - - if (ch < 0) { - PyErr_SetString(PyExc_ValueError, "invalid key number"); - return NULL; - } - knp = keyname(ch); - - return PyBytes_FromString((knp == NULL) ? "" : knp); -} -#endif - -static PyObject * -PyCurses_KillChar(PyObject *self) -{ - char ch; - - ch = killchar(); - - return PyBytes_FromStringAndSize(&ch, 1); -} - -static PyObject * -PyCurses_Meta(PyObject *self, PyObject *args) -{ - int ch; - - PyCursesInitialised; - - switch(PyTuple_Size(args)) { - case 1: - if (!PyArg_ParseTuple(args,"i;True(1), False(0)",&ch)) return NULL; - break; - default: - PyErr_SetString(PyExc_TypeError, "meta requires 1 argument"); - return NULL; - } - - return PyCursesCheckERR(meta(stdscr, ch), "meta"); -} - -#ifdef NCURSES_MOUSE_VERSION -static PyObject * -PyCurses_MouseInterval(PyObject *self, PyObject *args) -{ - int interval; - PyCursesInitialised; - - if (!PyArg_ParseTuple(args,"i;interval",&interval)) - return NULL; - return PyCursesCheckERR(mouseinterval(interval), "mouseinterval"); -} - -static PyObject * -PyCurses_MouseMask(PyObject *self, PyObject *args) -{ - int newmask; - mmask_t oldmask, availmask; - - PyCursesInitialised; - if (!PyArg_ParseTuple(args,"i;mousemask",&newmask)) - return NULL; - availmask = mousemask(newmask, &oldmask); - return Py_BuildValue("(ll)", (long)availmask, (long)oldmask); -} -#endif - -static PyObject * -PyCurses_Napms(PyObject *self, PyObject *args) -{ - int ms; - - PyCursesInitialised; - if (!PyArg_ParseTuple(args, "i;ms", &ms)) return NULL; - - return Py_BuildValue("i", napms(ms)); -} - - -static PyObject * -PyCurses_NewPad(PyObject *self, PyObject *args) -{ - WINDOW *win; - int nlines, ncols; - - PyCursesInitialised; - - if (!PyArg_ParseTuple(args,"ii;nlines,ncols",&nlines,&ncols)) return NULL; - - win = newpad(nlines, ncols); - - if (win == NULL) { - PyErr_SetString(PyCursesError, catchall_NULL); - return NULL; - } - - return (PyObject *)PyCursesWindow_New(win, NULL); -} - -static PyObject * -PyCurses_NewWindow(PyObject *self, PyObject *args) -{ - WINDOW *win; - int nlines, ncols, begin_y=0, begin_x=0; - - PyCursesInitialised; - - switch (PyTuple_Size(args)) { - case 2: - if (!PyArg_ParseTuple(args,"ii;nlines,ncols",&nlines,&ncols)) - return NULL; - break; - case 4: - if (!PyArg_ParseTuple(args, "iiii;nlines,ncols,begin_y,begin_x", - &nlines,&ncols,&begin_y,&begin_x)) - return NULL; - break; - default: - PyErr_SetString(PyExc_TypeError, "newwin requires 2 or 4 arguments"); - return NULL; - } - - win = newwin(nlines,ncols,begin_y,begin_x); - if (win == NULL) { - PyErr_SetString(PyCursesError, catchall_NULL); - return NULL; - } - - return (PyObject *)PyCursesWindow_New(win, NULL); -} - -static PyObject * -PyCurses_Pair_Content(PyObject *self, PyObject *args) -{ - short pair,f,b; - - PyCursesInitialised; - PyCursesInitialisedColor; - - switch(PyTuple_Size(args)) { - case 1: - if (!PyArg_ParseTuple(args, "h;pair", &pair)) return NULL; - break; - default: - PyErr_SetString(PyExc_TypeError, "pair_content requires 1 argument"); - return NULL; - } - - if (pair_content(pair, &f, &b)==ERR) { - PyErr_SetString(PyCursesError, - "Argument 1 was out of range. (1..COLOR_PAIRS-1)"); - return NULL; - } - - return Py_BuildValue("(ii)", f, b); -} - -static PyObject * -PyCurses_pair_number(PyObject *self, PyObject *args) -{ - int n; - - PyCursesInitialised; - PyCursesInitialisedColor; - - switch(PyTuple_Size(args)) { - case 1: - if (!PyArg_ParseTuple(args, "i;pairvalue", &n)) return NULL; - break; - default: - PyErr_SetString(PyExc_TypeError, - "pair_number requires 1 argument"); - return NULL; - } - - return PyLong_FromLong((long) ((n & A_COLOR) >> 8)); -} - -static PyObject * -PyCurses_Putp(PyObject *self, PyObject *args) -{ - char *str; - - if (!PyArg_ParseTuple(args,"y;str", &str)) - return NULL; - return PyCursesCheckERR(putp(str), "putp"); -} - -static PyObject * -PyCurses_QiFlush(PyObject *self, PyObject *args) -{ - int flag = 0; - - PyCursesInitialised; - - switch(PyTuple_Size(args)) { - case 0: - qiflush(); - Py_INCREF(Py_None); - return Py_None; - case 1: - if (!PyArg_ParseTuple(args, "i;True(1) or False(0)", &flag)) return NULL; - if (flag) qiflush(); - else noqiflush(); - Py_INCREF(Py_None); - return Py_None; - default: - PyErr_SetString(PyExc_TypeError, "qiflush requires 0 or 1 arguments"); - return NULL; - } -} - -/* Internal helper used for updating curses.LINES, curses.COLS, _curses.LINES - * and _curses.COLS */ -#if defined(HAVE_CURSES_RESIZETERM) || defined(HAVE_CURSES_RESIZE_TERM) -static int -update_lines_cols(void) -{ - PyObject *o; - PyObject *m = PyImport_ImportModuleNoBlock("curses"); - _Py_IDENTIFIER(LINES); - _Py_IDENTIFIER(COLS); - - if (!m) - return 0; - - o = PyLong_FromLong(LINES); - if (!o) { - Py_DECREF(m); - return 0; - } - if (_PyObject_SetAttrId(m, &PyId_LINES, o)) { - Py_DECREF(m); - Py_DECREF(o); - return 0; - } - /* PyId_LINES.object will be initialized here. */ - if (PyDict_SetItem(ModDict, PyId_LINES.object, o)) { - Py_DECREF(m); - Py_DECREF(o); - return 0; - } - Py_DECREF(o); - o = PyLong_FromLong(COLS); - if (!o) { - Py_DECREF(m); - return 0; - } - if (_PyObject_SetAttrId(m, &PyId_COLS, o)) { - Py_DECREF(m); - Py_DECREF(o); - return 0; - } - if (PyDict_SetItem(ModDict, PyId_COLS.object, o)) { - Py_DECREF(m); - Py_DECREF(o); - return 0; - } - Py_DECREF(o); - Py_DECREF(m); - return 1; -} -#endif - -#ifdef HAVE_CURSES_RESIZETERM -static PyObject * -PyCurses_ResizeTerm(PyObject *self, PyObject *args) -{ - int lines; - int columns; - PyObject *result; - - PyCursesInitialised; - - if (!PyArg_ParseTuple(args,"ii:resizeterm", &lines, &columns)) - return NULL; - - result = PyCursesCheckERR(resizeterm(lines, columns), "resizeterm"); - if (!result) - return NULL; - if (!update_lines_cols()) - return NULL; - return result; -} - -#endif - -#ifdef HAVE_CURSES_RESIZE_TERM -static PyObject * -PyCurses_Resize_Term(PyObject *self, PyObject *args) -{ - int lines; - int columns; - - PyObject *result; - - PyCursesInitialised; - - if (!PyArg_ParseTuple(args,"ii:resize_term", &lines, &columns)) - return NULL; - - result = PyCursesCheckERR(resize_term(lines, columns), "resize_term"); - if (!result) - return NULL; - if (!update_lines_cols()) - return NULL; - return result; -} -#endif /* HAVE_CURSES_RESIZE_TERM */ - -static PyObject * -PyCurses_setsyx(PyObject *self, PyObject *args) -{ - int y,x; - - PyCursesInitialised; - - if (PyTuple_Size(args)!=2) { - PyErr_SetString(PyExc_TypeError, "setsyx requires 2 arguments"); - return NULL; - } - - if (!PyArg_ParseTuple(args, "ii;y, x", &y, &x)) return NULL; - - setsyx(y,x); - - Py_INCREF(Py_None); - return Py_None; -} - -static PyObject * -PyCurses_Start_Color(PyObject *self) -{ - int code; - PyObject *c, *cp; - - PyCursesInitialised; - - code = start_color(); - if (code != ERR) { - initialisedcolors = TRUE; - c = PyLong_FromLong((long) COLORS); - if (c == NULL) - return NULL; - PyDict_SetItemString(ModDict, "COLORS", c); - Py_DECREF(c); - cp = PyLong_FromLong((long) COLOR_PAIRS); - if (cp == NULL) - return NULL; - PyDict_SetItemString(ModDict, "COLOR_PAIRS", cp); - Py_DECREF(cp); - Py_INCREF(Py_None); - return Py_None; - } else { - PyErr_SetString(PyCursesError, "start_color() returned ERR"); - return NULL; - } -} - -static PyObject * -PyCurses_tigetflag(PyObject *self, PyObject *args) -{ - char *capname; - - PyCursesSetupTermCalled; - - if (!PyArg_ParseTuple(args, "s", &capname)) - return NULL; - - return PyLong_FromLong( (long) tigetflag( capname ) ); -} - -static PyObject * -PyCurses_tigetnum(PyObject *self, PyObject *args) -{ - char *capname; - - PyCursesSetupTermCalled; - - if (!PyArg_ParseTuple(args, "s", &capname)) - return NULL; - - return PyLong_FromLong( (long) tigetnum( capname ) ); -} - -static PyObject * -PyCurses_tigetstr(PyObject *self, PyObject *args) -{ - char *capname; - - PyCursesSetupTermCalled; - - if (!PyArg_ParseTuple(args, "s", &capname)) - return NULL; - - capname = tigetstr( capname ); - if (capname == 0 || capname == (char*) -1) { - Py_INCREF(Py_None); - return Py_None; - } - return PyBytes_FromString( capname ); -} - -static PyObject * -PyCurses_tparm(PyObject *self, PyObject *args) -{ - char* fmt; - char* result = NULL; - int i1=0,i2=0,i3=0,i4=0,i5=0,i6=0,i7=0,i8=0,i9=0; - - PyCursesSetupTermCalled; - - if (!PyArg_ParseTuple(args, "y|iiiiiiiii:tparm", - &fmt, &i1, &i2, &i3, &i4, - &i5, &i6, &i7, &i8, &i9)) { - return NULL; - } - - result = tparm(fmt,i1,i2,i3,i4,i5,i6,i7,i8,i9); - if (!result) { - PyErr_SetString(PyCursesError, "tparm() returned NULL"); - return NULL; - } - - return PyBytes_FromString(result); -} - -static PyObject * -PyCurses_TypeAhead(PyObject *self, PyObject *args) -{ - int fd; - - PyCursesInitialised; - - if (!PyArg_ParseTuple(args,"i;fd",&fd)) return NULL; - - return PyCursesCheckERR(typeahead( fd ), "typeahead"); -} - -static PyObject * -PyCurses_UnCtrl(PyObject *self, PyObject *args) -{ - PyObject *temp; - chtype ch; - - PyCursesInitialised; - - if (!PyArg_ParseTuple(args,"O;ch or int",&temp)) return NULL; - - if (!PyCurses_ConvertToChtype(NULL, temp, &ch)) - return NULL; - - return PyBytes_FromString(unctrl(ch)); -} - -static PyObject * -PyCurses_UngetCh(PyObject *self, PyObject *args) -{ - PyObject *temp; - chtype ch; - - PyCursesInitialised; - - if (!PyArg_ParseTuple(args,"O;ch or int",&temp)) - return NULL; - - if (!PyCurses_ConvertToChtype(NULL, temp, &ch)) - return NULL; - - return PyCursesCheckERR(ungetch(ch), "ungetch"); -} - -#ifdef HAVE_NCURSESW -/* Convert an object to a character (wchar_t): - - - int - - str of length 1 - - Return 1 on success, 0 on error. */ -static int -PyCurses_ConvertToWchar_t(PyObject *obj, - wchar_t *wch) -{ - if (PyUnicode_Check(obj)) { - wchar_t buffer[2]; - if (PyUnicode_AsWideChar(obj, buffer, 2) != 1) { - PyErr_Format(PyExc_TypeError, - "expect bytes or str of length 1, or int, " - "got a str of length %zi", - PyUnicode_GET_LENGTH(obj)); - return 0; - } - *wch = buffer[0]; - return 2; - } - else if (PyLong_CheckExact(obj)) { - long value; - int overflow; - value = PyLong_AsLongAndOverflow(obj, &overflow); - if (overflow) { - PyErr_SetString(PyExc_OverflowError, - "int doesn't fit in long"); - return 0; - } - *wch = (wchar_t)value; - if ((long)*wch != value) { - PyErr_Format(PyExc_OverflowError, - "character doesn't fit in wchar_t"); - return 0; - } - return 1; - } - else { - PyErr_Format(PyExc_TypeError, - "expect bytes or str of length 1, or int, got %s", - Py_TYPE(obj)->tp_name); - return 0; - } -} - -static PyObject * -PyCurses_Unget_Wch(PyObject *self, PyObject *args) -{ - PyObject *obj; - wchar_t wch; - - PyCursesInitialised; - - if (!PyArg_ParseTuple(args,"O", &obj)) - return NULL; - - if (!PyCurses_ConvertToWchar_t(obj, &wch)) - return NULL; - return PyCursesCheckERR(unget_wch(wch), "unget_wch"); -} -#endif - -static PyObject * -PyCurses_Use_Env(PyObject *self, PyObject *args) -{ - int flag; - - switch(PyTuple_Size(args)) { - case 1: - if (!PyArg_ParseTuple(args,"i;True(1), False(0)",&flag)) - return NULL; - break; - default: - PyErr_SetString(PyExc_TypeError, "use_env requires 1 argument"); - return NULL; - } - use_env(flag); - Py_INCREF(Py_None); - return Py_None; -} - -#ifndef STRICT_SYSV_CURSES -static PyObject * -PyCurses_Use_Default_Colors(PyObject *self) -{ - int code; - - PyCursesInitialised; - PyCursesInitialisedColor; - - code = use_default_colors(); - if (code != ERR) { - Py_INCREF(Py_None); - return Py_None; - } else { - PyErr_SetString(PyCursesError, "use_default_colors() returned ERR"); - return NULL; - } -} -#endif /* STRICT_SYSV_CURSES */ - -/* List of functions defined in the module */ - -static PyMethodDef PyCurses_methods[] = { - {"baudrate", (PyCFunction)PyCurses_baudrate, METH_NOARGS}, - {"beep", (PyCFunction)PyCurses_beep, METH_NOARGS}, - {"can_change_color", (PyCFunction)PyCurses_can_change_color, METH_NOARGS}, - {"cbreak", (PyCFunction)PyCurses_cbreak, METH_VARARGS}, - {"color_content", (PyCFunction)PyCurses_Color_Content, METH_VARARGS}, - {"color_pair", (PyCFunction)PyCurses_color_pair, METH_VARARGS}, - {"curs_set", (PyCFunction)PyCurses_Curs_Set, METH_VARARGS}, - {"def_prog_mode", (PyCFunction)PyCurses_def_prog_mode, METH_NOARGS}, - {"def_shell_mode", (PyCFunction)PyCurses_def_shell_mode, METH_NOARGS}, - {"delay_output", (PyCFunction)PyCurses_Delay_Output, METH_VARARGS}, - {"doupdate", (PyCFunction)PyCurses_doupdate, METH_NOARGS}, - {"echo", (PyCFunction)PyCurses_echo, METH_VARARGS}, - {"endwin", (PyCFunction)PyCurses_endwin, METH_NOARGS}, - {"erasechar", (PyCFunction)PyCurses_EraseChar, METH_NOARGS}, - {"filter", (PyCFunction)PyCurses_filter, METH_NOARGS}, - {"flash", (PyCFunction)PyCurses_flash, METH_NOARGS}, - {"flushinp", (PyCFunction)PyCurses_flushinp, METH_NOARGS}, -#ifdef NCURSES_MOUSE_VERSION - {"getmouse", (PyCFunction)PyCurses_GetMouse, METH_NOARGS}, - {"ungetmouse", (PyCFunction)PyCurses_UngetMouse, METH_VARARGS}, -#endif - {"getsyx", (PyCFunction)PyCurses_getsyx, METH_NOARGS}, - {"getwin", (PyCFunction)PyCurses_GetWin, METH_O}, - {"has_colors", (PyCFunction)PyCurses_has_colors, METH_NOARGS}, - {"has_ic", (PyCFunction)PyCurses_has_ic, METH_NOARGS}, - {"has_il", (PyCFunction)PyCurses_has_il, METH_NOARGS}, -#ifndef STRICT_SYSV_CURSES - {"has_key", (PyCFunction)PyCurses_has_key, METH_VARARGS}, -#endif - {"halfdelay", (PyCFunction)PyCurses_HalfDelay, METH_VARARGS}, - {"init_color", (PyCFunction)PyCurses_Init_Color, METH_VARARGS}, - {"init_pair", (PyCFunction)PyCurses_Init_Pair, METH_VARARGS}, - {"initscr", (PyCFunction)PyCurses_InitScr, METH_NOARGS}, - {"intrflush", (PyCFunction)PyCurses_IntrFlush, METH_VARARGS}, - {"isendwin", (PyCFunction)PyCurses_isendwin, METH_NOARGS}, -#ifdef HAVE_CURSES_IS_TERM_RESIZED - {"is_term_resized", (PyCFunction)PyCurses_Is_Term_Resized, METH_VARARGS}, -#endif -#if !defined(__NetBSD__) - {"keyname", (PyCFunction)PyCurses_KeyName, METH_VARARGS}, -#endif - {"killchar", (PyCFunction)PyCurses_KillChar, METH_NOARGS}, - {"longname", (PyCFunction)PyCurses_longname, METH_NOARGS}, - {"meta", (PyCFunction)PyCurses_Meta, METH_VARARGS}, -#ifdef NCURSES_MOUSE_VERSION - {"mouseinterval", (PyCFunction)PyCurses_MouseInterval, METH_VARARGS}, - {"mousemask", (PyCFunction)PyCurses_MouseMask, METH_VARARGS}, -#endif - {"napms", (PyCFunction)PyCurses_Napms, METH_VARARGS}, - {"newpad", (PyCFunction)PyCurses_NewPad, METH_VARARGS}, - {"newwin", (PyCFunction)PyCurses_NewWindow, METH_VARARGS}, - {"nl", (PyCFunction)PyCurses_nl, METH_VARARGS}, - {"nocbreak", (PyCFunction)PyCurses_nocbreak, METH_NOARGS}, - {"noecho", (PyCFunction)PyCurses_noecho, METH_NOARGS}, - {"nonl", (PyCFunction)PyCurses_nonl, METH_NOARGS}, - {"noqiflush", (PyCFunction)PyCurses_noqiflush, METH_NOARGS}, - {"noraw", (PyCFunction)PyCurses_noraw, METH_NOARGS}, - {"pair_content", (PyCFunction)PyCurses_Pair_Content, METH_VARARGS}, - {"pair_number", (PyCFunction)PyCurses_pair_number, METH_VARARGS}, - {"putp", (PyCFunction)PyCurses_Putp, METH_VARARGS}, - {"qiflush", (PyCFunction)PyCurses_QiFlush, METH_VARARGS}, - {"raw", (PyCFunction)PyCurses_raw, METH_VARARGS}, - {"reset_prog_mode", (PyCFunction)PyCurses_reset_prog_mode, METH_NOARGS}, - {"reset_shell_mode", (PyCFunction)PyCurses_reset_shell_mode, METH_NOARGS}, - {"resetty", (PyCFunction)PyCurses_resetty, METH_NOARGS}, -#ifdef HAVE_CURSES_RESIZETERM - {"resizeterm", (PyCFunction)PyCurses_ResizeTerm, METH_VARARGS}, -#endif -#ifdef HAVE_CURSES_RESIZE_TERM - {"resize_term", (PyCFunction)PyCurses_Resize_Term, METH_VARARGS}, -#endif - {"savetty", (PyCFunction)PyCurses_savetty, METH_NOARGS}, - {"setsyx", (PyCFunction)PyCurses_setsyx, METH_VARARGS}, - {"setupterm", (PyCFunction)PyCurses_setupterm, - METH_VARARGS|METH_KEYWORDS}, - {"start_color", (PyCFunction)PyCurses_Start_Color, METH_NOARGS}, - {"termattrs", (PyCFunction)PyCurses_termattrs, METH_NOARGS}, - {"termname", (PyCFunction)PyCurses_termname, METH_NOARGS}, - {"tigetflag", (PyCFunction)PyCurses_tigetflag, METH_VARARGS}, - {"tigetnum", (PyCFunction)PyCurses_tigetnum, METH_VARARGS}, - {"tigetstr", (PyCFunction)PyCurses_tigetstr, METH_VARARGS}, - {"tparm", (PyCFunction)PyCurses_tparm, METH_VARARGS}, - {"typeahead", (PyCFunction)PyCurses_TypeAhead, METH_VARARGS}, - {"unctrl", (PyCFunction)PyCurses_UnCtrl, METH_VARARGS}, - {"ungetch", (PyCFunction)PyCurses_UngetCh, METH_VARARGS}, -#ifdef HAVE_NCURSESW - {"unget_wch", (PyCFunction)PyCurses_Unget_Wch, METH_VARARGS}, -#endif - {"use_env", (PyCFunction)PyCurses_Use_Env, METH_VARARGS}, -#ifndef STRICT_SYSV_CURSES - {"use_default_colors", (PyCFunction)PyCurses_Use_Default_Colors, METH_NOARGS}, -#endif - {NULL, NULL} /* sentinel */ -}; - -/* Initialization function for the module */ - - -static struct PyModuleDef _cursesmodule = { - PyModuleDef_HEAD_INIT, - "_curses", - NULL, - -1, - PyCurses_methods, - NULL, - NULL, - NULL, - NULL -}; - -PyMODINIT_FUNC -PyInit__curses(void) -{ - PyObject *m, *d, *v, *c_api_object; - static void *PyCurses_API[PyCurses_API_pointers]; - - /* Initialize object type */ - if (PyType_Ready(&PyCursesWindow_Type) < 0) - return NULL; - - /* Initialize the C API pointer array */ - PyCurses_API[0] = (void *)&PyCursesWindow_Type; - PyCurses_API[1] = (void *)func_PyCursesSetupTermCalled; - PyCurses_API[2] = (void *)func_PyCursesInitialised; - PyCurses_API[3] = (void *)func_PyCursesInitialisedColor; - - /* Create the module and add the functions */ - m = PyModule_Create(&_cursesmodule); - if (m == NULL) - return NULL; - - /* Add some symbolic constants to the module */ - d = PyModule_GetDict(m); - if (d == NULL) - return NULL; - ModDict = d; /* For PyCurses_InitScr to use later */ - - /* Add a capsule for the C API */ - c_api_object = PyCapsule_New(PyCurses_API, PyCurses_CAPSULE_NAME, NULL); - PyDict_SetItemString(d, "_C_API", c_api_object); - Py_DECREF(c_api_object); - - /* For exception curses.error */ - PyCursesError = PyErr_NewException("_curses.error", NULL, NULL); - PyDict_SetItemString(d, "error", PyCursesError); - - /* Make the version available */ - v = PyBytes_FromString(PyCursesVersion); - PyDict_SetItemString(d, "version", v); - PyDict_SetItemString(d, "__version__", v); - Py_DECREF(v); - - SetDictInt("ERR", ERR); - SetDictInt("OK", OK); - - /* Here are some attributes you can add to chars to print */ - - SetDictInt("A_ATTRIBUTES", A_ATTRIBUTES); - SetDictInt("A_NORMAL", A_NORMAL); - SetDictInt("A_STANDOUT", A_STANDOUT); - SetDictInt("A_UNDERLINE", A_UNDERLINE); - SetDictInt("A_REVERSE", A_REVERSE); - SetDictInt("A_BLINK", A_BLINK); - SetDictInt("A_DIM", A_DIM); - SetDictInt("A_BOLD", A_BOLD); - SetDictInt("A_ALTCHARSET", A_ALTCHARSET); -#if !defined(__NetBSD__) - SetDictInt("A_INVIS", A_INVIS); -#endif - SetDictInt("A_PROTECT", A_PROTECT); - SetDictInt("A_CHARTEXT", A_CHARTEXT); - SetDictInt("A_COLOR", A_COLOR); - - /* The following are never available with strict SYSV curses */ -#ifdef A_HORIZONTAL - SetDictInt("A_HORIZONTAL", A_HORIZONTAL); -#endif -#ifdef A_LEFT - SetDictInt("A_LEFT", A_LEFT); -#endif -#ifdef A_LOW - SetDictInt("A_LOW", A_LOW); -#endif -#ifdef A_RIGHT - SetDictInt("A_RIGHT", A_RIGHT); -#endif -#ifdef A_TOP - SetDictInt("A_TOP", A_TOP); -#endif -#ifdef A_VERTICAL - SetDictInt("A_VERTICAL", A_VERTICAL); -#endif - - SetDictInt("COLOR_BLACK", COLOR_BLACK); - SetDictInt("COLOR_RED", COLOR_RED); - SetDictInt("COLOR_GREEN", COLOR_GREEN); - SetDictInt("COLOR_YELLOW", COLOR_YELLOW); - SetDictInt("COLOR_BLUE", COLOR_BLUE); - SetDictInt("COLOR_MAGENTA", COLOR_MAGENTA); - SetDictInt("COLOR_CYAN", COLOR_CYAN); - SetDictInt("COLOR_WHITE", COLOR_WHITE); - -#ifdef NCURSES_MOUSE_VERSION - /* Mouse-related constants */ - SetDictInt("BUTTON1_PRESSED", BUTTON1_PRESSED); - SetDictInt("BUTTON1_RELEASED", BUTTON1_RELEASED); - SetDictInt("BUTTON1_CLICKED", BUTTON1_CLICKED); - SetDictInt("BUTTON1_DOUBLE_CLICKED", BUTTON1_DOUBLE_CLICKED); - SetDictInt("BUTTON1_TRIPLE_CLICKED", BUTTON1_TRIPLE_CLICKED); - - SetDictInt("BUTTON2_PRESSED", BUTTON2_PRESSED); - SetDictInt("BUTTON2_RELEASED", BUTTON2_RELEASED); - SetDictInt("BUTTON2_CLICKED", BUTTON2_CLICKED); - SetDictInt("BUTTON2_DOUBLE_CLICKED", BUTTON2_DOUBLE_CLICKED); - SetDictInt("BUTTON2_TRIPLE_CLICKED", BUTTON2_TRIPLE_CLICKED); - - SetDictInt("BUTTON3_PRESSED", BUTTON3_PRESSED); - SetDictInt("BUTTON3_RELEASED", BUTTON3_RELEASED); - SetDictInt("BUTTON3_CLICKED", BUTTON3_CLICKED); - SetDictInt("BUTTON3_DOUBLE_CLICKED", BUTTON3_DOUBLE_CLICKED); - SetDictInt("BUTTON3_TRIPLE_CLICKED", BUTTON3_TRIPLE_CLICKED); - - SetDictInt("BUTTON4_PRESSED", BUTTON4_PRESSED); - SetDictInt("BUTTON4_RELEASED", BUTTON4_RELEASED); - SetDictInt("BUTTON4_CLICKED", BUTTON4_CLICKED); - SetDictInt("BUTTON4_DOUBLE_CLICKED", BUTTON4_DOUBLE_CLICKED); - SetDictInt("BUTTON4_TRIPLE_CLICKED", BUTTON4_TRIPLE_CLICKED); - - SetDictInt("BUTTON_SHIFT", BUTTON_SHIFT); - SetDictInt("BUTTON_CTRL", BUTTON_CTRL); - SetDictInt("BUTTON_ALT", BUTTON_ALT); - - SetDictInt("ALL_MOUSE_EVENTS", ALL_MOUSE_EVENTS); - SetDictInt("REPORT_MOUSE_POSITION", REPORT_MOUSE_POSITION); -#endif - /* Now set everything up for KEY_ variables */ - { - int key; - char *key_n; - char *key_n2; -#if !defined(__NetBSD__) - for (key=KEY_MIN;key < KEY_MAX; key++) { - key_n = (char *)keyname(key); - if (key_n == NULL || strcmp(key_n,"UNKNOWN KEY")==0) - continue; - if (strncmp(key_n,"KEY_F(",6)==0) { - char *p1, *p2; - key_n2 = PyMem_Malloc(strlen(key_n)+1); - if (!key_n2) { - PyErr_NoMemory(); - break; - } - p1 = key_n; - p2 = key_n2; - while (*p1) { - if (*p1 != '(' && *p1 != ')') { - *p2 = *p1; - p2++; - } - p1++; - } - *p2 = (char)0; - } else - key_n2 = key_n; - SetDictInt(key_n2,key); - if (key_n2 != key_n) - PyMem_Free(key_n2); - } -#endif - SetDictInt("KEY_MIN", KEY_MIN); - SetDictInt("KEY_MAX", KEY_MAX); - } - return m; -} +/*[clinic end generated code: output=660ab0ae6d8fbdda input=a9049054013a1b77]*/ diff --git a/Modules/_datetimemodule.c b/Modules/clinic/_datetimemodule.c.h copy from Modules/_datetimemodule.c copy to Modules/clinic/_datetimemodule.c.h --- a/Modules/_datetimemodule.c +++ b/Modules/clinic/_datetimemodule.c.h @@ -1,4136 +1,5 @@ -/* C implementation for the date/time type documented at - * http://www.zope.org/Members/fdrake/DateTimeWiki/FrontPage - */ - -#include "Python.h" -#include "structmember.h" - -#include - -#ifdef MS_WINDOWS -# include /* struct timeval */ -#endif - -/* Differentiate between building the core module and building extension - * modules. - */ -#ifndef Py_BUILD_CORE -#define Py_BUILD_CORE -#endif -#include "datetime.h" -#undef Py_BUILD_CORE - /*[clinic input] -module datetime -class datetime.datetime "PyDateTime_DateTime *" "&PyDateTime_DateTimeType" -[clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=78142cb64b9e98bc]*/ - -/* We require that C int be at least 32 bits, and use int virtually - * everywhere. In just a few cases we use a temp long, where a Python - * API returns a C long. In such cases, we have to ensure that the - * final result fits in a C int (this can be an issue on 64-bit boxes). - */ -#if SIZEOF_INT < 4 -# error "_datetime.c requires that C int have at least 32 bits" -#endif - -#define MINYEAR 1 -#define MAXYEAR 9999 -#define MAXORDINAL 3652059 /* date(9999,12,31).toordinal() */ - -/* Nine decimal digits is easy to communicate, and leaves enough room - * so that two delta days can be added w/o fear of overflowing a signed - * 32-bit int, and with plenty of room left over to absorb any possible - * carries from adding seconds. - */ -#define MAX_DELTA_DAYS 999999999 - -/* Rename the long macros in datetime.h to more reasonable short names. */ -#define GET_YEAR PyDateTime_GET_YEAR -#define GET_MONTH PyDateTime_GET_MONTH -#define GET_DAY PyDateTime_GET_DAY -#define DATE_GET_HOUR PyDateTime_DATE_GET_HOUR -#define DATE_GET_MINUTE PyDateTime_DATE_GET_MINUTE -#define DATE_GET_SECOND PyDateTime_DATE_GET_SECOND -#define DATE_GET_MICROSECOND PyDateTime_DATE_GET_MICROSECOND - -/* Date accessors for date and datetime. */ -#define SET_YEAR(o, v) (((o)->data[0] = ((v) & 0xff00) >> 8), \ - ((o)->data[1] = ((v) & 0x00ff))) -#define SET_MONTH(o, v) (PyDateTime_GET_MONTH(o) = (v)) -#define SET_DAY(o, v) (PyDateTime_GET_DAY(o) = (v)) - -/* Date/Time accessors for datetime. */ -#define DATE_SET_HOUR(o, v) (PyDateTime_DATE_GET_HOUR(o) = (v)) -#define DATE_SET_MINUTE(o, v) (PyDateTime_DATE_GET_MINUTE(o) = (v)) -#define DATE_SET_SECOND(o, v) (PyDateTime_DATE_GET_SECOND(o) = (v)) -#define DATE_SET_MICROSECOND(o, v) \ - (((o)->data[7] = ((v) & 0xff0000) >> 16), \ - ((o)->data[8] = ((v) & 0x00ff00) >> 8), \ - ((o)->data[9] = ((v) & 0x0000ff))) - -/* Time accessors for time. */ -#define TIME_GET_HOUR PyDateTime_TIME_GET_HOUR -#define TIME_GET_MINUTE PyDateTime_TIME_GET_MINUTE -#define TIME_GET_SECOND PyDateTime_TIME_GET_SECOND -#define TIME_GET_MICROSECOND PyDateTime_TIME_GET_MICROSECOND -#define TIME_SET_HOUR(o, v) (PyDateTime_TIME_GET_HOUR(o) = (v)) -#define TIME_SET_MINUTE(o, v) (PyDateTime_TIME_GET_MINUTE(o) = (v)) -#define TIME_SET_SECOND(o, v) (PyDateTime_TIME_GET_SECOND(o) = (v)) -#define TIME_SET_MICROSECOND(o, v) \ - (((o)->data[3] = ((v) & 0xff0000) >> 16), \ - ((o)->data[4] = ((v) & 0x00ff00) >> 8), \ - ((o)->data[5] = ((v) & 0x0000ff))) - -/* Delta accessors for timedelta. */ -#define GET_TD_DAYS(o) (((PyDateTime_Delta *)(o))->days) -#define GET_TD_SECONDS(o) (((PyDateTime_Delta *)(o))->seconds) -#define GET_TD_MICROSECONDS(o) (((PyDateTime_Delta *)(o))->microseconds) - -#define SET_TD_DAYS(o, v) ((o)->days = (v)) -#define SET_TD_SECONDS(o, v) ((o)->seconds = (v)) -#define SET_TD_MICROSECONDS(o, v) ((o)->microseconds = (v)) - -/* p is a pointer to a time or a datetime object; HASTZINFO(p) returns - * p->hastzinfo. - */ -#define HASTZINFO(p) (((_PyDateTime_BaseTZInfo *)(p))->hastzinfo) -#define GET_TIME_TZINFO(p) (HASTZINFO(p) ? \ - ((PyDateTime_Time *)(p))->tzinfo : Py_None) -#define GET_DT_TZINFO(p) (HASTZINFO(p) ? \ - ((PyDateTime_DateTime *)(p))->tzinfo : Py_None) -/* M is a char or int claiming to be a valid month. The macro is equivalent - * to the two-sided Python test - * 1 <= M <= 12 - */ -#define MONTH_IS_SANE(M) ((unsigned int)(M) - 1 < 12) - -/* Forward declarations. */ -static PyTypeObject PyDateTime_DateType; -static PyTypeObject PyDateTime_DateTimeType; -static PyTypeObject PyDateTime_DeltaType; -static PyTypeObject PyDateTime_TimeType; -static PyTypeObject PyDateTime_TZInfoType; -static PyTypeObject PyDateTime_TimeZoneType; - -_Py_IDENTIFIER(as_integer_ratio); -_Py_IDENTIFIER(fromutc); -_Py_IDENTIFIER(isoformat); -_Py_IDENTIFIER(strftime); - -/* --------------------------------------------------------------------------- - * Math utilities. - */ - -/* k = i+j overflows iff k differs in sign from both inputs, - * iff k^i has sign bit set and k^j has sign bit set, - * iff (k^i)&(k^j) has sign bit set. - */ -#define SIGNED_ADD_OVERFLOWED(RESULT, I, J) \ - ((((RESULT) ^ (I)) & ((RESULT) ^ (J))) < 0) - -/* Compute Python divmod(x, y), returning the quotient and storing the - * remainder into *r. The quotient is the floor of x/y, and that's - * the real point of this. C will probably truncate instead (C99 - * requires truncation; C89 left it implementation-defined). - * Simplification: we *require* that y > 0 here. That's appropriate - * for all the uses made of it. This simplifies the code and makes - * the overflow case impossible (divmod(LONG_MIN, -1) is the only - * overflow case). - */ -static int -divmod(int x, int y, int *r) -{ - int quo; - - assert(y > 0); - quo = x / y; - *r = x - quo * y; - if (*r < 0) { - --quo; - *r += y; - } - assert(0 <= *r && *r < y); - return quo; -} - -/* Nearest integer to m / n for integers m and n. Half-integer results - * are rounded to even. - */ -static PyObject * -divide_nearest(PyObject *m, PyObject *n) -{ - PyObject *result; - PyObject *temp; - - temp = _PyLong_DivmodNear(m, n); - if (temp == NULL) - return NULL; - result = PyTuple_GET_ITEM(temp, 0); - Py_INCREF(result); - Py_DECREF(temp); - - return result; -} - -/* --------------------------------------------------------------------------- - * General calendrical helper functions - */ - -/* For each month ordinal in 1..12, the number of days in that month, - * and the number of days before that month in the same year. These - * are correct for non-leap years only. - */ -static int _days_in_month[] = { - 0, /* unused; this vector uses 1-based indexing */ - 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 -}; - -static int _days_before_month[] = { - 0, /* unused; this vector uses 1-based indexing */ - 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 -}; - -/* year -> 1 if leap year, else 0. */ -static int -is_leap(int year) -{ - /* Cast year to unsigned. The result is the same either way, but - * C can generate faster code for unsigned mod than for signed - * mod (especially for % 4 -- a good compiler should just grab - * the last 2 bits when the LHS is unsigned). - */ - const unsigned int ayear = (unsigned int)year; - return ayear % 4 == 0 && (ayear % 100 != 0 || ayear % 400 == 0); -} - -/* year, month -> number of days in that month in that year */ -static int -days_in_month(int year, int month) -{ - assert(month >= 1); - assert(month <= 12); - if (month == 2 && is_leap(year)) - return 29; - else - return _days_in_month[month]; -} - -/* year, month -> number of days in year preceeding first day of month */ -static int -days_before_month(int year, int month) -{ - int days; - - assert(month >= 1); - assert(month <= 12); - days = _days_before_month[month]; - if (month > 2 && is_leap(year)) - ++days; - return days; -} - -/* year -> number of days before January 1st of year. Remember that we - * start with year 1, so days_before_year(1) == 0. - */ -static int -days_before_year(int year) -{ - int y = year - 1; - /* This is incorrect if year <= 0; we really want the floor - * here. But so long as MINYEAR is 1, the smallest year this - * can see is 1. - */ - assert (year >= 1); - return y*365 + y/4 - y/100 + y/400; -} - -/* Number of days in 4, 100, and 400 year cycles. That these have - * the correct values is asserted in the module init function. - */ -#define DI4Y 1461 /* days_before_year(5); days in 4 years */ -#define DI100Y 36524 /* days_before_year(101); days in 100 years */ -#define DI400Y 146097 /* days_before_year(401); days in 400 years */ - -/* ordinal -> year, month, day, considering 01-Jan-0001 as day 1. */ -static void -ord_to_ymd(int ordinal, int *year, int *month, int *day) -{ - int n, n1, n4, n100, n400, leapyear, preceding; - - /* ordinal is a 1-based index, starting at 1-Jan-1. The pattern of - * leap years repeats exactly every 400 years. The basic strategy is - * to find the closest 400-year boundary at or before ordinal, then - * work with the offset from that boundary to ordinal. Life is much - * clearer if we subtract 1 from ordinal first -- then the values - * of ordinal at 400-year boundaries are exactly those divisible - * by DI400Y: - * - * D M Y n n-1 - * -- --- ---- ---------- ---------------- - * 31 Dec -400 -DI400Y -DI400Y -1 - * 1 Jan -399 -DI400Y +1 -DI400Y 400-year boundary - * ... - * 30 Dec 000 -1 -2 - * 31 Dec 000 0 -1 - * 1 Jan 001 1 0 400-year boundary - * 2 Jan 001 2 1 - * 3 Jan 001 3 2 - * ... - * 31 Dec 400 DI400Y DI400Y -1 - * 1 Jan 401 DI400Y +1 DI400Y 400-year boundary - */ - assert(ordinal >= 1); - --ordinal; - n400 = ordinal / DI400Y; - n = ordinal % DI400Y; - *year = n400 * 400 + 1; - - /* Now n is the (non-negative) offset, in days, from January 1 of - * year, to the desired date. Now compute how many 100-year cycles - * precede n. - * Note that it's possible for n100 to equal 4! In that case 4 full - * 100-year cycles precede the desired day, which implies the - * desired day is December 31 at the end of a 400-year cycle. - */ - n100 = n / DI100Y; - n = n % DI100Y; - - /* Now compute how many 4-year cycles precede it. */ - n4 = n / DI4Y; - n = n % DI4Y; - - /* And now how many single years. Again n1 can be 4, and again - * meaning that the desired day is December 31 at the end of the - * 4-year cycle. - */ - n1 = n / 365; - n = n % 365; - - *year += n100 * 100 + n4 * 4 + n1; - if (n1 == 4 || n100 == 4) { - assert(n == 0); - *year -= 1; - *month = 12; - *day = 31; - return; - } - - /* Now the year is correct, and n is the offset from January 1. We - * find the month via an estimate that's either exact or one too - * large. - */ - leapyear = n1 == 3 && (n4 != 24 || n100 == 3); - assert(leapyear == is_leap(*year)); - *month = (n + 50) >> 5; - preceding = (_days_before_month[*month] + (*month > 2 && leapyear)); - if (preceding > n) { - /* estimate is too large */ - *month -= 1; - preceding -= days_in_month(*year, *month); - } - n -= preceding; - assert(0 <= n); - assert(n < days_in_month(*year, *month)); - - *day = n + 1; -} - -/* year, month, day -> ordinal, considering 01-Jan-0001 as day 1. */ -static int -ymd_to_ord(int year, int month, int day) -{ - return days_before_year(year) + days_before_month(year, month) + day; -} - -/* Day of week, where Monday==0, ..., Sunday==6. 1/1/1 was a Monday. */ -static int -weekday(int year, int month, int day) -{ - return (ymd_to_ord(year, month, day) + 6) % 7; -} - -/* Ordinal of the Monday starting week 1 of the ISO year. Week 1 is the - * first calendar week containing a Thursday. - */ -static int -iso_week1_monday(int year) -{ - int first_day = ymd_to_ord(year, 1, 1); /* ord of 1/1 */ - /* 0 if 1/1 is a Monday, 1 if a Tue, etc. */ - int first_weekday = (first_day + 6) % 7; - /* ordinal of closest Monday at or before 1/1 */ - int week1_monday = first_day - first_weekday; - - if (first_weekday > 3) /* if 1/1 was Fri, Sat, Sun */ - week1_monday += 7; - return week1_monday; -} - -/* --------------------------------------------------------------------------- - * Range checkers. - */ - -/* Check that -MAX_DELTA_DAYS <= days <= MAX_DELTA_DAYS. If so, return 0. - * If not, raise OverflowError and return -1. - */ -static int -check_delta_day_range(int days) -{ - if (-MAX_DELTA_DAYS <= days && days <= MAX_DELTA_DAYS) - return 0; - PyErr_Format(PyExc_OverflowError, - "days=%d; must have magnitude <= %d", - days, MAX_DELTA_DAYS); - return -1; -} - -/* Check that date arguments are in range. Return 0 if they are. If they - * aren't, raise ValueError and return -1. - */ -static int -check_date_args(int year, int month, int day) -{ - - if (year < MINYEAR || year > MAXYEAR) { - PyErr_SetString(PyExc_ValueError, - "year is out of range"); - return -1; - } - if (month < 1 || month > 12) { - PyErr_SetString(PyExc_ValueError, - "month must be in 1..12"); - return -1; - } - if (day < 1 || day > days_in_month(year, month)) { - PyErr_SetString(PyExc_ValueError, - "day is out of range for month"); - return -1; - } - return 0; -} - -/* Check that time arguments are in range. Return 0 if they are. If they - * aren't, raise ValueError and return -1. - */ -static int -check_time_args(int h, int m, int s, int us) -{ - if (h < 0 || h > 23) { - PyErr_SetString(PyExc_ValueError, - "hour must be in 0..23"); - return -1; - } - if (m < 0 || m > 59) { - PyErr_SetString(PyExc_ValueError, - "minute must be in 0..59"); - return -1; - } - if (s < 0 || s > 59) { - PyErr_SetString(PyExc_ValueError, - "second must be in 0..59"); - return -1; - } - if (us < 0 || us > 999999) { - PyErr_SetString(PyExc_ValueError, - "microsecond must be in 0..999999"); - return -1; - } - return 0; -} - -/* --------------------------------------------------------------------------- - * Normalization utilities. - */ - -/* One step of a mixed-radix conversion. A "hi" unit is equivalent to - * factor "lo" units. factor must be > 0. If *lo is less than 0, or - * at least factor, enough of *lo is converted into "hi" units so that - * 0 <= *lo < factor. The input values must be such that int overflow - * is impossible. - */ -static void -normalize_pair(int *hi, int *lo, int factor) -{ - assert(factor > 0); - assert(lo != hi); - if (*lo < 0 || *lo >= factor) { - const int num_hi = divmod(*lo, factor, lo); - const int new_hi = *hi + num_hi; - assert(! SIGNED_ADD_OVERFLOWED(new_hi, *hi, num_hi)); - *hi = new_hi; - } - assert(0 <= *lo && *lo < factor); -} - -/* Fiddle days (d), seconds (s), and microseconds (us) so that - * 0 <= *s < 24*3600 - * 0 <= *us < 1000000 - * The input values must be such that the internals don't overflow. - * The way this routine is used, we don't get close. - */ -static void -normalize_d_s_us(int *d, int *s, int *us) -{ - if (*us < 0 || *us >= 1000000) { - normalize_pair(s, us, 1000000); - /* |s| can't be bigger than about - * |original s| + |original us|/1000000 now. - */ - - } - if (*s < 0 || *s >= 24*3600) { - normalize_pair(d, s, 24*3600); - /* |d| can't be bigger than about - * |original d| + - * (|original s| + |original us|/1000000) / (24*3600) now. - */ - } - assert(0 <= *s && *s < 24*3600); - assert(0 <= *us && *us < 1000000); -} - -/* Fiddle years (y), months (m), and days (d) so that - * 1 <= *m <= 12 - * 1 <= *d <= days_in_month(*y, *m) - * The input values must be such that the internals don't overflow. - * The way this routine is used, we don't get close. - */ -static int -normalize_y_m_d(int *y, int *m, int *d) -{ - int dim; /* # of days in month */ - - /* In actual use, m is always the month component extracted from a - * date/datetime object. Therefore it is always in [1, 12] range. - */ - - assert(1 <= *m && *m <= 12); - - /* Now only day can be out of bounds (year may also be out of bounds - * for a datetime object, but we don't care about that here). - * If day is out of bounds, what to do is arguable, but at least the - * method here is principled and explainable. - */ - dim = days_in_month(*y, *m); - if (*d < 1 || *d > dim) { - /* Move day-1 days from the first of the month. First try to - * get off cheap if we're only one day out of range - * (adjustments for timezone alone can't be worse than that). - */ - if (*d == 0) { - --*m; - if (*m > 0) - *d = days_in_month(*y, *m); - else { - --*y; - *m = 12; - *d = 31; - } - } - else if (*d == dim + 1) { - /* move forward a day */ - ++*m; - *d = 1; - if (*m > 12) { - *m = 1; - ++*y; - } - } - else { - int ordinal = ymd_to_ord(*y, *m, 1) + - *d - 1; - if (ordinal < 1 || ordinal > MAXORDINAL) { - goto error; - } else { - ord_to_ymd(ordinal, y, m, d); - return 0; - } - } - } - assert(*m > 0); - assert(*d > 0); - if (MINYEAR <= *y && *y <= MAXYEAR) - return 0; - error: - PyErr_SetString(PyExc_OverflowError, - "date value out of range"); - return -1; - -} - -/* Fiddle out-of-bounds months and days so that the result makes some kind - * of sense. The parameters are both inputs and outputs. Returns < 0 on - * failure, where failure means the adjusted year is out of bounds. - */ -static int -normalize_date(int *year, int *month, int *day) -{ - return normalize_y_m_d(year, month, day); -} - -/* Force all the datetime fields into range. The parameters are both - * inputs and outputs. Returns < 0 on error. - */ -static int -normalize_datetime(int *year, int *month, int *day, - int *hour, int *minute, int *second, - int *microsecond) -{ - normalize_pair(second, microsecond, 1000000); - normalize_pair(minute, second, 60); - normalize_pair(hour, minute, 60); - normalize_pair(day, hour, 24); - return normalize_date(year, month, day); -} - -/* --------------------------------------------------------------------------- - * Basic object allocation: tp_alloc implementations. These allocate - * Python objects of the right size and type, and do the Python object- - * initialization bit. If there's not enough memory, they return NULL after - * setting MemoryError. All data members remain uninitialized trash. - * - * We abuse the tp_alloc "nitems" argument to communicate whether a tzinfo - * member is needed. This is ugly, imprecise, and possibly insecure. - * tp_basicsize for the time and datetime types is set to the size of the - * struct that has room for the tzinfo member, so subclasses in Python will - * allocate enough space for a tzinfo member whether or not one is actually - * needed. That's the "ugly and imprecise" parts. The "possibly insecure" - * part is that PyType_GenericAlloc() (which subclasses in Python end up - * using) just happens today to effectively ignore the nitems argument - * when tp_itemsize is 0, which it is for these type objects. If that - * changes, perhaps the callers of tp_alloc slots in this file should - * be changed to force a 0 nitems argument unless the type being allocated - * is a base type implemented in this file (so that tp_alloc is time_alloc - * or datetime_alloc below, which know about the nitems abuse). - */ - -static PyObject * -time_alloc(PyTypeObject *type, Py_ssize_t aware) -{ - PyObject *self; - - self = (PyObject *) - PyObject_MALLOC(aware ? - sizeof(PyDateTime_Time) : - sizeof(_PyDateTime_BaseTime)); - if (self == NULL) - return (PyObject *)PyErr_NoMemory(); - (void)PyObject_INIT(self, type); - return self; -} - -static PyObject * -datetime_alloc(PyTypeObject *type, Py_ssize_t aware) -{ - PyObject *self; - - self = (PyObject *) - PyObject_MALLOC(aware ? - sizeof(PyDateTime_DateTime) : - sizeof(_PyDateTime_BaseDateTime)); - if (self == NULL) - return (PyObject *)PyErr_NoMemory(); - (void)PyObject_INIT(self, type); - return self; -} - -/* --------------------------------------------------------------------------- - * Helpers for setting object fields. These work on pointers to the - * appropriate base class. - */ - -/* For date and datetime. */ -static void -set_date_fields(PyDateTime_Date *self, int y, int m, int d) -{ - self->hashcode = -1; - SET_YEAR(self, y); - SET_MONTH(self, m); - SET_DAY(self, d); -} - -/* --------------------------------------------------------------------------- - * Create various objects, mostly without range checking. - */ - -/* Create a date instance with no range checking. */ -static PyObject * -new_date_ex(int year, int month, int day, PyTypeObject *type) -{ - PyDateTime_Date *self; - - self = (PyDateTime_Date *) (type->tp_alloc(type, 0)); - if (self != NULL) - set_date_fields(self, year, month, day); - return (PyObject *) self; -} - -#define new_date(year, month, day) \ - new_date_ex(year, month, day, &PyDateTime_DateType) - -/* Create a datetime instance with no range checking. */ -static PyObject * -new_datetime_ex(int year, int month, int day, int hour, int minute, - int second, int usecond, PyObject *tzinfo, PyTypeObject *type) -{ - PyDateTime_DateTime *self; - char aware = tzinfo != Py_None; - - self = (PyDateTime_DateTime *) (type->tp_alloc(type, aware)); - if (self != NULL) { - self->hastzinfo = aware; - set_date_fields((PyDateTime_Date *)self, year, month, day); - DATE_SET_HOUR(self, hour); - DATE_SET_MINUTE(self, minute); - DATE_SET_SECOND(self, second); - DATE_SET_MICROSECOND(self, usecond); - if (aware) { - Py_INCREF(tzinfo); - self->tzinfo = tzinfo; - } - } - return (PyObject *)self; -} - -#define new_datetime(y, m, d, hh, mm, ss, us, tzinfo) \ - new_datetime_ex(y, m, d, hh, mm, ss, us, tzinfo, \ - &PyDateTime_DateTimeType) - -/* Create a time instance with no range checking. */ -static PyObject * -new_time_ex(int hour, int minute, int second, int usecond, - PyObject *tzinfo, PyTypeObject *type) -{ - PyDateTime_Time *self; - char aware = tzinfo != Py_None; - - self = (PyDateTime_Time *) (type->tp_alloc(type, aware)); - if (self != NULL) { - self->hastzinfo = aware; - self->hashcode = -1; - TIME_SET_HOUR(self, hour); - TIME_SET_MINUTE(self, minute); - TIME_SET_SECOND(self, second); - TIME_SET_MICROSECOND(self, usecond); - if (aware) { - Py_INCREF(tzinfo); - self->tzinfo = tzinfo; - } - } - return (PyObject *)self; -} - -#define new_time(hh, mm, ss, us, tzinfo) \ - new_time_ex(hh, mm, ss, us, tzinfo, &PyDateTime_TimeType) - -/* Create a timedelta instance. Normalize the members iff normalize is - * true. Passing false is a speed optimization, if you know for sure - * that seconds and microseconds are already in their proper ranges. In any - * case, raises OverflowError and returns NULL if the normalized days is out - * of range). - */ -static PyObject * -new_delta_ex(int days, int seconds, int microseconds, int normalize, - PyTypeObject *type) -{ - PyDateTime_Delta *self; - - if (normalize) - normalize_d_s_us(&days, &seconds, µseconds); - assert(0 <= seconds && seconds < 24*3600); - assert(0 <= microseconds && microseconds < 1000000); - - if (check_delta_day_range(days) < 0) - return NULL; - - self = (PyDateTime_Delta *) (type->tp_alloc(type, 0)); - if (self != NULL) { - self->hashcode = -1; - SET_TD_DAYS(self, days); - SET_TD_SECONDS(self, seconds); - SET_TD_MICROSECONDS(self, microseconds); - } - return (PyObject *) self; -} - -#define new_delta(d, s, us, normalize) \ - new_delta_ex(d, s, us, normalize, &PyDateTime_DeltaType) - - -typedef struct -{ - PyObject_HEAD - PyObject *offset; - PyObject *name; -} PyDateTime_TimeZone; - -/* The interned UTC timezone instance */ -static PyObject *PyDateTime_TimeZone_UTC; -/* The interned Epoch datetime instance */ -static PyObject *PyDateTime_Epoch; - -/* Create new timezone instance checking offset range. This - function does not check the name argument. Caller must assure - that offset is a timedelta instance and name is either NULL - or a unicode object. */ -static PyObject * -create_timezone(PyObject *offset, PyObject *name) -{ - PyDateTime_TimeZone *self; - PyTypeObject *type = &PyDateTime_TimeZoneType; - - assert(offset != NULL); - assert(PyDelta_Check(offset)); - assert(name == NULL || PyUnicode_Check(name)); - - self = (PyDateTime_TimeZone *)(type->tp_alloc(type, 0)); - if (self == NULL) { - return NULL; - } - Py_INCREF(offset); - self->offset = offset; - Py_XINCREF(name); - self->name = name; - return (PyObject *)self; -} - -static int delta_bool(PyDateTime_Delta *self); - -static PyObject * -new_timezone(PyObject *offset, PyObject *name) -{ - assert(offset != NULL); - assert(PyDelta_Check(offset)); - assert(name == NULL || PyUnicode_Check(name)); - - if (name == NULL && delta_bool((PyDateTime_Delta *)offset) == 0) { - Py_INCREF(PyDateTime_TimeZone_UTC); - return PyDateTime_TimeZone_UTC; - } - if (GET_TD_MICROSECONDS(offset) != 0 || GET_TD_SECONDS(offset) % 60 != 0) { - PyErr_Format(PyExc_ValueError, "offset must be a timedelta" - " representing a whole number of minutes," - " not %R.", offset); - return NULL; - } - if ((GET_TD_DAYS(offset) == -1 && GET_TD_SECONDS(offset) == 0) || - GET_TD_DAYS(offset) < -1 || GET_TD_DAYS(offset) >= 1) { - PyErr_Format(PyExc_ValueError, "offset must be a timedelta" - " strictly between -timedelta(hours=24) and" - " timedelta(hours=24)," - " not %R.", offset); - return NULL; - } - - return create_timezone(offset, name); -} - -/* --------------------------------------------------------------------------- - * tzinfo helpers. - */ - -/* Ensure that p is None or of a tzinfo subclass. Return 0 if OK; if not - * raise TypeError and return -1. - */ -static int -check_tzinfo_subclass(PyObject *p) -{ - if (p == Py_None || PyTZInfo_Check(p)) - return 0; - PyErr_Format(PyExc_TypeError, - "tzinfo argument must be None or of a tzinfo subclass, " - "not type '%s'", - Py_TYPE(p)->tp_name); - return -1; -} - -/* If self has a tzinfo member, return a BORROWED reference to it. Else - * return NULL, which is NOT AN ERROR. There are no error returns here, - * and the caller must not decref the result. - */ -static PyObject * -get_tzinfo_member(PyObject *self) -{ - PyObject *tzinfo = NULL; - - if (PyDateTime_Check(self) && HASTZINFO(self)) - tzinfo = ((PyDateTime_DateTime *)self)->tzinfo; - else if (PyTime_Check(self) && HASTZINFO(self)) - tzinfo = ((PyDateTime_Time *)self)->tzinfo; - - return tzinfo; -} - -/* Call getattr(tzinfo, name)(tzinfoarg), and check the result. tzinfo must - * be an instance of the tzinfo class. If the method returns None, this - * returns None. If the method doesn't return None or timedelta, TypeError is - * raised and this returns NULL. If it returns a timedelta and the value is - * out of range or isn't a whole number of minutes, ValueError is raised and - * this returns NULL. Else result is returned. - */ -static PyObject * -call_tzinfo_method(PyObject *tzinfo, char *name, PyObject *tzinfoarg) -{ - PyObject *offset; - - assert(tzinfo != NULL); - assert(PyTZInfo_Check(tzinfo) || tzinfo == Py_None); - assert(tzinfoarg != NULL); - - if (tzinfo == Py_None) - Py_RETURN_NONE; - offset = PyObject_CallMethod(tzinfo, name, "O", tzinfoarg); - if (offset == Py_None || offset == NULL) - return offset; - if (PyDelta_Check(offset)) { - if (GET_TD_MICROSECONDS(offset) != 0 || GET_TD_SECONDS(offset) % 60 != 0) { - Py_DECREF(offset); - PyErr_Format(PyExc_ValueError, "offset must be a timedelta" - " representing a whole number of minutes"); - return NULL; - } - if ((GET_TD_DAYS(offset) == -1 && GET_TD_SECONDS(offset) == 0) || - GET_TD_DAYS(offset) < -1 || GET_TD_DAYS(offset) >= 1) { - Py_DECREF(offset); - PyErr_Format(PyExc_ValueError, "offset must be a timedelta" - " strictly between -timedelta(hours=24) and" - " timedelta(hours=24)."); - return NULL; - } - } - else { - PyErr_Format(PyExc_TypeError, - "tzinfo.%s() must return None or " - "timedelta, not '%.200s'", - name, Py_TYPE(offset)->tp_name); - Py_DECREF(offset); - return NULL; - } - - return offset; -} - -/* Call tzinfo.utcoffset(tzinfoarg), and extract an integer from the - * result. tzinfo must be an instance of the tzinfo class. If utcoffset() - * returns None, call_utcoffset returns 0 and sets *none to 1. If uctoffset() - * doesn't return None or timedelta, TypeError is raised and this returns -1. - * If utcoffset() returns an invalid timedelta (out of range, or not a whole - * # of minutes), ValueError is raised and this returns -1. Else *none is - * set to 0 and the offset is returned (as int # of minutes east of UTC). - */ -static PyObject * -call_utcoffset(PyObject *tzinfo, PyObject *tzinfoarg) -{ - return call_tzinfo_method(tzinfo, "utcoffset", tzinfoarg); -} - -/* Call tzinfo.dst(tzinfoarg), and extract an integer from the - * result. tzinfo must be an instance of the tzinfo class. If dst() - * returns None, call_dst returns 0 and sets *none to 1. If dst() - & doesn't return None or timedelta, TypeError is raised and this - * returns -1. If dst() returns an invalid timedelta for a UTC offset, - * ValueError is raised and this returns -1. Else *none is set to 0 and - * the offset is returned (as an int # of minutes east of UTC). - */ -static PyObject * -call_dst(PyObject *tzinfo, PyObject *tzinfoarg) -{ - return call_tzinfo_method(tzinfo, "dst", tzinfoarg); -} - -/* Call tzinfo.tzname(tzinfoarg), and return the result. tzinfo must be - * an instance of the tzinfo class or None. If tzinfo isn't None, and - * tzname() doesn't return None or a string, TypeError is raised and this - * returns NULL. If the result is a string, we ensure it is a Unicode - * string. - */ -static PyObject * -call_tzname(PyObject *tzinfo, PyObject *tzinfoarg) -{ - PyObject *result; - _Py_IDENTIFIER(tzname); - - assert(tzinfo != NULL); - assert(check_tzinfo_subclass(tzinfo) >= 0); - assert(tzinfoarg != NULL); - - if (tzinfo == Py_None) - Py_RETURN_NONE; - - result = _PyObject_CallMethodId(tzinfo, &PyId_tzname, "O", tzinfoarg); - - if (result == NULL || result == Py_None) - return result; - - if (!PyUnicode_Check(result)) { - PyErr_Format(PyExc_TypeError, "tzinfo.tzname() must " - "return None or a string, not '%s'", - Py_TYPE(result)->tp_name); - Py_DECREF(result); - result = NULL; - } - - return result; -} - -/* repr is like "someclass(arg1, arg2)". If tzinfo isn't None, - * stuff - * ", tzinfo=" + repr(tzinfo) - * before the closing ")". - */ -static PyObject * -append_keyword_tzinfo(PyObject *repr, PyObject *tzinfo) -{ - PyObject *temp; - - assert(PyUnicode_Check(repr)); - assert(tzinfo); - if (tzinfo == Py_None) - return repr; - /* Get rid of the trailing ')'. */ - assert(PyUnicode_READ_CHAR(repr, PyUnicode_GET_LENGTH(repr)-1) == ')'); - temp = PyUnicode_Substring(repr, 0, PyUnicode_GET_LENGTH(repr) - 1); - Py_DECREF(repr); - if (temp == NULL) - return NULL; - repr = PyUnicode_FromFormat("%U, tzinfo=%R)", temp, tzinfo); - Py_DECREF(temp); - return repr; -} - -/* --------------------------------------------------------------------------- - * String format helpers. - */ - -static PyObject * -format_ctime(PyDateTime_Date *date, int hours, int minutes, int seconds) -{ - static const char *DayNames[] = { - "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun" - }; - static const char *MonthNames[] = { - "Jan", "Feb", "Mar", "Apr", "May", "Jun", - "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" - }; - - int wday = weekday(GET_YEAR(date), GET_MONTH(date), GET_DAY(date)); - - return PyUnicode_FromFormat("%s %s %2d %02d:%02d:%02d %04d", - DayNames[wday], MonthNames[GET_MONTH(date)-1], - GET_DAY(date), hours, minutes, seconds, - GET_YEAR(date)); -} - -static PyObject *delta_negative(PyDateTime_Delta *self); - -/* Add an hours & minutes UTC offset string to buf. buf has no more than - * buflen bytes remaining. The UTC offset is gotten by calling - * tzinfo.uctoffset(tzinfoarg). If that returns None, \0 is stored into - * *buf, and that's all. Else the returned value is checked for sanity (an - * integer in range), and if that's OK it's converted to an hours & minutes - * string of the form - * sign HH sep MM - * Returns 0 if everything is OK. If the return value from utcoffset() is - * bogus, an appropriate exception is set and -1 is returned. - */ -static int -format_utcoffset(char *buf, size_t buflen, const char *sep, - PyObject *tzinfo, PyObject *tzinfoarg) -{ - PyObject *offset; - int hours, minutes, seconds; - char sign; - - assert(buflen >= 1); - - offset = call_utcoffset(tzinfo, tzinfoarg); - if (offset == NULL) - return -1; - if (offset == Py_None) { - Py_DECREF(offset); - *buf = '\0'; - return 0; - } - /* Offset is normalized, so it is negative if days < 0 */ - if (GET_TD_DAYS(offset) < 0) { - PyObject *temp = offset; - sign = '-'; - offset = delta_negative((PyDateTime_Delta *)offset); - Py_DECREF(temp); - if (offset == NULL) - return -1; - } - else { - sign = '+'; - } - /* Offset is not negative here. */ - seconds = GET_TD_SECONDS(offset); - Py_DECREF(offset); - minutes = divmod(seconds, 60, &seconds); - hours = divmod(minutes, 60, &minutes); - assert(seconds == 0); - /* XXX ignore sub-minute data, curently not allowed. */ - PyOS_snprintf(buf, buflen, "%c%02d%s%02d", sign, hours, sep, minutes); - - return 0; -} - -static PyObject * -make_Zreplacement(PyObject *object, PyObject *tzinfoarg) -{ - PyObject *temp; - PyObject *tzinfo = get_tzinfo_member(object); - PyObject *Zreplacement = PyUnicode_FromStringAndSize(NULL, 0); - _Py_IDENTIFIER(replace); - - if (Zreplacement == NULL) - return NULL; - if (tzinfo == Py_None || tzinfo == NULL) - return Zreplacement; - - assert(tzinfoarg != NULL); - temp = call_tzname(tzinfo, tzinfoarg); - if (temp == NULL) - goto Error; - if (temp == Py_None) { - Py_DECREF(temp); - return Zreplacement; - } - - assert(PyUnicode_Check(temp)); - /* Since the tzname is getting stuffed into the - * format, we have to double any % signs so that - * strftime doesn't treat them as format codes. - */ - Py_DECREF(Zreplacement); - Zreplacement = _PyObject_CallMethodId(temp, &PyId_replace, "ss", "%", "%%"); - Py_DECREF(temp); - if (Zreplacement == NULL) - return NULL; - if (!PyUnicode_Check(Zreplacement)) { - PyErr_SetString(PyExc_TypeError, - "tzname.replace() did not return a string"); - goto Error; - } - return Zreplacement; - - Error: - Py_DECREF(Zreplacement); - return NULL; -} - -static PyObject * -make_freplacement(PyObject *object) -{ - char freplacement[64]; - if (PyTime_Check(object)) - sprintf(freplacement, "%06d", TIME_GET_MICROSECOND(object)); - else if (PyDateTime_Check(object)) - sprintf(freplacement, "%06d", DATE_GET_MICROSECOND(object)); - else - sprintf(freplacement, "%06d", 0); - - return PyBytes_FromStringAndSize(freplacement, strlen(freplacement)); -} - -/* I sure don't want to reproduce the strftime code from the time module, - * so this imports the module and calls it. All the hair is due to - * giving special meanings to the %z, %Z and %f format codes via a - * preprocessing step on the format string. - * tzinfoarg is the argument to pass to the object's tzinfo method, if - * needed. - */ -static PyObject * -wrap_strftime(PyObject *object, PyObject *format, PyObject *timetuple, - PyObject *tzinfoarg) -{ - PyObject *result = NULL; /* guilty until proved innocent */ - - PyObject *zreplacement = NULL; /* py string, replacement for %z */ - PyObject *Zreplacement = NULL; /* py string, replacement for %Z */ - PyObject *freplacement = NULL; /* py string, replacement for %f */ - - const char *pin; /* pointer to next char in input format */ - Py_ssize_t flen; /* length of input format */ - char ch; /* next char in input format */ - - PyObject *newfmt = NULL; /* py string, the output format */ - char *pnew; /* pointer to available byte in output format */ - size_t totalnew; /* number bytes total in output format buffer, - exclusive of trailing \0 */ - size_t usednew; /* number bytes used so far in output format buffer */ - - const char *ptoappend; /* ptr to string to append to output buffer */ - Py_ssize_t ntoappend; /* # of bytes to append to output buffer */ - - assert(object && format && timetuple); - assert(PyUnicode_Check(format)); - /* Convert the input format to a C string and size */ - pin = _PyUnicode_AsStringAndSize(format, &flen); - if (!pin) - return NULL; - - /* Scan the input format, looking for %z/%Z/%f escapes, building - * a new format. Since computing the replacements for those codes - * is expensive, don't unless they're actually used. - */ - if (flen > INT_MAX - 1) { - PyErr_NoMemory(); - goto Done; - } - - totalnew = flen + 1; /* realistic if no %z/%Z */ - newfmt = PyBytes_FromStringAndSize(NULL, totalnew); - if (newfmt == NULL) goto Done; - pnew = PyBytes_AsString(newfmt); - usednew = 0; - - while ((ch = *pin++) != '\0') { - if (ch != '%') { - ptoappend = pin - 1; - ntoappend = 1; - } - else if ((ch = *pin++) == '\0') { - /* There's a lone trailing %; doesn't make sense. */ - PyErr_SetString(PyExc_ValueError, "strftime format " - "ends with raw %"); - goto Done; - } - /* A % has been seen and ch is the character after it. */ - else if (ch == 'z') { - if (zreplacement == NULL) { - /* format utcoffset */ - char buf[100]; - PyObject *tzinfo = get_tzinfo_member(object); - zreplacement = PyBytes_FromStringAndSize("", 0); - if (zreplacement == NULL) goto Done; - if (tzinfo != Py_None && tzinfo != NULL) { - assert(tzinfoarg != NULL); - if (format_utcoffset(buf, - sizeof(buf), - "", - tzinfo, - tzinfoarg) < 0) - goto Done; - Py_DECREF(zreplacement); - zreplacement = - PyBytes_FromStringAndSize(buf, - strlen(buf)); - if (zreplacement == NULL) - goto Done; - } - } - assert(zreplacement != NULL); - ptoappend = PyBytes_AS_STRING(zreplacement); - ntoappend = PyBytes_GET_SIZE(zreplacement); - } - else if (ch == 'Z') { - /* format tzname */ - if (Zreplacement == NULL) { - Zreplacement = make_Zreplacement(object, - tzinfoarg); - if (Zreplacement == NULL) - goto Done; - } - assert(Zreplacement != NULL); - assert(PyUnicode_Check(Zreplacement)); - ptoappend = _PyUnicode_AsStringAndSize(Zreplacement, - &ntoappend); - if (ptoappend == NULL) - goto Done; - } - else if (ch == 'f') { - /* format microseconds */ - if (freplacement == NULL) { - freplacement = make_freplacement(object); - if (freplacement == NULL) - goto Done; - } - assert(freplacement != NULL); - assert(PyBytes_Check(freplacement)); - ptoappend = PyBytes_AS_STRING(freplacement); - ntoappend = PyBytes_GET_SIZE(freplacement); - } - else { - /* percent followed by neither z nor Z */ - ptoappend = pin - 2; - ntoappend = 2; - } - - /* Append the ntoappend chars starting at ptoappend to - * the new format. - */ - if (ntoappend == 0) - continue; - assert(ptoappend != NULL); - assert(ntoappend > 0); - while (usednew + ntoappend > totalnew) { - if (totalnew > (PY_SSIZE_T_MAX >> 1)) { /* overflow */ - PyErr_NoMemory(); - goto Done; - } - totalnew <<= 1; - if (_PyBytes_Resize(&newfmt, totalnew) < 0) - goto Done; - pnew = PyBytes_AsString(newfmt) + usednew; - } - memcpy(pnew, ptoappend, ntoappend); - pnew += ntoappend; - usednew += ntoappend; - assert(usednew <= totalnew); - } /* end while() */ - - if (_PyBytes_Resize(&newfmt, usednew) < 0) - goto Done; - { - PyObject *format; - PyObject *time = PyImport_ImportModuleNoBlock("time"); - - if (time == NULL) - goto Done; - format = PyUnicode_FromString(PyBytes_AS_STRING(newfmt)); - if (format != NULL) { - result = _PyObject_CallMethodId(time, &PyId_strftime, "OO", - format, timetuple, NULL); - Py_DECREF(format); - } - Py_DECREF(time); - } - Done: - Py_XDECREF(freplacement); - Py_XDECREF(zreplacement); - Py_XDECREF(Zreplacement); - Py_XDECREF(newfmt); - return result; -} - -/* --------------------------------------------------------------------------- - * Wrap functions from the time module. These aren't directly available - * from C. Perhaps they should be. - */ - -/* Call time.time() and return its result (a Python float). */ -static PyObject * -time_time(void) -{ - PyObject *result = NULL; - PyObject *time = PyImport_ImportModuleNoBlock("time"); - - if (time != NULL) { - _Py_IDENTIFIER(time); - - result = _PyObject_CallMethodId(time, &PyId_time, "()"); - Py_DECREF(time); - } - return result; -} - -/* Build a time.struct_time. The weekday and day number are automatically - * computed from the y,m,d args. - */ -static PyObject * -build_struct_time(int y, int m, int d, int hh, int mm, int ss, int dstflag) -{ - PyObject *time; - PyObject *result = NULL; - - time = PyImport_ImportModuleNoBlock("time"); - if (time != NULL) { - _Py_IDENTIFIER(struct_time); - - result = _PyObject_CallMethodId(time, &PyId_struct_time, - "((iiiiiiiii))", - y, m, d, - hh, mm, ss, - weekday(y, m, d), - days_before_month(y, m) + d, - dstflag); - Py_DECREF(time); - } - return result; -} - -/* --------------------------------------------------------------------------- - * Miscellaneous helpers. - */ - -/* For various reasons, we need to use tp_richcompare instead of tp_reserved. - * The comparisons here all most naturally compute a cmp()-like result. - * This little helper turns that into a bool result for rich comparisons. - */ -static PyObject * -diff_to_bool(int diff, int op) -{ - PyObject *result; - int istrue; - - switch (op) { - case Py_EQ: istrue = diff == 0; break; - case Py_NE: istrue = diff != 0; break; - case Py_LE: istrue = diff <= 0; break; - case Py_GE: istrue = diff >= 0; break; - case Py_LT: istrue = diff < 0; break; - case Py_GT: istrue = diff > 0; break; - default: - assert(! "op unknown"); - istrue = 0; /* To shut up compiler */ - } - result = istrue ? Py_True : Py_False; - Py_INCREF(result); - return result; -} - -/* Raises a "can't compare" TypeError and returns NULL. */ -static PyObject * -cmperror(PyObject *a, PyObject *b) -{ - PyErr_Format(PyExc_TypeError, - "can't compare %s to %s", - Py_TYPE(a)->tp_name, Py_TYPE(b)->tp_name); - return NULL; -} - -/* --------------------------------------------------------------------------- - * Cached Python objects; these are set by the module init function. - */ - -/* Conversion factors. */ -static PyObject *one = NULL; /* 1 */ -static PyObject *us_per_ms = NULL; /* 1000 */ -static PyObject *us_per_second = NULL; /* 1000000 */ -static PyObject *us_per_minute = NULL; /* 1e6 * 60 as Python int */ -static PyObject *us_per_hour = NULL; /* 1e6 * 3600 as Python int */ -static PyObject *us_per_day = NULL; /* 1e6 * 3600 * 24 as Python int */ -static PyObject *us_per_week = NULL; /* 1e6*3600*24*7 as Python int */ -static PyObject *seconds_per_day = NULL; /* 3600*24 as Python int */ - -/* --------------------------------------------------------------------------- - * Class implementations. - */ - -/* - * PyDateTime_Delta implementation. - */ - -/* Convert a timedelta to a number of us, - * (24*3600*self.days + self.seconds)*1000000 + self.microseconds - * as a Python int. - * Doing mixed-radix arithmetic by hand instead is excruciating in C, - * due to ubiquitous overflow possibilities. - */ -static PyObject * -delta_to_microseconds(PyDateTime_Delta *self) -{ - PyObject *x1 = NULL; - PyObject *x2 = NULL; - PyObject *x3 = NULL; - PyObject *result = NULL; - - x1 = PyLong_FromLong(GET_TD_DAYS(self)); - if (x1 == NULL) - goto Done; - x2 = PyNumber_Multiply(x1, seconds_per_day); /* days in seconds */ - if (x2 == NULL) - goto Done; - Py_DECREF(x1); - x1 = NULL; - - /* x2 has days in seconds */ - x1 = PyLong_FromLong(GET_TD_SECONDS(self)); /* seconds */ - if (x1 == NULL) - goto Done; - x3 = PyNumber_Add(x1, x2); /* days and seconds in seconds */ - if (x3 == NULL) - goto Done; - Py_DECREF(x1); - Py_DECREF(x2); - /* x1 = */ x2 = NULL; - - /* x3 has days+seconds in seconds */ - x1 = PyNumber_Multiply(x3, us_per_second); /* us */ - if (x1 == NULL) - goto Done; - Py_DECREF(x3); - x3 = NULL; - - /* x1 has days+seconds in us */ - x2 = PyLong_FromLong(GET_TD_MICROSECONDS(self)); - if (x2 == NULL) - goto Done; - result = PyNumber_Add(x1, x2); - -Done: - Py_XDECREF(x1); - Py_XDECREF(x2); - Py_XDECREF(x3); - return result; -} - -/* Convert a number of us (as a Python int) to a timedelta. - */ -static PyObject * -microseconds_to_delta_ex(PyObject *pyus, PyTypeObject *type) -{ - int us; - int s; - int d; - long temp; - - PyObject *tuple = NULL; - PyObject *num = NULL; - PyObject *result = NULL; - - tuple = PyNumber_Divmod(pyus, us_per_second); - if (tuple == NULL) - goto Done; - - num = PyTuple_GetItem(tuple, 1); /* us */ - if (num == NULL) - goto Done; - temp = PyLong_AsLong(num); - num = NULL; - if (temp == -1 && PyErr_Occurred()) - goto Done; - assert(0 <= temp && temp < 1000000); - us = (int)temp; - if (us < 0) { - /* The divisor was positive, so this must be an error. */ - assert(PyErr_Occurred()); - goto Done; - } - - num = PyTuple_GetItem(tuple, 0); /* leftover seconds */ - if (num == NULL) - goto Done; - Py_INCREF(num); - Py_DECREF(tuple); - - tuple = PyNumber_Divmod(num, seconds_per_day); - if (tuple == NULL) - goto Done; - Py_DECREF(num); - - num = PyTuple_GetItem(tuple, 1); /* seconds */ - if (num == NULL) - goto Done; - temp = PyLong_AsLong(num); - num = NULL; - if (temp == -1 && PyErr_Occurred()) - goto Done; - assert(0 <= temp && temp < 24*3600); - s = (int)temp; - - if (s < 0) { - /* The divisor was positive, so this must be an error. */ - assert(PyErr_Occurred()); - goto Done; - } - - num = PyTuple_GetItem(tuple, 0); /* leftover days */ - if (num == NULL) - goto Done; - Py_INCREF(num); - temp = PyLong_AsLong(num); - if (temp == -1 && PyErr_Occurred()) - goto Done; - d = (int)temp; - if ((long)d != temp) { - PyErr_SetString(PyExc_OverflowError, "normalized days too " - "large to fit in a C int"); - goto Done; - } - result = new_delta_ex(d, s, us, 0, type); - -Done: - Py_XDECREF(tuple); - Py_XDECREF(num); - return result; -} - -#define microseconds_to_delta(pymicros) \ - microseconds_to_delta_ex(pymicros, &PyDateTime_DeltaType) - -static PyObject * -multiply_int_timedelta(PyObject *intobj, PyDateTime_Delta *delta) -{ - PyObject *pyus_in; - PyObject *pyus_out; - PyObject *result; - - pyus_in = delta_to_microseconds(delta); - if (pyus_in == NULL) - return NULL; - - pyus_out = PyNumber_Multiply(pyus_in, intobj); - Py_DECREF(pyus_in); - if (pyus_out == NULL) - return NULL; - - result = microseconds_to_delta(pyus_out); - Py_DECREF(pyus_out); - return result; -} - -static PyObject * -multiply_float_timedelta(PyObject *floatobj, PyDateTime_Delta *delta) -{ - PyObject *result = NULL; - PyObject *pyus_in = NULL, *temp, *pyus_out; - PyObject *ratio = NULL; - - pyus_in = delta_to_microseconds(delta); - if (pyus_in == NULL) - return NULL; - ratio = _PyObject_CallMethodId(floatobj, &PyId_as_integer_ratio, NULL); - if (ratio == NULL) - goto error; - temp = PyNumber_Multiply(pyus_in, PyTuple_GET_ITEM(ratio, 0)); - Py_DECREF(pyus_in); - pyus_in = NULL; - if (temp == NULL) - goto error; - pyus_out = divide_nearest(temp, PyTuple_GET_ITEM(ratio, 1)); - Py_DECREF(temp); - if (pyus_out == NULL) - goto error; - result = microseconds_to_delta(pyus_out); - Py_DECREF(pyus_out); - error: - Py_XDECREF(pyus_in); - Py_XDECREF(ratio); - - return result; -} - -static PyObject * -divide_timedelta_int(PyDateTime_Delta *delta, PyObject *intobj) -{ - PyObject *pyus_in; - PyObject *pyus_out; - PyObject *result; - - pyus_in = delta_to_microseconds(delta); - if (pyus_in == NULL) - return NULL; - - pyus_out = PyNumber_FloorDivide(pyus_in, intobj); - Py_DECREF(pyus_in); - if (pyus_out == NULL) - return NULL; - - result = microseconds_to_delta(pyus_out); - Py_DECREF(pyus_out); - return result; -} - -static PyObject * -divide_timedelta_timedelta(PyDateTime_Delta *left, PyDateTime_Delta *right) -{ - PyObject *pyus_left; - PyObject *pyus_right; - PyObject *result; - - pyus_left = delta_to_microseconds(left); - if (pyus_left == NULL) - return NULL; - - pyus_right = delta_to_microseconds(right); - if (pyus_right == NULL) { - Py_DECREF(pyus_left); - return NULL; - } - - result = PyNumber_FloorDivide(pyus_left, pyus_right); - Py_DECREF(pyus_left); - Py_DECREF(pyus_right); - return result; -} - -static PyObject * -truedivide_timedelta_timedelta(PyDateTime_Delta *left, PyDateTime_Delta *right) -{ - PyObject *pyus_left; - PyObject *pyus_right; - PyObject *result; - - pyus_left = delta_to_microseconds(left); - if (pyus_left == NULL) - return NULL; - - pyus_right = delta_to_microseconds(right); - if (pyus_right == NULL) { - Py_DECREF(pyus_left); - return NULL; - } - - result = PyNumber_TrueDivide(pyus_left, pyus_right); - Py_DECREF(pyus_left); - Py_DECREF(pyus_right); - return result; -} - -static PyObject * -truedivide_timedelta_float(PyDateTime_Delta *delta, PyObject *f) -{ - PyObject *result = NULL; - PyObject *pyus_in = NULL, *temp, *pyus_out; - PyObject *ratio = NULL; - - pyus_in = delta_to_microseconds(delta); - if (pyus_in == NULL) - return NULL; - ratio = _PyObject_CallMethodId(f, &PyId_as_integer_ratio, NULL); - if (ratio == NULL) - goto error; - temp = PyNumber_Multiply(pyus_in, PyTuple_GET_ITEM(ratio, 1)); - Py_DECREF(pyus_in); - pyus_in = NULL; - if (temp == NULL) - goto error; - pyus_out = divide_nearest(temp, PyTuple_GET_ITEM(ratio, 0)); - Py_DECREF(temp); - if (pyus_out == NULL) - goto error; - result = microseconds_to_delta(pyus_out); - Py_DECREF(pyus_out); - error: - Py_XDECREF(pyus_in); - Py_XDECREF(ratio); - - return result; -} - -static PyObject * -truedivide_timedelta_int(PyDateTime_Delta *delta, PyObject *i) -{ - PyObject *result; - PyObject *pyus_in, *pyus_out; - pyus_in = delta_to_microseconds(delta); - if (pyus_in == NULL) - return NULL; - pyus_out = divide_nearest(pyus_in, i); - Py_DECREF(pyus_in); - if (pyus_out == NULL) - return NULL; - result = microseconds_to_delta(pyus_out); - Py_DECREF(pyus_out); - - return result; -} - -static PyObject * -delta_add(PyObject *left, PyObject *right) -{ - PyObject *result = Py_NotImplemented; - - if (PyDelta_Check(left) && PyDelta_Check(right)) { - /* delta + delta */ - /* The C-level additions can't overflow because of the - * invariant bounds. - */ - int days = GET_TD_DAYS(left) + GET_TD_DAYS(right); - int seconds = GET_TD_SECONDS(left) + GET_TD_SECONDS(right); - int microseconds = GET_TD_MICROSECONDS(left) + - GET_TD_MICROSECONDS(right); - result = new_delta(days, seconds, microseconds, 1); - } - - if (result == Py_NotImplemented) - Py_INCREF(result); - return result; -} - -static PyObject * -delta_negative(PyDateTime_Delta *self) -{ - return new_delta(-GET_TD_DAYS(self), - -GET_TD_SECONDS(self), - -GET_TD_MICROSECONDS(self), - 1); -} - -static PyObject * -delta_positive(PyDateTime_Delta *self) -{ - /* Could optimize this (by returning self) if this isn't a - * subclass -- but who uses unary + ? Approximately nobody. - */ - return new_delta(GET_TD_DAYS(self), - GET_TD_SECONDS(self), - GET_TD_MICROSECONDS(self), - 0); -} - -static PyObject * -delta_abs(PyDateTime_Delta *self) -{ - PyObject *result; - - assert(GET_TD_MICROSECONDS(self) >= 0); - assert(GET_TD_SECONDS(self) >= 0); - - if (GET_TD_DAYS(self) < 0) - result = delta_negative(self); - else - result = delta_positive(self); - - return result; -} - -static PyObject * -delta_subtract(PyObject *left, PyObject *right) -{ - PyObject *result = Py_NotImplemented; - - if (PyDelta_Check(left) && PyDelta_Check(right)) { - /* delta - delta */ - /* The C-level additions can't overflow because of the - * invariant bounds. - */ - int days = GET_TD_DAYS(left) - GET_TD_DAYS(right); - int seconds = GET_TD_SECONDS(left) - GET_TD_SECONDS(right); - int microseconds = GET_TD_MICROSECONDS(left) - - GET_TD_MICROSECONDS(right); - result = new_delta(days, seconds, microseconds, 1); - } - - if (result == Py_NotImplemented) - Py_INCREF(result); - return result; -} - -static int -delta_cmp(PyObject *self, PyObject *other) -{ - int diff = GET_TD_DAYS(self) - GET_TD_DAYS(other); - if (diff == 0) { - diff = GET_TD_SECONDS(self) - GET_TD_SECONDS(other); - if (diff == 0) - diff = GET_TD_MICROSECONDS(self) - - GET_TD_MICROSECONDS(other); - } - return diff; -} - -static PyObject * -delta_richcompare(PyObject *self, PyObject *other, int op) -{ - if (PyDelta_Check(other)) { - int diff = delta_cmp(self, other); - return diff_to_bool(diff, op); - } - else { - Py_RETURN_NOTIMPLEMENTED; - } -} - -static PyObject *delta_getstate(PyDateTime_Delta *self); - -static Py_hash_t -delta_hash(PyDateTime_Delta *self) -{ - if (self->hashcode == -1) { - PyObject *temp = delta_getstate(self); - if (temp != NULL) { - self->hashcode = PyObject_Hash(temp); - Py_DECREF(temp); - } - } - return self->hashcode; -} - -static PyObject * -delta_multiply(PyObject *left, PyObject *right) -{ - PyObject *result = Py_NotImplemented; - - if (PyDelta_Check(left)) { - /* delta * ??? */ - if (PyLong_Check(right)) - result = multiply_int_timedelta(right, - (PyDateTime_Delta *) left); - else if (PyFloat_Check(right)) - result = multiply_float_timedelta(right, - (PyDateTime_Delta *) left); - } - else if (PyLong_Check(left)) - result = multiply_int_timedelta(left, - (PyDateTime_Delta *) right); - else if (PyFloat_Check(left)) - result = multiply_float_timedelta(left, - (PyDateTime_Delta *) right); - - if (result == Py_NotImplemented) - Py_INCREF(result); - return result; -} - -static PyObject * -delta_divide(PyObject *left, PyObject *right) -{ - PyObject *result = Py_NotImplemented; - - if (PyDelta_Check(left)) { - /* delta * ??? */ - if (PyLong_Check(right)) - result = divide_timedelta_int( - (PyDateTime_Delta *)left, - right); - else if (PyDelta_Check(right)) - result = divide_timedelta_timedelta( - (PyDateTime_Delta *)left, - (PyDateTime_Delta *)right); - } - - if (result == Py_NotImplemented) - Py_INCREF(result); - return result; -} - -static PyObject * -delta_truedivide(PyObject *left, PyObject *right) -{ - PyObject *result = Py_NotImplemented; - - if (PyDelta_Check(left)) { - if (PyDelta_Check(right)) - result = truedivide_timedelta_timedelta( - (PyDateTime_Delta *)left, - (PyDateTime_Delta *)right); - else if (PyFloat_Check(right)) - result = truedivide_timedelta_float( - (PyDateTime_Delta *)left, right); - else if (PyLong_Check(right)) - result = truedivide_timedelta_int( - (PyDateTime_Delta *)left, right); - } - - if (result == Py_NotImplemented) - Py_INCREF(result); - return result; -} - -static PyObject * -delta_remainder(PyObject *left, PyObject *right) -{ - PyObject *pyus_left; - PyObject *pyus_right; - PyObject *pyus_remainder; - PyObject *remainder; - - if (!PyDelta_Check(left) || !PyDelta_Check(right)) - Py_RETURN_NOTIMPLEMENTED; - - pyus_left = delta_to_microseconds((PyDateTime_Delta *)left); - if (pyus_left == NULL) - return NULL; - - pyus_right = delta_to_microseconds((PyDateTime_Delta *)right); - if (pyus_right == NULL) { - Py_DECREF(pyus_left); - return NULL; - } - - pyus_remainder = PyNumber_Remainder(pyus_left, pyus_right); - Py_DECREF(pyus_left); - Py_DECREF(pyus_right); - if (pyus_remainder == NULL) - return NULL; - - remainder = microseconds_to_delta(pyus_remainder); - Py_DECREF(pyus_remainder); - if (remainder == NULL) - return NULL; - - return remainder; -} - -static PyObject * -delta_divmod(PyObject *left, PyObject *right) -{ - PyObject *pyus_left; - PyObject *pyus_right; - PyObject *divmod; - PyObject *delta; - PyObject *result; - - if (!PyDelta_Check(left) || !PyDelta_Check(right)) - Py_RETURN_NOTIMPLEMENTED; - - pyus_left = delta_to_microseconds((PyDateTime_Delta *)left); - if (pyus_left == NULL) - return NULL; - - pyus_right = delta_to_microseconds((PyDateTime_Delta *)right); - if (pyus_right == NULL) { - Py_DECREF(pyus_left); - return NULL; - } - - divmod = PyNumber_Divmod(pyus_left, pyus_right); - Py_DECREF(pyus_left); - Py_DECREF(pyus_right); - if (divmod == NULL) - return NULL; - - assert(PyTuple_Size(divmod) == 2); - delta = microseconds_to_delta(PyTuple_GET_ITEM(divmod, 1)); - if (delta == NULL) { - Py_DECREF(divmod); - return NULL; - } - result = PyTuple_Pack(2, PyTuple_GET_ITEM(divmod, 0), delta); - Py_DECREF(delta); - Py_DECREF(divmod); - return result; -} - -/* Fold in the value of the tag ("seconds", "weeks", etc) component of a - * timedelta constructor. sofar is the # of microseconds accounted for - * so far, and there are factor microseconds per current unit, the number - * of which is given by num. num * factor is added to sofar in a - * numerically careful way, and that's the result. Any fractional - * microseconds left over (this can happen if num is a float type) are - * added into *leftover. - * Note that there are many ways this can give an error (NULL) return. - */ -static PyObject * -accum(const char* tag, PyObject *sofar, PyObject *num, PyObject *factor, - double *leftover) -{ - PyObject *prod; - PyObject *sum; - - assert(num != NULL); - - if (PyLong_Check(num)) { - prod = PyNumber_Multiply(num, factor); - if (prod == NULL) - return NULL; - sum = PyNumber_Add(sofar, prod); - Py_DECREF(prod); - return sum; - } - - if (PyFloat_Check(num)) { - double dnum; - double fracpart; - double intpart; - PyObject *x; - PyObject *y; - - /* The Plan: decompose num into an integer part and a - * fractional part, num = intpart + fracpart. - * Then num * factor == - * intpart * factor + fracpart * factor - * and the LHS can be computed exactly in long arithmetic. - * The RHS is again broken into an int part and frac part. - * and the frac part is added into *leftover. - */ - dnum = PyFloat_AsDouble(num); - if (dnum == -1.0 && PyErr_Occurred()) - return NULL; - fracpart = modf(dnum, &intpart); - x = PyLong_FromDouble(intpart); - if (x == NULL) - return NULL; - - prod = PyNumber_Multiply(x, factor); - Py_DECREF(x); - if (prod == NULL) - return NULL; - - sum = PyNumber_Add(sofar, prod); - Py_DECREF(prod); - if (sum == NULL) - return NULL; - - if (fracpart == 0.0) - return sum; - /* So far we've lost no information. Dealing with the - * fractional part requires float arithmetic, and may - * lose a little info. - */ - assert(PyLong_Check(factor)); - dnum = PyLong_AsDouble(factor); - - dnum *= fracpart; - fracpart = modf(dnum, &intpart); - x = PyLong_FromDouble(intpart); - if (x == NULL) { - Py_DECREF(sum); - return NULL; - } - - y = PyNumber_Add(sum, x); - Py_DECREF(sum); - Py_DECREF(x); - *leftover += fracpart; - return y; - } - - PyErr_Format(PyExc_TypeError, - "unsupported type for timedelta %s component: %s", - tag, Py_TYPE(num)->tp_name); - return NULL; -} - -static PyObject * -delta_new(PyTypeObject *type, PyObject *args, PyObject *kw) -{ - PyObject *self = NULL; - - /* Argument objects. */ - PyObject *day = NULL; - PyObject *second = NULL; - PyObject *us = NULL; - PyObject *ms = NULL; - PyObject *minute = NULL; - PyObject *hour = NULL; - PyObject *week = NULL; - - PyObject *x = NULL; /* running sum of microseconds */ - PyObject *y = NULL; /* temp sum of microseconds */ - double leftover_us = 0.0; - - static char *keywords[] = { - "days", "seconds", "microseconds", "milliseconds", - "minutes", "hours", "weeks", NULL - }; - - if (PyArg_ParseTupleAndKeywords(args, kw, "|OOOOOOO:__new__", - keywords, - &day, &second, &us, - &ms, &minute, &hour, &week) == 0) - goto Done; - - x = PyLong_FromLong(0); - if (x == NULL) - goto Done; - -#define CLEANUP \ - Py_DECREF(x); \ - x = y; \ - if (x == NULL) \ - goto Done - - if (us) { - y = accum("microseconds", x, us, one, &leftover_us); - CLEANUP; - } - if (ms) { - y = accum("milliseconds", x, ms, us_per_ms, &leftover_us); - CLEANUP; - } - if (second) { - y = accum("seconds", x, second, us_per_second, &leftover_us); - CLEANUP; - } - if (minute) { - y = accum("minutes", x, minute, us_per_minute, &leftover_us); - CLEANUP; - } - if (hour) { - y = accum("hours", x, hour, us_per_hour, &leftover_us); - CLEANUP; - } - if (day) { - y = accum("days", x, day, us_per_day, &leftover_us); - CLEANUP; - } - if (week) { - y = accum("weeks", x, week, us_per_week, &leftover_us); - CLEANUP; - } - if (leftover_us) { - /* Round to nearest whole # of us, and add into x. */ - double whole_us = round(leftover_us); - int x_is_odd; - PyObject *temp; - - whole_us = round(leftover_us); - if (fabs(whole_us - leftover_us) == 0.5) { - /* We're exactly halfway between two integers. In order - * to do round-half-to-even, we must determine whether x - * is odd. Note that x is odd when it's last bit is 1. The - * code below uses bitwise and operation to check the last - * bit. */ - temp = PyNumber_And(x, one); /* temp <- x & 1 */ - if (temp == NULL) { - Py_DECREF(x); - goto Done; - } - x_is_odd = PyObject_IsTrue(temp); - Py_DECREF(temp); - if (x_is_odd == -1) { - Py_DECREF(x); - goto Done; - } - whole_us = 2.0 * round((leftover_us + x_is_odd) * 0.5) - x_is_odd; - } - - temp = PyLong_FromLong((long)whole_us); - - if (temp == NULL) { - Py_DECREF(x); - goto Done; - } - y = PyNumber_Add(x, temp); - Py_DECREF(temp); - CLEANUP; - } - - self = microseconds_to_delta_ex(x, type); - Py_DECREF(x); -Done: - return self; - -#undef CLEANUP -} - -static int -delta_bool(PyDateTime_Delta *self) -{ - return (GET_TD_DAYS(self) != 0 - || GET_TD_SECONDS(self) != 0 - || GET_TD_MICROSECONDS(self) != 0); -} - -static PyObject * -delta_repr(PyDateTime_Delta *self) -{ - if (GET_TD_MICROSECONDS(self) != 0) - return PyUnicode_FromFormat("%s(%d, %d, %d)", - Py_TYPE(self)->tp_name, - GET_TD_DAYS(self), - GET_TD_SECONDS(self), - GET_TD_MICROSECONDS(self)); - if (GET_TD_SECONDS(self) != 0) - return PyUnicode_FromFormat("%s(%d, %d)", - Py_TYPE(self)->tp_name, - GET_TD_DAYS(self), - GET_TD_SECONDS(self)); - - return PyUnicode_FromFormat("%s(%d)", - Py_TYPE(self)->tp_name, - GET_TD_DAYS(self)); -} - -static PyObject * -delta_str(PyDateTime_Delta *self) -{ - int us = GET_TD_MICROSECONDS(self); - int seconds = GET_TD_SECONDS(self); - int minutes = divmod(seconds, 60, &seconds); - int hours = divmod(minutes, 60, &minutes); - int days = GET_TD_DAYS(self); - - if (days) { - if (us) - return PyUnicode_FromFormat("%d day%s, %d:%02d:%02d.%06d", - days, (days == 1 || days == -1) ? "" : "s", - hours, minutes, seconds, us); - else - return PyUnicode_FromFormat("%d day%s, %d:%02d:%02d", - days, (days == 1 || days == -1) ? "" : "s", - hours, minutes, seconds); - } else { - if (us) - return PyUnicode_FromFormat("%d:%02d:%02d.%06d", - hours, minutes, seconds, us); - else - return PyUnicode_FromFormat("%d:%02d:%02d", - hours, minutes, seconds); - } - -} - -/* Pickle support, a simple use of __reduce__. */ - -/* __getstate__ isn't exposed */ -static PyObject * -delta_getstate(PyDateTime_Delta *self) -{ - return Py_BuildValue("iii", GET_TD_DAYS(self), - GET_TD_SECONDS(self), - GET_TD_MICROSECONDS(self)); -} - -static PyObject * -delta_total_seconds(PyObject *self) -{ - PyObject *total_seconds; - PyObject *total_microseconds; - - total_microseconds = delta_to_microseconds((PyDateTime_Delta *)self); - if (total_microseconds == NULL) - return NULL; - - total_seconds = PyNumber_TrueDivide(total_microseconds, us_per_second); - - Py_DECREF(total_microseconds); - return total_seconds; -} - -static PyObject * -delta_reduce(PyDateTime_Delta* self) -{ - return Py_BuildValue("ON", Py_TYPE(self), delta_getstate(self)); -} - -#define OFFSET(field) offsetof(PyDateTime_Delta, field) - -static PyMemberDef delta_members[] = { - - {"days", T_INT, OFFSET(days), READONLY, - PyDoc_STR("Number of days.")}, - - {"seconds", T_INT, OFFSET(seconds), READONLY, - PyDoc_STR("Number of seconds (>= 0 and less than 1 day).")}, - - {"microseconds", T_INT, OFFSET(microseconds), READONLY, - PyDoc_STR("Number of microseconds (>= 0 and less than 1 second).")}, - {NULL} -}; - -static PyMethodDef delta_methods[] = { - {"total_seconds", (PyCFunction)delta_total_seconds, METH_NOARGS, - PyDoc_STR("Total seconds in the duration.")}, - - {"__reduce__", (PyCFunction)delta_reduce, METH_NOARGS, - PyDoc_STR("__reduce__() -> (cls, state)")}, - - {NULL, NULL}, -}; - -static char delta_doc[] = -PyDoc_STR("Difference between two datetime values."); - -static PyNumberMethods delta_as_number = { - delta_add, /* nb_add */ - delta_subtract, /* nb_subtract */ - delta_multiply, /* nb_multiply */ - delta_remainder, /* nb_remainder */ - delta_divmod, /* nb_divmod */ - 0, /* nb_power */ - (unaryfunc)delta_negative, /* nb_negative */ - (unaryfunc)delta_positive, /* nb_positive */ - (unaryfunc)delta_abs, /* nb_absolute */ - (inquiry)delta_bool, /* nb_bool */ - 0, /*nb_invert*/ - 0, /*nb_lshift*/ - 0, /*nb_rshift*/ - 0, /*nb_and*/ - 0, /*nb_xor*/ - 0, /*nb_or*/ - 0, /*nb_int*/ - 0, /*nb_reserved*/ - 0, /*nb_float*/ - 0, /*nb_inplace_add*/ - 0, /*nb_inplace_subtract*/ - 0, /*nb_inplace_multiply*/ - 0, /*nb_inplace_remainder*/ - 0, /*nb_inplace_power*/ - 0, /*nb_inplace_lshift*/ - 0, /*nb_inplace_rshift*/ - 0, /*nb_inplace_and*/ - 0, /*nb_inplace_xor*/ - 0, /*nb_inplace_or*/ - delta_divide, /* nb_floor_divide */ - delta_truedivide, /* nb_true_divide */ - 0, /* nb_inplace_floor_divide */ - 0, /* nb_inplace_true_divide */ -}; - -static PyTypeObject PyDateTime_DeltaType = { - PyVarObject_HEAD_INIT(NULL, 0) - "datetime.timedelta", /* tp_name */ - sizeof(PyDateTime_Delta), /* tp_basicsize */ - 0, /* tp_itemsize */ - 0, /* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_reserved */ - (reprfunc)delta_repr, /* tp_repr */ - &delta_as_number, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - (hashfunc)delta_hash, /* tp_hash */ - 0, /* tp_call */ - (reprfunc)delta_str, /* tp_str */ - PyObject_GenericGetAttr, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ - delta_doc, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - delta_richcompare, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - delta_methods, /* tp_methods */ - delta_members, /* 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 */ - delta_new, /* tp_new */ - 0, /* tp_free */ -}; - -/* - * PyDateTime_Date implementation. - */ - -/* Accessor properties. */ - -static PyObject * -date_year(PyDateTime_Date *self, void *unused) -{ - return PyLong_FromLong(GET_YEAR(self)); -} - -static PyObject * -date_month(PyDateTime_Date *self, void *unused) -{ - return PyLong_FromLong(GET_MONTH(self)); -} - -static PyObject * -date_day(PyDateTime_Date *self, void *unused) -{ - return PyLong_FromLong(GET_DAY(self)); -} - -static PyGetSetDef date_getset[] = { - {"year", (getter)date_year}, - {"month", (getter)date_month}, - {"day", (getter)date_day}, - {NULL} -}; - -/* Constructors. */ - -static char *date_kws[] = {"year", "month", "day", NULL}; - -static PyObject * -date_new(PyTypeObject *type, PyObject *args, PyObject *kw) -{ - PyObject *self = NULL; - PyObject *state; - int year; - int month; - int day; - - /* Check for invocation from pickle with __getstate__ state */ - if (PyTuple_GET_SIZE(args) == 1 && - PyBytes_Check(state = PyTuple_GET_ITEM(args, 0)) && - PyBytes_GET_SIZE(state) == _PyDateTime_DATE_DATASIZE && - MONTH_IS_SANE(PyBytes_AS_STRING(state)[2])) - { - PyDateTime_Date *me; - - me = (PyDateTime_Date *) (type->tp_alloc(type, 0)); - if (me != NULL) { - char *pdata = PyBytes_AS_STRING(state); - memcpy(me->data, pdata, _PyDateTime_DATE_DATASIZE); - me->hashcode = -1; - } - return (PyObject *)me; - } - - if (PyArg_ParseTupleAndKeywords(args, kw, "iii", date_kws, - &year, &month, &day)) { - if (check_date_args(year, month, day) < 0) - return NULL; - self = new_date_ex(year, month, day, type); - } - return self; -} - -/* Return new date from localtime(t). */ -static PyObject * -date_local_from_object(PyObject *cls, PyObject *obj) -{ - struct tm *tm; - time_t t; - - if (_PyTime_ObjectToTime_t(obj, &t, _PyTime_ROUND_FLOOR) == -1) - return NULL; - - tm = localtime(&t); - if (tm == NULL) { - /* unconvertible time */ -#ifdef EINVAL - if (errno == 0) - errno = EINVAL; -#endif - PyErr_SetFromErrno(PyExc_OSError); - return NULL; - } - - return PyObject_CallFunction(cls, "iii", - tm->tm_year + 1900, - tm->tm_mon + 1, - tm->tm_mday); -} - -/* Return new date from current time. - * We say this is equivalent to fromtimestamp(time.time()), and the - * only way to be sure of that is to *call* time.time(). That's not - * generally the same as calling C's time. - */ -static PyObject * -date_today(PyObject *cls, PyObject *dummy) -{ - PyObject *time; - PyObject *result; - _Py_IDENTIFIER(fromtimestamp); - - time = time_time(); - if (time == NULL) - return NULL; - - /* Note well: today() is a class method, so this may not call - * date.fromtimestamp. For example, it may call - * datetime.fromtimestamp. That's why we need all the accuracy - * time.time() delivers; if someone were gonzo about optimization, - * date.today() could get away with plain C time(). - */ - result = _PyObject_CallMethodId(cls, &PyId_fromtimestamp, "O", time); - Py_DECREF(time); - return result; -} - -/* Return new date from given timestamp (Python timestamp -- a double). */ -static PyObject * -date_fromtimestamp(PyObject *cls, PyObject *args) -{ - PyObject *timestamp; - PyObject *result = NULL; - - if (PyArg_ParseTuple(args, "O:fromtimestamp", ×tamp)) - result = date_local_from_object(cls, timestamp); - return result; -} - -/* Return new date from proleptic Gregorian ordinal. Raises ValueError if - * the ordinal is out of range. - */ -static PyObject * -date_fromordinal(PyObject *cls, PyObject *args) -{ - PyObject *result = NULL; - int ordinal; - - if (PyArg_ParseTuple(args, "i:fromordinal", &ordinal)) { - int year; - int month; - int day; - - if (ordinal < 1) - PyErr_SetString(PyExc_ValueError, "ordinal must be " - ">= 1"); - else { - ord_to_ymd(ordinal, &year, &month, &day); - result = PyObject_CallFunction(cls, "iii", - year, month, day); - } - } - return result; -} - -/* - * Date arithmetic. - */ - -/* date + timedelta -> date. If arg negate is true, subtract the timedelta - * instead. - */ -static PyObject * -add_date_timedelta(PyDateTime_Date *date, PyDateTime_Delta *delta, int negate) -{ - PyObject *result = NULL; - int year = GET_YEAR(date); - int month = GET_MONTH(date); - int deltadays = GET_TD_DAYS(delta); - /* C-level overflow is impossible because |deltadays| < 1e9. */ - int day = GET_DAY(date) + (negate ? -deltadays : deltadays); - - if (normalize_date(&year, &month, &day) >= 0) - result = new_date(year, month, day); - return result; -} - -static PyObject * -date_add(PyObject *left, PyObject *right) -{ - if (PyDateTime_Check(left) || PyDateTime_Check(right)) - Py_RETURN_NOTIMPLEMENTED; - - if (PyDate_Check(left)) { - /* date + ??? */ - if (PyDelta_Check(right)) - /* date + delta */ - return add_date_timedelta((PyDateTime_Date *) left, - (PyDateTime_Delta *) right, - 0); - } - else { - /* ??? + date - * 'right' must be one of us, or we wouldn't have been called - */ - if (PyDelta_Check(left)) - /* delta + date */ - return add_date_timedelta((PyDateTime_Date *) right, - (PyDateTime_Delta *) left, - 0); - } - Py_RETURN_NOTIMPLEMENTED; -} - -static PyObject * -date_subtract(PyObject *left, PyObject *right) -{ - if (PyDateTime_Check(left) || PyDateTime_Check(right)) - Py_RETURN_NOTIMPLEMENTED; - - if (PyDate_Check(left)) { - if (PyDate_Check(right)) { - /* date - date */ - int left_ord = ymd_to_ord(GET_YEAR(left), - GET_MONTH(left), - GET_DAY(left)); - int right_ord = ymd_to_ord(GET_YEAR(right), - GET_MONTH(right), - GET_DAY(right)); - return new_delta(left_ord - right_ord, 0, 0, 0); - } - if (PyDelta_Check(right)) { - /* date - delta */ - return add_date_timedelta((PyDateTime_Date *) left, - (PyDateTime_Delta *) right, - 1); - } - } - Py_RETURN_NOTIMPLEMENTED; -} - - -/* Various ways to turn a date into a string. */ - -static PyObject * -date_repr(PyDateTime_Date *self) -{ - return PyUnicode_FromFormat("%s(%d, %d, %d)", - Py_TYPE(self)->tp_name, - GET_YEAR(self), GET_MONTH(self), GET_DAY(self)); -} - -static PyObject * -date_isoformat(PyDateTime_Date *self) -{ - return PyUnicode_FromFormat("%04d-%02d-%02d", - GET_YEAR(self), GET_MONTH(self), GET_DAY(self)); -} - -/* str() calls the appropriate isoformat() method. */ -static PyObject * -date_str(PyDateTime_Date *self) -{ - return _PyObject_CallMethodId((PyObject *)self, &PyId_isoformat, "()"); -} - - -static PyObject * -date_ctime(PyDateTime_Date *self) -{ - return format_ctime(self, 0, 0, 0); -} - -static PyObject * -date_strftime(PyDateTime_Date *self, PyObject *args, PyObject *kw) -{ - /* This method can be inherited, and needs to call the - * timetuple() method appropriate to self's class. - */ - PyObject *result; - PyObject *tuple; - PyObject *format; - _Py_IDENTIFIER(timetuple); - static char *keywords[] = {"format", NULL}; - - if (! PyArg_ParseTupleAndKeywords(args, kw, "U:strftime", keywords, - &format)) - return NULL; - - tuple = _PyObject_CallMethodId((PyObject *)self, &PyId_timetuple, "()"); - if (tuple == NULL) - return NULL; - result = wrap_strftime((PyObject *)self, format, tuple, - (PyObject *)self); - Py_DECREF(tuple); - return result; -} - -static PyObject * -date_format(PyDateTime_Date *self, PyObject *args) -{ - PyObject *format; - - if (!PyArg_ParseTuple(args, "U:__format__", &format)) - return NULL; - - /* if the format is zero length, return str(self) */ - if (PyUnicode_GetLength(format) == 0) - return PyObject_Str((PyObject *)self); - - return _PyObject_CallMethodId((PyObject *)self, &PyId_strftime, "O", format); -} - -/* ISO methods. */ - -static PyObject * -date_isoweekday(PyDateTime_Date *self) -{ - int dow = weekday(GET_YEAR(self), GET_MONTH(self), GET_DAY(self)); - - return PyLong_FromLong(dow + 1); -} - -static PyObject * -date_isocalendar(PyDateTime_Date *self) -{ - int year = GET_YEAR(self); - int week1_monday = iso_week1_monday(year); - int today = ymd_to_ord(year, GET_MONTH(self), GET_DAY(self)); - int week; - int day; - - week = divmod(today - week1_monday, 7, &day); - if (week < 0) { - --year; - week1_monday = iso_week1_monday(year); - week = divmod(today - week1_monday, 7, &day); - } - else if (week >= 52 && today >= iso_week1_monday(year + 1)) { - ++year; - week = 0; - } - return Py_BuildValue("iii", year, week + 1, day + 1); -} - -/* Miscellaneous methods. */ - -static PyObject * -date_richcompare(PyObject *self, PyObject *other, int op) -{ - if (PyDate_Check(other)) { - int diff = memcmp(((PyDateTime_Date *)self)->data, - ((PyDateTime_Date *)other)->data, - _PyDateTime_DATE_DATASIZE); - return diff_to_bool(diff, op); - } - else - Py_RETURN_NOTIMPLEMENTED; -} - -static PyObject * -date_timetuple(PyDateTime_Date *self) -{ - return build_struct_time(GET_YEAR(self), - GET_MONTH(self), - GET_DAY(self), - 0, 0, 0, -1); -} - -static PyObject * -date_replace(PyDateTime_Date *self, PyObject *args, PyObject *kw) -{ - PyObject *clone; - PyObject *tuple; - int year = GET_YEAR(self); - int month = GET_MONTH(self); - int day = GET_DAY(self); - - if (! PyArg_ParseTupleAndKeywords(args, kw, "|iii:replace", date_kws, - &year, &month, &day)) - return NULL; - tuple = Py_BuildValue("iii", year, month, day); - if (tuple == NULL) - return NULL; - clone = date_new(Py_TYPE(self), tuple, NULL); - Py_DECREF(tuple); - return clone; -} - -static Py_hash_t -generic_hash(unsigned char *data, int len) -{ - return _Py_HashBytes(data, len); -} - - -static PyObject *date_getstate(PyDateTime_Date *self); - -static Py_hash_t -date_hash(PyDateTime_Date *self) -{ - if (self->hashcode == -1) - self->hashcode = generic_hash( - (unsigned char *)self->data, _PyDateTime_DATE_DATASIZE); - - return self->hashcode; -} - -static PyObject * -date_toordinal(PyDateTime_Date *self) -{ - return PyLong_FromLong(ymd_to_ord(GET_YEAR(self), GET_MONTH(self), - GET_DAY(self))); -} - -static PyObject * -date_weekday(PyDateTime_Date *self) -{ - int dow = weekday(GET_YEAR(self), GET_MONTH(self), GET_DAY(self)); - - return PyLong_FromLong(dow); -} - -/* Pickle support, a simple use of __reduce__. */ - -/* __getstate__ isn't exposed */ -static PyObject * -date_getstate(PyDateTime_Date *self) -{ - PyObject* field; - field = PyBytes_FromStringAndSize((char*)self->data, - _PyDateTime_DATE_DATASIZE); - return Py_BuildValue("(N)", field); -} - -static PyObject * -date_reduce(PyDateTime_Date *self, PyObject *arg) -{ - return Py_BuildValue("(ON)", Py_TYPE(self), date_getstate(self)); -} - -static PyMethodDef date_methods[] = { - - /* Class methods: */ - - {"fromtimestamp", (PyCFunction)date_fromtimestamp, METH_VARARGS | - METH_CLASS, - PyDoc_STR("timestamp -> local date from a POSIX timestamp (like " - "time.time()).")}, - - {"fromordinal", (PyCFunction)date_fromordinal, METH_VARARGS | - METH_CLASS, - PyDoc_STR("int -> date corresponding to a proleptic Gregorian " - "ordinal.")}, - - {"today", (PyCFunction)date_today, METH_NOARGS | METH_CLASS, - PyDoc_STR("Current date or datetime: same as " - "self.__class__.fromtimestamp(time.time()).")}, - - /* Instance methods: */ - - {"ctime", (PyCFunction)date_ctime, METH_NOARGS, - PyDoc_STR("Return ctime() style string.")}, - - {"strftime", (PyCFunction)date_strftime, METH_VARARGS | METH_KEYWORDS, - PyDoc_STR("format -> strftime() style string.")}, - - {"__format__", (PyCFunction)date_format, METH_VARARGS, - PyDoc_STR("Formats self with strftime.")}, - - {"timetuple", (PyCFunction)date_timetuple, METH_NOARGS, - PyDoc_STR("Return time tuple, compatible with time.localtime().")}, - - {"isocalendar", (PyCFunction)date_isocalendar, METH_NOARGS, - PyDoc_STR("Return a 3-tuple containing ISO year, week number, and " - "weekday.")}, - - {"isoformat", (PyCFunction)date_isoformat, METH_NOARGS, - PyDoc_STR("Return string in ISO 8601 format, YYYY-MM-DD.")}, - - {"isoweekday", (PyCFunction)date_isoweekday, METH_NOARGS, - PyDoc_STR("Return the day of the week represented by the date.\n" - "Monday == 1 ... Sunday == 7")}, - - {"toordinal", (PyCFunction)date_toordinal, METH_NOARGS, - PyDoc_STR("Return proleptic Gregorian ordinal. January 1 of year " - "1 is day 1.")}, - - {"weekday", (PyCFunction)date_weekday, METH_NOARGS, - PyDoc_STR("Return the day of the week represented by the date.\n" - "Monday == 0 ... Sunday == 6")}, - - {"replace", (PyCFunction)date_replace, METH_VARARGS | METH_KEYWORDS, - PyDoc_STR("Return date with new specified fields.")}, - - {"__reduce__", (PyCFunction)date_reduce, METH_NOARGS, - PyDoc_STR("__reduce__() -> (cls, state)")}, - - {NULL, NULL} -}; - -static char date_doc[] = -PyDoc_STR("date(year, month, day) --> date object"); - -static PyNumberMethods date_as_number = { - date_add, /* nb_add */ - date_subtract, /* nb_subtract */ - 0, /* nb_multiply */ - 0, /* nb_remainder */ - 0, /* nb_divmod */ - 0, /* nb_power */ - 0, /* nb_negative */ - 0, /* nb_positive */ - 0, /* nb_absolute */ - 0, /* nb_bool */ -}; - -static PyTypeObject PyDateTime_DateType = { - PyVarObject_HEAD_INIT(NULL, 0) - "datetime.date", /* tp_name */ - sizeof(PyDateTime_Date), /* tp_basicsize */ - 0, /* tp_itemsize */ - 0, /* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_reserved */ - (reprfunc)date_repr, /* tp_repr */ - &date_as_number, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - (hashfunc)date_hash, /* tp_hash */ - 0, /* tp_call */ - (reprfunc)date_str, /* tp_str */ - PyObject_GenericGetAttr, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ - date_doc, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - date_richcompare, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - date_methods, /* tp_methods */ - 0, /* tp_members */ - date_getset, /* 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 */ - date_new, /* tp_new */ - 0, /* tp_free */ -}; - -/* - * PyDateTime_TZInfo implementation. - */ - -/* This is a pure abstract base class, so doesn't do anything beyond - * raising NotImplemented exceptions. Real tzinfo classes need - * to derive from this. This is mostly for clarity, and for efficiency in - * datetime and time constructors (their tzinfo arguments need to - * be subclasses of this tzinfo class, which is easy and quick to check). - * - * Note: For reasons having to do with pickling of subclasses, we have - * to allow tzinfo objects to be instantiated. This wasn't an issue - * in the Python implementation (__init__() could raise NotImplementedError - * there without ill effect), but doing so in the C implementation hit a - * brick wall. - */ - -static PyObject * -tzinfo_nogo(const char* methodname) -{ - PyErr_Format(PyExc_NotImplementedError, - "a tzinfo subclass must implement %s()", - methodname); - return NULL; -} - -/* Methods. A subclass must implement these. */ - -static PyObject * -tzinfo_tzname(PyDateTime_TZInfo *self, PyObject *dt) -{ - return tzinfo_nogo("tzname"); -} - -static PyObject * -tzinfo_utcoffset(PyDateTime_TZInfo *self, PyObject *dt) -{ - return tzinfo_nogo("utcoffset"); -} - -static PyObject * -tzinfo_dst(PyDateTime_TZInfo *self, PyObject *dt) -{ - return tzinfo_nogo("dst"); -} - - -static PyObject *add_datetime_timedelta(PyDateTime_DateTime *date, - PyDateTime_Delta *delta, - int factor); -static PyObject *datetime_utcoffset(PyObject *self, PyObject *); -static PyObject *datetime_dst(PyObject *self, PyObject *); - -static PyObject * -tzinfo_fromutc(PyDateTime_TZInfo *self, PyObject *dt) -{ - PyObject *result = NULL; - PyObject *off = NULL, *dst = NULL; - PyDateTime_Delta *delta = NULL; - - if (!PyDateTime_Check(dt)) { - PyErr_SetString(PyExc_TypeError, - "fromutc: argument must be a datetime"); - return NULL; - } - if (GET_DT_TZINFO(dt) != (PyObject *)self) { - PyErr_SetString(PyExc_ValueError, "fromutc: dt.tzinfo " - "is not self"); - return NULL; - } - - off = datetime_utcoffset(dt, NULL); - if (off == NULL) - return NULL; - if (off == Py_None) { - PyErr_SetString(PyExc_ValueError, "fromutc: non-None " - "utcoffset() result required"); - goto Fail; - } - - dst = datetime_dst(dt, NULL); - if (dst == NULL) - goto Fail; - if (dst == Py_None) { - PyErr_SetString(PyExc_ValueError, "fromutc: non-None " - "dst() result required"); - goto Fail; - } - - delta = (PyDateTime_Delta *)delta_subtract(off, dst); - if (delta == NULL) - goto Fail; - result = add_datetime_timedelta((PyDateTime_DateTime *)dt, delta, 1); - if (result == NULL) - goto Fail; - - Py_DECREF(dst); - dst = call_dst(GET_DT_TZINFO(dt), result); - if (dst == NULL) - goto Fail; - if (dst == Py_None) - goto Inconsistent; - if (delta_bool(delta) != 0) { - PyObject *temp = result; - result = add_datetime_timedelta((PyDateTime_DateTime *)result, - (PyDateTime_Delta *)dst, 1); - Py_DECREF(temp); - if (result == NULL) - goto Fail; - } - Py_DECREF(delta); - Py_DECREF(dst); - Py_DECREF(off); - return result; - -Inconsistent: - PyErr_SetString(PyExc_ValueError, "fromutc: tz.dst() gave" - "inconsistent results; cannot convert"); - - /* fall thru to failure */ -Fail: - Py_XDECREF(off); - Py_XDECREF(dst); - Py_XDECREF(delta); - Py_XDECREF(result); - return NULL; -} - -/* - * Pickle support. This is solely so that tzinfo subclasses can use - * pickling -- tzinfo itself is supposed to be uninstantiable. - */ - -static PyObject * -tzinfo_reduce(PyObject *self) -{ - PyObject *args, *state, *tmp; - PyObject *getinitargs, *getstate; - _Py_IDENTIFIER(__getinitargs__); - _Py_IDENTIFIER(__getstate__); - - tmp = PyTuple_New(0); - if (tmp == NULL) - return NULL; - - getinitargs = _PyObject_GetAttrId(self, &PyId___getinitargs__); - if (getinitargs != NULL) { - args = PyObject_CallObject(getinitargs, tmp); - Py_DECREF(getinitargs); - if (args == NULL) { - Py_DECREF(tmp); - return NULL; - } - } - else { - PyErr_Clear(); - args = tmp; - Py_INCREF(args); - } - - getstate = _PyObject_GetAttrId(self, &PyId___getstate__); - if (getstate != NULL) { - state = PyObject_CallObject(getstate, tmp); - Py_DECREF(getstate); - if (state == NULL) { - Py_DECREF(args); - Py_DECREF(tmp); - return NULL; - } - } - else { - PyObject **dictptr; - PyErr_Clear(); - state = Py_None; - dictptr = _PyObject_GetDictPtr(self); - if (dictptr && *dictptr && PyDict_Size(*dictptr)) - state = *dictptr; - Py_INCREF(state); - } - - Py_DECREF(tmp); - - if (state == Py_None) { - Py_DECREF(state); - return Py_BuildValue("(ON)", Py_TYPE(self), args); - } - else - return Py_BuildValue("(ONN)", Py_TYPE(self), args, state); -} - -static PyMethodDef tzinfo_methods[] = { - - {"tzname", (PyCFunction)tzinfo_tzname, METH_O, - PyDoc_STR("datetime -> string name of time zone.")}, - - {"utcoffset", (PyCFunction)tzinfo_utcoffset, METH_O, - PyDoc_STR("datetime -> timedelta showing offset from UTC, negative " - "values indicating West of UTC")}, - - {"dst", (PyCFunction)tzinfo_dst, METH_O, - PyDoc_STR("datetime -> DST offset in minutes east of UTC.")}, - - {"fromutc", (PyCFunction)tzinfo_fromutc, METH_O, - PyDoc_STR("datetime in UTC -> datetime in local time.")}, - - {"__reduce__", (PyCFunction)tzinfo_reduce, METH_NOARGS, - PyDoc_STR("-> (cls, state)")}, - - {NULL, NULL} -}; - -static char tzinfo_doc[] = -PyDoc_STR("Abstract base class for time zone info objects."); - -static PyTypeObject PyDateTime_TZInfoType = { - PyVarObject_HEAD_INIT(NULL, 0) - "datetime.tzinfo", /* tp_name */ - sizeof(PyDateTime_TZInfo), /* 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 */ - PyObject_GenericGetAttr, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ - tzinfo_doc, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - tzinfo_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 */ - PyType_GenericNew, /* tp_new */ - 0, /* tp_free */ -}; - -static char *timezone_kws[] = {"offset", "name", NULL}; - -static PyObject * -timezone_new(PyTypeObject *type, PyObject *args, PyObject *kw) -{ - PyObject *offset; - PyObject *name = NULL; - if (PyArg_ParseTupleAndKeywords(args, kw, "O!|O!:timezone", timezone_kws, - &PyDateTime_DeltaType, &offset, - &PyUnicode_Type, &name)) - return new_timezone(offset, name); - - return NULL; -} - -static void -timezone_dealloc(PyDateTime_TimeZone *self) -{ - Py_CLEAR(self->offset); - Py_CLEAR(self->name); - Py_TYPE(self)->tp_free((PyObject *)self); -} - -static PyObject * -timezone_richcompare(PyDateTime_TimeZone *self, - PyDateTime_TimeZone *other, int op) -{ - if (op != Py_EQ && op != Py_NE) - Py_RETURN_NOTIMPLEMENTED; - if (Py_TYPE(other) != &PyDateTime_TimeZoneType) { - if (op == Py_EQ) - Py_RETURN_FALSE; - else - Py_RETURN_TRUE; - } - return delta_richcompare(self->offset, other->offset, op); -} - -static Py_hash_t -timezone_hash(PyDateTime_TimeZone *self) -{ - return delta_hash((PyDateTime_Delta *)self->offset); -} - -/* Check argument type passed to tzname, utcoffset, or dst methods. - Returns 0 for good argument. Returns -1 and sets exception info - otherwise. - */ -static int -_timezone_check_argument(PyObject *dt, const char *meth) -{ - if (dt == Py_None || PyDateTime_Check(dt)) - return 0; - PyErr_Format(PyExc_TypeError, "%s(dt) argument must be a datetime instance" - " or None, not %.200s", meth, Py_TYPE(dt)->tp_name); - return -1; -} - -static PyObject * -timezone_repr(PyDateTime_TimeZone *self) -{ - /* Note that although timezone is not subclassable, it is convenient - to use Py_TYPE(self)->tp_name here. */ - const char *type_name = Py_TYPE(self)->tp_name; - - if (((PyObject *)self) == PyDateTime_TimeZone_UTC) - return PyUnicode_FromFormat("%s.utc", type_name); - - if (self->name == NULL) - return PyUnicode_FromFormat("%s(%R)", type_name, self->offset); - - return PyUnicode_FromFormat("%s(%R, %R)", type_name, self->offset, - self->name); -} - - -static PyObject * -timezone_str(PyDateTime_TimeZone *self) -{ - int hours, minutes, seconds; - PyObject *offset; - char sign; - - if (self->name != NULL) { - Py_INCREF(self->name); - return self->name; - } - /* Offset is normalized, so it is negative if days < 0 */ - if (GET_TD_DAYS(self->offset) < 0) { - sign = '-'; - offset = delta_negative((PyDateTime_Delta *)self->offset); - if (offset == NULL) - return NULL; - } - else { - sign = '+'; - offset = self->offset; - Py_INCREF(offset); - } - /* Offset is not negative here. */ - seconds = GET_TD_SECONDS(offset); - Py_DECREF(offset); - minutes = divmod(seconds, 60, &seconds); - hours = divmod(minutes, 60, &minutes); - /* XXX ignore sub-minute data, curently not allowed. */ - assert(seconds == 0); - return PyUnicode_FromFormat("UTC%c%02d:%02d", sign, hours, minutes); -} - -static PyObject * -timezone_tzname(PyDateTime_TimeZone *self, PyObject *dt) -{ - if (_timezone_check_argument(dt, "tzname") == -1) - return NULL; - - return timezone_str(self); -} - -static PyObject * -timezone_utcoffset(PyDateTime_TimeZone *self, PyObject *dt) -{ - if (_timezone_check_argument(dt, "utcoffset") == -1) - return NULL; - - Py_INCREF(self->offset); - return self->offset; -} - -static PyObject * -timezone_dst(PyObject *self, PyObject *dt) -{ - if (_timezone_check_argument(dt, "dst") == -1) - return NULL; - - Py_RETURN_NONE; -} - -static PyObject * -timezone_fromutc(PyDateTime_TimeZone *self, PyDateTime_DateTime *dt) -{ - if (!PyDateTime_Check(dt)) { - PyErr_SetString(PyExc_TypeError, - "fromutc: argument must be a datetime"); - return NULL; - } - if (!HASTZINFO(dt) || dt->tzinfo != (PyObject *)self) { - PyErr_SetString(PyExc_ValueError, "fromutc: dt.tzinfo " - "is not self"); - return NULL; - } - - return add_datetime_timedelta(dt, (PyDateTime_Delta *)self->offset, 1); -} - -static PyObject * -timezone_getinitargs(PyDateTime_TimeZone *self) -{ - if (self->name == NULL) - return Py_BuildValue("(O)", self->offset); - return Py_BuildValue("(OO)", self->offset, self->name); -} - -static PyMethodDef timezone_methods[] = { - {"tzname", (PyCFunction)timezone_tzname, METH_O, - PyDoc_STR("If name is specified when timezone is created, returns the name." - " Otherwise returns offset as 'UTC(+|-)HH:MM'.")}, - - {"utcoffset", (PyCFunction)timezone_utcoffset, METH_O, - PyDoc_STR("Return fixed offset.")}, - - {"dst", (PyCFunction)timezone_dst, METH_O, - PyDoc_STR("Return None.")}, - - {"fromutc", (PyCFunction)timezone_fromutc, METH_O, - PyDoc_STR("datetime in UTC -> datetime in local time.")}, - - {"__getinitargs__", (PyCFunction)timezone_getinitargs, METH_NOARGS, - PyDoc_STR("pickle support")}, - - {NULL, NULL} -}; - -static char timezone_doc[] = -PyDoc_STR("Fixed offset from UTC implementation of tzinfo."); - -static PyTypeObject PyDateTime_TimeZoneType = { - PyVarObject_HEAD_INIT(NULL, 0) - "datetime.timezone", /* tp_name */ - sizeof(PyDateTime_TimeZone), /* tp_basicsize */ - 0, /* tp_itemsize */ - (destructor)timezone_dealloc, /* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_reserved */ - (reprfunc)timezone_repr, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - (hashfunc)timezone_hash, /* tp_hash */ - 0, /* tp_call */ - (reprfunc)timezone_str, /* tp_str */ - 0, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT, /* tp_flags */ - timezone_doc, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - (richcmpfunc)timezone_richcompare,/* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - timezone_methods, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - &PyDateTime_TZInfoType, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - timezone_new, /* tp_new */ -}; - -/* - * PyDateTime_Time implementation. - */ - -/* Accessor properties. - */ - -static PyObject * -time_hour(PyDateTime_Time *self, void *unused) -{ - return PyLong_FromLong(TIME_GET_HOUR(self)); -} - -static PyObject * -time_minute(PyDateTime_Time *self, void *unused) -{ - return PyLong_FromLong(TIME_GET_MINUTE(self)); -} - -/* The name time_second conflicted with some platform header file. */ -static PyObject * -py_time_second(PyDateTime_Time *self, void *unused) -{ - return PyLong_FromLong(TIME_GET_SECOND(self)); -} - -static PyObject * -time_microsecond(PyDateTime_Time *self, void *unused) -{ - return PyLong_FromLong(TIME_GET_MICROSECOND(self)); -} - -static PyObject * -time_tzinfo(PyDateTime_Time *self, void *unused) -{ - PyObject *result = HASTZINFO(self) ? self->tzinfo : Py_None; - Py_INCREF(result); - return result; -} - -static PyGetSetDef time_getset[] = { - {"hour", (getter)time_hour}, - {"minute", (getter)time_minute}, - {"second", (getter)py_time_second}, - {"microsecond", (getter)time_microsecond}, - {"tzinfo", (getter)time_tzinfo}, - {NULL} -}; - -/* - * Constructors. - */ - -static char *time_kws[] = {"hour", "minute", "second", "microsecond", - "tzinfo", NULL}; - -static PyObject * -time_new(PyTypeObject *type, PyObject *args, PyObject *kw) -{ - PyObject *self = NULL; - PyObject *state; - int hour = 0; - int minute = 0; - int second = 0; - int usecond = 0; - PyObject *tzinfo = Py_None; - - /* Check for invocation from pickle with __getstate__ state */ - if (PyTuple_GET_SIZE(args) >= 1 && - PyTuple_GET_SIZE(args) <= 2 && - PyBytes_Check(state = PyTuple_GET_ITEM(args, 0)) && - PyBytes_GET_SIZE(state) == _PyDateTime_TIME_DATASIZE && - ((unsigned char) (PyBytes_AS_STRING(state)[0])) < 24) - { - PyDateTime_Time *me; - char aware; - - if (PyTuple_GET_SIZE(args) == 2) { - tzinfo = PyTuple_GET_ITEM(args, 1); - if (check_tzinfo_subclass(tzinfo) < 0) { - PyErr_SetString(PyExc_TypeError, "bad " - "tzinfo state arg"); - return NULL; - } - } - aware = (char)(tzinfo != Py_None); - me = (PyDateTime_Time *) (type->tp_alloc(type, aware)); - if (me != NULL) { - char *pdata = PyBytes_AS_STRING(state); - - memcpy(me->data, pdata, _PyDateTime_TIME_DATASIZE); - me->hashcode = -1; - me->hastzinfo = aware; - if (aware) { - Py_INCREF(tzinfo); - me->tzinfo = tzinfo; - } - } - return (PyObject *)me; - } - - if (PyArg_ParseTupleAndKeywords(args, kw, "|iiiiO", time_kws, - &hour, &minute, &second, &usecond, - &tzinfo)) { - if (check_time_args(hour, minute, second, usecond) < 0) - return NULL; - if (check_tzinfo_subclass(tzinfo) < 0) - return NULL; - self = new_time_ex(hour, minute, second, usecond, tzinfo, - type); - } - return self; -} - -/* - * Destructor. - */ - -static void -time_dealloc(PyDateTime_Time *self) -{ - if (HASTZINFO(self)) { - Py_XDECREF(self->tzinfo); - } - Py_TYPE(self)->tp_free((PyObject *)self); -} - -/* - * Indirect access to tzinfo methods. - */ - -/* These are all METH_NOARGS, so don't need to check the arglist. */ -static PyObject * -time_utcoffset(PyObject *self, PyObject *unused) { - return call_utcoffset(GET_TIME_TZINFO(self), Py_None); -} - -static PyObject * -time_dst(PyObject *self, PyObject *unused) { - return call_dst(GET_TIME_TZINFO(self), Py_None); -} - -static PyObject * -time_tzname(PyDateTime_Time *self, PyObject *unused) { - return call_tzname(GET_TIME_TZINFO(self), Py_None); -} - -/* - * Various ways to turn a time into a string. - */ - -static PyObject * -time_repr(PyDateTime_Time *self) -{ - const char *type_name = Py_TYPE(self)->tp_name; - int h = TIME_GET_HOUR(self); - int m = TIME_GET_MINUTE(self); - int s = TIME_GET_SECOND(self); - int us = TIME_GET_MICROSECOND(self); - PyObject *result = NULL; - - if (us) - result = PyUnicode_FromFormat("%s(%d, %d, %d, %d)", - type_name, h, m, s, us); - else if (s) - result = PyUnicode_FromFormat("%s(%d, %d, %d)", - type_name, h, m, s); - else - result = PyUnicode_FromFormat("%s(%d, %d)", type_name, h, m); - if (result != NULL && HASTZINFO(self)) - result = append_keyword_tzinfo(result, self->tzinfo); - return result; -} - -static PyObject * -time_str(PyDateTime_Time *self) -{ - return _PyObject_CallMethodId((PyObject *)self, &PyId_isoformat, "()"); -} - -static PyObject * -time_isoformat(PyDateTime_Time *self, PyObject *unused) -{ - char buf[100]; - PyObject *result; - int us = TIME_GET_MICROSECOND(self); - - if (us) - result = PyUnicode_FromFormat("%02d:%02d:%02d.%06d", - TIME_GET_HOUR(self), - TIME_GET_MINUTE(self), - TIME_GET_SECOND(self), - us); - else - result = PyUnicode_FromFormat("%02d:%02d:%02d", - TIME_GET_HOUR(self), - TIME_GET_MINUTE(self), - TIME_GET_SECOND(self)); - - if (result == NULL || !HASTZINFO(self) || self->tzinfo == Py_None) - return result; - - /* We need to append the UTC offset. */ - if (format_utcoffset(buf, sizeof(buf), ":", self->tzinfo, - Py_None) < 0) { - Py_DECREF(result); - return NULL; - } - PyUnicode_AppendAndDel(&result, PyUnicode_FromString(buf)); - return result; -} - -static PyObject * -time_strftime(PyDateTime_Time *self, PyObject *args, PyObject *kw) -{ - PyObject *result; - PyObject *tuple; - PyObject *format; - static char *keywords[] = {"format", NULL}; - - if (! PyArg_ParseTupleAndKeywords(args, kw, "U:strftime", keywords, - &format)) - return NULL; - - /* Python's strftime does insane things with the year part of the - * timetuple. The year is forced to (the otherwise nonsensical) - * 1900 to work around that. - */ - tuple = Py_BuildValue("iiiiiiiii", - 1900, 1, 1, /* year, month, day */ - TIME_GET_HOUR(self), - TIME_GET_MINUTE(self), - TIME_GET_SECOND(self), - 0, 1, -1); /* weekday, daynum, dst */ - if (tuple == NULL) - return NULL; - assert(PyTuple_Size(tuple) == 9); - result = wrap_strftime((PyObject *)self, format, tuple, - Py_None); - Py_DECREF(tuple); - return result; -} - -/* - * Miscellaneous methods. - */ - -static PyObject * -time_richcompare(PyObject *self, PyObject *other, int op) -{ - PyObject *result = NULL; - PyObject *offset1, *offset2; - int diff; - - if (! PyTime_Check(other)) - Py_RETURN_NOTIMPLEMENTED; - - if (GET_TIME_TZINFO(self) == GET_TIME_TZINFO(other)) { - diff = memcmp(((PyDateTime_Time *)self)->data, - ((PyDateTime_Time *)other)->data, - _PyDateTime_TIME_DATASIZE); - return diff_to_bool(diff, op); - } - offset1 = time_utcoffset(self, NULL); - if (offset1 == NULL) - return NULL; - offset2 = time_utcoffset(other, NULL); - if (offset2 == NULL) - goto done; - /* If they're both naive, or both aware and have the same offsets, - * we get off cheap. Note that if they're both naive, offset1 == - * offset2 == Py_None at this point. - */ - if ((offset1 == offset2) || - (PyDelta_Check(offset1) && PyDelta_Check(offset2) && - delta_cmp(offset1, offset2) == 0)) { - diff = memcmp(((PyDateTime_Time *)self)->data, - ((PyDateTime_Time *)other)->data, - _PyDateTime_TIME_DATASIZE); - result = diff_to_bool(diff, op); - } - /* The hard case: both aware with different UTC offsets */ - else if (offset1 != Py_None && offset2 != Py_None) { - int offsecs1, offsecs2; - assert(offset1 != offset2); /* else last "if" handled it */ - offsecs1 = TIME_GET_HOUR(self) * 3600 + - TIME_GET_MINUTE(self) * 60 + - TIME_GET_SECOND(self) - - GET_TD_DAYS(offset1) * 86400 - - GET_TD_SECONDS(offset1); - offsecs2 = TIME_GET_HOUR(other) * 3600 + - TIME_GET_MINUTE(other) * 60 + - TIME_GET_SECOND(other) - - GET_TD_DAYS(offset2) * 86400 - - GET_TD_SECONDS(offset2); - diff = offsecs1 - offsecs2; - if (diff == 0) - diff = TIME_GET_MICROSECOND(self) - - TIME_GET_MICROSECOND(other); - result = diff_to_bool(diff, op); - } - else if (op == Py_EQ) { - result = Py_False; - Py_INCREF(result); - } - else if (op == Py_NE) { - result = Py_True; - Py_INCREF(result); - } - else { - PyErr_SetString(PyExc_TypeError, - "can't compare offset-naive and " - "offset-aware times"); - } - done: - Py_DECREF(offset1); - Py_XDECREF(offset2); - return result; -} - -static Py_hash_t -time_hash(PyDateTime_Time *self) -{ - if (self->hashcode == -1) { - PyObject *offset; - - offset = time_utcoffset((PyObject *)self, NULL); - - if (offset == NULL) - return -1; - - /* Reduce this to a hash of another object. */ - if (offset == Py_None) - self->hashcode = generic_hash( - (unsigned char *)self->data, _PyDateTime_TIME_DATASIZE); - else { - PyObject *temp1, *temp2; - int seconds, microseconds; - assert(HASTZINFO(self)); - seconds = TIME_GET_HOUR(self) * 3600 + - TIME_GET_MINUTE(self) * 60 + - TIME_GET_SECOND(self); - microseconds = TIME_GET_MICROSECOND(self); - temp1 = new_delta(0, seconds, microseconds, 1); - if (temp1 == NULL) { - Py_DECREF(offset); - return -1; - } - temp2 = delta_subtract(temp1, offset); - Py_DECREF(temp1); - if (temp2 == NULL) { - Py_DECREF(offset); - return -1; - } - self->hashcode = PyObject_Hash(temp2); - Py_DECREF(temp2); - } - Py_DECREF(offset); - } - return self->hashcode; -} - -static PyObject * -time_replace(PyDateTime_Time *self, PyObject *args, PyObject *kw) -{ - PyObject *clone; - PyObject *tuple; - int hh = TIME_GET_HOUR(self); - int mm = TIME_GET_MINUTE(self); - int ss = TIME_GET_SECOND(self); - int us = TIME_GET_MICROSECOND(self); - PyObject *tzinfo = HASTZINFO(self) ? self->tzinfo : Py_None; - - if (! PyArg_ParseTupleAndKeywords(args, kw, "|iiiiO:replace", - time_kws, - &hh, &mm, &ss, &us, &tzinfo)) - return NULL; - tuple = Py_BuildValue("iiiiO", hh, mm, ss, us, tzinfo); - if (tuple == NULL) - return NULL; - clone = time_new(Py_TYPE(self), tuple, NULL); - Py_DECREF(tuple); - return clone; -} - -/* Pickle support, a simple use of __reduce__. */ - -/* Let basestate be the non-tzinfo data string. - * If tzinfo is None, this returns (basestate,), else (basestate, tzinfo). - * So it's a tuple in any (non-error) case. - * __getstate__ isn't exposed. - */ -static PyObject * -time_getstate(PyDateTime_Time *self) -{ - PyObject *basestate; - PyObject *result = NULL; - - basestate = PyBytes_FromStringAndSize((char *)self->data, - _PyDateTime_TIME_DATASIZE); - if (basestate != NULL) { - if (! HASTZINFO(self) || self->tzinfo == Py_None) - result = PyTuple_Pack(1, basestate); - else - result = PyTuple_Pack(2, basestate, self->tzinfo); - Py_DECREF(basestate); - } - return result; -} - -static PyObject * -time_reduce(PyDateTime_Time *self, PyObject *arg) -{ - return Py_BuildValue("(ON)", Py_TYPE(self), time_getstate(self)); -} - -static PyMethodDef time_methods[] = { - - {"isoformat", (PyCFunction)time_isoformat, METH_NOARGS, - PyDoc_STR("Return string in ISO 8601 format, HH:MM:SS[.mmmmmm]" - "[+HH:MM].")}, - - {"strftime", (PyCFunction)time_strftime, METH_VARARGS | METH_KEYWORDS, - PyDoc_STR("format -> strftime() style string.")}, - - {"__format__", (PyCFunction)date_format, METH_VARARGS, - PyDoc_STR("Formats self with strftime.")}, - - {"utcoffset", (PyCFunction)time_utcoffset, METH_NOARGS, - PyDoc_STR("Return self.tzinfo.utcoffset(self).")}, - - {"tzname", (PyCFunction)time_tzname, METH_NOARGS, - PyDoc_STR("Return self.tzinfo.tzname(self).")}, - - {"dst", (PyCFunction)time_dst, METH_NOARGS, - PyDoc_STR("Return self.tzinfo.dst(self).")}, - - {"replace", (PyCFunction)time_replace, METH_VARARGS | METH_KEYWORDS, - PyDoc_STR("Return time with new specified fields.")}, - - {"__reduce__", (PyCFunction)time_reduce, METH_NOARGS, - PyDoc_STR("__reduce__() -> (cls, state)")}, - - {NULL, NULL} -}; - -static char time_doc[] = -PyDoc_STR("time([hour[, minute[, second[, microsecond[, tzinfo]]]]]) --> a time object\n\ -\n\ -All arguments are optional. tzinfo may be None, or an instance of\n\ -a tzinfo subclass. The remaining arguments may be ints.\n"); - -static PyTypeObject PyDateTime_TimeType = { - PyVarObject_HEAD_INIT(NULL, 0) - "datetime.time", /* tp_name */ - sizeof(PyDateTime_Time), /* tp_basicsize */ - 0, /* tp_itemsize */ - (destructor)time_dealloc, /* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_reserved */ - (reprfunc)time_repr, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - (hashfunc)time_hash, /* tp_hash */ - 0, /* tp_call */ - (reprfunc)time_str, /* tp_str */ - PyObject_GenericGetAttr, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ - time_doc, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - time_richcompare, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - time_methods, /* tp_methods */ - 0, /* tp_members */ - time_getset, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - time_alloc, /* tp_alloc */ - time_new, /* tp_new */ - 0, /* tp_free */ -}; - -/* - * PyDateTime_DateTime implementation. - */ - -/* Accessor properties. Properties for day, month, and year are inherited - * from date. - */ - -static PyObject * -datetime_hour(PyDateTime_DateTime *self, void *unused) -{ - return PyLong_FromLong(DATE_GET_HOUR(self)); -} - -static PyObject * -datetime_minute(PyDateTime_DateTime *self, void *unused) -{ - return PyLong_FromLong(DATE_GET_MINUTE(self)); -} - -static PyObject * -datetime_second(PyDateTime_DateTime *self, void *unused) -{ - return PyLong_FromLong(DATE_GET_SECOND(self)); -} - -static PyObject * -datetime_microsecond(PyDateTime_DateTime *self, void *unused) -{ - return PyLong_FromLong(DATE_GET_MICROSECOND(self)); -} - -static PyObject * -datetime_tzinfo(PyDateTime_DateTime *self, void *unused) -{ - PyObject *result = HASTZINFO(self) ? self->tzinfo : Py_None; - Py_INCREF(result); - return result; -} - -static PyGetSetDef datetime_getset[] = { - {"hour", (getter)datetime_hour}, - {"minute", (getter)datetime_minute}, - {"second", (getter)datetime_second}, - {"microsecond", (getter)datetime_microsecond}, - {"tzinfo", (getter)datetime_tzinfo}, - {NULL} -}; - -/* - * Constructors. - */ - -static char *datetime_kws[] = { - "year", "month", "day", "hour", "minute", "second", - "microsecond", "tzinfo", NULL -}; - -static PyObject * -datetime_new(PyTypeObject *type, PyObject *args, PyObject *kw) -{ - PyObject *self = NULL; - PyObject *state; - int year; - int month; - int day; - int hour = 0; - int minute = 0; - int second = 0; - int usecond = 0; - PyObject *tzinfo = Py_None; - - /* Check for invocation from pickle with __getstate__ state */ - if (PyTuple_GET_SIZE(args) >= 1 && - PyTuple_GET_SIZE(args) <= 2 && - PyBytes_Check(state = PyTuple_GET_ITEM(args, 0)) && - PyBytes_GET_SIZE(state) == _PyDateTime_DATETIME_DATASIZE && - MONTH_IS_SANE(PyBytes_AS_STRING(state)[2])) - { - PyDateTime_DateTime *me; - char aware; - - if (PyTuple_GET_SIZE(args) == 2) { - tzinfo = PyTuple_GET_ITEM(args, 1); - if (check_tzinfo_subclass(tzinfo) < 0) { - PyErr_SetString(PyExc_TypeError, "bad " - "tzinfo state arg"); - return NULL; - } - } - aware = (char)(tzinfo != Py_None); - me = (PyDateTime_DateTime *) (type->tp_alloc(type , aware)); - if (me != NULL) { - char *pdata = PyBytes_AS_STRING(state); - - memcpy(me->data, pdata, _PyDateTime_DATETIME_DATASIZE); - me->hashcode = -1; - me->hastzinfo = aware; - if (aware) { - Py_INCREF(tzinfo); - me->tzinfo = tzinfo; - } - } - return (PyObject *)me; - } - - if (PyArg_ParseTupleAndKeywords(args, kw, "iii|iiiiO", datetime_kws, - &year, &month, &day, &hour, &minute, - &second, &usecond, &tzinfo)) { - if (check_date_args(year, month, day) < 0) - return NULL; - if (check_time_args(hour, minute, second, usecond) < 0) - return NULL; - if (check_tzinfo_subclass(tzinfo) < 0) - return NULL; - self = new_datetime_ex(year, month, day, - hour, minute, second, usecond, - tzinfo, type); - } - return self; -} - -/* TM_FUNC is the shared type of localtime() and gmtime(). */ -typedef struct tm *(*TM_FUNC)(const time_t *timer); - -/* Internal helper. - * Build datetime from a time_t and a distinct count of microseconds. - * Pass localtime or gmtime for f, to control the interpretation of timet. - */ -static PyObject * -datetime_from_timet_and_us(PyObject *cls, TM_FUNC f, time_t timet, int us, - PyObject *tzinfo) -{ - struct tm *tm; - - tm = f(&timet); - if (tm == NULL) { -#ifdef EINVAL - if (errno == 0) - errno = EINVAL; -#endif - return PyErr_SetFromErrno(PyExc_OSError); - } - - /* The platform localtime/gmtime may insert leap seconds, - * indicated by tm->tm_sec > 59. We don't care about them, - * except to the extent that passing them on to the datetime - * constructor would raise ValueError for a reason that - * made no sense to the user. - */ - if (tm->tm_sec > 59) - tm->tm_sec = 59; - return PyObject_CallFunction(cls, "iiiiiiiO", - tm->tm_year + 1900, - tm->tm_mon + 1, - tm->tm_mday, - tm->tm_hour, - tm->tm_min, - tm->tm_sec, - us, - tzinfo); -} - -/* Internal helper. - * Build datetime from a Python timestamp. Pass localtime or gmtime for f, - * to control the interpretation of the timestamp. Since a double doesn't - * have enough bits to cover a datetime's full range of precision, it's - * better to call datetime_from_timet_and_us provided you have a way - * to get that much precision (e.g., C time() isn't good enough). - */ -static PyObject * -datetime_from_timestamp(PyObject *cls, TM_FUNC f, PyObject *timestamp, - PyObject *tzinfo) -{ - time_t timet; - long us; - - if (_PyTime_ObjectToTimeval(timestamp, - &timet, &us, _PyTime_ROUND_FLOOR) == -1) - return NULL; - assert(0 <= us && us <= 999999); - - return datetime_from_timet_and_us(cls, f, timet, (int)us, tzinfo); -} - -/* Internal helper. - * Build most accurate possible datetime for current time. Pass localtime or - * gmtime for f as appropriate. - */ -static PyObject * -datetime_best_possible(PyObject *cls, TM_FUNC f, PyObject *tzinfo) -{ - _PyTime_t ts = _PyTime_GetSystemClock(); - struct timeval tv; - - if (_PyTime_AsTimeval(ts, &tv, _PyTime_ROUND_FLOOR) < 0) - return NULL; - assert(0 <= tv.tv_usec && tv.tv_usec <= 999999); - - return datetime_from_timet_and_us(cls, f, tv.tv_sec, tv.tv_usec, tzinfo); -} - -/*[clinic input] - - at classmethod -datetime.datetime.now - - tz: object = None - Timezone object. - -Returns new datetime object representing current time local to tz. - -If no tz is specified, uses local timezone. +preserve [clinic start generated code]*/ PyDoc_STRVAR(datetime_datetime_now__doc__, @@ -4166,1425 +35,4 @@ exit: return return_value; } - -static PyObject * -datetime_datetime_now_impl(PyTypeObject *type, PyObject *tz) -/*[clinic end generated code: output=583c5637e3c843fa input=80d09869c5267d00]*/ -{ - PyObject *self; - - /* Return best possible local time -- this isn't constrained by the - * precision of a timestamp. - */ - if (check_tzinfo_subclass(tz) < 0) - return NULL; - - self = datetime_best_possible((PyObject *)type, - tz == Py_None ? localtime : gmtime, - tz); - if (self != NULL && tz != Py_None) { - /* Convert UTC to tzinfo's zone. */ - PyObject *temp = self; - - self = _PyObject_CallMethodId(tz, &PyId_fromutc, "O", self); - Py_DECREF(temp); - } - return self; -} - -/* Return best possible UTC time -- this isn't constrained by the - * precision of a timestamp. - */ -static PyObject * -datetime_utcnow(PyObject *cls, PyObject *dummy) -{ - return datetime_best_possible(cls, gmtime, Py_None); -} - -/* Return new local datetime from timestamp (Python timestamp -- a double). */ -static PyObject * -datetime_fromtimestamp(PyObject *cls, PyObject *args, PyObject *kw) -{ - PyObject *self; - PyObject *timestamp; - PyObject *tzinfo = Py_None; - static char *keywords[] = {"timestamp", "tz", NULL}; - - if (! PyArg_ParseTupleAndKeywords(args, kw, "O|O:fromtimestamp", - keywords, ×tamp, &tzinfo)) - return NULL; - if (check_tzinfo_subclass(tzinfo) < 0) - return NULL; - - self = datetime_from_timestamp(cls, - tzinfo == Py_None ? localtime : gmtime, - timestamp, - tzinfo); - if (self != NULL && tzinfo != Py_None) { - /* Convert UTC to tzinfo's zone. */ - PyObject *temp = self; - - self = _PyObject_CallMethodId(tzinfo, &PyId_fromutc, "O", self); - Py_DECREF(temp); - } - return self; -} - -/* Return new UTC datetime from timestamp (Python timestamp -- a double). */ -static PyObject * -datetime_utcfromtimestamp(PyObject *cls, PyObject *args) -{ - PyObject *timestamp; - PyObject *result = NULL; - - if (PyArg_ParseTuple(args, "O:utcfromtimestamp", ×tamp)) - result = datetime_from_timestamp(cls, gmtime, timestamp, - Py_None); - return result; -} - -/* Return new datetime from _strptime.strptime_datetime(). */ -static PyObject * -datetime_strptime(PyObject *cls, PyObject *args) -{ - static PyObject *module = NULL; - PyObject *string, *format; - _Py_IDENTIFIER(_strptime_datetime); - - if (!PyArg_ParseTuple(args, "UU:strptime", &string, &format)) - return NULL; - - if (module == NULL) { - module = PyImport_ImportModuleNoBlock("_strptime"); - if (module == NULL) - return NULL; - } - return _PyObject_CallMethodId(module, &PyId__strptime_datetime, "OOO", - cls, string, format); -} - -/* Return new datetime from date/datetime and time arguments. */ -static PyObject * -datetime_combine(PyObject *cls, PyObject *args, PyObject *kw) -{ - static char *keywords[] = {"date", "time", NULL}; - PyObject *date; - PyObject *time; - PyObject *result = NULL; - - if (PyArg_ParseTupleAndKeywords(args, kw, "O!O!:combine", keywords, - &PyDateTime_DateType, &date, - &PyDateTime_TimeType, &time)) { - PyObject *tzinfo = Py_None; - - if (HASTZINFO(time)) - tzinfo = ((PyDateTime_Time *)time)->tzinfo; - result = PyObject_CallFunction(cls, "iiiiiiiO", - GET_YEAR(date), - GET_MONTH(date), - GET_DAY(date), - TIME_GET_HOUR(time), - TIME_GET_MINUTE(time), - TIME_GET_SECOND(time), - TIME_GET_MICROSECOND(time), - tzinfo); - } - return result; -} - -/* - * Destructor. - */ - -static void -datetime_dealloc(PyDateTime_DateTime *self) -{ - if (HASTZINFO(self)) { - Py_XDECREF(self->tzinfo); - } - Py_TYPE(self)->tp_free((PyObject *)self); -} - -/* - * Indirect access to tzinfo methods. - */ - -/* These are all METH_NOARGS, so don't need to check the arglist. */ -static PyObject * -datetime_utcoffset(PyObject *self, PyObject *unused) { - return call_utcoffset(GET_DT_TZINFO(self), self); -} - -static PyObject * -datetime_dst(PyObject *self, PyObject *unused) { - return call_dst(GET_DT_TZINFO(self), self); -} - -static PyObject * -datetime_tzname(PyObject *self, PyObject *unused) { - return call_tzname(GET_DT_TZINFO(self), self); -} - -/* - * datetime arithmetic. - */ - -/* factor must be 1 (to add) or -1 (to subtract). The result inherits - * the tzinfo state of date. - */ -static PyObject * -add_datetime_timedelta(PyDateTime_DateTime *date, PyDateTime_Delta *delta, - int factor) -{ - /* Note that the C-level additions can't overflow, because of - * invariant bounds on the member values. - */ - int year = GET_YEAR(date); - int month = GET_MONTH(date); - int day = GET_DAY(date) + GET_TD_DAYS(delta) * factor; - int hour = DATE_GET_HOUR(date); - int minute = DATE_GET_MINUTE(date); - int second = DATE_GET_SECOND(date) + GET_TD_SECONDS(delta) * factor; - int microsecond = DATE_GET_MICROSECOND(date) + - GET_TD_MICROSECONDS(delta) * factor; - - assert(factor == 1 || factor == -1); - if (normalize_datetime(&year, &month, &day, - &hour, &minute, &second, µsecond) < 0) - return NULL; - else - return new_datetime(year, month, day, - hour, minute, second, microsecond, - HASTZINFO(date) ? date->tzinfo : Py_None); -} - -static PyObject * -datetime_add(PyObject *left, PyObject *right) -{ - if (PyDateTime_Check(left)) { - /* datetime + ??? */ - if (PyDelta_Check(right)) - /* datetime + delta */ - return add_datetime_timedelta( - (PyDateTime_DateTime *)left, - (PyDateTime_Delta *)right, - 1); - } - else if (PyDelta_Check(left)) { - /* delta + datetime */ - return add_datetime_timedelta((PyDateTime_DateTime *) right, - (PyDateTime_Delta *) left, - 1); - } - Py_RETURN_NOTIMPLEMENTED; -} - -static PyObject * -datetime_subtract(PyObject *left, PyObject *right) -{ - PyObject *result = Py_NotImplemented; - - if (PyDateTime_Check(left)) { - /* datetime - ??? */ - if (PyDateTime_Check(right)) { - /* datetime - datetime */ - PyObject *offset1, *offset2, *offdiff = NULL; - int delta_d, delta_s, delta_us; - - if (GET_DT_TZINFO(left) == GET_DT_TZINFO(right)) { - offset2 = offset1 = Py_None; - Py_INCREF(offset1); - Py_INCREF(offset2); - } - else { - offset1 = datetime_utcoffset(left, NULL); - if (offset1 == NULL) - return NULL; - offset2 = datetime_utcoffset(right, NULL); - if (offset2 == NULL) { - Py_DECREF(offset1); - return NULL; - } - if ((offset1 != Py_None) != (offset2 != Py_None)) { - PyErr_SetString(PyExc_TypeError, - "can't subtract offset-naive and " - "offset-aware datetimes"); - Py_DECREF(offset1); - Py_DECREF(offset2); - return NULL; - } - } - if ((offset1 != offset2) && - delta_cmp(offset1, offset2) != 0) { - offdiff = delta_subtract(offset1, offset2); - if (offdiff == NULL) { - Py_DECREF(offset1); - Py_DECREF(offset2); - return NULL; - } - } - Py_DECREF(offset1); - Py_DECREF(offset2); - delta_d = ymd_to_ord(GET_YEAR(left), - GET_MONTH(left), - GET_DAY(left)) - - ymd_to_ord(GET_YEAR(right), - GET_MONTH(right), - GET_DAY(right)); - /* These can't overflow, since the values are - * normalized. At most this gives the number of - * seconds in one day. - */ - delta_s = (DATE_GET_HOUR(left) - - DATE_GET_HOUR(right)) * 3600 + - (DATE_GET_MINUTE(left) - - DATE_GET_MINUTE(right)) * 60 + - (DATE_GET_SECOND(left) - - DATE_GET_SECOND(right)); - delta_us = DATE_GET_MICROSECOND(left) - - DATE_GET_MICROSECOND(right); - result = new_delta(delta_d, delta_s, delta_us, 1); - if (result == NULL) - return NULL; - - if (offdiff != NULL) { - PyObject *temp = result; - result = delta_subtract(result, offdiff); - Py_DECREF(temp); - Py_DECREF(offdiff); - } - } - else if (PyDelta_Check(right)) { - /* datetime - delta */ - result = add_datetime_timedelta( - (PyDateTime_DateTime *)left, - (PyDateTime_Delta *)right, - -1); - } - } - - if (result == Py_NotImplemented) - Py_INCREF(result); - return result; -} - -/* Various ways to turn a datetime into a string. */ - -static PyObject * -datetime_repr(PyDateTime_DateTime *self) -{ - const char *type_name = Py_TYPE(self)->tp_name; - PyObject *baserepr; - - if (DATE_GET_MICROSECOND(self)) { - baserepr = PyUnicode_FromFormat( - "%s(%d, %d, %d, %d, %d, %d, %d)", - type_name, - GET_YEAR(self), GET_MONTH(self), GET_DAY(self), - DATE_GET_HOUR(self), DATE_GET_MINUTE(self), - DATE_GET_SECOND(self), - DATE_GET_MICROSECOND(self)); - } - else if (DATE_GET_SECOND(self)) { - baserepr = PyUnicode_FromFormat( - "%s(%d, %d, %d, %d, %d, %d)", - type_name, - GET_YEAR(self), GET_MONTH(self), GET_DAY(self), - DATE_GET_HOUR(self), DATE_GET_MINUTE(self), - DATE_GET_SECOND(self)); - } - else { - baserepr = PyUnicode_FromFormat( - "%s(%d, %d, %d, %d, %d)", - type_name, - GET_YEAR(self), GET_MONTH(self), GET_DAY(self), - DATE_GET_HOUR(self), DATE_GET_MINUTE(self)); - } - if (baserepr == NULL || ! HASTZINFO(self)) - return baserepr; - return append_keyword_tzinfo(baserepr, self->tzinfo); -} - -static PyObject * -datetime_str(PyDateTime_DateTime *self) -{ - return _PyObject_CallMethodId((PyObject *)self, &PyId_isoformat, "(s)", " "); -} - -static PyObject * -datetime_isoformat(PyDateTime_DateTime *self, PyObject *args, PyObject *kw) -{ - int sep = 'T'; - static char *keywords[] = {"sep", NULL}; - char buffer[100]; - PyObject *result; - int us = DATE_GET_MICROSECOND(self); - - if (!PyArg_ParseTupleAndKeywords(args, kw, "|C:isoformat", keywords, &sep)) - return NULL; - if (us) - result = PyUnicode_FromFormat("%04d-%02d-%02d%c%02d:%02d:%02d.%06d", - GET_YEAR(self), GET_MONTH(self), - GET_DAY(self), (int)sep, - DATE_GET_HOUR(self), DATE_GET_MINUTE(self), - DATE_GET_SECOND(self), us); - else - result = PyUnicode_FromFormat("%04d-%02d-%02d%c%02d:%02d:%02d", - GET_YEAR(self), GET_MONTH(self), - GET_DAY(self), (int)sep, - DATE_GET_HOUR(self), DATE_GET_MINUTE(self), - DATE_GET_SECOND(self)); - - if (!result || !HASTZINFO(self)) - return result; - - /* We need to append the UTC offset. */ - if (format_utcoffset(buffer, sizeof(buffer), ":", self->tzinfo, - (PyObject *)self) < 0) { - Py_DECREF(result); - return NULL; - } - PyUnicode_AppendAndDel(&result, PyUnicode_FromString(buffer)); - return result; -} - -static PyObject * -datetime_ctime(PyDateTime_DateTime *self) -{ - return format_ctime((PyDateTime_Date *)self, - DATE_GET_HOUR(self), - DATE_GET_MINUTE(self), - DATE_GET_SECOND(self)); -} - -/* Miscellaneous methods. */ - -static PyObject * -datetime_richcompare(PyObject *self, PyObject *other, int op) -{ - PyObject *result = NULL; - PyObject *offset1, *offset2; - int diff; - - if (! PyDateTime_Check(other)) { - if (PyDate_Check(other)) { - /* Prevent invocation of date_richcompare. We want to - return NotImplemented here to give the other object - a chance. But since DateTime is a subclass of - Date, if the other object is a Date, it would - compute an ordering based on the date part alone, - and we don't want that. So force unequal or - uncomparable here in that case. */ - if (op == Py_EQ) - Py_RETURN_FALSE; - if (op == Py_NE) - Py_RETURN_TRUE; - return cmperror(self, other); - } - Py_RETURN_NOTIMPLEMENTED; - } - - if (GET_DT_TZINFO(self) == GET_DT_TZINFO(other)) { - diff = memcmp(((PyDateTime_DateTime *)self)->data, - ((PyDateTime_DateTime *)other)->data, - _PyDateTime_DATETIME_DATASIZE); - return diff_to_bool(diff, op); - } - offset1 = datetime_utcoffset(self, NULL); - if (offset1 == NULL) - return NULL; - offset2 = datetime_utcoffset(other, NULL); - if (offset2 == NULL) - goto done; - /* If they're both naive, or both aware and have the same offsets, - * we get off cheap. Note that if they're both naive, offset1 == - * offset2 == Py_None at this point. - */ - if ((offset1 == offset2) || - (PyDelta_Check(offset1) && PyDelta_Check(offset2) && - delta_cmp(offset1, offset2) == 0)) { - diff = memcmp(((PyDateTime_DateTime *)self)->data, - ((PyDateTime_DateTime *)other)->data, - _PyDateTime_DATETIME_DATASIZE); - result = diff_to_bool(diff, op); - } - else if (offset1 != Py_None && offset2 != Py_None) { - PyDateTime_Delta *delta; - - assert(offset1 != offset2); /* else last "if" handled it */ - delta = (PyDateTime_Delta *)datetime_subtract((PyObject *)self, - other); - if (delta == NULL) - goto done; - diff = GET_TD_DAYS(delta); - if (diff == 0) - diff = GET_TD_SECONDS(delta) | - GET_TD_MICROSECONDS(delta); - Py_DECREF(delta); - result = diff_to_bool(diff, op); - } - else if (op == Py_EQ) { - result = Py_False; - Py_INCREF(result); - } - else if (op == Py_NE) { - result = Py_True; - Py_INCREF(result); - } - else { - PyErr_SetString(PyExc_TypeError, - "can't compare offset-naive and " - "offset-aware datetimes"); - } - done: - Py_DECREF(offset1); - Py_XDECREF(offset2); - return result; -} - -static Py_hash_t -datetime_hash(PyDateTime_DateTime *self) -{ - if (self->hashcode == -1) { - PyObject *offset; - - offset = datetime_utcoffset((PyObject *)self, NULL); - - if (offset == NULL) - return -1; - - /* Reduce this to a hash of another object. */ - if (offset == Py_None) - self->hashcode = generic_hash( - (unsigned char *)self->data, _PyDateTime_DATETIME_DATASIZE); - else { - PyObject *temp1, *temp2; - int days, seconds; - - assert(HASTZINFO(self)); - days = ymd_to_ord(GET_YEAR(self), - GET_MONTH(self), - GET_DAY(self)); - seconds = DATE_GET_HOUR(self) * 3600 + - DATE_GET_MINUTE(self) * 60 + - DATE_GET_SECOND(self); - temp1 = new_delta(days, seconds, - DATE_GET_MICROSECOND(self), - 1); - if (temp1 == NULL) { - Py_DECREF(offset); - return -1; - } - temp2 = delta_subtract(temp1, offset); - Py_DECREF(temp1); - if (temp2 == NULL) { - Py_DECREF(offset); - return -1; - } - self->hashcode = PyObject_Hash(temp2); - Py_DECREF(temp2); - } - Py_DECREF(offset); - } - return self->hashcode; -} - -static PyObject * -datetime_replace(PyDateTime_DateTime *self, PyObject *args, PyObject *kw) -{ - PyObject *clone; - PyObject *tuple; - int y = GET_YEAR(self); - int m = GET_MONTH(self); - int d = GET_DAY(self); - int hh = DATE_GET_HOUR(self); - int mm = DATE_GET_MINUTE(self); - int ss = DATE_GET_SECOND(self); - int us = DATE_GET_MICROSECOND(self); - PyObject *tzinfo = HASTZINFO(self) ? self->tzinfo : Py_None; - - if (! PyArg_ParseTupleAndKeywords(args, kw, "|iiiiiiiO:replace", - datetime_kws, - &y, &m, &d, &hh, &mm, &ss, &us, - &tzinfo)) - return NULL; - tuple = Py_BuildValue("iiiiiiiO", y, m, d, hh, mm, ss, us, tzinfo); - if (tuple == NULL) - return NULL; - clone = datetime_new(Py_TYPE(self), tuple, NULL); - Py_DECREF(tuple); - return clone; -} - -static PyObject * -local_timezone(PyDateTime_DateTime *utc_time) -{ - PyObject *result = NULL; - struct tm *timep; - time_t timestamp; - PyObject *delta; - PyObject *one_second; - PyObject *seconds; - PyObject *nameo = NULL; - const char *zone = NULL; - - delta = datetime_subtract((PyObject *)utc_time, PyDateTime_Epoch); - if (delta == NULL) - return NULL; - one_second = new_delta(0, 1, 0, 0); - if (one_second == NULL) - goto error; - seconds = divide_timedelta_timedelta((PyDateTime_Delta *)delta, - (PyDateTime_Delta *)one_second); - Py_DECREF(one_second); - if (seconds == NULL) - goto error; - Py_DECREF(delta); - timestamp = PyLong_AsLong(seconds); - Py_DECREF(seconds); - if (timestamp == -1 && PyErr_Occurred()) - return NULL; - timep = localtime(×tamp); -#ifdef HAVE_STRUCT_TM_TM_ZONE - zone = timep->tm_zone; - delta = new_delta(0, timep->tm_gmtoff, 0, 1); -#else /* HAVE_STRUCT_TM_TM_ZONE */ - { - PyObject *local_time; - local_time = new_datetime(timep->tm_year + 1900, timep->tm_mon + 1, - timep->tm_mday, timep->tm_hour, timep->tm_min, - timep->tm_sec, DATE_GET_MICROSECOND(utc_time), - utc_time->tzinfo); - if (local_time == NULL) - goto error; - delta = datetime_subtract(local_time, (PyObject*)utc_time); - /* XXX: before relying on tzname, we should compare delta - to the offset implied by timezone/altzone */ - if (daylight && timep->tm_isdst >= 0) - zone = tzname[timep->tm_isdst % 2]; - else - zone = tzname[0]; - Py_DECREF(local_time); - } -#endif /* HAVE_STRUCT_TM_TM_ZONE */ - if (zone != NULL) { - nameo = PyUnicode_DecodeLocale(zone, "surrogateescape"); - if (nameo == NULL) - goto error; - } - result = new_timezone(delta, nameo); - Py_XDECREF(nameo); - error: - Py_DECREF(delta); - return result; -} - -static PyDateTime_DateTime * -datetime_astimezone(PyDateTime_DateTime *self, PyObject *args, PyObject *kw) -{ - PyDateTime_DateTime *result; - PyObject *offset; - PyObject *temp; - PyObject *tzinfo = Py_None; - static char *keywords[] = {"tz", NULL}; - - if (! PyArg_ParseTupleAndKeywords(args, kw, "|O:astimezone", keywords, - &tzinfo)) - return NULL; - - if (check_tzinfo_subclass(tzinfo) == -1) - return NULL; - - if (!HASTZINFO(self) || self->tzinfo == Py_None) - goto NeedAware; - - /* Conversion to self's own time zone is a NOP. */ - if (self->tzinfo == tzinfo) { - Py_INCREF(self); - return self; - } - - /* Convert self to UTC. */ - offset = datetime_utcoffset((PyObject *)self, NULL); - if (offset == NULL) - return NULL; - if (offset == Py_None) { - Py_DECREF(offset); - NeedAware: - PyErr_SetString(PyExc_ValueError, "astimezone() cannot be applied to " - "a naive datetime"); - return NULL; - } - - /* result = self - offset */ - result = (PyDateTime_DateTime *)add_datetime_timedelta(self, - (PyDateTime_Delta *)offset, -1); - Py_DECREF(offset); - if (result == NULL) - return NULL; - - /* Attach new tzinfo and let fromutc() do the rest. */ - temp = result->tzinfo; - if (tzinfo == Py_None) { - tzinfo = local_timezone(result); - if (tzinfo == NULL) { - Py_DECREF(result); - return NULL; - } - } - else - Py_INCREF(tzinfo); - result->tzinfo = tzinfo; - Py_DECREF(temp); - - temp = (PyObject *)result; - result = (PyDateTime_DateTime *) - _PyObject_CallMethodId(tzinfo, &PyId_fromutc, "O", temp); - Py_DECREF(temp); - - return result; -} - -static PyObject * -datetime_timetuple(PyDateTime_DateTime *self) -{ - int dstflag = -1; - - if (HASTZINFO(self) && self->tzinfo != Py_None) { - PyObject * dst; - - dst = call_dst(self->tzinfo, (PyObject *)self); - if (dst == NULL) - return NULL; - - if (dst != Py_None) - dstflag = delta_bool((PyDateTime_Delta *)dst); - Py_DECREF(dst); - } - return build_struct_time(GET_YEAR(self), - GET_MONTH(self), - GET_DAY(self), - DATE_GET_HOUR(self), - DATE_GET_MINUTE(self), - DATE_GET_SECOND(self), - dstflag); -} - -static PyObject * -datetime_timestamp(PyDateTime_DateTime *self) -{ - PyObject *result; - - if (HASTZINFO(self) && self->tzinfo != Py_None) { - PyObject *delta; - delta = datetime_subtract((PyObject *)self, PyDateTime_Epoch); - if (delta == NULL) - return NULL; - result = delta_total_seconds(delta); - Py_DECREF(delta); - } - else { - struct tm time; - time_t timestamp; - memset((void *) &time, '\0', sizeof(struct tm)); - time.tm_year = GET_YEAR(self) - 1900; - time.tm_mon = GET_MONTH(self) - 1; - time.tm_mday = GET_DAY(self); - time.tm_hour = DATE_GET_HOUR(self); - time.tm_min = DATE_GET_MINUTE(self); - time.tm_sec = DATE_GET_SECOND(self); - time.tm_wday = -1; - time.tm_isdst = -1; - timestamp = mktime(&time); - if (timestamp == (time_t)(-1) -#ifndef _AIX - /* Return value of -1 does not necessarily mean an error, - * but tm_wday cannot remain set to -1 if mktime succeeded. */ - && time.tm_wday == -1 -#else - /* on AIX, tm_wday is always sets, even on error */ -#endif - ) - { - PyErr_SetString(PyExc_OverflowError, - "timestamp out of range"); - return NULL; - } - result = PyFloat_FromDouble(timestamp + DATE_GET_MICROSECOND(self) / 1e6); - } - return result; -} - -static PyObject * -datetime_getdate(PyDateTime_DateTime *self) -{ - return new_date(GET_YEAR(self), - GET_MONTH(self), - GET_DAY(self)); -} - -static PyObject * -datetime_gettime(PyDateTime_DateTime *self) -{ - return new_time(DATE_GET_HOUR(self), - DATE_GET_MINUTE(self), - DATE_GET_SECOND(self), - DATE_GET_MICROSECOND(self), - Py_None); -} - -static PyObject * -datetime_gettimetz(PyDateTime_DateTime *self) -{ - return new_time(DATE_GET_HOUR(self), - DATE_GET_MINUTE(self), - DATE_GET_SECOND(self), - DATE_GET_MICROSECOND(self), - GET_DT_TZINFO(self)); -} - -static PyObject * -datetime_utctimetuple(PyDateTime_DateTime *self) -{ - int y, m, d, hh, mm, ss; - PyObject *tzinfo; - PyDateTime_DateTime *utcself; - - tzinfo = GET_DT_TZINFO(self); - if (tzinfo == Py_None) { - utcself = self; - Py_INCREF(utcself); - } - else { - PyObject *offset; - offset = call_utcoffset(tzinfo, (PyObject *)self); - if (offset == NULL) - return NULL; - if (offset == Py_None) { - Py_DECREF(offset); - utcself = self; - Py_INCREF(utcself); - } - else { - utcself = (PyDateTime_DateTime *)add_datetime_timedelta(self, - (PyDateTime_Delta *)offset, -1); - Py_DECREF(offset); - if (utcself == NULL) - return NULL; - } - } - y = GET_YEAR(utcself); - m = GET_MONTH(utcself); - d = GET_DAY(utcself); - hh = DATE_GET_HOUR(utcself); - mm = DATE_GET_MINUTE(utcself); - ss = DATE_GET_SECOND(utcself); - - Py_DECREF(utcself); - return build_struct_time(y, m, d, hh, mm, ss, 0); -} - -/* Pickle support, a simple use of __reduce__. */ - -/* Let basestate be the non-tzinfo data string. - * If tzinfo is None, this returns (basestate,), else (basestate, tzinfo). - * So it's a tuple in any (non-error) case. - * __getstate__ isn't exposed. - */ -static PyObject * -datetime_getstate(PyDateTime_DateTime *self) -{ - PyObject *basestate; - PyObject *result = NULL; - - basestate = PyBytes_FromStringAndSize((char *)self->data, - _PyDateTime_DATETIME_DATASIZE); - if (basestate != NULL) { - if (! HASTZINFO(self) || self->tzinfo == Py_None) - result = PyTuple_Pack(1, basestate); - else - result = PyTuple_Pack(2, basestate, self->tzinfo); - Py_DECREF(basestate); - } - return result; -} - -static PyObject * -datetime_reduce(PyDateTime_DateTime *self, PyObject *arg) -{ - return Py_BuildValue("(ON)", Py_TYPE(self), datetime_getstate(self)); -} - -static PyMethodDef datetime_methods[] = { - - /* Class methods: */ - - DATETIME_DATETIME_NOW_METHODDEF - - {"utcnow", (PyCFunction)datetime_utcnow, - METH_NOARGS | METH_CLASS, - PyDoc_STR("Return a new datetime representing UTC day and time.")}, - - {"fromtimestamp", (PyCFunction)datetime_fromtimestamp, - METH_VARARGS | METH_KEYWORDS | METH_CLASS, - PyDoc_STR("timestamp[, tz] -> tz's local time from POSIX timestamp.")}, - - {"utcfromtimestamp", (PyCFunction)datetime_utcfromtimestamp, - METH_VARARGS | METH_CLASS, - PyDoc_STR("Construct a naive UTC datetime from a POSIX timestamp.")}, - - {"strptime", (PyCFunction)datetime_strptime, - METH_VARARGS | METH_CLASS, - PyDoc_STR("string, format -> new datetime parsed from a string " - "(like time.strptime()).")}, - - {"combine", (PyCFunction)datetime_combine, - METH_VARARGS | METH_KEYWORDS | METH_CLASS, - PyDoc_STR("date, time -> datetime with same date and time fields")}, - - /* Instance methods: */ - - {"date", (PyCFunction)datetime_getdate, METH_NOARGS, - PyDoc_STR("Return date object with same year, month and day.")}, - - {"time", (PyCFunction)datetime_gettime, METH_NOARGS, - PyDoc_STR("Return time object with same time but with tzinfo=None.")}, - - {"timetz", (PyCFunction)datetime_gettimetz, METH_NOARGS, - PyDoc_STR("Return time object with same time and tzinfo.")}, - - {"ctime", (PyCFunction)datetime_ctime, METH_NOARGS, - PyDoc_STR("Return ctime() style string.")}, - - {"timetuple", (PyCFunction)datetime_timetuple, METH_NOARGS, - PyDoc_STR("Return time tuple, compatible with time.localtime().")}, - - {"timestamp", (PyCFunction)datetime_timestamp, METH_NOARGS, - PyDoc_STR("Return POSIX timestamp as float.")}, - - {"utctimetuple", (PyCFunction)datetime_utctimetuple, METH_NOARGS, - PyDoc_STR("Return UTC time tuple, compatible with time.localtime().")}, - - {"isoformat", (PyCFunction)datetime_isoformat, METH_VARARGS | METH_KEYWORDS, - PyDoc_STR("[sep] -> string in ISO 8601 format, " - "YYYY-MM-DDTHH:MM:SS[.mmmmmm][+HH:MM].\n\n" - "sep is used to separate the year from the time, and " - "defaults to 'T'.")}, - - {"utcoffset", (PyCFunction)datetime_utcoffset, METH_NOARGS, - PyDoc_STR("Return self.tzinfo.utcoffset(self).")}, - - {"tzname", (PyCFunction)datetime_tzname, METH_NOARGS, - PyDoc_STR("Return self.tzinfo.tzname(self).")}, - - {"dst", (PyCFunction)datetime_dst, METH_NOARGS, - PyDoc_STR("Return self.tzinfo.dst(self).")}, - - {"replace", (PyCFunction)datetime_replace, METH_VARARGS | METH_KEYWORDS, - PyDoc_STR("Return datetime with new specified fields.")}, - - {"astimezone", (PyCFunction)datetime_astimezone, METH_VARARGS | METH_KEYWORDS, - PyDoc_STR("tz -> convert to local time in new timezone tz\n")}, - - {"__reduce__", (PyCFunction)datetime_reduce, METH_NOARGS, - PyDoc_STR("__reduce__() -> (cls, state)")}, - - {NULL, NULL} -}; - -static char datetime_doc[] = -PyDoc_STR("datetime(year, month, day[, hour[, minute[, second[, microsecond[,tzinfo]]]]])\n\ -\n\ -The year, month and day arguments are required. tzinfo may be None, or an\n\ -instance of a tzinfo subclass. The remaining arguments may be ints.\n"); - -static PyNumberMethods datetime_as_number = { - datetime_add, /* nb_add */ - datetime_subtract, /* nb_subtract */ - 0, /* nb_multiply */ - 0, /* nb_remainder */ - 0, /* nb_divmod */ - 0, /* nb_power */ - 0, /* nb_negative */ - 0, /* nb_positive */ - 0, /* nb_absolute */ - 0, /* nb_bool */ -}; - -static PyTypeObject PyDateTime_DateTimeType = { - PyVarObject_HEAD_INIT(NULL, 0) - "datetime.datetime", /* tp_name */ - sizeof(PyDateTime_DateTime), /* tp_basicsize */ - 0, /* tp_itemsize */ - (destructor)datetime_dealloc, /* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_reserved */ - (reprfunc)datetime_repr, /* tp_repr */ - &datetime_as_number, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - (hashfunc)datetime_hash, /* tp_hash */ - 0, /* tp_call */ - (reprfunc)datetime_str, /* tp_str */ - PyObject_GenericGetAttr, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ - datetime_doc, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - datetime_richcompare, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - datetime_methods, /* tp_methods */ - 0, /* tp_members */ - datetime_getset, /* tp_getset */ - &PyDateTime_DateType, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - datetime_alloc, /* tp_alloc */ - datetime_new, /* tp_new */ - 0, /* tp_free */ -}; - -/* --------------------------------------------------------------------------- - * Module methods and initialization. - */ - -static PyMethodDef module_methods[] = { - {NULL, NULL} -}; - -/* C API. Clients get at this via PyDateTime_IMPORT, defined in - * datetime.h. - */ -static PyDateTime_CAPI CAPI = { - &PyDateTime_DateType, - &PyDateTime_DateTimeType, - &PyDateTime_TimeType, - &PyDateTime_DeltaType, - &PyDateTime_TZInfoType, - new_date_ex, - new_datetime_ex, - new_time_ex, - new_delta_ex, - datetime_fromtimestamp, - date_fromtimestamp -}; - - - -static struct PyModuleDef datetimemodule = { - PyModuleDef_HEAD_INIT, - "_datetime", - "Fast implementation of the datetime type.", - -1, - module_methods, - NULL, - NULL, - NULL, - NULL -}; - -PyMODINIT_FUNC -PyInit__datetime(void) -{ - PyObject *m; /* a module object */ - PyObject *d; /* its dict */ - PyObject *x; - PyObject *delta; - - m = PyModule_Create(&datetimemodule); - if (m == NULL) - return NULL; - - if (PyType_Ready(&PyDateTime_DateType) < 0) - return NULL; - if (PyType_Ready(&PyDateTime_DateTimeType) < 0) - return NULL; - if (PyType_Ready(&PyDateTime_DeltaType) < 0) - return NULL; - if (PyType_Ready(&PyDateTime_TimeType) < 0) - return NULL; - if (PyType_Ready(&PyDateTime_TZInfoType) < 0) - return NULL; - if (PyType_Ready(&PyDateTime_TimeZoneType) < 0) - return NULL; - - /* timedelta values */ - d = PyDateTime_DeltaType.tp_dict; - - x = new_delta(0, 0, 1, 0); - if (x == NULL || PyDict_SetItemString(d, "resolution", x) < 0) - return NULL; - Py_DECREF(x); - - x = new_delta(-MAX_DELTA_DAYS, 0, 0, 0); - if (x == NULL || PyDict_SetItemString(d, "min", x) < 0) - return NULL; - Py_DECREF(x); - - x = new_delta(MAX_DELTA_DAYS, 24*3600-1, 1000000-1, 0); - if (x == NULL || PyDict_SetItemString(d, "max", x) < 0) - return NULL; - Py_DECREF(x); - - /* date values */ - d = PyDateTime_DateType.tp_dict; - - x = new_date(1, 1, 1); - if (x == NULL || PyDict_SetItemString(d, "min", x) < 0) - return NULL; - Py_DECREF(x); - - x = new_date(MAXYEAR, 12, 31); - if (x == NULL || PyDict_SetItemString(d, "max", x) < 0) - return NULL; - Py_DECREF(x); - - x = new_delta(1, 0, 0, 0); - if (x == NULL || PyDict_SetItemString(d, "resolution", x) < 0) - return NULL; - Py_DECREF(x); - - /* time values */ - d = PyDateTime_TimeType.tp_dict; - - x = new_time(0, 0, 0, 0, Py_None); - if (x == NULL || PyDict_SetItemString(d, "min", x) < 0) - return NULL; - Py_DECREF(x); - - x = new_time(23, 59, 59, 999999, Py_None); - if (x == NULL || PyDict_SetItemString(d, "max", x) < 0) - return NULL; - Py_DECREF(x); - - x = new_delta(0, 0, 1, 0); - if (x == NULL || PyDict_SetItemString(d, "resolution", x) < 0) - return NULL; - Py_DECREF(x); - - /* datetime values */ - d = PyDateTime_DateTimeType.tp_dict; - - x = new_datetime(1, 1, 1, 0, 0, 0, 0, Py_None); - if (x == NULL || PyDict_SetItemString(d, "min", x) < 0) - return NULL; - Py_DECREF(x); - - x = new_datetime(MAXYEAR, 12, 31, 23, 59, 59, 999999, Py_None); - if (x == NULL || PyDict_SetItemString(d, "max", x) < 0) - return NULL; - Py_DECREF(x); - - x = new_delta(0, 0, 1, 0); - if (x == NULL || PyDict_SetItemString(d, "resolution", x) < 0) - return NULL; - Py_DECREF(x); - - /* timezone values */ - d = PyDateTime_TimeZoneType.tp_dict; - - delta = new_delta(0, 0, 0, 0); - if (delta == NULL) - return NULL; - x = create_timezone(delta, NULL); - Py_DECREF(delta); - if (x == NULL || PyDict_SetItemString(d, "utc", x) < 0) - return NULL; - PyDateTime_TimeZone_UTC = x; - - delta = new_delta(-1, 60, 0, 1); /* -23:59 */ - if (delta == NULL) - return NULL; - x = create_timezone(delta, NULL); - Py_DECREF(delta); - if (x == NULL || PyDict_SetItemString(d, "min", x) < 0) - return NULL; - Py_DECREF(x); - - delta = new_delta(0, (23 * 60 + 59) * 60, 0, 0); /* +23:59 */ - if (delta == NULL) - return NULL; - x = create_timezone(delta, NULL); - Py_DECREF(delta); - if (x == NULL || PyDict_SetItemString(d, "max", x) < 0) - return NULL; - Py_DECREF(x); - - /* Epoch */ - PyDateTime_Epoch = new_datetime(1970, 1, 1, 0, 0, 0, 0, - PyDateTime_TimeZone_UTC); - if (PyDateTime_Epoch == NULL) - return NULL; - - /* module initialization */ - PyModule_AddIntMacro(m, MINYEAR); - PyModule_AddIntMacro(m, MAXYEAR); - - Py_INCREF(&PyDateTime_DateType); - PyModule_AddObject(m, "date", (PyObject *) &PyDateTime_DateType); - - Py_INCREF(&PyDateTime_DateTimeType); - PyModule_AddObject(m, "datetime", - (PyObject *)&PyDateTime_DateTimeType); - - Py_INCREF(&PyDateTime_TimeType); - PyModule_AddObject(m, "time", (PyObject *) &PyDateTime_TimeType); - - Py_INCREF(&PyDateTime_DeltaType); - PyModule_AddObject(m, "timedelta", (PyObject *) &PyDateTime_DeltaType); - - Py_INCREF(&PyDateTime_TZInfoType); - PyModule_AddObject(m, "tzinfo", (PyObject *) &PyDateTime_TZInfoType); - - Py_INCREF(&PyDateTime_TimeZoneType); - PyModule_AddObject(m, "timezone", (PyObject *) &PyDateTime_TimeZoneType); - - x = PyCapsule_New(&CAPI, PyDateTime_CAPSULE_NAME, NULL); - if (x == NULL) - return NULL; - PyModule_AddObject(m, "datetime_CAPI", x); - - /* A 4-year cycle has an extra leap day over what we'd get from - * pasting together 4 single years. - */ - assert(DI4Y == 4 * 365 + 1); - assert(DI4Y == days_before_year(4+1)); - - /* Similarly, a 400-year cycle has an extra leap day over what we'd - * get from pasting together 4 100-year cycles. - */ - assert(DI400Y == 4 * DI100Y + 1); - assert(DI400Y == days_before_year(400+1)); - - /* OTOH, a 100-year cycle has one fewer leap day than we'd get from - * pasting together 25 4-year cycles. - */ - assert(DI100Y == 25 * DI4Y - 1); - assert(DI100Y == days_before_year(100+1)); - - one = PyLong_FromLong(1); - us_per_ms = PyLong_FromLong(1000); - us_per_second = PyLong_FromLong(1000000); - us_per_minute = PyLong_FromLong(60000000); - seconds_per_day = PyLong_FromLong(24 * 3600); - if (one == NULL || us_per_ms == NULL || us_per_second == NULL || - us_per_minute == NULL || seconds_per_day == NULL) - return NULL; - - /* The rest are too big for 32-bit ints, but even - * us_per_week fits in 40 bits, so doubles should be exact. - */ - us_per_hour = PyLong_FromDouble(3600000000.0); - us_per_day = PyLong_FromDouble(86400000000.0); - us_per_week = PyLong_FromDouble(604800000000.0); - if (us_per_hour == NULL || us_per_day == NULL || us_per_week == NULL) - return NULL; - return m; -} - -/* --------------------------------------------------------------------------- -Some time zone algebra. For a datetime x, let - x.n = x stripped of its timezone -- its naive time. - x.o = x.utcoffset(), and assuming that doesn't raise an exception or - return None - x.d = x.dst(), and assuming that doesn't raise an exception or - return None - x.s = x's standard offset, x.o - x.d - -Now some derived rules, where k is a duration (timedelta). - -1. x.o = x.s + x.d - This follows from the definition of x.s. - -2. If x and y have the same tzinfo member, x.s = y.s. - This is actually a requirement, an assumption we need to make about - sane tzinfo classes. - -3. The naive UTC time corresponding to x is x.n - x.o. - This is again a requirement for a sane tzinfo class. - -4. (x+k).s = x.s - This follows from #2, and that datimetimetz+timedelta preserves tzinfo. - -5. (x+k).n = x.n + k - Again follows from how arithmetic is defined. - -Now we can explain tz.fromutc(x). Let's assume it's an interesting case -(meaning that the various tzinfo methods exist, and don't blow up or return -None when called). - -The function wants to return a datetime y with timezone tz, equivalent to x. -x is already in UTC. - -By #3, we want - - y.n - y.o = x.n [1] - -The algorithm starts by attaching tz to x.n, and calling that y. So -x.n = y.n at the start. Then it wants to add a duration k to y, so that [1] -becomes true; in effect, we want to solve [2] for k: - - (y+k).n - (y+k).o = x.n [2] - -By #1, this is the same as - - (y+k).n - ((y+k).s + (y+k).d) = x.n [3] - -By #5, (y+k).n = y.n + k, which equals x.n + k because x.n=y.n at the start. -Substituting that into [3], - - x.n + k - (y+k).s - (y+k).d = x.n; the x.n terms cancel, leaving - k - (y+k).s - (y+k).d = 0; rearranging, - k = (y+k).s - (y+k).d; by #4, (y+k).s == y.s, so - k = y.s - (y+k).d - -On the RHS, (y+k).d can't be computed directly, but y.s can be, and we -approximate k by ignoring the (y+k).d term at first. Note that k can't be -very large, since all offset-returning methods return a duration of magnitude -less than 24 hours. For that reason, if y is firmly in std time, (y+k).d must -be 0, so ignoring it has no consequence then. - -In any case, the new value is - - z = y + y.s [4] - -It's helpful to step back at look at [4] from a higher level: it's simply -mapping from UTC to tz's standard time. - -At this point, if - - z.n - z.o = x.n [5] - -we have an equivalent time, and are almost done. The insecurity here is -at the start of daylight time. Picture US Eastern for concreteness. The wall -time jumps from 1:59 to 3:00, and wall hours of the form 2:MM don't make good -sense then. The docs ask that an Eastern tzinfo class consider such a time to -be EDT (because it's "after 2"), which is a redundant spelling of 1:MM EST -on the day DST starts. We want to return the 1:MM EST spelling because that's -the only spelling that makes sense on the local wall clock. - -In fact, if [5] holds at this point, we do have the standard-time spelling, -but that takes a bit of proof. We first prove a stronger result. What's the -difference between the LHS and RHS of [5]? Let - - diff = x.n - (z.n - z.o) [6] - -Now - z.n = by [4] - (y + y.s).n = by #5 - y.n + y.s = since y.n = x.n - x.n + y.s = since z and y are have the same tzinfo member, - y.s = z.s by #2 - x.n + z.s - -Plugging that back into [6] gives - - diff = - x.n - ((x.n + z.s) - z.o) = expanding - x.n - x.n - z.s + z.o = cancelling - - z.s + z.o = by #2 - z.d - -So diff = z.d. - -If [5] is true now, diff = 0, so z.d = 0 too, and we have the standard-time -spelling we wanted in the endcase described above. We're done. Contrarily, -if z.d = 0, then we have a UTC equivalent, and are also done. - -If [5] is not true now, diff = z.d != 0, and z.d is the offset we need to -add to z (in effect, z is in tz's standard time, and we need to shift the -local clock into tz's daylight time). - -Let - - z' = z + z.d = z + diff [7] - -and we can again ask whether - - z'.n - z'.o = x.n [8] - -If so, we're done. If not, the tzinfo class is insane, according to the -assumptions we've made. This also requires a bit of proof. As before, let's -compute the difference between the LHS and RHS of [8] (and skipping some of -the justifications for the kinds of substitutions we've done several times -already): - - diff' = x.n - (z'.n - z'.o) = replacing z'.n via [7] - x.n - (z.n + diff - z'.o) = replacing diff via [6] - x.n - (z.n + x.n - (z.n - z.o) - z'.o) = - x.n - z.n - x.n + z.n - z.o + z'.o = cancel x.n - - z.n + z.n - z.o + z'.o = cancel z.n - - z.o + z'.o = #1 twice - -z.s - z.d + z'.s + z'.d = z and z' have same tzinfo - z'.d - z.d - -So z' is UTC-equivalent to x iff z'.d = z.d at this point. If they are equal, -we've found the UTC-equivalent so are done. In fact, we stop with [7] and -return z', not bothering to compute z'.d. - -How could z.d and z'd differ? z' = z + z.d [7], so merely moving z' by -a dst() offset, and starting *from* a time already in DST (we know z.d != 0), -would have to change the result dst() returns: we start in DST, and moving -a little further into it takes us out of DST. - -There isn't a sane case where this can happen. The closest it gets is at -the end of DST, where there's an hour in UTC with no spelling in a hybrid -tzinfo class. In US Eastern, that's 5:MM UTC = 0:MM EST = 1:MM EDT. During -that hour, on an Eastern clock 1:MM is taken as being in standard time (6:MM -UTC) because the docs insist on that, but 0:MM is taken as being in daylight -time (4:MM UTC). There is no local time mapping to 5:MM UTC. The local -clock jumps from 1:59 back to 1:00 again, and repeats the 1:MM hour in -standard time. Since that's what the local clock *does*, we want to map both -UTC hours 5:MM and 6:MM to 1:MM Eastern. The result is ambiguous -in local time, but so it goes -- it's the way the local clock works. - -When x = 5:MM UTC is the input to this algorithm, x.o=0, y.o=-5 and y.d=0, -so z=0:MM. z.d=60 (minutes) then, so [5] doesn't hold and we keep going. -z' = z + z.d = 1:MM then, and z'.d=0, and z'.d - z.d = -60 != 0 so [8] -(correctly) concludes that z' is not UTC-equivalent to x. - -Because we know z.d said z was in daylight time (else [5] would have held and -we would have stopped then), and we know z.d != z'.d (else [8] would have held -and we would have stopped then), and there are only 2 possible values dst() can -return in Eastern, it follows that z'.d must be 0 (which it is in the example, -but the reasoning doesn't depend on the example -- it depends on there being -two possible dst() outcomes, one zero and the other non-zero). Therefore -z' must be in standard time, and is the spelling we want in this case. - -Note again that z' is not UTC-equivalent as far as the hybrid tzinfo class is -concerned (because it takes z' as being in standard time rather than the -daylight time we intend here), but returning it gives the real-life "local -clock repeats an hour" behavior when mapping the "unspellable" UTC hour into -tz. - -When the input is 6:MM, z=1:MM and z.d=0, and we stop at once, again with -the 1:MM standard time spelling we want. - -So how can this break? One of the assumptions must be violated. Two -possibilities: - -1) [2] effectively says that y.s is invariant across all y belong to a given - time zone. This isn't true if, for political reasons or continental drift, - a region decides to change its base offset from UTC. - -2) There may be versions of "double daylight" time where the tail end of - the analysis gives up a step too early. I haven't thought about that - enough to say. - -In any case, it's clear that the default fromutc() is strong enough to handle -"almost all" time zones: so long as the standard offset is invariant, it -doesn't matter if daylight time transition points change from year to year, or -if daylight time is skipped in some years; it doesn't matter how large or -small dst() may get within its bounds; and it doesn't even matter if some -perverse time zone returns a negative dst()). So a breaking case must be -pretty bizarre, and a tzinfo subclass can override fromutc() if it is. ---------------------------------------------------------------------------- */ +/*[clinic end generated code: output=a5c51b96f10c462c input=a9049054013a1b77]*/ diff --git a/Modules/_dbmmodule.c b/Modules/clinic/_dbmmodule.c.h copy from Modules/_dbmmodule.c copy to Modules/clinic/_dbmmodule.c.h --- a/Modules/_dbmmodule.c +++ b/Modules/clinic/_dbmmodule.c.h @@ -1,280 +1,5 @@ - -/* DBM module using dictionary interface */ - - -#define PY_SSIZE_T_CLEAN -#include "Python.h" - -#include -#include -#include - -/* Some Linux systems install gdbm/ndbm.h, but not ndbm.h. This supports - * whichever configure was able to locate. - */ -#if defined(HAVE_NDBM_H) -#include -static char *which_dbm = "GNU gdbm"; /* EMX port of GDBM */ -#elif defined(HAVE_GDBM_NDBM_H) -#include -static char *which_dbm = "GNU gdbm"; -#elif defined(HAVE_GDBM_DASH_NDBM_H) -#include -static char *which_dbm = "GNU gdbm"; -#elif defined(HAVE_BERKDB_H) -#include -static char *which_dbm = "Berkeley DB"; -#else -#error "No ndbm.h available!" -#endif - /*[clinic input] -module dbm -class dbm.dbm "dbmobject *" "&Dbmtype" -[clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=92450564684a69a3]*/ - -typedef struct { - PyObject_HEAD - int di_size; /* -1 means recompute */ - DBM *di_dbm; -} dbmobject; - -static PyTypeObject Dbmtype; - -#define is_dbmobject(v) (Py_TYPE(v) == &Dbmtype) -#define check_dbmobject_open(v) if ((v)->di_dbm == NULL) \ - { PyErr_SetString(DbmError, "DBM object has already been closed"); \ - return NULL; } - -static PyObject *DbmError; - -/*[python input] -class dbmobject_converter(self_converter): - type = "dbmobject *" - def pre_render(self): - super().pre_render() - self.name = 'dp' -[python start generated code]*/ -/*[python end generated code: output=da39a3ee5e6b4b0d input=6ad536357913879a]*/ - -static PyObject * -newdbmobject(const char *file, int flags, int mode) -{ - dbmobject *dp; - - dp = PyObject_New(dbmobject, &Dbmtype); - if (dp == NULL) - return NULL; - dp->di_size = -1; - /* See issue #19296 */ - if ( (dp->di_dbm = dbm_open((char *)file, flags, mode)) == 0 ) { - PyErr_SetFromErrno(DbmError); - Py_DECREF(dp); - return NULL; - } - return (PyObject *)dp; -} - -/* Methods */ - -static void -dbm_dealloc(dbmobject *dp) -{ - if ( dp->di_dbm ) - dbm_close(dp->di_dbm); - PyObject_Del(dp); -} - -static Py_ssize_t -dbm_length(dbmobject *dp) -{ - if (dp->di_dbm == NULL) { - PyErr_SetString(DbmError, "DBM object has already been closed"); - return -1; - } - if ( dp->di_size < 0 ) { - datum key; - int size; - - size = 0; - for ( key=dbm_firstkey(dp->di_dbm); key.dptr; - key = dbm_nextkey(dp->di_dbm)) - size++; - dp->di_size = size; - } - return dp->di_size; -} - -static PyObject * -dbm_subscript(dbmobject *dp, PyObject *key) -{ - datum drec, krec; - Py_ssize_t tmp_size; - - if (!PyArg_Parse(key, "s#", &krec.dptr, &tmp_size) ) - return NULL; - - krec.dsize = tmp_size; - check_dbmobject_open(dp); - drec = dbm_fetch(dp->di_dbm, krec); - if ( drec.dptr == 0 ) { - PyErr_SetObject(PyExc_KeyError, key); - return NULL; - } - if ( dbm_error(dp->di_dbm) ) { - dbm_clearerr(dp->di_dbm); - PyErr_SetString(DbmError, ""); - return NULL; - } - return PyBytes_FromStringAndSize(drec.dptr, drec.dsize); -} - -static int -dbm_ass_sub(dbmobject *dp, PyObject *v, PyObject *w) -{ - datum krec, drec; - Py_ssize_t tmp_size; - - if ( !PyArg_Parse(v, "s#", &krec.dptr, &tmp_size) ) { - PyErr_SetString(PyExc_TypeError, - "dbm mappings have bytes or string keys only"); - return -1; - } - krec.dsize = tmp_size; - if (dp->di_dbm == NULL) { - PyErr_SetString(DbmError, "DBM object has already been closed"); - return -1; - } - dp->di_size = -1; - if (w == NULL) { - if ( dbm_delete(dp->di_dbm, krec) < 0 ) { - dbm_clearerr(dp->di_dbm); - PyErr_SetObject(PyExc_KeyError, v); - return -1; - } - } else { - if ( !PyArg_Parse(w, "s#", &drec.dptr, &tmp_size) ) { - PyErr_SetString(PyExc_TypeError, - "dbm mappings have byte or string elements only"); - return -1; - } - drec.dsize = tmp_size; - if ( dbm_store(dp->di_dbm, krec, drec, DBM_REPLACE) < 0 ) { - dbm_clearerr(dp->di_dbm); - PyErr_SetString(DbmError, - "cannot add item to database"); - return -1; - } - } - if ( dbm_error(dp->di_dbm) ) { - dbm_clearerr(dp->di_dbm); - PyErr_SetString(DbmError, ""); - return -1; - } - return 0; -} - -static PyMappingMethods dbm_as_mapping = { - (lenfunc)dbm_length, /*mp_length*/ - (binaryfunc)dbm_subscript, /*mp_subscript*/ - (objobjargproc)dbm_ass_sub, /*mp_ass_subscript*/ -}; - -static PyObject * -dbm__close(dbmobject *dp, PyObject *unused) -{ - if (dp->di_dbm) - dbm_close(dp->di_dbm); - dp->di_dbm = NULL; - Py_INCREF(Py_None); - return Py_None; -} - -static PyObject * -dbm_keys(dbmobject *dp, PyObject *unused) -{ - PyObject *v, *item; - datum key; - int err; - - check_dbmobject_open(dp); - v = PyList_New(0); - if (v == NULL) - return NULL; - for (key = dbm_firstkey(dp->di_dbm); key.dptr; - key = dbm_nextkey(dp->di_dbm)) { - item = PyBytes_FromStringAndSize(key.dptr, key.dsize); - if (item == NULL) { - Py_DECREF(v); - return NULL; - } - err = PyList_Append(v, item); - Py_DECREF(item); - if (err != 0) { - Py_DECREF(v); - return NULL; - } - } - return v; -} - -static int -dbm_contains(PyObject *self, PyObject *arg) -{ - dbmobject *dp = (dbmobject *)self; - datum key, val; - Py_ssize_t size; - - if ((dp)->di_dbm == NULL) { - PyErr_SetString(DbmError, - "DBM object has already been closed"); - return -1; - } - if (PyUnicode_Check(arg)) { - key.dptr = PyUnicode_AsUTF8AndSize(arg, &size); - key.dsize = size; - if (key.dptr == NULL) - return -1; - } - else if (!PyBytes_Check(arg)) { - PyErr_Format(PyExc_TypeError, - "dbm key must be bytes or string, not %.100s", - arg->ob_type->tp_name); - return -1; - } - else { - key.dptr = PyBytes_AS_STRING(arg); - key.dsize = PyBytes_GET_SIZE(arg); - } - val = dbm_fetch(dp->di_dbm, key); - return val.dptr != NULL; -} - -static PySequenceMethods dbm_as_sequence = { - 0, /* sq_length */ - 0, /* sq_concat */ - 0, /* sq_repeat */ - 0, /* sq_item */ - 0, /* sq_slice */ - 0, /* sq_ass_item */ - 0, /* sq_ass_slice */ - dbm_contains, /* sq_contains */ - 0, /* sq_inplace_concat */ - 0, /* sq_inplace_repeat */ -}; - -/*[clinic input] - -dbm.dbm.get - - self: dbmobject - - key: str(length=True) - default: object = None - / - -Return the value for key if present, otherwise default. +preserve [clinic start generated code]*/ PyDoc_STRVAR(dbm_dbm_get__doc__, @@ -307,148 +32,6 @@ return return_value; } -static PyObject * -dbm_dbm_get_impl(dbmobject *dp, const char *key, Py_ssize_clean_t key_length, PyObject *default_value) -/*[clinic end generated code: output=452ea11394e7e92d input=aecf5efd2f2b1a3b]*/ -{ - datum dbm_key, val; - - dbm_key.dptr = (char *)key; - dbm_key.dsize = key_length; - check_dbmobject_open(dp); - val = dbm_fetch(dp->di_dbm, dbm_key); - if (val.dptr != NULL) - return PyBytes_FromStringAndSize(val.dptr, val.dsize); - - Py_INCREF(default_value); - return default_value; -} - -static PyObject * -dbm_setdefault(dbmobject *dp, PyObject *args) -{ - datum key, val; - PyObject *defvalue = NULL; - char *tmp_ptr; - Py_ssize_t tmp_size; - - if (!PyArg_ParseTuple(args, "s#|O:setdefault", - &tmp_ptr, &tmp_size, &defvalue)) - return NULL; - key.dptr = tmp_ptr; - key.dsize = tmp_size; - check_dbmobject_open(dp); - val = dbm_fetch(dp->di_dbm, key); - if (val.dptr != NULL) - return PyBytes_FromStringAndSize(val.dptr, val.dsize); - if (defvalue == NULL) { - defvalue = PyBytes_FromStringAndSize(NULL, 0); - if (defvalue == NULL) - return NULL; - val.dptr = NULL; - val.dsize = 0; - } - else { - if ( !PyArg_Parse(defvalue, "s#", &val.dptr, &tmp_size) ) { - PyErr_SetString(PyExc_TypeError, - "dbm mappings have byte string elements only"); - return NULL; - } - val.dsize = tmp_size; - Py_INCREF(defvalue); - } - if (dbm_store(dp->di_dbm, key, val, DBM_INSERT) < 0) { - dbm_clearerr(dp->di_dbm); - PyErr_SetString(DbmError, "cannot add item to database"); - Py_DECREF(defvalue); - return NULL; - } - return defvalue; -} - -static PyObject * -dbm__enter__(PyObject *self, PyObject *args) -{ - Py_INCREF(self); - return self; -} - -static PyObject * -dbm__exit__(PyObject *self, PyObject *args) -{ - _Py_IDENTIFIER(close); - return _PyObject_CallMethodId(self, &PyId_close, NULL); -} - - -static PyMethodDef dbm_methods[] = { - {"close", (PyCFunction)dbm__close, METH_NOARGS, - "close()\nClose the database."}, - {"keys", (PyCFunction)dbm_keys, METH_NOARGS, - "keys() -> list\nReturn a list of all keys in the database."}, - DBM_DBM_GET_METHODDEF - {"setdefault", (PyCFunction)dbm_setdefault, METH_VARARGS, - "setdefault(key[, default]) -> value\n" - "Return the value for key if present, otherwise default. If key\n" - "is not in the database, it is inserted with default as the value."}, - {"__enter__", dbm__enter__, METH_NOARGS, NULL}, - {"__exit__", dbm__exit__, METH_VARARGS, NULL}, - {NULL, NULL} /* sentinel */ -}; - -static PyTypeObject Dbmtype = { - PyVarObject_HEAD_INIT(NULL, 0) - "_dbm.dbm", - sizeof(dbmobject), - 0, - (destructor)dbm_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_reserved*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - &dbm_as_sequence, /*tp_as_sequence*/ - &dbm_as_mapping, /*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*/ - dbm_methods, /*tp_methods*/ -}; - -/* ----------------------------------------------------------------- */ - -/*[clinic input] - -dbm.open as dbmopen - - filename: str - The filename to open. - - flags: str="r" - How to open the file. "r" for reading, "w" for writing, etc. - - mode: int(py_default="0o666") = 0o666 - If creating a new file, the mode bits for the new file - (e.g. os.O_RDWR). - - / - -Return a database object. - -[clinic start generated code]*/ - PyDoc_STRVAR(dbmopen__doc__, "open($module, filename, flags=\'r\', mode=0o666, /)\n" "--\n" @@ -486,72 +69,4 @@ exit: return return_value; } - -static PyObject * -dbmopen_impl(PyModuleDef *module, const char *filename, const char *flags, int mode) -/*[clinic end generated code: output=9a7b725f9c4dcec2 input=6499ab0fab1333ac]*/ -{ - int iflags; - - if ( strcmp(flags, "r") == 0 ) - iflags = O_RDONLY; - else if ( strcmp(flags, "w") == 0 ) - iflags = O_RDWR; - else if ( strcmp(flags, "rw") == 0 ) /* B/W compat */ - iflags = O_RDWR|O_CREAT; - else if ( strcmp(flags, "c") == 0 ) - iflags = O_RDWR|O_CREAT; - else if ( strcmp(flags, "n") == 0 ) - iflags = O_RDWR|O_CREAT|O_TRUNC; - else { - PyErr_SetString(DbmError, - "arg 2 to open should be 'r', 'w', 'c', or 'n'"); - return NULL; - } - return newdbmobject(filename, iflags, mode); -} - -static PyMethodDef dbmmodule_methods[] = { - DBMOPEN_METHODDEF - { 0, 0 }, -}; - - -static struct PyModuleDef _dbmmodule = { - PyModuleDef_HEAD_INIT, - "_dbm", - NULL, - -1, - dbmmodule_methods, - NULL, - NULL, - NULL, - NULL -}; - -PyMODINIT_FUNC -PyInit__dbm(void) { - PyObject *m, *d, *s; - - if (PyType_Ready(&Dbmtype) < 0) - return NULL; - m = PyModule_Create(&_dbmmodule); - if (m == NULL) - return NULL; - d = PyModule_GetDict(m); - if (DbmError == NULL) - DbmError = PyErr_NewException("_dbm.error", - PyExc_IOError, NULL); - s = PyUnicode_FromString(which_dbm); - if (s != NULL) { - PyDict_SetItemString(d, "library", s); - Py_DECREF(s); - } - if (DbmError != NULL) - PyDict_SetItemString(d, "error", DbmError); - if (PyErr_Occurred()) { - Py_DECREF(m); - m = NULL; - } - return m; -} +/*[clinic end generated code: output=78d62d1aa3ddd13c input=a9049054013a1b77]*/ diff --git a/Modules/_opcode.c b/Modules/clinic/_opcode.c.h copy from Modules/_opcode.c copy to Modules/clinic/_opcode.c.h --- a/Modules/_opcode.c +++ b/Modules/clinic/_opcode.c.h @@ -1,20 +1,5 @@ -#include "Python.h" -#include "opcode.h" - /*[clinic input] -module _opcode -[clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=117442e66eb376e6]*/ - -/*[clinic input] - -_opcode.stack_effect -> int - - opcode: int - oparg: object = None - / - -Compute the stack effect of the opcode. +preserve [clinic start generated code]*/ PyDoc_STRVAR(_opcode_stack_effect__doc__, @@ -49,61 +34,4 @@ exit: return return_value; } - -static int -_opcode_stack_effect_impl(PyModuleDef *module, int opcode, PyObject *oparg) -/*[clinic end generated code: output=9e1133f8d587bc67 input=2d0a9ee53c0418f5]*/ -{ - int effect; - int oparg_int = 0; - if (HAS_ARG(opcode)) { - if (oparg == Py_None) { - PyErr_SetString(PyExc_ValueError, - "stack_effect: opcode requires oparg but oparg was not specified"); - return -1; - } - oparg_int = (int)PyLong_AsLong(oparg); - if ((oparg_int == -1) && PyErr_Occurred()) - return -1; - } - else if (oparg != Py_None) { - PyErr_SetString(PyExc_ValueError, - "stack_effect: opcode does not permit oparg but oparg was specified"); - return -1; - } - effect = PyCompile_OpcodeStackEffect(opcode, oparg_int); - if (effect == PY_INVALID_STACK_EFFECT) { - PyErr_SetString(PyExc_ValueError, - "invalid opcode or oparg"); - return -1; - } - return effect; -} - - - - -static PyMethodDef -opcode_functions[] = { - _OPCODE_STACK_EFFECT_METHODDEF - {NULL, NULL, 0, NULL} -}; - - -static struct PyModuleDef opcodemodule = { - PyModuleDef_HEAD_INIT, - "_opcode", - "Opcode support module.", - -1, - opcode_functions, - NULL, - NULL, - NULL, - NULL -}; - -PyMODINIT_FUNC -PyInit__opcode(void) -{ - return PyModule_Create(&opcodemodule); -} +/*[clinic end generated code: output=dbe45148bc21ecdf input=a9049054013a1b77]*/ diff --git a/Modules/_weakref.c b/Modules/clinic/_weakref.c.h copy from Modules/_weakref.c copy to Modules/clinic/_weakref.c.h --- a/Modules/_weakref.c +++ b/Modules/clinic/_weakref.c.h @@ -1,22 +1,5 @@ -#include "Python.h" - - -#define GET_WEAKREFS_LISTPTR(o) \ - ((PyWeakReference **) PyObject_GET_WEAKREFS_LISTPTR(o)) - /*[clinic input] -module _weakref -[clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=ffec73b85846596d]*/ - -/*[clinic input] - -_weakref.getweakrefcount -> Py_ssize_t - - object: object - / - -Return the number of weak references to 'object'. +preserve [clinic start generated code]*/ PyDoc_STRVAR(_weakref_getweakrefcount__doc__, @@ -45,114 +28,4 @@ exit: return return_value; } - -static Py_ssize_t -_weakref_getweakrefcount_impl(PyModuleDef *module, PyObject *object) -/*[clinic end generated code: output=032eedbfd7d69e10 input=cedb69711b6a2507]*/ -{ - PyWeakReference **list; - - if (!PyType_SUPPORTS_WEAKREFS(Py_TYPE(object))) - return 0; - - list = GET_WEAKREFS_LISTPTR(object); - return _PyWeakref_GetWeakrefCount(*list); -} - - -PyDoc_STRVAR(weakref_getweakrefs__doc__, -"getweakrefs(object) -- return a list of all weak reference objects\n" -"that point to 'object'."); - -static PyObject * -weakref_getweakrefs(PyObject *self, PyObject *object) -{ - PyObject *result = NULL; - - if (PyType_SUPPORTS_WEAKREFS(Py_TYPE(object))) { - PyWeakReference **list = GET_WEAKREFS_LISTPTR(object); - Py_ssize_t count = _PyWeakref_GetWeakrefCount(*list); - - result = PyList_New(count); - if (result != NULL) { - PyWeakReference *current = *list; - Py_ssize_t i; - for (i = 0; i < count; ++i) { - PyList_SET_ITEM(result, i, (PyObject *) current); - Py_INCREF(current); - current = current->wr_next; - } - } - } - else { - result = PyList_New(0); - } - return result; -} - - -PyDoc_STRVAR(weakref_proxy__doc__, -"proxy(object[, callback]) -- create a proxy object that weakly\n" -"references 'object'. 'callback', if given, is called with a\n" -"reference to the proxy when 'object' is about to be finalized."); - -static PyObject * -weakref_proxy(PyObject *self, PyObject *args) -{ - PyObject *object; - PyObject *callback = NULL; - PyObject *result = NULL; - - if (PyArg_UnpackTuple(args, "proxy", 1, 2, &object, &callback)) { - result = PyWeakref_NewProxy(object, callback); - } - return result; -} - - -static PyMethodDef -weakref_functions[] = { - _WEAKREF_GETWEAKREFCOUNT_METHODDEF - {"getweakrefs", weakref_getweakrefs, METH_O, - weakref_getweakrefs__doc__}, - {"proxy", weakref_proxy, METH_VARARGS, - weakref_proxy__doc__}, - {NULL, NULL, 0, NULL} -}; - - -static struct PyModuleDef weakrefmodule = { - PyModuleDef_HEAD_INIT, - "_weakref", - "Weak-reference support module.", - -1, - weakref_functions, - NULL, - NULL, - NULL, - NULL -}; - -PyMODINIT_FUNC -PyInit__weakref(void) -{ - PyObject *m; - - m = PyModule_Create(&weakrefmodule); - - if (m != NULL) { - Py_INCREF(&_PyWeakref_RefType); - PyModule_AddObject(m, "ref", - (PyObject *) &_PyWeakref_RefType); - Py_INCREF(&_PyWeakref_RefType); - PyModule_AddObject(m, "ReferenceType", - (PyObject *) &_PyWeakref_RefType); - Py_INCREF(&_PyWeakref_ProxyType); - PyModule_AddObject(m, "ProxyType", - (PyObject *) &_PyWeakref_ProxyType); - Py_INCREF(&_PyWeakref_CallableProxyType); - PyModule_AddObject(m, "CallableProxyType", - (PyObject *) &_PyWeakref_CallableProxyType); - } - return m; -} +/*[clinic end generated code: output=4da9aade63eed77f input=a9049054013a1b77]*/ diff --git a/Modules/md5module.c b/Modules/clinic/md5module.c.h copy from Modules/md5module.c copy to Modules/clinic/md5module.c.h --- a/Modules/md5module.c +++ b/Modules/clinic/md5module.c.h @@ -1,346 +1,5 @@ -/* MD5 module */ - -/* This module provides an interface to the MD5 algorithm */ - -/* See below for information about the original code this module was - based upon. Additional work performed by: - - Andrew Kuchling (amk at amk.ca) - Greg Stein (gstein at lyra.org) - Trevor Perrin (trevp at trevp.net) - - Copyright (C) 2005-2007 Gregory P. Smith (greg at krypto.org) - Licensed to PSF under a Contributor Agreement. - -*/ - -/* MD5 objects */ - -#include "Python.h" -#include "hashlib.h" - /*[clinic input] -module _md5 -class MD5Type "MD5object *" "&PyType_Type" -[clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=6e5261719957a912]*/ - -/* Some useful types */ - -#if SIZEOF_INT == 4 -typedef unsigned int MD5_INT32; /* 32-bit integer */ -typedef PY_LONG_LONG MD5_INT64; /* 64-bit integer */ -#else -/* not defined. compilation will die. */ -#endif - -/* The MD5 block size and message digest sizes, in bytes */ - -#define MD5_BLOCKSIZE 64 -#define MD5_DIGESTSIZE 16 - -/* The structure for storing MD5 info */ - -struct md5_state { - MD5_INT64 length; - MD5_INT32 state[4], curlen; - unsigned char buf[MD5_BLOCKSIZE]; -}; - -typedef struct { - PyObject_HEAD - - struct md5_state hash_state; -} MD5object; - - -/* ------------------------------------------------------------------------ - * - * This code for the MD5 algorithm was noted as public domain. The - * original headers are pasted below. - * - * Several changes have been made to make it more compatible with the - * Python environment and desired interface. - * - */ - -/* LibTomCrypt, modular cryptographic library -- Tom St Denis - * - * LibTomCrypt is a library that provides various cryptographic - * algorithms in a highly modular and flexible manner. - * - * The library is free for all purposes without any express - * guarantee it works. - * - * Tom St Denis, tomstdenis at gmail.com, http://libtom.org - */ - -/* rotate the hard way (platform optimizations could be done) */ -#define ROLc(x, y) ( (((unsigned long)(x)<<(unsigned long)((y)&31)) | (((unsigned long)(x)&0xFFFFFFFFUL)>>(unsigned long)(32-((y)&31)))) & 0xFFFFFFFFUL) - -/* Endian Neutral macros that work on all platforms */ - -#define STORE32L(x, y) \ - { (y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255); \ - (y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); } - -#define LOAD32L(x, y) \ - { x = ((unsigned long)((y)[3] & 255)<<24) | \ - ((unsigned long)((y)[2] & 255)<<16) | \ - ((unsigned long)((y)[1] & 255)<<8) | \ - ((unsigned long)((y)[0] & 255)); } - -#define STORE64L(x, y) \ - { (y)[7] = (unsigned char)(((x)>>56)&255); (y)[6] = (unsigned char)(((x)>>48)&255); \ - (y)[5] = (unsigned char)(((x)>>40)&255); (y)[4] = (unsigned char)(((x)>>32)&255); \ - (y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255); \ - (y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); } - - -/* MD5 macros */ - -#define F(x,y,z) (z ^ (x & (y ^ z))) -#define G(x,y,z) (y ^ (z & (y ^ x))) -#define H(x,y,z) (x^y^z) -#define I(x,y,z) (y^(x|(~z))) - -#define FF(a,b,c,d,M,s,t) \ - a = (a + F(b,c,d) + M + t); a = ROLc(a, s) + b; - -#define GG(a,b,c,d,M,s,t) \ - a = (a + G(b,c,d) + M + t); a = ROLc(a, s) + b; - -#define HH(a,b,c,d,M,s,t) \ - a = (a + H(b,c,d) + M + t); a = ROLc(a, s) + b; - -#define II(a,b,c,d,M,s,t) \ - a = (a + I(b,c,d) + M + t); a = ROLc(a, s) + b; - - -static void md5_compress(struct md5_state *md5, unsigned char *buf) -{ - MD5_INT32 i, W[16], a, b, c, d; - - assert(md5 != NULL); - assert(buf != NULL); - - /* copy the state into 512-bits into W[0..15] */ - for (i = 0; i < 16; i++) { - LOAD32L(W[i], buf + (4*i)); - } - - /* copy state */ - a = md5->state[0]; - b = md5->state[1]; - c = md5->state[2]; - d = md5->state[3]; - - FF(a,b,c,d,W[0],7,0xd76aa478UL) - FF(d,a,b,c,W[1],12,0xe8c7b756UL) - FF(c,d,a,b,W[2],17,0x242070dbUL) - FF(b,c,d,a,W[3],22,0xc1bdceeeUL) - FF(a,b,c,d,W[4],7,0xf57c0fafUL) - FF(d,a,b,c,W[5],12,0x4787c62aUL) - FF(c,d,a,b,W[6],17,0xa8304613UL) - FF(b,c,d,a,W[7],22,0xfd469501UL) - FF(a,b,c,d,W[8],7,0x698098d8UL) - FF(d,a,b,c,W[9],12,0x8b44f7afUL) - FF(c,d,a,b,W[10],17,0xffff5bb1UL) - FF(b,c,d,a,W[11],22,0x895cd7beUL) - FF(a,b,c,d,W[12],7,0x6b901122UL) - FF(d,a,b,c,W[13],12,0xfd987193UL) - FF(c,d,a,b,W[14],17,0xa679438eUL) - FF(b,c,d,a,W[15],22,0x49b40821UL) - GG(a,b,c,d,W[1],5,0xf61e2562UL) - GG(d,a,b,c,W[6],9,0xc040b340UL) - GG(c,d,a,b,W[11],14,0x265e5a51UL) - GG(b,c,d,a,W[0],20,0xe9b6c7aaUL) - GG(a,b,c,d,W[5],5,0xd62f105dUL) - GG(d,a,b,c,W[10],9,0x02441453UL) - GG(c,d,a,b,W[15],14,0xd8a1e681UL) - GG(b,c,d,a,W[4],20,0xe7d3fbc8UL) - GG(a,b,c,d,W[9],5,0x21e1cde6UL) - GG(d,a,b,c,W[14],9,0xc33707d6UL) - GG(c,d,a,b,W[3],14,0xf4d50d87UL) - GG(b,c,d,a,W[8],20,0x455a14edUL) - GG(a,b,c,d,W[13],5,0xa9e3e905UL) - GG(d,a,b,c,W[2],9,0xfcefa3f8UL) - GG(c,d,a,b,W[7],14,0x676f02d9UL) - GG(b,c,d,a,W[12],20,0x8d2a4c8aUL) - HH(a,b,c,d,W[5],4,0xfffa3942UL) - HH(d,a,b,c,W[8],11,0x8771f681UL) - HH(c,d,a,b,W[11],16,0x6d9d6122UL) - HH(b,c,d,a,W[14],23,0xfde5380cUL) - HH(a,b,c,d,W[1],4,0xa4beea44UL) - HH(d,a,b,c,W[4],11,0x4bdecfa9UL) - HH(c,d,a,b,W[7],16,0xf6bb4b60UL) - HH(b,c,d,a,W[10],23,0xbebfbc70UL) - HH(a,b,c,d,W[13],4,0x289b7ec6UL) - HH(d,a,b,c,W[0],11,0xeaa127faUL) - HH(c,d,a,b,W[3],16,0xd4ef3085UL) - HH(b,c,d,a,W[6],23,0x04881d05UL) - HH(a,b,c,d,W[9],4,0xd9d4d039UL) - HH(d,a,b,c,W[12],11,0xe6db99e5UL) - HH(c,d,a,b,W[15],16,0x1fa27cf8UL) - HH(b,c,d,a,W[2],23,0xc4ac5665UL) - II(a,b,c,d,W[0],6,0xf4292244UL) - II(d,a,b,c,W[7],10,0x432aff97UL) - II(c,d,a,b,W[14],15,0xab9423a7UL) - II(b,c,d,a,W[5],21,0xfc93a039UL) - II(a,b,c,d,W[12],6,0x655b59c3UL) - II(d,a,b,c,W[3],10,0x8f0ccc92UL) - II(c,d,a,b,W[10],15,0xffeff47dUL) - II(b,c,d,a,W[1],21,0x85845dd1UL) - II(a,b,c,d,W[8],6,0x6fa87e4fUL) - II(d,a,b,c,W[15],10,0xfe2ce6e0UL) - II(c,d,a,b,W[6],15,0xa3014314UL) - II(b,c,d,a,W[13],21,0x4e0811a1UL) - II(a,b,c,d,W[4],6,0xf7537e82UL) - II(d,a,b,c,W[11],10,0xbd3af235UL) - II(c,d,a,b,W[2],15,0x2ad7d2bbUL) - II(b,c,d,a,W[9],21,0xeb86d391UL) - - md5->state[0] = md5->state[0] + a; - md5->state[1] = md5->state[1] + b; - md5->state[2] = md5->state[2] + c; - md5->state[3] = md5->state[3] + d; -} - - -/** - Initialize the hash state - @param sha1 The hash state you wish to initialize -*/ -static void -md5_init(struct md5_state *md5) -{ - assert(md5 != NULL); - md5->state[0] = 0x67452301UL; - md5->state[1] = 0xefcdab89UL; - md5->state[2] = 0x98badcfeUL; - md5->state[3] = 0x10325476UL; - md5->curlen = 0; - md5->length = 0; -} - -/** - Process a block of memory though the hash - @param sha1 The hash state - @param in The data to hash - @param inlen The length of the data (octets) -*/ -static void -md5_process(struct md5_state *md5, const unsigned char *in, Py_ssize_t inlen) -{ - Py_ssize_t n; - - assert(md5 != NULL); - assert(in != NULL); - assert(md5->curlen <= sizeof(md5->buf)); - - while (inlen > 0) { - if (md5->curlen == 0 && inlen >= MD5_BLOCKSIZE) { - md5_compress(md5, (unsigned char *)in); - md5->length += MD5_BLOCKSIZE * 8; - in += MD5_BLOCKSIZE; - inlen -= MD5_BLOCKSIZE; - } else { - n = Py_MIN(inlen, (Py_ssize_t)(MD5_BLOCKSIZE - md5->curlen)); - memcpy(md5->buf + md5->curlen, in, (size_t)n); - md5->curlen += (MD5_INT32)n; - in += n; - inlen -= n; - if (md5->curlen == MD5_BLOCKSIZE) { - md5_compress(md5, md5->buf); - md5->length += 8*MD5_BLOCKSIZE; - md5->curlen = 0; - } - } - } -} - -/** - Terminate the hash to get the digest - @param sha1 The hash state - @param out [out] The destination of the hash (16 bytes) -*/ -static void -md5_done(struct md5_state *md5, unsigned char *out) -{ - int i; - - assert(md5 != NULL); - assert(out != NULL); - assert(md5->curlen < sizeof(md5->buf)); - - /* increase the length of the message */ - md5->length += md5->curlen * 8; - - /* append the '1' bit */ - md5->buf[md5->curlen++] = (unsigned char)0x80; - - /* if the length is currently above 56 bytes we append zeros - * then compress. Then we can fall back to padding zeros and length - * encoding like normal. - */ - if (md5->curlen > 56) { - while (md5->curlen < 64) { - md5->buf[md5->curlen++] = (unsigned char)0; - } - md5_compress(md5, md5->buf); - md5->curlen = 0; - } - - /* pad upto 56 bytes of zeroes */ - while (md5->curlen < 56) { - md5->buf[md5->curlen++] = (unsigned char)0; - } - - /* store length */ - STORE64L(md5->length, md5->buf+56); - md5_compress(md5, md5->buf); - - /* copy output */ - for (i = 0; i < 4; i++) { - STORE32L(md5->state[i], out+(4*i)); - } -} - -/* .Source: /cvs/libtom/libtomcrypt/src/hashes/md5.c,v $ */ -/* .Revision: 1.10 $ */ -/* .Date: 2007/05/12 14:25:28 $ */ - -/* - * End of copied MD5 code. - * - * ------------------------------------------------------------------------ - */ - -static PyTypeObject MD5type; - - -static MD5object * -newMD5object(void) -{ - return (MD5object *)PyObject_New(MD5object, &MD5type); -} - - -/* Internal methods for a hash object */ - -static void -MD5_dealloc(PyObject *ptr) -{ - PyObject_Del(ptr); -} - - -/* External methods for a hash object */ - -/*[clinic input] -MD5Type.copy - -Return a copy of the hash object. +preserve [clinic start generated code]*/ PyDoc_STRVAR(MD5Type_copy__doc__, @@ -361,30 +20,6 @@ return MD5Type_copy_impl(self); } -static PyObject * -MD5Type_copy_impl(MD5object *self) -/*[clinic end generated code: output=3b3a88920b3dc7f4 input=2c09e6d2493f3079]*/ -{ - MD5object *newobj; - - if (Py_TYPE(self) == &MD5type) { - if ( (newobj = newMD5object())==NULL) - return NULL; - } else { - if ( (newobj = newMD5object())==NULL) - return NULL; - } - - newobj->hash_state = self->hash_state; - return (PyObject *)newobj; -} - -/*[clinic input] -MD5Type.digest - -Return the digest value as a string of binary data. -[clinic start generated code]*/ - PyDoc_STRVAR(MD5Type_digest__doc__, "digest($self, /)\n" "--\n" @@ -403,24 +38,6 @@ return MD5Type_digest_impl(self); } -static PyObject * -MD5Type_digest_impl(MD5object *self) -/*[clinic end generated code: output=7a796b28fa89485f input=7b96e65389412a34]*/ -{ - unsigned char digest[MD5_DIGESTSIZE]; - struct md5_state temp; - - temp = self->hash_state; - md5_done(&temp, digest); - return PyBytes_FromStringAndSize((const char *)digest, MD5_DIGESTSIZE); -} - -/*[clinic input] -MD5Type.hexdigest - -Return the digest value as a string of hexadecimal digits. -[clinic start generated code]*/ - PyDoc_STRVAR(MD5Type_hexdigest__doc__, "hexdigest($self, /)\n" "--\n" @@ -439,49 +56,6 @@ return MD5Type_hexdigest_impl(self); } -static PyObject * -MD5Type_hexdigest_impl(MD5object *self) -/*[clinic end generated code: output=daa73609f94f92e1 input=b60b19de644798dd]*/ -{ - unsigned char digest[MD5_DIGESTSIZE]; - struct md5_state temp; - PyObject *retval; - Py_UCS1 *hex_digest; - int i, j; - - /* Get the raw (binary) digest value */ - temp = self->hash_state; - md5_done(&temp, digest); - - /* Create a new string */ - retval = PyUnicode_New(MD5_DIGESTSIZE * 2, 127); - if (!retval) - return NULL; - hex_digest = PyUnicode_1BYTE_DATA(retval); - - /* Make hex version of the digest */ - for(i=j=0; i> 4) & 0xf; - hex_digest[j++] = Py_hexdigits[c]; - c = (digest[i] & 0xf); - hex_digest[j++] = Py_hexdigits[c]; - } -#ifdef Py_DEBUG - assert(_PyUnicode_CheckConsistency(retval, 1)); -#endif - return retval; -} - -/*[clinic input] -MD5Type.update - - obj: object - / - -Update this hash object's state with the provided string. -[clinic start generated code]*/ - PyDoc_STRVAR(MD5Type_update__doc__, "update($self, obj, /)\n" "--\n" @@ -491,109 +65,6 @@ #define MD5TYPE_UPDATE_METHODDEF \ {"update", (PyCFunction)MD5Type_update, METH_O, MD5Type_update__doc__}, -static PyObject * -MD5Type_update(MD5object *self, PyObject *obj) -/*[clinic end generated code: output=9d09b6c6cdc6cac3 input=6e1efcd9ecf17032]*/ -{ - Py_buffer buf; - - GET_BUFFER_VIEW_OR_ERROUT(obj, &buf); - - md5_process(&self->hash_state, buf.buf, buf.len); - - PyBuffer_Release(&buf); - Py_INCREF(Py_None); - return Py_None; -} - -static PyMethodDef MD5_methods[] = { - MD5TYPE_COPY_METHODDEF - MD5TYPE_DIGEST_METHODDEF - MD5TYPE_HEXDIGEST_METHODDEF - MD5TYPE_UPDATE_METHODDEF - {NULL, NULL} /* sentinel */ -}; - -static PyObject * -MD5_get_block_size(PyObject *self, void *closure) -{ - return PyLong_FromLong(MD5_BLOCKSIZE); -} - -static PyObject * -MD5_get_name(PyObject *self, void *closure) -{ - return PyUnicode_FromStringAndSize("md5", 3); -} - -static PyObject * -md5_get_digest_size(PyObject *self, void *closure) -{ - return PyLong_FromLong(MD5_DIGESTSIZE); -} - - -static PyGetSetDef MD5_getseters[] = { - {"block_size", - (getter)MD5_get_block_size, NULL, - NULL, - NULL}, - {"name", - (getter)MD5_get_name, NULL, - NULL, - NULL}, - {"digest_size", - (getter)md5_get_digest_size, NULL, - NULL, - NULL}, - {NULL} /* Sentinel */ -}; - -static PyTypeObject MD5type = { - PyVarObject_HEAD_INIT(NULL, 0) - "_md5.md5", /*tp_name*/ - sizeof(MD5object), /*tp_size*/ - 0, /*tp_itemsize*/ - /* methods */ - MD5_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_reserved*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash*/ - 0, /*tp_call*/ - 0, /*tp_str*/ - 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*/ - MD5_methods, /* tp_methods */ - NULL, /* tp_members */ - MD5_getseters, /* tp_getset */ -}; - - -/* The single module-level function: new() */ - -/*[clinic input] -_md5.md5 - - string: object(c_default="NULL") = b'' - -Return a new MD5 hash object; optionally initialized with a string. -[clinic start generated code]*/ - PyDoc_STRVAR(_md5_md5__doc__, "md5($module, /, string=b\'\')\n" "--\n" @@ -622,79 +93,4 @@ exit: return return_value; } - -static PyObject * -_md5_md5_impl(PyModuleDef *module, PyObject *string) -/*[clinic end generated code: output=1039e912d919880e input=d12ef8f72d684f7b]*/ -{ - MD5object *new; - Py_buffer buf; - - if (string) - GET_BUFFER_VIEW_OR_ERROUT(string, &buf); - - if ((new = newMD5object()) == NULL) { - if (string) - PyBuffer_Release(&buf); - return NULL; - } - - md5_init(&new->hash_state); - - if (PyErr_Occurred()) { - Py_DECREF(new); - if (string) - PyBuffer_Release(&buf); - return NULL; - } - if (string) { - md5_process(&new->hash_state, buf.buf, buf.len); - PyBuffer_Release(&buf); - } - - return (PyObject *)new; -} - - -/* List of functions exported by this module */ - -static struct PyMethodDef MD5_functions[] = { - _MD5_MD5_METHODDEF - {NULL, NULL} /* Sentinel */ -}; - - -/* Initialize this module. */ - -#define insint(n,v) { PyModule_AddIntConstant(m,n,v); } - - -static struct PyModuleDef _md5module = { - PyModuleDef_HEAD_INIT, - "_md5", - NULL, - -1, - MD5_functions, - NULL, - NULL, - NULL, - NULL -}; - -PyMODINIT_FUNC -PyInit__md5(void) -{ - PyObject *m; - - Py_TYPE(&MD5type) = &PyType_Type; - if (PyType_Ready(&MD5type) < 0) - return NULL; - - m = PyModule_Create(&_md5module); - if (m == NULL) - return NULL; - - Py_INCREF((PyObject *)&MD5type); - PyModule_AddObject(m, "MD5Type", (PyObject *)&MD5type); - return m; -} +/*[clinic end generated code: output=f72618edfd35d984 input=a9049054013a1b77]*/ diff --git a/Modules/posixmodule.c b/Modules/clinic/posixmodule.c.h copy from Modules/posixmodule.c copy to Modules/clinic/posixmodule.c.h --- a/Modules/posixmodule.c +++ b/Modules/clinic/posixmodule.c.h @@ -1,2473 +1,5 @@ - -/* POSIX module implementation */ - -/* This file is also used for Windows NT/MS-Win. In that case the - module actually calls itself 'nt', not 'posix', and a few - functions are either unimplemented or implemented differently. The source - assumes that for Windows NT, the macro 'MS_WINDOWS' is defined independent - of the compiler used. Different compilers define their own feature - test macro, e.g. '_MSC_VER'. */ - - - -#ifdef __APPLE__ - /* - * Step 1 of support for weak-linking a number of symbols existing on - * OSX 10.4 and later, see the comment in the #ifdef __APPLE__ block - * at the end of this file for more information. - */ -# pragma weak lchown -# pragma weak statvfs -# pragma weak fstatvfs - -#endif /* __APPLE__ */ - -#define PY_SSIZE_T_CLEAN - -#include "Python.h" -#include "structmember.h" -#ifndef MS_WINDOWS -#include "posixmodule.h" -#else -#include "winreparse.h" -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -PyDoc_STRVAR(posix__doc__, -"This module provides access to operating system functionality that is\n\ -standardized by the C Standard and the POSIX standard (a thinly\n\ -disguised Unix interface). Refer to the library manual and\n\ -corresponding Unix manual entries for more information on calls."); - - -#ifdef HAVE_SYS_UIO_H -#include -#endif - -#ifdef HAVE_SYS_TYPES_H -#include -#endif /* HAVE_SYS_TYPES_H */ - -#ifdef HAVE_SYS_STAT_H -#include -#endif /* HAVE_SYS_STAT_H */ - -#ifdef HAVE_SYS_WAIT_H -#include /* For WNOHANG */ -#endif - -#ifdef HAVE_SIGNAL_H -#include -#endif - -#ifdef HAVE_FCNTL_H -#include -#endif /* HAVE_FCNTL_H */ - -#ifdef HAVE_GRP_H -#include -#endif - -#ifdef HAVE_SYSEXITS_H -#include -#endif /* HAVE_SYSEXITS_H */ - -#ifdef HAVE_SYS_LOADAVG_H -#include -#endif - -#ifdef HAVE_LANGINFO_H -#include -#endif - -#ifdef HAVE_SYS_SENDFILE_H -#include -#endif - -#ifdef HAVE_SCHED_H -#include -#endif - -#if !defined(CPU_ALLOC) && defined(HAVE_SCHED_SETAFFINITY) -#undef HAVE_SCHED_SETAFFINITY -#endif - -#if defined(HAVE_SYS_XATTR_H) && defined(__GLIBC__) && !defined(__FreeBSD_kernel__) && !defined(__GNU__) -#define USE_XATTRS -#endif - -#ifdef USE_XATTRS -#include -#endif - -#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__) -#ifdef HAVE_SYS_SOCKET_H -#include -#endif -#endif - -#ifdef HAVE_DLFCN_H -#include -#endif - -#ifdef __hpux -#include -#endif - -#if defined(__DragonFly__) || \ - defined(__OpenBSD__) || \ - defined(__FreeBSD__) || \ - defined(__NetBSD__) || \ - defined(__APPLE__) -#include -#endif - -#if defined(MS_WINDOWS) -# define TERMSIZE_USE_CONIO -#elif defined(HAVE_SYS_IOCTL_H) -# include -# if defined(HAVE_TERMIOS_H) -# include -# endif -# if defined(TIOCGWINSZ) -# define TERMSIZE_USE_IOCTL -# endif -#endif /* MS_WINDOWS */ - -/* Various compilers have only certain posix functions */ -/* XXX Gosh I wish these were all moved into pyconfig.h */ -#if defined(__WATCOMC__) && !defined(__QNX__) /* Watcom compiler */ -#define HAVE_OPENDIR 1 -#define HAVE_SYSTEM 1 -#include -#else -#ifdef _MSC_VER /* Microsoft compiler */ -#define HAVE_GETPPID 1 -#define HAVE_GETLOGIN 1 -#define HAVE_SPAWNV 1 -#define HAVE_EXECV 1 -#define HAVE_PIPE 1 -#define HAVE_SYSTEM 1 -#define HAVE_CWAIT 1 -#define HAVE_FSYNC 1 -#define fsync _commit -#else -/* Unix functions that the configure script doesn't check for */ -#define HAVE_EXECV 1 -#define HAVE_FORK 1 -#if defined(__USLC__) && defined(__SCO_VERSION__) /* SCO UDK Compiler */ -#define HAVE_FORK1 1 -#endif -#define HAVE_GETEGID 1 -#define HAVE_GETEUID 1 -#define HAVE_GETGID 1 -#define HAVE_GETPPID 1 -#define HAVE_GETUID 1 -#define HAVE_KILL 1 -#define HAVE_OPENDIR 1 -#define HAVE_PIPE 1 -#define HAVE_SYSTEM 1 -#define HAVE_WAIT 1 -#define HAVE_TTYNAME 1 -#endif /* _MSC_VER */ -#endif /* ! __WATCOMC__ || __QNX__ */ - - /*[clinic input] -# one of the few times we lie about this name! -module os -[clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=94a0f0f978acae17]*/ - -#ifndef _MSC_VER - -#if defined(__sgi)&&_COMPILER_VERSION>=700 -/* declare ctermid_r if compiling with MIPSPro 7.x in ANSI C mode - (default) */ -extern char *ctermid_r(char *); -#endif - -#ifndef HAVE_UNISTD_H -#if defined(PYCC_VACPP) -extern int mkdir(char *); -#else -#if ( defined(__WATCOMC__) || defined(_MSC_VER) ) && !defined(__QNX__) -extern int mkdir(const char *); -#else -extern int mkdir(const char *, mode_t); -#endif -#endif -#if defined(__IBMC__) || defined(__IBMCPP__) -extern int chdir(char *); -extern int rmdir(char *); -#else -extern int chdir(const char *); -extern int rmdir(const char *); -#endif -extern int chmod(const char *, mode_t); -/*#ifdef HAVE_FCHMOD -extern int fchmod(int, mode_t); -#endif*/ -/*#ifdef HAVE_LCHMOD -extern int lchmod(const char *, mode_t); -#endif*/ -extern int chown(const char *, uid_t, gid_t); -extern char *getcwd(char *, int); -extern char *strerror(int); -extern int link(const char *, const char *); -extern int rename(const char *, const char *); -extern int stat(const char *, struct stat *); -extern int unlink(const char *); -#ifdef HAVE_SYMLINK -extern int symlink(const char *, const char *); -#endif /* HAVE_SYMLINK */ -#ifdef HAVE_LSTAT -extern int lstat(const char *, struct stat *); -#endif /* HAVE_LSTAT */ -#endif /* !HAVE_UNISTD_H */ - -#endif /* !_MSC_VER */ - -#ifdef HAVE_UTIME_H -#include -#endif /* HAVE_UTIME_H */ - -#ifdef HAVE_SYS_UTIME_H -#include -#define HAVE_UTIME_H /* pretend we do for the rest of this file */ -#endif /* HAVE_SYS_UTIME_H */ - -#ifdef HAVE_SYS_TIMES_H -#include -#endif /* HAVE_SYS_TIMES_H */ - -#ifdef HAVE_SYS_PARAM_H -#include -#endif /* HAVE_SYS_PARAM_H */ - -#ifdef HAVE_SYS_UTSNAME_H -#include -#endif /* HAVE_SYS_UTSNAME_H */ - -#ifdef HAVE_DIRENT_H -#include -#define NAMLEN(dirent) strlen((dirent)->d_name) -#else -#if defined(__WATCOMC__) && !defined(__QNX__) -#include -#define NAMLEN(dirent) strlen((dirent)->d_name) -#else -#define dirent direct -#define NAMLEN(dirent) (dirent)->d_namlen -#endif -#ifdef HAVE_SYS_NDIR_H -#include -#endif -#ifdef HAVE_SYS_DIR_H -#include -#endif -#ifdef HAVE_NDIR_H -#include -#endif -#endif - -#ifdef _MSC_VER -#ifdef HAVE_DIRECT_H -#include -#endif -#ifdef HAVE_IO_H -#include -#endif -#ifdef HAVE_PROCESS_H -#include -#endif -#ifndef VOLUME_NAME_DOS -#define VOLUME_NAME_DOS 0x0 -#endif -#ifndef VOLUME_NAME_NT -#define VOLUME_NAME_NT 0x2 -#endif -#ifndef IO_REPARSE_TAG_SYMLINK -#define IO_REPARSE_TAG_SYMLINK (0xA000000CL) -#endif -#ifndef IO_REPARSE_TAG_MOUNT_POINT -#define IO_REPARSE_TAG_MOUNT_POINT (0xA0000003L) -#endif -#include "osdefs.h" -#include -#include -#include /* for ShellExecute() */ -#include /* for UNLEN */ -#ifdef SE_CREATE_SYMBOLIC_LINK_NAME /* Available starting with Vista */ -#define HAVE_SYMLINK -static int win32_can_symlink = 0; -#endif -#endif /* _MSC_VER */ - -#ifndef MAXPATHLEN -#if defined(PATH_MAX) && PATH_MAX > 1024 -#define MAXPATHLEN PATH_MAX -#else -#define MAXPATHLEN 1024 -#endif -#endif /* MAXPATHLEN */ - -#ifdef UNION_WAIT -/* Emulate some macros on systems that have a union instead of macros */ - -#ifndef WIFEXITED -#define WIFEXITED(u_wait) (!(u_wait).w_termsig && !(u_wait).w_coredump) -#endif - -#ifndef WEXITSTATUS -#define WEXITSTATUS(u_wait) (WIFEXITED(u_wait)?((u_wait).w_retcode):-1) -#endif - -#ifndef WTERMSIG -#define WTERMSIG(u_wait) ((u_wait).w_termsig) -#endif - -#define WAIT_TYPE union wait -#define WAIT_STATUS_INT(s) (s.w_status) - -#else /* !UNION_WAIT */ -#define WAIT_TYPE int -#define WAIT_STATUS_INT(s) (s) -#endif /* UNION_WAIT */ - -/* Don't use the "_r" form if we don't need it (also, won't have a - prototype for it, at least on Solaris -- maybe others as well?). */ -#if defined(HAVE_CTERMID_R) && defined(WITH_THREAD) -#define USE_CTERMID_R -#endif - -/* choose the appropriate stat and fstat functions and return structs */ -#undef STAT -#undef FSTAT -#undef STRUCT_STAT -#ifdef MS_WINDOWS -# define STAT win32_stat -# define LSTAT win32_lstat -# define FSTAT _Py_fstat_noraise -# define STRUCT_STAT struct _Py_stat_struct -#else -# define STAT stat -# define LSTAT lstat -# define FSTAT fstat -# define STRUCT_STAT struct stat -#endif - -#if defined(MAJOR_IN_MKDEV) -#include -#else -#if defined(MAJOR_IN_SYSMACROS) -#include -#endif -#if defined(HAVE_MKNOD) && defined(HAVE_SYS_MKDEV_H) -#include -#endif -#endif - -#define DWORD_MAX 4294967295U - -#ifdef MS_WINDOWS -#define INITFUNC PyInit_nt -#define MODNAME "nt" -#else -#define INITFUNC PyInit_posix -#define MODNAME "posix" -#endif - -#ifdef MS_WINDOWS -/* defined in fileutils.c */ -PyAPI_FUNC(void) _Py_time_t_to_FILE_TIME(time_t, int, FILETIME *); -PyAPI_FUNC(void) _Py_attribute_data_to_stat(BY_HANDLE_FILE_INFORMATION *, - ULONG, struct _Py_stat_struct *); -#endif - -#ifdef MS_WINDOWS -static int -win32_warn_bytes_api() -{ - return PyErr_WarnEx(PyExc_DeprecationWarning, - "The Windows bytes API has been deprecated, " - "use Unicode filenames instead", - 1); -} -#endif - - -#ifndef MS_WINDOWS -PyObject * -_PyLong_FromUid(uid_t uid) -{ - if (uid == (uid_t)-1) - return PyLong_FromLong(-1); - return PyLong_FromUnsignedLong(uid); -} - -PyObject * -_PyLong_FromGid(gid_t gid) -{ - if (gid == (gid_t)-1) - return PyLong_FromLong(-1); - return PyLong_FromUnsignedLong(gid); -} - -int -_Py_Uid_Converter(PyObject *obj, void *p) -{ - uid_t uid; - PyObject *index; - int overflow; - long result; - unsigned long uresult; - - index = PyNumber_Index(obj); - if (index == NULL) { - PyErr_Format(PyExc_TypeError, - "uid should be integer, not %.200s", - Py_TYPE(obj)->tp_name); - return 0; - } - - /* - * Handling uid_t is complicated for two reasons: - * * Although uid_t is (always?) unsigned, it still - * accepts -1. - * * We don't know its size in advance--it may be - * bigger than an int, or it may be smaller than - * a long. - * - * So a bit of defensive programming is in order. - * Start with interpreting the value passed - * in as a signed long and see if it works. - */ - - result = PyLong_AsLongAndOverflow(index, &overflow); - - if (!overflow) { - uid = (uid_t)result; - - if (result == -1) { - if (PyErr_Occurred()) - goto fail; - /* It's a legitimate -1, we're done. */ - goto success; - } - - /* Any other negative number is disallowed. */ - if (result < 0) - goto underflow; - - /* Ensure the value wasn't truncated. */ - if (sizeof(uid_t) < sizeof(long) && - (long)uid != result) - goto underflow; - goto success; - } - - if (overflow < 0) - goto underflow; - - /* - * Okay, the value overflowed a signed long. If it - * fits in an *unsigned* long, it may still be okay, - * as uid_t may be unsigned long on this platform. - */ - uresult = PyLong_AsUnsignedLong(index); - if (PyErr_Occurred()) { - if (PyErr_ExceptionMatches(PyExc_OverflowError)) - goto overflow; - goto fail; - } - - uid = (uid_t)uresult; - - /* - * If uid == (uid_t)-1, the user actually passed in ULONG_MAX, - * but this value would get interpreted as (uid_t)-1 by chown - * and its siblings. That's not what the user meant! So we - * throw an overflow exception instead. (We already - * handled a real -1 with PyLong_AsLongAndOverflow() above.) - */ - if (uid == (uid_t)-1) - goto overflow; - - /* Ensure the value wasn't truncated. */ - if (sizeof(uid_t) < sizeof(long) && - (unsigned long)uid != uresult) - goto overflow; - /* fallthrough */ - -success: - Py_DECREF(index); - *(uid_t *)p = uid; - return 1; - -underflow: - PyErr_SetString(PyExc_OverflowError, - "uid is less than minimum"); - goto fail; - -overflow: - PyErr_SetString(PyExc_OverflowError, - "uid is greater than maximum"); - /* fallthrough */ - -fail: - Py_DECREF(index); - return 0; -} - -int -_Py_Gid_Converter(PyObject *obj, void *p) -{ - gid_t gid; - PyObject *index; - int overflow; - long result; - unsigned long uresult; - - index = PyNumber_Index(obj); - if (index == NULL) { - PyErr_Format(PyExc_TypeError, - "gid should be integer, not %.200s", - Py_TYPE(obj)->tp_name); - return 0; - } - - /* - * Handling gid_t is complicated for two reasons: - * * Although gid_t is (always?) unsigned, it still - * accepts -1. - * * We don't know its size in advance--it may be - * bigger than an int, or it may be smaller than - * a long. - * - * So a bit of defensive programming is in order. - * Start with interpreting the value passed - * in as a signed long and see if it works. - */ - - result = PyLong_AsLongAndOverflow(index, &overflow); - - if (!overflow) { - gid = (gid_t)result; - - if (result == -1) { - if (PyErr_Occurred()) - goto fail; - /* It's a legitimate -1, we're done. */ - goto success; - } - - /* Any other negative number is disallowed. */ - if (result < 0) { - goto underflow; - } - - /* Ensure the value wasn't truncated. */ - if (sizeof(gid_t) < sizeof(long) && - (long)gid != result) - goto underflow; - goto success; - } - - if (overflow < 0) - goto underflow; - - /* - * Okay, the value overflowed a signed long. If it - * fits in an *unsigned* long, it may still be okay, - * as gid_t may be unsigned long on this platform. - */ - uresult = PyLong_AsUnsignedLong(index); - if (PyErr_Occurred()) { - if (PyErr_ExceptionMatches(PyExc_OverflowError)) - goto overflow; - goto fail; - } - - gid = (gid_t)uresult; - - /* - * If gid == (gid_t)-1, the user actually passed in ULONG_MAX, - * but this value would get interpreted as (gid_t)-1 by chown - * and its siblings. That's not what the user meant! So we - * throw an overflow exception instead. (We already - * handled a real -1 with PyLong_AsLongAndOverflow() above.) - */ - if (gid == (gid_t)-1) - goto overflow; - - /* Ensure the value wasn't truncated. */ - if (sizeof(gid_t) < sizeof(long) && - (unsigned long)gid != uresult) - goto overflow; - /* fallthrough */ - -success: - Py_DECREF(index); - *(gid_t *)p = gid; - return 1; - -underflow: - PyErr_SetString(PyExc_OverflowError, - "gid is less than minimum"); - goto fail; - -overflow: - PyErr_SetString(PyExc_OverflowError, - "gid is greater than maximum"); - /* fallthrough */ - -fail: - Py_DECREF(index); - return 0; -} -#endif /* MS_WINDOWS */ - - -#ifdef HAVE_LONG_LONG -# define _PyLong_FromDev PyLong_FromLongLong -#else -# define _PyLong_FromDev PyLong_FromLong -#endif - - -#if defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV) -static int -_Py_Dev_Converter(PyObject *obj, void *p) -{ -#ifdef HAVE_LONG_LONG - *((dev_t *)p) = PyLong_AsUnsignedLongLong(obj); -#else - *((dev_t *)p) = PyLong_AsUnsignedLong(obj); -#endif - if (PyErr_Occurred()) - return 0; - return 1; -} -#endif /* HAVE_MKNOD && HAVE_MAKEDEV */ - - -#ifdef AT_FDCWD -/* - * Why the (int) cast? Solaris 10 defines AT_FDCWD as 0xffd19553 (-3041965); - * without the int cast, the value gets interpreted as uint (4291925331), - * which doesn't play nicely with all the initializer lines in this file that - * look like this: - * int dir_fd = DEFAULT_DIR_FD; - */ -#define DEFAULT_DIR_FD (int)AT_FDCWD -#else -#define DEFAULT_DIR_FD (-100) -#endif - -static int -_fd_converter(PyObject *o, int *p, const char *allowed) -{ - int overflow; - long long_value; - - PyObject *index = PyNumber_Index(o); - if (index == NULL) { - PyErr_Format(PyExc_TypeError, - "argument should be %s, not %.200s", - allowed, Py_TYPE(o)->tp_name); - return 0; - } - - long_value = PyLong_AsLongAndOverflow(index, &overflow); - Py_DECREF(index); - if (overflow > 0 || long_value > INT_MAX) { - PyErr_SetString(PyExc_OverflowError, - "fd is greater than maximum"); - return 0; - } - if (overflow < 0 || long_value < INT_MIN) { - PyErr_SetString(PyExc_OverflowError, - "fd is less than minimum"); - return 0; - } - - *p = (int)long_value; - return 1; -} - -static int -dir_fd_converter(PyObject *o, void *p) -{ - if (o == Py_None) { - *(int *)p = DEFAULT_DIR_FD; - return 1; - } - return _fd_converter(o, (int *)p, "integer"); -} - - -/* - * A PyArg_ParseTuple "converter" function - * that handles filesystem paths in the manner - * preferred by the os module. - * - * path_converter accepts (Unicode) strings and their - * subclasses, and bytes and their subclasses. What - * it does with the argument depends on the platform: - * - * * On Windows, if we get a (Unicode) string we - * extract the wchar_t * and return it; if we get - * bytes we extract the char * and return that. - * - * * On all other platforms, strings are encoded - * to bytes using PyUnicode_FSConverter, then we - * extract the char * from the bytes object and - * return that. - * - * path_converter also optionally accepts signed - * integers (representing open file descriptors) instead - * of path strings. - * - * Input fields: - * path.nullable - * If nonzero, the path is permitted to be None. - * path.allow_fd - * If nonzero, the path is permitted to be a file handle - * (a signed int) instead of a string. - * path.function_name - * If non-NULL, path_converter will use that as the name - * of the function in error messages. - * (If path.function_name is NULL it omits the function name.) - * path.argument_name - * If non-NULL, path_converter will use that as the name - * of the parameter in error messages. - * (If path.argument_name is NULL it uses "path".) - * - * Output fields: - * path.wide - * Points to the path if it was expressed as Unicode - * and was not encoded. (Only used on Windows.) - * path.narrow - * Points to the path if it was expressed as bytes, - * or it was Unicode and was encoded to bytes. - * path.fd - * Contains a file descriptor if path.accept_fd was true - * and the caller provided a signed integer instead of any - * sort of string. - * - * WARNING: if your "path" parameter is optional, and is - * unspecified, path_converter will never get called. - * So if you set allow_fd, you *MUST* initialize path.fd = -1 - * yourself! - * path.length - * The length of the path in characters, if specified as - * a string. - * path.object - * The original object passed in. - * path.cleanup - * For internal use only. May point to a temporary object. - * (Pay no attention to the man behind the curtain.) - * - * At most one of path.wide or path.narrow will be non-NULL. - * If path was None and path.nullable was set, - * or if path was an integer and path.allow_fd was set, - * both path.wide and path.narrow will be NULL - * and path.length will be 0. - * - * path_converter takes care to not write to the path_t - * unless it's successful. However it must reset the - * "cleanup" field each time it's called. - * - * Use as follows: - * path_t path; - * memset(&path, 0, sizeof(path)); - * PyArg_ParseTuple(args, "O&", path_converter, &path); - * // ... use values from path ... - * path_cleanup(&path); - * - * (Note that if PyArg_Parse fails you don't need to call - * path_cleanup(). However it is safe to do so.) - */ -typedef struct { - const char *function_name; - const char *argument_name; - int nullable; - int allow_fd; - wchar_t *wide; - char *narrow; - int fd; - Py_ssize_t length; - PyObject *object; - PyObject *cleanup; -} path_t; - -#define PATH_T_INITIALIZE(function_name, argument_name, nullable, allow_fd) \ - {function_name, argument_name, nullable, allow_fd, NULL, NULL, -1, 0, NULL, NULL} - -static void -path_cleanup(path_t *path) { - if (path->cleanup) { - Py_CLEAR(path->cleanup); - } -} - -static int -path_converter(PyObject *o, void *p) { - path_t *path = (path_t *)p; - PyObject *unicode, *bytes; - Py_ssize_t length; - char *narrow; - -#define FORMAT_EXCEPTION(exc, fmt) \ - PyErr_Format(exc, "%s%s" fmt, \ - path->function_name ? path->function_name : "", \ - path->function_name ? ": " : "", \ - path->argument_name ? path->argument_name : "path") - - /* Py_CLEANUP_SUPPORTED support */ - if (o == NULL) { - path_cleanup(path); - return 1; - } - - /* ensure it's always safe to call path_cleanup() */ - path->cleanup = NULL; - - if (o == Py_None) { - if (!path->nullable) { - FORMAT_EXCEPTION(PyExc_TypeError, - "can't specify None for %s argument"); - return 0; - } - path->wide = NULL; - path->narrow = NULL; - path->length = 0; - path->object = o; - path->fd = -1; - return 1; - } - - unicode = PyUnicode_FromObject(o); - if (unicode) { -#ifdef MS_WINDOWS - wchar_t *wide; - - wide = PyUnicode_AsUnicodeAndSize(unicode, &length); - if (!wide) { - Py_DECREF(unicode); - return 0; - } - if (length > 32767) { - FORMAT_EXCEPTION(PyExc_ValueError, "%s too long for Windows"); - Py_DECREF(unicode); - return 0; - } - - path->wide = wide; - path->narrow = NULL; - path->length = length; - path->object = o; - path->fd = -1; - path->cleanup = unicode; - return Py_CLEANUP_SUPPORTED; -#else - int converted = PyUnicode_FSConverter(unicode, &bytes); - Py_DECREF(unicode); - if (!converted) - bytes = NULL; -#endif - } - else { - PyErr_Clear(); - if (PyObject_CheckBuffer(o)) - bytes = PyBytes_FromObject(o); - else - bytes = NULL; - if (!bytes) { - PyErr_Clear(); - if (path->allow_fd) { - int fd; - int result = _fd_converter(o, &fd, - "string, bytes or integer"); - if (result) { - path->wide = NULL; - path->narrow = NULL; - path->length = 0; - path->object = o; - path->fd = fd; - return result; - } - } - } - } - - if (!bytes) { - if (!PyErr_Occurred()) - FORMAT_EXCEPTION(PyExc_TypeError, "illegal type for %s parameter"); - return 0; - } - -#ifdef MS_WINDOWS - if (win32_warn_bytes_api()) { - Py_DECREF(bytes); - return 0; - } -#endif - - length = PyBytes_GET_SIZE(bytes); -#ifdef MS_WINDOWS - if (length > MAX_PATH-1) { - FORMAT_EXCEPTION(PyExc_ValueError, "%s too long for Windows"); - Py_DECREF(bytes); - return 0; - } -#endif - - narrow = PyBytes_AS_STRING(bytes); - if ((size_t)length != strlen(narrow)) { - FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character in %s"); - Py_DECREF(bytes); - return 0; - } - - path->wide = NULL; - path->narrow = narrow; - path->length = length; - path->object = o; - path->fd = -1; - path->cleanup = bytes; - return Py_CLEANUP_SUPPORTED; -} - -static void -argument_unavailable_error(char *function_name, char *argument_name) { - PyErr_Format(PyExc_NotImplementedError, - "%s%s%s unavailable on this platform", - (function_name != NULL) ? function_name : "", - (function_name != NULL) ? ": ": "", - argument_name); -} - -static int -dir_fd_unavailable(PyObject *o, void *p) -{ - int dir_fd; - if (!dir_fd_converter(o, &dir_fd)) - return 0; - if (dir_fd != DEFAULT_DIR_FD) { - argument_unavailable_error(NULL, "dir_fd"); - return 0; - } - *(int *)p = dir_fd; - return 1; -} - -static int -fd_specified(char *function_name, int fd) { - if (fd == -1) - return 0; - - argument_unavailable_error(function_name, "fd"); - return 1; -} - -static int -follow_symlinks_specified(char *function_name, int follow_symlinks) { - if (follow_symlinks) - return 0; - - argument_unavailable_error(function_name, "follow_symlinks"); - return 1; -} - -static int -path_and_dir_fd_invalid(char *function_name, path_t *path, int dir_fd) { - if (!path->narrow && !path->wide && (dir_fd != DEFAULT_DIR_FD)) { - PyErr_Format(PyExc_ValueError, - "%s: can't specify dir_fd without matching path", - function_name); - return 1; - } - return 0; -} - -static int -dir_fd_and_fd_invalid(char *function_name, int dir_fd, int fd) { - if ((dir_fd != DEFAULT_DIR_FD) && (fd != -1)) { - PyErr_Format(PyExc_ValueError, - "%s: can't specify both dir_fd and fd", - function_name); - return 1; - } - return 0; -} - -static int -fd_and_follow_symlinks_invalid(char *function_name, int fd, - int follow_symlinks) { - if ((fd > 0) && (!follow_symlinks)) { - PyErr_Format(PyExc_ValueError, - "%s: cannot use fd and follow_symlinks together", - function_name); - return 1; - } - return 0; -} - -static int -dir_fd_and_follow_symlinks_invalid(char *function_name, int dir_fd, - int follow_symlinks) { - if ((dir_fd != DEFAULT_DIR_FD) && (!follow_symlinks)) { - PyErr_Format(PyExc_ValueError, - "%s: cannot use dir_fd and follow_symlinks together", - function_name); - return 1; - } - return 0; -} - -#ifdef MS_WINDOWS - typedef PY_LONG_LONG Py_off_t; -#else - typedef off_t Py_off_t; -#endif - -static int -Py_off_t_converter(PyObject *arg, void *addr) -{ -#ifdef HAVE_LARGEFILE_SUPPORT - *((Py_off_t *)addr) = PyLong_AsLongLong(arg); -#else - *((Py_off_t *)addr) = PyLong_AsLong(arg); -#endif - if (PyErr_Occurred()) - return 0; - return 1; -} - -static PyObject * -PyLong_FromPy_off_t(Py_off_t offset) -{ -#ifdef HAVE_LARGEFILE_SUPPORT - return PyLong_FromLongLong(offset); -#else - return PyLong_FromLong(offset); -#endif -} - - -#if defined _MSC_VER && _MSC_VER >= 1400 && _MSC_VER < 1900 -/* Legacy implementation of _PyVerify_fd_dup2 while transitioning to - * MSVC 14.0. This should eventually be removed. (issue23524) - */ -#define IOINFO_L2E 5 -#define IOINFO_ARRAYS 64 -#define IOINFO_ARRAY_ELTS (1 << IOINFO_L2E) -#define _NHANDLE_ (IOINFO_ARRAYS * IOINFO_ARRAY_ELTS) -#define _NO_CONSOLE_FILENO (intptr_t)-2 - -/* the special case of checking dup2. The target fd must be in a sensible range */ -static int -_PyVerify_fd_dup2(int fd1, int fd2) -{ - if (!_PyVerify_fd(fd1)) - return 0; - if (fd2 == _NO_CONSOLE_FILENO) - return 0; - if ((unsigned)fd2 < _NHANDLE_) - return 1; - else - return 0; -} -#else -#define _PyVerify_fd_dup2(fd1, fd2) (_PyVerify_fd(fd1) && (fd2) >= 0) -#endif - -#ifdef MS_WINDOWS - -static int -win32_get_reparse_tag(HANDLE reparse_point_handle, ULONG *reparse_tag) -{ - char target_buffer[MAXIMUM_REPARSE_DATA_BUFFER_SIZE]; - REPARSE_DATA_BUFFER *rdb = (REPARSE_DATA_BUFFER *)target_buffer; - DWORD n_bytes_returned; - - if (0 == DeviceIoControl( - reparse_point_handle, - FSCTL_GET_REPARSE_POINT, - NULL, 0, /* in buffer */ - target_buffer, sizeof(target_buffer), - &n_bytes_returned, - NULL)) /* we're not using OVERLAPPED_IO */ - return FALSE; - - if (reparse_tag) - *reparse_tag = rdb->ReparseTag; - - return TRUE; -} - -#endif /* MS_WINDOWS */ - -/* Return a dictionary corresponding to the POSIX environment table */ -#if defined(WITH_NEXT_FRAMEWORK) || (defined(__APPLE__) && defined(Py_ENABLE_SHARED)) -/* On Darwin/MacOSX a shared library or framework has no access to -** environ directly, we must obtain it with _NSGetEnviron(). See also -** man environ(7). -*/ -#include -static char **environ; -#elif !defined(_MSC_VER) && ( !defined(__WATCOMC__) || defined(__QNX__) ) -extern char **environ; -#endif /* !_MSC_VER */ - -static PyObject * -convertenviron(void) -{ - PyObject *d; -#ifdef MS_WINDOWS - wchar_t **e; -#else - char **e; -#endif - - d = PyDict_New(); - if (d == NULL) - return NULL; -#if defined(WITH_NEXT_FRAMEWORK) || (defined(__APPLE__) && defined(Py_ENABLE_SHARED)) - if (environ == NULL) - environ = *_NSGetEnviron(); -#endif -#ifdef MS_WINDOWS - /* _wenviron must be initialized in this way if the program is started - through main() instead of wmain(). */ - _wgetenv(L""); - if (_wenviron == NULL) - return d; - /* This part ignores errors */ - for (e = _wenviron; *e != NULL; e++) { - PyObject *k; - PyObject *v; - wchar_t *p = wcschr(*e, L'='); - if (p == NULL) - continue; - k = PyUnicode_FromWideChar(*e, (Py_ssize_t)(p-*e)); - if (k == NULL) { - PyErr_Clear(); - continue; - } - v = PyUnicode_FromWideChar(p+1, wcslen(p+1)); - if (v == NULL) { - PyErr_Clear(); - Py_DECREF(k); - continue; - } - if (PyDict_GetItem(d, k) == NULL) { - if (PyDict_SetItem(d, k, v) != 0) - PyErr_Clear(); - } - Py_DECREF(k); - Py_DECREF(v); - } -#else - if (environ == NULL) - return d; - /* This part ignores errors */ - for (e = environ; *e != NULL; e++) { - PyObject *k; - PyObject *v; - char *p = strchr(*e, '='); - if (p == NULL) - continue; - k = PyBytes_FromStringAndSize(*e, (int)(p-*e)); - if (k == NULL) { - PyErr_Clear(); - continue; - } - v = PyBytes_FromStringAndSize(p+1, strlen(p+1)); - if (v == NULL) { - PyErr_Clear(); - Py_DECREF(k); - continue; - } - if (PyDict_GetItem(d, k) == NULL) { - if (PyDict_SetItem(d, k, v) != 0) - PyErr_Clear(); - } - Py_DECREF(k); - Py_DECREF(v); - } -#endif - return d; -} - -/* Set a POSIX-specific error from errno, and return NULL */ - -static PyObject * -posix_error(void) -{ - return PyErr_SetFromErrno(PyExc_OSError); -} - -#ifdef MS_WINDOWS -static PyObject * -win32_error(char* function, const char* filename) -{ - /* XXX We should pass the function name along in the future. - (winreg.c also wants to pass the function name.) - This would however require an additional param to the - Windows error object, which is non-trivial. - */ - errno = GetLastError(); - if (filename) - return PyErr_SetFromWindowsErrWithFilename(errno, filename); - else - return PyErr_SetFromWindowsErr(errno); -} - -static PyObject * -win32_error_object(char* function, PyObject* filename) -{ - /* XXX - see win32_error for comments on 'function' */ - errno = GetLastError(); - if (filename) - return PyErr_SetExcFromWindowsErrWithFilenameObject( - PyExc_OSError, - errno, - filename); - else - return PyErr_SetFromWindowsErr(errno); -} - -#endif /* MS_WINDOWS */ - -static PyObject * -path_error(path_t *path) -{ -#ifdef MS_WINDOWS - return PyErr_SetExcFromWindowsErrWithFilenameObject(PyExc_OSError, - 0, path->object); -#else - return PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path->object); -#endif -} - - -static PyObject * -path_error2(path_t *path, path_t *path2) -{ -#ifdef MS_WINDOWS - return PyErr_SetExcFromWindowsErrWithFilenameObjects(PyExc_OSError, - 0, path->object, path2->object); -#else - return PyErr_SetFromErrnoWithFilenameObjects(PyExc_OSError, - path->object, path2->object); -#endif -} - - -/* POSIX generic methods */ - -static int -fildes_converter(PyObject *o, void *p) -{ - int fd; - int *pointer = (int *)p; - fd = PyObject_AsFileDescriptor(o); - if (fd < 0) - return 0; - if (!_PyVerify_fd(fd)) { - posix_error(); - return 0; - } - *pointer = fd; - return 1; -} - -static PyObject * -posix_fildes_fd(int fd, int (*func)(int)) -{ - int res; - int async_err = 0; - - do { - Py_BEGIN_ALLOW_THREADS - res = (*func)(fd); - Py_END_ALLOW_THREADS - } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); - if (res != 0) - return (!async_err) ? posix_error() : NULL; - Py_RETURN_NONE; -} - - -#ifdef MS_WINDOWS -/* This is a reimplementation of the C library's chdir function, - but one that produces Win32 errors instead of DOS error codes. - chdir is essentially a wrapper around SetCurrentDirectory; however, - it also needs to set "magic" environment variables indicating - the per-drive current directory, which are of the form =: */ -static BOOL __stdcall -win32_chdir(LPCSTR path) -{ - char new_path[MAX_PATH]; - int result; - char env[4] = "=x:"; - - if(!SetCurrentDirectoryA(path)) - return FALSE; - result = GetCurrentDirectoryA(Py_ARRAY_LENGTH(new_path), new_path); - if (!result) - return FALSE; - /* In the ANSI API, there should not be any paths longer - than MAX_PATH-1 (not including the final null character). */ - assert(result < Py_ARRAY_LENGTH(new_path)); - if (strncmp(new_path, "\\\\", 2) == 0 || - strncmp(new_path, "//", 2) == 0) - /* UNC path, nothing to do. */ - return TRUE; - env[1] = new_path[0]; - return SetEnvironmentVariableA(env, new_path); -} - -/* The Unicode version differs from the ANSI version - since the current directory might exceed MAX_PATH characters */ -static BOOL __stdcall -win32_wchdir(LPCWSTR path) -{ - wchar_t _new_path[MAX_PATH], *new_path = _new_path; - int result; - wchar_t env[4] = L"=x:"; - - if(!SetCurrentDirectoryW(path)) - return FALSE; - result = GetCurrentDirectoryW(Py_ARRAY_LENGTH(new_path), new_path); - if (!result) - return FALSE; - if (result > Py_ARRAY_LENGTH(new_path)) { - new_path = PyMem_RawMalloc(result * sizeof(wchar_t)); - if (!new_path) { - SetLastError(ERROR_OUTOFMEMORY); - return FALSE; - } - result = GetCurrentDirectoryW(result, new_path); - if (!result) { - PyMem_RawFree(new_path); - return FALSE; - } - } - if (wcsncmp(new_path, L"\\\\", 2) == 0 || - wcsncmp(new_path, L"//", 2) == 0) - /* UNC path, nothing to do. */ - return TRUE; - env[1] = new_path[0]; - result = SetEnvironmentVariableW(env, new_path); - if (new_path != _new_path) - PyMem_RawFree(new_path); - return result; -} -#endif - -#ifdef MS_WINDOWS -/* The CRT of Windows has a number of flaws wrt. its stat() implementation: - - time stamps are restricted to second resolution - - file modification times suffer from forth-and-back conversions between - UTC and local time - Therefore, we implement our own stat, based on the Win32 API directly. -*/ -#define HAVE_STAT_NSEC 1 -#define HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES 1 - -static BOOL -attributes_from_dir(LPCSTR pszFile, BY_HANDLE_FILE_INFORMATION *info, ULONG *reparse_tag) -{ - HANDLE hFindFile; - WIN32_FIND_DATAA FileData; - hFindFile = FindFirstFileA(pszFile, &FileData); - if (hFindFile == INVALID_HANDLE_VALUE) - return FALSE; - FindClose(hFindFile); - memset(info, 0, sizeof(*info)); - *reparse_tag = 0; - info->dwFileAttributes = FileData.dwFileAttributes; - info->ftCreationTime = FileData.ftCreationTime; - info->ftLastAccessTime = FileData.ftLastAccessTime; - info->ftLastWriteTime = FileData.ftLastWriteTime; - info->nFileSizeHigh = FileData.nFileSizeHigh; - info->nFileSizeLow = FileData.nFileSizeLow; -/* info->nNumberOfLinks = 1; */ - if (FileData.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) - *reparse_tag = FileData.dwReserved0; - return TRUE; -} - -static void -find_data_to_file_info_w(WIN32_FIND_DATAW *pFileData, - BY_HANDLE_FILE_INFORMATION *info, - ULONG *reparse_tag) -{ - memset(info, 0, sizeof(*info)); - info->dwFileAttributes = pFileData->dwFileAttributes; - info->ftCreationTime = pFileData->ftCreationTime; - info->ftLastAccessTime = pFileData->ftLastAccessTime; - info->ftLastWriteTime = pFileData->ftLastWriteTime; - info->nFileSizeHigh = pFileData->nFileSizeHigh; - info->nFileSizeLow = pFileData->nFileSizeLow; -/* info->nNumberOfLinks = 1; */ - if (pFileData->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) - *reparse_tag = pFileData->dwReserved0; - else - *reparse_tag = 0; -} - -static BOOL -attributes_from_dir_w(LPCWSTR pszFile, BY_HANDLE_FILE_INFORMATION *info, ULONG *reparse_tag) -{ - HANDLE hFindFile; - WIN32_FIND_DATAW FileData; - hFindFile = FindFirstFileW(pszFile, &FileData); - if (hFindFile == INVALID_HANDLE_VALUE) - return FALSE; - FindClose(hFindFile); - find_data_to_file_info_w(&FileData, info, reparse_tag); - return TRUE; -} - -static BOOL -get_target_path(HANDLE hdl, wchar_t **target_path) -{ - int buf_size, result_length; - wchar_t *buf; - - /* We have a good handle to the target, use it to determine - the target path name (then we'll call lstat on it). */ - buf_size = GetFinalPathNameByHandleW(hdl, 0, 0, - VOLUME_NAME_DOS); - if(!buf_size) - return FALSE; - - buf = PyMem_New(wchar_t, buf_size+1); - if (!buf) { - SetLastError(ERROR_OUTOFMEMORY); - return FALSE; - } - - result_length = GetFinalPathNameByHandleW(hdl, - buf, buf_size, VOLUME_NAME_DOS); - - if(!result_length) { - PyMem_Free(buf); - return FALSE; - } - - if(!CloseHandle(hdl)) { - PyMem_Free(buf); - return FALSE; - } - - buf[result_length] = 0; - - *target_path = buf; - return TRUE; -} - -static int -win32_xstat_impl_w(const wchar_t *path, struct _Py_stat_struct *result, - BOOL traverse); -static int -win32_xstat_impl(const char *path, struct _Py_stat_struct *result, - BOOL traverse) -{ - int code; - HANDLE hFile, hFile2; - BY_HANDLE_FILE_INFORMATION info; - ULONG reparse_tag = 0; - wchar_t *target_path; - const char *dot; - - hFile = CreateFileA( - path, - FILE_READ_ATTRIBUTES, /* desired access */ - 0, /* share mode */ - NULL, /* security attributes */ - OPEN_EXISTING, - /* FILE_FLAG_BACKUP_SEMANTICS is required to open a directory */ - /* FILE_FLAG_OPEN_REPARSE_POINT does not follow the symlink. - Because of this, calls like GetFinalPathNameByHandle will return - the symlink path again and not the actual final path. */ - FILE_ATTRIBUTE_NORMAL|FILE_FLAG_BACKUP_SEMANTICS| - FILE_FLAG_OPEN_REPARSE_POINT, - NULL); - - if (hFile == INVALID_HANDLE_VALUE) { - /* Either the target doesn't exist, or we don't have access to - get a handle to it. If the former, we need to return an error. - If the latter, we can use attributes_from_dir. */ - if (GetLastError() != ERROR_SHARING_VIOLATION) - return -1; - /* Could not get attributes on open file. Fall back to - reading the directory. */ - if (!attributes_from_dir(path, &info, &reparse_tag)) - /* Very strange. This should not fail now */ - return -1; - if (info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) { - if (traverse) { - /* Should traverse, but could not open reparse point handle */ - SetLastError(ERROR_SHARING_VIOLATION); - return -1; - } - } - } else { - if (!GetFileInformationByHandle(hFile, &info)) { - CloseHandle(hFile); - return -1; - } - if (info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) { - if (!win32_get_reparse_tag(hFile, &reparse_tag)) - return -1; - - /* Close the outer open file handle now that we're about to - reopen it with different flags. */ - if (!CloseHandle(hFile)) - return -1; - - if (traverse) { - /* In order to call GetFinalPathNameByHandle we need to open - the file without the reparse handling flag set. */ - hFile2 = CreateFileA( - path, FILE_READ_ATTRIBUTES, FILE_SHARE_READ, - NULL, OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL|FILE_FLAG_BACKUP_SEMANTICS, - NULL); - if (hFile2 == INVALID_HANDLE_VALUE) - return -1; - - if (!get_target_path(hFile2, &target_path)) - return -1; - - code = win32_xstat_impl_w(target_path, result, FALSE); - PyMem_Free(target_path); - return code; - } - } else - CloseHandle(hFile); - } - _Py_attribute_data_to_stat(&info, reparse_tag, result); - - /* Set S_IEXEC if it is an .exe, .bat, ... */ - dot = strrchr(path, '.'); - if (dot) { - if (stricmp(dot, ".bat") == 0 || stricmp(dot, ".cmd") == 0 || - stricmp(dot, ".exe") == 0 || stricmp(dot, ".com") == 0) - result->st_mode |= 0111; - } - return 0; -} - -static int -win32_xstat_impl_w(const wchar_t *path, struct _Py_stat_struct *result, - BOOL traverse) -{ - int code; - HANDLE hFile, hFile2; - BY_HANDLE_FILE_INFORMATION info; - ULONG reparse_tag = 0; - wchar_t *target_path; - const wchar_t *dot; - - hFile = CreateFileW( - path, - FILE_READ_ATTRIBUTES, /* desired access */ - 0, /* share mode */ - NULL, /* security attributes */ - OPEN_EXISTING, - /* FILE_FLAG_BACKUP_SEMANTICS is required to open a directory */ - /* FILE_FLAG_OPEN_REPARSE_POINT does not follow the symlink. - Because of this, calls like GetFinalPathNameByHandle will return - the symlink path again and not the actual final path. */ - FILE_ATTRIBUTE_NORMAL|FILE_FLAG_BACKUP_SEMANTICS| - FILE_FLAG_OPEN_REPARSE_POINT, - NULL); - - if (hFile == INVALID_HANDLE_VALUE) { - /* Either the target doesn't exist, or we don't have access to - get a handle to it. If the former, we need to return an error. - If the latter, we can use attributes_from_dir. */ - if (GetLastError() != ERROR_SHARING_VIOLATION) - return -1; - /* Could not get attributes on open file. Fall back to - reading the directory. */ - if (!attributes_from_dir_w(path, &info, &reparse_tag)) - /* Very strange. This should not fail now */ - return -1; - if (info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) { - if (traverse) { - /* Should traverse, but could not open reparse point handle */ - SetLastError(ERROR_SHARING_VIOLATION); - return -1; - } - } - } else { - if (!GetFileInformationByHandle(hFile, &info)) { - CloseHandle(hFile); - return -1; - } - if (info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) { - if (!win32_get_reparse_tag(hFile, &reparse_tag)) - return -1; - - /* Close the outer open file handle now that we're about to - reopen it with different flags. */ - if (!CloseHandle(hFile)) - return -1; - - if (traverse) { - /* In order to call GetFinalPathNameByHandle we need to open - the file without the reparse handling flag set. */ - hFile2 = CreateFileW( - path, FILE_READ_ATTRIBUTES, FILE_SHARE_READ, - NULL, OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL|FILE_FLAG_BACKUP_SEMANTICS, - NULL); - if (hFile2 == INVALID_HANDLE_VALUE) - return -1; - - if (!get_target_path(hFile2, &target_path)) - return -1; - - code = win32_xstat_impl_w(target_path, result, FALSE); - PyMem_Free(target_path); - return code; - } - } else - CloseHandle(hFile); - } - _Py_attribute_data_to_stat(&info, reparse_tag, result); - - /* Set S_IEXEC if it is an .exe, .bat, ... */ - dot = wcsrchr(path, '.'); - if (dot) { - if (_wcsicmp(dot, L".bat") == 0 || _wcsicmp(dot, L".cmd") == 0 || - _wcsicmp(dot, L".exe") == 0 || _wcsicmp(dot, L".com") == 0) - result->st_mode |= 0111; - } - return 0; -} - -static int -win32_xstat(const char *path, struct _Py_stat_struct *result, BOOL traverse) -{ - /* Protocol violation: we explicitly clear errno, instead of - setting it to a POSIX error. Callers should use GetLastError. */ - int code = win32_xstat_impl(path, result, traverse); - errno = 0; - return code; -} - -static int -win32_xstat_w(const wchar_t *path, struct _Py_stat_struct *result, BOOL traverse) -{ - /* Protocol violation: we explicitly clear errno, instead of - setting it to a POSIX error. Callers should use GetLastError. */ - int code = win32_xstat_impl_w(path, result, traverse); - errno = 0; - return code; -} -/* About the following functions: win32_lstat_w, win32_stat, win32_stat_w - - In Posix, stat automatically traverses symlinks and returns the stat - structure for the target. In Windows, the equivalent GetFileAttributes by - default does not traverse symlinks and instead returns attributes for - the symlink. - - Therefore, win32_lstat will get the attributes traditionally, and - win32_stat will first explicitly resolve the symlink target and then will - call win32_lstat on that result. - - The _w represent Unicode equivalents of the aforementioned ANSI functions. */ - -static int -win32_lstat(const char* path, struct _Py_stat_struct *result) -{ - return win32_xstat(path, result, FALSE); -} - -static int -win32_lstat_w(const wchar_t* path, struct _Py_stat_struct *result) -{ - return win32_xstat_w(path, result, FALSE); -} - -static int -win32_stat(const char* path, struct _Py_stat_struct *result) -{ - return win32_xstat(path, result, TRUE); -} - -static int -win32_stat_w(const wchar_t* path, struct _Py_stat_struct *result) -{ - return win32_xstat_w(path, result, TRUE); -} - -#endif /* MS_WINDOWS */ - -PyDoc_STRVAR(stat_result__doc__, -"stat_result: Result from stat, fstat, or lstat.\n\n\ -This object may be accessed either as a tuple of\n\ - (mode, ino, dev, nlink, uid, gid, size, atime, mtime, ctime)\n\ -or via the attributes st_mode, st_ino, st_dev, st_nlink, st_uid, and so on.\n\ -\n\ -Posix/windows: If your platform supports st_blksize, st_blocks, st_rdev,\n\ -or st_flags, they are available as attributes only.\n\ -\n\ -See os.stat for more information."); - -static PyStructSequence_Field stat_result_fields[] = { - {"st_mode", "protection bits"}, - {"st_ino", "inode"}, - {"st_dev", "device"}, - {"st_nlink", "number of hard links"}, - {"st_uid", "user ID of owner"}, - {"st_gid", "group ID of owner"}, - {"st_size", "total size, in bytes"}, - /* The NULL is replaced with PyStructSequence_UnnamedField later. */ - {NULL, "integer time of last access"}, - {NULL, "integer time of last modification"}, - {NULL, "integer time of last change"}, - {"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 -#ifdef HAVE_STRUCT_STAT_ST_BLOCKS - {"st_blocks", "number of blocks allocated"}, -#endif -#ifdef HAVE_STRUCT_STAT_ST_RDEV - {"st_rdev", "device type (if inode device)"}, -#endif -#ifdef HAVE_STRUCT_STAT_ST_FLAGS - {"st_flags", "user defined flags for file"}, -#endif -#ifdef HAVE_STRUCT_STAT_ST_GEN - {"st_gen", "generation number"}, -#endif -#ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME - {"st_birthtime", "time of creation"}, -#endif -#ifdef HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES - {"st_file_attributes", "Windows file attribute bits"}, -#endif - {0} -}; - -#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE -#define ST_BLKSIZE_IDX 16 -#else -#define ST_BLKSIZE_IDX 15 -#endif - -#ifdef HAVE_STRUCT_STAT_ST_BLOCKS -#define ST_BLOCKS_IDX (ST_BLKSIZE_IDX+1) -#else -#define ST_BLOCKS_IDX ST_BLKSIZE_IDX -#endif - -#ifdef HAVE_STRUCT_STAT_ST_RDEV -#define ST_RDEV_IDX (ST_BLOCKS_IDX+1) -#else -#define ST_RDEV_IDX ST_BLOCKS_IDX -#endif - -#ifdef HAVE_STRUCT_STAT_ST_FLAGS -#define ST_FLAGS_IDX (ST_RDEV_IDX+1) -#else -#define ST_FLAGS_IDX ST_RDEV_IDX -#endif - -#ifdef HAVE_STRUCT_STAT_ST_GEN -#define ST_GEN_IDX (ST_FLAGS_IDX+1) -#else -#define ST_GEN_IDX ST_FLAGS_IDX -#endif - -#ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME -#define ST_BIRTHTIME_IDX (ST_GEN_IDX+1) -#else -#define ST_BIRTHTIME_IDX ST_GEN_IDX -#endif - -#ifdef HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES -#define ST_FILE_ATTRIBUTES_IDX (ST_BIRTHTIME_IDX+1) -#else -#define ST_FILE_ATTRIBUTES_IDX ST_BIRTHTIME_IDX -#endif - -static PyStructSequence_Desc stat_result_desc = { - "stat_result", /* name */ - stat_result__doc__, /* doc */ - stat_result_fields, - 10 -}; - -PyDoc_STRVAR(statvfs_result__doc__, -"statvfs_result: Result from statvfs or fstatvfs.\n\n\ -This object may be accessed either as a tuple of\n\ - (bsize, frsize, blocks, bfree, bavail, files, ffree, favail, flag, namemax),\n\ -or via the attributes f_bsize, f_frsize, f_blocks, f_bfree, and so on.\n\ -\n\ -See os.statvfs for more information."); - -static PyStructSequence_Field statvfs_result_fields[] = { - {"f_bsize", }, - {"f_frsize", }, - {"f_blocks", }, - {"f_bfree", }, - {"f_bavail", }, - {"f_files", }, - {"f_ffree", }, - {"f_favail", }, - {"f_flag", }, - {"f_namemax",}, - {0} -}; - -static PyStructSequence_Desc statvfs_result_desc = { - "statvfs_result", /* name */ - statvfs_result__doc__, /* doc */ - statvfs_result_fields, - 10 -}; - -#if defined(HAVE_WAITID) && !defined(__APPLE__) -PyDoc_STRVAR(waitid_result__doc__, -"waitid_result: Result from waitid.\n\n\ -This object may be accessed either as a tuple of\n\ - (si_pid, si_uid, si_signo, si_status, si_code),\n\ -or via the attributes si_pid, si_uid, and so on.\n\ -\n\ -See os.waitid for more information."); - -static PyStructSequence_Field waitid_result_fields[] = { - {"si_pid", }, - {"si_uid", }, - {"si_signo", }, - {"si_status", }, - {"si_code", }, - {0} -}; - -static PyStructSequence_Desc waitid_result_desc = { - "waitid_result", /* name */ - waitid_result__doc__, /* doc */ - waitid_result_fields, - 5 -}; -static PyTypeObject WaitidResultType; -#endif - -static int initialized; -static PyTypeObject StatResultType; -static PyTypeObject StatVFSResultType; -#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) -static PyTypeObject SchedParamType; -#endif -static newfunc structseq_new; - -static PyObject * -statresult_new(PyTypeObject *type, PyObject *args, PyObject *kwds) -{ - PyStructSequence *result; - int i; - - result = (PyStructSequence*)structseq_new(type, args, kwds); - if (!result) - return NULL; - /* If we have been initialized from a tuple, - st_?time might be set to None. Initialize it - from the int slots. */ - for (i = 7; i <= 9; i++) { - if (result->ob_item[i+3] == Py_None) { - Py_DECREF(Py_None); - Py_INCREF(result->ob_item[i]); - result->ob_item[i+3] = result->ob_item[i]; - } - } - return (PyObject*)result; -} - - - -/* If true, st_?time is float. */ -static int _stat_float_times = 1; - -PyDoc_STRVAR(stat_float_times__doc__, -"stat_float_times([newval]) -> oldval\n\n\ -Determine whether os.[lf]stat represents time stamps as float objects.\n\ -\n\ -If value is True, future calls to stat() return floats; if it is False,\n\ -future calls return ints.\n\ -If value is omitted, return the current setting.\n"); - -/* AC 3.5: the public default value should be None, not ready for that yet */ -static PyObject* -stat_float_times(PyObject* self, PyObject *args) -{ - int newval = -1; - if (!PyArg_ParseTuple(args, "|i:stat_float_times", &newval)) - return NULL; - if (PyErr_WarnEx(PyExc_DeprecationWarning, - "stat_float_times() is deprecated", - 1)) - return NULL; - if (newval == -1) - /* Return old value */ - return PyBool_FromLong(_stat_float_times); - _stat_float_times = newval; - Py_INCREF(Py_None); - return Py_None; -} - -static PyObject *billion = NULL; - -static void -fill_time(PyObject *v, int index, time_t sec, unsigned long nsec) -{ - 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) { - 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 - (used by posix_stat() and posix_fstat()) */ -static PyObject* -_pystat_fromstructstat(STRUCT_STAT *st) -{ - unsigned long ansec, mnsec, cnsec; - PyObject *v = PyStructSequence_New(&StatResultType); - if (v == NULL) - return NULL; - - PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long)st->st_mode)); -#ifdef HAVE_LARGEFILE_SUPPORT - PyStructSequence_SET_ITEM(v, 1, - PyLong_FromLongLong((PY_LONG_LONG)st->st_ino)); -#else - PyStructSequence_SET_ITEM(v, 1, PyLong_FromLong((long)st->st_ino)); -#endif -#ifdef MS_WINDOWS - PyStructSequence_SET_ITEM(v, 2, PyLong_FromUnsignedLong(st->st_dev)); -#else - PyStructSequence_SET_ITEM(v, 2, _PyLong_FromDev(st->st_dev)); -#endif - PyStructSequence_SET_ITEM(v, 3, PyLong_FromLong((long)st->st_nlink)); -#if defined(MS_WINDOWS) - PyStructSequence_SET_ITEM(v, 4, PyLong_FromLong(0)); - PyStructSequence_SET_ITEM(v, 5, PyLong_FromLong(0)); -#else - PyStructSequence_SET_ITEM(v, 4, _PyLong_FromUid(st->st_uid)); - PyStructSequence_SET_ITEM(v, 5, _PyLong_FromGid(st->st_gid)); -#endif -#ifdef HAVE_LARGEFILE_SUPPORT - PyStructSequence_SET_ITEM(v, 6, - PyLong_FromLongLong((PY_LONG_LONG)st->st_size)); -#else - PyStructSequence_SET_ITEM(v, 6, PyLong_FromLong(st->st_size)); -#endif - -#if defined(HAVE_STAT_TV_NSEC) - ansec = st->st_atim.tv_nsec; - mnsec = st->st_mtim.tv_nsec; - cnsec = st->st_ctim.tv_nsec; -#elif defined(HAVE_STAT_TV_NSEC2) - ansec = st->st_atimespec.tv_nsec; - mnsec = st->st_mtimespec.tv_nsec; - cnsec = st->st_ctimespec.tv_nsec; -#elif defined(HAVE_STAT_NSEC) - ansec = st->st_atime_nsec; - mnsec = st->st_mtime_nsec; - cnsec = st->st_ctime_nsec; -#else - ansec = mnsec = cnsec = 0; -#endif - fill_time(v, 7, st->st_atime, ansec); - fill_time(v, 8, st->st_mtime, mnsec); - fill_time(v, 9, st->st_ctime, cnsec); - -#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE - PyStructSequence_SET_ITEM(v, ST_BLKSIZE_IDX, - PyLong_FromLong((long)st->st_blksize)); -#endif -#ifdef HAVE_STRUCT_STAT_ST_BLOCKS - PyStructSequence_SET_ITEM(v, ST_BLOCKS_IDX, - PyLong_FromLong((long)st->st_blocks)); -#endif -#ifdef HAVE_STRUCT_STAT_ST_RDEV - PyStructSequence_SET_ITEM(v, ST_RDEV_IDX, - PyLong_FromLong((long)st->st_rdev)); -#endif -#ifdef HAVE_STRUCT_STAT_ST_GEN - PyStructSequence_SET_ITEM(v, ST_GEN_IDX, - PyLong_FromLong((long)st->st_gen)); -#endif -#ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME - { - PyObject *val; - unsigned long bsec,bnsec; - bsec = (long)st->st_birthtime; -#ifdef HAVE_STAT_TV_NSEC2 - bnsec = st->st_birthtimespec.tv_nsec; -#else - bnsec = 0; -#endif - if (_stat_float_times) { - val = PyFloat_FromDouble(bsec + 1e-9*bnsec); - } else { - val = PyLong_FromLong((long)bsec); - } - PyStructSequence_SET_ITEM(v, ST_BIRTHTIME_IDX, - val); - } -#endif -#ifdef HAVE_STRUCT_STAT_ST_FLAGS - PyStructSequence_SET_ITEM(v, ST_FLAGS_IDX, - PyLong_FromLong((long)st->st_flags)); -#endif -#ifdef HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES - PyStructSequence_SET_ITEM(v, ST_FILE_ATTRIBUTES_IDX, - PyLong_FromUnsignedLong(st->st_file_attributes)); -#endif - - if (PyErr_Occurred()) { - Py_DECREF(v); - return NULL; - } - - return v; -} - -/* POSIX methods */ - - -static PyObject * -posix_do_stat(char *function_name, path_t *path, - int dir_fd, int follow_symlinks) -{ - STRUCT_STAT st; - int result; - -#if !defined(MS_WINDOWS) && !defined(HAVE_FSTATAT) && !defined(HAVE_LSTAT) - if (follow_symlinks_specified(function_name, follow_symlinks)) - return NULL; -#endif - - if (path_and_dir_fd_invalid("stat", path, dir_fd) || - dir_fd_and_fd_invalid("stat", dir_fd, path->fd) || - fd_and_follow_symlinks_invalid("stat", path->fd, follow_symlinks)) - return NULL; - - Py_BEGIN_ALLOW_THREADS - if (path->fd != -1) - result = FSTAT(path->fd, &st); - else -#ifdef MS_WINDOWS - if (path->wide) { - if (follow_symlinks) - result = win32_stat_w(path->wide, &st); - else - result = win32_lstat_w(path->wide, &st); - } - else -#endif -#if defined(HAVE_LSTAT) || defined(MS_WINDOWS) - if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD)) - result = LSTAT(path->narrow, &st); - else -#endif -#ifdef HAVE_FSTATAT - if ((dir_fd != DEFAULT_DIR_FD) || !follow_symlinks) - result = fstatat(dir_fd, path->narrow, &st, - follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW); - else -#endif - result = STAT(path->narrow, &st); - Py_END_ALLOW_THREADS - - if (result != 0) { - return path_error(path); - } - - return _pystat_fromstructstat(&st); -} - -/*[python input] - -for s in """ - -FACCESSAT -FCHMODAT -FCHOWNAT -FSTATAT -LINKAT -MKDIRAT -MKFIFOAT -MKNODAT -OPENAT -READLINKAT -SYMLINKAT -UNLINKAT - -""".strip().split(): - s = s.strip() - print(""" -#ifdef HAVE_{s} - #define {s}_DIR_FD_CONVERTER dir_fd_converter -#else - #define {s}_DIR_FD_CONVERTER dir_fd_unavailable -#endif -""".rstrip().format(s=s)) - -for s in """ - -FCHDIR -FCHMOD -FCHOWN -FDOPENDIR -FEXECVE -FPATHCONF -FSTATVFS -FTRUNCATE - -""".strip().split(): - s = s.strip() - print(""" -#ifdef HAVE_{s} - #define PATH_HAVE_{s} 1 -#else - #define PATH_HAVE_{s} 0 -#endif - -""".rstrip().format(s=s)) -[python start generated code]*/ - -#ifdef HAVE_FACCESSAT - #define FACCESSAT_DIR_FD_CONVERTER dir_fd_converter -#else - #define FACCESSAT_DIR_FD_CONVERTER dir_fd_unavailable -#endif - -#ifdef HAVE_FCHMODAT - #define FCHMODAT_DIR_FD_CONVERTER dir_fd_converter -#else - #define FCHMODAT_DIR_FD_CONVERTER dir_fd_unavailable -#endif - -#ifdef HAVE_FCHOWNAT - #define FCHOWNAT_DIR_FD_CONVERTER dir_fd_converter -#else - #define FCHOWNAT_DIR_FD_CONVERTER dir_fd_unavailable -#endif - -#ifdef HAVE_FSTATAT - #define FSTATAT_DIR_FD_CONVERTER dir_fd_converter -#else - #define FSTATAT_DIR_FD_CONVERTER dir_fd_unavailable -#endif - -#ifdef HAVE_LINKAT - #define LINKAT_DIR_FD_CONVERTER dir_fd_converter -#else - #define LINKAT_DIR_FD_CONVERTER dir_fd_unavailable -#endif - -#ifdef HAVE_MKDIRAT - #define MKDIRAT_DIR_FD_CONVERTER dir_fd_converter -#else - #define MKDIRAT_DIR_FD_CONVERTER dir_fd_unavailable -#endif - -#ifdef HAVE_MKFIFOAT - #define MKFIFOAT_DIR_FD_CONVERTER dir_fd_converter -#else - #define MKFIFOAT_DIR_FD_CONVERTER dir_fd_unavailable -#endif - -#ifdef HAVE_MKNODAT - #define MKNODAT_DIR_FD_CONVERTER dir_fd_converter -#else - #define MKNODAT_DIR_FD_CONVERTER dir_fd_unavailable -#endif - -#ifdef HAVE_OPENAT - #define OPENAT_DIR_FD_CONVERTER dir_fd_converter -#else - #define OPENAT_DIR_FD_CONVERTER dir_fd_unavailable -#endif - -#ifdef HAVE_READLINKAT - #define READLINKAT_DIR_FD_CONVERTER dir_fd_converter -#else - #define READLINKAT_DIR_FD_CONVERTER dir_fd_unavailable -#endif - -#ifdef HAVE_SYMLINKAT - #define SYMLINKAT_DIR_FD_CONVERTER dir_fd_converter -#else - #define SYMLINKAT_DIR_FD_CONVERTER dir_fd_unavailable -#endif - -#ifdef HAVE_UNLINKAT - #define UNLINKAT_DIR_FD_CONVERTER dir_fd_converter -#else - #define UNLINKAT_DIR_FD_CONVERTER dir_fd_unavailable -#endif - -#ifdef HAVE_FCHDIR - #define PATH_HAVE_FCHDIR 1 -#else - #define PATH_HAVE_FCHDIR 0 -#endif - -#ifdef HAVE_FCHMOD - #define PATH_HAVE_FCHMOD 1 -#else - #define PATH_HAVE_FCHMOD 0 -#endif - -#ifdef HAVE_FCHOWN - #define PATH_HAVE_FCHOWN 1 -#else - #define PATH_HAVE_FCHOWN 0 -#endif - -#ifdef HAVE_FDOPENDIR - #define PATH_HAVE_FDOPENDIR 1 -#else - #define PATH_HAVE_FDOPENDIR 0 -#endif - -#ifdef HAVE_FEXECVE - #define PATH_HAVE_FEXECVE 1 -#else - #define PATH_HAVE_FEXECVE 0 -#endif - -#ifdef HAVE_FPATHCONF - #define PATH_HAVE_FPATHCONF 1 -#else - #define PATH_HAVE_FPATHCONF 0 -#endif - -#ifdef HAVE_FSTATVFS - #define PATH_HAVE_FSTATVFS 1 -#else - #define PATH_HAVE_FSTATVFS 0 -#endif - -#ifdef HAVE_FTRUNCATE - #define PATH_HAVE_FTRUNCATE 1 -#else - #define PATH_HAVE_FTRUNCATE 0 -#endif -/*[python end generated code: output=4bd4f6f7d41267f1 input=80b4c890b6774ea5]*/ - - -/*[python input] - -class path_t_converter(CConverter): - - type = "path_t" - impl_by_reference = True - parse_by_reference = True - - converter = 'path_converter' - - def converter_init(self, *, allow_fd=False, nullable=False): - # right now path_t doesn't support default values. - # to support a default value, you'll need to override initialize(). - if self.default not in (unspecified, None): - fail("Can't specify a default to the path_t converter!") - - if self.c_default not in (None, 'Py_None'): - raise RuntimeError("Can't specify a c_default to the path_t converter!") - - self.nullable = nullable - self.allow_fd = allow_fd - - def pre_render(self): - def strify(value): - if isinstance(value, str): - return value - return str(int(bool(value))) - - # add self.py_name here when merging with posixmodule conversion - self.c_default = 'PATH_T_INITIALIZE("{}", "{}", {}, {})'.format( - self.function.name, - self.name, - strify(self.nullable), - strify(self.allow_fd), - ) - - def cleanup(self): - return "path_cleanup(&" + self.name + ");\n" - - -class dir_fd_converter(CConverter): - type = 'int' - - def converter_init(self, requires=None): - if self.default in (unspecified, None): - self.c_default = 'DEFAULT_DIR_FD' - if isinstance(requires, str): - self.converter = requires.upper() + '_DIR_FD_CONVERTER' - else: - self.converter = 'dir_fd_converter' - -class fildes_converter(CConverter): - type = 'int' - converter = 'fildes_converter' - -class uid_t_converter(CConverter): - type = "uid_t" - converter = '_Py_Uid_Converter' - -class gid_t_converter(CConverter): - type = "gid_t" - converter = '_Py_Gid_Converter' - -class dev_t_converter(CConverter): - type = 'dev_t' - converter = '_Py_Dev_Converter' - -class dev_t_return_converter(unsigned_long_return_converter): - type = 'dev_t' - conversion_fn = '_PyLong_FromDev' - unsigned_cast = '(dev_t)' - -class FSConverter_converter(CConverter): - type = 'PyObject *' - converter = 'PyUnicode_FSConverter' - def converter_init(self): - if self.default is not unspecified: - fail("FSConverter_converter does not support default values") - self.c_default = 'NULL' - - def cleanup(self): - return "Py_XDECREF(" + self.name + ");\n" - -class pid_t_converter(CConverter): - type = 'pid_t' - format_unit = '" _Py_PARSE_PID "' - -class idtype_t_converter(int_converter): - type = 'idtype_t' - -class id_t_converter(CConverter): - type = 'id_t' - format_unit = '" _Py_PARSE_PID "' - -class Py_intptr_t_converter(CConverter): - type = 'Py_intptr_t' - format_unit = '" _Py_PARSE_INTPTR "' - -class Py_off_t_converter(CConverter): - type = 'Py_off_t' - converter = 'Py_off_t_converter' - -class Py_off_t_return_converter(long_return_converter): - type = 'Py_off_t' - conversion_fn = 'PyLong_FromPy_off_t' - -class path_confname_converter(CConverter): - type="int" - converter="conv_path_confname" - -class confstr_confname_converter(path_confname_converter): - converter='conv_confstr_confname' - -class sysconf_confname_converter(path_confname_converter): - converter="conv_sysconf_confname" - -class sched_param_converter(CConverter): - type = 'struct sched_param' - converter = 'convert_sched_param' - impl_by_reference = True; - -[python start generated code]*/ -/*[python end generated code: output=da39a3ee5e6b4b0d input=affe68316f160401]*/ - -/*[clinic input] - -os.stat - - path : path_t(allow_fd=True) - Path to be examined; can be string, bytes, or open-file-descriptor int. - - * - - dir_fd : dir_fd(requires='fstatat') = None - If not None, it should be a file descriptor open to a directory, - and path should be a relative string; path will then be relative to - that directory. - - follow_symlinks: bool = True - If False, and the last element of the path is a symbolic link, - stat will examine the symbolic link itself instead of the file - the link points to. - -Perform a stat system call on the given path. - -dir_fd and follow_symlinks may not be implemented - on your platform. If they are unavailable, using them will raise a - NotImplementedError. - -It's an error to use dir_fd or follow_symlinks when specifying path as - an open file descriptor. - +preserve [clinic start generated code]*/ PyDoc_STRVAR(os_stat__doc__, @@ -2522,29 +54,6 @@ return return_value; } -static PyObject * -os_stat_impl(PyModuleDef *module, path_t *path, int dir_fd, int follow_symlinks) -/*[clinic end generated code: output=0e9f9508fa0c0607 input=099d356c306fa24a]*/ -{ - return posix_do_stat("stat", path, dir_fd, follow_symlinks); -} - - -/*[clinic input] -os.lstat - - path : path_t - - * - - dir_fd : dir_fd(requires='fstatat') = None - -Perform a stat system call on the given path, without following symbolic links. - -Like stat(), but do not follow symbolic links. -Equivalent to stat(path, follow_symlinks=False). -[clinic start generated code]*/ - PyDoc_STRVAR(os_lstat__doc__, "lstat($module, /, path, *, dir_fd=None)\n" "--\n" @@ -2581,54 +90,6 @@ return return_value; } -static PyObject * -os_lstat_impl(PyModuleDef *module, path_t *path, int dir_fd) -/*[clinic end generated code: output=85702247224a2b1c input=0b7474765927b925]*/ -{ - int follow_symlinks = 0; - return posix_do_stat("lstat", path, dir_fd, follow_symlinks); -} - - -/*[clinic input] -os.access -> bool - - path: path_t(allow_fd=True) - Path to be tested; can be string, bytes, or open-file-descriptor int. - - mode: int - Operating-system mode bitfield. Can be F_OK to test existence, - or the inclusive-OR of R_OK, W_OK, and X_OK. - - * - - dir_fd : dir_fd(requires='faccessat') = None - If not None, it should be a file descriptor open to a directory, - and path should be relative; path will then be relative to that - directory. - - effective_ids: bool = False - If True, access will use the effective uid/gid instead of - the real uid/gid. - - follow_symlinks: bool = True - If False, and the last element of the path is a symbolic link, - access will examine the symbolic link itself instead of the file - the link points to. - -Use the real uid/gid to test for access to a path. - -{parameters} -dir_fd, effective_ids, and follow_symlinks may not be implemented - on your platform. If they are unavailable, using them will raise a - NotImplementedError. - -Note that most operations will use the effective uid/gid, therefore this - routine can be used in a suid/sgid environment to test if the invoking user - has the specified access to the path. - -[clinic start generated code]*/ - PyDoc_STRVAR(os_access__doc__, "access($module, /, path, mode, *, dir_fd=None, effective_ids=False,\n" " follow_symlinks=True)\n" @@ -2695,97 +156,7 @@ return return_value; } -static int -os_access_impl(PyModuleDef *module, path_t *path, int mode, int dir_fd, int effective_ids, int follow_symlinks) -/*[clinic end generated code: output=dfd404666906f012 input=b75a756797af45ec]*/ -{ - int return_value; - -#ifdef MS_WINDOWS - DWORD attr; -#else - int result; -#endif - -#ifndef HAVE_FACCESSAT - if (follow_symlinks_specified("access", follow_symlinks)) - return -1; - - if (effective_ids) { - argument_unavailable_error("access", "effective_ids"); - return -1; - } -#endif - -#ifdef MS_WINDOWS - Py_BEGIN_ALLOW_THREADS - if (path->wide != NULL) - attr = GetFileAttributesW(path->wide); - else - attr = GetFileAttributesA(path->narrow); - Py_END_ALLOW_THREADS - - /* - * Access is possible if - * * we didn't get a -1, and - * * write access wasn't requested, - * * or the file isn't read-only, - * * or it's a directory. - * (Directories cannot be read-only on Windows.) - */ - return_value = (attr != INVALID_FILE_ATTRIBUTES) && - (!(mode & 2) || - !(attr & FILE_ATTRIBUTE_READONLY) || - (attr & FILE_ATTRIBUTE_DIRECTORY)); -#else - - Py_BEGIN_ALLOW_THREADS -#ifdef HAVE_FACCESSAT - if ((dir_fd != DEFAULT_DIR_FD) || - effective_ids || - !follow_symlinks) { - int flags = 0; - if (!follow_symlinks) - flags |= AT_SYMLINK_NOFOLLOW; - if (effective_ids) - flags |= AT_EACCESS; - result = faccessat(dir_fd, path->narrow, mode, flags); - } - else -#endif - result = access(path->narrow, mode); - Py_END_ALLOW_THREADS - return_value = !result; -#endif - - return return_value; -} - -#ifndef F_OK -#define F_OK 0 -#endif -#ifndef R_OK -#define R_OK 4 -#endif -#ifndef W_OK -#define W_OK 2 -#endif -#ifndef X_OK -#define X_OK 1 -#endif - - -#ifdef HAVE_TTYNAME -/*[clinic input] -os.ttyname -> DecodeFSDefault - - fd: int - Integer file descriptor handle. - - / - -Return the name of the terminal device connected to 'fd'. -[clinic start generated code]*/ +#if defined(HAVE_TTYNAME) PyDoc_STRVAR(os_ttyname__doc__, "ttyname($module, fd, /)\n" @@ -2822,25 +193,9 @@ return return_value; } -static char * -os_ttyname_impl(PyModuleDef *module, int fd) -/*[clinic end generated code: output=cee7bc4cffec01a2 input=5f72ca83e76b3b45]*/ -{ - char *ret; - - ret = ttyname(fd); - if (ret == NULL) - posix_error(); - return ret; -} -#endif - -#ifdef HAVE_CTERMID -/*[clinic input] -os.ctermid - -Return the name of the controlling terminal for this process. -[clinic start generated code]*/ +#endif /* defined(HAVE_TTYNAME) */ + +#if defined(HAVE_CTERMID) PyDoc_STRVAR(os_ctermid__doc__, "ctermid($module, /)\n" @@ -2860,36 +215,7 @@ return os_ctermid_impl(module); } -static PyObject * -os_ctermid_impl(PyModuleDef *module) -/*[clinic end generated code: output=277bf7964ec2d782 input=3b87fdd52556382d]*/ -{ - char *ret; - char buffer[L_ctermid]; - -#ifdef USE_CTERMID_R - ret = ctermid_r(buffer); -#else - ret = ctermid(buffer); -#endif - if (ret == NULL) - return posix_error(); - return PyUnicode_DecodeFSDefault(buffer); -} -#endif /* HAVE_CTERMID */ - - -/*[clinic input] -os.chdir - - path: path_t(allow_fd='PATH_HAVE_FCHDIR') - -Change the current working directory to the specified path. - -path may always be specified as a string. -On some platforms, path may also be specified as an open file descriptor. - If this functionality is unavailable, using it raises an exception. -[clinic start generated code]*/ +#endif /* defined(HAVE_CTERMID) */ PyDoc_STRVAR(os_chdir__doc__, "chdir($module, /, path)\n" @@ -2927,49 +253,7 @@ return return_value; } -static PyObject * -os_chdir_impl(PyModuleDef *module, path_t *path) -/*[clinic end generated code: output=cc07592dd23ca9e0 input=1a4a15b4d12cb15d]*/ -{ - int result; - - Py_BEGIN_ALLOW_THREADS -#ifdef MS_WINDOWS - if (path->wide) - result = win32_wchdir(path->wide); - else - result = win32_chdir(path->narrow); - result = !result; /* on unix, success = 0, on windows, success = !0 */ -#else -#ifdef HAVE_FCHDIR - if (path->fd != -1) - result = fchdir(path->fd); - else -#endif - result = chdir(path->narrow); -#endif - Py_END_ALLOW_THREADS - - if (result) { - return path_error(path); - } - - Py_RETURN_NONE; -} - - -#ifdef HAVE_FCHDIR -/*[clinic input] -os.fchdir - - fd: fildes - -Change to the directory of the given file descriptor. - -fd must be opened on a directory, not a file. -Equivalent to os.chdir(fd). - -[clinic start generated code]*/ +#if defined(HAVE_FCHDIR) PyDoc_STRVAR(os_fchdir__doc__, "fchdir($module, /, fd)\n" @@ -3003,46 +287,7 @@ return return_value; } -static PyObject * -os_fchdir_impl(PyModuleDef *module, int fd) -/*[clinic end generated code: output=9f6dbc89b2778834 input=18e816479a2fa985]*/ -{ - return posix_fildes_fd(fd, fchdir); -} -#endif /* HAVE_FCHDIR */ - - -/*[clinic input] -os.chmod - - path: path_t(allow_fd='PATH_HAVE_FCHMOD') - Path to be modified. May always be specified as a str or bytes. - On some platforms, path may also be specified as an open file descriptor. - If this functionality is unavailable, using it raises an exception. - - mode: int - Operating-system mode bitfield. - - * - - dir_fd : dir_fd(requires='fchmodat') = None - If not None, it should be a file descriptor open to a directory, - and path should be relative; path will then be relative to that - directory. - - follow_symlinks: bool = True - If False, and the last element of the path is a symbolic link, - chmod will modify the symbolic link itself instead of the file - the link points to. - -Change the access permissions of a file. - -It is an error to use dir_fd or follow_symlinks when specifying path as - an open file descriptor. -dir_fd and follow_symlinks may not be implemented on your platform. - If they are unavailable, using them will raise a NotImplementedError. - -[clinic start generated code]*/ +#endif /* defined(HAVE_FCHDIR) */ PyDoc_STRVAR(os_chmod__doc__, "chmod($module, /, path, mode, *, dir_fd=None, follow_symlinks=True)\n" @@ -3099,118 +344,7 @@ return return_value; } -static PyObject * -os_chmod_impl(PyModuleDef *module, path_t *path, int mode, int dir_fd, int follow_symlinks) -/*[clinic end generated code: output=1e9db031aea46422 input=7f1618e5e15cc196]*/ -{ - int result; - -#ifdef MS_WINDOWS - DWORD attr; -#endif - -#ifdef HAVE_FCHMODAT - int fchmodat_nofollow_unsupported = 0; -#endif - -#if !(defined(HAVE_FCHMODAT) || defined(HAVE_LCHMOD)) - if (follow_symlinks_specified("chmod", follow_symlinks)) - return NULL; -#endif - -#ifdef MS_WINDOWS - Py_BEGIN_ALLOW_THREADS - if (path->wide) - attr = GetFileAttributesW(path->wide); - else - attr = GetFileAttributesA(path->narrow); - if (attr == INVALID_FILE_ATTRIBUTES) - result = 0; - else { - if (mode & _S_IWRITE) - attr &= ~FILE_ATTRIBUTE_READONLY; - else - attr |= FILE_ATTRIBUTE_READONLY; - if (path->wide) - result = SetFileAttributesW(path->wide, attr); - else - result = SetFileAttributesA(path->narrow, attr); - } - Py_END_ALLOW_THREADS - - if (!result) { - return path_error(path); - } -#else /* MS_WINDOWS */ - Py_BEGIN_ALLOW_THREADS -#ifdef HAVE_FCHMOD - if (path->fd != -1) - result = fchmod(path->fd, mode); - else -#endif -#ifdef HAVE_LCHMOD - if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD)) - result = lchmod(path->narrow, mode); - else -#endif -#ifdef HAVE_FCHMODAT - if ((dir_fd != DEFAULT_DIR_FD) || !follow_symlinks) { - /* - * fchmodat() doesn't currently support AT_SYMLINK_NOFOLLOW! - * The documentation specifically shows how to use it, - * and then says it isn't implemented yet. - * (true on linux with glibc 2.15, and openindiana 3.x) - * - * Once it is supported, os.chmod will automatically - * support dir_fd and follow_symlinks=False. (Hopefully.) - * Until then, we need to be careful what exception we raise. - */ - result = fchmodat(dir_fd, path->narrow, mode, - follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW); - /* - * But wait! We can't throw the exception without allowing threads, - * and we can't do that in this nested scope. (Macro trickery, sigh.) - */ - fchmodat_nofollow_unsupported = - result && - ((errno == ENOTSUP) || (errno == EOPNOTSUPP)) && - !follow_symlinks; - } - else -#endif - result = chmod(path->narrow, mode); - Py_END_ALLOW_THREADS - - if (result) { -#ifdef HAVE_FCHMODAT - if (fchmodat_nofollow_unsupported) { - if (dir_fd != DEFAULT_DIR_FD) - dir_fd_and_follow_symlinks_invalid("chmod", - dir_fd, follow_symlinks); - else - follow_symlinks_specified("chmod", follow_symlinks); - } - else -#endif - return path_error(path); - } -#endif - - Py_RETURN_NONE; -} - - -#ifdef HAVE_FCHMOD -/*[clinic input] -os.fchmod - - fd: int - mode: int - -Change the access permissions of the file given by file descriptor fd. - -Equivalent to os.chmod(fd, mode). -[clinic start generated code]*/ +#if defined(HAVE_FCHMOD) PyDoc_STRVAR(os_fchmod__doc__, "fchmod($module, /, fd, mode)\n" @@ -3244,38 +378,9 @@ return return_value; } -static PyObject * -os_fchmod_impl(PyModuleDef *module, int fd, int mode) -/*[clinic end generated code: output=3c19fbfd724a8e0f input=8ab11975ca01ee5b]*/ -{ - int res; - int async_err = 0; - - do { - Py_BEGIN_ALLOW_THREADS - res = fchmod(fd, mode); - Py_END_ALLOW_THREADS - } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); - if (res != 0) - return (!async_err) ? posix_error() : NULL; - - Py_RETURN_NONE; -} -#endif /* HAVE_FCHMOD */ - - -#ifdef HAVE_LCHMOD -/*[clinic input] -os.lchmod - - path: path_t - mode: int - -Change the access permissions of a file, without following symbolic links. - -If path is a symlink, this affects the link itself rather than the target. -Equivalent to chmod(path, mode, follow_symlinks=False)." -[clinic start generated code]*/ +#endif /* defined(HAVE_FCHMOD) */ + +#if defined(HAVE_LCHMOD) PyDoc_STRVAR(os_lchmod__doc__, "lchmod($module, /, path, mode)\n" @@ -3313,40 +418,9 @@ return return_value; } -static PyObject * -os_lchmod_impl(PyModuleDef *module, path_t *path, int mode) -/*[clinic end generated code: output=2849977d65f8c68c input=90c5663c7465d24f]*/ -{ - int res; - Py_BEGIN_ALLOW_THREADS - res = lchmod(path->narrow, mode); - Py_END_ALLOW_THREADS - if (res < 0) { - path_error(path); - return NULL; - } - Py_RETURN_NONE; -} -#endif /* HAVE_LCHMOD */ - - -#ifdef HAVE_CHFLAGS -/*[clinic input] -os.chflags - - path: path_t - flags: unsigned_long(bitwise=True) - follow_symlinks: bool=True - -Set file flags. - -If follow_symlinks is False, and the last element of the path is a symbolic - link, chflags will change flags on the symbolic link itself instead of the - file the link points to. -follow_symlinks may not be implemented on your platform. If it is -unavailable, using it will raise a NotImplementedError. - -[clinic start generated code]*/ +#endif /* defined(HAVE_LCHMOD) */ + +#if defined(HAVE_CHFLAGS) PyDoc_STRVAR(os_chflags__doc__, "chflags($module, /, path, flags, follow_symlinks=True)\n" @@ -3388,46 +462,9 @@ return return_value; } -static PyObject * -os_chflags_impl(PyModuleDef *module, path_t *path, unsigned long flags, int follow_symlinks) -/*[clinic end generated code: output=2767927bf071e3cf input=0327e29feb876236]*/ -{ - int result; - -#ifndef HAVE_LCHFLAGS - if (follow_symlinks_specified("chflags", follow_symlinks)) - return NULL; -#endif - - Py_BEGIN_ALLOW_THREADS -#ifdef HAVE_LCHFLAGS - if (!follow_symlinks) - result = lchflags(path->narrow, flags); - else -#endif - result = chflags(path->narrow, flags); - Py_END_ALLOW_THREADS - - if (result) - return path_error(path); - - Py_RETURN_NONE; -} -#endif /* HAVE_CHFLAGS */ - - -#ifdef HAVE_LCHFLAGS -/*[clinic input] -os.lchflags - - path: path_t - flags: unsigned_long(bitwise=True) - -Set file flags. - -This function will not follow symbolic links. -Equivalent to chflags(path, flags, follow_symlinks=False). -[clinic start generated code]*/ +#endif /* defined(HAVE_CHFLAGS) */ + +#if defined(HAVE_LCHFLAGS) PyDoc_STRVAR(os_lchflags__doc__, "lchflags($module, /, path, flags)\n" @@ -3465,30 +502,9 @@ return return_value; } -static PyObject * -os_lchflags_impl(PyModuleDef *module, path_t *path, unsigned long flags) -/*[clinic end generated code: output=bb93b6b8a5e45aa7 input=f9f82ea8b585ca9d]*/ -{ - int res; - Py_BEGIN_ALLOW_THREADS - res = lchflags(path->narrow, flags); - Py_END_ALLOW_THREADS - if (res < 0) { - return path_error(path); - } - Py_RETURN_NONE; -} -#endif /* HAVE_LCHFLAGS */ - - -#ifdef HAVE_CHROOT -/*[clinic input] -os.chroot - path: path_t - -Change root directory to path. - -[clinic start generated code]*/ +#endif /* defined(HAVE_LCHFLAGS) */ + +#if defined(HAVE_CHROOT) PyDoc_STRVAR(os_chroot__doc__, "chroot($module, /, path)\n" @@ -3522,29 +538,9 @@ return return_value; } -static PyObject * -os_chroot_impl(PyModuleDef *module, path_t *path) -/*[clinic end generated code: output=15b1256cbe4f24a1 input=14822965652c3dc3]*/ -{ - int res; - Py_BEGIN_ALLOW_THREADS - res = chroot(path->narrow); - Py_END_ALLOW_THREADS - if (res < 0) - return path_error(path); - Py_RETURN_NONE; -} -#endif /* HAVE_CHROOT */ - - -#ifdef HAVE_FSYNC -/*[clinic input] -os.fsync - - fd: fildes - -Force write of fd to disk. -[clinic start generated code]*/ +#endif /* defined(HAVE_CHROOT) */ + +#if defined(HAVE_FSYNC) PyDoc_STRVAR(os_fsync__doc__, "fsync($module, /, fd)\n" @@ -3575,21 +571,9 @@ return return_value; } -static PyObject * -os_fsync_impl(PyModuleDef *module, int fd) -/*[clinic end generated code: output=59f32d3a0b360133 input=21c3645c056967f2]*/ -{ - return posix_fildes_fd(fd, fsync); -} -#endif /* HAVE_FSYNC */ - - -#ifdef HAVE_SYNC -/*[clinic input] -os.sync - -Force write of everything to disk. -[clinic start generated code]*/ +#endif /* defined(HAVE_FSYNC) */ + +#if defined(HAVE_SYNC) PyDoc_STRVAR(os_sync__doc__, "sync($module, /)\n" @@ -3609,30 +593,9 @@ return os_sync_impl(module); } -static PyObject * -os_sync_impl(PyModuleDef *module) -/*[clinic end generated code: output=526c495683d0bb38 input=84749fe5e9b404ff]*/ -{ - Py_BEGIN_ALLOW_THREADS - sync(); - Py_END_ALLOW_THREADS - Py_RETURN_NONE; -} -#endif /* HAVE_SYNC */ - - -#ifdef HAVE_FDATASYNC -#ifdef __hpux -extern int fdatasync(int); /* On HP-UX, in libc but not in unistd.h */ -#endif - -/*[clinic input] -os.fdatasync - - fd: fildes - -Force write of fd to disk without forcing update of metadata. -[clinic start generated code]*/ +#endif /* defined(HAVE_SYNC) */ + +#if defined(HAVE_FDATASYNC) PyDoc_STRVAR(os_fdatasync__doc__, "fdatasync($module, /, fd)\n" @@ -3663,54 +626,9 @@ return return_value; } -static PyObject * -os_fdatasync_impl(PyModuleDef *module, int fd) -/*[clinic end generated code: output=2335fdfd37c92180 input=bc74791ee54dd291]*/ -{ - return posix_fildes_fd(fd, fdatasync); -} -#endif /* HAVE_FDATASYNC */ - - -#ifdef HAVE_CHOWN -/*[clinic input] -os.chown - - path : path_t(allow_fd='PATH_HAVE_FCHOWN') - Path to be examined; can be string, bytes, or open-file-descriptor int. - - uid: uid_t - - gid: gid_t - - * - - dir_fd : dir_fd(requires='fchownat') = None - If not None, it should be a file descriptor open to a directory, - and path should be relative; path will then be relative to that - directory. - - follow_symlinks: bool = True - If False, and the last element of the path is a symbolic link, - stat will examine the symbolic link itself instead of the file - the link points to. - -Change the owner and group id of path to the numeric uid and gid.\ - -path may always be specified as a string. -On some platforms, path may also be specified as an open file descriptor. - If this functionality is unavailable, using it raises an exception. -If dir_fd is not None, it should be a file descriptor open to a directory, - and path should be relative; path will then be relative to that directory. -If follow_symlinks is False, and the last element of the path is a symbolic - link, chown will modify the symbolic link itself instead of the file the - link points to. -It is an error to use dir_fd or follow_symlinks when specifying path as - an open file descriptor. -dir_fd and follow_symlinks may not be implemented on your platform. - If they are unavailable, using them will raise a NotImplementedError. - -[clinic start generated code]*/ +#endif /* defined(HAVE_FDATASYNC) */ + +#if defined(HAVE_CHOWN) PyDoc_STRVAR(os_chown__doc__, "chown($module, /, path, uid, gid, *, dir_fd=None, follow_symlinks=True)\n" @@ -3772,74 +690,9 @@ return return_value; } -static PyObject * -os_chown_impl(PyModuleDef *module, path_t *path, uid_t uid, gid_t gid, int dir_fd, int follow_symlinks) -/*[clinic end generated code: output=22f011e3b4f9ff49 input=a61cc35574814d5d]*/ -{ - int result; - -#if !(defined(HAVE_LCHOWN) || defined(HAVE_FCHOWNAT)) - if (follow_symlinks_specified("chown", follow_symlinks)) - return NULL; -#endif - if (dir_fd_and_fd_invalid("chown", dir_fd, path->fd) || - fd_and_follow_symlinks_invalid("chown", path->fd, follow_symlinks)) - return NULL; - -#ifdef __APPLE__ - /* - * This is for Mac OS X 10.3, which doesn't have lchown. - * (But we still have an lchown symbol because of weak-linking.) - * It doesn't have fchownat either. So there's no possibility - * of a graceful failover. - */ - if ((!follow_symlinks) && (lchown == NULL)) { - follow_symlinks_specified("chown", follow_symlinks); - return NULL; - } -#endif - - Py_BEGIN_ALLOW_THREADS -#ifdef HAVE_FCHOWN - if (path->fd != -1) - result = fchown(path->fd, uid, gid); - else -#endif -#ifdef HAVE_LCHOWN - if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD)) - result = lchown(path->narrow, uid, gid); - else -#endif -#ifdef HAVE_FCHOWNAT - if ((dir_fd != DEFAULT_DIR_FD) || (!follow_symlinks)) - result = fchownat(dir_fd, path->narrow, uid, gid, - follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW); - else -#endif - result = chown(path->narrow, uid, gid); - Py_END_ALLOW_THREADS - - if (result) - return path_error(path); - - Py_RETURN_NONE; -} -#endif /* HAVE_CHOWN */ - - -#ifdef HAVE_FCHOWN -/*[clinic input] -os.fchown - - fd: int - uid: uid_t - gid: gid_t - -Change the owner and group id of the file specified by file descriptor. - -Equivalent to os.chown(fd, uid, gid). - -[clinic start generated code]*/ +#endif /* defined(HAVE_CHOWN) */ + +#if defined(HAVE_FCHOWN) PyDoc_STRVAR(os_fchown__doc__, "fchown($module, /, fd, uid, gid)\n" @@ -3874,39 +727,9 @@ return return_value; } -static PyObject * -os_fchown_impl(PyModuleDef *module, int fd, uid_t uid, gid_t gid) -/*[clinic end generated code: output=687781cb7d8974d6 input=3af544ba1b13a0d7]*/ -{ - int res; - int async_err = 0; - - do { - Py_BEGIN_ALLOW_THREADS - res = fchown(fd, uid, gid); - Py_END_ALLOW_THREADS - } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); - if (res != 0) - return (!async_err) ? posix_error() : NULL; - - Py_RETURN_NONE; -} -#endif /* HAVE_FCHOWN */ - - -#ifdef HAVE_LCHOWN -/*[clinic input] -os.lchown - - path : path_t - uid: uid_t - gid: gid_t - -Change the owner and group id of path to the numeric uid and gid. - -This function will not follow symbolic links. -Equivalent to os.chown(path, uid, gid, follow_symlinks=False). -[clinic start generated code]*/ +#endif /* defined(HAVE_FCHOWN) */ + +#if defined(HAVE_LCHOWN) PyDoc_STRVAR(os_lchown__doc__, "lchown($module, /, path, uid, gid)\n" @@ -3945,80 +768,7 @@ return return_value; } -static PyObject * -os_lchown_impl(PyModuleDef *module, path_t *path, uid_t uid, gid_t gid) -/*[clinic end generated code: output=bf25fdb0d25130e2 input=b1c6014d563a7161]*/ -{ - int res; - Py_BEGIN_ALLOW_THREADS - res = lchown(path->narrow, uid, gid); - Py_END_ALLOW_THREADS - if (res < 0) { - return path_error(path); - } - Py_RETURN_NONE; -} -#endif /* HAVE_LCHOWN */ - - -static PyObject * -posix_getcwd(int use_bytes) -{ - char buf[1026]; - char *res; - -#ifdef MS_WINDOWS - if (!use_bytes) { - wchar_t wbuf[1026]; - wchar_t *wbuf2 = wbuf; - PyObject *resobj; - DWORD len; - Py_BEGIN_ALLOW_THREADS - len = GetCurrentDirectoryW(Py_ARRAY_LENGTH(wbuf), wbuf); - /* If the buffer is large enough, len does not include the - terminating \0. If the buffer is too small, len includes - the space needed for the terminator. */ - if (len >= Py_ARRAY_LENGTH(wbuf)) { - wbuf2 = PyMem_RawMalloc(len * sizeof(wchar_t)); - if (wbuf2) - len = GetCurrentDirectoryW(len, wbuf2); - } - Py_END_ALLOW_THREADS - if (!wbuf2) { - PyErr_NoMemory(); - return NULL; - } - if (!len) { - if (wbuf2 != wbuf) - PyMem_RawFree(wbuf2); - return PyErr_SetFromWindowsErr(0); - } - resobj = PyUnicode_FromWideChar(wbuf2, len); - if (wbuf2 != wbuf) - PyMem_RawFree(wbuf2); - return resobj; - } - - if (win32_warn_bytes_api()) - return NULL; -#endif - - Py_BEGIN_ALLOW_THREADS - res = getcwd(buf, sizeof buf); - Py_END_ALLOW_THREADS - if (res == NULL) - return posix_error(); - if (use_bytes) - return PyBytes_FromStringAndSize(buf, strlen(buf)); - return PyUnicode_DecodeFSDefault(buf); -} - - -/*[clinic input] -os.getcwd - -Return a unicode string representing the current working directory. -[clinic start generated code]*/ +#endif /* defined(HAVE_LCHOWN) */ PyDoc_STRVAR(os_getcwd__doc__, "getcwd($module, /)\n" @@ -4038,20 +788,6 @@ return os_getcwd_impl(module); } -static PyObject * -os_getcwd_impl(PyModuleDef *module) -/*[clinic end generated code: output=d70b281db5c78ff7 input=f069211bb70e3d39]*/ -{ - return posix_getcwd(0); -} - - -/*[clinic input] -os.getcwdb - -Return a bytes string representing the current working directory. -[clinic start generated code]*/ - PyDoc_STRVAR(os_getcwdb__doc__, "getcwdb($module, /)\n" "--\n" @@ -4070,42 +806,7 @@ return os_getcwdb_impl(module); } -static PyObject * -os_getcwdb_impl(PyModuleDef *module) -/*[clinic end generated code: output=75da47f2d75f9166 input=f6f6a378dad3d9cb]*/ -{ - return posix_getcwd(1); -} - - -#if ((!defined(HAVE_LINK)) && defined(MS_WINDOWS)) -#define HAVE_LINK 1 -#endif - -#ifdef HAVE_LINK -/*[clinic input] - -os.link - - src : path_t - dst : path_t - * - src_dir_fd : dir_fd = None - dst_dir_fd : dir_fd = None - follow_symlinks: bool = True - -Create a hard link to a file. - -If either src_dir_fd or dst_dir_fd is not None, it should be a file - descriptor open to a directory, and the respective path string (src or dst) - should be relative; the path will then be relative to that directory. -If follow_symlinks is False, and the last element of src is a symbolic - link, link will create a link to the symbolic link itself instead of the - file the link points to. -src_dir_fd, dst_dir_fd, and follow_symlinks may not be implemented on your - platform. If they are unavailable, using them will raise a - NotImplementedError. -[clinic start generated code]*/ +#if defined(HAVE_LINK) PyDoc_STRVAR(os_link__doc__, "link($module, /, src, dst, *, src_dir_fd=None, dst_dir_fd=None,\n" @@ -4156,345 +857,7 @@ return return_value; } -static PyObject * -os_link_impl(PyModuleDef *module, path_t *src, path_t *dst, int src_dir_fd, int dst_dir_fd, int follow_symlinks) -/*[clinic end generated code: output=53477662fe02e183 input=b0095ebbcbaa7e04]*/ -{ -#ifdef MS_WINDOWS - BOOL result; -#else - int result; -#endif - -#ifndef HAVE_LINKAT - if ((src_dir_fd != DEFAULT_DIR_FD) || (dst_dir_fd != DEFAULT_DIR_FD)) { - argument_unavailable_error("link", "src_dir_fd and dst_dir_fd"); - return NULL; - } -#endif - - if ((src->narrow && dst->wide) || (src->wide && dst->narrow)) { - PyErr_SetString(PyExc_NotImplementedError, - "link: src and dst must be the same type"); - return NULL; - } - -#ifdef MS_WINDOWS - Py_BEGIN_ALLOW_THREADS - if (src->wide) - result = CreateHardLinkW(dst->wide, src->wide, NULL); - else - result = CreateHardLinkA(dst->narrow, src->narrow, NULL); - Py_END_ALLOW_THREADS - - if (!result) - return path_error2(src, dst); -#else - Py_BEGIN_ALLOW_THREADS -#ifdef HAVE_LINKAT - if ((src_dir_fd != DEFAULT_DIR_FD) || - (dst_dir_fd != DEFAULT_DIR_FD) || - (!follow_symlinks)) - result = linkat(src_dir_fd, src->narrow, - dst_dir_fd, dst->narrow, - follow_symlinks ? AT_SYMLINK_FOLLOW : 0); - else -#endif - result = link(src->narrow, dst->narrow); - Py_END_ALLOW_THREADS - - if (result) - return path_error2(src, dst); -#endif - - Py_RETURN_NONE; -} -#endif - - -#if defined(MS_WINDOWS) && !defined(HAVE_OPENDIR) -static PyObject * -_listdir_windows_no_opendir(path_t *path, PyObject *list) -{ - PyObject *v; - HANDLE hFindFile = INVALID_HANDLE_VALUE; - BOOL result; - WIN32_FIND_DATA FileData; - char namebuf[MAX_PATH+4]; /* Overallocate for "\*.*" */ - char *bufptr = namebuf; - /* only claim to have space for MAX_PATH */ - Py_ssize_t len = Py_ARRAY_LENGTH(namebuf)-4; - PyObject *po = NULL; - wchar_t *wnamebuf = NULL; - - if (!path->narrow) { - WIN32_FIND_DATAW wFileData; - wchar_t *po_wchars; - - if (!path->wide) { /* Default arg: "." */ - po_wchars = L"."; - len = 1; - } else { - po_wchars = path->wide; - len = wcslen(path->wide); - } - /* The +5 is so we can append "\\*.*\0" */ - wnamebuf = PyMem_New(wchar_t, len + 5); - if (!wnamebuf) { - PyErr_NoMemory(); - goto exit; - } - wcscpy(wnamebuf, po_wchars); - if (len > 0) { - wchar_t wch = wnamebuf[len-1]; - if (wch != SEP && wch != ALTSEP && wch != L':') - wnamebuf[len++] = SEP; - wcscpy(wnamebuf + len, L"*.*"); - } - if ((list = PyList_New(0)) == NULL) { - goto exit; - } - Py_BEGIN_ALLOW_THREADS - hFindFile = FindFirstFileW(wnamebuf, &wFileData); - Py_END_ALLOW_THREADS - if (hFindFile == INVALID_HANDLE_VALUE) { - int error = GetLastError(); - if (error == ERROR_FILE_NOT_FOUND) - goto exit; - Py_DECREF(list); - list = path_error(path); - goto exit; - } - do { - /* Skip over . and .. */ - if (wcscmp(wFileData.cFileName, L".") != 0 && - wcscmp(wFileData.cFileName, L"..") != 0) { - v = PyUnicode_FromWideChar(wFileData.cFileName, - wcslen(wFileData.cFileName)); - if (v == NULL) { - Py_DECREF(list); - list = NULL; - break; - } - if (PyList_Append(list, v) != 0) { - Py_DECREF(v); - Py_DECREF(list); - list = NULL; - break; - } - Py_DECREF(v); - } - Py_BEGIN_ALLOW_THREADS - result = FindNextFileW(hFindFile, &wFileData); - Py_END_ALLOW_THREADS - /* FindNextFile sets error to ERROR_NO_MORE_FILES if - it got to the end of the directory. */ - if (!result && GetLastError() != ERROR_NO_MORE_FILES) { - Py_DECREF(list); - list = path_error(path); - goto exit; - } - } while (result == TRUE); - - goto exit; - } - strcpy(namebuf, path->narrow); - len = path->length; - if (len > 0) { - char ch = namebuf[len-1]; - if (ch != '\\' && ch != '/' && ch != ':') - namebuf[len++] = '\\'; - strcpy(namebuf + len, "*.*"); - } - - if ((list = PyList_New(0)) == NULL) - return NULL; - - Py_BEGIN_ALLOW_THREADS - hFindFile = FindFirstFile(namebuf, &FileData); - Py_END_ALLOW_THREADS - if (hFindFile == INVALID_HANDLE_VALUE) { - int error = GetLastError(); - if (error == ERROR_FILE_NOT_FOUND) - goto exit; - Py_DECREF(list); - list = path_error(path); - goto exit; - } - do { - /* Skip over . and .. */ - if (strcmp(FileData.cFileName, ".") != 0 && - strcmp(FileData.cFileName, "..") != 0) { - v = PyBytes_FromString(FileData.cFileName); - if (v == NULL) { - Py_DECREF(list); - list = NULL; - break; - } - if (PyList_Append(list, v) != 0) { - Py_DECREF(v); - Py_DECREF(list); - list = NULL; - break; - } - Py_DECREF(v); - } - Py_BEGIN_ALLOW_THREADS - result = FindNextFile(hFindFile, &FileData); - Py_END_ALLOW_THREADS - /* FindNextFile sets error to ERROR_NO_MORE_FILES if - it got to the end of the directory. */ - if (!result && GetLastError() != ERROR_NO_MORE_FILES) { - Py_DECREF(list); - list = path_error(path); - goto exit; - } - } while (result == TRUE); - -exit: - if (hFindFile != INVALID_HANDLE_VALUE) { - if (FindClose(hFindFile) == FALSE) { - if (list != NULL) { - Py_DECREF(list); - list = path_error(path); - } - } - } - PyMem_Free(wnamebuf); - - return list; -} /* end of _listdir_windows_no_opendir */ - -#else /* thus POSIX, ie: not (MS_WINDOWS and not HAVE_OPENDIR) */ - -static PyObject * -_posix_listdir(path_t *path, PyObject *list) -{ - PyObject *v; - DIR *dirp = NULL; - struct dirent *ep; - int return_str; /* if false, return bytes */ -#ifdef HAVE_FDOPENDIR - int fd = -1; -#endif - - errno = 0; -#ifdef HAVE_FDOPENDIR - if (path->fd != -1) { - /* closedir() closes the FD, so we duplicate it */ - fd = _Py_dup(path->fd); - if (fd == -1) - return NULL; - - return_str = 1; - - Py_BEGIN_ALLOW_THREADS - dirp = fdopendir(fd); - Py_END_ALLOW_THREADS - } - else -#endif - { - char *name; - if (path->narrow) { - name = path->narrow; - /* only return bytes if they specified a bytes object */ - return_str = !(PyBytes_Check(path->object)); - } - else { - name = "."; - return_str = 1; - } - - Py_BEGIN_ALLOW_THREADS - dirp = opendir(name); - Py_END_ALLOW_THREADS - } - - if (dirp == NULL) { - list = path_error(path); -#ifdef HAVE_FDOPENDIR - if (fd != -1) { - Py_BEGIN_ALLOW_THREADS - close(fd); - Py_END_ALLOW_THREADS - } -#endif - goto exit; - } - if ((list = PyList_New(0)) == NULL) { - goto exit; - } - for (;;) { - errno = 0; - Py_BEGIN_ALLOW_THREADS - ep = readdir(dirp); - Py_END_ALLOW_THREADS - if (ep == NULL) { - if (errno == 0) { - break; - } else { - Py_DECREF(list); - list = path_error(path); - goto exit; - } - } - if (ep->d_name[0] == '.' && - (NAMLEN(ep) == 1 || - (ep->d_name[1] == '.' && NAMLEN(ep) == 2))) - continue; - if (return_str) - v = PyUnicode_DecodeFSDefaultAndSize(ep->d_name, NAMLEN(ep)); - else - v = PyBytes_FromStringAndSize(ep->d_name, NAMLEN(ep)); - if (v == NULL) { - Py_CLEAR(list); - break; - } - if (PyList_Append(list, v) != 0) { - Py_DECREF(v); - Py_CLEAR(list); - break; - } - Py_DECREF(v); - } - -exit: - if (dirp != NULL) { - Py_BEGIN_ALLOW_THREADS -#ifdef HAVE_FDOPENDIR - if (fd > -1) - rewinddir(dirp); -#endif - closedir(dirp); - Py_END_ALLOW_THREADS - } - - return list; -} /* end of _posix_listdir */ -#endif /* which OS */ - - -/*[clinic input] -os.listdir - - path : path_t(nullable=True, allow_fd='PATH_HAVE_FDOPENDIR') = None - -Return a list containing the names of the files in the directory. - -path can be specified as either str or bytes. If path is bytes, - the filenames returned will also be bytes; in all other circumstances - the filenames returned will be str. -If path is None, uses the path='.'. -On some platforms, path may also be specified as an open file descriptor;\ - the file descriptor must refer to a directory. - If this functionality is unavailable, using it raises NotImplementedError. - -The list is in arbitrary order. It does not include the special -entries '.' and '..' even if they are present in the directory. - - -[clinic start generated code]*/ +#endif /* defined(HAVE_LINK) */ PyDoc_STRVAR(os_listdir__doc__, "listdir($module, /, path=None)\n" @@ -4539,86 +902,7 @@ return return_value; } -static PyObject * -os_listdir_impl(PyModuleDef *module, path_t *path) -/*[clinic end generated code: output=e159bd9be6909018 input=09e300416e3cd729]*/ -{ -#if defined(MS_WINDOWS) && !defined(HAVE_OPENDIR) - return _listdir_windows_no_opendir(path, NULL); -#else - return _posix_listdir(path, NULL); -#endif -} - -#ifdef MS_WINDOWS -/* A helper function for abspath on win32 */ -/* AC 3.5: probably just convert to using path converter */ -static PyObject * -posix__getfullpathname(PyObject *self, PyObject *args) -{ - const char *path; - char outbuf[MAX_PATH]; - char *temp; - PyObject *po; - - if (PyArg_ParseTuple(args, "U|:_getfullpathname", &po)) - { - wchar_t *wpath; - wchar_t woutbuf[MAX_PATH], *woutbufp = woutbuf; - wchar_t *wtemp; - DWORD result; - PyObject *v; - - wpath = PyUnicode_AsUnicode(po); - if (wpath == NULL) - return NULL; - result = GetFullPathNameW(wpath, - Py_ARRAY_LENGTH(woutbuf), - woutbuf, &wtemp); - if (result > Py_ARRAY_LENGTH(woutbuf)) { - woutbufp = PyMem_New(wchar_t, result); - if (!woutbufp) - return PyErr_NoMemory(); - result = GetFullPathNameW(wpath, result, woutbufp, &wtemp); - } - if (result) - v = PyUnicode_FromWideChar(woutbufp, wcslen(woutbufp)); - else - v = win32_error_object("GetFullPathNameW", po); - if (woutbufp != woutbuf) - PyMem_Free(woutbufp); - return v; - } - /* Drop the argument parsing error as narrow strings - are also valid. */ - PyErr_Clear(); - - if (!PyArg_ParseTuple (args, "y:_getfullpathname", - &path)) - return NULL; - if (win32_warn_bytes_api()) - return NULL; - if (!GetFullPathName(path, Py_ARRAY_LENGTH(outbuf), - outbuf, &temp)) { - win32_error("GetFullPathName", path); - return NULL; - } - if (PyUnicode_Check(PyTuple_GetItem(args, 0))) { - return PyUnicode_Decode(outbuf, strlen(outbuf), - Py_FileSystemDefaultEncoding, NULL); - } - return PyBytes_FromString(outbuf); -} - - -/*[clinic input] -os._getfinalpathname - - path: unicode - / - -A helper function for samepath on windows. -[clinic start generated code]*/ +#if defined(MS_WINDOWS) PyDoc_STRVAR(os__getfinalpathname__doc__, "_getfinalpathname($module, path, /)\n" @@ -4648,107 +932,9 @@ return return_value; } -static PyObject * -os__getfinalpathname_impl(PyModuleDef *module, PyObject *path) -/*[clinic end generated code: output=4563c6eacf1b0881 input=71d5e89334891bf4]*/ -{ - HANDLE hFile; - int buf_size; - wchar_t *target_path; - int result_length; - PyObject *result; - wchar_t *path_wchar; - - path_wchar = PyUnicode_AsUnicode(path); - if (path_wchar == NULL) - return NULL; - - hFile = CreateFileW( - path_wchar, - 0, /* desired access */ - 0, /* share mode */ - NULL, /* security attributes */ - OPEN_EXISTING, - /* FILE_FLAG_BACKUP_SEMANTICS is required to open a directory */ - FILE_FLAG_BACKUP_SEMANTICS, - NULL); - - if(hFile == INVALID_HANDLE_VALUE) - return win32_error_object("CreateFileW", path); - - /* We have a good handle to the target, use it to determine the - target path name. */ - buf_size = GetFinalPathNameByHandleW(hFile, 0, 0, VOLUME_NAME_NT); - - if(!buf_size) - return win32_error_object("GetFinalPathNameByHandle", path); - - target_path = PyMem_New(wchar_t, buf_size+1); - if(!target_path) - return PyErr_NoMemory(); - - result_length = GetFinalPathNameByHandleW(hFile, target_path, - buf_size, VOLUME_NAME_DOS); - if(!result_length) - return win32_error_object("GetFinalPathNamyByHandle", path); - - if(!CloseHandle(hFile)) - return win32_error_object("CloseHandle", path); - - target_path[result_length] = 0; - result = PyUnicode_FromWideChar(target_path, result_length); - PyMem_Free(target_path); - return result; -} - -PyDoc_STRVAR(posix__isdir__doc__, -"Return true if the pathname refers to an existing directory."); - -/* AC 3.5: convert using path converter */ -static PyObject * -posix__isdir(PyObject *self, PyObject *args) -{ - const char *path; - PyObject *po; - DWORD attributes; - - if (PyArg_ParseTuple(args, "U|:_isdir", &po)) { - wchar_t *wpath = PyUnicode_AsUnicode(po); - if (wpath == NULL) - return NULL; - - attributes = GetFileAttributesW(wpath); - if (attributes == INVALID_FILE_ATTRIBUTES) - Py_RETURN_FALSE; - goto check; - } - /* Drop the argument parsing error as narrow strings - are also valid. */ - PyErr_Clear(); - - if (!PyArg_ParseTuple(args, "y:_isdir", &path)) - return NULL; - if (win32_warn_bytes_api()) - return NULL; - attributes = GetFileAttributesA(path); - if (attributes == INVALID_FILE_ATTRIBUTES) - Py_RETURN_FALSE; - -check: - if (attributes & FILE_ATTRIBUTE_DIRECTORY) - Py_RETURN_TRUE; - else - Py_RETURN_FALSE; -} - - -/*[clinic input] -os._getvolumepathname - - path: unicode - -A helper function for ismount on Win32. -[clinic start generated code]*/ +#endif /* defined(MS_WINDOWS) */ + +#if defined(MS_WINDOWS) PyDoc_STRVAR(os__getvolumepathname__doc__, "_getvolumepathname($module, /, path)\n" @@ -4779,73 +965,7 @@ return return_value; } -static PyObject * -os__getvolumepathname_impl(PyModuleDef *module, PyObject *path) -/*[clinic end generated code: output=ac0833b6d6da7657 input=7eacadc40acbda6b]*/ -{ - PyObject *result; - wchar_t *path_wchar, *mountpath=NULL; - size_t buflen; - BOOL ret; - - path_wchar = PyUnicode_AsUnicodeAndSize(path, &buflen); - if (path_wchar == NULL) - return NULL; - buflen += 1; - - /* Volume path should be shorter than entire path */ - buflen = Py_MAX(buflen, MAX_PATH); - - if (buflen > DWORD_MAX) { - PyErr_SetString(PyExc_OverflowError, "path too long"); - return NULL; - } - - mountpath = PyMem_New(wchar_t, buflen); - if (mountpath == NULL) - return PyErr_NoMemory(); - - Py_BEGIN_ALLOW_THREADS - ret = GetVolumePathNameW(path_wchar, mountpath, - Py_SAFE_DOWNCAST(buflen, size_t, DWORD)); - Py_END_ALLOW_THREADS - - if (!ret) { - result = win32_error_object("_getvolumepathname", path); - goto exit; - } - result = PyUnicode_FromWideChar(mountpath, wcslen(mountpath)); - -exit: - PyMem_Free(mountpath); - return result; -} - -#endif /* MS_WINDOWS */ - - -/*[clinic input] -os.mkdir - - path : path_t - - mode: int = 0o777 - - * - - dir_fd : dir_fd(requires='mkdirat') = None - -# "mkdir(path, mode=0o777, *, dir_fd=None)\n\n\ - -Create a directory. - -If dir_fd is not None, it should be a file descriptor open to a directory, - and path should be relative; path will then be relative to that directory. -dir_fd may not be implemented on your platform. - If it is unavailable, using it will raise a NotImplementedError. - -The mode argument is ignored on Windows. -[clinic start generated code]*/ +#endif /* defined(MS_WINDOWS) */ PyDoc_STRVAR(os_mkdir__doc__, "mkdir($module, /, path, mode=511, *, dir_fd=None)\n" @@ -4888,57 +1008,7 @@ return return_value; } -static PyObject * -os_mkdir_impl(PyModuleDef *module, path_t *path, int mode, int dir_fd) -/*[clinic end generated code: output=55c6ef2bc1b207e6 input=e965f68377e9b1ce]*/ -{ - int result; - -#ifdef MS_WINDOWS - Py_BEGIN_ALLOW_THREADS - if (path->wide) - result = CreateDirectoryW(path->wide, NULL); - else - result = CreateDirectoryA(path->narrow, NULL); - Py_END_ALLOW_THREADS - - if (!result) - return path_error(path); -#else - Py_BEGIN_ALLOW_THREADS -#if HAVE_MKDIRAT - if (dir_fd != DEFAULT_DIR_FD) - result = mkdirat(dir_fd, path->narrow, mode); - else -#endif -#if ( defined(__WATCOMC__) || defined(PYCC_VACPP) ) && !defined(__QNX__) - result = mkdir(path->narrow); -#else - result = mkdir(path->narrow, mode); -#endif - Py_END_ALLOW_THREADS - if (result < 0) - return path_error(path); -#endif - Py_RETURN_NONE; -} - - -/* sys/resource.h is needed for at least: wait3(), wait4(), broken nice. */ -#if defined(HAVE_SYS_RESOURCE_H) -#include -#endif - - -#ifdef HAVE_NICE -/*[clinic input] -os.nice - - increment: int - / - -Add increment to the priority of process and return the new priority. -[clinic start generated code]*/ +#if defined(HAVE_NICE) PyDoc_STRVAR(os_nice__doc__, "nice($module, increment, /)\n" @@ -4968,45 +1038,9 @@ return return_value; } -static PyObject * -os_nice_impl(PyModuleDef *module, int increment) -/*[clinic end generated code: output=c360dc2a3bd8e3d0 input=864be2d402a21da2]*/ -{ - int value; - - /* There are two flavours of 'nice': one that returns the new - priority (as required by almost all standards out there) and the - Linux/FreeBSD/BSDI one, which returns '0' on success and advices - the use of getpriority() to get the new priority. - - If we are of the nice family that returns the new priority, we - need to clear errno before the call, and check if errno is filled - before calling posix_error() on a returnvalue of -1, because the - -1 may be the actual new priority! */ - - errno = 0; - value = nice(increment); -#if defined(HAVE_BROKEN_NICE) && defined(HAVE_GETPRIORITY) - if (value == 0) - value = getpriority(PRIO_PROCESS, 0); -#endif - if (value == -1 && errno != 0) - /* either nice() or getpriority() returned an error */ - return posix_error(); - return PyLong_FromLong((long) value); -} -#endif /* HAVE_NICE */ - - -#ifdef HAVE_GETPRIORITY -/*[clinic input] -os.getpriority - - which: int - who: int - -Return program scheduling priority. -[clinic start generated code]*/ +#endif /* defined(HAVE_NICE) */ + +#if defined(HAVE_GETPRIORITY) PyDoc_STRVAR(os_getpriority__doc__, "getpriority($module, /, which, who)\n" @@ -5038,31 +1072,9 @@ return return_value; } -static PyObject * -os_getpriority_impl(PyModuleDef *module, int which, int who) -/*[clinic end generated code: output=81639cf765f05dae input=9be615d40e2544ef]*/ -{ - int retval; - - errno = 0; - retval = getpriority(which, who); - if (errno != 0) - return posix_error(); - return PyLong_FromLong((long)retval); -} -#endif /* HAVE_GETPRIORITY */ - - -#ifdef HAVE_SETPRIORITY -/*[clinic input] -os.setpriority - - which: int - who: int - priority: int - -Set program scheduling priority. -[clinic start generated code]*/ +#endif /* defined(HAVE_GETPRIORITY) */ + +#if defined(HAVE_SETPRIORITY) PyDoc_STRVAR(os_setpriority__doc__, "setpriority($module, /, which, who, priority)\n" @@ -5095,93 +1107,7 @@ return return_value; } -static PyObject * -os_setpriority_impl(PyModuleDef *module, int which, int who, int priority) -/*[clinic end generated code: output=ddad62651fb2120c input=710ccbf65b9dc513]*/ -{ - int retval; - - retval = setpriority(which, who, priority); - if (retval == -1) - return posix_error(); - Py_RETURN_NONE; -} -#endif /* HAVE_SETPRIORITY */ - - -static PyObject * -internal_rename(path_t *src, path_t *dst, int src_dir_fd, int dst_dir_fd, int is_replace) -{ - char *function_name = is_replace ? "replace" : "rename"; - int dir_fd_specified; - -#ifdef MS_WINDOWS - BOOL result; - int flags = is_replace ? MOVEFILE_REPLACE_EXISTING : 0; -#else - int result; -#endif - - dir_fd_specified = (src_dir_fd != DEFAULT_DIR_FD) || - (dst_dir_fd != DEFAULT_DIR_FD); -#ifndef HAVE_RENAMEAT - if (dir_fd_specified) { - argument_unavailable_error(function_name, "src_dir_fd and dst_dir_fd"); - return NULL; - } -#endif - - if ((src->narrow && dst->wide) || (src->wide && dst->narrow)) { - PyErr_Format(PyExc_ValueError, - "%s: src and dst must be the same type", function_name); - return NULL; - } - -#ifdef MS_WINDOWS - Py_BEGIN_ALLOW_THREADS - if (src->wide) - result = MoveFileExW(src->wide, dst->wide, flags); - else - result = MoveFileExA(src->narrow, dst->narrow, flags); - Py_END_ALLOW_THREADS - - if (!result) - return path_error2(src, dst); - -#else - Py_BEGIN_ALLOW_THREADS -#ifdef HAVE_RENAMEAT - if (dir_fd_specified) - result = renameat(src_dir_fd, src->narrow, dst_dir_fd, dst->narrow); - else -#endif - result = rename(src->narrow, dst->narrow); - Py_END_ALLOW_THREADS - - if (result) - return path_error2(src, dst); -#endif - Py_RETURN_NONE; -} - - -/*[clinic input] -os.rename - - src : path_t - dst : path_t - * - src_dir_fd : dir_fd = None - dst_dir_fd : dir_fd = None - -Rename a file or directory. - -If either src_dir_fd or dst_dir_fd is not None, it should be a file - descriptor open to a directory, and the respective path string (src or dst) - should be relative; the path will then be relative to that directory. -src_dir_fd and dst_dir_fd, may not be implemented on your platform. - If they are unavailable, using them will raise a NotImplementedError. -[clinic start generated code]*/ +#endif /* defined(HAVE_SETPRIORITY) */ PyDoc_STRVAR(os_rename__doc__, "rename($module, /, src, dst, *, src_dir_fd=None, dst_dir_fd=None)\n" @@ -5226,26 +1152,6 @@ return return_value; } -static PyObject * -os_rename_impl(PyModuleDef *module, path_t *src, path_t *dst, int src_dir_fd, int dst_dir_fd) -/*[clinic end generated code: output=c936bdc81f460a1e input=faa61c847912c850]*/ -{ - return internal_rename(src, dst, src_dir_fd, dst_dir_fd, 0); -} - - -/*[clinic input] -os.replace = os.rename - -Rename a file or directory, overwriting the destination. - -If either src_dir_fd or dst_dir_fd is not None, it should be a file - descriptor open to a directory, and the respective path string (src or dst) - should be relative; the path will then be relative to that directory. -src_dir_fd and dst_dir_fd, may not be implemented on your platform. - If they are unavailable, using them will raise a NotImplementedError." -[clinic start generated code]*/ - PyDoc_STRVAR(os_replace__doc__, "replace($module, /, src, dst, *, src_dir_fd=None, dst_dir_fd=None)\n" "--\n" @@ -5289,29 +1195,6 @@ return return_value; } -static PyObject * -os_replace_impl(PyModuleDef *module, path_t *src, path_t *dst, int src_dir_fd, int dst_dir_fd) -/*[clinic end generated code: output=224e4710d290d171 input=25515dfb107c8421]*/ -{ - return internal_rename(src, dst, src_dir_fd, dst_dir_fd, 1); -} - - -/*[clinic input] -os.rmdir - - path: path_t - * - dir_fd: dir_fd(requires='unlinkat') = None - -Remove a directory. - -If dir_fd is not None, it should be a file descriptor open to a directory, - and path should be relative; path will then be relative to that directory. -dir_fd may not be implemented on your platform. - If it is unavailable, using it will raise a NotImplementedError. -[clinic start generated code]*/ - PyDoc_STRVAR(os_rmdir__doc__, "rmdir($module, /, path, *, dir_fd=None)\n" "--\n" @@ -5350,45 +1233,7 @@ return return_value; } -static PyObject * -os_rmdir_impl(PyModuleDef *module, path_t *path, int dir_fd) -/*[clinic end generated code: output=70b9fdbe3bee0591 input=38c8b375ca34a7e2]*/ -{ - int result; - - Py_BEGIN_ALLOW_THREADS -#ifdef MS_WINDOWS - if (path->wide) - result = RemoveDirectoryW(path->wide); - else - result = RemoveDirectoryA(path->narrow); - result = !result; /* Windows, success=1, UNIX, success=0 */ -#else -#ifdef HAVE_UNLINKAT - if (dir_fd != DEFAULT_DIR_FD) - result = unlinkat(dir_fd, path->narrow, AT_REMOVEDIR); - else -#endif - result = rmdir(path->narrow); -#endif - Py_END_ALLOW_THREADS - - if (result) - return path_error(path); - - Py_RETURN_NONE; -} - - -#ifdef HAVE_SYSTEM -#ifdef MS_WINDOWS -/*[clinic input] -os.system -> long - - command: Py_UNICODE - -Execute the command in a subshell. -[clinic start generated code]*/ +#if defined(HAVE_SYSTEM) && defined(MS_WINDOWS) PyDoc_STRVAR(os_system__doc__, "system($module, /, command)\n" @@ -5423,24 +1268,9 @@ return return_value; } -static long -os_system_impl(PyModuleDef *module, Py_UNICODE *command) -/*[clinic end generated code: output=29fe699c0b2e9d38 input=303f5ce97df606b0]*/ -{ - long result; - Py_BEGIN_ALLOW_THREADS - result = _wsystem(command); - Py_END_ALLOW_THREADS - return result; -} -#else /* MS_WINDOWS */ -/*[clinic input] -os.system -> long - - command: FSConverter - -Execute the command in a subshell. -[clinic start generated code]*/ +#endif /* defined(HAVE_SYSTEM) && defined(MS_WINDOWS) */ + +#if defined(HAVE_SYSTEM) && !defined(MS_WINDOWS) PyDoc_STRVAR(os_system__doc__, "system($module, /, command)\n" @@ -5478,29 +1308,7 @@ return return_value; } -static long -os_system_impl(PyModuleDef *module, PyObject *command) -/*[clinic end generated code: output=5be9f3c40ead3bad input=86a58554ba6094af]*/ -{ - long result; - char *bytes = PyBytes_AsString(command); - Py_BEGIN_ALLOW_THREADS - result = system(bytes); - Py_END_ALLOW_THREADS - return result; -} -#endif -#endif /* HAVE_SYSTEM */ - - -/*[clinic input] -os.umask - - mask: int - / - -Set the current numeric umask and return the previous umask. -[clinic start generated code]*/ +#endif /* defined(HAVE_SYSTEM) && !defined(MS_WINDOWS) */ PyDoc_STRVAR(os_umask__doc__, "umask($module, mask, /)\n" @@ -5530,72 +1338,6 @@ return return_value; } -static PyObject * -os_umask_impl(PyModuleDef *module, int mask) -/*[clinic end generated code: output=90048b39d2d4a961 input=ab6bfd9b24d8a7e8]*/ -{ - int i = (int)umask(mask); - if (i < 0) - return posix_error(); - return PyLong_FromLong((long)i); -} - -#ifdef MS_WINDOWS - -/* override the default DeleteFileW behavior so that directory -symlinks can be removed with this function, the same as with -Unix symlinks */ -BOOL WINAPI Py_DeleteFileW(LPCWSTR lpFileName) -{ - WIN32_FILE_ATTRIBUTE_DATA info; - WIN32_FIND_DATAW find_data; - HANDLE find_data_handle; - int is_directory = 0; - int is_link = 0; - - if (GetFileAttributesExW(lpFileName, GetFileExInfoStandard, &info)) { - is_directory = info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY; - - /* Get WIN32_FIND_DATA structure for the path to determine if - it is a symlink */ - if(is_directory && - info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) { - find_data_handle = FindFirstFileW(lpFileName, &find_data); - - if(find_data_handle != INVALID_HANDLE_VALUE) { - /* IO_REPARSE_TAG_SYMLINK if it is a symlink and - IO_REPARSE_TAG_MOUNT_POINT if it is a junction point. */ - is_link = find_data.dwReserved0 == IO_REPARSE_TAG_SYMLINK || - find_data.dwReserved0 == IO_REPARSE_TAG_MOUNT_POINT; - FindClose(find_data_handle); - } - } - } - - if (is_directory && is_link) - return RemoveDirectoryW(lpFileName); - - return DeleteFileW(lpFileName); -} -#endif /* MS_WINDOWS */ - - -/*[clinic input] -os.unlink - - path: path_t - * - dir_fd: dir_fd(requires='unlinkat')=None - -Remove a file (same as remove()). - -If dir_fd is not None, it should be a file descriptor open to a directory, - and path should be relative; path will then be relative to that directory. -dir_fd may not be implemented on your platform. - If it is unavailable, using it will raise a NotImplementedError. - -[clinic start generated code]*/ - PyDoc_STRVAR(os_unlink__doc__, "unlink($module, /, path, *, dir_fd=None)\n" "--\n" @@ -5634,47 +1376,6 @@ return return_value; } -static PyObject * -os_unlink_impl(PyModuleDef *module, path_t *path, int dir_fd) -/*[clinic end generated code: output=59a6e66d67ff2e75 input=d7bcde2b1b2a2552]*/ -{ - int result; - - Py_BEGIN_ALLOW_THREADS -#ifdef MS_WINDOWS - if (path->wide) - result = Py_DeleteFileW(path->wide); - else - result = DeleteFileA(path->narrow); - result = !result; /* Windows, success=1, UNIX, success=0 */ -#else -#ifdef HAVE_UNLINKAT - if (dir_fd != DEFAULT_DIR_FD) - result = unlinkat(dir_fd, path->narrow, 0); - else -#endif /* HAVE_UNLINKAT */ - result = unlink(path->narrow); -#endif - Py_END_ALLOW_THREADS - - if (result) - return path_error(path); - - Py_RETURN_NONE; -} - - -/*[clinic input] -os.remove = os.unlink - -Remove a file (same as unlink()). - -If dir_fd is not None, it should be a file descriptor open to a directory, - and path should be relative; path will then be relative to that directory. -dir_fd may not be implemented on your platform. - If it is unavailable, using it will raise a NotImplementedError. -[clinic start generated code]*/ - PyDoc_STRVAR(os_remove__doc__, "remove($module, /, path, *, dir_fd=None)\n" "--\n" @@ -5713,51 +1414,7 @@ return return_value; } -static PyObject * -os_remove_impl(PyModuleDef *module, path_t *path, int dir_fd) -/*[clinic end generated code: output=cb170cf1e195b8ed input=e05c5ab55cd30983]*/ -{ - return os_unlink_impl(module, path, dir_fd); -} - - -static PyStructSequence_Field uname_result_fields[] = { - {"sysname", "operating system name"}, - {"nodename", "name of machine on network (implementation-defined)"}, - {"release", "operating system release"}, - {"version", "operating system version"}, - {"machine", "hardware identifier"}, - {NULL} -}; - -PyDoc_STRVAR(uname_result__doc__, -"uname_result: Result from os.uname().\n\n\ -This object may be accessed either as a tuple of\n\ - (sysname, nodename, release, version, machine),\n\ -or via the attributes sysname, nodename, release, version, and machine.\n\ -\n\ -See os.uname for more information."); - -static PyStructSequence_Desc uname_result_desc = { - "uname_result", /* name */ - uname_result__doc__, /* doc */ - uname_result_fields, - 5 -}; - -static PyTypeObject UnameResultType; - - -#ifdef HAVE_UNAME -/*[clinic input] -os.uname - -Return an object identifying the current operating system. - -The object behaves like a named tuple with the following fields: - (sysname, nodename, release, version, machine) - -[clinic start generated code]*/ +#if defined(HAVE_UNAME) PyDoc_STRVAR(os_uname__doc__, "uname($module, /)\n" @@ -5780,259 +1437,7 @@ return os_uname_impl(module); } -static PyObject * -os_uname_impl(PyModuleDef *module) -/*[clinic end generated code: output=459a86521ff5041c input=e68bd246db3043ed]*/ -{ - struct utsname u; - int res; - PyObject *value; - - Py_BEGIN_ALLOW_THREADS - res = uname(&u); - Py_END_ALLOW_THREADS - if (res < 0) - return posix_error(); - - value = PyStructSequence_New(&UnameResultType); - if (value == NULL) - return NULL; - -#define SET(i, field) \ - { \ - PyObject *o = PyUnicode_DecodeFSDefault(field); \ - if (!o) { \ - Py_DECREF(value); \ - return NULL; \ - } \ - PyStructSequence_SET_ITEM(value, i, o); \ - } \ - - SET(0, u.sysname); - SET(1, u.nodename); - SET(2, u.release); - SET(3, u.version); - SET(4, u.machine); - -#undef SET - - return value; -} -#endif /* HAVE_UNAME */ - - - -typedef struct { - int now; - time_t atime_s; - long atime_ns; - time_t mtime_s; - long mtime_ns; -} utime_t; - -/* - * these macros assume that "ut" is a pointer to a utime_t - * they also intentionally leak the declaration of a pointer named "time" - */ -#define UTIME_TO_TIMESPEC \ - struct timespec ts[2]; \ - struct timespec *time; \ - if (ut->now) \ - time = NULL; \ - else { \ - ts[0].tv_sec = ut->atime_s; \ - ts[0].tv_nsec = ut->atime_ns; \ - ts[1].tv_sec = ut->mtime_s; \ - ts[1].tv_nsec = ut->mtime_ns; \ - time = ts; \ - } \ - -#define UTIME_TO_TIMEVAL \ - struct timeval tv[2]; \ - struct timeval *time; \ - if (ut->now) \ - time = NULL; \ - else { \ - tv[0].tv_sec = ut->atime_s; \ - tv[0].tv_usec = ut->atime_ns / 1000; \ - tv[1].tv_sec = ut->mtime_s; \ - tv[1].tv_usec = ut->mtime_ns / 1000; \ - time = tv; \ - } \ - -#define UTIME_TO_UTIMBUF \ - struct utimbuf u; \ - struct utimbuf *time; \ - if (ut->now) \ - time = NULL; \ - else { \ - u.actime = ut->atime_s; \ - u.modtime = ut->mtime_s; \ - time = &u; \ - } - -#define UTIME_TO_TIME_T \ - time_t timet[2]; \ - time_t *time; \ - if (ut->now) \ - time = NULL; \ - else { \ - timet[0] = ut->atime_s; \ - timet[1] = ut->mtime_s; \ - time = timet; \ - } \ - - -#define UTIME_HAVE_DIR_FD (defined(HAVE_FUTIMESAT) || defined(HAVE_UTIMENSAT)) - -#if UTIME_HAVE_DIR_FD - -static int -utime_dir_fd(utime_t *ut, int dir_fd, char *path, int follow_symlinks) -{ -#ifdef HAVE_UTIMENSAT - int flags = follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW; - UTIME_TO_TIMESPEC; - return utimensat(dir_fd, path, time, flags); -#elif defined(HAVE_FUTIMESAT) - UTIME_TO_TIMEVAL; - /* - * follow_symlinks will never be false here; - * we only allow !follow_symlinks and dir_fd together - * if we have utimensat() - */ - assert(follow_symlinks); - return futimesat(dir_fd, path, time); -#endif -} - - #define FUTIMENSAT_DIR_FD_CONVERTER dir_fd_converter -#else - #define FUTIMENSAT_DIR_FD_CONVERTER dir_fd_unavailable -#endif - -#define UTIME_HAVE_FD (defined(HAVE_FUTIMES) || defined(HAVE_FUTIMENS)) - -#if UTIME_HAVE_FD - -static int -utime_fd(utime_t *ut, int fd) -{ -#ifdef HAVE_FUTIMENS - UTIME_TO_TIMESPEC; - return futimens(fd, time); -#else - UTIME_TO_TIMEVAL; - return futimes(fd, time); -#endif -} - - #define PATH_UTIME_HAVE_FD 1 -#else - #define PATH_UTIME_HAVE_FD 0 -#endif - - -#define UTIME_HAVE_NOFOLLOW_SYMLINKS \ - (defined(HAVE_UTIMENSAT) || defined(HAVE_LUTIMES)) - -#if UTIME_HAVE_NOFOLLOW_SYMLINKS - -static int -utime_nofollow_symlinks(utime_t *ut, char *path) -{ -#ifdef HAVE_UTIMENSAT - UTIME_TO_TIMESPEC; - return utimensat(DEFAULT_DIR_FD, path, time, AT_SYMLINK_NOFOLLOW); -#else - UTIME_TO_TIMEVAL; - return lutimes(path, time); -#endif -} - -#endif - -#ifndef MS_WINDOWS - -static int -utime_default(utime_t *ut, char *path) -{ -#ifdef HAVE_UTIMENSAT - UTIME_TO_TIMESPEC; - return utimensat(DEFAULT_DIR_FD, path, time, 0); -#elif defined(HAVE_UTIMES) - UTIME_TO_TIMEVAL; - return utimes(path, time); -#elif defined(HAVE_UTIME_H) - UTIME_TO_UTIMBUF; - return utime(path, time); -#else - UTIME_TO_TIME_T; - return utime(path, time); -#endif -} - -#endif - -static int -split_py_long_to_s_and_ns(PyObject *py_long, time_t *s, long *ns) -{ - int result = 0; - PyObject *divmod; - divmod = PyNumber_Divmod(py_long, billion); - if (!divmod) - goto exit; - *s = _PyLong_AsTime_t(PyTuple_GET_ITEM(divmod, 0)); - if ((*s == -1) && PyErr_Occurred()) - goto exit; - *ns = PyLong_AsLong(PyTuple_GET_ITEM(divmod, 1)); - if ((*ns == -1) && PyErr_Occurred()) - goto exit; - - result = 1; -exit: - Py_XDECREF(divmod); - return result; -} - - -/*[clinic input] -os.utime - - path: path_t(allow_fd='PATH_UTIME_HAVE_FD') - times: object = NULL - * - ns: object = NULL - dir_fd: dir_fd(requires='futimensat') = None - follow_symlinks: bool=True - -# "utime(path, times=None, *, ns=None, dir_fd=None, follow_symlinks=True)\n\ - -Set the access and modified time of path. - -path may always be specified as a string. -On some platforms, path may also be specified as an open file descriptor. - If this functionality is unavailable, using it raises an exception. - -If times is not None, it must be a tuple (atime, mtime); - atime and mtime should be expressed as float seconds since the epoch. -If ns is not None, it must be a tuple (atime_ns, mtime_ns); - atime_ns and mtime_ns should be expressed as integer nanoseconds - since the epoch. -If both times and ns are None, utime uses the current time. -Specifying tuples for both times and ns is an error. - -If dir_fd is not None, it should be a file descriptor open to a directory, - and path should be relative; path will then be relative to that directory. -If follow_symlinks is False, and the last element of the path is a symbolic - link, utime will modify the symbolic link itself instead of the file the - link points to. -It is an error to use dir_fd or follow_symlinks when specifying path - as an open file descriptor. -dir_fd and follow_symlinks may not be available on your platform. - If they are unavailable, using them will raise a NotImplementedError. - -[clinic start generated code]*/ +#endif /* defined(HAVE_UNAME) */ PyDoc_STRVAR(os_utime__doc__, "utime($module, /, path, times=None, *, ns=None, dir_fd=None,\n" @@ -6093,175 +1498,6 @@ return return_value; } -static PyObject * -os_utime_impl(PyModuleDef *module, path_t *path, PyObject *times, PyObject *ns, int dir_fd, int follow_symlinks) -/*[clinic end generated code: output=891489c35cc68c5d input=1f18c17d5941aa82]*/ -{ -#ifdef MS_WINDOWS - HANDLE hFile; - FILETIME atime, mtime; -#else - int result; -#endif - - PyObject *return_value = NULL; - utime_t utime; - - memset(&utime, 0, sizeof(utime_t)); - - if (times && (times != Py_None) && ns) { - PyErr_SetString(PyExc_ValueError, - "utime: you may specify either 'times'" - " or 'ns' but not both"); - goto exit; - } - - if (times && (times != Py_None)) { - time_t a_sec, m_sec; - long a_nsec, m_nsec; - if (!PyTuple_CheckExact(times) || (PyTuple_Size(times) != 2)) { - PyErr_SetString(PyExc_TypeError, - "utime: 'times' must be either" - " a tuple of two ints or None"); - goto exit; - } - utime.now = 0; - if (_PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 0), - &a_sec, &a_nsec, _PyTime_ROUND_FLOOR) == -1 || - _PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 1), - &m_sec, &m_nsec, _PyTime_ROUND_FLOOR) == -1) { - goto exit; - } - utime.atime_s = a_sec; - utime.atime_ns = a_nsec; - utime.mtime_s = m_sec; - utime.mtime_ns = m_nsec; - } - else if (ns) { - if (!PyTuple_CheckExact(ns) || (PyTuple_Size(ns) != 2)) { - PyErr_SetString(PyExc_TypeError, - "utime: 'ns' must be a tuple of two ints"); - goto exit; - } - utime.now = 0; - if (!split_py_long_to_s_and_ns(PyTuple_GET_ITEM(ns, 0), - &utime.atime_s, &utime.atime_ns) || - !split_py_long_to_s_and_ns(PyTuple_GET_ITEM(ns, 1), - &utime.mtime_s, &utime.mtime_ns)) { - goto exit; - } - } - else { - /* times and ns are both None/unspecified. use "now". */ - utime.now = 1; - } - -#if !UTIME_HAVE_NOFOLLOW_SYMLINKS - if (follow_symlinks_specified("utime", follow_symlinks)) - goto exit; -#endif - - if (path_and_dir_fd_invalid("utime", path, dir_fd) || - dir_fd_and_fd_invalid("utime", dir_fd, path->fd) || - fd_and_follow_symlinks_invalid("utime", path->fd, follow_symlinks)) - goto exit; - -#if !defined(HAVE_UTIMENSAT) - if ((dir_fd != DEFAULT_DIR_FD) && (!follow_symlinks)) { - PyErr_SetString(PyExc_ValueError, - "utime: cannot use dir_fd and follow_symlinks " - "together on this platform"); - goto exit; - } -#endif - -#ifdef MS_WINDOWS - Py_BEGIN_ALLOW_THREADS - if (path->wide) - hFile = CreateFileW(path->wide, FILE_WRITE_ATTRIBUTES, 0, - NULL, OPEN_EXISTING, - FILE_FLAG_BACKUP_SEMANTICS, NULL); - else - hFile = CreateFileA(path->narrow, FILE_WRITE_ATTRIBUTES, 0, - NULL, OPEN_EXISTING, - FILE_FLAG_BACKUP_SEMANTICS, NULL); - Py_END_ALLOW_THREADS - if (hFile == INVALID_HANDLE_VALUE) { - path_error(path); - goto exit; - } - - if (utime.now) { - GetSystemTimeAsFileTime(&mtime); - atime = mtime; - } - else { - _Py_time_t_to_FILE_TIME(utime.atime_s, utime.atime_ns, &atime); - _Py_time_t_to_FILE_TIME(utime.mtime_s, utime.mtime_ns, &mtime); - } - if (!SetFileTime(hFile, NULL, &atime, &mtime)) { - /* Avoid putting the file name into the error here, - as that may confuse the user into believing that - something is wrong with the file, when it also - could be the time stamp that gives a problem. */ - PyErr_SetFromWindowsErr(0); - goto exit; - } -#else /* MS_WINDOWS */ - Py_BEGIN_ALLOW_THREADS - -#if UTIME_HAVE_NOFOLLOW_SYMLINKS - if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD)) - result = utime_nofollow_symlinks(&utime, path->narrow); - else -#endif - -#if UTIME_HAVE_DIR_FD - if ((dir_fd != DEFAULT_DIR_FD) || (!follow_symlinks)) - result = utime_dir_fd(&utime, dir_fd, path->narrow, follow_symlinks); - else -#endif - -#if UTIME_HAVE_FD - if (path->fd != -1) - result = utime_fd(&utime, path->fd); - else -#endif - - result = utime_default(&utime, path->narrow); - - Py_END_ALLOW_THREADS - - if (result < 0) { - /* see previous comment about not putting filename in error here */ - return_value = posix_error(); - goto exit; - } - -#endif /* MS_WINDOWS */ - - Py_INCREF(Py_None); - return_value = Py_None; - -exit: -#ifdef MS_WINDOWS - if (hFile != INVALID_HANDLE_VALUE) - CloseHandle(hFile); -#endif - return return_value; -} - -/* Process operations */ - - -/*[clinic input] -os._exit - - status: int - -Exit to the system with specified status, without normal exit processing. -[clinic start generated code]*/ - PyDoc_STRVAR(os__exit__doc__, "_exit($module, /, status)\n" "--\n" @@ -6291,161 +1527,7 @@ return return_value; } -static PyObject * -os__exit_impl(PyModuleDef *module, int status) -/*[clinic end generated code: output=4f9858c4cc2dcb89 input=5e6d57556b0c4a62]*/ -{ - _exit(status); - return NULL; /* Make gcc -Wall happy */ -} - -#if defined(HAVE_EXECV) || defined(HAVE_SPAWNV) -static void -free_string_array(char **array, Py_ssize_t count) -{ - Py_ssize_t i; - for (i = 0; i < count; i++) - PyMem_Free(array[i]); - PyMem_DEL(array); -} - -static -int fsconvert_strdup(PyObject *o, char**out) -{ - PyObject *bytes; - Py_ssize_t size; - if (!PyUnicode_FSConverter(o, &bytes)) - return 0; - size = PyBytes_GET_SIZE(bytes); - *out = PyMem_Malloc(size+1); - if (!*out) { - PyErr_NoMemory(); - return 0; - } - memcpy(*out, PyBytes_AsString(bytes), size+1); - Py_DECREF(bytes); - return 1; -} -#endif - -#if defined(HAVE_EXECV) || defined (HAVE_FEXECVE) -static char** -parse_envlist(PyObject* env, Py_ssize_t *envc_ptr) -{ - char **envlist; - Py_ssize_t i, pos, envc; - PyObject *keys=NULL, *vals=NULL; - PyObject *key, *val, *key2, *val2; - char *p, *k, *v; - size_t len; - - i = PyMapping_Size(env); - if (i < 0) - return NULL; - envlist = PyMem_NEW(char *, i + 1); - if (envlist == NULL) { - PyErr_NoMemory(); - return NULL; - } - envc = 0; - keys = PyMapping_Keys(env); - if (!keys) - goto error; - vals = PyMapping_Values(env); - if (!vals) - goto error; - if (!PyList_Check(keys) || !PyList_Check(vals)) { - PyErr_Format(PyExc_TypeError, - "env.keys() or env.values() is not a list"); - goto error; - } - - for (pos = 0; pos < i; pos++) { - key = PyList_GetItem(keys, pos); - val = PyList_GetItem(vals, pos); - if (!key || !val) - goto error; - - if (PyUnicode_FSConverter(key, &key2) == 0) - goto error; - if (PyUnicode_FSConverter(val, &val2) == 0) { - Py_DECREF(key2); - goto error; - } - - k = PyBytes_AsString(key2); - v = PyBytes_AsString(val2); - len = PyBytes_GET_SIZE(key2) + PyBytes_GET_SIZE(val2) + 2; - - p = PyMem_NEW(char, len); - if (p == NULL) { - PyErr_NoMemory(); - Py_DECREF(key2); - Py_DECREF(val2); - goto error; - } - PyOS_snprintf(p, len, "%s=%s", k, v); - envlist[envc++] = p; - Py_DECREF(key2); - Py_DECREF(val2); - } - Py_DECREF(vals); - Py_DECREF(keys); - - envlist[envc] = 0; - *envc_ptr = envc; - return envlist; - -error: - Py_XDECREF(keys); - Py_XDECREF(vals); - while (--envc >= 0) - PyMem_DEL(envlist[envc]); - PyMem_DEL(envlist); - return NULL; -} - -static char** -parse_arglist(PyObject* argv, Py_ssize_t *argc) -{ - int i; - char **argvlist = PyMem_NEW(char *, *argc+1); - if (argvlist == NULL) { - PyErr_NoMemory(); - return NULL; - } - for (i = 0; i < *argc; i++) { - PyObject* item = PySequence_ITEM(argv, i); - if (item == NULL) - goto fail; - if (!fsconvert_strdup(item, &argvlist[i])) { - Py_DECREF(item); - goto fail; - } - Py_DECREF(item); - } - argvlist[*argc] = NULL; - return argvlist; -fail: - *argc = i; - free_string_array(argvlist, *argc); - return NULL; -} -#endif - - -#ifdef HAVE_EXECV -/*[clinic input] -os.execv - - path: FSConverter - Path of executable file. - argv: object - Tuple or list of strings. - / - -Execute an executable path with arguments, replacing current process. -[clinic start generated code]*/ +#if defined(HAVE_EXECV) PyDoc_STRVAR(os_execv__doc__, "execv($module, path, argv, /)\n" @@ -6484,55 +1566,9 @@ return return_value; } -static PyObject * -os_execv_impl(PyModuleDef *module, PyObject *path, PyObject *argv) -/*[clinic end generated code: output=b0f5f2caa6097edc input=96041559925e5229]*/ -{ - char *path_char; - char **argvlist; - Py_ssize_t argc; - - /* execv has two arguments: (path, argv), where - argv is a list or tuple of strings. */ - - path_char = PyBytes_AsString(path); - if (!PyList_Check(argv) && !PyTuple_Check(argv)) { - PyErr_SetString(PyExc_TypeError, - "execv() arg 2 must be a tuple or list"); - return NULL; - } - argc = PySequence_Size(argv); - if (argc < 1) { - PyErr_SetString(PyExc_ValueError, "execv() arg 2 must not be empty"); - return NULL; - } - - argvlist = parse_arglist(argv, &argc); - if (argvlist == NULL) { - return NULL; - } - - execv(path_char, argvlist); - - /* If we get here it's definitely an error */ - - free_string_array(argvlist, argc); - return posix_error(); -} - - -/*[clinic input] -os.execve - - path: path_t(allow_fd='PATH_HAVE_FEXECVE') - Path of executable file. - argv: object - Tuple or list of strings. - env: object - Dictionary of strings mapping to strings. - -Execute an executable path with arguments, replacing current process. -[clinic start generated code]*/ +#endif /* defined(HAVE_EXECV) */ + +#if defined(HAVE_EXECV) PyDoc_STRVAR(os_execve__doc__, "execve($module, /, path, argv, env)\n" @@ -6575,75 +1611,9 @@ return return_value; } -static PyObject * -os_execve_impl(PyModuleDef *module, path_t *path, PyObject *argv, PyObject *env) -/*[clinic end generated code: output=fb283760f5d15ab7 input=626804fa092606d9]*/ -{ - char **argvlist = NULL; - char **envlist; - Py_ssize_t argc, envc; - - /* execve has three arguments: (path, argv, env), where - argv is a list or tuple of strings and env is a dictionary - like posix.environ. */ - - if (!PyList_Check(argv) && !PyTuple_Check(argv)) { - PyErr_SetString(PyExc_TypeError, - "execve: argv must be a tuple or list"); - goto fail; - } - argc = PySequence_Size(argv); - if (!PyMapping_Check(env)) { - PyErr_SetString(PyExc_TypeError, - "execve: environment must be a mapping object"); - goto fail; - } - - argvlist = parse_arglist(argv, &argc); - if (argvlist == NULL) { - goto fail; - } - - envlist = parse_envlist(env, &envc); - if (envlist == NULL) - goto fail; - -#ifdef HAVE_FEXECVE - if (path->fd > -1) - fexecve(path->fd, argvlist, envlist); - else -#endif - execve(path->narrow, argvlist, envlist); - - /* If we get here it's definitely an error */ - - path_error(path); - - while (--envc >= 0) - PyMem_DEL(envlist[envc]); - PyMem_DEL(envlist); - fail: - if (argvlist) - free_string_array(argvlist, argc); - return NULL; -} -#endif /* HAVE_EXECV */ - - -#ifdef HAVE_SPAWNV -/*[clinic input] -os.spawnv - - mode: int - Mode of process creation. - path: FSConverter - Path of executable file. - argv: object - Tuple or list of strings. - / - -Execute the program specified by path in a new process. -[clinic start generated code]*/ +#endif /* defined(HAVE_EXECV) */ + +#if defined(HAVE_SPAWNV) PyDoc_STRVAR(os_spawnv__doc__, "spawnv($module, mode, path, argv, /)\n" @@ -6685,82 +1655,9 @@ return return_value; } -static PyObject * -os_spawnv_impl(PyModuleDef *module, int mode, PyObject *path, PyObject *argv) -/*[clinic end generated code: output=dfee6be062e780e3 input=042c91dfc1e6debc]*/ -{ - char *path_char; - char **argvlist; - int i; - Py_ssize_t argc; - Py_intptr_t spawnval; - PyObject *(*getitem)(PyObject *, Py_ssize_t); - - /* spawnv has three arguments: (mode, path, argv), where - argv is a list or tuple of strings. */ - - path_char = PyBytes_AsString(path); - if (PyList_Check(argv)) { - argc = PyList_Size(argv); - getitem = PyList_GetItem; - } - else if (PyTuple_Check(argv)) { - argc = PyTuple_Size(argv); - getitem = PyTuple_GetItem; - } - else { - PyErr_SetString(PyExc_TypeError, - "spawnv() arg 2 must be a tuple or list"); - return NULL; - } - - argvlist = PyMem_NEW(char *, argc+1); - if (argvlist == NULL) { - return PyErr_NoMemory(); - } - for (i = 0; i < argc; i++) { - if (!fsconvert_strdup((*getitem)(argv, i), - &argvlist[i])) { - free_string_array(argvlist, i); - PyErr_SetString( - PyExc_TypeError, - "spawnv() arg 2 must contain only strings"); - return NULL; - } - } - argvlist[argc] = NULL; - - if (mode == _OLD_P_OVERLAY) - mode = _P_OVERLAY; - - Py_BEGIN_ALLOW_THREADS - spawnval = _spawnv(mode, path_char, argvlist); - Py_END_ALLOW_THREADS - - free_string_array(argvlist, argc); - - if (spawnval == -1) - return posix_error(); - else - return Py_BuildValue(_Py_PARSE_INTPTR, spawnval); -} - - -/*[clinic input] -os.spawnve - - mode: int - Mode of process creation. - path: FSConverter - Path of executable file. - argv: object - Tuple or list of strings. - env: object - Dictionary of strings mapping to strings. - / - -Execute the program specified by path in a new process. -[clinic start generated code]*/ +#endif /* defined(HAVE_SPAWNV) */ + +#if defined(HAVE_SPAWNV) PyDoc_STRVAR(os_spawnve__doc__, "spawnve($module, mode, path, argv, env, /)\n" @@ -6805,95 +1702,9 @@ return return_value; } -static PyObject * -os_spawnve_impl(PyModuleDef *module, int mode, PyObject *path, PyObject *argv, PyObject *env) -/*[clinic end generated code: output=6f7df38473f63c7c input=02362fd937963f8f]*/ -{ - char *path_char; - char **argvlist; - char **envlist; - PyObject *res = NULL; - Py_ssize_t argc, i, envc; - Py_intptr_t spawnval; - PyObject *(*getitem)(PyObject *, Py_ssize_t); - Py_ssize_t lastarg = 0; - - /* spawnve has four arguments: (mode, path, argv, env), where - argv is a list or tuple of strings and env is a dictionary - like posix.environ. */ - - path_char = PyBytes_AsString(path); - if (PyList_Check(argv)) { - argc = PyList_Size(argv); - getitem = PyList_GetItem; - } - else if (PyTuple_Check(argv)) { - argc = PyTuple_Size(argv); - getitem = PyTuple_GetItem; - } - else { - PyErr_SetString(PyExc_TypeError, - "spawnve() arg 2 must be a tuple or list"); - goto fail_0; - } - if (!PyMapping_Check(env)) { - PyErr_SetString(PyExc_TypeError, - "spawnve() arg 3 must be a mapping object"); - goto fail_0; - } - - argvlist = PyMem_NEW(char *, argc+1); - if (argvlist == NULL) { - PyErr_NoMemory(); - goto fail_0; - } - for (i = 0; i < argc; i++) { - if (!fsconvert_strdup((*getitem)(argv, i), - &argvlist[i])) - { - lastarg = i; - goto fail_1; - } - } - lastarg = argc; - argvlist[argc] = NULL; - - envlist = parse_envlist(env, &envc); - if (envlist == NULL) - goto fail_1; - - if (mode == _OLD_P_OVERLAY) - mode = _P_OVERLAY; - - Py_BEGIN_ALLOW_THREADS - spawnval = _spawnve(mode, path_char, argvlist, envlist); - Py_END_ALLOW_THREADS - - if (spawnval == -1) - (void) posix_error(); - else - res = Py_BuildValue(_Py_PARSE_INTPTR, spawnval); - - while (--envc >= 0) - PyMem_DEL(envlist[envc]); - PyMem_DEL(envlist); - fail_1: - free_string_array(argvlist, lastarg); - fail_0: - return res; -} - -#endif /* HAVE_SPAWNV */ - - -#ifdef HAVE_FORK1 -/*[clinic input] -os.fork1 - -Fork a child process with a single multiplexed (i.e., not bound) thread. - -Return 0 to child process and PID of child to parent process. -[clinic start generated code]*/ +#endif /* defined(HAVE_SPAWNV) */ + +#if defined(HAVE_FORK1) PyDoc_STRVAR(os_fork1__doc__, "fork1($module, /)\n" @@ -6915,42 +1726,9 @@ return os_fork1_impl(module); } -static PyObject * -os_fork1_impl(PyModuleDef *module) -/*[clinic end generated code: output=fa04088d6bc02efa input=12db02167893926e]*/ -{ - pid_t pid; - int result = 0; - _PyImport_AcquireLock(); - pid = fork1(); - if (pid == 0) { - /* child: this clobbers and resets the import lock. */ - PyOS_AfterFork(); - } else { - /* parent: release the import lock. */ - result = _PyImport_ReleaseLock(); - } - if (pid == -1) - return posix_error(); - if (result < 0) { - /* Don't clobber the OSError if the fork failed. */ - PyErr_SetString(PyExc_RuntimeError, - "not holding the import lock"); - return NULL; - } - return PyLong_FromPid(pid); -} -#endif /* HAVE_FORK1 */ - - -#ifdef HAVE_FORK -/*[clinic input] -os.fork - -Fork a child process. - -Return 0 to child process and PID of child to parent process. -[clinic start generated code]*/ +#endif /* defined(HAVE_FORK1) */ + +#if defined(HAVE_FORK) PyDoc_STRVAR(os_fork__doc__, "fork($module, /)\n" @@ -6972,43 +1750,9 @@ return os_fork_impl(module); } -static PyObject * -os_fork_impl(PyModuleDef *module) -/*[clinic end generated code: output=b3c8e6bdc11eedc6 input=13c956413110eeaa]*/ -{ - pid_t pid; - int result = 0; - _PyImport_AcquireLock(); - pid = fork(); - if (pid == 0) { - /* child: this clobbers and resets the import lock. */ - PyOS_AfterFork(); - } else { - /* parent: release the import lock. */ - result = _PyImport_ReleaseLock(); - } - if (pid == -1) - return posix_error(); - if (result < 0) { - /* Don't clobber the OSError if the fork failed. */ - PyErr_SetString(PyExc_RuntimeError, - "not holding the import lock"); - return NULL; - } - return PyLong_FromPid(pid); -} -#endif /* HAVE_FORK */ - - -#ifdef HAVE_SCHED_H -#ifdef HAVE_SCHED_GET_PRIORITY_MAX -/*[clinic input] -os.sched_get_priority_max - - policy: int - -Get the maximum scheduling priority for policy. -[clinic start generated code]*/ +#endif /* defined(HAVE_FORK) */ + +#if defined(HAVE_SCHED_H) && defined(HAVE_SCHED_GET_PRIORITY_MAX) PyDoc_STRVAR(os_sched_get_priority_max__doc__, "sched_get_priority_max($module, /, policy)\n" @@ -7039,26 +1783,9 @@ return return_value; } -static PyObject * -os_sched_get_priority_max_impl(PyModuleDef *module, int policy) -/*[clinic end generated code: output=a580a52f25238c1f input=2097b7998eca6874]*/ -{ - int max; - - max = sched_get_priority_max(policy); - if (max < 0) - return posix_error(); - return PyLong_FromLong(max); -} - - -/*[clinic input] -os.sched_get_priority_min - - policy: int - -Get the minimum scheduling priority for policy. -[clinic start generated code]*/ +#endif /* defined(HAVE_SCHED_H) && defined(HAVE_SCHED_GET_PRIORITY_MAX) */ + +#if defined(HAVE_SCHED_H) && defined(HAVE_SCHED_GET_PRIORITY_MAX) PyDoc_STRVAR(os_sched_get_priority_min__doc__, "sched_get_priority_min($module, /, policy)\n" @@ -7089,28 +1816,9 @@ return return_value; } -static PyObject * -os_sched_get_priority_min_impl(PyModuleDef *module, int policy) -/*[clinic end generated code: output=bad8ba10e7d0e977 input=21bc8fa0d70983bf]*/ -{ - int min = sched_get_priority_min(policy); - if (min < 0) - return posix_error(); - return PyLong_FromLong(min); -} -#endif /* HAVE_SCHED_GET_PRIORITY_MAX */ - - -#ifdef HAVE_SCHED_SETSCHEDULER -/*[clinic input] -os.sched_getscheduler - pid: pid_t - / - -Get the scheduling policy for the process identifiedy by pid. - -Passing 0 for pid returns the scheduling policy for the calling process. -[clinic start generated code]*/ +#endif /* defined(HAVE_SCHED_H) && defined(HAVE_SCHED_GET_PRIORITY_MAX) */ + +#if defined(HAVE_SCHED_H) && defined(HAVE_SCHED_SETSCHEDULER) PyDoc_STRVAR(os_sched_getscheduler__doc__, "sched_getscheduler($module, pid, /)\n" @@ -7142,32 +1850,9 @@ return return_value; } -static PyObject * -os_sched_getscheduler_impl(PyModuleDef *module, pid_t pid) -/*[clinic end generated code: output=e0d6244207b1d828 input=5f14cfd1f189e1a0]*/ -{ - int policy; - - policy = sched_getscheduler(pid); - if (policy < 0) - return posix_error(); - return PyLong_FromLong(policy); -} -#endif /* HAVE_SCHED_SETSCHEDULER */ - - -#if defined(HAVE_SCHED_SETSCHEDULER) || defined(HAVE_SCHED_SETPARAM) -/*[clinic input] -class os.sched_param "PyObject *" "&SchedParamType" - - at classmethod -os.sched_param.__new__ - - sched_priority: object - A scheduling parameter. - -Current has only one field: sched_priority"); -[clinic start generated code]*/ +#endif /* defined(HAVE_SCHED_H) && defined(HAVE_SCHED_SETSCHEDULER) */ + +#if defined(HAVE_SCHED_H) && (defined(HAVE_SCHED_SETSCHEDULER) || defined(HAVE_SCHED_SETPARAM)) PyDoc_STRVAR(os_sched_param__doc__, "sched_param(sched_priority)\n" @@ -7198,69 +1883,9 @@ return return_value; } -static PyObject * -os_sched_param_impl(PyTypeObject *type, PyObject *sched_priority) -/*[clinic end generated code: output=d3791e345f7fe573 input=73a4c22f7071fc62]*/ -{ - PyObject *res; - - res = PyStructSequence_New(type); - if (!res) - return NULL; - Py_INCREF(sched_priority); - PyStructSequence_SET_ITEM(res, 0, sched_priority); - return res; -} - - -static PyStructSequence_Field sched_param_fields[] = { - {"sched_priority", "the scheduling priority"}, - {0} -}; - -static PyStructSequence_Desc sched_param_desc = { - "sched_param", /* name */ - os_sched_param__doc__, /* doc */ - sched_param_fields, - 1 -}; - -static int -convert_sched_param(PyObject *param, struct sched_param *res) -{ - long priority; - - if (Py_TYPE(param) != &SchedParamType) { - PyErr_SetString(PyExc_TypeError, "must have a sched_param object"); - return 0; - } - priority = PyLong_AsLong(PyStructSequence_GET_ITEM(param, 0)); - if (priority == -1 && PyErr_Occurred()) - return 0; - if (priority > INT_MAX || priority < INT_MIN) { - PyErr_SetString(PyExc_OverflowError, "sched_priority out of range"); - return 0; - } - res->sched_priority = Py_SAFE_DOWNCAST(priority, long, int); - return 1; -} -#endif /* defined(HAVE_SCHED_SETSCHEDULER) || defined(HAVE_SCHED_SETPARAM) */ - - -#ifdef HAVE_SCHED_SETSCHEDULER -/*[clinic input] -os.sched_setscheduler - - pid: pid_t - policy: int - param: sched_param - / - -Set the scheduling policy for the process identified by pid. - -If pid is 0, the calling process is changed. -param is an instance of sched_param. -[clinic start generated code]*/ +#endif /* defined(HAVE_SCHED_H) && (defined(HAVE_SCHED_SETSCHEDULER) || defined(HAVE_SCHED_SETPARAM)) */ + +#if defined(HAVE_SCHED_H) && defined(HAVE_SCHED_SETSCHEDULER) PyDoc_STRVAR(os_sched_setscheduler__doc__, "sched_setscheduler($module, pid, policy, param, /)\n" @@ -7295,33 +1920,9 @@ return return_value; } -static PyObject * -os_sched_setscheduler_impl(PyModuleDef *module, pid_t pid, int policy, struct sched_param *param) -/*[clinic end generated code: output=36abdb73f81c224f input=c581f9469a5327dd]*/ -{ - /* - ** sched_setscheduler() returns 0 in Linux, but the previous - ** scheduling policy under Solaris/Illumos, and others. - ** On error, -1 is returned in all Operating Systems. - */ - if (sched_setscheduler(pid, policy, param) == -1) - return posix_error(); - Py_RETURN_NONE; -} -#endif /* HAVE_SCHED_SETSCHEDULER*/ - - -#ifdef HAVE_SCHED_SETPARAM -/*[clinic input] -os.sched_getparam - pid: pid_t - / - -Returns scheduling parameters for the process identified by pid. - -If pid is 0, returns parameters for the calling process. -Return value is an instance of sched_param. -[clinic start generated code]*/ +#endif /* defined(HAVE_SCHED_H) && defined(HAVE_SCHED_SETSCHEDULER) */ + +#if defined(HAVE_SCHED_H) && defined(HAVE_SCHED_SETPARAM) PyDoc_STRVAR(os_sched_getparam__doc__, "sched_getparam($module, pid, /)\n" @@ -7354,40 +1955,9 @@ return return_value; } -static PyObject * -os_sched_getparam_impl(PyModuleDef *module, pid_t pid) -/*[clinic end generated code: output=b33acc8db004a8c9 input=18a1ef9c2efae296]*/ -{ - struct sched_param param; - PyObject *result; - PyObject *priority; - - if (sched_getparam(pid, ¶m)) - return posix_error(); - result = PyStructSequence_New(&SchedParamType); - if (!result) - return NULL; - priority = PyLong_FromLong(param.sched_priority); - if (!priority) { - Py_DECREF(result); - return NULL; - } - PyStructSequence_SET_ITEM(result, 0, priority); - return result; -} - - -/*[clinic input] -os.sched_setparam - pid: pid_t - param: sched_param - / - -Set scheduling parameters for the process identified by pid. - -If pid is 0, sets parameters for the calling process. -param should be an instance of sched_param. -[clinic start generated code]*/ +#endif /* defined(HAVE_SCHED_H) && defined(HAVE_SCHED_SETPARAM) */ + +#if defined(HAVE_SCHED_H) && defined(HAVE_SCHED_SETPARAM) PyDoc_STRVAR(os_sched_setparam__doc__, "sched_setparam($module, pid, param, /)\n" @@ -7421,27 +1991,9 @@ return return_value; } -static PyObject * -os_sched_setparam_impl(PyModuleDef *module, pid_t pid, struct sched_param *param) -/*[clinic end generated code: output=488bdf5bcbe0d4e8 input=6b8d6dfcecdc21bd]*/ -{ - if (sched_setparam(pid, param)) - return posix_error(); - Py_RETURN_NONE; -} -#endif /* HAVE_SCHED_SETPARAM */ - - -#ifdef HAVE_SCHED_RR_GET_INTERVAL -/*[clinic input] -os.sched_rr_get_interval -> double - pid: pid_t - / - -Return the round-robin quantum for the process identified by pid, in seconds. - -Value returned is a float. -[clinic start generated code]*/ +#endif /* defined(HAVE_SCHED_H) && defined(HAVE_SCHED_SETPARAM) */ + +#if defined(HAVE_SCHED_H) && defined(HAVE_SCHED_RR_GET_INTERVAL) PyDoc_STRVAR(os_sched_rr_get_interval__doc__, "sched_rr_get_interval($module, pid, /)\n" @@ -7477,25 +2029,9 @@ return return_value; } -static double -os_sched_rr_get_interval_impl(PyModuleDef *module, pid_t pid) -/*[clinic end generated code: output=5b3b8d1f27fb2c0a input=2a973da15cca6fae]*/ -{ - struct timespec interval; - if (sched_rr_get_interval(pid, &interval)) { - posix_error(); - return -1.0; - } - return (double)interval.tv_sec + 1e-9*interval.tv_nsec; -} -#endif /* HAVE_SCHED_RR_GET_INTERVAL */ - - -/*[clinic input] -os.sched_yield - -Voluntarily relinquish the CPU. -[clinic start generated code]*/ +#endif /* defined(HAVE_SCHED_H) && defined(HAVE_SCHED_RR_GET_INTERVAL) */ + +#if defined(HAVE_SCHED_H) PyDoc_STRVAR(os_sched_yield__doc__, "sched_yield($module, /)\n" @@ -7515,29 +2051,9 @@ return os_sched_yield_impl(module); } -static PyObject * -os_sched_yield_impl(PyModuleDef *module) -/*[clinic end generated code: output=9d2e5f29f1370324 input=e54d6f98189391d4]*/ -{ - if (sched_yield()) - return posix_error(); - Py_RETURN_NONE; -} - -#ifdef HAVE_SCHED_SETAFFINITY -/* The minimum number of CPUs allocated in a cpu_set_t */ -static const int NCPUS_START = sizeof(unsigned long) * CHAR_BIT; - -/*[clinic input] -os.sched_setaffinity - pid: pid_t - mask : object - / - -Set the CPU affinity of the process identified by pid to mask. - -mask should be an iterable of integers identifying CPUs. -[clinic start generated code]*/ +#endif /* defined(HAVE_SCHED_H) */ + +#if defined(HAVE_SCHED_H) && defined(HAVE_SCHED_SETAFFINITY) PyDoc_STRVAR(os_sched_setaffinity__doc__, "sched_setaffinity($module, pid, mask, /)\n" @@ -7570,101 +2086,9 @@ return return_value; } -static PyObject * -os_sched_setaffinity_impl(PyModuleDef *module, pid_t pid, PyObject *mask) -/*[clinic end generated code: output=5199929738130196 input=a0791a597c7085ba]*/ -{ - int ncpus; - size_t setsize; - cpu_set_t *cpu_set = NULL; - PyObject *iterator = NULL, *item; - - iterator = PyObject_GetIter(mask); - if (iterator == NULL) - return NULL; - - ncpus = NCPUS_START; - setsize = CPU_ALLOC_SIZE(ncpus); - cpu_set = CPU_ALLOC(ncpus); - if (cpu_set == NULL) { - PyErr_NoMemory(); - goto error; - } - CPU_ZERO_S(setsize, cpu_set); - - while ((item = PyIter_Next(iterator))) { - long cpu; - if (!PyLong_Check(item)) { - PyErr_Format(PyExc_TypeError, - "expected an iterator of ints, " - "but iterator yielded %R", - Py_TYPE(item)); - Py_DECREF(item); - goto error; - } - cpu = PyLong_AsLong(item); - Py_DECREF(item); - if (cpu < 0) { - if (!PyErr_Occurred()) - PyErr_SetString(PyExc_ValueError, "negative CPU number"); - goto error; - } - if (cpu > INT_MAX - 1) { - PyErr_SetString(PyExc_OverflowError, "CPU number too large"); - goto error; - } - if (cpu >= ncpus) { - /* Grow CPU mask to fit the CPU number */ - int newncpus = ncpus; - cpu_set_t *newmask; - size_t newsetsize; - while (newncpus <= cpu) { - if (newncpus > INT_MAX / 2) - newncpus = cpu + 1; - else - newncpus = newncpus * 2; - } - newmask = CPU_ALLOC(newncpus); - if (newmask == NULL) { - PyErr_NoMemory(); - goto error; - } - newsetsize = CPU_ALLOC_SIZE(newncpus); - CPU_ZERO_S(newsetsize, newmask); - memcpy(newmask, cpu_set, setsize); - CPU_FREE(cpu_set); - setsize = newsetsize; - cpu_set = newmask; - ncpus = newncpus; - } - CPU_SET_S(cpu, setsize, cpu_set); - } - Py_CLEAR(iterator); - - if (sched_setaffinity(pid, setsize, cpu_set)) { - posix_error(); - goto error; - } - CPU_FREE(cpu_set); - Py_RETURN_NONE; - -error: - if (cpu_set) - CPU_FREE(cpu_set); - Py_XDECREF(iterator); - return NULL; -} - - -/*[clinic input] -os.sched_getaffinity - pid: pid_t - / - -Return the affinity of the process identified by pid. - -The affinity is returned as a set of CPU identifiers. -[clinic start generated code]*/ +#endif /* defined(HAVE_SCHED_H) && defined(HAVE_SCHED_SETAFFINITY) */ + +#if defined(HAVE_SCHED_H) && defined(HAVE_SCHED_SETAFFINITY) PyDoc_STRVAR(os_sched_getaffinity__doc__, "sched_getaffinity($module, pid, /)\n" @@ -7696,141 +2120,9 @@ return return_value; } -static PyObject * -os_sched_getaffinity_impl(PyModuleDef *module, pid_t pid) -/*[clinic end generated code: output=7b273b0fca9830f0 input=eaf161936874b8a1]*/ -{ - int cpu, ncpus, count; - size_t setsize; - cpu_set_t *mask = NULL; - PyObject *res = NULL; - - ncpus = NCPUS_START; - while (1) { - setsize = CPU_ALLOC_SIZE(ncpus); - mask = CPU_ALLOC(ncpus); - if (mask == NULL) - return PyErr_NoMemory(); - if (sched_getaffinity(pid, setsize, mask) == 0) - break; - CPU_FREE(mask); - if (errno != EINVAL) - return posix_error(); - if (ncpus > INT_MAX / 2) { - PyErr_SetString(PyExc_OverflowError, "could not allocate " - "a large enough CPU set"); - return NULL; - } - ncpus = ncpus * 2; - } - - res = PySet_New(NULL); - if (res == NULL) - goto error; - for (cpu = 0, count = CPU_COUNT_S(setsize, mask); count; cpu++) { - if (CPU_ISSET_S(cpu, setsize, mask)) { - PyObject *cpu_num = PyLong_FromLong(cpu); - --count; - if (cpu_num == NULL) - goto error; - if (PySet_Add(res, cpu_num)) { - Py_DECREF(cpu_num); - goto error; - } - Py_DECREF(cpu_num); - } - } - CPU_FREE(mask); - return res; - -error: - if (mask) - CPU_FREE(mask); - Py_XDECREF(res); - return NULL; -} - -#endif /* HAVE_SCHED_SETAFFINITY */ - -#endif /* HAVE_SCHED_H */ - -#ifndef OS_SCHED_GET_PRIORITY_MAX_METHODDEF -#define OS_SCHED_GET_PRIORITY_MAX_METHODDEF -#endif /* OS_SCHED_GET_PRIORITY_MAX_METHODDEF */ - -#ifndef OS_SCHED_GET_PRIORITY_MIN_METHODDEF -#define OS_SCHED_GET_PRIORITY_MIN_METHODDEF -#endif /* OS_SCHED_GET_PRIORITY_MIN_METHODDEF */ - -#ifndef OS_SCHED_GETSCHEDULER_METHODDEF -#define OS_SCHED_GETSCHEDULER_METHODDEF -#endif /* OS_SCHED_GETSCHEDULER_METHODDEF */ - -#ifndef OS_SCHED_SETSCHEDULER_METHODDEF -#define OS_SCHED_SETSCHEDULER_METHODDEF -#endif /* OS_SCHED_SETSCHEDULER_METHODDEF */ - -#ifndef OS_SCHED_GETPARAM_METHODDEF -#define OS_SCHED_GETPARAM_METHODDEF -#endif /* OS_SCHED_GETPARAM_METHODDEF */ - -#ifndef OS_SCHED_SETPARAM_METHODDEF -#define OS_SCHED_SETPARAM_METHODDEF -#endif /* OS_SCHED_SETPARAM_METHODDEF */ - -#ifndef OS_SCHED_RR_GET_INTERVAL_METHODDEF -#define OS_SCHED_RR_GET_INTERVAL_METHODDEF -#endif /* OS_SCHED_RR_GET_INTERVAL_METHODDEF */ - -#ifndef OS_SCHED_YIELD_METHODDEF -#define OS_SCHED_YIELD_METHODDEF -#endif /* OS_SCHED_YIELD_METHODDEF */ - -#ifndef OS_SCHED_SETAFFINITY_METHODDEF -#define OS_SCHED_SETAFFINITY_METHODDEF -#endif /* OS_SCHED_SETAFFINITY_METHODDEF */ - -#ifndef OS_SCHED_GETAFFINITY_METHODDEF -#define OS_SCHED_GETAFFINITY_METHODDEF -#endif /* OS_SCHED_GETAFFINITY_METHODDEF */ - - -/* AIX uses /dev/ptc but is otherwise the same as /dev/ptmx */ -/* IRIX has both /dev/ptc and /dev/ptmx, use ptmx */ -#if defined(HAVE_DEV_PTC) && !defined(HAVE_DEV_PTMX) -#define DEV_PTY_FILE "/dev/ptc" -#define HAVE_DEV_PTMX -#else -#define DEV_PTY_FILE "/dev/ptmx" -#endif - -#if defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_DEV_PTMX) -#ifdef HAVE_PTY_H -#include -#else -#ifdef HAVE_LIBUTIL_H -#include -#else -#ifdef HAVE_UTIL_H -#include -#endif /* HAVE_UTIL_H */ -#endif /* HAVE_LIBUTIL_H */ -#endif /* HAVE_PTY_H */ -#ifdef HAVE_STROPTS_H -#include -#endif -#endif /* defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_DEV_PTMX */ - - -#if defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX) -/*[clinic input] -os.openpty - -Open a pseudo-terminal. - -Return a tuple of (master_fd, slave_fd) containing open file descriptors -for both the master and slave ends. -[clinic start generated code]*/ +#endif /* defined(HAVE_SCHED_H) && defined(HAVE_SCHED_SETAFFINITY) */ + +#if (defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX)) PyDoc_STRVAR(os_openpty__doc__, "openpty($module, /)\n" @@ -7853,107 +2145,9 @@ return os_openpty_impl(module); } -static PyObject * -os_openpty_impl(PyModuleDef *module) -/*[clinic end generated code: output=b12d3c1735468464 input=f3d99fd99e762907]*/ -{ - int master_fd = -1, slave_fd = -1; -#ifndef HAVE_OPENPTY - char * slave_name; -#endif -#if defined(HAVE_DEV_PTMX) && !defined(HAVE_OPENPTY) && !defined(HAVE__GETPTY) - PyOS_sighandler_t sig_saved; -#ifdef sun - extern char *ptsname(int fildes); -#endif -#endif - -#ifdef HAVE_OPENPTY - if (openpty(&master_fd, &slave_fd, NULL, NULL, NULL) != 0) - goto posix_error; - - if (_Py_set_inheritable(master_fd, 0, NULL) < 0) - goto error; - if (_Py_set_inheritable(slave_fd, 0, NULL) < 0) - goto error; - -#elif defined(HAVE__GETPTY) - slave_name = _getpty(&master_fd, O_RDWR, 0666, 0); - if (slave_name == NULL) - goto posix_error; - if (_Py_set_inheritable(master_fd, 0, NULL) < 0) - goto error; - - slave_fd = _Py_open(slave_name, O_RDWR); - if (slave_fd < 0) - goto error; - -#else - master_fd = open(DEV_PTY_FILE, O_RDWR | O_NOCTTY); /* open master */ - if (master_fd < 0) - goto posix_error; - - sig_saved = PyOS_setsig(SIGCHLD, SIG_DFL); - - /* change permission of slave */ - if (grantpt(master_fd) < 0) { - PyOS_setsig(SIGCHLD, sig_saved); - goto posix_error; - } - - /* unlock slave */ - if (unlockpt(master_fd) < 0) { - PyOS_setsig(SIGCHLD, sig_saved); - goto posix_error; - } - - PyOS_setsig(SIGCHLD, sig_saved); - - slave_name = ptsname(master_fd); /* get name of slave */ - if (slave_name == NULL) - goto posix_error; - - slave_fd = _Py_open(slave_name, O_RDWR | O_NOCTTY); /* open slave */ - if (slave_fd == -1) - goto error; - - if (_Py_set_inheritable(master_fd, 0, NULL) < 0) - goto posix_error; - -#if !defined(__CYGWIN__) && !defined(HAVE_DEV_PTC) - ioctl(slave_fd, I_PUSH, "ptem"); /* push ptem */ - ioctl(slave_fd, I_PUSH, "ldterm"); /* push ldterm */ -#ifndef __hpux - ioctl(slave_fd, I_PUSH, "ttcompat"); /* push ttcompat */ -#endif /* __hpux */ -#endif /* HAVE_CYGWIN */ -#endif /* HAVE_OPENPTY */ - - return Py_BuildValue("(ii)", master_fd, slave_fd); - -posix_error: - posix_error(); -error: - if (master_fd != -1) - close(master_fd); - if (slave_fd != -1) - close(slave_fd); - return NULL; -} -#endif /* defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX) */ - - -#ifdef HAVE_FORKPTY -/*[clinic input] -os.forkpty - -Fork a new process with a new pseudo-terminal as controlling tty. - -Returns a tuple of (pid, master_fd). -Like fork(), return pid of 0 to the child process, -and pid of child to the parent process. -To both, return fd of newly opened pseudo-terminal. -[clinic start generated code]*/ +#endif /* (defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX)) */ + +#if defined(HAVE_FORKPTY) PyDoc_STRVAR(os_forkpty__doc__, "forkpty($module, /)\n" @@ -7978,41 +2172,9 @@ return os_forkpty_impl(module); } -static PyObject * -os_forkpty_impl(PyModuleDef *module) -/*[clinic end generated code: output=d4f82958d2ed5cad input=f1f7f4bae3966010]*/ -{ - int master_fd = -1, result = 0; - pid_t pid; - - _PyImport_AcquireLock(); - pid = forkpty(&master_fd, NULL, NULL, NULL); - if (pid == 0) { - /* child: this clobbers and resets the import lock. */ - PyOS_AfterFork(); - } else { - /* parent: release the import lock. */ - result = _PyImport_ReleaseLock(); - } - if (pid == -1) - return posix_error(); - if (result < 0) { - /* Don't clobber the OSError if the fork failed. */ - PyErr_SetString(PyExc_RuntimeError, - "not holding the import lock"); - return NULL; - } - return Py_BuildValue("(Ni)", PyLong_FromPid(pid), master_fd); -} -#endif /* HAVE_FORKPTY */ - - -#ifdef HAVE_GETEGID -/*[clinic input] -os.getegid - -Return the current process's effective group id. -[clinic start generated code]*/ +#endif /* defined(HAVE_FORKPTY) */ + +#if defined(HAVE_GETEGID) PyDoc_STRVAR(os_getegid__doc__, "getegid($module, /)\n" @@ -8032,21 +2194,9 @@ return os_getegid_impl(module); } -static PyObject * -os_getegid_impl(PyModuleDef *module) -/*[clinic end generated code: output=fd12c346fa41cccb input=1596f79ad1107d5d]*/ -{ - return _PyLong_FromGid(getegid()); -} -#endif /* HAVE_GETEGID */ - - -#ifdef HAVE_GETEUID -/*[clinic input] -os.geteuid - -Return the current process's effective user id. -[clinic start generated code]*/ +#endif /* defined(HAVE_GETEGID) */ + +#if defined(HAVE_GETEUID) PyDoc_STRVAR(os_geteuid__doc__, "geteuid($module, /)\n" @@ -8066,21 +2216,9 @@ return os_geteuid_impl(module); } -static PyObject * -os_geteuid_impl(PyModuleDef *module) -/*[clinic end generated code: output=03d98e07f4bc03d4 input=4644c662d3bd9f19]*/ -{ - return _PyLong_FromUid(geteuid()); -} -#endif /* HAVE_GETEUID */ - - -#ifdef HAVE_GETGID -/*[clinic input] -os.getgid - -Return the current process's group id. -[clinic start generated code]*/ +#endif /* defined(HAVE_GETEUID) */ + +#if defined(HAVE_GETGID) PyDoc_STRVAR(os_getgid__doc__, "getgid($module, /)\n" @@ -8100,20 +2238,7 @@ return os_getgid_impl(module); } -static PyObject * -os_getgid_impl(PyModuleDef *module) -/*[clinic end generated code: output=07b0356121b8098d input=58796344cd87c0f6]*/ -{ - return _PyLong_FromGid(getgid()); -} -#endif /* HAVE_GETGID */ - - -/*[clinic input] -os.getpid - -Return the current process id. -[clinic start generated code]*/ +#endif /* defined(HAVE_GETGID) */ PyDoc_STRVAR(os_getpid__doc__, "getpid($module, /)\n" @@ -8133,97 +2258,7 @@ return os_getpid_impl(module); } -static PyObject * -os_getpid_impl(PyModuleDef *module) -/*[clinic end generated code: output=d63a01a3cebc573d input=5a9a00f0ab68aa00]*/ -{ - return PyLong_FromPid(getpid()); -} - -#ifdef HAVE_GETGROUPLIST - -/* AC 3.5: funny apple logic below */ -PyDoc_STRVAR(posix_getgrouplist__doc__, -"getgrouplist(user, group) -> list of groups to which a user belongs\n\n\ -Returns a list of groups to which a user belongs.\n\n\ - user: username to lookup\n\ - group: base group id of the user"); - -static PyObject * -posix_getgrouplist(PyObject *self, PyObject *args) -{ -#ifdef NGROUPS_MAX -#define MAX_GROUPS NGROUPS_MAX -#else - /* defined to be 16 on Solaris7, so this should be a small number */ -#define MAX_GROUPS 64 -#endif - - const char *user; - int i, ngroups; - PyObject *list; -#ifdef __APPLE__ - int *groups, basegid; -#else - gid_t *groups, basegid; -#endif - ngroups = MAX_GROUPS; - -#ifdef __APPLE__ - if (!PyArg_ParseTuple(args, "si:getgrouplist", &user, &basegid)) - return NULL; -#else - if (!PyArg_ParseTuple(args, "sO&:getgrouplist", &user, - _Py_Gid_Converter, &basegid)) - return NULL; -#endif - -#ifdef __APPLE__ - groups = PyMem_New(int, ngroups); -#else - groups = PyMem_New(gid_t, ngroups); -#endif - if (groups == NULL) - return PyErr_NoMemory(); - - if (getgrouplist(user, basegid, groups, &ngroups) == -1) { - PyMem_Del(groups); - return posix_error(); - } - - list = PyList_New(ngroups); - if (list == NULL) { - PyMem_Del(groups); - return NULL; - } - - for (i = 0; i < ngroups; i++) { -#ifdef __APPLE__ - PyObject *o = PyLong_FromUnsignedLong((unsigned long)groups[i]); -#else - PyObject *o = _PyLong_FromGid(groups[i]); -#endif - if (o == NULL) { - Py_DECREF(list); - PyMem_Del(groups); - return NULL; - } - PyList_SET_ITEM(list, i, o); - } - - PyMem_Del(groups); - - return list; -} -#endif /* HAVE_GETGROUPLIST */ - - -#ifdef HAVE_GETGROUPS -/*[clinic input] -os.getgroups - -Return list of supplemental group IDs for the process. -[clinic start generated code]*/ +#if defined(HAVE_GETGROUPS) PyDoc_STRVAR(os_getgroups__doc__, "getgroups($module, /)\n" @@ -8243,160 +2278,9 @@ return os_getgroups_impl(module); } -static PyObject * -os_getgroups_impl(PyModuleDef *module) -/*[clinic end generated code: output=d9a3559b2e6f4ab8 input=d3f109412e6a155c]*/ -{ - PyObject *result = NULL; - -#ifdef NGROUPS_MAX -#define MAX_GROUPS NGROUPS_MAX -#else - /* defined to be 16 on Solaris7, so this should be a small number */ -#define MAX_GROUPS 64 -#endif - gid_t grouplist[MAX_GROUPS]; - - /* On MacOSX getgroups(2) can return more than MAX_GROUPS results - * This is a helper variable to store the intermediate result when - * that happens. - * - * To keep the code readable the OSX behaviour is unconditional, - * according to the POSIX spec this should be safe on all unix-y - * systems. - */ - gid_t* alt_grouplist = grouplist; - int n; - -#ifdef __APPLE__ - /* Issue #17557: As of OS X 10.8, getgroups(2) no longer raises EINVAL if - * there are more groups than can fit in grouplist. Therefore, on OS X - * always first call getgroups with length 0 to get the actual number - * of groups. - */ - n = getgroups(0, NULL); - if (n < 0) { - return posix_error(); - } else if (n <= MAX_GROUPS) { - /* groups will fit in existing array */ - alt_grouplist = grouplist; - } else { - alt_grouplist = PyMem_New(gid_t, n); - if (alt_grouplist == NULL) { - errno = EINVAL; - return posix_error(); - } - } - - n = getgroups(n, alt_grouplist); - if (n == -1) { - if (alt_grouplist != grouplist) { - PyMem_Free(alt_grouplist); - } - return posix_error(); - } -#else - n = getgroups(MAX_GROUPS, grouplist); - if (n < 0) { - if (errno == EINVAL) { - n = getgroups(0, NULL); - if (n == -1) { - return posix_error(); - } - if (n == 0) { - /* Avoid malloc(0) */ - alt_grouplist = grouplist; - } else { - alt_grouplist = PyMem_New(gid_t, n); - if (alt_grouplist == NULL) { - errno = EINVAL; - return posix_error(); - } - n = getgroups(n, alt_grouplist); - if (n == -1) { - PyMem_Free(alt_grouplist); - return posix_error(); - } - } - } else { - return posix_error(); - } - } -#endif - - result = PyList_New(n); - if (result != NULL) { - int i; - for (i = 0; i < n; ++i) { - PyObject *o = _PyLong_FromGid(alt_grouplist[i]); - if (o == NULL) { - Py_DECREF(result); - result = NULL; - break; - } - PyList_SET_ITEM(result, i, o); - } - } - - if (alt_grouplist != grouplist) { - PyMem_Free(alt_grouplist); - } - - return result; -} -#endif /* HAVE_GETGROUPS */ - -#ifdef HAVE_INITGROUPS -PyDoc_STRVAR(posix_initgroups__doc__, -"initgroups(username, gid) -> None\n\n\ -Call the system initgroups() to initialize the group access list with all of\n\ -the groups of which the specified username is a member, plus the specified\n\ -group id."); - -/* AC 3.5: funny apple logic */ -static PyObject * -posix_initgroups(PyObject *self, PyObject *args) -{ - PyObject *oname; - char *username; - int res; -#ifdef __APPLE__ - int gid; -#else - gid_t gid; -#endif - -#ifdef __APPLE__ - if (!PyArg_ParseTuple(args, "O&i:initgroups", - PyUnicode_FSConverter, &oname, - &gid)) -#else - if (!PyArg_ParseTuple(args, "O&O&:initgroups", - PyUnicode_FSConverter, &oname, - _Py_Gid_Converter, &gid)) -#endif - return NULL; - username = PyBytes_AS_STRING(oname); - - res = initgroups(username, gid); - Py_DECREF(oname); - if (res == -1) - return PyErr_SetFromErrno(PyExc_OSError); - - Py_INCREF(Py_None); - return Py_None; -} -#endif /* HAVE_INITGROUPS */ - - -#ifdef HAVE_GETPGID -/*[clinic input] -os.getpgid - - pid: pid_t - -Call the system call getpgid(), and return the result. -[clinic start generated code]*/ +#endif /* defined(HAVE_GETGROUPS) */ + +#if defined(HAVE_GETPGID) PyDoc_STRVAR(os_getpgid__doc__, "getpgid($module, /, pid)\n" @@ -8427,24 +2311,9 @@ return return_value; } -static PyObject * -os_getpgid_impl(PyModuleDef *module, pid_t pid) -/*[clinic end generated code: output=3db4ed686179160d input=39d710ae3baaf1c7]*/ -{ - pid_t pgid = getpgid(pid); - if (pgid < 0) - return posix_error(); - return PyLong_FromPid(pgid); -} -#endif /* HAVE_GETPGID */ - - -#ifdef HAVE_GETPGRP -/*[clinic input] -os.getpgrp - -Return the current process group id. -[clinic start generated code]*/ +#endif /* defined(HAVE_GETPGID) */ + +#if defined(HAVE_GETPGRP) PyDoc_STRVAR(os_getpgrp__doc__, "getpgrp($module, /)\n" @@ -8464,25 +2333,9 @@ return os_getpgrp_impl(module); } -static PyObject * -os_getpgrp_impl(PyModuleDef *module) -/*[clinic end generated code: output=3b0d3663ea054277 input=6846fb2bb9a3705e]*/ -{ -#ifdef GETPGRP_HAVE_ARG - return PyLong_FromPid(getpgrp(0)); -#else /* GETPGRP_HAVE_ARG */ - return PyLong_FromPid(getpgrp()); -#endif /* GETPGRP_HAVE_ARG */ -} -#endif /* HAVE_GETPGRP */ - - -#ifdef HAVE_SETPGRP -/*[clinic input] -os.setpgrp - -Make the current process the leader of its process group. -[clinic start generated code]*/ +#endif /* defined(HAVE_GETPGRP) */ + +#if defined(HAVE_SETPGRP) PyDoc_STRVAR(os_setpgrp__doc__, "setpgrp($module, /)\n" @@ -8502,74 +2355,9 @@ return os_setpgrp_impl(module); } -static PyObject * -os_setpgrp_impl(PyModuleDef *module) -/*[clinic end generated code: output=8fbb0ee29ef6fb2d input=1f0619fcb5731e7e]*/ -{ -#ifdef SETPGRP_HAVE_ARG - if (setpgrp(0, 0) < 0) -#else /* SETPGRP_HAVE_ARG */ - if (setpgrp() < 0) -#endif /* SETPGRP_HAVE_ARG */ - return posix_error(); - Py_INCREF(Py_None); - return Py_None; -} -#endif /* HAVE_SETPGRP */ - -#ifdef HAVE_GETPPID - -#ifdef MS_WINDOWS -#include - -static PyObject* -win32_getppid() -{ - HANDLE snapshot; - pid_t mypid; - PyObject* result = NULL; - BOOL have_record; - PROCESSENTRY32 pe; - - mypid = getpid(); /* This function never fails */ - - snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); - if (snapshot == INVALID_HANDLE_VALUE) - return PyErr_SetFromWindowsErr(GetLastError()); - - pe.dwSize = sizeof(pe); - have_record = Process32First(snapshot, &pe); - while (have_record) { - if (mypid == (pid_t)pe.th32ProcessID) { - /* We could cache the ulong value in a static variable. */ - result = PyLong_FromPid((pid_t)pe.th32ParentProcessID); - break; - } - - have_record = Process32Next(snapshot, &pe); - } - - /* If our loop exits and our pid was not found (result will be NULL) - * then GetLastError will return ERROR_NO_MORE_FILES. This is an - * error anyway, so let's raise it. */ - if (!result) - result = PyErr_SetFromWindowsErr(GetLastError()); - - CloseHandle(snapshot); - - return result; -} -#endif /*MS_WINDOWS*/ - - -/*[clinic input] -os.getppid - -Return the parent's process id. - -If the parent process has already exited, Windows machines will still -return its id; others systems will return the id of the 'init' process (1). -[clinic start generated code]*/ +#endif /* defined(HAVE_SETPGRP) */ + +#if defined(HAVE_GETPPID) PyDoc_STRVAR(os_getppid__doc__, "getppid($module, /)\n" @@ -8592,25 +2380,9 @@ return os_getppid_impl(module); } -static PyObject * -os_getppid_impl(PyModuleDef *module) -/*[clinic end generated code: output=9ff3b387781edf3a input=e637cb87539c030e]*/ -{ -#ifdef MS_WINDOWS - return win32_getppid(); -#else - return PyLong_FromPid(getppid()); -#endif -} -#endif /* HAVE_GETPPID */ - - -#ifdef HAVE_GETLOGIN -/*[clinic input] -os.getlogin - -Return the actual login name. -[clinic start generated code]*/ +#endif /* defined(HAVE_GETPPID) */ + +#if defined(HAVE_GETLOGIN) PyDoc_STRVAR(os_getlogin__doc__, "getlogin($module, /)\n" @@ -8630,48 +2402,9 @@ return os_getlogin_impl(module); } -static PyObject * -os_getlogin_impl(PyModuleDef *module) -/*[clinic end generated code: output=ab6211dab104cbb2 input=2a21ab1e917163df]*/ -{ - PyObject *result = NULL; -#ifdef MS_WINDOWS - wchar_t user_name[UNLEN + 1]; - DWORD num_chars = Py_ARRAY_LENGTH(user_name); - - if (GetUserNameW(user_name, &num_chars)) { - /* num_chars is the number of unicode chars plus null terminator */ - result = PyUnicode_FromWideChar(user_name, num_chars - 1); - } - else - result = PyErr_SetFromWindowsErr(GetLastError()); -#else - char *name; - int old_errno = errno; - - errno = 0; - name = getlogin(); - if (name == NULL) { - if (errno) - posix_error(); - else - PyErr_SetString(PyExc_OSError, "unable to determine login name"); - } - else - result = PyUnicode_DecodeFSDefault(name); - errno = old_errno; -#endif - return result; -} -#endif /* HAVE_GETLOGIN */ - - -#ifdef HAVE_GETUID -/*[clinic input] -os.getuid - -Return the current process's user id. -[clinic start generated code]*/ +#endif /* defined(HAVE_GETLOGIN) */ + +#if defined(HAVE_GETUID) PyDoc_STRVAR(os_getuid__doc__, "getuid($module, /)\n" @@ -8691,29 +2424,9 @@ return os_getuid_impl(module); } -static PyObject * -os_getuid_impl(PyModuleDef *module) -/*[clinic end generated code: output=77e0dcf2e37d1e89 input=b53c8b35f110a516]*/ -{ - return _PyLong_FromUid(getuid()); -} -#endif /* HAVE_GETUID */ - - -#ifdef MS_WINDOWS -#define HAVE_KILL -#endif /* MS_WINDOWS */ - -#ifdef HAVE_KILL -/*[clinic input] -os.kill - - pid: pid_t - signal: Py_ssize_t - / - -Kill a process with a signal. -[clinic start generated code]*/ +#endif /* defined(HAVE_GETUID) */ + +#if defined(HAVE_KILL) PyDoc_STRVAR(os_kill__doc__, "kill($module, pid, signal, /)\n" @@ -8744,66 +2457,9 @@ return return_value; } -static PyObject * -os_kill_impl(PyModuleDef *module, pid_t pid, Py_ssize_t signal) -/*[clinic end generated code: output=2f5c77920ed575e6 input=61a36b86ca275ab9]*/ -#ifndef MS_WINDOWS -{ - if (kill(pid, (int)signal) == -1) - return posix_error(); - Py_RETURN_NONE; -} -#else /* !MS_WINDOWS */ -{ - PyObject *result; - DWORD sig = (DWORD)signal; - DWORD err; - HANDLE handle; - - /* Console processes which share a common console can be sent CTRL+C or - CTRL+BREAK events, provided they handle said events. */ - if (sig == CTRL_C_EVENT || sig == CTRL_BREAK_EVENT) { - if (GenerateConsoleCtrlEvent(sig, (DWORD)pid) == 0) { - err = GetLastError(); - PyErr_SetFromWindowsErr(err); - } - else - Py_RETURN_NONE; - } - - /* If the signal is outside of what GenerateConsoleCtrlEvent can use, - attempt to open and terminate the process. */ - handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, (DWORD)pid); - if (handle == NULL) { - err = GetLastError(); - return PyErr_SetFromWindowsErr(err); - } - - if (TerminateProcess(handle, sig) == 0) { - err = GetLastError(); - result = PyErr_SetFromWindowsErr(err); - } else { - Py_INCREF(Py_None); - result = Py_None; - } - - CloseHandle(handle); - return result; -} -#endif /* !MS_WINDOWS */ -#endif /* HAVE_KILL */ - - -#ifdef HAVE_KILLPG -/*[clinic input] -os.killpg - - pgid: pid_t - signal: int - / - -Kill a process group with a signal. -[clinic start generated code]*/ +#endif /* defined(HAVE_KILL) */ + +#if defined(HAVE_KILLPG) PyDoc_STRVAR(os_killpg__doc__, "killpg($module, pgid, signal, /)\n" @@ -8834,33 +2490,9 @@ return return_value; } -static PyObject * -os_killpg_impl(PyModuleDef *module, pid_t pgid, int signal) -/*[clinic end generated code: output=0e05215d1c007e01 input=38b5449eb8faec19]*/ -{ - /* XXX some man pages make the `pgid` parameter an int, others - a pid_t. Since getpgrp() returns a pid_t, we assume killpg should - take the same type. Moreover, pid_t is always at least as wide as - int (else compilation of this module fails), which is safe. */ - if (killpg(pgid, signal) == -1) - return posix_error(); - Py_RETURN_NONE; -} -#endif /* HAVE_KILLPG */ - - -#ifdef HAVE_PLOCK -#ifdef HAVE_SYS_LOCK_H -#include -#endif - -/*[clinic input] -os.plock - op: int - / - -Lock program segments into memory."); -[clinic start generated code]*/ +#endif /* defined(HAVE_KILLPG) */ + +#if defined(HAVE_PLOCK) PyDoc_STRVAR(os_plock__doc__, "plock($module, op, /)\n" @@ -8890,26 +2522,9 @@ return return_value; } -static PyObject * -os_plock_impl(PyModuleDef *module, int op) -/*[clinic end generated code: output=2744fe4b6e5f4dbc input=e6e5e348e1525f60]*/ -{ - if (plock(op) == -1) - return posix_error(); - Py_RETURN_NONE; -} -#endif /* HAVE_PLOCK */ - - -#ifdef HAVE_SETUID -/*[clinic input] -os.setuid - - uid: uid_t - / - -Set the current process's user id. -[clinic start generated code]*/ +#endif /* defined(HAVE_PLOCK) */ + +#if defined(HAVE_SETUID) PyDoc_STRVAR(os_setuid__doc__, "setuid($module, uid, /)\n" @@ -8939,26 +2554,9 @@ return return_value; } -static PyObject * -os_setuid_impl(PyModuleDef *module, uid_t uid) -/*[clinic end generated code: output=aea344bc22ccf400 input=c921a3285aa22256]*/ -{ - if (setuid(uid) < 0) - return posix_error(); - Py_RETURN_NONE; -} -#endif /* HAVE_SETUID */ - - -#ifdef HAVE_SETEUID -/*[clinic input] -os.seteuid - - euid: uid_t - / - -Set the current process's effective user id. -[clinic start generated code]*/ +#endif /* defined(HAVE_SETUID) */ + +#if defined(HAVE_SETEUID) PyDoc_STRVAR(os_seteuid__doc__, "seteuid($module, euid, /)\n" @@ -8988,26 +2586,9 @@ return return_value; } -static PyObject * -os_seteuid_impl(PyModuleDef *module, uid_t euid) -/*[clinic end generated code: output=6e824cce4f3b8a5d input=ba93d927e4781aa9]*/ -{ - if (seteuid(euid) < 0) - return posix_error(); - Py_RETURN_NONE; -} -#endif /* HAVE_SETEUID */ - - -#ifdef HAVE_SETEGID -/*[clinic input] -os.setegid - - egid: gid_t - / - -Set the current process's effective group id. -[clinic start generated code]*/ +#endif /* defined(HAVE_SETEUID) */ + +#if defined(HAVE_SETEGID) PyDoc_STRVAR(os_setegid__doc__, "setegid($module, egid, /)\n" @@ -9037,27 +2618,9 @@ return return_value; } -static PyObject * -os_setegid_impl(PyModuleDef *module, gid_t egid) -/*[clinic end generated code: output=80a32263a4d56a9c input=4080526d0ccd6ce3]*/ -{ - if (setegid(egid) < 0) - return posix_error(); - Py_RETURN_NONE; -} -#endif /* HAVE_SETEGID */ - - -#ifdef HAVE_SETREUID -/*[clinic input] -os.setreuid - - ruid: uid_t - euid: uid_t - / - -Set the current process's real and effective user ids. -[clinic start generated code]*/ +#endif /* defined(HAVE_SETEGID) */ + +#if defined(HAVE_SETREUID) PyDoc_STRVAR(os_setreuid__doc__, "setreuid($module, ruid, euid, /)\n" @@ -9088,30 +2651,9 @@ return return_value; } -static PyObject * -os_setreuid_impl(PyModuleDef *module, uid_t ruid, uid_t euid) -/*[clinic end generated code: output=d7f226f943dad739 input=0ca8978de663880c]*/ -{ - if (setreuid(ruid, euid) < 0) { - return posix_error(); - } else { - Py_INCREF(Py_None); - return Py_None; - } -} -#endif /* HAVE_SETREUID */ - - -#ifdef HAVE_SETREGID -/*[clinic input] -os.setregid - - rgid: gid_t - egid: gid_t - / - -Set the current process's real and effective group ids. -[clinic start generated code]*/ +#endif /* defined(HAVE_SETREUID) */ + +#if defined(HAVE_SETREGID) PyDoc_STRVAR(os_setregid__doc__, "setregid($module, rgid, egid, /)\n" @@ -9142,25 +2684,9 @@ return return_value; } -static PyObject * -os_setregid_impl(PyModuleDef *module, gid_t rgid, gid_t egid) -/*[clinic end generated code: output=a82d9ab70f8e6562 input=c59499f72846db78]*/ -{ - if (setregid(rgid, egid) < 0) - return posix_error(); - Py_RETURN_NONE; -} -#endif /* HAVE_SETREGID */ - - -#ifdef HAVE_SETGID -/*[clinic input] -os.setgid - gid: gid_t - / - -Set the current process's group id. -[clinic start generated code]*/ +#endif /* defined(HAVE_SETREGID) */ + +#if defined(HAVE_SETGID) PyDoc_STRVAR(os_setgid__doc__, "setgid($module, gid, /)\n" @@ -9190,26 +2716,9 @@ return return_value; } -static PyObject * -os_setgid_impl(PyModuleDef *module, gid_t gid) -/*[clinic end generated code: output=08287886db435f23 input=27d30c4059045dc6]*/ -{ - if (setgid(gid) < 0) - return posix_error(); - Py_RETURN_NONE; -} -#endif /* HAVE_SETGID */ - - -#ifdef HAVE_SETGROUPS -/*[clinic input] -os.setgroups - - groups: object - / - -Set the groups of the current process to list. -[clinic start generated code]*/ +#endif /* defined(HAVE_SETGID) */ + +#if defined(HAVE_SETGROUPS) PyDoc_STRVAR(os_setgroups__doc__, "setgroups($module, groups, /)\n" @@ -9220,120 +2729,9 @@ #define OS_SETGROUPS_METHODDEF \ {"setgroups", (PyCFunction)os_setgroups, METH_O, os_setgroups__doc__}, -static PyObject * -os_setgroups(PyModuleDef *module, PyObject *groups) -/*[clinic end generated code: output=0b8de65d5b3cda94 input=fa742ca3daf85a7e]*/ -{ - int i, len; - gid_t grouplist[MAX_GROUPS]; - - if (!PySequence_Check(groups)) { - PyErr_SetString(PyExc_TypeError, "setgroups argument must be a sequence"); - return NULL; - } - len = PySequence_Size(groups); - if (len > MAX_GROUPS) { - PyErr_SetString(PyExc_ValueError, "too many groups"); - return NULL; - } - for(i = 0; i < len; i++) { - PyObject *elem; - elem = PySequence_GetItem(groups, i); - if (!elem) - return NULL; - if (!PyLong_Check(elem)) { - PyErr_SetString(PyExc_TypeError, - "groups must be integers"); - Py_DECREF(elem); - return NULL; - } else { - if (!_Py_Gid_Converter(elem, &grouplist[i])) { - Py_DECREF(elem); - return NULL; - } - } - Py_DECREF(elem); - } - - if (setgroups(len, grouplist) < 0) - return posix_error(); - Py_INCREF(Py_None); - return Py_None; -} -#endif /* HAVE_SETGROUPS */ - -#if defined(HAVE_WAIT3) || defined(HAVE_WAIT4) -static PyObject * -wait_helper(pid_t pid, int status, struct rusage *ru) -{ - PyObject *result; - static PyObject *struct_rusage; - _Py_IDENTIFIER(struct_rusage); - - if (pid == -1) - return posix_error(); - - if (struct_rusage == NULL) { - PyObject *m = PyImport_ImportModuleNoBlock("resource"); - if (m == NULL) - return NULL; - struct_rusage = _PyObject_GetAttrId(m, &PyId_struct_rusage); - Py_DECREF(m); - if (struct_rusage == NULL) - return NULL; - } - - /* XXX(nnorwitz): Copied (w/mods) from resource.c, there should be only one. */ - result = PyStructSequence_New((PyTypeObject*) struct_rusage); - if (!result) - return NULL; - -#ifndef doubletime -#define doubletime(TV) ((double)(TV).tv_sec + (TV).tv_usec * 0.000001) -#endif - - PyStructSequence_SET_ITEM(result, 0, - PyFloat_FromDouble(doubletime(ru->ru_utime))); - PyStructSequence_SET_ITEM(result, 1, - PyFloat_FromDouble(doubletime(ru->ru_stime))); -#define SET_INT(result, index, value)\ - PyStructSequence_SET_ITEM(result, index, PyLong_FromLong(value)) - SET_INT(result, 2, ru->ru_maxrss); - SET_INT(result, 3, ru->ru_ixrss); - SET_INT(result, 4, ru->ru_idrss); - SET_INT(result, 5, ru->ru_isrss); - SET_INT(result, 6, ru->ru_minflt); - SET_INT(result, 7, ru->ru_majflt); - SET_INT(result, 8, ru->ru_nswap); - SET_INT(result, 9, ru->ru_inblock); - SET_INT(result, 10, ru->ru_oublock); - SET_INT(result, 11, ru->ru_msgsnd); - SET_INT(result, 12, ru->ru_msgrcv); - SET_INT(result, 13, ru->ru_nsignals); - SET_INT(result, 14, ru->ru_nvcsw); - SET_INT(result, 15, ru->ru_nivcsw); -#undef SET_INT - - if (PyErr_Occurred()) { - Py_DECREF(result); - return NULL; - } - - return Py_BuildValue("NiN", PyLong_FromPid(pid), status, result); -} -#endif /* HAVE_WAIT3 || HAVE_WAIT4 */ - - -#ifdef HAVE_WAIT3 -/*[clinic input] -os.wait3 - - options: int -Wait for completion of a child process. - -Returns a tuple of information about the child process: - (pid, status, rusage) -[clinic start generated code]*/ +#endif /* defined(HAVE_SETGROUPS) */ + +#if defined(HAVE_WAIT3) PyDoc_STRVAR(os_wait3__doc__, "wait3($module, /, options)\n" @@ -9367,42 +2765,9 @@ return return_value; } -static PyObject * -os_wait3_impl(PyModuleDef *module, int options) -/*[clinic end generated code: output=1f2a63b6a93cbb57 input=8ac4c56956b61710]*/ -{ - pid_t pid; - struct rusage ru; - int async_err = 0; - WAIT_TYPE status; - WAIT_STATUS_INT(status) = 0; - - do { - Py_BEGIN_ALLOW_THREADS - pid = wait3(&status, options, &ru); - Py_END_ALLOW_THREADS - } while (pid < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); - if (pid < 0) - return (!async_err) ? posix_error() : NULL; - - return wait_helper(pid, WAIT_STATUS_INT(status), &ru); -} -#endif /* HAVE_WAIT3 */ - - -#ifdef HAVE_WAIT4 -/*[clinic input] - -os.wait4 - - pid: pid_t - options: int - -Wait for completion of a specific child process. - -Returns a tuple of information about the child process: - (pid, status, rusage) -[clinic start generated code]*/ +#endif /* defined(HAVE_WAIT3) */ + +#if defined(HAVE_WAIT4) PyDoc_STRVAR(os_wait4__doc__, "wait4($module, /, pid, options)\n" @@ -9437,47 +2802,9 @@ return return_value; } -static PyObject * -os_wait4_impl(PyModuleDef *module, pid_t pid, int options) -/*[clinic end generated code: output=20dfb05289d37dc6 input=d11deed0750600ba]*/ -{ - pid_t res; - struct rusage ru; - int async_err = 0; - WAIT_TYPE status; - WAIT_STATUS_INT(status) = 0; - - do { - Py_BEGIN_ALLOW_THREADS - res = wait4(pid, &status, options, &ru); - Py_END_ALLOW_THREADS - } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); - if (res < 0) - return (!async_err) ? posix_error() : NULL; - - return wait_helper(res, WAIT_STATUS_INT(status), &ru); -} -#endif /* HAVE_WAIT4 */ - - -#if defined(HAVE_WAITID) && !defined(__APPLE__) -/*[clinic input] -os.waitid - - idtype: idtype_t - Must be one of be P_PID, P_PGID or P_ALL. - id: id_t - The id to wait on. - options: int - Constructed from the ORing of one or more of WEXITED, WSTOPPED - or WCONTINUED and additionally may be ORed with WNOHANG or WNOWAIT. - / - -Returns the result of waiting for a process or processes. - -Returns either waitid_result or None if WNOHANG is specified and there are -no children in a waitable state. -[clinic start generated code]*/ +#endif /* defined(HAVE_WAIT4) */ + +#if (defined(HAVE_WAITID) && !defined(__APPLE__)) PyDoc_STRVAR(os_waitid__doc__, "waitid($module, idtype, id, options, /)\n" @@ -9520,60 +2847,9 @@ return return_value; } -static PyObject * -os_waitid_impl(PyModuleDef *module, idtype_t idtype, id_t id, int options) -/*[clinic end generated code: output=fb44bf97f01021b2 input=d8e7f76e052b7920]*/ -{ - PyObject *result; - int res; - int async_err = 0; - siginfo_t si; - si.si_pid = 0; - - do { - Py_BEGIN_ALLOW_THREADS - res = waitid(idtype, id, &si, options); - Py_END_ALLOW_THREADS - } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); - if (res < 0) - return (!async_err) ? posix_error() : NULL; - - if (si.si_pid == 0) - Py_RETURN_NONE; - - result = PyStructSequence_New(&WaitidResultType); - if (!result) - return NULL; - - PyStructSequence_SET_ITEM(result, 0, PyLong_FromPid(si.si_pid)); - PyStructSequence_SET_ITEM(result, 1, _PyLong_FromUid(si.si_uid)); - PyStructSequence_SET_ITEM(result, 2, PyLong_FromLong((long)(si.si_signo))); - PyStructSequence_SET_ITEM(result, 3, PyLong_FromLong((long)(si.si_status))); - PyStructSequence_SET_ITEM(result, 4, PyLong_FromLong((long)(si.si_code))); - if (PyErr_Occurred()) { - Py_DECREF(result); - return NULL; - } - - return result; -} -#endif /* defined(HAVE_WAITID) && !defined(__APPLE__) */ - +#endif /* (defined(HAVE_WAITID) && !defined(__APPLE__)) */ #if defined(HAVE_WAITPID) -/*[clinic input] -os.waitpid - pid: pid_t - options: int - / - -Wait for completion of a given child process. - -Returns a tuple of information regarding the child process: - (pid, status) - -The options argument is ignored on Windows. -[clinic start generated code]*/ PyDoc_STRVAR(os_waitpid__doc__, "waitpid($module, pid, options, /)\n" @@ -9609,40 +2885,9 @@ return return_value; } -static PyObject * -os_waitpid_impl(PyModuleDef *module, pid_t pid, int options) -/*[clinic end generated code: output=095a6b00af70b7ac input=0bf1666b8758fda3]*/ -{ - pid_t res; - int async_err = 0; - WAIT_TYPE status; - WAIT_STATUS_INT(status) = 0; - - do { - Py_BEGIN_ALLOW_THREADS - res = waitpid(pid, &status, options); - Py_END_ALLOW_THREADS - } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); - if (res < 0) - return (!async_err) ? posix_error() : NULL; - - return Py_BuildValue("Ni", PyLong_FromPid(res), WAIT_STATUS_INT(status)); -} -#elif defined(HAVE_CWAIT) -/* MS C has a variant of waitpid() that's usable for most purposes. */ -/*[clinic input] -os.waitpid - pid: Py_intptr_t - options: int - / - -Wait for completion of a given process. - -Returns a tuple of information regarding the process: - (pid, status << 8) - -The options argument is ignored on Windows. -[clinic start generated code]*/ +#endif /* defined(HAVE_WAITPID) */ + +#if defined(HAVE_CWAIT) PyDoc_STRVAR(os_waitpid__doc__, "waitpid($module, pid, options, /)\n" @@ -9678,37 +2923,9 @@ return return_value; } -static PyObject * -os_waitpid_impl(PyModuleDef *module, Py_intptr_t pid, int options) -/*[clinic end generated code: output=c20b95b15ad44a3a input=444c8f51cca5b862]*/ -{ - int status; - Py_intptr_t res; - int async_err = 0; - - do { - Py_BEGIN_ALLOW_THREADS - res = _cwait(&status, pid, options); - Py_END_ALLOW_THREADS - } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); - if (res != 0) - return (!async_err) ? posix_error() : NULL; - - /* shift the status left a byte so this is more like the POSIX waitpid */ - return Py_BuildValue(_Py_PARSE_INTPTR "i", res, status << 8); -} -#endif - - -#ifdef HAVE_WAIT -/*[clinic input] -os.wait - -Wait for completion of a child process. - -Returns a tuple of information about the child process: - (pid, status) -[clinic start generated code]*/ +#endif /* defined(HAVE_CWAIT) */ + +#if defined(HAVE_WAIT) PyDoc_STRVAR(os_wait__doc__, "wait($module, /)\n" @@ -9731,333 +2948,9 @@ return os_wait_impl(module); } -static PyObject * -os_wait_impl(PyModuleDef *module) -/*[clinic end generated code: output=2a83a9d164e7e6a8 input=03b0182d4a4700ce]*/ -{ - pid_t pid; - int async_err = 0; - WAIT_TYPE status; - WAIT_STATUS_INT(status) = 0; - - do { - Py_BEGIN_ALLOW_THREADS - pid = wait(&status); - Py_END_ALLOW_THREADS - } while (pid < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); - if (pid < 0) - return (!async_err) ? posix_error() : NULL; - - return Py_BuildValue("Ni", PyLong_FromPid(pid), WAIT_STATUS_INT(status)); -} -#endif /* HAVE_WAIT */ - - -#if defined(HAVE_READLINK) || defined(MS_WINDOWS) -PyDoc_STRVAR(readlink__doc__, -"readlink(path, *, dir_fd=None) -> path\n\n\ -Return a string representing the path to which the symbolic link points.\n\ -\n\ -If dir_fd is not None, it should be a file descriptor open to a directory,\n\ - and path should be relative; path will then be relative to that directory.\n\ -dir_fd may not be implemented on your platform.\n\ - If it is unavailable, using it will raise a NotImplementedError."); -#endif - -#ifdef HAVE_READLINK - -/* AC 3.5: merge win32 and not together */ -static PyObject * -posix_readlink(PyObject *self, PyObject *args, PyObject *kwargs) -{ - path_t path; - int dir_fd = DEFAULT_DIR_FD; - char buffer[MAXPATHLEN]; - ssize_t length; - PyObject *return_value = NULL; - static char *keywords[] = {"path", "dir_fd", NULL}; - - memset(&path, 0, sizeof(path)); - path.function_name = "readlink"; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&|$O&:readlink", keywords, - path_converter, &path, - READLINKAT_DIR_FD_CONVERTER, &dir_fd)) - return NULL; - - Py_BEGIN_ALLOW_THREADS -#ifdef HAVE_READLINKAT - if (dir_fd != DEFAULT_DIR_FD) - length = readlinkat(dir_fd, path.narrow, buffer, sizeof(buffer)); - else -#endif - length = readlink(path.narrow, buffer, sizeof(buffer)); - Py_END_ALLOW_THREADS - - if (length < 0) { - return_value = path_error(&path); - goto exit; - } - - if (PyUnicode_Check(path.object)) - return_value = PyUnicode_DecodeFSDefaultAndSize(buffer, length); - else - return_value = PyBytes_FromStringAndSize(buffer, length); -exit: - path_cleanup(&path); - return return_value; -} - -#endif /* HAVE_READLINK */ - -#if !defined(HAVE_READLINK) && defined(MS_WINDOWS) - -static PyObject * -win_readlink(PyObject *self, PyObject *args, PyObject *kwargs) -{ - wchar_t *path; - DWORD n_bytes_returned; - DWORD io_result; - PyObject *po, *result; - int dir_fd; - HANDLE reparse_point_handle; - - char target_buffer[MAXIMUM_REPARSE_DATA_BUFFER_SIZE]; - REPARSE_DATA_BUFFER *rdb = (REPARSE_DATA_BUFFER *)target_buffer; - wchar_t *print_name; - - static char *keywords[] = {"path", "dir_fd", NULL}; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "U|$O&:readlink", keywords, - &po, - dir_fd_unavailable, &dir_fd - )) - return NULL; - - path = PyUnicode_AsUnicode(po); - if (path == NULL) - return NULL; - - /* First get a handle to the reparse point */ - Py_BEGIN_ALLOW_THREADS - reparse_point_handle = CreateFileW( - path, - 0, - 0, - 0, - OPEN_EXISTING, - FILE_FLAG_OPEN_REPARSE_POINT|FILE_FLAG_BACKUP_SEMANTICS, - 0); - Py_END_ALLOW_THREADS - - if (reparse_point_handle==INVALID_HANDLE_VALUE) - return win32_error_object("readlink", po); - - Py_BEGIN_ALLOW_THREADS - /* New call DeviceIoControl to read the reparse point */ - io_result = DeviceIoControl( - reparse_point_handle, - FSCTL_GET_REPARSE_POINT, - 0, 0, /* in buffer */ - target_buffer, sizeof(target_buffer), - &n_bytes_returned, - 0 /* we're not using OVERLAPPED_IO */ - ); - CloseHandle(reparse_point_handle); - Py_END_ALLOW_THREADS - - if (io_result==0) - return win32_error_object("readlink", po); - - if (rdb->ReparseTag != IO_REPARSE_TAG_SYMLINK) - { - PyErr_SetString(PyExc_ValueError, - "not a symbolic link"); - return NULL; - } - print_name = rdb->SymbolicLinkReparseBuffer.PathBuffer + - rdb->SymbolicLinkReparseBuffer.PrintNameOffset; - - result = PyUnicode_FromWideChar(print_name, - rdb->SymbolicLinkReparseBuffer.PrintNameLength/2); - return result; -} - -#endif /* !defined(HAVE_READLINK) && defined(MS_WINDOWS) */ - - - -#ifdef HAVE_SYMLINK - -#if defined(MS_WINDOWS) - -/* Grab CreateSymbolicLinkW dynamically from kernel32 */ -static DWORD (CALLBACK *Py_CreateSymbolicLinkW)(LPWSTR, LPWSTR, DWORD) = NULL; -static DWORD (CALLBACK *Py_CreateSymbolicLinkA)(LPSTR, LPSTR, DWORD) = NULL; - -static int -check_CreateSymbolicLink(void) -{ - HINSTANCE hKernel32; - /* only recheck */ - if (Py_CreateSymbolicLinkW && Py_CreateSymbolicLinkA) - return 1; - hKernel32 = GetModuleHandleW(L"KERNEL32"); - *(FARPROC*)&Py_CreateSymbolicLinkW = GetProcAddress(hKernel32, - "CreateSymbolicLinkW"); - *(FARPROC*)&Py_CreateSymbolicLinkA = GetProcAddress(hKernel32, - "CreateSymbolicLinkA"); - return (Py_CreateSymbolicLinkW && Py_CreateSymbolicLinkA); -} - -/* Remove the last portion of the path */ -static void -_dirnameW(WCHAR *path) -{ - WCHAR *ptr; - - /* walk the path from the end until a backslash is encountered */ - for(ptr = path + wcslen(path); ptr != path; ptr--) { - if (*ptr == L'\\' || *ptr == L'/') - break; - } - *ptr = 0; -} - -/* Remove the last portion of the path */ -static void -_dirnameA(char *path) -{ - char *ptr; - - /* walk the path from the end until a backslash is encountered */ - for(ptr = path + strlen(path); ptr != path; ptr--) { - if (*ptr == '\\' || *ptr == '/') - break; - } - *ptr = 0; -} - -/* Is this path absolute? */ -static int -_is_absW(const WCHAR *path) -{ - return path[0] == L'\\' || path[0] == L'/' || path[1] == L':'; - -} - -/* Is this path absolute? */ -static int -_is_absA(const char *path) -{ - return path[0] == '\\' || path[0] == '/' || path[1] == ':'; - -} - -/* join root and rest with a backslash */ -static void -_joinW(WCHAR *dest_path, const WCHAR *root, const WCHAR *rest) -{ - size_t root_len; - - if (_is_absW(rest)) { - wcscpy(dest_path, rest); - return; - } - - root_len = wcslen(root); - - wcscpy(dest_path, root); - if(root_len) { - dest_path[root_len] = L'\\'; - root_len++; - } - wcscpy(dest_path+root_len, rest); -} - -/* join root and rest with a backslash */ -static void -_joinA(char *dest_path, const char *root, const char *rest) -{ - size_t root_len; - - if (_is_absA(rest)) { - strcpy(dest_path, rest); - return; - } - - root_len = strlen(root); - - strcpy(dest_path, root); - if(root_len) { - dest_path[root_len] = '\\'; - root_len++; - } - strcpy(dest_path+root_len, rest); -} - -/* Return True if the path at src relative to dest is a directory */ -static int -_check_dirW(WCHAR *src, WCHAR *dest) -{ - WIN32_FILE_ATTRIBUTE_DATA src_info; - WCHAR dest_parent[MAX_PATH]; - WCHAR src_resolved[MAX_PATH] = L""; - - /* dest_parent = os.path.dirname(dest) */ - wcscpy(dest_parent, dest); - _dirnameW(dest_parent); - /* src_resolved = os.path.join(dest_parent, src) */ - _joinW(src_resolved, dest_parent, src); - return ( - GetFileAttributesExW(src_resolved, GetFileExInfoStandard, &src_info) - && src_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY - ); -} - -/* Return True if the path at src relative to dest is a directory */ -static int -_check_dirA(char *src, char *dest) -{ - WIN32_FILE_ATTRIBUTE_DATA src_info; - char dest_parent[MAX_PATH]; - char src_resolved[MAX_PATH] = ""; - - /* dest_parent = os.path.dirname(dest) */ - strcpy(dest_parent, dest); - _dirnameA(dest_parent); - /* src_resolved = os.path.join(dest_parent, src) */ - _joinA(src_resolved, dest_parent, src); - return ( - GetFileAttributesExA(src_resolved, GetFileExInfoStandard, &src_info) - && src_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY - ); -} -#endif - - -/*[clinic input] -os.symlink - src: path_t - dst: path_t - target_is_directory: bool = False - * - dir_fd: dir_fd(requires='symlinkat')=None - -# "symlink(src, dst, target_is_directory=False, *, dir_fd=None)\n\n\ - -Create a symbolic link pointing to src named dst. - -target_is_directory is required on Windows if the target is to be - interpreted as a directory. (On Windows, symlink requires - Windows 6.0 or greater, and raises a NotImplementedError otherwise.) - target_is_directory is ignored on non-Windows platforms. - -If dir_fd is not None, it should be a file descriptor open to a directory, - and path should be relative; path will then be relative to that directory. -dir_fd may not be implemented on your platform. - If it is unavailable, using it will raise a NotImplementedError. - -[clinic start generated code]*/ +#endif /* defined(HAVE_WAIT) */ + +#if defined(HAVE_SYMLINK) PyDoc_STRVAR(os_symlink__doc__, "symlink($module, /, src, dst, target_is_directory=False, *, dir_fd=None)\n" @@ -10106,154 +2999,9 @@ return return_value; } -static PyObject * -os_symlink_impl(PyModuleDef *module, path_t *src, path_t *dst, int target_is_directory, int dir_fd) -/*[clinic end generated code: output=1a31e6d88aafe9b6 input=e820ec4472547bc3]*/ -{ -#ifdef MS_WINDOWS - DWORD result; -#else - int result; -#endif - -#ifdef MS_WINDOWS - if (!check_CreateSymbolicLink()) { - PyErr_SetString(PyExc_NotImplementedError, - "CreateSymbolicLink functions not found"); - return NULL; - } - if (!win32_can_symlink) { - PyErr_SetString(PyExc_OSError, "symbolic link privilege not held"); - return NULL; - } -#endif - - if ((src->narrow && dst->wide) || (src->wide && dst->narrow)) { - PyErr_SetString(PyExc_ValueError, - "symlink: src and dst must be the same type"); - return NULL; - } - -#ifdef MS_WINDOWS - - Py_BEGIN_ALLOW_THREADS - if (dst->wide) { - /* if src is a directory, ensure target_is_directory==1 */ - target_is_directory |= _check_dirW(src->wide, dst->wide); - result = Py_CreateSymbolicLinkW(dst->wide, src->wide, - target_is_directory); - } - else { - /* if src is a directory, ensure target_is_directory==1 */ - target_is_directory |= _check_dirA(src->narrow, dst->narrow); - result = Py_CreateSymbolicLinkA(dst->narrow, src->narrow, - target_is_directory); - } - Py_END_ALLOW_THREADS - - if (!result) - return path_error2(src, dst); - -#else - - Py_BEGIN_ALLOW_THREADS -#if HAVE_SYMLINKAT - if (dir_fd != DEFAULT_DIR_FD) - result = symlinkat(src->narrow, dir_fd, dst->narrow); - else -#endif - result = symlink(src->narrow, dst->narrow); - Py_END_ALLOW_THREADS - - if (result) - return path_error2(src, dst); -#endif - - Py_RETURN_NONE; -} -#endif /* HAVE_SYMLINK */ - - - - -static PyStructSequence_Field times_result_fields[] = { - {"user", "user time"}, - {"system", "system time"}, - {"children_user", "user time of children"}, - {"children_system", "system time of children"}, - {"elapsed", "elapsed time since an arbitrary point in the past"}, - {NULL} -}; - -PyDoc_STRVAR(times_result__doc__, -"times_result: Result from os.times().\n\n\ -This object may be accessed either as a tuple of\n\ - (user, system, children_user, children_system, elapsed),\n\ -or via the attributes user, system, children_user, children_system,\n\ -and elapsed.\n\ -\n\ -See os.times for more information."); - -static PyStructSequence_Desc times_result_desc = { - "times_result", /* name */ - times_result__doc__, /* doc */ - times_result_fields, - 5 -}; - -static PyTypeObject TimesResultType; - -#ifdef MS_WINDOWS -#define HAVE_TIMES /* mandatory, for the method table */ -#endif - -#ifdef HAVE_TIMES - -static PyObject * -build_times_result(double user, double system, - double children_user, double children_system, - double elapsed) -{ - PyObject *value = PyStructSequence_New(&TimesResultType); - if (value == NULL) - return NULL; - -#define SET(i, field) \ - { \ - PyObject *o = PyFloat_FromDouble(field); \ - if (!o) { \ - Py_DECREF(value); \ - return NULL; \ - } \ - PyStructSequence_SET_ITEM(value, i, o); \ - } \ - - SET(0, user); - SET(1, system); - SET(2, children_user); - SET(3, children_system); - SET(4, elapsed); - -#undef SET - - return value; -} - - -#ifndef MS_WINDOWS -#define NEED_TICKS_PER_SECOND -static long ticks_per_second = -1; -#endif /* MS_WINDOWS */ - -/*[clinic input] -os.times - -Return a collection containing process timing information. - -The object returned behaves like a named tuple with these fields: - (utime, stime, cutime, cstime, elapsed_time) -All fields are floating point numbers. -[clinic start generated code]*/ +#endif /* defined(HAVE_SYMLINK) */ + +#if defined(HAVE_TIMES) PyDoc_STRVAR(os_times__doc__, "times($module, /)\n" @@ -10277,59 +3025,9 @@ return os_times_impl(module); } -static PyObject * -os_times_impl(PyModuleDef *module) -/*[clinic end generated code: output=b86896d031a9b768 input=2bf9df3d6ab2e48b]*/ -#ifdef MS_WINDOWS -{ - FILETIME create, exit, kernel, user; - HANDLE hProc; - hProc = GetCurrentProcess(); - GetProcessTimes(hProc, &create, &exit, &kernel, &user); - /* The fields of a FILETIME structure are the hi and lo part - of a 64-bit value expressed in 100 nanosecond units. - 1e7 is one second in such units; 1e-7 the inverse. - 429.4967296 is 2**32 / 1e7 or 2**32 * 1e-7. - */ - return build_times_result( - (double)(user.dwHighDateTime*429.4967296 + - user.dwLowDateTime*1e-7), - (double)(kernel.dwHighDateTime*429.4967296 + - kernel.dwLowDateTime*1e-7), - (double)0, - (double)0, - (double)0); -} -#else /* MS_WINDOWS */ -{ - - - struct tms t; - clock_t c; - errno = 0; - c = times(&t); - if (c == (clock_t) -1) - return posix_error(); - return build_times_result( - (double)t.tms_utime / ticks_per_second, - (double)t.tms_stime / ticks_per_second, - (double)t.tms_cutime / ticks_per_second, - (double)t.tms_cstime / ticks_per_second, - (double)c / ticks_per_second); -} -#endif /* MS_WINDOWS */ -#endif /* HAVE_TIMES */ - - -#ifdef HAVE_GETSID -/*[clinic input] -os.getsid - - pid: pid_t - / - -Call the system call getsid(pid) and return the result. -[clinic start generated code]*/ +#endif /* defined(HAVE_TIMES) */ + +#if defined(HAVE_GETSID) PyDoc_STRVAR(os_getsid__doc__, "getsid($module, pid, /)\n" @@ -10359,25 +3057,9 @@ return return_value; } -static PyObject * -os_getsid_impl(PyModuleDef *module, pid_t pid) -/*[clinic end generated code: output=ea8390f395f4e0e1 input=eeb2b923a30ce04e]*/ -{ - int sid; - sid = getsid(pid); - if (sid < 0) - return posix_error(); - return PyLong_FromLong((long)sid); -} -#endif /* HAVE_GETSID */ - - -#ifdef HAVE_SETSID -/*[clinic input] -os.setsid - -Call the system call setsid(). -[clinic start generated code]*/ +#endif /* defined(HAVE_GETSID) */ + +#if defined(HAVE_SETSID) PyDoc_STRVAR(os_setsid__doc__, "setsid($module, /)\n" @@ -10397,27 +3079,9 @@ return os_setsid_impl(module); } -static PyObject * -os_setsid_impl(PyModuleDef *module) -/*[clinic end generated code: output=2a9a1435d8d764d5 input=5fff45858e2f0776]*/ -{ - if (setsid() < 0) - return posix_error(); - Py_RETURN_NONE; -} -#endif /* HAVE_SETSID */ - - -#ifdef HAVE_SETPGID -/*[clinic input] -os.setpgid - - pid: pid_t - pgrp: pid_t - / - -Call the system call setpgid(pid, pgrp). -[clinic start generated code]*/ +#endif /* defined(HAVE_SETSID) */ + +#if defined(HAVE_SETPGID) PyDoc_STRVAR(os_setpgid__doc__, "setpgid($module, pid, pgrp, /)\n" @@ -10448,26 +3112,9 @@ return return_value; } -static PyObject * -os_setpgid_impl(PyModuleDef *module, pid_t pid, pid_t pgrp) -/*[clinic end generated code: output=7ad79b725f890e1f input=fceb395eca572e1a]*/ -{ - if (setpgid(pid, pgrp) < 0) - return posix_error(); - Py_RETURN_NONE; -} -#endif /* HAVE_SETPGID */ - - -#ifdef HAVE_TCGETPGRP -/*[clinic input] -os.tcgetpgrp - - fd: int - / - -Return the process group associated with the terminal specified by fd. -[clinic start generated code]*/ +#endif /* defined(HAVE_SETPGID) */ + +#if defined(HAVE_TCGETPGRP) PyDoc_STRVAR(os_tcgetpgrp__doc__, "tcgetpgrp($module, fd, /)\n" @@ -10497,28 +3144,9 @@ return return_value; } -static PyObject * -os_tcgetpgrp_impl(PyModuleDef *module, int fd) -/*[clinic end generated code: output=abcf52ed4c8d22cb input=7f6c18eac10ada86]*/ -{ - pid_t pgid = tcgetpgrp(fd); - if (pgid < 0) - return posix_error(); - return PyLong_FromPid(pgid); -} -#endif /* HAVE_TCGETPGRP */ - - -#ifdef HAVE_TCSETPGRP -/*[clinic input] -os.tcsetpgrp - - fd: int - pgid: pid_t - / - -Set the process group associated with the terminal specified by fd. -[clinic start generated code]*/ +#endif /* defined(HAVE_TCGETPGRP) */ + +#if defined(HAVE_TCSETPGRP) PyDoc_STRVAR(os_tcsetpgrp__doc__, "tcsetpgrp($module, fd, pgid, /)\n" @@ -10549,40 +3177,7 @@ return return_value; } -static PyObject * -os_tcsetpgrp_impl(PyModuleDef *module, int fd, pid_t pgid) -/*[clinic end generated code: output=76f9bb8fd00f20f5 input=5bdc997c6a619020]*/ -{ - if (tcsetpgrp(fd, pgid) < 0) - return posix_error(); - Py_RETURN_NONE; -} -#endif /* HAVE_TCSETPGRP */ - -/* Functions acting on file descriptors */ - -#ifdef O_CLOEXEC -extern int _Py_open_cloexec_works; -#endif - - -/*[clinic input] -os.open -> int - path: path_t - flags: int - mode: int = 0o777 - * - dir_fd: dir_fd(requires='openat') = None - -# "open(path, flags, mode=0o777, *, dir_fd=None)\n\n\ - -Open a file for low level IO. Returns a file descriptor (integer). - -If dir_fd is not None, it should be a file descriptor open to a directory, - and path should be relative; path will then be relative to that directory. -dir_fd may not be implemented on your platform. - If it is unavailable, using it will raise a NotImplementedError. -[clinic start generated code]*/ +#endif /* defined(HAVE_TCSETPGRP) */ PyDoc_STRVAR(os_open__doc__, "open($module, /, path, flags, mode=511, *, dir_fd=None)\n" @@ -10628,66 +3223,6 @@ return return_value; } -static int -os_open_impl(PyModuleDef *module, path_t *path, int flags, int mode, int dir_fd) -/*[clinic end generated code: output=05b68fc4ed5e29c9 input=ad8623b29acd2934]*/ -{ - int fd; - int async_err = 0; - -#ifdef O_CLOEXEC - int *atomic_flag_works = &_Py_open_cloexec_works; -#elif !defined(MS_WINDOWS) - int *atomic_flag_works = NULL; -#endif - -#ifdef MS_WINDOWS - flags |= O_NOINHERIT; -#elif defined(O_CLOEXEC) - flags |= O_CLOEXEC; -#endif - - do { - Py_BEGIN_ALLOW_THREADS -#ifdef MS_WINDOWS - if (path->wide) - fd = _wopen(path->wide, flags, mode); - else -#endif -#ifdef HAVE_OPENAT - if (dir_fd != DEFAULT_DIR_FD) - fd = openat(dir_fd, path->narrow, flags, mode); - else -#endif - fd = open(path->narrow, flags, mode); - Py_END_ALLOW_THREADS - } while (fd < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); - - if (fd == -1) { - if (!async_err) - PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path->object); - return -1; - } - -#ifndef MS_WINDOWS - if (_Py_set_inheritable(fd, 0, atomic_flag_works) < 0) { - close(fd); - return -1; - } -#endif - - return fd; -} - - -/*[clinic input] -os.close - - fd: int - -Close a file descriptor. -[clinic start generated code]*/ - PyDoc_STRVAR(os_close__doc__, "close($module, /, fd)\n" "--\n" @@ -10717,36 +3252,6 @@ return return_value; } -static PyObject * -os_close_impl(PyModuleDef *module, int fd) -/*[clinic end generated code: output=927004e29ad55808 input=2bc42451ca5c3223]*/ -{ - int res; - if (!_PyVerify_fd(fd)) - return posix_error(); - /* We do not want to retry upon EINTR: see http://lwn.net/Articles/576478/ - * and http://linux.derkeiler.com/Mailing-Lists/Kernel/2005-09/3000.html - * for more details. - */ - Py_BEGIN_ALLOW_THREADS - res = close(fd); - Py_END_ALLOW_THREADS - if (res < 0) - return posix_error(); - Py_RETURN_NONE; -} - - -/*[clinic input] -os.closerange - - fd_low: int - fd_high: int - / - -Closes all file descriptors in [fd_low, fd_high), ignoring errors. -[clinic start generated code]*/ - PyDoc_STRVAR(os_closerange__doc__, "closerange($module, fd_low, fd_high, /)\n" "--\n" @@ -10776,29 +3281,6 @@ return return_value; } -static PyObject * -os_closerange_impl(PyModuleDef *module, int fd_low, int fd_high) -/*[clinic end generated code: output=0a929ece386811c3 input=5855a3d053ebd4ec]*/ -{ - int i; - Py_BEGIN_ALLOW_THREADS - for (i = fd_low; i < fd_high; i++) - if (_PyVerify_fd(i)) - close(i); - Py_END_ALLOW_THREADS - Py_RETURN_NONE; -} - - -/*[clinic input] -os.dup -> int - - fd: int - / - -Return a duplicate of a file descriptor. -[clinic start generated code]*/ - PyDoc_STRVAR(os_dup__doc__, "dup($module, fd, /)\n" "--\n" @@ -10831,23 +3313,6 @@ return return_value; } -static int -os_dup_impl(PyModuleDef *module, int fd) -/*[clinic end generated code: output=75943e057b25e1bd input=6f10f7ea97f7852a]*/ -{ - return _Py_dup(fd); -} - - -/*[clinic input] -os.dup2 - fd: int - fd2: int - inheritable: bool=True - -Duplicate file descriptor. -[clinic start generated code]*/ - PyDoc_STRVAR(os_dup2__doc__, "dup2($module, /, fd, fd2, inheritable=True)\n" "--\n" @@ -10879,100 +3344,7 @@ return return_value; } -static PyObject * -os_dup2_impl(PyModuleDef *module, int fd, int fd2, int inheritable) -/*[clinic end generated code: output=531e482dd11a99a0 input=76e96f511be0352f]*/ -{ - int res; -#if defined(HAVE_DUP3) && \ - !(defined(HAVE_FCNTL_H) && defined(F_DUP2FD_CLOEXEC)) - /* dup3() is available on Linux 2.6.27+ and glibc 2.9 */ - int dup3_works = -1; -#endif - - if (!_PyVerify_fd_dup2(fd, fd2)) - return posix_error(); - - /* dup2() can fail with EINTR if the target FD is already open, because it - * then has to be closed. See os_close_impl() for why we don't handle EINTR - * upon close(), and therefore below. - */ -#ifdef MS_WINDOWS - Py_BEGIN_ALLOW_THREADS - res = dup2(fd, fd2); - Py_END_ALLOW_THREADS - if (res < 0) - return posix_error(); - - /* Character files like console cannot be make non-inheritable */ - if (!inheritable && _Py_set_inheritable(fd2, 0, NULL) < 0) { - close(fd2); - return NULL; - } - -#elif defined(HAVE_FCNTL_H) && defined(F_DUP2FD_CLOEXEC) - Py_BEGIN_ALLOW_THREADS - if (!inheritable) - res = fcntl(fd, F_DUP2FD_CLOEXEC, fd2); - else - res = dup2(fd, fd2); - Py_END_ALLOW_THREADS - if (res < 0) - return posix_error(); - -#else - -#ifdef HAVE_DUP3 - if (!inheritable && dup3_works != 0) { - Py_BEGIN_ALLOW_THREADS - res = dup3(fd, fd2, O_CLOEXEC); - Py_END_ALLOW_THREADS - if (res < 0) { - if (dup3_works == -1) - dup3_works = (errno != ENOSYS); - if (dup3_works) - return posix_error(); - } - } - - if (inheritable || dup3_works == 0) - { -#endif - Py_BEGIN_ALLOW_THREADS - res = dup2(fd, fd2); - Py_END_ALLOW_THREADS - if (res < 0) - return posix_error(); - - if (!inheritable && _Py_set_inheritable(fd2, 0, NULL) < 0) { - close(fd2); - return NULL; - } -#ifdef HAVE_DUP3 - } -#endif - -#endif - - Py_RETURN_NONE; -} - - -#ifdef HAVE_LOCKF -/*[clinic input] -os.lockf - - fd: int - An open file descriptor. - command: int - One of F_LOCK, F_TLOCK, F_ULOCK or F_TEST. - length: Py_off_t - The number of bytes to lock, starting at the current position. - / - -Apply, test or remove a POSIX lock on an open file descriptor. - -[clinic start generated code]*/ +#if defined(HAVE_LOCKF) PyDoc_STRVAR(os_lockf__doc__, "lockf($module, fd, command, length, /)\n" @@ -11011,37 +3383,7 @@ return return_value; } -static PyObject * -os_lockf_impl(PyModuleDef *module, int fd, int command, Py_off_t length) -/*[clinic end generated code: output=1b28346ac7335c0f input=65da41d2106e9b79]*/ -{ - int res; - - Py_BEGIN_ALLOW_THREADS - res = lockf(fd, command, length); - Py_END_ALLOW_THREADS - - if (res < 0) - return posix_error(); - - Py_RETURN_NONE; -} -#endif /* HAVE_LOCKF */ - - -/*[clinic input] -os.lseek -> Py_off_t - - fd: int - position: Py_off_t - how: int - / - -Set the position of a file descriptor. Return the new position. - -Return the new cursor position in number of bytes -relative to the beginning of the file. -[clinic start generated code]*/ +#endif /* defined(HAVE_LOCKF) */ PyDoc_STRVAR(os_lseek__doc__, "lseek($module, fd, position, how, /)\n" @@ -11080,55 +3422,6 @@ return return_value; } -static Py_off_t -os_lseek_impl(PyModuleDef *module, int fd, Py_off_t position, int how) -/*[clinic end generated code: output=88cfc146f55667af input=902654ad3f96a6d3]*/ -{ - Py_off_t result; - - if (!_PyVerify_fd(fd)) { - posix_error(); - return -1; - } -#ifdef SEEK_SET - /* Turn 0, 1, 2 into SEEK_{SET,CUR,END} */ - switch (how) { - case 0: how = SEEK_SET; break; - case 1: how = SEEK_CUR; break; - case 2: how = SEEK_END; break; - } -#endif /* SEEK_END */ - - if (PyErr_Occurred()) - return -1; - - if (!_PyVerify_fd(fd)) { - posix_error(); - return -1; - } - Py_BEGIN_ALLOW_THREADS -#ifdef MS_WINDOWS - result = _lseeki64(fd, position, how); -#else - result = lseek(fd, position, how); -#endif - Py_END_ALLOW_THREADS - if (result < 0) - posix_error(); - - return result; -} - - -/*[clinic input] -os.read - fd: int - length: Py_ssize_t - / - -Read from a file descriptor. Returns a bytes object. -[clinic start generated code]*/ - PyDoc_STRVAR(os_read__doc__, "read($module, fd, length, /)\n" "--\n" @@ -11158,117 +3451,7 @@ return return_value; } -static PyObject * -os_read_impl(PyModuleDef *module, int fd, Py_ssize_t length) -/*[clinic end generated code: output=1f3bc27260a24968 input=1df2eaa27c0bf1d3]*/ -{ - Py_ssize_t n; - PyObject *buffer; - - if (length < 0) { - errno = EINVAL; - return posix_error(); - } - -#ifdef MS_WINDOWS - /* On Windows, the count parameter of read() is an int */ - if (length > INT_MAX) - length = INT_MAX; -#endif - - buffer = PyBytes_FromStringAndSize((char *)NULL, length); - if (buffer == NULL) - return NULL; - - n = _Py_read(fd, PyBytes_AS_STRING(buffer), length); - if (n == -1) { - Py_DECREF(buffer); - return NULL; - } - - if (n != length) - _PyBytes_Resize(&buffer, n); - - return buffer; -} - -#if (defined(HAVE_SENDFILE) && (defined(__FreeBSD__) || defined(__DragonFly__) \ - || defined(__APPLE__))) || defined(HAVE_READV) || defined(HAVE_WRITEV) -static Py_ssize_t -iov_setup(struct iovec **iov, Py_buffer **buf, PyObject *seq, int cnt, int type) -{ - int i, j; - Py_ssize_t blen, total = 0; - - *iov = PyMem_New(struct iovec, cnt); - if (*iov == NULL) { - PyErr_NoMemory(); - return -1; - } - - *buf = PyMem_New(Py_buffer, cnt); - if (*buf == NULL) { - PyMem_Del(*iov); - PyErr_NoMemory(); - return -1; - } - - for (i = 0; i < cnt; i++) { - PyObject *item = PySequence_GetItem(seq, i); - if (item == NULL) - goto fail; - if (PyObject_GetBuffer(item, &(*buf)[i], type) == -1) { - Py_DECREF(item); - goto fail; - } - Py_DECREF(item); - (*iov)[i].iov_base = (*buf)[i].buf; - blen = (*buf)[i].len; - (*iov)[i].iov_len = blen; - total += blen; - } - return total; - -fail: - PyMem_Del(*iov); - for (j = 0; j < i; j++) { - PyBuffer_Release(&(*buf)[j]); - } - PyMem_Del(*buf); - return -1; -} - -static void -iov_cleanup(struct iovec *iov, Py_buffer *buf, int cnt) -{ - int i; - PyMem_Del(iov); - for (i = 0; i < cnt; i++) { - PyBuffer_Release(&buf[i]); - } - PyMem_Del(buf); -} -#endif - - -#ifdef HAVE_READV -/*[clinic input] -os.readv -> Py_ssize_t - - fd: int - buffers: object - / - -Read from a file descriptor fd into an iterable of buffers. - -The buffers should be mutable buffers accepting bytes. -readv will transfer data into each buffer until it is full -and then move on to the next buffer in the sequence to hold -the rest of the data. - -readv returns the total number of bytes read, -which may be less than the total capacity of all the buffers. -[clinic start generated code]*/ +#if defined(HAVE_READV) PyDoc_STRVAR(os_readv__doc__, "readv($module, fd, buffers, /)\n" @@ -11311,60 +3494,9 @@ return return_value; } -static Py_ssize_t -os_readv_impl(PyModuleDef *module, int fd, PyObject *buffers) -/*[clinic end generated code: output=72748b1c32a6e2a1 input=e679eb5dbfa0357d]*/ -{ - int cnt; - Py_ssize_t n; - int async_err = 0; - struct iovec *iov; - Py_buffer *buf; - - if (!PySequence_Check(buffers)) { - PyErr_SetString(PyExc_TypeError, - "readv() arg 2 must be a sequence"); - return -1; - } - - cnt = PySequence_Size(buffers); - - if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_WRITABLE) < 0) - return -1; - - do { - Py_BEGIN_ALLOW_THREADS - n = readv(fd, iov, cnt); - Py_END_ALLOW_THREADS - } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); - - iov_cleanup(iov, buf, cnt); - if (n < 0) { - if (!async_err) - posix_error(); - return -1; - } - - return n; -} -#endif /* HAVE_READV */ - - -#ifdef HAVE_PREAD -/*[clinic input] -# TODO length should be size_t! but Python doesn't support parsing size_t yet. -os.pread - - fd: int - length: int - offset: Py_off_t - / - -Read a number of bytes from a file descriptor starting at a particular offset. - -Read length bytes from file descriptor fd, starting at offset bytes from -the beginning of the file. The file offset remains unchanged. -[clinic start generated code]*/ +#endif /* defined(HAVE_READV) */ + +#if defined(HAVE_PREAD) PyDoc_STRVAR(os_pread__doc__, "pread($module, fd, length, offset, /)\n" @@ -11399,52 +3531,7 @@ return return_value; } -static PyObject * -os_pread_impl(PyModuleDef *module, int fd, int length, Py_off_t offset) -/*[clinic end generated code: output=7b62bf6c06e20ae8 input=084948dcbaa35d4c]*/ -{ - Py_ssize_t n; - int async_err = 0; - PyObject *buffer; - - if (length < 0) { - errno = EINVAL; - return posix_error(); - } - buffer = PyBytes_FromStringAndSize((char *)NULL, length); - if (buffer == NULL) - return NULL; - if (!_PyVerify_fd(fd)) { - Py_DECREF(buffer); - return posix_error(); - } - - do { - Py_BEGIN_ALLOW_THREADS - n = pread(fd, PyBytes_AS_STRING(buffer), length, offset); - Py_END_ALLOW_THREADS - } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); - - if (n < 0) { - Py_DECREF(buffer); - return (!async_err) ? posix_error() : NULL; - } - if (n != length) - _PyBytes_Resize(&buffer, n); - return buffer; -} -#endif /* HAVE_PREAD */ - - -/*[clinic input] -os.write -> Py_ssize_t - - fd: int - data: Py_buffer - / - -Write a bytes object to a file descriptor. -[clinic start generated code]*/ +#endif /* defined(HAVE_PREAD) */ PyDoc_STRVAR(os_write__doc__, "write($module, fd, data, /)\n" @@ -11483,174 +3570,6 @@ return return_value; } -static Py_ssize_t -os_write_impl(PyModuleDef *module, int fd, Py_buffer *data) -/*[clinic end generated code: output=aeb96acfdd4d5112 input=3207e28963234f3c]*/ -{ - return _Py_write(fd, data->buf, data->len); -} - -#ifdef HAVE_SENDFILE -PyDoc_STRVAR(posix_sendfile__doc__, -"sendfile(out, in, offset, nbytes) -> byteswritten\n\ -sendfile(out, in, offset, nbytes, headers=None, trailers=None, flags=0)\n\ - -> byteswritten\n\ -Copy nbytes bytes from file descriptor in to file descriptor out."); - -/* AC 3.5: don't bother converting, has optional group*/ -static PyObject * -posix_sendfile(PyObject *self, PyObject *args, PyObject *kwdict) -{ - int in, out; - Py_ssize_t ret; - int async_err = 0; - off_t offset; - -#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__) -#ifndef __APPLE__ - Py_ssize_t len; -#endif - PyObject *headers = NULL, *trailers = NULL; - Py_buffer *hbuf, *tbuf; - off_t sbytes; - struct sf_hdtr sf; - int flags = 0; - static char *keywords[] = {"out", "in", - "offset", "count", - "headers", "trailers", "flags", NULL}; - - sf.headers = NULL; - sf.trailers = NULL; - -#ifdef __APPLE__ - if (!PyArg_ParseTupleAndKeywords(args, kwdict, "iiO&O&|OOi:sendfile", - keywords, &out, &in, Py_off_t_converter, &offset, Py_off_t_converter, &sbytes, -#else - if (!PyArg_ParseTupleAndKeywords(args, kwdict, "iiO&n|OOi:sendfile", - keywords, &out, &in, Py_off_t_converter, &offset, &len, -#endif - &headers, &trailers, &flags)) - return NULL; - if (headers != NULL) { - if (!PySequence_Check(headers)) { - PyErr_SetString(PyExc_TypeError, - "sendfile() headers must be a sequence or None"); - return NULL; - } else { - Py_ssize_t i = 0; /* Avoid uninitialized warning */ - sf.hdr_cnt = PySequence_Size(headers); - if (sf.hdr_cnt > 0 && - (i = iov_setup(&(sf.headers), &hbuf, - headers, sf.hdr_cnt, PyBUF_SIMPLE)) < 0) - return NULL; -#ifdef __APPLE__ - sbytes += i; -#endif - } - } - if (trailers != NULL) { - if (!PySequence_Check(trailers)) { - PyErr_SetString(PyExc_TypeError, - "sendfile() trailers must be a sequence or None"); - return NULL; - } else { - Py_ssize_t i = 0; /* Avoid uninitialized warning */ - sf.trl_cnt = PySequence_Size(trailers); - if (sf.trl_cnt > 0 && - (i = iov_setup(&(sf.trailers), &tbuf, - trailers, sf.trl_cnt, PyBUF_SIMPLE)) < 0) - return NULL; -#ifdef __APPLE__ - sbytes += i; -#endif - } - } - - do { - Py_BEGIN_ALLOW_THREADS -#ifdef __APPLE__ - ret = sendfile(in, out, offset, &sbytes, &sf, flags); -#else - ret = sendfile(in, out, offset, len, &sf, &sbytes, flags); -#endif - Py_END_ALLOW_THREADS - } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); - - if (sf.headers != NULL) - iov_cleanup(sf.headers, hbuf, sf.hdr_cnt); - if (sf.trailers != NULL) - iov_cleanup(sf.trailers, tbuf, sf.trl_cnt); - - if (ret < 0) { - if ((errno == EAGAIN) || (errno == EBUSY)) { - if (sbytes != 0) { - // some data has been sent - goto done; - } - else { - // no data has been sent; upper application is supposed - // to retry on EAGAIN or EBUSY - return posix_error(); - } - } - return (!async_err) ? posix_error() : NULL; - } - goto done; - -done: - #if !defined(HAVE_LARGEFILE_SUPPORT) - return Py_BuildValue("l", sbytes); - #else - return Py_BuildValue("L", sbytes); - #endif - -#else - Py_ssize_t count; - PyObject *offobj; - static char *keywords[] = {"out", "in", - "offset", "count", NULL}; - if (!PyArg_ParseTupleAndKeywords(args, kwdict, "iiOn:sendfile", - keywords, &out, &in, &offobj, &count)) - return NULL; -#ifdef linux - if (offobj == Py_None) { - do { - Py_BEGIN_ALLOW_THREADS - ret = sendfile(out, in, NULL, count); - Py_END_ALLOW_THREADS - } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); - if (ret < 0) - return (!async_err) ? posix_error() : NULL; - return Py_BuildValue("n", ret); - } -#endif - if (!Py_off_t_converter(offobj, &offset)) - return NULL; - - do { - Py_BEGIN_ALLOW_THREADS - ret = sendfile(out, in, &offset, count); - Py_END_ALLOW_THREADS - } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); - if (ret < 0) - return (!async_err) ? posix_error() : NULL; - return Py_BuildValue("n", ret); -#endif -} -#endif /* HAVE_SENDFILE */ - - -/*[clinic input] -os.fstat - - fd : int - -Perform a stat system call on the given file descriptor. - -Like stat(), but for an open file descriptor. -Equivalent to os.stat(fd). -[clinic start generated code]*/ - PyDoc_STRVAR(os_fstat__doc__, "fstat($module, /, fd)\n" "--\n" @@ -11683,42 +3602,6 @@ return return_value; } -static PyObject * -os_fstat_impl(PyModuleDef *module, int fd) -/*[clinic end generated code: output=dae4a9678c7bd881 input=27e0e0ebbe5600c9]*/ -{ - STRUCT_STAT st; - int res; - int async_err = 0; - - do { - Py_BEGIN_ALLOW_THREADS - res = FSTAT(fd, &st); - Py_END_ALLOW_THREADS - } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); - if (res != 0) { -#ifdef MS_WINDOWS - return PyErr_SetFromWindowsErr(0); -#else - return (!async_err) ? posix_error() : NULL; -#endif - } - - return _pystat_fromstructstat(&st); -} - - -/*[clinic input] -os.isatty -> bool - fd: int - / - -Return True if the fd is connected to a terminal. - -Return True if the file descriptor is an open file descriptor -connected to the slave end of a terminal. -[clinic start generated code]*/ - PyDoc_STRVAR(os_isatty__doc__, "isatty($module, fd, /)\n" "--\n" @@ -11754,25 +3637,7 @@ return return_value; } -static int -os_isatty_impl(PyModuleDef *module, int fd) -/*[clinic end generated code: output=4bfadbfe22715097 input=08ce94aa1eaf7b5e]*/ -{ - if (!_PyVerify_fd(fd)) - return 0; - return isatty(fd); -} - - -#ifdef HAVE_PIPE -/*[clinic input] -os.pipe - -Create a pipe. - -Returns a tuple of two file descriptors: - (read_fd, write_fd) -[clinic start generated code]*/ +#if defined(HAVE_PIPE) PyDoc_STRVAR(os_pipe__doc__, "pipe($module, /)\n" @@ -11795,92 +3660,9 @@ return os_pipe_impl(module); } -static PyObject * -os_pipe_impl(PyModuleDef *module) -/*[clinic end generated code: output=0da2479f2266e774 input=02535e8c8fa6c4d4]*/ -{ - int fds[2]; -#ifdef MS_WINDOWS - HANDLE read, write; - SECURITY_ATTRIBUTES attr; - BOOL ok; -#else - int res; -#endif - -#ifdef MS_WINDOWS - attr.nLength = sizeof(attr); - attr.lpSecurityDescriptor = NULL; - attr.bInheritHandle = FALSE; - - Py_BEGIN_ALLOW_THREADS - ok = CreatePipe(&read, &write, &attr, 0); - if (ok) { - fds[0] = _open_osfhandle((Py_intptr_t)read, _O_RDONLY); - fds[1] = _open_osfhandle((Py_intptr_t)write, _O_WRONLY); - if (fds[0] == -1 || fds[1] == -1) { - CloseHandle(read); - CloseHandle(write); - ok = 0; - } - } - Py_END_ALLOW_THREADS - - if (!ok) - return PyErr_SetFromWindowsErr(0); -#else - -#ifdef HAVE_PIPE2 - Py_BEGIN_ALLOW_THREADS - res = pipe2(fds, O_CLOEXEC); - Py_END_ALLOW_THREADS - - if (res != 0 && errno == ENOSYS) - { -#endif - Py_BEGIN_ALLOW_THREADS - res = pipe(fds); - Py_END_ALLOW_THREADS - - if (res == 0) { - if (_Py_set_inheritable(fds[0], 0, NULL) < 0) { - close(fds[0]); - close(fds[1]); - return NULL; - } - if (_Py_set_inheritable(fds[1], 0, NULL) < 0) { - close(fds[0]); - close(fds[1]); - return NULL; - } - } -#ifdef HAVE_PIPE2 - } -#endif - - if (res != 0) - return PyErr_SetFromErrno(PyExc_OSError); -#endif /* !MS_WINDOWS */ - return Py_BuildValue("(ii)", fds[0], fds[1]); -} -#endif /* HAVE_PIPE */ - - -#ifdef HAVE_PIPE2 -/*[clinic input] -os.pipe2 - - flags: int - / - -Create a pipe with flags set atomically. - -Returns a tuple of two file descriptors: - (read_fd, write_fd) - -flags can be constructed by ORing together one or more of these values: -O_NONBLOCK, O_CLOEXEC. -[clinic start generated code]*/ +#endif /* defined(HAVE_PIPE) */ + +#if defined(HAVE_PIPE2) PyDoc_STRVAR(os_pipe2__doc__, "pipe2($module, flags, /)\n" @@ -11916,33 +3698,9 @@ return return_value; } -static PyObject * -os_pipe2_impl(PyModuleDef *module, int flags) -/*[clinic end generated code: output=9e27c799ce19220b input=f261b6e7e63c6817]*/ -{ - int fds[2]; - int res; - - res = pipe2(fds, flags); - if (res != 0) - return posix_error(); - return Py_BuildValue("(ii)", fds[0], fds[1]); -} -#endif /* HAVE_PIPE2 */ - - -#ifdef HAVE_WRITEV -/*[clinic input] -os.writev -> Py_ssize_t - fd: int - buffers: object - / - -Iterate over buffers, and write the contents of each to a file descriptor. - -Returns the total number of bytes written. -buffers must be a sequence of bytes-like objects. -[clinic start generated code]*/ +#endif /* defined(HAVE_PIPE2) */ + +#if defined(HAVE_WRITEV) PyDoc_STRVAR(os_writev__doc__, "writev($module, fd, buffers, /)\n" @@ -11980,57 +3738,9 @@ return return_value; } -static Py_ssize_t -os_writev_impl(PyModuleDef *module, int fd, PyObject *buffers) -/*[clinic end generated code: output=591c662dccbe4951 input=5b8d17fe4189d2fe]*/ -{ - int cnt; - Py_ssize_t result; - int async_err = 0; - struct iovec *iov; - Py_buffer *buf; - - if (!PySequence_Check(buffers)) { - PyErr_SetString(PyExc_TypeError, - "writev() arg 2 must be a sequence"); - return -1; - } - cnt = PySequence_Size(buffers); - - if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_SIMPLE) < 0) { - return -1; - } - - do { - Py_BEGIN_ALLOW_THREADS - result = writev(fd, iov, cnt); - Py_END_ALLOW_THREADS - } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); - - iov_cleanup(iov, buf, cnt); - if (result < 0 && !async_err) - posix_error(); - - return result; -} -#endif /* HAVE_WRITEV */ - - -#ifdef HAVE_PWRITE -/*[clinic input] -os.pwrite -> Py_ssize_t - - fd: int - buffer: Py_buffer - offset: Py_off_t - / - -Write bytes to a file descriptor starting at a particular offset. - -Write buffer to fd, starting at offset bytes from the beginning of -the file. Returns the number of bytes writte. Does not change the -current file offset. -[clinic start generated code]*/ +#endif /* defined(HAVE_WRITEV) */ + +#if defined(HAVE_PWRITE) PyDoc_STRVAR(os_pwrite__doc__, "pwrite($module, fd, buffer, offset, /)\n" @@ -12074,47 +3784,9 @@ return return_value; } -static Py_ssize_t -os_pwrite_impl(PyModuleDef *module, int fd, Py_buffer *buffer, Py_off_t offset) -/*[clinic end generated code: output=ec9cc5b2238e96a7 input=19903f1b3dd26377]*/ -{ - Py_ssize_t size; - int async_err = 0; - - if (!_PyVerify_fd(fd)) { - posix_error(); - return -1; - } - - do { - Py_BEGIN_ALLOW_THREADS - size = pwrite(fd, buffer->buf, (size_t)buffer->len, offset); - Py_END_ALLOW_THREADS - } while (size < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); - - if (size < 0 && !async_err) - posix_error(); - return size; -} -#endif /* HAVE_PWRITE */ - - -#ifdef HAVE_MKFIFO -/*[clinic input] -os.mkfifo - - path: path_t - mode: int=0o666 - * - dir_fd: dir_fd(requires='mkfifoat')=None - -Create a "fifo" (a POSIX named pipe). - -If dir_fd is not None, it should be a file descriptor open to a directory, - and path should be relative; path will then be relative to that directory. -dir_fd may not be implemented on your platform. - If it is unavailable, using it will raise a NotImplementedError. -[clinic start generated code]*/ +#endif /* defined(HAVE_PWRITE) */ + +#if defined(HAVE_MKFIFO) PyDoc_STRVAR(os_mkfifo__doc__, "mkfifo($module, /, path, mode=438, *, dir_fd=None)\n" @@ -12155,56 +3827,9 @@ return return_value; } -static PyObject * -os_mkfifo_impl(PyModuleDef *module, path_t *path, int mode, int dir_fd) -/*[clinic end generated code: output=b3321927546893d0 input=73032e98a36e0e19]*/ -{ - int result; - int async_err = 0; - - do { - Py_BEGIN_ALLOW_THREADS -#ifdef HAVE_MKFIFOAT - if (dir_fd != DEFAULT_DIR_FD) - result = mkfifoat(dir_fd, path->narrow, mode); - else -#endif - result = mkfifo(path->narrow, mode); - Py_END_ALLOW_THREADS - } while (result != 0 && errno == EINTR && - !(async_err = PyErr_CheckSignals())); - if (result != 0) - return (!async_err) ? posix_error() : NULL; - - Py_RETURN_NONE; -} -#endif /* HAVE_MKFIFO */ - - -#if defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV) -/*[clinic input] -os.mknod - - path: path_t - mode: int=0o600 - device: dev_t=0 - * - dir_fd: dir_fd(requires='mknodat')=None - -Create a node in the file system. - -Create a node in the file system (file, device special file or named pipe) -at path. mode specifies both the permissions to use and the -type of node to be created, being combined (bitwise OR) with one of -S_IFREG, S_IFCHR, S_IFBLK, and S_IFIFO. If S_IFCHR or S_IFBLK is set on mode, -device defines the newly created device special file (probably using -os.makedev()). Otherwise device is ignored. - -If dir_fd is not None, it should be a file descriptor open to a directory, - and path should be relative; path will then be relative to that directory. -dir_fd may not be implemented on your platform. - If it is unavailable, using it will raise a NotImplementedError. -[clinic start generated code]*/ +#endif /* defined(HAVE_MKFIFO) */ + +#if (defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV)) PyDoc_STRVAR(os_mknod__doc__, "mknod($module, /, path, mode=384, device=0, *, dir_fd=None)\n" @@ -12253,41 +3878,9 @@ return return_value; } -static PyObject * -os_mknod_impl(PyModuleDef *module, path_t *path, int mode, dev_t device, int dir_fd) -/*[clinic end generated code: output=f71d54eaf9bb6f1a input=ee44531551a4d83b]*/ -{ - int result; - int async_err = 0; - - do { - Py_BEGIN_ALLOW_THREADS -#ifdef HAVE_MKNODAT - if (dir_fd != DEFAULT_DIR_FD) - result = mknodat(dir_fd, path->narrow, mode, device); - else -#endif - result = mknod(path->narrow, mode, device); - Py_END_ALLOW_THREADS - } while (result != 0 && errno == EINTR && - !(async_err = PyErr_CheckSignals())); - if (result != 0) - return (!async_err) ? posix_error() : NULL; - - Py_RETURN_NONE; -} -#endif /* defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV) */ - - -#ifdef HAVE_DEVICE_MACROS -/*[clinic input] -os.major -> unsigned_int - - device: dev_t - / - -Extracts a device major number from a raw device number. -[clinic start generated code]*/ +#endif /* (defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV)) */ + +#if defined(HAVE_DEVICE_MACROS) PyDoc_STRVAR(os_major__doc__, "major($module, device, /)\n" @@ -12321,22 +3914,9 @@ return return_value; } -static unsigned int -os_major_impl(PyModuleDef *module, dev_t device) -/*[clinic end generated code: output=a2d06e908ebf95b5 input=1e16a4d30c4d4462]*/ -{ - return major(device); -} - - -/*[clinic input] -os.minor -> unsigned_int - - device: dev_t - / - -Extracts a device minor number from a raw device number. -[clinic start generated code]*/ +#endif /* defined(HAVE_DEVICE_MACROS) */ + +#if defined(HAVE_DEVICE_MACROS) PyDoc_STRVAR(os_minor__doc__, "minor($module, device, /)\n" @@ -12370,23 +3950,9 @@ return return_value; } -static unsigned int -os_minor_impl(PyModuleDef *module, dev_t device) -/*[clinic end generated code: output=6332287ee3f006e2 input=0842c6d23f24c65e]*/ -{ - return minor(device); -} - - -/*[clinic input] -os.makedev -> dev_t - - major: int - minor: int - / - -Composes a raw device number from the major and minor device numbers. -[clinic start generated code]*/ +#endif /* defined(HAVE_DEVICE_MACROS) */ + +#if defined(HAVE_DEVICE_MACROS) PyDoc_STRVAR(os_makedev__doc__, "makedev($module, major, minor, /)\n" @@ -12421,25 +3987,9 @@ return return_value; } -static dev_t -os_makedev_impl(PyModuleDef *module, int major, int minor) -/*[clinic end generated code: output=38e9a9774c96511a input=4b9fd8fc73cbe48f]*/ -{ - return makedev(major, minor); -} -#endif /* HAVE_DEVICE_MACROS */ - - -#ifdef HAVE_FTRUNCATE -/*[clinic input] -os.ftruncate - - fd: int - length: Py_off_t - / - -Truncate a file, specified by file descriptor, to a specific length. -[clinic start generated code]*/ +#endif /* defined(HAVE_DEVICE_MACROS) */ + +#if defined(HAVE_FTRUNCATE) PyDoc_STRVAR(os_ftruncate__doc__, "ftruncate($module, fd, length, /)\n" @@ -12470,37 +4020,9 @@ return return_value; } -static PyObject * -os_ftruncate_impl(PyModuleDef *module, int fd, Py_off_t length) -/*[clinic end generated code: output=62326766cb9b76bf input=63b43641e52818f2]*/ -{ - int result; - int async_err = 0; - - do { - Py_BEGIN_ALLOW_THREADS - result = ftruncate(fd, length); - Py_END_ALLOW_THREADS - } while (result != 0 && errno == EINTR && - !(async_err = PyErr_CheckSignals())); - if (result != 0) - return (!async_err) ? posix_error() : NULL; - Py_RETURN_NONE; -} -#endif /* HAVE_FTRUNCATE */ - - -#ifdef HAVE_TRUNCATE -/*[clinic input] -os.truncate - path: path_t(allow_fd='PATH_HAVE_FTRUNCATE') - length: Py_off_t - -Truncate a file, specified by path, to a specific length. - -On some platforms, path may also be specified as an open file descriptor. - If this functionality is unavailable, using it raises an exception. -[clinic start generated code]*/ +#endif /* defined(HAVE_FTRUNCATE) */ + +#if defined(HAVE_TRUNCATE) PyDoc_STRVAR(os_truncate__doc__, "truncate($module, /, path, length)\n" @@ -12538,51 +4060,9 @@ return return_value; } -static PyObject * -os_truncate_impl(PyModuleDef *module, path_t *path, Py_off_t length) -/*[clinic end generated code: output=6bd76262d2e027c6 input=77229cf0b50a9b77]*/ -{ - int result; - - Py_BEGIN_ALLOW_THREADS -#ifdef HAVE_FTRUNCATE - if (path->fd != -1) - result = ftruncate(path->fd, length); - else -#endif - result = truncate(path->narrow, length); - Py_END_ALLOW_THREADS - if (result < 0) - return path_error(path); - - Py_RETURN_NONE; -} -#endif /* HAVE_TRUNCATE */ - - -/* Issue #22396: On 32-bit AIX platform, the prototypes of os.posix_fadvise() - and os.posix_fallocate() in system headers are wrong if _LARGE_FILES is - defined, which is the case in Python on AIX. AIX bug report: - http://www-01.ibm.com/support/docview.wss?uid=isg1IV56170 */ -#if defined(_AIX) && defined(_LARGE_FILES) && !defined(__64BIT__) -# define POSIX_FADVISE_AIX_BUG -#endif - - -#if defined(HAVE_POSIX_FALLOCATE) && !defined(POSIX_FADVISE_AIX_BUG) -/*[clinic input] -os.posix_fallocate - - fd: int - offset: Py_off_t - length: Py_off_t - / - -Ensure a file has allocated at least a particular number of bytes on disk. - -Ensure that the file specified by fd encompasses a range of bytes -starting at offset bytes from the beginning and continuing for length bytes. -[clinic start generated code]*/ +#endif /* defined(HAVE_TRUNCATE) */ + +#if (defined(HAVE_POSIX_FALLOCATE) && !defined(POSIX_FADVISE_AIX_BUG)) PyDoc_STRVAR(os_posix_fallocate__doc__, "posix_fallocate($module, fd, offset, length, /)\n" @@ -12617,46 +4097,9 @@ return return_value; } -static PyObject * -os_posix_fallocate_impl(PyModuleDef *module, int fd, Py_off_t offset, Py_off_t length) -/*[clinic end generated code: output=0cd702d2065c79db input=d7a2ef0ab2ca52fb]*/ -{ - int result; - int async_err = 0; - - do { - Py_BEGIN_ALLOW_THREADS - result = posix_fallocate(fd, offset, length); - Py_END_ALLOW_THREADS - } while (result != 0 && errno == EINTR && - !(async_err = PyErr_CheckSignals())); - if (result != 0) - return (!async_err) ? posix_error() : NULL; - Py_RETURN_NONE; -} -#endif /* HAVE_POSIX_FALLOCATE) && !POSIX_FADVISE_AIX_BUG */ - - -#if defined(HAVE_POSIX_FADVISE) && !defined(POSIX_FADVISE_AIX_BUG) -/*[clinic input] -os.posix_fadvise - - fd: int - offset: Py_off_t - length: Py_off_t - advice: int - / - -Announce an intention to access data in a specific pattern. - -Announce an intention to access data in a specific pattern, thus allowing -the kernel to make optimizations. -The advice applies to the region of the file specified by fd starting at -offset and continuing for length bytes. -advice is one of POSIX_FADV_NORMAL, POSIX_FADV_SEQUENTIAL, -POSIX_FADV_RANDOM, POSIX_FADV_NOREUSE, POSIX_FADV_WILLNEED, or -POSIX_FADV_DONTNEED. -[clinic start generated code]*/ +#endif /* (defined(HAVE_POSIX_FALLOCATE) && !defined(POSIX_FADVISE_AIX_BUG)) */ + +#if (defined(HAVE_POSIX_FADVISE) && !defined(POSIX_FADVISE_AIX_BUG)) PyDoc_STRVAR(os_posix_fadvise__doc__, "posix_fadvise($module, fd, offset, length, advice, /)\n" @@ -12697,56 +4140,9 @@ return return_value; } -static PyObject * -os_posix_fadvise_impl(PyModuleDef *module, int fd, Py_off_t offset, Py_off_t length, int advice) -/*[clinic end generated code: output=dad93f32c04dd4f7 input=0fbe554edc2f04b5]*/ -{ - int result; - int async_err = 0; - - do { - Py_BEGIN_ALLOW_THREADS - result = posix_fadvise(fd, offset, length, advice); - Py_END_ALLOW_THREADS - } while (result != 0 && errno == EINTR && - !(async_err = PyErr_CheckSignals())); - if (result != 0) - return (!async_err) ? posix_error() : NULL; - Py_RETURN_NONE; -} -#endif /* HAVE_POSIX_FADVISE && !POSIX_FADVISE_AIX_BUG */ - -#ifdef HAVE_PUTENV - -/* Save putenv() parameters as values here, so we can collect them when they - * get re-set with another call for the same key. */ -static PyObject *posix_putenv_garbage; - -static void -posix_putenv_garbage_setitem(PyObject *name, PyObject *value) -{ - /* Install the first arg and newstr in posix_putenv_garbage; - * this will cause previous value to be collected. This has to - * happen after the real putenv() call because the old value - * was still accessible until then. */ - if (PyDict_SetItem(posix_putenv_garbage, name, value)) - /* really not much we can do; just leak */ - PyErr_Clear(); - else - Py_DECREF(value); -} - - -#ifdef MS_WINDOWS -/*[clinic input] -os.putenv - - name: unicode - value: unicode - / - -Change or add an environment variable. -[clinic start generated code]*/ +#endif /* (defined(HAVE_POSIX_FADVISE) && !defined(POSIX_FADVISE_AIX_BUG)) */ + +#if defined(HAVE_PUTENV) && defined(MS_WINDOWS) PyDoc_STRVAR(os_putenv__doc__, "putenv($module, name, value, /)\n" @@ -12777,49 +4173,9 @@ return return_value; } -static PyObject * -os_putenv_impl(PyModuleDef *module, PyObject *name, PyObject *value) -/*[clinic end generated code: output=5ce9ef9b15606e7e input=ba586581c2e6105f]*/ -{ - wchar_t *env; - - PyObject *unicode = PyUnicode_FromFormat("%U=%U", name, value); - if (unicode == NULL) { - PyErr_NoMemory(); - return NULL; - } - if (_MAX_ENV < PyUnicode_GET_LENGTH(unicode)) { - PyErr_Format(PyExc_ValueError, - "the environment variable is longer than %u characters", - _MAX_ENV); - goto error; - } - - env = PyUnicode_AsUnicode(unicode); - if (env == NULL) - goto error; - if (_wputenv(env)) { - posix_error(); - goto error; - } - - posix_putenv_garbage_setitem(name, unicode); - Py_RETURN_NONE; - -error: - Py_DECREF(unicode); - return NULL; -} -#else /* MS_WINDOWS */ -/*[clinic input] -os.putenv - - name: FSConverter - value: FSConverter - / - -Change or add an environment variable. -[clinic start generated code]*/ +#endif /* defined(HAVE_PUTENV) && defined(MS_WINDOWS) */ + +#if defined(HAVE_PUTENV) && !defined(MS_WINDOWS) PyDoc_STRVAR(os_putenv__doc__, "putenv($module, name, value, /)\n" @@ -12855,42 +4211,9 @@ return return_value; } -static PyObject * -os_putenv_impl(PyModuleDef *module, PyObject *name, PyObject *value) -/*[clinic end generated code: output=85ab223393dc7afd input=a97bc6152f688d31]*/ -{ - PyObject *bytes = NULL; - char *env; - char *name_string = PyBytes_AsString(name); - char *value_string = PyBytes_AsString(value); - - bytes = PyBytes_FromFormat("%s=%s", name_string, value_string); - if (bytes == NULL) { - PyErr_NoMemory(); - return NULL; - } - - env = PyBytes_AS_STRING(bytes); - if (putenv(env)) { - Py_DECREF(bytes); - return posix_error(); - } - - posix_putenv_garbage_setitem(name, bytes); - Py_RETURN_NONE; -} -#endif /* MS_WINDOWS */ -#endif /* HAVE_PUTENV */ - - -#ifdef HAVE_UNSETENV -/*[clinic input] -os.unsetenv - name: FSConverter - / - -Delete an environment variable. -[clinic start generated code]*/ +#endif /* defined(HAVE_PUTENV) && !defined(MS_WINDOWS) */ + +#if defined(HAVE_UNSETENV) PyDoc_STRVAR(os_unsetenv__doc__, "unsetenv($module, name, /)\n" @@ -12923,44 +4246,7 @@ return return_value; } -static PyObject * -os_unsetenv_impl(PyModuleDef *module, PyObject *name) -/*[clinic end generated code: output=91318c995f9a0767 input=2bb5288a599c7107]*/ -{ -#ifndef HAVE_BROKEN_UNSETENV - int err; -#endif - -#ifdef HAVE_BROKEN_UNSETENV - unsetenv(PyBytes_AS_STRING(name)); -#else - err = unsetenv(PyBytes_AS_STRING(name)); - if (err) - return posix_error(); -#endif - - /* Remove the key from posix_putenv_garbage; - * this will cause it to be collected. This has to - * happen after the real unsetenv() call because the - * old value was still accessible until then. - */ - if (PyDict_DelItem(posix_putenv_garbage, name)) { - /* really not much we can do; just leak */ - PyErr_Clear(); - } - Py_RETURN_NONE; -} -#endif /* HAVE_UNSETENV */ - - -/*[clinic input] -os.strerror - - code: int - / - -Translate an error code to a message string. -[clinic start generated code]*/ +#endif /* defined(HAVE_UNSETENV) */ PyDoc_STRVAR(os_strerror__doc__, "strerror($module, code, /)\n" @@ -12990,30 +4276,7 @@ return return_value; } -static PyObject * -os_strerror_impl(PyModuleDef *module, int code) -/*[clinic end generated code: output=8665c70bb2ca4720 input=75a8673d97915a91]*/ -{ - char *message = strerror(code); - if (message == NULL) { - PyErr_SetString(PyExc_ValueError, - "strerror() argument out of range"); - return NULL; - } - return PyUnicode_DecodeLocale(message, "surrogateescape"); -} - - -#ifdef HAVE_SYS_WAIT_H -#ifdef WCOREDUMP -/*[clinic input] -os.WCOREDUMP -> bool - - status: int - / - -Return True if the process returning status was dumped to a core file. -[clinic start generated code]*/ +#if defined(HAVE_SYS_WAIT_H) && defined(WCOREDUMP) PyDoc_STRVAR(os_WCOREDUMP__doc__, "WCOREDUMP($module, status, /)\n" @@ -13047,28 +4310,9 @@ return return_value; } -static int -os_WCOREDUMP_impl(PyModuleDef *module, int status) -/*[clinic end generated code: output=e04d55c09c299828 input=8b05e7ab38528d04]*/ -{ - WAIT_TYPE wait_status; - WAIT_STATUS_INT(wait_status) = status; - return WCOREDUMP(wait_status); -} -#endif /* WCOREDUMP */ - - -#ifdef WIFCONTINUED -/*[clinic input] -os.WIFCONTINUED -> bool - - status: int - -Return True if a particular process was continued from a job control stop. - -Return True if the process returning status was continued from a -job control stop. -[clinic start generated code]*/ +#endif /* defined(HAVE_SYS_WAIT_H) && defined(WCOREDUMP) */ + +#if defined(HAVE_SYS_WAIT_H) && defined(WIFCONTINUED) PyDoc_STRVAR(os_WIFCONTINUED__doc__, "WIFCONTINUED($module, /, status)\n" @@ -13106,25 +4350,9 @@ return return_value; } -static int -os_WIFCONTINUED_impl(PyModuleDef *module, int status) -/*[clinic end generated code: output=9c4e6105a4520ab5 input=e777e7d38eb25bd9]*/ -{ - WAIT_TYPE wait_status; - WAIT_STATUS_INT(wait_status) = status; - return WIFCONTINUED(wait_status); -} -#endif /* WIFCONTINUED */ - - -#ifdef WIFSTOPPED -/*[clinic input] -os.WIFSTOPPED -> bool - - status: int - -Return True if the process returning status was stopped. -[clinic start generated code]*/ +#endif /* defined(HAVE_SYS_WAIT_H) && defined(WIFCONTINUED) */ + +#if defined(HAVE_SYS_WAIT_H) && defined(WIFSTOPPED) PyDoc_STRVAR(os_WIFSTOPPED__doc__, "WIFSTOPPED($module, /, status)\n" @@ -13159,25 +4387,9 @@ return return_value; } -static int -os_WIFSTOPPED_impl(PyModuleDef *module, int status) -/*[clinic end generated code: output=e0de2da8ec9593ff input=043cb7f1289ef904]*/ -{ - WAIT_TYPE wait_status; - WAIT_STATUS_INT(wait_status) = status; - return WIFSTOPPED(wait_status); -} -#endif /* WIFSTOPPED */ - - -#ifdef WIFSIGNALED -/*[clinic input] -os.WIFSIGNALED -> bool - - status: int - -Return True if the process returning status was terminated by a signal. -[clinic start generated code]*/ +#endif /* defined(HAVE_SYS_WAIT_H) && defined(WIFSTOPPED) */ + +#if defined(HAVE_SYS_WAIT_H) && defined(WIFSIGNALED) PyDoc_STRVAR(os_WIFSIGNALED__doc__, "WIFSIGNALED($module, /, status)\n" @@ -13212,25 +4424,9 @@ return return_value; } -static int -os_WIFSIGNALED_impl(PyModuleDef *module, int status) -/*[clinic end generated code: output=f14d106558f406be input=d55ba7cc9ce5dc43]*/ -{ - WAIT_TYPE wait_status; - WAIT_STATUS_INT(wait_status) = status; - return WIFSIGNALED(wait_status); -} -#endif /* WIFSIGNALED */ - - -#ifdef WIFEXITED -/*[clinic input] -os.WIFEXITED -> bool - - status: int - -Return True if the process returning status exited via the exit() system call. -[clinic start generated code]*/ +#endif /* defined(HAVE_SYS_WAIT_H) && defined(WIFSIGNALED) */ + +#if defined(HAVE_SYS_WAIT_H) && defined(WIFEXITED) PyDoc_STRVAR(os_WIFEXITED__doc__, "WIFEXITED($module, /, status)\n" @@ -13265,25 +4461,9 @@ return return_value; } -static int -os_WIFEXITED_impl(PyModuleDef *module, int status) -/*[clinic end generated code: output=2f76087d53721255 input=d63775a6791586c0]*/ -{ - WAIT_TYPE wait_status; - WAIT_STATUS_INT(wait_status) = status; - return WIFEXITED(wait_status); -} -#endif /* WIFEXITED */ - - -#ifdef WEXITSTATUS -/*[clinic input] -os.WEXITSTATUS -> int - - status: int - -Return the process return code from status. -[clinic start generated code]*/ +#endif /* defined(HAVE_SYS_WAIT_H) && defined(WIFEXITED) */ + +#if defined(HAVE_SYS_WAIT_H) && defined(WEXITSTATUS) PyDoc_STRVAR(os_WEXITSTATUS__doc__, "WEXITSTATUS($module, /, status)\n" @@ -13318,25 +4498,9 @@ return return_value; } -static int -os_WEXITSTATUS_impl(PyModuleDef *module, int status) -/*[clinic end generated code: output=13b6c270e2a326b1 input=e1fb4944e377585b]*/ -{ - WAIT_TYPE wait_status; - WAIT_STATUS_INT(wait_status) = status; - return WEXITSTATUS(wait_status); -} -#endif /* WEXITSTATUS */ - - -#ifdef WTERMSIG -/*[clinic input] -os.WTERMSIG -> int - - status: int - -Return the signal that terminated the process that provided the status value. -[clinic start generated code]*/ +#endif /* defined(HAVE_SYS_WAIT_H) && defined(WEXITSTATUS) */ + +#if defined(HAVE_SYS_WAIT_H) && defined(WTERMSIG) PyDoc_STRVAR(os_WTERMSIG__doc__, "WTERMSIG($module, /, status)\n" @@ -13371,25 +4535,9 @@ return return_value; } -static int -os_WTERMSIG_impl(PyModuleDef *module, int status) -/*[clinic end generated code: output=bf1fd4b002d0a9ed input=727fd7f84ec3f243]*/ -{ - WAIT_TYPE wait_status; - WAIT_STATUS_INT(wait_status) = status; - return WTERMSIG(wait_status); -} -#endif /* WTERMSIG */ - - -#ifdef WSTOPSIG -/*[clinic input] -os.WSTOPSIG -> int - - status: int - -Return the signal that stopped the process that provided the status value. -[clinic start generated code]*/ +#endif /* defined(HAVE_SYS_WAIT_H) && defined(WTERMSIG) */ + +#if defined(HAVE_SYS_WAIT_H) && defined(WSTOPSIG) PyDoc_STRVAR(os_WSTOPSIG__doc__, "WSTOPSIG($module, /, status)\n" @@ -13424,112 +4572,9 @@ return return_value; } -static int -os_WSTOPSIG_impl(PyModuleDef *module, int status) -/*[clinic end generated code: output=92e1647d29ee0549 input=46ebf1d1b293c5c1]*/ -{ - WAIT_TYPE wait_status; - WAIT_STATUS_INT(wait_status) = status; - return WSTOPSIG(wait_status); -} -#endif /* WSTOPSIG */ -#endif /* HAVE_SYS_WAIT_H */ - - -#ifndef OS_WCOREDUMP_METHODDEF -#define OS_WCOREDUMP_METHODDEF -#endif /* OS_WCOREDUMP_METHODDEF */ - -#ifndef OS_WIFCONTINUED_METHODDEF -#define OS_WIFCONTINUED_METHODDEF -#endif /* OS_WIFCONTINUED_METHODDEF */ - -#ifndef OS_WIFSTOPPED_METHODDEF -#define OS_WIFSTOPPED_METHODDEF -#endif /* OS_WIFSTOPPED_METHODDEF */ - -#ifndef OS_WIFSIGNALED_METHODDEF -#define OS_WIFSIGNALED_METHODDEF -#endif /* OS_WIFSIGNALED_METHODDEF */ - -#ifndef OS_WIFEXITED_METHODDEF -#define OS_WIFEXITED_METHODDEF -#endif /* OS_WIFEXITED_METHODDEF */ - -#ifndef OS_WEXITSTATUS_METHODDEF -#define OS_WEXITSTATUS_METHODDEF -#endif /* OS_WEXITSTATUS_METHODDEF */ - -#ifndef OS_WTERMSIG_METHODDEF -#define OS_WTERMSIG_METHODDEF -#endif /* OS_WTERMSIG_METHODDEF */ - -#ifndef OS_WSTOPSIG_METHODDEF -#define OS_WSTOPSIG_METHODDEF -#endif /* OS_WSTOPSIG_METHODDEF */ - - -#if defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H) -#ifdef _SCO_DS -/* SCO OpenServer 5.0 and later requires _SVID3 before it reveals the - needed definitions in sys/statvfs.h */ -#define _SVID3 -#endif -#include - -static PyObject* -_pystatvfs_fromstructstatvfs(struct statvfs st) { - PyObject *v = PyStructSequence_New(&StatVFSResultType); - if (v == NULL) - return NULL; - -#if !defined(HAVE_LARGEFILE_SUPPORT) - PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long) st.f_bsize)); - PyStructSequence_SET_ITEM(v, 1, PyLong_FromLong((long) st.f_frsize)); - PyStructSequence_SET_ITEM(v, 2, PyLong_FromLong((long) st.f_blocks)); - PyStructSequence_SET_ITEM(v, 3, PyLong_FromLong((long) st.f_bfree)); - PyStructSequence_SET_ITEM(v, 4, PyLong_FromLong((long) st.f_bavail)); - PyStructSequence_SET_ITEM(v, 5, PyLong_FromLong((long) st.f_files)); - PyStructSequence_SET_ITEM(v, 6, PyLong_FromLong((long) st.f_ffree)); - PyStructSequence_SET_ITEM(v, 7, PyLong_FromLong((long) st.f_favail)); - PyStructSequence_SET_ITEM(v, 8, PyLong_FromLong((long) st.f_flag)); - PyStructSequence_SET_ITEM(v, 9, PyLong_FromLong((long) st.f_namemax)); -#else - PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long) st.f_bsize)); - PyStructSequence_SET_ITEM(v, 1, PyLong_FromLong((long) st.f_frsize)); - PyStructSequence_SET_ITEM(v, 2, - PyLong_FromLongLong((PY_LONG_LONG) st.f_blocks)); - PyStructSequence_SET_ITEM(v, 3, - PyLong_FromLongLong((PY_LONG_LONG) st.f_bfree)); - PyStructSequence_SET_ITEM(v, 4, - PyLong_FromLongLong((PY_LONG_LONG) st.f_bavail)); - PyStructSequence_SET_ITEM(v, 5, - PyLong_FromLongLong((PY_LONG_LONG) st.f_files)); - PyStructSequence_SET_ITEM(v, 6, - PyLong_FromLongLong((PY_LONG_LONG) st.f_ffree)); - PyStructSequence_SET_ITEM(v, 7, - PyLong_FromLongLong((PY_LONG_LONG) st.f_favail)); - PyStructSequence_SET_ITEM(v, 8, PyLong_FromLong((long) st.f_flag)); - PyStructSequence_SET_ITEM(v, 9, PyLong_FromLong((long) st.f_namemax)); -#endif - if (PyErr_Occurred()) { - Py_DECREF(v); - return NULL; - } - - return v; -} - - -/*[clinic input] -os.fstatvfs - fd: int - / - -Perform an fstatvfs system call on the given fd. - -Equivalent to statvfs(fd). -[clinic start generated code]*/ +#endif /* defined(HAVE_SYS_WAIT_H) && defined(WSTOPSIG) */ + +#if (defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H)) PyDoc_STRVAR(os_fstatvfs__doc__, "fstatvfs($module, fd, /)\n" @@ -13561,41 +4606,9 @@ return return_value; } -static PyObject * -os_fstatvfs_impl(PyModuleDef *module, int fd) -/*[clinic end generated code: output=0e32bf07f946ec0d input=d8122243ac50975e]*/ -{ - int result; - int async_err = 0; - struct statvfs st; - - do { - Py_BEGIN_ALLOW_THREADS - result = fstatvfs(fd, &st); - Py_END_ALLOW_THREADS - } while (result != 0 && errno == EINTR && - !(async_err = PyErr_CheckSignals())); - if (result != 0) - return (!async_err) ? posix_error() : NULL; - - return _pystatvfs_fromstructstatvfs(st); -} -#endif /* defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H) */ - - -#if defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H) -#include -/*[clinic input] -os.statvfs - - path: path_t(allow_fd='PATH_HAVE_FSTATVFS') - -Perform a statvfs system call on the given path. - -path may always be specified as a string. -On some platforms, path may also be specified as an open file descriptor. - If this functionality is unavailable, using it raises an exception. -[clinic start generated code]*/ +#endif /* (defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H)) */ + +#if (defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H)) PyDoc_STRVAR(os_statvfs__doc__, "statvfs($module, /, path)\n" @@ -13633,47 +4646,9 @@ return return_value; } -static PyObject * -os_statvfs_impl(PyModuleDef *module, path_t *path) -/*[clinic end generated code: output=00ff54983360b446 input=3f5c35791c669bd9]*/ -{ - int result; - struct statvfs st; - - Py_BEGIN_ALLOW_THREADS -#ifdef HAVE_FSTATVFS - if (path->fd != -1) { -#ifdef __APPLE__ - /* handle weak-linking on Mac OS X 10.3 */ - if (fstatvfs == NULL) { - fd_specified("statvfs", path->fd); - return NULL; - } -#endif - result = fstatvfs(path->fd, &st); - } - else -#endif - result = statvfs(path->narrow, &st); - Py_END_ALLOW_THREADS - - if (result) { - return path_error(path); - } - - return _pystatvfs_fromstructstatvfs(st); -} -#endif /* defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H) */ - - -#ifdef MS_WINDOWS -/*[clinic input] -os._getdiskusage - - path: Py_UNICODE - -Return disk usage statistics about the given path as a (total, free) tuple. -[clinic start generated code]*/ +#endif /* (defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H)) */ + +#if defined(MS_WINDOWS) PyDoc_STRVAR(os__getdiskusage__doc__, "_getdiskusage($module, /, path)\n" @@ -13704,191 +4679,9 @@ return return_value; } -static PyObject * -os__getdiskusage_impl(PyModuleDef *module, Py_UNICODE *path) -/*[clinic end generated code: output=054c972179b13708 input=6458133aed893c78]*/ -{ - BOOL retval; - ULARGE_INTEGER _, total, free; - - Py_BEGIN_ALLOW_THREADS - retval = GetDiskFreeSpaceExW(path, &_, &total, &free); - Py_END_ALLOW_THREADS - if (retval == 0) - return PyErr_SetFromWindowsErr(0); - - return Py_BuildValue("(LL)", total.QuadPart, free.QuadPart); -} -#endif /* MS_WINDOWS */ - - -/* This is used for fpathconf(), pathconf(), confstr() and sysconf(). - * It maps strings representing configuration variable names to - * integer values, allowing those functions to be called with the - * magic names instead of polluting the module's namespace with tons of - * rarely-used constants. There are three separate tables that use - * these definitions. - * - * This code is always included, even if none of the interfaces that - * need it are included. The #if hackery needed to avoid it would be - * sufficiently pervasive that it's not worth the loss of readability. - */ -struct constdef { - char *name; - long value; -}; - -static int -conv_confname(PyObject *arg, int *valuep, struct constdef *table, - size_t tablesize) -{ - if (PyLong_Check(arg)) { - *valuep = PyLong_AS_LONG(arg); - return 1; - } - else { - /* look up the value in the table using a binary search */ - size_t lo = 0; - size_t mid; - size_t hi = tablesize; - int cmp; - const char *confname; - if (!PyUnicode_Check(arg)) { - PyErr_SetString(PyExc_TypeError, - "configuration names must be strings or integers"); - return 0; - } - confname = _PyUnicode_AsString(arg); - if (confname == NULL) - return 0; - while (lo < hi) { - mid = (lo + hi) / 2; - cmp = strcmp(confname, table[mid].name); - if (cmp < 0) - hi = mid; - else if (cmp > 0) - lo = mid + 1; - else { - *valuep = table[mid].value; - return 1; - } - } - PyErr_SetString(PyExc_ValueError, "unrecognized configuration name"); - return 0; - } -} - - -#if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF) -static struct constdef posix_constants_pathconf[] = { -#ifdef _PC_ABI_AIO_XFER_MAX - {"PC_ABI_AIO_XFER_MAX", _PC_ABI_AIO_XFER_MAX}, -#endif -#ifdef _PC_ABI_ASYNC_IO - {"PC_ABI_ASYNC_IO", _PC_ABI_ASYNC_IO}, -#endif -#ifdef _PC_ASYNC_IO - {"PC_ASYNC_IO", _PC_ASYNC_IO}, -#endif -#ifdef _PC_CHOWN_RESTRICTED - {"PC_CHOWN_RESTRICTED", _PC_CHOWN_RESTRICTED}, -#endif -#ifdef _PC_FILESIZEBITS - {"PC_FILESIZEBITS", _PC_FILESIZEBITS}, -#endif -#ifdef _PC_LAST - {"PC_LAST", _PC_LAST}, -#endif -#ifdef _PC_LINK_MAX - {"PC_LINK_MAX", _PC_LINK_MAX}, -#endif -#ifdef _PC_MAX_CANON - {"PC_MAX_CANON", _PC_MAX_CANON}, -#endif -#ifdef _PC_MAX_INPUT - {"PC_MAX_INPUT", _PC_MAX_INPUT}, -#endif -#ifdef _PC_NAME_MAX - {"PC_NAME_MAX", _PC_NAME_MAX}, -#endif -#ifdef _PC_NO_TRUNC - {"PC_NO_TRUNC", _PC_NO_TRUNC}, -#endif -#ifdef _PC_PATH_MAX - {"PC_PATH_MAX", _PC_PATH_MAX}, -#endif -#ifdef _PC_PIPE_BUF - {"PC_PIPE_BUF", _PC_PIPE_BUF}, -#endif -#ifdef _PC_PRIO_IO - {"PC_PRIO_IO", _PC_PRIO_IO}, -#endif -#ifdef _PC_SOCK_MAXBUF - {"PC_SOCK_MAXBUF", _PC_SOCK_MAXBUF}, -#endif -#ifdef _PC_SYNC_IO - {"PC_SYNC_IO", _PC_SYNC_IO}, -#endif -#ifdef _PC_VDISABLE - {"PC_VDISABLE", _PC_VDISABLE}, -#endif -#ifdef _PC_ACL_ENABLED - {"PC_ACL_ENABLED", _PC_ACL_ENABLED}, -#endif -#ifdef _PC_MIN_HOLE_SIZE - {"PC_MIN_HOLE_SIZE", _PC_MIN_HOLE_SIZE}, -#endif -#ifdef _PC_ALLOC_SIZE_MIN - {"PC_ALLOC_SIZE_MIN", _PC_ALLOC_SIZE_MIN}, -#endif -#ifdef _PC_REC_INCR_XFER_SIZE - {"PC_REC_INCR_XFER_SIZE", _PC_REC_INCR_XFER_SIZE}, -#endif -#ifdef _PC_REC_MAX_XFER_SIZE - {"PC_REC_MAX_XFER_SIZE", _PC_REC_MAX_XFER_SIZE}, -#endif -#ifdef _PC_REC_MIN_XFER_SIZE - {"PC_REC_MIN_XFER_SIZE", _PC_REC_MIN_XFER_SIZE}, -#endif -#ifdef _PC_REC_XFER_ALIGN - {"PC_REC_XFER_ALIGN", _PC_REC_XFER_ALIGN}, -#endif -#ifdef _PC_SYMLINK_MAX - {"PC_SYMLINK_MAX", _PC_SYMLINK_MAX}, -#endif -#ifdef _PC_XATTR_ENABLED - {"PC_XATTR_ENABLED", _PC_XATTR_ENABLED}, -#endif -#ifdef _PC_XATTR_EXISTS - {"PC_XATTR_EXISTS", _PC_XATTR_EXISTS}, -#endif -#ifdef _PC_TIMESTAMP_RESOLUTION - {"PC_TIMESTAMP_RESOLUTION", _PC_TIMESTAMP_RESOLUTION}, -#endif -}; - -static int -conv_path_confname(PyObject *arg, int *valuep) -{ - return conv_confname(arg, valuep, posix_constants_pathconf, - sizeof(posix_constants_pathconf) - / sizeof(struct constdef)); -} -#endif - - -#ifdef HAVE_FPATHCONF -/*[clinic input] -os.fpathconf -> long - - fd: int - name: path_confname - / - -Return the configuration limit name for the file descriptor fd. - -If there is no limit, return -1. -[clinic start generated code]*/ +#endif /* defined(MS_WINDOWS) */ + +#if defined(HAVE_FPATHCONF) PyDoc_STRVAR(os_fpathconf__doc__, "fpathconf($module, fd, name, /)\n" @@ -13925,34 +4718,9 @@ return return_value; } -static long -os_fpathconf_impl(PyModuleDef *module, int fd, int name) -/*[clinic end generated code: output=3bf04b40e0523a8c input=5942a024d3777810]*/ -{ - long limit; - - errno = 0; - limit = fpathconf(fd, name); - if (limit == -1 && errno != 0) - posix_error(); - - return limit; -} -#endif /* HAVE_FPATHCONF */ - - -#ifdef HAVE_PATHCONF -/*[clinic input] -os.pathconf -> long - path: path_t(allow_fd='PATH_HAVE_FPATHCONF') - name: path_confname - -Return the configuration limit name for the file or directory path. - -If there is no limit, return -1. -On some platforms, path may also be specified as an open file descriptor. - If this functionality is unavailable, using it raises an exception. -[clinic start generated code]*/ +#endif /* defined(HAVE_FPATHCONF) */ + +#if defined(HAVE_PATHCONF) PyDoc_STRVAR(os_pathconf__doc__, "pathconf($module, /, path, name)\n" @@ -13995,202 +4763,9 @@ return return_value; } -static long -os_pathconf_impl(PyModuleDef *module, path_t *path, int name) -/*[clinic end generated code: output=1a53e125b6cf63e4 input=bc3e2a985af27e5e]*/ -{ - long limit; - - errno = 0; -#ifdef HAVE_FPATHCONF - if (path->fd != -1) - limit = fpathconf(path->fd, name); - else -#endif - limit = pathconf(path->narrow, name); - if (limit == -1 && errno != 0) { - if (errno == EINVAL) - /* could be a path or name problem */ - posix_error(); - else - path_error(path); - } - - return limit; -} -#endif /* HAVE_PATHCONF */ - -#ifdef HAVE_CONFSTR -static struct constdef posix_constants_confstr[] = { -#ifdef _CS_ARCHITECTURE - {"CS_ARCHITECTURE", _CS_ARCHITECTURE}, -#endif -#ifdef _CS_GNU_LIBC_VERSION - {"CS_GNU_LIBC_VERSION", _CS_GNU_LIBC_VERSION}, -#endif -#ifdef _CS_GNU_LIBPTHREAD_VERSION - {"CS_GNU_LIBPTHREAD_VERSION", _CS_GNU_LIBPTHREAD_VERSION}, -#endif -#ifdef _CS_HOSTNAME - {"CS_HOSTNAME", _CS_HOSTNAME}, -#endif -#ifdef _CS_HW_PROVIDER - {"CS_HW_PROVIDER", _CS_HW_PROVIDER}, -#endif -#ifdef _CS_HW_SERIAL - {"CS_HW_SERIAL", _CS_HW_SERIAL}, -#endif -#ifdef _CS_INITTAB_NAME - {"CS_INITTAB_NAME", _CS_INITTAB_NAME}, -#endif -#ifdef _CS_LFS64_CFLAGS - {"CS_LFS64_CFLAGS", _CS_LFS64_CFLAGS}, -#endif -#ifdef _CS_LFS64_LDFLAGS - {"CS_LFS64_LDFLAGS", _CS_LFS64_LDFLAGS}, -#endif -#ifdef _CS_LFS64_LIBS - {"CS_LFS64_LIBS", _CS_LFS64_LIBS}, -#endif -#ifdef _CS_LFS64_LINTFLAGS - {"CS_LFS64_LINTFLAGS", _CS_LFS64_LINTFLAGS}, -#endif -#ifdef _CS_LFS_CFLAGS - {"CS_LFS_CFLAGS", _CS_LFS_CFLAGS}, -#endif -#ifdef _CS_LFS_LDFLAGS - {"CS_LFS_LDFLAGS", _CS_LFS_LDFLAGS}, -#endif -#ifdef _CS_LFS_LIBS - {"CS_LFS_LIBS", _CS_LFS_LIBS}, -#endif -#ifdef _CS_LFS_LINTFLAGS - {"CS_LFS_LINTFLAGS", _CS_LFS_LINTFLAGS}, -#endif -#ifdef _CS_MACHINE - {"CS_MACHINE", _CS_MACHINE}, -#endif -#ifdef _CS_PATH - {"CS_PATH", _CS_PATH}, -#endif -#ifdef _CS_RELEASE - {"CS_RELEASE", _CS_RELEASE}, -#endif -#ifdef _CS_SRPC_DOMAIN - {"CS_SRPC_DOMAIN", _CS_SRPC_DOMAIN}, -#endif -#ifdef _CS_SYSNAME - {"CS_SYSNAME", _CS_SYSNAME}, -#endif -#ifdef _CS_VERSION - {"CS_VERSION", _CS_VERSION}, -#endif -#ifdef _CS_XBS5_ILP32_OFF32_CFLAGS - {"CS_XBS5_ILP32_OFF32_CFLAGS", _CS_XBS5_ILP32_OFF32_CFLAGS}, -#endif -#ifdef _CS_XBS5_ILP32_OFF32_LDFLAGS - {"CS_XBS5_ILP32_OFF32_LDFLAGS", _CS_XBS5_ILP32_OFF32_LDFLAGS}, -#endif -#ifdef _CS_XBS5_ILP32_OFF32_LIBS - {"CS_XBS5_ILP32_OFF32_LIBS", _CS_XBS5_ILP32_OFF32_LIBS}, -#endif -#ifdef _CS_XBS5_ILP32_OFF32_LINTFLAGS - {"CS_XBS5_ILP32_OFF32_LINTFLAGS", _CS_XBS5_ILP32_OFF32_LINTFLAGS}, -#endif -#ifdef _CS_XBS5_ILP32_OFFBIG_CFLAGS - {"CS_XBS5_ILP32_OFFBIG_CFLAGS", _CS_XBS5_ILP32_OFFBIG_CFLAGS}, -#endif -#ifdef _CS_XBS5_ILP32_OFFBIG_LDFLAGS - {"CS_XBS5_ILP32_OFFBIG_LDFLAGS", _CS_XBS5_ILP32_OFFBIG_LDFLAGS}, -#endif -#ifdef _CS_XBS5_ILP32_OFFBIG_LIBS - {"CS_XBS5_ILP32_OFFBIG_LIBS", _CS_XBS5_ILP32_OFFBIG_LIBS}, -#endif -#ifdef _CS_XBS5_ILP32_OFFBIG_LINTFLAGS - {"CS_XBS5_ILP32_OFFBIG_LINTFLAGS", _CS_XBS5_ILP32_OFFBIG_LINTFLAGS}, -#endif -#ifdef _CS_XBS5_LP64_OFF64_CFLAGS - {"CS_XBS5_LP64_OFF64_CFLAGS", _CS_XBS5_LP64_OFF64_CFLAGS}, -#endif -#ifdef _CS_XBS5_LP64_OFF64_LDFLAGS - {"CS_XBS5_LP64_OFF64_LDFLAGS", _CS_XBS5_LP64_OFF64_LDFLAGS}, -#endif -#ifdef _CS_XBS5_LP64_OFF64_LIBS - {"CS_XBS5_LP64_OFF64_LIBS", _CS_XBS5_LP64_OFF64_LIBS}, -#endif -#ifdef _CS_XBS5_LP64_OFF64_LINTFLAGS - {"CS_XBS5_LP64_OFF64_LINTFLAGS", _CS_XBS5_LP64_OFF64_LINTFLAGS}, -#endif -#ifdef _CS_XBS5_LPBIG_OFFBIG_CFLAGS - {"CS_XBS5_LPBIG_OFFBIG_CFLAGS", _CS_XBS5_LPBIG_OFFBIG_CFLAGS}, -#endif -#ifdef _CS_XBS5_LPBIG_OFFBIG_LDFLAGS - {"CS_XBS5_LPBIG_OFFBIG_LDFLAGS", _CS_XBS5_LPBIG_OFFBIG_LDFLAGS}, -#endif -#ifdef _CS_XBS5_LPBIG_OFFBIG_LIBS - {"CS_XBS5_LPBIG_OFFBIG_LIBS", _CS_XBS5_LPBIG_OFFBIG_LIBS}, -#endif -#ifdef _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS - {"CS_XBS5_LPBIG_OFFBIG_LINTFLAGS", _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS}, -#endif -#ifdef _MIPS_CS_AVAIL_PROCESSORS - {"MIPS_CS_AVAIL_PROCESSORS", _MIPS_CS_AVAIL_PROCESSORS}, -#endif -#ifdef _MIPS_CS_BASE - {"MIPS_CS_BASE", _MIPS_CS_BASE}, -#endif -#ifdef _MIPS_CS_HOSTID - {"MIPS_CS_HOSTID", _MIPS_CS_HOSTID}, -#endif -#ifdef _MIPS_CS_HW_NAME - {"MIPS_CS_HW_NAME", _MIPS_CS_HW_NAME}, -#endif -#ifdef _MIPS_CS_NUM_PROCESSORS - {"MIPS_CS_NUM_PROCESSORS", _MIPS_CS_NUM_PROCESSORS}, -#endif -#ifdef _MIPS_CS_OSREL_MAJ - {"MIPS_CS_OSREL_MAJ", _MIPS_CS_OSREL_MAJ}, -#endif -#ifdef _MIPS_CS_OSREL_MIN - {"MIPS_CS_OSREL_MIN", _MIPS_CS_OSREL_MIN}, -#endif -#ifdef _MIPS_CS_OSREL_PATCH - {"MIPS_CS_OSREL_PATCH", _MIPS_CS_OSREL_PATCH}, -#endif -#ifdef _MIPS_CS_OS_NAME - {"MIPS_CS_OS_NAME", _MIPS_CS_OS_NAME}, -#endif -#ifdef _MIPS_CS_OS_PROVIDER - {"MIPS_CS_OS_PROVIDER", _MIPS_CS_OS_PROVIDER}, -#endif -#ifdef _MIPS_CS_PROCESSORS - {"MIPS_CS_PROCESSORS", _MIPS_CS_PROCESSORS}, -#endif -#ifdef _MIPS_CS_SERIAL - {"MIPS_CS_SERIAL", _MIPS_CS_SERIAL}, -#endif -#ifdef _MIPS_CS_VENDOR - {"MIPS_CS_VENDOR", _MIPS_CS_VENDOR}, -#endif -}; - -static int -conv_confstr_confname(PyObject *arg, int *valuep) -{ - return conv_confname(arg, valuep, posix_constants_confstr, - sizeof(posix_constants_confstr) - / sizeof(struct constdef)); -} - - -/*[clinic input] -os.confstr - - name: confstr_confname - / - -Return a string-valued system configuration variable. -[clinic start generated code]*/ +#endif /* defined(HAVE_PATHCONF) */ + +#if defined(HAVE_CONFSTR) PyDoc_STRVAR(os_confstr__doc__, "confstr($module, name, /)\n" @@ -14220,555 +4795,9 @@ return return_value; } -static PyObject * -os_confstr_impl(PyModuleDef *module, int name) -/*[clinic end generated code: output=3f5e8aba9f8e3174 input=18fb4d0567242e65]*/ -{ - PyObject *result = NULL; - char buffer[255]; - size_t len; - - errno = 0; - len = confstr(name, buffer, sizeof(buffer)); - if (len == 0) { - if (errno) { - posix_error(); - return NULL; - } - else { - Py_RETURN_NONE; - } - } - - if (len >= sizeof(buffer)) { - size_t len2; - char *buf = PyMem_Malloc(len); - if (buf == NULL) - return PyErr_NoMemory(); - len2 = confstr(name, buf, len); - assert(len == len2); - result = PyUnicode_DecodeFSDefaultAndSize(buf, len-1); - PyMem_Free(buf); - } - else - result = PyUnicode_DecodeFSDefaultAndSize(buffer, len-1); - return result; -} -#endif /* HAVE_CONFSTR */ - - -#ifdef HAVE_SYSCONF -static struct constdef posix_constants_sysconf[] = { -#ifdef _SC_2_CHAR_TERM - {"SC_2_CHAR_TERM", _SC_2_CHAR_TERM}, -#endif -#ifdef _SC_2_C_BIND - {"SC_2_C_BIND", _SC_2_C_BIND}, -#endif -#ifdef _SC_2_C_DEV - {"SC_2_C_DEV", _SC_2_C_DEV}, -#endif -#ifdef _SC_2_C_VERSION - {"SC_2_C_VERSION", _SC_2_C_VERSION}, -#endif -#ifdef _SC_2_FORT_DEV - {"SC_2_FORT_DEV", _SC_2_FORT_DEV}, -#endif -#ifdef _SC_2_FORT_RUN - {"SC_2_FORT_RUN", _SC_2_FORT_RUN}, -#endif -#ifdef _SC_2_LOCALEDEF - {"SC_2_LOCALEDEF", _SC_2_LOCALEDEF}, -#endif -#ifdef _SC_2_SW_DEV - {"SC_2_SW_DEV", _SC_2_SW_DEV}, -#endif -#ifdef _SC_2_UPE - {"SC_2_UPE", _SC_2_UPE}, -#endif -#ifdef _SC_2_VERSION - {"SC_2_VERSION", _SC_2_VERSION}, -#endif -#ifdef _SC_ABI_ASYNCHRONOUS_IO - {"SC_ABI_ASYNCHRONOUS_IO", _SC_ABI_ASYNCHRONOUS_IO}, -#endif -#ifdef _SC_ACL - {"SC_ACL", _SC_ACL}, -#endif -#ifdef _SC_AIO_LISTIO_MAX - {"SC_AIO_LISTIO_MAX", _SC_AIO_LISTIO_MAX}, -#endif -#ifdef _SC_AIO_MAX - {"SC_AIO_MAX", _SC_AIO_MAX}, -#endif -#ifdef _SC_AIO_PRIO_DELTA_MAX - {"SC_AIO_PRIO_DELTA_MAX", _SC_AIO_PRIO_DELTA_MAX}, -#endif -#ifdef _SC_ARG_MAX - {"SC_ARG_MAX", _SC_ARG_MAX}, -#endif -#ifdef _SC_ASYNCHRONOUS_IO - {"SC_ASYNCHRONOUS_IO", _SC_ASYNCHRONOUS_IO}, -#endif -#ifdef _SC_ATEXIT_MAX - {"SC_ATEXIT_MAX", _SC_ATEXIT_MAX}, -#endif -#ifdef _SC_AUDIT - {"SC_AUDIT", _SC_AUDIT}, -#endif -#ifdef _SC_AVPHYS_PAGES - {"SC_AVPHYS_PAGES", _SC_AVPHYS_PAGES}, -#endif -#ifdef _SC_BC_BASE_MAX - {"SC_BC_BASE_MAX", _SC_BC_BASE_MAX}, -#endif -#ifdef _SC_BC_DIM_MAX - {"SC_BC_DIM_MAX", _SC_BC_DIM_MAX}, -#endif -#ifdef _SC_BC_SCALE_MAX - {"SC_BC_SCALE_MAX", _SC_BC_SCALE_MAX}, -#endif -#ifdef _SC_BC_STRING_MAX - {"SC_BC_STRING_MAX", _SC_BC_STRING_MAX}, -#endif -#ifdef _SC_CAP - {"SC_CAP", _SC_CAP}, -#endif -#ifdef _SC_CHARCLASS_NAME_MAX - {"SC_CHARCLASS_NAME_MAX", _SC_CHARCLASS_NAME_MAX}, -#endif -#ifdef _SC_CHAR_BIT - {"SC_CHAR_BIT", _SC_CHAR_BIT}, -#endif -#ifdef _SC_CHAR_MAX - {"SC_CHAR_MAX", _SC_CHAR_MAX}, -#endif -#ifdef _SC_CHAR_MIN - {"SC_CHAR_MIN", _SC_CHAR_MIN}, -#endif -#ifdef _SC_CHILD_MAX - {"SC_CHILD_MAX", _SC_CHILD_MAX}, -#endif -#ifdef _SC_CLK_TCK - {"SC_CLK_TCK", _SC_CLK_TCK}, -#endif -#ifdef _SC_COHER_BLKSZ - {"SC_COHER_BLKSZ", _SC_COHER_BLKSZ}, -#endif -#ifdef _SC_COLL_WEIGHTS_MAX - {"SC_COLL_WEIGHTS_MAX", _SC_COLL_WEIGHTS_MAX}, -#endif -#ifdef _SC_DCACHE_ASSOC - {"SC_DCACHE_ASSOC", _SC_DCACHE_ASSOC}, -#endif -#ifdef _SC_DCACHE_BLKSZ - {"SC_DCACHE_BLKSZ", _SC_DCACHE_BLKSZ}, -#endif -#ifdef _SC_DCACHE_LINESZ - {"SC_DCACHE_LINESZ", _SC_DCACHE_LINESZ}, -#endif -#ifdef _SC_DCACHE_SZ - {"SC_DCACHE_SZ", _SC_DCACHE_SZ}, -#endif -#ifdef _SC_DCACHE_TBLKSZ - {"SC_DCACHE_TBLKSZ", _SC_DCACHE_TBLKSZ}, -#endif -#ifdef _SC_DELAYTIMER_MAX - {"SC_DELAYTIMER_MAX", _SC_DELAYTIMER_MAX}, -#endif -#ifdef _SC_EQUIV_CLASS_MAX - {"SC_EQUIV_CLASS_MAX", _SC_EQUIV_CLASS_MAX}, -#endif -#ifdef _SC_EXPR_NEST_MAX - {"SC_EXPR_NEST_MAX", _SC_EXPR_NEST_MAX}, -#endif -#ifdef _SC_FSYNC - {"SC_FSYNC", _SC_FSYNC}, -#endif -#ifdef _SC_GETGR_R_SIZE_MAX - {"SC_GETGR_R_SIZE_MAX", _SC_GETGR_R_SIZE_MAX}, -#endif -#ifdef _SC_GETPW_R_SIZE_MAX - {"SC_GETPW_R_SIZE_MAX", _SC_GETPW_R_SIZE_MAX}, -#endif -#ifdef _SC_ICACHE_ASSOC - {"SC_ICACHE_ASSOC", _SC_ICACHE_ASSOC}, -#endif -#ifdef _SC_ICACHE_BLKSZ - {"SC_ICACHE_BLKSZ", _SC_ICACHE_BLKSZ}, -#endif -#ifdef _SC_ICACHE_LINESZ - {"SC_ICACHE_LINESZ", _SC_ICACHE_LINESZ}, -#endif -#ifdef _SC_ICACHE_SZ - {"SC_ICACHE_SZ", _SC_ICACHE_SZ}, -#endif -#ifdef _SC_INF - {"SC_INF", _SC_INF}, -#endif -#ifdef _SC_INT_MAX - {"SC_INT_MAX", _SC_INT_MAX}, -#endif -#ifdef _SC_INT_MIN - {"SC_INT_MIN", _SC_INT_MIN}, -#endif -#ifdef _SC_IOV_MAX - {"SC_IOV_MAX", _SC_IOV_MAX}, -#endif -#ifdef _SC_IP_SECOPTS - {"SC_IP_SECOPTS", _SC_IP_SECOPTS}, -#endif -#ifdef _SC_JOB_CONTROL - {"SC_JOB_CONTROL", _SC_JOB_CONTROL}, -#endif -#ifdef _SC_KERN_POINTERS - {"SC_KERN_POINTERS", _SC_KERN_POINTERS}, -#endif -#ifdef _SC_KERN_SIM - {"SC_KERN_SIM", _SC_KERN_SIM}, -#endif -#ifdef _SC_LINE_MAX - {"SC_LINE_MAX", _SC_LINE_MAX}, -#endif -#ifdef _SC_LOGIN_NAME_MAX - {"SC_LOGIN_NAME_MAX", _SC_LOGIN_NAME_MAX}, -#endif -#ifdef _SC_LOGNAME_MAX - {"SC_LOGNAME_MAX", _SC_LOGNAME_MAX}, -#endif -#ifdef _SC_LONG_BIT - {"SC_LONG_BIT", _SC_LONG_BIT}, -#endif -#ifdef _SC_MAC - {"SC_MAC", _SC_MAC}, -#endif -#ifdef _SC_MAPPED_FILES - {"SC_MAPPED_FILES", _SC_MAPPED_FILES}, -#endif -#ifdef _SC_MAXPID - {"SC_MAXPID", _SC_MAXPID}, -#endif -#ifdef _SC_MB_LEN_MAX - {"SC_MB_LEN_MAX", _SC_MB_LEN_MAX}, -#endif -#ifdef _SC_MEMLOCK - {"SC_MEMLOCK", _SC_MEMLOCK}, -#endif -#ifdef _SC_MEMLOCK_RANGE - {"SC_MEMLOCK_RANGE", _SC_MEMLOCK_RANGE}, -#endif -#ifdef _SC_MEMORY_PROTECTION - {"SC_MEMORY_PROTECTION", _SC_MEMORY_PROTECTION}, -#endif -#ifdef _SC_MESSAGE_PASSING - {"SC_MESSAGE_PASSING", _SC_MESSAGE_PASSING}, -#endif -#ifdef _SC_MMAP_FIXED_ALIGNMENT - {"SC_MMAP_FIXED_ALIGNMENT", _SC_MMAP_FIXED_ALIGNMENT}, -#endif -#ifdef _SC_MQ_OPEN_MAX - {"SC_MQ_OPEN_MAX", _SC_MQ_OPEN_MAX}, -#endif -#ifdef _SC_MQ_PRIO_MAX - {"SC_MQ_PRIO_MAX", _SC_MQ_PRIO_MAX}, -#endif -#ifdef _SC_NACLS_MAX - {"SC_NACLS_MAX", _SC_NACLS_MAX}, -#endif -#ifdef _SC_NGROUPS_MAX - {"SC_NGROUPS_MAX", _SC_NGROUPS_MAX}, -#endif -#ifdef _SC_NL_ARGMAX - {"SC_NL_ARGMAX", _SC_NL_ARGMAX}, -#endif -#ifdef _SC_NL_LANGMAX - {"SC_NL_LANGMAX", _SC_NL_LANGMAX}, -#endif -#ifdef _SC_NL_MSGMAX - {"SC_NL_MSGMAX", _SC_NL_MSGMAX}, -#endif -#ifdef _SC_NL_NMAX - {"SC_NL_NMAX", _SC_NL_NMAX}, -#endif -#ifdef _SC_NL_SETMAX - {"SC_NL_SETMAX", _SC_NL_SETMAX}, -#endif -#ifdef _SC_NL_TEXTMAX - {"SC_NL_TEXTMAX", _SC_NL_TEXTMAX}, -#endif -#ifdef _SC_NPROCESSORS_CONF - {"SC_NPROCESSORS_CONF", _SC_NPROCESSORS_CONF}, -#endif -#ifdef _SC_NPROCESSORS_ONLN - {"SC_NPROCESSORS_ONLN", _SC_NPROCESSORS_ONLN}, -#endif -#ifdef _SC_NPROC_CONF - {"SC_NPROC_CONF", _SC_NPROC_CONF}, -#endif -#ifdef _SC_NPROC_ONLN - {"SC_NPROC_ONLN", _SC_NPROC_ONLN}, -#endif -#ifdef _SC_NZERO - {"SC_NZERO", _SC_NZERO}, -#endif -#ifdef _SC_OPEN_MAX - {"SC_OPEN_MAX", _SC_OPEN_MAX}, -#endif -#ifdef _SC_PAGESIZE - {"SC_PAGESIZE", _SC_PAGESIZE}, -#endif -#ifdef _SC_PAGE_SIZE - {"SC_PAGE_SIZE", _SC_PAGE_SIZE}, -#endif -#ifdef _SC_PASS_MAX - {"SC_PASS_MAX", _SC_PASS_MAX}, -#endif -#ifdef _SC_PHYS_PAGES - {"SC_PHYS_PAGES", _SC_PHYS_PAGES}, -#endif -#ifdef _SC_PII - {"SC_PII", _SC_PII}, -#endif -#ifdef _SC_PII_INTERNET - {"SC_PII_INTERNET", _SC_PII_INTERNET}, -#endif -#ifdef _SC_PII_INTERNET_DGRAM - {"SC_PII_INTERNET_DGRAM", _SC_PII_INTERNET_DGRAM}, -#endif -#ifdef _SC_PII_INTERNET_STREAM - {"SC_PII_INTERNET_STREAM", _SC_PII_INTERNET_STREAM}, -#endif -#ifdef _SC_PII_OSI - {"SC_PII_OSI", _SC_PII_OSI}, -#endif -#ifdef _SC_PII_OSI_CLTS - {"SC_PII_OSI_CLTS", _SC_PII_OSI_CLTS}, -#endif -#ifdef _SC_PII_OSI_COTS - {"SC_PII_OSI_COTS", _SC_PII_OSI_COTS}, -#endif -#ifdef _SC_PII_OSI_M - {"SC_PII_OSI_M", _SC_PII_OSI_M}, -#endif -#ifdef _SC_PII_SOCKET - {"SC_PII_SOCKET", _SC_PII_SOCKET}, -#endif -#ifdef _SC_PII_XTI - {"SC_PII_XTI", _SC_PII_XTI}, -#endif -#ifdef _SC_POLL - {"SC_POLL", _SC_POLL}, -#endif -#ifdef _SC_PRIORITIZED_IO - {"SC_PRIORITIZED_IO", _SC_PRIORITIZED_IO}, -#endif -#ifdef _SC_PRIORITY_SCHEDULING - {"SC_PRIORITY_SCHEDULING", _SC_PRIORITY_SCHEDULING}, -#endif -#ifdef _SC_REALTIME_SIGNALS - {"SC_REALTIME_SIGNALS", _SC_REALTIME_SIGNALS}, -#endif -#ifdef _SC_RE_DUP_MAX - {"SC_RE_DUP_MAX", _SC_RE_DUP_MAX}, -#endif -#ifdef _SC_RTSIG_MAX - {"SC_RTSIG_MAX", _SC_RTSIG_MAX}, -#endif -#ifdef _SC_SAVED_IDS - {"SC_SAVED_IDS", _SC_SAVED_IDS}, -#endif -#ifdef _SC_SCHAR_MAX - {"SC_SCHAR_MAX", _SC_SCHAR_MAX}, -#endif -#ifdef _SC_SCHAR_MIN - {"SC_SCHAR_MIN", _SC_SCHAR_MIN}, -#endif -#ifdef _SC_SELECT - {"SC_SELECT", _SC_SELECT}, -#endif -#ifdef _SC_SEMAPHORES - {"SC_SEMAPHORES", _SC_SEMAPHORES}, -#endif -#ifdef _SC_SEM_NSEMS_MAX - {"SC_SEM_NSEMS_MAX", _SC_SEM_NSEMS_MAX}, -#endif -#ifdef _SC_SEM_VALUE_MAX - {"SC_SEM_VALUE_MAX", _SC_SEM_VALUE_MAX}, -#endif -#ifdef _SC_SHARED_MEMORY_OBJECTS - {"SC_SHARED_MEMORY_OBJECTS", _SC_SHARED_MEMORY_OBJECTS}, -#endif -#ifdef _SC_SHRT_MAX - {"SC_SHRT_MAX", _SC_SHRT_MAX}, -#endif -#ifdef _SC_SHRT_MIN - {"SC_SHRT_MIN", _SC_SHRT_MIN}, -#endif -#ifdef _SC_SIGQUEUE_MAX - {"SC_SIGQUEUE_MAX", _SC_SIGQUEUE_MAX}, -#endif -#ifdef _SC_SIGRT_MAX - {"SC_SIGRT_MAX", _SC_SIGRT_MAX}, -#endif -#ifdef _SC_SIGRT_MIN - {"SC_SIGRT_MIN", _SC_SIGRT_MIN}, -#endif -#ifdef _SC_SOFTPOWER - {"SC_SOFTPOWER", _SC_SOFTPOWER}, -#endif -#ifdef _SC_SPLIT_CACHE - {"SC_SPLIT_CACHE", _SC_SPLIT_CACHE}, -#endif -#ifdef _SC_SSIZE_MAX - {"SC_SSIZE_MAX", _SC_SSIZE_MAX}, -#endif -#ifdef _SC_STACK_PROT - {"SC_STACK_PROT", _SC_STACK_PROT}, -#endif -#ifdef _SC_STREAM_MAX - {"SC_STREAM_MAX", _SC_STREAM_MAX}, -#endif -#ifdef _SC_SYNCHRONIZED_IO - {"SC_SYNCHRONIZED_IO", _SC_SYNCHRONIZED_IO}, -#endif -#ifdef _SC_THREADS - {"SC_THREADS", _SC_THREADS}, -#endif -#ifdef _SC_THREAD_ATTR_STACKADDR - {"SC_THREAD_ATTR_STACKADDR", _SC_THREAD_ATTR_STACKADDR}, -#endif -#ifdef _SC_THREAD_ATTR_STACKSIZE - {"SC_THREAD_ATTR_STACKSIZE", _SC_THREAD_ATTR_STACKSIZE}, -#endif -#ifdef _SC_THREAD_DESTRUCTOR_ITERATIONS - {"SC_THREAD_DESTRUCTOR_ITERATIONS", _SC_THREAD_DESTRUCTOR_ITERATIONS}, -#endif -#ifdef _SC_THREAD_KEYS_MAX - {"SC_THREAD_KEYS_MAX", _SC_THREAD_KEYS_MAX}, -#endif -#ifdef _SC_THREAD_PRIORITY_SCHEDULING - {"SC_THREAD_PRIORITY_SCHEDULING", _SC_THREAD_PRIORITY_SCHEDULING}, -#endif -#ifdef _SC_THREAD_PRIO_INHERIT - {"SC_THREAD_PRIO_INHERIT", _SC_THREAD_PRIO_INHERIT}, -#endif -#ifdef _SC_THREAD_PRIO_PROTECT - {"SC_THREAD_PRIO_PROTECT", _SC_THREAD_PRIO_PROTECT}, -#endif -#ifdef _SC_THREAD_PROCESS_SHARED - {"SC_THREAD_PROCESS_SHARED", _SC_THREAD_PROCESS_SHARED}, -#endif -#ifdef _SC_THREAD_SAFE_FUNCTIONS - {"SC_THREAD_SAFE_FUNCTIONS", _SC_THREAD_SAFE_FUNCTIONS}, -#endif -#ifdef _SC_THREAD_STACK_MIN - {"SC_THREAD_STACK_MIN", _SC_THREAD_STACK_MIN}, -#endif -#ifdef _SC_THREAD_THREADS_MAX - {"SC_THREAD_THREADS_MAX", _SC_THREAD_THREADS_MAX}, -#endif -#ifdef _SC_TIMERS - {"SC_TIMERS", _SC_TIMERS}, -#endif -#ifdef _SC_TIMER_MAX - {"SC_TIMER_MAX", _SC_TIMER_MAX}, -#endif -#ifdef _SC_TTY_NAME_MAX - {"SC_TTY_NAME_MAX", _SC_TTY_NAME_MAX}, -#endif -#ifdef _SC_TZNAME_MAX - {"SC_TZNAME_MAX", _SC_TZNAME_MAX}, -#endif -#ifdef _SC_T_IOV_MAX - {"SC_T_IOV_MAX", _SC_T_IOV_MAX}, -#endif -#ifdef _SC_UCHAR_MAX - {"SC_UCHAR_MAX", _SC_UCHAR_MAX}, -#endif -#ifdef _SC_UINT_MAX - {"SC_UINT_MAX", _SC_UINT_MAX}, -#endif -#ifdef _SC_UIO_MAXIOV - {"SC_UIO_MAXIOV", _SC_UIO_MAXIOV}, -#endif -#ifdef _SC_ULONG_MAX - {"SC_ULONG_MAX", _SC_ULONG_MAX}, -#endif -#ifdef _SC_USHRT_MAX - {"SC_USHRT_MAX", _SC_USHRT_MAX}, -#endif -#ifdef _SC_VERSION - {"SC_VERSION", _SC_VERSION}, -#endif -#ifdef _SC_WORD_BIT - {"SC_WORD_BIT", _SC_WORD_BIT}, -#endif -#ifdef _SC_XBS5_ILP32_OFF32 - {"SC_XBS5_ILP32_OFF32", _SC_XBS5_ILP32_OFF32}, -#endif -#ifdef _SC_XBS5_ILP32_OFFBIG - {"SC_XBS5_ILP32_OFFBIG", _SC_XBS5_ILP32_OFFBIG}, -#endif -#ifdef _SC_XBS5_LP64_OFF64 - {"SC_XBS5_LP64_OFF64", _SC_XBS5_LP64_OFF64}, -#endif -#ifdef _SC_XBS5_LPBIG_OFFBIG - {"SC_XBS5_LPBIG_OFFBIG", _SC_XBS5_LPBIG_OFFBIG}, -#endif -#ifdef _SC_XOPEN_CRYPT - {"SC_XOPEN_CRYPT", _SC_XOPEN_CRYPT}, -#endif -#ifdef _SC_XOPEN_ENH_I18N - {"SC_XOPEN_ENH_I18N", _SC_XOPEN_ENH_I18N}, -#endif -#ifdef _SC_XOPEN_LEGACY - {"SC_XOPEN_LEGACY", _SC_XOPEN_LEGACY}, -#endif -#ifdef _SC_XOPEN_REALTIME - {"SC_XOPEN_REALTIME", _SC_XOPEN_REALTIME}, -#endif -#ifdef _SC_XOPEN_REALTIME_THREADS - {"SC_XOPEN_REALTIME_THREADS", _SC_XOPEN_REALTIME_THREADS}, -#endif -#ifdef _SC_XOPEN_SHM - {"SC_XOPEN_SHM", _SC_XOPEN_SHM}, -#endif -#ifdef _SC_XOPEN_UNIX - {"SC_XOPEN_UNIX", _SC_XOPEN_UNIX}, -#endif -#ifdef _SC_XOPEN_VERSION - {"SC_XOPEN_VERSION", _SC_XOPEN_VERSION}, -#endif -#ifdef _SC_XOPEN_XCU_VERSION - {"SC_XOPEN_XCU_VERSION", _SC_XOPEN_XCU_VERSION}, -#endif -#ifdef _SC_XOPEN_XPG2 - {"SC_XOPEN_XPG2", _SC_XOPEN_XPG2}, -#endif -#ifdef _SC_XOPEN_XPG3 - {"SC_XOPEN_XPG3", _SC_XOPEN_XPG3}, -#endif -#ifdef _SC_XOPEN_XPG4 - {"SC_XOPEN_XPG4", _SC_XOPEN_XPG4}, -#endif -}; - -static int -conv_sysconf_confname(PyObject *arg, int *valuep) -{ - return conv_confname(arg, valuep, posix_constants_sysconf, - sizeof(posix_constants_sysconf) - / sizeof(struct constdef)); -} - - -/*[clinic input] -os.sysconf -> long - name: sysconf_confname - / - -Return an integer-valued system configuration variable. -[clinic start generated code]*/ +#endif /* defined(HAVE_CONFSTR) */ + +#if defined(HAVE_SYSCONF) PyDoc_STRVAR(os_sysconf__doc__, "sysconf($module, name, /)\n" @@ -14802,103 +4831,7 @@ return return_value; } -static long -os_sysconf_impl(PyModuleDef *module, int name) -/*[clinic end generated code: output=7b06dfdc472431e4 input=279e3430a33f29e4]*/ -{ - long value; - - errno = 0; - value = sysconf(name); - if (value == -1 && errno != 0) - posix_error(); - return value; -} -#endif /* HAVE_SYSCONF */ - - -/* This code is used to ensure that the tables of configuration value names - * are in sorted order as required by conv_confname(), and also to build - * the exported dictionaries that are used to publish information about the - * names available on the host platform. - * - * Sorting the table at runtime ensures that the table is properly ordered - * when used, even for platforms we're not able to test on. It also makes - * it easier to add additional entries to the tables. - */ - -static int -cmp_constdefs(const void *v1, const void *v2) -{ - const struct constdef *c1 = - (const struct constdef *) v1; - const struct constdef *c2 = - (const struct constdef *) v2; - - return strcmp(c1->name, c2->name); -} - -static int -setup_confname_table(struct constdef *table, size_t tablesize, - char *tablename, PyObject *module) -{ - PyObject *d = NULL; - size_t i; - - qsort(table, tablesize, sizeof(struct constdef), cmp_constdefs); - d = PyDict_New(); - if (d == NULL) - return -1; - - for (i=0; i < tablesize; ++i) { - PyObject *o = PyLong_FromLong(table[i].value); - if (o == NULL || PyDict_SetItemString(d, table[i].name, o) == -1) { - Py_XDECREF(o); - Py_DECREF(d); - return -1; - } - Py_DECREF(o); - } - return PyModule_AddObject(module, tablename, d); -} - -/* Return -1 on failure, 0 on success. */ -static int -setup_confname_tables(PyObject *module) -{ -#if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF) - if (setup_confname_table(posix_constants_pathconf, - sizeof(posix_constants_pathconf) - / sizeof(struct constdef), - "pathconf_names", module)) - return -1; -#endif -#ifdef HAVE_CONFSTR - if (setup_confname_table(posix_constants_confstr, - sizeof(posix_constants_confstr) - / sizeof(struct constdef), - "confstr_names", module)) - return -1; -#endif -#ifdef HAVE_SYSCONF - if (setup_confname_table(posix_constants_sysconf, - sizeof(posix_constants_sysconf) - / sizeof(struct constdef), - "sysconf_names", module)) - return -1; -#endif - return 0; -} - - -/*[clinic input] -os.abort - -Abort the interpreter immediately. - -This function 'dumps core' or otherwise fails in the hardest way possible -on the hosting operating system. This function never returns. -[clinic start generated code]*/ +#endif /* defined(HAVE_SYSCONF) */ PyDoc_STRVAR(os_abort__doc__, "abort($module, /)\n" @@ -14921,163 +4854,7 @@ return os_abort_impl(module); } -static PyObject * -os_abort_impl(PyModuleDef *module) -/*[clinic end generated code: output=cded2cc8c5453d3a input=cf2c7d98bc504047]*/ -{ - abort(); - /*NOTREACHED*/ - Py_FatalError("abort() called from Python code didn't abort!"); - return NULL; -} - -#ifdef MS_WINDOWS -/* AC 3.5: change to path_t? but that might change exceptions */ -PyDoc_STRVAR(win32_startfile__doc__, -"startfile(filepath [, operation])\n\ -\n\ -Start a file with its associated application.\n\ -\n\ -When \"operation\" is not specified or \"open\", this acts like\n\ -double-clicking the file in Explorer, or giving the file name as an\n\ -argument to the DOS \"start\" command: the file is opened with whatever\n\ -application (if any) its extension is associated.\n\ -When another \"operation\" is given, it specifies what should be done with\n\ -the file. A typical operation is \"print\".\n\ -\n\ -startfile returns as soon as the associated application is launched.\n\ -There is no option to wait for the application to close, and no way\n\ -to retrieve the application's exit status.\n\ -\n\ -The filepath is relative to the current directory. If you want to use\n\ -an absolute path, make sure the first character is not a slash (\"/\");\n\ -the underlying Win32 ShellExecute function doesn't work if it is."); - -/* Grab ShellExecute dynamically from shell32 */ -static int has_ShellExecute = -1; -static HINSTANCE (CALLBACK *Py_ShellExecuteA)(HWND, LPCSTR, LPCSTR, LPCSTR, - LPCSTR, INT); -static HINSTANCE (CALLBACK *Py_ShellExecuteW)(HWND, LPCWSTR, LPCWSTR, LPCWSTR, - LPCWSTR, INT); -static int -check_ShellExecute() -{ - HINSTANCE hShell32; - - /* only recheck */ - if (-1 == has_ShellExecute) { - Py_BEGIN_ALLOW_THREADS - hShell32 = LoadLibraryW(L"SHELL32"); - Py_END_ALLOW_THREADS - if (hShell32) { - *(FARPROC*)&Py_ShellExecuteA = GetProcAddress(hShell32, - "ShellExecuteA"); - *(FARPROC*)&Py_ShellExecuteW = GetProcAddress(hShell32, - "ShellExecuteW"); - has_ShellExecute = Py_ShellExecuteA && - Py_ShellExecuteW; - } else { - has_ShellExecute = 0; - } - } - return has_ShellExecute; -} - - -static PyObject * -win32_startfile(PyObject *self, PyObject *args) -{ - PyObject *ofilepath; - char *filepath; - char *operation = NULL; - wchar_t *wpath, *woperation; - HINSTANCE rc; - - PyObject *unipath, *uoperation = NULL; - - if(!check_ShellExecute()) { - /* If the OS doesn't have ShellExecute, return a - NotImplementedError. */ - return PyErr_Format(PyExc_NotImplementedError, - "startfile not available on this platform"); - } - - if (!PyArg_ParseTuple(args, "U|s:startfile", - &unipath, &operation)) { - PyErr_Clear(); - goto normal; - } - - if (operation) { - uoperation = PyUnicode_DecodeASCII(operation, - strlen(operation), NULL); - if (!uoperation) { - PyErr_Clear(); - operation = NULL; - goto normal; - } - } - - wpath = PyUnicode_AsUnicode(unipath); - if (wpath == NULL) - goto normal; - if (uoperation) { - woperation = PyUnicode_AsUnicode(uoperation); - if (woperation == NULL) - goto normal; - } - else - woperation = NULL; - - Py_BEGIN_ALLOW_THREADS - rc = Py_ShellExecuteW((HWND)0, woperation, wpath, - NULL, NULL, SW_SHOWNORMAL); - Py_END_ALLOW_THREADS - - Py_XDECREF(uoperation); - if (rc <= (HINSTANCE)32) { - win32_error_object("startfile", unipath); - return NULL; - } - Py_INCREF(Py_None); - return Py_None; - -normal: - if (!PyArg_ParseTuple(args, "O&|s:startfile", - PyUnicode_FSConverter, &ofilepath, - &operation)) - return NULL; - if (win32_warn_bytes_api()) { - Py_DECREF(ofilepath); - return NULL; - } - filepath = PyBytes_AsString(ofilepath); - Py_BEGIN_ALLOW_THREADS - rc = Py_ShellExecuteA((HWND)0, operation, filepath, - NULL, NULL, SW_SHOWNORMAL); - Py_END_ALLOW_THREADS - if (rc <= (HINSTANCE)32) { - PyObject *errval = win32_error("startfile", filepath); - Py_DECREF(ofilepath); - return errval; - } - Py_DECREF(ofilepath); - Py_INCREF(Py_None); - return Py_None; -} -#endif /* MS_WINDOWS */ - - -#ifdef HAVE_GETLOADAVG -/*[clinic input] -os.getloadavg - -Return average recent system load information. - -Return the number of processes in the system run queue averaged over -the last 1, 5, and 15 minutes as a tuple of three floats. -Raises OSError if the load average was unobtainable. -[clinic start generated code]*/ +#if defined(HAVE_GETLOADAVG) PyDoc_STRVAR(os_getloadavg__doc__, "getloadavg($module, /)\n" @@ -15101,29 +4878,7 @@ return os_getloadavg_impl(module); } -static PyObject * -os_getloadavg_impl(PyModuleDef *module) -/*[clinic end generated code: output=67593a92457d55af input=3d6d826b76d8a34e]*/ -{ - double loadavg[3]; - if (getloadavg(loadavg, 3)!=3) { - PyErr_SetString(PyExc_OSError, "Load averages are unobtainable"); - return NULL; - } else - return Py_BuildValue("ddd", loadavg[0], loadavg[1], loadavg[2]); -} -#endif /* HAVE_GETLOADAVG */ - - -/*[clinic input] -os.device_encoding - fd: int - -Return a string describing the encoding of a terminal's file descriptor. - -The file descriptor must be attached to a terminal. -If the device is not a terminal, return None. -[clinic start generated code]*/ +#endif /* defined(HAVE_GETLOADAVG) */ PyDoc_STRVAR(os_device_encoding__doc__, "device_encoding($module, /, fd)\n" @@ -15157,25 +4912,7 @@ return return_value; } -static PyObject * -os_device_encoding_impl(PyModuleDef *module, int fd) -/*[clinic end generated code: output=e9f8274d42f5cce3 input=9e1d4a42b66df312]*/ -{ - return _Py_device_encoding(fd); -} - - -#ifdef HAVE_SETRESUID -/*[clinic input] -os.setresuid - - ruid: uid_t - euid: uid_t - suid: uid_t - / - -Set the current process's real, effective, and saved user ids. -[clinic start generated code]*/ +#if defined(HAVE_SETRESUID) PyDoc_STRVAR(os_setresuid__doc__, "setresuid($module, ruid, euid, suid, /)\n" @@ -15207,28 +4944,9 @@ return return_value; } -static PyObject * -os_setresuid_impl(PyModuleDef *module, uid_t ruid, uid_t euid, uid_t suid) -/*[clinic end generated code: output=2e3457cfe7cd1f94 input=9e33cb79a82792f3]*/ -{ - if (setresuid(ruid, euid, suid) < 0) - return posix_error(); - Py_RETURN_NONE; -} -#endif /* HAVE_SETRESUID */ - - -#ifdef HAVE_SETRESGID -/*[clinic input] -os.setresgid - - rgid: gid_t - egid: gid_t - sgid: gid_t - / - -Set the current process's real, effective, and saved group ids. -[clinic start generated code]*/ +#endif /* defined(HAVE_SETRESUID) */ + +#if defined(HAVE_SETRESGID) PyDoc_STRVAR(os_setresgid__doc__, "setresgid($module, rgid, egid, sgid, /)\n" @@ -15260,23 +4978,9 @@ return return_value; } -static PyObject * -os_setresgid_impl(PyModuleDef *module, gid_t rgid, gid_t egid, gid_t sgid) -/*[clinic end generated code: output=8a7ee6c1f2482362 input=33e9e0785ef426b1]*/ -{ - if (setresgid(rgid, egid, sgid) < 0) - return posix_error(); - Py_RETURN_NONE; -} -#endif /* HAVE_SETRESGID */ - - -#ifdef HAVE_GETRESUID -/*[clinic input] -os.getresuid - -Return a tuple of the current process's real, effective, and saved user ids. -[clinic start generated code]*/ +#endif /* defined(HAVE_SETRESGID) */ + +#if defined(HAVE_GETRESUID) PyDoc_STRVAR(os_getresuid__doc__, "getresuid($module, /)\n" @@ -15296,26 +5000,9 @@ return os_getresuid_impl(module); } -static PyObject * -os_getresuid_impl(PyModuleDef *module) -/*[clinic end generated code: output=d0786686a6ef1320 input=41ccfa8e1f6517ad]*/ -{ - uid_t ruid, euid, suid; - if (getresuid(&ruid, &euid, &suid) < 0) - return posix_error(); - return Py_BuildValue("(NNN)", _PyLong_FromUid(ruid), - _PyLong_FromUid(euid), - _PyLong_FromUid(suid)); -} -#endif /* HAVE_GETRESUID */ - - -#ifdef HAVE_GETRESGID -/*[clinic input] -os.getresgid - -Return a tuple of the current process's real, effective, and saved group ids. -[clinic start generated code]*/ +#endif /* defined(HAVE_GETRESUID) */ + +#if defined(HAVE_GETRESGID) PyDoc_STRVAR(os_getresgid__doc__, "getresgid($module, /)\n" @@ -15335,37 +5022,9 @@ return os_getresgid_impl(module); } -static PyObject * -os_getresgid_impl(PyModuleDef *module) -/*[clinic end generated code: output=05249ac795fa759f input=517e68db9ca32df6]*/ -{ - gid_t rgid, egid, sgid; - if (getresgid(&rgid, &egid, &sgid) < 0) - return posix_error(); - return Py_BuildValue("(NNN)", _PyLong_FromGid(rgid), - _PyLong_FromGid(egid), - _PyLong_FromGid(sgid)); -} -#endif /* HAVE_GETRESGID */ - - -#ifdef USE_XATTRS -/*[clinic input] -os.getxattr - - path: path_t(allow_fd=True) - attribute: path_t - * - follow_symlinks: bool = True - -Return the value of extended attribute attribute on path. - -path may be either a string or an open file descriptor. -If follow_symlinks is False, and the last element of the path is a symbolic - link, getxattr will examine the symbolic link itself instead of the file - the link points to. - -[clinic start generated code]*/ +#endif /* defined(HAVE_GETRESGID) */ + +#if defined(USE_XATTRS) PyDoc_STRVAR(os_getxattr__doc__, "getxattr($module, /, path, attribute, *, follow_symlinks=True)\n" @@ -15408,76 +5067,9 @@ return return_value; } -static PyObject * -os_getxattr_impl(PyModuleDef *module, path_t *path, path_t *attribute, int follow_symlinks) -/*[clinic end generated code: output=bbc9454fe2b9ea86 input=8c8ea3bab78d89c2]*/ -{ - Py_ssize_t i; - PyObject *buffer = NULL; - - if (fd_and_follow_symlinks_invalid("getxattr", path->fd, follow_symlinks)) - return NULL; - - for (i = 0; ; i++) { - void *ptr; - ssize_t result; - static Py_ssize_t buffer_sizes[] = {128, XATTR_SIZE_MAX, 0}; - Py_ssize_t buffer_size = buffer_sizes[i]; - if (!buffer_size) { - path_error(path); - return NULL; - } - buffer = PyBytes_FromStringAndSize(NULL, buffer_size); - if (!buffer) - return NULL; - ptr = PyBytes_AS_STRING(buffer); - - Py_BEGIN_ALLOW_THREADS; - if (path->fd >= 0) - result = fgetxattr(path->fd, attribute->narrow, ptr, buffer_size); - else if (follow_symlinks) - result = getxattr(path->narrow, attribute->narrow, ptr, buffer_size); - else - result = lgetxattr(path->narrow, attribute->narrow, ptr, buffer_size); - Py_END_ALLOW_THREADS; - - if (result < 0) { - Py_DECREF(buffer); - if (errno == ERANGE) - continue; - path_error(path); - return NULL; - } - - if (result != buffer_size) { - /* Can only shrink. */ - _PyBytes_Resize(&buffer, result); - } - break; - } - - return buffer; -} - - -/*[clinic input] -os.setxattr - - path: path_t(allow_fd=True) - attribute: path_t - value: Py_buffer - flags: int = 0 - * - follow_symlinks: bool = True - -Set extended attribute attribute on path to value. - -path may be either a string or an open file descriptor. -If follow_symlinks is False, and the last element of the path is a symbolic - link, setxattr will modify the symbolic link itself instead of the file - the link points to. - -[clinic start generated code]*/ +#endif /* defined(USE_XATTRS) */ + +#if defined(USE_XATTRS) PyDoc_STRVAR(os_setxattr__doc__, "setxattr($module, /, path, attribute, value, flags=0, *,\n" @@ -15526,52 +5118,9 @@ return return_value; } -static PyObject * -os_setxattr_impl(PyModuleDef *module, path_t *path, path_t *attribute, Py_buffer *value, int flags, int follow_symlinks) -/*[clinic end generated code: output=2ff845d8e024b218 input=f0d26833992015c2]*/ -{ - ssize_t result; - - if (fd_and_follow_symlinks_invalid("setxattr", path->fd, follow_symlinks)) - return NULL; - - Py_BEGIN_ALLOW_THREADS; - if (path->fd > -1) - result = fsetxattr(path->fd, attribute->narrow, - value->buf, value->len, flags); - else if (follow_symlinks) - result = setxattr(path->narrow, attribute->narrow, - value->buf, value->len, flags); - else - result = lsetxattr(path->narrow, attribute->narrow, - value->buf, value->len, flags); - Py_END_ALLOW_THREADS; - - if (result) { - path_error(path); - return NULL; - } - - Py_RETURN_NONE; -} - - -/*[clinic input] -os.removexattr - - path: path_t(allow_fd=True) - attribute: path_t - * - follow_symlinks: bool = True - -Remove extended attribute attribute on path. - -path may be either a string or an open file descriptor. -If follow_symlinks is False, and the last element of the path is a symbolic - link, removexattr will modify the symbolic link itself instead of the file - the link points to. - -[clinic start generated code]*/ +#endif /* defined(USE_XATTRS) */ + +#if defined(USE_XATTRS) PyDoc_STRVAR(os_removexattr__doc__, "removexattr($module, /, path, attribute, *, follow_symlinks=True)\n" @@ -15614,47 +5163,9 @@ return return_value; } -static PyObject * -os_removexattr_impl(PyModuleDef *module, path_t *path, path_t *attribute, int follow_symlinks) -/*[clinic end generated code: output=8dfc715bf607c4cf input=cdb54834161e3329]*/ -{ - ssize_t result; - - if (fd_and_follow_symlinks_invalid("removexattr", path->fd, follow_symlinks)) - return NULL; - - Py_BEGIN_ALLOW_THREADS; - if (path->fd > -1) - result = fremovexattr(path->fd, attribute->narrow); - else if (follow_symlinks) - result = removexattr(path->narrow, attribute->narrow); - else - result = lremovexattr(path->narrow, attribute->narrow); - Py_END_ALLOW_THREADS; - - if (result) { - return path_error(path); - } - - Py_RETURN_NONE; -} - - -/*[clinic input] -os.listxattr - - path: path_t(allow_fd=True, nullable=True) = None - * - follow_symlinks: bool = True - -Return a list of extended attributes on path. - -path may be either None, a string, or an open file descriptor. -if path is None, listxattr will examine the current directory. -If follow_symlinks is False, and the last element of the path is a symbolic - link, listxattr will examine the symbolic link itself instead of the file - the link points to. -[clinic start generated code]*/ +#endif /* defined(USE_XATTRS) */ + +#if defined(USE_XATTRS) PyDoc_STRVAR(os_listxattr__doc__, "listxattr($module, /, path=None, *, follow_symlinks=True)\n" @@ -15695,99 +5206,7 @@ return return_value; } -static PyObject * -os_listxattr_impl(PyModuleDef *module, path_t *path, int follow_symlinks) -/*[clinic end generated code: output=3104cafda1a3d887 input=08cca53ac0b07c13]*/ -{ - Py_ssize_t i; - PyObject *result = NULL; - const char *name; - char *buffer = NULL; - - if (fd_and_follow_symlinks_invalid("listxattr", path->fd, follow_symlinks)) - goto exit; - - name = path->narrow ? path->narrow : "."; - - for (i = 0; ; i++) { - char *start, *trace, *end; - ssize_t length; - static Py_ssize_t buffer_sizes[] = { 256, XATTR_LIST_MAX, 0 }; - Py_ssize_t buffer_size = buffer_sizes[i]; - if (!buffer_size) { - /* ERANGE */ - path_error(path); - break; - } - buffer = PyMem_MALLOC(buffer_size); - if (!buffer) { - PyErr_NoMemory(); - break; - } - - Py_BEGIN_ALLOW_THREADS; - if (path->fd > -1) - length = flistxattr(path->fd, buffer, buffer_size); - else if (follow_symlinks) - length = listxattr(name, buffer, buffer_size); - else - length = llistxattr(name, buffer, buffer_size); - Py_END_ALLOW_THREADS; - - if (length < 0) { - if (errno == ERANGE) { - PyMem_FREE(buffer); - buffer = NULL; - continue; - } - path_error(path); - break; - } - - result = PyList_New(0); - if (!result) { - goto exit; - } - - end = buffer + length; - for (trace = start = buffer; trace != end; trace++) { - if (!*trace) { - int error; - PyObject *attribute = PyUnicode_DecodeFSDefaultAndSize(start, - trace - start); - if (!attribute) { - Py_DECREF(result); - result = NULL; - goto exit; - } - error = PyList_Append(result, attribute); - Py_DECREF(attribute); - if (error) { - Py_DECREF(result); - result = NULL; - goto exit; - } - start = trace + 1; - } - } - break; - } -exit: - if (buffer) - PyMem_FREE(buffer); - return result; -} -#endif /* USE_XATTRS */ - - -/*[clinic input] -os.urandom - - size: Py_ssize_t - / - -Return a bytes object containing random bytes suitable for cryptographic use. -[clinic start generated code]*/ +#endif /* defined(USE_XATTRS) */ PyDoc_STRVAR(os_urandom__doc__, "urandom($module, size, /)\n" @@ -15817,143 +5236,6 @@ return return_value; } -static PyObject * -os_urandom_impl(PyModuleDef *module, Py_ssize_t size) -/*[clinic end generated code: output=5dbff582cab94cb9 input=4067cdb1b6776c29]*/ -{ - PyObject *bytes; - int result; - - if (size < 0) - return PyErr_Format(PyExc_ValueError, - "negative argument not allowed"); - bytes = PyBytes_FromStringAndSize(NULL, size); - if (bytes == NULL) - return NULL; - - result = _PyOS_URandom(PyBytes_AS_STRING(bytes), - PyBytes_GET_SIZE(bytes)); - if (result == -1) { - Py_DECREF(bytes); - return NULL; - } - return bytes; -} - -/* Terminal size querying */ - -static PyTypeObject TerminalSizeType; - -PyDoc_STRVAR(TerminalSize_docstring, - "A tuple of (columns, lines) for holding terminal window size"); - -static PyStructSequence_Field TerminalSize_fields[] = { - {"columns", "width of the terminal window in characters"}, - {"lines", "height of the terminal window in characters"}, - {NULL, NULL} -}; - -static PyStructSequence_Desc TerminalSize_desc = { - "os.terminal_size", - TerminalSize_docstring, - TerminalSize_fields, - 2, -}; - -#if defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL) -/* AC 3.5: fd should accept None */ -PyDoc_STRVAR(termsize__doc__, - "Return the size of the terminal window as (columns, lines).\n" \ - "\n" \ - "The optional argument fd (default standard output) specifies\n" \ - "which file descriptor should be queried.\n" \ - "\n" \ - "If the file descriptor is not connected to a terminal, an OSError\n" \ - "is thrown.\n" \ - "\n" \ - "This function will only be defined if an implementation is\n" \ - "available for this system.\n" \ - "\n" \ - "shutil.get_terminal_size is the high-level function which should \n" \ - "normally be used, os.get_terminal_size is the low-level implementation."); - -static PyObject* -get_terminal_size(PyObject *self, PyObject *args) -{ - int columns, lines; - PyObject *termsize; - - int fd = fileno(stdout); - /* Under some conditions stdout may not be connected and - * fileno(stdout) may point to an invalid file descriptor. For example - * GUI apps don't have valid standard streams by default. - * - * If this happens, and the optional fd argument is not present, - * the ioctl below will fail returning EBADF. This is what we want. - */ - - if (!PyArg_ParseTuple(args, "|i", &fd)) - return NULL; - -#ifdef TERMSIZE_USE_IOCTL - { - struct winsize w; - if (ioctl(fd, TIOCGWINSZ, &w)) - return PyErr_SetFromErrno(PyExc_OSError); - columns = w.ws_col; - lines = w.ws_row; - } -#endif /* TERMSIZE_USE_IOCTL */ - -#ifdef TERMSIZE_USE_CONIO - { - DWORD nhandle; - HANDLE handle; - CONSOLE_SCREEN_BUFFER_INFO csbi; - switch (fd) { - case 0: nhandle = STD_INPUT_HANDLE; - break; - case 1: nhandle = STD_OUTPUT_HANDLE; - break; - case 2: nhandle = STD_ERROR_HANDLE; - break; - default: - return PyErr_Format(PyExc_ValueError, "bad file descriptor"); - } - handle = GetStdHandle(nhandle); - if (handle == NULL) - return PyErr_Format(PyExc_OSError, "handle cannot be retrieved"); - if (handle == INVALID_HANDLE_VALUE) - return PyErr_SetFromWindowsErr(0); - - if (!GetConsoleScreenBufferInfo(handle, &csbi)) - return PyErr_SetFromWindowsErr(0); - - columns = csbi.srWindow.Right - csbi.srWindow.Left + 1; - lines = csbi.srWindow.Bottom - csbi.srWindow.Top + 1; - } -#endif /* TERMSIZE_USE_CONIO */ - - termsize = PyStructSequence_New(&TerminalSizeType); - if (termsize == NULL) - return NULL; - PyStructSequence_SET_ITEM(termsize, 0, PyLong_FromLong(columns)); - PyStructSequence_SET_ITEM(termsize, 1, PyLong_FromLong(lines)); - if (PyErr_Occurred()) { - Py_DECREF(termsize); - return NULL; - } - return termsize; -} -#endif /* defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL) */ - - -/*[clinic input] -os.cpu_count - -Return the number of CPUs in the system; return None if indeterminable. -[clinic start generated code]*/ - PyDoc_STRVAR(os_cpu_count__doc__, "cpu_count($module, /)\n" "--\n" @@ -15972,47 +5254,6 @@ return os_cpu_count_impl(module); } -static PyObject * -os_cpu_count_impl(PyModuleDef *module) -/*[clinic end generated code: output=92e2a4a729eb7740 input=d55e2f8f3823a628]*/ -{ - int ncpu = 0; -#ifdef MS_WINDOWS - SYSTEM_INFO sysinfo; - GetSystemInfo(&sysinfo); - ncpu = sysinfo.dwNumberOfProcessors; -#elif defined(__hpux) - ncpu = mpctl(MPC_GETNUMSPUS, NULL, NULL); -#elif defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_ONLN) - ncpu = sysconf(_SC_NPROCESSORS_ONLN); -#elif defined(__DragonFly__) || \ - defined(__OpenBSD__) || \ - defined(__FreeBSD__) || \ - defined(__NetBSD__) || \ - defined(__APPLE__) - int mib[2]; - size_t len = sizeof(ncpu); - mib[0] = CTL_HW; - mib[1] = HW_NCPU; - if (sysctl(mib, 2, &ncpu, &len, NULL, 0) != 0) - ncpu = 0; -#endif - if (ncpu >= 1) - return PyLong_FromLong(ncpu); - else - Py_RETURN_NONE; -} - - -/*[clinic input] -os.get_inheritable -> bool - - fd: int - / - -Get the close-on-exe flag of the specified file descriptor. -[clinic start generated code]*/ - PyDoc_STRVAR(os_get_inheritable__doc__, "get_inheritable($module, fd, /)\n" "--\n" @@ -16045,28 +5286,6 @@ return return_value; } -static int -os_get_inheritable_impl(PyModuleDef *module, int fd) -/*[clinic end generated code: output=261d1dd2b0dbdc35 input=89ac008dc9ab6b95]*/ -{ - if (!_PyVerify_fd(fd)){ - posix_error(); - return -1; - } - - return _Py_get_inheritable(fd); -} - - -/*[clinic input] -os.set_inheritable - fd: int - inheritable: int - / - -Set the inheritable flag of the specified file descriptor. -[clinic start generated code]*/ - PyDoc_STRVAR(os_set_inheritable__doc__, "set_inheritable($module, fd, inheritable, /)\n" "--\n" @@ -16096,27 +5315,7 @@ return return_value; } -static PyObject * -os_set_inheritable_impl(PyModuleDef *module, int fd, int inheritable) -/*[clinic end generated code: output=64dfe5e15c906539 input=9ceaead87a1e2402]*/ -{ - if (!_PyVerify_fd(fd)) - return posix_error(); - - if (_Py_set_inheritable(fd, inheritable, NULL) < 0) - return NULL; - Py_RETURN_NONE; -} - - -#ifdef MS_WINDOWS -/*[clinic input] -os.get_handle_inheritable -> bool - handle: Py_intptr_t - / - -Get the close-on-exe flag of the specified file descriptor. -[clinic start generated code]*/ +#if defined(MS_WINDOWS) PyDoc_STRVAR(os_get_handle_inheritable__doc__, "get_handle_inheritable($module, handle, /)\n" @@ -16150,29 +5349,9 @@ return return_value; } -static int -os_get_handle_inheritable_impl(PyModuleDef *module, Py_intptr_t handle) -/*[clinic end generated code: output=d5bf9d86900bf457 input=5f7759443aae3dc5]*/ -{ - DWORD flags; - - if (!GetHandleInformation((HANDLE)handle, &flags)) { - PyErr_SetFromWindowsErr(0); - return -1; - } - - return flags & HANDLE_FLAG_INHERIT; -} - - -/*[clinic input] -os.set_handle_inheritable - handle: Py_intptr_t - inheritable: bool - / - -Set the inheritable flag of the specified handle. -[clinic start generated code]*/ +#endif /* defined(MS_WINDOWS) */ + +#if defined(MS_WINDOWS) PyDoc_STRVAR(os_set_handle_inheritable__doc__, "set_handle_inheritable($module, handle, inheritable, /)\n" @@ -16203,848 +5382,7 @@ return return_value; } -static PyObject * -os_set_handle_inheritable_impl(PyModuleDef *module, Py_intptr_t handle, int inheritable) -/*[clinic end generated code: output=ee5fcc6d9f0d4f8b input=e64b2b2730469def]*/ -{ - DWORD flags = inheritable ? HANDLE_FLAG_INHERIT : 0; - if (!SetHandleInformation((HANDLE)handle, HANDLE_FLAG_INHERIT, flags)) { - PyErr_SetFromWindowsErr(0); - return NULL; - } - Py_RETURN_NONE; -} -#endif /* MS_WINDOWS */ - -#ifndef MS_WINDOWS -PyDoc_STRVAR(get_blocking__doc__, - "get_blocking(fd) -> bool\n" \ - "\n" \ - "Get the blocking mode of the file descriptor:\n" \ - "False if the O_NONBLOCK flag is set, True if the flag is cleared."); - -static PyObject* -posix_get_blocking(PyObject *self, PyObject *args) -{ - int fd; - int blocking; - - if (!PyArg_ParseTuple(args, "i:get_blocking", &fd)) - return NULL; - - if (!_PyVerify_fd(fd)) - return posix_error(); - - blocking = _Py_get_blocking(fd); - if (blocking < 0) - return NULL; - return PyBool_FromLong(blocking); -} - -PyDoc_STRVAR(set_blocking__doc__, - "set_blocking(fd, blocking)\n" \ - "\n" \ - "Set the blocking mode of the specified file descriptor.\n" \ - "Set the O_NONBLOCK flag if blocking is False,\n" \ - "clear the O_NONBLOCK flag otherwise."); - -static PyObject* -posix_set_blocking(PyObject *self, PyObject *args) -{ - int fd, blocking; - - if (!PyArg_ParseTuple(args, "ii:set_blocking", &fd, &blocking)) - return NULL; - - if (!_PyVerify_fd(fd)) - return posix_error(); - - if (_Py_set_blocking(fd, blocking) < 0) - return NULL; - Py_RETURN_NONE; -} -#endif /* !MS_WINDOWS */ - - -PyDoc_STRVAR(posix_scandir__doc__, -"scandir(path='.') -> iterator of DirEntry objects for given path"); - -static char *follow_symlinks_keywords[] = {"follow_symlinks", NULL}; - -typedef struct { - PyObject_HEAD - PyObject *name; - PyObject *path; - PyObject *stat; - PyObject *lstat; -#ifdef MS_WINDOWS - struct _Py_stat_struct win32_lstat; - __int64 win32_file_index; - int got_file_index; -#else /* POSIX */ -#ifdef HAVE_DIRENT_D_TYPE - unsigned char d_type; -#endif - ino_t d_ino; -#endif -} DirEntry; - -static void -DirEntry_dealloc(DirEntry *entry) -{ - Py_XDECREF(entry->name); - Py_XDECREF(entry->path); - Py_XDECREF(entry->stat); - Py_XDECREF(entry->lstat); - Py_TYPE(entry)->tp_free((PyObject *)entry); -} - -/* Forward reference */ -static int -DirEntry_test_mode(DirEntry *self, int follow_symlinks, unsigned short mode_bits); - -/* Set exception and return -1 on error, 0 for False, 1 for True */ -static int -DirEntry_is_symlink(DirEntry *self) -{ -#ifdef MS_WINDOWS - return (self->win32_lstat.st_mode & S_IFMT) == S_IFLNK; -#elif defined(HAVE_DIRENT_D_TYPE) - /* POSIX */ - if (self->d_type != DT_UNKNOWN) - return self->d_type == DT_LNK; - else - return DirEntry_test_mode(self, 0, S_IFLNK); -#else - /* POSIX without d_type */ - return DirEntry_test_mode(self, 0, S_IFLNK); -#endif -} - -static PyObject * -DirEntry_py_is_symlink(DirEntry *self) -{ - int result; - - result = DirEntry_is_symlink(self); - if (result == -1) - return NULL; - return PyBool_FromLong(result); -} - -static PyObject * -DirEntry_fetch_stat(DirEntry *self, int follow_symlinks) -{ - int result; - struct _Py_stat_struct st; - -#ifdef MS_WINDOWS - wchar_t *path; - - path = PyUnicode_AsUnicode(self->path); - if (!path) - return NULL; - - if (follow_symlinks) - result = win32_stat_w(path, &st); - else - result = win32_lstat_w(path, &st); - - if (result != 0) { - return PyErr_SetExcFromWindowsErrWithFilenameObject(PyExc_OSError, - 0, self->path); - } -#else /* POSIX */ - PyObject *bytes; - char *path; - - if (!PyUnicode_FSConverter(self->path, &bytes)) - return NULL; - path = PyBytes_AS_STRING(bytes); - - if (follow_symlinks) - result = STAT(path, &st); - else - result = LSTAT(path, &st); - Py_DECREF(bytes); - - if (result != 0) - return PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, self->path); -#endif - - return _pystat_fromstructstat(&st); -} - -static PyObject * -DirEntry_get_lstat(DirEntry *self) -{ - if (!self->lstat) { -#ifdef MS_WINDOWS - self->lstat = _pystat_fromstructstat(&self->win32_lstat); -#else /* POSIX */ - self->lstat = DirEntry_fetch_stat(self, 0); -#endif - } - Py_XINCREF(self->lstat); - return self->lstat; -} - -static PyObject * -DirEntry_get_stat(DirEntry *self, int follow_symlinks) -{ - if (!follow_symlinks) - return DirEntry_get_lstat(self); - - if (!self->stat) { - int result = DirEntry_is_symlink(self); - if (result == -1) - return NULL; - else if (result) - self->stat = DirEntry_fetch_stat(self, 1); - else - self->stat = DirEntry_get_lstat(self); - } - - Py_XINCREF(self->stat); - return self->stat; -} - -static PyObject * -DirEntry_stat(DirEntry *self, PyObject *args, PyObject *kwargs) -{ - int follow_symlinks = 1; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|$p:DirEntry.stat", - follow_symlinks_keywords, &follow_symlinks)) - return NULL; - - return DirEntry_get_stat(self, follow_symlinks); -} - -/* Set exception and return -1 on error, 0 for False, 1 for True */ -static int -DirEntry_test_mode(DirEntry *self, int follow_symlinks, unsigned short mode_bits) -{ - PyObject *stat = NULL; - PyObject *st_mode = NULL; - long mode; - int result; -#if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE) - int is_symlink; - int need_stat; -#endif -#ifdef MS_WINDOWS - unsigned long dir_bits; -#endif - _Py_IDENTIFIER(st_mode); - -#ifdef MS_WINDOWS - is_symlink = (self->win32_lstat.st_mode & S_IFMT) == S_IFLNK; - need_stat = follow_symlinks && is_symlink; -#elif defined(HAVE_DIRENT_D_TYPE) - is_symlink = self->d_type == DT_LNK; - need_stat = self->d_type == DT_UNKNOWN || (follow_symlinks && is_symlink); -#endif - -#if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE) - if (need_stat) { -#endif - stat = DirEntry_get_stat(self, follow_symlinks); - if (!stat) { - if (PyErr_ExceptionMatches(PyExc_FileNotFoundError)) { - /* If file doesn't exist (anymore), then return False - (i.e., say it's not a file/directory) */ - PyErr_Clear(); - return 0; - } - goto error; - } - st_mode = _PyObject_GetAttrId(stat, &PyId_st_mode); - if (!st_mode) - goto error; - - mode = PyLong_AsLong(st_mode); - if (mode == -1 && PyErr_Occurred()) - goto error; - Py_CLEAR(st_mode); - Py_CLEAR(stat); - result = (mode & S_IFMT) == mode_bits; -#if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE) - } - else if (is_symlink) { - assert(mode_bits != S_IFLNK); - result = 0; - } - else { - assert(mode_bits == S_IFDIR || mode_bits == S_IFREG); -#ifdef MS_WINDOWS - dir_bits = self->win32_lstat.st_file_attributes & FILE_ATTRIBUTE_DIRECTORY; - if (mode_bits == S_IFDIR) - result = dir_bits != 0; - else - result = dir_bits == 0; -#else /* POSIX */ - if (mode_bits == S_IFDIR) - result = self->d_type == DT_DIR; - else - result = self->d_type == DT_REG; -#endif - } -#endif - - return result; - -error: - Py_XDECREF(st_mode); - Py_XDECREF(stat); - return -1; -} - -static PyObject * -DirEntry_py_test_mode(DirEntry *self, int follow_symlinks, unsigned short mode_bits) -{ - int result; - - result = DirEntry_test_mode(self, follow_symlinks, mode_bits); - if (result == -1) - return NULL; - return PyBool_FromLong(result); -} - -static PyObject * -DirEntry_is_dir(DirEntry *self, PyObject *args, PyObject *kwargs) -{ - int follow_symlinks = 1; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|$p:DirEntry.is_dir", - follow_symlinks_keywords, &follow_symlinks)) - return NULL; - - return DirEntry_py_test_mode(self, follow_symlinks, S_IFDIR); -} - -static PyObject * -DirEntry_is_file(DirEntry *self, PyObject *args, PyObject *kwargs) -{ - int follow_symlinks = 1; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|$p:DirEntry.is_file", - follow_symlinks_keywords, &follow_symlinks)) - return NULL; - - return DirEntry_py_test_mode(self, follow_symlinks, S_IFREG); -} - -static PyObject * -DirEntry_inode(DirEntry *self) -{ -#ifdef MS_WINDOWS - if (!self->got_file_index) { - wchar_t *path; - struct _Py_stat_struct stat; - - path = PyUnicode_AsUnicode(self->path); - if (!path) - return NULL; - - if (win32_lstat_w(path, &stat) != 0) { - return PyErr_SetExcFromWindowsErrWithFilenameObject(PyExc_OSError, - 0, self->path); - } - - self->win32_file_index = stat.st_ino; - self->got_file_index = 1; - } - return PyLong_FromLongLong((PY_LONG_LONG)self->win32_file_index); -#else /* POSIX */ -#ifdef HAVE_LARGEFILE_SUPPORT - return PyLong_FromLongLong((PY_LONG_LONG)self->d_ino); -#else - return PyLong_FromLong((long)self->d_ino); -#endif -#endif -} - -static PyObject * -DirEntry_repr(DirEntry *self) -{ - return PyUnicode_FromFormat("", self->name); -} - -static PyMemberDef DirEntry_members[] = { - {"name", T_OBJECT_EX, offsetof(DirEntry, name), READONLY, - "the entry's base filename, relative to scandir() \"path\" argument"}, - {"path", T_OBJECT_EX, offsetof(DirEntry, path), READONLY, - "the entry's full path name; equivalent to os.path.join(scandir_path, entry.name)"}, - {NULL} -}; - -static PyMethodDef DirEntry_methods[] = { - {"is_dir", (PyCFunction)DirEntry_is_dir, METH_VARARGS | METH_KEYWORDS, - "return True if the entry is a directory; cached per entry" - }, - {"is_file", (PyCFunction)DirEntry_is_file, METH_VARARGS | METH_KEYWORDS, - "return True if the entry is a file; cached per entry" - }, - {"is_symlink", (PyCFunction)DirEntry_py_is_symlink, METH_NOARGS, - "return True if the entry is a symbolic link; cached per entry" - }, - {"stat", (PyCFunction)DirEntry_stat, METH_VARARGS | METH_KEYWORDS, - "return stat_result object for the entry; cached per entry" - }, - {"inode", (PyCFunction)DirEntry_inode, METH_NOARGS, - "return inode of the entry; cached per entry", - }, - {NULL} -}; - -PyTypeObject DirEntryType = { - PyVarObject_HEAD_INIT(NULL, 0) - MODNAME ".DirEntry", /* tp_name */ - sizeof(DirEntry), /* tp_basicsize */ - 0, /* tp_itemsize */ - /* methods */ - (destructor)DirEntry_dealloc, /* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_compare */ - (reprfunc)DirEntry_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 */ - 0, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - DirEntry_methods, /* tp_methods */ - DirEntry_members, /* tp_members */ -}; - -#ifdef MS_WINDOWS - -static wchar_t * -join_path_filenameW(wchar_t *path_wide, wchar_t* filename) -{ - Py_ssize_t path_len; - Py_ssize_t size; - wchar_t *result; - wchar_t ch; - - if (!path_wide) { /* Default arg: "." */ - path_wide = L"."; - path_len = 1; - } - else { - path_len = wcslen(path_wide); - } - - /* The +1's are for the path separator and the NUL */ - size = path_len + 1 + wcslen(filename) + 1; - result = PyMem_New(wchar_t, size); - if (!result) { - PyErr_NoMemory(); - return NULL; - } - wcscpy(result, path_wide); - if (path_len > 0) { - ch = result[path_len - 1]; - if (ch != SEP && ch != ALTSEP && ch != L':') - result[path_len++] = SEP; - wcscpy(result + path_len, filename); - } - return result; -} - -static PyObject * -DirEntry_from_find_data(path_t *path, WIN32_FIND_DATAW *dataW) -{ - DirEntry *entry; - BY_HANDLE_FILE_INFORMATION file_info; - ULONG reparse_tag; - wchar_t *joined_path; - - entry = PyObject_New(DirEntry, &DirEntryType); - if (!entry) - return NULL; - entry->name = NULL; - entry->path = NULL; - entry->stat = NULL; - entry->lstat = NULL; - entry->got_file_index = 0; - - entry->name = PyUnicode_FromWideChar(dataW->cFileName, -1); - if (!entry->name) - goto error; - - joined_path = join_path_filenameW(path->wide, dataW->cFileName); - if (!joined_path) - goto error; - - entry->path = PyUnicode_FromWideChar(joined_path, -1); - PyMem_Free(joined_path); - if (!entry->path) - goto error; - - find_data_to_file_info_w(dataW, &file_info, &reparse_tag); - _Py_attribute_data_to_stat(&file_info, reparse_tag, &entry->win32_lstat); - - return (PyObject *)entry; - -error: - Py_DECREF(entry); - return NULL; -} - -#else /* POSIX */ - -static char * -join_path_filename(char *path_narrow, char* filename, Py_ssize_t filename_len) -{ - Py_ssize_t path_len; - Py_ssize_t size; - char *result; - - if (!path_narrow) { /* Default arg: "." */ - path_narrow = "."; - path_len = 1; - } - else { - path_len = strlen(path_narrow); - } - - if (filename_len == -1) - filename_len = strlen(filename); - - /* The +1's are for the path separator and the NUL */ - size = path_len + 1 + filename_len + 1; - result = PyMem_New(char, size); - if (!result) { - PyErr_NoMemory(); - return NULL; - } - strcpy(result, path_narrow); - if (path_len > 0 && result[path_len - 1] != '/') - result[path_len++] = '/'; - strcpy(result + path_len, filename); - return result; -} - -static PyObject * -DirEntry_from_posix_info(path_t *path, char *name, Py_ssize_t name_len, - ino_t d_ino -#ifdef HAVE_DIRENT_D_TYPE - , unsigned char d_type -#endif - ) -{ - DirEntry *entry; - char *joined_path; - - entry = PyObject_New(DirEntry, &DirEntryType); - if (!entry) - return NULL; - entry->name = NULL; - entry->path = NULL; - entry->stat = NULL; - entry->lstat = NULL; - - joined_path = join_path_filename(path->narrow, name, name_len); - if (!joined_path) - goto error; - - if (!path->narrow || !PyBytes_Check(path->object)) { - entry->name = PyUnicode_DecodeFSDefaultAndSize(name, name_len); - entry->path = PyUnicode_DecodeFSDefault(joined_path); - } - else { - entry->name = PyBytes_FromStringAndSize(name, name_len); - entry->path = PyBytes_FromString(joined_path); - } - PyMem_Free(joined_path); - if (!entry->name || !entry->path) - goto error; - -#ifdef HAVE_DIRENT_D_TYPE - entry->d_type = d_type; -#endif - entry->d_ino = d_ino; - - return (PyObject *)entry; - -error: - Py_XDECREF(entry); - return NULL; -} - -#endif - - -typedef struct { - PyObject_HEAD - path_t path; -#ifdef MS_WINDOWS - HANDLE handle; - WIN32_FIND_DATAW file_data; - int first_time; -#else /* POSIX */ - DIR *dirp; -#endif -} ScandirIterator; - -#ifdef MS_WINDOWS - -static void -ScandirIterator_close(ScandirIterator *iterator) -{ - if (iterator->handle == INVALID_HANDLE_VALUE) - return; - - Py_BEGIN_ALLOW_THREADS - FindClose(iterator->handle); - Py_END_ALLOW_THREADS - iterator->handle = INVALID_HANDLE_VALUE; -} - -static PyObject * -ScandirIterator_iternext(ScandirIterator *iterator) -{ - WIN32_FIND_DATAW *file_data = &iterator->file_data; - BOOL success; - - /* Happens if the iterator is iterated twice */ - if (iterator->handle == INVALID_HANDLE_VALUE) { - PyErr_SetNone(PyExc_StopIteration); - return NULL; - } - - while (1) { - if (!iterator->first_time) { - Py_BEGIN_ALLOW_THREADS - success = FindNextFileW(iterator->handle, file_data); - Py_END_ALLOW_THREADS - if (!success) { - if (GetLastError() != ERROR_NO_MORE_FILES) - return path_error(&iterator->path); - /* No more files found in directory, stop iterating */ - break; - } - } - iterator->first_time = 0; - - /* Skip over . and .. */ - if (wcscmp(file_data->cFileName, L".") != 0 && - wcscmp(file_data->cFileName, L"..") != 0) - return DirEntry_from_find_data(&iterator->path, file_data); - - /* Loop till we get a non-dot directory or finish iterating */ - } - - ScandirIterator_close(iterator); - - PyErr_SetNone(PyExc_StopIteration); - return NULL; -} - -#else /* POSIX */ - -static void -ScandirIterator_close(ScandirIterator *iterator) -{ - if (!iterator->dirp) - return; - - Py_BEGIN_ALLOW_THREADS - closedir(iterator->dirp); - Py_END_ALLOW_THREADS - iterator->dirp = NULL; - return; -} - -static PyObject * -ScandirIterator_iternext(ScandirIterator *iterator) -{ - struct dirent *direntp; - Py_ssize_t name_len; - int is_dot; - - /* Happens if the iterator is iterated twice */ - if (!iterator->dirp) { - PyErr_SetNone(PyExc_StopIteration); - return NULL; - } - - while (1) { - errno = 0; - Py_BEGIN_ALLOW_THREADS - direntp = readdir(iterator->dirp); - Py_END_ALLOW_THREADS - - if (!direntp) { - if (errno != 0) - return path_error(&iterator->path); - /* No more files found in directory, stop iterating */ - break; - } - - /* Skip over . and .. */ - name_len = NAMLEN(direntp); - is_dot = direntp->d_name[0] == '.' && - (name_len == 1 || (direntp->d_name[1] == '.' && name_len == 2)); - if (!is_dot) { - return DirEntry_from_posix_info(&iterator->path, direntp->d_name, - name_len, direntp->d_ino -#ifdef HAVE_DIRENT_D_TYPE - , direntp->d_type -#endif - ); - } - - /* Loop till we get a non-dot directory or finish iterating */ - } - - ScandirIterator_close(iterator); - - PyErr_SetNone(PyExc_StopIteration); - return NULL; -} - -#endif - -static void -ScandirIterator_dealloc(ScandirIterator *iterator) -{ - ScandirIterator_close(iterator); - Py_XDECREF(iterator->path.object); - path_cleanup(&iterator->path); - Py_TYPE(iterator)->tp_free((PyObject *)iterator); -} - -PyTypeObject ScandirIteratorType = { - PyVarObject_HEAD_INIT(NULL, 0) - MODNAME ".ScandirIterator", /* tp_name */ - sizeof(ScandirIterator), /* tp_basicsize */ - 0, /* tp_itemsize */ - /* methods */ - (destructor)ScandirIterator_dealloc, /* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_compare */ - 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 */ - 0, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - PyObject_SelfIter, /* tp_iter */ - (iternextfunc)ScandirIterator_iternext, /* tp_iternext */ -}; - -static PyObject * -posix_scandir(PyObject *self, PyObject *args, PyObject *kwargs) -{ - ScandirIterator *iterator; - static char *keywords[] = {"path", NULL}; -#ifdef MS_WINDOWS - wchar_t *path_strW; -#else - char *path; -#endif - - iterator = PyObject_New(ScandirIterator, &ScandirIteratorType); - if (!iterator) - return NULL; - memset(&iterator->path, 0, sizeof(path_t)); - iterator->path.function_name = "scandir"; - iterator->path.nullable = 1; - -#ifdef MS_WINDOWS - iterator->handle = INVALID_HANDLE_VALUE; -#else - iterator->dirp = NULL; -#endif - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O&:scandir", keywords, - path_converter, &iterator->path)) - goto error; - - /* path_converter doesn't keep path.object around, so do it - manually for the lifetime of the iterator here (the refcount - is decremented in ScandirIterator_dealloc) - */ - Py_XINCREF(iterator->path.object); - -#ifdef MS_WINDOWS - if (iterator->path.narrow) { - PyErr_SetString(PyExc_TypeError, - "os.scandir() doesn't support bytes path on Windows, use Unicode instead"); - goto error; - } - iterator->first_time = 1; - - path_strW = join_path_filenameW(iterator->path.wide, L"*.*"); - if (!path_strW) - goto error; - - Py_BEGIN_ALLOW_THREADS - iterator->handle = FindFirstFileW(path_strW, &iterator->file_data); - Py_END_ALLOW_THREADS - - PyMem_Free(path_strW); - - if (iterator->handle == INVALID_HANDLE_VALUE) { - path_error(&iterator->path); - goto error; - } -#else /* POSIX */ - if (iterator->path.narrow) - path = iterator->path.narrow; - else - path = "."; - - errno = 0; - Py_BEGIN_ALLOW_THREADS - iterator->dirp = opendir(path); - Py_END_ALLOW_THREADS - - if (!iterator->dirp) { - path_error(&iterator->path); - goto error; - } -#endif - - return (PyObject *)iterator; - -error: - Py_DECREF(iterator); - return NULL; -} - - -/*[clinic input] -dump buffer -[clinic start generated code]*/ +#endif /* defined(MS_WINDOWS) */ #ifndef OS_TTYNAME_METHODDEF #define OS_TTYNAME_METHODDEF @@ -17509,973 +5847,4 @@ #ifndef OS_SET_HANDLE_INHERITABLE_METHODDEF #define OS_SET_HANDLE_INHERITABLE_METHODDEF #endif /* !defined(OS_SET_HANDLE_INHERITABLE_METHODDEF) */ -/*[clinic end generated code: output=b788c2d6010113e8 input=524ce2e021e4eba6]*/ - - -static PyMethodDef posix_methods[] = { - - OS_STAT_METHODDEF - OS_ACCESS_METHODDEF - OS_TTYNAME_METHODDEF - OS_CHDIR_METHODDEF - OS_CHFLAGS_METHODDEF - OS_CHMOD_METHODDEF - OS_FCHMOD_METHODDEF - OS_LCHMOD_METHODDEF - OS_CHOWN_METHODDEF - OS_FCHOWN_METHODDEF - OS_LCHOWN_METHODDEF - OS_LCHFLAGS_METHODDEF - OS_CHROOT_METHODDEF - OS_CTERMID_METHODDEF - OS_GETCWD_METHODDEF - OS_GETCWDB_METHODDEF - OS_LINK_METHODDEF - OS_LISTDIR_METHODDEF - OS_LSTAT_METHODDEF - OS_MKDIR_METHODDEF - OS_NICE_METHODDEF - OS_GETPRIORITY_METHODDEF - OS_SETPRIORITY_METHODDEF -#ifdef HAVE_READLINK - {"readlink", (PyCFunction)posix_readlink, - METH_VARARGS | METH_KEYWORDS, - readlink__doc__}, -#endif /* HAVE_READLINK */ -#if !defined(HAVE_READLINK) && defined(MS_WINDOWS) - {"readlink", (PyCFunction)win_readlink, - METH_VARARGS | METH_KEYWORDS, - readlink__doc__}, -#endif /* !defined(HAVE_READLINK) && defined(MS_WINDOWS) */ - OS_RENAME_METHODDEF - OS_REPLACE_METHODDEF - OS_RMDIR_METHODDEF - {"stat_float_times", stat_float_times, METH_VARARGS, stat_float_times__doc__}, - OS_SYMLINK_METHODDEF - OS_SYSTEM_METHODDEF - OS_UMASK_METHODDEF - OS_UNAME_METHODDEF - OS_UNLINK_METHODDEF - OS_REMOVE_METHODDEF - OS_UTIME_METHODDEF - OS_TIMES_METHODDEF - OS__EXIT_METHODDEF - OS_EXECV_METHODDEF - OS_EXECVE_METHODDEF - OS_SPAWNV_METHODDEF - OS_SPAWNVE_METHODDEF - OS_FORK1_METHODDEF - OS_FORK_METHODDEF - OS_SCHED_GET_PRIORITY_MAX_METHODDEF - OS_SCHED_GET_PRIORITY_MIN_METHODDEF - OS_SCHED_GETPARAM_METHODDEF - OS_SCHED_GETSCHEDULER_METHODDEF - OS_SCHED_RR_GET_INTERVAL_METHODDEF - OS_SCHED_SETPARAM_METHODDEF - OS_SCHED_SETSCHEDULER_METHODDEF - OS_SCHED_YIELD_METHODDEF - OS_SCHED_SETAFFINITY_METHODDEF - OS_SCHED_GETAFFINITY_METHODDEF - OS_OPENPTY_METHODDEF - OS_FORKPTY_METHODDEF - OS_GETEGID_METHODDEF - OS_GETEUID_METHODDEF - OS_GETGID_METHODDEF -#ifdef HAVE_GETGROUPLIST - {"getgrouplist", posix_getgrouplist, METH_VARARGS, posix_getgrouplist__doc__}, -#endif - OS_GETGROUPS_METHODDEF - OS_GETPID_METHODDEF - OS_GETPGRP_METHODDEF - OS_GETPPID_METHODDEF - OS_GETUID_METHODDEF - OS_GETLOGIN_METHODDEF - OS_KILL_METHODDEF - OS_KILLPG_METHODDEF - OS_PLOCK_METHODDEF -#ifdef MS_WINDOWS - {"startfile", win32_startfile, METH_VARARGS, win32_startfile__doc__}, -#endif - OS_SETUID_METHODDEF - OS_SETEUID_METHODDEF - OS_SETREUID_METHODDEF - OS_SETGID_METHODDEF - OS_SETEGID_METHODDEF - OS_SETREGID_METHODDEF - OS_SETGROUPS_METHODDEF -#ifdef HAVE_INITGROUPS - {"initgroups", posix_initgroups, METH_VARARGS, posix_initgroups__doc__}, -#endif /* HAVE_INITGROUPS */ - OS_GETPGID_METHODDEF - OS_SETPGRP_METHODDEF - OS_WAIT_METHODDEF - OS_WAIT3_METHODDEF - OS_WAIT4_METHODDEF - OS_WAITID_METHODDEF - OS_WAITPID_METHODDEF - OS_GETSID_METHODDEF - OS_SETSID_METHODDEF - OS_SETPGID_METHODDEF - OS_TCGETPGRP_METHODDEF - OS_TCSETPGRP_METHODDEF - OS_OPEN_METHODDEF - OS_CLOSE_METHODDEF - OS_CLOSERANGE_METHODDEF - OS_DEVICE_ENCODING_METHODDEF - OS_DUP_METHODDEF - OS_DUP2_METHODDEF - OS_LOCKF_METHODDEF - OS_LSEEK_METHODDEF - OS_READ_METHODDEF - OS_READV_METHODDEF - OS_PREAD_METHODDEF - OS_WRITE_METHODDEF - OS_WRITEV_METHODDEF - OS_PWRITE_METHODDEF -#ifdef HAVE_SENDFILE - {"sendfile", (PyCFunction)posix_sendfile, METH_VARARGS | METH_KEYWORDS, - posix_sendfile__doc__}, -#endif - OS_FSTAT_METHODDEF - OS_ISATTY_METHODDEF - OS_PIPE_METHODDEF - OS_PIPE2_METHODDEF - OS_MKFIFO_METHODDEF - OS_MKNOD_METHODDEF - OS_MAJOR_METHODDEF - OS_MINOR_METHODDEF - OS_MAKEDEV_METHODDEF - OS_FTRUNCATE_METHODDEF - OS_TRUNCATE_METHODDEF - OS_POSIX_FALLOCATE_METHODDEF - OS_POSIX_FADVISE_METHODDEF - OS_PUTENV_METHODDEF - OS_UNSETENV_METHODDEF - OS_STRERROR_METHODDEF - OS_FCHDIR_METHODDEF - OS_FSYNC_METHODDEF - OS_SYNC_METHODDEF - OS_FDATASYNC_METHODDEF - OS_WCOREDUMP_METHODDEF - OS_WIFCONTINUED_METHODDEF - OS_WIFSTOPPED_METHODDEF - OS_WIFSIGNALED_METHODDEF - OS_WIFEXITED_METHODDEF - OS_WEXITSTATUS_METHODDEF - OS_WTERMSIG_METHODDEF - OS_WSTOPSIG_METHODDEF - OS_FSTATVFS_METHODDEF - OS_STATVFS_METHODDEF - OS_CONFSTR_METHODDEF - OS_SYSCONF_METHODDEF - OS_FPATHCONF_METHODDEF - OS_PATHCONF_METHODDEF - OS_ABORT_METHODDEF -#ifdef MS_WINDOWS - {"_getfullpathname", posix__getfullpathname, METH_VARARGS, NULL}, - {"_isdir", posix__isdir, METH_VARARGS, posix__isdir__doc__}, -#endif - OS__GETDISKUSAGE_METHODDEF - OS__GETFINALPATHNAME_METHODDEF - OS__GETVOLUMEPATHNAME_METHODDEF - OS_GETLOADAVG_METHODDEF - OS_URANDOM_METHODDEF - OS_SETRESUID_METHODDEF - OS_SETRESGID_METHODDEF - OS_GETRESUID_METHODDEF - OS_GETRESGID_METHODDEF - - OS_GETXATTR_METHODDEF - OS_SETXATTR_METHODDEF - OS_REMOVEXATTR_METHODDEF - OS_LISTXATTR_METHODDEF - -#if defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL) - {"get_terminal_size", get_terminal_size, METH_VARARGS, termsize__doc__}, -#endif - OS_CPU_COUNT_METHODDEF - OS_GET_INHERITABLE_METHODDEF - OS_SET_INHERITABLE_METHODDEF - OS_GET_HANDLE_INHERITABLE_METHODDEF - OS_SET_HANDLE_INHERITABLE_METHODDEF -#ifndef MS_WINDOWS - {"get_blocking", posix_get_blocking, METH_VARARGS, get_blocking__doc__}, - {"set_blocking", posix_set_blocking, METH_VARARGS, set_blocking__doc__}, -#endif - {"scandir", (PyCFunction)posix_scandir, - METH_VARARGS | METH_KEYWORDS, - posix_scandir__doc__}, - {NULL, NULL} /* Sentinel */ -}; - - -#if defined(HAVE_SYMLINK) && defined(MS_WINDOWS) -static int -enable_symlink() -{ - HANDLE tok; - TOKEN_PRIVILEGES tok_priv; - LUID luid; - int meth_idx = 0; - - if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &tok)) - return 0; - - if (!LookupPrivilegeValue(NULL, SE_CREATE_SYMBOLIC_LINK_NAME, &luid)) - return 0; - - tok_priv.PrivilegeCount = 1; - tok_priv.Privileges[0].Luid = luid; - tok_priv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; - - if (!AdjustTokenPrivileges(tok, FALSE, &tok_priv, - sizeof(TOKEN_PRIVILEGES), - (PTOKEN_PRIVILEGES) NULL, (PDWORD) NULL)) - return 0; - - /* ERROR_NOT_ALL_ASSIGNED returned when the privilege can't be assigned. */ - return GetLastError() == ERROR_NOT_ALL_ASSIGNED ? 0 : 1; -} -#endif /* defined(HAVE_SYMLINK) && defined(MS_WINDOWS) */ - -static int -all_ins(PyObject *m) -{ -#ifdef F_OK - if (PyModule_AddIntMacro(m, F_OK)) return -1; -#endif -#ifdef R_OK - if (PyModule_AddIntMacro(m, R_OK)) return -1; -#endif -#ifdef W_OK - if (PyModule_AddIntMacro(m, W_OK)) return -1; -#endif -#ifdef X_OK - if (PyModule_AddIntMacro(m, X_OK)) return -1; -#endif -#ifdef NGROUPS_MAX - if (PyModule_AddIntMacro(m, NGROUPS_MAX)) return -1; -#endif -#ifdef TMP_MAX - if (PyModule_AddIntMacro(m, TMP_MAX)) return -1; -#endif -#ifdef WCONTINUED - if (PyModule_AddIntMacro(m, WCONTINUED)) return -1; -#endif -#ifdef WNOHANG - if (PyModule_AddIntMacro(m, WNOHANG)) return -1; -#endif -#ifdef WUNTRACED - if (PyModule_AddIntMacro(m, WUNTRACED)) return -1; -#endif -#ifdef O_RDONLY - if (PyModule_AddIntMacro(m, O_RDONLY)) return -1; -#endif -#ifdef O_WRONLY - if (PyModule_AddIntMacro(m, O_WRONLY)) return -1; -#endif -#ifdef O_RDWR - if (PyModule_AddIntMacro(m, O_RDWR)) return -1; -#endif -#ifdef O_NDELAY - if (PyModule_AddIntMacro(m, O_NDELAY)) return -1; -#endif -#ifdef O_NONBLOCK - if (PyModule_AddIntMacro(m, O_NONBLOCK)) return -1; -#endif -#ifdef O_APPEND - if (PyModule_AddIntMacro(m, O_APPEND)) return -1; -#endif -#ifdef O_DSYNC - if (PyModule_AddIntMacro(m, O_DSYNC)) return -1; -#endif -#ifdef O_RSYNC - if (PyModule_AddIntMacro(m, O_RSYNC)) return -1; -#endif -#ifdef O_SYNC - if (PyModule_AddIntMacro(m, O_SYNC)) return -1; -#endif -#ifdef O_NOCTTY - if (PyModule_AddIntMacro(m, O_NOCTTY)) return -1; -#endif -#ifdef O_CREAT - if (PyModule_AddIntMacro(m, O_CREAT)) return -1; -#endif -#ifdef O_EXCL - if (PyModule_AddIntMacro(m, O_EXCL)) return -1; -#endif -#ifdef O_TRUNC - if (PyModule_AddIntMacro(m, O_TRUNC)) return -1; -#endif -#ifdef O_BINARY - if (PyModule_AddIntMacro(m, O_BINARY)) return -1; -#endif -#ifdef O_TEXT - if (PyModule_AddIntMacro(m, O_TEXT)) return -1; -#endif -#ifdef O_XATTR - if (PyModule_AddIntMacro(m, O_XATTR)) return -1; -#endif -#ifdef O_LARGEFILE - if (PyModule_AddIntMacro(m, O_LARGEFILE)) return -1; -#endif -#ifdef O_SHLOCK - if (PyModule_AddIntMacro(m, O_SHLOCK)) return -1; -#endif -#ifdef O_EXLOCK - if (PyModule_AddIntMacro(m, O_EXLOCK)) return -1; -#endif -#ifdef O_EXEC - if (PyModule_AddIntMacro(m, O_EXEC)) return -1; -#endif -#ifdef O_SEARCH - if (PyModule_AddIntMacro(m, O_SEARCH)) return -1; -#endif -#ifdef O_PATH - if (PyModule_AddIntMacro(m, O_PATH)) return -1; -#endif -#ifdef O_TTY_INIT - if (PyModule_AddIntMacro(m, O_TTY_INIT)) return -1; -#endif -#ifdef O_TMPFILE - if (PyModule_AddIntMacro(m, O_TMPFILE)) return -1; -#endif -#ifdef PRIO_PROCESS - if (PyModule_AddIntMacro(m, PRIO_PROCESS)) return -1; -#endif -#ifdef PRIO_PGRP - if (PyModule_AddIntMacro(m, PRIO_PGRP)) return -1; -#endif -#ifdef PRIO_USER - if (PyModule_AddIntMacro(m, PRIO_USER)) return -1; -#endif -#ifdef O_CLOEXEC - if (PyModule_AddIntMacro(m, O_CLOEXEC)) return -1; -#endif -#ifdef O_ACCMODE - if (PyModule_AddIntMacro(m, O_ACCMODE)) return -1; -#endif - - -#ifdef SEEK_HOLE - if (PyModule_AddIntMacro(m, SEEK_HOLE)) return -1; -#endif -#ifdef SEEK_DATA - if (PyModule_AddIntMacro(m, SEEK_DATA)) return -1; -#endif - -/* MS Windows */ -#ifdef O_NOINHERIT - /* Don't inherit in child processes. */ - if (PyModule_AddIntMacro(m, O_NOINHERIT)) return -1; -#endif -#ifdef _O_SHORT_LIVED - /* Optimize for short life (keep in memory). */ - /* MS forgot to define this one with a non-underscore form too. */ - if (PyModule_AddIntConstant(m, "O_SHORT_LIVED", _O_SHORT_LIVED)) return -1; -#endif -#ifdef O_TEMPORARY - /* Automatically delete when last handle is closed. */ - if (PyModule_AddIntMacro(m, O_TEMPORARY)) return -1; -#endif -#ifdef O_RANDOM - /* Optimize for random access. */ - if (PyModule_AddIntMacro(m, O_RANDOM)) return -1; -#endif -#ifdef O_SEQUENTIAL - /* Optimize for sequential access. */ - if (PyModule_AddIntMacro(m, O_SEQUENTIAL)) return -1; -#endif - -/* GNU extensions. */ -#ifdef O_ASYNC - /* Send a SIGIO signal whenever input or output - becomes available on file descriptor */ - if (PyModule_AddIntMacro(m, O_ASYNC)) return -1; -#endif -#ifdef O_DIRECT - /* Direct disk access. */ - if (PyModule_AddIntMacro(m, O_DIRECT)) return -1; -#endif -#ifdef O_DIRECTORY - /* Must be a directory. */ - if (PyModule_AddIntMacro(m, O_DIRECTORY)) return -1; -#endif -#ifdef O_NOFOLLOW - /* Do not follow links. */ - if (PyModule_AddIntMacro(m, O_NOFOLLOW)) return -1; -#endif -#ifdef O_NOLINKS - /* Fails if link count of the named file is greater than 1 */ - if (PyModule_AddIntMacro(m, O_NOLINKS)) return -1; -#endif -#ifdef O_NOATIME - /* Do not update the access time. */ - if (PyModule_AddIntMacro(m, O_NOATIME)) return -1; -#endif - - /* These come from sysexits.h */ -#ifdef EX_OK - if (PyModule_AddIntMacro(m, EX_OK)) return -1; -#endif /* EX_OK */ -#ifdef EX_USAGE - if (PyModule_AddIntMacro(m, EX_USAGE)) return -1; -#endif /* EX_USAGE */ -#ifdef EX_DATAERR - if (PyModule_AddIntMacro(m, EX_DATAERR)) return -1; -#endif /* EX_DATAERR */ -#ifdef EX_NOINPUT - if (PyModule_AddIntMacro(m, EX_NOINPUT)) return -1; -#endif /* EX_NOINPUT */ -#ifdef EX_NOUSER - if (PyModule_AddIntMacro(m, EX_NOUSER)) return -1; -#endif /* EX_NOUSER */ -#ifdef EX_NOHOST - if (PyModule_AddIntMacro(m, EX_NOHOST)) return -1; -#endif /* EX_NOHOST */ -#ifdef EX_UNAVAILABLE - if (PyModule_AddIntMacro(m, EX_UNAVAILABLE)) return -1; -#endif /* EX_UNAVAILABLE */ -#ifdef EX_SOFTWARE - if (PyModule_AddIntMacro(m, EX_SOFTWARE)) return -1; -#endif /* EX_SOFTWARE */ -#ifdef EX_OSERR - if (PyModule_AddIntMacro(m, EX_OSERR)) return -1; -#endif /* EX_OSERR */ -#ifdef EX_OSFILE - if (PyModule_AddIntMacro(m, EX_OSFILE)) return -1; -#endif /* EX_OSFILE */ -#ifdef EX_CANTCREAT - if (PyModule_AddIntMacro(m, EX_CANTCREAT)) return -1; -#endif /* EX_CANTCREAT */ -#ifdef EX_IOERR - if (PyModule_AddIntMacro(m, EX_IOERR)) return -1; -#endif /* EX_IOERR */ -#ifdef EX_TEMPFAIL - if (PyModule_AddIntMacro(m, EX_TEMPFAIL)) return -1; -#endif /* EX_TEMPFAIL */ -#ifdef EX_PROTOCOL - if (PyModule_AddIntMacro(m, EX_PROTOCOL)) return -1; -#endif /* EX_PROTOCOL */ -#ifdef EX_NOPERM - if (PyModule_AddIntMacro(m, EX_NOPERM)) return -1; -#endif /* EX_NOPERM */ -#ifdef EX_CONFIG - if (PyModule_AddIntMacro(m, EX_CONFIG)) return -1; -#endif /* EX_CONFIG */ -#ifdef EX_NOTFOUND - if (PyModule_AddIntMacro(m, EX_NOTFOUND)) return -1; -#endif /* EX_NOTFOUND */ - - /* statvfs */ -#ifdef ST_RDONLY - if (PyModule_AddIntMacro(m, ST_RDONLY)) return -1; -#endif /* ST_RDONLY */ -#ifdef ST_NOSUID - if (PyModule_AddIntMacro(m, ST_NOSUID)) return -1; -#endif /* ST_NOSUID */ - - /* GNU extensions */ -#ifdef ST_NODEV - if (PyModule_AddIntMacro(m, ST_NODEV)) return -1; -#endif /* ST_NODEV */ -#ifdef ST_NOEXEC - if (PyModule_AddIntMacro(m, ST_NOEXEC)) return -1; -#endif /* ST_NOEXEC */ -#ifdef ST_SYNCHRONOUS - if (PyModule_AddIntMacro(m, ST_SYNCHRONOUS)) return -1; -#endif /* ST_SYNCHRONOUS */ -#ifdef ST_MANDLOCK - if (PyModule_AddIntMacro(m, ST_MANDLOCK)) return -1; -#endif /* ST_MANDLOCK */ -#ifdef ST_WRITE - if (PyModule_AddIntMacro(m, ST_WRITE)) return -1; -#endif /* ST_WRITE */ -#ifdef ST_APPEND - if (PyModule_AddIntMacro(m, ST_APPEND)) return -1; -#endif /* ST_APPEND */ -#ifdef ST_NOATIME - if (PyModule_AddIntMacro(m, ST_NOATIME)) return -1; -#endif /* ST_NOATIME */ -#ifdef ST_NODIRATIME - if (PyModule_AddIntMacro(m, ST_NODIRATIME)) return -1; -#endif /* ST_NODIRATIME */ -#ifdef ST_RELATIME - if (PyModule_AddIntMacro(m, ST_RELATIME)) return -1; -#endif /* ST_RELATIME */ - - /* FreeBSD sendfile() constants */ -#ifdef SF_NODISKIO - if (PyModule_AddIntMacro(m, SF_NODISKIO)) return -1; -#endif -#ifdef SF_MNOWAIT - if (PyModule_AddIntMacro(m, SF_MNOWAIT)) return -1; -#endif -#ifdef SF_SYNC - if (PyModule_AddIntMacro(m, SF_SYNC)) return -1; -#endif - - /* constants for posix_fadvise */ -#ifdef POSIX_FADV_NORMAL - if (PyModule_AddIntMacro(m, POSIX_FADV_NORMAL)) return -1; -#endif -#ifdef POSIX_FADV_SEQUENTIAL - if (PyModule_AddIntMacro(m, POSIX_FADV_SEQUENTIAL)) return -1; -#endif -#ifdef POSIX_FADV_RANDOM - if (PyModule_AddIntMacro(m, POSIX_FADV_RANDOM)) return -1; -#endif -#ifdef POSIX_FADV_NOREUSE - if (PyModule_AddIntMacro(m, POSIX_FADV_NOREUSE)) return -1; -#endif -#ifdef POSIX_FADV_WILLNEED - if (PyModule_AddIntMacro(m, POSIX_FADV_WILLNEED)) return -1; -#endif -#ifdef POSIX_FADV_DONTNEED - if (PyModule_AddIntMacro(m, POSIX_FADV_DONTNEED)) return -1; -#endif - - /* constants for waitid */ -#if defined(HAVE_SYS_WAIT_H) && defined(HAVE_WAITID) - if (PyModule_AddIntMacro(m, P_PID)) return -1; - if (PyModule_AddIntMacro(m, P_PGID)) return -1; - if (PyModule_AddIntMacro(m, P_ALL)) return -1; -#endif -#ifdef WEXITED - if (PyModule_AddIntMacro(m, WEXITED)) return -1; -#endif -#ifdef WNOWAIT - if (PyModule_AddIntMacro(m, WNOWAIT)) return -1; -#endif -#ifdef WSTOPPED - if (PyModule_AddIntMacro(m, WSTOPPED)) return -1; -#endif -#ifdef CLD_EXITED - if (PyModule_AddIntMacro(m, CLD_EXITED)) return -1; -#endif -#ifdef CLD_DUMPED - if (PyModule_AddIntMacro(m, CLD_DUMPED)) return -1; -#endif -#ifdef CLD_TRAPPED - if (PyModule_AddIntMacro(m, CLD_TRAPPED)) return -1; -#endif -#ifdef CLD_CONTINUED - if (PyModule_AddIntMacro(m, CLD_CONTINUED)) return -1; -#endif - - /* constants for lockf */ -#ifdef F_LOCK - if (PyModule_AddIntMacro(m, F_LOCK)) return -1; -#endif -#ifdef F_TLOCK - if (PyModule_AddIntMacro(m, F_TLOCK)) return -1; -#endif -#ifdef F_ULOCK - if (PyModule_AddIntMacro(m, F_ULOCK)) return -1; -#endif -#ifdef F_TEST - if (PyModule_AddIntMacro(m, F_TEST)) return -1; -#endif - -#ifdef HAVE_SPAWNV - if (PyModule_AddIntConstant(m, "P_WAIT", _P_WAIT)) return -1; - if (PyModule_AddIntConstant(m, "P_NOWAIT", _P_NOWAIT)) return -1; - if (PyModule_AddIntConstant(m, "P_OVERLAY", _OLD_P_OVERLAY)) return -1; - if (PyModule_AddIntConstant(m, "P_NOWAITO", _P_NOWAITO)) return -1; - if (PyModule_AddIntConstant(m, "P_DETACH", _P_DETACH)) return -1; -#endif - -#ifdef HAVE_SCHED_H - if (PyModule_AddIntMacro(m, SCHED_OTHER)) return -1; - if (PyModule_AddIntMacro(m, SCHED_FIFO)) return -1; - if (PyModule_AddIntMacro(m, SCHED_RR)) return -1; -#ifdef SCHED_SPORADIC - if (PyModule_AddIntMacro(m, SCHED_SPORADIC) return -1; -#endif -#ifdef SCHED_BATCH - if (PyModule_AddIntMacro(m, SCHED_BATCH)) return -1; -#endif -#ifdef SCHED_IDLE - if (PyModule_AddIntMacro(m, SCHED_IDLE)) return -1; -#endif -#ifdef SCHED_RESET_ON_FORK - if (PyModule_AddIntMacro(m, SCHED_RESET_ON_FORK)) return -1; -#endif -#ifdef SCHED_SYS - if (PyModule_AddIntMacro(m, SCHED_SYS)) return -1; -#endif -#ifdef SCHED_IA - if (PyModule_AddIntMacro(m, SCHED_IA)) return -1; -#endif -#ifdef SCHED_FSS - if (PyModule_AddIntMacro(m, SCHED_FSS)) return -1; -#endif -#ifdef SCHED_FX - if (PyModule_AddIntConstant(m, "SCHED_FX", SCHED_FSS)) return -1; -#endif -#endif - -#ifdef USE_XATTRS - if (PyModule_AddIntMacro(m, XATTR_CREATE)) return -1; - if (PyModule_AddIntMacro(m, XATTR_REPLACE)) return -1; - if (PyModule_AddIntMacro(m, XATTR_SIZE_MAX)) return -1; -#endif - -#ifdef RTLD_LAZY - if (PyModule_AddIntMacro(m, RTLD_LAZY)) return -1; -#endif -#ifdef RTLD_NOW - if (PyModule_AddIntMacro(m, RTLD_NOW)) return -1; -#endif -#ifdef RTLD_GLOBAL - if (PyModule_AddIntMacro(m, RTLD_GLOBAL)) return -1; -#endif -#ifdef RTLD_LOCAL - if (PyModule_AddIntMacro(m, RTLD_LOCAL)) return -1; -#endif -#ifdef RTLD_NODELETE - if (PyModule_AddIntMacro(m, RTLD_NODELETE)) return -1; -#endif -#ifdef RTLD_NOLOAD - if (PyModule_AddIntMacro(m, RTLD_NOLOAD)) return -1; -#endif -#ifdef RTLD_DEEPBIND - if (PyModule_AddIntMacro(m, RTLD_DEEPBIND)) return -1; -#endif - - return 0; -} - - -static struct PyModuleDef posixmodule = { - PyModuleDef_HEAD_INIT, - MODNAME, - posix__doc__, - -1, - posix_methods, - NULL, - NULL, - NULL, - NULL -}; - - -static char *have_functions[] = { - -#ifdef HAVE_FACCESSAT - "HAVE_FACCESSAT", -#endif - -#ifdef HAVE_FCHDIR - "HAVE_FCHDIR", -#endif - -#ifdef HAVE_FCHMOD - "HAVE_FCHMOD", -#endif - -#ifdef HAVE_FCHMODAT - "HAVE_FCHMODAT", -#endif - -#ifdef HAVE_FCHOWN - "HAVE_FCHOWN", -#endif - -#ifdef HAVE_FCHOWNAT - "HAVE_FCHOWNAT", -#endif - -#ifdef HAVE_FEXECVE - "HAVE_FEXECVE", -#endif - -#ifdef HAVE_FDOPENDIR - "HAVE_FDOPENDIR", -#endif - -#ifdef HAVE_FPATHCONF - "HAVE_FPATHCONF", -#endif - -#ifdef HAVE_FSTATAT - "HAVE_FSTATAT", -#endif - -#ifdef HAVE_FSTATVFS - "HAVE_FSTATVFS", -#endif - -#ifdef HAVE_FTRUNCATE - "HAVE_FTRUNCATE", -#endif - -#ifdef HAVE_FUTIMENS - "HAVE_FUTIMENS", -#endif - -#ifdef HAVE_FUTIMES - "HAVE_FUTIMES", -#endif - -#ifdef HAVE_FUTIMESAT - "HAVE_FUTIMESAT", -#endif - -#ifdef HAVE_LINKAT - "HAVE_LINKAT", -#endif - -#ifdef HAVE_LCHFLAGS - "HAVE_LCHFLAGS", -#endif - -#ifdef HAVE_LCHMOD - "HAVE_LCHMOD", -#endif - -#ifdef HAVE_LCHOWN - "HAVE_LCHOWN", -#endif - -#ifdef HAVE_LSTAT - "HAVE_LSTAT", -#endif - -#ifdef HAVE_LUTIMES - "HAVE_LUTIMES", -#endif - -#ifdef HAVE_MKDIRAT - "HAVE_MKDIRAT", -#endif - -#ifdef HAVE_MKFIFOAT - "HAVE_MKFIFOAT", -#endif - -#ifdef HAVE_MKNODAT - "HAVE_MKNODAT", -#endif - -#ifdef HAVE_OPENAT - "HAVE_OPENAT", -#endif - -#ifdef HAVE_READLINKAT - "HAVE_READLINKAT", -#endif - -#ifdef HAVE_RENAMEAT - "HAVE_RENAMEAT", -#endif - -#ifdef HAVE_SYMLINKAT - "HAVE_SYMLINKAT", -#endif - -#ifdef HAVE_UNLINKAT - "HAVE_UNLINKAT", -#endif - -#ifdef HAVE_UTIMENSAT - "HAVE_UTIMENSAT", -#endif - -#ifdef MS_WINDOWS - "MS_WINDOWS", -#endif - - NULL -}; - - -PyMODINIT_FUNC -INITFUNC(void) -{ - PyObject *m, *v; - PyObject *list; - char **trace; - -#if defined(HAVE_SYMLINK) && defined(MS_WINDOWS) - win32_can_symlink = enable_symlink(); -#endif - - m = PyModule_Create(&posixmodule); - if (m == NULL) - return NULL; - - /* Initialize environ dictionary */ - v = convertenviron(); - Py_XINCREF(v); - if (v == NULL || PyModule_AddObject(m, "environ", v) != 0) - return NULL; - Py_DECREF(v); - - if (all_ins(m)) - return NULL; - - if (setup_confname_tables(m)) - return NULL; - - Py_INCREF(PyExc_OSError); - PyModule_AddObject(m, "error", PyExc_OSError); - -#ifdef HAVE_PUTENV - if (posix_putenv_garbage == NULL) - posix_putenv_garbage = PyDict_New(); -#endif - - if (!initialized) { -#if defined(HAVE_WAITID) && !defined(__APPLE__) - waitid_result_desc.name = MODNAME ".waitid_result"; - if (PyStructSequence_InitType2(&WaitidResultType, &waitid_result_desc) < 0) - return NULL; -#endif - - stat_result_desc.name = "os.stat_result"; /* see issue #19209 */ - stat_result_desc.fields[7].name = PyStructSequence_UnnamedField; - stat_result_desc.fields[8].name = PyStructSequence_UnnamedField; - stat_result_desc.fields[9].name = PyStructSequence_UnnamedField; - if (PyStructSequence_InitType2(&StatResultType, &stat_result_desc) < 0) - return NULL; - structseq_new = StatResultType.tp_new; - StatResultType.tp_new = statresult_new; - - statvfs_result_desc.name = "os.statvfs_result"; /* see issue #19209 */ - if (PyStructSequence_InitType2(&StatVFSResultType, - &statvfs_result_desc) < 0) - return NULL; -#ifdef NEED_TICKS_PER_SECOND -# if defined(HAVE_SYSCONF) && defined(_SC_CLK_TCK) - ticks_per_second = sysconf(_SC_CLK_TCK); -# elif defined(HZ) - ticks_per_second = HZ; -# else - ticks_per_second = 60; /* magic fallback value; may be bogus */ -# endif -#endif - -#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) - sched_param_desc.name = MODNAME ".sched_param"; - if (PyStructSequence_InitType2(&SchedParamType, &sched_param_desc) < 0) - return NULL; - SchedParamType.tp_new = os_sched_param; -#endif - - /* initialize TerminalSize_info */ - if (PyStructSequence_InitType2(&TerminalSizeType, - &TerminalSize_desc) < 0) - return NULL; - - /* initialize scandir types */ - if (PyType_Ready(&ScandirIteratorType) < 0) - return NULL; - if (PyType_Ready(&DirEntryType) < 0) - return NULL; - } -#if defined(HAVE_WAITID) && !defined(__APPLE__) - Py_INCREF((PyObject*) &WaitidResultType); - PyModule_AddObject(m, "waitid_result", (PyObject*) &WaitidResultType); -#endif - Py_INCREF((PyObject*) &StatResultType); - PyModule_AddObject(m, "stat_result", (PyObject*) &StatResultType); - Py_INCREF((PyObject*) &StatVFSResultType); - PyModule_AddObject(m, "statvfs_result", - (PyObject*) &StatVFSResultType); - -#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) - Py_INCREF(&SchedParamType); - PyModule_AddObject(m, "sched_param", (PyObject *)&SchedParamType); -#endif - - times_result_desc.name = MODNAME ".times_result"; - if (PyStructSequence_InitType2(&TimesResultType, ×_result_desc) < 0) - return NULL; - PyModule_AddObject(m, "times_result", (PyObject *)&TimesResultType); - - uname_result_desc.name = MODNAME ".uname_result"; - if (PyStructSequence_InitType2(&UnameResultType, &uname_result_desc) < 0) - return NULL; - PyModule_AddObject(m, "uname_result", (PyObject *)&UnameResultType); - -#ifdef __APPLE__ - /* - * Step 2 of weak-linking support on Mac OS X. - * - * The code below removes functions that are not available on the - * currently active platform. - * - * This block allow one to use a python binary that was build on - * OSX 10.4 on OSX 10.3, without losing access to new APIs on - * OSX 10.4. - */ -#ifdef HAVE_FSTATVFS - if (fstatvfs == NULL) { - if (PyObject_DelAttrString(m, "fstatvfs") == -1) { - return NULL; - } - } -#endif /* HAVE_FSTATVFS */ - -#ifdef HAVE_STATVFS - if (statvfs == NULL) { - if (PyObject_DelAttrString(m, "statvfs") == -1) { - return NULL; - } - } -#endif /* HAVE_STATVFS */ - -# ifdef HAVE_LCHOWN - if (lchown == NULL) { - if (PyObject_DelAttrString(m, "lchown") == -1) { - return NULL; - } - } -#endif /* HAVE_LCHOWN */ - - -#endif /* __APPLE__ */ - - Py_INCREF(&TerminalSizeType); - PyModule_AddObject(m, "terminal_size", (PyObject*) &TerminalSizeType); - - billion = PyLong_FromLong(1000000000); - if (!billion) - return NULL; - - /* suppress "function not used" warnings */ - { - int ignored; - fd_specified("", -1); - follow_symlinks_specified("", 1); - dir_fd_and_follow_symlinks_invalid("chmod", DEFAULT_DIR_FD, 1); - dir_fd_converter(Py_None, &ignored); - dir_fd_unavailable(Py_None, &ignored); - } - - /* - * provide list of locally available functions - * so os.py can populate support_* lists - */ - list = PyList_New(0); - if (!list) - return NULL; - for (trace = have_functions; *trace; trace++) { - PyObject *unicode = PyUnicode_DecodeASCII(*trace, strlen(*trace), NULL); - if (!unicode) - return NULL; - if (PyList_Append(list, unicode)) - return NULL; - Py_DECREF(unicode); - } - PyModule_AddObject(m, "_have_functions", list); - - initialized = 1; - - return m; -} - -#ifdef __cplusplus -} -#endif +/*[clinic end generated code: output=d17c625afa72886b input=a9049054013a1b77]*/ diff --git a/Modules/pyexpat.c b/Modules/clinic/pyexpat.c.h copy from Modules/pyexpat.c copy to Modules/clinic/pyexpat.c.h --- a/Modules/pyexpat.c +++ b/Modules/clinic/pyexpat.c.h @@ -1,716 +1,5 @@ -#include "Python.h" -#include - -#include "frameobject.h" -#include "expat.h" - -#include "pyexpat.h" - -/* Do not emit Clinic output to a file as that wreaks havoc with conditionally - included methods. */ /*[clinic input] -module pyexpat -[clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=b168d503a4490c15]*/ - -#define XML_COMBINED_VERSION (10000*XML_MAJOR_VERSION+100*XML_MINOR_VERSION+XML_MICRO_VERSION) - -static XML_Memory_Handling_Suite ExpatMemoryHandler = { - PyObject_Malloc, PyObject_Realloc, PyObject_Free}; - -enum HandlerTypes { - StartElement, - EndElement, - ProcessingInstruction, - CharacterData, - UnparsedEntityDecl, - NotationDecl, - StartNamespaceDecl, - EndNamespaceDecl, - Comment, - StartCdataSection, - EndCdataSection, - Default, - DefaultHandlerExpand, - NotStandalone, - ExternalEntityRef, - StartDoctypeDecl, - EndDoctypeDecl, - EntityDecl, - XmlDecl, - ElementDecl, - AttlistDecl, -#if XML_COMBINED_VERSION >= 19504 - SkippedEntity, -#endif - _DummyDecl -}; - -static PyObject *ErrorObject; - -/* ----------------------------------------------------- */ - -/* Declarations for objects of type xmlparser */ - -typedef struct { - PyObject_HEAD - - XML_Parser itself; - int ordered_attributes; /* Return attributes as a list. */ - int specified_attributes; /* Report only specified attributes. */ - int in_callback; /* Is a callback active? */ - int ns_prefixes; /* Namespace-triplets mode? */ - XML_Char *buffer; /* Buffer used when accumulating characters */ - /* NULL if not enabled */ - int buffer_size; /* Size of buffer, in XML_Char units */ - int buffer_used; /* Buffer units in use */ - PyObject *intern; /* Dictionary to intern strings */ - PyObject **handlers; -} xmlparseobject; - -#define CHARACTER_DATA_BUFFER_SIZE 8192 - -static PyTypeObject Xmlparsetype; - -typedef void (*xmlhandlersetter)(XML_Parser self, void *meth); -typedef void* xmlhandler; - -struct HandlerInfo { - const char *name; - xmlhandlersetter setter; - xmlhandler handler; - PyCodeObject *tb_code; - PyObject *nameobj; -}; - -static struct HandlerInfo handler_info[64]; - -/* Set an integer attribute on the error object; return true on success, - * false on an exception. - */ -static int -set_error_attr(PyObject *err, char *name, int value) -{ - PyObject *v = PyLong_FromLong(value); - - if (v == NULL || PyObject_SetAttrString(err, name, v) == -1) { - Py_XDECREF(v); - return 0; - } - Py_DECREF(v); - return 1; -} - -/* Build and set an Expat exception, including positioning - * information. Always returns NULL. - */ -static PyObject * -set_error(xmlparseobject *self, enum XML_Error code) -{ - PyObject *err; - PyObject *buffer; - XML_Parser parser = self->itself; - int lineno = XML_GetErrorLineNumber(parser); - int column = XML_GetErrorColumnNumber(parser); - - buffer = PyUnicode_FromFormat("%s: line %i, column %i", - XML_ErrorString(code), lineno, column); - if (buffer == NULL) - return NULL; - err = PyObject_CallFunction(ErrorObject, "O", buffer); - Py_DECREF(buffer); - if ( err != NULL - && set_error_attr(err, "code", code) - && set_error_attr(err, "offset", column) - && set_error_attr(err, "lineno", lineno)) { - PyErr_SetObject(ErrorObject, err); - } - Py_XDECREF(err); - return NULL; -} - -static int -have_handler(xmlparseobject *self, int type) -{ - PyObject *handler = self->handlers[type]; - return handler != NULL; -} - -static PyObject * -get_handler_name(struct HandlerInfo *hinfo) -{ - PyObject *name = hinfo->nameobj; - if (name == NULL) { - name = PyUnicode_FromString(hinfo->name); - hinfo->nameobj = name; - } - Py_XINCREF(name); - return name; -} - - -/* Convert a string of XML_Chars into a Unicode string. - Returns None if str is a null pointer. */ - -static PyObject * -conv_string_to_unicode(const XML_Char *str) -{ - /* XXX currently this code assumes that XML_Char is 8-bit, - and hence in UTF-8. */ - /* UTF-8 from Expat, Unicode desired */ - if (str == NULL) { - Py_INCREF(Py_None); - return Py_None; - } - return PyUnicode_DecodeUTF8(str, strlen(str), "strict"); -} - -static PyObject * -conv_string_len_to_unicode(const XML_Char *str, int len) -{ - /* XXX currently this code assumes that XML_Char is 8-bit, - and hence in UTF-8. */ - /* UTF-8 from Expat, Unicode desired */ - if (str == NULL) { - Py_INCREF(Py_None); - return Py_None; - } - return PyUnicode_DecodeUTF8((const char *)str, len, "strict"); -} - -/* Callback routines */ - -static void clear_handlers(xmlparseobject *self, int initial); - -/* This handler is used when an error has been detected, in the hope - that actual parsing can be terminated early. This will only help - if an external entity reference is encountered. */ -static int -error_external_entity_ref_handler(XML_Parser parser, - const XML_Char *context, - const XML_Char *base, - const XML_Char *systemId, - const XML_Char *publicId) -{ - return 0; -} - -/* Dummy character data handler used when an error (exception) has - been detected, and the actual parsing can be terminated early. - This is needed since character data handler can't be safely removed - from within the character data handler, but can be replaced. It is - used only from the character data handler trampoline, and must be - used right after `flag_error()` is called. */ -static void -noop_character_data_handler(void *userData, const XML_Char *data, int len) -{ - /* Do nothing. */ -} - -static void -flag_error(xmlparseobject *self) -{ - clear_handlers(self, 0); - XML_SetExternalEntityRefHandler(self->itself, - error_external_entity_ref_handler); -} - -static PyObject* -call_with_frame(char *funcname, int lineno, PyObject* func, PyObject* args, - xmlparseobject *self) -{ - PyObject *res; - - res = PyEval_CallObject(func, args); - if (res == NULL) { - _PyTraceback_Add(funcname, __FILE__, lineno); - XML_StopParser(self->itself, XML_FALSE); - } - return res; -} - -static PyObject* -string_intern(xmlparseobject *self, const char* str) -{ - PyObject *result = conv_string_to_unicode(str); - PyObject *value; - /* result can be NULL if the unicode conversion failed. */ - if (!result) - return result; - if (!self->intern) - return result; - value = PyDict_GetItem(self->intern, result); - if (!value) { - if (PyDict_SetItem(self->intern, result, result) == 0) - return result; - else - return NULL; - } - Py_INCREF(value); - Py_DECREF(result); - return value; -} - -/* Return 0 on success, -1 on exception. - * flag_error() will be called before return if needed. - */ -static int -call_character_handler(xmlparseobject *self, const XML_Char *buffer, int len) -{ - PyObject *args; - PyObject *temp; - - if (!have_handler(self, CharacterData)) - return -1; - - args = PyTuple_New(1); - if (args == NULL) - return -1; - temp = (conv_string_len_to_unicode(buffer, len)); - if (temp == NULL) { - Py_DECREF(args); - flag_error(self); - XML_SetCharacterDataHandler(self->itself, - noop_character_data_handler); - return -1; - } - PyTuple_SET_ITEM(args, 0, temp); - /* temp is now a borrowed reference; consider it unused. */ - self->in_callback = 1; - temp = call_with_frame("CharacterData", __LINE__, - self->handlers[CharacterData], args, self); - /* temp is an owned reference again, or NULL */ - self->in_callback = 0; - Py_DECREF(args); - if (temp == NULL) { - flag_error(self); - XML_SetCharacterDataHandler(self->itself, - noop_character_data_handler); - return -1; - } - Py_DECREF(temp); - return 0; -} - -static int -flush_character_buffer(xmlparseobject *self) -{ - int rc; - if (self->buffer == NULL || self->buffer_used == 0) - return 0; - rc = call_character_handler(self, self->buffer, self->buffer_used); - self->buffer_used = 0; - return rc; -} - -static void -my_CharacterDataHandler(void *userData, const XML_Char *data, int len) -{ - xmlparseobject *self = (xmlparseobject *) userData; - - if (PyErr_Occurred()) - return; - - if (self->buffer == NULL) - call_character_handler(self, data, len); - else { - if ((self->buffer_used + len) > self->buffer_size) { - if (flush_character_buffer(self) < 0) - return; - /* handler might have changed; drop the rest on the floor - * if there isn't a handler anymore - */ - if (!have_handler(self, CharacterData)) - return; - } - if (len > self->buffer_size) { - call_character_handler(self, data, len); - self->buffer_used = 0; - } - else { - memcpy(self->buffer + self->buffer_used, - data, len * sizeof(XML_Char)); - self->buffer_used += len; - } - } -} - -static void -my_StartElementHandler(void *userData, - const XML_Char *name, const XML_Char *atts[]) -{ - xmlparseobject *self = (xmlparseobject *)userData; - - if (have_handler(self, StartElement)) { - PyObject *container, *rv, *args; - int i, max; - - if (PyErr_Occurred()) - return; - - if (flush_character_buffer(self) < 0) - return; - /* Set max to the number of slots filled in atts[]; max/2 is - * the number of attributes we need to process. - */ - if (self->specified_attributes) { - max = XML_GetSpecifiedAttributeCount(self->itself); - } - else { - max = 0; - while (atts[max] != NULL) - max += 2; - } - /* Build the container. */ - if (self->ordered_attributes) - container = PyList_New(max); - else - container = PyDict_New(); - if (container == NULL) { - flag_error(self); - return; - } - for (i = 0; i < max; i += 2) { - PyObject *n = string_intern(self, (XML_Char *) atts[i]); - PyObject *v; - if (n == NULL) { - flag_error(self); - Py_DECREF(container); - return; - } - v = conv_string_to_unicode((XML_Char *) atts[i+1]); - if (v == NULL) { - flag_error(self); - Py_DECREF(container); - Py_DECREF(n); - return; - } - if (self->ordered_attributes) { - PyList_SET_ITEM(container, i, n); - PyList_SET_ITEM(container, i+1, v); - } - else if (PyDict_SetItem(container, n, v)) { - flag_error(self); - Py_DECREF(n); - Py_DECREF(v); - return; - } - else { - Py_DECREF(n); - Py_DECREF(v); - } - } - args = string_intern(self, name); - if (args != NULL) - args = Py_BuildValue("(NN)", args, container); - if (args == NULL) { - Py_DECREF(container); - return; - } - /* Container is now a borrowed reference; ignore it. */ - self->in_callback = 1; - rv = call_with_frame("StartElement", __LINE__, - self->handlers[StartElement], args, self); - self->in_callback = 0; - Py_DECREF(args); - if (rv == NULL) { - flag_error(self); - return; - } - Py_DECREF(rv); - } -} - -#define RC_HANDLER(RC, NAME, PARAMS, INIT, PARAM_FORMAT, CONVERSION, \ - RETURN, GETUSERDATA) \ -static RC \ -my_##NAME##Handler PARAMS {\ - xmlparseobject *self = GETUSERDATA ; \ - PyObject *args = NULL; \ - PyObject *rv = NULL; \ - INIT \ -\ - if (have_handler(self, NAME)) { \ - if (PyErr_Occurred()) \ - return RETURN; \ - if (flush_character_buffer(self) < 0) \ - return RETURN; \ - args = Py_BuildValue PARAM_FORMAT ;\ - if (!args) { flag_error(self); return RETURN;} \ - self->in_callback = 1; \ - rv = call_with_frame(#NAME,__LINE__, \ - self->handlers[NAME], args, self); \ - self->in_callback = 0; \ - Py_DECREF(args); \ - if (rv == NULL) { \ - flag_error(self); \ - return RETURN; \ - } \ - CONVERSION \ - Py_DECREF(rv); \ - } \ - return RETURN; \ -} - -#define VOID_HANDLER(NAME, PARAMS, PARAM_FORMAT) \ - RC_HANDLER(void, NAME, PARAMS, ;, PARAM_FORMAT, ;, ;,\ - (xmlparseobject *)userData) - -#define INT_HANDLER(NAME, PARAMS, PARAM_FORMAT)\ - RC_HANDLER(int, NAME, PARAMS, int rc=0;, PARAM_FORMAT, \ - rc = PyLong_AsLong(rv);, rc, \ - (xmlparseobject *)userData) - -VOID_HANDLER(EndElement, - (void *userData, const XML_Char *name), - ("(N)", string_intern(self, name))) - -VOID_HANDLER(ProcessingInstruction, - (void *userData, - const XML_Char *target, - const XML_Char *data), - ("(NO&)", string_intern(self, target), conv_string_to_unicode ,data)) - -VOID_HANDLER(UnparsedEntityDecl, - (void *userData, - const XML_Char *entityName, - const XML_Char *base, - const XML_Char *systemId, - const XML_Char *publicId, - const XML_Char *notationName), - ("(NNNNN)", - string_intern(self, entityName), string_intern(self, base), - string_intern(self, systemId), string_intern(self, publicId), - string_intern(self, notationName))) - -VOID_HANDLER(EntityDecl, - (void *userData, - const XML_Char *entityName, - int is_parameter_entity, - const XML_Char *value, - int value_length, - const XML_Char *base, - const XML_Char *systemId, - const XML_Char *publicId, - const XML_Char *notationName), - ("NiNNNNN", - string_intern(self, entityName), is_parameter_entity, - (conv_string_len_to_unicode(value, value_length)), - string_intern(self, base), string_intern(self, systemId), - string_intern(self, publicId), - string_intern(self, notationName))) - -VOID_HANDLER(XmlDecl, - (void *userData, - const XML_Char *version, - const XML_Char *encoding, - int standalone), - ("(O&O&i)", - conv_string_to_unicode ,version, conv_string_to_unicode ,encoding, - standalone)) - -static PyObject * -conv_content_model(XML_Content * const model, - PyObject *(*conv_string)(const XML_Char *)) -{ - PyObject *result = NULL; - PyObject *children = PyTuple_New(model->numchildren); - int i; - - if (children != NULL) { - assert(model->numchildren < INT_MAX); - for (i = 0; i < (int)model->numchildren; ++i) { - PyObject *child = conv_content_model(&model->children[i], - conv_string); - if (child == NULL) { - Py_XDECREF(children); - return NULL; - } - PyTuple_SET_ITEM(children, i, child); - } - result = Py_BuildValue("(iiO&N)", - model->type, model->quant, - conv_string,model->name, children); - } - return result; -} - -static void -my_ElementDeclHandler(void *userData, - const XML_Char *name, - XML_Content *model) -{ - xmlparseobject *self = (xmlparseobject *)userData; - PyObject *args = NULL; - - if (have_handler(self, ElementDecl)) { - PyObject *rv = NULL; - PyObject *modelobj, *nameobj; - - if (PyErr_Occurred()) - return; - - if (flush_character_buffer(self) < 0) - goto finally; - modelobj = conv_content_model(model, (conv_string_to_unicode)); - if (modelobj == NULL) { - flag_error(self); - goto finally; - } - nameobj = string_intern(self, name); - if (nameobj == NULL) { - Py_DECREF(modelobj); - flag_error(self); - goto finally; - } - args = Py_BuildValue("NN", nameobj, modelobj); - if (args == NULL) { - Py_DECREF(modelobj); - flag_error(self); - goto finally; - } - self->in_callback = 1; - rv = call_with_frame("ElementDecl", __LINE__, - self->handlers[ElementDecl], args, self); - self->in_callback = 0; - if (rv == NULL) { - flag_error(self); - goto finally; - } - Py_DECREF(rv); - } - finally: - Py_XDECREF(args); - XML_FreeContentModel(self->itself, model); - return; -} - -VOID_HANDLER(AttlistDecl, - (void *userData, - const XML_Char *elname, - const XML_Char *attname, - const XML_Char *att_type, - const XML_Char *dflt, - int isrequired), - ("(NNO&O&i)", - string_intern(self, elname), string_intern(self, attname), - conv_string_to_unicode ,att_type, conv_string_to_unicode ,dflt, - isrequired)) - -#if XML_COMBINED_VERSION >= 19504 -VOID_HANDLER(SkippedEntity, - (void *userData, - const XML_Char *entityName, - int is_parameter_entity), - ("Ni", - string_intern(self, entityName), is_parameter_entity)) -#endif - -VOID_HANDLER(NotationDecl, - (void *userData, - const XML_Char *notationName, - const XML_Char *base, - const XML_Char *systemId, - const XML_Char *publicId), - ("(NNNN)", - string_intern(self, notationName), string_intern(self, base), - string_intern(self, systemId), string_intern(self, publicId))) - -VOID_HANDLER(StartNamespaceDecl, - (void *userData, - const XML_Char *prefix, - const XML_Char *uri), - ("(NN)", - string_intern(self, prefix), string_intern(self, uri))) - -VOID_HANDLER(EndNamespaceDecl, - (void *userData, - const XML_Char *prefix), - ("(N)", string_intern(self, prefix))) - -VOID_HANDLER(Comment, - (void *userData, const XML_Char *data), - ("(O&)", conv_string_to_unicode ,data)) - -VOID_HANDLER(StartCdataSection, - (void *userData), - ("()")) - -VOID_HANDLER(EndCdataSection, - (void *userData), - ("()")) - -VOID_HANDLER(Default, - (void *userData, const XML_Char *s, int len), - ("(N)", (conv_string_len_to_unicode(s,len)))) - -VOID_HANDLER(DefaultHandlerExpand, - (void *userData, const XML_Char *s, int len), - ("(N)", (conv_string_len_to_unicode(s,len)))) - -INT_HANDLER(NotStandalone, - (void *userData), - ("()")) - -RC_HANDLER(int, ExternalEntityRef, - (XML_Parser parser, - const XML_Char *context, - const XML_Char *base, - const XML_Char *systemId, - const XML_Char *publicId), - int rc=0;, - ("(O&NNN)", - conv_string_to_unicode ,context, string_intern(self, base), - string_intern(self, systemId), string_intern(self, publicId)), - rc = PyLong_AsLong(rv);, rc, - XML_GetUserData(parser)) - -/* XXX UnknownEncodingHandler */ - -VOID_HANDLER(StartDoctypeDecl, - (void *userData, const XML_Char *doctypeName, - const XML_Char *sysid, const XML_Char *pubid, - int has_internal_subset), - ("(NNNi)", string_intern(self, doctypeName), - string_intern(self, sysid), string_intern(self, pubid), - has_internal_subset)) - -VOID_HANDLER(EndDoctypeDecl, (void *userData), ("()")) - -/* ---------------------------------------------------------------- */ -/*[clinic input] -class pyexpat.xmlparser "xmlparseobject *" "&Xmlparsetype" -[clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=2393162385232e1c]*/ - - -static PyObject * -get_parse_result(xmlparseobject *self, int rv) -{ - if (PyErr_Occurred()) { - return NULL; - } - if (rv == 0) { - return set_error(self, XML_GetErrorCode(self->itself)); - } - if (flush_character_buffer(self) < 0) { - return NULL; - } - return PyLong_FromLong(rv); -} - -#define MAX_CHUNK_SIZE (1 << 20) - -/*[clinic input] -pyexpat.xmlparser.Parse - - data: object - isFinal: int = 0 - / - -Parse XML data. - -`isfinal' should be true at end of input. +preserve [clinic start generated code]*/ PyDoc_STRVAR(pyexpat_xmlparser_Parse__doc__, @@ -744,98 +33,6 @@ return return_value; } -static PyObject * -pyexpat_xmlparser_Parse_impl(xmlparseobject *self, PyObject *data, int isFinal) -/*[clinic end generated code: output=65b1652b01f20856 input=e37b81b8948ca7e0]*/ -{ - const char *s; - Py_ssize_t slen; - Py_buffer view; - int rc; - - if (PyUnicode_Check(data)) { - view.buf = NULL; - s = PyUnicode_AsUTF8AndSize(data, &slen); - if (s == NULL) - return NULL; - /* Explicitly set UTF-8 encoding. Return code ignored. */ - (void)XML_SetEncoding(self->itself, "utf-8"); - } - else { - if (PyObject_GetBuffer(data, &view, PyBUF_SIMPLE) < 0) - return NULL; - s = view.buf; - slen = view.len; - } - - while (slen > MAX_CHUNK_SIZE) { - rc = XML_Parse(self->itself, s, MAX_CHUNK_SIZE, 0); - if (!rc) - goto done; - s += MAX_CHUNK_SIZE; - slen -= MAX_CHUNK_SIZE; - } - assert(MAX_CHUNK_SIZE < INT_MAX && slen < INT_MAX); - rc = XML_Parse(self->itself, s, (int)slen, isFinal); - -done: - if (view.buf != NULL) - PyBuffer_Release(&view); - return get_parse_result(self, rc); -} - -/* File reading copied from cPickle */ - -#define BUF_SIZE 2048 - -static int -readinst(char *buf, int buf_size, PyObject *meth) -{ - PyObject *str; - Py_ssize_t len; - char *ptr; - - str = PyObject_CallFunction(meth, "n", buf_size); - if (str == NULL) - goto error; - - if (PyBytes_Check(str)) - ptr = PyBytes_AS_STRING(str); - else if (PyByteArray_Check(str)) - ptr = PyByteArray_AS_STRING(str); - else { - PyErr_Format(PyExc_TypeError, - "read() did not return a bytes object (type=%.400s)", - Py_TYPE(str)->tp_name); - goto error; - } - len = Py_SIZE(str); - if (len > buf_size) { - PyErr_Format(PyExc_ValueError, - "read() returned too much data: " - "%i bytes requested, %zd returned", - buf_size, len); - goto error; - } - memcpy(buf, ptr, len); - Py_DECREF(str); - /* len <= buf_size <= INT_MAX */ - return (int)len; - -error: - Py_XDECREF(str); - return -1; -} - -/*[clinic input] -pyexpat.xmlparser.ParseFile - - file: object - / - -Parse XML data from file-like object. -[clinic start generated code]*/ - PyDoc_STRVAR(pyexpat_xmlparser_ParseFile__doc__, "ParseFile($self, file, /)\n" "--\n" @@ -845,55 +42,6 @@ #define PYEXPAT_XMLPARSER_PARSEFILE_METHODDEF \ {"ParseFile", (PyCFunction)pyexpat_xmlparser_ParseFile, METH_O, pyexpat_xmlparser_ParseFile__doc__}, -static PyObject * -pyexpat_xmlparser_ParseFile(xmlparseobject *self, PyObject *file) -/*[clinic end generated code: output=2e13803c3d8c22b2 input=fbb5a12b6038d735]*/ -{ - int rv = 1; - PyObject *readmethod = NULL; - _Py_IDENTIFIER(read); - - readmethod = _PyObject_GetAttrId(file, &PyId_read); - if (readmethod == NULL) { - PyErr_SetString(PyExc_TypeError, - "argument must have 'read' attribute"); - return NULL; - } - for (;;) { - int bytes_read; - void *buf = XML_GetBuffer(self->itself, BUF_SIZE); - if (buf == NULL) { - Py_XDECREF(readmethod); - return get_parse_result(self, 0); - } - - bytes_read = readinst(buf, BUF_SIZE, readmethod); - if (bytes_read < 0) { - Py_DECREF(readmethod); - return NULL; - } - rv = XML_ParseBuffer(self->itself, bytes_read, bytes_read == 0); - if (PyErr_Occurred()) { - Py_XDECREF(readmethod); - return NULL; - } - - if (!rv || bytes_read == 0) - break; - } - Py_XDECREF(readmethod); - return get_parse_result(self, rv); -} - -/*[clinic input] -pyexpat.xmlparser.SetBase - - base: str - / - -Set the base URL for the parser. -[clinic start generated code]*/ - PyDoc_STRVAR(pyexpat_xmlparser_SetBase__doc__, "SetBase($self, base, /)\n" "--\n" @@ -922,22 +70,6 @@ return return_value; } -static PyObject * -pyexpat_xmlparser_SetBase_impl(xmlparseobject *self, const char *base) -/*[clinic end generated code: output=5bdb49f6689a5f93 input=c684e5de895ee1a8]*/ -{ - if (!XML_SetBase(self->itself, base)) { - return PyErr_NoMemory(); - } - Py_RETURN_NONE; -} - -/*[clinic input] -pyexpat.xmlparser.GetBase - -Return base URL string for the parser. -[clinic start generated code]*/ - PyDoc_STRVAR(pyexpat_xmlparser_GetBase__doc__, "GetBase($self, /)\n" "--\n" @@ -956,22 +88,6 @@ return pyexpat_xmlparser_GetBase_impl(self); } -static PyObject * -pyexpat_xmlparser_GetBase_impl(xmlparseobject *self) -/*[clinic end generated code: output=ef6046ee28f2b8ee input=918d71c38009620e]*/ -{ - return Py_BuildValue("z", XML_GetBase(self->itself)); -} - -/*[clinic input] -pyexpat.xmlparser.GetInputContext - -Return the untranslated text of the input that caused the current event. - -If the event was generated by a large amount of text (such as a start tag -for an element with many attributes), not all of the text may be available. -[clinic start generated code]*/ - PyDoc_STRVAR(pyexpat_xmlparser_GetInputContext__doc__, "GetInputContext($self, /)\n" "--\n" @@ -993,35 +109,6 @@ return pyexpat_xmlparser_GetInputContext_impl(self); } -static PyObject * -pyexpat_xmlparser_GetInputContext_impl(xmlparseobject *self) -/*[clinic end generated code: output=62ff03390f074cd2 input=034df8712db68379]*/ -{ - if (self->in_callback) { - int offset, size; - const char *buffer - = XML_GetInputContext(self->itself, &offset, &size); - - if (buffer != NULL) - return PyBytes_FromStringAndSize(buffer + offset, - size - offset); - else - Py_RETURN_NONE; - } - else - Py_RETURN_NONE; -} - -/*[clinic input] -pyexpat.xmlparser.ExternalEntityParserCreate - - context: str(nullable=True) - encoding: str = NULL - / - -Create a parser for parsing an external entity based on the information passed to the ExternalEntityRefHandler. -[clinic start generated code]*/ - PyDoc_STRVAR(pyexpat_xmlparser_ExternalEntityParserCreate__doc__, "ExternalEntityParserCreate($self, context, encoding=None, /)\n" "--\n" @@ -1051,82 +138,6 @@ return return_value; } -static PyObject * -pyexpat_xmlparser_ExternalEntityParserCreate_impl(xmlparseobject *self, const char *context, const char *encoding) -/*[clinic end generated code: output=4948c35f3dd01133 input=283206575d960272]*/ -{ - xmlparseobject *new_parser; - int i; - - new_parser = PyObject_GC_New(xmlparseobject, &Xmlparsetype); - if (new_parser == NULL) - return NULL; - new_parser->buffer_size = self->buffer_size; - new_parser->buffer_used = 0; - new_parser->buffer = NULL; - new_parser->ordered_attributes = self->ordered_attributes; - new_parser->specified_attributes = self->specified_attributes; - new_parser->in_callback = 0; - new_parser->ns_prefixes = self->ns_prefixes; - new_parser->itself = XML_ExternalEntityParserCreate(self->itself, context, - encoding); - new_parser->handlers = 0; - new_parser->intern = self->intern; - Py_XINCREF(new_parser->intern); - PyObject_GC_Track(new_parser); - - if (self->buffer != NULL) { - new_parser->buffer = PyMem_Malloc(new_parser->buffer_size); - if (new_parser->buffer == NULL) { - Py_DECREF(new_parser); - return PyErr_NoMemory(); - } - } - if (!new_parser->itself) { - Py_DECREF(new_parser); - return PyErr_NoMemory(); - } - - XML_SetUserData(new_parser->itself, (void *)new_parser); - - /* allocate and clear handlers first */ - for (i = 0; handler_info[i].name != NULL; i++) - /* do nothing */; - - new_parser->handlers = PyMem_New(PyObject *, i); - if (!new_parser->handlers) { - Py_DECREF(new_parser); - return PyErr_NoMemory(); - } - clear_handlers(new_parser, 1); - - /* then copy handlers from self */ - for (i = 0; handler_info[i].name != NULL; i++) { - PyObject *handler = self->handlers[i]; - if (handler != NULL) { - Py_INCREF(handler); - new_parser->handlers[i] = handler; - handler_info[i].setter(new_parser->itself, - handler_info[i].handler); - } - } - return (PyObject *)new_parser; -} - -/*[clinic input] -pyexpat.xmlparser.SetParamEntityParsing - - flag: int - / - -Controls parsing of parameter entities (including the external DTD subset). - -Possible flag values are XML_PARAM_ENTITY_PARSING_NEVER, -XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE and -XML_PARAM_ENTITY_PARSING_ALWAYS. Returns true if setting the flag -was successful. -[clinic start generated code]*/ - PyDoc_STRVAR(pyexpat_xmlparser_SetParamEntityParsing__doc__, "SetParamEntityParsing($self, flag, /)\n" "--\n" @@ -1160,28 +171,7 @@ return return_value; } -static PyObject * -pyexpat_xmlparser_SetParamEntityParsing_impl(xmlparseobject *self, int flag) -/*[clinic end generated code: output=0f820882bc7768cc input=8aea19b4b15e9af1]*/ -{ - flag = XML_SetParamEntityParsing(self->itself, flag); - return PyLong_FromLong(flag); -} - - -#if XML_COMBINED_VERSION >= 19505 -/*[clinic input] -pyexpat.xmlparser.UseForeignDTD - - flag: bool = True - / - -Allows the application to provide an artificial external subset if one is not specified as part of the document instance. - -This readily allows the use of a 'default' document type controlled by the -application, while still getting the advantage of providing document type -information to the parser. 'flag' defaults to True if not provided. -[clinic start generated code]*/ +#if (XML_COMBINED_VERSION >= 19505) PyDoc_STRVAR(pyexpat_xmlparser_UseForeignDTD__doc__, "UseForeignDTD($self, flag=True, /)\n" @@ -1215,24 +205,7 @@ return return_value; } -static PyObject * -pyexpat_xmlparser_UseForeignDTD_impl(xmlparseobject *self, int flag) -/*[clinic end generated code: output=22e924ae6cad67d6 input=78144c519d116a6e]*/ -{ - enum XML_Error rc; - - rc = XML_UseForeignDTD(self->itself, flag ? XML_TRUE : XML_FALSE); - if (rc != XML_ERROR_NONE) { - return set_error(self, rc); - } - Py_INCREF(Py_None); - return Py_None; -} -#endif - -/*[clinic input] -pyexpat.xmlparser.__dir__ -[clinic start generated code]*/ +#endif /* (XML_COMBINED_VERSION >= 19505) */ PyDoc_STRVAR(pyexpat_xmlparser___dir____doc__, "__dir__($self, /)\n" @@ -1250,521 +223,6 @@ return pyexpat_xmlparser___dir___impl(self); } -static PyObject * -pyexpat_xmlparser___dir___impl(xmlparseobject *self) -/*[clinic end generated code: output=1ed6efe83bc304cc input=76aa455f2a661384]*/ -{ -#define APPEND(list, str) \ - do { \ - PyObject *o = PyUnicode_FromString(str); \ - if (o != NULL) \ - PyList_Append(list, o); \ - Py_XDECREF(o); \ - } while (0) - - int i; - PyObject *rc = PyList_New(0); - if (!rc) - return NULL; - for (i = 0; handler_info[i].name != NULL; i++) { - PyObject *o = get_handler_name(&handler_info[i]); - if (o != NULL) - PyList_Append(rc, o); - Py_XDECREF(o); - } - APPEND(rc, "ErrorCode"); - APPEND(rc, "ErrorLineNumber"); - APPEND(rc, "ErrorColumnNumber"); - APPEND(rc, "ErrorByteIndex"); - APPEND(rc, "CurrentLineNumber"); - APPEND(rc, "CurrentColumnNumber"); - APPEND(rc, "CurrentByteIndex"); - APPEND(rc, "buffer_size"); - APPEND(rc, "buffer_text"); - APPEND(rc, "buffer_used"); - APPEND(rc, "namespace_prefixes"); - APPEND(rc, "ordered_attributes"); - APPEND(rc, "specified_attributes"); - APPEND(rc, "intern"); - -#undef APPEND - - if (PyErr_Occurred()) { - Py_DECREF(rc); - rc = NULL; - } - - return rc; -} - -static struct PyMethodDef xmlparse_methods[] = { - PYEXPAT_XMLPARSER_PARSE_METHODDEF - PYEXPAT_XMLPARSER_PARSEFILE_METHODDEF - PYEXPAT_XMLPARSER_SETBASE_METHODDEF - PYEXPAT_XMLPARSER_GETBASE_METHODDEF - PYEXPAT_XMLPARSER_GETINPUTCONTEXT_METHODDEF - PYEXPAT_XMLPARSER_EXTERNALENTITYPARSERCREATE_METHODDEF - PYEXPAT_XMLPARSER_SETPARAMENTITYPARSING_METHODDEF -#if XML_COMBINED_VERSION >= 19505 - PYEXPAT_XMLPARSER_USEFOREIGNDTD_METHODDEF -#endif - PYEXPAT_XMLPARSER___DIR___METHODDEF - {NULL, NULL} /* sentinel */ -}; - -/* ---------- */ - - - -/* pyexpat international encoding support. - Make it as simple as possible. -*/ - -static int -PyUnknownEncodingHandler(void *encodingHandlerData, - const XML_Char *name, - XML_Encoding *info) -{ - static unsigned char template_buffer[256] = {0}; - PyObject* u; - int i; - void *data; - unsigned int kind; - - if (PyErr_Occurred()) - return XML_STATUS_ERROR; - - if (template_buffer[1] == 0) { - for (i = 0; i < 256; i++) - template_buffer[i] = i; - } - - u = PyUnicode_Decode((char*) template_buffer, 256, name, "replace"); - if (u == NULL || PyUnicode_READY(u)) { - Py_XDECREF(u); - return XML_STATUS_ERROR; - } - - if (PyUnicode_GET_LENGTH(u) != 256) { - Py_DECREF(u); - PyErr_SetString(PyExc_ValueError, - "multi-byte encodings are not supported"); - return XML_STATUS_ERROR; - } - - kind = PyUnicode_KIND(u); - data = PyUnicode_DATA(u); - for (i = 0; i < 256; i++) { - Py_UCS4 ch = PyUnicode_READ(kind, data, i); - if (ch != Py_UNICODE_REPLACEMENT_CHARACTER) - info->map[i] = ch; - else - info->map[i] = -1; - } - - info->data = NULL; - info->convert = NULL; - info->release = NULL; - Py_DECREF(u); - - return XML_STATUS_OK; -} - - -static PyObject * -newxmlparseobject(const char *encoding, const char *namespace_separator, PyObject *intern) -{ - int i; - xmlparseobject *self; - - self = PyObject_GC_New(xmlparseobject, &Xmlparsetype); - if (self == NULL) - return NULL; - - self->buffer = NULL; - self->buffer_size = CHARACTER_DATA_BUFFER_SIZE; - self->buffer_used = 0; - self->ordered_attributes = 0; - self->specified_attributes = 0; - self->in_callback = 0; - self->ns_prefixes = 0; - self->handlers = NULL; - self->intern = intern; - Py_XINCREF(self->intern); - PyObject_GC_Track(self); - - /* namespace_separator is either NULL or contains one char + \0 */ - self->itself = XML_ParserCreate_MM(encoding, &ExpatMemoryHandler, - namespace_separator); - if (self->itself == NULL) { - PyErr_SetString(PyExc_RuntimeError, - "XML_ParserCreate failed"); - Py_DECREF(self); - return NULL; - } -#if ((XML_MAJOR_VERSION >= 2) && (XML_MINOR_VERSION >= 1)) || defined(XML_HAS_SET_HASH_SALT) - /* This feature was added upstream in libexpat 2.1.0. Our expat copy - * has a backport of this feature where we also define XML_HAS_SET_HASH_SALT - * to indicate that we can still use it. */ - XML_SetHashSalt(self->itself, - (unsigned long)_Py_HashSecret.expat.hashsalt); -#endif - XML_SetUserData(self->itself, (void *)self); - XML_SetUnknownEncodingHandler(self->itself, - (XML_UnknownEncodingHandler) PyUnknownEncodingHandler, NULL); - - for (i = 0; handler_info[i].name != NULL; i++) - /* do nothing */; - - self->handlers = PyMem_New(PyObject *, i); - if (!self->handlers) { - Py_DECREF(self); - return PyErr_NoMemory(); - } - clear_handlers(self, 1); - - return (PyObject*)self; -} - - -static void -xmlparse_dealloc(xmlparseobject *self) -{ - int i; - PyObject_GC_UnTrack(self); - if (self->itself != NULL) - XML_ParserFree(self->itself); - self->itself = NULL; - - if (self->handlers != NULL) { - PyObject *temp; - for (i = 0; handler_info[i].name != NULL; i++) { - temp = self->handlers[i]; - self->handlers[i] = NULL; - Py_XDECREF(temp); - } - PyMem_Free(self->handlers); - self->handlers = NULL; - } - if (self->buffer != NULL) { - PyMem_Free(self->buffer); - self->buffer = NULL; - } - Py_XDECREF(self->intern); - PyObject_GC_Del(self); -} - -static int -handlername2int(PyObject *name) -{ - int i; - for (i = 0; handler_info[i].name != NULL; i++) { - if (PyUnicode_CompareWithASCIIString( - name, handler_info[i].name) == 0) { - return i; - } - } - return -1; -} - -static PyObject * -get_pybool(int istrue) -{ - PyObject *result = istrue ? Py_True : Py_False; - Py_INCREF(result); - return result; -} - -static PyObject * -xmlparse_getattro(xmlparseobject *self, PyObject *nameobj) -{ - Py_UCS4 first_char; - int handlernum = -1; - - if (!PyUnicode_Check(nameobj)) - goto generic; - if (PyUnicode_READY(nameobj)) - return NULL; - - handlernum = handlername2int(nameobj); - - if (handlernum != -1) { - PyObject *result = self->handlers[handlernum]; - if (result == NULL) - result = Py_None; - Py_INCREF(result); - return result; - } - - first_char = PyUnicode_READ_CHAR(nameobj, 0); - if (first_char == 'E') { - if (PyUnicode_CompareWithASCIIString(nameobj, "ErrorCode") == 0) - return PyLong_FromLong((long) - XML_GetErrorCode(self->itself)); - if (PyUnicode_CompareWithASCIIString(nameobj, "ErrorLineNumber") == 0) - return PyLong_FromLong((long) - XML_GetErrorLineNumber(self->itself)); - if (PyUnicode_CompareWithASCIIString(nameobj, "ErrorColumnNumber") == 0) - return PyLong_FromLong((long) - XML_GetErrorColumnNumber(self->itself)); - if (PyUnicode_CompareWithASCIIString(nameobj, "ErrorByteIndex") == 0) - return PyLong_FromLong((long) - XML_GetErrorByteIndex(self->itself)); - } - if (first_char == 'C') { - if (PyUnicode_CompareWithASCIIString(nameobj, "CurrentLineNumber") == 0) - return PyLong_FromLong((long) - XML_GetCurrentLineNumber(self->itself)); - if (PyUnicode_CompareWithASCIIString(nameobj, "CurrentColumnNumber") == 0) - return PyLong_FromLong((long) - XML_GetCurrentColumnNumber(self->itself)); - if (PyUnicode_CompareWithASCIIString(nameobj, "CurrentByteIndex") == 0) - return PyLong_FromLong((long) - XML_GetCurrentByteIndex(self->itself)); - } - if (first_char == 'b') { - if (PyUnicode_CompareWithASCIIString(nameobj, "buffer_size") == 0) - return PyLong_FromLong((long) self->buffer_size); - if (PyUnicode_CompareWithASCIIString(nameobj, "buffer_text") == 0) - return get_pybool(self->buffer != NULL); - if (PyUnicode_CompareWithASCIIString(nameobj, "buffer_used") == 0) - return PyLong_FromLong((long) self->buffer_used); - } - if (PyUnicode_CompareWithASCIIString(nameobj, "namespace_prefixes") == 0) - return get_pybool(self->ns_prefixes); - if (PyUnicode_CompareWithASCIIString(nameobj, "ordered_attributes") == 0) - return get_pybool(self->ordered_attributes); - if (PyUnicode_CompareWithASCIIString(nameobj, "specified_attributes") == 0) - return get_pybool((long) self->specified_attributes); - if (PyUnicode_CompareWithASCIIString(nameobj, "intern") == 0) { - if (self->intern == NULL) { - Py_INCREF(Py_None); - return Py_None; - } - else { - Py_INCREF(self->intern); - return self->intern; - } - } - generic: - return PyObject_GenericGetAttr((PyObject*)self, nameobj); -} - -static int -sethandler(xmlparseobject *self, PyObject *name, PyObject* v) -{ - int handlernum = handlername2int(name); - if (handlernum >= 0) { - xmlhandler c_handler = NULL; - PyObject *temp = self->handlers[handlernum]; - - if (v == Py_None) { - /* If this is the character data handler, and a character - data handler is already active, we need to be more - careful. What we can safely do is replace the existing - character data handler callback function with a no-op - function that will refuse to call Python. The downside - is that this doesn't completely remove the character - data handler from the C layer if there's any callback - active, so Expat does a little more work than it - otherwise would, but that's really an odd case. A more - elaborate system of handlers and state could remove the - C handler more effectively. */ - if (handlernum == CharacterData && self->in_callback) - c_handler = noop_character_data_handler; - v = NULL; - } - else if (v != NULL) { - Py_INCREF(v); - c_handler = handler_info[handlernum].handler; - } - self->handlers[handlernum] = v; - Py_XDECREF(temp); - handler_info[handlernum].setter(self->itself, c_handler); - return 1; - } - return 0; -} - -static int -xmlparse_setattro(xmlparseobject *self, PyObject *name, PyObject *v) -{ - /* Set attribute 'name' to value 'v'. v==NULL means delete */ - if (v == NULL) { - PyErr_SetString(PyExc_RuntimeError, "Cannot delete attribute"); - return -1; - } - assert(PyUnicode_Check(name)); - if (PyUnicode_CompareWithASCIIString(name, "buffer_text") == 0) { - int b = PyObject_IsTrue(v); - if (b < 0) - return -1; - if (b) { - if (self->buffer == NULL) { - self->buffer = PyMem_Malloc(self->buffer_size); - if (self->buffer == NULL) { - PyErr_NoMemory(); - return -1; - } - self->buffer_used = 0; - } - } - else if (self->buffer != NULL) { - if (flush_character_buffer(self) < 0) - return -1; - PyMem_Free(self->buffer); - self->buffer = NULL; - } - return 0; - } - if (PyUnicode_CompareWithASCIIString(name, "namespace_prefixes") == 0) { - int b = PyObject_IsTrue(v); - if (b < 0) - return -1; - self->ns_prefixes = b; - XML_SetReturnNSTriplet(self->itself, self->ns_prefixes); - return 0; - } - if (PyUnicode_CompareWithASCIIString(name, "ordered_attributes") == 0) { - int b = PyObject_IsTrue(v); - if (b < 0) - return -1; - self->ordered_attributes = b; - return 0; - } - if (PyUnicode_CompareWithASCIIString(name, "specified_attributes") == 0) { - int b = PyObject_IsTrue(v); - if (b < 0) - return -1; - self->specified_attributes = b; - return 0; - } - - if (PyUnicode_CompareWithASCIIString(name, "buffer_size") == 0) { - long new_buffer_size; - if (!PyLong_Check(v)) { - PyErr_SetString(PyExc_TypeError, "buffer_size must be an integer"); - return -1; - } - - new_buffer_size=PyLong_AS_LONG(v); - /* trivial case -- no change */ - if (new_buffer_size == self->buffer_size) { - return 0; - } - - if (new_buffer_size <= 0) { - PyErr_SetString(PyExc_ValueError, "buffer_size must be greater than zero"); - return -1; - } - - /* check maximum */ - if (new_buffer_size > INT_MAX) { - char errmsg[100]; - sprintf(errmsg, "buffer_size must not be greater than %i", INT_MAX); - PyErr_SetString(PyExc_ValueError, errmsg); - return -1; - } - - if (self->buffer != NULL) { - /* there is already a buffer */ - if (self->buffer_used != 0) { - if (flush_character_buffer(self) < 0) { - return -1; - } - } - /* free existing buffer */ - PyMem_Free(self->buffer); - } - self->buffer = PyMem_Malloc(new_buffer_size); - if (self->buffer == NULL) { - PyErr_NoMemory(); - return -1; - } - self->buffer_size = new_buffer_size; - return 0; - } - - if (PyUnicode_CompareWithASCIIString(name, "CharacterDataHandler") == 0) { - /* If we're changing the character data handler, flush all - * cached data with the old handler. Not sure there's a - * "right" thing to do, though, but this probably won't - * happen. - */ - if (flush_character_buffer(self) < 0) - return -1; - } - if (sethandler(self, name, v)) { - return 0; - } - PyErr_SetObject(PyExc_AttributeError, name); - return -1; -} - -static int -xmlparse_traverse(xmlparseobject *op, visitproc visit, void *arg) -{ - int i; - for (i = 0; handler_info[i].name != NULL; i++) - Py_VISIT(op->handlers[i]); - return 0; -} - -static int -xmlparse_clear(xmlparseobject *op) -{ - clear_handlers(op, 0); - Py_CLEAR(op->intern); - return 0; -} - -PyDoc_STRVAR(Xmlparsetype__doc__, "XML parser"); - -static PyTypeObject Xmlparsetype = { - PyVarObject_HEAD_INIT(NULL, 0) - "pyexpat.xmlparser", /*tp_name*/ - sizeof(xmlparseobject), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - /* methods */ - (destructor)xmlparse_dealloc, /*tp_dealloc*/ - (printfunc)0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_reserved*/ - (reprfunc)0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - (hashfunc)0, /*tp_hash*/ - (ternaryfunc)0, /*tp_call*/ - (reprfunc)0, /*tp_str*/ - (getattrofunc)xmlparse_getattro, /* tp_getattro */ - (setattrofunc)xmlparse_setattro, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /*tp_flags*/ - Xmlparsetype__doc__, /* tp_doc - Documentation string */ - (traverseproc)xmlparse_traverse, /* tp_traverse */ - (inquiry)xmlparse_clear, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - xmlparse_methods, /* tp_methods */ -}; - -/* End of code for xmlparser objects */ -/* -------------------------------------------------------- */ - -/*[clinic input] -pyexpat.ParserCreate - - encoding: str(nullable=True) = NULL - namespace_separator: str(nullable=True) = NULL - intern: object = NULL - -Return a new XML parser object. -[clinic start generated code]*/ - PyDoc_STRVAR(pyexpat_ParserCreate__doc__, "ParserCreate($module, /, encoding=None, namespace_separator=None,\n" " intern=None)\n" @@ -1797,51 +255,6 @@ return return_value; } -static PyObject * -pyexpat_ParserCreate_impl(PyModuleDef *module, const char *encoding, const char *namespace_separator, PyObject *intern) -/*[clinic end generated code: output=4fc027dd33b7a2ac input=71b9f471aa6f8f86]*/ -{ - PyObject *result; - int intern_decref = 0; - - if (namespace_separator != NULL - && strlen(namespace_separator) > 1) { - PyErr_SetString(PyExc_ValueError, - "namespace_separator must be at most one" - " character, omitted, or None"); - return NULL; - } - /* Explicitly passing None means no interning is desired. - Not passing anything means that a new dictionary is used. */ - if (intern == Py_None) - intern = NULL; - else if (intern == NULL) { - intern = PyDict_New(); - if (!intern) - return NULL; - intern_decref = 1; - } - else if (!PyDict_Check(intern)) { - PyErr_SetString(PyExc_TypeError, "intern must be a dictionary"); - return NULL; - } - - result = newxmlparseobject(encoding, namespace_separator, intern); - if (intern_decref) { - Py_DECREF(intern); - } - return result; -} - -/*[clinic input] -pyexpat.ErrorString - - code: long - / - -Returns string error for given number. -[clinic start generated code]*/ - PyDoc_STRVAR(pyexpat_ErrorString__doc__, "ErrorString($module, code, /)\n" "--\n" @@ -1870,390 +283,7 @@ return return_value; } -static PyObject * -pyexpat_ErrorString_impl(PyModuleDef *module, long code) -/*[clinic end generated code: output=c70f3cd82bfaf067 input=cc67de010d9e62b3]*/ -{ - return Py_BuildValue("z", XML_ErrorString((int)code)); -} - -/* List of methods defined in the module */ - -static struct PyMethodDef pyexpat_methods[] = { - PYEXPAT_PARSERCREATE_METHODDEF - PYEXPAT_ERRORSTRING_METHODDEF - {NULL, NULL} /* sentinel */ -}; - -/* Module docstring */ - -PyDoc_STRVAR(pyexpat_module_documentation, -"Python wrapper for Expat parser."); - -/* Initialization function for the module */ - -#ifndef MODULE_NAME -#define MODULE_NAME "pyexpat" -#endif - -#ifndef MODULE_INITFUNC -#define MODULE_INITFUNC PyInit_pyexpat -#endif - -static struct PyModuleDef pyexpatmodule = { - PyModuleDef_HEAD_INIT, - MODULE_NAME, - pyexpat_module_documentation, - -1, - pyexpat_methods, - NULL, - NULL, - NULL, - NULL -}; - -PyMODINIT_FUNC -MODULE_INITFUNC(void) -{ - PyObject *m, *d; - PyObject *errmod_name = PyUnicode_FromString(MODULE_NAME ".errors"); - PyObject *errors_module; - PyObject *modelmod_name; - PyObject *model_module; - PyObject *sys_modules; - PyObject *tmpnum, *tmpstr; - PyObject *codes_dict; - PyObject *rev_codes_dict; - int res; - static struct PyExpat_CAPI capi; - PyObject *capi_object; - - if (errmod_name == NULL) - return NULL; - modelmod_name = PyUnicode_FromString(MODULE_NAME ".model"); - if (modelmod_name == NULL) - return NULL; - - if (PyType_Ready(&Xmlparsetype) < 0) - return NULL; - - /* Create the module and add the functions */ - m = PyModule_Create(&pyexpatmodule); - if (m == NULL) - return NULL; - - /* Add some symbolic constants to the module */ - if (ErrorObject == NULL) { - ErrorObject = PyErr_NewException("xml.parsers.expat.ExpatError", - NULL, NULL); - if (ErrorObject == NULL) - return NULL; - } - Py_INCREF(ErrorObject); - PyModule_AddObject(m, "error", ErrorObject); - Py_INCREF(ErrorObject); - PyModule_AddObject(m, "ExpatError", ErrorObject); - Py_INCREF(&Xmlparsetype); - PyModule_AddObject(m, "XMLParserType", (PyObject *) &Xmlparsetype); - - PyModule_AddStringConstant(m, "EXPAT_VERSION", - XML_ExpatVersion()); - { - XML_Expat_Version info = XML_ExpatVersionInfo(); - PyModule_AddObject(m, "version_info", - Py_BuildValue("(iii)", info.major, - info.minor, info.micro)); - } - /* XXX When Expat supports some way of figuring out how it was - compiled, this should check and set native_encoding - appropriately. - */ - PyModule_AddStringConstant(m, "native_encoding", "UTF-8"); - - sys_modules = PySys_GetObject("modules"); - d = PyModule_GetDict(m); - errors_module = PyDict_GetItem(d, errmod_name); - if (errors_module == NULL) { - errors_module = PyModule_New(MODULE_NAME ".errors"); - if (errors_module != NULL) { - PyDict_SetItem(sys_modules, errmod_name, errors_module); - /* gives away the reference to errors_module */ - PyModule_AddObject(m, "errors", errors_module); - } - } - Py_DECREF(errmod_name); - model_module = PyDict_GetItem(d, modelmod_name); - if (model_module == NULL) { - model_module = PyModule_New(MODULE_NAME ".model"); - if (model_module != NULL) { - PyDict_SetItem(sys_modules, modelmod_name, model_module); - /* gives away the reference to model_module */ - PyModule_AddObject(m, "model", model_module); - } - } - Py_DECREF(modelmod_name); - if (errors_module == NULL || model_module == NULL) - /* Don't core dump later! */ - return NULL; - -#if XML_COMBINED_VERSION > 19505 - { - const XML_Feature *features = XML_GetFeatureList(); - PyObject *list = PyList_New(0); - if (list == NULL) - /* just ignore it */ - PyErr_Clear(); - else { - int i = 0; - for (; features[i].feature != XML_FEATURE_END; ++i) { - int ok; - PyObject *item = Py_BuildValue("si", features[i].name, - features[i].value); - if (item == NULL) { - Py_DECREF(list); - list = NULL; - break; - } - ok = PyList_Append(list, item); - Py_DECREF(item); - if (ok < 0) { - PyErr_Clear(); - break; - } - } - if (list != NULL) - PyModule_AddObject(m, "features", list); - } - } -#endif - - codes_dict = PyDict_New(); - rev_codes_dict = PyDict_New(); - if (codes_dict == NULL || rev_codes_dict == NULL) { - Py_XDECREF(codes_dict); - Py_XDECREF(rev_codes_dict); - return NULL; - } - -#define MYCONST(name) \ - if (PyModule_AddStringConstant(errors_module, #name, \ - XML_ErrorString(name)) < 0) \ - return NULL; \ - tmpnum = PyLong_FromLong(name); \ - if (tmpnum == NULL) return NULL; \ - res = PyDict_SetItemString(codes_dict, \ - XML_ErrorString(name), tmpnum); \ - if (res < 0) return NULL; \ - tmpstr = PyUnicode_FromString(XML_ErrorString(name)); \ - if (tmpstr == NULL) return NULL; \ - res = PyDict_SetItem(rev_codes_dict, tmpnum, tmpstr); \ - Py_DECREF(tmpstr); \ - Py_DECREF(tmpnum); \ - if (res < 0) return NULL; \ - - MYCONST(XML_ERROR_NO_MEMORY); - MYCONST(XML_ERROR_SYNTAX); - MYCONST(XML_ERROR_NO_ELEMENTS); - MYCONST(XML_ERROR_INVALID_TOKEN); - MYCONST(XML_ERROR_UNCLOSED_TOKEN); - MYCONST(XML_ERROR_PARTIAL_CHAR); - MYCONST(XML_ERROR_TAG_MISMATCH); - MYCONST(XML_ERROR_DUPLICATE_ATTRIBUTE); - MYCONST(XML_ERROR_JUNK_AFTER_DOC_ELEMENT); - MYCONST(XML_ERROR_PARAM_ENTITY_REF); - MYCONST(XML_ERROR_UNDEFINED_ENTITY); - MYCONST(XML_ERROR_RECURSIVE_ENTITY_REF); - MYCONST(XML_ERROR_ASYNC_ENTITY); - MYCONST(XML_ERROR_BAD_CHAR_REF); - MYCONST(XML_ERROR_BINARY_ENTITY_REF); - MYCONST(XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF); - MYCONST(XML_ERROR_MISPLACED_XML_PI); - MYCONST(XML_ERROR_UNKNOWN_ENCODING); - MYCONST(XML_ERROR_INCORRECT_ENCODING); - MYCONST(XML_ERROR_UNCLOSED_CDATA_SECTION); - MYCONST(XML_ERROR_EXTERNAL_ENTITY_HANDLING); - MYCONST(XML_ERROR_NOT_STANDALONE); - MYCONST(XML_ERROR_UNEXPECTED_STATE); - MYCONST(XML_ERROR_ENTITY_DECLARED_IN_PE); - MYCONST(XML_ERROR_FEATURE_REQUIRES_XML_DTD); - MYCONST(XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING); - /* Added in Expat 1.95.7. */ - MYCONST(XML_ERROR_UNBOUND_PREFIX); - /* Added in Expat 1.95.8. */ - MYCONST(XML_ERROR_UNDECLARING_PREFIX); - MYCONST(XML_ERROR_INCOMPLETE_PE); - MYCONST(XML_ERROR_XML_DECL); - MYCONST(XML_ERROR_TEXT_DECL); - MYCONST(XML_ERROR_PUBLICID); - MYCONST(XML_ERROR_SUSPENDED); - MYCONST(XML_ERROR_NOT_SUSPENDED); - MYCONST(XML_ERROR_ABORTED); - MYCONST(XML_ERROR_FINISHED); - MYCONST(XML_ERROR_SUSPEND_PE); - - if (PyModule_AddStringConstant(errors_module, "__doc__", - "Constants used to describe " - "error conditions.") < 0) - return NULL; - - if (PyModule_AddObject(errors_module, "codes", codes_dict) < 0) - return NULL; - if (PyModule_AddObject(errors_module, "messages", rev_codes_dict) < 0) - return NULL; - -#undef MYCONST - -#define MYCONST(c) PyModule_AddIntConstant(m, #c, c) - MYCONST(XML_PARAM_ENTITY_PARSING_NEVER); - MYCONST(XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE); - MYCONST(XML_PARAM_ENTITY_PARSING_ALWAYS); -#undef MYCONST - -#define MYCONST(c) PyModule_AddIntConstant(model_module, #c, c) - PyModule_AddStringConstant(model_module, "__doc__", - "Constants used to interpret content model information."); - - MYCONST(XML_CTYPE_EMPTY); - MYCONST(XML_CTYPE_ANY); - MYCONST(XML_CTYPE_MIXED); - MYCONST(XML_CTYPE_NAME); - MYCONST(XML_CTYPE_CHOICE); - MYCONST(XML_CTYPE_SEQ); - - MYCONST(XML_CQUANT_NONE); - MYCONST(XML_CQUANT_OPT); - MYCONST(XML_CQUANT_REP); - MYCONST(XML_CQUANT_PLUS); -#undef MYCONST - - /* initialize pyexpat dispatch table */ - capi.size = sizeof(capi); - capi.magic = PyExpat_CAPI_MAGIC; - capi.MAJOR_VERSION = XML_MAJOR_VERSION; - capi.MINOR_VERSION = XML_MINOR_VERSION; - capi.MICRO_VERSION = XML_MICRO_VERSION; - capi.ErrorString = XML_ErrorString; - capi.GetErrorCode = XML_GetErrorCode; - capi.GetErrorColumnNumber = XML_GetErrorColumnNumber; - capi.GetErrorLineNumber = XML_GetErrorLineNumber; - capi.Parse = XML_Parse; - capi.ParserCreate_MM = XML_ParserCreate_MM; - capi.ParserFree = XML_ParserFree; - capi.SetCharacterDataHandler = XML_SetCharacterDataHandler; - capi.SetCommentHandler = XML_SetCommentHandler; - capi.SetDefaultHandlerExpand = XML_SetDefaultHandlerExpand; - capi.SetElementHandler = XML_SetElementHandler; - capi.SetNamespaceDeclHandler = XML_SetNamespaceDeclHandler; - capi.SetProcessingInstructionHandler = XML_SetProcessingInstructionHandler; - capi.SetUnknownEncodingHandler = XML_SetUnknownEncodingHandler; - capi.SetUserData = XML_SetUserData; - capi.SetStartDoctypeDeclHandler = XML_SetStartDoctypeDeclHandler; - capi.SetEncoding = XML_SetEncoding; - capi.DefaultUnknownEncodingHandler = PyUnknownEncodingHandler; - - /* export using capsule */ - capi_object = PyCapsule_New(&capi, PyExpat_CAPSULE_NAME, NULL); - if (capi_object) - PyModule_AddObject(m, "expat_CAPI", capi_object); - return m; -} - -static void -clear_handlers(xmlparseobject *self, int initial) -{ - int i = 0; - PyObject *temp; - - for (; handler_info[i].name != NULL; i++) { - if (initial) - self->handlers[i] = NULL; - else { - temp = self->handlers[i]; - self->handlers[i] = NULL; - Py_XDECREF(temp); - handler_info[i].setter(self->itself, NULL); - } - } -} - -static struct HandlerInfo handler_info[] = { - {"StartElementHandler", - (xmlhandlersetter)XML_SetStartElementHandler, - (xmlhandler)my_StartElementHandler}, - {"EndElementHandler", - (xmlhandlersetter)XML_SetEndElementHandler, - (xmlhandler)my_EndElementHandler}, - {"ProcessingInstructionHandler", - (xmlhandlersetter)XML_SetProcessingInstructionHandler, - (xmlhandler)my_ProcessingInstructionHandler}, - {"CharacterDataHandler", - (xmlhandlersetter)XML_SetCharacterDataHandler, - (xmlhandler)my_CharacterDataHandler}, - {"UnparsedEntityDeclHandler", - (xmlhandlersetter)XML_SetUnparsedEntityDeclHandler, - (xmlhandler)my_UnparsedEntityDeclHandler}, - {"NotationDeclHandler", - (xmlhandlersetter)XML_SetNotationDeclHandler, - (xmlhandler)my_NotationDeclHandler}, - {"StartNamespaceDeclHandler", - (xmlhandlersetter)XML_SetStartNamespaceDeclHandler, - (xmlhandler)my_StartNamespaceDeclHandler}, - {"EndNamespaceDeclHandler", - (xmlhandlersetter)XML_SetEndNamespaceDeclHandler, - (xmlhandler)my_EndNamespaceDeclHandler}, - {"CommentHandler", - (xmlhandlersetter)XML_SetCommentHandler, - (xmlhandler)my_CommentHandler}, - {"StartCdataSectionHandler", - (xmlhandlersetter)XML_SetStartCdataSectionHandler, - (xmlhandler)my_StartCdataSectionHandler}, - {"EndCdataSectionHandler", - (xmlhandlersetter)XML_SetEndCdataSectionHandler, - (xmlhandler)my_EndCdataSectionHandler}, - {"DefaultHandler", - (xmlhandlersetter)XML_SetDefaultHandler, - (xmlhandler)my_DefaultHandler}, - {"DefaultHandlerExpand", - (xmlhandlersetter)XML_SetDefaultHandlerExpand, - (xmlhandler)my_DefaultHandlerExpandHandler}, - {"NotStandaloneHandler", - (xmlhandlersetter)XML_SetNotStandaloneHandler, - (xmlhandler)my_NotStandaloneHandler}, - {"ExternalEntityRefHandler", - (xmlhandlersetter)XML_SetExternalEntityRefHandler, - (xmlhandler)my_ExternalEntityRefHandler}, - {"StartDoctypeDeclHandler", - (xmlhandlersetter)XML_SetStartDoctypeDeclHandler, - (xmlhandler)my_StartDoctypeDeclHandler}, - {"EndDoctypeDeclHandler", - (xmlhandlersetter)XML_SetEndDoctypeDeclHandler, - (xmlhandler)my_EndDoctypeDeclHandler}, - {"EntityDeclHandler", - (xmlhandlersetter)XML_SetEntityDeclHandler, - (xmlhandler)my_EntityDeclHandler}, - {"XmlDeclHandler", - (xmlhandlersetter)XML_SetXmlDeclHandler, - (xmlhandler)my_XmlDeclHandler}, - {"ElementDeclHandler", - (xmlhandlersetter)XML_SetElementDeclHandler, - (xmlhandler)my_ElementDeclHandler}, - {"AttlistDeclHandler", - (xmlhandlersetter)XML_SetAttlistDeclHandler, - (xmlhandler)my_AttlistDeclHandler}, -#if XML_COMBINED_VERSION >= 19504 - {"SkippedEntityHandler", - (xmlhandlersetter)XML_SetSkippedEntityHandler, - (xmlhandler)my_SkippedEntityHandler}, -#endif - - {NULL, NULL, NULL} /* sentinel */ -}; - -/*[clinic input] -dump buffer -[clinic start generated code]*/ - #ifndef PYEXPAT_XMLPARSER_USEFOREIGNDTD_METHODDEF #define PYEXPAT_XMLPARSER_USEFOREIGNDTD_METHODDEF #endif /* !defined(PYEXPAT_XMLPARSER_USEFOREIGNDTD_METHODDEF) */ -/*[clinic end generated code: output=a7880cb78bbd58ce input=524ce2e021e4eba6]*/ +/*[clinic end generated code: output=0198390005e40e1c input=a9049054013a1b77]*/ diff --git a/Modules/sha1module.c b/Modules/clinic/sha1module.c.h copy from Modules/sha1module.c copy to Modules/clinic/sha1module.c.h --- a/Modules/sha1module.c +++ b/Modules/clinic/sha1module.c.h @@ -1,323 +1,5 @@ -/* SHA1 module */ - -/* This module provides an interface to the SHA1 algorithm */ - -/* See below for information about the original code this module was - based upon. Additional work performed by: - - Andrew Kuchling (amk at amk.ca) - Greg Stein (gstein at lyra.org) - Trevor Perrin (trevp at trevp.net) - - Copyright (C) 2005-2007 Gregory P. Smith (greg at krypto.org) - Licensed to PSF under a Contributor Agreement. - -*/ - -/* SHA1 objects */ - -#include "Python.h" -#include "hashlib.h" - /*[clinic input] -module _sha1 -class SHA1Type "SHA1object *" "&PyType_Type" -[clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=3dc9a20d1becb759]*/ - -/* Some useful types */ - -#if SIZEOF_INT == 4 -typedef unsigned int SHA1_INT32; /* 32-bit integer */ -typedef PY_LONG_LONG SHA1_INT64; /* 64-bit integer */ -#else -/* not defined. compilation will die. */ -#endif - -/* The SHA1 block size and message digest sizes, in bytes */ - -#define SHA1_BLOCKSIZE 64 -#define SHA1_DIGESTSIZE 20 - -/* The structure for storing SHA1 info */ - -struct sha1_state { - SHA1_INT64 length; - SHA1_INT32 state[5], curlen; - unsigned char buf[SHA1_BLOCKSIZE]; -}; - -typedef struct { - PyObject_HEAD - - struct sha1_state hash_state; -} SHA1object; - - -/* ------------------------------------------------------------------------ - * - * This code for the SHA1 algorithm was noted as public domain. The - * original headers are pasted below. - * - * Several changes have been made to make it more compatible with the - * Python environment and desired interface. - * - */ - -/* LibTomCrypt, modular cryptographic library -- Tom St Denis - * - * LibTomCrypt is a library that provides various cryptographic - * algorithms in a highly modular and flexible manner. - * - * The library is free for all purposes without any express - * guarantee it works. - * - * Tom St Denis, tomstdenis at gmail.com, http://libtom.org - */ - -/* rotate the hard way (platform optimizations could be done) */ -#define ROL(x, y) ( (((unsigned long)(x)<<(unsigned long)((y)&31)) | (((unsigned long)(x)&0xFFFFFFFFUL)>>(unsigned long)(32-((y)&31)))) & 0xFFFFFFFFUL) -#define ROLc(x, y) ( (((unsigned long)(x)<<(unsigned long)((y)&31)) | (((unsigned long)(x)&0xFFFFFFFFUL)>>(unsigned long)(32-((y)&31)))) & 0xFFFFFFFFUL) - -/* Endian Neutral macros that work on all platforms */ - -#define STORE32H(x, y) \ - { (y)[0] = (unsigned char)(((x)>>24)&255); (y)[1] = (unsigned char)(((x)>>16)&255); \ - (y)[2] = (unsigned char)(((x)>>8)&255); (y)[3] = (unsigned char)((x)&255); } - -#define LOAD32H(x, y) \ - { x = ((unsigned long)((y)[0] & 255)<<24) | \ - ((unsigned long)((y)[1] & 255)<<16) | \ - ((unsigned long)((y)[2] & 255)<<8) | \ - ((unsigned long)((y)[3] & 255)); } - -#define STORE64H(x, y) \ - { (y)[0] = (unsigned char)(((x)>>56)&255); (y)[1] = (unsigned char)(((x)>>48)&255); \ - (y)[2] = (unsigned char)(((x)>>40)&255); (y)[3] = (unsigned char)(((x)>>32)&255); \ - (y)[4] = (unsigned char)(((x)>>24)&255); (y)[5] = (unsigned char)(((x)>>16)&255); \ - (y)[6] = (unsigned char)(((x)>>8)&255); (y)[7] = (unsigned char)((x)&255); } - - -/* SHA1 macros */ - -#define F0(x,y,z) (z ^ (x & (y ^ z))) -#define F1(x,y,z) (x ^ y ^ z) -#define F2(x,y,z) ((x & y) | (z & (x | y))) -#define F3(x,y,z) (x ^ y ^ z) - -static void sha1_compress(struct sha1_state *sha1, unsigned char *buf) -{ - SHA1_INT32 a,b,c,d,e,W[80],i; - - /* copy the state into 512-bits into W[0..15] */ - for (i = 0; i < 16; i++) { - LOAD32H(W[i], buf + (4*i)); - } - - /* copy state */ - a = sha1->state[0]; - b = sha1->state[1]; - c = sha1->state[2]; - d = sha1->state[3]; - e = sha1->state[4]; - - /* expand it */ - for (i = 16; i < 80; i++) { - W[i] = ROL(W[i-3] ^ W[i-8] ^ W[i-14] ^ W[i-16], 1); - } - - /* compress */ - /* round one */ - #define FF_0(a,b,c,d,e,i) e = (ROLc(a, 5) + F0(b,c,d) + e + W[i] + 0x5a827999UL); b = ROLc(b, 30); - #define FF_1(a,b,c,d,e,i) e = (ROLc(a, 5) + F1(b,c,d) + e + W[i] + 0x6ed9eba1UL); b = ROLc(b, 30); - #define FF_2(a,b,c,d,e,i) e = (ROLc(a, 5) + F2(b,c,d) + e + W[i] + 0x8f1bbcdcUL); b = ROLc(b, 30); - #define FF_3(a,b,c,d,e,i) e = (ROLc(a, 5) + F3(b,c,d) + e + W[i] + 0xca62c1d6UL); b = ROLc(b, 30); - - for (i = 0; i < 20; ) { - FF_0(a,b,c,d,e,i++); - FF_0(e,a,b,c,d,i++); - FF_0(d,e,a,b,c,i++); - FF_0(c,d,e,a,b,i++); - FF_0(b,c,d,e,a,i++); - } - - /* round two */ - for (; i < 40; ) { - FF_1(a,b,c,d,e,i++); - FF_1(e,a,b,c,d,i++); - FF_1(d,e,a,b,c,i++); - FF_1(c,d,e,a,b,i++); - FF_1(b,c,d,e,a,i++); - } - - /* round three */ - for (; i < 60; ) { - FF_2(a,b,c,d,e,i++); - FF_2(e,a,b,c,d,i++); - FF_2(d,e,a,b,c,i++); - FF_2(c,d,e,a,b,i++); - FF_2(b,c,d,e,a,i++); - } - - /* round four */ - for (; i < 80; ) { - FF_3(a,b,c,d,e,i++); - FF_3(e,a,b,c,d,i++); - FF_3(d,e,a,b,c,i++); - FF_3(c,d,e,a,b,i++); - FF_3(b,c,d,e,a,i++); - } - - #undef FF_0 - #undef FF_1 - #undef FF_2 - #undef FF_3 - - /* store */ - sha1->state[0] = sha1->state[0] + a; - sha1->state[1] = sha1->state[1] + b; - sha1->state[2] = sha1->state[2] + c; - sha1->state[3] = sha1->state[3] + d; - sha1->state[4] = sha1->state[4] + e; -} - -/** - Initialize the hash state - @param sha1 The hash state you wish to initialize -*/ -static void -sha1_init(struct sha1_state *sha1) -{ - assert(sha1 != NULL); - sha1->state[0] = 0x67452301UL; - sha1->state[1] = 0xefcdab89UL; - sha1->state[2] = 0x98badcfeUL; - sha1->state[3] = 0x10325476UL; - sha1->state[4] = 0xc3d2e1f0UL; - sha1->curlen = 0; - sha1->length = 0; -} - -/** - Process a block of memory though the hash - @param sha1 The hash state - @param in The data to hash - @param inlen The length of the data (octets) -*/ -static void -sha1_process(struct sha1_state *sha1, - const unsigned char *in, Py_ssize_t inlen) -{ - Py_ssize_t n; - - assert(sha1 != NULL); - assert(in != NULL); - assert(sha1->curlen <= sizeof(sha1->buf)); - - while (inlen > 0) { - if (sha1->curlen == 0 && inlen >= SHA1_BLOCKSIZE) { - sha1_compress(sha1, (unsigned char *)in); - sha1->length += SHA1_BLOCKSIZE * 8; - in += SHA1_BLOCKSIZE; - inlen -= SHA1_BLOCKSIZE; - } else { - n = Py_MIN(inlen, (Py_ssize_t)(SHA1_BLOCKSIZE - sha1->curlen)); - memcpy(sha1->buf + sha1->curlen, in, (size_t)n); - sha1->curlen += (SHA1_INT32)n; - in += n; - inlen -= n; - if (sha1->curlen == SHA1_BLOCKSIZE) { - sha1_compress(sha1, sha1->buf); - sha1->length += 8*SHA1_BLOCKSIZE; - sha1->curlen = 0; - } - } - } -} - -/** - Terminate the hash to get the digest - @param sha1 The hash state - @param out [out] The destination of the hash (20 bytes) -*/ -static void -sha1_done(struct sha1_state *sha1, unsigned char *out) -{ - int i; - - assert(sha1 != NULL); - assert(out != NULL); - assert(sha1->curlen < sizeof(sha1->buf)); - - /* increase the length of the message */ - sha1->length += sha1->curlen * 8; - - /* append the '1' bit */ - sha1->buf[sha1->curlen++] = (unsigned char)0x80; - - /* if the length is currently above 56 bytes we append zeros - * then compress. Then we can fall back to padding zeros and length - * encoding like normal. - */ - if (sha1->curlen > 56) { - while (sha1->curlen < 64) { - sha1->buf[sha1->curlen++] = (unsigned char)0; - } - sha1_compress(sha1, sha1->buf); - sha1->curlen = 0; - } - - /* pad upto 56 bytes of zeroes */ - while (sha1->curlen < 56) { - sha1->buf[sha1->curlen++] = (unsigned char)0; - } - - /* store length */ - STORE64H(sha1->length, sha1->buf+56); - sha1_compress(sha1, sha1->buf); - - /* copy output */ - for (i = 0; i < 5; i++) { - STORE32H(sha1->state[i], out+(4*i)); - } -} - - -/* .Source: /cvs/libtom/libtomcrypt/src/hashes/sha1.c,v $ */ -/* .Revision: 1.10 $ */ -/* .Date: 2007/05/12 14:25:28 $ */ - -/* - * End of copied SHA1 code. - * - * ------------------------------------------------------------------------ - */ - -static PyTypeObject SHA1type; - - -static SHA1object * -newSHA1object(void) -{ - return (SHA1object *)PyObject_New(SHA1object, &SHA1type); -} - - -/* Internal methods for a hash object */ - -static void -SHA1_dealloc(PyObject *ptr) -{ - PyObject_Del(ptr); -} - - -/* External methods for a hash object */ - -/*[clinic input] -SHA1Type.copy - -Return a copy of the hash object. +preserve [clinic start generated code]*/ PyDoc_STRVAR(SHA1Type_copy__doc__, @@ -338,25 +20,6 @@ return SHA1Type_copy_impl(self); } -static PyObject * -SHA1Type_copy_impl(SHA1object *self) -/*[clinic end generated code: output=1a320e75a7444098 input=b7eae10df6f89b36]*/ -{ - SHA1object *newobj; - - if ((newobj = newSHA1object()) == NULL) - return NULL; - - newobj->hash_state = self->hash_state; - return (PyObject *)newobj; -} - -/*[clinic input] -SHA1Type.digest - -Return the digest value as a string of binary data. -[clinic start generated code]*/ - PyDoc_STRVAR(SHA1Type_digest__doc__, "digest($self, /)\n" "--\n" @@ -375,24 +38,6 @@ return SHA1Type_digest_impl(self); } -static PyObject * -SHA1Type_digest_impl(SHA1object *self) -/*[clinic end generated code: output=c4920f75228bfbfd input=205d47e1927fd009]*/ -{ - unsigned char digest[SHA1_DIGESTSIZE]; - struct sha1_state temp; - - temp = self->hash_state; - sha1_done(&temp, digest); - return PyBytes_FromStringAndSize((const char *)digest, SHA1_DIGESTSIZE); -} - -/*[clinic input] -SHA1Type.hexdigest - -Return the digest value as a string of hexadecimal digits. -[clinic start generated code]*/ - PyDoc_STRVAR(SHA1Type_hexdigest__doc__, "hexdigest($self, /)\n" "--\n" @@ -411,49 +56,6 @@ return SHA1Type_hexdigest_impl(self); } -static PyObject * -SHA1Type_hexdigest_impl(SHA1object *self) -/*[clinic end generated code: output=6e345aac201887b2 input=97691055c0c74ab0]*/ -{ - unsigned char digest[SHA1_DIGESTSIZE]; - struct sha1_state temp; - PyObject *retval; - Py_UCS1 *hex_digest; - int i, j; - - /* Get the raw (binary) digest value */ - temp = self->hash_state; - sha1_done(&temp, digest); - - /* Create a new string */ - retval = PyUnicode_New(SHA1_DIGESTSIZE * 2, 127); - if (!retval) - return NULL; - hex_digest = PyUnicode_1BYTE_DATA(retval); - - /* Make hex version of the digest */ - for(i=j=0; i> 4) & 0xf; - hex_digest[j++] = Py_hexdigits[c]; - c = (digest[i] & 0xf); - hex_digest[j++] = Py_hexdigits[c]; - } -#ifdef Py_DEBUG - assert(_PyUnicode_CheckConsistency(retval, 1)); -#endif - return retval; -} - -/*[clinic input] -SHA1Type.update - - obj: object - / - -Update this hash object's state with the provided string. -[clinic start generated code]*/ - PyDoc_STRVAR(SHA1Type_update__doc__, "update($self, obj, /)\n" "--\n" @@ -463,109 +65,6 @@ #define SHA1TYPE_UPDATE_METHODDEF \ {"update", (PyCFunction)SHA1Type_update, METH_O, SHA1Type_update__doc__}, -static PyObject * -SHA1Type_update(SHA1object *self, PyObject *obj) -/*[clinic end generated code: output=ab20a86a25e7d255 input=aad8e07812edbba3]*/ -{ - Py_buffer buf; - - GET_BUFFER_VIEW_OR_ERROUT(obj, &buf); - - sha1_process(&self->hash_state, buf.buf, buf.len); - - PyBuffer_Release(&buf); - Py_INCREF(Py_None); - return Py_None; -} - -static PyMethodDef SHA1_methods[] = { - SHA1TYPE_COPY_METHODDEF - SHA1TYPE_DIGEST_METHODDEF - SHA1TYPE_HEXDIGEST_METHODDEF - SHA1TYPE_UPDATE_METHODDEF - {NULL, NULL} /* sentinel */ -}; - -static PyObject * -SHA1_get_block_size(PyObject *self, void *closure) -{ - return PyLong_FromLong(SHA1_BLOCKSIZE); -} - -static PyObject * -SHA1_get_name(PyObject *self, void *closure) -{ - return PyUnicode_FromStringAndSize("sha1", 4); -} - -static PyObject * -sha1_get_digest_size(PyObject *self, void *closure) -{ - return PyLong_FromLong(SHA1_DIGESTSIZE); -} - - -static PyGetSetDef SHA1_getseters[] = { - {"block_size", - (getter)SHA1_get_block_size, NULL, - NULL, - NULL}, - {"name", - (getter)SHA1_get_name, NULL, - NULL, - NULL}, - {"digest_size", - (getter)sha1_get_digest_size, NULL, - NULL, - NULL}, - {NULL} /* Sentinel */ -}; - -static PyTypeObject SHA1type = { - PyVarObject_HEAD_INIT(NULL, 0) - "_sha1.sha1", /*tp_name*/ - sizeof(SHA1object), /*tp_size*/ - 0, /*tp_itemsize*/ - /* methods */ - SHA1_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_reserved*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash*/ - 0, /*tp_call*/ - 0, /*tp_str*/ - 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*/ - SHA1_methods, /* tp_methods */ - NULL, /* tp_members */ - SHA1_getseters, /* tp_getset */ -}; - - -/* The single module-level function: new() */ - -/*[clinic input] -_sha1.sha1 - - string: object(c_default="NULL") = b'' - -Return a new SHA1 hash object; optionally initialized with a string. -[clinic start generated code]*/ - PyDoc_STRVAR(_sha1_sha1__doc__, "sha1($module, /, string=b\'\')\n" "--\n" @@ -594,79 +93,4 @@ exit: return return_value; } - -static PyObject * -_sha1_sha1_impl(PyModuleDef *module, PyObject *string) -/*[clinic end generated code: output=c9068552f07b8954 input=27ea54281d995ec2]*/ -{ - SHA1object *new; - Py_buffer buf; - - if (string) - GET_BUFFER_VIEW_OR_ERROUT(string, &buf); - - if ((new = newSHA1object()) == NULL) { - if (string) - PyBuffer_Release(&buf); - return NULL; - } - - sha1_init(&new->hash_state); - - if (PyErr_Occurred()) { - Py_DECREF(new); - if (string) - PyBuffer_Release(&buf); - return NULL; - } - if (string) { - sha1_process(&new->hash_state, buf.buf, buf.len); - PyBuffer_Release(&buf); - } - - return (PyObject *)new; -} - - -/* List of functions exported by this module */ - -static struct PyMethodDef SHA1_functions[] = { - _SHA1_SHA1_METHODDEF - {NULL, NULL} /* Sentinel */ -}; - - -/* Initialize this module. */ - -#define insint(n,v) { PyModule_AddIntConstant(m,n,v); } - - -static struct PyModuleDef _sha1module = { - PyModuleDef_HEAD_INIT, - "_sha1", - NULL, - -1, - SHA1_functions, - NULL, - NULL, - NULL, - NULL -}; - -PyMODINIT_FUNC -PyInit__sha1(void) -{ - PyObject *m; - - Py_TYPE(&SHA1type) = &PyType_Type; - if (PyType_Ready(&SHA1type) < 0) - return NULL; - - m = PyModule_Create(&_sha1module); - if (m == NULL) - return NULL; - - Py_INCREF((PyObject *)&SHA1type); - PyModule_AddObject(m, "SHA1Type", (PyObject *)&SHA1type); - return m; -} +/*[clinic end generated code: output=b2890b9ca964b217 input=a9049054013a1b77]*/ diff --git a/Modules/sha256module.c b/Modules/clinic/sha256module.c.h copy from Modules/sha256module.c copy to Modules/clinic/sha256module.c.h --- a/Modules/sha256module.c +++ b/Modules/clinic/sha256module.c.h @@ -1,407 +1,5 @@ -/* SHA256 module */ - -/* This module provides an interface to NIST's SHA-256 and SHA-224 Algorithms */ - -/* See below for information about the original code this module was - based upon. Additional work performed by: - - Andrew Kuchling (amk at amk.ca) - Greg Stein (gstein at lyra.org) - Trevor Perrin (trevp at trevp.net) - - Copyright (C) 2005-2007 Gregory P. Smith (greg at krypto.org) - Licensed to PSF under a Contributor Agreement. - -*/ - -/* SHA objects */ - -#include "Python.h" -#include "structmember.h" -#include "hashlib.h" - /*[clinic input] -module _sha256 -class SHA256Type "SHAobject *" "&PyType_Type" -[clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=71a39174d4f0a744]*/ - -/* Some useful types */ - -typedef unsigned char SHA_BYTE; - -#if SIZEOF_INT == 4 -typedef unsigned int SHA_INT32; /* 32-bit integer */ -#else -/* not defined. compilation will die. */ -#endif - -/* The SHA block size and message digest sizes, in bytes */ - -#define SHA_BLOCKSIZE 64 -#define SHA_DIGESTSIZE 32 - -/* The structure for storing SHA info */ - -typedef struct { - PyObject_HEAD - SHA_INT32 digest[8]; /* Message digest */ - SHA_INT32 count_lo, count_hi; /* 64-bit bit count */ - SHA_BYTE data[SHA_BLOCKSIZE]; /* SHA data buffer */ - int local; /* unprocessed amount in data */ - int digestsize; -} SHAobject; - -/* When run on a little-endian CPU we need to perform byte reversal on an - array of longwords. */ - -#if PY_LITTLE_ENDIAN -static void longReverse(SHA_INT32 *buffer, int byteCount) -{ - SHA_INT32 value; - - byteCount /= sizeof(*buffer); - while (byteCount--) { - value = *buffer; - value = ( ( value & 0xFF00FF00L ) >> 8 ) | \ - ( ( value & 0x00FF00FFL ) << 8 ); - *buffer++ = ( value << 16 ) | ( value >> 16 ); - } -} -#endif - -static void SHAcopy(SHAobject *src, SHAobject *dest) -{ - dest->local = src->local; - dest->digestsize = src->digestsize; - dest->count_lo = src->count_lo; - dest->count_hi = src->count_hi; - memcpy(dest->digest, src->digest, sizeof(src->digest)); - memcpy(dest->data, src->data, sizeof(src->data)); -} - - -/* ------------------------------------------------------------------------ - * - * This code for the SHA-256 algorithm was noted as public domain. The - * original headers are pasted below. - * - * Several changes have been made to make it more compatible with the - * Python environment and desired interface. - * - */ - -/* LibTomCrypt, modular cryptographic library -- Tom St Denis - * - * LibTomCrypt is a library that provides various cryptographic - * algorithms in a highly modular and flexible manner. - * - * The library is free for all purposes without any express - * gurantee it works. - * - * Tom St Denis, tomstdenis at iahu.ca, http://libtom.org - */ - - -/* SHA256 by Tom St Denis */ - -/* Various logical functions */ -#define ROR(x, y)\ -( ((((unsigned long)(x)&0xFFFFFFFFUL)>>(unsigned long)((y)&31)) | \ -((unsigned long)(x)<<(unsigned long)(32-((y)&31)))) & 0xFFFFFFFFUL) -#define Ch(x,y,z) (z ^ (x & (y ^ z))) -#define Maj(x,y,z) (((x | y) & z) | (x & y)) -#define S(x, n) ROR((x),(n)) -#define R(x, n) (((x)&0xFFFFFFFFUL)>>(n)) -#define Sigma0(x) (S(x, 2) ^ S(x, 13) ^ S(x, 22)) -#define Sigma1(x) (S(x, 6) ^ S(x, 11) ^ S(x, 25)) -#define Gamma0(x) (S(x, 7) ^ S(x, 18) ^ R(x, 3)) -#define Gamma1(x) (S(x, 17) ^ S(x, 19) ^ R(x, 10)) - - -static void -sha_transform(SHAobject *sha_info) -{ - int i; - SHA_INT32 S[8], W[64], t0, t1; - - memcpy(W, sha_info->data, sizeof(sha_info->data)); -#if PY_LITTLE_ENDIAN - longReverse(W, (int)sizeof(sha_info->data)); -#endif - - for (i = 16; i < 64; ++i) { - W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) + W[i - 16]; - } - for (i = 0; i < 8; ++i) { - S[i] = sha_info->digest[i]; - } - - /* Compress */ -#define RND(a,b,c,d,e,f,g,h,i,ki) \ - t0 = h + Sigma1(e) + Ch(e, f, g) + ki + W[i]; \ - t1 = Sigma0(a) + Maj(a, b, c); \ - d += t0; \ - h = t0 + t1; - - RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],0,0x428a2f98); - RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],1,0x71374491); - RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],2,0xb5c0fbcf); - RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],3,0xe9b5dba5); - RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],4,0x3956c25b); - RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],5,0x59f111f1); - RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],6,0x923f82a4); - RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],7,0xab1c5ed5); - RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],8,0xd807aa98); - RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],9,0x12835b01); - RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],10,0x243185be); - RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],11,0x550c7dc3); - RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],12,0x72be5d74); - RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],13,0x80deb1fe); - RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],14,0x9bdc06a7); - RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],15,0xc19bf174); - RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],16,0xe49b69c1); - RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],17,0xefbe4786); - RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],18,0x0fc19dc6); - RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],19,0x240ca1cc); - RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],20,0x2de92c6f); - RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],21,0x4a7484aa); - RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],22,0x5cb0a9dc); - RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],23,0x76f988da); - RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],24,0x983e5152); - RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],25,0xa831c66d); - RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],26,0xb00327c8); - RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],27,0xbf597fc7); - RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],28,0xc6e00bf3); - RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],29,0xd5a79147); - RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],30,0x06ca6351); - RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],31,0x14292967); - RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],32,0x27b70a85); - RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],33,0x2e1b2138); - RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],34,0x4d2c6dfc); - RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],35,0x53380d13); - RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],36,0x650a7354); - RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],37,0x766a0abb); - RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],38,0x81c2c92e); - RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],39,0x92722c85); - RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],40,0xa2bfe8a1); - RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],41,0xa81a664b); - RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],42,0xc24b8b70); - RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],43,0xc76c51a3); - RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],44,0xd192e819); - RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],45,0xd6990624); - RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],46,0xf40e3585); - RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],47,0x106aa070); - RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],48,0x19a4c116); - RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],49,0x1e376c08); - RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],50,0x2748774c); - RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],51,0x34b0bcb5); - RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],52,0x391c0cb3); - RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],53,0x4ed8aa4a); - RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],54,0x5b9cca4f); - RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],55,0x682e6ff3); - RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],56,0x748f82ee); - RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],57,0x78a5636f); - RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],58,0x84c87814); - RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],59,0x8cc70208); - RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],60,0x90befffa); - RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],61,0xa4506ceb); - RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],62,0xbef9a3f7); - RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],63,0xc67178f2); - -#undef RND - - /* feedback */ - for (i = 0; i < 8; i++) { - sha_info->digest[i] = sha_info->digest[i] + S[i]; - } - -} - - - -/* initialize the SHA digest */ - -static void -sha_init(SHAobject *sha_info) -{ - sha_info->digest[0] = 0x6A09E667L; - sha_info->digest[1] = 0xBB67AE85L; - sha_info->digest[2] = 0x3C6EF372L; - sha_info->digest[3] = 0xA54FF53AL; - sha_info->digest[4] = 0x510E527FL; - sha_info->digest[5] = 0x9B05688CL; - sha_info->digest[6] = 0x1F83D9ABL; - sha_info->digest[7] = 0x5BE0CD19L; - sha_info->count_lo = 0L; - sha_info->count_hi = 0L; - sha_info->local = 0; - sha_info->digestsize = 32; -} - -static void -sha224_init(SHAobject *sha_info) -{ - sha_info->digest[0] = 0xc1059ed8L; - sha_info->digest[1] = 0x367cd507L; - sha_info->digest[2] = 0x3070dd17L; - sha_info->digest[3] = 0xf70e5939L; - sha_info->digest[4] = 0xffc00b31L; - sha_info->digest[5] = 0x68581511L; - sha_info->digest[6] = 0x64f98fa7L; - sha_info->digest[7] = 0xbefa4fa4L; - sha_info->count_lo = 0L; - sha_info->count_hi = 0L; - sha_info->local = 0; - sha_info->digestsize = 28; -} - - -/* update the SHA digest */ - -static void -sha_update(SHAobject *sha_info, SHA_BYTE *buffer, Py_ssize_t count) -{ - Py_ssize_t i; - SHA_INT32 clo; - - clo = sha_info->count_lo + ((SHA_INT32) count << 3); - if (clo < sha_info->count_lo) { - ++sha_info->count_hi; - } - sha_info->count_lo = clo; - sha_info->count_hi += (SHA_INT32) count >> 29; - if (sha_info->local) { - i = SHA_BLOCKSIZE - sha_info->local; - if (i > count) { - i = count; - } - memcpy(((SHA_BYTE *) sha_info->data) + sha_info->local, buffer, i); - count -= i; - buffer += i; - sha_info->local += (int)i; - if (sha_info->local == SHA_BLOCKSIZE) { - sha_transform(sha_info); - } - else { - return; - } - } - while (count >= SHA_BLOCKSIZE) { - memcpy(sha_info->data, buffer, SHA_BLOCKSIZE); - buffer += SHA_BLOCKSIZE; - count -= SHA_BLOCKSIZE; - sha_transform(sha_info); - } - memcpy(sha_info->data, buffer, count); - sha_info->local = (int)count; -} - -/* finish computing the SHA digest */ - -static void -sha_final(unsigned char digest[SHA_DIGESTSIZE], SHAobject *sha_info) -{ - int count; - SHA_INT32 lo_bit_count, hi_bit_count; - - lo_bit_count = sha_info->count_lo; - hi_bit_count = sha_info->count_hi; - count = (int) ((lo_bit_count >> 3) & 0x3f); - ((SHA_BYTE *) sha_info->data)[count++] = 0x80; - if (count > SHA_BLOCKSIZE - 8) { - memset(((SHA_BYTE *) sha_info->data) + count, 0, - SHA_BLOCKSIZE - count); - sha_transform(sha_info); - memset((SHA_BYTE *) sha_info->data, 0, SHA_BLOCKSIZE - 8); - } - else { - memset(((SHA_BYTE *) sha_info->data) + count, 0, - SHA_BLOCKSIZE - 8 - count); - } - - /* GJS: note that we add the hi/lo in big-endian. sha_transform will - swap these values into host-order. */ - sha_info->data[56] = (hi_bit_count >> 24) & 0xff; - sha_info->data[57] = (hi_bit_count >> 16) & 0xff; - sha_info->data[58] = (hi_bit_count >> 8) & 0xff; - sha_info->data[59] = (hi_bit_count >> 0) & 0xff; - sha_info->data[60] = (lo_bit_count >> 24) & 0xff; - sha_info->data[61] = (lo_bit_count >> 16) & 0xff; - sha_info->data[62] = (lo_bit_count >> 8) & 0xff; - sha_info->data[63] = (lo_bit_count >> 0) & 0xff; - sha_transform(sha_info); - digest[ 0] = (unsigned char) ((sha_info->digest[0] >> 24) & 0xff); - digest[ 1] = (unsigned char) ((sha_info->digest[0] >> 16) & 0xff); - digest[ 2] = (unsigned char) ((sha_info->digest[0] >> 8) & 0xff); - digest[ 3] = (unsigned char) ((sha_info->digest[0] ) & 0xff); - digest[ 4] = (unsigned char) ((sha_info->digest[1] >> 24) & 0xff); - digest[ 5] = (unsigned char) ((sha_info->digest[1] >> 16) & 0xff); - digest[ 6] = (unsigned char) ((sha_info->digest[1] >> 8) & 0xff); - digest[ 7] = (unsigned char) ((sha_info->digest[1] ) & 0xff); - digest[ 8] = (unsigned char) ((sha_info->digest[2] >> 24) & 0xff); - digest[ 9] = (unsigned char) ((sha_info->digest[2] >> 16) & 0xff); - digest[10] = (unsigned char) ((sha_info->digest[2] >> 8) & 0xff); - digest[11] = (unsigned char) ((sha_info->digest[2] ) & 0xff); - digest[12] = (unsigned char) ((sha_info->digest[3] >> 24) & 0xff); - digest[13] = (unsigned char) ((sha_info->digest[3] >> 16) & 0xff); - digest[14] = (unsigned char) ((sha_info->digest[3] >> 8) & 0xff); - digest[15] = (unsigned char) ((sha_info->digest[3] ) & 0xff); - digest[16] = (unsigned char) ((sha_info->digest[4] >> 24) & 0xff); - digest[17] = (unsigned char) ((sha_info->digest[4] >> 16) & 0xff); - digest[18] = (unsigned char) ((sha_info->digest[4] >> 8) & 0xff); - digest[19] = (unsigned char) ((sha_info->digest[4] ) & 0xff); - digest[20] = (unsigned char) ((sha_info->digest[5] >> 24) & 0xff); - digest[21] = (unsigned char) ((sha_info->digest[5] >> 16) & 0xff); - digest[22] = (unsigned char) ((sha_info->digest[5] >> 8) & 0xff); - digest[23] = (unsigned char) ((sha_info->digest[5] ) & 0xff); - digest[24] = (unsigned char) ((sha_info->digest[6] >> 24) & 0xff); - digest[25] = (unsigned char) ((sha_info->digest[6] >> 16) & 0xff); - digest[26] = (unsigned char) ((sha_info->digest[6] >> 8) & 0xff); - digest[27] = (unsigned char) ((sha_info->digest[6] ) & 0xff); - digest[28] = (unsigned char) ((sha_info->digest[7] >> 24) & 0xff); - digest[29] = (unsigned char) ((sha_info->digest[7] >> 16) & 0xff); - digest[30] = (unsigned char) ((sha_info->digest[7] >> 8) & 0xff); - digest[31] = (unsigned char) ((sha_info->digest[7] ) & 0xff); -} - -/* - * End of copied SHA code. - * - * ------------------------------------------------------------------------ - */ - -static PyTypeObject SHA224type; -static PyTypeObject SHA256type; - - -static SHAobject * -newSHA224object(void) -{ - return (SHAobject *)PyObject_New(SHAobject, &SHA224type); -} - -static SHAobject * -newSHA256object(void) -{ - return (SHAobject *)PyObject_New(SHAobject, &SHA256type); -} - -/* Internal methods for a hash object */ - -static void -SHA_dealloc(PyObject *ptr) -{ - PyObject_Del(ptr); -} - - -/* External methods for a hash object */ - -/*[clinic input] -SHA256Type.copy - -Return a copy of the hash object. +preserve [clinic start generated code]*/ PyDoc_STRVAR(SHA256Type_copy__doc__, @@ -422,30 +20,6 @@ return SHA256Type_copy_impl(self); } -static PyObject * -SHA256Type_copy_impl(SHAobject *self) -/*[clinic end generated code: output=f716c39d3f81c27c input=f58840a618d4f2a7]*/ -{ - SHAobject *newobj; - - if (Py_TYPE(self) == &SHA256type) { - if ( (newobj = newSHA256object())==NULL) - return NULL; - } else { - if ( (newobj = newSHA224object())==NULL) - return NULL; - } - - SHAcopy(self, newobj); - return (PyObject *)newobj; -} - -/*[clinic input] -SHA256Type.digest - -Return the digest value as a string of binary data. -[clinic start generated code]*/ - PyDoc_STRVAR(SHA256Type_digest__doc__, "digest($self, /)\n" "--\n" @@ -464,24 +38,6 @@ return SHA256Type_digest_impl(self); } -static PyObject * -SHA256Type_digest_impl(SHAobject *self) -/*[clinic end generated code: output=72d34723d7bb694c input=1fb752e58954157d]*/ -{ - unsigned char digest[SHA_DIGESTSIZE]; - SHAobject temp; - - SHAcopy(self, &temp); - sha_final(digest, &temp); - return PyBytes_FromStringAndSize((const char *)digest, self->digestsize); -} - -/*[clinic input] -SHA256Type.hexdigest - -Return the digest value as a string of hexadecimal digits. -[clinic start generated code]*/ - PyDoc_STRVAR(SHA256Type_hexdigest__doc__, "hexdigest($self, /)\n" "--\n" @@ -500,49 +56,6 @@ return SHA256Type_hexdigest_impl(self); } -static PyObject * -SHA256Type_hexdigest_impl(SHAobject *self) -/*[clinic end generated code: output=3687aa6183c7d27f input=0cc4c714693010d1]*/ -{ - unsigned char digest[SHA_DIGESTSIZE]; - SHAobject temp; - PyObject *retval; - Py_UCS1 *hex_digest; - int i, j; - - /* Get the raw (binary) digest value */ - SHAcopy(self, &temp); - sha_final(digest, &temp); - - /* Create a new string */ - retval = PyUnicode_New(self->digestsize * 2, 127); - if (!retval) - return NULL; - hex_digest = PyUnicode_1BYTE_DATA(retval); - - /* Make hex version of the digest */ - for(i=j=0; idigestsize; i++) { - unsigned char c; - c = (digest[i] >> 4) & 0xf; - hex_digest[j++] = Py_hexdigits[c]; - c = (digest[i] & 0xf); - hex_digest[j++] = Py_hexdigits[c]; - } -#ifdef Py_DEBUG - assert(_PyUnicode_CheckConsistency(retval, 1)); -#endif - return retval; -} - -/*[clinic input] -SHA256Type.update - - obj: object - / - -Update this hash object's state with the provided string. -[clinic start generated code]*/ - PyDoc_STRVAR(SHA256Type_update__doc__, "update($self, obj, /)\n" "--\n" @@ -552,140 +65,6 @@ #define SHA256TYPE_UPDATE_METHODDEF \ {"update", (PyCFunction)SHA256Type_update, METH_O, SHA256Type_update__doc__}, -static PyObject * -SHA256Type_update(SHAobject *self, PyObject *obj) -/*[clinic end generated code: output=b47f53d7cbeabee4 input=b2d449d5b30f0f5a]*/ -{ - Py_buffer buf; - - GET_BUFFER_VIEW_OR_ERROUT(obj, &buf); - - sha_update(self, buf.buf, buf.len); - - PyBuffer_Release(&buf); - Py_INCREF(Py_None); - return Py_None; -} - -static PyMethodDef SHA_methods[] = { - SHA256TYPE_COPY_METHODDEF - SHA256TYPE_DIGEST_METHODDEF - SHA256TYPE_HEXDIGEST_METHODDEF - SHA256TYPE_UPDATE_METHODDEF - {NULL, NULL} /* sentinel */ -}; - -static PyObject * -SHA256_get_block_size(PyObject *self, void *closure) -{ - return PyLong_FromLong(SHA_BLOCKSIZE); -} - -static PyObject * -SHA256_get_name(PyObject *self, void *closure) -{ - if (((SHAobject *)self)->digestsize == 32) - return PyUnicode_FromStringAndSize("sha256", 6); - else - return PyUnicode_FromStringAndSize("sha224", 6); -} - -static PyGetSetDef SHA_getseters[] = { - {"block_size", - (getter)SHA256_get_block_size, NULL, - NULL, - NULL}, - {"name", - (getter)SHA256_get_name, NULL, - NULL, - NULL}, - {NULL} /* Sentinel */ -}; - -static PyMemberDef SHA_members[] = { - {"digest_size", T_INT, offsetof(SHAobject, digestsize), READONLY, NULL}, - {NULL} /* Sentinel */ -}; - -static PyTypeObject SHA224type = { - PyVarObject_HEAD_INIT(NULL, 0) - "_sha256.sha224", /*tp_name*/ - sizeof(SHAobject), /*tp_size*/ - 0, /*tp_itemsize*/ - /* methods */ - SHA_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_reserved*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash*/ - 0, /*tp_call*/ - 0, /*tp_str*/ - 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*/ - SHA_methods, /* tp_methods */ - SHA_members, /* tp_members */ - SHA_getseters, /* tp_getset */ -}; - -static PyTypeObject SHA256type = { - PyVarObject_HEAD_INIT(NULL, 0) - "_sha256.sha256", /*tp_name*/ - sizeof(SHAobject), /*tp_size*/ - 0, /*tp_itemsize*/ - /* methods */ - SHA_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_reserved*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash*/ - 0, /*tp_call*/ - 0, /*tp_str*/ - 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*/ - SHA_methods, /* tp_methods */ - SHA_members, /* tp_members */ - SHA_getseters, /* tp_getset */ -}; - - -/* The single module-level function: new() */ - -/*[clinic input] -_sha256.sha256 - - string: object(c_default="NULL") = b'' - -Return a new SHA-256 hash object; optionally initialized with a string. -[clinic start generated code]*/ - PyDoc_STRVAR(_sha256_sha256__doc__, "sha256($module, /, string=b\'\')\n" "--\n" @@ -715,46 +94,6 @@ return return_value; } -static PyObject * -_sha256_sha256_impl(PyModuleDef *module, PyObject *string) -/*[clinic end generated code: output=4b1263d1e2fcdb98 input=09cce3fb855056b2]*/ -{ - SHAobject *new; - Py_buffer buf; - - if (string) - GET_BUFFER_VIEW_OR_ERROUT(string, &buf); - - if ((new = newSHA256object()) == NULL) { - if (string) - PyBuffer_Release(&buf); - return NULL; - } - - sha_init(new); - - if (PyErr_Occurred()) { - Py_DECREF(new); - if (string) - PyBuffer_Release(&buf); - return NULL; - } - if (string) { - sha_update(new, buf.buf, buf.len); - PyBuffer_Release(&buf); - } - - return (PyObject *)new; -} - -/*[clinic input] -_sha256.sha224 - - string: object(c_default="NULL") = b'' - -Return a new SHA-224 hash object; optionally initialized with a string. -[clinic start generated code]*/ - PyDoc_STRVAR(_sha256_sha224__doc__, "sha224($module, /, string=b\'\')\n" "--\n" @@ -783,86 +122,4 @@ exit: return return_value; } - -static PyObject * -_sha256_sha224_impl(PyModuleDef *module, PyObject *string) -/*[clinic end generated code: output=4dde0eb1cdaebc06 input=27a04ba24c353a73]*/ -{ - SHAobject *new; - Py_buffer buf; - - if (string) - GET_BUFFER_VIEW_OR_ERROUT(string, &buf); - - if ((new = newSHA224object()) == NULL) { - if (string) - PyBuffer_Release(&buf); - return NULL; - } - - sha224_init(new); - - if (PyErr_Occurred()) { - Py_DECREF(new); - if (string) - PyBuffer_Release(&buf); - return NULL; - } - if (string) { - sha_update(new, buf.buf, buf.len); - PyBuffer_Release(&buf); - } - - return (PyObject *)new; -} - - -/* List of functions exported by this module */ - -static struct PyMethodDef SHA_functions[] = { - _SHA256_SHA256_METHODDEF - _SHA256_SHA224_METHODDEF - {NULL, NULL} /* Sentinel */ -}; - - -/* Initialize this module. */ - -#define insint(n,v) { PyModule_AddIntConstant(m,n,v); } - - -static struct PyModuleDef _sha256module = { - PyModuleDef_HEAD_INIT, - "_sha256", - NULL, - -1, - SHA_functions, - NULL, - NULL, - NULL, - NULL -}; - -PyMODINIT_FUNC -PyInit__sha256(void) -{ - PyObject *m; - - Py_TYPE(&SHA224type) = &PyType_Type; - if (PyType_Ready(&SHA224type) < 0) - return NULL; - Py_TYPE(&SHA256type) = &PyType_Type; - if (PyType_Ready(&SHA256type) < 0) - return NULL; - - m = PyModule_Create(&_sha256module); - if (m == NULL) - return NULL; - - Py_INCREF((PyObject *)&SHA224type); - PyModule_AddObject(m, "SHA224Type", (PyObject *)&SHA224type); - Py_INCREF((PyObject *)&SHA256type); - PyModule_AddObject(m, "SHA256Type", (PyObject *)&SHA256type); - return m; - -} +/*[clinic end generated code: output=8a0520371b097358 input=a9049054013a1b77]*/ diff --git a/Modules/sha512module.c b/Modules/clinic/sha512module.c.h copy from Modules/sha512module.c copy to Modules/clinic/sha512module.c.h --- a/Modules/sha512module.c +++ b/Modules/clinic/sha512module.c.h @@ -1,475 +1,8 @@ -/* SHA512 module */ +/*[clinic input] +preserve +[clinic start generated code]*/ -/* This module provides an interface to NIST's SHA-512 and SHA-384 Algorithms */ - -/* See below for information about the original code this module was - based upon. Additional work performed by: - - Andrew Kuchling (amk at amk.ca) - Greg Stein (gstein at lyra.org) - Trevor Perrin (trevp at trevp.net) - - Copyright (C) 2005-2007 Gregory P. Smith (greg at krypto.org) - Licensed to PSF under a Contributor Agreement. - -*/ - -/* SHA objects */ - -#include "Python.h" -#include "structmember.h" -#include "hashlib.h" - -/*[clinic input] -module _sha512 -class SHA512Type "SHAobject *" "&PyType_Type" -[clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=81a3ccde92bcfe8d]*/ - -#ifdef PY_LONG_LONG /* If no PY_LONG_LONG, don't compile anything! */ - -/* Some useful types */ - -typedef unsigned char SHA_BYTE; - -#if SIZEOF_INT == 4 -typedef unsigned int SHA_INT32; /* 32-bit integer */ -typedef unsigned PY_LONG_LONG SHA_INT64; /* 64-bit integer */ -#else -/* not defined. compilation will die. */ -#endif - -/* The SHA block size and message digest sizes, in bytes */ - -#define SHA_BLOCKSIZE 128 -#define SHA_DIGESTSIZE 64 - -/* The structure for storing SHA info */ - -typedef struct { - PyObject_HEAD - SHA_INT64 digest[8]; /* Message digest */ - SHA_INT32 count_lo, count_hi; /* 64-bit bit count */ - SHA_BYTE data[SHA_BLOCKSIZE]; /* SHA data buffer */ - int local; /* unprocessed amount in data */ - int digestsize; -} SHAobject; - -/* When run on a little-endian CPU we need to perform byte reversal on an - array of longwords. */ - -#if PY_LITTLE_ENDIAN -static void longReverse(SHA_INT64 *buffer, int byteCount) -{ - SHA_INT64 value; - - byteCount /= sizeof(*buffer); - while (byteCount--) { - value = *buffer; - - ((unsigned char*)buffer)[0] = (unsigned char)(value >> 56) & 0xff; - ((unsigned char*)buffer)[1] = (unsigned char)(value >> 48) & 0xff; - ((unsigned char*)buffer)[2] = (unsigned char)(value >> 40) & 0xff; - ((unsigned char*)buffer)[3] = (unsigned char)(value >> 32) & 0xff; - ((unsigned char*)buffer)[4] = (unsigned char)(value >> 24) & 0xff; - ((unsigned char*)buffer)[5] = (unsigned char)(value >> 16) & 0xff; - ((unsigned char*)buffer)[6] = (unsigned char)(value >> 8) & 0xff; - ((unsigned char*)buffer)[7] = (unsigned char)(value ) & 0xff; - - buffer++; - } -} -#endif - -static void SHAcopy(SHAobject *src, SHAobject *dest) -{ - dest->local = src->local; - dest->digestsize = src->digestsize; - dest->count_lo = src->count_lo; - dest->count_hi = src->count_hi; - memcpy(dest->digest, src->digest, sizeof(src->digest)); - memcpy(dest->data, src->data, sizeof(src->data)); -} - - -/* ------------------------------------------------------------------------ - * - * This code for the SHA-512 algorithm was noted as public domain. The - * original headers are pasted below. - * - * Several changes have been made to make it more compatible with the - * Python environment and desired interface. - * - */ - -/* LibTomCrypt, modular cryptographic library -- Tom St Denis - * - * LibTomCrypt is a library that provides various cryptographic - * algorithms in a highly modular and flexible manner. - * - * The library is free for all purposes without any express - * gurantee it works. - * - * Tom St Denis, tomstdenis at iahu.ca, http://libtom.org - */ - - -/* SHA512 by Tom St Denis */ - -/* Various logical functions */ -#define ROR64(x, y) \ - ( ((((x) & Py_ULL(0xFFFFFFFFFFFFFFFF))>>((unsigned PY_LONG_LONG)(y) & 63)) | \ - ((x)<<((unsigned PY_LONG_LONG)(64-((y) & 63))))) & Py_ULL(0xFFFFFFFFFFFFFFFF)) -#define Ch(x,y,z) (z ^ (x & (y ^ z))) -#define Maj(x,y,z) (((x | y) & z) | (x & y)) -#define S(x, n) ROR64((x),(n)) -#define R(x, n) (((x) & Py_ULL(0xFFFFFFFFFFFFFFFF)) >> ((unsigned PY_LONG_LONG)n)) -#define Sigma0(x) (S(x, 28) ^ S(x, 34) ^ S(x, 39)) -#define Sigma1(x) (S(x, 14) ^ S(x, 18) ^ S(x, 41)) -#define Gamma0(x) (S(x, 1) ^ S(x, 8) ^ R(x, 7)) -#define Gamma1(x) (S(x, 19) ^ S(x, 61) ^ R(x, 6)) - - -static void -sha512_transform(SHAobject *sha_info) -{ - int i; - SHA_INT64 S[8], W[80], t0, t1; - - memcpy(W, sha_info->data, sizeof(sha_info->data)); -#if PY_LITTLE_ENDIAN - longReverse(W, (int)sizeof(sha_info->data)); -#endif - - for (i = 16; i < 80; ++i) { - W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) + W[i - 16]; - } - for (i = 0; i < 8; ++i) { - S[i] = sha_info->digest[i]; - } - - /* Compress */ -#define RND(a,b,c,d,e,f,g,h,i,ki) \ - t0 = h + Sigma1(e) + Ch(e, f, g) + ki + W[i]; \ - t1 = Sigma0(a) + Maj(a, b, c); \ - d += t0; \ - h = t0 + t1; - - RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],0,Py_ULL(0x428a2f98d728ae22)); - RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],1,Py_ULL(0x7137449123ef65cd)); - RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],2,Py_ULL(0xb5c0fbcfec4d3b2f)); - RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],3,Py_ULL(0xe9b5dba58189dbbc)); - RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],4,Py_ULL(0x3956c25bf348b538)); - RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],5,Py_ULL(0x59f111f1b605d019)); - RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],6,Py_ULL(0x923f82a4af194f9b)); - RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],7,Py_ULL(0xab1c5ed5da6d8118)); - RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],8,Py_ULL(0xd807aa98a3030242)); - RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],9,Py_ULL(0x12835b0145706fbe)); - RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],10,Py_ULL(0x243185be4ee4b28c)); - RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],11,Py_ULL(0x550c7dc3d5ffb4e2)); - RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],12,Py_ULL(0x72be5d74f27b896f)); - RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],13,Py_ULL(0x80deb1fe3b1696b1)); - RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],14,Py_ULL(0x9bdc06a725c71235)); - RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],15,Py_ULL(0xc19bf174cf692694)); - RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],16,Py_ULL(0xe49b69c19ef14ad2)); - RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],17,Py_ULL(0xefbe4786384f25e3)); - RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],18,Py_ULL(0x0fc19dc68b8cd5b5)); - RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],19,Py_ULL(0x240ca1cc77ac9c65)); - RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],20,Py_ULL(0x2de92c6f592b0275)); - RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],21,Py_ULL(0x4a7484aa6ea6e483)); - RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],22,Py_ULL(0x5cb0a9dcbd41fbd4)); - RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],23,Py_ULL(0x76f988da831153b5)); - RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],24,Py_ULL(0x983e5152ee66dfab)); - RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],25,Py_ULL(0xa831c66d2db43210)); - RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],26,Py_ULL(0xb00327c898fb213f)); - RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],27,Py_ULL(0xbf597fc7beef0ee4)); - RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],28,Py_ULL(0xc6e00bf33da88fc2)); - RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],29,Py_ULL(0xd5a79147930aa725)); - RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],30,Py_ULL(0x06ca6351e003826f)); - RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],31,Py_ULL(0x142929670a0e6e70)); - RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],32,Py_ULL(0x27b70a8546d22ffc)); - RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],33,Py_ULL(0x2e1b21385c26c926)); - RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],34,Py_ULL(0x4d2c6dfc5ac42aed)); - RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],35,Py_ULL(0x53380d139d95b3df)); - RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],36,Py_ULL(0x650a73548baf63de)); - RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],37,Py_ULL(0x766a0abb3c77b2a8)); - RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],38,Py_ULL(0x81c2c92e47edaee6)); - RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],39,Py_ULL(0x92722c851482353b)); - RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],40,Py_ULL(0xa2bfe8a14cf10364)); - RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],41,Py_ULL(0xa81a664bbc423001)); - RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],42,Py_ULL(0xc24b8b70d0f89791)); - RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],43,Py_ULL(0xc76c51a30654be30)); - RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],44,Py_ULL(0xd192e819d6ef5218)); - RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],45,Py_ULL(0xd69906245565a910)); - RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],46,Py_ULL(0xf40e35855771202a)); - RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],47,Py_ULL(0x106aa07032bbd1b8)); - RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],48,Py_ULL(0x19a4c116b8d2d0c8)); - RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],49,Py_ULL(0x1e376c085141ab53)); - RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],50,Py_ULL(0x2748774cdf8eeb99)); - RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],51,Py_ULL(0x34b0bcb5e19b48a8)); - RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],52,Py_ULL(0x391c0cb3c5c95a63)); - RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],53,Py_ULL(0x4ed8aa4ae3418acb)); - RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],54,Py_ULL(0x5b9cca4f7763e373)); - RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],55,Py_ULL(0x682e6ff3d6b2b8a3)); - RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],56,Py_ULL(0x748f82ee5defb2fc)); - RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],57,Py_ULL(0x78a5636f43172f60)); - RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],58,Py_ULL(0x84c87814a1f0ab72)); - RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],59,Py_ULL(0x8cc702081a6439ec)); - RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],60,Py_ULL(0x90befffa23631e28)); - RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],61,Py_ULL(0xa4506cebde82bde9)); - RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],62,Py_ULL(0xbef9a3f7b2c67915)); - RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],63,Py_ULL(0xc67178f2e372532b)); - RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],64,Py_ULL(0xca273eceea26619c)); - RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],65,Py_ULL(0xd186b8c721c0c207)); - RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],66,Py_ULL(0xeada7dd6cde0eb1e)); - RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],67,Py_ULL(0xf57d4f7fee6ed178)); - RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],68,Py_ULL(0x06f067aa72176fba)); - RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],69,Py_ULL(0x0a637dc5a2c898a6)); - RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],70,Py_ULL(0x113f9804bef90dae)); - RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],71,Py_ULL(0x1b710b35131c471b)); - RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],72,Py_ULL(0x28db77f523047d84)); - RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],73,Py_ULL(0x32caab7b40c72493)); - RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],74,Py_ULL(0x3c9ebe0a15c9bebc)); - RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],75,Py_ULL(0x431d67c49c100d4c)); - RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],76,Py_ULL(0x4cc5d4becb3e42b6)); - RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],77,Py_ULL(0x597f299cfc657e2a)); - RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],78,Py_ULL(0x5fcb6fab3ad6faec)); - RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],79,Py_ULL(0x6c44198c4a475817)); - -#undef RND - - /* feedback */ - for (i = 0; i < 8; i++) { - sha_info->digest[i] = sha_info->digest[i] + S[i]; - } - -} - - - -/* initialize the SHA digest */ - -static void -sha512_init(SHAobject *sha_info) -{ - sha_info->digest[0] = Py_ULL(0x6a09e667f3bcc908); - sha_info->digest[1] = Py_ULL(0xbb67ae8584caa73b); - sha_info->digest[2] = Py_ULL(0x3c6ef372fe94f82b); - sha_info->digest[3] = Py_ULL(0xa54ff53a5f1d36f1); - sha_info->digest[4] = Py_ULL(0x510e527fade682d1); - sha_info->digest[5] = Py_ULL(0x9b05688c2b3e6c1f); - sha_info->digest[6] = Py_ULL(0x1f83d9abfb41bd6b); - sha_info->digest[7] = Py_ULL(0x5be0cd19137e2179); - sha_info->count_lo = 0L; - sha_info->count_hi = 0L; - sha_info->local = 0; - sha_info->digestsize = 64; -} - -static void -sha384_init(SHAobject *sha_info) -{ - sha_info->digest[0] = Py_ULL(0xcbbb9d5dc1059ed8); - sha_info->digest[1] = Py_ULL(0x629a292a367cd507); - sha_info->digest[2] = Py_ULL(0x9159015a3070dd17); - sha_info->digest[3] = Py_ULL(0x152fecd8f70e5939); - sha_info->digest[4] = Py_ULL(0x67332667ffc00b31); - sha_info->digest[5] = Py_ULL(0x8eb44a8768581511); - sha_info->digest[6] = Py_ULL(0xdb0c2e0d64f98fa7); - sha_info->digest[7] = Py_ULL(0x47b5481dbefa4fa4); - sha_info->count_lo = 0L; - sha_info->count_hi = 0L; - sha_info->local = 0; - sha_info->digestsize = 48; -} - - -/* update the SHA digest */ - -static void -sha512_update(SHAobject *sha_info, SHA_BYTE *buffer, Py_ssize_t count) -{ - Py_ssize_t i; - SHA_INT32 clo; - - clo = sha_info->count_lo + ((SHA_INT32) count << 3); - if (clo < sha_info->count_lo) { - ++sha_info->count_hi; - } - sha_info->count_lo = clo; - sha_info->count_hi += (SHA_INT32) count >> 29; - if (sha_info->local) { - i = SHA_BLOCKSIZE - sha_info->local; - if (i > count) { - i = count; - } - memcpy(((SHA_BYTE *) sha_info->data) + sha_info->local, buffer, i); - count -= i; - buffer += i; - sha_info->local += (int)i; - if (sha_info->local == SHA_BLOCKSIZE) { - sha512_transform(sha_info); - } - else { - return; - } - } - while (count >= SHA_BLOCKSIZE) { - memcpy(sha_info->data, buffer, SHA_BLOCKSIZE); - buffer += SHA_BLOCKSIZE; - count -= SHA_BLOCKSIZE; - sha512_transform(sha_info); - } - memcpy(sha_info->data, buffer, count); - sha_info->local = (int)count; -} - -/* finish computing the SHA digest */ - -static void -sha512_final(unsigned char digest[SHA_DIGESTSIZE], SHAobject *sha_info) -{ - int count; - SHA_INT32 lo_bit_count, hi_bit_count; - - lo_bit_count = sha_info->count_lo; - hi_bit_count = sha_info->count_hi; - count = (int) ((lo_bit_count >> 3) & 0x7f); - ((SHA_BYTE *) sha_info->data)[count++] = 0x80; - if (count > SHA_BLOCKSIZE - 16) { - memset(((SHA_BYTE *) sha_info->data) + count, 0, - SHA_BLOCKSIZE - count); - sha512_transform(sha_info); - memset((SHA_BYTE *) sha_info->data, 0, SHA_BLOCKSIZE - 16); - } - else { - memset(((SHA_BYTE *) sha_info->data) + count, 0, - SHA_BLOCKSIZE - 16 - count); - } - - /* GJS: note that we add the hi/lo in big-endian. sha512_transform will - swap these values into host-order. */ - sha_info->data[112] = 0; - sha_info->data[113] = 0; - sha_info->data[114] = 0; - sha_info->data[115] = 0; - sha_info->data[116] = 0; - sha_info->data[117] = 0; - sha_info->data[118] = 0; - sha_info->data[119] = 0; - sha_info->data[120] = (hi_bit_count >> 24) & 0xff; - sha_info->data[121] = (hi_bit_count >> 16) & 0xff; - sha_info->data[122] = (hi_bit_count >> 8) & 0xff; - sha_info->data[123] = (hi_bit_count >> 0) & 0xff; - sha_info->data[124] = (lo_bit_count >> 24) & 0xff; - sha_info->data[125] = (lo_bit_count >> 16) & 0xff; - sha_info->data[126] = (lo_bit_count >> 8) & 0xff; - sha_info->data[127] = (lo_bit_count >> 0) & 0xff; - sha512_transform(sha_info); - digest[ 0] = (unsigned char) ((sha_info->digest[0] >> 56) & 0xff); - digest[ 1] = (unsigned char) ((sha_info->digest[0] >> 48) & 0xff); - digest[ 2] = (unsigned char) ((sha_info->digest[0] >> 40) & 0xff); - digest[ 3] = (unsigned char) ((sha_info->digest[0] >> 32) & 0xff); - digest[ 4] = (unsigned char) ((sha_info->digest[0] >> 24) & 0xff); - digest[ 5] = (unsigned char) ((sha_info->digest[0] >> 16) & 0xff); - digest[ 6] = (unsigned char) ((sha_info->digest[0] >> 8) & 0xff); - digest[ 7] = (unsigned char) ((sha_info->digest[0] ) & 0xff); - digest[ 8] = (unsigned char) ((sha_info->digest[1] >> 56) & 0xff); - digest[ 9] = (unsigned char) ((sha_info->digest[1] >> 48) & 0xff); - digest[10] = (unsigned char) ((sha_info->digest[1] >> 40) & 0xff); - digest[11] = (unsigned char) ((sha_info->digest[1] >> 32) & 0xff); - digest[12] = (unsigned char) ((sha_info->digest[1] >> 24) & 0xff); - digest[13] = (unsigned char) ((sha_info->digest[1] >> 16) & 0xff); - digest[14] = (unsigned char) ((sha_info->digest[1] >> 8) & 0xff); - digest[15] = (unsigned char) ((sha_info->digest[1] ) & 0xff); - digest[16] = (unsigned char) ((sha_info->digest[2] >> 56) & 0xff); - digest[17] = (unsigned char) ((sha_info->digest[2] >> 48) & 0xff); - digest[18] = (unsigned char) ((sha_info->digest[2] >> 40) & 0xff); - digest[19] = (unsigned char) ((sha_info->digest[2] >> 32) & 0xff); - digest[20] = (unsigned char) ((sha_info->digest[2] >> 24) & 0xff); - digest[21] = (unsigned char) ((sha_info->digest[2] >> 16) & 0xff); - digest[22] = (unsigned char) ((sha_info->digest[2] >> 8) & 0xff); - digest[23] = (unsigned char) ((sha_info->digest[2] ) & 0xff); - digest[24] = (unsigned char) ((sha_info->digest[3] >> 56) & 0xff); - digest[25] = (unsigned char) ((sha_info->digest[3] >> 48) & 0xff); - digest[26] = (unsigned char) ((sha_info->digest[3] >> 40) & 0xff); - digest[27] = (unsigned char) ((sha_info->digest[3] >> 32) & 0xff); - digest[28] = (unsigned char) ((sha_info->digest[3] >> 24) & 0xff); - digest[29] = (unsigned char) ((sha_info->digest[3] >> 16) & 0xff); - digest[30] = (unsigned char) ((sha_info->digest[3] >> 8) & 0xff); - digest[31] = (unsigned char) ((sha_info->digest[3] ) & 0xff); - digest[32] = (unsigned char) ((sha_info->digest[4] >> 56) & 0xff); - digest[33] = (unsigned char) ((sha_info->digest[4] >> 48) & 0xff); - digest[34] = (unsigned char) ((sha_info->digest[4] >> 40) & 0xff); - digest[35] = (unsigned char) ((sha_info->digest[4] >> 32) & 0xff); - digest[36] = (unsigned char) ((sha_info->digest[4] >> 24) & 0xff); - digest[37] = (unsigned char) ((sha_info->digest[4] >> 16) & 0xff); - digest[38] = (unsigned char) ((sha_info->digest[4] >> 8) & 0xff); - digest[39] = (unsigned char) ((sha_info->digest[4] ) & 0xff); - digest[40] = (unsigned char) ((sha_info->digest[5] >> 56) & 0xff); - digest[41] = (unsigned char) ((sha_info->digest[5] >> 48) & 0xff); - digest[42] = (unsigned char) ((sha_info->digest[5] >> 40) & 0xff); - digest[43] = (unsigned char) ((sha_info->digest[5] >> 32) & 0xff); - digest[44] = (unsigned char) ((sha_info->digest[5] >> 24) & 0xff); - digest[45] = (unsigned char) ((sha_info->digest[5] >> 16) & 0xff); - digest[46] = (unsigned char) ((sha_info->digest[5] >> 8) & 0xff); - digest[47] = (unsigned char) ((sha_info->digest[5] ) & 0xff); - digest[48] = (unsigned char) ((sha_info->digest[6] >> 56) & 0xff); - digest[49] = (unsigned char) ((sha_info->digest[6] >> 48) & 0xff); - digest[50] = (unsigned char) ((sha_info->digest[6] >> 40) & 0xff); - digest[51] = (unsigned char) ((sha_info->digest[6] >> 32) & 0xff); - digest[52] = (unsigned char) ((sha_info->digest[6] >> 24) & 0xff); - digest[53] = (unsigned char) ((sha_info->digest[6] >> 16) & 0xff); - digest[54] = (unsigned char) ((sha_info->digest[6] >> 8) & 0xff); - digest[55] = (unsigned char) ((sha_info->digest[6] ) & 0xff); - digest[56] = (unsigned char) ((sha_info->digest[7] >> 56) & 0xff); - digest[57] = (unsigned char) ((sha_info->digest[7] >> 48) & 0xff); - digest[58] = (unsigned char) ((sha_info->digest[7] >> 40) & 0xff); - digest[59] = (unsigned char) ((sha_info->digest[7] >> 32) & 0xff); - digest[60] = (unsigned char) ((sha_info->digest[7] >> 24) & 0xff); - digest[61] = (unsigned char) ((sha_info->digest[7] >> 16) & 0xff); - digest[62] = (unsigned char) ((sha_info->digest[7] >> 8) & 0xff); - digest[63] = (unsigned char) ((sha_info->digest[7] ) & 0xff); -} - -/* - * End of copied SHA code. - * - * ------------------------------------------------------------------------ - */ - -static PyTypeObject SHA384type; -static PyTypeObject SHA512type; - - -static SHAobject * -newSHA384object(void) -{ - return (SHAobject *)PyObject_New(SHAobject, &SHA384type); -} - -static SHAobject * -newSHA512object(void) -{ - return (SHAobject *)PyObject_New(SHAobject, &SHA512type); -} - -/* Internal methods for a hash object */ - -static void -SHA512_dealloc(PyObject *ptr) -{ - PyObject_Del(ptr); -} - - -/* External methods for a hash object */ - -/*[clinic input] -SHA512Type.copy - -Return a copy of the hash object. -[clinic start generated code]*/ +#if defined(PY_LONG_LONG) PyDoc_STRVAR(SHA512Type_copy__doc__, "copy($self, /)\n" @@ -489,29 +22,9 @@ return SHA512Type_copy_impl(self); } -static PyObject * -SHA512Type_copy_impl(SHAobject *self) -/*[clinic end generated code: output=14f8e6ce9c61ece0 input=9f5f31e6c457776a]*/ -{ - SHAobject *newobj; +#endif /* defined(PY_LONG_LONG) */ - if (((PyObject*)self)->ob_type == &SHA512type) { - if ( (newobj = newSHA512object())==NULL) - return NULL; - } else { - if ( (newobj = newSHA384object())==NULL) - return NULL; - } - - SHAcopy(self, newobj); - return (PyObject *)newobj; -} - -/*[clinic input] -SHA512Type.digest - -Return the digest value as a string of binary data. -[clinic start generated code]*/ +#if defined(PY_LONG_LONG) PyDoc_STRVAR(SHA512Type_digest__doc__, "digest($self, /)\n" @@ -531,23 +44,9 @@ return SHA512Type_digest_impl(self); } -static PyObject * -SHA512Type_digest_impl(SHAobject *self) -/*[clinic end generated code: output=be8de024b232977e input=60c2cede9e023018]*/ -{ - unsigned char digest[SHA_DIGESTSIZE]; - SHAobject temp; +#endif /* defined(PY_LONG_LONG) */ - SHAcopy(self, &temp); - sha512_final(digest, &temp); - return PyBytes_FromStringAndSize((const char *)digest, self->digestsize); -} - -/*[clinic input] -SHA512Type.hexdigest - -Return the digest value as a string of hexadecimal digits. -[clinic start generated code]*/ +#if defined(PY_LONG_LONG) PyDoc_STRVAR(SHA512Type_hexdigest__doc__, "hexdigest($self, /)\n" @@ -567,48 +66,9 @@ return SHA512Type_hexdigest_impl(self); } -static PyObject * -SHA512Type_hexdigest_impl(SHAobject *self) -/*[clinic end generated code: output=28a4ab2f9a1781b8 input=498b877b25cbe0a2]*/ -{ - unsigned char digest[SHA_DIGESTSIZE]; - SHAobject temp; - PyObject *retval; - Py_UCS1 *hex_digest; - int i, j; +#endif /* defined(PY_LONG_LONG) */ - /* Get the raw (binary) digest value */ - SHAcopy(self, &temp); - sha512_final(digest, &temp); - - /* Create a new string */ - retval = PyUnicode_New(self->digestsize * 2, 127); - if (!retval) - return NULL; - hex_digest = PyUnicode_1BYTE_DATA(retval); - - /* Make hex version of the digest */ - for (i=j=0; idigestsize; i++) { - unsigned char c; - c = (digest[i] >> 4) & 0xf; - hex_digest[j++] = Py_hexdigits[c]; - c = (digest[i] & 0xf); - hex_digest[j++] = Py_hexdigits[c]; - } -#ifdef Py_DEBUG - assert(_PyUnicode_CheckConsistency(retval, 1)); -#endif - return retval; -} - -/*[clinic input] -SHA512Type.update - - obj: object - / - -Update this hash object's state with the provided string. -[clinic start generated code]*/ +#if defined(PY_LONG_LONG) PyDoc_STRVAR(SHA512Type_update__doc__, "update($self, obj, /)\n" @@ -619,159 +79,9 @@ #define SHA512TYPE_UPDATE_METHODDEF \ {"update", (PyCFunction)SHA512Type_update, METH_O, SHA512Type_update__doc__}, -static PyObject * -SHA512Type_update(SHAobject *self, PyObject *obj) -/*[clinic end generated code: output=6be574cdc3a9c52d input=ded2b46656566283]*/ -{ - Py_buffer buf; +#endif /* defined(PY_LONG_LONG) */ - GET_BUFFER_VIEW_OR_ERROUT(obj, &buf); - - sha512_update(self, buf.buf, buf.len); - - PyBuffer_Release(&buf); - Py_INCREF(Py_None); - return Py_None; -} -/*[clinic input] -dump buffer -[clinic start generated code]*/ - -#ifndef SHA512TYPE_COPY_METHODDEF - #define SHA512TYPE_COPY_METHODDEF -#endif /* !defined(SHA512TYPE_COPY_METHODDEF) */ - -#ifndef SHA512TYPE_DIGEST_METHODDEF - #define SHA512TYPE_DIGEST_METHODDEF -#endif /* !defined(SHA512TYPE_DIGEST_METHODDEF) */ - -#ifndef SHA512TYPE_HEXDIGEST_METHODDEF - #define SHA512TYPE_HEXDIGEST_METHODDEF -#endif /* !defined(SHA512TYPE_HEXDIGEST_METHODDEF) */ - -#ifndef SHA512TYPE_UPDATE_METHODDEF - #define SHA512TYPE_UPDATE_METHODDEF -#endif /* !defined(SHA512TYPE_UPDATE_METHODDEF) */ -/*[clinic end generated code: output=de713947d31130e9 input=524ce2e021e4eba6]*/ - -static PyMethodDef SHA_methods[] = { - SHA512TYPE_COPY_METHODDEF - SHA512TYPE_DIGEST_METHODDEF - SHA512TYPE_HEXDIGEST_METHODDEF - SHA512TYPE_UPDATE_METHODDEF - {NULL, NULL} /* sentinel */ -}; - -static PyObject * -SHA512_get_block_size(PyObject *self, void *closure) -{ - return PyLong_FromLong(SHA_BLOCKSIZE); -} - -static PyObject * -SHA512_get_name(PyObject *self, void *closure) -{ - if (((SHAobject *)self)->digestsize == 64) - return PyUnicode_FromStringAndSize("sha512", 6); - else - return PyUnicode_FromStringAndSize("sha384", 6); -} - -static PyGetSetDef SHA_getseters[] = { - {"block_size", - (getter)SHA512_get_block_size, NULL, - NULL, - NULL}, - {"name", - (getter)SHA512_get_name, NULL, - NULL, - NULL}, - {NULL} /* Sentinel */ -}; - -static PyMemberDef SHA_members[] = { - {"digest_size", T_INT, offsetof(SHAobject, digestsize), READONLY, NULL}, - {NULL} /* Sentinel */ -}; - -static PyTypeObject SHA384type = { - PyVarObject_HEAD_INIT(NULL, 0) - "_sha512.sha384", /*tp_name*/ - sizeof(SHAobject), /*tp_size*/ - 0, /*tp_itemsize*/ - /* methods */ - SHA512_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_reserved*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash*/ - 0, /*tp_call*/ - 0, /*tp_str*/ - 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*/ - SHA_methods, /* tp_methods */ - SHA_members, /* tp_members */ - SHA_getseters, /* tp_getset */ -}; - -static PyTypeObject SHA512type = { - PyVarObject_HEAD_INIT(NULL, 0) - "_sha512.sha512", /*tp_name*/ - sizeof(SHAobject), /*tp_size*/ - 0, /*tp_itemsize*/ - /* methods */ - SHA512_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_reserved*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash*/ - 0, /*tp_call*/ - 0, /*tp_str*/ - 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*/ - SHA_methods, /* tp_methods */ - SHA_members, /* tp_members */ - SHA_getseters, /* tp_getset */ -}; - - -/* The single module-level function: new() */ - -/*[clinic input] -_sha512.sha512 - - string: object(c_default="NULL") = b'' - -Return a new SHA-512 hash object; optionally initialized with a string. -[clinic start generated code]*/ +#if defined(PY_LONG_LONG) PyDoc_STRVAR(_sha512_sha512__doc__, "sha512($module, /, string=b\'\')\n" @@ -802,45 +112,9 @@ return return_value; } -static PyObject * -_sha512_sha512_impl(PyModuleDef *module, PyObject *string) -/*[clinic end generated code: output=9e39b11115f36878 input=e69bad9ae9b6a308]*/ -{ - SHAobject *new; - Py_buffer buf; +#endif /* defined(PY_LONG_LONG) */ - if (string) - GET_BUFFER_VIEW_OR_ERROUT(string, &buf); - - if ((new = newSHA512object()) == NULL) { - if (string) - PyBuffer_Release(&buf); - return NULL; - } - - sha512_init(new); - - if (PyErr_Occurred()) { - Py_DECREF(new); - if (string) - PyBuffer_Release(&buf); - return NULL; - } - if (string) { - sha512_update(new, buf.buf, buf.len); - PyBuffer_Release(&buf); - } - - return (PyObject *)new; -} - -/*[clinic input] -_sha512.sha384 - - string: object(c_default="NULL") = b'' - -Return a new SHA-384 hash object; optionally initialized with a string. -[clinic start generated code]*/ +#if defined(PY_LONG_LONG) PyDoc_STRVAR(_sha512_sha384__doc__, "sha384($module, /, string=b\'\')\n" @@ -871,42 +145,23 @@ return return_value; } -static PyObject * -_sha512_sha384_impl(PyModuleDef *module, PyObject *string) -/*[clinic end generated code: output=397c6fba3525b93a input=c9327788d4ea4545]*/ -{ - SHAobject *new; - Py_buffer buf; +#endif /* defined(PY_LONG_LONG) */ - if (string) - GET_BUFFER_VIEW_OR_ERROUT(string, &buf); +#ifndef SHA512TYPE_COPY_METHODDEF + #define SHA512TYPE_COPY_METHODDEF +#endif /* !defined(SHA512TYPE_COPY_METHODDEF) */ - if ((new = newSHA384object()) == NULL) { - if (string) - PyBuffer_Release(&buf); - return NULL; - } +#ifndef SHA512TYPE_DIGEST_METHODDEF + #define SHA512TYPE_DIGEST_METHODDEF +#endif /* !defined(SHA512TYPE_DIGEST_METHODDEF) */ - sha384_init(new); +#ifndef SHA512TYPE_HEXDIGEST_METHODDEF + #define SHA512TYPE_HEXDIGEST_METHODDEF +#endif /* !defined(SHA512TYPE_HEXDIGEST_METHODDEF) */ - if (PyErr_Occurred()) { - Py_DECREF(new); - if (string) - PyBuffer_Release(&buf); - return NULL; - } - if (string) { - sha512_update(new, buf.buf, buf.len); - PyBuffer_Release(&buf); - } - - return (PyObject *)new; -} - - -/*[clinic input] -dump buffer -[clinic start generated code]*/ +#ifndef SHA512TYPE_UPDATE_METHODDEF + #define SHA512TYPE_UPDATE_METHODDEF +#endif /* !defined(SHA512TYPE_UPDATE_METHODDEF) */ #ifndef _SHA512_SHA512_METHODDEF #define _SHA512_SHA512_METHODDEF @@ -915,55 +170,4 @@ #ifndef _SHA512_SHA384_METHODDEF #define _SHA512_SHA384_METHODDEF #endif /* !defined(_SHA512_SHA384_METHODDEF) */ -/*[clinic end generated code: output=69d84aa9445b01d8 input=524ce2e021e4eba6]*/ - -/* List of functions exported by this module */ - -static struct PyMethodDef SHA_functions[] = { - _SHA512_SHA512_METHODDEF - _SHA512_SHA384_METHODDEF - {NULL, NULL} /* Sentinel */ -}; - - -/* Initialize this module. */ - -#define insint(n,v) { PyModule_AddIntConstant(m,n,v); } - - -static struct PyModuleDef _sha512module = { - PyModuleDef_HEAD_INIT, - "_sha512", - NULL, - -1, - SHA_functions, - NULL, - NULL, - NULL, - NULL -}; - -PyMODINIT_FUNC -PyInit__sha512(void) -{ - PyObject *m; - - Py_TYPE(&SHA384type) = &PyType_Type; - if (PyType_Ready(&SHA384type) < 0) - return NULL; - Py_TYPE(&SHA512type) = &PyType_Type; - if (PyType_Ready(&SHA512type) < 0) - return NULL; - - m = PyModule_Create(&_sha512module); - if (m == NULL) - return NULL; - - Py_INCREF((PyObject *)&SHA384type); - PyModule_AddObject(m, "SHA384Type", (PyObject *)&SHA384type); - Py_INCREF((PyObject *)&SHA512type); - PyModule_AddObject(m, "SHA512Type", (PyObject *)&SHA512type); - return m; -} - -#endif +/*[clinic end generated code: output=de7bda19fde49310 input=a9049054013a1b77]*/ diff --git a/Modules/unicodedata.c b/Modules/clinic/unicodedata.c.h copy from Modules/unicodedata.c copy to Modules/clinic/unicodedata.c.h --- a/Modules/unicodedata.c +++ b/Modules/clinic/unicodedata.c.h @@ -1,133 +1,5 @@ -/* ------------------------------------------------------------------------ - - unicodedata -- Provides access to the Unicode database. - - Data was extracted from the UnicodeData.txt file. - The current version number is reported in the unidata_version constant. - - Written by Marc-Andre Lemburg (mal at lemburg.com). - Modified for Python 2.0 by Fredrik Lundh (fredrik at pythonware.com) - Modified by Martin v. L?wis (martin at v.loewis.de) - - Copyright (c) Corporation for National Research Initiatives. - - ------------------------------------------------------------------------ */ - -#define PY_SSIZE_T_CLEAN - -#include "Python.h" -#include "ucnhash.h" -#include "structmember.h" - /*[clinic input] -module unicodedata -class unicodedata.UCD 'PreviousDBVersion *' '&UCD_Type' -[clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=6dac153082d150bc]*/ - -/* character properties */ - -typedef struct { - const unsigned char category; /* index into - _PyUnicode_CategoryNames */ - const unsigned char combining; /* combining class value 0 - 255 */ - const unsigned char bidirectional; /* index into - _PyUnicode_BidirectionalNames */ - const unsigned char mirrored; /* true if mirrored in bidir mode */ - const unsigned char east_asian_width; /* index into - _PyUnicode_EastAsianWidth */ - const unsigned char normalization_quick_check; /* see is_normalized() */ -} _PyUnicode_DatabaseRecord; - -typedef struct change_record { - /* sequence of fields should be the same as in merge_old_version */ - const unsigned char bidir_changed; - const unsigned char category_changed; - const unsigned char decimal_changed; - const unsigned char mirrored_changed; - const double numeric_changed; -} change_record; - -/* data file generated by Tools/unicode/makeunicodedata.py */ -#include "unicodedata_db.h" - -static const _PyUnicode_DatabaseRecord* -_getrecord_ex(Py_UCS4 code) -{ - int index; - if (code >= 0x110000) - index = 0; - else { - index = index1[(code>>SHIFT)]; - index = index2[(index<getrecord)(v)) - -static PyMemberDef DB_members[] = { - {"unidata_version", T_STRING, offsetof(PreviousDBVersion, name), READONLY}, - {NULL} -}; - -/* forward declaration */ -static PyTypeObject UCD_Type; -#define UCD_Check(o) (Py_TYPE(o)==&UCD_Type) - -static PyObject* -new_previous_version(const char*name, const change_record* (*getrecord)(Py_UCS4), - Py_UCS4 (*normalization)(Py_UCS4)) -{ - PreviousDBVersion *self; - self = PyObject_New(PreviousDBVersion, &UCD_Type); - if (self == NULL) - return NULL; - self->name = name; - self->getrecord = getrecord; - self->normalization = normalization; - return (PyObject*)self; -} - - -static Py_UCS4 getuchar(PyUnicodeObject *obj) -{ - if (PyUnicode_READY(obj)) - return (Py_UCS4)-1; - if (PyUnicode_GET_LENGTH(obj) == 1) { - if (PyUnicode_READY(obj)) - return (Py_UCS4)-1; - return PyUnicode_READ_CHAR(obj, 0); - } - PyErr_SetString(PyExc_TypeError, - "need a single Unicode character as parameter"); - return (Py_UCS4)-1; -} - -/* --- Module API --------------------------------------------------------- */ - -/*[clinic input] - -unicodedata.UCD.decimal - - unichr: object(type='PyUnicodeObject *', subclass_of='&PyUnicode_Type') - default: object=NULL - / - -Converts a Unicode character into its equivalent decimal value. - -Returns the decimal value assigned to the Unicode character unichr -as integer. If no such value is defined, default is returned, or, if -not given, ValueError is raised. +preserve [clinic start generated code]*/ PyDoc_STRVAR(unicodedata_UCD_decimal__doc__, @@ -162,1270 +34,4 @@ exit: return return_value; } - -static PyObject * -unicodedata_UCD_decimal_impl(PreviousDBVersion *self, PyUnicodeObject *unichr, PyObject *default_value) -/*[clinic end generated code: output=8689669896d293df input=c25c9d2b4de076b1]*/ -{ - int have_old = 0; - long rc; - Py_UCS4 c; - - c = getuchar(unichr); - if (c == (Py_UCS4)-1) - return NULL; - - if (self && UCD_Check(self)) { - const change_record *old = get_old_record(self, c); - if (old->category_changed == 0) { - /* unassigned */ - have_old = 1; - rc = -1; - } - else if (old->decimal_changed != 0xFF) { - have_old = 1; - rc = old->decimal_changed; - } - } - - if (!have_old) - rc = Py_UNICODE_TODECIMAL(c); - if (rc < 0) { - if (default_value == NULL) { - PyErr_SetString(PyExc_ValueError, - "not a decimal"); - return NULL; - } - else { - Py_INCREF(default_value); - return default_value; - } - } - return PyLong_FromLong(rc); -} - -PyDoc_STRVAR(unicodedata_digit__doc__, -"digit(unichr[, default])\n\ -\n\ -Returns the digit value assigned to the Unicode character unichr as\n\ -integer. If no such value is defined, default is returned, or, if\n\ -not given, ValueError is raised."); - -static PyObject * -unicodedata_digit(PyObject *self, PyObject *args) -{ - PyUnicodeObject *v; - PyObject *defobj = NULL; - long rc; - Py_UCS4 c; - - if (!PyArg_ParseTuple(args, "O!|O:digit", &PyUnicode_Type, &v, &defobj)) - return NULL; - c = getuchar(v); - if (c == (Py_UCS4)-1) - return NULL; - rc = Py_UNICODE_TODIGIT(c); - if (rc < 0) { - if (defobj == NULL) { - PyErr_SetString(PyExc_ValueError, "not a digit"); - return NULL; - } - else { - Py_INCREF(defobj); - return defobj; - } - } - return PyLong_FromLong(rc); -} - -PyDoc_STRVAR(unicodedata_numeric__doc__, -"numeric(unichr[, default])\n\ -\n\ -Returns the numeric value assigned to the Unicode character unichr\n\ -as float. If no such value is defined, default is returned, or, if\n\ -not given, ValueError is raised."); - -static PyObject * -unicodedata_numeric(PyObject *self, PyObject *args) -{ - PyUnicodeObject *v; - PyObject *defobj = NULL; - int have_old = 0; - double rc; - Py_UCS4 c; - - if (!PyArg_ParseTuple(args, "O!|O:numeric", &PyUnicode_Type, &v, &defobj)) - return NULL; - c = getuchar(v); - if (c == (Py_UCS4)-1) - return NULL; - - if (self && UCD_Check(self)) { - const change_record *old = get_old_record(self, c); - if (old->category_changed == 0) { - /* unassigned */ - have_old = 1; - rc = -1.0; - } - else if (old->decimal_changed != 0xFF) { - have_old = 1; - rc = old->decimal_changed; - } - } - - if (!have_old) - rc = Py_UNICODE_TONUMERIC(c); - if (rc == -1.0) { - if (defobj == NULL) { - PyErr_SetString(PyExc_ValueError, "not a numeric character"); - return NULL; - } - else { - Py_INCREF(defobj); - return defobj; - } - } - return PyFloat_FromDouble(rc); -} - -PyDoc_STRVAR(unicodedata_category__doc__, -"category(unichr)\n\ -\n\ -Returns the general category assigned to the Unicode character\n\ -unichr as string."); - -static PyObject * -unicodedata_category(PyObject *self, PyObject *args) -{ - PyUnicodeObject *v; - int index; - Py_UCS4 c; - - if (!PyArg_ParseTuple(args, "O!:category", - &PyUnicode_Type, &v)) - return NULL; - c = getuchar(v); - if (c == (Py_UCS4)-1) - return NULL; - index = (int) _getrecord_ex(c)->category; - if (self && UCD_Check(self)) { - const change_record *old = get_old_record(self, c); - if (old->category_changed != 0xFF) - index = old->category_changed; - } - return PyUnicode_FromString(_PyUnicode_CategoryNames[index]); -} - -PyDoc_STRVAR(unicodedata_bidirectional__doc__, -"bidirectional(unichr)\n\ -\n\ -Returns the bidirectional class assigned to the Unicode character\n\ -unichr as string. If no such value is defined, an empty string is\n\ -returned."); - -static PyObject * -unicodedata_bidirectional(PyObject *self, PyObject *args) -{ - PyUnicodeObject *v; - int index; - Py_UCS4 c; - - if (!PyArg_ParseTuple(args, "O!:bidirectional", - &PyUnicode_Type, &v)) - return NULL; - c = getuchar(v); - if (c == (Py_UCS4)-1) - return NULL; - index = (int) _getrecord_ex(c)->bidirectional; - if (self && UCD_Check(self)) { - const change_record *old = get_old_record(self, c); - if (old->category_changed == 0) - index = 0; /* unassigned */ - else if (old->bidir_changed != 0xFF) - index = old->bidir_changed; - } - return PyUnicode_FromString(_PyUnicode_BidirectionalNames[index]); -} - -PyDoc_STRVAR(unicodedata_combining__doc__, -"combining(unichr)\n\ -\n\ -Returns the canonical combining class assigned to the Unicode\n\ -character unichr as integer. Returns 0 if no combining class is\n\ -defined."); - -static PyObject * -unicodedata_combining(PyObject *self, PyObject *args) -{ - PyUnicodeObject *v; - int index; - Py_UCS4 c; - - if (!PyArg_ParseTuple(args, "O!:combining", - &PyUnicode_Type, &v)) - return NULL; - c = getuchar(v); - if (c == (Py_UCS4)-1) - return NULL; - index = (int) _getrecord_ex(c)->combining; - if (self && UCD_Check(self)) { - const change_record *old = get_old_record(self, c); - if (old->category_changed == 0) - index = 0; /* unassigned */ - } - return PyLong_FromLong(index); -} - -PyDoc_STRVAR(unicodedata_mirrored__doc__, -"mirrored(unichr)\n\ -\n\ -Returns the mirrored property assigned to the Unicode character\n\ -unichr as integer. Returns 1 if the character has been identified as\n\ -a \"mirrored\" character in bidirectional text, 0 otherwise."); - -static PyObject * -unicodedata_mirrored(PyObject *self, PyObject *args) -{ - PyUnicodeObject *v; - int index; - Py_UCS4 c; - - if (!PyArg_ParseTuple(args, "O!:mirrored", - &PyUnicode_Type, &v)) - return NULL; - c = getuchar(v); - if (c == (Py_UCS4)-1) - return NULL; - index = (int) _getrecord_ex(c)->mirrored; - if (self && UCD_Check(self)) { - const change_record *old = get_old_record(self, c); - if (old->category_changed == 0) - index = 0; /* unassigned */ - else if (old->mirrored_changed != 0xFF) - index = old->mirrored_changed; - } - return PyLong_FromLong(index); -} - -PyDoc_STRVAR(unicodedata_east_asian_width__doc__, -"east_asian_width(unichr)\n\ -\n\ -Returns the east asian width assigned to the Unicode character\n\ -unichr as string."); - -static PyObject * -unicodedata_east_asian_width(PyObject *self, PyObject *args) -{ - PyUnicodeObject *v; - int index; - Py_UCS4 c; - - if (!PyArg_ParseTuple(args, "O!:east_asian_width", - &PyUnicode_Type, &v)) - return NULL; - c = getuchar(v); - if (c == (Py_UCS4)-1) - return NULL; - index = (int) _getrecord_ex(c)->east_asian_width; - if (self && UCD_Check(self)) { - const change_record *old = get_old_record(self, c); - if (old->category_changed == 0) - index = 0; /* unassigned */ - } - return PyUnicode_FromString(_PyUnicode_EastAsianWidthNames[index]); -} - -PyDoc_STRVAR(unicodedata_decomposition__doc__, -"decomposition(unichr)\n\ -\n\ -Returns the character decomposition mapping assigned to the Unicode\n\ -character unichr as string. An empty string is returned in case no\n\ -such mapping is defined."); - -static PyObject * -unicodedata_decomposition(PyObject *self, PyObject *args) -{ - PyUnicodeObject *v; - char decomp[256]; - int code, index, count; - size_t i; - unsigned int prefix_index; - Py_UCS4 c; - - if (!PyArg_ParseTuple(args, "O!:decomposition", - &PyUnicode_Type, &v)) - return NULL; - c = getuchar(v); - if (c == (Py_UCS4)-1) - return NULL; - - code = (int)c; - - if (self && UCD_Check(self)) { - const change_record *old = get_old_record(self, c); - if (old->category_changed == 0) - return PyUnicode_FromString(""); /* unassigned */ - } - - if (code < 0 || code >= 0x110000) - index = 0; - else { - index = decomp_index1[(code>>DECOMP_SHIFT)]; - index = decomp_index2[(index<> 8; - - /* XXX: could allocate the PyString up front instead - (strlen(prefix) + 5 * count + 1 bytes) */ - - /* Based on how index is calculated above and decomp_data is generated - from Tools/unicode/makeunicodedata.py, it should not be possible - to overflow decomp_prefix. */ - prefix_index = decomp_data[index] & 255; - assert(prefix_index < Py_ARRAY_LENGTH(decomp_prefix)); - - /* copy prefix */ - i = strlen(decomp_prefix[prefix_index]); - memcpy(decomp, decomp_prefix[prefix_index], i); - - while (count-- > 0) { - if (i) - decomp[i++] = ' '; - assert(i < sizeof(decomp)); - PyOS_snprintf(decomp + i, sizeof(decomp) - i, "%04X", - decomp_data[++index]); - i += strlen(decomp + i); - } - return PyUnicode_FromStringAndSize(decomp, i); -} - -static void -get_decomp_record(PyObject *self, Py_UCS4 code, int *index, int *prefix, int *count) -{ - if (code >= 0x110000) { - *index = 0; - } else if (self && UCD_Check(self) && - get_old_record(self, code)->category_changed==0) { - /* unassigned in old version */ - *index = 0; - } - else { - *index = decomp_index1[(code>>DECOMP_SHIFT)]; - *index = decomp_index2[(*index<> 8; - *prefix = decomp_data[*index] & 255; - - (*index)++; -} - -#define SBase 0xAC00 -#define LBase 0x1100 -#define VBase 0x1161 -#define TBase 0x11A7 -#define LCount 19 -#define VCount 21 -#define TCount 28 -#define NCount (VCount*TCount) -#define SCount (LCount*NCount) - -static PyObject* -nfd_nfkd(PyObject *self, PyObject *input, int k) -{ - PyObject *result; - Py_UCS4 *output; - Py_ssize_t i, o, osize; - int kind; - void *data; - /* Longest decomposition in Unicode 3.2: U+FDFA */ - Py_UCS4 stack[20]; - Py_ssize_t space, isize; - int index, prefix, count, stackptr; - unsigned char prev, cur; - - stackptr = 0; - isize = PyUnicode_GET_LENGTH(input); - space = isize; - /* Overallocate at most 10 characters. */ - if (space > 10) { - if (space <= PY_SSIZE_T_MAX - 10) - space += 10; - } - else { - space *= 2; - } - osize = space; - output = PyMem_NEW(Py_UCS4, space); - if (!output) { - PyErr_NoMemory(); - return NULL; - } - i = o = 0; - kind = PyUnicode_KIND(input); - data = PyUnicode_DATA(input); - - while (i < isize) { - stack[stackptr++] = PyUnicode_READ(kind, data, i++); - while(stackptr) { - Py_UCS4 code = stack[--stackptr]; - /* Hangul Decomposition adds three characters in - a single step, so we need at least that much room. */ - if (space < 3) { - Py_UCS4 *new_output; - osize += 10; - space += 10; - new_output = PyMem_Realloc(output, osize*sizeof(Py_UCS4)); - if (new_output == NULL) { - PyMem_Free(output); - PyErr_NoMemory(); - return NULL; - } - output = new_output; - } - /* Hangul Decomposition. */ - if (SBase <= code && code < (SBase+SCount)) { - int SIndex = code - SBase; - int L = LBase + SIndex / NCount; - int V = VBase + (SIndex % NCount) / TCount; - int T = TBase + SIndex % TCount; - output[o++] = L; - output[o++] = V; - space -= 2; - if (T != TBase) { - output[o++] = T; - space --; - } - continue; - } - /* normalization changes */ - if (self && UCD_Check(self)) { - Py_UCS4 value = ((PreviousDBVersion*)self)->normalization(code); - if (value != 0) { - stack[stackptr++] = value; - continue; - } - } - - /* Other decompositions. */ - get_decomp_record(self, code, &index, &prefix, &count); - - /* Copy character if it is not decomposable, or has a - compatibility decomposition, but we do NFD. */ - if (!count || (prefix && !k)) { - output[o++] = code; - space--; - continue; - } - /* Copy decomposition onto the stack, in reverse - order. */ - while(count) { - code = decomp_data[index + (--count)]; - stack[stackptr++] = code; - } - } - } - - result = PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND, - output, o); - PyMem_Free(output); - if (!result) - return NULL; - /* result is guaranteed to be ready, as it is compact. */ - kind = PyUnicode_KIND(result); - data = PyUnicode_DATA(result); - - /* Sort canonically. */ - i = 0; - prev = _getrecord_ex(PyUnicode_READ(kind, data, i))->combining; - for (i++; i < PyUnicode_GET_LENGTH(result); i++) { - cur = _getrecord_ex(PyUnicode_READ(kind, data, i))->combining; - if (prev == 0 || cur == 0 || prev <= cur) { - prev = cur; - continue; - } - /* Non-canonical order. Need to switch *i with previous. */ - o = i - 1; - while (1) { - Py_UCS4 tmp = PyUnicode_READ(kind, data, o+1); - PyUnicode_WRITE(kind, data, o+1, - PyUnicode_READ(kind, data, o)); - PyUnicode_WRITE(kind, data, o, tmp); - o--; - if (o < 0) - break; - prev = _getrecord_ex(PyUnicode_READ(kind, data, o))->combining; - if (prev == 0 || prev <= cur) - break; - } - prev = _getrecord_ex(PyUnicode_READ(kind, data, i))->combining; - } - return result; -} - -static int -find_nfc_index(PyObject *self, struct reindex* nfc, Py_UCS4 code) -{ - unsigned int index; - for (index = 0; nfc[index].start; index++) { - unsigned int start = nfc[index].start; - if (code < start) - return -1; - if (code <= start + nfc[index].count) { - unsigned int delta = code - start; - return nfc[index].index + delta; - } - } - return -1; -} - -static PyObject* -nfc_nfkc(PyObject *self, PyObject *input, int k) -{ - PyObject *result; - int kind; - void *data; - Py_UCS4 *output; - Py_ssize_t i, i1, o, len; - int f,l,index,index1,comb; - Py_UCS4 code; - Py_ssize_t skipped[20]; - int cskipped = 0; - - result = nfd_nfkd(self, input, k); - if (!result) - return NULL; - /* result will be "ready". */ - kind = PyUnicode_KIND(result); - data = PyUnicode_DATA(result); - len = PyUnicode_GET_LENGTH(result); - - /* We allocate a buffer for the output. - If we find that we made no changes, we still return - the NFD result. */ - output = PyMem_NEW(Py_UCS4, len); - if (!output) { - PyErr_NoMemory(); - Py_DECREF(result); - return 0; - } - i = o = 0; - - again: - while (i < len) { - for (index = 0; index < cskipped; index++) { - if (skipped[index] == i) { - /* *i character is skipped. - Remove from list. */ - skipped[index] = skipped[cskipped-1]; - cskipped--; - i++; - goto again; /* continue while */ - } - } - /* Hangul Composition. We don't need to check for - pairs, since we always have decomposed data. */ - code = PyUnicode_READ(kind, data, i); - if (LBase <= code && code < (LBase+LCount) && - i + 1 < len && - VBase <= PyUnicode_READ(kind, data, i+1) && - PyUnicode_READ(kind, data, i+1) <= (VBase+VCount)) { - int LIndex, VIndex; - LIndex = code - LBase; - VIndex = PyUnicode_READ(kind, data, i+1) - VBase; - code = SBase + (LIndex*VCount+VIndex)*TCount; - i+=2; - if (i < len && - TBase <= PyUnicode_READ(kind, data, i) && - PyUnicode_READ(kind, data, i) <= (TBase+TCount)) { - code += PyUnicode_READ(kind, data, i)-TBase; - i++; - } - output[o++] = code; - continue; - } - - /* code is still input[i] here */ - f = find_nfc_index(self, nfc_first, code); - if (f == -1) { - output[o++] = code; - i++; - continue; - } - /* Find next unblocked character. */ - i1 = i+1; - comb = 0; - /* output base character for now; might be updated later. */ - output[o] = PyUnicode_READ(kind, data, i); - while (i1 < len) { - Py_UCS4 code1 = PyUnicode_READ(kind, data, i1); - int comb1 = _getrecord_ex(code1)->combining; - if (comb) { - if (comb1 == 0) - break; - if (comb >= comb1) { - /* Character is blocked. */ - i1++; - continue; - } - } - l = find_nfc_index(self, nfc_last, code1); - /* i1 cannot be combined with i. If i1 - is a starter, we don't need to look further. - Otherwise, record the combining class. */ - if (l == -1) { - not_combinable: - if (comb1 == 0) - break; - comb = comb1; - i1++; - continue; - } - index = f*TOTAL_LAST + l; - index1 = comp_index[index >> COMP_SHIFT]; - code = comp_data[(index1<combining; - unsigned char quickcheck = record->normalization_quick_check; - - if (quickcheck & quickcheck_mask) - return 0; /* this string might need normalization */ - if (combining && prev_combining > combining) - return 0; /* non-canonical sort order, not normalized */ - prev_combining = combining; - } - return 1; /* certainly normalized */ -} - -PyDoc_STRVAR(unicodedata_normalize__doc__, -"normalize(form, unistr)\n\ -\n\ -Return the normal form 'form' for the Unicode string unistr. Valid\n\ -values for form are 'NFC', 'NFKC', 'NFD', and 'NFKD'."); - -static PyObject* -unicodedata_normalize(PyObject *self, PyObject *args) -{ - char *form; - PyObject *input; - - if(!PyArg_ParseTuple(args, "sO!:normalize", - &form, &PyUnicode_Type, &input)) - return NULL; - - if (PyUnicode_READY(input) == -1) - return NULL; - - if (PyUnicode_GET_LENGTH(input) == 0) { - /* Special case empty input strings, since resizing - them later would cause internal errors. */ - Py_INCREF(input); - return input; - } - - if (strcmp(form, "NFC") == 0) { - if (is_normalized(self, input, 1, 0)) { - Py_INCREF(input); - return input; - } - return nfc_nfkc(self, input, 0); - } - if (strcmp(form, "NFKC") == 0) { - if (is_normalized(self, input, 1, 1)) { - Py_INCREF(input); - return input; - } - return nfc_nfkc(self, input, 1); - } - if (strcmp(form, "NFD") == 0) { - if (is_normalized(self, input, 0, 0)) { - Py_INCREF(input); - return input; - } - return nfd_nfkd(self, input, 0); - } - if (strcmp(form, "NFKD") == 0) { - if (is_normalized(self, input, 0, 1)) { - Py_INCREF(input); - return input; - } - return nfd_nfkd(self, input, 1); - } - PyErr_SetString(PyExc_ValueError, "invalid normalization form"); - return NULL; -} - -/* -------------------------------------------------------------------- */ -/* unicode character name tables */ - -/* data file generated by Tools/unicode/makeunicodedata.py */ -#include "unicodename_db.h" - -/* -------------------------------------------------------------------- */ -/* database code (cut and pasted from the unidb package) */ - -static unsigned long -_gethash(const char *s, int len, int scale) -{ - int i; - unsigned long h = 0; - unsigned long ix; - for (i = 0; i < len; i++) { - h = (h * scale) + (unsigned char) Py_TOUPPER(Py_CHARMASK(s[i])); - ix = h & 0xff000000; - if (ix) - h = (h ^ ((ix>>24) & 0xff)) & 0x00ffffff; - } - return h; -} - -static char *hangul_syllables[][3] = { - { "G", "A", "" }, - { "GG", "AE", "G" }, - { "N", "YA", "GG" }, - { "D", "YAE", "GS" }, - { "DD", "EO", "N", }, - { "R", "E", "NJ" }, - { "M", "YEO", "NH" }, - { "B", "YE", "D" }, - { "BB", "O", "L" }, - { "S", "WA", "LG" }, - { "SS", "WAE", "LM" }, - { "", "OE", "LB" }, - { "J", "YO", "LS" }, - { "JJ", "U", "LT" }, - { "C", "WEO", "LP" }, - { "K", "WE", "LH" }, - { "T", "WI", "M" }, - { "P", "YU", "B" }, - { "H", "EU", "BS" }, - { 0, "YI", "S" }, - { 0, "I", "SS" }, - { 0, 0, "NG" }, - { 0, 0, "J" }, - { 0, 0, "C" }, - { 0, 0, "K" }, - { 0, 0, "T" }, - { 0, 0, "P" }, - { 0, 0, "H" } -}; - -/* These ranges need to match makeunicodedata.py:cjk_ranges. */ -static int -is_unified_ideograph(Py_UCS4 code) -{ - return - (0x3400 <= code && code <= 0x4DB5) || /* CJK Ideograph Extension A */ - (0x4E00 <= code && code <= 0x9FCC) || /* CJK Ideograph */ - (0x20000 <= code && code <= 0x2A6D6) || /* CJK Ideograph Extension B */ - (0x2A700 <= code && code <= 0x2B734) || /* CJK Ideograph Extension C */ - (0x2B740 <= code && code <= 0x2B81D); /* CJK Ideograph Extension D */ -} - -/* macros used to determine if the given code point is in the PUA range that - * we are using to store aliases and named sequences */ -#define IS_ALIAS(cp) ((cp >= aliases_start) && (cp < aliases_end)) -#define IS_NAMED_SEQ(cp) ((cp >= named_sequences_start) && \ - (cp < named_sequences_end)) - -static int -_getucname(PyObject *self, Py_UCS4 code, char* buffer, int buflen, - int with_alias_and_seq) -{ - /* Find the name associated with the given code point. - * If with_alias_and_seq is 1, check for names in the Private Use Area 15 - * that we are using for aliases and named sequences. */ - int offset; - int i; - int word; - unsigned char* w; - - if (code >= 0x110000) - return 0; - - /* XXX should we just skip all the code points in the PUAs here? */ - if (!with_alias_and_seq && (IS_ALIAS(code) || IS_NAMED_SEQ(code))) - return 0; - - if (self && UCD_Check(self)) { - /* in 3.2.0 there are no aliases and named sequences */ - const change_record *old; - if (IS_ALIAS(code) || IS_NAMED_SEQ(code)) - return 0; - old = get_old_record(self, code); - if (old->category_changed == 0) { - /* unassigned */ - return 0; - } - } - - if (SBase <= code && code < SBase+SCount) { - /* Hangul syllable. */ - int SIndex = code - SBase; - int L = SIndex / NCount; - int V = (SIndex % NCount) / TCount; - int T = SIndex % TCount; - - if (buflen < 27) - /* Worst case: HANGUL SYLLABLE <10chars>. */ - return 0; - strcpy(buffer, "HANGUL SYLLABLE "); - buffer += 16; - strcpy(buffer, hangul_syllables[L][0]); - buffer += strlen(hangul_syllables[L][0]); - strcpy(buffer, hangul_syllables[V][1]); - buffer += strlen(hangul_syllables[V][1]); - strcpy(buffer, hangul_syllables[T][2]); - buffer += strlen(hangul_syllables[T][2]); - *buffer = '\0'; - return 1; - } - - if (is_unified_ideograph(code)) { - if (buflen < 28) - /* Worst case: CJK UNIFIED IDEOGRAPH-20000 */ - return 0; - sprintf(buffer, "CJK UNIFIED IDEOGRAPH-%X", code); - return 1; - } - - /* get offset into phrasebook */ - offset = phrasebook_offset1[(code>>phrasebook_shift)]; - offset = phrasebook_offset2[(offset<= 0) { - word = (word << 8) + phrasebook[offset+1]; - offset += 2; - } else - word = phrasebook[offset++]; - if (i) { - if (i > buflen) - return 0; /* buffer overflow */ - buffer[i++] = ' '; - } - /* copy word string from lexicon. the last character in the - word has bit 7 set. the last word in a string ends with - 0x80 */ - w = lexicon + lexicon_offset[word]; - while (*w < 128) { - if (i >= buflen) - return 0; /* buffer overflow */ - buffer[i++] = *w++; - } - if (i >= buflen) - return 0; /* buffer overflow */ - buffer[i++] = *w & 127; - if (*w == 128) - break; /* end of word */ - } - - return 1; -} - -static int -_cmpname(PyObject *self, int code, const char* name, int namelen) -{ - /* check if code corresponds to the given name */ - int i; - char buffer[NAME_MAXLEN]; - if (!_getucname(self, code, buffer, sizeof(buffer), 1)) - return 0; - for (i = 0; i < namelen; i++) { - if (Py_TOUPPER(Py_CHARMASK(name[i])) != buffer[i]) - return 0; - } - return buffer[namelen] == '\0'; -} - -static void -find_syllable(const char *str, int *len, int *pos, int count, int column) -{ - int i, len1; - *len = -1; - for (i = 0; i < count; i++) { - char *s = hangul_syllables[i][column]; - len1 = Py_SAFE_DOWNCAST(strlen(s), size_t, int); - if (len1 <= *len) - continue; - if (strncmp(str, s, len1) == 0) { - *len = len1; - *pos = i; - } - } - if (*len == -1) { - *len = 0; - } -} - -static int -_check_alias_and_seq(unsigned int cp, Py_UCS4* code, int with_named_seq) -{ - /* check if named sequences are allowed */ - if (!with_named_seq && IS_NAMED_SEQ(cp)) - return 0; - /* if the code point is in the PUA range that we use for aliases, - * convert it to obtain the right code point */ - if (IS_ALIAS(cp)) - *code = name_aliases[cp-aliases_start]; - else - *code = cp; - return 1; -} - -static int -_getcode(PyObject* self, const char* name, int namelen, Py_UCS4* code, - int with_named_seq) -{ - /* Return the code point associated with the given name. - * Named aliases are resolved too (unless self != NULL (i.e. we are using - * 3.2.0)). If with_named_seq is 1, returns the PUA code point that we are - * using for the named sequence, and the caller must then convert it. */ - unsigned int h, v; - unsigned int mask = code_size-1; - unsigned int i, incr; - - /* Check for hangul syllables. */ - if (strncmp(name, "HANGUL SYLLABLE ", 16) == 0) { - int len, L = -1, V = -1, T = -1; - const char *pos = name + 16; - find_syllable(pos, &len, &L, LCount, 0); - pos += len; - find_syllable(pos, &len, &V, VCount, 1); - pos += len; - find_syllable(pos, &len, &T, TCount, 2); - pos += len; - if (L != -1 && V != -1 && T != -1 && pos-name == namelen) { - *code = SBase + (L*VCount+V)*TCount + T; - return 1; - } - /* Otherwise, it's an illegal syllable name. */ - return 0; - } - - /* Check for unified ideographs. */ - if (strncmp(name, "CJK UNIFIED IDEOGRAPH-", 22) == 0) { - /* Four or five hexdigits must follow. */ - v = 0; - name += 22; - namelen -= 22; - if (namelen != 4 && namelen != 5) - return 0; - while (namelen--) { - v *= 16; - if (*name >= '0' && *name <= '9') - v += *name - '0'; - else if (*name >= 'A' && *name <= 'F') - v += *name - 'A' + 10; - else - return 0; - name++; - } - if (!is_unified_ideograph(v)) - return 0; - *code = v; - return 1; - } - - /* the following is the same as python's dictionary lookup, with - only minor changes. see the makeunicodedata script for more - details */ - - h = (unsigned int) _gethash(name, namelen, code_magic); - i = (~h) & mask; - v = code_hash[i]; - if (!v) - return 0; - if (_cmpname(self, v, name, namelen)) - return _check_alias_and_seq(v, code, with_named_seq); - incr = (h ^ (h >> 3)) & mask; - if (!incr) - incr = mask; - for (;;) { - i = (i + incr) & mask; - v = code_hash[i]; - if (!v) - return 0; - if (_cmpname(self, v, name, namelen)) - return _check_alias_and_seq(v, code, with_named_seq); - incr = incr << 1; - if (incr > mask) - incr = incr ^ code_poly; - } -} - -static const _PyUnicode_Name_CAPI hashAPI = -{ - sizeof(_PyUnicode_Name_CAPI), - _getucname, - _getcode -}; - -/* -------------------------------------------------------------------- */ -/* Python bindings */ - -PyDoc_STRVAR(unicodedata_name__doc__, -"name(unichr[, default])\n\ -Returns the name assigned to the Unicode character unichr as a\n\ -string. If no name is defined, default is returned, or, if not\n\ -given, ValueError is raised."); - -static PyObject * -unicodedata_name(PyObject* self, PyObject* args) -{ - char name[NAME_MAXLEN]; - Py_UCS4 c; - - PyUnicodeObject* v; - PyObject* defobj = NULL; - if (!PyArg_ParseTuple(args, "O!|O:name", &PyUnicode_Type, &v, &defobj)) - return NULL; - - c = getuchar(v); - if (c == (Py_UCS4)-1) - return NULL; - - if (!_getucname(self, c, name, sizeof(name), 0)) { - if (defobj == NULL) { - PyErr_SetString(PyExc_ValueError, "no such name"); - return NULL; - } - else { - Py_INCREF(defobj); - return defobj; - } - } - - return PyUnicode_FromString(name); -} - -PyDoc_STRVAR(unicodedata_lookup__doc__, -"lookup(name)\n\ -\n\ -Look up character by name. If a character with the\n\ -given name is found, return the corresponding Unicode\n\ -character. If not found, KeyError is raised."); - -static PyObject * -unicodedata_lookup(PyObject* self, PyObject* args) -{ - Py_UCS4 code; - - char* name; - Py_ssize_t namelen; - unsigned int index; - if (!PyArg_ParseTuple(args, "s#:lookup", &name, &namelen)) - return NULL; - if (namelen > INT_MAX) { - PyErr_SetString(PyExc_KeyError, "name too long"); - return NULL; - } - - if (!_getcode(self, name, (int)namelen, &code, 1)) { - PyErr_Format(PyExc_KeyError, "undefined character name '%s'", name); - return NULL; - } - /* check if code is in the PUA range that we use for named sequences - and convert it */ - if (IS_NAMED_SEQ(code)) { - index = code-named_sequences_start; - return PyUnicode_FromKindAndData(PyUnicode_2BYTE_KIND, - named_sequences[index].seq, - named_sequences[index].seqlen); - } - return PyUnicode_FromOrdinal(code); -} - -/* XXX Add doc strings. */ - -static PyMethodDef unicodedata_functions[] = { - UNICODEDATA_UCD_DECIMAL_METHODDEF - {"digit", unicodedata_digit, METH_VARARGS, unicodedata_digit__doc__}, - {"numeric", unicodedata_numeric, METH_VARARGS, unicodedata_numeric__doc__}, - {"category", unicodedata_category, METH_VARARGS, - unicodedata_category__doc__}, - {"bidirectional", unicodedata_bidirectional, METH_VARARGS, - unicodedata_bidirectional__doc__}, - {"combining", unicodedata_combining, METH_VARARGS, - unicodedata_combining__doc__}, - {"mirrored", unicodedata_mirrored, METH_VARARGS, - unicodedata_mirrored__doc__}, - {"east_asian_width", unicodedata_east_asian_width, METH_VARARGS, - unicodedata_east_asian_width__doc__}, - {"decomposition", unicodedata_decomposition, METH_VARARGS, - unicodedata_decomposition__doc__}, - {"name", unicodedata_name, METH_VARARGS, unicodedata_name__doc__}, - {"lookup", unicodedata_lookup, METH_VARARGS, unicodedata_lookup__doc__}, - {"normalize", unicodedata_normalize, METH_VARARGS, - unicodedata_normalize__doc__}, - {NULL, NULL} /* sentinel */ -}; - -static PyTypeObject UCD_Type = { - /* The ob_type field must be initialized in the module init function - * to be portable to Windows without using C++. */ - PyVarObject_HEAD_INIT(NULL, 0) - "unicodedata.UCD", /*tp_name*/ - sizeof(PreviousDBVersion), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - /* methods */ - (destructor)PyObject_Del, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_reserved*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash*/ - 0, /*tp_call*/ - 0, /*tp_str*/ - PyObject_GenericGetAttr,/*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - 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*/ - unicodedata_functions, /*tp_methods*/ - DB_members, /*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*/ - 0, /*tp_new*/ - 0, /*tp_free*/ - 0, /*tp_is_gc*/ -}; - -PyDoc_STRVAR(unicodedata_docstring, -"This module provides access to the Unicode Character Database which\n\ -defines character properties for all Unicode characters. The data in\n\ -this database is based on the UnicodeData.txt file version\n\ -" UNIDATA_VERSION " which is publically available from ftp://ftp.unicode.org/.\n\ -\n\ -The module uses the same names and symbols as defined by the\n\ -UnicodeData File Format " UNIDATA_VERSION "."); - -static struct PyModuleDef unicodedatamodule = { - PyModuleDef_HEAD_INIT, - "unicodedata", - unicodedata_docstring, - -1, - unicodedata_functions, - NULL, - NULL, - NULL, - NULL -}; - -PyMODINIT_FUNC -PyInit_unicodedata(void) -{ - PyObject *m, *v; - - Py_TYPE(&UCD_Type) = &PyType_Type; - - m = PyModule_Create(&unicodedatamodule); - if (!m) - return NULL; - - PyModule_AddStringConstant(m, "unidata_version", UNIDATA_VERSION); - Py_INCREF(&UCD_Type); - PyModule_AddObject(m, "UCD", (PyObject*)&UCD_Type); - - /* Previous versions */ - v = new_previous_version("3.2.0", get_change_3_2_0, normalization_3_2_0); - if (v != NULL) - PyModule_AddObject(m, "ucd_3_2_0", v); - - /* Export C API */ - v = PyCapsule_New((void *)&hashAPI, PyUnicodeData_CAPSULE_NAME, NULL); - if (v != NULL) - PyModule_AddObject(m, "ucnhash_CAPI", v); - return m; -} - -/* -Local variables: -c-basic-offset: 4 -indent-tabs-mode: nil -End: -*/ +/*[clinic end generated code: output=15b82651419cc823 input=a9049054013a1b77]*/ diff --git a/Modules/cmathmodule.c b/Modules/cmathmodule.c --- a/Modules/cmathmodule.c +++ b/Modules/cmathmodule.c @@ -10,10 +10,9 @@ #include "clinic/cmathmodule.c.h" /*[clinic input] -output preset file module cmath [clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=ef7e0fdd8a143c03]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=308d6839f4a46333]*/ /*[python input] class Py_complex_protected_converter(Py_complex_converter): diff --git a/Modules/fcntlmodule.c b/Modules/fcntlmodule.c --- a/Modules/fcntlmodule.c +++ b/Modules/fcntlmodule.c @@ -16,10 +16,9 @@ #endif /*[clinic input] -output preset file module fcntl [clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=c7356fdb126a904a]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=124b58387c158179]*/ static int conv_descriptor(PyObject *object, int *target) diff --git a/Modules/grpmodule.c b/Modules/grpmodule.c --- a/Modules/grpmodule.c +++ b/Modules/grpmodule.c @@ -8,10 +8,9 @@ #include "clinic/grpmodule.c.h" /*[clinic input] -output preset file module grp [clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=68180a9a9efb8506]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=cade63f2ed1bd9f8]*/ static PyStructSequence_Field struct_group_type_fields[] = { {"gr_name", "group name"}, diff --git a/Modules/md5module.c b/Modules/md5module.c --- a/Modules/md5module.c +++ b/Modules/md5module.c @@ -53,6 +53,7 @@ struct md5_state hash_state; } MD5object; +#include "clinic/md5module.c.h" /* ------------------------------------------------------------------------ * @@ -343,27 +344,9 @@ Return a copy of the hash object. [clinic start generated code]*/ -PyDoc_STRVAR(MD5Type_copy__doc__, -"copy($self, /)\n" -"--\n" -"\n" -"Return a copy of the hash object."); - -#define MD5TYPE_COPY_METHODDEF \ - {"copy", (PyCFunction)MD5Type_copy, METH_NOARGS, MD5Type_copy__doc__}, - -static PyObject * -MD5Type_copy_impl(MD5object *self); - -static PyObject * -MD5Type_copy(MD5object *self, PyObject *Py_UNUSED(ignored)) -{ - return MD5Type_copy_impl(self); -} - static PyObject * MD5Type_copy_impl(MD5object *self) -/*[clinic end generated code: output=3b3a88920b3dc7f4 input=2c09e6d2493f3079]*/ +/*[clinic end generated code: output=596eb36852f02071 input=2c09e6d2493f3079]*/ { MD5object *newobj; @@ -385,27 +368,9 @@ Return the digest value as a string of binary data. [clinic start generated code]*/ -PyDoc_STRVAR(MD5Type_digest__doc__, -"digest($self, /)\n" -"--\n" -"\n" -"Return the digest value as a string of binary data."); - -#define MD5TYPE_DIGEST_METHODDEF \ - {"digest", (PyCFunction)MD5Type_digest, METH_NOARGS, MD5Type_digest__doc__}, - -static PyObject * -MD5Type_digest_impl(MD5object *self); - -static PyObject * -MD5Type_digest(MD5object *self, PyObject *Py_UNUSED(ignored)) -{ - return MD5Type_digest_impl(self); -} - static PyObject * MD5Type_digest_impl(MD5object *self) -/*[clinic end generated code: output=7a796b28fa89485f input=7b96e65389412a34]*/ +/*[clinic end generated code: output=eb691dc4190a07ec input=7b96e65389412a34]*/ { unsigned char digest[MD5_DIGESTSIZE]; struct md5_state temp; @@ -421,27 +386,9 @@ Return the digest value as a string of hexadecimal digits. [clinic start generated code]*/ -PyDoc_STRVAR(MD5Type_hexdigest__doc__, -"hexdigest($self, /)\n" -"--\n" -"\n" -"Return the digest value as a string of hexadecimal digits."); - -#define MD5TYPE_HEXDIGEST_METHODDEF \ - {"hexdigest", (PyCFunction)MD5Type_hexdigest, METH_NOARGS, MD5Type_hexdigest__doc__}, - -static PyObject * -MD5Type_hexdigest_impl(MD5object *self); - -static PyObject * -MD5Type_hexdigest(MD5object *self, PyObject *Py_UNUSED(ignored)) -{ - return MD5Type_hexdigest_impl(self); -} - static PyObject * MD5Type_hexdigest_impl(MD5object *self) -/*[clinic end generated code: output=daa73609f94f92e1 input=b60b19de644798dd]*/ +/*[clinic end generated code: output=17badced1f3ac932 input=b60b19de644798dd]*/ { unsigned char digest[MD5_DIGESTSIZE]; struct md5_state temp; @@ -482,18 +429,9 @@ Update this hash object's state with the provided string. [clinic start generated code]*/ -PyDoc_STRVAR(MD5Type_update__doc__, -"update($self, obj, /)\n" -"--\n" -"\n" -"Update this hash object\'s state with the provided string."); - -#define MD5TYPE_UPDATE_METHODDEF \ - {"update", (PyCFunction)MD5Type_update, METH_O, MD5Type_update__doc__}, - static PyObject * MD5Type_update(MD5object *self, PyObject *obj) -/*[clinic end generated code: output=9d09b6c6cdc6cac3 input=6e1efcd9ecf17032]*/ +/*[clinic end generated code: output=f6ad168416338423 input=6e1efcd9ecf17032]*/ { Py_buffer buf; @@ -594,38 +532,9 @@ Return a new MD5 hash object; optionally initialized with a string. [clinic start generated code]*/ -PyDoc_STRVAR(_md5_md5__doc__, -"md5($module, /, string=b\'\')\n" -"--\n" -"\n" -"Return a new MD5 hash object; optionally initialized with a string."); - -#define _MD5_MD5_METHODDEF \ - {"md5", (PyCFunction)_md5_md5, METH_VARARGS|METH_KEYWORDS, _md5_md5__doc__}, - -static PyObject * -_md5_md5_impl(PyModuleDef *module, PyObject *string); - -static PyObject * -_md5_md5(PyModuleDef *module, PyObject *args, PyObject *kwargs) -{ - PyObject *return_value = NULL; - static char *_keywords[] = {"string", NULL}; - PyObject *string = NULL; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "|O:md5", _keywords, - &string)) - goto exit; - return_value = _md5_md5_impl(module, string); - -exit: - return return_value; -} - static PyObject * _md5_md5_impl(PyModuleDef *module, PyObject *string) -/*[clinic end generated code: output=1039e912d919880e input=d12ef8f72d684f7b]*/ +/*[clinic end generated code: output=3527436a2090b956 input=d12ef8f72d684f7b]*/ { MD5object *new; Py_buffer buf; diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -2470,61 +2470,9 @@ [clinic start generated code]*/ -PyDoc_STRVAR(os_stat__doc__, -"stat($module, /, path, *, dir_fd=None, follow_symlinks=True)\n" -"--\n" -"\n" -"Perform a stat system call on the given path.\n" -"\n" -" path\n" -" Path to be examined; can be string, bytes, or open-file-descriptor int.\n" -" dir_fd\n" -" If not None, it should be a file descriptor open to a directory,\n" -" and path should be a relative string; path will then be relative to\n" -" that directory.\n" -" follow_symlinks\n" -" If False, and the last element of the path is a symbolic link,\n" -" stat will examine the symbolic link itself instead of the file\n" -" the link points to.\n" -"\n" -"dir_fd and follow_symlinks may not be implemented\n" -" on your platform. If they are unavailable, using them will raise a\n" -" NotImplementedError.\n" -"\n" -"It\'s an error to use dir_fd or follow_symlinks when specifying path as\n" -" an open file descriptor."); - -#define OS_STAT_METHODDEF \ - {"stat", (PyCFunction)os_stat, METH_VARARGS|METH_KEYWORDS, os_stat__doc__}, - -static PyObject * -os_stat_impl(PyModuleDef *module, path_t *path, int dir_fd, int follow_symlinks); - -static PyObject * -os_stat(PyModuleDef *module, PyObject *args, PyObject *kwargs) -{ - PyObject *return_value = NULL; - static char *_keywords[] = {"path", "dir_fd", "follow_symlinks", NULL}; - path_t path = PATH_T_INITIALIZE("stat", "path", 0, 1); - int dir_fd = DEFAULT_DIR_FD; - int follow_symlinks = 1; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "O&|$O&p:stat", _keywords, - path_converter, &path, FSTATAT_DIR_FD_CONVERTER, &dir_fd, &follow_symlinks)) - goto exit; - return_value = os_stat_impl(module, &path, dir_fd, follow_symlinks); - -exit: - /* Cleanup for path */ - path_cleanup(&path); - - return return_value; -} - static PyObject * os_stat_impl(PyModuleDef *module, path_t *path, int dir_fd, int follow_symlinks) -/*[clinic end generated code: output=0e9f9508fa0c0607 input=099d356c306fa24a]*/ +/*[clinic end generated code: output=708c225f94fcfc8e input=099d356c306fa24a]*/ { return posix_do_stat("stat", path, dir_fd, follow_symlinks); } @@ -2545,45 +2493,9 @@ Equivalent to stat(path, follow_symlinks=False). [clinic start generated code]*/ -PyDoc_STRVAR(os_lstat__doc__, -"lstat($module, /, path, *, dir_fd=None)\n" -"--\n" -"\n" -"Perform a stat system call on the given path, without following symbolic links.\n" -"\n" -"Like stat(), but do not follow symbolic links.\n" -"Equivalent to stat(path, follow_symlinks=False)."); - -#define OS_LSTAT_METHODDEF \ - {"lstat", (PyCFunction)os_lstat, METH_VARARGS|METH_KEYWORDS, os_lstat__doc__}, - -static PyObject * -os_lstat_impl(PyModuleDef *module, path_t *path, int dir_fd); - -static PyObject * -os_lstat(PyModuleDef *module, PyObject *args, PyObject *kwargs) -{ - PyObject *return_value = NULL; - static char *_keywords[] = {"path", "dir_fd", NULL}; - path_t path = PATH_T_INITIALIZE("lstat", "path", 0, 0); - int dir_fd = DEFAULT_DIR_FD; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "O&|$O&:lstat", _keywords, - path_converter, &path, FSTATAT_DIR_FD_CONVERTER, &dir_fd)) - goto exit; - return_value = os_lstat_impl(module, &path, dir_fd); - -exit: - /* Cleanup for path */ - path_cleanup(&path); - - return return_value; -} - static PyObject * os_lstat_impl(PyModuleDef *module, path_t *path, int dir_fd) -/*[clinic end generated code: output=85702247224a2b1c input=0b7474765927b925]*/ +/*[clinic end generated code: output=7a748e333fcb39bd input=0b7474765927b925]*/ { int follow_symlinks = 0; return posix_do_stat("lstat", path, dir_fd, follow_symlinks); @@ -2629,75 +2541,9 @@ [clinic start generated code]*/ -PyDoc_STRVAR(os_access__doc__, -"access($module, /, path, mode, *, dir_fd=None, effective_ids=False,\n" -" follow_symlinks=True)\n" -"--\n" -"\n" -"Use the real uid/gid to test for access to a path.\n" -"\n" -" path\n" -" Path to be tested; can be string, bytes, or open-file-descriptor int.\n" -" mode\n" -" Operating-system mode bitfield. Can be F_OK to test existence,\n" -" or the inclusive-OR of R_OK, W_OK, and X_OK.\n" -" dir_fd\n" -" If not None, it should be a file descriptor open to a directory,\n" -" and path should be relative; path will then be relative to that\n" -" directory.\n" -" effective_ids\n" -" If True, access will use the effective uid/gid instead of\n" -" the real uid/gid.\n" -" follow_symlinks\n" -" If False, and the last element of the path is a symbolic link,\n" -" access will examine the symbolic link itself instead of the file\n" -" the link points to.\n" -"\n" -"dir_fd, effective_ids, and follow_symlinks may not be implemented\n" -" on your platform. If they are unavailable, using them will raise a\n" -" NotImplementedError.\n" -"\n" -"Note that most operations will use the effective uid/gid, therefore this\n" -" routine can be used in a suid/sgid environment to test if the invoking user\n" -" has the specified access to the path."); - -#define OS_ACCESS_METHODDEF \ - {"access", (PyCFunction)os_access, METH_VARARGS|METH_KEYWORDS, os_access__doc__}, - -static int -os_access_impl(PyModuleDef *module, path_t *path, int mode, int dir_fd, int effective_ids, int follow_symlinks); - -static PyObject * -os_access(PyModuleDef *module, PyObject *args, PyObject *kwargs) -{ - PyObject *return_value = NULL; - static char *_keywords[] = {"path", "mode", "dir_fd", "effective_ids", "follow_symlinks", NULL}; - path_t path = PATH_T_INITIALIZE("access", "path", 0, 1); - int mode; - int dir_fd = DEFAULT_DIR_FD; - int effective_ids = 0; - int follow_symlinks = 1; - int _return_value; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "O&i|$O&pp:access", _keywords, - path_converter, &path, &mode, FACCESSAT_DIR_FD_CONVERTER, &dir_fd, &effective_ids, &follow_symlinks)) - goto exit; - _return_value = os_access_impl(module, &path, mode, dir_fd, effective_ids, follow_symlinks); - if ((_return_value == -1) && PyErr_Occurred()) - goto exit; - return_value = PyBool_FromLong((long)_return_value); - -exit: - /* Cleanup for path */ - path_cleanup(&path); - - return return_value; -} - static int os_access_impl(PyModuleDef *module, path_t *path, int mode, int dir_fd, int effective_ids, int follow_symlinks) -/*[clinic end generated code: output=dfd404666906f012 input=b75a756797af45ec]*/ +/*[clinic end generated code: output=f9e734db3d88b767 input=b75a756797af45ec]*/ { int return_value; @@ -2787,44 +2633,9 @@ Return the name of the terminal device connected to 'fd'. [clinic start generated code]*/ -PyDoc_STRVAR(os_ttyname__doc__, -"ttyname($module, fd, /)\n" -"--\n" -"\n" -"Return the name of the terminal device connected to \'fd\'.\n" -"\n" -" fd\n" -" Integer file descriptor handle."); - -#define OS_TTYNAME_METHODDEF \ - {"ttyname", (PyCFunction)os_ttyname, METH_VARARGS, os_ttyname__doc__}, - -static char * -os_ttyname_impl(PyModuleDef *module, int fd); - -static PyObject * -os_ttyname(PyModuleDef *module, PyObject *args) -{ - PyObject *return_value = NULL; - int fd; - char *_return_value; - - if (!PyArg_ParseTuple(args, - "i:ttyname", - &fd)) - goto exit; - _return_value = os_ttyname_impl(module, fd); - if (_return_value == NULL) - goto exit; - return_value = PyUnicode_DecodeFSDefault(_return_value); - -exit: - return return_value; -} - static char * os_ttyname_impl(PyModuleDef *module, int fd) -/*[clinic end generated code: output=cee7bc4cffec01a2 input=5f72ca83e76b3b45]*/ +/*[clinic end generated code: output=03ad3d5ccaef75c3 input=5f72ca83e76b3b45]*/ { char *ret; @@ -2842,27 +2653,9 @@ Return the name of the controlling terminal for this process. [clinic start generated code]*/ -PyDoc_STRVAR(os_ctermid__doc__, -"ctermid($module, /)\n" -"--\n" -"\n" -"Return the name of the controlling terminal for this process."); - -#define OS_CTERMID_METHODDEF \ - {"ctermid", (PyCFunction)os_ctermid, METH_NOARGS, os_ctermid__doc__}, - -static PyObject * -os_ctermid_impl(PyModuleDef *module); - -static PyObject * -os_ctermid(PyModuleDef *module, PyObject *Py_UNUSED(ignored)) -{ - return os_ctermid_impl(module); -} - static PyObject * os_ctermid_impl(PyModuleDef *module) -/*[clinic end generated code: output=277bf7964ec2d782 input=3b87fdd52556382d]*/ +/*[clinic end generated code: output=1b73788201e0aebd input=3b87fdd52556382d]*/ { char *ret; char buffer[L_ctermid]; @@ -2891,45 +2684,9 @@ If this functionality is unavailable, using it raises an exception. [clinic start generated code]*/ -PyDoc_STRVAR(os_chdir__doc__, -"chdir($module, /, path)\n" -"--\n" -"\n" -"Change the current working directory to the specified path.\n" -"\n" -"path may always be specified as a string.\n" -"On some platforms, path may also be specified as an open file descriptor.\n" -" If this functionality is unavailable, using it raises an exception."); - -#define OS_CHDIR_METHODDEF \ - {"chdir", (PyCFunction)os_chdir, METH_VARARGS|METH_KEYWORDS, os_chdir__doc__}, - -static PyObject * -os_chdir_impl(PyModuleDef *module, path_t *path); - -static PyObject * -os_chdir(PyModuleDef *module, PyObject *args, PyObject *kwargs) -{ - PyObject *return_value = NULL; - static char *_keywords[] = {"path", NULL}; - path_t path = PATH_T_INITIALIZE("chdir", "path", 0, PATH_HAVE_FCHDIR); - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "O&:chdir", _keywords, - path_converter, &path)) - goto exit; - return_value = os_chdir_impl(module, &path); - -exit: - /* Cleanup for path */ - path_cleanup(&path); - - return return_value; -} - static PyObject * os_chdir_impl(PyModuleDef *module, path_t *path) -/*[clinic end generated code: output=cc07592dd23ca9e0 input=1a4a15b4d12cb15d]*/ +/*[clinic end generated code: output=7358e3a20fb5aa93 input=1a4a15b4d12cb15d]*/ { int result; @@ -2971,41 +2728,9 @@ [clinic start generated code]*/ -PyDoc_STRVAR(os_fchdir__doc__, -"fchdir($module, /, fd)\n" -"--\n" -"\n" -"Change to the directory of the given file descriptor.\n" -"\n" -"fd must be opened on a directory, not a file.\n" -"Equivalent to os.chdir(fd)."); - -#define OS_FCHDIR_METHODDEF \ - {"fchdir", (PyCFunction)os_fchdir, METH_VARARGS|METH_KEYWORDS, os_fchdir__doc__}, - -static PyObject * -os_fchdir_impl(PyModuleDef *module, int fd); - -static PyObject * -os_fchdir(PyModuleDef *module, PyObject *args, PyObject *kwargs) -{ - PyObject *return_value = NULL; - static char *_keywords[] = {"fd", NULL}; - int fd; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "O&:fchdir", _keywords, - fildes_converter, &fd)) - goto exit; - return_value = os_fchdir_impl(module, fd); - -exit: - return return_value; -} - static PyObject * os_fchdir_impl(PyModuleDef *module, int fd) -/*[clinic end generated code: output=9f6dbc89b2778834 input=18e816479a2fa985]*/ +/*[clinic end generated code: output=361d30df6b2d3418 input=18e816479a2fa985]*/ { return posix_fildes_fd(fd, fchdir); } @@ -3044,64 +2769,9 @@ [clinic start generated code]*/ -PyDoc_STRVAR(os_chmod__doc__, -"chmod($module, /, path, mode, *, dir_fd=None, follow_symlinks=True)\n" -"--\n" -"\n" -"Change the access permissions of a file.\n" -"\n" -" path\n" -" Path to be modified. May always be specified as a str or bytes.\n" -" On some platforms, path may also be specified as an open file descriptor.\n" -" If this functionality is unavailable, using it raises an exception.\n" -" mode\n" -" Operating-system mode bitfield.\n" -" dir_fd\n" -" If not None, it should be a file descriptor open to a directory,\n" -" and path should be relative; path will then be relative to that\n" -" directory.\n" -" follow_symlinks\n" -" If False, and the last element of the path is a symbolic link,\n" -" chmod will modify the symbolic link itself instead of the file\n" -" the link points to.\n" -"\n" -"It is an error to use dir_fd or follow_symlinks when specifying path as\n" -" an open file descriptor.\n" -"dir_fd and follow_symlinks may not be implemented on your platform.\n" -" If they are unavailable, using them will raise a NotImplementedError."); - -#define OS_CHMOD_METHODDEF \ - {"chmod", (PyCFunction)os_chmod, METH_VARARGS|METH_KEYWORDS, os_chmod__doc__}, - -static PyObject * -os_chmod_impl(PyModuleDef *module, path_t *path, int mode, int dir_fd, int follow_symlinks); - -static PyObject * -os_chmod(PyModuleDef *module, PyObject *args, PyObject *kwargs) -{ - PyObject *return_value = NULL; - static char *_keywords[] = {"path", "mode", "dir_fd", "follow_symlinks", NULL}; - path_t path = PATH_T_INITIALIZE("chmod", "path", 0, PATH_HAVE_FCHMOD); - int mode; - int dir_fd = DEFAULT_DIR_FD; - int follow_symlinks = 1; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "O&i|$O&p:chmod", _keywords, - path_converter, &path, &mode, FCHMODAT_DIR_FD_CONVERTER, &dir_fd, &follow_symlinks)) - goto exit; - return_value = os_chmod_impl(module, &path, mode, dir_fd, follow_symlinks); - -exit: - /* Cleanup for path */ - path_cleanup(&path); - - return return_value; -} - static PyObject * os_chmod_impl(PyModuleDef *module, path_t *path, int mode, int dir_fd, int follow_symlinks) -/*[clinic end generated code: output=1e9db031aea46422 input=7f1618e5e15cc196]*/ +/*[clinic end generated code: output=96063c976f23106a input=7f1618e5e15cc196]*/ { int result; @@ -3212,41 +2882,9 @@ Equivalent to os.chmod(fd, mode). [clinic start generated code]*/ -PyDoc_STRVAR(os_fchmod__doc__, -"fchmod($module, /, fd, mode)\n" -"--\n" -"\n" -"Change the access permissions of the file given by file descriptor fd.\n" -"\n" -"Equivalent to os.chmod(fd, mode)."); - -#define OS_FCHMOD_METHODDEF \ - {"fchmod", (PyCFunction)os_fchmod, METH_VARARGS|METH_KEYWORDS, os_fchmod__doc__}, - -static PyObject * -os_fchmod_impl(PyModuleDef *module, int fd, int mode); - -static PyObject * -os_fchmod(PyModuleDef *module, PyObject *args, PyObject *kwargs) -{ - PyObject *return_value = NULL; - static char *_keywords[] = {"fd", "mode", NULL}; - int fd; - int mode; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "ii:fchmod", _keywords, - &fd, &mode)) - goto exit; - return_value = os_fchmod_impl(module, fd, mode); - -exit: - return return_value; -} - static PyObject * os_fchmod_impl(PyModuleDef *module, int fd, int mode) -/*[clinic end generated code: output=3c19fbfd724a8e0f input=8ab11975ca01ee5b]*/ +/*[clinic end generated code: output=2ee31ca226d1ed33 input=8ab11975ca01ee5b]*/ { int res; int async_err = 0; @@ -3277,45 +2915,9 @@ Equivalent to chmod(path, mode, follow_symlinks=False)." [clinic start generated code]*/ -PyDoc_STRVAR(os_lchmod__doc__, -"lchmod($module, /, path, mode)\n" -"--\n" -"\n" -"Change the access permissions of a file, without following symbolic links.\n" -"\n" -"If path is a symlink, this affects the link itself rather than the target.\n" -"Equivalent to chmod(path, mode, follow_symlinks=False).\""); - -#define OS_LCHMOD_METHODDEF \ - {"lchmod", (PyCFunction)os_lchmod, METH_VARARGS|METH_KEYWORDS, os_lchmod__doc__}, - -static PyObject * -os_lchmod_impl(PyModuleDef *module, path_t *path, int mode); - -static PyObject * -os_lchmod(PyModuleDef *module, PyObject *args, PyObject *kwargs) -{ - PyObject *return_value = NULL; - static char *_keywords[] = {"path", "mode", NULL}; - path_t path = PATH_T_INITIALIZE("lchmod", "path", 0, 0); - int mode; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "O&i:lchmod", _keywords, - path_converter, &path, &mode)) - goto exit; - return_value = os_lchmod_impl(module, &path, mode); - -exit: - /* Cleanup for path */ - path_cleanup(&path); - - return return_value; -} - static PyObject * os_lchmod_impl(PyModuleDef *module, path_t *path, int mode) -/*[clinic end generated code: output=2849977d65f8c68c input=90c5663c7465d24f]*/ +/*[clinic end generated code: output=7c0cc46588d89e46 input=90c5663c7465d24f]*/ { int res; Py_BEGIN_ALLOW_THREADS @@ -3348,49 +2950,9 @@ [clinic start generated code]*/ -PyDoc_STRVAR(os_chflags__doc__, -"chflags($module, /, path, flags, follow_symlinks=True)\n" -"--\n" -"\n" -"Set file flags.\n" -"\n" -"If follow_symlinks is False, and the last element of the path is a symbolic\n" -" link, chflags will change flags on the symbolic link itself instead of the\n" -" file the link points to.\n" -"follow_symlinks may not be implemented on your platform. If it is\n" -"unavailable, using it will raise a NotImplementedError."); - -#define OS_CHFLAGS_METHODDEF \ - {"chflags", (PyCFunction)os_chflags, METH_VARARGS|METH_KEYWORDS, os_chflags__doc__}, - -static PyObject * -os_chflags_impl(PyModuleDef *module, path_t *path, unsigned long flags, int follow_symlinks); - -static PyObject * -os_chflags(PyModuleDef *module, PyObject *args, PyObject *kwargs) -{ - PyObject *return_value = NULL; - static char *_keywords[] = {"path", "flags", "follow_symlinks", NULL}; - path_t path = PATH_T_INITIALIZE("chflags", "path", 0, 0); - unsigned long flags; - int follow_symlinks = 1; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "O&k|p:chflags", _keywords, - path_converter, &path, &flags, &follow_symlinks)) - goto exit; - return_value = os_chflags_impl(module, &path, flags, follow_symlinks); - -exit: - /* Cleanup for path */ - path_cleanup(&path); - - return return_value; -} - static PyObject * os_chflags_impl(PyModuleDef *module, path_t *path, unsigned long flags, int follow_symlinks) -/*[clinic end generated code: output=2767927bf071e3cf input=0327e29feb876236]*/ +/*[clinic end generated code: output=9e5f9417afc20c4b input=0327e29feb876236]*/ { int result; @@ -3429,45 +2991,9 @@ Equivalent to chflags(path, flags, follow_symlinks=False). [clinic start generated code]*/ -PyDoc_STRVAR(os_lchflags__doc__, -"lchflags($module, /, path, flags)\n" -"--\n" -"\n" -"Set file flags.\n" -"\n" -"This function will not follow symbolic links.\n" -"Equivalent to chflags(path, flags, follow_symlinks=False)."); - -#define OS_LCHFLAGS_METHODDEF \ - {"lchflags", (PyCFunction)os_lchflags, METH_VARARGS|METH_KEYWORDS, os_lchflags__doc__}, - -static PyObject * -os_lchflags_impl(PyModuleDef *module, path_t *path, unsigned long flags); - -static PyObject * -os_lchflags(PyModuleDef *module, PyObject *args, PyObject *kwargs) -{ - PyObject *return_value = NULL; - static char *_keywords[] = {"path", "flags", NULL}; - path_t path = PATH_T_INITIALIZE("lchflags", "path", 0, 0); - unsigned long flags; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "O&k:lchflags", _keywords, - path_converter, &path, &flags)) - goto exit; - return_value = os_lchflags_impl(module, &path, flags); - -exit: - /* Cleanup for path */ - path_cleanup(&path); - - return return_value; -} - static PyObject * os_lchflags_impl(PyModuleDef *module, path_t *path, unsigned long flags) -/*[clinic end generated code: output=bb93b6b8a5e45aa7 input=f9f82ea8b585ca9d]*/ +/*[clinic end generated code: output=6741322fb949661b input=f9f82ea8b585ca9d]*/ { int res; Py_BEGIN_ALLOW_THREADS @@ -3490,41 +3016,9 @@ [clinic start generated code]*/ -PyDoc_STRVAR(os_chroot__doc__, -"chroot($module, /, path)\n" -"--\n" -"\n" -"Change root directory to path."); - -#define OS_CHROOT_METHODDEF \ - {"chroot", (PyCFunction)os_chroot, METH_VARARGS|METH_KEYWORDS, os_chroot__doc__}, - -static PyObject * -os_chroot_impl(PyModuleDef *module, path_t *path); - -static PyObject * -os_chroot(PyModuleDef *module, PyObject *args, PyObject *kwargs) -{ - PyObject *return_value = NULL; - static char *_keywords[] = {"path", NULL}; - path_t path = PATH_T_INITIALIZE("chroot", "path", 0, 0); - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "O&:chroot", _keywords, - path_converter, &path)) - goto exit; - return_value = os_chroot_impl(module, &path); - -exit: - /* Cleanup for path */ - path_cleanup(&path); - - return return_value; -} - static PyObject * os_chroot_impl(PyModuleDef *module, path_t *path) -/*[clinic end generated code: output=15b1256cbe4f24a1 input=14822965652c3dc3]*/ +/*[clinic end generated code: output=b6dbfabe74ecaa9d input=14822965652c3dc3]*/ { int res; Py_BEGIN_ALLOW_THREADS @@ -3546,38 +3040,9 @@ Force write of fd to disk. [clinic start generated code]*/ -PyDoc_STRVAR(os_fsync__doc__, -"fsync($module, /, fd)\n" -"--\n" -"\n" -"Force write of fd to disk."); - -#define OS_FSYNC_METHODDEF \ - {"fsync", (PyCFunction)os_fsync, METH_VARARGS|METH_KEYWORDS, os_fsync__doc__}, - -static PyObject * -os_fsync_impl(PyModuleDef *module, int fd); - -static PyObject * -os_fsync(PyModuleDef *module, PyObject *args, PyObject *kwargs) -{ - PyObject *return_value = NULL; - static char *_keywords[] = {"fd", NULL}; - int fd; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "O&:fsync", _keywords, - fildes_converter, &fd)) - goto exit; - return_value = os_fsync_impl(module, fd); - -exit: - return return_value; -} - static PyObject * os_fsync_impl(PyModuleDef *module, int fd) -/*[clinic end generated code: output=59f32d3a0b360133 input=21c3645c056967f2]*/ +/*[clinic end generated code: output=83a350851064aea7 input=21c3645c056967f2]*/ { return posix_fildes_fd(fd, fsync); } @@ -3591,27 +3056,9 @@ Force write of everything to disk. [clinic start generated code]*/ -PyDoc_STRVAR(os_sync__doc__, -"sync($module, /)\n" -"--\n" -"\n" -"Force write of everything to disk."); - -#define OS_SYNC_METHODDEF \ - {"sync", (PyCFunction)os_sync, METH_NOARGS, os_sync__doc__}, - -static PyObject * -os_sync_impl(PyModuleDef *module); - -static PyObject * -os_sync(PyModuleDef *module, PyObject *Py_UNUSED(ignored)) -{ - return os_sync_impl(module); -} - static PyObject * os_sync_impl(PyModuleDef *module) -/*[clinic end generated code: output=526c495683d0bb38 input=84749fe5e9b404ff]*/ +/*[clinic end generated code: output=ba524f656c201c40 input=84749fe5e9b404ff]*/ { Py_BEGIN_ALLOW_THREADS sync(); @@ -3634,38 +3081,9 @@ Force write of fd to disk without forcing update of metadata. [clinic start generated code]*/ -PyDoc_STRVAR(os_fdatasync__doc__, -"fdatasync($module, /, fd)\n" -"--\n" -"\n" -"Force write of fd to disk without forcing update of metadata."); - -#define OS_FDATASYNC_METHODDEF \ - {"fdatasync", (PyCFunction)os_fdatasync, METH_VARARGS|METH_KEYWORDS, os_fdatasync__doc__}, - -static PyObject * -os_fdatasync_impl(PyModuleDef *module, int fd); - -static PyObject * -os_fdatasync(PyModuleDef *module, PyObject *args, PyObject *kwargs) -{ - PyObject *return_value = NULL; - static char *_keywords[] = {"fd", NULL}; - int fd; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "O&:fdatasync", _keywords, - fildes_converter, &fd)) - goto exit; - return_value = os_fdatasync_impl(module, fd); - -exit: - return return_value; -} - static PyObject * os_fdatasync_impl(PyModuleDef *module, int fd) -/*[clinic end generated code: output=2335fdfd37c92180 input=bc74791ee54dd291]*/ +/*[clinic end generated code: output=e0f04a3aff515b75 input=bc74791ee54dd291]*/ { return posix_fildes_fd(fd, fdatasync); } @@ -3712,69 +3130,9 @@ [clinic start generated code]*/ -PyDoc_STRVAR(os_chown__doc__, -"chown($module, /, path, uid, gid, *, dir_fd=None, follow_symlinks=True)\n" -"--\n" -"\n" -"Change the owner and group id of path to the numeric uid and gid.\\\n" -"\n" -" path\n" -" Path to be examined; can be string, bytes, or open-file-descriptor int.\n" -" dir_fd\n" -" If not None, it should be a file descriptor open to a directory,\n" -" and path should be relative; path will then be relative to that\n" -" directory.\n" -" follow_symlinks\n" -" If False, and the last element of the path is a symbolic link,\n" -" stat will examine the symbolic link itself instead of the file\n" -" the link points to.\n" -"\n" -"path may always be specified as a string.\n" -"On some platforms, path may also be specified as an open file descriptor.\n" -" If this functionality is unavailable, using it raises an exception.\n" -"If dir_fd is not None, it should be a file descriptor open to a directory,\n" -" and path should be relative; path will then be relative to that directory.\n" -"If follow_symlinks is False, and the last element of the path is a symbolic\n" -" link, chown will modify the symbolic link itself instead of the file the\n" -" link points to.\n" -"It is an error to use dir_fd or follow_symlinks when specifying path as\n" -" an open file descriptor.\n" -"dir_fd and follow_symlinks may not be implemented on your platform.\n" -" If they are unavailable, using them will raise a NotImplementedError."); - -#define OS_CHOWN_METHODDEF \ - {"chown", (PyCFunction)os_chown, METH_VARARGS|METH_KEYWORDS, os_chown__doc__}, - -static PyObject * -os_chown_impl(PyModuleDef *module, path_t *path, uid_t uid, gid_t gid, int dir_fd, int follow_symlinks); - -static PyObject * -os_chown(PyModuleDef *module, PyObject *args, PyObject *kwargs) -{ - PyObject *return_value = NULL; - static char *_keywords[] = {"path", "uid", "gid", "dir_fd", "follow_symlinks", NULL}; - path_t path = PATH_T_INITIALIZE("chown", "path", 0, PATH_HAVE_FCHOWN); - uid_t uid; - gid_t gid; - int dir_fd = DEFAULT_DIR_FD; - int follow_symlinks = 1; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "O&O&O&|$O&p:chown", _keywords, - path_converter, &path, _Py_Uid_Converter, &uid, _Py_Gid_Converter, &gid, FCHOWNAT_DIR_FD_CONVERTER, &dir_fd, &follow_symlinks)) - goto exit; - return_value = os_chown_impl(module, &path, uid, gid, dir_fd, follow_symlinks); - -exit: - /* Cleanup for path */ - path_cleanup(&path); - - return return_value; -} - static PyObject * os_chown_impl(PyModuleDef *module, path_t *path, uid_t uid, gid_t gid, int dir_fd, int follow_symlinks) -/*[clinic end generated code: output=22f011e3b4f9ff49 input=a61cc35574814d5d]*/ +/*[clinic end generated code: output=59a8db91897fb46c input=a61cc35574814d5d]*/ { int result; @@ -3841,42 +3199,9 @@ [clinic start generated code]*/ -PyDoc_STRVAR(os_fchown__doc__, -"fchown($module, /, fd, uid, gid)\n" -"--\n" -"\n" -"Change the owner and group id of the file specified by file descriptor.\n" -"\n" -"Equivalent to os.chown(fd, uid, gid)."); - -#define OS_FCHOWN_METHODDEF \ - {"fchown", (PyCFunction)os_fchown, METH_VARARGS|METH_KEYWORDS, os_fchown__doc__}, - -static PyObject * -os_fchown_impl(PyModuleDef *module, int fd, uid_t uid, gid_t gid); - -static PyObject * -os_fchown(PyModuleDef *module, PyObject *args, PyObject *kwargs) -{ - PyObject *return_value = NULL; - static char *_keywords[] = {"fd", "uid", "gid", NULL}; - int fd; - uid_t uid; - gid_t gid; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "iO&O&:fchown", _keywords, - &fd, _Py_Uid_Converter, &uid, _Py_Gid_Converter, &gid)) - goto exit; - return_value = os_fchown_impl(module, fd, uid, gid); - -exit: - return return_value; -} - static PyObject * os_fchown_impl(PyModuleDef *module, int fd, uid_t uid, gid_t gid) -/*[clinic end generated code: output=687781cb7d8974d6 input=3af544ba1b13a0d7]*/ +/*[clinic end generated code: output=7545abf8f6086d76 input=3af544ba1b13a0d7]*/ { int res; int async_err = 0; @@ -3908,46 +3233,9 @@ Equivalent to os.chown(path, uid, gid, follow_symlinks=False). [clinic start generated code]*/ -PyDoc_STRVAR(os_lchown__doc__, -"lchown($module, /, path, uid, gid)\n" -"--\n" -"\n" -"Change the owner and group id of path to the numeric uid and gid.\n" -"\n" -"This function will not follow symbolic links.\n" -"Equivalent to os.chown(path, uid, gid, follow_symlinks=False)."); - -#define OS_LCHOWN_METHODDEF \ - {"lchown", (PyCFunction)os_lchown, METH_VARARGS|METH_KEYWORDS, os_lchown__doc__}, - -static PyObject * -os_lchown_impl(PyModuleDef *module, path_t *path, uid_t uid, gid_t gid); - -static PyObject * -os_lchown(PyModuleDef *module, PyObject *args, PyObject *kwargs) -{ - PyObject *return_value = NULL; - static char *_keywords[] = {"path", "uid", "gid", NULL}; - path_t path = PATH_T_INITIALIZE("lchown", "path", 0, 0); - uid_t uid; - gid_t gid; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "O&O&O&:lchown", _keywords, - path_converter, &path, _Py_Uid_Converter, &uid, _Py_Gid_Converter, &gid)) - goto exit; - return_value = os_lchown_impl(module, &path, uid, gid); - -exit: - /* Cleanup for path */ - path_cleanup(&path); - - return return_value; -} - static PyObject * os_lchown_impl(PyModuleDef *module, path_t *path, uid_t uid, gid_t gid) -/*[clinic end generated code: output=bf25fdb0d25130e2 input=b1c6014d563a7161]*/ +/*[clinic end generated code: output=bb0d2da1579ac275 input=b1c6014d563a7161]*/ { int res; Py_BEGIN_ALLOW_THREADS @@ -4020,27 +3308,9 @@ Return a unicode string representing the current working directory. [clinic start generated code]*/ -PyDoc_STRVAR(os_getcwd__doc__, -"getcwd($module, /)\n" -"--\n" -"\n" -"Return a unicode string representing the current working directory."); - -#define OS_GETCWD_METHODDEF \ - {"getcwd", (PyCFunction)os_getcwd, METH_NOARGS, os_getcwd__doc__}, - -static PyObject * -os_getcwd_impl(PyModuleDef *module); - -static PyObject * -os_getcwd(PyModuleDef *module, PyObject *Py_UNUSED(ignored)) -{ - return os_getcwd_impl(module); -} - static PyObject * os_getcwd_impl(PyModuleDef *module) -/*[clinic end generated code: output=d70b281db5c78ff7 input=f069211bb70e3d39]*/ +/*[clinic end generated code: output=efe3a8c0121525ea input=f069211bb70e3d39]*/ { return posix_getcwd(0); } @@ -4052,27 +3322,9 @@ Return a bytes string representing the current working directory. [clinic start generated code]*/ -PyDoc_STRVAR(os_getcwdb__doc__, -"getcwdb($module, /)\n" -"--\n" -"\n" -"Return a bytes string representing the current working directory."); - -#define OS_GETCWDB_METHODDEF \ - {"getcwdb", (PyCFunction)os_getcwdb, METH_NOARGS, os_getcwdb__doc__}, - -static PyObject * -os_getcwdb_impl(PyModuleDef *module); - -static PyObject * -os_getcwdb(PyModuleDef *module, PyObject *Py_UNUSED(ignored)) -{ - return os_getcwdb_impl(module); -} - static PyObject * os_getcwdb_impl(PyModuleDef *module) -/*[clinic end generated code: output=75da47f2d75f9166 input=f6f6a378dad3d9cb]*/ +/*[clinic end generated code: output=7fce42ee4b2a296a input=f6f6a378dad3d9cb]*/ { return posix_getcwd(1); } @@ -4107,58 +3359,9 @@ NotImplementedError. [clinic start generated code]*/ -PyDoc_STRVAR(os_link__doc__, -"link($module, /, src, dst, *, src_dir_fd=None, dst_dir_fd=None,\n" -" follow_symlinks=True)\n" -"--\n" -"\n" -"Create a hard link to a file.\n" -"\n" -"If either src_dir_fd or dst_dir_fd is not None, it should be a file\n" -" descriptor open to a directory, and the respective path string (src or dst)\n" -" should be relative; the path will then be relative to that directory.\n" -"If follow_symlinks is False, and the last element of src is a symbolic\n" -" link, link will create a link to the symbolic link itself instead of the\n" -" file the link points to.\n" -"src_dir_fd, dst_dir_fd, and follow_symlinks may not be implemented on your\n" -" platform. If they are unavailable, using them will raise a\n" -" NotImplementedError."); - -#define OS_LINK_METHODDEF \ - {"link", (PyCFunction)os_link, METH_VARARGS|METH_KEYWORDS, os_link__doc__}, - -static PyObject * -os_link_impl(PyModuleDef *module, path_t *src, path_t *dst, int src_dir_fd, int dst_dir_fd, int follow_symlinks); - -static PyObject * -os_link(PyModuleDef *module, PyObject *args, PyObject *kwargs) -{ - PyObject *return_value = NULL; - static char *_keywords[] = {"src", "dst", "src_dir_fd", "dst_dir_fd", "follow_symlinks", NULL}; - path_t src = PATH_T_INITIALIZE("link", "src", 0, 0); - path_t dst = PATH_T_INITIALIZE("link", "dst", 0, 0); - int src_dir_fd = DEFAULT_DIR_FD; - int dst_dir_fd = DEFAULT_DIR_FD; - int follow_symlinks = 1; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "O&O&|$O&O&p:link", _keywords, - path_converter, &src, path_converter, &dst, dir_fd_converter, &src_dir_fd, dir_fd_converter, &dst_dir_fd, &follow_symlinks)) - goto exit; - return_value = os_link_impl(module, &src, &dst, src_dir_fd, dst_dir_fd, follow_symlinks); - -exit: - /* Cleanup for src */ - path_cleanup(&src); - /* Cleanup for dst */ - path_cleanup(&dst); - - return return_value; -} - static PyObject * os_link_impl(PyModuleDef *module, path_t *src, path_t *dst, int src_dir_fd, int dst_dir_fd, int follow_symlinks) -/*[clinic end generated code: output=53477662fe02e183 input=b0095ebbcbaa7e04]*/ +/*[clinic end generated code: output=c0a9ded8111d2a79 input=b0095ebbcbaa7e04]*/ { #ifdef MS_WINDOWS BOOL result; @@ -4496,52 +3699,9 @@ [clinic start generated code]*/ -PyDoc_STRVAR(os_listdir__doc__, -"listdir($module, /, path=None)\n" -"--\n" -"\n" -"Return a list containing the names of the files in the directory.\n" -"\n" -"path can be specified as either str or bytes. If path is bytes,\n" -" the filenames returned will also be bytes; in all other circumstances\n" -" the filenames returned will be str.\n" -"If path is None, uses the path=\'.\'.\n" -"On some platforms, path may also be specified as an open file descriptor;\\\n" -" the file descriptor must refer to a directory.\n" -" If this functionality is unavailable, using it raises NotImplementedError.\n" -"\n" -"The list is in arbitrary order. It does not include the special\n" -"entries \'.\' and \'..\' even if they are present in the directory."); - -#define OS_LISTDIR_METHODDEF \ - {"listdir", (PyCFunction)os_listdir, METH_VARARGS|METH_KEYWORDS, os_listdir__doc__}, - -static PyObject * -os_listdir_impl(PyModuleDef *module, path_t *path); - -static PyObject * -os_listdir(PyModuleDef *module, PyObject *args, PyObject *kwargs) -{ - PyObject *return_value = NULL; - static char *_keywords[] = {"path", NULL}; - path_t path = PATH_T_INITIALIZE("listdir", "path", 1, PATH_HAVE_FDOPENDIR); - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "|O&:listdir", _keywords, - path_converter, &path)) - goto exit; - return_value = os_listdir_impl(module, &path); - -exit: - /* Cleanup for path */ - path_cleanup(&path); - - return return_value; -} - static PyObject * os_listdir_impl(PyModuleDef *module, path_t *path) -/*[clinic end generated code: output=e159bd9be6909018 input=09e300416e3cd729]*/ +/*[clinic end generated code: output=1fbe67c1f780c8b7 input=09e300416e3cd729]*/ { #if defined(MS_WINDOWS) && !defined(HAVE_OPENDIR) return _listdir_windows_no_opendir(path, NULL); @@ -4620,37 +3780,9 @@ A helper function for samepath on windows. [clinic start generated code]*/ -PyDoc_STRVAR(os__getfinalpathname__doc__, -"_getfinalpathname($module, path, /)\n" -"--\n" -"\n" -"A helper function for samepath on windows."); - -#define OS__GETFINALPATHNAME_METHODDEF \ - {"_getfinalpathname", (PyCFunction)os__getfinalpathname, METH_VARARGS, os__getfinalpathname__doc__}, - -static PyObject * -os__getfinalpathname_impl(PyModuleDef *module, PyObject *path); - -static PyObject * -os__getfinalpathname(PyModuleDef *module, PyObject *args) -{ - PyObject *return_value = NULL; - PyObject *path; - - if (!PyArg_ParseTuple(args, - "U:_getfinalpathname", - &path)) - goto exit; - return_value = os__getfinalpathname_impl(module, path); - -exit: - return return_value; -} - static PyObject * os__getfinalpathname_impl(PyModuleDef *module, PyObject *path) -/*[clinic end generated code: output=4563c6eacf1b0881 input=71d5e89334891bf4]*/ +/*[clinic end generated code: output=8be81a5f51a34bcf input=71d5e89334891bf4]*/ { HANDLE hFile; int buf_size; @@ -4750,38 +3882,9 @@ A helper function for ismount on Win32. [clinic start generated code]*/ -PyDoc_STRVAR(os__getvolumepathname__doc__, -"_getvolumepathname($module, /, path)\n" -"--\n" -"\n" -"A helper function for ismount on Win32."); - -#define OS__GETVOLUMEPATHNAME_METHODDEF \ - {"_getvolumepathname", (PyCFunction)os__getvolumepathname, METH_VARARGS|METH_KEYWORDS, os__getvolumepathname__doc__}, - -static PyObject * -os__getvolumepathname_impl(PyModuleDef *module, PyObject *path); - -static PyObject * -os__getvolumepathname(PyModuleDef *module, PyObject *args, PyObject *kwargs) -{ - PyObject *return_value = NULL; - static char *_keywords[] = {"path", NULL}; - PyObject *path; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "U:_getvolumepathname", _keywords, - &path)) - goto exit; - return_value = os__getvolumepathname_impl(module, path); - -exit: - return return_value; -} - static PyObject * os__getvolumepathname_impl(PyModuleDef *module, PyObject *path) -/*[clinic end generated code: output=ac0833b6d6da7657 input=7eacadc40acbda6b]*/ +/*[clinic end generated code: output=79a0ba729f956dbe input=7eacadc40acbda6b]*/ { PyObject *result; wchar_t *path_wchar, *mountpath=NULL; @@ -4847,50 +3950,9 @@ The mode argument is ignored on Windows. [clinic start generated code]*/ -PyDoc_STRVAR(os_mkdir__doc__, -"mkdir($module, /, path, mode=511, *, dir_fd=None)\n" -"--\n" -"\n" -"Create a directory.\n" -"\n" -"If dir_fd is not None, it should be a file descriptor open to a directory,\n" -" and path should be relative; path will then be relative to that directory.\n" -"dir_fd may not be implemented on your platform.\n" -" If it is unavailable, using it will raise a NotImplementedError.\n" -"\n" -"The mode argument is ignored on Windows."); - -#define OS_MKDIR_METHODDEF \ - {"mkdir", (PyCFunction)os_mkdir, METH_VARARGS|METH_KEYWORDS, os_mkdir__doc__}, - -static PyObject * -os_mkdir_impl(PyModuleDef *module, path_t *path, int mode, int dir_fd); - -static PyObject * -os_mkdir(PyModuleDef *module, PyObject *args, PyObject *kwargs) -{ - PyObject *return_value = NULL; - static char *_keywords[] = {"path", "mode", "dir_fd", NULL}; - path_t path = PATH_T_INITIALIZE("mkdir", "path", 0, 0); - int mode = 511; - int dir_fd = DEFAULT_DIR_FD; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "O&|i$O&:mkdir", _keywords, - path_converter, &path, &mode, MKDIRAT_DIR_FD_CONVERTER, &dir_fd)) - goto exit; - return_value = os_mkdir_impl(module, &path, mode, dir_fd); - -exit: - /* Cleanup for path */ - path_cleanup(&path); - - return return_value; -} - static PyObject * os_mkdir_impl(PyModuleDef *module, path_t *path, int mode, int dir_fd) -/*[clinic end generated code: output=55c6ef2bc1b207e6 input=e965f68377e9b1ce]*/ +/*[clinic end generated code: output=8bf1f738873ef2c5 input=e965f68377e9b1ce]*/ { int result; @@ -4940,37 +4002,9 @@ Add increment to the priority of process and return the new priority. [clinic start generated code]*/ -PyDoc_STRVAR(os_nice__doc__, -"nice($module, increment, /)\n" -"--\n" -"\n" -"Add increment to the priority of process and return the new priority."); - -#define OS_NICE_METHODDEF \ - {"nice", (PyCFunction)os_nice, METH_VARARGS, os_nice__doc__}, - -static PyObject * -os_nice_impl(PyModuleDef *module, int increment); - -static PyObject * -os_nice(PyModuleDef *module, PyObject *args) -{ - PyObject *return_value = NULL; - int increment; - - if (!PyArg_ParseTuple(args, - "i:nice", - &increment)) - goto exit; - return_value = os_nice_impl(module, increment); - -exit: - return return_value; -} - static PyObject * os_nice_impl(PyModuleDef *module, int increment) -/*[clinic end generated code: output=c360dc2a3bd8e3d0 input=864be2d402a21da2]*/ +/*[clinic end generated code: output=8870418a3fc07b51 input=864be2d402a21da2]*/ { int value; @@ -5008,39 +4042,9 @@ Return program scheduling priority. [clinic start generated code]*/ -PyDoc_STRVAR(os_getpriority__doc__, -"getpriority($module, /, which, who)\n" -"--\n" -"\n" -"Return program scheduling priority."); - -#define OS_GETPRIORITY_METHODDEF \ - {"getpriority", (PyCFunction)os_getpriority, METH_VARARGS|METH_KEYWORDS, os_getpriority__doc__}, - -static PyObject * -os_getpriority_impl(PyModuleDef *module, int which, int who); - -static PyObject * -os_getpriority(PyModuleDef *module, PyObject *args, PyObject *kwargs) -{ - PyObject *return_value = NULL; - static char *_keywords[] = {"which", "who", NULL}; - int which; - int who; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "ii:getpriority", _keywords, - &which, &who)) - goto exit; - return_value = os_getpriority_impl(module, which, who); - -exit: - return return_value; -} - static PyObject * os_getpriority_impl(PyModuleDef *module, int which, int who) -/*[clinic end generated code: output=81639cf765f05dae input=9be615d40e2544ef]*/ +/*[clinic end generated code: output=4759937aa5b67ed6 input=9be615d40e2544ef]*/ { int retval; @@ -5064,40 +4068,9 @@ Set program scheduling priority. [clinic start generated code]*/ -PyDoc_STRVAR(os_setpriority__doc__, -"setpriority($module, /, which, who, priority)\n" -"--\n" -"\n" -"Set program scheduling priority."); - -#define OS_SETPRIORITY_METHODDEF \ - {"setpriority", (PyCFunction)os_setpriority, METH_VARARGS|METH_KEYWORDS, os_setpriority__doc__}, - -static PyObject * -os_setpriority_impl(PyModuleDef *module, int which, int who, int priority); - -static PyObject * -os_setpriority(PyModuleDef *module, PyObject *args, PyObject *kwargs) -{ - PyObject *return_value = NULL; - static char *_keywords[] = {"which", "who", "priority", NULL}; - int which; - int who; - int priority; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "iii:setpriority", _keywords, - &which, &who, &priority)) - goto exit; - return_value = os_setpriority_impl(module, which, who, priority); - -exit: - return return_value; -} - static PyObject * os_setpriority_impl(PyModuleDef *module, int which, int who, int priority) -/*[clinic end generated code: output=ddad62651fb2120c input=710ccbf65b9dc513]*/ +/*[clinic end generated code: output=6497d3301547e7d5 input=710ccbf65b9dc513]*/ { int retval; @@ -5183,52 +4156,9 @@ If they are unavailable, using them will raise a NotImplementedError. [clinic start generated code]*/ -PyDoc_STRVAR(os_rename__doc__, -"rename($module, /, src, dst, *, src_dir_fd=None, dst_dir_fd=None)\n" -"--\n" -"\n" -"Rename a file or directory.\n" -"\n" -"If either src_dir_fd or dst_dir_fd is not None, it should be a file\n" -" descriptor open to a directory, and the respective path string (src or dst)\n" -" should be relative; the path will then be relative to that directory.\n" -"src_dir_fd and dst_dir_fd, may not be implemented on your platform.\n" -" If they are unavailable, using them will raise a NotImplementedError."); - -#define OS_RENAME_METHODDEF \ - {"rename", (PyCFunction)os_rename, METH_VARARGS|METH_KEYWORDS, os_rename__doc__}, - -static PyObject * -os_rename_impl(PyModuleDef *module, path_t *src, path_t *dst, int src_dir_fd, int dst_dir_fd); - -static PyObject * -os_rename(PyModuleDef *module, PyObject *args, PyObject *kwargs) -{ - PyObject *return_value = NULL; - static char *_keywords[] = {"src", "dst", "src_dir_fd", "dst_dir_fd", NULL}; - path_t src = PATH_T_INITIALIZE("rename", "src", 0, 0); - path_t dst = PATH_T_INITIALIZE("rename", "dst", 0, 0); - int src_dir_fd = DEFAULT_DIR_FD; - int dst_dir_fd = DEFAULT_DIR_FD; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "O&O&|$O&O&:rename", _keywords, - path_converter, &src, path_converter, &dst, dir_fd_converter, &src_dir_fd, dir_fd_converter, &dst_dir_fd)) - goto exit; - return_value = os_rename_impl(module, &src, &dst, src_dir_fd, dst_dir_fd); - -exit: - /* Cleanup for src */ - path_cleanup(&src); - /* Cleanup for dst */ - path_cleanup(&dst); - - return return_value; -} - static PyObject * os_rename_impl(PyModuleDef *module, path_t *src, path_t *dst, int src_dir_fd, int dst_dir_fd) -/*[clinic end generated code: output=c936bdc81f460a1e input=faa61c847912c850]*/ +/*[clinic end generated code: output=1bb520bf2fad186d input=faa61c847912c850]*/ { return internal_rename(src, dst, src_dir_fd, dst_dir_fd, 0); } @@ -5246,52 +4176,9 @@ If they are unavailable, using them will raise a NotImplementedError." [clinic start generated code]*/ -PyDoc_STRVAR(os_replace__doc__, -"replace($module, /, src, dst, *, src_dir_fd=None, dst_dir_fd=None)\n" -"--\n" -"\n" -"Rename a file or directory, overwriting the destination.\n" -"\n" -"If either src_dir_fd or dst_dir_fd is not None, it should be a file\n" -" descriptor open to a directory, and the respective path string (src or dst)\n" -" should be relative; the path will then be relative to that directory.\n" -"src_dir_fd and dst_dir_fd, may not be implemented on your platform.\n" -" If they are unavailable, using them will raise a NotImplementedError.\""); - -#define OS_REPLACE_METHODDEF \ - {"replace", (PyCFunction)os_replace, METH_VARARGS|METH_KEYWORDS, os_replace__doc__}, - -static PyObject * -os_replace_impl(PyModuleDef *module, path_t *src, path_t *dst, int src_dir_fd, int dst_dir_fd); - -static PyObject * -os_replace(PyModuleDef *module, PyObject *args, PyObject *kwargs) -{ - PyObject *return_value = NULL; - static char *_keywords[] = {"src", "dst", "src_dir_fd", "dst_dir_fd", NULL}; - path_t src = PATH_T_INITIALIZE("replace", "src", 0, 0); - path_t dst = PATH_T_INITIALIZE("replace", "dst", 0, 0); - int src_dir_fd = DEFAULT_DIR_FD; - int dst_dir_fd = DEFAULT_DIR_FD; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "O&O&|$O&O&:replace", _keywords, - path_converter, &src, path_converter, &dst, dir_fd_converter, &src_dir_fd, dir_fd_converter, &dst_dir_fd)) - goto exit; - return_value = os_replace_impl(module, &src, &dst, src_dir_fd, dst_dir_fd); - -exit: - /* Cleanup for src */ - path_cleanup(&src); - /* Cleanup for dst */ - path_cleanup(&dst); - - return return_value; -} - static PyObject * os_replace_impl(PyModuleDef *module, path_t *src, path_t *dst, int src_dir_fd, int dst_dir_fd) -/*[clinic end generated code: output=224e4710d290d171 input=25515dfb107c8421]*/ +/*[clinic end generated code: output=aa9ddad55fdef8e3 input=25515dfb107c8421]*/ { return internal_rename(src, dst, src_dir_fd, dst_dir_fd, 1); } @@ -5312,47 +4199,9 @@ If it is unavailable, using it will raise a NotImplementedError. [clinic start generated code]*/ -PyDoc_STRVAR(os_rmdir__doc__, -"rmdir($module, /, path, *, dir_fd=None)\n" -"--\n" -"\n" -"Remove a directory.\n" -"\n" -"If dir_fd is not None, it should be a file descriptor open to a directory,\n" -" and path should be relative; path will then be relative to that directory.\n" -"dir_fd may not be implemented on your platform.\n" -" If it is unavailable, using it will raise a NotImplementedError."); - -#define OS_RMDIR_METHODDEF \ - {"rmdir", (PyCFunction)os_rmdir, METH_VARARGS|METH_KEYWORDS, os_rmdir__doc__}, - -static PyObject * -os_rmdir_impl(PyModuleDef *module, path_t *path, int dir_fd); - -static PyObject * -os_rmdir(PyModuleDef *module, PyObject *args, PyObject *kwargs) -{ - PyObject *return_value = NULL; - static char *_keywords[] = {"path", "dir_fd", NULL}; - path_t path = PATH_T_INITIALIZE("rmdir", "path", 0, 0); - int dir_fd = DEFAULT_DIR_FD; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "O&|$O&:rmdir", _keywords, - path_converter, &path, UNLINKAT_DIR_FD_CONVERTER, &dir_fd)) - goto exit; - return_value = os_rmdir_impl(module, &path, dir_fd); - -exit: - /* Cleanup for path */ - path_cleanup(&path); - - return return_value; -} - static PyObject * os_rmdir_impl(PyModuleDef *module, path_t *path, int dir_fd) -/*[clinic end generated code: output=70b9fdbe3bee0591 input=38c8b375ca34a7e2]*/ +/*[clinic end generated code: output=cabadec80d5a77c7 input=38c8b375ca34a7e2]*/ { int result; @@ -5390,42 +4239,9 @@ Execute the command in a subshell. [clinic start generated code]*/ -PyDoc_STRVAR(os_system__doc__, -"system($module, /, command)\n" -"--\n" -"\n" -"Execute the command in a subshell."); - -#define OS_SYSTEM_METHODDEF \ - {"system", (PyCFunction)os_system, METH_VARARGS|METH_KEYWORDS, os_system__doc__}, - -static long -os_system_impl(PyModuleDef *module, Py_UNICODE *command); - -static PyObject * -os_system(PyModuleDef *module, PyObject *args, PyObject *kwargs) -{ - PyObject *return_value = NULL; - static char *_keywords[] = {"command", NULL}; - Py_UNICODE *command; - long _return_value; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "u:system", _keywords, - &command)) - goto exit; - _return_value = os_system_impl(module, command); - if ((_return_value == -1) && PyErr_Occurred()) - goto exit; - return_value = PyLong_FromLong(_return_value); - -exit: - return return_value; -} - static long os_system_impl(PyModuleDef *module, Py_UNICODE *command) -/*[clinic end generated code: output=29fe699c0b2e9d38 input=303f5ce97df606b0]*/ +/*[clinic end generated code: output=4c3bd5abcd9c29e7 input=303f5ce97df606b0]*/ { long result; Py_BEGIN_ALLOW_THREADS @@ -5442,45 +4258,9 @@ Execute the command in a subshell. [clinic start generated code]*/ -PyDoc_STRVAR(os_system__doc__, -"system($module, /, command)\n" -"--\n" -"\n" -"Execute the command in a subshell."); - -#define OS_SYSTEM_METHODDEF \ - {"system", (PyCFunction)os_system, METH_VARARGS|METH_KEYWORDS, os_system__doc__}, - -static long -os_system_impl(PyModuleDef *module, PyObject *command); - -static PyObject * -os_system(PyModuleDef *module, PyObject *args, PyObject *kwargs) -{ - PyObject *return_value = NULL; - static char *_keywords[] = {"command", NULL}; - PyObject *command = NULL; - long _return_value; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "O&:system", _keywords, - PyUnicode_FSConverter, &command)) - goto exit; - _return_value = os_system_impl(module, command); - if ((_return_value == -1) && PyErr_Occurred()) - goto exit; - return_value = PyLong_FromLong(_return_value); - -exit: - /* Cleanup for command */ - Py_XDECREF(command); - - return return_value; -} - static long os_system_impl(PyModuleDef *module, PyObject *command) -/*[clinic end generated code: output=5be9f3c40ead3bad input=86a58554ba6094af]*/ +/*[clinic end generated code: output=800f775e10b7be55 input=86a58554ba6094af]*/ { long result; char *bytes = PyBytes_AsString(command); @@ -5502,37 +4282,9 @@ Set the current numeric umask and return the previous umask. [clinic start generated code]*/ -PyDoc_STRVAR(os_umask__doc__, -"umask($module, mask, /)\n" -"--\n" -"\n" -"Set the current numeric umask and return the previous umask."); - -#define OS_UMASK_METHODDEF \ - {"umask", (PyCFunction)os_umask, METH_VARARGS, os_umask__doc__}, - -static PyObject * -os_umask_impl(PyModuleDef *module, int mask); - -static PyObject * -os_umask(PyModuleDef *module, PyObject *args) -{ - PyObject *return_value = NULL; - int mask; - - if (!PyArg_ParseTuple(args, - "i:umask", - &mask)) - goto exit; - return_value = os_umask_impl(module, mask); - -exit: - return return_value; -} - static PyObject * os_umask_impl(PyModuleDef *module, int mask) -/*[clinic end generated code: output=90048b39d2d4a961 input=ab6bfd9b24d8a7e8]*/ +/*[clinic end generated code: output=9e1fe3c9f14d6a05 input=ab6bfd9b24d8a7e8]*/ { int i = (int)umask(mask); if (i < 0) @@ -5596,47 +4348,9 @@ [clinic start generated code]*/ -PyDoc_STRVAR(os_unlink__doc__, -"unlink($module, /, path, *, dir_fd=None)\n" -"--\n" -"\n" -"Remove a file (same as remove()).\n" -"\n" -"If dir_fd is not None, it should be a file descriptor open to a directory,\n" -" and path should be relative; path will then be relative to that directory.\n" -"dir_fd may not be implemented on your platform.\n" -" If it is unavailable, using it will raise a NotImplementedError."); - -#define OS_UNLINK_METHODDEF \ - {"unlink", (PyCFunction)os_unlink, METH_VARARGS|METH_KEYWORDS, os_unlink__doc__}, - -static PyObject * -os_unlink_impl(PyModuleDef *module, path_t *path, int dir_fd); - -static PyObject * -os_unlink(PyModuleDef *module, PyObject *args, PyObject *kwargs) -{ - PyObject *return_value = NULL; - static char *_keywords[] = {"path", "dir_fd", NULL}; - path_t path = PATH_T_INITIALIZE("unlink", "path", 0, 0); - int dir_fd = DEFAULT_DIR_FD; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "O&|$O&:unlink", _keywords, - path_converter, &path, UNLINKAT_DIR_FD_CONVERTER, &dir_fd)) - goto exit; - return_value = os_unlink_impl(module, &path, dir_fd); - -exit: - /* Cleanup for path */ - path_cleanup(&path); - - return return_value; -} - static PyObject * os_unlink_impl(PyModuleDef *module, path_t *path, int dir_fd) -/*[clinic end generated code: output=59a6e66d67ff2e75 input=d7bcde2b1b2a2552]*/ +/*[clinic end generated code: output=474afd5cd09b237e input=d7bcde2b1b2a2552]*/ { int result; @@ -5675,47 +4389,9 @@ If it is unavailable, using it will raise a NotImplementedError. [clinic start generated code]*/ -PyDoc_STRVAR(os_remove__doc__, -"remove($module, /, path, *, dir_fd=None)\n" -"--\n" -"\n" -"Remove a file (same as unlink()).\n" -"\n" -"If dir_fd is not None, it should be a file descriptor open to a directory,\n" -" and path should be relative; path will then be relative to that directory.\n" -"dir_fd may not be implemented on your platform.\n" -" If it is unavailable, using it will raise a NotImplementedError."); - -#define OS_REMOVE_METHODDEF \ - {"remove", (PyCFunction)os_remove, METH_VARARGS|METH_KEYWORDS, os_remove__doc__}, - -static PyObject * -os_remove_impl(PyModuleDef *module, path_t *path, int dir_fd); - -static PyObject * -os_remove(PyModuleDef *module, PyObject *args, PyObject *kwargs) -{ - PyObject *return_value = NULL; - static char *_keywords[] = {"path", "dir_fd", NULL}; - path_t path = PATH_T_INITIALIZE("remove", "path", 0, 0); - int dir_fd = DEFAULT_DIR_FD; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "O&|$O&:remove", _keywords, - path_converter, &path, UNLINKAT_DIR_FD_CONVERTER, &dir_fd)) - goto exit; - return_value = os_remove_impl(module, &path, dir_fd); - -exit: - /* Cleanup for path */ - path_cleanup(&path); - - return return_value; -} - static PyObject * os_remove_impl(PyModuleDef *module, path_t *path, int dir_fd) -/*[clinic end generated code: output=cb170cf1e195b8ed input=e05c5ab55cd30983]*/ +/*[clinic end generated code: output=d0d5149e64832b9e input=e05c5ab55cd30983]*/ { return os_unlink_impl(module, path, dir_fd); } @@ -5759,30 +4435,9 @@ [clinic start generated code]*/ -PyDoc_STRVAR(os_uname__doc__, -"uname($module, /)\n" -"--\n" -"\n" -"Return an object identifying the current operating system.\n" -"\n" -"The object behaves like a named tuple with the following fields:\n" -" (sysname, nodename, release, version, machine)"); - -#define OS_UNAME_METHODDEF \ - {"uname", (PyCFunction)os_uname, METH_NOARGS, os_uname__doc__}, - -static PyObject * -os_uname_impl(PyModuleDef *module); - -static PyObject * -os_uname(PyModuleDef *module, PyObject *Py_UNUSED(ignored)) -{ - return os_uname_impl(module); -} - static PyObject * os_uname_impl(PyModuleDef *module) -/*[clinic end generated code: output=459a86521ff5041c input=e68bd246db3043ed]*/ +/*[clinic end generated code: output=01e1421b757e753f input=e68bd246db3043ed]*/ { struct utsname u; int res; @@ -6034,68 +4689,9 @@ [clinic start generated code]*/ -PyDoc_STRVAR(os_utime__doc__, -"utime($module, /, path, times=None, *, ns=None, dir_fd=None,\n" -" follow_symlinks=True)\n" -"--\n" -"\n" -"Set the access and modified time of path.\n" -"\n" -"path may always be specified as a string.\n" -"On some platforms, path may also be specified as an open file descriptor.\n" -" If this functionality is unavailable, using it raises an exception.\n" -"\n" -"If times is not None, it must be a tuple (atime, mtime);\n" -" atime and mtime should be expressed as float seconds since the epoch.\n" -"If ns is not None, it must be a tuple (atime_ns, mtime_ns);\n" -" atime_ns and mtime_ns should be expressed as integer nanoseconds\n" -" since the epoch.\n" -"If both times and ns are None, utime uses the current time.\n" -"Specifying tuples for both times and ns is an error.\n" -"\n" -"If dir_fd is not None, it should be a file descriptor open to a directory,\n" -" and path should be relative; path will then be relative to that directory.\n" -"If follow_symlinks is False, and the last element of the path is a symbolic\n" -" link, utime will modify the symbolic link itself instead of the file the\n" -" link points to.\n" -"It is an error to use dir_fd or follow_symlinks when specifying path\n" -" as an open file descriptor.\n" -"dir_fd and follow_symlinks may not be available on your platform.\n" -" If they are unavailable, using them will raise a NotImplementedError."); - -#define OS_UTIME_METHODDEF \ - {"utime", (PyCFunction)os_utime, METH_VARARGS|METH_KEYWORDS, os_utime__doc__}, - -static PyObject * -os_utime_impl(PyModuleDef *module, path_t *path, PyObject *times, PyObject *ns, int dir_fd, int follow_symlinks); - -static PyObject * -os_utime(PyModuleDef *module, PyObject *args, PyObject *kwargs) -{ - PyObject *return_value = NULL; - static char *_keywords[] = {"path", "times", "ns", "dir_fd", "follow_symlinks", NULL}; - path_t path = PATH_T_INITIALIZE("utime", "path", 0, PATH_UTIME_HAVE_FD); - PyObject *times = NULL; - PyObject *ns = NULL; - int dir_fd = DEFAULT_DIR_FD; - int follow_symlinks = 1; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "O&|O$OO&p:utime", _keywords, - path_converter, &path, ×, &ns, FUTIMENSAT_DIR_FD_CONVERTER, &dir_fd, &follow_symlinks)) - goto exit; - return_value = os_utime_impl(module, &path, times, ns, dir_fd, follow_symlinks); - -exit: - /* Cleanup for path */ - path_cleanup(&path); - - return return_value; -} - static PyObject * os_utime_impl(PyModuleDef *module, path_t *path, PyObject *times, PyObject *ns, int dir_fd, int follow_symlinks) -/*[clinic end generated code: output=891489c35cc68c5d input=1f18c17d5941aa82]*/ +/*[clinic end generated code: output=c52d8fd0d1067f0b input=1f18c17d5941aa82]*/ { #ifdef MS_WINDOWS HANDLE hFile; @@ -6262,38 +4858,9 @@ Exit to the system with specified status, without normal exit processing. [clinic start generated code]*/ -PyDoc_STRVAR(os__exit__doc__, -"_exit($module, /, status)\n" -"--\n" -"\n" -"Exit to the system with specified status, without normal exit processing."); - -#define OS__EXIT_METHODDEF \ - {"_exit", (PyCFunction)os__exit, METH_VARARGS|METH_KEYWORDS, os__exit__doc__}, - -static PyObject * -os__exit_impl(PyModuleDef *module, int status); - -static PyObject * -os__exit(PyModuleDef *module, PyObject *args, PyObject *kwargs) -{ - PyObject *return_value = NULL; - static char *_keywords[] = {"status", NULL}; - int status; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "i:_exit", _keywords, - &status)) - goto exit; - return_value = os__exit_impl(module, status); - -exit: - return return_value; -} - static PyObject * os__exit_impl(PyModuleDef *module, int status) -/*[clinic end generated code: output=4f9858c4cc2dcb89 input=5e6d57556b0c4a62]*/ +/*[clinic end generated code: output=472a3cbaf68f3621 input=5e6d57556b0c4a62]*/ { _exit(status); return NULL; /* Make gcc -Wall happy */ @@ -6447,46 +5014,9 @@ Execute an executable path with arguments, replacing current process. [clinic start generated code]*/ -PyDoc_STRVAR(os_execv__doc__, -"execv($module, path, argv, /)\n" -"--\n" -"\n" -"Execute an executable path with arguments, replacing current process.\n" -"\n" -" path\n" -" Path of executable file.\n" -" argv\n" -" Tuple or list of strings."); - -#define OS_EXECV_METHODDEF \ - {"execv", (PyCFunction)os_execv, METH_VARARGS, os_execv__doc__}, - -static PyObject * -os_execv_impl(PyModuleDef *module, PyObject *path, PyObject *argv); - -static PyObject * -os_execv(PyModuleDef *module, PyObject *args) -{ - PyObject *return_value = NULL; - PyObject *path = NULL; - PyObject *argv; - - if (!PyArg_ParseTuple(args, - "O&O:execv", - PyUnicode_FSConverter, &path, &argv)) - goto exit; - return_value = os_execv_impl(module, path, argv); - -exit: - /* Cleanup for path */ - Py_XDECREF(path); - - return return_value; -} - static PyObject * os_execv_impl(PyModuleDef *module, PyObject *path, PyObject *argv) -/*[clinic end generated code: output=b0f5f2caa6097edc input=96041559925e5229]*/ +/*[clinic end generated code: output=9221f08143146fff input=96041559925e5229]*/ { char *path_char; char **argvlist; @@ -6534,50 +5064,9 @@ Execute an executable path with arguments, replacing current process. [clinic start generated code]*/ -PyDoc_STRVAR(os_execve__doc__, -"execve($module, /, path, argv, env)\n" -"--\n" -"\n" -"Execute an executable path with arguments, replacing current process.\n" -"\n" -" path\n" -" Path of executable file.\n" -" argv\n" -" Tuple or list of strings.\n" -" env\n" -" Dictionary of strings mapping to strings."); - -#define OS_EXECVE_METHODDEF \ - {"execve", (PyCFunction)os_execve, METH_VARARGS|METH_KEYWORDS, os_execve__doc__}, - -static PyObject * -os_execve_impl(PyModuleDef *module, path_t *path, PyObject *argv, PyObject *env); - -static PyObject * -os_execve(PyModuleDef *module, PyObject *args, PyObject *kwargs) -{ - PyObject *return_value = NULL; - static char *_keywords[] = {"path", "argv", "env", NULL}; - path_t path = PATH_T_INITIALIZE("execve", "path", 0, PATH_HAVE_FEXECVE); - PyObject *argv; - PyObject *env; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "O&OO:execve", _keywords, - path_converter, &path, &argv, &env)) - goto exit; - return_value = os_execve_impl(module, &path, argv, env); - -exit: - /* Cleanup for path */ - path_cleanup(&path); - - return return_value; -} - static PyObject * os_execve_impl(PyModuleDef *module, path_t *path, PyObject *argv, PyObject *env) -/*[clinic end generated code: output=fb283760f5d15ab7 input=626804fa092606d9]*/ +/*[clinic end generated code: output=7758d4f230d8aac6 input=626804fa092606d9]*/ { char **argvlist = NULL; char **envlist; @@ -6645,49 +5134,9 @@ Execute the program specified by path in a new process. [clinic start generated code]*/ -PyDoc_STRVAR(os_spawnv__doc__, -"spawnv($module, mode, path, argv, /)\n" -"--\n" -"\n" -"Execute the program specified by path in a new process.\n" -"\n" -" mode\n" -" Mode of process creation.\n" -" path\n" -" Path of executable file.\n" -" argv\n" -" Tuple or list of strings."); - -#define OS_SPAWNV_METHODDEF \ - {"spawnv", (PyCFunction)os_spawnv, METH_VARARGS, os_spawnv__doc__}, - -static PyObject * -os_spawnv_impl(PyModuleDef *module, int mode, PyObject *path, PyObject *argv); - -static PyObject * -os_spawnv(PyModuleDef *module, PyObject *args) -{ - PyObject *return_value = NULL; - int mode; - PyObject *path = NULL; - PyObject *argv; - - if (!PyArg_ParseTuple(args, - "iO&O:spawnv", - &mode, PyUnicode_FSConverter, &path, &argv)) - goto exit; - return_value = os_spawnv_impl(module, mode, path, argv); - -exit: - /* Cleanup for path */ - Py_XDECREF(path); - - return return_value; -} - static PyObject * os_spawnv_impl(PyModuleDef *module, int mode, PyObject *path, PyObject *argv) -/*[clinic end generated code: output=dfee6be062e780e3 input=042c91dfc1e6debc]*/ +/*[clinic end generated code: output=140a7945484c8cc5 input=042c91dfc1e6debc]*/ { char *path_char; char **argvlist; @@ -6762,52 +5211,9 @@ Execute the program specified by path in a new process. [clinic start generated code]*/ -PyDoc_STRVAR(os_spawnve__doc__, -"spawnve($module, mode, path, argv, env, /)\n" -"--\n" -"\n" -"Execute the program specified by path in a new process.\n" -"\n" -" mode\n" -" Mode of process creation.\n" -" path\n" -" Path of executable file.\n" -" argv\n" -" Tuple or list of strings.\n" -" env\n" -" Dictionary of strings mapping to strings."); - -#define OS_SPAWNVE_METHODDEF \ - {"spawnve", (PyCFunction)os_spawnve, METH_VARARGS, os_spawnve__doc__}, - -static PyObject * -os_spawnve_impl(PyModuleDef *module, int mode, PyObject *path, PyObject *argv, PyObject *env); - -static PyObject * -os_spawnve(PyModuleDef *module, PyObject *args) -{ - PyObject *return_value = NULL; - int mode; - PyObject *path = NULL; - PyObject *argv; - PyObject *env; - - if (!PyArg_ParseTuple(args, - "iO&OO:spawnve", - &mode, PyUnicode_FSConverter, &path, &argv, &env)) - goto exit; - return_value = os_spawnve_impl(module, mode, path, argv, env); - -exit: - /* Cleanup for path */ - Py_XDECREF(path); - - return return_value; -} - static PyObject * os_spawnve_impl(PyModuleDef *module, int mode, PyObject *path, PyObject *argv, PyObject *env) -/*[clinic end generated code: output=6f7df38473f63c7c input=02362fd937963f8f]*/ +/*[clinic end generated code: output=1c52955789461be8 input=02362fd937963f8f]*/ { char *path_char; char **argvlist; @@ -6895,29 +5301,9 @@ Return 0 to child process and PID of child to parent process. [clinic start generated code]*/ -PyDoc_STRVAR(os_fork1__doc__, -"fork1($module, /)\n" -"--\n" -"\n" -"Fork a child process with a single multiplexed (i.e., not bound) thread.\n" -"\n" -"Return 0 to child process and PID of child to parent process."); - -#define OS_FORK1_METHODDEF \ - {"fork1", (PyCFunction)os_fork1, METH_NOARGS, os_fork1__doc__}, - -static PyObject * -os_fork1_impl(PyModuleDef *module); - -static PyObject * -os_fork1(PyModuleDef *module, PyObject *Py_UNUSED(ignored)) -{ - return os_fork1_impl(module); -} - static PyObject * os_fork1_impl(PyModuleDef *module) -/*[clinic end generated code: output=fa04088d6bc02efa input=12db02167893926e]*/ +/*[clinic end generated code: output=e27b4f66419c9dcf input=12db02167893926e]*/ { pid_t pid; int result = 0; @@ -6952,29 +5338,9 @@ Return 0 to child process and PID of child to parent process. [clinic start generated code]*/ -PyDoc_STRVAR(os_fork__doc__, -"fork($module, /)\n" -"--\n" -"\n" -"Fork a child process.\n" -"\n" -"Return 0 to child process and PID of child to parent process."); - -#define OS_FORK_METHODDEF \ - {"fork", (PyCFunction)os_fork, METH_NOARGS, os_fork__doc__}, - -static PyObject * -os_fork_impl(PyModuleDef *module); - -static PyObject * -os_fork(PyModuleDef *module, PyObject *Py_UNUSED(ignored)) -{ - return os_fork_impl(module); -} - static PyObject * os_fork_impl(PyModuleDef *module) -/*[clinic end generated code: output=b3c8e6bdc11eedc6 input=13c956413110eeaa]*/ +/*[clinic end generated code: output=898b1ecd3498ba12 input=13c956413110eeaa]*/ { pid_t pid; int result = 0; @@ -7010,38 +5376,9 @@ Get the maximum scheduling priority for policy. [clinic start generated code]*/ -PyDoc_STRVAR(os_sched_get_priority_max__doc__, -"sched_get_priority_max($module, /, policy)\n" -"--\n" -"\n" -"Get the maximum scheduling priority for policy."); - -#define OS_SCHED_GET_PRIORITY_MAX_METHODDEF \ - {"sched_get_priority_max", (PyCFunction)os_sched_get_priority_max, METH_VARARGS|METH_KEYWORDS, os_sched_get_priority_max__doc__}, - -static PyObject * -os_sched_get_priority_max_impl(PyModuleDef *module, int policy); - -static PyObject * -os_sched_get_priority_max(PyModuleDef *module, PyObject *args, PyObject *kwargs) -{ - PyObject *return_value = NULL; - static char *_keywords[] = {"policy", NULL}; - int policy; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "i:sched_get_priority_max", _keywords, - &policy)) - goto exit; - return_value = os_sched_get_priority_max_impl(module, policy); - -exit: - return return_value; -} - static PyObject * os_sched_get_priority_max_impl(PyModuleDef *module, int policy) -/*[clinic end generated code: output=a580a52f25238c1f input=2097b7998eca6874]*/ +/*[clinic end generated code: output=a6a30fa5071f2d81 input=2097b7998eca6874]*/ { int max; @@ -7060,38 +5397,9 @@ Get the minimum scheduling priority for policy. [clinic start generated code]*/ -PyDoc_STRVAR(os_sched_get_priority_min__doc__, -"sched_get_priority_min($module, /, policy)\n" -"--\n" -"\n" -"Get the minimum scheduling priority for policy."); - -#define OS_SCHED_GET_PRIORITY_MIN_METHODDEF \ - {"sched_get_priority_min", (PyCFunction)os_sched_get_priority_min, METH_VARARGS|METH_KEYWORDS, os_sched_get_priority_min__doc__}, - -static PyObject * -os_sched_get_priority_min_impl(PyModuleDef *module, int policy); - -static PyObject * -os_sched_get_priority_min(PyModuleDef *module, PyObject *args, PyObject *kwargs) -{ - PyObject *return_value = NULL; - static char *_keywords[] = {"policy", NULL}; - int policy; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "i:sched_get_priority_min", _keywords, - &policy)) - goto exit; - return_value = os_sched_get_priority_min_impl(module, policy); - -exit: - return return_value; -} - static PyObject * os_sched_get_priority_min_impl(PyModuleDef *module, int policy) -/*[clinic end generated code: output=bad8ba10e7d0e977 input=21bc8fa0d70983bf]*/ +/*[clinic end generated code: output=5ca3ed6bc43e9b20 input=21bc8fa0d70983bf]*/ { int min = sched_get_priority_min(policy); if (min < 0) @@ -7112,39 +5420,9 @@ Passing 0 for pid returns the scheduling policy for the calling process. [clinic start generated code]*/ -PyDoc_STRVAR(os_sched_getscheduler__doc__, -"sched_getscheduler($module, pid, /)\n" -"--\n" -"\n" -"Get the scheduling policy for the process identifiedy by pid.\n" -"\n" -"Passing 0 for pid returns the scheduling policy for the calling process."); - -#define OS_SCHED_GETSCHEDULER_METHODDEF \ - {"sched_getscheduler", (PyCFunction)os_sched_getscheduler, METH_VARARGS, os_sched_getscheduler__doc__}, - -static PyObject * -os_sched_getscheduler_impl(PyModuleDef *module, pid_t pid); - -static PyObject * -os_sched_getscheduler(PyModuleDef *module, PyObject *args) -{ - PyObject *return_value = NULL; - pid_t pid; - - if (!PyArg_ParseTuple(args, - "" _Py_PARSE_PID ":sched_getscheduler", - &pid)) - goto exit; - return_value = os_sched_getscheduler_impl(module, pid); - -exit: - return return_value; -} - static PyObject * os_sched_getscheduler_impl(PyModuleDef *module, pid_t pid) -/*[clinic end generated code: output=e0d6244207b1d828 input=5f14cfd1f189e1a0]*/ +/*[clinic end generated code: output=8cd63c15caf54fa9 input=5f14cfd1f189e1a0]*/ { int policy; @@ -7169,38 +5447,9 @@ Current has only one field: sched_priority"); [clinic start generated code]*/ -PyDoc_STRVAR(os_sched_param__doc__, -"sched_param(sched_priority)\n" -"--\n" -"\n" -"Current has only one field: sched_priority\");\n" -"\n" -" sched_priority\n" -" A scheduling parameter."); - -static PyObject * -os_sched_param_impl(PyTypeObject *type, PyObject *sched_priority); - -static PyObject * -os_sched_param(PyTypeObject *type, PyObject *args, PyObject *kwargs) -{ - PyObject *return_value = NULL; - static char *_keywords[] = {"sched_priority", NULL}; - PyObject *sched_priority; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "O:sched_param", _keywords, - &sched_priority)) - goto exit; - return_value = os_sched_param_impl(type, sched_priority); - -exit: - return return_value; -} - static PyObject * os_sched_param_impl(PyTypeObject *type, PyObject *sched_priority) -/*[clinic end generated code: output=d3791e345f7fe573 input=73a4c22f7071fc62]*/ +/*[clinic end generated code: output=48f4067d60f48c13 input=73a4c22f7071fc62]*/ { PyObject *res; @@ -7213,6 +5462,8 @@ } +PyDoc_VAR(os_sched_param__doc__); + static PyStructSequence_Field sched_param_fields[] = { {"sched_priority", "the scheduling priority"}, {0} @@ -7262,42 +5513,9 @@ param is an instance of sched_param. [clinic start generated code]*/ -PyDoc_STRVAR(os_sched_setscheduler__doc__, -"sched_setscheduler($module, pid, policy, param, /)\n" -"--\n" -"\n" -"Set the scheduling policy for the process identified by pid.\n" -"\n" -"If pid is 0, the calling process is changed.\n" -"param is an instance of sched_param."); - -#define OS_SCHED_SETSCHEDULER_METHODDEF \ - {"sched_setscheduler", (PyCFunction)os_sched_setscheduler, METH_VARARGS, os_sched_setscheduler__doc__}, - -static PyObject * -os_sched_setscheduler_impl(PyModuleDef *module, pid_t pid, int policy, struct sched_param *param); - -static PyObject * -os_sched_setscheduler(PyModuleDef *module, PyObject *args) -{ - PyObject *return_value = NULL; - pid_t pid; - int policy; - struct sched_param param; - - if (!PyArg_ParseTuple(args, - "" _Py_PARSE_PID "iO&:sched_setscheduler", - &pid, &policy, convert_sched_param, ¶m)) - goto exit; - return_value = os_sched_setscheduler_impl(module, pid, policy, ¶m); - -exit: - return return_value; -} - static PyObject * os_sched_setscheduler_impl(PyModuleDef *module, pid_t pid, int policy, struct sched_param *param) -/*[clinic end generated code: output=36abdb73f81c224f input=c581f9469a5327dd]*/ +/*[clinic end generated code: output=97f40f8384e554b0 input=c581f9469a5327dd]*/ { /* ** sched_setscheduler() returns 0 in Linux, but the previous @@ -7323,40 +5541,9 @@ Return value is an instance of sched_param. [clinic start generated code]*/ -PyDoc_STRVAR(os_sched_getparam__doc__, -"sched_getparam($module, pid, /)\n" -"--\n" -"\n" -"Returns scheduling parameters for the process identified by pid.\n" -"\n" -"If pid is 0, returns parameters for the calling process.\n" -"Return value is an instance of sched_param."); - -#define OS_SCHED_GETPARAM_METHODDEF \ - {"sched_getparam", (PyCFunction)os_sched_getparam, METH_VARARGS, os_sched_getparam__doc__}, - -static PyObject * -os_sched_getparam_impl(PyModuleDef *module, pid_t pid); - -static PyObject * -os_sched_getparam(PyModuleDef *module, PyObject *args) -{ - PyObject *return_value = NULL; - pid_t pid; - - if (!PyArg_ParseTuple(args, - "" _Py_PARSE_PID ":sched_getparam", - &pid)) - goto exit; - return_value = os_sched_getparam_impl(module, pid); - -exit: - return return_value; -} - static PyObject * os_sched_getparam_impl(PyModuleDef *module, pid_t pid) -/*[clinic end generated code: output=b33acc8db004a8c9 input=18a1ef9c2efae296]*/ +/*[clinic end generated code: output=f42c5bd2604ecd08 input=18a1ef9c2efae296]*/ { struct sched_param param; PyObject *result; @@ -7389,41 +5576,9 @@ param should be an instance of sched_param. [clinic start generated code]*/ -PyDoc_STRVAR(os_sched_setparam__doc__, -"sched_setparam($module, pid, param, /)\n" -"--\n" -"\n" -"Set scheduling parameters for the process identified by pid.\n" -"\n" -"If pid is 0, sets parameters for the calling process.\n" -"param should be an instance of sched_param."); - -#define OS_SCHED_SETPARAM_METHODDEF \ - {"sched_setparam", (PyCFunction)os_sched_setparam, METH_VARARGS, os_sched_setparam__doc__}, - -static PyObject * -os_sched_setparam_impl(PyModuleDef *module, pid_t pid, struct sched_param *param); - -static PyObject * -os_sched_setparam(PyModuleDef *module, PyObject *args) -{ - PyObject *return_value = NULL; - pid_t pid; - struct sched_param param; - - if (!PyArg_ParseTuple(args, - "" _Py_PARSE_PID "O&:sched_setparam", - &pid, convert_sched_param, ¶m)) - goto exit; - return_value = os_sched_setparam_impl(module, pid, ¶m); - -exit: - return return_value; -} - static PyObject * os_sched_setparam_impl(PyModuleDef *module, pid_t pid, struct sched_param *param) -/*[clinic end generated code: output=488bdf5bcbe0d4e8 input=6b8d6dfcecdc21bd]*/ +/*[clinic end generated code: output=c6560b34395bb343 input=6b8d6dfcecdc21bd]*/ { if (sched_setparam(pid, param)) return posix_error(); @@ -7443,43 +5598,9 @@ Value returned is a float. [clinic start generated code]*/ -PyDoc_STRVAR(os_sched_rr_get_interval__doc__, -"sched_rr_get_interval($module, pid, /)\n" -"--\n" -"\n" -"Return the round-robin quantum for the process identified by pid, in seconds.\n" -"\n" -"Value returned is a float."); - -#define OS_SCHED_RR_GET_INTERVAL_METHODDEF \ - {"sched_rr_get_interval", (PyCFunction)os_sched_rr_get_interval, METH_VARARGS, os_sched_rr_get_interval__doc__}, - -static double -os_sched_rr_get_interval_impl(PyModuleDef *module, pid_t pid); - -static PyObject * -os_sched_rr_get_interval(PyModuleDef *module, PyObject *args) -{ - PyObject *return_value = NULL; - pid_t pid; - double _return_value; - - if (!PyArg_ParseTuple(args, - "" _Py_PARSE_PID ":sched_rr_get_interval", - &pid)) - goto exit; - _return_value = os_sched_rr_get_interval_impl(module, pid); - if ((_return_value == -1.0) && PyErr_Occurred()) - goto exit; - return_value = PyFloat_FromDouble(_return_value); - -exit: - return return_value; -} - static double os_sched_rr_get_interval_impl(PyModuleDef *module, pid_t pid) -/*[clinic end generated code: output=5b3b8d1f27fb2c0a input=2a973da15cca6fae]*/ +/*[clinic end generated code: output=7adc137a86dea581 input=2a973da15cca6fae]*/ { struct timespec interval; if (sched_rr_get_interval(pid, &interval)) { @@ -7497,27 +5618,9 @@ Voluntarily relinquish the CPU. [clinic start generated code]*/ -PyDoc_STRVAR(os_sched_yield__doc__, -"sched_yield($module, /)\n" -"--\n" -"\n" -"Voluntarily relinquish the CPU."); - -#define OS_SCHED_YIELD_METHODDEF \ - {"sched_yield", (PyCFunction)os_sched_yield, METH_NOARGS, os_sched_yield__doc__}, - -static PyObject * -os_sched_yield_impl(PyModuleDef *module); - -static PyObject * -os_sched_yield(PyModuleDef *module, PyObject *Py_UNUSED(ignored)) -{ - return os_sched_yield_impl(module); -} - static PyObject * os_sched_yield_impl(PyModuleDef *module) -/*[clinic end generated code: output=9d2e5f29f1370324 input=e54d6f98189391d4]*/ +/*[clinic end generated code: output=d7bd51869c4cb6a8 input=e54d6f98189391d4]*/ { if (sched_yield()) return posix_error(); @@ -7539,40 +5642,9 @@ mask should be an iterable of integers identifying CPUs. [clinic start generated code]*/ -PyDoc_STRVAR(os_sched_setaffinity__doc__, -"sched_setaffinity($module, pid, mask, /)\n" -"--\n" -"\n" -"Set the CPU affinity of the process identified by pid to mask.\n" -"\n" -"mask should be an iterable of integers identifying CPUs."); - -#define OS_SCHED_SETAFFINITY_METHODDEF \ - {"sched_setaffinity", (PyCFunction)os_sched_setaffinity, METH_VARARGS, os_sched_setaffinity__doc__}, - -static PyObject * -os_sched_setaffinity_impl(PyModuleDef *module, pid_t pid, PyObject *mask); - -static PyObject * -os_sched_setaffinity(PyModuleDef *module, PyObject *args) -{ - PyObject *return_value = NULL; - pid_t pid; - PyObject *mask; - - if (!PyArg_ParseTuple(args, - "" _Py_PARSE_PID "O:sched_setaffinity", - &pid, &mask)) - goto exit; - return_value = os_sched_setaffinity_impl(module, pid, mask); - -exit: - return return_value; -} - static PyObject * os_sched_setaffinity_impl(PyModuleDef *module, pid_t pid, PyObject *mask) -/*[clinic end generated code: output=5199929738130196 input=a0791a597c7085ba]*/ +/*[clinic end generated code: output=582bcbf40d3253a9 input=a0791a597c7085ba]*/ { int ncpus; size_t setsize; @@ -7666,39 +5738,9 @@ The affinity is returned as a set of CPU identifiers. [clinic start generated code]*/ -PyDoc_STRVAR(os_sched_getaffinity__doc__, -"sched_getaffinity($module, pid, /)\n" -"--\n" -"\n" -"Return the affinity of the process identified by pid.\n" -"\n" -"The affinity is returned as a set of CPU identifiers."); - -#define OS_SCHED_GETAFFINITY_METHODDEF \ - {"sched_getaffinity", (PyCFunction)os_sched_getaffinity, METH_VARARGS, os_sched_getaffinity__doc__}, - -static PyObject * -os_sched_getaffinity_impl(PyModuleDef *module, pid_t pid); - -static PyObject * -os_sched_getaffinity(PyModuleDef *module, PyObject *args) -{ - PyObject *return_value = NULL; - pid_t pid; - - if (!PyArg_ParseTuple(args, - "" _Py_PARSE_PID ":sched_getaffinity", - &pid)) - goto exit; - return_value = os_sched_getaffinity_impl(module, pid); - -exit: - return return_value; -} - static PyObject * os_sched_getaffinity_impl(PyModuleDef *module, pid_t pid) -/*[clinic end generated code: output=7b273b0fca9830f0 input=eaf161936874b8a1]*/ +/*[clinic end generated code: output=b431a8f310e369e7 input=eaf161936874b8a1]*/ { int cpu, ncpus, count; size_t setsize; @@ -7754,46 +5796,6 @@ #endif /* HAVE_SCHED_H */ -#ifndef OS_SCHED_GET_PRIORITY_MAX_METHODDEF -#define OS_SCHED_GET_PRIORITY_MAX_METHODDEF -#endif /* OS_SCHED_GET_PRIORITY_MAX_METHODDEF */ - -#ifndef OS_SCHED_GET_PRIORITY_MIN_METHODDEF -#define OS_SCHED_GET_PRIORITY_MIN_METHODDEF -#endif /* OS_SCHED_GET_PRIORITY_MIN_METHODDEF */ - -#ifndef OS_SCHED_GETSCHEDULER_METHODDEF -#define OS_SCHED_GETSCHEDULER_METHODDEF -#endif /* OS_SCHED_GETSCHEDULER_METHODDEF */ - -#ifndef OS_SCHED_SETSCHEDULER_METHODDEF -#define OS_SCHED_SETSCHEDULER_METHODDEF -#endif /* OS_SCHED_SETSCHEDULER_METHODDEF */ - -#ifndef OS_SCHED_GETPARAM_METHODDEF -#define OS_SCHED_GETPARAM_METHODDEF -#endif /* OS_SCHED_GETPARAM_METHODDEF */ - -#ifndef OS_SCHED_SETPARAM_METHODDEF -#define OS_SCHED_SETPARAM_METHODDEF -#endif /* OS_SCHED_SETPARAM_METHODDEF */ - -#ifndef OS_SCHED_RR_GET_INTERVAL_METHODDEF -#define OS_SCHED_RR_GET_INTERVAL_METHODDEF -#endif /* OS_SCHED_RR_GET_INTERVAL_METHODDEF */ - -#ifndef OS_SCHED_YIELD_METHODDEF -#define OS_SCHED_YIELD_METHODDEF -#endif /* OS_SCHED_YIELD_METHODDEF */ - -#ifndef OS_SCHED_SETAFFINITY_METHODDEF -#define OS_SCHED_SETAFFINITY_METHODDEF -#endif /* OS_SCHED_SETAFFINITY_METHODDEF */ - -#ifndef OS_SCHED_GETAFFINITY_METHODDEF -#define OS_SCHED_GETAFFINITY_METHODDEF -#endif /* OS_SCHED_GETAFFINITY_METHODDEF */ - /* AIX uses /dev/ptc but is otherwise the same as /dev/ptmx */ /* IRIX has both /dev/ptc and /dev/ptmx, use ptmx */ @@ -7832,30 +5834,9 @@ for both the master and slave ends. [clinic start generated code]*/ -PyDoc_STRVAR(os_openpty__doc__, -"openpty($module, /)\n" -"--\n" -"\n" -"Open a pseudo-terminal.\n" -"\n" -"Return a tuple of (master_fd, slave_fd) containing open file descriptors\n" -"for both the master and slave ends."); - -#define OS_OPENPTY_METHODDEF \ - {"openpty", (PyCFunction)os_openpty, METH_NOARGS, os_openpty__doc__}, - -static PyObject * -os_openpty_impl(PyModuleDef *module); - -static PyObject * -os_openpty(PyModuleDef *module, PyObject *Py_UNUSED(ignored)) -{ - return os_openpty_impl(module); -} - static PyObject * os_openpty_impl(PyModuleDef *module) -/*[clinic end generated code: output=b12d3c1735468464 input=f3d99fd99e762907]*/ +/*[clinic end generated code: output=358e571c1ba135ee input=f3d99fd99e762907]*/ { int master_fd = -1, slave_fd = -1; #ifndef HAVE_OPENPTY @@ -7955,32 +5936,9 @@ To both, return fd of newly opened pseudo-terminal. [clinic start generated code]*/ -PyDoc_STRVAR(os_forkpty__doc__, -"forkpty($module, /)\n" -"--\n" -"\n" -"Fork a new process with a new pseudo-terminal as controlling tty.\n" -"\n" -"Returns a tuple of (pid, master_fd).\n" -"Like fork(), return pid of 0 to the child process,\n" -"and pid of child to the parent process.\n" -"To both, return fd of newly opened pseudo-terminal."); - -#define OS_FORKPTY_METHODDEF \ - {"forkpty", (PyCFunction)os_forkpty, METH_NOARGS, os_forkpty__doc__}, - -static PyObject * -os_forkpty_impl(PyModuleDef *module); - -static PyObject * -os_forkpty(PyModuleDef *module, PyObject *Py_UNUSED(ignored)) -{ - return os_forkpty_impl(module); -} - static PyObject * os_forkpty_impl(PyModuleDef *module) -/*[clinic end generated code: output=d4f82958d2ed5cad input=f1f7f4bae3966010]*/ +/*[clinic end generated code: output=a11b8391dce3cb57 input=f1f7f4bae3966010]*/ { int master_fd = -1, result = 0; pid_t pid; @@ -8014,27 +5972,9 @@ Return the current process's effective group id. [clinic start generated code]*/ -PyDoc_STRVAR(os_getegid__doc__, -"getegid($module, /)\n" -"--\n" -"\n" -"Return the current process\'s effective group id."); - -#define OS_GETEGID_METHODDEF \ - {"getegid", (PyCFunction)os_getegid, METH_NOARGS, os_getegid__doc__}, - -static PyObject * -os_getegid_impl(PyModuleDef *module); - -static PyObject * -os_getegid(PyModuleDef *module, PyObject *Py_UNUSED(ignored)) -{ - return os_getegid_impl(module); -} - static PyObject * os_getegid_impl(PyModuleDef *module) -/*[clinic end generated code: output=fd12c346fa41cccb input=1596f79ad1107d5d]*/ +/*[clinic end generated code: output=90f433a8c0b1d919 input=1596f79ad1107d5d]*/ { return _PyLong_FromGid(getegid()); } @@ -8048,27 +5988,9 @@ Return the current process's effective user id. [clinic start generated code]*/ -PyDoc_STRVAR(os_geteuid__doc__, -"geteuid($module, /)\n" -"--\n" -"\n" -"Return the current process\'s effective user id."); - -#define OS_GETEUID_METHODDEF \ - {"geteuid", (PyCFunction)os_geteuid, METH_NOARGS, os_geteuid__doc__}, - -static PyObject * -os_geteuid_impl(PyModuleDef *module); - -static PyObject * -os_geteuid(PyModuleDef *module, PyObject *Py_UNUSED(ignored)) -{ - return os_geteuid_impl(module); -} - static PyObject * os_geteuid_impl(PyModuleDef *module) -/*[clinic end generated code: output=03d98e07f4bc03d4 input=4644c662d3bd9f19]*/ +/*[clinic end generated code: output=1a532c4a66874357 input=4644c662d3bd9f19]*/ { return _PyLong_FromUid(geteuid()); } @@ -8082,27 +6004,9 @@ Return the current process's group id. [clinic start generated code]*/ -PyDoc_STRVAR(os_getgid__doc__, -"getgid($module, /)\n" -"--\n" -"\n" -"Return the current process\'s group id."); - -#define OS_GETGID_METHODDEF \ - {"getgid", (PyCFunction)os_getgid, METH_NOARGS, os_getgid__doc__}, - -static PyObject * -os_getgid_impl(PyModuleDef *module); - -static PyObject * -os_getgid(PyModuleDef *module, PyObject *Py_UNUSED(ignored)) -{ - return os_getgid_impl(module); -} - static PyObject * os_getgid_impl(PyModuleDef *module) -/*[clinic end generated code: output=07b0356121b8098d input=58796344cd87c0f6]*/ +/*[clinic end generated code: output=91a22021b74ea46b input=58796344cd87c0f6]*/ { return _PyLong_FromGid(getgid()); } @@ -8115,27 +6019,9 @@ Return the current process id. [clinic start generated code]*/ -PyDoc_STRVAR(os_getpid__doc__, -"getpid($module, /)\n" -"--\n" -"\n" -"Return the current process id."); - -#define OS_GETPID_METHODDEF \ - {"getpid", (PyCFunction)os_getpid, METH_NOARGS, os_getpid__doc__}, - -static PyObject * -os_getpid_impl(PyModuleDef *module); - -static PyObject * -os_getpid(PyModuleDef *module, PyObject *Py_UNUSED(ignored)) -{ - return os_getpid_impl(module); -} - static PyObject * os_getpid_impl(PyModuleDef *module) -/*[clinic end generated code: output=d63a01a3cebc573d input=5a9a00f0ab68aa00]*/ +/*[clinic end generated code: output=8fbf3a934ee09e62 input=5a9a00f0ab68aa00]*/ { return PyLong_FromPid(getpid()); } @@ -8225,27 +6111,9 @@ Return list of supplemental group IDs for the process. [clinic start generated code]*/ -PyDoc_STRVAR(os_getgroups__doc__, -"getgroups($module, /)\n" -"--\n" -"\n" -"Return list of supplemental group IDs for the process."); - -#define OS_GETGROUPS_METHODDEF \ - {"getgroups", (PyCFunction)os_getgroups, METH_NOARGS, os_getgroups__doc__}, - -static PyObject * -os_getgroups_impl(PyModuleDef *module); - -static PyObject * -os_getgroups(PyModuleDef *module, PyObject *Py_UNUSED(ignored)) -{ - return os_getgroups_impl(module); -} - static PyObject * os_getgroups_impl(PyModuleDef *module) -/*[clinic end generated code: output=d9a3559b2e6f4ab8 input=d3f109412e6a155c]*/ +/*[clinic end generated code: output=6e7c4fd2db6d5c60 input=d3f109412e6a155c]*/ { PyObject *result = NULL; @@ -8398,38 +6266,9 @@ Call the system call getpgid(), and return the result. [clinic start generated code]*/ -PyDoc_STRVAR(os_getpgid__doc__, -"getpgid($module, /, pid)\n" -"--\n" -"\n" -"Call the system call getpgid(), and return the result."); - -#define OS_GETPGID_METHODDEF \ - {"getpgid", (PyCFunction)os_getpgid, METH_VARARGS|METH_KEYWORDS, os_getpgid__doc__}, - -static PyObject * -os_getpgid_impl(PyModuleDef *module, pid_t pid); - -static PyObject * -os_getpgid(PyModuleDef *module, PyObject *args, PyObject *kwargs) -{ - PyObject *return_value = NULL; - static char *_keywords[] = {"pid", NULL}; - pid_t pid; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "" _Py_PARSE_PID ":getpgid", _keywords, - &pid)) - goto exit; - return_value = os_getpgid_impl(module, pid); - -exit: - return return_value; -} - static PyObject * os_getpgid_impl(PyModuleDef *module, pid_t pid) -/*[clinic end generated code: output=3db4ed686179160d input=39d710ae3baaf1c7]*/ +/*[clinic end generated code: output=70e713b4d54b7c61 input=39d710ae3baaf1c7]*/ { pid_t pgid = getpgid(pid); if (pgid < 0) @@ -8446,27 +6285,9 @@ Return the current process group id. [clinic start generated code]*/ -PyDoc_STRVAR(os_getpgrp__doc__, -"getpgrp($module, /)\n" -"--\n" -"\n" -"Return the current process group id."); - -#define OS_GETPGRP_METHODDEF \ - {"getpgrp", (PyCFunction)os_getpgrp, METH_NOARGS, os_getpgrp__doc__}, - -static PyObject * -os_getpgrp_impl(PyModuleDef *module); - -static PyObject * -os_getpgrp(PyModuleDef *module, PyObject *Py_UNUSED(ignored)) -{ - return os_getpgrp_impl(module); -} - static PyObject * os_getpgrp_impl(PyModuleDef *module) -/*[clinic end generated code: output=3b0d3663ea054277 input=6846fb2bb9a3705e]*/ +/*[clinic end generated code: output=cf3403585846811f input=6846fb2bb9a3705e]*/ { #ifdef GETPGRP_HAVE_ARG return PyLong_FromPid(getpgrp(0)); @@ -8484,27 +6305,9 @@ Make the current process the leader of its process group. [clinic start generated code]*/ -PyDoc_STRVAR(os_setpgrp__doc__, -"setpgrp($module, /)\n" -"--\n" -"\n" -"Make the current process the leader of its process group."); - -#define OS_SETPGRP_METHODDEF \ - {"setpgrp", (PyCFunction)os_setpgrp, METH_NOARGS, os_setpgrp__doc__}, - -static PyObject * -os_setpgrp_impl(PyModuleDef *module); - -static PyObject * -os_setpgrp(PyModuleDef *module, PyObject *Py_UNUSED(ignored)) -{ - return os_setpgrp_impl(module); -} - static PyObject * os_setpgrp_impl(PyModuleDef *module) -/*[clinic end generated code: output=8fbb0ee29ef6fb2d input=1f0619fcb5731e7e]*/ +/*[clinic end generated code: output=59650f55a963d7ac input=1f0619fcb5731e7e]*/ { #ifdef SETPGRP_HAVE_ARG if (setpgrp(0, 0) < 0) @@ -8571,30 +6374,9 @@ return its id; others systems will return the id of the 'init' process (1). [clinic start generated code]*/ -PyDoc_STRVAR(os_getppid__doc__, -"getppid($module, /)\n" -"--\n" -"\n" -"Return the parent\'s process id.\n" -"\n" -"If the parent process has already exited, Windows machines will still\n" -"return its id; others systems will return the id of the \'init\' process (1)."); - -#define OS_GETPPID_METHODDEF \ - {"getppid", (PyCFunction)os_getppid, METH_NOARGS, os_getppid__doc__}, - -static PyObject * -os_getppid_impl(PyModuleDef *module); - -static PyObject * -os_getppid(PyModuleDef *module, PyObject *Py_UNUSED(ignored)) -{ - return os_getppid_impl(module); -} - static PyObject * os_getppid_impl(PyModuleDef *module) -/*[clinic end generated code: output=9ff3b387781edf3a input=e637cb87539c030e]*/ +/*[clinic end generated code: output=4e49c8e7a8738cd2 input=e637cb87539c030e]*/ { #ifdef MS_WINDOWS return win32_getppid(); @@ -8612,27 +6394,9 @@ Return the actual login name. [clinic start generated code]*/ -PyDoc_STRVAR(os_getlogin__doc__, -"getlogin($module, /)\n" -"--\n" -"\n" -"Return the actual login name."); - -#define OS_GETLOGIN_METHODDEF \ - {"getlogin", (PyCFunction)os_getlogin, METH_NOARGS, os_getlogin__doc__}, - -static PyObject * -os_getlogin_impl(PyModuleDef *module); - -static PyObject * -os_getlogin(PyModuleDef *module, PyObject *Py_UNUSED(ignored)) -{ - return os_getlogin_impl(module); -} - static PyObject * os_getlogin_impl(PyModuleDef *module) -/*[clinic end generated code: output=ab6211dab104cbb2 input=2a21ab1e917163df]*/ +/*[clinic end generated code: output=037ebdb3e4b5dac1 input=2a21ab1e917163df]*/ { PyObject *result = NULL; #ifdef MS_WINDOWS @@ -8673,27 +6437,9 @@ Return the current process's user id. [clinic start generated code]*/ -PyDoc_STRVAR(os_getuid__doc__, -"getuid($module, /)\n" -"--\n" -"\n" -"Return the current process\'s user id."); - -#define OS_GETUID_METHODDEF \ - {"getuid", (PyCFunction)os_getuid, METH_NOARGS, os_getuid__doc__}, - -static PyObject * -os_getuid_impl(PyModuleDef *module); - -static PyObject * -os_getuid(PyModuleDef *module, PyObject *Py_UNUSED(ignored)) -{ - return os_getuid_impl(module); -} - static PyObject * os_getuid_impl(PyModuleDef *module) -/*[clinic end generated code: output=77e0dcf2e37d1e89 input=b53c8b35f110a516]*/ +/*[clinic end generated code: output=03a8b894cefb3fa5 input=b53c8b35f110a516]*/ { return _PyLong_FromUid(getuid()); } @@ -8715,38 +6461,9 @@ Kill a process with a signal. [clinic start generated code]*/ -PyDoc_STRVAR(os_kill__doc__, -"kill($module, pid, signal, /)\n" -"--\n" -"\n" -"Kill a process with a signal."); - -#define OS_KILL_METHODDEF \ - {"kill", (PyCFunction)os_kill, METH_VARARGS, os_kill__doc__}, - -static PyObject * -os_kill_impl(PyModuleDef *module, pid_t pid, Py_ssize_t signal); - -static PyObject * -os_kill(PyModuleDef *module, PyObject *args) -{ - PyObject *return_value = NULL; - pid_t pid; - Py_ssize_t signal; - - if (!PyArg_ParseTuple(args, - "" _Py_PARSE_PID "n:kill", - &pid, &signal)) - goto exit; - return_value = os_kill_impl(module, pid, signal); - -exit: - return return_value; -} - static PyObject * os_kill_impl(PyModuleDef *module, pid_t pid, Py_ssize_t signal) -/*[clinic end generated code: output=2f5c77920ed575e6 input=61a36b86ca275ab9]*/ +/*[clinic end generated code: output=74f907dd00a83c26 input=61a36b86ca275ab9]*/ #ifndef MS_WINDOWS { if (kill(pid, (int)signal) == -1) @@ -8805,38 +6522,9 @@ Kill a process group with a signal. [clinic start generated code]*/ -PyDoc_STRVAR(os_killpg__doc__, -"killpg($module, pgid, signal, /)\n" -"--\n" -"\n" -"Kill a process group with a signal."); - -#define OS_KILLPG_METHODDEF \ - {"killpg", (PyCFunction)os_killpg, METH_VARARGS, os_killpg__doc__}, - -static PyObject * -os_killpg_impl(PyModuleDef *module, pid_t pgid, int signal); - -static PyObject * -os_killpg(PyModuleDef *module, PyObject *args) -{ - PyObject *return_value = NULL; - pid_t pgid; - int signal; - - if (!PyArg_ParseTuple(args, - "" _Py_PARSE_PID "i:killpg", - &pgid, &signal)) - goto exit; - return_value = os_killpg_impl(module, pgid, signal); - -exit: - return return_value; -} - static PyObject * os_killpg_impl(PyModuleDef *module, pid_t pgid, int signal) -/*[clinic end generated code: output=0e05215d1c007e01 input=38b5449eb8faec19]*/ +/*[clinic end generated code: output=3434a766ef945f93 input=38b5449eb8faec19]*/ { /* XXX some man pages make the `pgid` parameter an int, others a pid_t. Since getpgrp() returns a pid_t, we assume killpg should @@ -8862,37 +6550,9 @@ Lock program segments into memory."); [clinic start generated code]*/ -PyDoc_STRVAR(os_plock__doc__, -"plock($module, op, /)\n" -"--\n" -"\n" -"Lock program segments into memory.\");"); - -#define OS_PLOCK_METHODDEF \ - {"plock", (PyCFunction)os_plock, METH_VARARGS, os_plock__doc__}, - -static PyObject * -os_plock_impl(PyModuleDef *module, int op); - -static PyObject * -os_plock(PyModuleDef *module, PyObject *args) -{ - PyObject *return_value = NULL; - int op; - - if (!PyArg_ParseTuple(args, - "i:plock", - &op)) - goto exit; - return_value = os_plock_impl(module, op); - -exit: - return return_value; -} - static PyObject * os_plock_impl(PyModuleDef *module, int op) -/*[clinic end generated code: output=2744fe4b6e5f4dbc input=e6e5e348e1525f60]*/ +/*[clinic end generated code: output=5cb851f81b914984 input=e6e5e348e1525f60]*/ { if (plock(op) == -1) return posix_error(); @@ -8911,37 +6571,9 @@ Set the current process's user id. [clinic start generated code]*/ -PyDoc_STRVAR(os_setuid__doc__, -"setuid($module, uid, /)\n" -"--\n" -"\n" -"Set the current process\'s user id."); - -#define OS_SETUID_METHODDEF \ - {"setuid", (PyCFunction)os_setuid, METH_VARARGS, os_setuid__doc__}, - -static PyObject * -os_setuid_impl(PyModuleDef *module, uid_t uid); - -static PyObject * -os_setuid(PyModuleDef *module, PyObject *args) -{ - PyObject *return_value = NULL; - uid_t uid; - - if (!PyArg_ParseTuple(args, - "O&:setuid", - _Py_Uid_Converter, &uid)) - goto exit; - return_value = os_setuid_impl(module, uid); - -exit: - return return_value; -} - static PyObject * os_setuid_impl(PyModuleDef *module, uid_t uid) -/*[clinic end generated code: output=aea344bc22ccf400 input=c921a3285aa22256]*/ +/*[clinic end generated code: output=941ea9a8d1e5d565 input=c921a3285aa22256]*/ { if (setuid(uid) < 0) return posix_error(); @@ -8960,37 +6592,9 @@ Set the current process's effective user id. [clinic start generated code]*/ -PyDoc_STRVAR(os_seteuid__doc__, -"seteuid($module, euid, /)\n" -"--\n" -"\n" -"Set the current process\'s effective user id."); - -#define OS_SETEUID_METHODDEF \ - {"seteuid", (PyCFunction)os_seteuid, METH_VARARGS, os_seteuid__doc__}, - -static PyObject * -os_seteuid_impl(PyModuleDef *module, uid_t euid); - -static PyObject * -os_seteuid(PyModuleDef *module, PyObject *args) -{ - PyObject *return_value = NULL; - uid_t euid; - - if (!PyArg_ParseTuple(args, - "O&:seteuid", - _Py_Uid_Converter, &euid)) - goto exit; - return_value = os_seteuid_impl(module, euid); - -exit: - return return_value; -} - static PyObject * os_seteuid_impl(PyModuleDef *module, uid_t euid) -/*[clinic end generated code: output=6e824cce4f3b8a5d input=ba93d927e4781aa9]*/ +/*[clinic end generated code: output=66f4f6823a648d6d input=ba93d927e4781aa9]*/ { if (seteuid(euid) < 0) return posix_error(); @@ -9009,37 +6613,9 @@ Set the current process's effective group id. [clinic start generated code]*/ -PyDoc_STRVAR(os_setegid__doc__, -"setegid($module, egid, /)\n" -"--\n" -"\n" -"Set the current process\'s effective group id."); - -#define OS_SETEGID_METHODDEF \ - {"setegid", (PyCFunction)os_setegid, METH_VARARGS, os_setegid__doc__}, - -static PyObject * -os_setegid_impl(PyModuleDef *module, gid_t egid); - -static PyObject * -os_setegid(PyModuleDef *module, PyObject *args) -{ - PyObject *return_value = NULL; - gid_t egid; - - if (!PyArg_ParseTuple(args, - "O&:setegid", - _Py_Gid_Converter, &egid)) - goto exit; - return_value = os_setegid_impl(module, egid); - -exit: - return return_value; -} - static PyObject * os_setegid_impl(PyModuleDef *module, gid_t egid) -/*[clinic end generated code: output=80a32263a4d56a9c input=4080526d0ccd6ce3]*/ +/*[clinic end generated code: output=ca094a69a081a60f input=4080526d0ccd6ce3]*/ { if (setegid(egid) < 0) return posix_error(); @@ -9059,38 +6635,9 @@ Set the current process's real and effective user ids. [clinic start generated code]*/ -PyDoc_STRVAR(os_setreuid__doc__, -"setreuid($module, ruid, euid, /)\n" -"--\n" -"\n" -"Set the current process\'s real and effective user ids."); - -#define OS_SETREUID_METHODDEF \ - {"setreuid", (PyCFunction)os_setreuid, METH_VARARGS, os_setreuid__doc__}, - -static PyObject * -os_setreuid_impl(PyModuleDef *module, uid_t ruid, uid_t euid); - -static PyObject * -os_setreuid(PyModuleDef *module, PyObject *args) -{ - PyObject *return_value = NULL; - uid_t ruid; - uid_t euid; - - if (!PyArg_ParseTuple(args, - "O&O&:setreuid", - _Py_Uid_Converter, &ruid, _Py_Uid_Converter, &euid)) - goto exit; - return_value = os_setreuid_impl(module, ruid, euid); - -exit: - return return_value; -} - static PyObject * os_setreuid_impl(PyModuleDef *module, uid_t ruid, uid_t euid) -/*[clinic end generated code: output=d7f226f943dad739 input=0ca8978de663880c]*/ +/*[clinic end generated code: output=b2938c3e73d27ec7 input=0ca8978de663880c]*/ { if (setreuid(ruid, euid) < 0) { return posix_error(); @@ -9113,38 +6660,9 @@ Set the current process's real and effective group ids. [clinic start generated code]*/ -PyDoc_STRVAR(os_setregid__doc__, -"setregid($module, rgid, egid, /)\n" -"--\n" -"\n" -"Set the current process\'s real and effective group ids."); - -#define OS_SETREGID_METHODDEF \ - {"setregid", (PyCFunction)os_setregid, METH_VARARGS, os_setregid__doc__}, - -static PyObject * -os_setregid_impl(PyModuleDef *module, gid_t rgid, gid_t egid); - -static PyObject * -os_setregid(PyModuleDef *module, PyObject *args) -{ - PyObject *return_value = NULL; - gid_t rgid; - gid_t egid; - - if (!PyArg_ParseTuple(args, - "O&O&:setregid", - _Py_Gid_Converter, &rgid, _Py_Gid_Converter, &egid)) - goto exit; - return_value = os_setregid_impl(module, rgid, egid); - -exit: - return return_value; -} - static PyObject * os_setregid_impl(PyModuleDef *module, gid_t rgid, gid_t egid) -/*[clinic end generated code: output=a82d9ab70f8e6562 input=c59499f72846db78]*/ +/*[clinic end generated code: output=db18f1839ababe3d input=c59499f72846db78]*/ { if (setregid(rgid, egid) < 0) return posix_error(); @@ -9162,37 +6680,9 @@ Set the current process's group id. [clinic start generated code]*/ -PyDoc_STRVAR(os_setgid__doc__, -"setgid($module, gid, /)\n" -"--\n" -"\n" -"Set the current process\'s group id."); - -#define OS_SETGID_METHODDEF \ - {"setgid", (PyCFunction)os_setgid, METH_VARARGS, os_setgid__doc__}, - -static PyObject * -os_setgid_impl(PyModuleDef *module, gid_t gid); - -static PyObject * -os_setgid(PyModuleDef *module, PyObject *args) -{ - PyObject *return_value = NULL; - gid_t gid; - - if (!PyArg_ParseTuple(args, - "O&:setgid", - _Py_Gid_Converter, &gid)) - goto exit; - return_value = os_setgid_impl(module, gid); - -exit: - return return_value; -} - static PyObject * os_setgid_impl(PyModuleDef *module, gid_t gid) -/*[clinic end generated code: output=08287886db435f23 input=27d30c4059045dc6]*/ +/*[clinic end generated code: output=756cb42c6abd9d87 input=27d30c4059045dc6]*/ { if (setgid(gid) < 0) return posix_error(); @@ -9211,18 +6701,9 @@ Set the groups of the current process to list. [clinic start generated code]*/ -PyDoc_STRVAR(os_setgroups__doc__, -"setgroups($module, groups, /)\n" -"--\n" -"\n" -"Set the groups of the current process to list."); - -#define OS_SETGROUPS_METHODDEF \ - {"setgroups", (PyCFunction)os_setgroups, METH_O, os_setgroups__doc__}, - static PyObject * os_setgroups(PyModuleDef *module, PyObject *groups) -/*[clinic end generated code: output=0b8de65d5b3cda94 input=fa742ca3daf85a7e]*/ +/*[clinic end generated code: output=7945c2e3cc817c58 input=fa742ca3daf85a7e]*/ { int i, len; gid_t grouplist[MAX_GROUPS]; @@ -9335,41 +6816,9 @@ (pid, status, rusage) [clinic start generated code]*/ -PyDoc_STRVAR(os_wait3__doc__, -"wait3($module, /, options)\n" -"--\n" -"\n" -"Wait for completion of a child process.\n" -"\n" -"Returns a tuple of information about the child process:\n" -" (pid, status, rusage)"); - -#define OS_WAIT3_METHODDEF \ - {"wait3", (PyCFunction)os_wait3, METH_VARARGS|METH_KEYWORDS, os_wait3__doc__}, - -static PyObject * -os_wait3_impl(PyModuleDef *module, int options); - -static PyObject * -os_wait3(PyModuleDef *module, PyObject *args, PyObject *kwargs) -{ - PyObject *return_value = NULL; - static char *_keywords[] = {"options", NULL}; - int options; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "i:wait3", _keywords, - &options)) - goto exit; - return_value = os_wait3_impl(module, options); - -exit: - return return_value; -} - static PyObject * os_wait3_impl(PyModuleDef *module, int options) -/*[clinic end generated code: output=1f2a63b6a93cbb57 input=8ac4c56956b61710]*/ +/*[clinic end generated code: output=e18af4924dc54945 input=8ac4c56956b61710]*/ { pid_t pid; struct rusage ru; @@ -9404,42 +6853,9 @@ (pid, status, rusage) [clinic start generated code]*/ -PyDoc_STRVAR(os_wait4__doc__, -"wait4($module, /, pid, options)\n" -"--\n" -"\n" -"Wait for completion of a specific child process.\n" -"\n" -"Returns a tuple of information about the child process:\n" -" (pid, status, rusage)"); - -#define OS_WAIT4_METHODDEF \ - {"wait4", (PyCFunction)os_wait4, METH_VARARGS|METH_KEYWORDS, os_wait4__doc__}, - -static PyObject * -os_wait4_impl(PyModuleDef *module, pid_t pid, int options); - -static PyObject * -os_wait4(PyModuleDef *module, PyObject *args, PyObject *kwargs) -{ - PyObject *return_value = NULL; - static char *_keywords[] = {"pid", "options", NULL}; - pid_t pid; - int options; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "" _Py_PARSE_PID "i:wait4", _keywords, - &pid, &options)) - goto exit; - return_value = os_wait4_impl(module, pid, options); - -exit: - return return_value; -} - static PyObject * os_wait4_impl(PyModuleDef *module, pid_t pid, int options) -/*[clinic end generated code: output=20dfb05289d37dc6 input=d11deed0750600ba]*/ +/*[clinic end generated code: output=714f19e6ff01e099 input=d11deed0750600ba]*/ { pid_t res; struct rusage ru; @@ -9479,50 +6895,9 @@ no children in a waitable state. [clinic start generated code]*/ -PyDoc_STRVAR(os_waitid__doc__, -"waitid($module, idtype, id, options, /)\n" -"--\n" -"\n" -"Returns the result of waiting for a process or processes.\n" -"\n" -" idtype\n" -" Must be one of be P_PID, P_PGID or P_ALL.\n" -" id\n" -" The id to wait on.\n" -" options\n" -" Constructed from the ORing of one or more of WEXITED, WSTOPPED\n" -" or WCONTINUED and additionally may be ORed with WNOHANG or WNOWAIT.\n" -"\n" -"Returns either waitid_result or None if WNOHANG is specified and there are\n" -"no children in a waitable state."); - -#define OS_WAITID_METHODDEF \ - {"waitid", (PyCFunction)os_waitid, METH_VARARGS, os_waitid__doc__}, - -static PyObject * -os_waitid_impl(PyModuleDef *module, idtype_t idtype, id_t id, int options); - -static PyObject * -os_waitid(PyModuleDef *module, PyObject *args) -{ - PyObject *return_value = NULL; - idtype_t idtype; - id_t id; - int options; - - if (!PyArg_ParseTuple(args, - "i" _Py_PARSE_PID "i:waitid", - &idtype, &id, &options)) - goto exit; - return_value = os_waitid_impl(module, idtype, id, options); - -exit: - return return_value; -} - static PyObject * os_waitid_impl(PyModuleDef *module, idtype_t idtype, id_t id, int options) -/*[clinic end generated code: output=fb44bf97f01021b2 input=d8e7f76e052b7920]*/ +/*[clinic end generated code: output=5c0192750e22fa2e input=d8e7f76e052b7920]*/ { PyObject *result; int res; @@ -9575,43 +6950,9 @@ The options argument is ignored on Windows. [clinic start generated code]*/ -PyDoc_STRVAR(os_waitpid__doc__, -"waitpid($module, pid, options, /)\n" -"--\n" -"\n" -"Wait for completion of a given child process.\n" -"\n" -"Returns a tuple of information regarding the child process:\n" -" (pid, status)\n" -"\n" -"The options argument is ignored on Windows."); - -#define OS_WAITPID_METHODDEF \ - {"waitpid", (PyCFunction)os_waitpid, METH_VARARGS, os_waitpid__doc__}, - -static PyObject * -os_waitpid_impl(PyModuleDef *module, pid_t pid, int options); - -static PyObject * -os_waitpid(PyModuleDef *module, PyObject *args) -{ - PyObject *return_value = NULL; - pid_t pid; - int options; - - if (!PyArg_ParseTuple(args, - "" _Py_PARSE_PID "i:waitpid", - &pid, &options)) - goto exit; - return_value = os_waitpid_impl(module, pid, options); - -exit: - return return_value; -} - static PyObject * os_waitpid_impl(PyModuleDef *module, pid_t pid, int options) -/*[clinic end generated code: output=095a6b00af70b7ac input=0bf1666b8758fda3]*/ +/*[clinic end generated code: output=5e3593353d54b15b input=0bf1666b8758fda3]*/ { pid_t res; int async_err = 0; @@ -9644,43 +6985,9 @@ The options argument is ignored on Windows. [clinic start generated code]*/ -PyDoc_STRVAR(os_waitpid__doc__, -"waitpid($module, pid, options, /)\n" -"--\n" -"\n" -"Wait for completion of a given process.\n" -"\n" -"Returns a tuple of information regarding the process:\n" -" (pid, status << 8)\n" -"\n" -"The options argument is ignored on Windows."); - -#define OS_WAITPID_METHODDEF \ - {"waitpid", (PyCFunction)os_waitpid, METH_VARARGS, os_waitpid__doc__}, - -static PyObject * -os_waitpid_impl(PyModuleDef *module, Py_intptr_t pid, int options); - -static PyObject * -os_waitpid(PyModuleDef *module, PyObject *args) -{ - PyObject *return_value = NULL; - Py_intptr_t pid; - int options; - - if (!PyArg_ParseTuple(args, - "" _Py_PARSE_INTPTR "i:waitpid", - &pid, &options)) - goto exit; - return_value = os_waitpid_impl(module, pid, options); - -exit: - return return_value; -} - static PyObject * os_waitpid_impl(PyModuleDef *module, Py_intptr_t pid, int options) -/*[clinic end generated code: output=c20b95b15ad44a3a input=444c8f51cca5b862]*/ +/*[clinic end generated code: output=fc1d520db019625f input=444c8f51cca5b862]*/ { int status; Py_intptr_t res; @@ -9710,30 +7017,9 @@ (pid, status) [clinic start generated code]*/ -PyDoc_STRVAR(os_wait__doc__, -"wait($module, /)\n" -"--\n" -"\n" -"Wait for completion of a child process.\n" -"\n" -"Returns a tuple of information about the child process:\n" -" (pid, status)"); - -#define OS_WAIT_METHODDEF \ - {"wait", (PyCFunction)os_wait, METH_NOARGS, os_wait__doc__}, - -static PyObject * -os_wait_impl(PyModuleDef *module); - -static PyObject * -os_wait(PyModuleDef *module, PyObject *Py_UNUSED(ignored)) -{ - return os_wait_impl(module); -} - static PyObject * os_wait_impl(PyModuleDef *module) -/*[clinic end generated code: output=2a83a9d164e7e6a8 input=03b0182d4a4700ce]*/ +/*[clinic end generated code: output=4a7f4978393e0654 input=03b0182d4a4700ce]*/ { pid_t pid; int async_err = 0; @@ -10059,56 +7345,9 @@ [clinic start generated code]*/ -PyDoc_STRVAR(os_symlink__doc__, -"symlink($module, /, src, dst, target_is_directory=False, *, dir_fd=None)\n" -"--\n" -"\n" -"Create a symbolic link pointing to src named dst.\n" -"\n" -"target_is_directory is required on Windows if the target is to be\n" -" interpreted as a directory. (On Windows, symlink requires\n" -" Windows 6.0 or greater, and raises a NotImplementedError otherwise.)\n" -" target_is_directory is ignored on non-Windows platforms.\n" -"\n" -"If dir_fd is not None, it should be a file descriptor open to a directory,\n" -" and path should be relative; path will then be relative to that directory.\n" -"dir_fd may not be implemented on your platform.\n" -" If it is unavailable, using it will raise a NotImplementedError."); - -#define OS_SYMLINK_METHODDEF \ - {"symlink", (PyCFunction)os_symlink, METH_VARARGS|METH_KEYWORDS, os_symlink__doc__}, - -static PyObject * -os_symlink_impl(PyModuleDef *module, path_t *src, path_t *dst, int target_is_directory, int dir_fd); - -static PyObject * -os_symlink(PyModuleDef *module, PyObject *args, PyObject *kwargs) -{ - PyObject *return_value = NULL; - static char *_keywords[] = {"src", "dst", "target_is_directory", "dir_fd", NULL}; - path_t src = PATH_T_INITIALIZE("symlink", "src", 0, 0); - path_t dst = PATH_T_INITIALIZE("symlink", "dst", 0, 0); - int target_is_directory = 0; - int dir_fd = DEFAULT_DIR_FD; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "O&O&|p$O&:symlink", _keywords, - path_converter, &src, path_converter, &dst, &target_is_directory, SYMLINKAT_DIR_FD_CONVERTER, &dir_fd)) - goto exit; - return_value = os_symlink_impl(module, &src, &dst, target_is_directory, dir_fd); - -exit: - /* Cleanup for src */ - path_cleanup(&src); - /* Cleanup for dst */ - path_cleanup(&dst); - - return return_value; -} - static PyObject * os_symlink_impl(PyModuleDef *module, path_t *src, path_t *dst, int target_is_directory, int dir_fd) -/*[clinic end generated code: output=1a31e6d88aafe9b6 input=e820ec4472547bc3]*/ +/*[clinic end generated code: output=11aa03f278bb2c8a input=e820ec4472547bc3]*/ { #ifdef MS_WINDOWS DWORD result; @@ -10255,31 +7494,9 @@ All fields are floating point numbers. [clinic start generated code]*/ -PyDoc_STRVAR(os_times__doc__, -"times($module, /)\n" -"--\n" -"\n" -"Return a collection containing process timing information.\n" -"\n" -"The object returned behaves like a named tuple with these fields:\n" -" (utime, stime, cutime, cstime, elapsed_time)\n" -"All fields are floating point numbers."); - -#define OS_TIMES_METHODDEF \ - {"times", (PyCFunction)os_times, METH_NOARGS, os_times__doc__}, - -static PyObject * -os_times_impl(PyModuleDef *module); - -static PyObject * -os_times(PyModuleDef *module, PyObject *Py_UNUSED(ignored)) -{ - return os_times_impl(module); -} - static PyObject * os_times_impl(PyModuleDef *module) -/*[clinic end generated code: output=b86896d031a9b768 input=2bf9df3d6ab2e48b]*/ +/*[clinic end generated code: output=df0a63ebe6e6f091 input=2bf9df3d6ab2e48b]*/ #ifdef MS_WINDOWS { FILETIME create, exit, kernel, user; @@ -10331,37 +7548,9 @@ Call the system call getsid(pid) and return the result. [clinic start generated code]*/ -PyDoc_STRVAR(os_getsid__doc__, -"getsid($module, pid, /)\n" -"--\n" -"\n" -"Call the system call getsid(pid) and return the result."); - -#define OS_GETSID_METHODDEF \ - {"getsid", (PyCFunction)os_getsid, METH_VARARGS, os_getsid__doc__}, - -static PyObject * -os_getsid_impl(PyModuleDef *module, pid_t pid); - -static PyObject * -os_getsid(PyModuleDef *module, PyObject *args) -{ - PyObject *return_value = NULL; - pid_t pid; - - if (!PyArg_ParseTuple(args, - "" _Py_PARSE_PID ":getsid", - &pid)) - goto exit; - return_value = os_getsid_impl(module, pid); - -exit: - return return_value; -} - static PyObject * os_getsid_impl(PyModuleDef *module, pid_t pid) -/*[clinic end generated code: output=ea8390f395f4e0e1 input=eeb2b923a30ce04e]*/ +/*[clinic end generated code: output=a074f80c0e6bfb38 input=eeb2b923a30ce04e]*/ { int sid; sid = getsid(pid); @@ -10379,27 +7568,9 @@ Call the system call setsid(). [clinic start generated code]*/ -PyDoc_STRVAR(os_setsid__doc__, -"setsid($module, /)\n" -"--\n" -"\n" -"Call the system call setsid()."); - -#define OS_SETSID_METHODDEF \ - {"setsid", (PyCFunction)os_setsid, METH_NOARGS, os_setsid__doc__}, - -static PyObject * -os_setsid_impl(PyModuleDef *module); - -static PyObject * -os_setsid(PyModuleDef *module, PyObject *Py_UNUSED(ignored)) -{ - return os_setsid_impl(module); -} - static PyObject * os_setsid_impl(PyModuleDef *module) -/*[clinic end generated code: output=2a9a1435d8d764d5 input=5fff45858e2f0776]*/ +/*[clinic end generated code: output=398fc152ae327330 input=5fff45858e2f0776]*/ { if (setsid() < 0) return posix_error(); @@ -10419,38 +7590,9 @@ Call the system call setpgid(pid, pgrp). [clinic start generated code]*/ -PyDoc_STRVAR(os_setpgid__doc__, -"setpgid($module, pid, pgrp, /)\n" -"--\n" -"\n" -"Call the system call setpgid(pid, pgrp)."); - -#define OS_SETPGID_METHODDEF \ - {"setpgid", (PyCFunction)os_setpgid, METH_VARARGS, os_setpgid__doc__}, - -static PyObject * -os_setpgid_impl(PyModuleDef *module, pid_t pid, pid_t pgrp); - -static PyObject * -os_setpgid(PyModuleDef *module, PyObject *args) -{ - PyObject *return_value = NULL; - pid_t pid; - pid_t pgrp; - - if (!PyArg_ParseTuple(args, - "" _Py_PARSE_PID "" _Py_PARSE_PID ":setpgid", - &pid, &pgrp)) - goto exit; - return_value = os_setpgid_impl(module, pid, pgrp); - -exit: - return return_value; -} - static PyObject * os_setpgid_impl(PyModuleDef *module, pid_t pid, pid_t pgrp) -/*[clinic end generated code: output=7ad79b725f890e1f input=fceb395eca572e1a]*/ +/*[clinic end generated code: output=7079a8e932912841 input=fceb395eca572e1a]*/ { if (setpgid(pid, pgrp) < 0) return posix_error(); @@ -10469,37 +7611,9 @@ Return the process group associated with the terminal specified by fd. [clinic start generated code]*/ -PyDoc_STRVAR(os_tcgetpgrp__doc__, -"tcgetpgrp($module, fd, /)\n" -"--\n" -"\n" -"Return the process group associated with the terminal specified by fd."); - -#define OS_TCGETPGRP_METHODDEF \ - {"tcgetpgrp", (PyCFunction)os_tcgetpgrp, METH_VARARGS, os_tcgetpgrp__doc__}, - -static PyObject * -os_tcgetpgrp_impl(PyModuleDef *module, int fd); - -static PyObject * -os_tcgetpgrp(PyModuleDef *module, PyObject *args) -{ - PyObject *return_value = NULL; - int fd; - - if (!PyArg_ParseTuple(args, - "i:tcgetpgrp", - &fd)) - goto exit; - return_value = os_tcgetpgrp_impl(module, fd); - -exit: - return return_value; -} - static PyObject * os_tcgetpgrp_impl(PyModuleDef *module, int fd) -/*[clinic end generated code: output=abcf52ed4c8d22cb input=7f6c18eac10ada86]*/ +/*[clinic end generated code: output=ebb6dc5f111c7dc0 input=7f6c18eac10ada86]*/ { pid_t pgid = tcgetpgrp(fd); if (pgid < 0) @@ -10520,38 +7634,9 @@ Set the process group associated with the terminal specified by fd. [clinic start generated code]*/ -PyDoc_STRVAR(os_tcsetpgrp__doc__, -"tcsetpgrp($module, fd, pgid, /)\n" -"--\n" -"\n" -"Set the process group associated with the terminal specified by fd."); - -#define OS_TCSETPGRP_METHODDEF \ - {"tcsetpgrp", (PyCFunction)os_tcsetpgrp, METH_VARARGS, os_tcsetpgrp__doc__}, - -static PyObject * -os_tcsetpgrp_impl(PyModuleDef *module, int fd, pid_t pgid); - -static PyObject * -os_tcsetpgrp(PyModuleDef *module, PyObject *args) -{ - PyObject *return_value = NULL; - int fd; - pid_t pgid; - - if (!PyArg_ParseTuple(args, - "i" _Py_PARSE_PID ":tcsetpgrp", - &fd, &pgid)) - goto exit; - return_value = os_tcsetpgrp_impl(module, fd, pgid); - -exit: - return return_value; -} - static PyObject * os_tcsetpgrp_impl(PyModuleDef *module, int fd, pid_t pgid) -/*[clinic end generated code: output=76f9bb8fd00f20f5 input=5bdc997c6a619020]*/ +/*[clinic end generated code: output=3e4b05177462cd22 input=5bdc997c6a619020]*/ { if (tcsetpgrp(fd, pgid) < 0) return posix_error(); @@ -10584,53 +7669,9 @@ If it is unavailable, using it will raise a NotImplementedError. [clinic start generated code]*/ -PyDoc_STRVAR(os_open__doc__, -"open($module, /, path, flags, mode=511, *, dir_fd=None)\n" -"--\n" -"\n" -"Open a file for low level IO. Returns a file descriptor (integer).\n" -"\n" -"If dir_fd is not None, it should be a file descriptor open to a directory,\n" -" and path should be relative; path will then be relative to that directory.\n" -"dir_fd may not be implemented on your platform.\n" -" If it is unavailable, using it will raise a NotImplementedError."); - -#define OS_OPEN_METHODDEF \ - {"open", (PyCFunction)os_open, METH_VARARGS|METH_KEYWORDS, os_open__doc__}, - -static int -os_open_impl(PyModuleDef *module, path_t *path, int flags, int mode, int dir_fd); - -static PyObject * -os_open(PyModuleDef *module, PyObject *args, PyObject *kwargs) -{ - PyObject *return_value = NULL; - static char *_keywords[] = {"path", "flags", "mode", "dir_fd", NULL}; - path_t path = PATH_T_INITIALIZE("open", "path", 0, 0); - int flags; - int mode = 511; - int dir_fd = DEFAULT_DIR_FD; - int _return_value; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "O&i|i$O&:open", _keywords, - path_converter, &path, &flags, &mode, OPENAT_DIR_FD_CONVERTER, &dir_fd)) - goto exit; - _return_value = os_open_impl(module, &path, flags, mode, dir_fd); - if ((_return_value == -1) && PyErr_Occurred()) - goto exit; - return_value = PyLong_FromLong((long)_return_value); - -exit: - /* Cleanup for path */ - path_cleanup(&path); - - return return_value; -} - static int os_open_impl(PyModuleDef *module, path_t *path, int flags, int mode, int dir_fd) -/*[clinic end generated code: output=05b68fc4ed5e29c9 input=ad8623b29acd2934]*/ +/*[clinic end generated code: output=c95a64f0e62f199b input=ad8623b29acd2934]*/ { int fd; int async_err = 0; @@ -10688,38 +7729,9 @@ Close a file descriptor. [clinic start generated code]*/ -PyDoc_STRVAR(os_close__doc__, -"close($module, /, fd)\n" -"--\n" -"\n" -"Close a file descriptor."); - -#define OS_CLOSE_METHODDEF \ - {"close", (PyCFunction)os_close, METH_VARARGS|METH_KEYWORDS, os_close__doc__}, - -static PyObject * -os_close_impl(PyModuleDef *module, int fd); - -static PyObject * -os_close(PyModuleDef *module, PyObject *args, PyObject *kwargs) -{ - PyObject *return_value = NULL; - static char *_keywords[] = {"fd", NULL}; - int fd; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "i:close", _keywords, - &fd)) - goto exit; - return_value = os_close_impl(module, fd); - -exit: - return return_value; -} - static PyObject * os_close_impl(PyModuleDef *module, int fd) -/*[clinic end generated code: output=927004e29ad55808 input=2bc42451ca5c3223]*/ +/*[clinic end generated code: output=47bf2ea536445a26 input=2bc42451ca5c3223]*/ { int res; if (!_PyVerify_fd(fd)) @@ -10747,38 +7759,9 @@ Closes all file descriptors in [fd_low, fd_high), ignoring errors. [clinic start generated code]*/ -PyDoc_STRVAR(os_closerange__doc__, -"closerange($module, fd_low, fd_high, /)\n" -"--\n" -"\n" -"Closes all file descriptors in [fd_low, fd_high), ignoring errors."); - -#define OS_CLOSERANGE_METHODDEF \ - {"closerange", (PyCFunction)os_closerange, METH_VARARGS, os_closerange__doc__}, - -static PyObject * -os_closerange_impl(PyModuleDef *module, int fd_low, int fd_high); - -static PyObject * -os_closerange(PyModuleDef *module, PyObject *args) -{ - PyObject *return_value = NULL; - int fd_low; - int fd_high; - - if (!PyArg_ParseTuple(args, - "ii:closerange", - &fd_low, &fd_high)) - goto exit; - return_value = os_closerange_impl(module, fd_low, fd_high); - -exit: - return return_value; -} - static PyObject * os_closerange_impl(PyModuleDef *module, int fd_low, int fd_high) -/*[clinic end generated code: output=0a929ece386811c3 input=5855a3d053ebd4ec]*/ +/*[clinic end generated code: output=70e6adb95220ba96 input=5855a3d053ebd4ec]*/ { int i; Py_BEGIN_ALLOW_THREADS @@ -10799,41 +7782,9 @@ Return a duplicate of a file descriptor. [clinic start generated code]*/ -PyDoc_STRVAR(os_dup__doc__, -"dup($module, fd, /)\n" -"--\n" -"\n" -"Return a duplicate of a file descriptor."); - -#define OS_DUP_METHODDEF \ - {"dup", (PyCFunction)os_dup, METH_VARARGS, os_dup__doc__}, - -static int -os_dup_impl(PyModuleDef *module, int fd); - -static PyObject * -os_dup(PyModuleDef *module, PyObject *args) -{ - PyObject *return_value = NULL; - int fd; - int _return_value; - - if (!PyArg_ParseTuple(args, - "i:dup", - &fd)) - goto exit; - _return_value = os_dup_impl(module, fd); - if ((_return_value == -1) && PyErr_Occurred()) - goto exit; - return_value = PyLong_FromLong((long)_return_value); - -exit: - return return_value; -} - static int os_dup_impl(PyModuleDef *module, int fd) -/*[clinic end generated code: output=75943e057b25e1bd input=6f10f7ea97f7852a]*/ +/*[clinic end generated code: output=f4bbac8c7652d05e input=6f10f7ea97f7852a]*/ { return _Py_dup(fd); } @@ -10848,40 +7799,9 @@ Duplicate file descriptor. [clinic start generated code]*/ -PyDoc_STRVAR(os_dup2__doc__, -"dup2($module, /, fd, fd2, inheritable=True)\n" -"--\n" -"\n" -"Duplicate file descriptor."); - -#define OS_DUP2_METHODDEF \ - {"dup2", (PyCFunction)os_dup2, METH_VARARGS|METH_KEYWORDS, os_dup2__doc__}, - -static PyObject * -os_dup2_impl(PyModuleDef *module, int fd, int fd2, int inheritable); - -static PyObject * -os_dup2(PyModuleDef *module, PyObject *args, PyObject *kwargs) -{ - PyObject *return_value = NULL; - static char *_keywords[] = {"fd", "fd2", "inheritable", NULL}; - int fd; - int fd2; - int inheritable = 1; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "ii|p:dup2", _keywords, - &fd, &fd2, &inheritable)) - goto exit; - return_value = os_dup2_impl(module, fd, fd2, inheritable); - -exit: - return return_value; -} - static PyObject * os_dup2_impl(PyModuleDef *module, int fd, int fd2, int inheritable) -/*[clinic end generated code: output=531e482dd11a99a0 input=76e96f511be0352f]*/ +/*[clinic end generated code: output=9a099d95881a7923 input=76e96f511be0352f]*/ { int res; #if defined(HAVE_DUP3) && \ @@ -10974,46 +7894,9 @@ [clinic start generated code]*/ -PyDoc_STRVAR(os_lockf__doc__, -"lockf($module, fd, command, length, /)\n" -"--\n" -"\n" -"Apply, test or remove a POSIX lock on an open file descriptor.\n" -"\n" -" fd\n" -" An open file descriptor.\n" -" command\n" -" One of F_LOCK, F_TLOCK, F_ULOCK or F_TEST.\n" -" length\n" -" The number of bytes to lock, starting at the current position."); - -#define OS_LOCKF_METHODDEF \ - {"lockf", (PyCFunction)os_lockf, METH_VARARGS, os_lockf__doc__}, - -static PyObject * -os_lockf_impl(PyModuleDef *module, int fd, int command, Py_off_t length); - -static PyObject * -os_lockf(PyModuleDef *module, PyObject *args) -{ - PyObject *return_value = NULL; - int fd; - int command; - Py_off_t length; - - if (!PyArg_ParseTuple(args, - "iiO&:lockf", - &fd, &command, Py_off_t_converter, &length)) - goto exit; - return_value = os_lockf_impl(module, fd, command, length); - -exit: - return return_value; -} - static PyObject * os_lockf_impl(PyModuleDef *module, int fd, int command, Py_off_t length) -/*[clinic end generated code: output=1b28346ac7335c0f input=65da41d2106e9b79]*/ +/*[clinic end generated code: output=25ff778f9e2fbf1b input=65da41d2106e9b79]*/ { int res; @@ -11043,46 +7926,9 @@ relative to the beginning of the file. [clinic start generated code]*/ -PyDoc_STRVAR(os_lseek__doc__, -"lseek($module, fd, position, how, /)\n" -"--\n" -"\n" -"Set the position of a file descriptor. Return the new position.\n" -"\n" -"Return the new cursor position in number of bytes\n" -"relative to the beginning of the file."); - -#define OS_LSEEK_METHODDEF \ - {"lseek", (PyCFunction)os_lseek, METH_VARARGS, os_lseek__doc__}, - -static Py_off_t -os_lseek_impl(PyModuleDef *module, int fd, Py_off_t position, int how); - -static PyObject * -os_lseek(PyModuleDef *module, PyObject *args) -{ - PyObject *return_value = NULL; - int fd; - Py_off_t position; - int how; - Py_off_t _return_value; - - if (!PyArg_ParseTuple(args, - "iO&i:lseek", - &fd, Py_off_t_converter, &position, &how)) - goto exit; - _return_value = os_lseek_impl(module, fd, position, how); - if ((_return_value == -1) && PyErr_Occurred()) - goto exit; - return_value = PyLong_FromPy_off_t(_return_value); - -exit: - return return_value; -} - static Py_off_t os_lseek_impl(PyModuleDef *module, int fd, Py_off_t position, int how) -/*[clinic end generated code: output=88cfc146f55667af input=902654ad3f96a6d3]*/ +/*[clinic end generated code: output=65d4ab96d664998c input=902654ad3f96a6d3]*/ { Py_off_t result; @@ -11129,38 +7975,9 @@ Read from a file descriptor. Returns a bytes object. [clinic start generated code]*/ -PyDoc_STRVAR(os_read__doc__, -"read($module, fd, length, /)\n" -"--\n" -"\n" -"Read from a file descriptor. Returns a bytes object."); - -#define OS_READ_METHODDEF \ - {"read", (PyCFunction)os_read, METH_VARARGS, os_read__doc__}, - -static PyObject * -os_read_impl(PyModuleDef *module, int fd, Py_ssize_t length); - -static PyObject * -os_read(PyModuleDef *module, PyObject *args) -{ - PyObject *return_value = NULL; - int fd; - Py_ssize_t length; - - if (!PyArg_ParseTuple(args, - "in:read", - &fd, &length)) - goto exit; - return_value = os_read_impl(module, fd, length); - -exit: - return return_value; -} - static PyObject * os_read_impl(PyModuleDef *module, int fd, Py_ssize_t length) -/*[clinic end generated code: output=1f3bc27260a24968 input=1df2eaa27c0bf1d3]*/ +/*[clinic end generated code: output=be24f44178455e8b input=1df2eaa27c0bf1d3]*/ { Py_ssize_t n; PyObject *buffer; @@ -11270,50 +8087,9 @@ which may be less than the total capacity of all the buffers. [clinic start generated code]*/ -PyDoc_STRVAR(os_readv__doc__, -"readv($module, fd, buffers, /)\n" -"--\n" -"\n" -"Read from a file descriptor fd into an iterable of buffers.\n" -"\n" -"The buffers should be mutable buffers accepting bytes.\n" -"readv will transfer data into each buffer until it is full\n" -"and then move on to the next buffer in the sequence to hold\n" -"the rest of the data.\n" -"\n" -"readv returns the total number of bytes read,\n" -"which may be less than the total capacity of all the buffers."); - -#define OS_READV_METHODDEF \ - {"readv", (PyCFunction)os_readv, METH_VARARGS, os_readv__doc__}, - -static Py_ssize_t -os_readv_impl(PyModuleDef *module, int fd, PyObject *buffers); - -static PyObject * -os_readv(PyModuleDef *module, PyObject *args) -{ - PyObject *return_value = NULL; - int fd; - PyObject *buffers; - Py_ssize_t _return_value; - - if (!PyArg_ParseTuple(args, - "iO:readv", - &fd, &buffers)) - goto exit; - _return_value = os_readv_impl(module, fd, buffers); - if ((_return_value == -1) && PyErr_Occurred()) - goto exit; - return_value = PyLong_FromSsize_t(_return_value); - -exit: - return return_value; -} - static Py_ssize_t os_readv_impl(PyModuleDef *module, int fd, PyObject *buffers) -/*[clinic end generated code: output=72748b1c32a6e2a1 input=e679eb5dbfa0357d]*/ +/*[clinic end generated code: output=00fc56ff1800059f input=e679eb5dbfa0357d]*/ { int cnt; Py_ssize_t n; @@ -11366,42 +8142,9 @@ the beginning of the file. The file offset remains unchanged. [clinic start generated code]*/ -PyDoc_STRVAR(os_pread__doc__, -"pread($module, fd, length, offset, /)\n" -"--\n" -"\n" -"Read a number of bytes from a file descriptor starting at a particular offset.\n" -"\n" -"Read length bytes from file descriptor fd, starting at offset bytes from\n" -"the beginning of the file. The file offset remains unchanged."); - -#define OS_PREAD_METHODDEF \ - {"pread", (PyCFunction)os_pread, METH_VARARGS, os_pread__doc__}, - -static PyObject * -os_pread_impl(PyModuleDef *module, int fd, int length, Py_off_t offset); - -static PyObject * -os_pread(PyModuleDef *module, PyObject *args) -{ - PyObject *return_value = NULL; - int fd; - int length; - Py_off_t offset; - - if (!PyArg_ParseTuple(args, - "iiO&:pread", - &fd, &length, Py_off_t_converter, &offset)) - goto exit; - return_value = os_pread_impl(module, fd, length, offset); - -exit: - return return_value; -} - static PyObject * os_pread_impl(PyModuleDef *module, int fd, int length, Py_off_t offset) -/*[clinic end generated code: output=7b62bf6c06e20ae8 input=084948dcbaa35d4c]*/ +/*[clinic end generated code: output=90d1fed87f68fa33 input=084948dcbaa35d4c]*/ { Py_ssize_t n; int async_err = 0; @@ -11446,46 +8189,9 @@ Write a bytes object to a file descriptor. [clinic start generated code]*/ -PyDoc_STRVAR(os_write__doc__, -"write($module, fd, data, /)\n" -"--\n" -"\n" -"Write a bytes object to a file descriptor."); - -#define OS_WRITE_METHODDEF \ - {"write", (PyCFunction)os_write, METH_VARARGS, os_write__doc__}, - -static Py_ssize_t -os_write_impl(PyModuleDef *module, int fd, Py_buffer *data); - -static PyObject * -os_write(PyModuleDef *module, PyObject *args) -{ - PyObject *return_value = NULL; - int fd; - Py_buffer data = {NULL, NULL}; - Py_ssize_t _return_value; - - if (!PyArg_ParseTuple(args, - "iy*:write", - &fd, &data)) - goto exit; - _return_value = os_write_impl(module, fd, &data); - if ((_return_value == -1) && PyErr_Occurred()) - goto exit; - return_value = PyLong_FromSsize_t(_return_value); - -exit: - /* Cleanup for data */ - if (data.obj) - PyBuffer_Release(&data); - - return return_value; -} - static Py_ssize_t os_write_impl(PyModuleDef *module, int fd, Py_buffer *data) -/*[clinic end generated code: output=aeb96acfdd4d5112 input=3207e28963234f3c]*/ +/*[clinic end generated code: output=58845c93c9ee1dda input=3207e28963234f3c]*/ { return _Py_write(fd, data->buf, data->len); } @@ -11651,41 +8357,9 @@ Equivalent to os.stat(fd). [clinic start generated code]*/ -PyDoc_STRVAR(os_fstat__doc__, -"fstat($module, /, fd)\n" -"--\n" -"\n" -"Perform a stat system call on the given file descriptor.\n" -"\n" -"Like stat(), but for an open file descriptor.\n" -"Equivalent to os.stat(fd)."); - -#define OS_FSTAT_METHODDEF \ - {"fstat", (PyCFunction)os_fstat, METH_VARARGS|METH_KEYWORDS, os_fstat__doc__}, - -static PyObject * -os_fstat_impl(PyModuleDef *module, int fd); - -static PyObject * -os_fstat(PyModuleDef *module, PyObject *args, PyObject *kwargs) -{ - PyObject *return_value = NULL; - static char *_keywords[] = {"fd", NULL}; - int fd; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "i:fstat", _keywords, - &fd)) - goto exit; - return_value = os_fstat_impl(module, fd); - -exit: - return return_value; -} - static PyObject * os_fstat_impl(PyModuleDef *module, int fd) -/*[clinic end generated code: output=dae4a9678c7bd881 input=27e0e0ebbe5600c9]*/ +/*[clinic end generated code: output=d71fe98bf042b626 input=27e0e0ebbe5600c9]*/ { STRUCT_STAT st; int res; @@ -11719,44 +8393,9 @@ connected to the slave end of a terminal. [clinic start generated code]*/ -PyDoc_STRVAR(os_isatty__doc__, -"isatty($module, fd, /)\n" -"--\n" -"\n" -"Return True if the fd is connected to a terminal.\n" -"\n" -"Return True if the file descriptor is an open file descriptor\n" -"connected to the slave end of a terminal."); - -#define OS_ISATTY_METHODDEF \ - {"isatty", (PyCFunction)os_isatty, METH_VARARGS, os_isatty__doc__}, - -static int -os_isatty_impl(PyModuleDef *module, int fd); - -static PyObject * -os_isatty(PyModuleDef *module, PyObject *args) -{ - PyObject *return_value = NULL; - int fd; - int _return_value; - - if (!PyArg_ParseTuple(args, - "i:isatty", - &fd)) - goto exit; - _return_value = os_isatty_impl(module, fd); - if ((_return_value == -1) && PyErr_Occurred()) - goto exit; - return_value = PyBool_FromLong((long)_return_value); - -exit: - return return_value; -} - static int os_isatty_impl(PyModuleDef *module, int fd) -/*[clinic end generated code: output=4bfadbfe22715097 input=08ce94aa1eaf7b5e]*/ +/*[clinic end generated code: output=acec9d3c29d16d33 input=08ce94aa1eaf7b5e]*/ { if (!_PyVerify_fd(fd)) return 0; @@ -11774,30 +8413,9 @@ (read_fd, write_fd) [clinic start generated code]*/ -PyDoc_STRVAR(os_pipe__doc__, -"pipe($module, /)\n" -"--\n" -"\n" -"Create a pipe.\n" -"\n" -"Returns a tuple of two file descriptors:\n" -" (read_fd, write_fd)"); - -#define OS_PIPE_METHODDEF \ - {"pipe", (PyCFunction)os_pipe, METH_NOARGS, os_pipe__doc__}, - -static PyObject * -os_pipe_impl(PyModuleDef *module); - -static PyObject * -os_pipe(PyModuleDef *module, PyObject *Py_UNUSED(ignored)) -{ - return os_pipe_impl(module); -} - static PyObject * os_pipe_impl(PyModuleDef *module) -/*[clinic end generated code: output=0da2479f2266e774 input=02535e8c8fa6c4d4]*/ +/*[clinic end generated code: output=6b0cd3f868ec3c40 input=02535e8c8fa6c4d4]*/ { int fds[2]; #ifdef MS_WINDOWS @@ -11882,43 +8500,9 @@ O_NONBLOCK, O_CLOEXEC. [clinic start generated code]*/ -PyDoc_STRVAR(os_pipe2__doc__, -"pipe2($module, flags, /)\n" -"--\n" -"\n" -"Create a pipe with flags set atomically.\n" -"\n" -"Returns a tuple of two file descriptors:\n" -" (read_fd, write_fd)\n" -"\n" -"flags can be constructed by ORing together one or more of these values:\n" -"O_NONBLOCK, O_CLOEXEC."); - -#define OS_PIPE2_METHODDEF \ - {"pipe2", (PyCFunction)os_pipe2, METH_VARARGS, os_pipe2__doc__}, - -static PyObject * -os_pipe2_impl(PyModuleDef *module, int flags); - -static PyObject * -os_pipe2(PyModuleDef *module, PyObject *args) -{ - PyObject *return_value = NULL; - int flags; - - if (!PyArg_ParseTuple(args, - "i:pipe2", - &flags)) - goto exit; - return_value = os_pipe2_impl(module, flags); - -exit: - return return_value; -} - static PyObject * os_pipe2_impl(PyModuleDef *module, int flags) -/*[clinic end generated code: output=9e27c799ce19220b input=f261b6e7e63c6817]*/ +/*[clinic end generated code: output=c15b6075d0c6b2e7 input=f261b6e7e63c6817]*/ { int fds[2]; int res; @@ -11944,45 +8528,9 @@ buffers must be a sequence of bytes-like objects. [clinic start generated code]*/ -PyDoc_STRVAR(os_writev__doc__, -"writev($module, fd, buffers, /)\n" -"--\n" -"\n" -"Iterate over buffers, and write the contents of each to a file descriptor.\n" -"\n" -"Returns the total number of bytes written.\n" -"buffers must be a sequence of bytes-like objects."); - -#define OS_WRITEV_METHODDEF \ - {"writev", (PyCFunction)os_writev, METH_VARARGS, os_writev__doc__}, - -static Py_ssize_t -os_writev_impl(PyModuleDef *module, int fd, PyObject *buffers); - -static PyObject * -os_writev(PyModuleDef *module, PyObject *args) -{ - PyObject *return_value = NULL; - int fd; - PyObject *buffers; - Py_ssize_t _return_value; - - if (!PyArg_ParseTuple(args, - "iO:writev", - &fd, &buffers)) - goto exit; - _return_value = os_writev_impl(module, fd, buffers); - if ((_return_value == -1) && PyErr_Occurred()) - goto exit; - return_value = PyLong_FromSsize_t(_return_value); - -exit: - return return_value; -} - static Py_ssize_t os_writev_impl(PyModuleDef *module, int fd, PyObject *buffers) -/*[clinic end generated code: output=591c662dccbe4951 input=5b8d17fe4189d2fe]*/ +/*[clinic end generated code: output=a48925dbf2d5c238 input=5b8d17fe4189d2fe]*/ { int cnt; Py_ssize_t result; @@ -12032,51 +8580,9 @@ current file offset. [clinic start generated code]*/ -PyDoc_STRVAR(os_pwrite__doc__, -"pwrite($module, fd, buffer, offset, /)\n" -"--\n" -"\n" -"Write bytes to a file descriptor starting at a particular offset.\n" -"\n" -"Write buffer to fd, starting at offset bytes from the beginning of\n" -"the file. Returns the number of bytes writte. Does not change the\n" -"current file offset."); - -#define OS_PWRITE_METHODDEF \ - {"pwrite", (PyCFunction)os_pwrite, METH_VARARGS, os_pwrite__doc__}, - -static Py_ssize_t -os_pwrite_impl(PyModuleDef *module, int fd, Py_buffer *buffer, Py_off_t offset); - -static PyObject * -os_pwrite(PyModuleDef *module, PyObject *args) -{ - PyObject *return_value = NULL; - int fd; - Py_buffer buffer = {NULL, NULL}; - Py_off_t offset; - Py_ssize_t _return_value; - - if (!PyArg_ParseTuple(args, - "iy*O&:pwrite", - &fd, &buffer, Py_off_t_converter, &offset)) - goto exit; - _return_value = os_pwrite_impl(module, fd, &buffer, offset); - if ((_return_value == -1) && PyErr_Occurred()) - goto exit; - return_value = PyLong_FromSsize_t(_return_value); - -exit: - /* Cleanup for buffer */ - if (buffer.obj) - PyBuffer_Release(&buffer); - - return return_value; -} - static Py_ssize_t os_pwrite_impl(PyModuleDef *module, int fd, Py_buffer *buffer, Py_off_t offset) -/*[clinic end generated code: output=ec9cc5b2238e96a7 input=19903f1b3dd26377]*/ +/*[clinic end generated code: output=95225f3b496feaf3 input=19903f1b3dd26377]*/ { Py_ssize_t size; int async_err = 0; @@ -12116,48 +8622,9 @@ If it is unavailable, using it will raise a NotImplementedError. [clinic start generated code]*/ -PyDoc_STRVAR(os_mkfifo__doc__, -"mkfifo($module, /, path, mode=438, *, dir_fd=None)\n" -"--\n" -"\n" -"Create a \"fifo\" (a POSIX named pipe).\n" -"\n" -"If dir_fd is not None, it should be a file descriptor open to a directory,\n" -" and path should be relative; path will then be relative to that directory.\n" -"dir_fd may not be implemented on your platform.\n" -" If it is unavailable, using it will raise a NotImplementedError."); - -#define OS_MKFIFO_METHODDEF \ - {"mkfifo", (PyCFunction)os_mkfifo, METH_VARARGS|METH_KEYWORDS, os_mkfifo__doc__}, - -static PyObject * -os_mkfifo_impl(PyModuleDef *module, path_t *path, int mode, int dir_fd); - -static PyObject * -os_mkfifo(PyModuleDef *module, PyObject *args, PyObject *kwargs) -{ - PyObject *return_value = NULL; - static char *_keywords[] = {"path", "mode", "dir_fd", NULL}; - path_t path = PATH_T_INITIALIZE("mkfifo", "path", 0, 0); - int mode = 438; - int dir_fd = DEFAULT_DIR_FD; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "O&|i$O&:mkfifo", _keywords, - path_converter, &path, &mode, MKFIFOAT_DIR_FD_CONVERTER, &dir_fd)) - goto exit; - return_value = os_mkfifo_impl(module, &path, mode, dir_fd); - -exit: - /* Cleanup for path */ - path_cleanup(&path); - - return return_value; -} - static PyObject * os_mkfifo_impl(PyModuleDef *module, path_t *path, int mode, int dir_fd) -/*[clinic end generated code: output=b3321927546893d0 input=73032e98a36e0e19]*/ +/*[clinic end generated code: output=8f5f5e72c630049a input=73032e98a36e0e19]*/ { int result; int async_err = 0; @@ -12206,56 +8673,9 @@ If it is unavailable, using it will raise a NotImplementedError. [clinic start generated code]*/ -PyDoc_STRVAR(os_mknod__doc__, -"mknod($module, /, path, mode=384, device=0, *, dir_fd=None)\n" -"--\n" -"\n" -"Create a node in the file system.\n" -"\n" -"Create a node in the file system (file, device special file or named pipe)\n" -"at path. mode specifies both the permissions to use and the\n" -"type of node to be created, being combined (bitwise OR) with one of\n" -"S_IFREG, S_IFCHR, S_IFBLK, and S_IFIFO. If S_IFCHR or S_IFBLK is set on mode,\n" -"device defines the newly created device special file (probably using\n" -"os.makedev()). Otherwise device is ignored.\n" -"\n" -"If dir_fd is not None, it should be a file descriptor open to a directory,\n" -" and path should be relative; path will then be relative to that directory.\n" -"dir_fd may not be implemented on your platform.\n" -" If it is unavailable, using it will raise a NotImplementedError."); - -#define OS_MKNOD_METHODDEF \ - {"mknod", (PyCFunction)os_mknod, METH_VARARGS|METH_KEYWORDS, os_mknod__doc__}, - -static PyObject * -os_mknod_impl(PyModuleDef *module, path_t *path, int mode, dev_t device, int dir_fd); - -static PyObject * -os_mknod(PyModuleDef *module, PyObject *args, PyObject *kwargs) -{ - PyObject *return_value = NULL; - static char *_keywords[] = {"path", "mode", "device", "dir_fd", NULL}; - path_t path = PATH_T_INITIALIZE("mknod", "path", 0, 0); - int mode = 384; - dev_t device = 0; - int dir_fd = DEFAULT_DIR_FD; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "O&|iO&$O&:mknod", _keywords, - path_converter, &path, &mode, _Py_Dev_Converter, &device, MKNODAT_DIR_FD_CONVERTER, &dir_fd)) - goto exit; - return_value = os_mknod_impl(module, &path, mode, device, dir_fd); - -exit: - /* Cleanup for path */ - path_cleanup(&path); - - return return_value; -} - static PyObject * os_mknod_impl(PyModuleDef *module, path_t *path, int mode, dev_t device, int dir_fd) -/*[clinic end generated code: output=f71d54eaf9bb6f1a input=ee44531551a4d83b]*/ +/*[clinic end generated code: output=f7f813e8847de12f input=ee44531551a4d83b]*/ { int result; int async_err = 0; @@ -12289,41 +8709,9 @@ Extracts a device major number from a raw device number. [clinic start generated code]*/ -PyDoc_STRVAR(os_major__doc__, -"major($module, device, /)\n" -"--\n" -"\n" -"Extracts a device major number from a raw device number."); - -#define OS_MAJOR_METHODDEF \ - {"major", (PyCFunction)os_major, METH_VARARGS, os_major__doc__}, - -static unsigned int -os_major_impl(PyModuleDef *module, dev_t device); - -static PyObject * -os_major(PyModuleDef *module, PyObject *args) -{ - PyObject *return_value = NULL; - dev_t device; - unsigned int _return_value; - - if (!PyArg_ParseTuple(args, - "O&:major", - _Py_Dev_Converter, &device)) - goto exit; - _return_value = os_major_impl(module, device); - if ((_return_value == (unsigned int)-1) && PyErr_Occurred()) - goto exit; - return_value = PyLong_FromUnsignedLong((unsigned long)_return_value); - -exit: - return return_value; -} - static unsigned int os_major_impl(PyModuleDef *module, dev_t device) -/*[clinic end generated code: output=a2d06e908ebf95b5 input=1e16a4d30c4d4462]*/ +/*[clinic end generated code: output=ba55693ab49bac34 input=1e16a4d30c4d4462]*/ { return major(device); } @@ -12338,41 +8726,9 @@ Extracts a device minor number from a raw device number. [clinic start generated code]*/ -PyDoc_STRVAR(os_minor__doc__, -"minor($module, device, /)\n" -"--\n" -"\n" -"Extracts a device minor number from a raw device number."); - -#define OS_MINOR_METHODDEF \ - {"minor", (PyCFunction)os_minor, METH_VARARGS, os_minor__doc__}, - -static unsigned int -os_minor_impl(PyModuleDef *module, dev_t device); - -static PyObject * -os_minor(PyModuleDef *module, PyObject *args) -{ - PyObject *return_value = NULL; - dev_t device; - unsigned int _return_value; - - if (!PyArg_ParseTuple(args, - "O&:minor", - _Py_Dev_Converter, &device)) - goto exit; - _return_value = os_minor_impl(module, device); - if ((_return_value == (unsigned int)-1) && PyErr_Occurred()) - goto exit; - return_value = PyLong_FromUnsignedLong((unsigned long)_return_value); - -exit: - return return_value; -} - static unsigned int os_minor_impl(PyModuleDef *module, dev_t device) -/*[clinic end generated code: output=6332287ee3f006e2 input=0842c6d23f24c65e]*/ +/*[clinic end generated code: output=2867219ebf274e27 input=0842c6d23f24c65e]*/ { return minor(device); } @@ -12388,42 +8744,9 @@ Composes a raw device number from the major and minor device numbers. [clinic start generated code]*/ -PyDoc_STRVAR(os_makedev__doc__, -"makedev($module, major, minor, /)\n" -"--\n" -"\n" -"Composes a raw device number from the major and minor device numbers."); - -#define OS_MAKEDEV_METHODDEF \ - {"makedev", (PyCFunction)os_makedev, METH_VARARGS, os_makedev__doc__}, - -static dev_t -os_makedev_impl(PyModuleDef *module, int major, int minor); - -static PyObject * -os_makedev(PyModuleDef *module, PyObject *args) -{ - PyObject *return_value = NULL; - int major; - int minor; - dev_t _return_value; - - if (!PyArg_ParseTuple(args, - "ii:makedev", - &major, &minor)) - goto exit; - _return_value = os_makedev_impl(module, major, minor); - if ((_return_value == (dev_t)-1) && PyErr_Occurred()) - goto exit; - return_value = _PyLong_FromDev(_return_value); - -exit: - return return_value; -} - static dev_t os_makedev_impl(PyModuleDef *module, int major, int minor) -/*[clinic end generated code: output=38e9a9774c96511a input=4b9fd8fc73cbe48f]*/ +/*[clinic end generated code: output=7cb6264352437660 input=4b9fd8fc73cbe48f]*/ { return makedev(major, minor); } @@ -12441,38 +8764,9 @@ Truncate a file, specified by file descriptor, to a specific length. [clinic start generated code]*/ -PyDoc_STRVAR(os_ftruncate__doc__, -"ftruncate($module, fd, length, /)\n" -"--\n" -"\n" -"Truncate a file, specified by file descriptor, to a specific length."); - -#define OS_FTRUNCATE_METHODDEF \ - {"ftruncate", (PyCFunction)os_ftruncate, METH_VARARGS, os_ftruncate__doc__}, - -static PyObject * -os_ftruncate_impl(PyModuleDef *module, int fd, Py_off_t length); - -static PyObject * -os_ftruncate(PyModuleDef *module, PyObject *args) -{ - PyObject *return_value = NULL; - int fd; - Py_off_t length; - - if (!PyArg_ParseTuple(args, - "iO&:ftruncate", - &fd, Py_off_t_converter, &length)) - goto exit; - return_value = os_ftruncate_impl(module, fd, length); - -exit: - return return_value; -} - static PyObject * os_ftruncate_impl(PyModuleDef *module, int fd, Py_off_t length) -/*[clinic end generated code: output=62326766cb9b76bf input=63b43641e52818f2]*/ +/*[clinic end generated code: output=3666f401d76bf834 input=63b43641e52818f2]*/ { int result; int async_err = 0; @@ -12502,45 +8796,9 @@ If this functionality is unavailable, using it raises an exception. [clinic start generated code]*/ -PyDoc_STRVAR(os_truncate__doc__, -"truncate($module, /, path, length)\n" -"--\n" -"\n" -"Truncate a file, specified by path, to a specific length.\n" -"\n" -"On some platforms, path may also be specified as an open file descriptor.\n" -" If this functionality is unavailable, using it raises an exception."); - -#define OS_TRUNCATE_METHODDEF \ - {"truncate", (PyCFunction)os_truncate, METH_VARARGS|METH_KEYWORDS, os_truncate__doc__}, - -static PyObject * -os_truncate_impl(PyModuleDef *module, path_t *path, Py_off_t length); - -static PyObject * -os_truncate(PyModuleDef *module, PyObject *args, PyObject *kwargs) -{ - PyObject *return_value = NULL; - static char *_keywords[] = {"path", "length", NULL}; - path_t path = PATH_T_INITIALIZE("truncate", "path", 0, PATH_HAVE_FTRUNCATE); - Py_off_t length; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "O&O&:truncate", _keywords, - path_converter, &path, Py_off_t_converter, &length)) - goto exit; - return_value = os_truncate_impl(module, &path, length); - -exit: - /* Cleanup for path */ - path_cleanup(&path); - - return return_value; -} - static PyObject * os_truncate_impl(PyModuleDef *module, path_t *path, Py_off_t length) -/*[clinic end generated code: output=6bd76262d2e027c6 input=77229cf0b50a9b77]*/ +/*[clinic end generated code: output=f60a9e08370e9e2e input=77229cf0b50a9b77]*/ { int result; @@ -12584,42 +8842,9 @@ starting at offset bytes from the beginning and continuing for length bytes. [clinic start generated code]*/ -PyDoc_STRVAR(os_posix_fallocate__doc__, -"posix_fallocate($module, fd, offset, length, /)\n" -"--\n" -"\n" -"Ensure a file has allocated at least a particular number of bytes on disk.\n" -"\n" -"Ensure that the file specified by fd encompasses a range of bytes\n" -"starting at offset bytes from the beginning and continuing for length bytes."); - -#define OS_POSIX_FALLOCATE_METHODDEF \ - {"posix_fallocate", (PyCFunction)os_posix_fallocate, METH_VARARGS, os_posix_fallocate__doc__}, - -static PyObject * -os_posix_fallocate_impl(PyModuleDef *module, int fd, Py_off_t offset, Py_off_t length); - -static PyObject * -os_posix_fallocate(PyModuleDef *module, PyObject *args) -{ - PyObject *return_value = NULL; - int fd; - Py_off_t offset; - Py_off_t length; - - if (!PyArg_ParseTuple(args, - "iO&O&:posix_fallocate", - &fd, Py_off_t_converter, &offset, Py_off_t_converter, &length)) - goto exit; - return_value = os_posix_fallocate_impl(module, fd, offset, length); - -exit: - return return_value; -} - static PyObject * os_posix_fallocate_impl(PyModuleDef *module, int fd, Py_off_t offset, Py_off_t length) -/*[clinic end generated code: output=0cd702d2065c79db input=d7a2ef0ab2ca52fb]*/ +/*[clinic end generated code: output=8ae5f7837004d454 input=d7a2ef0ab2ca52fb]*/ { int result; int async_err = 0; @@ -12658,48 +8883,9 @@ POSIX_FADV_DONTNEED. [clinic start generated code]*/ -PyDoc_STRVAR(os_posix_fadvise__doc__, -"posix_fadvise($module, fd, offset, length, advice, /)\n" -"--\n" -"\n" -"Announce an intention to access data in a specific pattern.\n" -"\n" -"Announce an intention to access data in a specific pattern, thus allowing\n" -"the kernel to make optimizations.\n" -"The advice applies to the region of the file specified by fd starting at\n" -"offset and continuing for length bytes.\n" -"advice is one of POSIX_FADV_NORMAL, POSIX_FADV_SEQUENTIAL,\n" -"POSIX_FADV_RANDOM, POSIX_FADV_NOREUSE, POSIX_FADV_WILLNEED, or\n" -"POSIX_FADV_DONTNEED."); - -#define OS_POSIX_FADVISE_METHODDEF \ - {"posix_fadvise", (PyCFunction)os_posix_fadvise, METH_VARARGS, os_posix_fadvise__doc__}, - -static PyObject * -os_posix_fadvise_impl(PyModuleDef *module, int fd, Py_off_t offset, Py_off_t length, int advice); - -static PyObject * -os_posix_fadvise(PyModuleDef *module, PyObject *args) -{ - PyObject *return_value = NULL; - int fd; - Py_off_t offset; - Py_off_t length; - int advice; - - if (!PyArg_ParseTuple(args, - "iO&O&i:posix_fadvise", - &fd, Py_off_t_converter, &offset, Py_off_t_converter, &length, &advice)) - goto exit; - return_value = os_posix_fadvise_impl(module, fd, offset, length, advice); - -exit: - return return_value; -} - static PyObject * os_posix_fadvise_impl(PyModuleDef *module, int fd, Py_off_t offset, Py_off_t length, int advice) -/*[clinic end generated code: output=dad93f32c04dd4f7 input=0fbe554edc2f04b5]*/ +/*[clinic end generated code: output=0e3f09f651661257 input=0fbe554edc2f04b5]*/ { int result; int async_err = 0; @@ -12748,38 +8934,9 @@ Change or add an environment variable. [clinic start generated code]*/ -PyDoc_STRVAR(os_putenv__doc__, -"putenv($module, name, value, /)\n" -"--\n" -"\n" -"Change or add an environment variable."); - -#define OS_PUTENV_METHODDEF \ - {"putenv", (PyCFunction)os_putenv, METH_VARARGS, os_putenv__doc__}, - -static PyObject * -os_putenv_impl(PyModuleDef *module, PyObject *name, PyObject *value); - -static PyObject * -os_putenv(PyModuleDef *module, PyObject *args) -{ - PyObject *return_value = NULL; - PyObject *name; - PyObject *value; - - if (!PyArg_ParseTuple(args, - "UU:putenv", - &name, &value)) - goto exit; - return_value = os_putenv_impl(module, name, value); - -exit: - return return_value; -} - static PyObject * os_putenv_impl(PyModuleDef *module, PyObject *name, PyObject *value) -/*[clinic end generated code: output=5ce9ef9b15606e7e input=ba586581c2e6105f]*/ +/*[clinic end generated code: output=a2438cf95e5a0c1c input=ba586581c2e6105f]*/ { wchar_t *env; @@ -12821,43 +8978,9 @@ Change or add an environment variable. [clinic start generated code]*/ -PyDoc_STRVAR(os_putenv__doc__, -"putenv($module, name, value, /)\n" -"--\n" -"\n" -"Change or add an environment variable."); - -#define OS_PUTENV_METHODDEF \ - {"putenv", (PyCFunction)os_putenv, METH_VARARGS, os_putenv__doc__}, - -static PyObject * -os_putenv_impl(PyModuleDef *module, PyObject *name, PyObject *value); - -static PyObject * -os_putenv(PyModuleDef *module, PyObject *args) -{ - PyObject *return_value = NULL; - PyObject *name = NULL; - PyObject *value = NULL; - - if (!PyArg_ParseTuple(args, - "O&O&:putenv", - PyUnicode_FSConverter, &name, PyUnicode_FSConverter, &value)) - goto exit; - return_value = os_putenv_impl(module, name, value); - -exit: - /* Cleanup for name */ - Py_XDECREF(name); - /* Cleanup for value */ - Py_XDECREF(value); - - return return_value; -} - static PyObject * os_putenv_impl(PyModuleDef *module, PyObject *name, PyObject *value) -/*[clinic end generated code: output=85ab223393dc7afd input=a97bc6152f688d31]*/ +/*[clinic end generated code: output=a2438cf95e5a0c1c input=a97bc6152f688d31]*/ { PyObject *bytes = NULL; char *env; @@ -12892,40 +9015,9 @@ Delete an environment variable. [clinic start generated code]*/ -PyDoc_STRVAR(os_unsetenv__doc__, -"unsetenv($module, name, /)\n" -"--\n" -"\n" -"Delete an environment variable."); - -#define OS_UNSETENV_METHODDEF \ - {"unsetenv", (PyCFunction)os_unsetenv, METH_VARARGS, os_unsetenv__doc__}, - -static PyObject * -os_unsetenv_impl(PyModuleDef *module, PyObject *name); - -static PyObject * -os_unsetenv(PyModuleDef *module, PyObject *args) -{ - PyObject *return_value = NULL; - PyObject *name = NULL; - - if (!PyArg_ParseTuple(args, - "O&:unsetenv", - PyUnicode_FSConverter, &name)) - goto exit; - return_value = os_unsetenv_impl(module, name); - -exit: - /* Cleanup for name */ - Py_XDECREF(name); - - return return_value; -} - static PyObject * os_unsetenv_impl(PyModuleDef *module, PyObject *name) -/*[clinic end generated code: output=91318c995f9a0767 input=2bb5288a599c7107]*/ +/*[clinic end generated code: output=25994b57016a2dc9 input=2bb5288a599c7107]*/ { #ifndef HAVE_BROKEN_UNSETENV int err; @@ -12962,37 +9054,9 @@ Translate an error code to a message string. [clinic start generated code]*/ -PyDoc_STRVAR(os_strerror__doc__, -"strerror($module, code, /)\n" -"--\n" -"\n" -"Translate an error code to a message string."); - -#define OS_STRERROR_METHODDEF \ - {"strerror", (PyCFunction)os_strerror, METH_VARARGS, os_strerror__doc__}, - -static PyObject * -os_strerror_impl(PyModuleDef *module, int code); - -static PyObject * -os_strerror(PyModuleDef *module, PyObject *args) -{ - PyObject *return_value = NULL; - int code; - - if (!PyArg_ParseTuple(args, - "i:strerror", - &code)) - goto exit; - return_value = os_strerror_impl(module, code); - -exit: - return return_value; -} - static PyObject * os_strerror_impl(PyModuleDef *module, int code) -/*[clinic end generated code: output=8665c70bb2ca4720 input=75a8673d97915a91]*/ +/*[clinic end generated code: output=0280c6af51e5c9fe input=75a8673d97915a91]*/ { char *message = strerror(code); if (message == NULL) { @@ -13015,41 +9079,9 @@ Return True if the process returning status was dumped to a core file. [clinic start generated code]*/ -PyDoc_STRVAR(os_WCOREDUMP__doc__, -"WCOREDUMP($module, status, /)\n" -"--\n" -"\n" -"Return True if the process returning status was dumped to a core file."); - -#define OS_WCOREDUMP_METHODDEF \ - {"WCOREDUMP", (PyCFunction)os_WCOREDUMP, METH_VARARGS, os_WCOREDUMP__doc__}, - -static int -os_WCOREDUMP_impl(PyModuleDef *module, int status); - -static PyObject * -os_WCOREDUMP(PyModuleDef *module, PyObject *args) -{ - PyObject *return_value = NULL; - int status; - int _return_value; - - if (!PyArg_ParseTuple(args, - "i:WCOREDUMP", - &status)) - goto exit; - _return_value = os_WCOREDUMP_impl(module, status); - if ((_return_value == -1) && PyErr_Occurred()) - goto exit; - return_value = PyBool_FromLong((long)_return_value); - -exit: - return return_value; -} - static int os_WCOREDUMP_impl(PyModuleDef *module, int status) -/*[clinic end generated code: output=e04d55c09c299828 input=8b05e7ab38528d04]*/ +/*[clinic end generated code: output=134f70bbe63fbf41 input=8b05e7ab38528d04]*/ { WAIT_TYPE wait_status; WAIT_STATUS_INT(wait_status) = status; @@ -13070,45 +9102,9 @@ job control stop. [clinic start generated code]*/ -PyDoc_STRVAR(os_WIFCONTINUED__doc__, -"WIFCONTINUED($module, /, status)\n" -"--\n" -"\n" -"Return True if a particular process was continued from a job control stop.\n" -"\n" -"Return True if the process returning status was continued from a\n" -"job control stop."); - -#define OS_WIFCONTINUED_METHODDEF \ - {"WIFCONTINUED", (PyCFunction)os_WIFCONTINUED, METH_VARARGS|METH_KEYWORDS, os_WIFCONTINUED__doc__}, - -static int -os_WIFCONTINUED_impl(PyModuleDef *module, int status); - -static PyObject * -os_WIFCONTINUED(PyModuleDef *module, PyObject *args, PyObject *kwargs) -{ - PyObject *return_value = NULL; - static char *_keywords[] = {"status", NULL}; - int status; - int _return_value; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "i:WIFCONTINUED", _keywords, - &status)) - goto exit; - _return_value = os_WIFCONTINUED_impl(module, status); - if ((_return_value == -1) && PyErr_Occurred()) - goto exit; - return_value = PyBool_FromLong((long)_return_value); - -exit: - return return_value; -} - static int os_WIFCONTINUED_impl(PyModuleDef *module, int status) -/*[clinic end generated code: output=9c4e6105a4520ab5 input=e777e7d38eb25bd9]*/ +/*[clinic end generated code: output=9cdd26543ebb6dcd input=e777e7d38eb25bd9]*/ { WAIT_TYPE wait_status; WAIT_STATUS_INT(wait_status) = status; @@ -13126,42 +9122,9 @@ Return True if the process returning status was stopped. [clinic start generated code]*/ -PyDoc_STRVAR(os_WIFSTOPPED__doc__, -"WIFSTOPPED($module, /, status)\n" -"--\n" -"\n" -"Return True if the process returning status was stopped."); - -#define OS_WIFSTOPPED_METHODDEF \ - {"WIFSTOPPED", (PyCFunction)os_WIFSTOPPED, METH_VARARGS|METH_KEYWORDS, os_WIFSTOPPED__doc__}, - -static int -os_WIFSTOPPED_impl(PyModuleDef *module, int status); - -static PyObject * -os_WIFSTOPPED(PyModuleDef *module, PyObject *args, PyObject *kwargs) -{ - PyObject *return_value = NULL; - static char *_keywords[] = {"status", NULL}; - int status; - int _return_value; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "i:WIFSTOPPED", _keywords, - &status)) - goto exit; - _return_value = os_WIFSTOPPED_impl(module, status); - if ((_return_value == -1) && PyErr_Occurred()) - goto exit; - return_value = PyBool_FromLong((long)_return_value); - -exit: - return return_value; -} - static int os_WIFSTOPPED_impl(PyModuleDef *module, int status) -/*[clinic end generated code: output=e0de2da8ec9593ff input=043cb7f1289ef904]*/ +/*[clinic end generated code: output=73bf35e44994a724 input=043cb7f1289ef904]*/ { WAIT_TYPE wait_status; WAIT_STATUS_INT(wait_status) = status; @@ -13179,42 +9142,9 @@ Return True if the process returning status was terminated by a signal. [clinic start generated code]*/ -PyDoc_STRVAR(os_WIFSIGNALED__doc__, -"WIFSIGNALED($module, /, status)\n" -"--\n" -"\n" -"Return True if the process returning status was terminated by a signal."); - -#define OS_WIFSIGNALED_METHODDEF \ - {"WIFSIGNALED", (PyCFunction)os_WIFSIGNALED, METH_VARARGS|METH_KEYWORDS, os_WIFSIGNALED__doc__}, - -static int -os_WIFSIGNALED_impl(PyModuleDef *module, int status); - -static PyObject * -os_WIFSIGNALED(PyModuleDef *module, PyObject *args, PyObject *kwargs) -{ - PyObject *return_value = NULL; - static char *_keywords[] = {"status", NULL}; - int status; - int _return_value; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "i:WIFSIGNALED", _keywords, - &status)) - goto exit; - _return_value = os_WIFSIGNALED_impl(module, status); - if ((_return_value == -1) && PyErr_Occurred()) - goto exit; - return_value = PyBool_FromLong((long)_return_value); - -exit: - return return_value; -} - static int os_WIFSIGNALED_impl(PyModuleDef *module, int status) -/*[clinic end generated code: output=f14d106558f406be input=d55ba7cc9ce5dc43]*/ +/*[clinic end generated code: output=2697975771872420 input=d55ba7cc9ce5dc43]*/ { WAIT_TYPE wait_status; WAIT_STATUS_INT(wait_status) = status; @@ -13232,42 +9162,9 @@ Return True if the process returning status exited via the exit() system call. [clinic start generated code]*/ -PyDoc_STRVAR(os_WIFEXITED__doc__, -"WIFEXITED($module, /, status)\n" -"--\n" -"\n" -"Return True if the process returning status exited via the exit() system call."); - -#define OS_WIFEXITED_METHODDEF \ - {"WIFEXITED", (PyCFunction)os_WIFEXITED, METH_VARARGS|METH_KEYWORDS, os_WIFEXITED__doc__}, - -static int -os_WIFEXITED_impl(PyModuleDef *module, int status); - -static PyObject * -os_WIFEXITED(PyModuleDef *module, PyObject *args, PyObject *kwargs) -{ - PyObject *return_value = NULL; - static char *_keywords[] = {"status", NULL}; - int status; - int _return_value; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "i:WIFEXITED", _keywords, - &status)) - goto exit; - _return_value = os_WIFEXITED_impl(module, status); - if ((_return_value == -1) && PyErr_Occurred()) - goto exit; - return_value = PyBool_FromLong((long)_return_value); - -exit: - return return_value; -} - static int os_WIFEXITED_impl(PyModuleDef *module, int status) -/*[clinic end generated code: output=2f76087d53721255 input=d63775a6791586c0]*/ +/*[clinic end generated code: output=ca8f8c61f0b8532e input=d63775a6791586c0]*/ { WAIT_TYPE wait_status; WAIT_STATUS_INT(wait_status) = status; @@ -13285,42 +9182,9 @@ Return the process return code from status. [clinic start generated code]*/ -PyDoc_STRVAR(os_WEXITSTATUS__doc__, -"WEXITSTATUS($module, /, status)\n" -"--\n" -"\n" -"Return the process return code from status."); - -#define OS_WEXITSTATUS_METHODDEF \ - {"WEXITSTATUS", (PyCFunction)os_WEXITSTATUS, METH_VARARGS|METH_KEYWORDS, os_WEXITSTATUS__doc__}, - -static int -os_WEXITSTATUS_impl(PyModuleDef *module, int status); - -static PyObject * -os_WEXITSTATUS(PyModuleDef *module, PyObject *args, PyObject *kwargs) -{ - PyObject *return_value = NULL; - static char *_keywords[] = {"status", NULL}; - int status; - int _return_value; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "i:WEXITSTATUS", _keywords, - &status)) - goto exit; - _return_value = os_WEXITSTATUS_impl(module, status); - if ((_return_value == -1) && PyErr_Occurred()) - goto exit; - return_value = PyLong_FromLong((long)_return_value); - -exit: - return return_value; -} - static int os_WEXITSTATUS_impl(PyModuleDef *module, int status) -/*[clinic end generated code: output=13b6c270e2a326b1 input=e1fb4944e377585b]*/ +/*[clinic end generated code: output=ea54da23d9e0f6af input=e1fb4944e377585b]*/ { WAIT_TYPE wait_status; WAIT_STATUS_INT(wait_status) = status; @@ -13338,42 +9202,9 @@ Return the signal that terminated the process that provided the status value. [clinic start generated code]*/ -PyDoc_STRVAR(os_WTERMSIG__doc__, -"WTERMSIG($module, /, status)\n" -"--\n" -"\n" -"Return the signal that terminated the process that provided the status value."); - -#define OS_WTERMSIG_METHODDEF \ - {"WTERMSIG", (PyCFunction)os_WTERMSIG, METH_VARARGS|METH_KEYWORDS, os_WTERMSIG__doc__}, - -static int -os_WTERMSIG_impl(PyModuleDef *module, int status); - -static PyObject * -os_WTERMSIG(PyModuleDef *module, PyObject *args, PyObject *kwargs) -{ - PyObject *return_value = NULL; - static char *_keywords[] = {"status", NULL}; - int status; - int _return_value; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "i:WTERMSIG", _keywords, - &status)) - goto exit; - _return_value = os_WTERMSIG_impl(module, status); - if ((_return_value == -1) && PyErr_Occurred()) - goto exit; - return_value = PyLong_FromLong((long)_return_value); - -exit: - return return_value; -} - static int os_WTERMSIG_impl(PyModuleDef *module, int status) -/*[clinic end generated code: output=bf1fd4b002d0a9ed input=727fd7f84ec3f243]*/ +/*[clinic end generated code: output=4d25367026cb852c input=727fd7f84ec3f243]*/ { WAIT_TYPE wait_status; WAIT_STATUS_INT(wait_status) = status; @@ -13391,42 +9222,9 @@ Return the signal that stopped the process that provided the status value. [clinic start generated code]*/ -PyDoc_STRVAR(os_WSTOPSIG__doc__, -"WSTOPSIG($module, /, status)\n" -"--\n" -"\n" -"Return the signal that stopped the process that provided the status value."); - -#define OS_WSTOPSIG_METHODDEF \ - {"WSTOPSIG", (PyCFunction)os_WSTOPSIG, METH_VARARGS|METH_KEYWORDS, os_WSTOPSIG__doc__}, - -static int -os_WSTOPSIG_impl(PyModuleDef *module, int status); - -static PyObject * -os_WSTOPSIG(PyModuleDef *module, PyObject *args, PyObject *kwargs) -{ - PyObject *return_value = NULL; - static char *_keywords[] = {"status", NULL}; - int status; - int _return_value; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "i:WSTOPSIG", _keywords, - &status)) - goto exit; - _return_value = os_WSTOPSIG_impl(module, status); - if ((_return_value == -1) && PyErr_Occurred()) - goto exit; - return_value = PyLong_FromLong((long)_return_value); - -exit: - return return_value; -} - static int os_WSTOPSIG_impl(PyModuleDef *module, int status) -/*[clinic end generated code: output=92e1647d29ee0549 input=46ebf1d1b293c5c1]*/ +/*[clinic end generated code: output=54eb9c13b001adb4 input=46ebf1d1b293c5c1]*/ { WAIT_TYPE wait_status; WAIT_STATUS_INT(wait_status) = status; @@ -13436,39 +9234,6 @@ #endif /* HAVE_SYS_WAIT_H */ -#ifndef OS_WCOREDUMP_METHODDEF -#define OS_WCOREDUMP_METHODDEF -#endif /* OS_WCOREDUMP_METHODDEF */ - -#ifndef OS_WIFCONTINUED_METHODDEF -#define OS_WIFCONTINUED_METHODDEF -#endif /* OS_WIFCONTINUED_METHODDEF */ - -#ifndef OS_WIFSTOPPED_METHODDEF -#define OS_WIFSTOPPED_METHODDEF -#endif /* OS_WIFSTOPPED_METHODDEF */ - -#ifndef OS_WIFSIGNALED_METHODDEF -#define OS_WIFSIGNALED_METHODDEF -#endif /* OS_WIFSIGNALED_METHODDEF */ - -#ifndef OS_WIFEXITED_METHODDEF -#define OS_WIFEXITED_METHODDEF -#endif /* OS_WIFEXITED_METHODDEF */ - -#ifndef OS_WEXITSTATUS_METHODDEF -#define OS_WEXITSTATUS_METHODDEF -#endif /* OS_WEXITSTATUS_METHODDEF */ - -#ifndef OS_WTERMSIG_METHODDEF -#define OS_WTERMSIG_METHODDEF -#endif /* OS_WTERMSIG_METHODDEF */ - -#ifndef OS_WSTOPSIG_METHODDEF -#define OS_WSTOPSIG_METHODDEF -#endif /* OS_WSTOPSIG_METHODDEF */ - - #if defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H) #ifdef _SCO_DS /* SCO OpenServer 5.0 and later requires _SVID3 before it reveals the @@ -13531,39 +9296,9 @@ Equivalent to statvfs(fd). [clinic start generated code]*/ -PyDoc_STRVAR(os_fstatvfs__doc__, -"fstatvfs($module, fd, /)\n" -"--\n" -"\n" -"Perform an fstatvfs system call on the given fd.\n" -"\n" -"Equivalent to statvfs(fd)."); - -#define OS_FSTATVFS_METHODDEF \ - {"fstatvfs", (PyCFunction)os_fstatvfs, METH_VARARGS, os_fstatvfs__doc__}, - -static PyObject * -os_fstatvfs_impl(PyModuleDef *module, int fd); - -static PyObject * -os_fstatvfs(PyModuleDef *module, PyObject *args) -{ - PyObject *return_value = NULL; - int fd; - - if (!PyArg_ParseTuple(args, - "i:fstatvfs", - &fd)) - goto exit; - return_value = os_fstatvfs_impl(module, fd); - -exit: - return return_value; -} - static PyObject * os_fstatvfs_impl(PyModuleDef *module, int fd) -/*[clinic end generated code: output=0e32bf07f946ec0d input=d8122243ac50975e]*/ +/*[clinic end generated code: output=584a94a754497ac0 input=d8122243ac50975e]*/ { int result; int async_err = 0; @@ -13597,45 +9332,9 @@ If this functionality is unavailable, using it raises an exception. [clinic start generated code]*/ -PyDoc_STRVAR(os_statvfs__doc__, -"statvfs($module, /, path)\n" -"--\n" -"\n" -"Perform a statvfs system call on the given path.\n" -"\n" -"path may always be specified as a string.\n" -"On some platforms, path may also be specified as an open file descriptor.\n" -" If this functionality is unavailable, using it raises an exception."); - -#define OS_STATVFS_METHODDEF \ - {"statvfs", (PyCFunction)os_statvfs, METH_VARARGS|METH_KEYWORDS, os_statvfs__doc__}, - -static PyObject * -os_statvfs_impl(PyModuleDef *module, path_t *path); - -static PyObject * -os_statvfs(PyModuleDef *module, PyObject *args, PyObject *kwargs) -{ - PyObject *return_value = NULL; - static char *_keywords[] = {"path", NULL}; - path_t path = PATH_T_INITIALIZE("statvfs", "path", 0, PATH_HAVE_FSTATVFS); - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "O&:statvfs", _keywords, - path_converter, &path)) - goto exit; - return_value = os_statvfs_impl(module, &path); - -exit: - /* Cleanup for path */ - path_cleanup(&path); - - return return_value; -} - static PyObject * os_statvfs_impl(PyModuleDef *module, path_t *path) -/*[clinic end generated code: output=00ff54983360b446 input=3f5c35791c669bd9]*/ +/*[clinic end generated code: output=5ced07a2cf931f41 input=3f5c35791c669bd9]*/ { int result; struct statvfs st; @@ -13675,38 +9374,9 @@ Return disk usage statistics about the given path as a (total, free) tuple. [clinic start generated code]*/ -PyDoc_STRVAR(os__getdiskusage__doc__, -"_getdiskusage($module, /, path)\n" -"--\n" -"\n" -"Return disk usage statistics about the given path as a (total, free) tuple."); - -#define OS__GETDISKUSAGE_METHODDEF \ - {"_getdiskusage", (PyCFunction)os__getdiskusage, METH_VARARGS|METH_KEYWORDS, os__getdiskusage__doc__}, - -static PyObject * -os__getdiskusage_impl(PyModuleDef *module, Py_UNICODE *path); - -static PyObject * -os__getdiskusage(PyModuleDef *module, PyObject *args, PyObject *kwargs) -{ - PyObject *return_value = NULL; - static char *_keywords[] = {"path", NULL}; - Py_UNICODE *path; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "u:_getdiskusage", _keywords, - &path)) - goto exit; - return_value = os__getdiskusage_impl(module, path); - -exit: - return return_value; -} - static PyObject * os__getdiskusage_impl(PyModuleDef *module, Py_UNICODE *path) -/*[clinic end generated code: output=054c972179b13708 input=6458133aed893c78]*/ +/*[clinic end generated code: output=60a9cf33449db1dd input=6458133aed893c78]*/ { BOOL retval; ULARGE_INTEGER _, total, free; @@ -13890,44 +9560,9 @@ If there is no limit, return -1. [clinic start generated code]*/ -PyDoc_STRVAR(os_fpathconf__doc__, -"fpathconf($module, fd, name, /)\n" -"--\n" -"\n" -"Return the configuration limit name for the file descriptor fd.\n" -"\n" -"If there is no limit, return -1."); - -#define OS_FPATHCONF_METHODDEF \ - {"fpathconf", (PyCFunction)os_fpathconf, METH_VARARGS, os_fpathconf__doc__}, - -static long -os_fpathconf_impl(PyModuleDef *module, int fd, int name); - -static PyObject * -os_fpathconf(PyModuleDef *module, PyObject *args) -{ - PyObject *return_value = NULL; - int fd; - int name; - long _return_value; - - if (!PyArg_ParseTuple(args, - "iO&:fpathconf", - &fd, conv_path_confname, &name)) - goto exit; - _return_value = os_fpathconf_impl(module, fd, name); - if ((_return_value == -1) && PyErr_Occurred()) - goto exit; - return_value = PyLong_FromLong(_return_value); - -exit: - return return_value; -} - static long os_fpathconf_impl(PyModuleDef *module, int fd, int name) -/*[clinic end generated code: output=3bf04b40e0523a8c input=5942a024d3777810]*/ +/*[clinic end generated code: output=082b2922d4441de7 input=5942a024d3777810]*/ { long limit; @@ -13954,50 +9589,9 @@ If this functionality is unavailable, using it raises an exception. [clinic start generated code]*/ -PyDoc_STRVAR(os_pathconf__doc__, -"pathconf($module, /, path, name)\n" -"--\n" -"\n" -"Return the configuration limit name for the file or directory path.\n" -"\n" -"If there is no limit, return -1.\n" -"On some platforms, path may also be specified as an open file descriptor.\n" -" If this functionality is unavailable, using it raises an exception."); - -#define OS_PATHCONF_METHODDEF \ - {"pathconf", (PyCFunction)os_pathconf, METH_VARARGS|METH_KEYWORDS, os_pathconf__doc__}, - -static long -os_pathconf_impl(PyModuleDef *module, path_t *path, int name); - -static PyObject * -os_pathconf(PyModuleDef *module, PyObject *args, PyObject *kwargs) -{ - PyObject *return_value = NULL; - static char *_keywords[] = {"path", "name", NULL}; - path_t path = PATH_T_INITIALIZE("pathconf", "path", 0, PATH_HAVE_FPATHCONF); - int name; - long _return_value; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "O&O&:pathconf", _keywords, - path_converter, &path, conv_path_confname, &name)) - goto exit; - _return_value = os_pathconf_impl(module, &path, name); - if ((_return_value == -1) && PyErr_Occurred()) - goto exit; - return_value = PyLong_FromLong(_return_value); - -exit: - /* Cleanup for path */ - path_cleanup(&path); - - return return_value; -} - static long os_pathconf_impl(PyModuleDef *module, path_t *path, int name) -/*[clinic end generated code: output=1a53e125b6cf63e4 input=bc3e2a985af27e5e]*/ +/*[clinic end generated code: output=3713029e9501f5ab input=bc3e2a985af27e5e]*/ { long limit; @@ -14192,37 +9786,9 @@ Return a string-valued system configuration variable. [clinic start generated code]*/ -PyDoc_STRVAR(os_confstr__doc__, -"confstr($module, name, /)\n" -"--\n" -"\n" -"Return a string-valued system configuration variable."); - -#define OS_CONFSTR_METHODDEF \ - {"confstr", (PyCFunction)os_confstr, METH_VARARGS, os_confstr__doc__}, - -static PyObject * -os_confstr_impl(PyModuleDef *module, int name); - -static PyObject * -os_confstr(PyModuleDef *module, PyObject *args) -{ - PyObject *return_value = NULL; - int name; - - if (!PyArg_ParseTuple(args, - "O&:confstr", - conv_confstr_confname, &name)) - goto exit; - return_value = os_confstr_impl(module, name); - -exit: - return return_value; -} - static PyObject * os_confstr_impl(PyModuleDef *module, int name) -/*[clinic end generated code: output=3f5e8aba9f8e3174 input=18fb4d0567242e65]*/ +/*[clinic end generated code: output=6ff79c9eed8c2daf input=18fb4d0567242e65]*/ { PyObject *result = NULL; char buffer[255]; @@ -14761,6 +10327,8 @@ / sizeof(struct constdef)); } +#include "clinic/posixmodule.c.h" + /*[clinic input] os.sysconf -> long @@ -14770,41 +10338,9 @@ Return an integer-valued system configuration variable. [clinic start generated code]*/ -PyDoc_STRVAR(os_sysconf__doc__, -"sysconf($module, name, /)\n" -"--\n" -"\n" -"Return an integer-valued system configuration variable."); - -#define OS_SYSCONF_METHODDEF \ - {"sysconf", (PyCFunction)os_sysconf, METH_VARARGS, os_sysconf__doc__}, - -static long -os_sysconf_impl(PyModuleDef *module, int name); - -static PyObject * -os_sysconf(PyModuleDef *module, PyObject *args) -{ - PyObject *return_value = NULL; - int name; - long _return_value; - - if (!PyArg_ParseTuple(args, - "O&:sysconf", - conv_sysconf_confname, &name)) - goto exit; - _return_value = os_sysconf_impl(module, name); - if ((_return_value == -1) && PyErr_Occurred()) - goto exit; - return_value = PyLong_FromLong(_return_value); - -exit: - return return_value; -} - static long os_sysconf_impl(PyModuleDef *module, int name) -/*[clinic end generated code: output=7b06dfdc472431e4 input=279e3430a33f29e4]*/ +/*[clinic end generated code: output=ed567306f58d69c4 input=279e3430a33f29e4]*/ { long value; @@ -14900,30 +10436,9 @@ on the hosting operating system. This function never returns. [clinic start generated code]*/ -PyDoc_STRVAR(os_abort__doc__, -"abort($module, /)\n" -"--\n" -"\n" -"Abort the interpreter immediately.\n" -"\n" -"This function \'dumps core\' or otherwise fails in the hardest way possible\n" -"on the hosting operating system. This function never returns."); - -#define OS_ABORT_METHODDEF \ - {"abort", (PyCFunction)os_abort, METH_NOARGS, os_abort__doc__}, - -static PyObject * -os_abort_impl(PyModuleDef *module); - -static PyObject * -os_abort(PyModuleDef *module, PyObject *Py_UNUSED(ignored)) -{ - return os_abort_impl(module); -} - static PyObject * os_abort_impl(PyModuleDef *module) -/*[clinic end generated code: output=cded2cc8c5453d3a input=cf2c7d98bc504047]*/ +/*[clinic end generated code: output=486bb96647c299b3 input=cf2c7d98bc504047]*/ { abort(); /*NOTREACHED*/ @@ -15079,31 +10594,9 @@ Raises OSError if the load average was unobtainable. [clinic start generated code]*/ -PyDoc_STRVAR(os_getloadavg__doc__, -"getloadavg($module, /)\n" -"--\n" -"\n" -"Return average recent system load information.\n" -"\n" -"Return the number of processes in the system run queue averaged over\n" -"the last 1, 5, and 15 minutes as a tuple of three floats.\n" -"Raises OSError if the load average was unobtainable."); - -#define OS_GETLOADAVG_METHODDEF \ - {"getloadavg", (PyCFunction)os_getloadavg, METH_NOARGS, os_getloadavg__doc__}, - -static PyObject * -os_getloadavg_impl(PyModuleDef *module); - -static PyObject * -os_getloadavg(PyModuleDef *module, PyObject *Py_UNUSED(ignored)) -{ - return os_getloadavg_impl(module); -} - static PyObject * os_getloadavg_impl(PyModuleDef *module) -/*[clinic end generated code: output=67593a92457d55af input=3d6d826b76d8a34e]*/ +/*[clinic end generated code: output=2b64c5b675d74c14 input=3d6d826b76d8a34e]*/ { double loadavg[3]; if (getloadavg(loadavg, 3)!=3) { @@ -15125,41 +10618,9 @@ If the device is not a terminal, return None. [clinic start generated code]*/ -PyDoc_STRVAR(os_device_encoding__doc__, -"device_encoding($module, /, fd)\n" -"--\n" -"\n" -"Return a string describing the encoding of a terminal\'s file descriptor.\n" -"\n" -"The file descriptor must be attached to a terminal.\n" -"If the device is not a terminal, return None."); - -#define OS_DEVICE_ENCODING_METHODDEF \ - {"device_encoding", (PyCFunction)os_device_encoding, METH_VARARGS|METH_KEYWORDS, os_device_encoding__doc__}, - -static PyObject * -os_device_encoding_impl(PyModuleDef *module, int fd); - -static PyObject * -os_device_encoding(PyModuleDef *module, PyObject *args, PyObject *kwargs) -{ - PyObject *return_value = NULL; - static char *_keywords[] = {"fd", NULL}; - int fd; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "i:device_encoding", _keywords, - &fd)) - goto exit; - return_value = os_device_encoding_impl(module, fd); - -exit: - return return_value; -} - static PyObject * os_device_encoding_impl(PyModuleDef *module, int fd) -/*[clinic end generated code: output=e9f8274d42f5cce3 input=9e1d4a42b66df312]*/ +/*[clinic end generated code: output=34f14e33468419c1 input=9e1d4a42b66df312]*/ { return _Py_device_encoding(fd); } @@ -15177,39 +10638,9 @@ Set the current process's real, effective, and saved user ids. [clinic start generated code]*/ -PyDoc_STRVAR(os_setresuid__doc__, -"setresuid($module, ruid, euid, suid, /)\n" -"--\n" -"\n" -"Set the current process\'s real, effective, and saved user ids."); - -#define OS_SETRESUID_METHODDEF \ - {"setresuid", (PyCFunction)os_setresuid, METH_VARARGS, os_setresuid__doc__}, - -static PyObject * -os_setresuid_impl(PyModuleDef *module, uid_t ruid, uid_t euid, uid_t suid); - -static PyObject * -os_setresuid(PyModuleDef *module, PyObject *args) -{ - PyObject *return_value = NULL; - uid_t ruid; - uid_t euid; - uid_t suid; - - if (!PyArg_ParseTuple(args, - "O&O&O&:setresuid", - _Py_Uid_Converter, &ruid, _Py_Uid_Converter, &euid, _Py_Uid_Converter, &suid)) - goto exit; - return_value = os_setresuid_impl(module, ruid, euid, suid); - -exit: - return return_value; -} - static PyObject * os_setresuid_impl(PyModuleDef *module, uid_t ruid, uid_t euid, uid_t suid) -/*[clinic end generated code: output=2e3457cfe7cd1f94 input=9e33cb79a82792f3]*/ +/*[clinic end generated code: output=92cc330812c6ed0f input=9e33cb79a82792f3]*/ { if (setresuid(ruid, euid, suid) < 0) return posix_error(); @@ -15230,39 +10661,9 @@ Set the current process's real, effective, and saved group ids. [clinic start generated code]*/ -PyDoc_STRVAR(os_setresgid__doc__, -"setresgid($module, rgid, egid, sgid, /)\n" -"--\n" -"\n" -"Set the current process\'s real, effective, and saved group ids."); - -#define OS_SETRESGID_METHODDEF \ - {"setresgid", (PyCFunction)os_setresgid, METH_VARARGS, os_setresgid__doc__}, - -static PyObject * -os_setresgid_impl(PyModuleDef *module, gid_t rgid, gid_t egid, gid_t sgid); - -static PyObject * -os_setresgid(PyModuleDef *module, PyObject *args) -{ - PyObject *return_value = NULL; - gid_t rgid; - gid_t egid; - gid_t sgid; - - if (!PyArg_ParseTuple(args, - "O&O&O&:setresgid", - _Py_Gid_Converter, &rgid, _Py_Gid_Converter, &egid, _Py_Gid_Converter, &sgid)) - goto exit; - return_value = os_setresgid_impl(module, rgid, egid, sgid); - -exit: - return return_value; -} - static PyObject * os_setresgid_impl(PyModuleDef *module, gid_t rgid, gid_t egid, gid_t sgid) -/*[clinic end generated code: output=8a7ee6c1f2482362 input=33e9e0785ef426b1]*/ +/*[clinic end generated code: output=e91dc4842a604429 input=33e9e0785ef426b1]*/ { if (setresgid(rgid, egid, sgid) < 0) return posix_error(); @@ -15278,27 +10679,9 @@ Return a tuple of the current process's real, effective, and saved user ids. [clinic start generated code]*/ -PyDoc_STRVAR(os_getresuid__doc__, -"getresuid($module, /)\n" -"--\n" -"\n" -"Return a tuple of the current process\'s real, effective, and saved user ids."); - -#define OS_GETRESUID_METHODDEF \ - {"getresuid", (PyCFunction)os_getresuid, METH_NOARGS, os_getresuid__doc__}, - -static PyObject * -os_getresuid_impl(PyModuleDef *module); - -static PyObject * -os_getresuid(PyModuleDef *module, PyObject *Py_UNUSED(ignored)) -{ - return os_getresuid_impl(module); -} - static PyObject * os_getresuid_impl(PyModuleDef *module) -/*[clinic end generated code: output=d0786686a6ef1320 input=41ccfa8e1f6517ad]*/ +/*[clinic end generated code: output=9ddef62faae8e477 input=41ccfa8e1f6517ad]*/ { uid_t ruid, euid, suid; if (getresuid(&ruid, &euid, &suid) < 0) @@ -15317,27 +10700,9 @@ Return a tuple of the current process's real, effective, and saved group ids. [clinic start generated code]*/ -PyDoc_STRVAR(os_getresgid__doc__, -"getresgid($module, /)\n" -"--\n" -"\n" -"Return a tuple of the current process\'s real, effective, and saved group ids."); - -#define OS_GETRESGID_METHODDEF \ - {"getresgid", (PyCFunction)os_getresgid, METH_NOARGS, os_getresgid__doc__}, - -static PyObject * -os_getresgid_impl(PyModuleDef *module); - -static PyObject * -os_getresgid(PyModuleDef *module, PyObject *Py_UNUSED(ignored)) -{ - return os_getresgid_impl(module); -} - static PyObject * os_getresgid_impl(PyModuleDef *module) -/*[clinic end generated code: output=05249ac795fa759f input=517e68db9ca32df6]*/ +/*[clinic end generated code: output=e1a553cbcf16234c input=517e68db9ca32df6]*/ { gid_t rgid, egid, sgid; if (getresgid(&rgid, &egid, &sgid) < 0) @@ -15367,50 +10732,9 @@ [clinic start generated code]*/ -PyDoc_STRVAR(os_getxattr__doc__, -"getxattr($module, /, path, attribute, *, follow_symlinks=True)\n" -"--\n" -"\n" -"Return the value of extended attribute attribute on path.\n" -"\n" -"path may be either a string or an open file descriptor.\n" -"If follow_symlinks is False, and the last element of the path is a symbolic\n" -" link, getxattr will examine the symbolic link itself instead of the file\n" -" the link points to."); - -#define OS_GETXATTR_METHODDEF \ - {"getxattr", (PyCFunction)os_getxattr, METH_VARARGS|METH_KEYWORDS, os_getxattr__doc__}, - -static PyObject * -os_getxattr_impl(PyModuleDef *module, path_t *path, path_t *attribute, int follow_symlinks); - -static PyObject * -os_getxattr(PyModuleDef *module, PyObject *args, PyObject *kwargs) -{ - PyObject *return_value = NULL; - static char *_keywords[] = {"path", "attribute", "follow_symlinks", NULL}; - path_t path = PATH_T_INITIALIZE("getxattr", "path", 0, 1); - path_t attribute = PATH_T_INITIALIZE("getxattr", "attribute", 0, 0); - int follow_symlinks = 1; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "O&O&|$p:getxattr", _keywords, - path_converter, &path, path_converter, &attribute, &follow_symlinks)) - goto exit; - return_value = os_getxattr_impl(module, &path, &attribute, follow_symlinks); - -exit: - /* Cleanup for path */ - path_cleanup(&path); - /* Cleanup for attribute */ - path_cleanup(&attribute); - - return return_value; -} - static PyObject * os_getxattr_impl(PyModuleDef *module, path_t *path, path_t *attribute, int follow_symlinks) -/*[clinic end generated code: output=bbc9454fe2b9ea86 input=8c8ea3bab78d89c2]*/ +/*[clinic end generated code: output=d90086b314859f8b input=8c8ea3bab78d89c2]*/ { Py_ssize_t i; PyObject *buffer = NULL; @@ -15479,56 +10803,9 @@ [clinic start generated code]*/ -PyDoc_STRVAR(os_setxattr__doc__, -"setxattr($module, /, path, attribute, value, flags=0, *,\n" -" follow_symlinks=True)\n" -"--\n" -"\n" -"Set extended attribute attribute on path to value.\n" -"\n" -"path may be either a string or an open file descriptor.\n" -"If follow_symlinks is False, and the last element of the path is a symbolic\n" -" link, setxattr will modify the symbolic link itself instead of the file\n" -" the link points to."); - -#define OS_SETXATTR_METHODDEF \ - {"setxattr", (PyCFunction)os_setxattr, METH_VARARGS|METH_KEYWORDS, os_setxattr__doc__}, - -static PyObject * -os_setxattr_impl(PyModuleDef *module, path_t *path, path_t *attribute, Py_buffer *value, int flags, int follow_symlinks); - -static PyObject * -os_setxattr(PyModuleDef *module, PyObject *args, PyObject *kwargs) -{ - PyObject *return_value = NULL; - static char *_keywords[] = {"path", "attribute", "value", "flags", "follow_symlinks", NULL}; - path_t path = PATH_T_INITIALIZE("setxattr", "path", 0, 1); - path_t attribute = PATH_T_INITIALIZE("setxattr", "attribute", 0, 0); - Py_buffer value = {NULL, NULL}; - int flags = 0; - int follow_symlinks = 1; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "O&O&y*|i$p:setxattr", _keywords, - path_converter, &path, path_converter, &attribute, &value, &flags, &follow_symlinks)) - goto exit; - return_value = os_setxattr_impl(module, &path, &attribute, &value, flags, follow_symlinks); - -exit: - /* Cleanup for path */ - path_cleanup(&path); - /* Cleanup for attribute */ - path_cleanup(&attribute); - /* Cleanup for value */ - if (value.obj) - PyBuffer_Release(&value); - - return return_value; -} - static PyObject * os_setxattr_impl(PyModuleDef *module, path_t *path, path_t *attribute, Py_buffer *value, int flags, int follow_symlinks) -/*[clinic end generated code: output=2ff845d8e024b218 input=f0d26833992015c2]*/ +/*[clinic end generated code: output=e3defa5c4b1ad0ae input=f0d26833992015c2]*/ { ssize_t result; @@ -15573,50 +10850,9 @@ [clinic start generated code]*/ -PyDoc_STRVAR(os_removexattr__doc__, -"removexattr($module, /, path, attribute, *, follow_symlinks=True)\n" -"--\n" -"\n" -"Remove extended attribute attribute on path.\n" -"\n" -"path may be either a string or an open file descriptor.\n" -"If follow_symlinks is False, and the last element of the path is a symbolic\n" -" link, removexattr will modify the symbolic link itself instead of the file\n" -" the link points to."); - -#define OS_REMOVEXATTR_METHODDEF \ - {"removexattr", (PyCFunction)os_removexattr, METH_VARARGS|METH_KEYWORDS, os_removexattr__doc__}, - -static PyObject * -os_removexattr_impl(PyModuleDef *module, path_t *path, path_t *attribute, int follow_symlinks); - -static PyObject * -os_removexattr(PyModuleDef *module, PyObject *args, PyObject *kwargs) -{ - PyObject *return_value = NULL; - static char *_keywords[] = {"path", "attribute", "follow_symlinks", NULL}; - path_t path = PATH_T_INITIALIZE("removexattr", "path", 0, 1); - path_t attribute = PATH_T_INITIALIZE("removexattr", "attribute", 0, 0); - int follow_symlinks = 1; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "O&O&|$p:removexattr", _keywords, - path_converter, &path, path_converter, &attribute, &follow_symlinks)) - goto exit; - return_value = os_removexattr_impl(module, &path, &attribute, follow_symlinks); - -exit: - /* Cleanup for path */ - path_cleanup(&path); - /* Cleanup for attribute */ - path_cleanup(&attribute); - - return return_value; -} - static PyObject * os_removexattr_impl(PyModuleDef *module, path_t *path, path_t *attribute, int follow_symlinks) -/*[clinic end generated code: output=8dfc715bf607c4cf input=cdb54834161e3329]*/ +/*[clinic end generated code: output=4870ec90249af875 input=cdb54834161e3329]*/ { ssize_t result; @@ -15656,48 +10892,9 @@ the link points to. [clinic start generated code]*/ -PyDoc_STRVAR(os_listxattr__doc__, -"listxattr($module, /, path=None, *, follow_symlinks=True)\n" -"--\n" -"\n" -"Return a list of extended attributes on path.\n" -"\n" -"path may be either None, a string, or an open file descriptor.\n" -"if path is None, listxattr will examine the current directory.\n" -"If follow_symlinks is False, and the last element of the path is a symbolic\n" -" link, listxattr will examine the symbolic link itself instead of the file\n" -" the link points to."); - -#define OS_LISTXATTR_METHODDEF \ - {"listxattr", (PyCFunction)os_listxattr, METH_VARARGS|METH_KEYWORDS, os_listxattr__doc__}, - -static PyObject * -os_listxattr_impl(PyModuleDef *module, path_t *path, int follow_symlinks); - -static PyObject * -os_listxattr(PyModuleDef *module, PyObject *args, PyObject *kwargs) -{ - PyObject *return_value = NULL; - static char *_keywords[] = {"path", "follow_symlinks", NULL}; - path_t path = PATH_T_INITIALIZE("listxattr", "path", 1, 1); - int follow_symlinks = 1; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "|O&$p:listxattr", _keywords, - path_converter, &path, &follow_symlinks)) - goto exit; - return_value = os_listxattr_impl(module, &path, follow_symlinks); - -exit: - /* Cleanup for path */ - path_cleanup(&path); - - return return_value; -} - static PyObject * os_listxattr_impl(PyModuleDef *module, path_t *path, int follow_symlinks) -/*[clinic end generated code: output=3104cafda1a3d887 input=08cca53ac0b07c13]*/ +/*[clinic end generated code: output=a87ad6ce56e42a4f input=08cca53ac0b07c13]*/ { Py_ssize_t i; PyObject *result = NULL; @@ -15789,37 +10986,9 @@ Return a bytes object containing random bytes suitable for cryptographic use. [clinic start generated code]*/ -PyDoc_STRVAR(os_urandom__doc__, -"urandom($module, size, /)\n" -"--\n" -"\n" -"Return a bytes object containing random bytes suitable for cryptographic use."); - -#define OS_URANDOM_METHODDEF \ - {"urandom", (PyCFunction)os_urandom, METH_VARARGS, os_urandom__doc__}, - -static PyObject * -os_urandom_impl(PyModuleDef *module, Py_ssize_t size); - -static PyObject * -os_urandom(PyModuleDef *module, PyObject *args) -{ - PyObject *return_value = NULL; - Py_ssize_t size; - - if (!PyArg_ParseTuple(args, - "n:urandom", - &size)) - goto exit; - return_value = os_urandom_impl(module, size); - -exit: - return return_value; -} - static PyObject * os_urandom_impl(PyModuleDef *module, Py_ssize_t size) -/*[clinic end generated code: output=5dbff582cab94cb9 input=4067cdb1b6776c29]*/ +/*[clinic end generated code: output=e0011f021501f03b input=4067cdb1b6776c29]*/ { PyObject *bytes; int result; @@ -15954,27 +11123,9 @@ Return the number of CPUs in the system; return None if indeterminable. [clinic start generated code]*/ -PyDoc_STRVAR(os_cpu_count__doc__, -"cpu_count($module, /)\n" -"--\n" -"\n" -"Return the number of CPUs in the system; return None if indeterminable."); - -#define OS_CPU_COUNT_METHODDEF \ - {"cpu_count", (PyCFunction)os_cpu_count, METH_NOARGS, os_cpu_count__doc__}, - -static PyObject * -os_cpu_count_impl(PyModuleDef *module); - -static PyObject * -os_cpu_count(PyModuleDef *module, PyObject *Py_UNUSED(ignored)) -{ - return os_cpu_count_impl(module); -} - static PyObject * os_cpu_count_impl(PyModuleDef *module) -/*[clinic end generated code: output=92e2a4a729eb7740 input=d55e2f8f3823a628]*/ +/*[clinic end generated code: output=c59ee7f6bce832b8 input=d55e2f8f3823a628]*/ { int ncpu = 0; #ifdef MS_WINDOWS @@ -16013,41 +11164,9 @@ Get the close-on-exe flag of the specified file descriptor. [clinic start generated code]*/ -PyDoc_STRVAR(os_get_inheritable__doc__, -"get_inheritable($module, fd, /)\n" -"--\n" -"\n" -"Get the close-on-exe flag of the specified file descriptor."); - -#define OS_GET_INHERITABLE_METHODDEF \ - {"get_inheritable", (PyCFunction)os_get_inheritable, METH_VARARGS, os_get_inheritable__doc__}, - -static int -os_get_inheritable_impl(PyModuleDef *module, int fd); - -static PyObject * -os_get_inheritable(PyModuleDef *module, PyObject *args) -{ - PyObject *return_value = NULL; - int fd; - int _return_value; - - if (!PyArg_ParseTuple(args, - "i:get_inheritable", - &fd)) - goto exit; - _return_value = os_get_inheritable_impl(module, fd); - if ((_return_value == -1) && PyErr_Occurred()) - goto exit; - return_value = PyBool_FromLong((long)_return_value); - -exit: - return return_value; -} - static int os_get_inheritable_impl(PyModuleDef *module, int fd) -/*[clinic end generated code: output=261d1dd2b0dbdc35 input=89ac008dc9ab6b95]*/ +/*[clinic end generated code: output=36110bb36efaa21e input=89ac008dc9ab6b95]*/ { if (!_PyVerify_fd(fd)){ posix_error(); @@ -16067,38 +11186,9 @@ Set the inheritable flag of the specified file descriptor. [clinic start generated code]*/ -PyDoc_STRVAR(os_set_inheritable__doc__, -"set_inheritable($module, fd, inheritable, /)\n" -"--\n" -"\n" -"Set the inheritable flag of the specified file descriptor."); - -#define OS_SET_INHERITABLE_METHODDEF \ - {"set_inheritable", (PyCFunction)os_set_inheritable, METH_VARARGS, os_set_inheritable__doc__}, - -static PyObject * -os_set_inheritable_impl(PyModuleDef *module, int fd, int inheritable); - -static PyObject * -os_set_inheritable(PyModuleDef *module, PyObject *args) -{ - PyObject *return_value = NULL; - int fd; - int inheritable; - - if (!PyArg_ParseTuple(args, - "ii:set_inheritable", - &fd, &inheritable)) - goto exit; - return_value = os_set_inheritable_impl(module, fd, inheritable); - -exit: - return return_value; -} - static PyObject * os_set_inheritable_impl(PyModuleDef *module, int fd, int inheritable) -/*[clinic end generated code: output=64dfe5e15c906539 input=9ceaead87a1e2402]*/ +/*[clinic end generated code: output=2ac5c6ce8623f045 input=9ceaead87a1e2402]*/ { if (!_PyVerify_fd(fd)) return posix_error(); @@ -16118,41 +11208,9 @@ Get the close-on-exe flag of the specified file descriptor. [clinic start generated code]*/ -PyDoc_STRVAR(os_get_handle_inheritable__doc__, -"get_handle_inheritable($module, handle, /)\n" -"--\n" -"\n" -"Get the close-on-exe flag of the specified file descriptor."); - -#define OS_GET_HANDLE_INHERITABLE_METHODDEF \ - {"get_handle_inheritable", (PyCFunction)os_get_handle_inheritable, METH_VARARGS, os_get_handle_inheritable__doc__}, - -static int -os_get_handle_inheritable_impl(PyModuleDef *module, Py_intptr_t handle); - -static PyObject * -os_get_handle_inheritable(PyModuleDef *module, PyObject *args) -{ - PyObject *return_value = NULL; - Py_intptr_t handle; - int _return_value; - - if (!PyArg_ParseTuple(args, - "" _Py_PARSE_INTPTR ":get_handle_inheritable", - &handle)) - goto exit; - _return_value = os_get_handle_inheritable_impl(module, handle); - if ((_return_value == -1) && PyErr_Occurred()) - goto exit; - return_value = PyBool_FromLong((long)_return_value); - -exit: - return return_value; -} - static int os_get_handle_inheritable_impl(PyModuleDef *module, Py_intptr_t handle) -/*[clinic end generated code: output=d5bf9d86900bf457 input=5f7759443aae3dc5]*/ +/*[clinic end generated code: output=3b7b3e1b43f312b6 input=5f7759443aae3dc5]*/ { DWORD flags; @@ -16174,38 +11232,9 @@ Set the inheritable flag of the specified handle. [clinic start generated code]*/ -PyDoc_STRVAR(os_set_handle_inheritable__doc__, -"set_handle_inheritable($module, handle, inheritable, /)\n" -"--\n" -"\n" -"Set the inheritable flag of the specified handle."); - -#define OS_SET_HANDLE_INHERITABLE_METHODDEF \ - {"set_handle_inheritable", (PyCFunction)os_set_handle_inheritable, METH_VARARGS, os_set_handle_inheritable__doc__}, - -static PyObject * -os_set_handle_inheritable_impl(PyModuleDef *module, Py_intptr_t handle, int inheritable); - -static PyObject * -os_set_handle_inheritable(PyModuleDef *module, PyObject *args) -{ - PyObject *return_value = NULL; - Py_intptr_t handle; - int inheritable; - - if (!PyArg_ParseTuple(args, - "" _Py_PARSE_INTPTR "p:set_handle_inheritable", - &handle, &inheritable)) - goto exit; - return_value = os_set_handle_inheritable_impl(module, handle, inheritable); - -exit: - return return_value; -} - static PyObject * os_set_handle_inheritable_impl(PyModuleDef *module, Py_intptr_t handle, int inheritable) -/*[clinic end generated code: output=ee5fcc6d9f0d4f8b input=e64b2b2730469def]*/ +/*[clinic end generated code: output=627aa5b158b69338 input=e64b2b2730469def]*/ { DWORD flags = inheritable ? HANDLE_FLAG_INHERIT : 0; if (!SetHandleInformation((HANDLE)handle, HANDLE_FLAG_INHERIT, flags)) { @@ -17045,471 +12074,7 @@ /*[clinic input] dump buffer [clinic start generated code]*/ - -#ifndef OS_TTYNAME_METHODDEF - #define OS_TTYNAME_METHODDEF -#endif /* !defined(OS_TTYNAME_METHODDEF) */ - -#ifndef OS_CTERMID_METHODDEF - #define OS_CTERMID_METHODDEF -#endif /* !defined(OS_CTERMID_METHODDEF) */ - -#ifndef OS_FCHDIR_METHODDEF - #define OS_FCHDIR_METHODDEF -#endif /* !defined(OS_FCHDIR_METHODDEF) */ - -#ifndef OS_FCHMOD_METHODDEF - #define OS_FCHMOD_METHODDEF -#endif /* !defined(OS_FCHMOD_METHODDEF) */ - -#ifndef OS_LCHMOD_METHODDEF - #define OS_LCHMOD_METHODDEF -#endif /* !defined(OS_LCHMOD_METHODDEF) */ - -#ifndef OS_CHFLAGS_METHODDEF - #define OS_CHFLAGS_METHODDEF -#endif /* !defined(OS_CHFLAGS_METHODDEF) */ - -#ifndef OS_LCHFLAGS_METHODDEF - #define OS_LCHFLAGS_METHODDEF -#endif /* !defined(OS_LCHFLAGS_METHODDEF) */ - -#ifndef OS_CHROOT_METHODDEF - #define OS_CHROOT_METHODDEF -#endif /* !defined(OS_CHROOT_METHODDEF) */ - -#ifndef OS_FSYNC_METHODDEF - #define OS_FSYNC_METHODDEF -#endif /* !defined(OS_FSYNC_METHODDEF) */ - -#ifndef OS_SYNC_METHODDEF - #define OS_SYNC_METHODDEF -#endif /* !defined(OS_SYNC_METHODDEF) */ - -#ifndef OS_FDATASYNC_METHODDEF - #define OS_FDATASYNC_METHODDEF -#endif /* !defined(OS_FDATASYNC_METHODDEF) */ - -#ifndef OS_CHOWN_METHODDEF - #define OS_CHOWN_METHODDEF -#endif /* !defined(OS_CHOWN_METHODDEF) */ - -#ifndef OS_FCHOWN_METHODDEF - #define OS_FCHOWN_METHODDEF -#endif /* !defined(OS_FCHOWN_METHODDEF) */ - -#ifndef OS_LCHOWN_METHODDEF - #define OS_LCHOWN_METHODDEF -#endif /* !defined(OS_LCHOWN_METHODDEF) */ - -#ifndef OS_LINK_METHODDEF - #define OS_LINK_METHODDEF -#endif /* !defined(OS_LINK_METHODDEF) */ - -#ifndef OS__GETFINALPATHNAME_METHODDEF - #define OS__GETFINALPATHNAME_METHODDEF -#endif /* !defined(OS__GETFINALPATHNAME_METHODDEF) */ - -#ifndef OS__GETVOLUMEPATHNAME_METHODDEF - #define OS__GETVOLUMEPATHNAME_METHODDEF -#endif /* !defined(OS__GETVOLUMEPATHNAME_METHODDEF) */ - -#ifndef OS_NICE_METHODDEF - #define OS_NICE_METHODDEF -#endif /* !defined(OS_NICE_METHODDEF) */ - -#ifndef OS_GETPRIORITY_METHODDEF - #define OS_GETPRIORITY_METHODDEF -#endif /* !defined(OS_GETPRIORITY_METHODDEF) */ - -#ifndef OS_SETPRIORITY_METHODDEF - #define OS_SETPRIORITY_METHODDEF -#endif /* !defined(OS_SETPRIORITY_METHODDEF) */ - -#ifndef OS_SYSTEM_METHODDEF - #define OS_SYSTEM_METHODDEF -#endif /* !defined(OS_SYSTEM_METHODDEF) */ - -#ifndef OS_UNAME_METHODDEF - #define OS_UNAME_METHODDEF -#endif /* !defined(OS_UNAME_METHODDEF) */ - -#ifndef OS_EXECV_METHODDEF - #define OS_EXECV_METHODDEF -#endif /* !defined(OS_EXECV_METHODDEF) */ - -#ifndef OS_EXECVE_METHODDEF - #define OS_EXECVE_METHODDEF -#endif /* !defined(OS_EXECVE_METHODDEF) */ - -#ifndef OS_SPAWNV_METHODDEF - #define OS_SPAWNV_METHODDEF -#endif /* !defined(OS_SPAWNV_METHODDEF) */ - -#ifndef OS_SPAWNVE_METHODDEF - #define OS_SPAWNVE_METHODDEF -#endif /* !defined(OS_SPAWNVE_METHODDEF) */ - -#ifndef OS_FORK1_METHODDEF - #define OS_FORK1_METHODDEF -#endif /* !defined(OS_FORK1_METHODDEF) */ - -#ifndef OS_FORK_METHODDEF - #define OS_FORK_METHODDEF -#endif /* !defined(OS_FORK_METHODDEF) */ - -#ifndef OS_SCHED_GET_PRIORITY_MAX_METHODDEF - #define OS_SCHED_GET_PRIORITY_MAX_METHODDEF -#endif /* !defined(OS_SCHED_GET_PRIORITY_MAX_METHODDEF) */ - -#ifndef OS_SCHED_GET_PRIORITY_MIN_METHODDEF - #define OS_SCHED_GET_PRIORITY_MIN_METHODDEF -#endif /* !defined(OS_SCHED_GET_PRIORITY_MIN_METHODDEF) */ - -#ifndef OS_SCHED_GETSCHEDULER_METHODDEF - #define OS_SCHED_GETSCHEDULER_METHODDEF -#endif /* !defined(OS_SCHED_GETSCHEDULER_METHODDEF) */ - -#ifndef OS_SCHED_SETSCHEDULER_METHODDEF - #define OS_SCHED_SETSCHEDULER_METHODDEF -#endif /* !defined(OS_SCHED_SETSCHEDULER_METHODDEF) */ - -#ifndef OS_SCHED_GETPARAM_METHODDEF - #define OS_SCHED_GETPARAM_METHODDEF -#endif /* !defined(OS_SCHED_GETPARAM_METHODDEF) */ - -#ifndef OS_SCHED_SETPARAM_METHODDEF - #define OS_SCHED_SETPARAM_METHODDEF -#endif /* !defined(OS_SCHED_SETPARAM_METHODDEF) */ - -#ifndef OS_SCHED_RR_GET_INTERVAL_METHODDEF - #define OS_SCHED_RR_GET_INTERVAL_METHODDEF -#endif /* !defined(OS_SCHED_RR_GET_INTERVAL_METHODDEF) */ - -#ifndef OS_SCHED_YIELD_METHODDEF - #define OS_SCHED_YIELD_METHODDEF -#endif /* !defined(OS_SCHED_YIELD_METHODDEF) */ - -#ifndef OS_SCHED_SETAFFINITY_METHODDEF - #define OS_SCHED_SETAFFINITY_METHODDEF -#endif /* !defined(OS_SCHED_SETAFFINITY_METHODDEF) */ - -#ifndef OS_SCHED_GETAFFINITY_METHODDEF - #define OS_SCHED_GETAFFINITY_METHODDEF -#endif /* !defined(OS_SCHED_GETAFFINITY_METHODDEF) */ - -#ifndef OS_OPENPTY_METHODDEF - #define OS_OPENPTY_METHODDEF -#endif /* !defined(OS_OPENPTY_METHODDEF) */ - -#ifndef OS_FORKPTY_METHODDEF - #define OS_FORKPTY_METHODDEF -#endif /* !defined(OS_FORKPTY_METHODDEF) */ - -#ifndef OS_GETEGID_METHODDEF - #define OS_GETEGID_METHODDEF -#endif /* !defined(OS_GETEGID_METHODDEF) */ - -#ifndef OS_GETEUID_METHODDEF - #define OS_GETEUID_METHODDEF -#endif /* !defined(OS_GETEUID_METHODDEF) */ - -#ifndef OS_GETGID_METHODDEF - #define OS_GETGID_METHODDEF -#endif /* !defined(OS_GETGID_METHODDEF) */ - -#ifndef OS_GETGROUPS_METHODDEF - #define OS_GETGROUPS_METHODDEF -#endif /* !defined(OS_GETGROUPS_METHODDEF) */ - -#ifndef OS_GETPGID_METHODDEF - #define OS_GETPGID_METHODDEF -#endif /* !defined(OS_GETPGID_METHODDEF) */ - -#ifndef OS_GETPGRP_METHODDEF - #define OS_GETPGRP_METHODDEF -#endif /* !defined(OS_GETPGRP_METHODDEF) */ - -#ifndef OS_SETPGRP_METHODDEF - #define OS_SETPGRP_METHODDEF -#endif /* !defined(OS_SETPGRP_METHODDEF) */ - -#ifndef OS_GETPPID_METHODDEF - #define OS_GETPPID_METHODDEF -#endif /* !defined(OS_GETPPID_METHODDEF) */ - -#ifndef OS_GETLOGIN_METHODDEF - #define OS_GETLOGIN_METHODDEF -#endif /* !defined(OS_GETLOGIN_METHODDEF) */ - -#ifndef OS_GETUID_METHODDEF - #define OS_GETUID_METHODDEF -#endif /* !defined(OS_GETUID_METHODDEF) */ - -#ifndef OS_KILL_METHODDEF - #define OS_KILL_METHODDEF -#endif /* !defined(OS_KILL_METHODDEF) */ - -#ifndef OS_KILLPG_METHODDEF - #define OS_KILLPG_METHODDEF -#endif /* !defined(OS_KILLPG_METHODDEF) */ - -#ifndef OS_PLOCK_METHODDEF - #define OS_PLOCK_METHODDEF -#endif /* !defined(OS_PLOCK_METHODDEF) */ - -#ifndef OS_SETUID_METHODDEF - #define OS_SETUID_METHODDEF -#endif /* !defined(OS_SETUID_METHODDEF) */ - -#ifndef OS_SETEUID_METHODDEF - #define OS_SETEUID_METHODDEF -#endif /* !defined(OS_SETEUID_METHODDEF) */ - -#ifndef OS_SETEGID_METHODDEF - #define OS_SETEGID_METHODDEF -#endif /* !defined(OS_SETEGID_METHODDEF) */ - -#ifndef OS_SETREUID_METHODDEF - #define OS_SETREUID_METHODDEF -#endif /* !defined(OS_SETREUID_METHODDEF) */ - -#ifndef OS_SETREGID_METHODDEF - #define OS_SETREGID_METHODDEF -#endif /* !defined(OS_SETREGID_METHODDEF) */ - -#ifndef OS_SETGID_METHODDEF - #define OS_SETGID_METHODDEF -#endif /* !defined(OS_SETGID_METHODDEF) */ - -#ifndef OS_SETGROUPS_METHODDEF - #define OS_SETGROUPS_METHODDEF -#endif /* !defined(OS_SETGROUPS_METHODDEF) */ - -#ifndef OS_WAIT3_METHODDEF - #define OS_WAIT3_METHODDEF -#endif /* !defined(OS_WAIT3_METHODDEF) */ - -#ifndef OS_WAIT4_METHODDEF - #define OS_WAIT4_METHODDEF -#endif /* !defined(OS_WAIT4_METHODDEF) */ - -#ifndef OS_WAITID_METHODDEF - #define OS_WAITID_METHODDEF -#endif /* !defined(OS_WAITID_METHODDEF) */ - -#ifndef OS_WAITPID_METHODDEF - #define OS_WAITPID_METHODDEF -#endif /* !defined(OS_WAITPID_METHODDEF) */ - -#ifndef OS_WAIT_METHODDEF - #define OS_WAIT_METHODDEF -#endif /* !defined(OS_WAIT_METHODDEF) */ - -#ifndef OS_SYMLINK_METHODDEF - #define OS_SYMLINK_METHODDEF -#endif /* !defined(OS_SYMLINK_METHODDEF) */ - -#ifndef OS_TIMES_METHODDEF - #define OS_TIMES_METHODDEF -#endif /* !defined(OS_TIMES_METHODDEF) */ - -#ifndef OS_GETSID_METHODDEF - #define OS_GETSID_METHODDEF -#endif /* !defined(OS_GETSID_METHODDEF) */ - -#ifndef OS_SETSID_METHODDEF - #define OS_SETSID_METHODDEF -#endif /* !defined(OS_SETSID_METHODDEF) */ - -#ifndef OS_SETPGID_METHODDEF - #define OS_SETPGID_METHODDEF -#endif /* !defined(OS_SETPGID_METHODDEF) */ - -#ifndef OS_TCGETPGRP_METHODDEF - #define OS_TCGETPGRP_METHODDEF -#endif /* !defined(OS_TCGETPGRP_METHODDEF) */ - -#ifndef OS_TCSETPGRP_METHODDEF - #define OS_TCSETPGRP_METHODDEF -#endif /* !defined(OS_TCSETPGRP_METHODDEF) */ - -#ifndef OS_LOCKF_METHODDEF - #define OS_LOCKF_METHODDEF -#endif /* !defined(OS_LOCKF_METHODDEF) */ - -#ifndef OS_READV_METHODDEF - #define OS_READV_METHODDEF -#endif /* !defined(OS_READV_METHODDEF) */ - -#ifndef OS_PREAD_METHODDEF - #define OS_PREAD_METHODDEF -#endif /* !defined(OS_PREAD_METHODDEF) */ - -#ifndef OS_PIPE_METHODDEF - #define OS_PIPE_METHODDEF -#endif /* !defined(OS_PIPE_METHODDEF) */ - -#ifndef OS_PIPE2_METHODDEF - #define OS_PIPE2_METHODDEF -#endif /* !defined(OS_PIPE2_METHODDEF) */ - -#ifndef OS_WRITEV_METHODDEF - #define OS_WRITEV_METHODDEF -#endif /* !defined(OS_WRITEV_METHODDEF) */ - -#ifndef OS_PWRITE_METHODDEF - #define OS_PWRITE_METHODDEF -#endif /* !defined(OS_PWRITE_METHODDEF) */ - -#ifndef OS_MKFIFO_METHODDEF - #define OS_MKFIFO_METHODDEF -#endif /* !defined(OS_MKFIFO_METHODDEF) */ - -#ifndef OS_MKNOD_METHODDEF - #define OS_MKNOD_METHODDEF -#endif /* !defined(OS_MKNOD_METHODDEF) */ - -#ifndef OS_MAJOR_METHODDEF - #define OS_MAJOR_METHODDEF -#endif /* !defined(OS_MAJOR_METHODDEF) */ - -#ifndef OS_MINOR_METHODDEF - #define OS_MINOR_METHODDEF -#endif /* !defined(OS_MINOR_METHODDEF) */ - -#ifndef OS_MAKEDEV_METHODDEF - #define OS_MAKEDEV_METHODDEF -#endif /* !defined(OS_MAKEDEV_METHODDEF) */ - -#ifndef OS_FTRUNCATE_METHODDEF - #define OS_FTRUNCATE_METHODDEF -#endif /* !defined(OS_FTRUNCATE_METHODDEF) */ - -#ifndef OS_TRUNCATE_METHODDEF - #define OS_TRUNCATE_METHODDEF -#endif /* !defined(OS_TRUNCATE_METHODDEF) */ - -#ifndef OS_POSIX_FALLOCATE_METHODDEF - #define OS_POSIX_FALLOCATE_METHODDEF -#endif /* !defined(OS_POSIX_FALLOCATE_METHODDEF) */ - -#ifndef OS_POSIX_FADVISE_METHODDEF - #define OS_POSIX_FADVISE_METHODDEF -#endif /* !defined(OS_POSIX_FADVISE_METHODDEF) */ - -#ifndef OS_PUTENV_METHODDEF - #define OS_PUTENV_METHODDEF -#endif /* !defined(OS_PUTENV_METHODDEF) */ - -#ifndef OS_UNSETENV_METHODDEF - #define OS_UNSETENV_METHODDEF -#endif /* !defined(OS_UNSETENV_METHODDEF) */ - -#ifndef OS_WCOREDUMP_METHODDEF - #define OS_WCOREDUMP_METHODDEF -#endif /* !defined(OS_WCOREDUMP_METHODDEF) */ - -#ifndef OS_WIFCONTINUED_METHODDEF - #define OS_WIFCONTINUED_METHODDEF -#endif /* !defined(OS_WIFCONTINUED_METHODDEF) */ - -#ifndef OS_WIFSTOPPED_METHODDEF - #define OS_WIFSTOPPED_METHODDEF -#endif /* !defined(OS_WIFSTOPPED_METHODDEF) */ - -#ifndef OS_WIFSIGNALED_METHODDEF - #define OS_WIFSIGNALED_METHODDEF -#endif /* !defined(OS_WIFSIGNALED_METHODDEF) */ - -#ifndef OS_WIFEXITED_METHODDEF - #define OS_WIFEXITED_METHODDEF -#endif /* !defined(OS_WIFEXITED_METHODDEF) */ - -#ifndef OS_WEXITSTATUS_METHODDEF - #define OS_WEXITSTATUS_METHODDEF -#endif /* !defined(OS_WEXITSTATUS_METHODDEF) */ - -#ifndef OS_WTERMSIG_METHODDEF - #define OS_WTERMSIG_METHODDEF -#endif /* !defined(OS_WTERMSIG_METHODDEF) */ - -#ifndef OS_WSTOPSIG_METHODDEF - #define OS_WSTOPSIG_METHODDEF -#endif /* !defined(OS_WSTOPSIG_METHODDEF) */ - -#ifndef OS_FSTATVFS_METHODDEF - #define OS_FSTATVFS_METHODDEF -#endif /* !defined(OS_FSTATVFS_METHODDEF) */ - -#ifndef OS_STATVFS_METHODDEF - #define OS_STATVFS_METHODDEF -#endif /* !defined(OS_STATVFS_METHODDEF) */ - -#ifndef OS__GETDISKUSAGE_METHODDEF - #define OS__GETDISKUSAGE_METHODDEF -#endif /* !defined(OS__GETDISKUSAGE_METHODDEF) */ - -#ifndef OS_FPATHCONF_METHODDEF - #define OS_FPATHCONF_METHODDEF -#endif /* !defined(OS_FPATHCONF_METHODDEF) */ - -#ifndef OS_PATHCONF_METHODDEF - #define OS_PATHCONF_METHODDEF -#endif /* !defined(OS_PATHCONF_METHODDEF) */ - -#ifndef OS_CONFSTR_METHODDEF - #define OS_CONFSTR_METHODDEF -#endif /* !defined(OS_CONFSTR_METHODDEF) */ - -#ifndef OS_SYSCONF_METHODDEF - #define OS_SYSCONF_METHODDEF -#endif /* !defined(OS_SYSCONF_METHODDEF) */ - -#ifndef OS_GETLOADAVG_METHODDEF - #define OS_GETLOADAVG_METHODDEF -#endif /* !defined(OS_GETLOADAVG_METHODDEF) */ - -#ifndef OS_SETRESUID_METHODDEF - #define OS_SETRESUID_METHODDEF -#endif /* !defined(OS_SETRESUID_METHODDEF) */ - -#ifndef OS_SETRESGID_METHODDEF - #define OS_SETRESGID_METHODDEF -#endif /* !defined(OS_SETRESGID_METHODDEF) */ - -#ifndef OS_GETRESUID_METHODDEF - #define OS_GETRESUID_METHODDEF -#endif /* !defined(OS_GETRESUID_METHODDEF) */ - -#ifndef OS_GETRESGID_METHODDEF - #define OS_GETRESGID_METHODDEF -#endif /* !defined(OS_GETRESGID_METHODDEF) */ - -#ifndef OS_GETXATTR_METHODDEF - #define OS_GETXATTR_METHODDEF -#endif /* !defined(OS_GETXATTR_METHODDEF) */ - -#ifndef OS_SETXATTR_METHODDEF - #define OS_SETXATTR_METHODDEF -#endif /* !defined(OS_SETXATTR_METHODDEF) */ - -#ifndef OS_REMOVEXATTR_METHODDEF - #define OS_REMOVEXATTR_METHODDEF -#endif /* !defined(OS_REMOVEXATTR_METHODDEF) */ - -#ifndef OS_LISTXATTR_METHODDEF - #define OS_LISTXATTR_METHODDEF -#endif /* !defined(OS_LISTXATTR_METHODDEF) */ - -#ifndef OS_GET_HANDLE_INHERITABLE_METHODDEF - #define OS_GET_HANDLE_INHERITABLE_METHODDEF -#endif /* !defined(OS_GET_HANDLE_INHERITABLE_METHODDEF) */ - -#ifndef OS_SET_HANDLE_INHERITABLE_METHODDEF - #define OS_SET_HANDLE_INHERITABLE_METHODDEF -#endif /* !defined(OS_SET_HANDLE_INHERITABLE_METHODDEF) */ -/*[clinic end generated code: output=b788c2d6010113e8 input=524ce2e021e4eba6]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=524ce2e021e4eba6]*/ static PyMethodDef posix_methods[] = { diff --git a/Modules/pwdmodule.c b/Modules/pwdmodule.c --- a/Modules/pwdmodule.c +++ b/Modules/pwdmodule.c @@ -8,10 +8,9 @@ #include "clinic/pwdmodule.c.h" /*[clinic input] -output preset file module pwd [clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=bbcf68b1f549f917]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=60f628ef356b97b6]*/ static PyStructSequence_Field struct_pwd_type_fields[] = { {"pw_name", "user name"}, diff --git a/Modules/pyexpat.c b/Modules/pyexpat.c --- a/Modules/pyexpat.c +++ b/Modules/pyexpat.c @@ -68,6 +68,8 @@ PyObject **handlers; } xmlparseobject; +#include "clinic/pyexpat.c.h" + #define CHARACTER_DATA_BUFFER_SIZE 8192 static PyTypeObject Xmlparsetype; @@ -713,40 +715,9 @@ `isfinal' should be true at end of input. [clinic start generated code]*/ -PyDoc_STRVAR(pyexpat_xmlparser_Parse__doc__, -"Parse($self, data, isFinal=0, /)\n" -"--\n" -"\n" -"Parse XML data.\n" -"\n" -"`isfinal\' should be true at end of input."); - -#define PYEXPAT_XMLPARSER_PARSE_METHODDEF \ - {"Parse", (PyCFunction)pyexpat_xmlparser_Parse, METH_VARARGS, pyexpat_xmlparser_Parse__doc__}, - -static PyObject * -pyexpat_xmlparser_Parse_impl(xmlparseobject *self, PyObject *data, int isFinal); - -static PyObject * -pyexpat_xmlparser_Parse(xmlparseobject *self, PyObject *args) -{ - PyObject *return_value = NULL; - PyObject *data; - int isFinal = 0; - - if (!PyArg_ParseTuple(args, - "O|i:Parse", - &data, &isFinal)) - goto exit; - return_value = pyexpat_xmlparser_Parse_impl(self, data, isFinal); - -exit: - return return_value; -} - static PyObject * pyexpat_xmlparser_Parse_impl(xmlparseobject *self, PyObject *data, int isFinal) -/*[clinic end generated code: output=65b1652b01f20856 input=e37b81b8948ca7e0]*/ +/*[clinic end generated code: output=2d4dc77f4d434854 input=e37b81b8948ca7e0]*/ { const char *s; Py_ssize_t slen; @@ -836,18 +807,9 @@ Parse XML data from file-like object. [clinic start generated code]*/ -PyDoc_STRVAR(pyexpat_xmlparser_ParseFile__doc__, -"ParseFile($self, file, /)\n" -"--\n" -"\n" -"Parse XML data from file-like object."); - -#define PYEXPAT_XMLPARSER_PARSEFILE_METHODDEF \ - {"ParseFile", (PyCFunction)pyexpat_xmlparser_ParseFile, METH_O, pyexpat_xmlparser_ParseFile__doc__}, - static PyObject * pyexpat_xmlparser_ParseFile(xmlparseobject *self, PyObject *file) -/*[clinic end generated code: output=2e13803c3d8c22b2 input=fbb5a12b6038d735]*/ +/*[clinic end generated code: output=2adc6a13100cc42b input=fbb5a12b6038d735]*/ { int rv = 1; PyObject *readmethod = NULL; @@ -894,37 +856,9 @@ Set the base URL for the parser. [clinic start generated code]*/ -PyDoc_STRVAR(pyexpat_xmlparser_SetBase__doc__, -"SetBase($self, base, /)\n" -"--\n" -"\n" -"Set the base URL for the parser."); - -#define PYEXPAT_XMLPARSER_SETBASE_METHODDEF \ - {"SetBase", (PyCFunction)pyexpat_xmlparser_SetBase, METH_VARARGS, pyexpat_xmlparser_SetBase__doc__}, - -static PyObject * -pyexpat_xmlparser_SetBase_impl(xmlparseobject *self, const char *base); - -static PyObject * -pyexpat_xmlparser_SetBase(xmlparseobject *self, PyObject *args) -{ - PyObject *return_value = NULL; - const char *base; - - if (!PyArg_ParseTuple(args, - "s:SetBase", - &base)) - goto exit; - return_value = pyexpat_xmlparser_SetBase_impl(self, base); - -exit: - return return_value; -} - static PyObject * pyexpat_xmlparser_SetBase_impl(xmlparseobject *self, const char *base) -/*[clinic end generated code: output=5bdb49f6689a5f93 input=c684e5de895ee1a8]*/ +/*[clinic end generated code: output=c212ddceb607b539 input=c684e5de895ee1a8]*/ { if (!XML_SetBase(self->itself, base)) { return PyErr_NoMemory(); @@ -938,27 +872,9 @@ Return base URL string for the parser. [clinic start generated code]*/ -PyDoc_STRVAR(pyexpat_xmlparser_GetBase__doc__, -"GetBase($self, /)\n" -"--\n" -"\n" -"Return base URL string for the parser."); - -#define PYEXPAT_XMLPARSER_GETBASE_METHODDEF \ - {"GetBase", (PyCFunction)pyexpat_xmlparser_GetBase, METH_NOARGS, pyexpat_xmlparser_GetBase__doc__}, - -static PyObject * -pyexpat_xmlparser_GetBase_impl(xmlparseobject *self); - -static PyObject * -pyexpat_xmlparser_GetBase(xmlparseobject *self, PyObject *Py_UNUSED(ignored)) -{ - return pyexpat_xmlparser_GetBase_impl(self); -} - static PyObject * pyexpat_xmlparser_GetBase_impl(xmlparseobject *self) -/*[clinic end generated code: output=ef6046ee28f2b8ee input=918d71c38009620e]*/ +/*[clinic end generated code: output=2886cb21f9a8739a input=918d71c38009620e]*/ { return Py_BuildValue("z", XML_GetBase(self->itself)); } @@ -972,30 +888,9 @@ for an element with many attributes), not all of the text may be available. [clinic start generated code]*/ -PyDoc_STRVAR(pyexpat_xmlparser_GetInputContext__doc__, -"GetInputContext($self, /)\n" -"--\n" -"\n" -"Return the untranslated text of the input that caused the current event.\n" -"\n" -"If the event was generated by a large amount of text (such as a start tag\n" -"for an element with many attributes), not all of the text may be available."); - -#define PYEXPAT_XMLPARSER_GETINPUTCONTEXT_METHODDEF \ - {"GetInputContext", (PyCFunction)pyexpat_xmlparser_GetInputContext, METH_NOARGS, pyexpat_xmlparser_GetInputContext__doc__}, - -static PyObject * -pyexpat_xmlparser_GetInputContext_impl(xmlparseobject *self); - -static PyObject * -pyexpat_xmlparser_GetInputContext(xmlparseobject *self, PyObject *Py_UNUSED(ignored)) -{ - return pyexpat_xmlparser_GetInputContext_impl(self); -} - static PyObject * pyexpat_xmlparser_GetInputContext_impl(xmlparseobject *self) -/*[clinic end generated code: output=62ff03390f074cd2 input=034df8712db68379]*/ +/*[clinic end generated code: output=a88026d683fc22cc input=034df8712db68379]*/ { if (self->in_callback) { int offset, size; @@ -1022,38 +917,9 @@ Create a parser for parsing an external entity based on the information passed to the ExternalEntityRefHandler. [clinic start generated code]*/ -PyDoc_STRVAR(pyexpat_xmlparser_ExternalEntityParserCreate__doc__, -"ExternalEntityParserCreate($self, context, encoding=None, /)\n" -"--\n" -"\n" -"Create a parser for parsing an external entity based on the information passed to the ExternalEntityRefHandler."); - -#define PYEXPAT_XMLPARSER_EXTERNALENTITYPARSERCREATE_METHODDEF \ - {"ExternalEntityParserCreate", (PyCFunction)pyexpat_xmlparser_ExternalEntityParserCreate, METH_VARARGS, pyexpat_xmlparser_ExternalEntityParserCreate__doc__}, - -static PyObject * -pyexpat_xmlparser_ExternalEntityParserCreate_impl(xmlparseobject *self, const char *context, const char *encoding); - -static PyObject * -pyexpat_xmlparser_ExternalEntityParserCreate(xmlparseobject *self, PyObject *args) -{ - PyObject *return_value = NULL; - const char *context; - const char *encoding = NULL; - - if (!PyArg_ParseTuple(args, - "z|s:ExternalEntityParserCreate", - &context, &encoding)) - goto exit; - return_value = pyexpat_xmlparser_ExternalEntityParserCreate_impl(self, context, encoding); - -exit: - return return_value; -} - static PyObject * pyexpat_xmlparser_ExternalEntityParserCreate_impl(xmlparseobject *self, const char *context, const char *encoding) -/*[clinic end generated code: output=4948c35f3dd01133 input=283206575d960272]*/ +/*[clinic end generated code: output=942f300ed0e56054 input=283206575d960272]*/ { xmlparseobject *new_parser; int i; @@ -1127,42 +993,9 @@ was successful. [clinic start generated code]*/ -PyDoc_STRVAR(pyexpat_xmlparser_SetParamEntityParsing__doc__, -"SetParamEntityParsing($self, flag, /)\n" -"--\n" -"\n" -"Controls parsing of parameter entities (including the external DTD subset).\n" -"\n" -"Possible flag values are XML_PARAM_ENTITY_PARSING_NEVER,\n" -"XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE and\n" -"XML_PARAM_ENTITY_PARSING_ALWAYS. Returns true if setting the flag\n" -"was successful."); - -#define PYEXPAT_XMLPARSER_SETPARAMENTITYPARSING_METHODDEF \ - {"SetParamEntityParsing", (PyCFunction)pyexpat_xmlparser_SetParamEntityParsing, METH_VARARGS, pyexpat_xmlparser_SetParamEntityParsing__doc__}, - -static PyObject * -pyexpat_xmlparser_SetParamEntityParsing_impl(xmlparseobject *self, int flag); - -static PyObject * -pyexpat_xmlparser_SetParamEntityParsing(xmlparseobject *self, PyObject *args) -{ - PyObject *return_value = NULL; - int flag; - - if (!PyArg_ParseTuple(args, - "i:SetParamEntityParsing", - &flag)) - goto exit; - return_value = pyexpat_xmlparser_SetParamEntityParsing_impl(self, flag); - -exit: - return return_value; -} - static PyObject * pyexpat_xmlparser_SetParamEntityParsing_impl(xmlparseobject *self, int flag) -/*[clinic end generated code: output=0f820882bc7768cc input=8aea19b4b15e9af1]*/ +/*[clinic end generated code: output=18668ee8e760d64c input=8aea19b4b15e9af1]*/ { flag = XML_SetParamEntityParsing(self->itself, flag); return PyLong_FromLong(flag); @@ -1183,41 +1016,9 @@ information to the parser. 'flag' defaults to True if not provided. [clinic start generated code]*/ -PyDoc_STRVAR(pyexpat_xmlparser_UseForeignDTD__doc__, -"UseForeignDTD($self, flag=True, /)\n" -"--\n" -"\n" -"Allows the application to provide an artificial external subset if one is not specified as part of the document instance.\n" -"\n" -"This readily allows the use of a \'default\' document type controlled by the\n" -"application, while still getting the advantage of providing document type\n" -"information to the parser. \'flag\' defaults to True if not provided."); - -#define PYEXPAT_XMLPARSER_USEFOREIGNDTD_METHODDEF \ - {"UseForeignDTD", (PyCFunction)pyexpat_xmlparser_UseForeignDTD, METH_VARARGS, pyexpat_xmlparser_UseForeignDTD__doc__}, - -static PyObject * -pyexpat_xmlparser_UseForeignDTD_impl(xmlparseobject *self, int flag); - -static PyObject * -pyexpat_xmlparser_UseForeignDTD(xmlparseobject *self, PyObject *args) -{ - PyObject *return_value = NULL; - int flag = 1; - - if (!PyArg_ParseTuple(args, - "|p:UseForeignDTD", - &flag)) - goto exit; - return_value = pyexpat_xmlparser_UseForeignDTD_impl(self, flag); - -exit: - return return_value; -} - static PyObject * pyexpat_xmlparser_UseForeignDTD_impl(xmlparseobject *self, int flag) -/*[clinic end generated code: output=22e924ae6cad67d6 input=78144c519d116a6e]*/ +/*[clinic end generated code: output=cfaa9aa50bb0f65c input=78144c519d116a6e]*/ { enum XML_Error rc; @@ -1234,25 +1035,9 @@ pyexpat.xmlparser.__dir__ [clinic start generated code]*/ -PyDoc_STRVAR(pyexpat_xmlparser___dir____doc__, -"__dir__($self, /)\n" -"--"); - -#define PYEXPAT_XMLPARSER___DIR___METHODDEF \ - {"__dir__", (PyCFunction)pyexpat_xmlparser___dir__, METH_NOARGS, pyexpat_xmlparser___dir____doc__}, - -static PyObject * -pyexpat_xmlparser___dir___impl(xmlparseobject *self); - -static PyObject * -pyexpat_xmlparser___dir__(xmlparseobject *self, PyObject *Py_UNUSED(ignored)) -{ - return pyexpat_xmlparser___dir___impl(self); -} - static PyObject * pyexpat_xmlparser___dir___impl(xmlparseobject *self) -/*[clinic end generated code: output=1ed6efe83bc304cc input=76aa455f2a661384]*/ +/*[clinic end generated code: output=bc22451efb9e4d17 input=76aa455f2a661384]*/ { #define APPEND(list, str) \ do { \ @@ -1765,41 +1550,9 @@ Return a new XML parser object. [clinic start generated code]*/ -PyDoc_STRVAR(pyexpat_ParserCreate__doc__, -"ParserCreate($module, /, encoding=None, namespace_separator=None,\n" -" intern=None)\n" -"--\n" -"\n" -"Return a new XML parser object."); - -#define PYEXPAT_PARSERCREATE_METHODDEF \ - {"ParserCreate", (PyCFunction)pyexpat_ParserCreate, METH_VARARGS|METH_KEYWORDS, pyexpat_ParserCreate__doc__}, - -static PyObject * -pyexpat_ParserCreate_impl(PyModuleDef *module, const char *encoding, const char *namespace_separator, PyObject *intern); - -static PyObject * -pyexpat_ParserCreate(PyModuleDef *module, PyObject *args, PyObject *kwargs) -{ - PyObject *return_value = NULL; - static char *_keywords[] = {"encoding", "namespace_separator", "intern", NULL}; - const char *encoding = NULL; - const char *namespace_separator = NULL; - PyObject *intern = NULL; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "|zzO:ParserCreate", _keywords, - &encoding, &namespace_separator, &intern)) - goto exit; - return_value = pyexpat_ParserCreate_impl(module, encoding, namespace_separator, intern); - -exit: - return return_value; -} - static PyObject * pyexpat_ParserCreate_impl(PyModuleDef *module, const char *encoding, const char *namespace_separator, PyObject *intern) -/*[clinic end generated code: output=4fc027dd33b7a2ac input=71b9f471aa6f8f86]*/ +/*[clinic end generated code: output=b839b60992d8ce71 input=71b9f471aa6f8f86]*/ { PyObject *result; int intern_decref = 0; @@ -1842,37 +1595,9 @@ Returns string error for given number. [clinic start generated code]*/ -PyDoc_STRVAR(pyexpat_ErrorString__doc__, -"ErrorString($module, code, /)\n" -"--\n" -"\n" -"Returns string error for given number."); - -#define PYEXPAT_ERRORSTRING_METHODDEF \ - {"ErrorString", (PyCFunction)pyexpat_ErrorString, METH_VARARGS, pyexpat_ErrorString__doc__}, - -static PyObject * -pyexpat_ErrorString_impl(PyModuleDef *module, long code); - -static PyObject * -pyexpat_ErrorString(PyModuleDef *module, PyObject *args) -{ - PyObject *return_value = NULL; - long code; - - if (!PyArg_ParseTuple(args, - "l:ErrorString", - &code)) - goto exit; - return_value = pyexpat_ErrorString_impl(module, code); - -exit: - return return_value; -} - static PyObject * pyexpat_ErrorString_impl(PyModuleDef *module, long code) -/*[clinic end generated code: output=c70f3cd82bfaf067 input=cc67de010d9e62b3]*/ +/*[clinic end generated code: output=d87668108b6868e5 input=cc67de010d9e62b3]*/ { return Py_BuildValue("z", XML_ErrorString((int)code)); } @@ -2252,8 +1977,4 @@ /*[clinic input] dump buffer [clinic start generated code]*/ - -#ifndef PYEXPAT_XMLPARSER_USEFOREIGNDTD_METHODDEF - #define PYEXPAT_XMLPARSER_USEFOREIGNDTD_METHODDEF -#endif /* !defined(PYEXPAT_XMLPARSER_USEFOREIGNDTD_METHODDEF) */ -/*[clinic end generated code: output=a7880cb78bbd58ce input=524ce2e021e4eba6]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=524ce2e021e4eba6]*/ diff --git a/Modules/sha1module.c b/Modules/sha1module.c --- a/Modules/sha1module.c +++ b/Modules/sha1module.c @@ -53,6 +53,7 @@ struct sha1_state hash_state; } SHA1object; +#include "clinic/sha1module.c.h" /* ------------------------------------------------------------------------ * @@ -320,27 +321,9 @@ Return a copy of the hash object. [clinic start generated code]*/ -PyDoc_STRVAR(SHA1Type_copy__doc__, -"copy($self, /)\n" -"--\n" -"\n" -"Return a copy of the hash object."); - -#define SHA1TYPE_COPY_METHODDEF \ - {"copy", (PyCFunction)SHA1Type_copy, METH_NOARGS, SHA1Type_copy__doc__}, - -static PyObject * -SHA1Type_copy_impl(SHA1object *self); - -static PyObject * -SHA1Type_copy(SHA1object *self, PyObject *Py_UNUSED(ignored)) -{ - return SHA1Type_copy_impl(self); -} - static PyObject * SHA1Type_copy_impl(SHA1object *self) -/*[clinic end generated code: output=1a320e75a7444098 input=b7eae10df6f89b36]*/ +/*[clinic end generated code: output=b4e001264620f02a input=b7eae10df6f89b36]*/ { SHA1object *newobj; @@ -357,27 +340,9 @@ Return the digest value as a string of binary data. [clinic start generated code]*/ -PyDoc_STRVAR(SHA1Type_digest__doc__, -"digest($self, /)\n" -"--\n" -"\n" -"Return the digest value as a string of binary data."); - -#define SHA1TYPE_DIGEST_METHODDEF \ - {"digest", (PyCFunction)SHA1Type_digest, METH_NOARGS, SHA1Type_digest__doc__}, - -static PyObject * -SHA1Type_digest_impl(SHA1object *self); - -static PyObject * -SHA1Type_digest(SHA1object *self, PyObject *Py_UNUSED(ignored)) -{ - return SHA1Type_digest_impl(self); -} - static PyObject * SHA1Type_digest_impl(SHA1object *self) -/*[clinic end generated code: output=c4920f75228bfbfd input=205d47e1927fd009]*/ +/*[clinic end generated code: output=2f05302a7aa2b5cb input=205d47e1927fd009]*/ { unsigned char digest[SHA1_DIGESTSIZE]; struct sha1_state temp; @@ -393,27 +358,9 @@ Return the digest value as a string of hexadecimal digits. [clinic start generated code]*/ -PyDoc_STRVAR(SHA1Type_hexdigest__doc__, -"hexdigest($self, /)\n" -"--\n" -"\n" -"Return the digest value as a string of hexadecimal digits."); - -#define SHA1TYPE_HEXDIGEST_METHODDEF \ - {"hexdigest", (PyCFunction)SHA1Type_hexdigest, METH_NOARGS, SHA1Type_hexdigest__doc__}, - -static PyObject * -SHA1Type_hexdigest_impl(SHA1object *self); - -static PyObject * -SHA1Type_hexdigest(SHA1object *self, PyObject *Py_UNUSED(ignored)) -{ - return SHA1Type_hexdigest_impl(self); -} - static PyObject * SHA1Type_hexdigest_impl(SHA1object *self) -/*[clinic end generated code: output=6e345aac201887b2 input=97691055c0c74ab0]*/ +/*[clinic end generated code: output=4161fd71e68c6659 input=97691055c0c74ab0]*/ { unsigned char digest[SHA1_DIGESTSIZE]; struct sha1_state temp; @@ -454,18 +401,9 @@ Update this hash object's state with the provided string. [clinic start generated code]*/ -PyDoc_STRVAR(SHA1Type_update__doc__, -"update($self, obj, /)\n" -"--\n" -"\n" -"Update this hash object\'s state with the provided string."); - -#define SHA1TYPE_UPDATE_METHODDEF \ - {"update", (PyCFunction)SHA1Type_update, METH_O, SHA1Type_update__doc__}, - static PyObject * SHA1Type_update(SHA1object *self, PyObject *obj) -/*[clinic end generated code: output=ab20a86a25e7d255 input=aad8e07812edbba3]*/ +/*[clinic end generated code: output=d9902f0e5015e9ae input=aad8e07812edbba3]*/ { Py_buffer buf; @@ -566,38 +504,9 @@ Return a new SHA1 hash object; optionally initialized with a string. [clinic start generated code]*/ -PyDoc_STRVAR(_sha1_sha1__doc__, -"sha1($module, /, string=b\'\')\n" -"--\n" -"\n" -"Return a new SHA1 hash object; optionally initialized with a string."); - -#define _SHA1_SHA1_METHODDEF \ - {"sha1", (PyCFunction)_sha1_sha1, METH_VARARGS|METH_KEYWORDS, _sha1_sha1__doc__}, - -static PyObject * -_sha1_sha1_impl(PyModuleDef *module, PyObject *string); - -static PyObject * -_sha1_sha1(PyModuleDef *module, PyObject *args, PyObject *kwargs) -{ - PyObject *return_value = NULL; - static char *_keywords[] = {"string", NULL}; - PyObject *string = NULL; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "|O:sha1", _keywords, - &string)) - goto exit; - return_value = _sha1_sha1_impl(module, string); - -exit: - return return_value; -} - static PyObject * _sha1_sha1_impl(PyModuleDef *module, PyObject *string) -/*[clinic end generated code: output=c9068552f07b8954 input=27ea54281d995ec2]*/ +/*[clinic end generated code: output=3e4e841386b9e8db input=27ea54281d995ec2]*/ { SHA1object *new; Py_buffer buf; diff --git a/Modules/sha256module.c b/Modules/sha256module.c --- a/Modules/sha256module.c +++ b/Modules/sha256module.c @@ -52,6 +52,8 @@ int digestsize; } SHAobject; +#include "clinic/sha256module.c.h" + /* When run on a little-endian CPU we need to perform byte reversal on an array of longwords. */ @@ -404,27 +406,9 @@ Return a copy of the hash object. [clinic start generated code]*/ -PyDoc_STRVAR(SHA256Type_copy__doc__, -"copy($self, /)\n" -"--\n" -"\n" -"Return a copy of the hash object."); - -#define SHA256TYPE_COPY_METHODDEF \ - {"copy", (PyCFunction)SHA256Type_copy, METH_NOARGS, SHA256Type_copy__doc__}, - -static PyObject * -SHA256Type_copy_impl(SHAobject *self); - -static PyObject * -SHA256Type_copy(SHAobject *self, PyObject *Py_UNUSED(ignored)) -{ - return SHA256Type_copy_impl(self); -} - static PyObject * SHA256Type_copy_impl(SHAobject *self) -/*[clinic end generated code: output=f716c39d3f81c27c input=f58840a618d4f2a7]*/ +/*[clinic end generated code: output=1a8bbd66a0c9c168 input=f58840a618d4f2a7]*/ { SHAobject *newobj; @@ -446,27 +430,9 @@ Return the digest value as a string of binary data. [clinic start generated code]*/ -PyDoc_STRVAR(SHA256Type_digest__doc__, -"digest($self, /)\n" -"--\n" -"\n" -"Return the digest value as a string of binary data."); - -#define SHA256TYPE_DIGEST_METHODDEF \ - {"digest", (PyCFunction)SHA256Type_digest, METH_NOARGS, SHA256Type_digest__doc__}, - -static PyObject * -SHA256Type_digest_impl(SHAobject *self); - -static PyObject * -SHA256Type_digest(SHAobject *self, PyObject *Py_UNUSED(ignored)) -{ - return SHA256Type_digest_impl(self); -} - static PyObject * SHA256Type_digest_impl(SHAobject *self) -/*[clinic end generated code: output=72d34723d7bb694c input=1fb752e58954157d]*/ +/*[clinic end generated code: output=46616a5e909fbc3d input=1fb752e58954157d]*/ { unsigned char digest[SHA_DIGESTSIZE]; SHAobject temp; @@ -482,27 +448,9 @@ Return the digest value as a string of hexadecimal digits. [clinic start generated code]*/ -PyDoc_STRVAR(SHA256Type_hexdigest__doc__, -"hexdigest($self, /)\n" -"--\n" -"\n" -"Return the digest value as a string of hexadecimal digits."); - -#define SHA256TYPE_HEXDIGEST_METHODDEF \ - {"hexdigest", (PyCFunction)SHA256Type_hexdigest, METH_NOARGS, SHA256Type_hexdigest__doc__}, - -static PyObject * -SHA256Type_hexdigest_impl(SHAobject *self); - -static PyObject * -SHA256Type_hexdigest(SHAobject *self, PyObject *Py_UNUSED(ignored)) -{ - return SHA256Type_hexdigest_impl(self); -} - static PyObject * SHA256Type_hexdigest_impl(SHAobject *self) -/*[clinic end generated code: output=3687aa6183c7d27f input=0cc4c714693010d1]*/ +/*[clinic end generated code: output=725f8a7041ae97f3 input=0cc4c714693010d1]*/ { unsigned char digest[SHA_DIGESTSIZE]; SHAobject temp; @@ -543,18 +491,9 @@ Update this hash object's state with the provided string. [clinic start generated code]*/ -PyDoc_STRVAR(SHA256Type_update__doc__, -"update($self, obj, /)\n" -"--\n" -"\n" -"Update this hash object\'s state with the provided string."); - -#define SHA256TYPE_UPDATE_METHODDEF \ - {"update", (PyCFunction)SHA256Type_update, METH_O, SHA256Type_update__doc__}, - static PyObject * SHA256Type_update(SHAobject *self, PyObject *obj) -/*[clinic end generated code: output=b47f53d7cbeabee4 input=b2d449d5b30f0f5a]*/ +/*[clinic end generated code: output=0967fb2860c66af7 input=b2d449d5b30f0f5a]*/ { Py_buffer buf; @@ -686,38 +625,9 @@ Return a new SHA-256 hash object; optionally initialized with a string. [clinic start generated code]*/ -PyDoc_STRVAR(_sha256_sha256__doc__, -"sha256($module, /, string=b\'\')\n" -"--\n" -"\n" -"Return a new SHA-256 hash object; optionally initialized with a string."); - -#define _SHA256_SHA256_METHODDEF \ - {"sha256", (PyCFunction)_sha256_sha256, METH_VARARGS|METH_KEYWORDS, _sha256_sha256__doc__}, - -static PyObject * -_sha256_sha256_impl(PyModuleDef *module, PyObject *string); - -static PyObject * -_sha256_sha256(PyModuleDef *module, PyObject *args, PyObject *kwargs) -{ - PyObject *return_value = NULL; - static char *_keywords[] = {"string", NULL}; - PyObject *string = NULL; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "|O:sha256", _keywords, - &string)) - goto exit; - return_value = _sha256_sha256_impl(module, string); - -exit: - return return_value; -} - static PyObject * _sha256_sha256_impl(PyModuleDef *module, PyObject *string) -/*[clinic end generated code: output=4b1263d1e2fcdb98 input=09cce3fb855056b2]*/ +/*[clinic end generated code: output=d70e6e2d97112844 input=09cce3fb855056b2]*/ { SHAobject *new; Py_buffer buf; @@ -755,38 +665,9 @@ Return a new SHA-224 hash object; optionally initialized with a string. [clinic start generated code]*/ -PyDoc_STRVAR(_sha256_sha224__doc__, -"sha224($module, /, string=b\'\')\n" -"--\n" -"\n" -"Return a new SHA-224 hash object; optionally initialized with a string."); - -#define _SHA256_SHA224_METHODDEF \ - {"sha224", (PyCFunction)_sha256_sha224, METH_VARARGS|METH_KEYWORDS, _sha256_sha224__doc__}, - -static PyObject * -_sha256_sha224_impl(PyModuleDef *module, PyObject *string); - -static PyObject * -_sha256_sha224(PyModuleDef *module, PyObject *args, PyObject *kwargs) -{ - PyObject *return_value = NULL; - static char *_keywords[] = {"string", NULL}; - PyObject *string = NULL; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "|O:sha224", _keywords, - &string)) - goto exit; - return_value = _sha256_sha224_impl(module, string); - -exit: - return return_value; -} - static PyObject * _sha256_sha224_impl(PyModuleDef *module, PyObject *string) -/*[clinic end generated code: output=4dde0eb1cdaebc06 input=27a04ba24c353a73]*/ +/*[clinic end generated code: output=f2822bf28416b42a input=27a04ba24c353a73]*/ { SHAobject *new; Py_buffer buf; diff --git a/Modules/sha512module.c b/Modules/sha512module.c --- a/Modules/sha512module.c +++ b/Modules/sha512module.c @@ -55,6 +55,8 @@ int digestsize; } SHAobject; +#include "clinic/sha512module.c.h" + /* When run on a little-endian CPU we need to perform byte reversal on an array of longwords. */ @@ -471,27 +473,9 @@ Return a copy of the hash object. [clinic start generated code]*/ -PyDoc_STRVAR(SHA512Type_copy__doc__, -"copy($self, /)\n" -"--\n" -"\n" -"Return a copy of the hash object."); - -#define SHA512TYPE_COPY_METHODDEF \ - {"copy", (PyCFunction)SHA512Type_copy, METH_NOARGS, SHA512Type_copy__doc__}, - -static PyObject * -SHA512Type_copy_impl(SHAobject *self); - -static PyObject * -SHA512Type_copy(SHAobject *self, PyObject *Py_UNUSED(ignored)) -{ - return SHA512Type_copy_impl(self); -} - static PyObject * SHA512Type_copy_impl(SHAobject *self) -/*[clinic end generated code: output=14f8e6ce9c61ece0 input=9f5f31e6c457776a]*/ +/*[clinic end generated code: output=adea896ed3164821 input=9f5f31e6c457776a]*/ { SHAobject *newobj; @@ -513,27 +497,9 @@ Return the digest value as a string of binary data. [clinic start generated code]*/ -PyDoc_STRVAR(SHA512Type_digest__doc__, -"digest($self, /)\n" -"--\n" -"\n" -"Return the digest value as a string of binary data."); - -#define SHA512TYPE_DIGEST_METHODDEF \ - {"digest", (PyCFunction)SHA512Type_digest, METH_NOARGS, SHA512Type_digest__doc__}, - -static PyObject * -SHA512Type_digest_impl(SHAobject *self); - -static PyObject * -SHA512Type_digest(SHAobject *self, PyObject *Py_UNUSED(ignored)) -{ - return SHA512Type_digest_impl(self); -} - static PyObject * SHA512Type_digest_impl(SHAobject *self) -/*[clinic end generated code: output=be8de024b232977e input=60c2cede9e023018]*/ +/*[clinic end generated code: output=1080bbeeef7dde1b input=60c2cede9e023018]*/ { unsigned char digest[SHA_DIGESTSIZE]; SHAobject temp; @@ -549,27 +515,9 @@ Return the digest value as a string of hexadecimal digits. [clinic start generated code]*/ -PyDoc_STRVAR(SHA512Type_hexdigest__doc__, -"hexdigest($self, /)\n" -"--\n" -"\n" -"Return the digest value as a string of hexadecimal digits."); - -#define SHA512TYPE_HEXDIGEST_METHODDEF \ - {"hexdigest", (PyCFunction)SHA512Type_hexdigest, METH_NOARGS, SHA512Type_hexdigest__doc__}, - -static PyObject * -SHA512Type_hexdigest_impl(SHAobject *self); - -static PyObject * -SHA512Type_hexdigest(SHAobject *self, PyObject *Py_UNUSED(ignored)) -{ - return SHA512Type_hexdigest_impl(self); -} - static PyObject * SHA512Type_hexdigest_impl(SHAobject *self) -/*[clinic end generated code: output=28a4ab2f9a1781b8 input=498b877b25cbe0a2]*/ +/*[clinic end generated code: output=7373305b8601e18b input=498b877b25cbe0a2]*/ { unsigned char digest[SHA_DIGESTSIZE]; SHAobject temp; @@ -610,18 +558,9 @@ Update this hash object's state with the provided string. [clinic start generated code]*/ -PyDoc_STRVAR(SHA512Type_update__doc__, -"update($self, obj, /)\n" -"--\n" -"\n" -"Update this hash object\'s state with the provided string."); - -#define SHA512TYPE_UPDATE_METHODDEF \ - {"update", (PyCFunction)SHA512Type_update, METH_O, SHA512Type_update__doc__}, - static PyObject * SHA512Type_update(SHAobject *self, PyObject *obj) -/*[clinic end generated code: output=6be574cdc3a9c52d input=ded2b46656566283]*/ +/*[clinic end generated code: output=1cf333e73995a79e input=ded2b46656566283]*/ { Py_buffer buf; @@ -636,23 +575,7 @@ /*[clinic input] dump buffer [clinic start generated code]*/ - -#ifndef SHA512TYPE_COPY_METHODDEF - #define SHA512TYPE_COPY_METHODDEF -#endif /* !defined(SHA512TYPE_COPY_METHODDEF) */ - -#ifndef SHA512TYPE_DIGEST_METHODDEF - #define SHA512TYPE_DIGEST_METHODDEF -#endif /* !defined(SHA512TYPE_DIGEST_METHODDEF) */ - -#ifndef SHA512TYPE_HEXDIGEST_METHODDEF - #define SHA512TYPE_HEXDIGEST_METHODDEF -#endif /* !defined(SHA512TYPE_HEXDIGEST_METHODDEF) */ - -#ifndef SHA512TYPE_UPDATE_METHODDEF - #define SHA512TYPE_UPDATE_METHODDEF -#endif /* !defined(SHA512TYPE_UPDATE_METHODDEF) */ -/*[clinic end generated code: output=de713947d31130e9 input=524ce2e021e4eba6]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=524ce2e021e4eba6]*/ static PyMethodDef SHA_methods[] = { SHA512TYPE_COPY_METHODDEF @@ -773,38 +696,9 @@ Return a new SHA-512 hash object; optionally initialized with a string. [clinic start generated code]*/ -PyDoc_STRVAR(_sha512_sha512__doc__, -"sha512($module, /, string=b\'\')\n" -"--\n" -"\n" -"Return a new SHA-512 hash object; optionally initialized with a string."); - -#define _SHA512_SHA512_METHODDEF \ - {"sha512", (PyCFunction)_sha512_sha512, METH_VARARGS|METH_KEYWORDS, _sha512_sha512__doc__}, - -static PyObject * -_sha512_sha512_impl(PyModuleDef *module, PyObject *string); - -static PyObject * -_sha512_sha512(PyModuleDef *module, PyObject *args, PyObject *kwargs) -{ - PyObject *return_value = NULL; - static char *_keywords[] = {"string", NULL}; - PyObject *string = NULL; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "|O:sha512", _keywords, - &string)) - goto exit; - return_value = _sha512_sha512_impl(module, string); - -exit: - return return_value; -} - static PyObject * _sha512_sha512_impl(PyModuleDef *module, PyObject *string) -/*[clinic end generated code: output=9e39b11115f36878 input=e69bad9ae9b6a308]*/ +/*[clinic end generated code: output=da13bc0a94da6de3 input=e69bad9ae9b6a308]*/ { SHAobject *new; Py_buffer buf; @@ -842,38 +736,9 @@ Return a new SHA-384 hash object; optionally initialized with a string. [clinic start generated code]*/ -PyDoc_STRVAR(_sha512_sha384__doc__, -"sha384($module, /, string=b\'\')\n" -"--\n" -"\n" -"Return a new SHA-384 hash object; optionally initialized with a string."); - -#define _SHA512_SHA384_METHODDEF \ - {"sha384", (PyCFunction)_sha512_sha384, METH_VARARGS|METH_KEYWORDS, _sha512_sha384__doc__}, - -static PyObject * -_sha512_sha384_impl(PyModuleDef *module, PyObject *string); - -static PyObject * -_sha512_sha384(PyModuleDef *module, PyObject *args, PyObject *kwargs) -{ - PyObject *return_value = NULL; - static char *_keywords[] = {"string", NULL}; - PyObject *string = NULL; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "|O:sha384", _keywords, - &string)) - goto exit; - return_value = _sha512_sha384_impl(module, string); - -exit: - return return_value; -} - static PyObject * _sha512_sha384_impl(PyModuleDef *module, PyObject *string) -/*[clinic end generated code: output=397c6fba3525b93a input=c9327788d4ea4545]*/ +/*[clinic end generated code: output=ac731aea5509174d input=c9327788d4ea4545]*/ { SHAobject *new; Py_buffer buf; @@ -907,15 +772,7 @@ /*[clinic input] dump buffer [clinic start generated code]*/ - -#ifndef _SHA512_SHA512_METHODDEF - #define _SHA512_SHA512_METHODDEF -#endif /* !defined(_SHA512_SHA512_METHODDEF) */ - -#ifndef _SHA512_SHA384_METHODDEF - #define _SHA512_SHA384_METHODDEF -#endif /* !defined(_SHA512_SHA384_METHODDEF) */ -/*[clinic end generated code: output=69d84aa9445b01d8 input=524ce2e021e4eba6]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=524ce2e021e4eba6]*/ /* List of functions exported by this module */ diff --git a/Modules/spwdmodule.c b/Modules/spwdmodule.c --- a/Modules/spwdmodule.c +++ b/Modules/spwdmodule.c @@ -13,10 +13,9 @@ #include "clinic/spwdmodule.c.h" /*[clinic input] -output preset file module spwd [clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=b3464a3667278fae]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=c0b841b90a6a07ce]*/ PyDoc_STRVAR(spwd__doc__, "This module provides access to the Unix shadow password database.\n\ diff --git a/Modules/unicodedata.c b/Modules/unicodedata.c --- a/Modules/unicodedata.c +++ b/Modules/unicodedata.c @@ -73,6 +73,8 @@ Py_UCS4 (*normalization)(Py_UCS4); } PreviousDBVersion; +#include "clinic/unicodedata.c.h" + #define get_old_record(self, v) ((((PreviousDBVersion*)self)->getrecord)(v)) static PyMemberDef DB_members[] = { @@ -130,42 +132,9 @@ not given, ValueError is raised. [clinic start generated code]*/ -PyDoc_STRVAR(unicodedata_UCD_decimal__doc__, -"decimal($self, unichr, default=None, /)\n" -"--\n" -"\n" -"Converts a Unicode character into its equivalent decimal value.\n" -"\n" -"Returns the decimal value assigned to the Unicode character unichr\n" -"as integer. If no such value is defined, default is returned, or, if\n" -"not given, ValueError is raised."); - -#define UNICODEDATA_UCD_DECIMAL_METHODDEF \ - {"decimal", (PyCFunction)unicodedata_UCD_decimal, METH_VARARGS, unicodedata_UCD_decimal__doc__}, - -static PyObject * -unicodedata_UCD_decimal_impl(PreviousDBVersion *self, PyUnicodeObject *unichr, PyObject *default_value); - -static PyObject * -unicodedata_UCD_decimal(PreviousDBVersion *self, PyObject *args) -{ - PyObject *return_value = NULL; - PyUnicodeObject *unichr; - PyObject *default_value = NULL; - - if (!PyArg_ParseTuple(args, - "O!|O:decimal", - &PyUnicode_Type, &unichr, &default_value)) - goto exit; - return_value = unicodedata_UCD_decimal_impl(self, unichr, default_value); - -exit: - return return_value; -} - static PyObject * unicodedata_UCD_decimal_impl(PreviousDBVersion *self, PyUnicodeObject *unichr, PyObject *default_value) -/*[clinic end generated code: output=8689669896d293df input=c25c9d2b4de076b1]*/ +/*[clinic end generated code: output=d285215533b58b28 input=c25c9d2b4de076b1]*/ { int have_old = 0; long rc; diff --git a/Modules/zlibmodule.c b/Modules/zlibmodule.c --- a/Modules/zlibmodule.c +++ b/Modules/zlibmodule.c @@ -82,12 +82,11 @@ } /*[clinic input] -output preset file module zlib class zlib.Compress "compobject *" "&Comptype" class zlib.Decompress "compobject *" "&Decomptype" [clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=bfd4c340573ba91d]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=093935115c3e3158]*/ static compobject * newcompobject(PyTypeObject *type) diff --git a/Objects/bytearrayobject.c b/Objects/bytearrayobject.c --- a/Objects/bytearrayobject.c +++ b/Objects/bytearrayobject.c @@ -90,6 +90,8 @@ return 1; } +#include "clinic/bytearrayobject.c.h" + /* Direct API functions */ PyObject * @@ -1266,27 +1268,9 @@ Remove all items from the bytearray. [clinic start generated code]*/ -PyDoc_STRVAR(bytearray_clear__doc__, -"clear($self, /)\n" -"--\n" -"\n" -"Remove all items from the bytearray."); - -#define BYTEARRAY_CLEAR_METHODDEF \ - {"clear", (PyCFunction)bytearray_clear, METH_NOARGS, bytearray_clear__doc__}, - -static PyObject * -bytearray_clear_impl(PyByteArrayObject *self); - -static PyObject * -bytearray_clear(PyByteArrayObject *self, PyObject *Py_UNUSED(ignored)) -{ - return bytearray_clear_impl(self); -} - static PyObject * bytearray_clear_impl(PyByteArrayObject *self) -/*[clinic end generated code: output=5344093031e2f36c input=e524fd330abcdc18]*/ +/*[clinic end generated code: output=85c2fe6aede0956c input=e524fd330abcdc18]*/ { if (PyByteArray_Resize((PyObject *)self, 0) < 0) return NULL; @@ -1301,27 +1285,9 @@ Return a copy of B. [clinic start generated code]*/ -PyDoc_STRVAR(bytearray_copy__doc__, -"copy($self, /)\n" -"--\n" -"\n" -"Return a copy of B."); - -#define BYTEARRAY_COPY_METHODDEF \ - {"copy", (PyCFunction)bytearray_copy, METH_NOARGS, bytearray_copy__doc__}, - -static PyObject * -bytearray_copy_impl(PyByteArrayObject *self); - -static PyObject * -bytearray_copy(PyByteArrayObject *self, PyObject *Py_UNUSED(ignored)) -{ - return bytearray_copy_impl(self); -} - static PyObject * bytearray_copy_impl(PyByteArrayObject *self) -/*[clinic end generated code: output=8788ed299f7f2214 input=6d5d2975aa0f33f3]*/ +/*[clinic end generated code: output=68cfbcfed484c132 input=6d5d2975aa0f33f3]*/ { return PyByteArray_FromStringAndSize(PyByteArray_AS_STRING((PyObject *)self), PyByteArray_GET_SIZE(self)); @@ -1557,53 +1523,9 @@ The remaining characters are mapped through the given translation table. [clinic start generated code]*/ -PyDoc_STRVAR(bytearray_translate__doc__, -"translate(table, [deletechars])\n" -"Return a copy with each character mapped by the given translation table.\n" -"\n" -" table\n" -" Translation table, which must be a bytes object of length 256.\n" -"\n" -"All characters occurring in the optional argument deletechars are removed.\n" -"The remaining characters are mapped through the given translation table."); - -#define BYTEARRAY_TRANSLATE_METHODDEF \ - {"translate", (PyCFunction)bytearray_translate, METH_VARARGS, bytearray_translate__doc__}, - -static PyObject * -bytearray_translate_impl(PyByteArrayObject *self, PyObject *table, int group_right_1, PyObject *deletechars); - -static PyObject * -bytearray_translate(PyByteArrayObject *self, PyObject *args) -{ - PyObject *return_value = NULL; - PyObject *table; - int group_right_1 = 0; - PyObject *deletechars = NULL; - - switch (PyTuple_GET_SIZE(args)) { - case 1: - if (!PyArg_ParseTuple(args, "O:translate", &table)) - goto exit; - break; - case 2: - if (!PyArg_ParseTuple(args, "OO:translate", &table, &deletechars)) - goto exit; - group_right_1 = 1; - break; - default: - PyErr_SetString(PyExc_TypeError, "bytearray.translate requires 1 to 2 arguments"); - goto exit; - } - return_value = bytearray_translate_impl(self, table, group_right_1, deletechars); - -exit: - return return_value; -} - static PyObject * bytearray_translate_impl(PyByteArrayObject *self, PyObject *table, int group_right_1, PyObject *deletechars) -/*[clinic end generated code: output=a709df81d41db4b7 input=b749ad85f4860824]*/ +/*[clinic end generated code: output=fa3ea4f9a8d58bc7 input=b749ad85f4860824]*/ { char *input, *output; const char *table_chars; @@ -1708,50 +1630,9 @@ The bytes objects frm and to must be of the same length. [clinic start generated code]*/ -PyDoc_STRVAR(bytearray_maketrans__doc__, -"maketrans(frm, to, /)\n" -"--\n" -"\n" -"Return a translation table useable for the bytes or bytearray translate method.\n" -"\n" -"The returned table will be one where each byte in frm is mapped to the byte at\n" -"the same position in to.\n" -"\n" -"The bytes objects frm and to must be of the same length."); - -#define BYTEARRAY_MAKETRANS_METHODDEF \ - {"maketrans", (PyCFunction)bytearray_maketrans, METH_VARARGS|METH_STATIC, bytearray_maketrans__doc__}, - -static PyObject * -bytearray_maketrans_impl(Py_buffer *frm, Py_buffer *to); - -static PyObject * -bytearray_maketrans(void *null, PyObject *args) -{ - PyObject *return_value = NULL; - Py_buffer frm = {NULL, NULL}; - Py_buffer to = {NULL, NULL}; - - if (!PyArg_ParseTuple(args, - "y*y*:maketrans", - &frm, &to)) - goto exit; - return_value = bytearray_maketrans_impl(&frm, &to); - -exit: - /* Cleanup for frm */ - if (frm.obj) - PyBuffer_Release(&frm); - /* Cleanup for to */ - if (to.obj) - PyBuffer_Release(&to); - - return return_value; -} - static PyObject * bytearray_maketrans_impl(Py_buffer *frm, Py_buffer *to) -/*[clinic end generated code: output=d332622814c26f4b input=5925a81d2fbbf151]*/ +/*[clinic end generated code: output=1df267d99f56b15e input=5925a81d2fbbf151]*/ { return _Py_bytes_maketrans(frm, to); } @@ -2260,53 +2141,9 @@ replaced. [clinic start generated code]*/ -PyDoc_STRVAR(bytearray_replace__doc__, -"replace($self, old, new, count=-1, /)\n" -"--\n" -"\n" -"Return a copy with all occurrences of substring old replaced by new.\n" -"\n" -" count\n" -" Maximum number of occurrences to replace.\n" -" -1 (the default value) means replace all occurrences.\n" -"\n" -"If the optional argument count is given, only the first count occurrences are\n" -"replaced."); - -#define BYTEARRAY_REPLACE_METHODDEF \ - {"replace", (PyCFunction)bytearray_replace, METH_VARARGS, bytearray_replace__doc__}, - -static PyObject * -bytearray_replace_impl(PyByteArrayObject *self, Py_buffer *old, Py_buffer *new, Py_ssize_t count); - -static PyObject * -bytearray_replace(PyByteArrayObject *self, PyObject *args) -{ - PyObject *return_value = NULL; - Py_buffer old = {NULL, NULL}; - Py_buffer new = {NULL, NULL}; - Py_ssize_t count = -1; - - if (!PyArg_ParseTuple(args, - "y*y*|n:replace", - &old, &new, &count)) - goto exit; - return_value = bytearray_replace_impl(self, &old, &new, count); - -exit: - /* Cleanup for old */ - if (old.obj) - PyBuffer_Release(&old); - /* Cleanup for new */ - if (new.obj) - PyBuffer_Release(&new); - - return return_value; -} - static PyObject * bytearray_replace_impl(PyByteArrayObject *self, Py_buffer *old, Py_buffer *new, Py_ssize_t count) -/*[clinic end generated code: output=9997fbbd5bac4883 input=aa379d988637c7fb]*/ +/*[clinic end generated code: output=3fc105c8232d7b3f input=aa379d988637c7fb]*/ { return (PyObject *)replace((PyByteArrayObject *) self, old->buf, old->len, @@ -2327,47 +2164,9 @@ Return a list of the sections in the bytearray, using sep as the delimiter. [clinic start generated code]*/ -PyDoc_STRVAR(bytearray_split__doc__, -"split($self, /, sep=None, maxsplit=-1)\n" -"--\n" -"\n" -"Return a list of the sections in the bytearray, using sep as the delimiter.\n" -"\n" -" sep\n" -" The delimiter according which to split the bytearray.\n" -" None (the default value) means split on ASCII whitespace characters\n" -" (space, tab, return, newline, formfeed, vertical tab).\n" -" maxsplit\n" -" Maximum number of splits to do.\n" -" -1 (the default value) means no limit."); - -#define BYTEARRAY_SPLIT_METHODDEF \ - {"split", (PyCFunction)bytearray_split, METH_VARARGS|METH_KEYWORDS, bytearray_split__doc__}, - -static PyObject * -bytearray_split_impl(PyByteArrayObject *self, PyObject *sep, Py_ssize_t maxsplit); - -static PyObject * -bytearray_split(PyByteArrayObject *self, PyObject *args, PyObject *kwargs) -{ - PyObject *return_value = NULL; - static char *_keywords[] = {"sep", "maxsplit", NULL}; - PyObject *sep = Py_None; - Py_ssize_t maxsplit = -1; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "|On:split", _keywords, - &sep, &maxsplit)) - goto exit; - return_value = bytearray_split_impl(self, sep, maxsplit); - -exit: - return return_value; -} - static PyObject * bytearray_split_impl(PyByteArrayObject *self, PyObject *sep, Py_ssize_t maxsplit) -/*[clinic end generated code: output=062a3d87d6f918fa input=24f82669f41bf523]*/ +/*[clinic end generated code: output=cdccf5a29dbf7eb5 input=24f82669f41bf523]*/ { Py_ssize_t len = PyByteArray_GET_SIZE(self), n; const char *s = PyByteArray_AS_STRING(self), *sub; @@ -2409,25 +2208,9 @@ bytearray object and two empty bytearray objects. [clinic start generated code]*/ -PyDoc_STRVAR(bytearray_partition__doc__, -"partition($self, sep, /)\n" -"--\n" -"\n" -"Partition the bytearray into three parts using the given separator.\n" -"\n" -"This will search for the separator sep in the bytearray. If the separator is\n" -"found, returns a 3-tuple containing the part before the separator, the\n" -"separator itself, and the part after it.\n" -"\n" -"If the separator is not found, returns a 3-tuple containing the original\n" -"bytearray object and two empty bytearray objects."); - -#define BYTEARRAY_PARTITION_METHODDEF \ - {"partition", (PyCFunction)bytearray_partition, METH_O, bytearray_partition__doc__}, - static PyObject * bytearray_partition(PyByteArrayObject *self, PyObject *sep) -/*[clinic end generated code: output=2645138221fe6f4d input=7d7fe37b1696d506]*/ +/*[clinic end generated code: output=45d2525ddd35f957 input=7d7fe37b1696d506]*/ { PyObject *bytesep, *result; @@ -2463,25 +2246,9 @@ objects and the original bytearray object. [clinic start generated code]*/ -PyDoc_STRVAR(bytearray_rpartition__doc__, -"rpartition($self, sep, /)\n" -"--\n" -"\n" -"Partition the bytes into three parts using the given separator.\n" -"\n" -"This will search for the separator sep in the bytearray, starting and the end.\n" -"If the separator is found, returns a 3-tuple containing the part before the\n" -"separator, the separator itself, and the part after it.\n" -"\n" -"If the separator is not found, returns a 3-tuple containing two empty bytearray\n" -"objects and the original bytearray object."); - -#define BYTEARRAY_RPARTITION_METHODDEF \ - {"rpartition", (PyCFunction)bytearray_rpartition, METH_O, bytearray_rpartition__doc__}, - static PyObject * bytearray_rpartition(PyByteArrayObject *self, PyObject *sep) -/*[clinic end generated code: output=ed13e54605d007de input=9b8cd540c1b75853]*/ +/*[clinic end generated code: output=440de3c9426115e8 input=9b8cd540c1b75853]*/ { PyObject *bytesep, *result; @@ -2508,49 +2275,9 @@ Splitting is done starting at the end of the bytearray and working to the front. [clinic start generated code]*/ -PyDoc_STRVAR(bytearray_rsplit__doc__, -"rsplit($self, /, sep=None, maxsplit=-1)\n" -"--\n" -"\n" -"Return a list of the sections in the bytearray, using sep as the delimiter.\n" -"\n" -" sep\n" -" The delimiter according which to split the bytearray.\n" -" None (the default value) means split on ASCII whitespace characters\n" -" (space, tab, return, newline, formfeed, vertical tab).\n" -" maxsplit\n" -" Maximum number of splits to do.\n" -" -1 (the default value) means no limit.\n" -"\n" -"Splitting is done starting at the end of the bytearray and working to the front."); - -#define BYTEARRAY_RSPLIT_METHODDEF \ - {"rsplit", (PyCFunction)bytearray_rsplit, METH_VARARGS|METH_KEYWORDS, bytearray_rsplit__doc__}, - -static PyObject * -bytearray_rsplit_impl(PyByteArrayObject *self, PyObject *sep, Py_ssize_t maxsplit); - -static PyObject * -bytearray_rsplit(PyByteArrayObject *self, PyObject *args, PyObject *kwargs) -{ - PyObject *return_value = NULL; - static char *_keywords[] = {"sep", "maxsplit", NULL}; - PyObject *sep = Py_None; - Py_ssize_t maxsplit = -1; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "|On:rsplit", _keywords, - &sep, &maxsplit)) - goto exit; - return_value = bytearray_rsplit_impl(self, sep, maxsplit); - -exit: - return return_value; -} - static PyObject * bytearray_rsplit_impl(PyByteArrayObject *self, PyObject *sep, Py_ssize_t maxsplit) -/*[clinic end generated code: output=affaf9fc2aae8d41 input=a68286e4dd692ffe]*/ +/*[clinic end generated code: output=4d648cf3ac65c9e9 input=a68286e4dd692ffe]*/ { Py_ssize_t len = PyByteArray_GET_SIZE(self), n; const char *s = PyByteArray_AS_STRING(self), *sub; @@ -2583,27 +2310,9 @@ Reverse the order of the values in B in place. [clinic start generated code]*/ -PyDoc_STRVAR(bytearray_reverse__doc__, -"reverse($self, /)\n" -"--\n" -"\n" -"Reverse the order of the values in B in place."); - -#define BYTEARRAY_REVERSE_METHODDEF \ - {"reverse", (PyCFunction)bytearray_reverse, METH_NOARGS, bytearray_reverse__doc__}, - -static PyObject * -bytearray_reverse_impl(PyByteArrayObject *self); - -static PyObject * -bytearray_reverse(PyByteArrayObject *self, PyObject *Py_UNUSED(ignored)) -{ - return bytearray_reverse_impl(self); -} - static PyObject * bytearray_reverse_impl(PyByteArrayObject *self) -/*[clinic end generated code: output=5d5e5f0bfc67f476 input=7933a499b8597bd1]*/ +/*[clinic end generated code: output=9f7616f29ab309d3 input=7933a499b8597bd1]*/ { char swap, *head, *tail; Py_ssize_t i, j, n = Py_SIZE(self); @@ -2642,43 +2351,9 @@ Insert a single item into the bytearray before the given index. [clinic start generated code]*/ -PyDoc_STRVAR(bytearray_insert__doc__, -"insert($self, index, item, /)\n" -"--\n" -"\n" -"Insert a single item into the bytearray before the given index.\n" -"\n" -" index\n" -" The index where the value is to be inserted.\n" -" item\n" -" The item to be inserted."); - -#define BYTEARRAY_INSERT_METHODDEF \ - {"insert", (PyCFunction)bytearray_insert, METH_VARARGS, bytearray_insert__doc__}, - -static PyObject * -bytearray_insert_impl(PyByteArrayObject *self, Py_ssize_t index, int item); - -static PyObject * -bytearray_insert(PyByteArrayObject *self, PyObject *args) -{ - PyObject *return_value = NULL; - Py_ssize_t index; - int item; - - if (!PyArg_ParseTuple(args, - "nO&:insert", - &index, _getbytevalue, &item)) - goto exit; - return_value = bytearray_insert_impl(self, index, item); - -exit: - return return_value; -} - static PyObject * bytearray_insert_impl(PyByteArrayObject *self, Py_ssize_t index, int item) -/*[clinic end generated code: output=5ec9340d4ad19080 input=833766836ba30e1e]*/ +/*[clinic end generated code: output=76c775a70e7b07b7 input=833766836ba30e1e]*/ { Py_ssize_t n = Py_SIZE(self); char *buf; @@ -2716,40 +2391,9 @@ Append a single item to the end of the bytearray. [clinic start generated code]*/ -PyDoc_STRVAR(bytearray_append__doc__, -"append($self, item, /)\n" -"--\n" -"\n" -"Append a single item to the end of the bytearray.\n" -"\n" -" item\n" -" The item to be appended."); - -#define BYTEARRAY_APPEND_METHODDEF \ - {"append", (PyCFunction)bytearray_append, METH_VARARGS, bytearray_append__doc__}, - -static PyObject * -bytearray_append_impl(PyByteArrayObject *self, int item); - -static PyObject * -bytearray_append(PyByteArrayObject *self, PyObject *args) -{ - PyObject *return_value = NULL; - int item; - - if (!PyArg_ParseTuple(args, - "O&:append", - _getbytevalue, &item)) - goto exit; - return_value = bytearray_append_impl(self, item); - -exit: - return return_value; -} - static PyObject * bytearray_append_impl(PyByteArrayObject *self, int item) -/*[clinic end generated code: output=b5b3325bb3bbaf85 input=ae56ea87380407cc]*/ +/*[clinic end generated code: output=a154e19ed1886cb6 input=ae56ea87380407cc]*/ { Py_ssize_t n = Py_SIZE(self); @@ -2777,21 +2421,9 @@ Append all the items from the iterator or sequence to the end of the bytearray. [clinic start generated code]*/ -PyDoc_STRVAR(bytearray_extend__doc__, -"extend($self, iterable_of_ints, /)\n" -"--\n" -"\n" -"Append all the items from the iterator or sequence to the end of the bytearray.\n" -"\n" -" iterable_of_ints\n" -" The iterable of items to append."); - -#define BYTEARRAY_EXTEND_METHODDEF \ - {"extend", (PyCFunction)bytearray_extend, METH_O, bytearray_extend__doc__}, - static PyObject * bytearray_extend(PyByteArrayObject *self, PyObject *iterable_of_ints) -/*[clinic end generated code: output=13b0c13ad5110dfb input=ce83a5d75b70d850]*/ +/*[clinic end generated code: output=98155dbe249170b1 input=ce83a5d75b70d850]*/ { PyObject *it, *item, *bytearray_obj; Py_ssize_t buf_size = 0, len = 0; @@ -2877,43 +2509,9 @@ If no index argument is given, will pop the last item. [clinic start generated code]*/ -PyDoc_STRVAR(bytearray_pop__doc__, -"pop($self, index=-1, /)\n" -"--\n" -"\n" -"Remove and return a single item from B.\n" -"\n" -" index\n" -" The index from where to remove the item.\n" -" -1 (the default value) means remove the last item.\n" -"\n" -"If no index argument is given, will pop the last item."); - -#define BYTEARRAY_POP_METHODDEF \ - {"pop", (PyCFunction)bytearray_pop, METH_VARARGS, bytearray_pop__doc__}, - -static PyObject * -bytearray_pop_impl(PyByteArrayObject *self, Py_ssize_t index); - -static PyObject * -bytearray_pop(PyByteArrayObject *self, PyObject *args) -{ - PyObject *return_value = NULL; - Py_ssize_t index = -1; - - if (!PyArg_ParseTuple(args, - "|n:pop", - &index)) - goto exit; - return_value = bytearray_pop_impl(self, index); - -exit: - return return_value; -} - static PyObject * bytearray_pop_impl(PyByteArrayObject *self, Py_ssize_t index) -/*[clinic end generated code: output=3b763e548e79af96 input=0797e6c0ca9d5a85]*/ +/*[clinic end generated code: output=e0ccd401f8021da8 input=0797e6c0ca9d5a85]*/ { int value; Py_ssize_t n = Py_SIZE(self); @@ -2953,40 +2551,9 @@ Remove the first occurrence of a value in the bytearray. [clinic start generated code]*/ -PyDoc_STRVAR(bytearray_remove__doc__, -"remove($self, value, /)\n" -"--\n" -"\n" -"Remove the first occurrence of a value in the bytearray.\n" -"\n" -" value\n" -" The value to remove."); - -#define BYTEARRAY_REMOVE_METHODDEF \ - {"remove", (PyCFunction)bytearray_remove, METH_VARARGS, bytearray_remove__doc__}, - -static PyObject * -bytearray_remove_impl(PyByteArrayObject *self, int value); - -static PyObject * -bytearray_remove(PyByteArrayObject *self, PyObject *args) -{ - PyObject *return_value = NULL; - int value; - - if (!PyArg_ParseTuple(args, - "O&:remove", - _getbytevalue, &value)) - goto exit; - return_value = bytearray_remove_impl(self, value); - -exit: - return return_value; -} - static PyObject * bytearray_remove_impl(PyByteArrayObject *self, int value) -/*[clinic end generated code: output=c71c8bcf4703abfc input=47560b11fd856c24]*/ +/*[clinic end generated code: output=d659e37866709c13 input=47560b11fd856c24]*/ { Py_ssize_t where, n = Py_SIZE(self); char *buf = PyByteArray_AS_STRING(self); @@ -3042,39 +2609,9 @@ If the argument is omitted or None, strip leading and trailing ASCII whitespace. [clinic start generated code]*/ -PyDoc_STRVAR(bytearray_strip__doc__, -"strip($self, bytes=None, /)\n" -"--\n" -"\n" -"Strip leading and trailing bytes contained in the argument.\n" -"\n" -"If the argument is omitted or None, strip leading and trailing ASCII whitespace."); - -#define BYTEARRAY_STRIP_METHODDEF \ - {"strip", (PyCFunction)bytearray_strip, METH_VARARGS, bytearray_strip__doc__}, - -static PyObject * -bytearray_strip_impl(PyByteArrayObject *self, PyObject *bytes); - -static PyObject * -bytearray_strip(PyByteArrayObject *self, PyObject *args) -{ - PyObject *return_value = NULL; - PyObject *bytes = Py_None; - - if (!PyArg_UnpackTuple(args, "strip", - 0, 1, - &bytes)) - goto exit; - return_value = bytearray_strip_impl(self, bytes); - -exit: - return return_value; -} - static PyObject * bytearray_strip_impl(PyByteArrayObject *self, PyObject *bytes) -/*[clinic end generated code: output=2e3d3358acc4c235 input=ef7bb59b09c21d62]*/ +/*[clinic end generated code: output=760412661a34ad5a input=ef7bb59b09c21d62]*/ { Py_ssize_t left, right, mysize, byteslen; char *myptr, *bytesptr; @@ -3113,39 +2650,9 @@ If the argument is omitted or None, strip leading ASCII whitespace. [clinic start generated code]*/ -PyDoc_STRVAR(bytearray_lstrip__doc__, -"lstrip($self, bytes=None, /)\n" -"--\n" -"\n" -"Strip leading bytes contained in the argument.\n" -"\n" -"If the argument is omitted or None, strip leading ASCII whitespace."); - -#define BYTEARRAY_LSTRIP_METHODDEF \ - {"lstrip", (PyCFunction)bytearray_lstrip, METH_VARARGS, bytearray_lstrip__doc__}, - -static PyObject * -bytearray_lstrip_impl(PyByteArrayObject *self, PyObject *bytes); - -static PyObject * -bytearray_lstrip(PyByteArrayObject *self, PyObject *args) -{ - PyObject *return_value = NULL; - PyObject *bytes = Py_None; - - if (!PyArg_UnpackTuple(args, "lstrip", - 0, 1, - &bytes)) - goto exit; - return_value = bytearray_lstrip_impl(self, bytes); - -exit: - return return_value; -} - static PyObject * bytearray_lstrip_impl(PyByteArrayObject *self, PyObject *bytes) -/*[clinic end generated code: output=2599309808a9ec02 input=80843f975dd7c480]*/ +/*[clinic end generated code: output=d005c9d0ab909e66 input=80843f975dd7c480]*/ { Py_ssize_t left, right, mysize, byteslen; char *myptr, *bytesptr; @@ -3181,39 +2688,9 @@ If the argument is omitted or None, strip trailing ASCII whitespace. [clinic start generated code]*/ -PyDoc_STRVAR(bytearray_rstrip__doc__, -"rstrip($self, bytes=None, /)\n" -"--\n" -"\n" -"Strip trailing bytes contained in the argument.\n" -"\n" -"If the argument is omitted or None, strip trailing ASCII whitespace."); - -#define BYTEARRAY_RSTRIP_METHODDEF \ - {"rstrip", (PyCFunction)bytearray_rstrip, METH_VARARGS, bytearray_rstrip__doc__}, - -static PyObject * -bytearray_rstrip_impl(PyByteArrayObject *self, PyObject *bytes); - -static PyObject * -bytearray_rstrip(PyByteArrayObject *self, PyObject *args) -{ - PyObject *return_value = NULL; - PyObject *bytes = Py_None; - - if (!PyArg_UnpackTuple(args, "rstrip", - 0, 1, - &bytes)) - goto exit; - return_value = bytearray_rstrip_impl(self, bytes); - -exit: - return return_value; -} - static PyObject * bytearray_rstrip_impl(PyByteArrayObject *self, PyObject *bytes) -/*[clinic end generated code: output=b5ca6259f4f4f2a3 input=e728b994954cfd91]*/ +/*[clinic end generated code: output=030e2fbd2f7276bd input=e728b994954cfd91]*/ { Py_ssize_t right, mysize, byteslen; char *myptr, *bytesptr; @@ -3252,48 +2729,9 @@ Decode the bytearray using the codec registered for encoding. [clinic start generated code]*/ -PyDoc_STRVAR(bytearray_decode__doc__, -"decode($self, /, encoding=\'utf-8\', errors=\'strict\')\n" -"--\n" -"\n" -"Decode the bytearray using the codec registered for encoding.\n" -"\n" -" encoding\n" -" The encoding with which to decode the bytearray.\n" -" errors\n" -" The error handling scheme to use for the handling of decoding errors.\n" -" The default is \'strict\' meaning that decoding errors raise a\n" -" UnicodeDecodeError. Other possible values are \'ignore\' and \'replace\'\n" -" as well as any other name registered with codecs.register_error that\n" -" can handle UnicodeDecodeErrors."); - -#define BYTEARRAY_DECODE_METHODDEF \ - {"decode", (PyCFunction)bytearray_decode, METH_VARARGS|METH_KEYWORDS, bytearray_decode__doc__}, - -static PyObject * -bytearray_decode_impl(PyByteArrayObject *self, const char *encoding, const char *errors); - -static PyObject * -bytearray_decode(PyByteArrayObject *self, PyObject *args, PyObject *kwargs) -{ - PyObject *return_value = NULL; - static char *_keywords[] = {"encoding", "errors", NULL}; - const char *encoding = NULL; - const char *errors = NULL; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "|ss:decode", _keywords, - &encoding, &errors)) - goto exit; - return_value = bytearray_decode_impl(self, encoding, errors); - -exit: - return return_value; -} - static PyObject * bytearray_decode_impl(PyByteArrayObject *self, const char *encoding, const char *errors) -/*[clinic end generated code: output=38b83681f1e38a6c input=f28d8f903020257b]*/ +/*[clinic end generated code: output=7e64e2cc91573b26 input=f28d8f903020257b]*/ { if (encoding == NULL) encoding = PyUnicode_GetDefaultEncoding(); @@ -3324,22 +2762,9 @@ The result is returned as a new bytearray object. [clinic start generated code]*/ -PyDoc_STRVAR(bytearray_join__doc__, -"join($self, iterable_of_bytes, /)\n" -"--\n" -"\n" -"Concatenate any number of bytes/bytearray objects.\n" -"\n" -"The bytearray whose method is called is inserted in between each pair.\n" -"\n" -"The result is returned as a new bytearray object."); - -#define BYTEARRAY_JOIN_METHODDEF \ - {"join", (PyCFunction)bytearray_join, METH_O, bytearray_join__doc__}, - static PyObject * bytearray_join(PyByteArrayObject *self, PyObject *iterable_of_bytes) -/*[clinic end generated code: output=544e7430032dfdf4 input=aba6b1f9b30fcb8e]*/ +/*[clinic end generated code: output=a8516370bf68ae08 input=aba6b1f9b30fcb8e]*/ { return stringlib_bytes_join((PyObject*)self, iterable_of_bytes); } @@ -3355,41 +2780,9 @@ true. [clinic start generated code]*/ -PyDoc_STRVAR(bytearray_splitlines__doc__, -"splitlines($self, /, keepends=False)\n" -"--\n" -"\n" -"Return a list of the lines in the bytearray, breaking at line boundaries.\n" -"\n" -"Line breaks are not included in the resulting list unless keepends is given and\n" -"true."); - -#define BYTEARRAY_SPLITLINES_METHODDEF \ - {"splitlines", (PyCFunction)bytearray_splitlines, METH_VARARGS|METH_KEYWORDS, bytearray_splitlines__doc__}, - -static PyObject * -bytearray_splitlines_impl(PyByteArrayObject *self, int keepends); - -static PyObject * -bytearray_splitlines(PyByteArrayObject *self, PyObject *args, PyObject *kwargs) -{ - PyObject *return_value = NULL; - static char *_keywords[] = {"keepends", NULL}; - int keepends = 0; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "|i:splitlines", _keywords, - &keepends)) - goto exit; - return_value = bytearray_splitlines_impl(self, keepends); - -exit: - return return_value; -} - static PyObject * bytearray_splitlines_impl(PyByteArrayObject *self, int keepends) -/*[clinic end generated code: output=a837fd0512ad46ff input=36f0b25bc792f6c0]*/ +/*[clinic end generated code: output=4223c94b895f6ad9 input=36f0b25bc792f6c0]*/ { return stringlib_splitlines( (PyObject*) self, PyByteArray_AS_STRING(self), @@ -3427,40 +2820,9 @@ Example: bytearray.fromhex('B9 01EF') -> bytearray(b'\\xb9\\x01\\xef') [clinic start generated code]*/ -PyDoc_STRVAR(bytearray_fromhex__doc__, -"fromhex($type, string, /)\n" -"--\n" -"\n" -"Create a bytearray object from a string of hexadecimal numbers.\n" -"\n" -"Spaces between two numbers are accepted.\n" -"Example: bytearray.fromhex(\'B9 01EF\') -> bytearray(b\'\\\\xb9\\\\x01\\\\xef\')"); - -#define BYTEARRAY_FROMHEX_METHODDEF \ - {"fromhex", (PyCFunction)bytearray_fromhex, METH_VARARGS|METH_CLASS, bytearray_fromhex__doc__}, - -static PyObject * -bytearray_fromhex_impl(PyObject*cls, PyObject *string); - -static PyObject * -bytearray_fromhex(PyTypeObject *cls, PyObject *args) -{ - PyObject *return_value = NULL; - PyObject *string; - - if (!PyArg_ParseTuple(args, - "U:fromhex", - &string)) - goto exit; - return_value = bytearray_fromhex_impl((PyObject*)cls, string); - -exit: - return return_value; -} - static PyObject * bytearray_fromhex_impl(PyObject*cls, PyObject *string) -/*[clinic end generated code: output=adc3c804a74e56d4 input=907bbd2d34d9367a]*/ +/*[clinic end generated code: output=df3da60129b3700c input=907bbd2d34d9367a]*/ { PyObject *newbytes; char *buf; @@ -3550,27 +2912,9 @@ Return state information for pickling. [clinic start generated code]*/ -PyDoc_STRVAR(bytearray_reduce__doc__, -"__reduce__($self, /)\n" -"--\n" -"\n" -"Return state information for pickling."); - -#define BYTEARRAY_REDUCE_METHODDEF \ - {"__reduce__", (PyCFunction)bytearray_reduce, METH_NOARGS, bytearray_reduce__doc__}, - -static PyObject * -bytearray_reduce_impl(PyByteArrayObject *self); - -static PyObject * -bytearray_reduce(PyByteArrayObject *self, PyObject *Py_UNUSED(ignored)) -{ - return bytearray_reduce_impl(self); -} - static PyObject * bytearray_reduce_impl(PyByteArrayObject *self) -/*[clinic end generated code: output=b1b56fe87bf30fb0 input=fbb07de4d102a03a]*/ +/*[clinic end generated code: output=52bf304086464cab input=fbb07de4d102a03a]*/ { return _common_reduce(self, 2); } @@ -3585,37 +2929,9 @@ Return state information for pickling. [clinic start generated code]*/ -PyDoc_STRVAR(bytearray_reduce_ex__doc__, -"__reduce_ex__($self, proto=0, /)\n" -"--\n" -"\n" -"Return state information for pickling."); - -#define BYTEARRAY_REDUCE_EX_METHODDEF \ - {"__reduce_ex__", (PyCFunction)bytearray_reduce_ex, METH_VARARGS, bytearray_reduce_ex__doc__}, - -static PyObject * -bytearray_reduce_ex_impl(PyByteArrayObject *self, int proto); - -static PyObject * -bytearray_reduce_ex(PyByteArrayObject *self, PyObject *args) -{ - PyObject *return_value = NULL; - int proto = 0; - - if (!PyArg_ParseTuple(args, - "|i:__reduce_ex__", - &proto)) - goto exit; - return_value = bytearray_reduce_ex_impl(self, proto); - -exit: - return return_value; -} - static PyObject * bytearray_reduce_ex_impl(PyByteArrayObject *self, int proto) -/*[clinic end generated code: output=bbd9afb2f5953dc1 input=0e091a42ca6dbd91]*/ +/*[clinic end generated code: output=52eac33377197520 input=0e091a42ca6dbd91]*/ { return _common_reduce(self, proto); } @@ -3628,27 +2944,9 @@ Returns the size of the bytearray object in memory, in bytes. [clinic start generated code]*/ -PyDoc_STRVAR(bytearray_sizeof__doc__, -"__sizeof__($self, /)\n" -"--\n" -"\n" -"Returns the size of the bytearray object in memory, in bytes."); - -#define BYTEARRAY_SIZEOF_METHODDEF \ - {"__sizeof__", (PyCFunction)bytearray_sizeof, METH_NOARGS, bytearray_sizeof__doc__}, - -static PyObject * -bytearray_sizeof_impl(PyByteArrayObject *self); - -static PyObject * -bytearray_sizeof(PyByteArrayObject *self, PyObject *Py_UNUSED(ignored)) -{ - return bytearray_sizeof_impl(self); -} - static PyObject * bytearray_sizeof_impl(PyByteArrayObject *self) -/*[clinic end generated code: output=4a2254b0a85630c6 input=6b23d305362b462b]*/ +/*[clinic end generated code: output=738abdd17951c427 input=6b23d305362b462b]*/ { Py_ssize_t res; diff --git a/Objects/bytesobject.c b/Objects/bytesobject.c --- a/Objects/bytesobject.c +++ b/Objects/bytesobject.c @@ -12,6 +12,8 @@ [clinic start generated code]*/ /*[clinic end generated code: output=da39a3ee5e6b4b0d input=1a1d9102afc1b00c]*/ +#include "clinic/bytesobject.c.h" + #ifdef COUNT_ALLOCS Py_ssize_t null_strings, one_strings; #endif @@ -1614,47 +1616,9 @@ Return a list of the sections in the bytes, using sep as the delimiter. [clinic start generated code]*/ -PyDoc_STRVAR(bytes_split__doc__, -"split($self, /, sep=None, maxsplit=-1)\n" -"--\n" -"\n" -"Return a list of the sections in the bytes, using sep as the delimiter.\n" -"\n" -" sep\n" -" The delimiter according which to split the bytes.\n" -" None (the default value) means split on ASCII whitespace characters\n" -" (space, tab, return, newline, formfeed, vertical tab).\n" -" maxsplit\n" -" Maximum number of splits to do.\n" -" -1 (the default value) means no limit."); - -#define BYTES_SPLIT_METHODDEF \ - {"split", (PyCFunction)bytes_split, METH_VARARGS|METH_KEYWORDS, bytes_split__doc__}, - -static PyObject * -bytes_split_impl(PyBytesObject*self, PyObject *sep, Py_ssize_t maxsplit); - -static PyObject * -bytes_split(PyBytesObject*self, PyObject *args, PyObject *kwargs) -{ - PyObject *return_value = NULL; - static char *_keywords[] = {"sep", "maxsplit", NULL}; - PyObject *sep = Py_None; - Py_ssize_t maxsplit = -1; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "|On:split", _keywords, - &sep, &maxsplit)) - goto exit; - return_value = bytes_split_impl(self, sep, maxsplit); - -exit: - return return_value; -} - static PyObject * bytes_split_impl(PyBytesObject*self, PyObject *sep, Py_ssize_t maxsplit) -/*[clinic end generated code: output=c80a47afdd505975 input=8b809b39074abbfa]*/ +/*[clinic end generated code: output=8bde44dacb36ef2e input=8b809b39074abbfa]*/ { Py_ssize_t len = PyBytes_GET_SIZE(self), n; const char *s = PyBytes_AS_STRING(self), *sub; @@ -1692,48 +1656,9 @@ object and two empty bytes objects. [clinic start generated code]*/ -PyDoc_STRVAR(bytes_partition__doc__, -"partition($self, sep, /)\n" -"--\n" -"\n" -"Partition the bytes into three parts using the given separator.\n" -"\n" -"This will search for the separator sep in the bytes. If the separator is found,\n" -"returns a 3-tuple containing the part before the separator, the separator\n" -"itself, and the part after it.\n" -"\n" -"If the separator is not found, returns a 3-tuple containing the original bytes\n" -"object and two empty bytes objects."); - -#define BYTES_PARTITION_METHODDEF \ - {"partition", (PyCFunction)bytes_partition, METH_VARARGS, bytes_partition__doc__}, - -static PyObject * -bytes_partition_impl(PyBytesObject *self, Py_buffer *sep); - -static PyObject * -bytes_partition(PyBytesObject *self, PyObject *args) -{ - PyObject *return_value = NULL; - Py_buffer sep = {NULL, NULL}; - - if (!PyArg_ParseTuple(args, - "y*:partition", - &sep)) - goto exit; - return_value = bytes_partition_impl(self, &sep); - -exit: - /* Cleanup for sep */ - if (sep.obj) - PyBuffer_Release(&sep); - - return return_value; -} - static PyObject * bytes_partition_impl(PyBytesObject *self, Py_buffer *sep) -/*[clinic end generated code: output=3006727cfbf83aa4 input=bc855dc63ca949de]*/ +/*[clinic end generated code: output=f532b392a17ff695 input=bc855dc63ca949de]*/ { return stringlib_partition( (PyObject*) self, @@ -1759,48 +1684,9 @@ objects and the original bytes object. [clinic start generated code]*/ -PyDoc_STRVAR(bytes_rpartition__doc__, -"rpartition($self, sep, /)\n" -"--\n" -"\n" -"Partition the bytes into three parts using the given separator.\n" -"\n" -"This will search for the separator sep in the bytes, starting and the end. If\n" -"the separator is found, returns a 3-tuple containing the part before the\n" -"separator, the separator itself, and the part after it.\n" -"\n" -"If the separator is not found, returns a 3-tuple containing two empty bytes\n" -"objects and the original bytes object."); - -#define BYTES_RPARTITION_METHODDEF \ - {"rpartition", (PyCFunction)bytes_rpartition, METH_VARARGS, bytes_rpartition__doc__}, - -static PyObject * -bytes_rpartition_impl(PyBytesObject *self, Py_buffer *sep); - -static PyObject * -bytes_rpartition(PyBytesObject *self, PyObject *args) -{ - PyObject *return_value = NULL; - Py_buffer sep = {NULL, NULL}; - - if (!PyArg_ParseTuple(args, - "y*:rpartition", - &sep)) - goto exit; - return_value = bytes_rpartition_impl(self, &sep); - -exit: - /* Cleanup for sep */ - if (sep.obj) - PyBuffer_Release(&sep); - - return return_value; -} - static PyObject * bytes_rpartition_impl(PyBytesObject *self, Py_buffer *sep) -/*[clinic end generated code: output=57b169dc47fa90e8 input=6588fff262a9170e]*/ +/*[clinic end generated code: output=191b114cbb028e50 input=6588fff262a9170e]*/ { return stringlib_rpartition( (PyObject*) self, @@ -1817,49 +1703,9 @@ Splitting is done starting at the end of the bytes and working to the front. [clinic start generated code]*/ -PyDoc_STRVAR(bytes_rsplit__doc__, -"rsplit($self, /, sep=None, maxsplit=-1)\n" -"--\n" -"\n" -"Return a list of the sections in the bytes, using sep as the delimiter.\n" -"\n" -" sep\n" -" The delimiter according which to split the bytes.\n" -" None (the default value) means split on ASCII whitespace characters\n" -" (space, tab, return, newline, formfeed, vertical tab).\n" -" maxsplit\n" -" Maximum number of splits to do.\n" -" -1 (the default value) means no limit.\n" -"\n" -"Splitting is done starting at the end of the bytes and working to the front."); - -#define BYTES_RSPLIT_METHODDEF \ - {"rsplit", (PyCFunction)bytes_rsplit, METH_VARARGS|METH_KEYWORDS, bytes_rsplit__doc__}, - -static PyObject * -bytes_rsplit_impl(PyBytesObject*self, PyObject *sep, Py_ssize_t maxsplit); - -static PyObject * -bytes_rsplit(PyBytesObject*self, PyObject *args, PyObject *kwargs) -{ - PyObject *return_value = NULL; - static char *_keywords[] = {"sep", "maxsplit", NULL}; - PyObject *sep = Py_None; - Py_ssize_t maxsplit = -1; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "|On:rsplit", _keywords, - &sep, &maxsplit)) - goto exit; - return_value = bytes_rsplit_impl(self, sep, maxsplit); - -exit: - return return_value; -} - static PyObject * bytes_rsplit_impl(PyBytesObject*self, PyObject *sep, Py_ssize_t maxsplit) -/*[clinic end generated code: output=f86feddedbd7b26d input=0f86c9f28f7d7b7b]*/ +/*[clinic end generated code: output=0b6570b977911d88 input=0f86c9f28f7d7b7b]*/ { Py_ssize_t len = PyBytes_GET_SIZE(self), n; const char *s = PyBytes_AS_STRING(self), *sub; @@ -1896,24 +1742,9 @@ Example: b'.'.join([b'ab', b'pq', b'rs']) -> b'ab.pq.rs'. [clinic start generated code]*/ -PyDoc_STRVAR(bytes_join__doc__, -"join($self, iterable_of_bytes, /)\n" -"--\n" -"\n" -"Concatenate any number of bytes objects.\n" -"\n" -"The bytes whose method is called is inserted in between each pair.\n" -"\n" -"The result is returned as a new bytes object.\n" -"\n" -"Example: b\'.\'.join([b\'ab\', b\'pq\', b\'rs\']) -> b\'ab.pq.rs\'."); - -#define BYTES_JOIN_METHODDEF \ - {"join", (PyCFunction)bytes_join, METH_O, bytes_join__doc__}, - static PyObject * bytes_join(PyBytesObject*self, PyObject *iterable_of_bytes) -/*[clinic end generated code: output=e541a14a8da97908 input=7fe377b95bd549d2]*/ +/*[clinic end generated code: output=634aff14764ff997 input=7fe377b95bd549d2]*/ { return stringlib_bytes_join((PyObject*)self, iterable_of_bytes); } @@ -2170,39 +2001,9 @@ If the argument is omitted or None, strip leading and trailing ASCII whitespace. [clinic start generated code]*/ -PyDoc_STRVAR(bytes_strip__doc__, -"strip($self, bytes=None, /)\n" -"--\n" -"\n" -"Strip leading and trailing bytes contained in the argument.\n" -"\n" -"If the argument is omitted or None, strip leading and trailing ASCII whitespace."); - -#define BYTES_STRIP_METHODDEF \ - {"strip", (PyCFunction)bytes_strip, METH_VARARGS, bytes_strip__doc__}, - -static PyObject * -bytes_strip_impl(PyBytesObject *self, PyObject *bytes); - -static PyObject * -bytes_strip(PyBytesObject *self, PyObject *args) -{ - PyObject *return_value = NULL; - PyObject *bytes = Py_None; - - if (!PyArg_UnpackTuple(args, "strip", - 0, 1, - &bytes)) - goto exit; - return_value = bytes_strip_impl(self, bytes); - -exit: - return return_value; -} - static PyObject * bytes_strip_impl(PyBytesObject *self, PyObject *bytes) -/*[clinic end generated code: output=c8234a599ba5ec35 input=37daa5fad1395d95]*/ +/*[clinic end generated code: output=c7c228d3bd104a1b input=37daa5fad1395d95]*/ { return do_argstrip(self, BOTHSTRIP, bytes); } @@ -2219,39 +2020,9 @@ If the argument is omitted or None, strip leading ASCII whitespace. [clinic start generated code]*/ -PyDoc_STRVAR(bytes_lstrip__doc__, -"lstrip($self, bytes=None, /)\n" -"--\n" -"\n" -"Strip leading bytes contained in the argument.\n" -"\n" -"If the argument is omitted or None, strip leading ASCII whitespace."); - -#define BYTES_LSTRIP_METHODDEF \ - {"lstrip", (PyCFunction)bytes_lstrip, METH_VARARGS, bytes_lstrip__doc__}, - -static PyObject * -bytes_lstrip_impl(PyBytesObject *self, PyObject *bytes); - -static PyObject * -bytes_lstrip(PyBytesObject *self, PyObject *args) -{ - PyObject *return_value = NULL; - PyObject *bytes = Py_None; - - if (!PyArg_UnpackTuple(args, "lstrip", - 0, 1, - &bytes)) - goto exit; - return_value = bytes_lstrip_impl(self, bytes); - -exit: - return return_value; -} - static PyObject * bytes_lstrip_impl(PyBytesObject *self, PyObject *bytes) -/*[clinic end generated code: output=529e8511ab6f1115 input=88811b09dfbc2988]*/ +/*[clinic end generated code: output=28602e586f524e82 input=88811b09dfbc2988]*/ { return do_argstrip(self, LEFTSTRIP, bytes); } @@ -2268,39 +2039,9 @@ If the argument is omitted or None, strip trailing ASCII whitespace. [clinic start generated code]*/ -PyDoc_STRVAR(bytes_rstrip__doc__, -"rstrip($self, bytes=None, /)\n" -"--\n" -"\n" -"Strip trailing bytes contained in the argument.\n" -"\n" -"If the argument is omitted or None, strip trailing ASCII whitespace."); - -#define BYTES_RSTRIP_METHODDEF \ - {"rstrip", (PyCFunction)bytes_rstrip, METH_VARARGS, bytes_rstrip__doc__}, - -static PyObject * -bytes_rstrip_impl(PyBytesObject *self, PyObject *bytes); - -static PyObject * -bytes_rstrip(PyBytesObject *self, PyObject *args) -{ - PyObject *return_value = NULL; - PyObject *bytes = Py_None; - - if (!PyArg_UnpackTuple(args, "rstrip", - 0, 1, - &bytes)) - goto exit; - return_value = bytes_rstrip_impl(self, bytes); - -exit: - return return_value; -} - static PyObject * bytes_rstrip_impl(PyBytesObject *self, PyObject *bytes) -/*[clinic end generated code: output=e98730bd133e6593 input=8f93c9cd361f0140]*/ +/*[clinic end generated code: output=547e3815c95447da input=8f93c9cd361f0140]*/ { return do_argstrip(self, RIGHTSTRIP, bytes); } @@ -2371,53 +2112,9 @@ The remaining characters are mapped through the given translation table. [clinic start generated code]*/ -PyDoc_STRVAR(bytes_translate__doc__, -"translate(table, [deletechars])\n" -"Return a copy with each character mapped by the given translation table.\n" -"\n" -" table\n" -" Translation table, which must be a bytes object of length 256.\n" -"\n" -"All characters occurring in the optional argument deletechars are removed.\n" -"The remaining characters are mapped through the given translation table."); - -#define BYTES_TRANSLATE_METHODDEF \ - {"translate", (PyCFunction)bytes_translate, METH_VARARGS, bytes_translate__doc__}, - -static PyObject * -bytes_translate_impl(PyBytesObject *self, PyObject *table, int group_right_1, PyObject *deletechars); - -static PyObject * -bytes_translate(PyBytesObject *self, PyObject *args) -{ - PyObject *return_value = NULL; - PyObject *table; - int group_right_1 = 0; - PyObject *deletechars = NULL; - - switch (PyTuple_GET_SIZE(args)) { - case 1: - if (!PyArg_ParseTuple(args, "O:translate", &table)) - goto exit; - break; - case 2: - if (!PyArg_ParseTuple(args, "OO:translate", &table, &deletechars)) - goto exit; - group_right_1 = 1; - break; - default: - PyErr_SetString(PyExc_TypeError, "bytes.translate requires 1 to 2 arguments"); - goto exit; - } - return_value = bytes_translate_impl(self, table, group_right_1, deletechars); - -exit: - return return_value; -} - static PyObject * bytes_translate_impl(PyBytesObject *self, PyObject *table, int group_right_1, PyObject *deletechars) -/*[clinic end generated code: output=f0f29a57f41df5d8 input=d8fa5519d7cc4be7]*/ +/*[clinic end generated code: output=0ddd2cef4f4918f2 input=d8fa5519d7cc4be7]*/ { char *input, *output; Py_buffer table_view = {NULL, NULL}; @@ -2547,50 +2244,9 @@ The bytes objects frm and to must be of the same length. [clinic start generated code]*/ -PyDoc_STRVAR(bytes_maketrans__doc__, -"maketrans(frm, to, /)\n" -"--\n" -"\n" -"Return a translation table useable for the bytes or bytearray translate method.\n" -"\n" -"The returned table will be one where each byte in frm is mapped to the byte at\n" -"the same position in to.\n" -"\n" -"The bytes objects frm and to must be of the same length."); - -#define BYTES_MAKETRANS_METHODDEF \ - {"maketrans", (PyCFunction)bytes_maketrans, METH_VARARGS|METH_STATIC, bytes_maketrans__doc__}, - -static PyObject * -bytes_maketrans_impl(Py_buffer *frm, Py_buffer *to); - -static PyObject * -bytes_maketrans(void *null, PyObject *args) -{ - PyObject *return_value = NULL; - Py_buffer frm = {NULL, NULL}; - Py_buffer to = {NULL, NULL}; - - if (!PyArg_ParseTuple(args, - "y*y*:maketrans", - &frm, &to)) - goto exit; - return_value = bytes_maketrans_impl(&frm, &to); - -exit: - /* Cleanup for frm */ - if (frm.obj) - PyBuffer_Release(&frm); - /* Cleanup for to */ - if (to.obj) - PyBuffer_Release(&to); - - return return_value; -} - static PyObject * bytes_maketrans_impl(Py_buffer *frm, Py_buffer *to) -/*[clinic end generated code: output=7df47390c476ac60 input=de7a8fc5632bb8f1]*/ +/*[clinic end generated code: output=a36f6399d4b77f6f input=de7a8fc5632bb8f1]*/ { return _Py_bytes_maketrans(frm, to); } @@ -3104,53 +2760,9 @@ replaced. [clinic start generated code]*/ -PyDoc_STRVAR(bytes_replace__doc__, -"replace($self, old, new, count=-1, /)\n" -"--\n" -"\n" -"Return a copy with all occurrences of substring old replaced by new.\n" -"\n" -" count\n" -" Maximum number of occurrences to replace.\n" -" -1 (the default value) means replace all occurrences.\n" -"\n" -"If the optional argument count is given, only the first count occurrences are\n" -"replaced."); - -#define BYTES_REPLACE_METHODDEF \ - {"replace", (PyCFunction)bytes_replace, METH_VARARGS, bytes_replace__doc__}, - -static PyObject * -bytes_replace_impl(PyBytesObject*self, Py_buffer *old, Py_buffer *new, Py_ssize_t count); - -static PyObject * -bytes_replace(PyBytesObject*self, PyObject *args) -{ - PyObject *return_value = NULL; - Py_buffer old = {NULL, NULL}; - Py_buffer new = {NULL, NULL}; - Py_ssize_t count = -1; - - if (!PyArg_ParseTuple(args, - "y*y*|n:replace", - &old, &new, &count)) - goto exit; - return_value = bytes_replace_impl(self, &old, &new, count); - -exit: - /* Cleanup for old */ - if (old.obj) - PyBuffer_Release(&old); - /* Cleanup for new */ - if (new.obj) - PyBuffer_Release(&new); - - return return_value; -} - static PyObject * bytes_replace_impl(PyBytesObject*self, Py_buffer *old, Py_buffer *new, Py_ssize_t count) -/*[clinic end generated code: output=f07bd9ecf29ee8d8 input=b2fbbf0bf04de8e5]*/ +/*[clinic end generated code: output=3fe052c3c60cffc2 input=b2fbbf0bf04de8e5]*/ { return (PyObject *)replace((PyBytesObject *) self, (const char *)old->buf, old->len, @@ -3316,48 +2928,9 @@ Decode the bytes using the codec registered for encoding. [clinic start generated code]*/ -PyDoc_STRVAR(bytes_decode__doc__, -"decode($self, /, encoding=\'utf-8\', errors=\'strict\')\n" -"--\n" -"\n" -"Decode the bytes using the codec registered for encoding.\n" -"\n" -" encoding\n" -" The encoding with which to decode the bytes.\n" -" errors\n" -" The error handling scheme to use for the handling of decoding errors.\n" -" The default is \'strict\' meaning that decoding errors raise a\n" -" UnicodeDecodeError. Other possible values are \'ignore\' and \'replace\'\n" -" as well as any other name registered with codecs.register_error that\n" -" can handle UnicodeDecodeErrors."); - -#define BYTES_DECODE_METHODDEF \ - {"decode", (PyCFunction)bytes_decode, METH_VARARGS|METH_KEYWORDS, bytes_decode__doc__}, - -static PyObject * -bytes_decode_impl(PyBytesObject*self, const char *encoding, const char *errors); - -static PyObject * -bytes_decode(PyBytesObject*self, PyObject *args, PyObject *kwargs) -{ - PyObject *return_value = NULL; - static char *_keywords[] = {"encoding", "errors", NULL}; - const char *encoding = NULL; - const char *errors = NULL; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "|ss:decode", _keywords, - &encoding, &errors)) - goto exit; - return_value = bytes_decode_impl(self, encoding, errors); - -exit: - return return_value; -} - static PyObject * bytes_decode_impl(PyBytesObject*self, const char *encoding, const char *errors) -/*[clinic end generated code: output=61a80290bbfce696 input=958174769d2a40ca]*/ +/*[clinic end generated code: output=8038751c823b9038 input=958174769d2a40ca]*/ { return PyUnicode_FromEncodedObject((PyObject*)self, encoding, errors); } @@ -3374,41 +2947,9 @@ true. [clinic start generated code]*/ -PyDoc_STRVAR(bytes_splitlines__doc__, -"splitlines($self, /, keepends=False)\n" -"--\n" -"\n" -"Return a list of the lines in the bytes, breaking at line boundaries.\n" -"\n" -"Line breaks are not included in the resulting list unless keepends is given and\n" -"true."); - -#define BYTES_SPLITLINES_METHODDEF \ - {"splitlines", (PyCFunction)bytes_splitlines, METH_VARARGS|METH_KEYWORDS, bytes_splitlines__doc__}, - -static PyObject * -bytes_splitlines_impl(PyBytesObject*self, int keepends); - -static PyObject * -bytes_splitlines(PyBytesObject*self, PyObject *args, PyObject *kwargs) -{ - PyObject *return_value = NULL; - static char *_keywords[] = {"keepends", NULL}; - int keepends = 0; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "|i:splitlines", _keywords, - &keepends)) - goto exit; - return_value = bytes_splitlines_impl(self, keepends); - -exit: - return return_value; -} - static PyObject * bytes_splitlines_impl(PyBytesObject*self, int keepends) -/*[clinic end generated code: output=79da057d05d126de input=ddb93e3351080c8c]*/ +/*[clinic end generated code: output=995c3598f7833cad input=ddb93e3351080c8c]*/ { return stringlib_splitlines( (PyObject*) self, PyBytes_AS_STRING(self), @@ -3445,40 +2986,9 @@ Example: bytes.fromhex('B9 01EF') -> b'\\xb9\\x01\\xef'. [clinic start generated code]*/ -PyDoc_STRVAR(bytes_fromhex__doc__, -"fromhex($type, string, /)\n" -"--\n" -"\n" -"Create a bytes object from a string of hexadecimal numbers.\n" -"\n" -"Spaces between two numbers are accepted.\n" -"Example: bytes.fromhex(\'B9 01EF\') -> b\'\\\\xb9\\\\x01\\\\xef\'."); - -#define BYTES_FROMHEX_METHODDEF \ - {"fromhex", (PyCFunction)bytes_fromhex, METH_VARARGS|METH_CLASS, bytes_fromhex__doc__}, - -static PyObject * -bytes_fromhex_impl(PyTypeObject *type, PyObject *string); - -static PyObject * -bytes_fromhex(PyTypeObject *type, PyObject *args) -{ - PyObject *return_value = NULL; - PyObject *string; - - if (!PyArg_ParseTuple(args, - "U:fromhex", - &string)) - goto exit; - return_value = bytes_fromhex_impl(type, string); - -exit: - return return_value; -} - static PyObject * bytes_fromhex_impl(PyTypeObject *type, PyObject *string) -/*[clinic end generated code: output=09e6cbef56cbbb65 input=bf4d1c361670acd3]*/ +/*[clinic end generated code: output=0973acc63661bb2e input=bf4d1c361670acd3]*/ { PyObject *newstring; char *buf; diff --git a/Objects/bytearrayobject.c b/Objects/clinic/bytearrayobject.c.h copy from Objects/bytearrayobject.c copy to Objects/clinic/bytearrayobject.c.h --- a/Objects/bytearrayobject.c +++ b/Objects/clinic/bytearrayobject.c.h @@ -1,1269 +1,5 @@ -/* PyByteArray (bytearray) implementation */ - -#define PY_SSIZE_T_CLEAN -#include "Python.h" -#include "structmember.h" -#include "bytes_methods.h" -#include "bytesobject.h" - /*[clinic input] -class bytearray "PyByteArrayObject *" "&PyByteArray_Type" -[clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=5535b77c37a119e0]*/ - -char _PyByteArray_empty_string[] = ""; - -void -PyByteArray_Fini(void) -{ -} - -int -PyByteArray_Init(void) -{ - return 1; -} - -/* end nullbytes support */ - -/* Helpers */ - -static int -_getbytevalue(PyObject* arg, int *value) -{ - long face_value; - - if (PyLong_Check(arg)) { - face_value = PyLong_AsLong(arg); - } else { - PyObject *index = PyNumber_Index(arg); - if (index == NULL) { - PyErr_Format(PyExc_TypeError, "an integer is required"); - *value = -1; - return 0; - } - face_value = PyLong_AsLong(index); - Py_DECREF(index); - } - - if (face_value < 0 || face_value >= 256) { - /* this includes the OverflowError in case the long is too large */ - PyErr_SetString(PyExc_ValueError, "byte must be in range(0, 256)"); - *value = -1; - return 0; - } - - *value = face_value; - return 1; -} - -static int -bytearray_getbuffer(PyByteArrayObject *obj, Py_buffer *view, int flags) -{ - void *ptr; - if (view == NULL) { - PyErr_SetString(PyExc_BufferError, - "bytearray_getbuffer: view==NULL argument is obsolete"); - return -1; - } - ptr = (void *) PyByteArray_AS_STRING(obj); - /* cannot fail if view != NULL and readonly == 0 */ - (void)PyBuffer_FillInfo(view, (PyObject*)obj, ptr, Py_SIZE(obj), 0, flags); - obj->ob_exports++; - return 0; -} - -static void -bytearray_releasebuffer(PyByteArrayObject *obj, Py_buffer *view) -{ - obj->ob_exports--; -} - -static int -_canresize(PyByteArrayObject *self) -{ - if (self->ob_exports > 0) { - PyErr_SetString(PyExc_BufferError, - "Existing exports of data: object cannot be re-sized"); - return 0; - } - return 1; -} - -/* Direct API functions */ - -PyObject * -PyByteArray_FromObject(PyObject *input) -{ - return PyObject_CallFunctionObjArgs((PyObject *)&PyByteArray_Type, - input, NULL); -} - -PyObject * -PyByteArray_FromStringAndSize(const char *bytes, Py_ssize_t size) -{ - PyByteArrayObject *new; - Py_ssize_t alloc; - - if (size < 0) { - PyErr_SetString(PyExc_SystemError, - "Negative size passed to PyByteArray_FromStringAndSize"); - return NULL; - } - - /* Prevent buffer overflow when setting alloc to size+1. */ - if (size == PY_SSIZE_T_MAX) { - return PyErr_NoMemory(); - } - - new = PyObject_New(PyByteArrayObject, &PyByteArray_Type); - if (new == NULL) - return NULL; - - if (size == 0) { - new->ob_bytes = NULL; - alloc = 0; - } - else { - alloc = size + 1; - new->ob_bytes = PyObject_Malloc(alloc); - if (new->ob_bytes == NULL) { - Py_DECREF(new); - return PyErr_NoMemory(); - } - if (bytes != NULL && size > 0) - memcpy(new->ob_bytes, bytes, size); - new->ob_bytes[size] = '\0'; /* Trailing null byte */ - } - Py_SIZE(new) = size; - new->ob_alloc = alloc; - new->ob_start = new->ob_bytes; - new->ob_exports = 0; - - return (PyObject *)new; -} - -Py_ssize_t -PyByteArray_Size(PyObject *self) -{ - assert(self != NULL); - assert(PyByteArray_Check(self)); - - return PyByteArray_GET_SIZE(self); -} - -char * -PyByteArray_AsString(PyObject *self) -{ - assert(self != NULL); - assert(PyByteArray_Check(self)); - - return PyByteArray_AS_STRING(self); -} - -int -PyByteArray_Resize(PyObject *self, Py_ssize_t requested_size) -{ - void *sval; - PyByteArrayObject *obj = ((PyByteArrayObject *)self); - /* All computations are done unsigned to avoid integer overflows - (see issue #22335). */ - size_t alloc = (size_t) obj->ob_alloc; - size_t logical_offset = (size_t) (obj->ob_start - obj->ob_bytes); - size_t size = (size_t) requested_size; - - assert(self != NULL); - assert(PyByteArray_Check(self)); - assert(logical_offset <= alloc); - assert(requested_size >= 0); - - if (requested_size == Py_SIZE(self)) { - return 0; - } - if (!_canresize(obj)) { - return -1; - } - - if (size + logical_offset + 1 < alloc) { - /* Current buffer is large enough to host the requested size, - decide on a strategy. */ - if (size < alloc / 2) { - /* Major downsize; resize down to exact size */ - alloc = size + 1; - } - else { - /* Minor downsize; quick exit */ - Py_SIZE(self) = size; - PyByteArray_AS_STRING(self)[size] = '\0'; /* Trailing null */ - return 0; - } - } - else { - /* Need growing, decide on a strategy */ - if (size <= alloc * 1.125) { - /* Moderate upsize; overallocate similar to list_resize() */ - alloc = size + (size >> 3) + (size < 9 ? 3 : 6); - } - else { - /* Major upsize; resize up to exact size */ - alloc = size + 1; - } - } - if (alloc > PY_SSIZE_T_MAX) { - PyErr_NoMemory(); - return -1; - } - - if (logical_offset > 0) { - sval = PyObject_Malloc(alloc); - if (sval == NULL) { - PyErr_NoMemory(); - return -1; - } - memcpy(sval, PyByteArray_AS_STRING(self), - Py_MIN(requested_size, Py_SIZE(self))); - PyObject_Free(obj->ob_bytes); - } - else { - sval = PyObject_Realloc(obj->ob_bytes, alloc); - if (sval == NULL) { - PyErr_NoMemory(); - return -1; - } - } - - obj->ob_bytes = obj->ob_start = sval; - Py_SIZE(self) = size; - obj->ob_alloc = alloc; - obj->ob_bytes[size] = '\0'; /* Trailing null byte */ - - return 0; -} - -PyObject * -PyByteArray_Concat(PyObject *a, PyObject *b) -{ - Py_ssize_t size; - Py_buffer va, vb; - PyByteArrayObject *result = NULL; - - va.len = -1; - vb.len = -1; - if (PyObject_GetBuffer(a, &va, PyBUF_SIMPLE) != 0 || - PyObject_GetBuffer(b, &vb, PyBUF_SIMPLE) != 0) { - PyErr_Format(PyExc_TypeError, "can't concat %.100s to %.100s", - Py_TYPE(a)->tp_name, Py_TYPE(b)->tp_name); - goto done; - } - - size = va.len + vb.len; - if (size < 0) { - PyErr_NoMemory(); - goto done; - } - - result = (PyByteArrayObject *) PyByteArray_FromStringAndSize(NULL, size); - if (result != NULL) { - memcpy(result->ob_bytes, va.buf, va.len); - memcpy(result->ob_bytes + va.len, vb.buf, vb.len); - } - - done: - if (va.len != -1) - PyBuffer_Release(&va); - if (vb.len != -1) - PyBuffer_Release(&vb); - return (PyObject *)result; -} - -static PyObject * -bytearray_format(PyByteArrayObject *self, PyObject *args) -{ - PyObject *bytes_in, *bytes_out, *res; - char *bytestring; - - if (self == NULL || !PyByteArray_Check(self) || args == NULL) { - PyErr_BadInternalCall(); - return NULL; - } - bytestring = PyByteArray_AS_STRING(self); - bytes_in = PyBytes_FromString(bytestring); - if (bytes_in == NULL) - return NULL; - bytes_out = _PyBytes_Format(bytes_in, args); - Py_DECREF(bytes_in); - if (bytes_out == NULL) - return NULL; - res = PyByteArray_FromObject(bytes_out); - Py_DECREF(bytes_out); - if (res == NULL) - return NULL; - return res; -} - -/* Functions stuffed into the type object */ - -static Py_ssize_t -bytearray_length(PyByteArrayObject *self) -{ - return Py_SIZE(self); -} - -static PyObject * -bytearray_iconcat(PyByteArrayObject *self, PyObject *other) -{ - Py_ssize_t mysize; - Py_ssize_t size; - Py_buffer vo; - - if (PyObject_GetBuffer(other, &vo, PyBUF_SIMPLE) != 0) { - PyErr_Format(PyExc_TypeError, "can't concat %.100s to %.100s", - Py_TYPE(other)->tp_name, Py_TYPE(self)->tp_name); - return NULL; - } - - mysize = Py_SIZE(self); - size = mysize + vo.len; - if (size < 0) { - PyBuffer_Release(&vo); - return PyErr_NoMemory(); - } - if (size < self->ob_alloc) { - Py_SIZE(self) = size; - PyByteArray_AS_STRING(self)[Py_SIZE(self)] = '\0'; /* Trailing null byte */ - } - else if (PyByteArray_Resize((PyObject *)self, size) < 0) { - PyBuffer_Release(&vo); - return NULL; - } - memcpy(PyByteArray_AS_STRING(self) + mysize, vo.buf, vo.len); - PyBuffer_Release(&vo); - Py_INCREF(self); - return (PyObject *)self; -} - -static PyObject * -bytearray_repeat(PyByteArrayObject *self, Py_ssize_t count) -{ - PyByteArrayObject *result; - Py_ssize_t mysize; - Py_ssize_t size; - - if (count < 0) - count = 0; - mysize = Py_SIZE(self); - if (count > 0 && mysize > PY_SSIZE_T_MAX / count) - return PyErr_NoMemory(); - size = mysize * count; - result = (PyByteArrayObject *)PyByteArray_FromStringAndSize(NULL, size); - if (result != NULL && size != 0) { - if (mysize == 1) - memset(result->ob_bytes, self->ob_bytes[0], size); - else { - Py_ssize_t i; - for (i = 0; i < count; i++) - memcpy(result->ob_bytes + i*mysize, self->ob_bytes, mysize); - } - } - return (PyObject *)result; -} - -static PyObject * -bytearray_irepeat(PyByteArrayObject *self, Py_ssize_t count) -{ - Py_ssize_t mysize; - Py_ssize_t size; - char *buf; - - if (count < 0) - count = 0; - mysize = Py_SIZE(self); - if (count > 0 && mysize > PY_SSIZE_T_MAX / count) - return PyErr_NoMemory(); - size = mysize * count; - if (PyByteArray_Resize((PyObject *)self, size) < 0) - return NULL; - - buf = PyByteArray_AS_STRING(self); - if (mysize == 1) - memset(buf, buf[0], size); - else { - Py_ssize_t i; - for (i = 1; i < count; i++) - memcpy(buf + i*mysize, buf, mysize); - } - - Py_INCREF(self); - return (PyObject *)self; -} - -static PyObject * -bytearray_getitem(PyByteArrayObject *self, Py_ssize_t i) -{ - if (i < 0) - i += Py_SIZE(self); - if (i < 0 || i >= Py_SIZE(self)) { - PyErr_SetString(PyExc_IndexError, "bytearray index out of range"); - return NULL; - } - return PyLong_FromLong((unsigned char)(PyByteArray_AS_STRING(self)[i])); -} - -static PyObject * -bytearray_subscript(PyByteArrayObject *self, PyObject *index) -{ - if (PyIndex_Check(index)) { - Py_ssize_t i = PyNumber_AsSsize_t(index, PyExc_IndexError); - - if (i == -1 && PyErr_Occurred()) - return NULL; - - if (i < 0) - i += PyByteArray_GET_SIZE(self); - - if (i < 0 || i >= Py_SIZE(self)) { - PyErr_SetString(PyExc_IndexError, "bytearray index out of range"); - return NULL; - } - return PyLong_FromLong((unsigned char)(PyByteArray_AS_STRING(self)[i])); - } - else if (PySlice_Check(index)) { - Py_ssize_t start, stop, step, slicelength, cur, i; - if (PySlice_GetIndicesEx(index, - PyByteArray_GET_SIZE(self), - &start, &stop, &step, &slicelength) < 0) { - return NULL; - } - - if (slicelength <= 0) - return PyByteArray_FromStringAndSize("", 0); - else if (step == 1) { - return PyByteArray_FromStringAndSize( - PyByteArray_AS_STRING(self) + start, slicelength); - } - else { - char *source_buf = PyByteArray_AS_STRING(self); - char *result_buf; - PyObject *result; - - result = PyByteArray_FromStringAndSize(NULL, slicelength); - if (result == NULL) - return NULL; - - result_buf = PyByteArray_AS_STRING(result); - for (cur = start, i = 0; i < slicelength; - cur += step, i++) { - result_buf[i] = source_buf[cur]; - } - return result; - } - } - else { - PyErr_Format(PyExc_TypeError, - "bytearray indices must be integers or slices, not %.200s", - Py_TYPE(index)->tp_name); - return NULL; - } -} - -static int -bytearray_setslice_linear(PyByteArrayObject *self, - Py_ssize_t lo, Py_ssize_t hi, - char *bytes, Py_ssize_t bytes_len) -{ - Py_ssize_t avail = hi - lo; - char *buf = PyByteArray_AS_STRING(self); - Py_ssize_t growth = bytes_len - avail; - int res = 0; - assert(avail >= 0); - - if (growth < 0) { - if (!_canresize(self)) - return -1; - - if (lo == 0) { - /* Shrink the buffer by advancing its logical start */ - self->ob_start -= growth; - /* - 0 lo hi old_size - | |<----avail----->|<-----tail------>| - | |<-bytes_len->|<-----tail------>| - 0 new_lo new_hi new_size - */ - } - else { - /* - 0 lo hi old_size - | |<----avail----->|<-----tomove------>| - | |<-bytes_len->|<-----tomove------>| - 0 lo new_hi new_size - */ - memmove(buf + lo + bytes_len, buf + hi, - Py_SIZE(self) - hi); - } - if (PyByteArray_Resize((PyObject *)self, - Py_SIZE(self) + growth) < 0) { - /* Issue #19578: Handling the memory allocation failure here is - tricky here because the bytearray object has already been - modified. Depending on growth and lo, the behaviour is - different. - - If growth < 0 and lo != 0, the operation is completed, but a - MemoryError is still raised and the memory block is not - shrinked. Otherwise, the bytearray is restored in its previous - state and a MemoryError is raised. */ - if (lo == 0) { - self->ob_start += growth; - return -1; - } - /* memmove() removed bytes, the bytearray object cannot be - restored in its previous state. */ - Py_SIZE(self) += growth; - res = -1; - } - buf = PyByteArray_AS_STRING(self); - } - else if (growth > 0) { - if (Py_SIZE(self) > (Py_ssize_t)PY_SSIZE_T_MAX - growth) { - PyErr_NoMemory(); - return -1; - } - - if (PyByteArray_Resize((PyObject *)self, - Py_SIZE(self) + growth) < 0) { - return -1; - } - buf = PyByteArray_AS_STRING(self); - /* Make the place for the additional bytes */ - /* - 0 lo hi old_size - | |<-avail->|<-----tomove------>| - | |<---bytes_len-->|<-----tomove------>| - 0 lo new_hi new_size - */ - memmove(buf + lo + bytes_len, buf + hi, - Py_SIZE(self) - lo - bytes_len); - } - - if (bytes_len > 0) - memcpy(buf + lo, bytes, bytes_len); - return res; -} - -static int -bytearray_setslice(PyByteArrayObject *self, Py_ssize_t lo, Py_ssize_t hi, - PyObject *values) -{ - Py_ssize_t needed; - void *bytes; - Py_buffer vbytes; - int res = 0; - - vbytes.len = -1; - if (values == (PyObject *)self) { - /* Make a copy and call this function recursively */ - int err; - values = PyByteArray_FromObject(values); - if (values == NULL) - return -1; - err = bytearray_setslice(self, lo, hi, values); - Py_DECREF(values); - return err; - } - if (values == NULL) { - /* del b[lo:hi] */ - bytes = NULL; - needed = 0; - } - else { - if (PyObject_GetBuffer(values, &vbytes, PyBUF_SIMPLE) != 0) { - PyErr_Format(PyExc_TypeError, - "can't set bytearray slice from %.100s", - Py_TYPE(values)->tp_name); - return -1; - } - needed = vbytes.len; - bytes = vbytes.buf; - } - - if (lo < 0) - lo = 0; - if (hi < lo) - hi = lo; - if (hi > Py_SIZE(self)) - hi = Py_SIZE(self); - - res = bytearray_setslice_linear(self, lo, hi, bytes, needed); - if (vbytes.len != -1) - PyBuffer_Release(&vbytes); - return res; -} - -static int -bytearray_setitem(PyByteArrayObject *self, Py_ssize_t i, PyObject *value) -{ - int ival; - - if (i < 0) - i += Py_SIZE(self); - - if (i < 0 || i >= Py_SIZE(self)) { - PyErr_SetString(PyExc_IndexError, "bytearray index out of range"); - return -1; - } - - if (value == NULL) - return bytearray_setslice(self, i, i+1, NULL); - - if (!_getbytevalue(value, &ival)) - return -1; - - PyByteArray_AS_STRING(self)[i] = ival; - return 0; -} - -static int -bytearray_ass_subscript(PyByteArrayObject *self, PyObject *index, PyObject *values) -{ - Py_ssize_t start, stop, step, slicelen, needed; - char *buf, *bytes; - buf = PyByteArray_AS_STRING(self); - - if (PyIndex_Check(index)) { - Py_ssize_t i = PyNumber_AsSsize_t(index, PyExc_IndexError); - - if (i == -1 && PyErr_Occurred()) - return -1; - - if (i < 0) - i += PyByteArray_GET_SIZE(self); - - if (i < 0 || i >= Py_SIZE(self)) { - PyErr_SetString(PyExc_IndexError, "bytearray index out of range"); - return -1; - } - - if (values == NULL) { - /* Fall through to slice assignment */ - start = i; - stop = i + 1; - step = 1; - slicelen = 1; - } - else { - int ival; - if (!_getbytevalue(values, &ival)) - return -1; - buf[i] = (char)ival; - return 0; - } - } - else if (PySlice_Check(index)) { - if (PySlice_GetIndicesEx(index, - PyByteArray_GET_SIZE(self), - &start, &stop, &step, &slicelen) < 0) { - return -1; - } - } - else { - PyErr_Format(PyExc_TypeError, - "bytearray indices must be integers or slices, not %.200s", - Py_TYPE(index)->tp_name); - return -1; - } - - if (values == NULL) { - bytes = NULL; - needed = 0; - } - else if (values == (PyObject *)self || !PyByteArray_Check(values)) { - int err; - if (PyNumber_Check(values) || PyUnicode_Check(values)) { - PyErr_SetString(PyExc_TypeError, - "can assign only bytes, buffers, or iterables " - "of ints in range(0, 256)"); - return -1; - } - /* Make a copy and call this function recursively */ - values = PyByteArray_FromObject(values); - if (values == NULL) - return -1; - err = bytearray_ass_subscript(self, index, values); - Py_DECREF(values); - return err; - } - else { - assert(PyByteArray_Check(values)); - bytes = PyByteArray_AS_STRING(values); - needed = Py_SIZE(values); - } - /* Make sure b[5:2] = ... inserts before 5, not before 2. */ - if ((step < 0 && start < stop) || - (step > 0 && start > stop)) - stop = start; - if (step == 1) { - return bytearray_setslice_linear(self, start, stop, bytes, needed); - } - else { - if (needed == 0) { - /* Delete slice */ - size_t cur; - Py_ssize_t i; - - if (!_canresize(self)) - return -1; - - if (slicelen == 0) - /* Nothing to do here. */ - return 0; - - if (step < 0) { - stop = start + 1; - start = stop + step * (slicelen - 1) - 1; - step = -step; - } - for (cur = start, i = 0; - i < slicelen; cur += step, i++) { - Py_ssize_t lim = step - 1; - - if (cur + step >= (size_t)PyByteArray_GET_SIZE(self)) - lim = PyByteArray_GET_SIZE(self) - cur - 1; - - memmove(buf + cur - i, - buf + cur + 1, lim); - } - /* Move the tail of the bytes, in one chunk */ - cur = start + (size_t)slicelen*step; - if (cur < (size_t)PyByteArray_GET_SIZE(self)) { - memmove(buf + cur - slicelen, - buf + cur, - PyByteArray_GET_SIZE(self) - cur); - } - if (PyByteArray_Resize((PyObject *)self, - PyByteArray_GET_SIZE(self) - slicelen) < 0) - return -1; - - return 0; - } - else { - /* Assign slice */ - Py_ssize_t i; - size_t cur; - - if (needed != slicelen) { - PyErr_Format(PyExc_ValueError, - "attempt to assign bytes of size %zd " - "to extended slice of size %zd", - needed, slicelen); - return -1; - } - for (cur = start, i = 0; i < slicelen; cur += step, i++) - buf[cur] = bytes[i]; - return 0; - } - } -} - -static int -bytearray_init(PyByteArrayObject *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"source", "encoding", "errors", 0}; - PyObject *arg = NULL; - const char *encoding = NULL; - const char *errors = NULL; - Py_ssize_t count; - PyObject *it; - PyObject *(*iternext)(PyObject *); - - if (Py_SIZE(self) != 0) { - /* Empty previous contents (yes, do this first of all!) */ - if (PyByteArray_Resize((PyObject *)self, 0) < 0) - return -1; - } - - /* Parse arguments */ - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|Oss:bytearray", kwlist, - &arg, &encoding, &errors)) - return -1; - - /* Make a quick exit if no first argument */ - if (arg == NULL) { - if (encoding != NULL || errors != NULL) { - PyErr_SetString(PyExc_TypeError, - "encoding or errors without sequence argument"); - return -1; - } - return 0; - } - - if (PyUnicode_Check(arg)) { - /* Encode via the codec registry */ - PyObject *encoded, *new; - if (encoding == NULL) { - PyErr_SetString(PyExc_TypeError, - "string argument without an encoding"); - return -1; - } - encoded = PyUnicode_AsEncodedString(arg, encoding, errors); - if (encoded == NULL) - return -1; - assert(PyBytes_Check(encoded)); - new = bytearray_iconcat(self, encoded); - Py_DECREF(encoded); - if (new == NULL) - return -1; - Py_DECREF(new); - return 0; - } - - /* If it's not unicode, there can't be encoding or errors */ - if (encoding != NULL || errors != NULL) { - PyErr_SetString(PyExc_TypeError, - "encoding or errors without a string argument"); - return -1; - } - - /* Is it an int? */ - count = PyNumber_AsSsize_t(arg, PyExc_OverflowError); - if (count == -1 && PyErr_Occurred()) { - if (PyErr_ExceptionMatches(PyExc_OverflowError)) - return -1; - PyErr_Clear(); - } - else if (count < 0) { - PyErr_SetString(PyExc_ValueError, "negative count"); - return -1; - } - else { - if (count > 0) { - if (PyByteArray_Resize((PyObject *)self, count)) - return -1; - memset(PyByteArray_AS_STRING(self), 0, count); - } - return 0; - } - - /* Use the buffer API */ - if (PyObject_CheckBuffer(arg)) { - Py_ssize_t size; - Py_buffer view; - if (PyObject_GetBuffer(arg, &view, PyBUF_FULL_RO) < 0) - return -1; - size = view.len; - if (PyByteArray_Resize((PyObject *)self, size) < 0) goto fail; - if (PyBuffer_ToContiguous(PyByteArray_AS_STRING(self), - &view, size, 'C') < 0) - goto fail; - PyBuffer_Release(&view); - return 0; - fail: - PyBuffer_Release(&view); - return -1; - } - - /* XXX Optimize this if the arguments is a list, tuple */ - - /* Get the iterator */ - it = PyObject_GetIter(arg); - if (it == NULL) - return -1; - iternext = *Py_TYPE(it)->tp_iternext; - - /* Run the iterator to exhaustion */ - for (;;) { - PyObject *item; - int rc, value; - - /* Get the next item */ - item = iternext(it); - if (item == NULL) { - if (PyErr_Occurred()) { - if (!PyErr_ExceptionMatches(PyExc_StopIteration)) - goto error; - PyErr_Clear(); - } - break; - } - - /* Interpret it as an int (__index__) */ - rc = _getbytevalue(item, &value); - Py_DECREF(item); - if (!rc) - goto error; - - /* Append the byte */ - if (Py_SIZE(self) < self->ob_alloc) - Py_SIZE(self)++; - else if (PyByteArray_Resize((PyObject *)self, Py_SIZE(self)+1) < 0) - goto error; - PyByteArray_AS_STRING(self)[Py_SIZE(self)-1] = value; - } - - /* Clean up and return success */ - Py_DECREF(it); - return 0; - - error: - /* Error handling when it != NULL */ - Py_DECREF(it); - return -1; -} - -/* Mostly copied from string_repr, but without the - "smart quote" functionality. */ -static PyObject * -bytearray_repr(PyByteArrayObject *self) -{ - const char *quote_prefix = "bytearray(b"; - const char *quote_postfix = ")"; - Py_ssize_t length = Py_SIZE(self); - /* 15 == strlen(quote_prefix) + 2 + strlen(quote_postfix) + 1 */ - size_t newsize; - PyObject *v; - Py_ssize_t i; - char *bytes; - char c; - char *p; - int quote; - char *test, *start; - char *buffer; - - if (length > (PY_SSIZE_T_MAX - 15) / 4) { - PyErr_SetString(PyExc_OverflowError, - "bytearray object is too large to make repr"); - return NULL; - } - - newsize = 15 + length * 4; - buffer = PyObject_Malloc(newsize); - if (buffer == NULL) { - PyErr_NoMemory(); - return NULL; - } - - /* Figure out which quote to use; single is preferred */ - quote = '\''; - start = PyByteArray_AS_STRING(self); - for (test = start; test < start+length; ++test) { - if (*test == '"') { - quote = '\''; /* back to single */ - break; - } - else if (*test == '\'') - quote = '"'; - } - - p = buffer; - while (*quote_prefix) - *p++ = *quote_prefix++; - *p++ = quote; - - bytes = PyByteArray_AS_STRING(self); - for (i = 0; i < length; i++) { - /* There's at least enough room for a hex escape - and a closing quote. */ - assert(newsize - (p - buffer) >= 5); - c = bytes[i]; - if (c == '\'' || c == '\\') - *p++ = '\\', *p++ = c; - else if (c == '\t') - *p++ = '\\', *p++ = 't'; - else if (c == '\n') - *p++ = '\\', *p++ = 'n'; - else if (c == '\r') - *p++ = '\\', *p++ = 'r'; - else if (c == 0) - *p++ = '\\', *p++ = 'x', *p++ = '0', *p++ = '0'; - else if (c < ' ' || c >= 0x7f) { - *p++ = '\\'; - *p++ = 'x'; - *p++ = Py_hexdigits[(c & 0xf0) >> 4]; - *p++ = Py_hexdigits[c & 0xf]; - } - else - *p++ = c; - } - assert(newsize - (p - buffer) >= 1); - *p++ = quote; - while (*quote_postfix) { - *p++ = *quote_postfix++; - } - - v = PyUnicode_DecodeASCII(buffer, p - buffer, NULL); - PyObject_Free(buffer); - return v; -} - -static PyObject * -bytearray_str(PyObject *op) -{ - if (Py_BytesWarningFlag) { - if (PyErr_WarnEx(PyExc_BytesWarning, - "str() on a bytearray instance", 1)) - return NULL; - } - return bytearray_repr((PyByteArrayObject*)op); -} - -static PyObject * -bytearray_richcompare(PyObject *self, PyObject *other, int op) -{ - Py_ssize_t self_size, other_size; - Py_buffer self_bytes, other_bytes; - PyObject *res; - Py_ssize_t minsize; - int cmp; - - /* Bytes can be compared to anything that supports the (binary) - buffer API. Except that a comparison with Unicode is always an - error, even if the comparison is for equality. */ - if (PyObject_IsInstance(self, (PyObject*)&PyUnicode_Type) || - PyObject_IsInstance(other, (PyObject*)&PyUnicode_Type)) { - if (Py_BytesWarningFlag && (op == Py_EQ || op == Py_NE)) { - if (PyErr_WarnEx(PyExc_BytesWarning, - "Comparison between bytearray and string", 1)) - return NULL; - } - - Py_RETURN_NOTIMPLEMENTED; - } - - if (PyObject_GetBuffer(self, &self_bytes, PyBUF_SIMPLE) != 0) { - PyErr_Clear(); - Py_RETURN_NOTIMPLEMENTED; - } - self_size = self_bytes.len; - - if (PyObject_GetBuffer(other, &other_bytes, PyBUF_SIMPLE) != 0) { - PyErr_Clear(); - PyBuffer_Release(&self_bytes); - Py_RETURN_NOTIMPLEMENTED; - } - other_size = other_bytes.len; - - if (self_size != other_size && (op == Py_EQ || op == Py_NE)) { - /* Shortcut: if the lengths differ, the objects differ */ - cmp = (op == Py_NE); - } - else { - minsize = self_size; - if (other_size < minsize) - minsize = other_size; - - cmp = memcmp(self_bytes.buf, other_bytes.buf, minsize); - /* In ISO C, memcmp() guarantees to use unsigned bytes! */ - - if (cmp == 0) { - if (self_size < other_size) - cmp = -1; - else if (self_size > other_size) - cmp = 1; - } - - switch (op) { - case Py_LT: cmp = cmp < 0; break; - case Py_LE: cmp = cmp <= 0; break; - case Py_EQ: cmp = cmp == 0; break; - case Py_NE: cmp = cmp != 0; break; - case Py_GT: cmp = cmp > 0; break; - case Py_GE: cmp = cmp >= 0; break; - } - } - - res = cmp ? Py_True : Py_False; - PyBuffer_Release(&self_bytes); - PyBuffer_Release(&other_bytes); - Py_INCREF(res); - return res; -} - -static void -bytearray_dealloc(PyByteArrayObject *self) -{ - if (self->ob_exports > 0) { - PyErr_SetString(PyExc_SystemError, - "deallocated bytearray object has exported buffers"); - PyErr_Print(); - } - if (self->ob_bytes != 0) { - PyObject_Free(self->ob_bytes); - } - Py_TYPE(self)->tp_free((PyObject *)self); -} - - -/* -------------------------------------------------------------------- */ -/* Methods */ - -#define FASTSEARCH fastsearch -#define STRINGLIB(F) stringlib_##F -#define STRINGLIB_CHAR char -#define STRINGLIB_SIZEOF_CHAR 1 -#define STRINGLIB_LEN PyByteArray_GET_SIZE -#define STRINGLIB_STR PyByteArray_AS_STRING -#define STRINGLIB_NEW PyByteArray_FromStringAndSize -#define STRINGLIB_ISSPACE Py_ISSPACE -#define STRINGLIB_ISLINEBREAK(x) ((x == '\n') || (x == '\r')) -#define STRINGLIB_CHECK_EXACT PyByteArray_CheckExact -#define STRINGLIB_MUTABLE 1 - -#include "stringlib/fastsearch.h" -#include "stringlib/count.h" -#include "stringlib/find.h" -#include "stringlib/join.h" -#include "stringlib/partition.h" -#include "stringlib/split.h" -#include "stringlib/ctype.h" -#include "stringlib/transmogrify.h" - - -/* The following Py_LOCAL_INLINE and Py_LOCAL functions -were copied from the old char* style string object. */ - -/* helper macro to fixup start/end slice values */ -#define ADJUST_INDICES(start, end, len) \ - if (end > len) \ - end = len; \ - else if (end < 0) { \ - end += len; \ - if (end < 0) \ - end = 0; \ - } \ - if (start < 0) { \ - start += len; \ - if (start < 0) \ - start = 0; \ - } - -Py_LOCAL_INLINE(Py_ssize_t) -bytearray_find_internal(PyByteArrayObject *self, PyObject *args, int dir) -{ - PyObject *subobj; - char byte; - Py_buffer subbuf; - const char *sub; - Py_ssize_t len, sub_len; - Py_ssize_t start=0, end=PY_SSIZE_T_MAX; - Py_ssize_t res; - - if (!stringlib_parse_args_finds_byte("find/rfind/index/rindex", - args, &subobj, &byte, &start, &end)) - return -2; - - if (subobj) { - if (PyObject_GetBuffer(subobj, &subbuf, PyBUF_SIMPLE) != 0) - return -2; - - sub = subbuf.buf; - sub_len = subbuf.len; - } - else { - sub = &byte; - sub_len = 1; - } - len = PyByteArray_GET_SIZE(self); - - ADJUST_INDICES(start, end, len); - if (end - start < sub_len) - res = -1; - /* Issue #23573: FIXME, windows has no memrchr() */ - else if (sub_len == 1 && dir > 0) { - unsigned char needle = *sub; - int mode = (dir > 0) ? FAST_SEARCH : FAST_RSEARCH; - res = stringlib_fastsearch_memchr_1char( - PyByteArray_AS_STRING(self) + start, end - start, - needle, needle, mode); - if (res >= 0) - res += start; - } - else { - if (dir > 0) - res = stringlib_find_slice( - PyByteArray_AS_STRING(self), len, - sub, sub_len, start, end); - else - res = stringlib_rfind_slice( - PyByteArray_AS_STRING(self), len, - sub, sub_len, start, end); - } - - if (subobj) - PyBuffer_Release(&subbuf); - - return res; -} - -PyDoc_STRVAR(find__doc__, -"B.find(sub[, start[, end]]) -> int\n\ -\n\ -Return the lowest index in B where subsection sub is found,\n\ -such that sub is contained within B[start,end]. Optional\n\ -arguments start and end are interpreted as in slice notation.\n\ -\n\ -Return -1 on failure."); - -static PyObject * -bytearray_find(PyByteArrayObject *self, PyObject *args) -{ - Py_ssize_t result = bytearray_find_internal(self, args, +1); - if (result == -2) - return NULL; - return PyLong_FromSsize_t(result); -} - -PyDoc_STRVAR(count__doc__, -"B.count(sub[, start[, end]]) -> int\n\ -\n\ -Return the number of non-overlapping occurrences of subsection sub in\n\ -bytes B[start:end]. Optional arguments start and end are interpreted\n\ -as in slice notation."); - -static PyObject * -bytearray_count(PyByteArrayObject *self, PyObject *args) -{ - PyObject *sub_obj; - const char *str = PyByteArray_AS_STRING(self), *sub; - Py_ssize_t sub_len; - char byte; - Py_ssize_t start = 0, end = PY_SSIZE_T_MAX; - - Py_buffer vsub; - PyObject *count_obj; - - if (!stringlib_parse_args_finds_byte("count", args, &sub_obj, &byte, - &start, &end)) - return NULL; - - if (sub_obj) { - if (PyObject_GetBuffer(sub_obj, &vsub, PyBUF_SIMPLE) != 0) - return NULL; - - sub = vsub.buf; - sub_len = vsub.len; - } - else { - sub = &byte; - sub_len = 1; - } - - ADJUST_INDICES(start, end, PyByteArray_GET_SIZE(self)); - - count_obj = PyLong_FromSsize_t( - stringlib_count(str + start, end - start, sub, sub_len, PY_SSIZE_T_MAX) - ); - - if (sub_obj) - PyBuffer_Release(&vsub); - - return count_obj; -} - -/*[clinic input] -bytearray.clear - - self: self(type="PyByteArrayObject *") - -Remove all items from the bytearray. +preserve [clinic start generated code]*/ PyDoc_STRVAR(bytearray_clear__doc__, @@ -1284,23 +20,6 @@ return bytearray_clear_impl(self); } -static PyObject * -bytearray_clear_impl(PyByteArrayObject *self) -/*[clinic end generated code: output=5344093031e2f36c input=e524fd330abcdc18]*/ -{ - if (PyByteArray_Resize((PyObject *)self, 0) < 0) - return NULL; - Py_RETURN_NONE; -} - -/*[clinic input] -bytearray.copy - - self: self(type="PyByteArrayObject *") - -Return a copy of B. -[clinic start generated code]*/ - PyDoc_STRVAR(bytearray_copy__doc__, "copy($self, /)\n" "--\n" @@ -1319,244 +38,6 @@ return bytearray_copy_impl(self); } -static PyObject * -bytearray_copy_impl(PyByteArrayObject *self) -/*[clinic end generated code: output=8788ed299f7f2214 input=6d5d2975aa0f33f3]*/ -{ - return PyByteArray_FromStringAndSize(PyByteArray_AS_STRING((PyObject *)self), - PyByteArray_GET_SIZE(self)); -} - -PyDoc_STRVAR(index__doc__, -"B.index(sub[, start[, end]]) -> int\n\ -\n\ -Like B.find() but raise ValueError when the subsection is not found."); - -static PyObject * -bytearray_index(PyByteArrayObject *self, PyObject *args) -{ - Py_ssize_t result = bytearray_find_internal(self, args, +1); - if (result == -2) - return NULL; - if (result == -1) { - PyErr_SetString(PyExc_ValueError, - "subsection not found"); - return NULL; - } - return PyLong_FromSsize_t(result); -} - - -PyDoc_STRVAR(rfind__doc__, -"B.rfind(sub[, start[, end]]) -> int\n\ -\n\ -Return the highest index in B where subsection sub is found,\n\ -such that sub is contained within B[start,end]. Optional\n\ -arguments start and end are interpreted as in slice notation.\n\ -\n\ -Return -1 on failure."); - -static PyObject * -bytearray_rfind(PyByteArrayObject *self, PyObject *args) -{ - Py_ssize_t result = bytearray_find_internal(self, args, -1); - if (result == -2) - return NULL; - return PyLong_FromSsize_t(result); -} - - -PyDoc_STRVAR(rindex__doc__, -"B.rindex(sub[, start[, end]]) -> int\n\ -\n\ -Like B.rfind() but raise ValueError when the subsection is not found."); - -static PyObject * -bytearray_rindex(PyByteArrayObject *self, PyObject *args) -{ - Py_ssize_t result = bytearray_find_internal(self, args, -1); - if (result == -2) - return NULL; - if (result == -1) { - PyErr_SetString(PyExc_ValueError, - "subsection not found"); - return NULL; - } - return PyLong_FromSsize_t(result); -} - - -static int -bytearray_contains(PyObject *self, PyObject *arg) -{ - Py_ssize_t ival = PyNumber_AsSsize_t(arg, PyExc_ValueError); - if (ival == -1 && PyErr_Occurred()) { - Py_buffer varg; - Py_ssize_t pos; - PyErr_Clear(); - if (PyObject_GetBuffer(arg, &varg, PyBUF_SIMPLE) != 0) - return -1; - pos = stringlib_find(PyByteArray_AS_STRING(self), Py_SIZE(self), - varg.buf, varg.len, 0); - PyBuffer_Release(&varg); - return pos >= 0; - } - if (ival < 0 || ival >= 256) { - PyErr_SetString(PyExc_ValueError, "byte must be in range(0, 256)"); - return -1; - } - - return memchr(PyByteArray_AS_STRING(self), (int) ival, Py_SIZE(self)) != NULL; -} - - -/* Matches the end (direction >= 0) or start (direction < 0) of self - * against substr, using the start and end arguments. Returns - * -1 on error, 0 if not found and 1 if found. - */ -Py_LOCAL(int) -_bytearray_tailmatch(PyByteArrayObject *self, PyObject *substr, Py_ssize_t start, - Py_ssize_t end, int direction) -{ - Py_ssize_t len = PyByteArray_GET_SIZE(self); - const char* str; - Py_buffer vsubstr; - int rv = 0; - - str = PyByteArray_AS_STRING(self); - - if (PyObject_GetBuffer(substr, &vsubstr, PyBUF_SIMPLE) != 0) - return -1; - - ADJUST_INDICES(start, end, len); - - if (direction < 0) { - /* startswith */ - if (start+vsubstr.len > len) { - goto done; - } - } else { - /* endswith */ - if (end-start < vsubstr.len || start > len) { - goto done; - } - - if (end-vsubstr.len > start) - start = end - vsubstr.len; - } - if (end-start >= vsubstr.len) - rv = ! memcmp(str+start, vsubstr.buf, vsubstr.len); - -done: - PyBuffer_Release(&vsubstr); - return rv; -} - - -PyDoc_STRVAR(startswith__doc__, -"B.startswith(prefix[, start[, end]]) -> bool\n\ -\n\ -Return True if B starts with the specified prefix, False otherwise.\n\ -With optional start, test B beginning at that position.\n\ -With optional end, stop comparing B at that position.\n\ -prefix can also be a tuple of bytes to try."); - -static PyObject * -bytearray_startswith(PyByteArrayObject *self, PyObject *args) -{ - Py_ssize_t start = 0; - Py_ssize_t end = PY_SSIZE_T_MAX; - PyObject *subobj; - int result; - - if (!stringlib_parse_args_finds("startswith", args, &subobj, &start, &end)) - return NULL; - if (PyTuple_Check(subobj)) { - Py_ssize_t i; - for (i = 0; i < PyTuple_GET_SIZE(subobj); i++) { - result = _bytearray_tailmatch(self, - PyTuple_GET_ITEM(subobj, i), - start, end, -1); - if (result == -1) - return NULL; - else if (result) { - Py_RETURN_TRUE; - } - } - Py_RETURN_FALSE; - } - result = _bytearray_tailmatch(self, subobj, start, end, -1); - if (result == -1) { - if (PyErr_ExceptionMatches(PyExc_TypeError)) - PyErr_Format(PyExc_TypeError, "startswith first arg must be bytes " - "or a tuple of bytes, not %s", Py_TYPE(subobj)->tp_name); - return NULL; - } - else - return PyBool_FromLong(result); -} - -PyDoc_STRVAR(endswith__doc__, -"B.endswith(suffix[, start[, end]]) -> bool\n\ -\n\ -Return True if B ends with the specified suffix, False otherwise.\n\ -With optional start, test B beginning at that position.\n\ -With optional end, stop comparing B at that position.\n\ -suffix can also be a tuple of bytes to try."); - -static PyObject * -bytearray_endswith(PyByteArrayObject *self, PyObject *args) -{ - Py_ssize_t start = 0; - Py_ssize_t end = PY_SSIZE_T_MAX; - PyObject *subobj; - int result; - - if (!stringlib_parse_args_finds("endswith", args, &subobj, &start, &end)) - return NULL; - if (PyTuple_Check(subobj)) { - Py_ssize_t i; - for (i = 0; i < PyTuple_GET_SIZE(subobj); i++) { - result = _bytearray_tailmatch(self, - PyTuple_GET_ITEM(subobj, i), - start, end, +1); - if (result == -1) - return NULL; - else if (result) { - Py_RETURN_TRUE; - } - } - Py_RETURN_FALSE; - } - result = _bytearray_tailmatch(self, subobj, start, end, +1); - if (result == -1) { - if (PyErr_ExceptionMatches(PyExc_TypeError)) - PyErr_Format(PyExc_TypeError, "endswith first arg must be bytes or " - "a tuple of bytes, not %s", Py_TYPE(subobj)->tp_name); - return NULL; - } - else - return PyBool_FromLong(result); -} - - -/*[clinic input] -bytearray.translate - - self: self(type="PyByteArrayObject *") - table: object - Translation table, which must be a bytes object of length 256. - [ - deletechars: object - ] - / - -Return a copy with each character mapped by the given translation table. - -All characters occurring in the optional argument deletechars are removed. -The remaining characters are mapped through the given translation table. -[clinic start generated code]*/ - PyDoc_STRVAR(bytearray_translate__doc__, "translate(table, [deletechars])\n" "Return a copy with each character mapped by the given translation table.\n" @@ -1601,113 +82,6 @@ return return_value; } -static PyObject * -bytearray_translate_impl(PyByteArrayObject *self, PyObject *table, int group_right_1, PyObject *deletechars) -/*[clinic end generated code: output=a709df81d41db4b7 input=b749ad85f4860824]*/ -{ - char *input, *output; - const char *table_chars; - Py_ssize_t i, c; - PyObject *input_obj = (PyObject*)self; - const char *output_start; - Py_ssize_t inlen; - PyObject *result = NULL; - int trans_table[256]; - Py_buffer vtable, vdel; - - if (table == Py_None) { - table_chars = NULL; - table = NULL; - } else if (PyObject_GetBuffer(table, &vtable, PyBUF_SIMPLE) != 0) { - return NULL; - } else { - if (vtable.len != 256) { - PyErr_SetString(PyExc_ValueError, - "translation table must be 256 characters long"); - PyBuffer_Release(&vtable); - return NULL; - } - table_chars = (const char*)vtable.buf; - } - - if (deletechars != NULL) { - if (PyObject_GetBuffer(deletechars, &vdel, PyBUF_SIMPLE) != 0) { - if (table != NULL) - PyBuffer_Release(&vtable); - return NULL; - } - } - else { - vdel.buf = NULL; - vdel.len = 0; - } - - inlen = PyByteArray_GET_SIZE(input_obj); - result = PyByteArray_FromStringAndSize((char *)NULL, inlen); - if (result == NULL) - goto done; - output_start = output = PyByteArray_AsString(result); - input = PyByteArray_AS_STRING(input_obj); - - if (vdel.len == 0 && table_chars != NULL) { - /* If no deletions are required, use faster code */ - for (i = inlen; --i >= 0; ) { - c = Py_CHARMASK(*input++); - *output++ = table_chars[c]; - } - goto done; - } - - if (table_chars == NULL) { - for (i = 0; i < 256; i++) - trans_table[i] = Py_CHARMASK(i); - } else { - for (i = 0; i < 256; i++) - trans_table[i] = Py_CHARMASK(table_chars[i]); - } - - for (i = 0; i < vdel.len; i++) - trans_table[(int) Py_CHARMASK( ((unsigned char*)vdel.buf)[i] )] = -1; - - for (i = inlen; --i >= 0; ) { - c = Py_CHARMASK(*input++); - if (trans_table[c] != -1) - if (Py_CHARMASK(*output++ = (char)trans_table[c]) == c) - continue; - } - /* Fix the size of the resulting string */ - if (inlen > 0) - if (PyByteArray_Resize(result, output - output_start) < 0) { - Py_CLEAR(result); - goto done; - } - -done: - if (table != NULL) - PyBuffer_Release(&vtable); - if (deletechars != NULL) - PyBuffer_Release(&vdel); - return result; -} - - -/*[clinic input] - - at staticmethod -bytearray.maketrans - - frm: Py_buffer - to: Py_buffer - / - -Return a translation table useable for the bytes or bytearray translate method. - -The returned table will be one where each byte in frm is mapped to the byte at -the same position in to. - -The bytes objects frm and to must be of the same length. -[clinic start generated code]*/ - PyDoc_STRVAR(bytearray_maketrans__doc__, "maketrans(frm, to, /)\n" "--\n" @@ -1749,517 +123,6 @@ return return_value; } -static PyObject * -bytearray_maketrans_impl(Py_buffer *frm, Py_buffer *to) -/*[clinic end generated code: output=d332622814c26f4b input=5925a81d2fbbf151]*/ -{ - return _Py_bytes_maketrans(frm, to); -} - - -/* find and count characters and substrings */ - -#define findchar(target, target_len, c) \ - ((char *)memchr((const void *)(target), c, target_len)) - - -/* Bytes ops must return a string, create a copy */ -Py_LOCAL(PyByteArrayObject *) -return_self(PyByteArrayObject *self) -{ - /* always return a new bytearray */ - return (PyByteArrayObject *)PyByteArray_FromStringAndSize( - PyByteArray_AS_STRING(self), - PyByteArray_GET_SIZE(self)); -} - -Py_LOCAL_INLINE(Py_ssize_t) -countchar(const char *target, Py_ssize_t target_len, char c, Py_ssize_t maxcount) -{ - Py_ssize_t count=0; - const char *start=target; - const char *end=target+target_len; - - while ( (start=findchar(start, end-start, c)) != NULL ) { - count++; - if (count >= maxcount) - break; - start += 1; - } - return count; -} - - -/* Algorithms for different cases of string replacement */ - -/* len(self)>=1, from="", len(to)>=1, maxcount>=1 */ -Py_LOCAL(PyByteArrayObject *) -replace_interleave(PyByteArrayObject *self, - const char *to_s, Py_ssize_t to_len, - Py_ssize_t maxcount) -{ - char *self_s, *result_s; - Py_ssize_t self_len, result_len; - Py_ssize_t count, i; - PyByteArrayObject *result; - - self_len = PyByteArray_GET_SIZE(self); - - /* 1 at the end plus 1 after every character; - count = min(maxcount, self_len + 1) */ - if (maxcount <= self_len) - count = maxcount; - else - /* Can't overflow: self_len + 1 <= maxcount <= PY_SSIZE_T_MAX. */ - count = self_len + 1; - - /* Check for overflow */ - /* result_len = count * to_len + self_len; */ - assert(count > 0); - if (to_len > (PY_SSIZE_T_MAX - self_len) / count) { - PyErr_SetString(PyExc_OverflowError, - "replace string is too long"); - return NULL; - } - result_len = count * to_len + self_len; - - if (! (result = (PyByteArrayObject *) - PyByteArray_FromStringAndSize(NULL, result_len)) ) - return NULL; - - self_s = PyByteArray_AS_STRING(self); - result_s = PyByteArray_AS_STRING(result); - - /* TODO: special case single character, which doesn't need memcpy */ - - /* Lay the first one down (guaranteed this will occur) */ - Py_MEMCPY(result_s, to_s, to_len); - result_s += to_len; - count -= 1; - - for (i=0; i=1, len(from)==1, to="", maxcount>=1 */ -Py_LOCAL(PyByteArrayObject *) -replace_delete_single_character(PyByteArrayObject *self, - char from_c, Py_ssize_t maxcount) -{ - char *self_s, *result_s; - char *start, *next, *end; - Py_ssize_t self_len, result_len; - Py_ssize_t count; - PyByteArrayObject *result; - - self_len = PyByteArray_GET_SIZE(self); - self_s = PyByteArray_AS_STRING(self); - - count = countchar(self_s, self_len, from_c, maxcount); - if (count == 0) { - return return_self(self); - } - - result_len = self_len - count; /* from_len == 1 */ - assert(result_len>=0); - - if ( (result = (PyByteArrayObject *) - PyByteArray_FromStringAndSize(NULL, result_len)) == NULL) - return NULL; - result_s = PyByteArray_AS_STRING(result); - - start = self_s; - end = self_s + self_len; - while (count-- > 0) { - next = findchar(start, end-start, from_c); - if (next == NULL) - break; - Py_MEMCPY(result_s, start, next-start); - result_s += (next-start); - start = next+1; - } - Py_MEMCPY(result_s, start, end-start); - - return result; -} - -/* len(self)>=1, len(from)>=2, to="", maxcount>=1 */ - -Py_LOCAL(PyByteArrayObject *) -replace_delete_substring(PyByteArrayObject *self, - const char *from_s, Py_ssize_t from_len, - Py_ssize_t maxcount) -{ - char *self_s, *result_s; - char *start, *next, *end; - Py_ssize_t self_len, result_len; - Py_ssize_t count, offset; - PyByteArrayObject *result; - - self_len = PyByteArray_GET_SIZE(self); - self_s = PyByteArray_AS_STRING(self); - - count = stringlib_count(self_s, self_len, - from_s, from_len, - maxcount); - - if (count == 0) { - /* no matches */ - return return_self(self); - } - - result_len = self_len - (count * from_len); - assert (result_len>=0); - - if ( (result = (PyByteArrayObject *) - PyByteArray_FromStringAndSize(NULL, result_len)) == NULL ) - return NULL; - - result_s = PyByteArray_AS_STRING(result); - - start = self_s; - end = self_s + self_len; - while (count-- > 0) { - offset = stringlib_find(start, end-start, - from_s, from_len, - 0); - if (offset == -1) - break; - next = start + offset; - - Py_MEMCPY(result_s, start, next-start); - - result_s += (next-start); - start = next+from_len; - } - Py_MEMCPY(result_s, start, end-start); - return result; -} - -/* len(self)>=1, len(from)==len(to)==1, maxcount>=1 */ -Py_LOCAL(PyByteArrayObject *) -replace_single_character_in_place(PyByteArrayObject *self, - char from_c, char to_c, - Py_ssize_t maxcount) -{ - char *self_s, *result_s, *start, *end, *next; - Py_ssize_t self_len; - PyByteArrayObject *result; - - /* The result string will be the same size */ - self_s = PyByteArray_AS_STRING(self); - self_len = PyByteArray_GET_SIZE(self); - - next = findchar(self_s, self_len, from_c); - - if (next == NULL) { - /* No matches; return the original bytes */ - return return_self(self); - } - - /* Need to make a new bytes */ - result = (PyByteArrayObject *) PyByteArray_FromStringAndSize(NULL, self_len); - if (result == NULL) - return NULL; - result_s = PyByteArray_AS_STRING(result); - Py_MEMCPY(result_s, self_s, self_len); - - /* change everything in-place, starting with this one */ - start = result_s + (next-self_s); - *start = to_c; - start++; - end = result_s + self_len; - - while (--maxcount > 0) { - next = findchar(start, end-start, from_c); - if (next == NULL) - break; - *next = to_c; - start = next+1; - } - - return result; -} - -/* len(self)>=1, len(from)==len(to)>=2, maxcount>=1 */ -Py_LOCAL(PyByteArrayObject *) -replace_substring_in_place(PyByteArrayObject *self, - const char *from_s, Py_ssize_t from_len, - const char *to_s, Py_ssize_t to_len, - Py_ssize_t maxcount) -{ - char *result_s, *start, *end; - char *self_s; - Py_ssize_t self_len, offset; - PyByteArrayObject *result; - - /* The result bytes will be the same size */ - - self_s = PyByteArray_AS_STRING(self); - self_len = PyByteArray_GET_SIZE(self); - - offset = stringlib_find(self_s, self_len, - from_s, from_len, - 0); - if (offset == -1) { - /* No matches; return the original bytes */ - return return_self(self); - } - - /* Need to make a new bytes */ - result = (PyByteArrayObject *) PyByteArray_FromStringAndSize(NULL, self_len); - if (result == NULL) - return NULL; - result_s = PyByteArray_AS_STRING(result); - Py_MEMCPY(result_s, self_s, self_len); - - /* change everything in-place, starting with this one */ - start = result_s + offset; - Py_MEMCPY(start, to_s, from_len); - start += from_len; - end = result_s + self_len; - - while ( --maxcount > 0) { - offset = stringlib_find(start, end-start, - from_s, from_len, - 0); - if (offset==-1) - break; - Py_MEMCPY(start+offset, to_s, from_len); - start += offset+from_len; - } - - return result; -} - -/* len(self)>=1, len(from)==1, len(to)>=2, maxcount>=1 */ -Py_LOCAL(PyByteArrayObject *) -replace_single_character(PyByteArrayObject *self, - char from_c, - const char *to_s, Py_ssize_t to_len, - Py_ssize_t maxcount) -{ - char *self_s, *result_s; - char *start, *next, *end; - Py_ssize_t self_len, result_len; - Py_ssize_t count; - PyByteArrayObject *result; - - self_s = PyByteArray_AS_STRING(self); - self_len = PyByteArray_GET_SIZE(self); - - count = countchar(self_s, self_len, from_c, maxcount); - if (count == 0) { - /* no matches, return unchanged */ - return return_self(self); - } - - /* use the difference between current and new, hence the "-1" */ - /* result_len = self_len + count * (to_len-1) */ - assert(count > 0); - if (to_len - 1 > (PY_SSIZE_T_MAX - self_len) / count) { - PyErr_SetString(PyExc_OverflowError, "replace bytes is too long"); - return NULL; - } - result_len = self_len + count * (to_len - 1); - - if ( (result = (PyByteArrayObject *) - PyByteArray_FromStringAndSize(NULL, result_len)) == NULL) - return NULL; - result_s = PyByteArray_AS_STRING(result); - - start = self_s; - end = self_s + self_len; - while (count-- > 0) { - next = findchar(start, end-start, from_c); - if (next == NULL) - break; - - if (next == start) { - /* replace with the 'to' */ - Py_MEMCPY(result_s, to_s, to_len); - result_s += to_len; - start += 1; - } else { - /* copy the unchanged old then the 'to' */ - Py_MEMCPY(result_s, start, next-start); - result_s += (next-start); - Py_MEMCPY(result_s, to_s, to_len); - result_s += to_len; - start = next+1; - } - } - /* Copy the remainder of the remaining bytes */ - Py_MEMCPY(result_s, start, end-start); - - return result; -} - -/* len(self)>=1, len(from)>=2, len(to)>=2, maxcount>=1 */ -Py_LOCAL(PyByteArrayObject *) -replace_substring(PyByteArrayObject *self, - const char *from_s, Py_ssize_t from_len, - const char *to_s, Py_ssize_t to_len, - Py_ssize_t maxcount) -{ - char *self_s, *result_s; - char *start, *next, *end; - Py_ssize_t self_len, result_len; - Py_ssize_t count, offset; - PyByteArrayObject *result; - - self_s = PyByteArray_AS_STRING(self); - self_len = PyByteArray_GET_SIZE(self); - - count = stringlib_count(self_s, self_len, - from_s, from_len, - maxcount); - - if (count == 0) { - /* no matches, return unchanged */ - return return_self(self); - } - - /* Check for overflow */ - /* result_len = self_len + count * (to_len-from_len) */ - assert(count > 0); - if (to_len - from_len > (PY_SSIZE_T_MAX - self_len) / count) { - PyErr_SetString(PyExc_OverflowError, "replace bytes is too long"); - return NULL; - } - result_len = self_len + count * (to_len - from_len); - - if ( (result = (PyByteArrayObject *) - PyByteArray_FromStringAndSize(NULL, result_len)) == NULL) - return NULL; - result_s = PyByteArray_AS_STRING(result); - - start = self_s; - end = self_s + self_len; - while (count-- > 0) { - offset = stringlib_find(start, end-start, - from_s, from_len, - 0); - if (offset == -1) - break; - next = start+offset; - if (next == start) { - /* replace with the 'to' */ - Py_MEMCPY(result_s, to_s, to_len); - result_s += to_len; - start += from_len; - } else { - /* copy the unchanged old then the 'to' */ - Py_MEMCPY(result_s, start, next-start); - result_s += (next-start); - Py_MEMCPY(result_s, to_s, to_len); - result_s += to_len; - start = next+from_len; - } - } - /* Copy the remainder of the remaining bytes */ - Py_MEMCPY(result_s, start, end-start); - - return result; -} - - -Py_LOCAL(PyByteArrayObject *) -replace(PyByteArrayObject *self, - const char *from_s, Py_ssize_t from_len, - const char *to_s, Py_ssize_t to_len, - Py_ssize_t maxcount) -{ - if (maxcount < 0) { - maxcount = PY_SSIZE_T_MAX; - } else if (maxcount == 0 || PyByteArray_GET_SIZE(self) == 0) { - /* nothing to do; return the original bytes */ - return return_self(self); - } - - if (maxcount == 0 || - (from_len == 0 && to_len == 0)) { - /* nothing to do; return the original bytes */ - return return_self(self); - } - - /* Handle zero-length special cases */ - - if (from_len == 0) { - /* insert the 'to' bytes everywhere. */ - /* >>> "Python".replace("", ".") */ - /* '.P.y.t.h.o.n.' */ - return replace_interleave(self, to_s, to_len, maxcount); - } - - /* Except for "".replace("", "A") == "A" there is no way beyond this */ - /* point for an empty self bytes to generate a non-empty bytes */ - /* Special case so the remaining code always gets a non-empty bytes */ - if (PyByteArray_GET_SIZE(self) == 0) { - return return_self(self); - } - - if (to_len == 0) { - /* delete all occurrences of 'from' bytes */ - if (from_len == 1) { - return replace_delete_single_character( - self, from_s[0], maxcount); - } else { - return replace_delete_substring(self, from_s, from_len, maxcount); - } - } - - /* Handle special case where both bytes have the same length */ - - if (from_len == to_len) { - if (from_len == 1) { - return replace_single_character_in_place( - self, - from_s[0], - to_s[0], - maxcount); - } else { - return replace_substring_in_place( - self, from_s, from_len, to_s, to_len, maxcount); - } - } - - /* Otherwise use the more generic algorithms */ - if (from_len == 1) { - return replace_single_character(self, from_s[0], - to_s, to_len, maxcount); - } else { - /* len('from')>=2, len('to')>=1 */ - return replace_substring(self, from_s, from_len, to_s, to_len, maxcount); - } -} - - -/*[clinic input] -bytearray.replace - - old: Py_buffer - new: Py_buffer - count: Py_ssize_t = -1 - Maximum number of occurrences to replace. - -1 (the default value) means replace all occurrences. - / - -Return a copy with all occurrences of substring old replaced by new. - -If the optional argument count is given, only the first count occurrences are -replaced. -[clinic start generated code]*/ - PyDoc_STRVAR(bytearray_replace__doc__, "replace($self, old, new, count=-1, /)\n" "--\n" @@ -2304,29 +167,6 @@ return return_value; } -static PyObject * -bytearray_replace_impl(PyByteArrayObject *self, Py_buffer *old, Py_buffer *new, Py_ssize_t count) -/*[clinic end generated code: output=9997fbbd5bac4883 input=aa379d988637c7fb]*/ -{ - return (PyObject *)replace((PyByteArrayObject *) self, - old->buf, old->len, - new->buf, new->len, count); -} - -/*[clinic input] -bytearray.split - - sep: object = None - The delimiter according which to split the bytearray. - None (the default value) means split on ASCII whitespace characters - (space, tab, return, newline, formfeed, vertical tab). - maxsplit: Py_ssize_t = -1 - Maximum number of splits to do. - -1 (the default value) means no limit. - -Return a list of the sections in the bytearray, using sep as the delimiter. -[clinic start generated code]*/ - PyDoc_STRVAR(bytearray_split__doc__, "split($self, /, sep=None, maxsplit=-1)\n" "--\n" @@ -2365,50 +205,6 @@ return return_value; } -static PyObject * -bytearray_split_impl(PyByteArrayObject *self, PyObject *sep, Py_ssize_t maxsplit) -/*[clinic end generated code: output=062a3d87d6f918fa input=24f82669f41bf523]*/ -{ - Py_ssize_t len = PyByteArray_GET_SIZE(self), n; - const char *s = PyByteArray_AS_STRING(self), *sub; - PyObject *list; - Py_buffer vsub; - - if (maxsplit < 0) - maxsplit = PY_SSIZE_T_MAX; - - if (sep == Py_None) - return stringlib_split_whitespace((PyObject*) self, s, len, maxsplit); - - if (PyObject_GetBuffer(sep, &vsub, PyBUF_SIMPLE) != 0) - return NULL; - sub = vsub.buf; - n = vsub.len; - - list = stringlib_split( - (PyObject*) self, s, len, sub, n, maxsplit - ); - PyBuffer_Release(&vsub); - return list; -} - -/*[clinic input] -bytearray.partition - - self: self(type="PyByteArrayObject *") - sep: object - / - -Partition the bytearray into three parts using the given separator. - -This will search for the separator sep in the bytearray. If the separator is -found, returns a 3-tuple containing the part before the separator, the -separator itself, and the part after it. - -If the separator is not found, returns a 3-tuple containing the original -bytearray object and two empty bytearray objects. -[clinic start generated code]*/ - PyDoc_STRVAR(bytearray_partition__doc__, "partition($self, sep, /)\n" "--\n" @@ -2425,44 +221,6 @@ #define BYTEARRAY_PARTITION_METHODDEF \ {"partition", (PyCFunction)bytearray_partition, METH_O, bytearray_partition__doc__}, -static PyObject * -bytearray_partition(PyByteArrayObject *self, PyObject *sep) -/*[clinic end generated code: output=2645138221fe6f4d input=7d7fe37b1696d506]*/ -{ - PyObject *bytesep, *result; - - bytesep = PyByteArray_FromObject(sep); - if (! bytesep) - return NULL; - - result = stringlib_partition( - (PyObject*) self, - PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self), - bytesep, - PyByteArray_AS_STRING(bytesep), PyByteArray_GET_SIZE(bytesep) - ); - - Py_DECREF(bytesep); - return result; -} - -/*[clinic input] -bytearray.rpartition - - self: self(type="PyByteArrayObject *") - sep: object - / - -Partition the bytes into three parts using the given separator. - -This will search for the separator sep in the bytearray, starting and the end. -If the separator is found, returns a 3-tuple containing the part before the -separator, the separator itself, and the part after it. - -If the separator is not found, returns a 3-tuple containing two empty bytearray -objects and the original bytearray object. -[clinic start generated code]*/ - PyDoc_STRVAR(bytearray_rpartition__doc__, "rpartition($self, sep, /)\n" "--\n" @@ -2479,35 +237,6 @@ #define BYTEARRAY_RPARTITION_METHODDEF \ {"rpartition", (PyCFunction)bytearray_rpartition, METH_O, bytearray_rpartition__doc__}, -static PyObject * -bytearray_rpartition(PyByteArrayObject *self, PyObject *sep) -/*[clinic end generated code: output=ed13e54605d007de input=9b8cd540c1b75853]*/ -{ - PyObject *bytesep, *result; - - bytesep = PyByteArray_FromObject(sep); - if (! bytesep) - return NULL; - - result = stringlib_rpartition( - (PyObject*) self, - PyByteArray_AS_STRING(self), PyByteArray_GET_SIZE(self), - bytesep, - PyByteArray_AS_STRING(bytesep), PyByteArray_GET_SIZE(bytesep) - ); - - Py_DECREF(bytesep); - return result; -} - -/*[clinic input] -bytearray.rsplit = bytearray.split - -Return a list of the sections in the bytearray, using sep as the delimiter. - -Splitting is done starting at the end of the bytearray and working to the front. -[clinic start generated code]*/ - PyDoc_STRVAR(bytearray_rsplit__doc__, "rsplit($self, /, sep=None, maxsplit=-1)\n" "--\n" @@ -2548,41 +277,6 @@ return return_value; } -static PyObject * -bytearray_rsplit_impl(PyByteArrayObject *self, PyObject *sep, Py_ssize_t maxsplit) -/*[clinic end generated code: output=affaf9fc2aae8d41 input=a68286e4dd692ffe]*/ -{ - Py_ssize_t len = PyByteArray_GET_SIZE(self), n; - const char *s = PyByteArray_AS_STRING(self), *sub; - PyObject *list; - Py_buffer vsub; - - if (maxsplit < 0) - maxsplit = PY_SSIZE_T_MAX; - - if (sep == Py_None) - return stringlib_rsplit_whitespace((PyObject*) self, s, len, maxsplit); - - if (PyObject_GetBuffer(sep, &vsub, PyBUF_SIMPLE) != 0) - return NULL; - sub = vsub.buf; - n = vsub.len; - - list = stringlib_rsplit( - (PyObject*) self, s, len, sub, n, maxsplit - ); - PyBuffer_Release(&vsub); - return list; -} - -/*[clinic input] -bytearray.reverse - - self: self(type="PyByteArrayObject *") - -Reverse the order of the values in B in place. -[clinic start generated code]*/ - PyDoc_STRVAR(bytearray_reverse__doc__, "reverse($self, /)\n" "--\n" @@ -2601,47 +295,6 @@ return bytearray_reverse_impl(self); } -static PyObject * -bytearray_reverse_impl(PyByteArrayObject *self) -/*[clinic end generated code: output=5d5e5f0bfc67f476 input=7933a499b8597bd1]*/ -{ - char swap, *head, *tail; - Py_ssize_t i, j, n = Py_SIZE(self); - - j = n / 2; - head = PyByteArray_AS_STRING(self); - tail = head + n - 1; - for (i = 0; i < j; i++) { - swap = *head; - *head++ = *tail; - *tail-- = swap; - } - - Py_RETURN_NONE; -} - - -/*[python input] -class bytesvalue_converter(CConverter): - type = 'int' - converter = '_getbytevalue' -[python start generated code]*/ -/*[python end generated code: output=da39a3ee5e6b4b0d input=29c2e7c26c212812]*/ - - -/*[clinic input] -bytearray.insert - - self: self(type="PyByteArrayObject *") - index: Py_ssize_t - The index where the value is to be inserted. - item: bytesvalue - The item to be inserted. - / - -Insert a single item into the bytearray before the given index. -[clinic start generated code]*/ - PyDoc_STRVAR(bytearray_insert__doc__, "insert($self, index, item, /)\n" "--\n" @@ -2676,46 +329,6 @@ return return_value; } -static PyObject * -bytearray_insert_impl(PyByteArrayObject *self, Py_ssize_t index, int item) -/*[clinic end generated code: output=5ec9340d4ad19080 input=833766836ba30e1e]*/ -{ - Py_ssize_t n = Py_SIZE(self); - char *buf; - - if (n == PY_SSIZE_T_MAX) { - PyErr_SetString(PyExc_OverflowError, - "cannot add more objects to bytearray"); - return NULL; - } - if (PyByteArray_Resize((PyObject *)self, n + 1) < 0) - return NULL; - buf = PyByteArray_AS_STRING(self); - - if (index < 0) { - index += n; - if (index < 0) - index = 0; - } - if (index > n) - index = n; - memmove(buf + index + 1, buf + index, n - index); - buf[index] = item; - - Py_RETURN_NONE; -} - -/*[clinic input] -bytearray.append - - self: self(type="PyByteArrayObject *") - item: bytesvalue - The item to be appended. - / - -Append a single item to the end of the bytearray. -[clinic start generated code]*/ - PyDoc_STRVAR(bytearray_append__doc__, "append($self, item, /)\n" "--\n" @@ -2747,36 +360,6 @@ return return_value; } -static PyObject * -bytearray_append_impl(PyByteArrayObject *self, int item) -/*[clinic end generated code: output=b5b3325bb3bbaf85 input=ae56ea87380407cc]*/ -{ - Py_ssize_t n = Py_SIZE(self); - - if (n == PY_SSIZE_T_MAX) { - PyErr_SetString(PyExc_OverflowError, - "cannot add more objects to bytearray"); - return NULL; - } - if (PyByteArray_Resize((PyObject *)self, n + 1) < 0) - return NULL; - - PyByteArray_AS_STRING(self)[n] = item; - - Py_RETURN_NONE; -} - -/*[clinic input] -bytearray.extend - - self: self(type="PyByteArrayObject *") - iterable_of_ints: object - The iterable of items to append. - / - -Append all the items from the iterator or sequence to the end of the bytearray. -[clinic start generated code]*/ - PyDoc_STRVAR(bytearray_extend__doc__, "extend($self, iterable_of_ints, /)\n" "--\n" @@ -2789,94 +372,6 @@ #define BYTEARRAY_EXTEND_METHODDEF \ {"extend", (PyCFunction)bytearray_extend, METH_O, bytearray_extend__doc__}, -static PyObject * -bytearray_extend(PyByteArrayObject *self, PyObject *iterable_of_ints) -/*[clinic end generated code: output=13b0c13ad5110dfb input=ce83a5d75b70d850]*/ -{ - PyObject *it, *item, *bytearray_obj; - Py_ssize_t buf_size = 0, len = 0; - int value; - char *buf; - - /* bytearray_setslice code only accepts something supporting PEP 3118. */ - if (PyObject_CheckBuffer(iterable_of_ints)) { - if (bytearray_setslice(self, Py_SIZE(self), Py_SIZE(self), iterable_of_ints) == -1) - return NULL; - - Py_RETURN_NONE; - } - - it = PyObject_GetIter(iterable_of_ints); - if (it == NULL) - return NULL; - - /* Try to determine the length of the argument. 32 is arbitrary. */ - buf_size = PyObject_LengthHint(iterable_of_ints, 32); - if (buf_size == -1) { - Py_DECREF(it); - return NULL; - } - - bytearray_obj = PyByteArray_FromStringAndSize(NULL, buf_size); - if (bytearray_obj == NULL) { - Py_DECREF(it); - return NULL; - } - buf = PyByteArray_AS_STRING(bytearray_obj); - - while ((item = PyIter_Next(it)) != NULL) { - if (! _getbytevalue(item, &value)) { - Py_DECREF(item); - Py_DECREF(it); - Py_DECREF(bytearray_obj); - return NULL; - } - buf[len++] = value; - Py_DECREF(item); - - if (len >= buf_size) { - buf_size = len + (len >> 1) + 1; - if (PyByteArray_Resize((PyObject *)bytearray_obj, buf_size) < 0) { - Py_DECREF(it); - Py_DECREF(bytearray_obj); - return NULL; - } - /* Recompute the `buf' pointer, since the resizing operation may - have invalidated it. */ - buf = PyByteArray_AS_STRING(bytearray_obj); - } - } - Py_DECREF(it); - - /* Resize down to exact size. */ - if (PyByteArray_Resize((PyObject *)bytearray_obj, len) < 0) { - Py_DECREF(bytearray_obj); - return NULL; - } - - 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; -} - -/*[clinic input] -bytearray.pop - - self: self(type="PyByteArrayObject *") - index: Py_ssize_t = -1 - The index from where to remove the item. - -1 (the default value) means remove the last item. - / - -Remove and return a single item from B. - -If no index argument is given, will pop the last item. -[clinic start generated code]*/ - PyDoc_STRVAR(bytearray_pop__doc__, "pop($self, index=-1, /)\n" "--\n" @@ -2911,48 +406,6 @@ return return_value; } -static PyObject * -bytearray_pop_impl(PyByteArrayObject *self, Py_ssize_t index) -/*[clinic end generated code: output=3b763e548e79af96 input=0797e6c0ca9d5a85]*/ -{ - int value; - Py_ssize_t n = Py_SIZE(self); - char *buf; - - if (n == 0) { - PyErr_SetString(PyExc_IndexError, - "pop from empty bytearray"); - return NULL; - } - if (index < 0) - index += Py_SIZE(self); - if (index < 0 || index >= Py_SIZE(self)) { - PyErr_SetString(PyExc_IndexError, "pop index out of range"); - return NULL; - } - if (!_canresize(self)) - return NULL; - - buf = PyByteArray_AS_STRING(self); - value = buf[index]; - memmove(buf + index, buf + index + 1, n - index); - if (PyByteArray_Resize((PyObject *)self, n - 1) < 0) - return NULL; - - return PyLong_FromLong((unsigned char)value); -} - -/*[clinic input] -bytearray.remove - - self: self(type="PyByteArrayObject *") - value: bytesvalue - The value to remove. - / - -Remove the first occurrence of a value in the bytearray. -[clinic start generated code]*/ - PyDoc_STRVAR(bytearray_remove__doc__, "remove($self, value, /)\n" "--\n" @@ -2984,64 +437,6 @@ return return_value; } -static PyObject * -bytearray_remove_impl(PyByteArrayObject *self, int value) -/*[clinic end generated code: output=c71c8bcf4703abfc input=47560b11fd856c24]*/ -{ - Py_ssize_t where, n = Py_SIZE(self); - char *buf = PyByteArray_AS_STRING(self); - - for (where = 0; where < n; where++) { - if (buf[where] == value) - break; - } - if (where == n) { - PyErr_SetString(PyExc_ValueError, "value not found in bytearray"); - return NULL; - } - if (!_canresize(self)) - return NULL; - - memmove(buf + where, buf + where + 1, n - where); - if (PyByteArray_Resize((PyObject *)self, n - 1) < 0) - return NULL; - - Py_RETURN_NONE; -} - -/* XXX These two helpers could be optimized if argsize == 1 */ - -static Py_ssize_t -lstrip_helper(char *myptr, Py_ssize_t mysize, - void *argptr, Py_ssize_t argsize) -{ - Py_ssize_t i = 0; - while (i < mysize && memchr(argptr, (unsigned char) myptr[i], argsize)) - i++; - return i; -} - -static Py_ssize_t -rstrip_helper(char *myptr, Py_ssize_t mysize, - void *argptr, Py_ssize_t argsize) -{ - Py_ssize_t i = mysize - 1; - while (i >= 0 && memchr(argptr, (unsigned char) myptr[i], argsize)) - i--; - return i + 1; -} - -/*[clinic input] -bytearray.strip - - bytes: object = None - / - -Strip leading and trailing bytes contained in the argument. - -If the argument is omitted or None, strip leading and trailing ASCII whitespace. -[clinic start generated code]*/ - PyDoc_STRVAR(bytearray_strip__doc__, "strip($self, bytes=None, /)\n" "--\n" @@ -3072,47 +467,6 @@ return return_value; } -static PyObject * -bytearray_strip_impl(PyByteArrayObject *self, PyObject *bytes) -/*[clinic end generated code: output=2e3d3358acc4c235 input=ef7bb59b09c21d62]*/ -{ - Py_ssize_t left, right, mysize, byteslen; - char *myptr, *bytesptr; - Py_buffer vbytes; - - if (bytes == Py_None) { - bytesptr = "\t\n\r\f\v "; - byteslen = 6; - } - else { - if (PyObject_GetBuffer(bytes, &vbytes, PyBUF_SIMPLE) != 0) - return NULL; - bytesptr = (char *) vbytes.buf; - byteslen = vbytes.len; - } - myptr = PyByteArray_AS_STRING(self); - mysize = Py_SIZE(self); - left = lstrip_helper(myptr, mysize, bytesptr, byteslen); - if (left == mysize) - right = left; - else - right = rstrip_helper(myptr, mysize, bytesptr, byteslen); - if (bytes != Py_None) - PyBuffer_Release(&vbytes); - return PyByteArray_FromStringAndSize(myptr + left, right - left); -} - -/*[clinic input] -bytearray.lstrip - - bytes: object = None - / - -Strip leading bytes contained in the argument. - -If the argument is omitted or None, strip leading ASCII whitespace. -[clinic start generated code]*/ - PyDoc_STRVAR(bytearray_lstrip__doc__, "lstrip($self, bytes=None, /)\n" "--\n" @@ -3143,44 +497,6 @@ return return_value; } -static PyObject * -bytearray_lstrip_impl(PyByteArrayObject *self, PyObject *bytes) -/*[clinic end generated code: output=2599309808a9ec02 input=80843f975dd7c480]*/ -{ - Py_ssize_t left, right, mysize, byteslen; - char *myptr, *bytesptr; - Py_buffer vbytes; - - if (bytes == Py_None) { - bytesptr = "\t\n\r\f\v "; - byteslen = 6; - } - else { - if (PyObject_GetBuffer(bytes, &vbytes, PyBUF_SIMPLE) != 0) - return NULL; - bytesptr = (char *) vbytes.buf; - byteslen = vbytes.len; - } - myptr = PyByteArray_AS_STRING(self); - mysize = Py_SIZE(self); - left = lstrip_helper(myptr, mysize, bytesptr, byteslen); - right = mysize; - if (bytes != Py_None) - PyBuffer_Release(&vbytes); - return PyByteArray_FromStringAndSize(myptr + left, right - left); -} - -/*[clinic input] -bytearray.rstrip - - bytes: object = None - / - -Strip trailing bytes contained in the argument. - -If the argument is omitted or None, strip trailing ASCII whitespace. -[clinic start generated code]*/ - PyDoc_STRVAR(bytearray_rstrip__doc__, "rstrip($self, bytes=None, /)\n" "--\n" @@ -3211,47 +527,6 @@ return return_value; } -static PyObject * -bytearray_rstrip_impl(PyByteArrayObject *self, PyObject *bytes) -/*[clinic end generated code: output=b5ca6259f4f4f2a3 input=e728b994954cfd91]*/ -{ - Py_ssize_t right, mysize, byteslen; - char *myptr, *bytesptr; - Py_buffer vbytes; - - if (bytes == Py_None) { - bytesptr = "\t\n\r\f\v "; - byteslen = 6; - } - else { - if (PyObject_GetBuffer(bytes, &vbytes, PyBUF_SIMPLE) != 0) - return NULL; - bytesptr = (char *) vbytes.buf; - byteslen = vbytes.len; - } - myptr = PyByteArray_AS_STRING(self); - mysize = Py_SIZE(self); - right = rstrip_helper(myptr, mysize, bytesptr, byteslen); - if (bytes != Py_None) - PyBuffer_Release(&vbytes); - return PyByteArray_FromStringAndSize(myptr, right); -} - -/*[clinic input] -bytearray.decode - - encoding: str(c_default="NULL") = 'utf-8' - The encoding with which to decode the bytearray. - errors: str(c_default="NULL") = 'strict' - The error handling scheme to use for the handling of decoding errors. - The default is 'strict' meaning that decoding errors raise a - UnicodeDecodeError. Other possible values are 'ignore' and 'replace' - as well as any other name registered with codecs.register_error that - can handle UnicodeDecodeErrors. - -Decode the bytearray using the codec registered for encoding. -[clinic start generated code]*/ - PyDoc_STRVAR(bytearray_decode__doc__, "decode($self, /, encoding=\'utf-8\', errors=\'strict\')\n" "--\n" @@ -3291,39 +566,6 @@ return return_value; } -static PyObject * -bytearray_decode_impl(PyByteArrayObject *self, const char *encoding, const char *errors) -/*[clinic end generated code: output=38b83681f1e38a6c input=f28d8f903020257b]*/ -{ - if (encoding == NULL) - encoding = PyUnicode_GetDefaultEncoding(); - return PyUnicode_FromEncodedObject((PyObject*)self, encoding, errors); -} - -PyDoc_STRVAR(alloc_doc, -"B.__alloc__() -> int\n\ -\n\ -Return the number of bytes actually allocated."); - -static PyObject * -bytearray_alloc(PyByteArrayObject *self) -{ - return PyLong_FromSsize_t(self->ob_alloc); -} - -/*[clinic input] -bytearray.join - - iterable_of_bytes: object - / - -Concatenate any number of bytes/bytearray objects. - -The bytearray whose method is called is inserted in between each pair. - -The result is returned as a new bytearray object. -[clinic start generated code]*/ - PyDoc_STRVAR(bytearray_join__doc__, "join($self, iterable_of_bytes, /)\n" "--\n" @@ -3337,24 +579,6 @@ #define BYTEARRAY_JOIN_METHODDEF \ {"join", (PyCFunction)bytearray_join, METH_O, bytearray_join__doc__}, -static PyObject * -bytearray_join(PyByteArrayObject *self, PyObject *iterable_of_bytes) -/*[clinic end generated code: output=544e7430032dfdf4 input=aba6b1f9b30fcb8e]*/ -{ - return stringlib_bytes_join((PyObject*)self, iterable_of_bytes); -} - -/*[clinic input] -bytearray.splitlines - - keepends: int(py_default="False") = 0 - -Return a list of the lines in the bytearray, breaking at line boundaries. - -Line breaks are not included in the resulting list unless keepends is given and -true. -[clinic start generated code]*/ - PyDoc_STRVAR(bytearray_splitlines__doc__, "splitlines($self, /, keepends=False)\n" "--\n" @@ -3387,46 +611,6 @@ return return_value; } -static PyObject * -bytearray_splitlines_impl(PyByteArrayObject *self, int keepends) -/*[clinic end generated code: output=a837fd0512ad46ff input=36f0b25bc792f6c0]*/ -{ - return stringlib_splitlines( - (PyObject*) self, PyByteArray_AS_STRING(self), - PyByteArray_GET_SIZE(self), keepends - ); -} - -static int -hex_digit_to_int(Py_UCS4 c) -{ - if (c >= 128) - return -1; - if (Py_ISDIGIT(c)) - return c - '0'; - else { - if (Py_ISUPPER(c)) - c = Py_TOLOWER(c); - if (c >= 'a' && c <= 'f') - return c - 'a' + 10; - } - return -1; -} - -/*[clinic input] - at classmethod -bytearray.fromhex - - cls: self(type="PyObject*") - string: unicode - / - -Create a bytearray object from a string of hexadecimal numbers. - -Spaces between two numbers are accepted. -Example: bytearray.fromhex('B9 01EF') -> bytearray(b'\\xb9\\x01\\xef') -[clinic start generated code]*/ - PyDoc_STRVAR(bytearray_fromhex__doc__, "fromhex($type, string, /)\n" "--\n" @@ -3458,98 +642,6 @@ return return_value; } -static PyObject * -bytearray_fromhex_impl(PyObject*cls, PyObject *string) -/*[clinic end generated code: output=adc3c804a74e56d4 input=907bbd2d34d9367a]*/ -{ - PyObject *newbytes; - char *buf; - Py_ssize_t hexlen, byteslen, i, j; - int top, bot; - void *data; - unsigned int kind; - - assert(PyUnicode_Check(string)); - if (PyUnicode_READY(string)) - return NULL; - kind = PyUnicode_KIND(string); - data = PyUnicode_DATA(string); - hexlen = PyUnicode_GET_LENGTH(string); - - byteslen = hexlen/2; /* This overestimates if there are spaces */ - newbytes = PyByteArray_FromStringAndSize(NULL, byteslen); - if (!newbytes) - return NULL; - buf = PyByteArray_AS_STRING(newbytes); - for (i = j = 0; i < hexlen; i += 2) { - /* skip over spaces in the input */ - while (PyUnicode_READ(kind, data, i) == ' ') - i++; - if (i >= hexlen) - break; - top = hex_digit_to_int(PyUnicode_READ(kind, data, i)); - bot = hex_digit_to_int(PyUnicode_READ(kind, data, i+1)); - if (top == -1 || bot == -1) { - PyErr_Format(PyExc_ValueError, - "non-hexadecimal number found in " - "fromhex() arg at position %zd", i); - goto error; - } - buf[j++] = (top << 4) + bot; - } - if (PyByteArray_Resize(newbytes, j) < 0) - goto error; - return newbytes; - - error: - Py_DECREF(newbytes); - return NULL; -} - - -static PyObject * -_common_reduce(PyByteArrayObject *self, int proto) -{ - PyObject *dict; - _Py_IDENTIFIER(__dict__); - char *buf; - - dict = _PyObject_GetAttrId((PyObject *)self, &PyId___dict__); - if (dict == NULL) { - PyErr_Clear(); - dict = Py_None; - Py_INCREF(dict); - } - - buf = PyByteArray_AS_STRING(self); - if (proto < 3) { - /* use str based reduction for backwards compatibility with Python 2.x */ - PyObject *latin1; - if (Py_SIZE(self)) - latin1 = PyUnicode_DecodeLatin1(buf, Py_SIZE(self), NULL); - else - latin1 = PyUnicode_FromString(""); - return Py_BuildValue("(O(Ns)N)", Py_TYPE(self), latin1, "latin-1", dict); - } - else { - /* use more efficient byte based reduction */ - if (Py_SIZE(self)) { - return Py_BuildValue("(O(y#)N)", Py_TYPE(self), buf, Py_SIZE(self), dict); - } - else { - return Py_BuildValue("(O()N)", Py_TYPE(self), dict); - } - } -} - -/*[clinic input] -bytearray.__reduce__ as bytearray_reduce - - self: self(type="PyByteArrayObject *") - -Return state information for pickling. -[clinic start generated code]*/ - PyDoc_STRVAR(bytearray_reduce__doc__, "__reduce__($self, /)\n" "--\n" @@ -3568,23 +660,6 @@ return bytearray_reduce_impl(self); } -static PyObject * -bytearray_reduce_impl(PyByteArrayObject *self) -/*[clinic end generated code: output=b1b56fe87bf30fb0 input=fbb07de4d102a03a]*/ -{ - return _common_reduce(self, 2); -} - -/*[clinic input] -bytearray.__reduce_ex__ as bytearray_reduce_ex - - self: self(type="PyByteArrayObject *") - proto: int = 0 - / - -Return state information for pickling. -[clinic start generated code]*/ - PyDoc_STRVAR(bytearray_reduce_ex__doc__, "__reduce_ex__($self, proto=0, /)\n" "--\n" @@ -3613,21 +688,6 @@ return return_value; } -static PyObject * -bytearray_reduce_ex_impl(PyByteArrayObject *self, int proto) -/*[clinic end generated code: output=bbd9afb2f5953dc1 input=0e091a42ca6dbd91]*/ -{ - return _common_reduce(self, proto); -} - -/*[clinic input] -bytearray.__sizeof__ as bytearray_sizeof - - self: self(type="PyByteArrayObject *") - -Returns the size of the bytearray object in memory, in bytes. -[clinic start generated code]*/ - PyDoc_STRVAR(bytearray_sizeof__doc__, "__sizeof__($self, /)\n" "--\n" @@ -3645,331 +705,4 @@ { return bytearray_sizeof_impl(self); } - -static PyObject * -bytearray_sizeof_impl(PyByteArrayObject *self) -/*[clinic end generated code: output=4a2254b0a85630c6 input=6b23d305362b462b]*/ -{ - Py_ssize_t res; - - res = sizeof(PyByteArrayObject) + self->ob_alloc * sizeof(char); - return PyLong_FromSsize_t(res); -} - -static PySequenceMethods bytearray_as_sequence = { - (lenfunc)bytearray_length, /* sq_length */ - (binaryfunc)PyByteArray_Concat, /* sq_concat */ - (ssizeargfunc)bytearray_repeat, /* sq_repeat */ - (ssizeargfunc)bytearray_getitem, /* sq_item */ - 0, /* sq_slice */ - (ssizeobjargproc)bytearray_setitem, /* sq_ass_item */ - 0, /* sq_ass_slice */ - (objobjproc)bytearray_contains, /* sq_contains */ - (binaryfunc)bytearray_iconcat, /* sq_inplace_concat */ - (ssizeargfunc)bytearray_irepeat, /* sq_inplace_repeat */ -}; - -static PyMappingMethods bytearray_as_mapping = { - (lenfunc)bytearray_length, - (binaryfunc)bytearray_subscript, - (objobjargproc)bytearray_ass_subscript, -}; - -static PyBufferProcs bytearray_as_buffer = { - (getbufferproc)bytearray_getbuffer, - (releasebufferproc)bytearray_releasebuffer, -}; - -static PyMethodDef -bytearray_methods[] = { - {"__alloc__", (PyCFunction)bytearray_alloc, METH_NOARGS, alloc_doc}, - BYTEARRAY_REDUCE_METHODDEF - BYTEARRAY_REDUCE_EX_METHODDEF - BYTEARRAY_SIZEOF_METHODDEF - BYTEARRAY_APPEND_METHODDEF - {"capitalize", (PyCFunction)stringlib_capitalize, METH_NOARGS, - _Py_capitalize__doc__}, - {"center", (PyCFunction)stringlib_center, METH_VARARGS, center__doc__}, - BYTEARRAY_CLEAR_METHODDEF - BYTEARRAY_COPY_METHODDEF - {"count", (PyCFunction)bytearray_count, METH_VARARGS, count__doc__}, - BYTEARRAY_DECODE_METHODDEF - {"endswith", (PyCFunction)bytearray_endswith, METH_VARARGS, endswith__doc__}, - {"expandtabs", (PyCFunction)stringlib_expandtabs, METH_VARARGS | METH_KEYWORDS, - expandtabs__doc__}, - BYTEARRAY_EXTEND_METHODDEF - {"find", (PyCFunction)bytearray_find, METH_VARARGS, find__doc__}, - BYTEARRAY_FROMHEX_METHODDEF - {"index", (PyCFunction)bytearray_index, METH_VARARGS, index__doc__}, - BYTEARRAY_INSERT_METHODDEF - {"isalnum", (PyCFunction)stringlib_isalnum, METH_NOARGS, - _Py_isalnum__doc__}, - {"isalpha", (PyCFunction)stringlib_isalpha, METH_NOARGS, - _Py_isalpha__doc__}, - {"isdigit", (PyCFunction)stringlib_isdigit, METH_NOARGS, - _Py_isdigit__doc__}, - {"islower", (PyCFunction)stringlib_islower, METH_NOARGS, - _Py_islower__doc__}, - {"isspace", (PyCFunction)stringlib_isspace, METH_NOARGS, - _Py_isspace__doc__}, - {"istitle", (PyCFunction)stringlib_istitle, METH_NOARGS, - _Py_istitle__doc__}, - {"isupper", (PyCFunction)stringlib_isupper, METH_NOARGS, - _Py_isupper__doc__}, - BYTEARRAY_JOIN_METHODDEF - {"ljust", (PyCFunction)stringlib_ljust, METH_VARARGS, ljust__doc__}, - {"lower", (PyCFunction)stringlib_lower, METH_NOARGS, _Py_lower__doc__}, - BYTEARRAY_LSTRIP_METHODDEF - BYTEARRAY_MAKETRANS_METHODDEF - BYTEARRAY_PARTITION_METHODDEF - BYTEARRAY_POP_METHODDEF - BYTEARRAY_REMOVE_METHODDEF - BYTEARRAY_REPLACE_METHODDEF - BYTEARRAY_REVERSE_METHODDEF - {"rfind", (PyCFunction)bytearray_rfind, METH_VARARGS, rfind__doc__}, - {"rindex", (PyCFunction)bytearray_rindex, METH_VARARGS, rindex__doc__}, - {"rjust", (PyCFunction)stringlib_rjust, METH_VARARGS, rjust__doc__}, - BYTEARRAY_RPARTITION_METHODDEF - BYTEARRAY_RSPLIT_METHODDEF - BYTEARRAY_RSTRIP_METHODDEF - BYTEARRAY_SPLIT_METHODDEF - BYTEARRAY_SPLITLINES_METHODDEF - {"startswith", (PyCFunction)bytearray_startswith, METH_VARARGS , - startswith__doc__}, - BYTEARRAY_STRIP_METHODDEF - {"swapcase", (PyCFunction)stringlib_swapcase, METH_NOARGS, - _Py_swapcase__doc__}, - {"title", (PyCFunction)stringlib_title, METH_NOARGS, _Py_title__doc__}, - BYTEARRAY_TRANSLATE_METHODDEF - {"upper", (PyCFunction)stringlib_upper, METH_NOARGS, _Py_upper__doc__}, - {"zfill", (PyCFunction)stringlib_zfill, METH_VARARGS, zfill__doc__}, - {NULL} -}; - -static PyObject * -bytearray_mod(PyObject *v, PyObject *w) -{ - if (!PyByteArray_Check(v)) - Py_RETURN_NOTIMPLEMENTED; - return bytearray_format((PyByteArrayObject *)v, w); -} - -static PyNumberMethods bytearray_as_number = { - 0, /*nb_add*/ - 0, /*nb_subtract*/ - 0, /*nb_multiply*/ - bytearray_mod, /*nb_remainder*/ -}; - -PyDoc_STRVAR(bytearray_doc, -"bytearray(iterable_of_ints) -> bytearray\n\ -bytearray(string, encoding[, errors]) -> bytearray\n\ -bytearray(bytes_or_buffer) -> mutable copy of bytes_or_buffer\n\ -bytearray(int) -> bytes array of size given by the parameter initialized with null bytes\n\ -bytearray() -> empty bytes array\n\ -\n\ -Construct an mutable bytearray object from:\n\ - - an iterable yielding integers in range(256)\n\ - - a text string encoded using the specified encoding\n\ - - a bytes or a buffer object\n\ - - any object implementing the buffer API.\n\ - - an integer"); - - -static PyObject *bytearray_iter(PyObject *seq); - -PyTypeObject PyByteArray_Type = { - PyVarObject_HEAD_INIT(&PyType_Type, 0) - "bytearray", - sizeof(PyByteArrayObject), - 0, - (destructor)bytearray_dealloc, /* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_reserved */ - (reprfunc)bytearray_repr, /* tp_repr */ - &bytearray_as_number, /* tp_as_number */ - &bytearray_as_sequence, /* tp_as_sequence */ - &bytearray_as_mapping, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - bytearray_str, /* tp_str */ - PyObject_GenericGetAttr, /* tp_getattro */ - 0, /* tp_setattro */ - &bytearray_as_buffer, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ - bytearray_doc, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - (richcmpfunc)bytearray_richcompare, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - bytearray_iter, /* tp_iter */ - 0, /* tp_iternext */ - bytearray_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)bytearray_init, /* tp_init */ - PyType_GenericAlloc, /* tp_alloc */ - PyType_GenericNew, /* tp_new */ - PyObject_Del, /* tp_free */ -}; - -/*********************** Bytes Iterator ****************************/ - -typedef struct { - PyObject_HEAD - Py_ssize_t it_index; - PyByteArrayObject *it_seq; /* Set to NULL when iterator is exhausted */ -} bytesiterobject; - -static void -bytearrayiter_dealloc(bytesiterobject *it) -{ - _PyObject_GC_UNTRACK(it); - Py_XDECREF(it->it_seq); - PyObject_GC_Del(it); -} - -static int -bytearrayiter_traverse(bytesiterobject *it, visitproc visit, void *arg) -{ - Py_VISIT(it->it_seq); - return 0; -} - -static PyObject * -bytearrayiter_next(bytesiterobject *it) -{ - PyByteArrayObject *seq; - PyObject *item; - - assert(it != NULL); - seq = it->it_seq; - if (seq == NULL) - return NULL; - assert(PyByteArray_Check(seq)); - - if (it->it_index < PyByteArray_GET_SIZE(seq)) { - item = PyLong_FromLong( - (unsigned char)PyByteArray_AS_STRING(seq)[it->it_index]); - if (item != NULL) - ++it->it_index; - return item; - } - - Py_DECREF(seq); - it->it_seq = NULL; - return NULL; -} - -static PyObject * -bytearrayiter_length_hint(bytesiterobject *it) -{ - Py_ssize_t len = 0; - if (it->it_seq) - len = PyByteArray_GET_SIZE(it->it_seq) - it->it_index; - return PyLong_FromSsize_t(len); -} - -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 (it->it_seq != NULL) { - if (index < 0) - index = 0; - else if (index > PyByteArray_GET_SIZE(it->it_seq)) - index = PyByteArray_GET_SIZE(it->it_seq); /* iterator exhausted */ - it->it_index = index; - } - Py_RETURN_NONE; -} - -PyDoc_STRVAR(setstate_doc, "Set state information for unpickling."); - -static PyMethodDef bytearrayiter_methods[] = { - {"__length_hint__", (PyCFunction)bytearrayiter_length_hint, METH_NOARGS, - length_hint_doc}, - {"__reduce__", (PyCFunction)bytearrayiter_reduce, METH_NOARGS, - bytearray_reduce__doc__}, - {"__setstate__", (PyCFunction)bytearrayiter_setstate, METH_O, - setstate_doc}, - {NULL, NULL} /* sentinel */ -}; - -PyTypeObject PyByteArrayIter_Type = { - PyVarObject_HEAD_INIT(&PyType_Type, 0) - "bytearray_iterator", /* tp_name */ - sizeof(bytesiterobject), /* tp_basicsize */ - 0, /* tp_itemsize */ - /* methods */ - (destructor)bytearrayiter_dealloc, /* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_reserved */ - 0, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - PyObject_GenericGetAttr, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */ - 0, /* tp_doc */ - (traverseproc)bytearrayiter_traverse, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - PyObject_SelfIter, /* tp_iter */ - (iternextfunc)bytearrayiter_next, /* tp_iternext */ - bytearrayiter_methods, /* tp_methods */ - 0, -}; - -static PyObject * -bytearray_iter(PyObject *seq) -{ - bytesiterobject *it; - - if (!PyByteArray_Check(seq)) { - PyErr_BadInternalCall(); - return NULL; - } - it = PyObject_GC_New(bytesiterobject, &PyByteArrayIter_Type); - if (it == NULL) - return NULL; - it->it_index = 0; - Py_INCREF(seq); - it->it_seq = (PyByteArrayObject *)seq; - _PyObject_GC_TRACK(it); - return (PyObject *)it; -} +/*[clinic end generated code: output=70ea384faeca8d16 input=a9049054013a1b77]*/ diff --git a/Objects/bytesobject.c b/Objects/clinic/bytesobject.c.h copy from Objects/bytesobject.c copy to Objects/clinic/bytesobject.c.h --- a/Objects/bytesobject.c +++ b/Objects/clinic/bytesobject.c.h @@ -1,1617 +1,5 @@ -/* bytes object implementation */ - -#define PY_SSIZE_T_CLEAN - -#include "Python.h" - -#include "bytes_methods.h" -#include - /*[clinic input] -class bytes "PyBytesObject*" "&PyBytes_Type" -[clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=1a1d9102afc1b00c]*/ - -#ifdef COUNT_ALLOCS -Py_ssize_t null_strings, one_strings; -#endif - -static PyBytesObject *characters[UCHAR_MAX + 1]; -static PyBytesObject *nullstring; - -/* PyBytesObject_SIZE gives the basic size of a string; any memory allocation - for a string of length n should request PyBytesObject_SIZE + n bytes. - - Using PyBytesObject_SIZE instead of sizeof(PyBytesObject) saves - 3 bytes per string allocation on a typical system. -*/ -#define PyBytesObject_SIZE (offsetof(PyBytesObject, ob_sval) + 1) - -/* - For PyBytes_FromString(), the parameter `str' points to a null-terminated - string containing exactly `size' bytes. - - For PyBytes_FromStringAndSize(), the parameter the parameter `str' is - either NULL or else points to a string containing at least `size' bytes. - For PyBytes_FromStringAndSize(), the string in the `str' parameter does - not have to be null-terminated. (Therefore it is safe to construct a - substring by calling `PyBytes_FromStringAndSize(origstring, substrlen)'.) - If `str' is NULL then PyBytes_FromStringAndSize() will allocate `size+1' - bytes (setting the last byte to the null terminating character) and you can - fill in the data yourself. If `str' is non-NULL then the resulting - PyBytes object must be treated as immutable and you must not fill in nor - alter the data yourself, since the strings may be shared. - - The PyObject member `op->ob_size', which denotes the number of "extra - items" in a variable-size object, will contain the number of bytes - allocated for string data, not counting the null terminating character. - It is therefore equal to the `size' parameter (for - PyBytes_FromStringAndSize()) or the length of the string in the `str' - parameter (for PyBytes_FromString()). -*/ -static PyObject * -_PyBytes_FromSize(Py_ssize_t size, int use_calloc) -{ - PyBytesObject *op; - assert(size >= 0); - - if (size == 0 && (op = nullstring) != NULL) { -#ifdef COUNT_ALLOCS - null_strings++; -#endif - Py_INCREF(op); - return (PyObject *)op; - } - - if ((size_t)size > (size_t)PY_SSIZE_T_MAX - PyBytesObject_SIZE) { - PyErr_SetString(PyExc_OverflowError, - "byte string is too large"); - return NULL; - } - - /* Inline PyObject_NewVar */ - if (use_calloc) - op = (PyBytesObject *)PyObject_Calloc(1, PyBytesObject_SIZE + size); - else - op = (PyBytesObject *)PyObject_Malloc(PyBytesObject_SIZE + size); - if (op == NULL) - return PyErr_NoMemory(); - (void)PyObject_INIT_VAR(op, &PyBytes_Type, size); - op->ob_shash = -1; - if (!use_calloc) - op->ob_sval[size] = '\0'; - /* empty byte string singleton */ - if (size == 0) { - nullstring = op; - Py_INCREF(op); - } - return (PyObject *) op; -} - -PyObject * -PyBytes_FromStringAndSize(const char *str, Py_ssize_t size) -{ - PyBytesObject *op; - if (size < 0) { - PyErr_SetString(PyExc_SystemError, - "Negative size passed to PyBytes_FromStringAndSize"); - return NULL; - } - if (size == 1 && str != NULL && - (op = characters[*str & UCHAR_MAX]) != NULL) - { -#ifdef COUNT_ALLOCS - one_strings++; -#endif - Py_INCREF(op); - return (PyObject *)op; - } - - op = (PyBytesObject *)_PyBytes_FromSize(size, 0); - if (op == NULL) - return NULL; - if (str == NULL) - return (PyObject *) op; - - Py_MEMCPY(op->ob_sval, str, size); - /* share short strings */ - if (size == 1) { - characters[*str & UCHAR_MAX] = op; - Py_INCREF(op); - } - return (PyObject *) op; -} - -PyObject * -PyBytes_FromString(const char *str) -{ - size_t size; - PyBytesObject *op; - - assert(str != NULL); - size = strlen(str); - if (size > PY_SSIZE_T_MAX - PyBytesObject_SIZE) { - PyErr_SetString(PyExc_OverflowError, - "byte string is too long"); - return NULL; - } - if (size == 0 && (op = nullstring) != NULL) { -#ifdef COUNT_ALLOCS - null_strings++; -#endif - Py_INCREF(op); - return (PyObject *)op; - } - if (size == 1 && (op = characters[*str & UCHAR_MAX]) != NULL) { -#ifdef COUNT_ALLOCS - one_strings++; -#endif - Py_INCREF(op); - return (PyObject *)op; - } - - /* Inline PyObject_NewVar */ - op = (PyBytesObject *)PyObject_MALLOC(PyBytesObject_SIZE + size); - if (op == NULL) - return PyErr_NoMemory(); - (void)PyObject_INIT_VAR(op, &PyBytes_Type, size); - op->ob_shash = -1; - Py_MEMCPY(op->ob_sval, str, size+1); - /* share short strings */ - if (size == 0) { - nullstring = op; - Py_INCREF(op); - } else if (size == 1) { - characters[*str & UCHAR_MAX] = op; - Py_INCREF(op); - } - return (PyObject *) op; -} - -PyObject * -PyBytes_FromFormatV(const char *format, va_list vargs) -{ - va_list count; - Py_ssize_t n = 0; - const char* f; - char *s; - PyObject* string; - - Py_VA_COPY(count, vargs); - /* step 1: figure out how large a buffer we need */ - for (f = format; *f; f++) { - if (*f == '%') { - const char* p = f; - while (*++f && *f != '%' && !Py_ISALPHA(*f)) - ; - - /* skip the 'l' or 'z' in {%ld, %zd, %lu, %zu} since - * they don't affect the amount of space we reserve. - */ - if ((*f == 'l' || *f == 'z') && - (f[1] == 'd' || f[1] == 'u')) - ++f; - - switch (*f) { - case 'c': - { - int c = va_arg(count, int); - if (c < 0 || c > 255) { - PyErr_SetString(PyExc_OverflowError, - "PyBytes_FromFormatV(): %c format " - "expects an integer in range [0; 255]"); - return NULL; - } - n++; - break; - } - case '%': - n++; - break; - case 'd': case 'u': case 'i': case 'x': - (void) va_arg(count, int); - /* 20 bytes is enough to hold a 64-bit - integer. Decimal takes the most space. - This isn't enough for octal. */ - n += 20; - break; - case 's': - s = va_arg(count, char*); - n += strlen(s); - break; - case 'p': - (void) va_arg(count, int); - /* maximum 64-bit pointer representation: - * 0xffffffffffffffff - * so 19 characters is enough. - * XXX I count 18 -- what's the extra for? - */ - n += 19; - break; - default: - /* if we stumble upon an unknown - formatting code, copy the rest of - the format string to the output - string. (we cannot just skip the - code, since there's no way to know - what's in the argument list) */ - n += strlen(p); - goto expand; - } - } else - n++; - } - expand: - /* step 2: fill the buffer */ - /* Since we've analyzed how much space we need for the worst case, - use sprintf directly instead of the slower PyOS_snprintf. */ - string = PyBytes_FromStringAndSize(NULL, n); - if (!string) - return NULL; - - s = PyBytes_AsString(string); - - for (f = format; *f; f++) { - if (*f == '%') { - const char* p = f++; - Py_ssize_t i; - int longflag = 0; - int size_tflag = 0; - /* parse the width.precision part (we're only - interested in the precision value, if any) */ - n = 0; - while (Py_ISDIGIT(*f)) - n = (n*10) + *f++ - '0'; - if (*f == '.') { - f++; - n = 0; - while (Py_ISDIGIT(*f)) - n = (n*10) + *f++ - '0'; - } - while (*f && *f != '%' && !Py_ISALPHA(*f)) - f++; - /* handle the long flag, but only for %ld and %lu. - others can be added when necessary. */ - if (*f == 'l' && (f[1] == 'd' || f[1] == 'u')) { - longflag = 1; - ++f; - } - /* handle the size_t flag. */ - if (*f == 'z' && (f[1] == 'd' || f[1] == 'u')) { - size_tflag = 1; - ++f; - } - - switch (*f) { - case 'c': - { - int c = va_arg(vargs, int); - /* c has been checked for overflow in the first step */ - *s++ = (unsigned char)c; - break; - } - case 'd': - if (longflag) - sprintf(s, "%ld", va_arg(vargs, long)); - else if (size_tflag) - sprintf(s, "%" PY_FORMAT_SIZE_T "d", - va_arg(vargs, Py_ssize_t)); - else - sprintf(s, "%d", va_arg(vargs, int)); - s += strlen(s); - break; - case 'u': - if (longflag) - sprintf(s, "%lu", - va_arg(vargs, unsigned long)); - else if (size_tflag) - sprintf(s, "%" PY_FORMAT_SIZE_T "u", - va_arg(vargs, size_t)); - else - sprintf(s, "%u", - va_arg(vargs, unsigned int)); - s += strlen(s); - break; - case 'i': - sprintf(s, "%i", va_arg(vargs, int)); - s += strlen(s); - break; - case 'x': - sprintf(s, "%x", va_arg(vargs, int)); - s += strlen(s); - break; - case 's': - p = va_arg(vargs, char*); - i = strlen(p); - if (n > 0 && i > n) - i = n; - Py_MEMCPY(s, p, i); - s += i; - break; - case 'p': - sprintf(s, "%p", va_arg(vargs, void*)); - /* %p is ill-defined: ensure leading 0x. */ - if (s[1] == 'X') - s[1] = 'x'; - else if (s[1] != 'x') { - memmove(s+2, s, strlen(s)+1); - s[0] = '0'; - s[1] = 'x'; - } - s += strlen(s); - break; - case '%': - *s++ = '%'; - break; - default: - strcpy(s, p); - s += strlen(s); - goto end; - } - } else - *s++ = *f; - } - - end: - _PyBytes_Resize(&string, s - PyBytes_AS_STRING(string)); - return string; -} - -PyObject * -PyBytes_FromFormat(const char *format, ...) -{ - PyObject* ret; - va_list vargs; - -#ifdef HAVE_STDARG_PROTOTYPES - va_start(vargs, format); -#else - va_start(vargs); -#endif - ret = PyBytes_FromFormatV(format, vargs); - va_end(vargs); - return ret; -} - -/* Helpers for formatstring */ - -Py_LOCAL_INLINE(PyObject *) -getnextarg(PyObject *args, Py_ssize_t arglen, Py_ssize_t *p_argidx) -{ - Py_ssize_t argidx = *p_argidx; - if (argidx < arglen) { - (*p_argidx)++; - if (arglen < 0) - return args; - else - return PyTuple_GetItem(args, argidx); - } - PyErr_SetString(PyExc_TypeError, - "not enough arguments for format string"); - return NULL; -} - -/* Format codes - * F_LJUST '-' - * F_SIGN '+' - * F_BLANK ' ' - * F_ALT '#' - * F_ZERO '0' - */ -#define F_LJUST (1<<0) -#define F_SIGN (1<<1) -#define F_BLANK (1<<2) -#define F_ALT (1<<3) -#define F_ZERO (1<<4) - -/* Returns a new reference to a PyBytes object, or NULL on failure. */ - -static PyObject * -formatfloat(PyObject *v, int flags, int prec, int type) -{ - char *p; - PyObject *result; - double x; - - x = PyFloat_AsDouble(v); - if (x == -1.0 && PyErr_Occurred()) { - PyErr_Format(PyExc_TypeError, "float argument required, " - "not %.200s", Py_TYPE(v)->tp_name); - return NULL; - } - - if (prec < 0) - prec = 6; - - p = PyOS_double_to_string(x, type, prec, - (flags & F_ALT) ? Py_DTSF_ALT : 0, NULL); - - if (p == NULL) - return NULL; - result = PyBytes_FromStringAndSize(p, strlen(p)); - PyMem_Free(p); - return result; -} - -static PyObject * -formatlong(PyObject *v, int flags, int prec, int type) -{ - PyObject *result, *iobj; - if (type == 'i') - type = 'd'; - if (PyLong_Check(v)) - return _PyUnicode_FormatLong(v, flags & F_ALT, prec, type); - if (PyNumber_Check(v)) { - /* make sure number is a type of integer for o, x, and X */ - if (type == 'o' || type == 'x' || type == 'X') - iobj = PyNumber_Index(v); - else - iobj = PyNumber_Long(v); - if (iobj == NULL) { - if (!PyErr_ExceptionMatches(PyExc_TypeError)) - return NULL; - } - else if (!PyLong_Check(iobj)) - Py_CLEAR(iobj); - if (iobj != NULL) { - result = _PyUnicode_FormatLong(iobj, flags & F_ALT, prec, type); - Py_DECREF(iobj); - return result; - } - } - PyErr_Format(PyExc_TypeError, - "%%%c format: %s is required, not %.200s", type, - (type == 'o' || type == 'x' || type == 'X') ? "an integer" - : "a number", - Py_TYPE(v)->tp_name); - return NULL; -} - -static int -byte_converter(PyObject *arg, char *p) -{ - if (PyBytes_Check(arg) && PyBytes_Size(arg) == 1) { - *p = PyBytes_AS_STRING(arg)[0]; - return 1; - } - else if (PyByteArray_Check(arg) && PyByteArray_Size(arg) == 1) { - *p = PyByteArray_AS_STRING(arg)[0]; - return 1; - } - else { - PyObject *iobj; - long ival; - int overflow; - /* make sure number is a type of integer */ - if (PyLong_Check(arg)) { - ival = PyLong_AsLongAndOverflow(arg, &overflow); - } - else { - iobj = PyNumber_Index(arg); - if (iobj == NULL) { - if (!PyErr_ExceptionMatches(PyExc_TypeError)) - return 0; - goto onError; - } - ival = PyLong_AsLongAndOverflow(iobj, &overflow); - Py_DECREF(iobj); - } - if (!overflow && ival == -1 && PyErr_Occurred()) - goto onError; - if (overflow || !(0 <= ival && ival <= 255)) { - PyErr_SetString(PyExc_OverflowError, - "%c arg not in range(256)"); - return 0; - } - *p = (char)ival; - return 1; - } - onError: - PyErr_SetString(PyExc_TypeError, - "%c requires an integer in range(256) or a single byte"); - return 0; -} - -static PyObject * -format_obj(PyObject *v, const char **pbuf, Py_ssize_t *plen) -{ - PyObject *func, *result; - _Py_IDENTIFIER(__bytes__); - /* is it a bytes object? */ - if (PyBytes_Check(v)) { - *pbuf = PyBytes_AS_STRING(v); - *plen = PyBytes_GET_SIZE(v); - Py_INCREF(v); - return v; - } - if (PyByteArray_Check(v)) { - *pbuf = PyByteArray_AS_STRING(v); - *plen = PyByteArray_GET_SIZE(v); - Py_INCREF(v); - return v; - } - /* does it support __bytes__? */ - func = _PyObject_LookupSpecial(v, &PyId___bytes__); - if (func != NULL) { - result = PyObject_CallFunctionObjArgs(func, NULL); - Py_DECREF(func); - if (result == NULL) - return NULL; - if (!PyBytes_Check(result)) { - PyErr_Format(PyExc_TypeError, - "__bytes__ returned non-bytes (type %.200s)", - Py_TYPE(result)->tp_name); - Py_DECREF(result); - return NULL; - } - *pbuf = PyBytes_AS_STRING(result); - *plen = PyBytes_GET_SIZE(result); - return result; - } - PyErr_Format(PyExc_TypeError, - "%%b requires bytes, or an object that implements __bytes__, not '%.100s'", - Py_TYPE(v)->tp_name); - return NULL; -} - -/* fmt%(v1,v2,...) is roughly equivalent to sprintf(fmt, v1, v2, ...) - - FORMATBUFLEN is the length of the buffer in which the ints & - chars are formatted. XXX This is a magic number. Each formatting - routine does bounds checking to ensure no overflow, but a better - solution may be to malloc a buffer of appropriate size for each - format. For now, the current solution is sufficient. -*/ -#define FORMATBUFLEN (size_t)120 - -PyObject * -_PyBytes_Format(PyObject *format, PyObject *args) -{ - char *fmt, *res; - Py_ssize_t arglen, argidx; - Py_ssize_t reslen, rescnt, fmtcnt; - int args_owned = 0; - PyObject *result; - PyObject *dict = NULL; - if (format == NULL || !PyBytes_Check(format) || args == NULL) { - PyErr_BadInternalCall(); - return NULL; - } - fmt = PyBytes_AS_STRING(format); - fmtcnt = PyBytes_GET_SIZE(format); - reslen = rescnt = fmtcnt + 100; - result = PyBytes_FromStringAndSize((char *)NULL, reslen); - if (result == NULL) - return NULL; - res = PyBytes_AsString(result); - if (PyTuple_Check(args)) { - arglen = PyTuple_GET_SIZE(args); - argidx = 0; - } - else { - arglen = -1; - argidx = -2; - } - if (Py_TYPE(args)->tp_as_mapping && Py_TYPE(args)->tp_as_mapping->mp_subscript && - !PyTuple_Check(args) && !PyBytes_Check(args) && !PyUnicode_Check(args) && - !PyByteArray_Check(args)) { - dict = args; - } - while (--fmtcnt >= 0) { - if (*fmt != '%') { - if (--rescnt < 0) { - rescnt = fmtcnt + 100; - reslen += rescnt; - if (_PyBytes_Resize(&result, reslen)) - return NULL; - res = PyBytes_AS_STRING(result) - + reslen - rescnt; - --rescnt; - } - *res++ = *fmt++; - } - else { - /* Got a format specifier */ - int flags = 0; - Py_ssize_t width = -1; - int prec = -1; - int c = '\0'; - int fill; - PyObject *v = NULL; - PyObject *temp = NULL; - const char *pbuf = NULL; - int sign; - Py_ssize_t len = 0; - char onechar; /* For byte_converter() */ - - fmt++; - if (*fmt == '(') { - char *keystart; - Py_ssize_t keylen; - PyObject *key; - int pcount = 1; - - if (dict == NULL) { - PyErr_SetString(PyExc_TypeError, - "format requires a mapping"); - goto error; - } - ++fmt; - --fmtcnt; - keystart = fmt; - /* Skip over balanced parentheses */ - while (pcount > 0 && --fmtcnt >= 0) { - if (*fmt == ')') - --pcount; - else if (*fmt == '(') - ++pcount; - fmt++; - } - keylen = fmt - keystart - 1; - if (fmtcnt < 0 || pcount > 0) { - PyErr_SetString(PyExc_ValueError, - "incomplete format key"); - goto error; - } - key = PyBytes_FromStringAndSize(keystart, - keylen); - if (key == NULL) - goto error; - if (args_owned) { - Py_DECREF(args); - args_owned = 0; - } - args = PyObject_GetItem(dict, key); - Py_DECREF(key); - if (args == NULL) { - goto error; - } - args_owned = 1; - arglen = -1; - argidx = -2; - } - while (--fmtcnt >= 0) { - switch (c = *fmt++) { - case '-': flags |= F_LJUST; continue; - case '+': flags |= F_SIGN; continue; - case ' ': flags |= F_BLANK; continue; - case '#': flags |= F_ALT; continue; - case '0': flags |= F_ZERO; continue; - } - break; - } - if (c == '*') { - v = getnextarg(args, arglen, &argidx); - if (v == NULL) - goto error; - if (!PyLong_Check(v)) { - PyErr_SetString(PyExc_TypeError, - "* wants int"); - goto error; - } - width = PyLong_AsSsize_t(v); - if (width == -1 && PyErr_Occurred()) - goto error; - if (width < 0) { - flags |= F_LJUST; - width = -width; - } - if (--fmtcnt >= 0) - c = *fmt++; - } - else if (c >= 0 && isdigit(c)) { - width = c - '0'; - while (--fmtcnt >= 0) { - c = Py_CHARMASK(*fmt++); - if (!isdigit(c)) - break; - if (width > (PY_SSIZE_T_MAX - ((int)c - '0')) / 10) { - PyErr_SetString( - PyExc_ValueError, - "width too big"); - goto error; - } - width = width*10 + (c - '0'); - } - } - if (c == '.') { - prec = 0; - if (--fmtcnt >= 0) - c = *fmt++; - if (c == '*') { - v = getnextarg(args, arglen, &argidx); - if (v == NULL) - goto error; - if (!PyLong_Check(v)) { - PyErr_SetString( - PyExc_TypeError, - "* wants int"); - goto error; - } - prec = _PyLong_AsInt(v); - if (prec == -1 && PyErr_Occurred()) - goto error; - if (prec < 0) - prec = 0; - if (--fmtcnt >= 0) - c = *fmt++; - } - else if (c >= 0 && isdigit(c)) { - prec = c - '0'; - while (--fmtcnt >= 0) { - c = Py_CHARMASK(*fmt++); - if (!isdigit(c)) - break; - if (prec > (INT_MAX - ((int)c - '0')) / 10) { - PyErr_SetString( - PyExc_ValueError, - "prec too big"); - goto error; - } - prec = prec*10 + (c - '0'); - } - } - } /* prec */ - if (fmtcnt >= 0) { - if (c == 'h' || c == 'l' || c == 'L') { - if (--fmtcnt >= 0) - c = *fmt++; - } - } - if (fmtcnt < 0) { - PyErr_SetString(PyExc_ValueError, - "incomplete format"); - goto error; - } - if (c != '%') { - v = getnextarg(args, arglen, &argidx); - if (v == NULL) - goto error; - } - sign = 0; - fill = ' '; - switch (c) { - case '%': - pbuf = "%"; - len = 1; - break; - case 'r': - // %r is only for 2/3 code; 3 only code should use %a - case 'a': - temp = PyObject_ASCII(v); - if (temp == NULL) - goto error; - assert(PyUnicode_IS_ASCII(temp)); - pbuf = (const char *)PyUnicode_1BYTE_DATA(temp); - len = PyUnicode_GET_LENGTH(temp); - if (prec >= 0 && len > prec) - len = prec; - break; - case 's': - // %s is only for 2/3 code; 3 only code should use %b - case 'b': - temp = format_obj(v, &pbuf, &len); - if (temp == NULL) - goto error; - if (prec >= 0 && len > prec) - len = prec; - break; - case 'i': - case 'd': - case 'u': - case 'o': - case 'x': - case 'X': - temp = formatlong(v, flags, prec, c); - if (!temp) - goto error; - assert(PyUnicode_IS_ASCII(temp)); - pbuf = (const char *)PyUnicode_1BYTE_DATA(temp); - len = PyUnicode_GET_LENGTH(temp); - sign = 1; - if (flags & F_ZERO) - fill = '0'; - break; - case 'e': - case 'E': - case 'f': - case 'F': - case 'g': - case 'G': - temp = formatfloat(v, flags, prec, c); - if (temp == NULL) - goto error; - pbuf = PyBytes_AS_STRING(temp); - len = PyBytes_GET_SIZE(temp); - sign = 1; - if (flags & F_ZERO) - fill = '0'; - break; - case 'c': - pbuf = &onechar; - len = byte_converter(v, &onechar); - if (!len) - goto error; - break; - default: - PyErr_Format(PyExc_ValueError, - "unsupported format character '%c' (0x%x) " - "at index %zd", - c, c, - (Py_ssize_t)(fmt - 1 - - PyBytes_AsString(format))); - goto error; - } - if (sign) { - if (*pbuf == '-' || *pbuf == '+') { - sign = *pbuf++; - len--; - } - else if (flags & F_SIGN) - sign = '+'; - else if (flags & F_BLANK) - sign = ' '; - else - sign = 0; - } - if (width < len) - width = len; - if (rescnt - (sign != 0) < width) { - reslen -= rescnt; - rescnt = width + fmtcnt + 100; - reslen += rescnt; - if (reslen < 0) { - Py_DECREF(result); - Py_XDECREF(temp); - return PyErr_NoMemory(); - } - if (_PyBytes_Resize(&result, reslen)) { - Py_XDECREF(temp); - return NULL; - } - res = PyBytes_AS_STRING(result) - + reslen - rescnt; - } - if (sign) { - if (fill != ' ') - *res++ = sign; - rescnt--; - if (width > len) - width--; - } - if ((flags & F_ALT) && (c == 'x' || c == 'X')) { - assert(pbuf[0] == '0'); - assert(pbuf[1] == c); - if (fill != ' ') { - *res++ = *pbuf++; - *res++ = *pbuf++; - } - rescnt -= 2; - width -= 2; - if (width < 0) - width = 0; - len -= 2; - } - if (width > len && !(flags & F_LJUST)) { - do { - --rescnt; - *res++ = fill; - } while (--width > len); - } - if (fill == ' ') { - if (sign) - *res++ = sign; - if ((flags & F_ALT) && - (c == 'x' || c == 'X')) { - assert(pbuf[0] == '0'); - assert(pbuf[1] == c); - *res++ = *pbuf++; - *res++ = *pbuf++; - } - } - Py_MEMCPY(res, pbuf, len); - res += len; - rescnt -= len; - while (--width >= len) { - --rescnt; - *res++ = ' '; - } - if (dict && (argidx < arglen) && c != '%') { - PyErr_SetString(PyExc_TypeError, - "not all arguments converted during bytes formatting"); - Py_XDECREF(temp); - goto error; - } - Py_XDECREF(temp); - } /* '%' */ - } /* until end */ - if (argidx < arglen && !dict) { - PyErr_SetString(PyExc_TypeError, - "not all arguments converted during bytes formatting"); - goto error; - } - if (args_owned) { - Py_DECREF(args); - } - if (_PyBytes_Resize(&result, reslen - rescnt)) - return NULL; - return result; - - error: - Py_DECREF(result); - if (args_owned) { - Py_DECREF(args); - } - return NULL; -} - -/* =-= */ - -static void -bytes_dealloc(PyObject *op) -{ - Py_TYPE(op)->tp_free(op); -} - -/* Unescape a backslash-escaped string. If unicode is non-zero, - the string is a u-literal. If recode_encoding is non-zero, - the string is UTF-8 encoded and should be re-encoded in the - specified encoding. */ - -PyObject *PyBytes_DecodeEscape(const char *s, - Py_ssize_t len, - const char *errors, - Py_ssize_t unicode, - const char *recode_encoding) -{ - int c; - char *p, *buf; - const char *end; - PyObject *v; - Py_ssize_t newlen = recode_encoding ? 4*len:len; - v = PyBytes_FromStringAndSize((char *)NULL, newlen); - if (v == NULL) - return NULL; - p = buf = PyBytes_AsString(v); - end = s + len; - while (s < end) { - if (*s != '\\') { - non_esc: - if (recode_encoding && (*s & 0x80)) { - PyObject *u, *w; - char *r; - const char* t; - Py_ssize_t rn; - t = s; - /* Decode non-ASCII bytes as UTF-8. */ - while (t < end && (*t & 0x80)) t++; - u = PyUnicode_DecodeUTF8(s, t - s, errors); - if(!u) goto failed; - - /* Recode them in target encoding. */ - w = PyUnicode_AsEncodedString( - u, recode_encoding, errors); - Py_DECREF(u); - if (!w) goto failed; - - /* Append bytes to output buffer. */ - assert(PyBytes_Check(w)); - r = PyBytes_AS_STRING(w); - rn = PyBytes_GET_SIZE(w); - Py_MEMCPY(p, r, rn); - p += rn; - Py_DECREF(w); - s = t; - } else { - *p++ = *s++; - } - continue; - } - s++; - if (s==end) { - PyErr_SetString(PyExc_ValueError, - "Trailing \\ in string"); - goto failed; - } - switch (*s++) { - /* XXX This assumes ASCII! */ - case '\n': break; - case '\\': *p++ = '\\'; break; - case '\'': *p++ = '\''; break; - case '\"': *p++ = '\"'; break; - case 'b': *p++ = '\b'; break; - case 'f': *p++ = '\014'; break; /* FF */ - case 't': *p++ = '\t'; break; - case 'n': *p++ = '\n'; break; - case 'r': *p++ = '\r'; break; - case 'v': *p++ = '\013'; break; /* VT */ - case 'a': *p++ = '\007'; break; /* BEL, not classic C */ - case '0': case '1': case '2': case '3': - case '4': case '5': case '6': case '7': - c = s[-1] - '0'; - if (s < end && '0' <= *s && *s <= '7') { - c = (c<<3) + *s++ - '0'; - if (s < end && '0' <= *s && *s <= '7') - c = (c<<3) + *s++ - '0'; - } - *p++ = c; - break; - case 'x': - if (s+1 < end && Py_ISXDIGIT(s[0]) && Py_ISXDIGIT(s[1])) { - unsigned int x = 0; - c = Py_CHARMASK(*s); - s++; - if (Py_ISDIGIT(c)) - x = c - '0'; - else if (Py_ISLOWER(c)) - x = 10 + c - 'a'; - else - x = 10 + c - 'A'; - x = x << 4; - c = Py_CHARMASK(*s); - s++; - if (Py_ISDIGIT(c)) - x += c - '0'; - else if (Py_ISLOWER(c)) - x += 10 + c - 'a'; - else - x += 10 + c - 'A'; - *p++ = x; - break; - } - if (!errors || strcmp(errors, "strict") == 0) { - PyErr_Format(PyExc_ValueError, - "invalid \\x escape at position %d", - s - 2 - (end - len)); - goto failed; - } - if (strcmp(errors, "replace") == 0) { - *p++ = '?'; - } else if (strcmp(errors, "ignore") == 0) - /* do nothing */; - else { - PyErr_Format(PyExc_ValueError, - "decoding error; unknown " - "error handling code: %.400s", - errors); - goto failed; - } - /* skip \x */ - if (s < end && Py_ISXDIGIT(s[0])) - s++; /* and a hexdigit */ - break; - default: - *p++ = '\\'; - s--; - goto non_esc; /* an arbitrary number of unescaped - UTF-8 bytes may follow. */ - } - } - if (p-buf < newlen) - _PyBytes_Resize(&v, p - buf); - return v; - failed: - Py_DECREF(v); - return NULL; -} - -/* -------------------------------------------------------------------- */ -/* object api */ - -Py_ssize_t -PyBytes_Size(PyObject *op) -{ - if (!PyBytes_Check(op)) { - PyErr_Format(PyExc_TypeError, - "expected bytes, %.200s found", Py_TYPE(op)->tp_name); - return -1; - } - return Py_SIZE(op); -} - -char * -PyBytes_AsString(PyObject *op) -{ - if (!PyBytes_Check(op)) { - PyErr_Format(PyExc_TypeError, - "expected bytes, %.200s found", Py_TYPE(op)->tp_name); - return NULL; - } - return ((PyBytesObject *)op)->ob_sval; -} - -int -PyBytes_AsStringAndSize(PyObject *obj, - char **s, - Py_ssize_t *len) -{ - if (s == NULL) { - PyErr_BadInternalCall(); - return -1; - } - - if (!PyBytes_Check(obj)) { - PyErr_Format(PyExc_TypeError, - "expected bytes, %.200s found", Py_TYPE(obj)->tp_name); - return -1; - } - - *s = PyBytes_AS_STRING(obj); - if (len != NULL) - *len = PyBytes_GET_SIZE(obj); - else if (strlen(*s) != (size_t)PyBytes_GET_SIZE(obj)) { - PyErr_SetString(PyExc_ValueError, - "embedded null byte"); - return -1; - } - return 0; -} - -/* -------------------------------------------------------------------- */ -/* Methods */ - -#include "stringlib/stringdefs.h" - -#include "stringlib/fastsearch.h" -#include "stringlib/count.h" -#include "stringlib/find.h" -#include "stringlib/join.h" -#include "stringlib/partition.h" -#include "stringlib/split.h" -#include "stringlib/ctype.h" - -#include "stringlib/transmogrify.h" - -PyObject * -PyBytes_Repr(PyObject *obj, int smartquotes) -{ - PyBytesObject* op = (PyBytesObject*) obj; - Py_ssize_t i, length = Py_SIZE(op); - Py_ssize_t newsize, squotes, dquotes; - PyObject *v; - unsigned char quote, *s, *p; - - /* Compute size of output string */ - squotes = dquotes = 0; - newsize = 3; /* b'' */ - s = (unsigned char*)op->ob_sval; - for (i = 0; i < length; i++) { - Py_ssize_t incr = 1; - switch(s[i]) { - case '\'': squotes++; break; - case '"': dquotes++; break; - case '\\': case '\t': case '\n': case '\r': - incr = 2; break; /* \C */ - default: - if (s[i] < ' ' || s[i] >= 0x7f) - incr = 4; /* \xHH */ - } - if (newsize > PY_SSIZE_T_MAX - incr) - goto overflow; - newsize += incr; - } - quote = '\''; - if (smartquotes && squotes && !dquotes) - quote = '"'; - if (squotes && quote == '\'') { - if (newsize > PY_SSIZE_T_MAX - squotes) - goto overflow; - newsize += squotes; - } - - v = PyUnicode_New(newsize, 127); - if (v == NULL) { - return NULL; - } - p = PyUnicode_1BYTE_DATA(v); - - *p++ = 'b', *p++ = quote; - for (i = 0; i < length; i++) { - unsigned char c = op->ob_sval[i]; - if (c == quote || c == '\\') - *p++ = '\\', *p++ = c; - else if (c == '\t') - *p++ = '\\', *p++ = 't'; - else if (c == '\n') - *p++ = '\\', *p++ = 'n'; - else if (c == '\r') - *p++ = '\\', *p++ = 'r'; - else if (c < ' ' || c >= 0x7f) { - *p++ = '\\'; - *p++ = 'x'; - *p++ = Py_hexdigits[(c & 0xf0) >> 4]; - *p++ = Py_hexdigits[c & 0xf]; - } - else - *p++ = c; - } - *p++ = quote; - assert(_PyUnicode_CheckConsistency(v, 1)); - return v; - - overflow: - PyErr_SetString(PyExc_OverflowError, - "bytes object is too large to make repr"); - return NULL; -} - -static PyObject * -bytes_repr(PyObject *op) -{ - return PyBytes_Repr(op, 1); -} - -static PyObject * -bytes_str(PyObject *op) -{ - if (Py_BytesWarningFlag) { - if (PyErr_WarnEx(PyExc_BytesWarning, - "str() on a bytes instance", 1)) - return NULL; - } - return bytes_repr(op); -} - -static Py_ssize_t -bytes_length(PyBytesObject *a) -{ - return Py_SIZE(a); -} - -/* This is also used by PyBytes_Concat() */ -static PyObject * -bytes_concat(PyObject *a, PyObject *b) -{ - Py_ssize_t size; - Py_buffer va, vb; - PyObject *result = NULL; - - va.len = -1; - vb.len = -1; - if (PyObject_GetBuffer(a, &va, PyBUF_SIMPLE) != 0 || - PyObject_GetBuffer(b, &vb, PyBUF_SIMPLE) != 0) { - PyErr_Format(PyExc_TypeError, "can't concat %.100s to %.100s", - Py_TYPE(a)->tp_name, Py_TYPE(b)->tp_name); - goto done; - } - - /* Optimize end cases */ - if (va.len == 0 && PyBytes_CheckExact(b)) { - result = b; - Py_INCREF(result); - goto done; - } - if (vb.len == 0 && PyBytes_CheckExact(a)) { - result = a; - Py_INCREF(result); - goto done; - } - - size = va.len + vb.len; - if (size < 0) { - PyErr_NoMemory(); - goto done; - } - - result = PyBytes_FromStringAndSize(NULL, size); - if (result != NULL) { - memcpy(PyBytes_AS_STRING(result), va.buf, va.len); - memcpy(PyBytes_AS_STRING(result) + va.len, vb.buf, vb.len); - } - - done: - if (va.len != -1) - PyBuffer_Release(&va); - if (vb.len != -1) - PyBuffer_Release(&vb); - return result; -} - -static PyObject * -bytes_repeat(PyBytesObject *a, Py_ssize_t n) -{ - Py_ssize_t i; - Py_ssize_t j; - Py_ssize_t size; - PyBytesObject *op; - size_t nbytes; - if (n < 0) - n = 0; - /* watch out for overflows: the size can overflow int, - * and the # of bytes needed can overflow size_t - */ - if (n > 0 && Py_SIZE(a) > PY_SSIZE_T_MAX / n) { - PyErr_SetString(PyExc_OverflowError, - "repeated bytes are too long"); - return NULL; - } - size = Py_SIZE(a) * n; - if (size == Py_SIZE(a) && PyBytes_CheckExact(a)) { - Py_INCREF(a); - return (PyObject *)a; - } - nbytes = (size_t)size; - if (nbytes + PyBytesObject_SIZE <= nbytes) { - PyErr_SetString(PyExc_OverflowError, - "repeated bytes are too long"); - return NULL; - } - op = (PyBytesObject *)PyObject_MALLOC(PyBytesObject_SIZE + nbytes); - if (op == NULL) - return PyErr_NoMemory(); - (void)PyObject_INIT_VAR(op, &PyBytes_Type, size); - op->ob_shash = -1; - op->ob_sval[size] = '\0'; - if (Py_SIZE(a) == 1 && n > 0) { - memset(op->ob_sval, a->ob_sval[0] , n); - return (PyObject *) op; - } - i = 0; - if (i < size) { - Py_MEMCPY(op->ob_sval, a->ob_sval, Py_SIZE(a)); - i = Py_SIZE(a); - } - while (i < size) { - j = (i <= size-i) ? i : size-i; - Py_MEMCPY(op->ob_sval+i, op->ob_sval, j); - i += j; - } - return (PyObject *) op; -} - -static int -bytes_contains(PyObject *self, PyObject *arg) -{ - Py_ssize_t ival = PyNumber_AsSsize_t(arg, PyExc_ValueError); - if (ival == -1 && PyErr_Occurred()) { - Py_buffer varg; - Py_ssize_t pos; - PyErr_Clear(); - if (PyObject_GetBuffer(arg, &varg, PyBUF_SIMPLE) != 0) - return -1; - pos = stringlib_find(PyBytes_AS_STRING(self), Py_SIZE(self), - varg.buf, varg.len, 0); - PyBuffer_Release(&varg); - return pos >= 0; - } - if (ival < 0 || ival >= 256) { - PyErr_SetString(PyExc_ValueError, "byte must be in range(0, 256)"); - return -1; - } - - return memchr(PyBytes_AS_STRING(self), (int) ival, Py_SIZE(self)) != NULL; -} - -static PyObject * -bytes_item(PyBytesObject *a, Py_ssize_t i) -{ - if (i < 0 || i >= Py_SIZE(a)) { - PyErr_SetString(PyExc_IndexError, "index out of range"); - return NULL; - } - return PyLong_FromLong((unsigned char)a->ob_sval[i]); -} - -Py_LOCAL(int) -bytes_compare_eq(PyBytesObject *a, PyBytesObject *b) -{ - int cmp; - Py_ssize_t len; - - len = Py_SIZE(a); - if (Py_SIZE(b) != len) - return 0; - - if (a->ob_sval[0] != b->ob_sval[0]) - return 0; - - cmp = memcmp(a->ob_sval, b->ob_sval, len); - return (cmp == 0); -} - -static PyObject* -bytes_richcompare(PyBytesObject *a, PyBytesObject *b, int op) -{ - int c; - Py_ssize_t len_a, len_b; - Py_ssize_t min_len; - PyObject *result; - - /* Make sure both arguments are strings. */ - if (!(PyBytes_Check(a) && PyBytes_Check(b))) { - if (Py_BytesWarningFlag && (op == Py_EQ || op == Py_NE)) { - if (PyObject_IsInstance((PyObject*)a, - (PyObject*)&PyUnicode_Type) || - PyObject_IsInstance((PyObject*)b, - (PyObject*)&PyUnicode_Type)) { - if (PyErr_WarnEx(PyExc_BytesWarning, - "Comparison between bytes and string", 1)) - return NULL; - } - else if (PyObject_IsInstance((PyObject*)a, - (PyObject*)&PyLong_Type) || - PyObject_IsInstance((PyObject*)b, - (PyObject*)&PyLong_Type)) { - if (PyErr_WarnEx(PyExc_BytesWarning, - "Comparison between bytes and int", 1)) - return NULL; - } - } - result = Py_NotImplemented; - } - else if (a == b) { - switch (op) { - case Py_EQ: - case Py_LE: - case Py_GE: - /* a string is equal to itself */ - result = Py_True; - break; - case Py_NE: - case Py_LT: - case Py_GT: - result = Py_False; - break; - default: - PyErr_BadArgument(); - return NULL; - } - } - else if (op == Py_EQ || op == Py_NE) { - int eq = bytes_compare_eq(a, b); - eq ^= (op == Py_NE); - result = eq ? Py_True : Py_False; - } - else { - len_a = Py_SIZE(a); - len_b = Py_SIZE(b); - min_len = Py_MIN(len_a, len_b); - if (min_len > 0) { - c = Py_CHARMASK(*a->ob_sval) - Py_CHARMASK(*b->ob_sval); - if (c == 0) - c = memcmp(a->ob_sval, b->ob_sval, min_len); - } - else - c = 0; - if (c == 0) - c = (len_a < len_b) ? -1 : (len_a > len_b) ? 1 : 0; - switch (op) { - case Py_LT: c = c < 0; break; - case Py_LE: c = c <= 0; break; - case Py_GT: c = c > 0; break; - case Py_GE: c = c >= 0; break; - default: - PyErr_BadArgument(); - return NULL; - } - result = c ? Py_True : Py_False; - } - - Py_INCREF(result); - return result; -} - -static Py_hash_t -bytes_hash(PyBytesObject *a) -{ - if (a->ob_shash == -1) { - /* Can't fail */ - a->ob_shash = _Py_HashBytes(a->ob_sval, Py_SIZE(a)); - } - return a->ob_shash; -} - -static PyObject* -bytes_subscript(PyBytesObject* self, PyObject* item) -{ - if (PyIndex_Check(item)) { - Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError); - if (i == -1 && PyErr_Occurred()) - return NULL; - if (i < 0) - i += PyBytes_GET_SIZE(self); - if (i < 0 || i >= PyBytes_GET_SIZE(self)) { - PyErr_SetString(PyExc_IndexError, - "index out of range"); - return NULL; - } - return PyLong_FromLong((unsigned char)self->ob_sval[i]); - } - else if (PySlice_Check(item)) { - Py_ssize_t start, stop, step, slicelength, cur, i; - char* source_buf; - char* result_buf; - PyObject* result; - - if (PySlice_GetIndicesEx(item, - PyBytes_GET_SIZE(self), - &start, &stop, &step, &slicelength) < 0) { - return NULL; - } - - if (slicelength <= 0) { - return PyBytes_FromStringAndSize("", 0); - } - else if (start == 0 && step == 1 && - slicelength == PyBytes_GET_SIZE(self) && - PyBytes_CheckExact(self)) { - Py_INCREF(self); - return (PyObject *)self; - } - else if (step == 1) { - return PyBytes_FromStringAndSize( - PyBytes_AS_STRING(self) + start, - slicelength); - } - else { - source_buf = PyBytes_AS_STRING(self); - result = PyBytes_FromStringAndSize(NULL, slicelength); - if (result == NULL) - return NULL; - - result_buf = PyBytes_AS_STRING(result); - for (cur = start, i = 0; i < slicelength; - cur += step, i++) { - result_buf[i] = source_buf[cur]; - } - - return result; - } - } - else { - PyErr_Format(PyExc_TypeError, - "byte indices must be integers or slices, not %.200s", - Py_TYPE(item)->tp_name); - return NULL; - } -} - -static int -bytes_buffer_getbuffer(PyBytesObject *self, Py_buffer *view, int flags) -{ - return PyBuffer_FillInfo(view, (PyObject*)self, (void *)self->ob_sval, Py_SIZE(self), - 1, flags); -} - -static PySequenceMethods bytes_as_sequence = { - (lenfunc)bytes_length, /*sq_length*/ - (binaryfunc)bytes_concat, /*sq_concat*/ - (ssizeargfunc)bytes_repeat, /*sq_repeat*/ - (ssizeargfunc)bytes_item, /*sq_item*/ - 0, /*sq_slice*/ - 0, /*sq_ass_item*/ - 0, /*sq_ass_slice*/ - (objobjproc)bytes_contains /*sq_contains*/ -}; - -static PyMappingMethods bytes_as_mapping = { - (lenfunc)bytes_length, - (binaryfunc)bytes_subscript, - 0, -}; - -static PyBufferProcs bytes_as_buffer = { - (getbufferproc)bytes_buffer_getbuffer, - NULL, -}; - - -#define LEFTSTRIP 0 -#define RIGHTSTRIP 1 -#define BOTHSTRIP 2 - -/*[clinic input] -bytes.split - - sep: object = None - The delimiter according which to split the bytes. - None (the default value) means split on ASCII whitespace characters - (space, tab, return, newline, formfeed, vertical tab). - maxsplit: Py_ssize_t = -1 - Maximum number of splits to do. - -1 (the default value) means no limit. - -Return a list of the sections in the bytes, using sep as the delimiter. +preserve [clinic start generated code]*/ PyDoc_STRVAR(bytes_split__doc__, @@ -1652,46 +40,6 @@ return return_value; } -static PyObject * -bytes_split_impl(PyBytesObject*self, PyObject *sep, Py_ssize_t maxsplit) -/*[clinic end generated code: output=c80a47afdd505975 input=8b809b39074abbfa]*/ -{ - Py_ssize_t len = PyBytes_GET_SIZE(self), n; - const char *s = PyBytes_AS_STRING(self), *sub; - Py_buffer vsub; - PyObject *list; - - if (maxsplit < 0) - maxsplit = PY_SSIZE_T_MAX; - if (sep == Py_None) - return stringlib_split_whitespace((PyObject*) self, s, len, maxsplit); - if (PyObject_GetBuffer(sep, &vsub, PyBUF_SIMPLE) != 0) - return NULL; - sub = vsub.buf; - n = vsub.len; - - list = stringlib_split((PyObject*) self, s, len, sub, n, maxsplit); - PyBuffer_Release(&vsub); - return list; -} - -/*[clinic input] -bytes.partition - - self: self(type="PyBytesObject *") - sep: Py_buffer - / - -Partition the bytes into three parts using the given separator. - -This will search for the separator sep in the bytes. If the separator is found, -returns a 3-tuple containing the part before the separator, the separator -itself, and the part after it. - -If the separator is not found, returns a 3-tuple containing the original bytes -object and two empty bytes objects. -[clinic start generated code]*/ - PyDoc_STRVAR(bytes_partition__doc__, "partition($self, sep, /)\n" "--\n" @@ -1731,34 +79,6 @@ return return_value; } -static PyObject * -bytes_partition_impl(PyBytesObject *self, Py_buffer *sep) -/*[clinic end generated code: output=3006727cfbf83aa4 input=bc855dc63ca949de]*/ -{ - return stringlib_partition( - (PyObject*) self, - PyBytes_AS_STRING(self), PyBytes_GET_SIZE(self), - sep->obj, (const char *)sep->buf, sep->len - ); -} - -/*[clinic input] -bytes.rpartition - - self: self(type="PyBytesObject *") - sep: Py_buffer - / - -Partition the bytes into three parts using the given separator. - -This will search for the separator sep in the bytes, starting and the end. If -the separator is found, returns a 3-tuple containing the part before the -separator, the separator itself, and the part after it. - -If the separator is not found, returns a 3-tuple containing two empty bytes -objects and the original bytes object. -[clinic start generated code]*/ - PyDoc_STRVAR(bytes_rpartition__doc__, "rpartition($self, sep, /)\n" "--\n" @@ -1798,25 +118,6 @@ return return_value; } -static PyObject * -bytes_rpartition_impl(PyBytesObject *self, Py_buffer *sep) -/*[clinic end generated code: output=57b169dc47fa90e8 input=6588fff262a9170e]*/ -{ - return stringlib_rpartition( - (PyObject*) self, - PyBytes_AS_STRING(self), PyBytes_GET_SIZE(self), - sep->obj, (const char *)sep->buf, sep->len - ); -} - -/*[clinic input] -bytes.rsplit = bytes.split - -Return a list of the sections in the bytes, using sep as the delimiter. - -Splitting is done starting at the end of the bytes and working to the front. -[clinic start generated code]*/ - PyDoc_STRVAR(bytes_rsplit__doc__, "rsplit($self, /, sep=None, maxsplit=-1)\n" "--\n" @@ -1857,45 +158,6 @@ return return_value; } -static PyObject * -bytes_rsplit_impl(PyBytesObject*self, PyObject *sep, Py_ssize_t maxsplit) -/*[clinic end generated code: output=f86feddedbd7b26d input=0f86c9f28f7d7b7b]*/ -{ - Py_ssize_t len = PyBytes_GET_SIZE(self), n; - const char *s = PyBytes_AS_STRING(self), *sub; - Py_buffer vsub; - PyObject *list; - - if (maxsplit < 0) - maxsplit = PY_SSIZE_T_MAX; - if (sep == Py_None) - return stringlib_rsplit_whitespace((PyObject*) self, s, len, maxsplit); - if (PyObject_GetBuffer(sep, &vsub, PyBUF_SIMPLE) != 0) - return NULL; - sub = vsub.buf; - n = vsub.len; - - list = stringlib_rsplit((PyObject*) self, s, len, sub, n, maxsplit); - PyBuffer_Release(&vsub); - return list; -} - - -/*[clinic input] -bytes.join - - iterable_of_bytes: object - / - -Concatenate any number of bytes objects. - -The bytes whose method is called is inserted in between each pair. - -The result is returned as a new bytes object. - -Example: b'.'.join([b'ab', b'pq', b'rs']) -> b'ab.pq.rs'. -[clinic start generated code]*/ - PyDoc_STRVAR(bytes_join__doc__, "join($self, iterable_of_bytes, /)\n" "--\n" @@ -1911,265 +173,6 @@ #define BYTES_JOIN_METHODDEF \ {"join", (PyCFunction)bytes_join, METH_O, bytes_join__doc__}, -static PyObject * -bytes_join(PyBytesObject*self, PyObject *iterable_of_bytes) -/*[clinic end generated code: output=e541a14a8da97908 input=7fe377b95bd549d2]*/ -{ - return stringlib_bytes_join((PyObject*)self, iterable_of_bytes); -} - -PyObject * -_PyBytes_Join(PyObject *sep, PyObject *x) -{ - assert(sep != NULL && PyBytes_Check(sep)); - assert(x != NULL); - return bytes_join((PyBytesObject*)sep, x); -} - -/* helper macro to fixup start/end slice values */ -#define ADJUST_INDICES(start, end, len) \ - if (end > len) \ - end = len; \ - else if (end < 0) { \ - end += len; \ - if (end < 0) \ - end = 0; \ - } \ - if (start < 0) { \ - start += len; \ - if (start < 0) \ - start = 0; \ - } - -Py_LOCAL_INLINE(Py_ssize_t) -bytes_find_internal(PyBytesObject *self, PyObject *args, int dir) -{ - PyObject *subobj; - char byte; - Py_buffer subbuf; - const char *sub; - Py_ssize_t len, sub_len; - Py_ssize_t start=0, end=PY_SSIZE_T_MAX; - Py_ssize_t res; - - if (!stringlib_parse_args_finds_byte("find/rfind/index/rindex", - args, &subobj, &byte, &start, &end)) - return -2; - - if (subobj) { - if (PyObject_GetBuffer(subobj, &subbuf, PyBUF_SIMPLE) != 0) - return -2; - - sub = subbuf.buf; - sub_len = subbuf.len; - } - else { - sub = &byte; - sub_len = 1; - } - len = PyBytes_GET_SIZE(self); - - ADJUST_INDICES(start, end, len); - if (end - start < sub_len) - res = -1; - /* Issue #23573: FIXME, windows has no memrchr() */ - else if (sub_len == 1 && dir > 0) { - unsigned char needle = *sub; - int mode = (dir > 0) ? FAST_SEARCH : FAST_RSEARCH; - res = stringlib_fastsearch_memchr_1char( - PyBytes_AS_STRING(self) + start, end - start, - needle, needle, mode); - if (res >= 0) - res += start; - } - else { - if (dir > 0) - res = stringlib_find_slice( - PyBytes_AS_STRING(self), len, - sub, sub_len, start, end); - else - res = stringlib_rfind_slice( - PyBytes_AS_STRING(self), len, - sub, sub_len, start, end); - } - - if (subobj) - PyBuffer_Release(&subbuf); - - return res; -} - - -PyDoc_STRVAR(find__doc__, -"B.find(sub[, start[, end]]) -> int\n\ -\n\ -Return the lowest index in B where substring sub is found,\n\ -such that sub is contained within B[start:end]. Optional\n\ -arguments start and end are interpreted as in slice notation.\n\ -\n\ -Return -1 on failure."); - -static PyObject * -bytes_find(PyBytesObject *self, PyObject *args) -{ - Py_ssize_t result = bytes_find_internal(self, args, +1); - if (result == -2) - return NULL; - return PyLong_FromSsize_t(result); -} - - -PyDoc_STRVAR(index__doc__, -"B.index(sub[, start[, end]]) -> int\n\ -\n\ -Like B.find() but raise ValueError when the substring is not found."); - -static PyObject * -bytes_index(PyBytesObject *self, PyObject *args) -{ - Py_ssize_t result = bytes_find_internal(self, args, +1); - if (result == -2) - return NULL; - if (result == -1) { - PyErr_SetString(PyExc_ValueError, - "substring not found"); - return NULL; - } - return PyLong_FromSsize_t(result); -} - - -PyDoc_STRVAR(rfind__doc__, -"B.rfind(sub[, start[, end]]) -> int\n\ -\n\ -Return the highest index in B where substring sub is found,\n\ -such that sub is contained within B[start:end]. Optional\n\ -arguments start and end are interpreted as in slice notation.\n\ -\n\ -Return -1 on failure."); - -static PyObject * -bytes_rfind(PyBytesObject *self, PyObject *args) -{ - Py_ssize_t result = bytes_find_internal(self, args, -1); - if (result == -2) - return NULL; - return PyLong_FromSsize_t(result); -} - - -PyDoc_STRVAR(rindex__doc__, -"B.rindex(sub[, start[, end]]) -> int\n\ -\n\ -Like B.rfind() but raise ValueError when the substring is not found."); - -static PyObject * -bytes_rindex(PyBytesObject *self, PyObject *args) -{ - Py_ssize_t result = bytes_find_internal(self, args, -1); - if (result == -2) - return NULL; - if (result == -1) { - PyErr_SetString(PyExc_ValueError, - "substring not found"); - return NULL; - } - return PyLong_FromSsize_t(result); -} - - -Py_LOCAL_INLINE(PyObject *) -do_xstrip(PyBytesObject *self, int striptype, PyObject *sepobj) -{ - Py_buffer vsep; - char *s = PyBytes_AS_STRING(self); - Py_ssize_t len = PyBytes_GET_SIZE(self); - char *sep; - Py_ssize_t seplen; - Py_ssize_t i, j; - - if (PyObject_GetBuffer(sepobj, &vsep, PyBUF_SIMPLE) != 0) - return NULL; - sep = vsep.buf; - seplen = vsep.len; - - i = 0; - if (striptype != RIGHTSTRIP) { - while (i < len && memchr(sep, Py_CHARMASK(s[i]), seplen)) { - i++; - } - } - - j = len; - if (striptype != LEFTSTRIP) { - do { - j--; - } while (j >= i && memchr(sep, Py_CHARMASK(s[j]), seplen)); - j++; - } - - PyBuffer_Release(&vsep); - - if (i == 0 && j == len && PyBytes_CheckExact(self)) { - Py_INCREF(self); - return (PyObject*)self; - } - else - return PyBytes_FromStringAndSize(s+i, j-i); -} - - -Py_LOCAL_INLINE(PyObject *) -do_strip(PyBytesObject *self, int striptype) -{ - char *s = PyBytes_AS_STRING(self); - Py_ssize_t len = PyBytes_GET_SIZE(self), i, j; - - i = 0; - if (striptype != RIGHTSTRIP) { - while (i < len && Py_ISSPACE(s[i])) { - i++; - } - } - - j = len; - if (striptype != LEFTSTRIP) { - do { - j--; - } while (j >= i && Py_ISSPACE(s[j])); - j++; - } - - if (i == 0 && j == len && PyBytes_CheckExact(self)) { - Py_INCREF(self); - return (PyObject*)self; - } - else - return PyBytes_FromStringAndSize(s+i, j-i); -} - - -Py_LOCAL_INLINE(PyObject *) -do_argstrip(PyBytesObject *self, int striptype, PyObject *bytes) -{ - if (bytes != NULL && bytes != Py_None) { - return do_xstrip(self, striptype, bytes); - } - return do_strip(self, striptype); -} - -/*[clinic input] -bytes.strip - - self: self(type="PyBytesObject *") - bytes: object = None - / - -Strip leading and trailing bytes contained in the argument. - -If the argument is omitted or None, strip leading and trailing ASCII whitespace. -[clinic start generated code]*/ - PyDoc_STRVAR(bytes_strip__doc__, "strip($self, bytes=None, /)\n" "--\n" @@ -2200,25 +203,6 @@ return return_value; } -static PyObject * -bytes_strip_impl(PyBytesObject *self, PyObject *bytes) -/*[clinic end generated code: output=c8234a599ba5ec35 input=37daa5fad1395d95]*/ -{ - return do_argstrip(self, BOTHSTRIP, bytes); -} - -/*[clinic input] -bytes.lstrip - - self: self(type="PyBytesObject *") - bytes: object = None - / - -Strip leading bytes contained in the argument. - -If the argument is omitted or None, strip leading ASCII whitespace. -[clinic start generated code]*/ - PyDoc_STRVAR(bytes_lstrip__doc__, "lstrip($self, bytes=None, /)\n" "--\n" @@ -2249,25 +233,6 @@ return return_value; } -static PyObject * -bytes_lstrip_impl(PyBytesObject *self, PyObject *bytes) -/*[clinic end generated code: output=529e8511ab6f1115 input=88811b09dfbc2988]*/ -{ - return do_argstrip(self, LEFTSTRIP, bytes); -} - -/*[clinic input] -bytes.rstrip - - self: self(type="PyBytesObject *") - bytes: object = None - / - -Strip trailing bytes contained in the argument. - -If the argument is omitted or None, strip trailing ASCII whitespace. -[clinic start generated code]*/ - PyDoc_STRVAR(bytes_rstrip__doc__, "rstrip($self, bytes=None, /)\n" "--\n" @@ -2298,79 +263,6 @@ return return_value; } -static PyObject * -bytes_rstrip_impl(PyBytesObject *self, PyObject *bytes) -/*[clinic end generated code: output=e98730bd133e6593 input=8f93c9cd361f0140]*/ -{ - return do_argstrip(self, RIGHTSTRIP, bytes); -} - - -PyDoc_STRVAR(count__doc__, -"B.count(sub[, start[, end]]) -> int\n\ -\n\ -Return the number of non-overlapping occurrences of substring sub in\n\ -string B[start:end]. Optional arguments start and end are interpreted\n\ -as in slice notation."); - -static PyObject * -bytes_count(PyBytesObject *self, PyObject *args) -{ - PyObject *sub_obj; - const char *str = PyBytes_AS_STRING(self), *sub; - Py_ssize_t sub_len; - char byte; - Py_ssize_t start = 0, end = PY_SSIZE_T_MAX; - - Py_buffer vsub; - PyObject *count_obj; - - if (!stringlib_parse_args_finds_byte("count", args, &sub_obj, &byte, - &start, &end)) - return NULL; - - if (sub_obj) { - if (PyObject_GetBuffer(sub_obj, &vsub, PyBUF_SIMPLE) != 0) - return NULL; - - sub = vsub.buf; - sub_len = vsub.len; - } - else { - sub = &byte; - sub_len = 1; - } - - ADJUST_INDICES(start, end, PyBytes_GET_SIZE(self)); - - count_obj = PyLong_FromSsize_t( - stringlib_count(str + start, end - start, sub, sub_len, PY_SSIZE_T_MAX) - ); - - if (sub_obj) - PyBuffer_Release(&vsub); - - return count_obj; -} - - -/*[clinic input] -bytes.translate - - self: self(type="PyBytesObject *") - table: object - Translation table, which must be a bytes object of length 256. - [ - deletechars: object - ] - / - -Return a copy with each character mapped by the given translation table. - -All characters occurring in the optional argument deletechars are removed. -The remaining characters are mapped through the given translation table. -[clinic start generated code]*/ - PyDoc_STRVAR(bytes_translate__doc__, "translate(table, [deletechars])\n" "Return a copy with each character mapped by the given translation table.\n" @@ -2415,138 +307,6 @@ return return_value; } -static PyObject * -bytes_translate_impl(PyBytesObject *self, PyObject *table, int group_right_1, PyObject *deletechars) -/*[clinic end generated code: output=f0f29a57f41df5d8 input=d8fa5519d7cc4be7]*/ -{ - char *input, *output; - Py_buffer table_view = {NULL, NULL}; - Py_buffer del_table_view = {NULL, NULL}; - const char *table_chars; - Py_ssize_t i, c, changed = 0; - PyObject *input_obj = (PyObject*)self; - const char *output_start, *del_table_chars=NULL; - Py_ssize_t inlen, tablen, dellen = 0; - PyObject *result; - int trans_table[256]; - - if (PyBytes_Check(table)) { - table_chars = PyBytes_AS_STRING(table); - tablen = PyBytes_GET_SIZE(table); - } - else if (table == Py_None) { - table_chars = NULL; - tablen = 256; - } - else { - if (PyObject_GetBuffer(table, &table_view, PyBUF_SIMPLE) != 0) - return NULL; - table_chars = table_view.buf; - tablen = table_view.len; - } - - if (tablen != 256) { - PyErr_SetString(PyExc_ValueError, - "translation table must be 256 characters long"); - PyBuffer_Release(&table_view); - return NULL; - } - - if (deletechars != NULL) { - if (PyBytes_Check(deletechars)) { - del_table_chars = PyBytes_AS_STRING(deletechars); - dellen = PyBytes_GET_SIZE(deletechars); - } - else { - if (PyObject_GetBuffer(deletechars, &del_table_view, PyBUF_SIMPLE) != 0) { - PyBuffer_Release(&table_view); - return NULL; - } - del_table_chars = del_table_view.buf; - dellen = del_table_view.len; - } - } - else { - del_table_chars = NULL; - dellen = 0; - } - - inlen = PyBytes_GET_SIZE(input_obj); - result = PyBytes_FromStringAndSize((char *)NULL, inlen); - if (result == NULL) { - PyBuffer_Release(&del_table_view); - PyBuffer_Release(&table_view); - return NULL; - } - output_start = output = PyBytes_AsString(result); - input = PyBytes_AS_STRING(input_obj); - - if (dellen == 0 && table_chars != NULL) { - /* If no deletions are required, use faster code */ - for (i = inlen; --i >= 0; ) { - c = Py_CHARMASK(*input++); - if (Py_CHARMASK((*output++ = table_chars[c])) != c) - changed = 1; - } - if (!changed && PyBytes_CheckExact(input_obj)) { - Py_INCREF(input_obj); - Py_DECREF(result); - result = input_obj; - } - PyBuffer_Release(&del_table_view); - PyBuffer_Release(&table_view); - return result; - } - - if (table_chars == NULL) { - for (i = 0; i < 256; i++) - trans_table[i] = Py_CHARMASK(i); - } else { - for (i = 0; i < 256; i++) - trans_table[i] = Py_CHARMASK(table_chars[i]); - } - PyBuffer_Release(&table_view); - - for (i = 0; i < dellen; i++) - trans_table[(int) Py_CHARMASK(del_table_chars[i])] = -1; - PyBuffer_Release(&del_table_view); - - for (i = inlen; --i >= 0; ) { - c = Py_CHARMASK(*input++); - if (trans_table[c] != -1) - if (Py_CHARMASK(*output++ = (char)trans_table[c]) == c) - continue; - changed = 1; - } - if (!changed && PyBytes_CheckExact(input_obj)) { - Py_DECREF(result); - Py_INCREF(input_obj); - return input_obj; - } - /* Fix the size of the resulting string */ - if (inlen > 0) - _PyBytes_Resize(&result, output - output_start); - return result; -} - - -/*[clinic input] - - at staticmethod -bytes.maketrans - - frm: Py_buffer - to: Py_buffer - / - -Return a translation table useable for the bytes or bytearray translate method. - -The returned table will be one where each byte in frm is mapped to the byte at -the same position in to. - -The bytes objects frm and to must be of the same length. -[clinic start generated code]*/ - PyDoc_STRVAR(bytes_maketrans__doc__, "maketrans(frm, to, /)\n" "--\n" @@ -2588,522 +348,6 @@ return return_value; } -static PyObject * -bytes_maketrans_impl(Py_buffer *frm, Py_buffer *to) -/*[clinic end generated code: output=7df47390c476ac60 input=de7a8fc5632bb8f1]*/ -{ - return _Py_bytes_maketrans(frm, to); -} - -/* find and count characters and substrings */ - -#define findchar(target, target_len, c) \ - ((char *)memchr((const void *)(target), c, target_len)) - -/* String ops must return a string. */ -/* If the object is subclass of string, create a copy */ -Py_LOCAL(PyBytesObject *) -return_self(PyBytesObject *self) -{ - if (PyBytes_CheckExact(self)) { - Py_INCREF(self); - return self; - } - return (PyBytesObject *)PyBytes_FromStringAndSize( - PyBytes_AS_STRING(self), - PyBytes_GET_SIZE(self)); -} - -Py_LOCAL_INLINE(Py_ssize_t) -countchar(const char *target, Py_ssize_t target_len, char c, Py_ssize_t maxcount) -{ - Py_ssize_t count=0; - const char *start=target; - const char *end=target+target_len; - - while ( (start=findchar(start, end-start, c)) != NULL ) { - count++; - if (count >= maxcount) - break; - start += 1; - } - return count; -} - - -/* Algorithms for different cases of string replacement */ - -/* len(self)>=1, from="", len(to)>=1, maxcount>=1 */ -Py_LOCAL(PyBytesObject *) -replace_interleave(PyBytesObject *self, - const char *to_s, Py_ssize_t to_len, - Py_ssize_t maxcount) -{ - char *self_s, *result_s; - Py_ssize_t self_len, result_len; - Py_ssize_t count, i; - PyBytesObject *result; - - self_len = PyBytes_GET_SIZE(self); - - /* 1 at the end plus 1 after every character; - count = min(maxcount, self_len + 1) */ - if (maxcount <= self_len) - count = maxcount; - else - /* Can't overflow: self_len + 1 <= maxcount <= PY_SSIZE_T_MAX. */ - count = self_len + 1; - - /* Check for overflow */ - /* result_len = count * to_len + self_len; */ - assert(count > 0); - if (to_len > (PY_SSIZE_T_MAX - self_len) / count) { - PyErr_SetString(PyExc_OverflowError, - "replacement bytes are too long"); - return NULL; - } - result_len = count * to_len + self_len; - - if (! (result = (PyBytesObject *) - PyBytes_FromStringAndSize(NULL, result_len)) ) - return NULL; - - self_s = PyBytes_AS_STRING(self); - result_s = PyBytes_AS_STRING(result); - - /* TODO: special case single character, which doesn't need memcpy */ - - /* Lay the first one down (guaranteed this will occur) */ - Py_MEMCPY(result_s, to_s, to_len); - result_s += to_len; - count -= 1; - - for (i=0; i=1, len(from)==1, to="", maxcount>=1 */ -Py_LOCAL(PyBytesObject *) -replace_delete_single_character(PyBytesObject *self, - char from_c, Py_ssize_t maxcount) -{ - char *self_s, *result_s; - char *start, *next, *end; - Py_ssize_t self_len, result_len; - Py_ssize_t count; - PyBytesObject *result; - - self_len = PyBytes_GET_SIZE(self); - self_s = PyBytes_AS_STRING(self); - - count = countchar(self_s, self_len, from_c, maxcount); - if (count == 0) { - return return_self(self); - } - - result_len = self_len - count; /* from_len == 1 */ - assert(result_len>=0); - - if ( (result = (PyBytesObject *) - PyBytes_FromStringAndSize(NULL, result_len)) == NULL) - return NULL; - result_s = PyBytes_AS_STRING(result); - - start = self_s; - end = self_s + self_len; - while (count-- > 0) { - next = findchar(start, end-start, from_c); - if (next == NULL) - break; - Py_MEMCPY(result_s, start, next-start); - result_s += (next-start); - start = next+1; - } - Py_MEMCPY(result_s, start, end-start); - - return result; -} - -/* len(self)>=1, len(from)>=2, to="", maxcount>=1 */ - -Py_LOCAL(PyBytesObject *) -replace_delete_substring(PyBytesObject *self, - const char *from_s, Py_ssize_t from_len, - Py_ssize_t maxcount) { - char *self_s, *result_s; - char *start, *next, *end; - Py_ssize_t self_len, result_len; - Py_ssize_t count, offset; - PyBytesObject *result; - - self_len = PyBytes_GET_SIZE(self); - self_s = PyBytes_AS_STRING(self); - - count = stringlib_count(self_s, self_len, - from_s, from_len, - maxcount); - - if (count == 0) { - /* no matches */ - return return_self(self); - } - - result_len = self_len - (count * from_len); - assert (result_len>=0); - - if ( (result = (PyBytesObject *) - PyBytes_FromStringAndSize(NULL, result_len)) == NULL ) - return NULL; - - result_s = PyBytes_AS_STRING(result); - - start = self_s; - end = self_s + self_len; - while (count-- > 0) { - offset = stringlib_find(start, end-start, - from_s, from_len, - 0); - if (offset == -1) - break; - next = start + offset; - - Py_MEMCPY(result_s, start, next-start); - - result_s += (next-start); - start = next+from_len; - } - Py_MEMCPY(result_s, start, end-start); - return result; -} - -/* len(self)>=1, len(from)==len(to)==1, maxcount>=1 */ -Py_LOCAL(PyBytesObject *) -replace_single_character_in_place(PyBytesObject *self, - char from_c, char to_c, - Py_ssize_t maxcount) -{ - char *self_s, *result_s, *start, *end, *next; - Py_ssize_t self_len; - PyBytesObject *result; - - /* The result string will be the same size */ - self_s = PyBytes_AS_STRING(self); - self_len = PyBytes_GET_SIZE(self); - - next = findchar(self_s, self_len, from_c); - - if (next == NULL) { - /* No matches; return the original string */ - return return_self(self); - } - - /* Need to make a new string */ - result = (PyBytesObject *) PyBytes_FromStringAndSize(NULL, self_len); - if (result == NULL) - return NULL; - result_s = PyBytes_AS_STRING(result); - Py_MEMCPY(result_s, self_s, self_len); - - /* change everything in-place, starting with this one */ - start = result_s + (next-self_s); - *start = to_c; - start++; - end = result_s + self_len; - - while (--maxcount > 0) { - next = findchar(start, end-start, from_c); - if (next == NULL) - break; - *next = to_c; - start = next+1; - } - - return result; -} - -/* len(self)>=1, len(from)==len(to)>=2, maxcount>=1 */ -Py_LOCAL(PyBytesObject *) -replace_substring_in_place(PyBytesObject *self, - const char *from_s, Py_ssize_t from_len, - const char *to_s, Py_ssize_t to_len, - Py_ssize_t maxcount) -{ - char *result_s, *start, *end; - char *self_s; - Py_ssize_t self_len, offset; - PyBytesObject *result; - - /* The result string will be the same size */ - - self_s = PyBytes_AS_STRING(self); - self_len = PyBytes_GET_SIZE(self); - - offset = stringlib_find(self_s, self_len, - from_s, from_len, - 0); - if (offset == -1) { - /* No matches; return the original string */ - return return_self(self); - } - - /* Need to make a new string */ - result = (PyBytesObject *) PyBytes_FromStringAndSize(NULL, self_len); - if (result == NULL) - return NULL; - result_s = PyBytes_AS_STRING(result); - Py_MEMCPY(result_s, self_s, self_len); - - /* change everything in-place, starting with this one */ - start = result_s + offset; - Py_MEMCPY(start, to_s, from_len); - start += from_len; - end = result_s + self_len; - - while ( --maxcount > 0) { - offset = stringlib_find(start, end-start, - from_s, from_len, - 0); - if (offset==-1) - break; - Py_MEMCPY(start+offset, to_s, from_len); - start += offset+from_len; - } - - return result; -} - -/* len(self)>=1, len(from)==1, len(to)>=2, maxcount>=1 */ -Py_LOCAL(PyBytesObject *) -replace_single_character(PyBytesObject *self, - char from_c, - const char *to_s, Py_ssize_t to_len, - Py_ssize_t maxcount) -{ - char *self_s, *result_s; - char *start, *next, *end; - Py_ssize_t self_len, result_len; - Py_ssize_t count; - PyBytesObject *result; - - self_s = PyBytes_AS_STRING(self); - self_len = PyBytes_GET_SIZE(self); - - count = countchar(self_s, self_len, from_c, maxcount); - if (count == 0) { - /* no matches, return unchanged */ - return return_self(self); - } - - /* use the difference between current and new, hence the "-1" */ - /* result_len = self_len + count * (to_len-1) */ - assert(count > 0); - if (to_len - 1 > (PY_SSIZE_T_MAX - self_len) / count) { - PyErr_SetString(PyExc_OverflowError, - "replacement bytes are too long"); - return NULL; - } - result_len = self_len + count * (to_len - 1); - - if ( (result = (PyBytesObject *) - PyBytes_FromStringAndSize(NULL, result_len)) == NULL) - return NULL; - result_s = PyBytes_AS_STRING(result); - - start = self_s; - end = self_s + self_len; - while (count-- > 0) { - next = findchar(start, end-start, from_c); - if (next == NULL) - break; - - if (next == start) { - /* replace with the 'to' */ - Py_MEMCPY(result_s, to_s, to_len); - result_s += to_len; - start += 1; - } else { - /* copy the unchanged old then the 'to' */ - Py_MEMCPY(result_s, start, next-start); - result_s += (next-start); - Py_MEMCPY(result_s, to_s, to_len); - result_s += to_len; - start = next+1; - } - } - /* Copy the remainder of the remaining string */ - Py_MEMCPY(result_s, start, end-start); - - return result; -} - -/* len(self)>=1, len(from)>=2, len(to)>=2, maxcount>=1 */ -Py_LOCAL(PyBytesObject *) -replace_substring(PyBytesObject *self, - const char *from_s, Py_ssize_t from_len, - const char *to_s, Py_ssize_t to_len, - Py_ssize_t maxcount) { - char *self_s, *result_s; - char *start, *next, *end; - Py_ssize_t self_len, result_len; - Py_ssize_t count, offset; - PyBytesObject *result; - - self_s = PyBytes_AS_STRING(self); - self_len = PyBytes_GET_SIZE(self); - - count = stringlib_count(self_s, self_len, - from_s, from_len, - maxcount); - - if (count == 0) { - /* no matches, return unchanged */ - return return_self(self); - } - - /* Check for overflow */ - /* result_len = self_len + count * (to_len-from_len) */ - assert(count > 0); - if (to_len - from_len > (PY_SSIZE_T_MAX - self_len) / count) { - PyErr_SetString(PyExc_OverflowError, - "replacement bytes are too long"); - return NULL; - } - result_len = self_len + count * (to_len-from_len); - - if ( (result = (PyBytesObject *) - PyBytes_FromStringAndSize(NULL, result_len)) == NULL) - return NULL; - result_s = PyBytes_AS_STRING(result); - - start = self_s; - end = self_s + self_len; - while (count-- > 0) { - offset = stringlib_find(start, end-start, - from_s, from_len, - 0); - if (offset == -1) - break; - next = start+offset; - if (next == start) { - /* replace with the 'to' */ - Py_MEMCPY(result_s, to_s, to_len); - result_s += to_len; - start += from_len; - } else { - /* copy the unchanged old then the 'to' */ - Py_MEMCPY(result_s, start, next-start); - result_s += (next-start); - Py_MEMCPY(result_s, to_s, to_len); - result_s += to_len; - start = next+from_len; - } - } - /* Copy the remainder of the remaining string */ - Py_MEMCPY(result_s, start, end-start); - - return result; -} - - -Py_LOCAL(PyBytesObject *) -replace(PyBytesObject *self, - const char *from_s, Py_ssize_t from_len, - const char *to_s, Py_ssize_t to_len, - Py_ssize_t maxcount) -{ - if (maxcount < 0) { - maxcount = PY_SSIZE_T_MAX; - } else if (maxcount == 0 || PyBytes_GET_SIZE(self) == 0) { - /* nothing to do; return the original string */ - return return_self(self); - } - - if (maxcount == 0 || - (from_len == 0 && to_len == 0)) { - /* nothing to do; return the original string */ - return return_self(self); - } - - /* Handle zero-length special cases */ - - if (from_len == 0) { - /* insert the 'to' string everywhere. */ - /* >>> "Python".replace("", ".") */ - /* '.P.y.t.h.o.n.' */ - return replace_interleave(self, to_s, to_len, maxcount); - } - - /* Except for "".replace("", "A") == "A" there is no way beyond this */ - /* point for an empty self string to generate a non-empty string */ - /* Special case so the remaining code always gets a non-empty string */ - if (PyBytes_GET_SIZE(self) == 0) { - return return_self(self); - } - - if (to_len == 0) { - /* delete all occurrences of 'from' string */ - if (from_len == 1) { - return replace_delete_single_character( - self, from_s[0], maxcount); - } else { - return replace_delete_substring(self, from_s, - from_len, maxcount); - } - } - - /* Handle special case where both strings have the same length */ - - if (from_len == to_len) { - if (from_len == 1) { - return replace_single_character_in_place( - self, - from_s[0], - to_s[0], - maxcount); - } else { - return replace_substring_in_place( - self, from_s, from_len, to_s, to_len, - maxcount); - } - } - - /* Otherwise use the more generic algorithms */ - if (from_len == 1) { - return replace_single_character(self, from_s[0], - to_s, to_len, maxcount); - } else { - /* len('from')>=2, len('to')>=1 */ - return replace_substring(self, from_s, from_len, to_s, to_len, - maxcount); - } -} - - -/*[clinic input] -bytes.replace - - old: Py_buffer - new: Py_buffer - count: Py_ssize_t = -1 - Maximum number of occurrences to replace. - -1 (the default value) means replace all occurrences. - / - -Return a copy with all occurrences of substring old replaced by new. - -If the optional argument count is given, only the first count occurrences are -replaced. -[clinic start generated code]*/ - PyDoc_STRVAR(bytes_replace__doc__, "replace($self, old, new, count=-1, /)\n" "--\n" @@ -3148,174 +392,6 @@ return return_value; } -static PyObject * -bytes_replace_impl(PyBytesObject*self, Py_buffer *old, Py_buffer *new, Py_ssize_t count) -/*[clinic end generated code: output=f07bd9ecf29ee8d8 input=b2fbbf0bf04de8e5]*/ -{ - return (PyObject *)replace((PyBytesObject *) self, - (const char *)old->buf, old->len, - (const char *)new->buf, new->len, count); -} - -/** End DALKE **/ - -/* Matches the end (direction >= 0) or start (direction < 0) of self - * against substr, using the start and end arguments. Returns - * -1 on error, 0 if not found and 1 if found. - */ -Py_LOCAL(int) -_bytes_tailmatch(PyBytesObject *self, PyObject *substr, Py_ssize_t start, - Py_ssize_t end, int direction) -{ - Py_ssize_t len = PyBytes_GET_SIZE(self); - Py_ssize_t slen; - Py_buffer sub_view = {NULL, NULL}; - const char* sub; - const char* str; - - if (PyBytes_Check(substr)) { - sub = PyBytes_AS_STRING(substr); - slen = PyBytes_GET_SIZE(substr); - } - else { - if (PyObject_GetBuffer(substr, &sub_view, PyBUF_SIMPLE) != 0) - return -1; - sub = sub_view.buf; - slen = sub_view.len; - } - str = PyBytes_AS_STRING(self); - - ADJUST_INDICES(start, end, len); - - if (direction < 0) { - /* startswith */ - if (start+slen > len) - goto notfound; - } else { - /* endswith */ - if (end-start < slen || start > len) - goto notfound; - - if (end-slen > start) - start = end - slen; - } - if (end-start < slen) - goto notfound; - if (memcmp(str+start, sub, slen) != 0) - goto notfound; - - PyBuffer_Release(&sub_view); - return 1; - -notfound: - PyBuffer_Release(&sub_view); - return 0; -} - - -PyDoc_STRVAR(startswith__doc__, -"B.startswith(prefix[, start[, end]]) -> bool\n\ -\n\ -Return True if B starts with the specified prefix, False otherwise.\n\ -With optional start, test B beginning at that position.\n\ -With optional end, stop comparing B at that position.\n\ -prefix can also be a tuple of bytes to try."); - -static PyObject * -bytes_startswith(PyBytesObject *self, PyObject *args) -{ - Py_ssize_t start = 0; - Py_ssize_t end = PY_SSIZE_T_MAX; - PyObject *subobj; - int result; - - if (!stringlib_parse_args_finds("startswith", args, &subobj, &start, &end)) - return NULL; - if (PyTuple_Check(subobj)) { - Py_ssize_t i; - for (i = 0; i < PyTuple_GET_SIZE(subobj); i++) { - result = _bytes_tailmatch(self, - PyTuple_GET_ITEM(subobj, i), - start, end, -1); - if (result == -1) - return NULL; - else if (result) { - Py_RETURN_TRUE; - } - } - Py_RETURN_FALSE; - } - result = _bytes_tailmatch(self, subobj, start, end, -1); - if (result == -1) { - if (PyErr_ExceptionMatches(PyExc_TypeError)) - PyErr_Format(PyExc_TypeError, "startswith first arg must be bytes " - "or a tuple of bytes, not %s", Py_TYPE(subobj)->tp_name); - return NULL; - } - else - return PyBool_FromLong(result); -} - - -PyDoc_STRVAR(endswith__doc__, -"B.endswith(suffix[, start[, end]]) -> bool\n\ -\n\ -Return True if B ends with the specified suffix, False otherwise.\n\ -With optional start, test B beginning at that position.\n\ -With optional end, stop comparing B at that position.\n\ -suffix can also be a tuple of bytes to try."); - -static PyObject * -bytes_endswith(PyBytesObject *self, PyObject *args) -{ - Py_ssize_t start = 0; - Py_ssize_t end = PY_SSIZE_T_MAX; - PyObject *subobj; - int result; - - if (!stringlib_parse_args_finds("endswith", args, &subobj, &start, &end)) - return NULL; - if (PyTuple_Check(subobj)) { - Py_ssize_t i; - for (i = 0; i < PyTuple_GET_SIZE(subobj); i++) { - result = _bytes_tailmatch(self, - PyTuple_GET_ITEM(subobj, i), - start, end, +1); - if (result == -1) - return NULL; - else if (result) { - Py_RETURN_TRUE; - } - } - Py_RETURN_FALSE; - } - result = _bytes_tailmatch(self, subobj, start, end, +1); - if (result == -1) { - if (PyErr_ExceptionMatches(PyExc_TypeError)) - PyErr_Format(PyExc_TypeError, "endswith first arg must be bytes or " - "a tuple of bytes, not %s", Py_TYPE(subobj)->tp_name); - return NULL; - } - else - return PyBool_FromLong(result); -} - - -/*[clinic input] -bytes.decode - - encoding: str(c_default="NULL") = 'utf-8' - The encoding with which to decode the bytes. - errors: str(c_default="NULL") = 'strict' - The error handling scheme to use for the handling of decoding errors. - The default is 'strict' meaning that decoding errors raise a - UnicodeDecodeError. Other possible values are 'ignore' and 'replace' - as well as any other name registered with codecs.register_error that - can handle UnicodeDecodeErrors. - -Decode the bytes using the codec registered for encoding. -[clinic start generated code]*/ - PyDoc_STRVAR(bytes_decode__doc__, "decode($self, /, encoding=\'utf-8\', errors=\'strict\')\n" "--\n" @@ -3355,25 +431,6 @@ return return_value; } -static PyObject * -bytes_decode_impl(PyBytesObject*self, const char *encoding, const char *errors) -/*[clinic end generated code: output=61a80290bbfce696 input=958174769d2a40ca]*/ -{ - return PyUnicode_FromEncodedObject((PyObject*)self, encoding, errors); -} - - -/*[clinic input] -bytes.splitlines - - keepends: int(py_default="False") = 0 - -Return a list of the lines in the bytes, breaking at line boundaries. - -Line breaks are not included in the resulting list unless keepends is given and -true. -[clinic start generated code]*/ - PyDoc_STRVAR(bytes_splitlines__doc__, "splitlines($self, /, keepends=False)\n" "--\n" @@ -3406,45 +463,6 @@ return return_value; } -static PyObject * -bytes_splitlines_impl(PyBytesObject*self, int keepends) -/*[clinic end generated code: output=79da057d05d126de input=ddb93e3351080c8c]*/ -{ - return stringlib_splitlines( - (PyObject*) self, PyBytes_AS_STRING(self), - PyBytes_GET_SIZE(self), keepends - ); -} - -static int -hex_digit_to_int(Py_UCS4 c) -{ - if (c >= 128) - return -1; - if (Py_ISDIGIT(c)) - return c - '0'; - else { - if (Py_ISUPPER(c)) - c = Py_TOLOWER(c); - if (c >= 'a' && c <= 'f') - return c - 'a' + 10; - } - return -1; -} - -/*[clinic input] - at classmethod -bytes.fromhex - - string: unicode - / - -Create a bytes object from a string of hexadecimal numbers. - -Spaces between two numbers are accepted. -Example: bytes.fromhex('B9 01EF') -> b'\\xb9\\x01\\xef'. -[clinic start generated code]*/ - PyDoc_STRVAR(bytes_fromhex__doc__, "fromhex($type, string, /)\n" "--\n" @@ -3475,720 +493,4 @@ exit: return return_value; } - -static PyObject * -bytes_fromhex_impl(PyTypeObject *type, PyObject *string) -/*[clinic end generated code: output=09e6cbef56cbbb65 input=bf4d1c361670acd3]*/ -{ - PyObject *newstring; - char *buf; - Py_ssize_t hexlen, byteslen, i, j; - int top, bot; - void *data; - unsigned int kind; - - assert(PyUnicode_Check(string)); - if (PyUnicode_READY(string)) - return NULL; - kind = PyUnicode_KIND(string); - data = PyUnicode_DATA(string); - hexlen = PyUnicode_GET_LENGTH(string); - - byteslen = hexlen/2; /* This overestimates if there are spaces */ - newstring = PyBytes_FromStringAndSize(NULL, byteslen); - if (!newstring) - return NULL; - buf = PyBytes_AS_STRING(newstring); - for (i = j = 0; i < hexlen; i += 2) { - /* skip over spaces in the input */ - while (PyUnicode_READ(kind, data, i) == ' ') - i++; - if (i >= hexlen) - break; - top = hex_digit_to_int(PyUnicode_READ(kind, data, i)); - bot = hex_digit_to_int(PyUnicode_READ(kind, data, i+1)); - if (top == -1 || bot == -1) { - PyErr_Format(PyExc_ValueError, - "non-hexadecimal number found in " - "fromhex() arg at position %zd", i); - goto error; - } - buf[j++] = (top << 4) + bot; - } - if (j != byteslen && _PyBytes_Resize(&newstring, j) < 0) - goto error; - return newstring; - - error: - Py_XDECREF(newstring); - return NULL; -} - -static PyObject * -bytes_getnewargs(PyBytesObject *v) -{ - return Py_BuildValue("(y#)", v->ob_sval, Py_SIZE(v)); -} - - -static PyMethodDef -bytes_methods[] = { - {"__getnewargs__", (PyCFunction)bytes_getnewargs, METH_NOARGS}, - {"capitalize", (PyCFunction)stringlib_capitalize, METH_NOARGS, - _Py_capitalize__doc__}, - {"center", (PyCFunction)stringlib_center, METH_VARARGS, center__doc__}, - {"count", (PyCFunction)bytes_count, METH_VARARGS, count__doc__}, - BYTES_DECODE_METHODDEF - {"endswith", (PyCFunction)bytes_endswith, METH_VARARGS, - endswith__doc__}, - {"expandtabs", (PyCFunction)stringlib_expandtabs, METH_VARARGS | METH_KEYWORDS, - expandtabs__doc__}, - {"find", (PyCFunction)bytes_find, METH_VARARGS, find__doc__}, - BYTES_FROMHEX_METHODDEF - {"index", (PyCFunction)bytes_index, METH_VARARGS, index__doc__}, - {"isalnum", (PyCFunction)stringlib_isalnum, METH_NOARGS, - _Py_isalnum__doc__}, - {"isalpha", (PyCFunction)stringlib_isalpha, METH_NOARGS, - _Py_isalpha__doc__}, - {"isdigit", (PyCFunction)stringlib_isdigit, METH_NOARGS, - _Py_isdigit__doc__}, - {"islower", (PyCFunction)stringlib_islower, METH_NOARGS, - _Py_islower__doc__}, - {"isspace", (PyCFunction)stringlib_isspace, METH_NOARGS, - _Py_isspace__doc__}, - {"istitle", (PyCFunction)stringlib_istitle, METH_NOARGS, - _Py_istitle__doc__}, - {"isupper", (PyCFunction)stringlib_isupper, METH_NOARGS, - _Py_isupper__doc__}, - BYTES_JOIN_METHODDEF - {"ljust", (PyCFunction)stringlib_ljust, METH_VARARGS, ljust__doc__}, - {"lower", (PyCFunction)stringlib_lower, METH_NOARGS, _Py_lower__doc__}, - BYTES_LSTRIP_METHODDEF - BYTES_MAKETRANS_METHODDEF - BYTES_PARTITION_METHODDEF - BYTES_REPLACE_METHODDEF - {"rfind", (PyCFunction)bytes_rfind, METH_VARARGS, rfind__doc__}, - {"rindex", (PyCFunction)bytes_rindex, METH_VARARGS, rindex__doc__}, - {"rjust", (PyCFunction)stringlib_rjust, METH_VARARGS, rjust__doc__}, - BYTES_RPARTITION_METHODDEF - BYTES_RSPLIT_METHODDEF - BYTES_RSTRIP_METHODDEF - BYTES_SPLIT_METHODDEF - BYTES_SPLITLINES_METHODDEF - {"startswith", (PyCFunction)bytes_startswith, METH_VARARGS, - startswith__doc__}, - BYTES_STRIP_METHODDEF - {"swapcase", (PyCFunction)stringlib_swapcase, METH_NOARGS, - _Py_swapcase__doc__}, - {"title", (PyCFunction)stringlib_title, METH_NOARGS, _Py_title__doc__}, - BYTES_TRANSLATE_METHODDEF - {"upper", (PyCFunction)stringlib_upper, METH_NOARGS, _Py_upper__doc__}, - {"zfill", (PyCFunction)stringlib_zfill, METH_VARARGS, zfill__doc__}, - {NULL, NULL} /* sentinel */ -}; - -static PyObject * -bytes_mod(PyObject *v, PyObject *w) -{ - if (!PyBytes_Check(v)) - Py_RETURN_NOTIMPLEMENTED; - return _PyBytes_Format(v, w); -} - -static PyNumberMethods bytes_as_number = { - 0, /*nb_add*/ - 0, /*nb_subtract*/ - 0, /*nb_multiply*/ - bytes_mod, /*nb_remainder*/ -}; - -static PyObject * -str_subtype_new(PyTypeObject *type, PyObject *args, PyObject *kwds); - -static PyObject * -bytes_new(PyTypeObject *type, PyObject *args, PyObject *kwds) -{ - PyObject *x = NULL; - const char *encoding = NULL; - const char *errors = NULL; - PyObject *new = NULL; - PyObject *func; - Py_ssize_t size; - static char *kwlist[] = {"source", "encoding", "errors", 0}; - _Py_IDENTIFIER(__bytes__); - - if (type != &PyBytes_Type) - return str_subtype_new(type, args, kwds); - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|Oss:bytes", kwlist, &x, - &encoding, &errors)) - return NULL; - if (x == NULL) { - if (encoding != NULL || errors != NULL) { - PyErr_SetString(PyExc_TypeError, - "encoding or errors without sequence " - "argument"); - return NULL; - } - return PyBytes_FromStringAndSize(NULL, 0); - } - - if (PyUnicode_Check(x)) { - /* Encode via the codec registry */ - if (encoding == NULL) { - PyErr_SetString(PyExc_TypeError, - "string argument without an encoding"); - return NULL; - } - new = PyUnicode_AsEncodedString(x, encoding, errors); - if (new == NULL) - return NULL; - assert(PyBytes_Check(new)); - return new; - } - - /* If it's not unicode, there can't be encoding or errors */ - if (encoding != NULL || errors != NULL) { - PyErr_SetString(PyExc_TypeError, - "encoding or errors without a string argument"); - return NULL; - } - - /* We'd like to call PyObject_Bytes here, but we need to check for an - integer argument before deferring to PyBytes_FromObject, something - PyObject_Bytes doesn't do. */ - func = _PyObject_LookupSpecial(x, &PyId___bytes__); - if (func != NULL) { - new = PyObject_CallFunctionObjArgs(func, NULL); - Py_DECREF(func); - if (new == NULL) - return NULL; - if (!PyBytes_Check(new)) { - PyErr_Format(PyExc_TypeError, - "__bytes__ returned non-bytes (type %.200s)", - Py_TYPE(new)->tp_name); - Py_DECREF(new); - return NULL; - } - return new; - } - else if (PyErr_Occurred()) - return NULL; - - /* Is it an integer? */ - size = PyNumber_AsSsize_t(x, PyExc_OverflowError); - if (size == -1 && PyErr_Occurred()) { - if (PyErr_ExceptionMatches(PyExc_OverflowError)) - return NULL; - PyErr_Clear(); - } - else if (size < 0) { - PyErr_SetString(PyExc_ValueError, "negative count"); - return NULL; - } - else { - new = _PyBytes_FromSize(size, 1); - if (new == NULL) - return NULL; - return new; - } - - return PyBytes_FromObject(x); -} - -PyObject * -PyBytes_FromObject(PyObject *x) -{ - PyObject *new, *it; - Py_ssize_t i, size; - - if (x == NULL) { - PyErr_BadInternalCall(); - return NULL; - } - - if (PyBytes_CheckExact(x)) { - Py_INCREF(x); - return x; - } - - /* Use the modern buffer interface */ - if (PyObject_CheckBuffer(x)) { - Py_buffer view; - if (PyObject_GetBuffer(x, &view, PyBUF_FULL_RO) < 0) - return NULL; - new = PyBytes_FromStringAndSize(NULL, view.len); - if (!new) - goto fail; - if (PyBuffer_ToContiguous(((PyBytesObject *)new)->ob_sval, - &view, view.len, 'C') < 0) - goto fail; - PyBuffer_Release(&view); - return new; - fail: - Py_XDECREF(new); - PyBuffer_Release(&view); - return NULL; - } - if (PyUnicode_Check(x)) { - PyErr_SetString(PyExc_TypeError, - "cannot convert unicode object to bytes"); - return NULL; - } - - if (PyList_CheckExact(x)) { - new = PyBytes_FromStringAndSize(NULL, Py_SIZE(x)); - if (new == NULL) - return NULL; - for (i = 0; i < Py_SIZE(x); i++) { - Py_ssize_t value = PyNumber_AsSsize_t( - PyList_GET_ITEM(x, i), PyExc_ValueError); - if (value == -1 && PyErr_Occurred()) { - Py_DECREF(new); - return NULL; - } - if (value < 0 || value >= 256) { - PyErr_SetString(PyExc_ValueError, - "bytes must be in range(0, 256)"); - Py_DECREF(new); - return NULL; - } - ((PyBytesObject *)new)->ob_sval[i] = (char) value; - } - return new; - } - if (PyTuple_CheckExact(x)) { - new = PyBytes_FromStringAndSize(NULL, Py_SIZE(x)); - if (new == NULL) - return NULL; - for (i = 0; i < Py_SIZE(x); i++) { - Py_ssize_t value = PyNumber_AsSsize_t( - PyTuple_GET_ITEM(x, i), PyExc_ValueError); - if (value == -1 && PyErr_Occurred()) { - Py_DECREF(new); - return NULL; - } - if (value < 0 || value >= 256) { - PyErr_SetString(PyExc_ValueError, - "bytes must be in range(0, 256)"); - Py_DECREF(new); - return NULL; - } - ((PyBytesObject *)new)->ob_sval[i] = (char) value; - } - return new; - } - - /* For iterator version, create a string object and resize as needed */ - size = PyObject_LengthHint(x, 64); - if (size == -1 && PyErr_Occurred()) - return NULL; - /* Allocate an extra byte to prevent PyBytes_FromStringAndSize() from - returning a shared empty bytes string. This required because we - want to call _PyBytes_Resize() the returned object, which we can - only do on bytes objects with refcount == 1. */ - if (size == 0) - size = 1; - new = PyBytes_FromStringAndSize(NULL, size); - if (new == NULL) - return NULL; - assert(Py_REFCNT(new) == 1); - - /* Get the iterator */ - it = PyObject_GetIter(x); - if (it == NULL) - goto error; - - /* Run the iterator to exhaustion */ - for (i = 0; ; i++) { - PyObject *item; - Py_ssize_t value; - - /* Get the next item */ - item = PyIter_Next(it); - if (item == NULL) { - if (PyErr_Occurred()) - goto error; - break; - } - - /* Interpret it as an int (__index__) */ - value = PyNumber_AsSsize_t(item, PyExc_ValueError); - Py_DECREF(item); - if (value == -1 && PyErr_Occurred()) - goto error; - - /* Range check */ - if (value < 0 || value >= 256) { - PyErr_SetString(PyExc_ValueError, - "bytes must be in range(0, 256)"); - goto error; - } - - /* Append the byte */ - if (i >= size) { - size = 2 * size + 1; - if (_PyBytes_Resize(&new, size) < 0) - goto error; - } - ((PyBytesObject *)new)->ob_sval[i] = (char) value; - } - _PyBytes_Resize(&new, i); - - /* Clean up and return success */ - Py_DECREF(it); - return new; - - error: - Py_XDECREF(it); - Py_XDECREF(new); - return NULL; -} - -static PyObject * -str_subtype_new(PyTypeObject *type, PyObject *args, PyObject *kwds) -{ - PyObject *tmp, *pnew; - Py_ssize_t n; - - assert(PyType_IsSubtype(type, &PyBytes_Type)); - tmp = bytes_new(&PyBytes_Type, args, kwds); - if (tmp == NULL) - return NULL; - assert(PyBytes_CheckExact(tmp)); - n = PyBytes_GET_SIZE(tmp); - pnew = type->tp_alloc(type, n); - if (pnew != NULL) { - Py_MEMCPY(PyBytes_AS_STRING(pnew), - PyBytes_AS_STRING(tmp), n+1); - ((PyBytesObject *)pnew)->ob_shash = - ((PyBytesObject *)tmp)->ob_shash; - } - Py_DECREF(tmp); - return pnew; -} - -PyDoc_STRVAR(bytes_doc, -"bytes(iterable_of_ints) -> bytes\n\ -bytes(string, encoding[, errors]) -> bytes\n\ -bytes(bytes_or_buffer) -> immutable copy of bytes_or_buffer\n\ -bytes(int) -> bytes object of size given by the parameter initialized with null bytes\n\ -bytes() -> empty bytes object\n\ -\n\ -Construct an immutable array of bytes from:\n\ - - an iterable yielding integers in range(256)\n\ - - a text string encoded using the specified encoding\n\ - - any object implementing the buffer API.\n\ - - an integer"); - -static PyObject *bytes_iter(PyObject *seq); - -PyTypeObject PyBytes_Type = { - PyVarObject_HEAD_INIT(&PyType_Type, 0) - "bytes", - PyBytesObject_SIZE, - sizeof(char), - bytes_dealloc, /* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_reserved */ - (reprfunc)bytes_repr, /* tp_repr */ - &bytes_as_number, /* tp_as_number */ - &bytes_as_sequence, /* tp_as_sequence */ - &bytes_as_mapping, /* tp_as_mapping */ - (hashfunc)bytes_hash, /* tp_hash */ - 0, /* tp_call */ - bytes_str, /* tp_str */ - PyObject_GenericGetAttr, /* tp_getattro */ - 0, /* tp_setattro */ - &bytes_as_buffer, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | - Py_TPFLAGS_BYTES_SUBCLASS, /* tp_flags */ - bytes_doc, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - (richcmpfunc)bytes_richcompare, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - bytes_iter, /* tp_iter */ - 0, /* tp_iternext */ - bytes_methods, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - &PyBaseObject_Type, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - bytes_new, /* tp_new */ - PyObject_Del, /* tp_free */ -}; - -void -PyBytes_Concat(PyObject **pv, PyObject *w) -{ - assert(pv != NULL); - if (*pv == NULL) - return; - if (w == NULL) { - Py_CLEAR(*pv); - return; - } - - if (Py_REFCNT(*pv) == 1 && PyBytes_CheckExact(*pv)) { - /* Only one reference, so we can resize in place */ - Py_ssize_t oldsize; - Py_buffer wb; - - wb.len = -1; - if (PyObject_GetBuffer(w, &wb, PyBUF_SIMPLE) != 0) { - PyErr_Format(PyExc_TypeError, "can't concat %.100s to %.100s", - Py_TYPE(w)->tp_name, Py_TYPE(*pv)->tp_name); - Py_CLEAR(*pv); - return; - } - - oldsize = PyBytes_GET_SIZE(*pv); - if (oldsize > PY_SSIZE_T_MAX - wb.len) { - PyErr_NoMemory(); - goto error; - } - if (_PyBytes_Resize(pv, oldsize + wb.len) < 0) - goto error; - - memcpy(PyBytes_AS_STRING(*pv) + oldsize, wb.buf, wb.len); - PyBuffer_Release(&wb); - return; - - error: - PyBuffer_Release(&wb); - Py_CLEAR(*pv); - return; - } - - else { - /* Multiple references, need to create new object */ - PyObject *v; - v = bytes_concat(*pv, w); - Py_DECREF(*pv); - *pv = v; - } -} - -void -PyBytes_ConcatAndDel(PyObject **pv, PyObject *w) -{ - PyBytes_Concat(pv, w); - Py_XDECREF(w); -} - - -/* The following function breaks the notion that bytes are immutable: - it changes the size of a bytes object. We get away with this only if there - is only one module referencing the object. You can also think of it - as creating a new bytes object and destroying the old one, only - more efficiently. In any case, don't use this if the bytes object may - already be known to some other part of the code... - Note that if there's not enough memory to resize the bytes object, the - original bytes object at *pv is deallocated, *pv is set to NULL, an "out of - memory" exception is set, and -1 is returned. Else (on success) 0 is - returned, and the value in *pv may or may not be the same as on input. - As always, an extra byte is allocated for a trailing \0 byte (newsize - does *not* include that), and a trailing \0 byte is stored. -*/ - -int -_PyBytes_Resize(PyObject **pv, Py_ssize_t newsize) -{ - PyObject *v; - PyBytesObject *sv; - v = *pv; - if (!PyBytes_Check(v) || Py_REFCNT(v) != 1 || newsize < 0) { - *pv = 0; - Py_DECREF(v); - PyErr_BadInternalCall(); - return -1; - } - /* XXX UNREF/NEWREF interface should be more symmetrical */ - _Py_DEC_REFTOTAL; - _Py_ForgetReference(v); - *pv = (PyObject *) - PyObject_REALLOC(v, PyBytesObject_SIZE + newsize); - if (*pv == NULL) { - PyObject_Del(v); - PyErr_NoMemory(); - return -1; - } - _Py_NewReference(*pv); - sv = (PyBytesObject *) *pv; - Py_SIZE(sv) = newsize; - sv->ob_sval[newsize] = '\0'; - sv->ob_shash = -1; /* invalidate cached hash value */ - return 0; -} - -void -PyBytes_Fini(void) -{ - int i; - for (i = 0; i < UCHAR_MAX + 1; i++) - Py_CLEAR(characters[i]); - Py_CLEAR(nullstring); -} - -/*********************** Bytes Iterator ****************************/ - -typedef struct { - PyObject_HEAD - Py_ssize_t it_index; - PyBytesObject *it_seq; /* Set to NULL when iterator is exhausted */ -} striterobject; - -static void -striter_dealloc(striterobject *it) -{ - _PyObject_GC_UNTRACK(it); - Py_XDECREF(it->it_seq); - PyObject_GC_Del(it); -} - -static int -striter_traverse(striterobject *it, visitproc visit, void *arg) -{ - Py_VISIT(it->it_seq); - return 0; -} - -static PyObject * -striter_next(striterobject *it) -{ - PyBytesObject *seq; - PyObject *item; - - assert(it != NULL); - seq = it->it_seq; - if (seq == NULL) - return NULL; - assert(PyBytes_Check(seq)); - - if (it->it_index < PyBytes_GET_SIZE(seq)) { - item = PyLong_FromLong( - (unsigned char)seq->ob_sval[it->it_index]); - if (item != NULL) - ++it->it_index; - return item; - } - - Py_DECREF(seq); - it->it_seq = NULL; - return NULL; -} - -static PyObject * -striter_len(striterobject *it) -{ - Py_ssize_t len = 0; - if (it->it_seq) - len = PyBytes_GET_SIZE(it->it_seq) - it->it_index; - return PyLong_FromSsize_t(len); -} - -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 (it->it_seq != NULL) { - if (index < 0) - index = 0; - else if (index > PyBytes_GET_SIZE(it->it_seq)) - index = PyBytes_GET_SIZE(it->it_seq); /* iterator exhausted */ - 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 */ -}; - -PyTypeObject PyBytesIter_Type = { - PyVarObject_HEAD_INIT(&PyType_Type, 0) - "bytes_iterator", /* tp_name */ - sizeof(striterobject), /* tp_basicsize */ - 0, /* tp_itemsize */ - /* methods */ - (destructor)striter_dealloc, /* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_reserved */ - 0, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - PyObject_GenericGetAttr, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */ - 0, /* tp_doc */ - (traverseproc)striter_traverse, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - PyObject_SelfIter, /* tp_iter */ - (iternextfunc)striter_next, /* tp_iternext */ - striter_methods, /* tp_methods */ - 0, -}; - -static PyObject * -bytes_iter(PyObject *seq) -{ - striterobject *it; - - if (!PyBytes_Check(seq)) { - PyErr_BadInternalCall(); - return NULL; - } - it = PyObject_GC_New(striterobject, &PyBytesIter_Type); - if (it == NULL) - return NULL; - it->it_index = 0; - Py_INCREF(seq); - it->it_seq = (PyBytesObject *)seq; - _PyObject_GC_TRACK(it); - return (PyObject *)it; -} +/*[clinic end generated code: output=dfe5c9a317b99f49 input=a9049054013a1b77]*/ diff --git a/Objects/dictobject.c b/Objects/clinic/dictobject.c.h copy from Objects/dictobject.c copy to Objects/clinic/dictobject.c.h --- a/Objects/dictobject.c +++ b/Objects/clinic/dictobject.c.h @@ -1,1760 +1,5 @@ - -/* Dictionary object implementation using a hash table */ - -/* The distribution includes a separate file, Objects/dictnotes.txt, - describing explorations into dictionary design and optimization. - It covers typical dictionary use patterns, the parameters for - 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" - /*[clinic input] -class dict "PyDictObject *" "&PyDict_Type" -[clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=f157a5a0ce9589d6]*/ - -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. -*/ - -#define PERTURB_SHIFT 5 - -/* -Major subtleties ahead: Most hash schemes depend on having a "good" hash -function, in the sense of simulating randomness. Python doesn't: its most -important hash functions (for strings and ints) are very regular in common -cases: - - >>> map(hash, (0, 1, 2, 3)) - [0, 1, 2, 3] - >>> map(hash, ("namea", "nameb", "namec", "named")) - [-1658398457, -1658398460, -1658398459, -1658398462] - >>> - -This isn't necessarily bad! To the contrary, in a table of size 2**i, taking -the low-order i bits as the initial table index is extremely fast, and there -are no collisions at all for dicts indexed by a contiguous range of ints. -The same is approximately true when keys are "consecutive" strings. So this -gives better-than-random behavior in common cases, and that's very desirable. - -OTOH, when collisions occur, the tendency to fill contiguous slices of the -hash table makes a good collision resolution strategy crucial. Taking only -the last i bits of the hash code is also vulnerable: for example, consider -the list [i << 16 for i in range(20000)] as a set of keys. Since ints are -their own hash codes, and this fits in a dict of size 2**15, the last 15 bits - of every hash code are all 0: they *all* map to the same table index. - -But catering to unusual cases should not slow the usual ones, so we just take -the last i bits anyway. It's up to collision resolution to do the rest. If -we *usually* find the key we're looking for on the first try (and, it turns -out, we usually do -- the table load factor is kept under 2/3, so the odds -are solidly in our favor), then it makes best sense to keep the initial index -computation dirt cheap. - -The first half of collision resolution is to visit table indices via this -recurrence: - - j = ((5*j) + 1) mod 2**i - -For any initial j in range(2**i), repeating that 2**i times generates each -int in range(2**i) exactly once (see any text on random-number generation for -proof). By itself, this doesn't help much: like linear probing (setting -j += 1, or j -= 1, on each loop trip), it scans the table entries in a fixed -order. This would be bad, except that's not the only thing we do, and it's -actually *good* in the common cases where hash keys are consecutive. In an -example that's really too small to make this entirely clear, for a table of -size 2**3 the order of indices is: - - 0 -> 1 -> 6 -> 7 -> 4 -> 5 -> 2 -> 3 -> 0 [and here it's repeating] - -If two things come in at index 5, the first place we look after is index 2, -not 6, so if another comes in at index 6 the collision at 5 didn't hurt it. -Linear probing is deadly in this case because there the fixed probe order -is the *same* as the order consecutive keys are likely to arrive. But it's -extremely unlikely hash codes will follow a 5*j+1 recurrence by accident, -and certain that consecutive hash codes do not. - -The other half of the strategy is to get the other bits of the hash code -into play. This is done by initializing a (unsigned) vrbl "perturb" to the -full hash code, and changing the recurrence to: - - j = (5*j) + 1 + perturb; - perturb >>= PERTURB_SHIFT; - use j % 2**i as the next table index; - -Now the probe sequence depends (eventually) on every bit in the hash code, -and the pseudo-scrambling property of recurring on 5*j+1 is more valuable, -because it quickly magnifies small differences in the bits that didn't affect -the initial index. Note that because perturb is unsigned, if the recurrence -is executed often enough perturb eventually becomes and remains 0. At that -point (very rarely reached) the recurrence is on (just) 5*j+1 again, and -that's certain to find an empty slot eventually (since it generates every int -in range(2**i), and we make sure there's always at least one empty slot). - -Selecting a good value for PERTURB_SHIFT is a balancing act. You want it -small so that the high bits of the hash code continue to affect the probe -sequence across iterations; but you want it large so that in really bad cases -the high-order hash bits have an effect on early iterations. 5 was "the -best" in minimizing total collisions across experiments Tim Peters ran (on -both normal and pathological cases), but 4 and 6 weren't significantly worse. - -Historical: Reimer Behrends contributed the idea of using a polynomial-based -approach, using repeated multiplication by x in GF(2**n) where an irreducible -polynomial for each table size was chosen such that x was a primitive root. -Christian Tismer later extended that to use division by x instead, as an -efficient way to get the high bits of the hash code into play. This scheme -also gave excellent collision statistics, but was more expensive: two -if-tests were required inside the loop; computing "the next" index took about -the same number of operations but without as much potential parallelism -(e.g., computing 5*j can go on at the same time as computing 1+perturb in the -above, and then shifting perturb can be done while the table index is being -masked); and the PyDictObject struct required a member to hold the table's -polynomial. In Tim's experiments the current scheme ran faster, produced -equally good collision statistics, needed less code & used less memory. - -*/ - -/* 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 * -_PyDict_Dummy(void) -{ - return dummy; -} -#endif - -/* forward declarations */ -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 -#define PyDict_MAXFREELIST 80 -#endif -static PyDictObject *free_list[PyDict_MAXFREELIST]; -static int numfree = 0; - -int -PyDict_ClearFreeList(void) -{ - PyDictObject *op; - int ret = numfree; - while (numfree) { - op = free_list[--numfree]; - assert(PyDict_CheckExact(op)); - PyObject_GC_Del(op); - } - return ret; -} - -/* Print summary info about the state of the optimized allocator */ -void -_PyDict_DebugMallocStats(FILE *out) -{ - _PyDebugAllocatorStats(out, - "free PyDictObject", numfree, sizeof(PyDictObject)); -} - - -void -PyDict_Fini(void) -{ - PyDict_ClearFreeList(); -} - -#define DK_DEBUG_INCREF _Py_INC_REFTOTAL _Py_REF_DEBUG_COMMA -#define DK_DEBUG_DECREF _Py_DEC_REFTOTAL _Py_REF_DEBUG_COMMA - -#define DK_INCREF(dk) (DK_DEBUG_INCREF ++(dk)->dk_refcnt) -#define DK_DECREF(dk) if (DK_DEBUG_DECREF (--(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 is the maximum dictionary load. - * Currently set to (2n+1)/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. - * - * 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)) -*/ - -/* GROWTH_RATE. Growth rate upon hitting maximum load. - * Currently set to used*2 + capacity/2. - * This means that dicts double in size when growing without deletions, - * but have more head room when the number of deletions is on a par with the - * number of insertions. - * Raising this to used*4 doubles memory consumption depending on the size of - * the dictionary, but results in half the number of resizes, less effort to - * resize. - * GROWTH_RATE was set to used*4 up to version 3.2. - * GROWTH_RATE was set to used*2 in version 3.3.0 - */ -#define GROWTH_RATE(d) (((d)->ma_used*2)+((d)->ma_keys->dk_size>>1)) - -#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) -{ - 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_DEBUG_INCREF 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; - assert(keys != NULL); - if (numfree) { - mp = free_list[--numfree]; - assert (mp != NULL); - assert (Py_TYPE(mp) == &PyDict_Type); - _Py_NewReference((PyObject *)mp); - } - else { - mp = PyObject_GC_New(PyDictObject, &PyDict_Type); - if (mp == NULL) { - DK_DECREF(keys); - free_values(values); - return NULL; - } - } - 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) -{ - PyDictKeysObject *keys = new_keys_object(PyDict_MINSIZE_COMBINED); - if (keys == NULL) - return NULL; - return new_dict(keys, NULL); -} - -/* -The basic lookup function used by all operations. -This is based on Algorithm D from Knuth Vol. 3, Sec. 6.4. -Open addressing is preferred over chaining since the link overhead for -chaining would be substantial (100% with typical malloc overhead). - -The initial probe index is computed as hash mod the table size. Subsequent -probe indices are computed as explained earlier. - -All arithmetic on hash should ignore overflow. - -The details in this version are due to Tim Peters, building on many past -contributions by Reimer Behrends, Jyrki Alakuijala, Vladimir Marangozov and -Christian Tismer. - -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. -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 PyDictKeyEntry * -lookdict(PyDictObject *mp, PyObject *key, - Py_hash_t hash, PyObject ***value_addr) -{ - size_t i; - size_t perturb; - PyDictKeyEntry *freeslot; - size_t mask; - PyDictKeyEntry *ep0; - PyDictKeyEntry *ep; - int cmp; - PyObject *startkey; - -top: - mask = DK_MASK(mp->ma_keys); - ep0 = &mp->ma_keys->dk_entries[0]; - i = (size_t)hash & mask; - ep = &ep0[i]; - 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) { - startkey = ep->me_key; - Py_INCREF(startkey); - cmp = PyObject_RichCompareBool(startkey, key, Py_EQ); - Py_DECREF(startkey); - if (cmp < 0) - return NULL; - if (ep0 == mp->ma_keys->dk_entries && ep->me_key == startkey) { - if (cmp > 0) { - *value_addr = &ep->me_value; - return ep; - } - } - else { - /* The dict was mutated, restart */ - goto top; - } - } - freeslot = NULL; - } - - /* In the loop, me_key == dummy is by far (factor of 100s) the - least likely outcome, so test for that last. */ - for (perturb = hash; ; perturb >>= PERTURB_SHIFT) { - i = (i << 2) + i + perturb + 1; - ep = &ep0[i & mask]; - 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) { - *value_addr = NULL; - return NULL; - } - if (ep0 == mp->ma_keys->dk_entries && ep->me_key == startkey) { - if (cmp > 0) { - *value_addr = &ep->me_value; - return ep; - } - } - else { - /* The dict was mutated, restart */ - goto top; - } - } - else if (ep->me_key == dummy && freeslot == NULL) - freeslot = ep; - } - assert(0); /* NOT REACHED */ - return 0; -} - -/* Specialized version for string-only keys */ -static PyDictKeyEntry * -lookdict_unicode(PyDictObject *mp, PyObject *key, - Py_hash_t hash, PyObject ***value_addr) -{ - size_t i; - size_t perturb; - PyDictKeyEntry *freeslot; - size_t mask = DK_MASK(mp->ma_keys); - PyDictKeyEntry *ep0 = &mp->ma_keys->dk_entries[0]; - 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]; - 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)) { - *value_addr = &ep->me_value; - return ep; - } - freeslot = NULL; - } - - /* In the loop, me_key == dummy is by far (factor of 100s) the - least likely outcome, so test for that last. */ - for (perturb = hash; ; perturb >>= PERTURB_SHIFT) { - i = (i << 2) + i + perturb + 1; - ep = &ep0[i & mask]; - 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))) { - *value_addr = &ep->me_value; - return ep; - } - if (ep->me_key == dummy && freeslot == NULL) - freeslot = ep; - } - assert(0); /* NOT REACHED */ - 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) -{ - size_t i; - size_t perturb; - size_t mask = DK_MASK(mp->ma_keys); - PyDictKeyEntry *ep0 = &mp->ma_keys->dk_entries[0]; - 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) -{ - size_t i; - size_t perturb; - size_t mask = DK_MASK(mp->ma_keys); - PyDictKeyEntry *ep0 = &mp->ma_keys->dk_entries[0]; - PyDictKeyEntry *ep; - - if (!PyUnicode_CheckExact(key)) { - 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]; - 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) -{ - Py_ssize_t pos = 0; - PyObject *key, *value; - assert(PyDict_Check(dict)); - /* Shortcut */ - if (((PyDictObject *)dict)->ma_keys->dk_lookup != lookdict) - return 1; - while (PyDict_Next(dict, &pos, &key, &value)) - if (!PyUnicode_Check(key)) - return 0; - return 1; -} - -#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); \ - } \ - } \ - } while(0) - -void -_PyDict_MaybeUntrack(PyObject *op) -{ - PyDictObject *mp; - PyObject *value; - Py_ssize_t i, size; - - if (!PyDict_CheckExact(op) || !_PyObject_GC_IS_TRACKED(op)) - return; - - mp = (PyDictObject *) op; - 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; - } - } - } - 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 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 -insertion_resize(PyDictObject *mp) -{ - return dictresize(mp, GROWTH_RATE(mp)); -} - -/* -Internal routine to insert a new item into the table. -Used both by the internal resize routine and by the public insert routine. -Returns -1 if an error occurred, or 0 on success. -*/ -static int -insertdict(PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject *value) -{ - 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) { - return -1; - } - assert(PyUnicode_CheckExact(key) || mp->ma_keys->dk_lookup == lookdict); - 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 (see issue #22653) */ - } - else { - if (ep->me_key == NULL) { - Py_INCREF(key); - 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) { - Py_INCREF(key); - ep->me_key = key; - ep->me_hash = hash; - Py_DECREF(dummy); - } else { - assert(_PyDict_HasSplitTable(mp)); - } - } - mp->ma_used++; - *value_addr = value; - assert(ep->me_key != NULL && ep->me_key != dummy); - } - return 0; -} - -/* -Internal routine used by dictresize() to insert an item which is -known to be absent from the dict. This routine also assumes that -the dict contains no deleted entries. Besides the performance benefit, -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(PyDictObject *mp, PyObject *key, Py_hash_t hash, - PyObject *value) -{ - 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); - ep->me_key = key; - ep->me_hash = hash; - ep->me_value = value; -} - -/* -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; - 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) - ; - if (newsize <= 0) { - PyErr_NoMemory(); - return -1; - } - 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]; - } - } - } - /* 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); - } - } - 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); - } - } - assert(oldkeys->dk_refcnt == 1); - DK_DEBUG_DECREF PyMem_FREE(oldkeys); - } - 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) -{ - Py_ssize_t i; - Py_ssize_t size; - PyDictObject *mp = (PyDictObject *)op; - - if (!PyDict_CheckExact(op)) - return NULL; - 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) -{ - 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 new_dict(new_keys, NULL); -} - -/* Note that, for historical reasons, PyDict_GetItem() suppresses all errors - * that may occur (originally dicts supported only string keys, and exceptions - * weren't possible). So, while the original intent was that a NULL return - * meant the key wasn't present, in reality it can mean that, or that an error - * (suppressed) occurred while computing the key's hash, or that some error - * (suppressed) occurred when comparing keys in the dict's internal probe - * sequence. A nasty example of the latter is when a Python-coded comparison - * function hits a stack-depth error, which can cause this to return NULL - * even if the key is present. - */ -PyObject * -PyDict_GetItem(PyObject *op, PyObject *key) -{ - Py_hash_t hash; - PyDictObject *mp = (PyDictObject *)op; - PyDictKeyEntry *ep; - PyThreadState *tstate; - PyObject **value_addr; - - if (!PyDict_Check(op)) - return NULL; - if (!PyUnicode_CheckExact(key) || - (hash = ((PyASCIIObject *) key)->hash) == -1) - { - hash = PyObject_Hash(key); - if (hash == -1) { - PyErr_Clear(); - return NULL; - } - } - - /* We can arrive here with a NULL tstate during initialization: try - running "python -Wi" for an example related to string interning. - Let's just hope that no exception occurs then... This must be - _PyThreadState_Current and not PyThreadState_GET() because in debug - mode, the latter complains if tstate is NULL. */ - tstate = (PyThreadState*)_Py_atomic_load_relaxed( - &_PyThreadState_Current); - if (tstate != NULL && tstate->curexc_type != NULL) { - /* preserve the existing exception */ - PyObject *err_type, *err_value, *err_tb; - PyErr_Fetch(&err_type, &err_value, &err_tb); - 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_keys->dk_lookup)(mp, key, hash, &value_addr); - if (ep == NULL) { - PyErr_Clear(); - return NULL; - } - } - return *value_addr; -} - -PyObject * -_PyDict_GetItem_KnownHash(PyObject *op, PyObject *key, Py_hash_t hash) -{ - PyDictObject *mp = (PyDictObject *)op; - PyDictKeyEntry *ep; - PyThreadState *tstate; - PyObject **value_addr; - - if (!PyDict_Check(op)) - return NULL; - - /* We can arrive here with a NULL tstate during initialization: try - running "python -Wi" for an example related to string interning. - Let's just hope that no exception occurs then... This must be - _PyThreadState_Current and not PyThreadState_GET() because in debug - mode, the latter complains if tstate is NULL. */ - tstate = (PyThreadState*)_Py_atomic_load_relaxed( - &_PyThreadState_Current); - if (tstate != NULL && tstate->curexc_type != NULL) { - /* preserve the existing exception */ - PyObject *err_type, *err_value, *err_tb; - PyErr_Fetch(&err_type, &err_value, &err_tb); - 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_keys->dk_lookup)(mp, key, hash, &value_addr); - if (ep == NULL) { - PyErr_Clear(); - return NULL; - } - } - return *value_addr; -} - -/* Variant of PyDict_GetItem() that doesn't suppress exceptions. - This returns NULL *with* an exception set if an exception occurred. - It returns NULL *without* an exception set if the key wasn't present. -*/ -PyObject * -PyDict_GetItemWithError(PyObject *op, PyObject *key) -{ - Py_hash_t hash; - PyDictObject*mp = (PyDictObject *)op; - PyDictKeyEntry *ep; - PyObject **value_addr; - - if (!PyDict_Check(op)) { - PyErr_BadInternalCall(); - return NULL; - } - if (!PyUnicode_CheckExact(key) || - (hash = ((PyASCIIObject *) key)->hash) == -1) - { - hash = PyObject_Hash(key); - if (hash == -1) { - return NULL; - } - } - - ep = (mp->ma_keys->dk_lookup)(mp, key, hash, &value_addr); - if (ep == NULL) - return NULL; - return *value_addr; -} - -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); -} - -/* Fast version of global value lookup. - * Lookup in globals, then builtins. - */ -PyObject * -_PyDict_LoadGlobal(PyDictObject *globals, PyDictObject *builtins, PyObject *key) -{ - 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; - } - } - 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 - * dictionary if it's merely replacing the value for an existing key. - * This means that it's safe to loop over a dictionary with PyDict_Next() - * and occasionally replace a value -- but you can't insert new keys or - * remove them. - */ -int -PyDict_SetItem(PyObject *op, PyObject *key, PyObject *value) -{ - PyDictObject *mp; - Py_hash_t hash; - if (!PyDict_Check(op)) { - PyErr_BadInternalCall(); - return -1; - } - assert(key); - assert(value); - mp = (PyDictObject *)op; - if (!PyUnicode_CheckExact(key) || - (hash = ((PyASCIIObject *) key)->hash) == -1) - { - hash = PyObject_Hash(key); - if (hash == -1) - return -1; - } - - /* insertdict() handles any resizing that might be necessary */ - return insertdict(mp, key, hash, value); -} - -int -_PyDict_SetItem_KnownHash(PyObject *op, PyObject *key, PyObject *value, - Py_hash_t hash) -{ - PyDictObject *mp; - - if (!PyDict_Check(op)) { - PyErr_BadInternalCall(); - return -1; - } - assert(key); - assert(value); - mp = (PyDictObject *)op; - - /* insertdict() handles any resizing that might be necessary */ - return insertdict(mp, key, hash, value); -} - -int -PyDict_DelItem(PyObject *op, PyObject *key) -{ - PyDictObject *mp; - Py_hash_t hash; - PyDictKeyEntry *ep; - PyObject *old_key, *old_value; - PyObject **value_addr; - - if (!PyDict_Check(op)) { - PyErr_BadInternalCall(); - return -1; - } - assert(key); - if (!PyUnicode_CheckExact(key) || - (hash = ((PyASCIIObject *) key)->hash) == -1) { - hash = PyObject_Hash(key); - if (hash == -1) - return -1; - } - mp = (PyDictObject *)op; - ep = (mp->ma_keys->dk_lookup)(mp, key, hash, &value_addr); - if (ep == NULL) - return -1; - if (*value_addr == NULL) { - _PyErr_SetKeyError(key); - return -1; - } - 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); - return 0; -} - -void -PyDict_Clear(PyObject *op) -{ - PyDictObject *mp; - PyDictKeysObject *oldkeys; - PyObject **oldvalues; - Py_ssize_t i, n; - - 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); - DK_DECREF(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; - if (i < 0) - return -1; - if (mp->ma_values) { - value_ptr = &mp->ma_values[i]; - offset = sizeof(PyObject *); - } - else { - value_ptr = &mp->ma_keys->dk_entries[i].me_value; - offset = sizeof(PyDictKeyEntry); - } - 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; -} - -/* - * Iterate over a dict. Use like so: - * - * Py_ssize_t i; - * PyObject *key, *value; - * i = 0; # important! i should not otherwise be changed by you - * while (PyDict_Next(yourdict, &i, &key, &value)) { - * Refer to borrowed references in key and value. - * } - * - * CAUTION: In general, it isn't safe to use PyDict_Next in a loop that - * mutates the dict. One exception: it is safe if the loop merely changes - * the values associated with the keys (but doesn't insert new keys or - * delete keys), via PyDict_SetItem(). - */ -int -PyDict_Next(PyObject *op, Py_ssize_t *ppos, PyObject **pkey, PyObject **pvalue) -{ - PyDictObject *mp; - Py_ssize_t i = dict_next(op, *ppos, pvalue); - if (i < 0) - return 0; - mp = (PyDictObject *)op; - *ppos = i+1; - if (pkey) - *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. - */ -int -_PyDict_Next(PyObject *op, Py_ssize_t *ppos, PyObject **pkey, - PyObject **pvalue, Py_hash_t *phash) -{ - PyDictObject *mp; - Py_ssize_t i = dict_next(op, *ppos, pvalue); - if (i < 0) - return 0; - mp = (PyDictObject *)op; - *ppos = i+1; - *phash = mp->ma_keys->dk_entries[i].me_hash; - if (pkey) - *pkey = mp->ma_keys->dk_entries[i].me_key; - return 1; -} - -/* Methods */ - -static void -dict_dealloc(PyDictObject *mp) -{ - PyObject **values = mp->ma_values; - PyDictKeysObject *keys = mp->ma_keys; - Py_ssize_t i, n; - PyObject_GC_UnTrack(mp); - Py_TRASHCAN_SAFE_BEGIN(mp) - 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); - } - else if (keys != NULL) { - assert(keys->dk_refcnt == 1); - DK_DECREF(keys); - } - if (numfree < PyDict_MAXFREELIST && Py_TYPE(mp) == &PyDict_Type) - free_list[numfree++] = mp; - else - Py_TYPE(mp)->tp_free((PyObject *)mp); - Py_TRASHCAN_SAFE_END(mp) -} - - -static PyObject * -dict_repr(PyDictObject *mp) -{ - Py_ssize_t i; - PyObject *key = NULL, *value = NULL; - _PyUnicodeWriter writer; - int first; - - i = Py_ReprEnter((PyObject *)mp); - if (i != 0) { - return i > 0 ? PyUnicode_FromString("{...}") : NULL; - } - - if (mp->ma_used == 0) { - Py_ReprLeave((PyObject *)mp); - return PyUnicode_FromString("{}"); - } - - _PyUnicodeWriter_Init(&writer); - writer.overallocate = 1; - /* "{" + "1: 2" + ", 3: 4" * (len - 1) + "}" */ - writer.min_length = 1 + 4 + (2 + 4) * (mp->ma_used - 1) + 1; - - if (_PyUnicodeWriter_WriteChar(&writer, '{') < 0) - goto error; - - /* Do repr() on each key+value pair, and insert ": " between them. - Note that repr may mutate the dict. */ - i = 0; - first = 1; - while (PyDict_Next((PyObject *)mp, &i, &key, &value)) { - PyObject *s; - int res; - - /* Prevent repr from deleting key or value during key format. */ - Py_INCREF(key); - Py_INCREF(value); - - if (!first) { - if (_PyUnicodeWriter_WriteASCIIString(&writer, ", ", 2) < 0) - goto error; - } - first = 0; - - s = PyObject_Repr(key); - if (s == NULL) - goto error; - res = _PyUnicodeWriter_WriteStr(&writer, s); - Py_DECREF(s); - if (res < 0) - goto error; - - if (_PyUnicodeWriter_WriteASCIIString(&writer, ": ", 2) < 0) - goto error; - - s = PyObject_Repr(value); - if (s == NULL) - goto error; - res = _PyUnicodeWriter_WriteStr(&writer, s); - Py_DECREF(s); - if (res < 0) - goto error; - - Py_CLEAR(key); - Py_CLEAR(value); - } - - writer.overallocate = 0; - if (_PyUnicodeWriter_WriteChar(&writer, '}') < 0) - goto error; - - Py_ReprLeave((PyObject *)mp); - - return _PyUnicodeWriter_Finish(&writer); - -error: - Py_ReprLeave((PyObject *)mp); - _PyUnicodeWriter_Dealloc(&writer); - Py_XDECREF(key); - Py_XDECREF(value); - return NULL; -} - -static Py_ssize_t -dict_length(PyDictObject *mp) -{ - return mp->ma_used; -} - -static PyObject * -dict_subscript(PyDictObject *mp, PyObject *key) -{ - PyObject *v; - Py_hash_t hash; - 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_keys->dk_lookup)(mp, key, hash, &value_addr); - if (ep == NULL) - return NULL; - v = *value_addr; - if (v == NULL) { - if (!PyDict_CheckExact(mp)) { - /* Look up __missing__ method if we're a subclass. */ - PyObject *missing, *res; - _Py_IDENTIFIER(__missing__); - missing = _PyObject_LookupSpecial((PyObject *)mp, &PyId___missing__); - if (missing != NULL) { - res = PyObject_CallFunctionObjArgs(missing, - key, NULL); - Py_DECREF(missing); - return res; - } - else if (PyErr_Occurred()) - return NULL; - } - _PyErr_SetKeyError(key); - return NULL; - } - else - Py_INCREF(v); - return v; -} - -static int -dict_ass_sub(PyDictObject *mp, PyObject *v, PyObject *w) -{ - if (w == NULL) - return PyDict_DelItem((PyObject *)mp, v); - else - return PyDict_SetItem((PyObject *)mp, v, w); -} - -static PyMappingMethods dict_as_mapping = { - (lenfunc)dict_length, /*mp_length*/ - (binaryfunc)dict_subscript, /*mp_subscript*/ - (objobjargproc)dict_ass_sub, /*mp_ass_subscript*/ -}; - -static PyObject * -dict_keys(PyDictObject *mp) -{ - PyObject *v; - Py_ssize_t i, j; - PyDictKeyEntry *ep; - Py_ssize_t size, n, offset; - PyObject **value_ptr; - - again: - n = mp->ma_used; - v = PyList_New(n); - if (v == NULL) - return NULL; - if (n != mp->ma_used) { - /* Durnit. The allocations caused the dict to resize. - * Just start over, this shouldn't normally happen. - */ - Py_DECREF(v); - goto again; - } - 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; -} - -static PyObject * -dict_values(PyDictObject *mp) -{ - PyObject *v; - Py_ssize_t i, j; - Py_ssize_t size, n, offset; - PyObject **value_ptr; - - again: - n = mp->ma_used; - v = PyList_New(n); - if (v == NULL) - return NULL; - if (n != mp->ma_used) { - /* Durnit. The allocations caused the dict to resize. - * Just start over, this shouldn't normally happen. - */ - Py_DECREF(v); - goto again; - } - 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++; - } - } - assert(j == n); - return v; -} - -static PyObject * -dict_items(PyDictObject *mp) -{ - PyObject *v; - Py_ssize_t i, j, n; - 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 - * could resize the dict. :-( - */ - again: - n = mp->ma_used; - v = PyList_New(n); - if (v == NULL) - return NULL; - for (i = 0; i < n; i++) { - item = PyTuple_New(2); - if (item == NULL) { - Py_DECREF(v); - return NULL; - } - PyList_SET_ITEM(v, i, item); - } - if (n != mp->ma_used) { - /* Durnit. The allocations caused the dict to resize. - * Just start over, this shouldn't normally happen. - */ - Py_DECREF(v); - goto again; - } - /* Nothing we do below makes any function calls. */ - 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); - PyTuple_SET_ITEM(item, 0, key); - Py_INCREF(value); - PyTuple_SET_ITEM(item, 1, value); - j++; - } - } - assert(j == n); - return v; -} - -/*[clinic input] - at classmethod -dict.fromkeys - iterable: object - value: object=None - / - -Returns a new dict with keys from iterable and values equal to value. +preserve [clinic start generated code]*/ PyDoc_STRVAR(dict_fromkeys__doc__, @@ -1786,486 +31,6 @@ return return_value; } -static PyObject * -dict_fromkeys_impl(PyTypeObject *type, PyObject *iterable, PyObject *value) -/*[clinic end generated code: output=55f8dc0ffa87406f input=b85a667f9bf4669d]*/ -{ - PyObject *it; /* iter(seq) */ - PyObject *key; - PyObject *d; - int status; - - d = PyObject_CallObject((PyObject *)type, NULL); - if (d == NULL) - return NULL; - - if (PyDict_CheckExact(d) && ((PyDictObject *)d)->ma_used == 0) { - if (PyDict_CheckExact(iterable)) { - PyDictObject *mp = (PyDictObject *)d; - PyObject *oldvalue; - Py_ssize_t pos = 0; - PyObject *key; - Py_hash_t hash; - - if (dictresize(mp, Py_SIZE(iterable))) { - Py_DECREF(d); - return NULL; - } - - while (_PyDict_Next(iterable, &pos, &key, &oldvalue, &hash)) { - if (insertdict(mp, key, hash, value)) { - Py_DECREF(d); - return NULL; - } - } - return d; - } - if (PyAnySet_CheckExact(iterable)) { - PyDictObject *mp = (PyDictObject *)d; - Py_ssize_t pos = 0; - PyObject *key; - Py_hash_t hash; - - if (dictresize(mp, PySet_GET_SIZE(iterable))) { - Py_DECREF(d); - return NULL; - } - - while (_PySet_NextEntry(iterable, &pos, &key, &hash)) { - if (insertdict(mp, key, hash, value)) { - Py_DECREF(d); - return NULL; - } - } - return d; - } - } - - it = PyObject_GetIter(iterable); - if (it == NULL){ - Py_DECREF(d); - return NULL; - } - - if (PyDict_CheckExact(d)) { - while ((key = PyIter_Next(it)) != NULL) { - status = PyDict_SetItem(d, key, value); - Py_DECREF(key); - if (status < 0) - goto Fail; - } - } else { - while ((key = PyIter_Next(it)) != NULL) { - status = PyObject_SetItem(d, key, value); - Py_DECREF(key); - if (status < 0) - goto Fail; - } - } - - if (PyErr_Occurred()) - goto Fail; - Py_DECREF(it); - return d; - -Fail: - Py_DECREF(it); - Py_DECREF(d); - return NULL; -} - -static int -dict_update_common(PyObject *self, PyObject *args, PyObject *kwds, char *methname) -{ - PyObject *arg = NULL; - int result = 0; - - if (!PyArg_UnpackTuple(args, methname, 0, 1, &arg)) - result = -1; - - else if (arg != NULL) { - _Py_IDENTIFIER(keys); - if (_PyObject_HasAttrId(arg, &PyId_keys)) - result = PyDict_Merge(self, arg, 1); - else - result = PyDict_MergeFromSeq2(self, arg, 1); - } - if (result == 0 && kwds != NULL) { - if (PyArg_ValidateKeywordArguments(kwds)) - result = PyDict_Merge(self, kwds, 1); - else - result = -1; - } - return result; -} - -static PyObject * -dict_update(PyObject *self, PyObject *args, PyObject *kwds) -{ - if (dict_update_common(self, args, kwds, "update") != -1) - Py_RETURN_NONE; - return NULL; -} - -/* Update unconditionally replaces existing items. - Merge has a 3rd argument 'override'; if set, it acts like Update, - otherwise it leaves existing items unchanged. - - PyDict_{Update,Merge} update/merge from a mapping object. - - PyDict_MergeFromSeq2 updates/merges from any iterable object - producing iterable objects of length 2. -*/ - -int -PyDict_MergeFromSeq2(PyObject *d, PyObject *seq2, int override) -{ - PyObject *it; /* iter(seq2) */ - Py_ssize_t i; /* index into seq2 of current element */ - PyObject *item; /* seq2[i] */ - PyObject *fast; /* item as a 2-tuple or 2-list */ - - assert(d != NULL); - assert(PyDict_Check(d)); - assert(seq2 != NULL); - - it = PyObject_GetIter(seq2); - if (it == NULL) - return -1; - - for (i = 0; ; ++i) { - PyObject *key, *value; - Py_ssize_t n; - - fast = NULL; - item = PyIter_Next(it); - if (item == NULL) { - if (PyErr_Occurred()) - goto Fail; - break; - } - - /* Convert item to sequence, and verify length 2. */ - fast = PySequence_Fast(item, ""); - if (fast == NULL) { - if (PyErr_ExceptionMatches(PyExc_TypeError)) - PyErr_Format(PyExc_TypeError, - "cannot convert dictionary update " - "sequence element #%zd to a sequence", - i); - goto Fail; - } - n = PySequence_Fast_GET_SIZE(fast); - if (n != 2) { - PyErr_Format(PyExc_ValueError, - "dictionary update sequence element #%zd " - "has length %zd; 2 is required", - i, n); - goto Fail; - } - - /* Update/merge with this (key, value) pair. */ - key = PySequence_Fast_GET_ITEM(fast, 0); - value = PySequence_Fast_GET_ITEM(fast, 1); - if (override || PyDict_GetItem(d, key) == NULL) { - int status = PyDict_SetItem(d, key, value); - if (status < 0) - goto Fail; - } - Py_DECREF(fast); - Py_DECREF(item); - } - - i = 0; - goto Return; -Fail: - Py_XDECREF(item); - Py_XDECREF(fast); - i = -1; -Return: - Py_DECREF(it); - return Py_SAFE_DOWNCAST(i, Py_ssize_t, int); -} - -int -PyDict_Update(PyObject *a, PyObject *b) -{ - return PyDict_Merge(a, b, 1); -} - -int -PyDict_Merge(PyObject *a, PyObject *b, int override) -{ - PyDictObject *mp, *other; - 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 - * things quite efficiently. For the latter, we only require that - * PyMapping_Keys() and PyObject_GetItem() be supported. - */ - if (a == NULL || !PyDict_Check(a) || b == NULL) { - PyErr_BadInternalCall(); - return -1; - } - mp = (PyDictObject*)a; - if (PyDict_Check(b)) { - other = (PyDictObject*)b; - if (other == mp || other->ma_used == 0) - /* a.update(a) or a.update({}); nothing to do */ - return 0; - if (mp->ma_used == 0) - /* Since the target dict is empty, PyDict_GetItem() - * always returns NULL. Setting override to 1 - * skips the unnecessary test. - */ - override = 1; - /* Do one big resize at the start, rather than - * incrementally resizing as we insert new items. Expect - * that there will be no (or few) overlapping keys. - */ - 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, 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)) { - if (insertdict(mp, entry->me_key, - entry->me_hash, - value) != 0) - return -1; - } - } - } - else { - /* Do it the generic, slower way */ - PyObject *keys = PyMapping_Keys(b); - PyObject *iter; - PyObject *key, *value; - int status; - - if (keys == NULL) - /* Docstring says this is equivalent to E.keys() so - * if E doesn't have a .keys() method we want - * AttributeError to percolate up. Might as well - * do the same for any other error. - */ - return -1; - - iter = PyObject_GetIter(keys); - Py_DECREF(keys); - if (iter == NULL) - return -1; - - for (key = PyIter_Next(iter); key; key = PyIter_Next(iter)) { - if (!override && PyDict_GetItem(a, key) != NULL) { - Py_DECREF(key); - continue; - } - value = PyObject_GetItem(b, key); - if (value == NULL) { - Py_DECREF(iter); - Py_DECREF(key); - return -1; - } - status = PyDict_SetItem(a, key, value); - Py_DECREF(key); - Py_DECREF(value); - if (status < 0) { - Py_DECREF(iter); - return -1; - } - } - Py_DECREF(iter); - if (PyErr_Occurred()) - /* Iterator completed, via error */ - return -1; - } - return 0; -} - -static PyObject * -dict_copy(PyDictObject *mp) -{ - return PyDict_Copy((PyObject*)mp); -} - -PyObject * -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; - } - if (_PyObject_GC_IS_TRACKED(mp)) - _PyObject_GC_TRACK(split_copy); - return (PyObject *)split_copy; - } - copy = PyDict_New(); - if (copy == NULL) - return NULL; - if (PyDict_Merge(copy, o, 1) == 0) - return copy; - Py_DECREF(copy); - return NULL; -} - -Py_ssize_t -PyDict_Size(PyObject *mp) -{ - if (mp == NULL || !PyDict_Check(mp)) { - PyErr_BadInternalCall(); - return -1; - } - return ((PyDictObject *)mp)->ma_used; -} - -PyObject * -PyDict_Keys(PyObject *mp) -{ - if (mp == NULL || !PyDict_Check(mp)) { - PyErr_BadInternalCall(); - return NULL; - } - return dict_keys((PyDictObject *)mp); -} - -PyObject * -PyDict_Values(PyObject *mp) -{ - if (mp == NULL || !PyDict_Check(mp)) { - PyErr_BadInternalCall(); - return NULL; - } - return dict_values((PyDictObject *)mp); -} - -PyObject * -PyDict_Items(PyObject *mp) -{ - if (mp == NULL || !PyDict_Check(mp)) { - PyErr_BadInternalCall(); - return NULL; - } - return dict_items((PyDictObject *)mp); -} - -/* Return 1 if dicts equal, 0 if not, -1 if error. - * Gets out as soon as any difference is detected. - * Uses only Py_EQ comparison. - */ -static int -dict_equal(PyDictObject *a, PyDictObject *b) -{ - Py_ssize_t i; - - 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 < 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 **vaddr; - PyObject *key = ep->me_key; - /* temporarily bump aval's refcount to ensure it stays - alive until we're done with it */ - Py_INCREF(aval); - /* ditto for key */ - Py_INCREF(key); - /* reuse the known hash value */ - if ((b->ma_keys->dk_lookup)(b, key, ep->me_hash, &vaddr) == NULL) - bval = NULL; - else - bval = *vaddr; - Py_DECREF(key); - if (bval == NULL) { - Py_DECREF(aval); - if (PyErr_Occurred()) - return -1; - return 0; - } - cmp = PyObject_RichCompareBool(aval, bval, Py_EQ); - Py_DECREF(aval); - if (cmp <= 0) /* error or not equal */ - return cmp; - } - } - return 1; -} - -static PyObject * -dict_richcompare(PyObject *v, PyObject *w, int op) -{ - int cmp; - PyObject *res; - - if (!PyDict_Check(v) || !PyDict_Check(w)) { - res = Py_NotImplemented; - } - else if (op == Py_EQ || op == Py_NE) { - cmp = dict_equal((PyDictObject *)v, (PyDictObject *)w); - if (cmp < 0) - return NULL; - res = (cmp == (op == Py_EQ)) ? Py_True : Py_False; - } - else - res = Py_NotImplemented; - Py_INCREF(res); - return res; -} - -/*[clinic input] - - at coexist -dict.__contains__ - - key: object - / - -True if D has a key k, else False. -[clinic start generated code]*/ - PyDoc_STRVAR(dict___contains____doc__, "__contains__($self, key, /)\n" "--\n" @@ -2274,1654 +39,4 @@ #define DICT___CONTAINS___METHODDEF \ {"__contains__", (PyCFunction)dict___contains__, METH_O|METH_COEXIST, dict___contains____doc__}, - -static PyObject * -dict___contains__(PyDictObject *self, PyObject *key) -/*[clinic end generated code: output=3cf3f8aaf2cc5cc3 input=b852b2a19b51ab24]*/ -{ - register PyDictObject *mp = self; - Py_hash_t hash; - 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_keys->dk_lookup)(mp, key, hash, &value_addr); - if (ep == NULL) - return NULL; - return PyBool_FromLong(*value_addr != NULL); -} - -static PyObject * -dict_get(PyDictObject *mp, PyObject *args) -{ - PyObject *key; - PyObject *failobj = Py_None; - PyObject *val = NULL; - Py_hash_t hash; - PyDictKeyEntry *ep; - PyObject **value_addr; - - if (!PyArg_UnpackTuple(args, "get", 1, 2, &key, &failobj)) - return NULL; - - if (!PyUnicode_CheckExact(key) || - (hash = ((PyASCIIObject *) key)->hash) == -1) { - hash = PyObject_Hash(key); - if (hash == -1) - return NULL; - } - ep = (mp->ma_keys->dk_lookup)(mp, key, hash, &value_addr); - if (ep == NULL) - return NULL; - val = *value_addr; - if (val == NULL) - val = failobj; - Py_INCREF(val); - return val; -} - -PyObject * -PyDict_SetDefault(PyObject *d, PyObject *key, PyObject *defaultobj) -{ - PyDictObject *mp = (PyDictObject *)d; - PyObject *val = NULL; - Py_hash_t hash; - PyDictKeyEntry *ep; - PyObject **value_addr; - - if (!PyDict_Check(d)) { - PyErr_BadInternalCall(); - return NULL; - } - if (!PyUnicode_CheckExact(key) || - (hash = ((PyASCIIObject *) key)->hash) == -1) { - hash = PyObject_Hash(key); - if (hash == -1) - return NULL; - } - ep = (mp->ma_keys->dk_lookup)(mp, key, hash, &value_addr); - if (ep == NULL) - return NULL; - val = *value_addr; - if (val == NULL) { - 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); - } - Py_INCREF(defaultobj); - Py_INCREF(key); - MAINTAIN_TRACKING(mp, key, defaultobj); - ep->me_key = key; - ep->me_hash = hash; - *value_addr = defaultobj; - val = defaultobj; - mp->ma_keys->dk_usable--; - mp->ma_used++; - } - return val; -} - -static PyObject * -dict_setdefault(PyDictObject *mp, PyObject *args) -{ - PyObject *key, *val; - PyObject *defaultobj = Py_None; - - if (!PyArg_UnpackTuple(args, "setdefault", 1, 2, &key, &defaultobj)) - return NULL; - - val = PyDict_SetDefault((PyObject *)mp, key, defaultobj); - Py_XINCREF(val); - return val; -} - -static PyObject * -dict_clear(PyDictObject *mp) -{ - PyDict_Clear((PyObject *)mp); - Py_RETURN_NONE; -} - -static PyObject * -dict_pop(PyDictObject *mp, PyObject *args) -{ - Py_hash_t hash; - 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; - if (mp->ma_used == 0) { - if (deflt) { - Py_INCREF(deflt); - return deflt; - } - _PyErr_SetKeyError(key); - return NULL; - } - if (!PyUnicode_CheckExact(key) || - (hash = ((PyASCIIObject *) key)->hash) == -1) { - hash = PyObject_Hash(key); - if (hash == -1) - return NULL; - } - ep = (mp->ma_keys->dk_lookup)(mp, key, hash, &value_addr); - if (ep == NULL) - return NULL; - old_value = *value_addr; - if (old_value == NULL) { - if (deflt) { - Py_INCREF(deflt); - return deflt; - } - _PyErr_SetKeyError(key); - return NULL; - } - *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); - } - return old_value; -} - -static PyObject * -dict_popitem(PyDictObject *mp) -{ - Py_hash_t i = 0; - 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 - * happened, the result would be an infinite loop (searching for an - * entry that no longer exists). Note that the usual popitem() - * idiom is "while d: k, v = d.popitem()". so needing to throw the - * tuple away if the dict *is* empty isn't a significant - * inefficiency -- possible, but unlikely in practice. - */ - res = PyTuple_New(2); - if (res == NULL) - return NULL; - if (mp->ma_used == 0) { - Py_DECREF(res); - PyErr_SetString(PyExc_KeyError, - "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_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 > mask || i < 1) - i = 1; /* skip slot 0 */ - while ((ep = &mp->ma_keys->dk_entries[i])->me_value == NULL) { - i++; - if (i > mask) - i = 1; - } - } - PyTuple_SET_ITEM(res, 0, ep->me_key); - PyTuple_SET_ITEM(res, 1, ep->me_value); - Py_INCREF(dummy); - ep->me_key = dummy; - ep->me_value = NULL; - mp->ma_used--; - 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, 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; -} - -static int -dict_tp_clear(PyObject *op) -{ - PyDict_Clear(op); - return 0; -} - -static PyObject *dictiter_new(PyDictObject *, PyTypeObject *); - -static PyObject * -dict_sizeof(PyDictObject *mp) -{ - Py_ssize_t size, res; - - size = DK_SIZE(mp->ma_keys); - res = sizeof(PyDictObject); - if (mp->ma_values) - res += size * sizeof(PyObject*); - /* 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(getitem__doc__, "x.__getitem__(y) <==> x[y]"); - -PyDoc_STRVAR(sizeof__doc__, -"D.__sizeof__() -> size of D in memory, in bytes"); - -PyDoc_STRVAR(get__doc__, -"D.get(k[,d]) -> D[k] if k in D, else d. d defaults to None."); - -PyDoc_STRVAR(setdefault_doc__, -"D.setdefault(k[,d]) -> D.get(k,d), also set D[k]=d if k not in D"); - -PyDoc_STRVAR(pop__doc__, -"D.pop(k[,d]) -> v, remove specified key and return the corresponding value.\n\ -If key is not found, d is returned if given, otherwise KeyError is raised"); - -PyDoc_STRVAR(popitem__doc__, -"D.popitem() -> (k, v), remove and return some (key, value) pair as a\n\ -2-tuple; but raise KeyError if D is empty."); - -PyDoc_STRVAR(update__doc__, -"D.update([E, ]**F) -> None. Update D from dict/iterable E and F.\n\ -If E is present and has a .keys() method, then does: for k in E: D[k] = E[k]\n\ -If E is present and lacks a .keys() method, then does: for k, v in E: D[k] = v\n\ -In either case, this is followed by: for k in F: D[k] = F[k]"); - -PyDoc_STRVAR(clear__doc__, -"D.clear() -> None. Remove all items from D."); - -PyDoc_STRVAR(copy__doc__, -"D.copy() -> a shallow copy of D"); - -/* Forward */ -static PyObject *dictkeys_new(PyObject *); -static PyObject *dictitems_new(PyObject *); -static PyObject *dictvalues_new(PyObject *); - -PyDoc_STRVAR(keys__doc__, - "D.keys() -> a set-like object providing a view on D's keys"); -PyDoc_STRVAR(items__doc__, - "D.items() -> a set-like object providing a view on D's items"); -PyDoc_STRVAR(values__doc__, - "D.values() -> an object providing a view on D's values"); - -static PyMethodDef mapp_methods[] = { - DICT___CONTAINS___METHODDEF - {"__getitem__", (PyCFunction)dict_subscript, METH_O | METH_COEXIST, - getitem__doc__}, - {"__sizeof__", (PyCFunction)dict_sizeof, METH_NOARGS, - sizeof__doc__}, - {"get", (PyCFunction)dict_get, METH_VARARGS, - get__doc__}, - {"setdefault", (PyCFunction)dict_setdefault, METH_VARARGS, - setdefault_doc__}, - {"pop", (PyCFunction)dict_pop, METH_VARARGS, - pop__doc__}, - {"popitem", (PyCFunction)dict_popitem, METH_NOARGS, - popitem__doc__}, - {"keys", (PyCFunction)dictkeys_new, METH_NOARGS, - keys__doc__}, - {"items", (PyCFunction)dictitems_new, METH_NOARGS, - items__doc__}, - {"values", (PyCFunction)dictvalues_new, METH_NOARGS, - values__doc__}, - {"update", (PyCFunction)dict_update, METH_VARARGS | METH_KEYWORDS, - update__doc__}, - DICT_FROMKEYS_METHODDEF - {"clear", (PyCFunction)dict_clear, METH_NOARGS, - clear__doc__}, - {"copy", (PyCFunction)dict_copy, METH_NOARGS, - copy__doc__}, - {NULL, NULL} /* sentinel */ -}; - -/* Return 1 if `key` is in dict `op`, 0 if not, and -1 on error. */ -int -PyDict_Contains(PyObject *op, PyObject *key) -{ - Py_hash_t hash; - PyDictObject *mp = (PyDictObject *)op; - PyDictKeyEntry *ep; - PyObject **value_addr; - - if (!PyUnicode_CheckExact(key) || - (hash = ((PyASCIIObject *) key)->hash) == -1) { - hash = PyObject_Hash(key); - if (hash == -1) - return -1; - } - 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 */ -int -_PyDict_Contains(PyObject *op, PyObject *key, Py_hash_t hash) -{ - PyDictObject *mp = (PyDictObject *)op; - 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" */ -static PySequenceMethods dict_as_sequence = { - 0, /* sq_length */ - 0, /* sq_concat */ - 0, /* sq_repeat */ - 0, /* sq_item */ - 0, /* sq_slice */ - 0, /* sq_ass_item */ - 0, /* sq_ass_slice */ - PyDict_Contains, /* sq_contains */ - 0, /* sq_inplace_concat */ - 0, /* sq_inplace_repeat */ -}; - -static PyObject * -dict_new(PyTypeObject *type, PyObject *args, PyObject *kwds) -{ - PyObject *self; - PyDictObject *d; - - assert(type != NULL && type->tp_alloc != NULL); - self = type->tp_alloc(type, 0); - if (self == NULL) - return NULL; - d = (PyDictObject *)self; - - /* The object has been implicitly tracked by tp_alloc */ - if (type == &PyDict_Type) - _PyObject_GC_UNTRACK(d); - - d->ma_used = 0; - d->ma_keys = new_keys_object(PyDict_MINSIZE_COMBINED); - if (d->ma_keys == NULL) { - Py_DECREF(self); - return NULL; - } - return self; -} - -static int -dict_init(PyObject *self, PyObject *args, PyObject *kwds) -{ - return dict_update_common(self, args, kwds, "dict"); -} - -static PyObject * -dict_iter(PyDictObject *dict) -{ - return dictiter_new(dict, &PyDictIterKey_Type); -} - -PyDoc_STRVAR(dictionary_doc, -"dict() -> new empty dictionary\n" -"dict(mapping) -> new dictionary initialized from a mapping object's\n" -" (key, value) pairs\n" -"dict(iterable) -> new dictionary initialized as if via:\n" -" d = {}\n" -" for k, v in iterable:\n" -" d[k] = v\n" -"dict(**kwargs) -> new dictionary initialized with the name=value pairs\n" -" in the keyword argument list. For example: dict(one=1, two=2)"); - -PyTypeObject PyDict_Type = { - PyVarObject_HEAD_INIT(&PyType_Type, 0) - "dict", - sizeof(PyDictObject), - 0, - (destructor)dict_dealloc, /* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_reserved */ - (reprfunc)dict_repr, /* tp_repr */ - 0, /* tp_as_number */ - &dict_as_sequence, /* tp_as_sequence */ - &dict_as_mapping, /* tp_as_mapping */ - PyObject_HashNotImplemented, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - PyObject_GenericGetAttr, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | - Py_TPFLAGS_BASETYPE | Py_TPFLAGS_DICT_SUBCLASS, /* tp_flags */ - dictionary_doc, /* tp_doc */ - dict_traverse, /* tp_traverse */ - dict_tp_clear, /* tp_clear */ - dict_richcompare, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - (getiterfunc)dict_iter, /* tp_iter */ - 0, /* tp_iternext */ - mapp_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 */ - dict_init, /* tp_init */ - PyType_GenericAlloc, /* tp_alloc */ - dict_new, /* tp_new */ - PyObject_GC_Del, /* tp_free */ -}; - -PyObject * -_PyDict_GetItemId(PyObject *dp, struct _Py_Identifier *key) -{ - PyObject *kv; - kv = _PyUnicode_FromId(key); /* borrowed */ - if (kv == NULL) { - PyErr_Clear(); - return NULL; - } - return PyDict_GetItem(dp, kv); -} - -/* For backward compatibility with old dictionary interface */ - -PyObject * -PyDict_GetItemString(PyObject *v, const char *key) -{ - PyObject *kv, *rv; - kv = PyUnicode_FromString(key); - if (kv == NULL) { - PyErr_Clear(); - return NULL; - } - rv = PyDict_GetItem(v, kv); - Py_DECREF(kv); - return rv; -} - -int -_PyDict_SetItemId(PyObject *v, struct _Py_Identifier *key, PyObject *item) -{ - PyObject *kv; - kv = _PyUnicode_FromId(key); /* borrowed */ - if (kv == NULL) - return -1; - return PyDict_SetItem(v, kv, item); -} - -int -PyDict_SetItemString(PyObject *v, const char *key, PyObject *item) -{ - PyObject *kv; - int err; - kv = PyUnicode_FromString(key); - if (kv == NULL) - return -1; - PyUnicode_InternInPlace(&kv); /* XXX Should we really? */ - err = PyDict_SetItem(v, kv, item); - Py_DECREF(kv); - return err; -} - -int -_PyDict_DelItemId(PyObject *v, _Py_Identifier *key) -{ - PyObject *kv = _PyUnicode_FromId(key); /* borrowed */ - if (kv == NULL) - return -1; - return PyDict_DelItem(v, kv); -} - -int -PyDict_DelItemString(PyObject *v, const char *key) -{ - PyObject *kv; - int err; - kv = PyUnicode_FromString(key); - if (kv == NULL) - return -1; - err = PyDict_DelItem(v, kv); - Py_DECREF(kv); - return err; -} - -/* Dictionary iterator types */ - -typedef struct { - PyObject_HEAD - PyDictObject *di_dict; /* Set to NULL when iterator is exhausted */ - Py_ssize_t di_used; - Py_ssize_t di_pos; - PyObject* di_result; /* reusable result tuple for iteritems */ - Py_ssize_t len; -} dictiterobject; - -static PyObject * -dictiter_new(PyDictObject *dict, PyTypeObject *itertype) -{ - dictiterobject *di; - di = PyObject_GC_New(dictiterobject, itertype); - if (di == NULL) - return NULL; - Py_INCREF(dict); - di->di_dict = dict; - di->di_used = dict->ma_used; - di->di_pos = 0; - di->len = dict->ma_used; - if (itertype == &PyDictIterItem_Type) { - di->di_result = PyTuple_Pack(2, Py_None, Py_None); - if (di->di_result == NULL) { - Py_DECREF(di); - return NULL; - } - } - else - di->di_result = NULL; - _PyObject_GC_TRACK(di); - return (PyObject *)di; -} - -static void -dictiter_dealloc(dictiterobject *di) -{ - Py_XDECREF(di->di_dict); - Py_XDECREF(di->di_result); - PyObject_GC_Del(di); -} - -static int -dictiter_traverse(dictiterobject *di, visitproc visit, void *arg) -{ - Py_VISIT(di->di_dict); - Py_VISIT(di->di_result); - return 0; -} - -static PyObject * -dictiter_len(dictiterobject *di) -{ - Py_ssize_t len = 0; - if (di->di_dict != NULL && di->di_used == di->di_dict->ma_used) - len = di->len; - return PyLong_FromSize_t(len); -} - -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 */ -}; - -static PyObject *dictiter_iternextkey(dictiterobject *di) -{ - PyObject *key; - Py_ssize_t i, mask, offset; - PyDictKeysObject *k; - PyDictObject *d = di->di_dict; - PyObject **value_ptr; - - if (d == NULL) - return NULL; - assert (PyDict_Check(d)); - - if (di->di_used != d->ma_used) { - PyErr_SetString(PyExc_RuntimeError, - "dictionary changed size during iteration"); - di->di_used = -1; /* Make this state sticky */ - return NULL; - } - - i = di->di_pos; - if (i < 0) - goto fail; - 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 = k->dk_entries[i].me_key; - Py_INCREF(key); - return key; - -fail: - Py_DECREF(d); - di->di_dict = NULL; - return NULL; -} - -PyTypeObject PyDictIterKey_Type = { - PyVarObject_HEAD_INIT(&PyType_Type, 0) - "dict_keyiterator", /* tp_name */ - sizeof(dictiterobject), /* tp_basicsize */ - 0, /* tp_itemsize */ - /* methods */ - (destructor)dictiter_dealloc, /* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_reserved */ - 0, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - PyObject_GenericGetAttr, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */ - 0, /* tp_doc */ - (traverseproc)dictiter_traverse, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - PyObject_SelfIter, /* tp_iter */ - (iternextfunc)dictiter_iternextkey, /* tp_iternext */ - dictiter_methods, /* tp_methods */ - 0, -}; - -static PyObject *dictiter_iternextvalue(dictiterobject *di) -{ - PyObject *value; - Py_ssize_t i, mask, offset; - PyDictObject *d = di->di_dict; - PyObject **value_ptr; - - if (d == NULL) - return NULL; - assert (PyDict_Check(d)); - - if (di->di_used != d->ma_used) { - PyErr_SetString(PyExc_RuntimeError, - "dictionary changed size during iteration"); - di->di_used = -1; /* Make this state sticky */ - return NULL; - } - - i = di->di_pos; - mask = DK_SIZE(d->ma_keys)-1; - if (i < 0 || i > mask) - goto fail; - 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; - -fail: - Py_DECREF(d); - di->di_dict = NULL; - return NULL; -} - -PyTypeObject PyDictIterValue_Type = { - PyVarObject_HEAD_INIT(&PyType_Type, 0) - "dict_valueiterator", /* tp_name */ - sizeof(dictiterobject), /* tp_basicsize */ - 0, /* tp_itemsize */ - /* methods */ - (destructor)dictiter_dealloc, /* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_reserved */ - 0, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - PyObject_GenericGetAttr, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */ - 0, /* tp_doc */ - (traverseproc)dictiter_traverse, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - PyObject_SelfIter, /* tp_iter */ - (iternextfunc)dictiter_iternextvalue, /* tp_iternext */ - dictiter_methods, /* tp_methods */ - 0, -}; - -static PyObject *dictiter_iternextitem(dictiterobject *di) -{ - PyObject *key, *value, *result = di->di_result; - Py_ssize_t i, mask, offset; - PyDictObject *d = di->di_dict; - PyObject **value_ptr; - - if (d == NULL) - return NULL; - assert (PyDict_Check(d)); - - if (di->di_used != d->ma_used) { - PyErr_SetString(PyExc_RuntimeError, - "dictionary changed size during iteration"); - di->di_used = -1; /* Make this state sticky */ - return NULL; - } - - i = di->di_pos; - if (i < 0) - goto fail; - 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; - - if (result->ob_refcnt == 1) { - Py_INCREF(result); - Py_DECREF(PyTuple_GET_ITEM(result, 0)); - Py_DECREF(PyTuple_GET_ITEM(result, 1)); - } else { - result = PyTuple_New(2); - if (result == NULL) - return NULL; - } - di->len--; - key = d->ma_keys->dk_entries[i].me_key; - value = *value_ptr; - Py_INCREF(key); - Py_INCREF(value); - PyTuple_SET_ITEM(result, 0, key); - PyTuple_SET_ITEM(result, 1, value); - return result; - -fail: - Py_DECREF(d); - di->di_dict = NULL; - return NULL; -} - -PyTypeObject PyDictIterItem_Type = { - PyVarObject_HEAD_INIT(&PyType_Type, 0) - "dict_itemiterator", /* tp_name */ - sizeof(dictiterobject), /* tp_basicsize */ - 0, /* tp_itemsize */ - /* methods */ - (destructor)dictiter_dealloc, /* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_reserved */ - 0, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - PyObject_GenericGetAttr, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */ - 0, /* tp_doc */ - (traverseproc)dictiter_traverse, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - PyObject_SelfIter, /* tp_iter */ - (iternextfunc)dictiter_iternextitem, /* tp_iternext */ - dictiter_methods, /* tp_methods */ - 0, -}; - - -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(). */ -/***********************************************/ - -/* The instance lay-out is the same for all three; but the type differs. */ - -typedef struct { - PyObject_HEAD - PyDictObject *dv_dict; -} dictviewobject; - - -static void -dictview_dealloc(dictviewobject *dv) -{ - Py_XDECREF(dv->dv_dict); - PyObject_GC_Del(dv); -} - -static int -dictview_traverse(dictviewobject *dv, visitproc visit, void *arg) -{ - Py_VISIT(dv->dv_dict); - return 0; -} - -static Py_ssize_t -dictview_len(dictviewobject *dv) -{ - Py_ssize_t len = 0; - if (dv->dv_dict != NULL) - len = dv->dv_dict->ma_used; - return len; -} - -static PyObject * -dictview_new(PyObject *dict, PyTypeObject *type) -{ - dictviewobject *dv; - if (dict == NULL) { - PyErr_BadInternalCall(); - return NULL; - } - if (!PyDict_Check(dict)) { - /* XXX Get rid of this restriction later */ - PyErr_Format(PyExc_TypeError, - "%s() requires a dict argument, not '%s'", - type->tp_name, dict->ob_type->tp_name); - return NULL; - } - dv = PyObject_GC_New(dictviewobject, type); - if (dv == NULL) - return NULL; - Py_INCREF(dict); - dv->dv_dict = (PyDictObject *)dict; - _PyObject_GC_TRACK(dv); - return (PyObject *)dv; -} - -/* TODO(guido): The views objects are not complete: - - * support more set operations - * support arbitrary mappings? - - either these should be static or exported in dictobject.h - - if public then they should probably be in builtins -*/ - -/* Return 1 if self is a subset of other, iterating over self; - 0 if not; -1 if an error occurred. */ -static int -all_contained_in(PyObject *self, PyObject *other) -{ - PyObject *iter = PyObject_GetIter(self); - int ok = 1; - - if (iter == NULL) - return -1; - for (;;) { - PyObject *next = PyIter_Next(iter); - if (next == NULL) { - if (PyErr_Occurred()) - ok = -1; - break; - } - ok = PySequence_Contains(other, next); - Py_DECREF(next); - if (ok <= 0) - break; - } - Py_DECREF(iter); - return ok; -} - -static PyObject * -dictview_richcompare(PyObject *self, PyObject *other, int op) -{ - Py_ssize_t len_self, len_other; - int ok; - PyObject *result; - - assert(self != NULL); - assert(PyDictViewSet_Check(self)); - assert(other != NULL); - - if (!PyAnySet_Check(other) && !PyDictViewSet_Check(other)) - Py_RETURN_NOTIMPLEMENTED; - - len_self = PyObject_Size(self); - if (len_self < 0) - return NULL; - len_other = PyObject_Size(other); - if (len_other < 0) - return NULL; - - ok = 0; - switch(op) { - - case Py_NE: - case Py_EQ: - if (len_self == len_other) - ok = all_contained_in(self, other); - if (op == Py_NE && ok >= 0) - ok = !ok; - break; - - case Py_LT: - if (len_self < len_other) - ok = all_contained_in(self, other); - break; - - case Py_LE: - if (len_self <= len_other) - ok = all_contained_in(self, other); - break; - - case Py_GT: - if (len_self > len_other) - ok = all_contained_in(other, self); - break; - - case Py_GE: - if (len_self >= len_other) - ok = all_contained_in(other, self); - break; - - } - if (ok < 0) - return NULL; - result = ok ? Py_True : Py_False; - Py_INCREF(result); - return result; -} - -static PyObject * -dictview_repr(dictviewobject *dv) -{ - PyObject *seq; - PyObject *result; - - seq = PySequence_List((PyObject *)dv); - if (seq == NULL) - return NULL; - - result = PyUnicode_FromFormat("%s(%R)", Py_TYPE(dv)->tp_name, seq); - Py_DECREF(seq); - return result; -} - -/*** dict_keys ***/ - -static PyObject * -dictkeys_iter(dictviewobject *dv) -{ - if (dv->dv_dict == NULL) { - Py_RETURN_NONE; - } - return dictiter_new(dv->dv_dict, &PyDictIterKey_Type); -} - -static int -dictkeys_contains(dictviewobject *dv, PyObject *obj) -{ - if (dv->dv_dict == NULL) - return 0; - return PyDict_Contains((PyObject *)dv->dv_dict, obj); -} - -static PySequenceMethods dictkeys_as_sequence = { - (lenfunc)dictview_len, /* sq_length */ - 0, /* sq_concat */ - 0, /* sq_repeat */ - 0, /* sq_item */ - 0, /* sq_slice */ - 0, /* sq_ass_item */ - 0, /* sq_ass_slice */ - (objobjproc)dictkeys_contains, /* sq_contains */ -}; - -static PyObject* -dictviews_sub(PyObject* self, PyObject *other) -{ - PyObject *result = PySet_New(self); - PyObject *tmp; - _Py_IDENTIFIER(difference_update); - - if (result == NULL) - return NULL; - - tmp = _PyObject_CallMethodId(result, &PyId_difference_update, "O", other); - if (tmp == NULL) { - Py_DECREF(result); - return NULL; - } - - Py_DECREF(tmp); - return result; -} - -static PyObject* -dictviews_and(PyObject* self, PyObject *other) -{ - PyObject *result = PySet_New(self); - PyObject *tmp; - _Py_IDENTIFIER(intersection_update); - - if (result == NULL) - return NULL; - - tmp = _PyObject_CallMethodId(result, &PyId_intersection_update, "O", other); - if (tmp == NULL) { - Py_DECREF(result); - return NULL; - } - - Py_DECREF(tmp); - return result; -} - -static PyObject* -dictviews_or(PyObject* self, PyObject *other) -{ - PyObject *result = PySet_New(self); - PyObject *tmp; - _Py_IDENTIFIER(update); - - if (result == NULL) - return NULL; - - tmp = _PyObject_CallMethodId(result, &PyId_update, "O", other); - if (tmp == NULL) { - Py_DECREF(result); - return NULL; - } - - Py_DECREF(tmp); - return result; -} - -static PyObject* -dictviews_xor(PyObject* self, PyObject *other) -{ - PyObject *result = PySet_New(self); - PyObject *tmp; - _Py_IDENTIFIER(symmetric_difference_update); - - if (result == NULL) - return NULL; - - tmp = _PyObject_CallMethodId(result, &PyId_symmetric_difference_update, "O", - other); - if (tmp == NULL) { - Py_DECREF(result); - return NULL; - } - - Py_DECREF(tmp); - return result; -} - -static PyNumberMethods dictviews_as_number = { - 0, /*nb_add*/ - (binaryfunc)dictviews_sub, /*nb_subtract*/ - 0, /*nb_multiply*/ - 0, /*nb_remainder*/ - 0, /*nb_divmod*/ - 0, /*nb_power*/ - 0, /*nb_negative*/ - 0, /*nb_positive*/ - 0, /*nb_absolute*/ - 0, /*nb_bool*/ - 0, /*nb_invert*/ - 0, /*nb_lshift*/ - 0, /*nb_rshift*/ - (binaryfunc)dictviews_and, /*nb_and*/ - (binaryfunc)dictviews_xor, /*nb_xor*/ - (binaryfunc)dictviews_or, /*nb_or*/ -}; - -static PyObject* -dictviews_isdisjoint(PyObject *self, PyObject *other) -{ - PyObject *it; - PyObject *item = NULL; - - if (self == other) { - if (dictview_len((dictviewobject *)self) == 0) - Py_RETURN_TRUE; - else - Py_RETURN_FALSE; - } - - /* Iterate over the shorter object (only if other is a set, - * because PySequence_Contains may be expensive otherwise): */ - if (PyAnySet_Check(other) || PyDictViewSet_Check(other)) { - Py_ssize_t len_self = dictview_len((dictviewobject *)self); - Py_ssize_t len_other = PyObject_Size(other); - if (len_other == -1) - return NULL; - - if ((len_other > len_self)) { - PyObject *tmp = other; - other = self; - self = tmp; - } - } - - it = PyObject_GetIter(other); - if (it == NULL) - return NULL; - - while ((item = PyIter_Next(it)) != NULL) { - int contains = PySequence_Contains(self, item); - Py_DECREF(item); - if (contains == -1) { - Py_DECREF(it); - return NULL; - } - - if (contains) { - Py_DECREF(it); - Py_RETURN_FALSE; - } - } - Py_DECREF(it); - if (PyErr_Occurred()) - return NULL; /* PyIter_Next raised an exception. */ - Py_RETURN_TRUE; -} - -PyDoc_STRVAR(isdisjoint_doc, -"Return True if the view and the given iterable have a null intersection."); - -static PyMethodDef dictkeys_methods[] = { - {"isdisjoint", (PyCFunction)dictviews_isdisjoint, METH_O, - isdisjoint_doc}, - {NULL, NULL} /* sentinel */ -}; - -PyTypeObject PyDictKeys_Type = { - PyVarObject_HEAD_INIT(&PyType_Type, 0) - "dict_keys", /* tp_name */ - sizeof(dictviewobject), /* tp_basicsize */ - 0, /* tp_itemsize */ - /* methods */ - (destructor)dictview_dealloc, /* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_reserved */ - (reprfunc)dictview_repr, /* tp_repr */ - &dictviews_as_number, /* tp_as_number */ - &dictkeys_as_sequence, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - PyObject_GenericGetAttr, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */ - 0, /* tp_doc */ - (traverseproc)dictview_traverse, /* tp_traverse */ - 0, /* tp_clear */ - dictview_richcompare, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - (getiterfunc)dictkeys_iter, /* tp_iter */ - 0, /* tp_iternext */ - dictkeys_methods, /* tp_methods */ - 0, -}; - -static PyObject * -dictkeys_new(PyObject *dict) -{ - return dictview_new(dict, &PyDictKeys_Type); -} - -/*** dict_items ***/ - -static PyObject * -dictitems_iter(dictviewobject *dv) -{ - if (dv->dv_dict == NULL) { - Py_RETURN_NONE; - } - return dictiter_new(dv->dv_dict, &PyDictIterItem_Type); -} - -static int -dictitems_contains(dictviewobject *dv, PyObject *obj) -{ - PyObject *key, *value, *found; - if (dv->dv_dict == NULL) - return 0; - if (!PyTuple_Check(obj) || PyTuple_GET_SIZE(obj) != 2) - return 0; - key = PyTuple_GET_ITEM(obj, 0); - value = PyTuple_GET_ITEM(obj, 1); - found = PyDict_GetItem((PyObject *)dv->dv_dict, key); - if (found == NULL) { - if (PyErr_Occurred()) - return -1; - return 0; - } - return PyObject_RichCompareBool(value, found, Py_EQ); -} - -static PySequenceMethods dictitems_as_sequence = { - (lenfunc)dictview_len, /* sq_length */ - 0, /* sq_concat */ - 0, /* sq_repeat */ - 0, /* sq_item */ - 0, /* sq_slice */ - 0, /* sq_ass_item */ - 0, /* sq_ass_slice */ - (objobjproc)dictitems_contains, /* sq_contains */ -}; - -static PyMethodDef dictitems_methods[] = { - {"isdisjoint", (PyCFunction)dictviews_isdisjoint, METH_O, - isdisjoint_doc}, - {NULL, NULL} /* sentinel */ -}; - -PyTypeObject PyDictItems_Type = { - PyVarObject_HEAD_INIT(&PyType_Type, 0) - "dict_items", /* tp_name */ - sizeof(dictviewobject), /* tp_basicsize */ - 0, /* tp_itemsize */ - /* methods */ - (destructor)dictview_dealloc, /* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_reserved */ - (reprfunc)dictview_repr, /* tp_repr */ - &dictviews_as_number, /* tp_as_number */ - &dictitems_as_sequence, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - PyObject_GenericGetAttr, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */ - 0, /* tp_doc */ - (traverseproc)dictview_traverse, /* tp_traverse */ - 0, /* tp_clear */ - dictview_richcompare, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - (getiterfunc)dictitems_iter, /* tp_iter */ - 0, /* tp_iternext */ - dictitems_methods, /* tp_methods */ - 0, -}; - -static PyObject * -dictitems_new(PyObject *dict) -{ - return dictview_new(dict, &PyDictItems_Type); -} - -/*** dict_values ***/ - -static PyObject * -dictvalues_iter(dictviewobject *dv) -{ - if (dv->dv_dict == NULL) { - Py_RETURN_NONE; - } - return dictiter_new(dv->dv_dict, &PyDictIterValue_Type); -} - -static PySequenceMethods dictvalues_as_sequence = { - (lenfunc)dictview_len, /* sq_length */ - 0, /* sq_concat */ - 0, /* sq_repeat */ - 0, /* sq_item */ - 0, /* sq_slice */ - 0, /* sq_ass_item */ - 0, /* sq_ass_slice */ - (objobjproc)0, /* sq_contains */ -}; - -static PyMethodDef dictvalues_methods[] = { - {NULL, NULL} /* sentinel */ -}; - -PyTypeObject PyDictValues_Type = { - PyVarObject_HEAD_INIT(&PyType_Type, 0) - "dict_values", /* tp_name */ - sizeof(dictviewobject), /* tp_basicsize */ - 0, /* tp_itemsize */ - /* methods */ - (destructor)dictview_dealloc, /* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_reserved */ - (reprfunc)dictview_repr, /* tp_repr */ - 0, /* tp_as_number */ - &dictvalues_as_sequence, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - PyObject_GenericGetAttr, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */ - 0, /* tp_doc */ - (traverseproc)dictview_traverse, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - (getiterfunc)dictvalues_iter, /* tp_iter */ - 0, /* tp_iternext */ - dictvalues_methods, /* tp_methods */ - 0, -}; - -static PyObject * -dictvalues_new(PyObject *dict) -{ - 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); - } else { - CACHED_KEYS(tp) = NULL; - } - DK_DECREF(cached); - if (CACHED_KEYS(tp) == NULL && PyErr_Occurred()) - return -1; - } - } - } 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 -}; - +/*[clinic end generated code: output=fe74d676332fdba6 input=a9049054013a1b77]*/ diff --git a/Objects/unicodeobject.c b/Objects/clinic/unicodeobject.c.h copy from Objects/unicodeobject.c copy to Objects/clinic/unicodeobject.c.h --- a/Objects/unicodeobject.c +++ b/Objects/clinic/unicodeobject.c.h @@ -1,12958 +1,5 @@ -/* - -Unicode implementation based on original code by Fredrik Lundh, -modified by Marc-Andre Lemburg . - -Major speed upgrades to the method implementations at the Reykjavik -NeedForSpeed sprint, by Fredrik Lundh and Andrew Dalke. - -Copyright (c) Corporation for National Research Initiatives. - --------------------------------------------------------------------- -The original string type implementation is: - - Copyright (c) 1999 by Secret Labs AB - Copyright (c) 1999 by Fredrik Lundh - -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 Secret Labs -AB or the author not be used in advertising or publicity pertaining to -distribution of the software without specific, written prior -permission. - -SECRET LABS AB AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO -THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS. IN NO EVENT SHALL SECRET LABS AB OR THE AUTHOR 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. --------------------------------------------------------------------- - -*/ - -#define PY_SSIZE_T_CLEAN -#include "Python.h" -#include "ucnhash.h" -#include "bytes_methods.h" - -#ifdef MS_WINDOWS -#include -#endif - /*[clinic input] -class str "PyUnicodeObject *" "&PyUnicode_Type" -[clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=604e916854800fa8]*/ - -/* --- Globals ------------------------------------------------------------ - -NOTE: In the interpreter's initialization phase, some globals are currently - initialized dynamically as needed. In the process Unicode objects may - be created before the Unicode type is ready. - -*/ - - -#ifdef __cplusplus -extern "C" { -#endif - -/* Maximum code point of Unicode 6.0: 0x10ffff (1,114,111) */ -#define MAX_UNICODE 0x10ffff - -#ifdef Py_DEBUG -# define _PyUnicode_CHECK(op) _PyUnicode_CheckConsistency(op, 0) -#else -# define _PyUnicode_CHECK(op) PyUnicode_Check(op) -#endif - -#define _PyUnicode_UTF8(op) \ - (((PyCompactUnicodeObject*)(op))->utf8) -#define PyUnicode_UTF8(op) \ - (assert(_PyUnicode_CHECK(op)), \ - assert(PyUnicode_IS_READY(op)), \ - PyUnicode_IS_COMPACT_ASCII(op) ? \ - ((char*)((PyASCIIObject*)(op) + 1)) : \ - _PyUnicode_UTF8(op)) -#define _PyUnicode_UTF8_LENGTH(op) \ - (((PyCompactUnicodeObject*)(op))->utf8_length) -#define PyUnicode_UTF8_LENGTH(op) \ - (assert(_PyUnicode_CHECK(op)), \ - assert(PyUnicode_IS_READY(op)), \ - PyUnicode_IS_COMPACT_ASCII(op) ? \ - ((PyASCIIObject*)(op))->length : \ - _PyUnicode_UTF8_LENGTH(op)) -#define _PyUnicode_WSTR(op) \ - (((PyASCIIObject*)(op))->wstr) -#define _PyUnicode_WSTR_LENGTH(op) \ - (((PyCompactUnicodeObject*)(op))->wstr_length) -#define _PyUnicode_LENGTH(op) \ - (((PyASCIIObject *)(op))->length) -#define _PyUnicode_STATE(op) \ - (((PyASCIIObject *)(op))->state) -#define _PyUnicode_HASH(op) \ - (((PyASCIIObject *)(op))->hash) -#define _PyUnicode_KIND(op) \ - (assert(_PyUnicode_CHECK(op)), \ - ((PyASCIIObject *)(op))->state.kind) -#define _PyUnicode_GET_LENGTH(op) \ - (assert(_PyUnicode_CHECK(op)), \ - ((PyASCIIObject *)(op))->length) -#define _PyUnicode_DATA_ANY(op) \ - (((PyUnicodeObject*)(op))->data.any) - -#undef PyUnicode_READY -#define PyUnicode_READY(op) \ - (assert(_PyUnicode_CHECK(op)), \ - (PyUnicode_IS_READY(op) ? \ - 0 : \ - _PyUnicode_Ready(op))) - -#define _PyUnicode_SHARE_UTF8(op) \ - (assert(_PyUnicode_CHECK(op)), \ - assert(!PyUnicode_IS_COMPACT_ASCII(op)), \ - (_PyUnicode_UTF8(op) == PyUnicode_DATA(op))) -#define _PyUnicode_SHARE_WSTR(op) \ - (assert(_PyUnicode_CHECK(op)), \ - (_PyUnicode_WSTR(unicode) == PyUnicode_DATA(op))) - -/* true if the Unicode object has an allocated UTF-8 memory block - (not shared with other data) */ -#define _PyUnicode_HAS_UTF8_MEMORY(op) \ - ((!PyUnicode_IS_COMPACT_ASCII(op) \ - && _PyUnicode_UTF8(op) \ - && _PyUnicode_UTF8(op) != PyUnicode_DATA(op))) - -/* true if the Unicode object has an allocated wstr memory block - (not shared with other data) */ -#define _PyUnicode_HAS_WSTR_MEMORY(op) \ - ((_PyUnicode_WSTR(op) && \ - (!PyUnicode_IS_READY(op) || \ - _PyUnicode_WSTR(op) != PyUnicode_DATA(op)))) - -/* Generic helper macro to convert characters of different types. - from_type and to_type have to be valid type names, begin and end - are pointers to the source characters which should be of type - "from_type *". to is a pointer of type "to_type *" and points to the - buffer where the result characters are written to. */ -#define _PyUnicode_CONVERT_BYTES(from_type, to_type, begin, end, to) \ - do { \ - to_type *_to = (to_type *)(to); \ - const from_type *_iter = (from_type *)(begin); \ - const from_type *_end = (from_type *)(end); \ - Py_ssize_t n = (_end) - (_iter); \ - const from_type *_unrolled_end = \ - _iter + _Py_SIZE_ROUND_DOWN(n, 4); \ - while (_iter < (_unrolled_end)) { \ - _to[0] = (to_type) _iter[0]; \ - _to[1] = (to_type) _iter[1]; \ - _to[2] = (to_type) _iter[2]; \ - _to[3] = (to_type) _iter[3]; \ - _iter += 4; _to += 4; \ - } \ - while (_iter < (_end)) \ - *_to++ = (to_type) *_iter++; \ - } while (0) - -/* This dictionary holds all interned unicode strings. Note that references - to strings in this dictionary are *not* counted in the string's ob_refcnt. - When the interned string reaches a refcnt of 0 the string deallocation - function will delete the reference from this dictionary. - - Another way to look at this is that to say that the actual reference - count of a string is: s->ob_refcnt + (s->state ? 2 : 0) -*/ -static PyObject *interned = NULL; - -/* The empty Unicode object is shared to improve performance. */ -static PyObject *unicode_empty = NULL; - -#define _Py_INCREF_UNICODE_EMPTY() \ - do { \ - if (unicode_empty != NULL) \ - Py_INCREF(unicode_empty); \ - else { \ - unicode_empty = PyUnicode_New(0, 0); \ - if (unicode_empty != NULL) { \ - Py_INCREF(unicode_empty); \ - assert(_PyUnicode_CheckConsistency(unicode_empty, 1)); \ - } \ - } \ - } while (0) - -#define _Py_RETURN_UNICODE_EMPTY() \ - do { \ - _Py_INCREF_UNICODE_EMPTY(); \ - return unicode_empty; \ - } while (0) - -/* Forward declaration */ -Py_LOCAL_INLINE(int) -_PyUnicodeWriter_WriteCharInline(_PyUnicodeWriter *writer, Py_UCS4 ch); - -/* List of static strings. */ -static _Py_Identifier *static_strings = NULL; - -/* Single character Unicode strings in the Latin-1 range are being - shared as well. */ -static PyObject *unicode_latin1[256] = {NULL}; - -/* Fast detection of the most frequent whitespace characters */ -const unsigned char _Py_ascii_whitespace[] = { - 0, 0, 0, 0, 0, 0, 0, 0, -/* case 0x0009: * CHARACTER TABULATION */ -/* case 0x000A: * LINE FEED */ -/* case 0x000B: * LINE TABULATION */ -/* case 0x000C: * FORM FEED */ -/* case 0x000D: * CARRIAGE RETURN */ - 0, 1, 1, 1, 1, 1, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -/* case 0x001C: * FILE SEPARATOR */ -/* case 0x001D: * GROUP SEPARATOR */ -/* case 0x001E: * RECORD SEPARATOR */ -/* case 0x001F: * UNIT SEPARATOR */ - 0, 0, 0, 0, 1, 1, 1, 1, -/* case 0x0020: * SPACE */ - 1, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0 -}; - -/* forward */ -static PyUnicodeObject *_PyUnicode_New(Py_ssize_t length); -static PyObject* get_latin1_char(unsigned char ch); -static int unicode_modifiable(PyObject *unicode); - - -static PyObject * -_PyUnicode_FromUCS1(const Py_UCS1 *s, Py_ssize_t size); -static PyObject * -_PyUnicode_FromUCS2(const Py_UCS2 *s, Py_ssize_t size); -static PyObject * -_PyUnicode_FromUCS4(const Py_UCS4 *s, Py_ssize_t size); - -static PyObject * -unicode_encode_call_errorhandler(const char *errors, - PyObject **errorHandler,const char *encoding, const char *reason, - PyObject *unicode, PyObject **exceptionObject, - Py_ssize_t startpos, Py_ssize_t endpos, Py_ssize_t *newpos); - -static void -raise_encode_exception(PyObject **exceptionObject, - const char *encoding, - PyObject *unicode, - Py_ssize_t startpos, Py_ssize_t endpos, - const char *reason); - -/* Same for linebreaks */ -static unsigned char ascii_linebreak[] = { - 0, 0, 0, 0, 0, 0, 0, 0, -/* 0x000A, * LINE FEED */ -/* 0x000B, * LINE TABULATION */ -/* 0x000C, * FORM FEED */ -/* 0x000D, * CARRIAGE RETURN */ - 0, 0, 1, 1, 1, 1, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -/* 0x001C, * FILE SEPARATOR */ -/* 0x001D, * GROUP SEPARATOR */ -/* 0x001E, * RECORD SEPARATOR */ - 0, 0, 0, 0, 1, 1, 1, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0 -}; - -/* The max unicode value is always 0x10FFFF while using the PEP-393 API. - This function is kept for backward compatibility with the old API. */ -Py_UNICODE -PyUnicode_GetMax(void) -{ -#ifdef Py_UNICODE_WIDE - return 0x10FFFF; -#else - /* This is actually an illegal character, so it should - not be passed to unichr. */ - return 0xFFFF; -#endif -} - -#ifdef Py_DEBUG -int -_PyUnicode_CheckConsistency(PyObject *op, int check_content) -{ - PyASCIIObject *ascii; - unsigned int kind; - - assert(PyUnicode_Check(op)); - - ascii = (PyASCIIObject *)op; - kind = ascii->state.kind; - - if (ascii->state.ascii == 1 && ascii->state.compact == 1) { - assert(kind == PyUnicode_1BYTE_KIND); - assert(ascii->state.ready == 1); - } - else { - PyCompactUnicodeObject *compact = (PyCompactUnicodeObject *)op; - void *data; - - if (ascii->state.compact == 1) { - data = compact + 1; - assert(kind == PyUnicode_1BYTE_KIND - || kind == PyUnicode_2BYTE_KIND - || kind == PyUnicode_4BYTE_KIND); - assert(ascii->state.ascii == 0); - assert(ascii->state.ready == 1); - assert (compact->utf8 != data); - } - else { - PyUnicodeObject *unicode = (PyUnicodeObject *)op; - - data = unicode->data.any; - if (kind == PyUnicode_WCHAR_KIND) { - assert(ascii->length == 0); - assert(ascii->hash == -1); - assert(ascii->state.compact == 0); - assert(ascii->state.ascii == 0); - assert(ascii->state.ready == 0); - assert(ascii->state.interned == SSTATE_NOT_INTERNED); - assert(ascii->wstr != NULL); - assert(data == NULL); - assert(compact->utf8 == NULL); - } - else { - assert(kind == PyUnicode_1BYTE_KIND - || kind == PyUnicode_2BYTE_KIND - || kind == PyUnicode_4BYTE_KIND); - assert(ascii->state.compact == 0); - assert(ascii->state.ready == 1); - assert(data != NULL); - if (ascii->state.ascii) { - assert (compact->utf8 == data); - assert (compact->utf8_length == ascii->length); - } - else - assert (compact->utf8 != data); - } - } - if (kind != PyUnicode_WCHAR_KIND) { - if ( -#if SIZEOF_WCHAR_T == 2 - kind == PyUnicode_2BYTE_KIND -#else - kind == PyUnicode_4BYTE_KIND -#endif - ) - { - assert(ascii->wstr == data); - assert(compact->wstr_length == ascii->length); - } else - assert(ascii->wstr != data); - } - - if (compact->utf8 == NULL) - assert(compact->utf8_length == 0); - if (ascii->wstr == NULL) - assert(compact->wstr_length == 0); - } - /* check that the best kind is used */ - if (check_content && kind != PyUnicode_WCHAR_KIND) - { - Py_ssize_t i; - Py_UCS4 maxchar = 0; - void *data; - Py_UCS4 ch; - - data = PyUnicode_DATA(ascii); - for (i=0; i < ascii->length; i++) - { - ch = PyUnicode_READ(kind, data, i); - if (ch > maxchar) - maxchar = ch; - } - if (kind == PyUnicode_1BYTE_KIND) { - if (ascii->state.ascii == 0) { - assert(maxchar >= 128); - assert(maxchar <= 255); - } - else - assert(maxchar < 128); - } - else if (kind == PyUnicode_2BYTE_KIND) { - assert(maxchar >= 0x100); - assert(maxchar <= 0xFFFF); - } - else { - assert(maxchar >= 0x10000); - assert(maxchar <= MAX_UNICODE); - } - assert(PyUnicode_READ(kind, data, ascii->length) == 0); - } - return 1; -} -#endif - -static PyObject* -unicode_result_wchar(PyObject *unicode) -{ -#ifndef Py_DEBUG - Py_ssize_t len; - - len = _PyUnicode_WSTR_LENGTH(unicode); - if (len == 0) { - Py_DECREF(unicode); - _Py_RETURN_UNICODE_EMPTY(); - } - - if (len == 1) { - wchar_t ch = _PyUnicode_WSTR(unicode)[0]; - if ((Py_UCS4)ch < 256) { - PyObject *latin1_char = get_latin1_char((unsigned char)ch); - Py_DECREF(unicode); - return latin1_char; - } - } - - if (_PyUnicode_Ready(unicode) < 0) { - Py_DECREF(unicode); - return NULL; - } -#else - assert(Py_REFCNT(unicode) == 1); - - /* don't make the result ready in debug mode to ensure that the caller - makes the string ready before using it */ - assert(_PyUnicode_CheckConsistency(unicode, 1)); -#endif - return unicode; -} - -static PyObject* -unicode_result_ready(PyObject *unicode) -{ - Py_ssize_t length; - - length = PyUnicode_GET_LENGTH(unicode); - if (length == 0) { - if (unicode != unicode_empty) { - Py_DECREF(unicode); - _Py_RETURN_UNICODE_EMPTY(); - } - return unicode_empty; - } - - if (length == 1) { - void *data = PyUnicode_DATA(unicode); - int kind = PyUnicode_KIND(unicode); - Py_UCS4 ch = PyUnicode_READ(kind, data, 0); - if (ch < 256) { - PyObject *latin1_char = unicode_latin1[ch]; - if (latin1_char != NULL) { - if (unicode != latin1_char) { - Py_INCREF(latin1_char); - Py_DECREF(unicode); - } - return latin1_char; - } - else { - assert(_PyUnicode_CheckConsistency(unicode, 1)); - Py_INCREF(unicode); - unicode_latin1[ch] = unicode; - return unicode; - } - } - } - - assert(_PyUnicode_CheckConsistency(unicode, 1)); - return unicode; -} - -static PyObject* -unicode_result(PyObject *unicode) -{ - assert(_PyUnicode_CHECK(unicode)); - if (PyUnicode_IS_READY(unicode)) - return unicode_result_ready(unicode); - else - return unicode_result_wchar(unicode); -} - -static PyObject* -unicode_result_unchanged(PyObject *unicode) -{ - if (PyUnicode_CheckExact(unicode)) { - if (PyUnicode_READY(unicode) == -1) - return NULL; - Py_INCREF(unicode); - return unicode; - } - else - /* Subtype -- return genuine unicode string with the same value. */ - return _PyUnicode_Copy(unicode); -} - -/* --- Bloom Filters ----------------------------------------------------- */ - -/* stuff to implement simple "bloom filters" for Unicode characters. - to keep things simple, we use a single bitmask, using the least 5 - bits from each unicode characters as the bit index. */ - -/* the linebreak mask is set up by Unicode_Init below */ - -#if LONG_BIT >= 128 -#define BLOOM_WIDTH 128 -#elif LONG_BIT >= 64 -#define BLOOM_WIDTH 64 -#elif LONG_BIT >= 32 -#define BLOOM_WIDTH 32 -#else -#error "LONG_BIT is smaller than 32" -#endif - -#define BLOOM_MASK unsigned long - -static BLOOM_MASK bloom_linebreak = ~(BLOOM_MASK)0; - -#define BLOOM(mask, ch) ((mask & (1UL << ((ch) & (BLOOM_WIDTH - 1))))) - -#define BLOOM_LINEBREAK(ch) \ - ((ch) < 128U ? ascii_linebreak[(ch)] : \ - (BLOOM(bloom_linebreak, (ch)) && Py_UNICODE_ISLINEBREAK(ch))) - -Py_LOCAL_INLINE(BLOOM_MASK) -make_bloom_mask(int kind, void* ptr, Py_ssize_t len) -{ -#define BLOOM_UPDATE(TYPE, MASK, PTR, LEN) \ - do { \ - TYPE *data = (TYPE *)PTR; \ - TYPE *end = data + LEN; \ - Py_UCS4 ch; \ - for (; data != end; data++) { \ - ch = *data; \ - MASK |= (1UL << (ch & (BLOOM_WIDTH - 1))); \ - } \ - break; \ - } while (0) - - /* calculate simple bloom-style bitmask for a given unicode string */ - - BLOOM_MASK mask; - - mask = 0; - switch (kind) { - case PyUnicode_1BYTE_KIND: - BLOOM_UPDATE(Py_UCS1, mask, ptr, len); - break; - case PyUnicode_2BYTE_KIND: - BLOOM_UPDATE(Py_UCS2, mask, ptr, len); - break; - case PyUnicode_4BYTE_KIND: - BLOOM_UPDATE(Py_UCS4, mask, ptr, len); - break; - default: - assert(0); - } - return mask; - -#undef BLOOM_UPDATE -} - -/* Compilation of templated routines */ - -#include "stringlib/asciilib.h" -#include "stringlib/fastsearch.h" -#include "stringlib/partition.h" -#include "stringlib/split.h" -#include "stringlib/count.h" -#include "stringlib/find.h" -#include "stringlib/find_max_char.h" -#include "stringlib/localeutil.h" -#include "stringlib/undef.h" - -#include "stringlib/ucs1lib.h" -#include "stringlib/fastsearch.h" -#include "stringlib/partition.h" -#include "stringlib/split.h" -#include "stringlib/count.h" -#include "stringlib/find.h" -#include "stringlib/replace.h" -#include "stringlib/find_max_char.h" -#include "stringlib/localeutil.h" -#include "stringlib/undef.h" - -#include "stringlib/ucs2lib.h" -#include "stringlib/fastsearch.h" -#include "stringlib/partition.h" -#include "stringlib/split.h" -#include "stringlib/count.h" -#include "stringlib/find.h" -#include "stringlib/replace.h" -#include "stringlib/find_max_char.h" -#include "stringlib/localeutil.h" -#include "stringlib/undef.h" - -#include "stringlib/ucs4lib.h" -#include "stringlib/fastsearch.h" -#include "stringlib/partition.h" -#include "stringlib/split.h" -#include "stringlib/count.h" -#include "stringlib/find.h" -#include "stringlib/replace.h" -#include "stringlib/find_max_char.h" -#include "stringlib/localeutil.h" -#include "stringlib/undef.h" - -#include "stringlib/unicodedefs.h" -#include "stringlib/fastsearch.h" -#include "stringlib/count.h" -#include "stringlib/find.h" -#include "stringlib/undef.h" - -/* --- Unicode Object ----------------------------------------------------- */ - -static PyObject * -fixup(PyObject *self, Py_UCS4 (*fixfct)(PyObject *s)); - -Py_LOCAL_INLINE(Py_ssize_t) findchar(const void *s, int kind, - Py_ssize_t size, Py_UCS4 ch, - int direction) -{ - int mode = (direction == 1) ? FAST_SEARCH : FAST_RSEARCH; - - switch (kind) { - case PyUnicode_1BYTE_KIND: - { - Py_UCS1 ch1 = (Py_UCS1) ch; - if (ch1 == ch) - return ucs1lib_fastsearch((Py_UCS1 *) s, size, &ch1, 1, 0, mode); - else - return -1; - } - case PyUnicode_2BYTE_KIND: - { - Py_UCS2 ch2 = (Py_UCS2) ch; - if (ch2 == ch) - return ucs2lib_fastsearch((Py_UCS2 *) s, size, &ch2, 1, 0, mode); - else - return -1; - } - case PyUnicode_4BYTE_KIND: - return ucs4lib_fastsearch((Py_UCS4 *) s, size, &ch, 1, 0, mode); - default: - assert(0); - return -1; - } -} - -#ifdef Py_DEBUG -/* Fill the data of an Unicode string 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. */ -static void -unicode_fill_invalid(PyObject *unicode, Py_ssize_t old_length) -{ - int kind = PyUnicode_KIND(unicode); - Py_UCS1 *data = PyUnicode_1BYTE_DATA(unicode); - Py_ssize_t length = _PyUnicode_LENGTH(unicode); - if (length <= old_length) - return; - memset(data + old_length * kind, 0xff, (length - old_length) * kind); -} -#endif - -static PyObject* -resize_compact(PyObject *unicode, Py_ssize_t length) -{ - Py_ssize_t char_size; - Py_ssize_t struct_size; - Py_ssize_t new_size; - int share_wstr; - PyObject *new_unicode; -#ifdef Py_DEBUG - Py_ssize_t old_length = _PyUnicode_LENGTH(unicode); -#endif - - assert(unicode_modifiable(unicode)); - assert(PyUnicode_IS_READY(unicode)); - assert(PyUnicode_IS_COMPACT(unicode)); - - char_size = PyUnicode_KIND(unicode); - if (PyUnicode_IS_ASCII(unicode)) - struct_size = sizeof(PyASCIIObject); - else - struct_size = sizeof(PyCompactUnicodeObject); - share_wstr = _PyUnicode_SHARE_WSTR(unicode); - - if (length > ((PY_SSIZE_T_MAX - struct_size) / char_size - 1)) { - PyErr_NoMemory(); - return NULL; - } - new_size = (struct_size + (length + 1) * char_size); - - _Py_DEC_REFTOTAL; - _Py_ForgetReference(unicode); - - new_unicode = (PyObject *)PyObject_REALLOC(unicode, new_size); - if (new_unicode == NULL) { - _Py_NewReference(unicode); - PyErr_NoMemory(); - return NULL; - } - unicode = new_unicode; - _Py_NewReference(unicode); - - _PyUnicode_LENGTH(unicode) = length; - if (share_wstr) { - _PyUnicode_WSTR(unicode) = PyUnicode_DATA(unicode); - if (!PyUnicode_IS_ASCII(unicode)) - _PyUnicode_WSTR_LENGTH(unicode) = length; - } - else if (_PyUnicode_HAS_WSTR_MEMORY(unicode)) { - PyObject_DEL(_PyUnicode_WSTR(unicode)); - _PyUnicode_WSTR(unicode) = NULL; - } -#ifdef Py_DEBUG - unicode_fill_invalid(unicode, old_length); -#endif - PyUnicode_WRITE(PyUnicode_KIND(unicode), PyUnicode_DATA(unicode), - length, 0); - assert(_PyUnicode_CheckConsistency(unicode, 0)); - return unicode; -} - -static int -resize_inplace(PyObject *unicode, Py_ssize_t length) -{ - wchar_t *wstr; - Py_ssize_t new_size; - assert(!PyUnicode_IS_COMPACT(unicode)); - assert(Py_REFCNT(unicode) == 1); - - if (PyUnicode_IS_READY(unicode)) { - Py_ssize_t char_size; - int share_wstr, share_utf8; - void *data; -#ifdef Py_DEBUG - Py_ssize_t old_length = _PyUnicode_LENGTH(unicode); -#endif - - data = _PyUnicode_DATA_ANY(unicode); - char_size = PyUnicode_KIND(unicode); - share_wstr = _PyUnicode_SHARE_WSTR(unicode); - share_utf8 = _PyUnicode_SHARE_UTF8(unicode); - - if (length > (PY_SSIZE_T_MAX / char_size - 1)) { - PyErr_NoMemory(); - return -1; - } - new_size = (length + 1) * char_size; - - if (!share_utf8 && _PyUnicode_HAS_UTF8_MEMORY(unicode)) - { - PyObject_DEL(_PyUnicode_UTF8(unicode)); - _PyUnicode_UTF8(unicode) = NULL; - _PyUnicode_UTF8_LENGTH(unicode) = 0; - } - - data = (PyObject *)PyObject_REALLOC(data, new_size); - if (data == NULL) { - PyErr_NoMemory(); - return -1; - } - _PyUnicode_DATA_ANY(unicode) = data; - if (share_wstr) { - _PyUnicode_WSTR(unicode) = data; - _PyUnicode_WSTR_LENGTH(unicode) = length; - } - if (share_utf8) { - _PyUnicode_UTF8(unicode) = data; - _PyUnicode_UTF8_LENGTH(unicode) = length; - } - _PyUnicode_LENGTH(unicode) = length; - PyUnicode_WRITE(PyUnicode_KIND(unicode), data, length, 0); -#ifdef Py_DEBUG - unicode_fill_invalid(unicode, old_length); -#endif - if (share_wstr || _PyUnicode_WSTR(unicode) == NULL) { - assert(_PyUnicode_CheckConsistency(unicode, 0)); - return 0; - } - } - assert(_PyUnicode_WSTR(unicode) != NULL); - - /* check for integer overflow */ - if (length > PY_SSIZE_T_MAX / (Py_ssize_t)sizeof(wchar_t) - 1) { - PyErr_NoMemory(); - return -1; - } - new_size = sizeof(wchar_t) * (length + 1); - wstr = _PyUnicode_WSTR(unicode); - wstr = PyObject_REALLOC(wstr, new_size); - if (!wstr) { - PyErr_NoMemory(); - return -1; - } - _PyUnicode_WSTR(unicode) = wstr; - _PyUnicode_WSTR(unicode)[length] = 0; - _PyUnicode_WSTR_LENGTH(unicode) = length; - assert(_PyUnicode_CheckConsistency(unicode, 0)); - return 0; -} - -static PyObject* -resize_copy(PyObject *unicode, Py_ssize_t length) -{ - Py_ssize_t copy_length; - if (_PyUnicode_KIND(unicode) != PyUnicode_WCHAR_KIND) { - PyObject *copy; - - if (PyUnicode_READY(unicode) == -1) - return NULL; - - copy = PyUnicode_New(length, PyUnicode_MAX_CHAR_VALUE(unicode)); - if (copy == NULL) - return NULL; - - copy_length = Py_MIN(length, PyUnicode_GET_LENGTH(unicode)); - _PyUnicode_FastCopyCharacters(copy, 0, unicode, 0, copy_length); - return copy; - } - else { - PyObject *w; - - w = (PyObject*)_PyUnicode_New(length); - if (w == NULL) - return NULL; - copy_length = _PyUnicode_WSTR_LENGTH(unicode); - copy_length = Py_MIN(copy_length, length); - Py_MEMCPY(_PyUnicode_WSTR(w), _PyUnicode_WSTR(unicode), - copy_length * sizeof(wchar_t)); - return w; - } -} - -/* We allocate one more byte to make sure the string is - Ux0000 terminated; some code (e.g. new_identifier) - relies on that. - - XXX This allocator could further be enhanced by assuring that the - free list never reduces its size below 1. - -*/ - -static PyUnicodeObject * -_PyUnicode_New(Py_ssize_t length) -{ - PyUnicodeObject *unicode; - size_t new_size; - - /* Optimization for empty strings */ - if (length == 0 && unicode_empty != NULL) { - Py_INCREF(unicode_empty); - return (PyUnicodeObject*)unicode_empty; - } - - /* Ensure we won't overflow the size. */ - if (length > ((PY_SSIZE_T_MAX / (Py_ssize_t)sizeof(Py_UNICODE)) - 1)) { - return (PyUnicodeObject *)PyErr_NoMemory(); - } - if (length < 0) { - PyErr_SetString(PyExc_SystemError, - "Negative size passed to _PyUnicode_New"); - return NULL; - } - - unicode = PyObject_New(PyUnicodeObject, &PyUnicode_Type); - if (unicode == NULL) - return NULL; - new_size = sizeof(Py_UNICODE) * ((size_t)length + 1); - - _PyUnicode_WSTR_LENGTH(unicode) = length; - _PyUnicode_HASH(unicode) = -1; - _PyUnicode_STATE(unicode).interned = 0; - _PyUnicode_STATE(unicode).kind = 0; - _PyUnicode_STATE(unicode).compact = 0; - _PyUnicode_STATE(unicode).ready = 0; - _PyUnicode_STATE(unicode).ascii = 0; - _PyUnicode_DATA_ANY(unicode) = NULL; - _PyUnicode_LENGTH(unicode) = 0; - _PyUnicode_UTF8(unicode) = NULL; - _PyUnicode_UTF8_LENGTH(unicode) = 0; - - _PyUnicode_WSTR(unicode) = (Py_UNICODE*) PyObject_MALLOC(new_size); - if (!_PyUnicode_WSTR(unicode)) { - Py_DECREF(unicode); - PyErr_NoMemory(); - return NULL; - } - - /* Initialize the first element to guard against cases where - * the caller fails before initializing str -- unicode_resize() - * reads str[0], and the Keep-Alive optimization can keep memory - * allocated for str alive across a call to unicode_dealloc(unicode). - * We don't want unicode_resize to read uninitialized memory in - * that case. - */ - _PyUnicode_WSTR(unicode)[0] = 0; - _PyUnicode_WSTR(unicode)[length] = 0; - - assert(_PyUnicode_CheckConsistency((PyObject *)unicode, 0)); - return unicode; -} - -static const char* -unicode_kind_name(PyObject *unicode) -{ - /* don't check consistency: unicode_kind_name() is called from - _PyUnicode_Dump() */ - if (!PyUnicode_IS_COMPACT(unicode)) - { - if (!PyUnicode_IS_READY(unicode)) - return "wstr"; - switch (PyUnicode_KIND(unicode)) - { - case PyUnicode_1BYTE_KIND: - if (PyUnicode_IS_ASCII(unicode)) - return "legacy ascii"; - else - return "legacy latin1"; - case PyUnicode_2BYTE_KIND: - return "legacy UCS2"; - case PyUnicode_4BYTE_KIND: - return "legacy UCS4"; - default: - return ""; - } - } - assert(PyUnicode_IS_READY(unicode)); - switch (PyUnicode_KIND(unicode)) { - case PyUnicode_1BYTE_KIND: - if (PyUnicode_IS_ASCII(unicode)) - return "ascii"; - else - return "latin1"; - case PyUnicode_2BYTE_KIND: - return "UCS2"; - case PyUnicode_4BYTE_KIND: - return "UCS4"; - default: - return ""; - } -} - -#ifdef Py_DEBUG -/* Functions wrapping macros for use in debugger */ -char *_PyUnicode_utf8(void *unicode){ - return PyUnicode_UTF8(unicode); -} - -void *_PyUnicode_compact_data(void *unicode) { - return _PyUnicode_COMPACT_DATA(unicode); -} -void *_PyUnicode_data(void *unicode){ - printf("obj %p\n", unicode); - printf("compact %d\n", PyUnicode_IS_COMPACT(unicode)); - printf("compact ascii %d\n", PyUnicode_IS_COMPACT_ASCII(unicode)); - printf("ascii op %p\n", ((void*)((PyASCIIObject*)(unicode) + 1))); - printf("compact op %p\n", ((void*)((PyCompactUnicodeObject*)(unicode) + 1))); - printf("compact data %p\n", _PyUnicode_COMPACT_DATA(unicode)); - return PyUnicode_DATA(unicode); -} - -void -_PyUnicode_Dump(PyObject *op) -{ - PyASCIIObject *ascii = (PyASCIIObject *)op; - PyCompactUnicodeObject *compact = (PyCompactUnicodeObject *)op; - PyUnicodeObject *unicode = (PyUnicodeObject *)op; - void *data; - - if (ascii->state.compact) - { - if (ascii->state.ascii) - data = (ascii + 1); - else - data = (compact + 1); - } - else - data = unicode->data.any; - printf("%s: len=%" PY_FORMAT_SIZE_T "u, ", - unicode_kind_name(op), ascii->length); - - if (ascii->wstr == data) - printf("shared "); - printf("wstr=%p", ascii->wstr); - - if (!(ascii->state.ascii == 1 && ascii->state.compact == 1)) { - printf(" (%" PY_FORMAT_SIZE_T "u), ", compact->wstr_length); - if (!ascii->state.compact && compact->utf8 == unicode->data.any) - printf("shared "); - printf("utf8=%p (%" PY_FORMAT_SIZE_T "u)", - compact->utf8, compact->utf8_length); - } - printf(", data=%p\n", data); -} -#endif - -PyObject * -PyUnicode_New(Py_ssize_t size, Py_UCS4 maxchar) -{ - PyObject *obj; - PyCompactUnicodeObject *unicode; - void *data; - enum PyUnicode_Kind kind; - int is_sharing, is_ascii; - Py_ssize_t char_size; - Py_ssize_t struct_size; - - /* Optimization for empty strings */ - if (size == 0 && unicode_empty != NULL) { - Py_INCREF(unicode_empty); - return unicode_empty; - } - - is_ascii = 0; - is_sharing = 0; - struct_size = sizeof(PyCompactUnicodeObject); - if (maxchar < 128) { - kind = PyUnicode_1BYTE_KIND; - char_size = 1; - is_ascii = 1; - struct_size = sizeof(PyASCIIObject); - } - else if (maxchar < 256) { - kind = PyUnicode_1BYTE_KIND; - char_size = 1; - } - else if (maxchar < 65536) { - kind = PyUnicode_2BYTE_KIND; - char_size = 2; - if (sizeof(wchar_t) == 2) - is_sharing = 1; - } - else { - if (maxchar > MAX_UNICODE) { - PyErr_SetString(PyExc_SystemError, - "invalid maximum character passed to PyUnicode_New"); - return NULL; - } - kind = PyUnicode_4BYTE_KIND; - char_size = 4; - if (sizeof(wchar_t) == 4) - is_sharing = 1; - } - - /* Ensure we won't overflow the size. */ - if (size < 0) { - PyErr_SetString(PyExc_SystemError, - "Negative size passed to PyUnicode_New"); - return NULL; - } - if (size > ((PY_SSIZE_T_MAX - struct_size) / char_size - 1)) - return PyErr_NoMemory(); - - /* Duplicated allocation code from _PyObject_New() instead of a call to - * PyObject_New() so we are able to allocate space for the object and - * it's data buffer. - */ - obj = (PyObject *) PyObject_MALLOC(struct_size + (size + 1) * char_size); - if (obj == NULL) - return PyErr_NoMemory(); - obj = PyObject_INIT(obj, &PyUnicode_Type); - if (obj == NULL) - return NULL; - - unicode = (PyCompactUnicodeObject *)obj; - if (is_ascii) - data = ((PyASCIIObject*)obj) + 1; - else - data = unicode + 1; - _PyUnicode_LENGTH(unicode) = size; - _PyUnicode_HASH(unicode) = -1; - _PyUnicode_STATE(unicode).interned = 0; - _PyUnicode_STATE(unicode).kind = kind; - _PyUnicode_STATE(unicode).compact = 1; - _PyUnicode_STATE(unicode).ready = 1; - _PyUnicode_STATE(unicode).ascii = is_ascii; - if (is_ascii) { - ((char*)data)[size] = 0; - _PyUnicode_WSTR(unicode) = NULL; - } - 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 == PyUnicode_2BYTE_KIND) - ((Py_UCS2*)data)[size] = 0; - else /* kind == PyUnicode_4BYTE_KIND */ - ((Py_UCS4*)data)[size] = 0; - if (is_sharing) { - _PyUnicode_WSTR_LENGTH(unicode) = size; - _PyUnicode_WSTR(unicode) = (wchar_t *)data; - } - else { - _PyUnicode_WSTR_LENGTH(unicode) = 0; - _PyUnicode_WSTR(unicode) = NULL; - } - } -#ifdef Py_DEBUG - unicode_fill_invalid((PyObject*)unicode, 0); -#endif - assert(_PyUnicode_CheckConsistency((PyObject*)unicode, 0)); - return obj; -} - -#if SIZEOF_WCHAR_T == 2 -/* Helper function to convert a 16-bits wchar_t representation to UCS4, this - will decode surrogate pairs, the other conversions are implemented as macros - for efficiency. - - This function assumes that unicode can hold one more code point than wstr - characters for a terminating null character. */ -static void -unicode_convert_wchar_to_ucs4(const wchar_t *begin, const wchar_t *end, - PyObject *unicode) -{ - const wchar_t *iter; - Py_UCS4 *ucs4_out; - - assert(unicode != NULL); - assert(_PyUnicode_CHECK(unicode)); - assert(_PyUnicode_KIND(unicode) == PyUnicode_4BYTE_KIND); - ucs4_out = PyUnicode_4BYTE_DATA(unicode); - - for (iter = begin; iter < end; ) { - assert(ucs4_out < (PyUnicode_4BYTE_DATA(unicode) + - _PyUnicode_GET_LENGTH(unicode))); - if (Py_UNICODE_IS_HIGH_SURROGATE(iter[0]) - && (iter+1) < end - && Py_UNICODE_IS_LOW_SURROGATE(iter[1])) - { - *ucs4_out++ = Py_UNICODE_JOIN_SURROGATES(iter[0], iter[1]); - iter += 2; - } - else { - *ucs4_out++ = *iter; - iter++; - } - } - assert(ucs4_out == (PyUnicode_4BYTE_DATA(unicode) + - _PyUnicode_GET_LENGTH(unicode))); - -} -#endif - -static int -unicode_check_modifiable(PyObject *unicode) -{ - if (!unicode_modifiable(unicode)) { - PyErr_SetString(PyExc_SystemError, - "Cannot modify a string currently used"); - return -1; - } - return 0; -} - -static int -_copy_characters(PyObject *to, Py_ssize_t to_start, - PyObject *from, Py_ssize_t from_start, - Py_ssize_t how_many, int check_maxchar) -{ - unsigned int from_kind, to_kind; - void *from_data, *to_data; - - assert(0 <= how_many); - assert(0 <= from_start); - assert(0 <= to_start); - assert(PyUnicode_Check(from)); - assert(PyUnicode_IS_READY(from)); - assert(from_start + how_many <= PyUnicode_GET_LENGTH(from)); - - assert(PyUnicode_Check(to)); - assert(PyUnicode_IS_READY(to)); - assert(to_start + how_many <= PyUnicode_GET_LENGTH(to)); - - if (how_many == 0) - return 0; - - from_kind = PyUnicode_KIND(from); - from_data = PyUnicode_DATA(from); - to_kind = PyUnicode_KIND(to); - to_data = PyUnicode_DATA(to); - -#ifdef Py_DEBUG - if (!check_maxchar - && PyUnicode_MAX_CHAR_VALUE(from) > PyUnicode_MAX_CHAR_VALUE(to)) - { - const Py_UCS4 to_maxchar = PyUnicode_MAX_CHAR_VALUE(to); - Py_UCS4 ch; - Py_ssize_t i; - for (i=0; i < how_many; i++) { - ch = PyUnicode_READ(from_kind, from_data, from_start + i); - assert(ch <= to_maxchar); - } - } -#endif - - if (from_kind == to_kind) { - if (check_maxchar - && !PyUnicode_IS_ASCII(from) && PyUnicode_IS_ASCII(to)) - { - /* Writing Latin-1 characters into an ASCII string requires to - check that all written characters are pure ASCII */ - Py_UCS4 max_char; - max_char = ucs1lib_find_max_char(from_data, - (Py_UCS1*)from_data + how_many); - if (max_char >= 128) - return -1; - } - Py_MEMCPY((char*)to_data + to_kind * to_start, - (char*)from_data + from_kind * from_start, - to_kind * how_many); - } - else if (from_kind == PyUnicode_1BYTE_KIND - && to_kind == PyUnicode_2BYTE_KIND) - { - _PyUnicode_CONVERT_BYTES( - Py_UCS1, Py_UCS2, - PyUnicode_1BYTE_DATA(from) + from_start, - PyUnicode_1BYTE_DATA(from) + from_start + how_many, - PyUnicode_2BYTE_DATA(to) + to_start - ); - } - else if (from_kind == PyUnicode_1BYTE_KIND - && to_kind == PyUnicode_4BYTE_KIND) - { - _PyUnicode_CONVERT_BYTES( - Py_UCS1, Py_UCS4, - PyUnicode_1BYTE_DATA(from) + from_start, - PyUnicode_1BYTE_DATA(from) + from_start + how_many, - PyUnicode_4BYTE_DATA(to) + to_start - ); - } - else if (from_kind == PyUnicode_2BYTE_KIND - && to_kind == PyUnicode_4BYTE_KIND) - { - _PyUnicode_CONVERT_BYTES( - Py_UCS2, Py_UCS4, - PyUnicode_2BYTE_DATA(from) + from_start, - PyUnicode_2BYTE_DATA(from) + from_start + how_many, - PyUnicode_4BYTE_DATA(to) + to_start - ); - } - else { - assert (PyUnicode_MAX_CHAR_VALUE(from) > PyUnicode_MAX_CHAR_VALUE(to)); - - if (!check_maxchar) { - if (from_kind == PyUnicode_2BYTE_KIND - && to_kind == PyUnicode_1BYTE_KIND) - { - _PyUnicode_CONVERT_BYTES( - Py_UCS2, Py_UCS1, - PyUnicode_2BYTE_DATA(from) + from_start, - PyUnicode_2BYTE_DATA(from) + from_start + how_many, - PyUnicode_1BYTE_DATA(to) + to_start - ); - } - else if (from_kind == PyUnicode_4BYTE_KIND - && to_kind == PyUnicode_1BYTE_KIND) - { - _PyUnicode_CONVERT_BYTES( - Py_UCS4, Py_UCS1, - PyUnicode_4BYTE_DATA(from) + from_start, - PyUnicode_4BYTE_DATA(from) + from_start + how_many, - PyUnicode_1BYTE_DATA(to) + to_start - ); - } - else if (from_kind == PyUnicode_4BYTE_KIND - && to_kind == PyUnicode_2BYTE_KIND) - { - _PyUnicode_CONVERT_BYTES( - Py_UCS4, Py_UCS2, - PyUnicode_4BYTE_DATA(from) + from_start, - PyUnicode_4BYTE_DATA(from) + from_start + how_many, - PyUnicode_2BYTE_DATA(to) + to_start - ); - } - else { - assert(0); - return -1; - } - } - else { - const Py_UCS4 to_maxchar = PyUnicode_MAX_CHAR_VALUE(to); - Py_UCS4 ch; - Py_ssize_t i; - - for (i=0; i < how_many; i++) { - ch = PyUnicode_READ(from_kind, from_data, from_start + i); - if (ch > to_maxchar) - return -1; - PyUnicode_WRITE(to_kind, to_data, to_start + i, ch); - } - } - } - return 0; -} - -void -_PyUnicode_FastCopyCharacters( - PyObject *to, Py_ssize_t to_start, - PyObject *from, Py_ssize_t from_start, Py_ssize_t how_many) -{ - (void)_copy_characters(to, to_start, from, from_start, how_many, 0); -} - -Py_ssize_t -PyUnicode_CopyCharacters(PyObject *to, Py_ssize_t to_start, - PyObject *from, Py_ssize_t from_start, - Py_ssize_t how_many) -{ - int err; - - if (!PyUnicode_Check(from) || !PyUnicode_Check(to)) { - PyErr_BadInternalCall(); - return -1; - } - - if (PyUnicode_READY(from) == -1) - return -1; - if (PyUnicode_READY(to) == -1) - return -1; - - if (from_start < 0) { - PyErr_SetString(PyExc_IndexError, "string index out of range"); - return -1; - } - if (to_start < 0) { - PyErr_SetString(PyExc_IndexError, "string index out of range"); - return -1; - } - how_many = Py_MIN(PyUnicode_GET_LENGTH(from), how_many); - if (to_start + how_many > PyUnicode_GET_LENGTH(to)) { - PyErr_Format(PyExc_SystemError, - "Cannot write %zi characters at %zi " - "in a string of %zi characters", - how_many, to_start, PyUnicode_GET_LENGTH(to)); - return -1; - } - - if (how_many == 0) - return 0; - - if (unicode_check_modifiable(to)) - return -1; - - err = _copy_characters(to, to_start, from, from_start, how_many, 1); - if (err) { - PyErr_Format(PyExc_SystemError, - "Cannot copy %s characters " - "into a string of %s characters", - unicode_kind_name(from), - unicode_kind_name(to)); - return -1; - } - return how_many; -} - -/* Find the maximum code point and count the number of surrogate pairs so a - correct string length can be computed before converting a string to UCS4. - This function counts single surrogates as a character and not as a pair. - - Return 0 on success, or -1 on error. */ -static int -find_maxchar_surrogates(const wchar_t *begin, const wchar_t *end, - Py_UCS4 *maxchar, Py_ssize_t *num_surrogates) -{ - const wchar_t *iter; - Py_UCS4 ch; - - assert(num_surrogates != NULL && maxchar != NULL); - *num_surrogates = 0; - *maxchar = 0; - - for (iter = begin; iter < end; ) { -#if SIZEOF_WCHAR_T == 2 - if (Py_UNICODE_IS_HIGH_SURROGATE(iter[0]) - && (iter+1) < end - && Py_UNICODE_IS_LOW_SURROGATE(iter[1])) - { - ch = Py_UNICODE_JOIN_SURROGATES(iter[0], iter[1]); - ++(*num_surrogates); - iter += 2; - } - else -#endif - { - ch = *iter; - iter++; - } - if (ch > *maxchar) { - *maxchar = ch; - if (*maxchar > MAX_UNICODE) { - PyErr_Format(PyExc_ValueError, - "character U+%x is not in range [U+0000; U+10ffff]", - ch); - return -1; - } - } - } - return 0; -} - -int -_PyUnicode_Ready(PyObject *unicode) -{ - wchar_t *end; - Py_UCS4 maxchar = 0; - Py_ssize_t num_surrogates; -#if SIZEOF_WCHAR_T == 2 - Py_ssize_t length_wo_surrogates; -#endif - - /* _PyUnicode_Ready() is only intended for old-style API usage where - strings were created using _PyObject_New() and where no canonical - representation (the str field) has been set yet aka strings - which are not yet ready. */ - assert(_PyUnicode_CHECK(unicode)); - assert(_PyUnicode_KIND(unicode) == PyUnicode_WCHAR_KIND); - assert(_PyUnicode_WSTR(unicode) != NULL); - assert(_PyUnicode_DATA_ANY(unicode) == NULL); - assert(_PyUnicode_UTF8(unicode) == NULL); - /* Actually, it should neither be interned nor be anything else: */ - assert(_PyUnicode_STATE(unicode).interned == SSTATE_NOT_INTERNED); - - end = _PyUnicode_WSTR(unicode) + _PyUnicode_WSTR_LENGTH(unicode); - if (find_maxchar_surrogates(_PyUnicode_WSTR(unicode), end, - &maxchar, &num_surrogates) == -1) - return -1; - - if (maxchar < 256) { - _PyUnicode_DATA_ANY(unicode) = PyObject_MALLOC(_PyUnicode_WSTR_LENGTH(unicode) + 1); - if (!_PyUnicode_DATA_ANY(unicode)) { - PyErr_NoMemory(); - return -1; - } - _PyUnicode_CONVERT_BYTES(wchar_t, unsigned char, - _PyUnicode_WSTR(unicode), end, - PyUnicode_1BYTE_DATA(unicode)); - PyUnicode_1BYTE_DATA(unicode)[_PyUnicode_WSTR_LENGTH(unicode)] = '\0'; - _PyUnicode_LENGTH(unicode) = _PyUnicode_WSTR_LENGTH(unicode); - _PyUnicode_STATE(unicode).kind = PyUnicode_1BYTE_KIND; - if (maxchar < 128) { - _PyUnicode_STATE(unicode).ascii = 1; - _PyUnicode_UTF8(unicode) = _PyUnicode_DATA_ANY(unicode); - _PyUnicode_UTF8_LENGTH(unicode) = _PyUnicode_WSTR_LENGTH(unicode); - } - else { - _PyUnicode_STATE(unicode).ascii = 0; - _PyUnicode_UTF8(unicode) = NULL; - _PyUnicode_UTF8_LENGTH(unicode) = 0; - } - PyObject_FREE(_PyUnicode_WSTR(unicode)); - _PyUnicode_WSTR(unicode) = NULL; - _PyUnicode_WSTR_LENGTH(unicode) = 0; - } - /* In this case we might have to convert down from 4-byte native - wchar_t to 2-byte unicode. */ - else if (maxchar < 65536) { - assert(num_surrogates == 0 && - "FindMaxCharAndNumSurrogatePairs() messed up"); - -#if SIZEOF_WCHAR_T == 2 - /* We can share representations and are done. */ - _PyUnicode_DATA_ANY(unicode) = _PyUnicode_WSTR(unicode); - PyUnicode_2BYTE_DATA(unicode)[_PyUnicode_WSTR_LENGTH(unicode)] = '\0'; - _PyUnicode_LENGTH(unicode) = _PyUnicode_WSTR_LENGTH(unicode); - _PyUnicode_STATE(unicode).kind = PyUnicode_2BYTE_KIND; - _PyUnicode_UTF8(unicode) = NULL; - _PyUnicode_UTF8_LENGTH(unicode) = 0; -#else - /* sizeof(wchar_t) == 4 */ - _PyUnicode_DATA_ANY(unicode) = PyObject_MALLOC( - 2 * (_PyUnicode_WSTR_LENGTH(unicode) + 1)); - if (!_PyUnicode_DATA_ANY(unicode)) { - PyErr_NoMemory(); - return -1; - } - _PyUnicode_CONVERT_BYTES(wchar_t, Py_UCS2, - _PyUnicode_WSTR(unicode), end, - PyUnicode_2BYTE_DATA(unicode)); - PyUnicode_2BYTE_DATA(unicode)[_PyUnicode_WSTR_LENGTH(unicode)] = '\0'; - _PyUnicode_LENGTH(unicode) = _PyUnicode_WSTR_LENGTH(unicode); - _PyUnicode_STATE(unicode).kind = PyUnicode_2BYTE_KIND; - _PyUnicode_UTF8(unicode) = NULL; - _PyUnicode_UTF8_LENGTH(unicode) = 0; - PyObject_FREE(_PyUnicode_WSTR(unicode)); - _PyUnicode_WSTR(unicode) = NULL; - _PyUnicode_WSTR_LENGTH(unicode) = 0; -#endif - } - /* maxchar exeeds 16 bit, wee need 4 bytes for unicode characters */ - else { -#if SIZEOF_WCHAR_T == 2 - /* in case the native representation is 2-bytes, we need to allocate a - new normalized 4-byte version. */ - length_wo_surrogates = _PyUnicode_WSTR_LENGTH(unicode) - num_surrogates; - if (length_wo_surrogates > PY_SSIZE_T_MAX / 4 - 1) { - PyErr_NoMemory(); - return -1; - } - _PyUnicode_DATA_ANY(unicode) = PyObject_MALLOC(4 * (length_wo_surrogates + 1)); - if (!_PyUnicode_DATA_ANY(unicode)) { - PyErr_NoMemory(); - return -1; - } - _PyUnicode_LENGTH(unicode) = length_wo_surrogates; - _PyUnicode_STATE(unicode).kind = PyUnicode_4BYTE_KIND; - _PyUnicode_UTF8(unicode) = NULL; - _PyUnicode_UTF8_LENGTH(unicode) = 0; - /* unicode_convert_wchar_to_ucs4() requires a ready string */ - _PyUnicode_STATE(unicode).ready = 1; - unicode_convert_wchar_to_ucs4(_PyUnicode_WSTR(unicode), end, unicode); - PyObject_FREE(_PyUnicode_WSTR(unicode)); - _PyUnicode_WSTR(unicode) = NULL; - _PyUnicode_WSTR_LENGTH(unicode) = 0; -#else - assert(num_surrogates == 0); - - _PyUnicode_DATA_ANY(unicode) = _PyUnicode_WSTR(unicode); - _PyUnicode_LENGTH(unicode) = _PyUnicode_WSTR_LENGTH(unicode); - _PyUnicode_UTF8(unicode) = NULL; - _PyUnicode_UTF8_LENGTH(unicode) = 0; - _PyUnicode_STATE(unicode).kind = PyUnicode_4BYTE_KIND; -#endif - PyUnicode_4BYTE_DATA(unicode)[_PyUnicode_LENGTH(unicode)] = '\0'; - } - _PyUnicode_STATE(unicode).ready = 1; - assert(_PyUnicode_CheckConsistency(unicode, 1)); - return 0; -} - -static void -unicode_dealloc(PyObject *unicode) -{ - switch (PyUnicode_CHECK_INTERNED(unicode)) { - case SSTATE_NOT_INTERNED: - break; - - case SSTATE_INTERNED_MORTAL: - /* revive dead object temporarily for DelItem */ - Py_REFCNT(unicode) = 3; - if (PyDict_DelItem(interned, unicode) != 0) - Py_FatalError( - "deletion of interned string failed"); - break; - - case SSTATE_INTERNED_IMMORTAL: - Py_FatalError("Immortal interned string died."); - - default: - Py_FatalError("Inconsistent interned string state."); - } - - if (_PyUnicode_HAS_WSTR_MEMORY(unicode)) - PyObject_DEL(_PyUnicode_WSTR(unicode)); - if (_PyUnicode_HAS_UTF8_MEMORY(unicode)) - PyObject_DEL(_PyUnicode_UTF8(unicode)); - if (!PyUnicode_IS_COMPACT(unicode) && _PyUnicode_DATA_ANY(unicode)) - PyObject_DEL(_PyUnicode_DATA_ANY(unicode)); - - Py_TYPE(unicode)->tp_free(unicode); -} - -#ifdef Py_DEBUG -static int -unicode_is_singleton(PyObject *unicode) -{ - PyASCIIObject *ascii = (PyASCIIObject *)unicode; - if (unicode == unicode_empty) - return 1; - if (ascii->state.kind != PyUnicode_WCHAR_KIND && ascii->length == 1) - { - Py_UCS4 ch = PyUnicode_READ_CHAR(unicode, 0); - if (ch < 256 && unicode_latin1[ch] == unicode) - return 1; - } - return 0; -} -#endif - -static int -unicode_modifiable(PyObject *unicode) -{ - assert(_PyUnicode_CHECK(unicode)); - if (Py_REFCNT(unicode) != 1) - return 0; - if (_PyUnicode_HASH(unicode) != -1) - return 0; - if (PyUnicode_CHECK_INTERNED(unicode)) - return 0; - if (!PyUnicode_CheckExact(unicode)) - return 0; -#ifdef Py_DEBUG - /* singleton refcount is greater than 1 */ - assert(!unicode_is_singleton(unicode)); -#endif - return 1; -} - -static int -unicode_resize(PyObject **p_unicode, Py_ssize_t length) -{ - PyObject *unicode; - Py_ssize_t old_length; - - assert(p_unicode != NULL); - unicode = *p_unicode; - - assert(unicode != NULL); - assert(PyUnicode_Check(unicode)); - assert(0 <= length); - - if (_PyUnicode_KIND(unicode) == PyUnicode_WCHAR_KIND) - old_length = PyUnicode_WSTR_LENGTH(unicode); - else - old_length = PyUnicode_GET_LENGTH(unicode); - if (old_length == length) - return 0; - - if (length == 0) { - _Py_INCREF_UNICODE_EMPTY(); - if (!unicode_empty) - return -1; - Py_DECREF(*p_unicode); - *p_unicode = unicode_empty; - return 0; - } - - if (!unicode_modifiable(unicode)) { - PyObject *copy = resize_copy(unicode, length); - if (copy == NULL) - return -1; - Py_DECREF(*p_unicode); - *p_unicode = copy; - return 0; - } - - if (PyUnicode_IS_COMPACT(unicode)) { - PyObject *new_unicode = resize_compact(unicode, length); - if (new_unicode == NULL) - return -1; - *p_unicode = new_unicode; - return 0; - } - return resize_inplace(unicode, length); -} - -int -PyUnicode_Resize(PyObject **p_unicode, Py_ssize_t length) -{ - PyObject *unicode; - if (p_unicode == NULL) { - PyErr_BadInternalCall(); - return -1; - } - unicode = *p_unicode; - if (unicode == NULL || !PyUnicode_Check(unicode) || length < 0) - { - PyErr_BadInternalCall(); - return -1; - } - return unicode_resize(p_unicode, length); -} - -/* Copy a ASCII or latin1 char* string into a Python Unicode string. - - WARNING: The function doesn't copy the terminating null character and - doesn't check the maximum character (may write a latin1 character in an - ASCII string). */ -static void -unicode_write_cstr(PyObject *unicode, Py_ssize_t index, - const char *str, Py_ssize_t len) -{ - enum PyUnicode_Kind kind = PyUnicode_KIND(unicode); - void *data = PyUnicode_DATA(unicode); - const char *end = str + len; - - switch (kind) { - case PyUnicode_1BYTE_KIND: { - assert(index + len <= PyUnicode_GET_LENGTH(unicode)); -#ifdef Py_DEBUG - if (PyUnicode_IS_ASCII(unicode)) { - Py_UCS4 maxchar = ucs1lib_find_max_char( - (const Py_UCS1*)str, - (const Py_UCS1*)str + len); - assert(maxchar < 128); - } -#endif - memcpy((char *) data + index, str, len); - break; - } - case PyUnicode_2BYTE_KIND: { - Py_UCS2 *start = (Py_UCS2 *)data + index; - Py_UCS2 *ucs2 = start; - assert(index <= PyUnicode_GET_LENGTH(unicode)); - - for (; str < end; ++ucs2, ++str) - *ucs2 = (Py_UCS2)*str; - - assert((ucs2 - start) <= PyUnicode_GET_LENGTH(unicode)); - break; - } - default: { - Py_UCS4 *start = (Py_UCS4 *)data + index; - Py_UCS4 *ucs4 = start; - assert(kind == PyUnicode_4BYTE_KIND); - assert(index <= PyUnicode_GET_LENGTH(unicode)); - - for (; str < end; ++ucs4, ++str) - *ucs4 = (Py_UCS4)*str; - - assert((ucs4 - start) <= PyUnicode_GET_LENGTH(unicode)); - } - } -} - -static PyObject* -get_latin1_char(unsigned char ch) -{ - PyObject *unicode = unicode_latin1[ch]; - if (!unicode) { - unicode = PyUnicode_New(1, ch); - if (!unicode) - return NULL; - PyUnicode_1BYTE_DATA(unicode)[0] = ch; - assert(_PyUnicode_CheckConsistency(unicode, 1)); - unicode_latin1[ch] = unicode; - } - Py_INCREF(unicode); - return unicode; -} - -static PyObject* -unicode_char(Py_UCS4 ch) -{ - PyObject *unicode; - - assert(ch <= MAX_UNICODE); - - if (ch < 256) - return get_latin1_char(ch); - - unicode = PyUnicode_New(1, ch); - if (unicode == NULL) - return NULL; - switch (PyUnicode_KIND(unicode)) { - case PyUnicode_1BYTE_KIND: - PyUnicode_1BYTE_DATA(unicode)[0] = (Py_UCS1)ch; - break; - case PyUnicode_2BYTE_KIND: - PyUnicode_2BYTE_DATA(unicode)[0] = (Py_UCS2)ch; - break; - default: - assert(PyUnicode_KIND(unicode) == PyUnicode_4BYTE_KIND); - PyUnicode_4BYTE_DATA(unicode)[0] = ch; - } - assert(_PyUnicode_CheckConsistency(unicode, 1)); - return unicode; -} - -PyObject * -PyUnicode_FromUnicode(const Py_UNICODE *u, Py_ssize_t size) -{ - PyObject *unicode; - Py_UCS4 maxchar = 0; - Py_ssize_t num_surrogates; - - if (u == NULL) - return (PyObject*)_PyUnicode_New(size); - - /* If the Unicode data is known at construction time, we can apply - some optimizations which share commonly used objects. */ - - /* Optimization for empty strings */ - if (size == 0) - _Py_RETURN_UNICODE_EMPTY(); - - /* Single character Unicode objects in the Latin-1 range are - shared when using this constructor */ - if (size == 1 && (Py_UCS4)*u < 256) - return get_latin1_char((unsigned char)*u); - - /* If not empty and not single character, copy the Unicode data - into the new object */ - if (find_maxchar_surrogates(u, u + size, - &maxchar, &num_surrogates) == -1) - return NULL; - - unicode = PyUnicode_New(size - num_surrogates, maxchar); - if (!unicode) - return NULL; - - switch (PyUnicode_KIND(unicode)) { - case PyUnicode_1BYTE_KIND: - _PyUnicode_CONVERT_BYTES(Py_UNICODE, unsigned char, - u, u + size, PyUnicode_1BYTE_DATA(unicode)); - break; - case PyUnicode_2BYTE_KIND: -#if Py_UNICODE_SIZE == 2 - Py_MEMCPY(PyUnicode_2BYTE_DATA(unicode), u, size * 2); -#else - _PyUnicode_CONVERT_BYTES(Py_UNICODE, Py_UCS2, - u, u + size, PyUnicode_2BYTE_DATA(unicode)); -#endif - break; - case PyUnicode_4BYTE_KIND: -#if SIZEOF_WCHAR_T == 2 - /* This is the only case which has to process surrogates, thus - a simple copy loop is not enough and we need a function. */ - unicode_convert_wchar_to_ucs4(u, u + size, unicode); -#else - assert(num_surrogates == 0); - Py_MEMCPY(PyUnicode_4BYTE_DATA(unicode), u, size * 4); -#endif - break; - default: - assert(0 && "Impossible state"); - } - - return unicode_result(unicode); -} - -PyObject * -PyUnicode_FromStringAndSize(const char *u, Py_ssize_t size) -{ - if (size < 0) { - PyErr_SetString(PyExc_SystemError, - "Negative size passed to PyUnicode_FromStringAndSize"); - return NULL; - } - if (u != NULL) - return PyUnicode_DecodeUTF8Stateful(u, size, NULL, NULL); - else - return (PyObject *)_PyUnicode_New(size); -} - -PyObject * -PyUnicode_FromString(const char *u) -{ - size_t size = strlen(u); - if (size > PY_SSIZE_T_MAX) { - PyErr_SetString(PyExc_OverflowError, "input too long"); - return NULL; - } - return PyUnicode_DecodeUTF8Stateful(u, (Py_ssize_t)size, NULL, NULL); -} - -PyObject * -_PyUnicode_FromId(_Py_Identifier *id) -{ - if (!id->object) { - id->object = PyUnicode_DecodeUTF8Stateful(id->string, - strlen(id->string), - NULL, NULL); - if (!id->object) - return NULL; - PyUnicode_InternInPlace(&id->object); - assert(!id->next); - id->next = static_strings; - static_strings = id; - } - return id->object; -} - -void -_PyUnicode_ClearStaticStrings() -{ - _Py_Identifier *tmp, *s = static_strings; - while (s) { - Py_CLEAR(s->object); - tmp = s->next; - s->next = NULL; - s = tmp; - } - static_strings = NULL; -} - -/* Internal function, doesn't check maximum character */ - -PyObject* -_PyUnicode_FromASCII(const char *buffer, Py_ssize_t size) -{ - const unsigned char *s = (const unsigned char *)buffer; - PyObject *unicode; - if (size == 1) { -#ifdef Py_DEBUG - assert((unsigned char)s[0] < 128); -#endif - return get_latin1_char(s[0]); - } - unicode = PyUnicode_New(size, 127); - if (!unicode) - return NULL; - memcpy(PyUnicode_1BYTE_DATA(unicode), s, size); - assert(_PyUnicode_CheckConsistency(unicode, 1)); - return unicode; -} - -static Py_UCS4 -kind_maxchar_limit(unsigned int kind) -{ - switch (kind) { - case PyUnicode_1BYTE_KIND: - return 0x80; - case PyUnicode_2BYTE_KIND: - return 0x100; - case PyUnicode_4BYTE_KIND: - return 0x10000; - default: - assert(0 && "invalid kind"); - return MAX_UNICODE; - } -} - -Py_LOCAL_INLINE(Py_UCS4) -align_maxchar(Py_UCS4 maxchar) -{ - if (maxchar <= 127) - return 127; - else if (maxchar <= 255) - return 255; - else if (maxchar <= 65535) - return 65535; - else - return MAX_UNICODE; -} - -static PyObject* -_PyUnicode_FromUCS1(const Py_UCS1* u, Py_ssize_t size) -{ - PyObject *res; - unsigned char max_char; - - if (size == 0) - _Py_RETURN_UNICODE_EMPTY(); - assert(size > 0); - if (size == 1) - return get_latin1_char(u[0]); - - max_char = ucs1lib_find_max_char(u, u + size); - res = PyUnicode_New(size, max_char); - if (!res) - return NULL; - memcpy(PyUnicode_1BYTE_DATA(res), u, size); - assert(_PyUnicode_CheckConsistency(res, 1)); - return res; -} - -static PyObject* -_PyUnicode_FromUCS2(const Py_UCS2 *u, Py_ssize_t size) -{ - PyObject *res; - Py_UCS2 max_char; - - if (size == 0) - _Py_RETURN_UNICODE_EMPTY(); - assert(size > 0); - if (size == 1) - return unicode_char(u[0]); - - max_char = ucs2lib_find_max_char(u, u + size); - res = PyUnicode_New(size, max_char); - if (!res) - return NULL; - if (max_char >= 256) - memcpy(PyUnicode_2BYTE_DATA(res), u, sizeof(Py_UCS2)*size); - else { - _PyUnicode_CONVERT_BYTES( - Py_UCS2, Py_UCS1, u, u + size, PyUnicode_1BYTE_DATA(res)); - } - assert(_PyUnicode_CheckConsistency(res, 1)); - return res; -} - -static PyObject* -_PyUnicode_FromUCS4(const Py_UCS4 *u, Py_ssize_t size) -{ - PyObject *res; - Py_UCS4 max_char; - - if (size == 0) - _Py_RETURN_UNICODE_EMPTY(); - assert(size > 0); - if (size == 1) - return unicode_char(u[0]); - - max_char = ucs4lib_find_max_char(u, u + size); - res = PyUnicode_New(size, max_char); - if (!res) - return NULL; - if (max_char < 256) - _PyUnicode_CONVERT_BYTES(Py_UCS4, Py_UCS1, u, u + size, - PyUnicode_1BYTE_DATA(res)); - else if (max_char < 0x10000) - _PyUnicode_CONVERT_BYTES(Py_UCS4, Py_UCS2, u, u + size, - PyUnicode_2BYTE_DATA(res)); - else - memcpy(PyUnicode_4BYTE_DATA(res), u, sizeof(Py_UCS4)*size); - assert(_PyUnicode_CheckConsistency(res, 1)); - return res; -} - -PyObject* -PyUnicode_FromKindAndData(int kind, const void *buffer, Py_ssize_t size) -{ - if (size < 0) { - PyErr_SetString(PyExc_ValueError, "size must be positive"); - return NULL; - } - switch (kind) { - case PyUnicode_1BYTE_KIND: - return _PyUnicode_FromUCS1(buffer, size); - case PyUnicode_2BYTE_KIND: - return _PyUnicode_FromUCS2(buffer, size); - case PyUnicode_4BYTE_KIND: - return _PyUnicode_FromUCS4(buffer, size); - default: - PyErr_SetString(PyExc_SystemError, "invalid kind"); - return NULL; - } -} - -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; - - if (PyUnicode_IS_ASCII(unicode)) - return 127; - - kind = PyUnicode_KIND(unicode); - startptr = PyUnicode_DATA(unicode); - endptr = (char *)startptr + end * kind; - 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); - case PyUnicode_4BYTE_KIND: - return ucs4lib_find_max_char(startptr, endptr); - default: - assert(0); - return 0; - } -} - -/* 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. */ -static void -unicode_adjust_maxchar(PyObject **p_unicode) -{ - PyObject *unicode, *copy; - Py_UCS4 max_char; - Py_ssize_t len; - unsigned int kind; - - assert(p_unicode != NULL); - unicode = *p_unicode; - assert(PyUnicode_IS_READY(unicode)); - if (PyUnicode_IS_ASCII(unicode)) - return; - - len = PyUnicode_GET_LENGTH(unicode); - kind = PyUnicode_KIND(unicode); - if (kind == PyUnicode_1BYTE_KIND) { - const Py_UCS1 *u = PyUnicode_1BYTE_DATA(unicode); - max_char = ucs1lib_find_max_char(u, u + len); - if (max_char >= 128) - return; - } - else if (kind == PyUnicode_2BYTE_KIND) { - const Py_UCS2 *u = PyUnicode_2BYTE_DATA(unicode); - max_char = ucs2lib_find_max_char(u, u + len); - if (max_char >= 256) - return; - } - else { - const Py_UCS4 *u = PyUnicode_4BYTE_DATA(unicode); - assert(kind == PyUnicode_4BYTE_KIND); - max_char = ucs4lib_find_max_char(u, u + len); - if (max_char >= 0x10000) - return; - } - copy = PyUnicode_New(len, max_char); - if (copy != NULL) - _PyUnicode_FastCopyCharacters(copy, 0, unicode, 0, len); - Py_DECREF(unicode); - *p_unicode = copy; -} - -PyObject* -_PyUnicode_Copy(PyObject *unicode) -{ - Py_ssize_t length; - PyObject *copy; - - if (!PyUnicode_Check(unicode)) { - PyErr_BadInternalCall(); - return NULL; - } - if (PyUnicode_READY(unicode) == -1) - return NULL; - - length = PyUnicode_GET_LENGTH(unicode); - copy = PyUnicode_New(length, PyUnicode_MAX_CHAR_VALUE(unicode)); - if (!copy) - return NULL; - assert(PyUnicode_KIND(copy) == PyUnicode_KIND(unicode)); - - Py_MEMCPY(PyUnicode_DATA(copy), PyUnicode_DATA(unicode), - length * PyUnicode_KIND(unicode)); - assert(_PyUnicode_CheckConsistency(copy, 1)); - return copy; -} - - -/* Widen Unicode objects to larger buffers. Don't write terminating null - character. Return NULL on error. */ - -void* -_PyUnicode_AsKind(PyObject *s, unsigned int kind) -{ - Py_ssize_t len; - void *result; - unsigned int skind; - - if (PyUnicode_READY(s) == -1) - return NULL; - - len = PyUnicode_GET_LENGTH(s); - skind = PyUnicode_KIND(s); - if (skind >= kind) { - PyErr_SetString(PyExc_SystemError, "invalid widening attempt"); - return NULL; - } - switch (kind) { - case PyUnicode_2BYTE_KIND: - result = PyMem_New(Py_UCS2, len); - if (!result) - return PyErr_NoMemory(); - assert(skind == PyUnicode_1BYTE_KIND); - _PyUnicode_CONVERT_BYTES( - Py_UCS1, Py_UCS2, - PyUnicode_1BYTE_DATA(s), - PyUnicode_1BYTE_DATA(s) + len, - result); - return result; - case PyUnicode_4BYTE_KIND: - result = PyMem_New(Py_UCS4, len); - if (!result) - return PyErr_NoMemory(); - if (skind == PyUnicode_2BYTE_KIND) { - _PyUnicode_CONVERT_BYTES( - Py_UCS2, Py_UCS4, - PyUnicode_2BYTE_DATA(s), - PyUnicode_2BYTE_DATA(s) + len, - result); - } - else { - assert(skind == PyUnicode_1BYTE_KIND); - _PyUnicode_CONVERT_BYTES( - Py_UCS1, Py_UCS4, - PyUnicode_1BYTE_DATA(s), - PyUnicode_1BYTE_DATA(s) + len, - result); - } - return result; - default: - break; - } - PyErr_SetString(PyExc_SystemError, "invalid kind"); - return NULL; -} - -static Py_UCS4* -as_ucs4(PyObject *string, Py_UCS4 *target, Py_ssize_t targetsize, - int copy_null) -{ - int kind; - void *data; - Py_ssize_t len, targetlen; - if (PyUnicode_READY(string) == -1) - return NULL; - kind = PyUnicode_KIND(string); - data = PyUnicode_DATA(string); - len = PyUnicode_GET_LENGTH(string); - targetlen = len; - if (copy_null) - targetlen++; - if (!target) { - target = PyMem_New(Py_UCS4, targetlen); - if (!target) { - PyErr_NoMemory(); - return NULL; - } - } - else { - if (targetsize < targetlen) { - PyErr_Format(PyExc_SystemError, - "string is longer than the buffer"); - if (copy_null && 0 < targetsize) - target[0] = 0; - return NULL; - } - } - if (kind == PyUnicode_1BYTE_KIND) { - Py_UCS1 *start = (Py_UCS1 *) data; - _PyUnicode_CONVERT_BYTES(Py_UCS1, Py_UCS4, start, start + len, target); - } - else if (kind == PyUnicode_2BYTE_KIND) { - Py_UCS2 *start = (Py_UCS2 *) data; - _PyUnicode_CONVERT_BYTES(Py_UCS2, Py_UCS4, start, start + len, target); - } - else { - assert(kind == PyUnicode_4BYTE_KIND); - Py_MEMCPY(target, data, len * sizeof(Py_UCS4)); - } - if (copy_null) - target[len] = 0; - return target; -} - -Py_UCS4* -PyUnicode_AsUCS4(PyObject *string, Py_UCS4 *target, Py_ssize_t targetsize, - int copy_null) -{ - if (target == NULL || targetsize < 0) { - PyErr_BadInternalCall(); - return NULL; - } - return as_ucs4(string, target, targetsize, copy_null); -} - -Py_UCS4* -PyUnicode_AsUCS4Copy(PyObject *string) -{ - return as_ucs4(string, NULL, 0, 1); -} - -#ifdef HAVE_WCHAR_H - -PyObject * -PyUnicode_FromWideChar(const wchar_t *w, Py_ssize_t size) -{ - if (w == NULL) { - if (size == 0) - _Py_RETURN_UNICODE_EMPTY(); - PyErr_BadInternalCall(); - return NULL; - } - - if (size == -1) { - size = wcslen(w); - } - - return PyUnicode_FromUnicode(w, size); -} - -#endif /* HAVE_WCHAR_H */ - -/* maximum number of characters required for output of %lld or %p. - We need at most ceil(log10(256)*SIZEOF_LONG_LONG) digits, - plus 1 for the sign. 53/22 is an upper bound for log10(256). */ -#define MAX_LONG_LONG_CHARS (2 + (SIZEOF_LONG_LONG*53-1) / 22) - -static int -unicode_fromformat_write_str(_PyUnicodeWriter *writer, PyObject *str, - Py_ssize_t width, Py_ssize_t precision) -{ - Py_ssize_t length, fill, arglen; - Py_UCS4 maxchar; - - if (PyUnicode_READY(str) == -1) - return -1; - - length = PyUnicode_GET_LENGTH(str); - if ((precision == -1 || precision >= length) - && width <= length) - return _PyUnicodeWriter_WriteStr(writer, str); - - if (precision != -1) - length = Py_MIN(precision, length); - - arglen = Py_MAX(length, width); - if (PyUnicode_MAX_CHAR_VALUE(str) > writer->maxchar) - maxchar = _PyUnicode_FindMaxChar(str, 0, length); - else - maxchar = writer->maxchar; - - if (_PyUnicodeWriter_Prepare(writer, arglen, maxchar) == -1) - return -1; - - if (width > length) { - fill = width - length; - if (PyUnicode_Fill(writer->buffer, writer->pos, fill, ' ') == -1) - return -1; - writer->pos += fill; - } - - _PyUnicode_FastCopyCharacters(writer->buffer, writer->pos, - str, 0, length); - writer->pos += length; - return 0; -} - -static int -unicode_fromformat_write_cstr(_PyUnicodeWriter *writer, const char *str, - Py_ssize_t width, Py_ssize_t precision) -{ - /* UTF-8 */ - Py_ssize_t length; - PyObject *unicode; - int res; - - length = strlen(str); - if (precision != -1) - length = Py_MIN(length, precision); - unicode = PyUnicode_DecodeUTF8Stateful(str, length, "replace", NULL); - if (unicode == NULL) - return -1; - - res = unicode_fromformat_write_str(writer, unicode, width, -1); - Py_DECREF(unicode); - return res; -} - -static const char* -unicode_fromformat_arg(_PyUnicodeWriter *writer, - const char *f, va_list *vargs) -{ - const char *p; - Py_ssize_t len; - int zeropad; - Py_ssize_t width; - Py_ssize_t precision; - int longflag; - int longlongflag; - int size_tflag; - Py_ssize_t fill; - - p = f; - f++; - zeropad = 0; - if (*f == '0') { - zeropad = 1; - f++; - } - - /* parse the width.precision part, e.g. "%2.5s" => width=2, precision=5 */ - width = -1; - if (Py_ISDIGIT((unsigned)*f)) { - width = *f - '0'; - f++; - while (Py_ISDIGIT((unsigned)*f)) { - if (width > (PY_SSIZE_T_MAX - ((int)*f - '0')) / 10) { - PyErr_SetString(PyExc_ValueError, - "width too big"); - return NULL; - } - width = (width * 10) + (*f - '0'); - f++; - } - } - precision = -1; - if (*f == '.') { - f++; - if (Py_ISDIGIT((unsigned)*f)) { - precision = (*f - '0'); - f++; - while (Py_ISDIGIT((unsigned)*f)) { - if (precision > (PY_SSIZE_T_MAX - ((int)*f - '0')) / 10) { - PyErr_SetString(PyExc_ValueError, - "precision too big"); - return NULL; - } - precision = (precision * 10) + (*f - '0'); - f++; - } - } - if (*f == '%') { - /* "%.3%s" => f points to "3" */ - f--; - } - } - if (*f == '\0') { - /* bogus format "%.123" => go backward, f points to "3" */ - f--; - } - - /* Handle %ld, %lu, %lld and %llu. */ - longflag = 0; - longlongflag = 0; - size_tflag = 0; - if (*f == 'l') { - if (f[1] == 'd' || f[1] == 'u' || f[1] == 'i') { - longflag = 1; - ++f; - } -#ifdef HAVE_LONG_LONG - else if (f[1] == 'l' && - (f[2] == 'd' || f[2] == 'u' || f[2] == 'i')) { - longlongflag = 1; - f += 2; - } -#endif - } - /* handle the size_t flag. */ - else if (*f == 'z' && (f[1] == 'd' || f[1] == 'u' || f[1] == 'i')) { - size_tflag = 1; - ++f; - } - - if (f[1] == '\0') - writer->overallocate = 0; - - switch (*f) { - case 'c': - { - int ordinal = va_arg(*vargs, int); - if (ordinal < 0 || ordinal > MAX_UNICODE) { - PyErr_SetString(PyExc_OverflowError, - "character argument not in range(0x110000)"); - return NULL; - } - if (_PyUnicodeWriter_WriteCharInline(writer, ordinal) < 0) - return NULL; - break; - } - - case 'i': - case 'd': - case 'u': - case 'x': - { - /* used by sprintf */ - char buffer[MAX_LONG_LONG_CHARS]; - Py_ssize_t arglen; - - if (*f == 'u') { - if (longflag) - len = sprintf(buffer, "%lu", - va_arg(*vargs, unsigned long)); -#ifdef HAVE_LONG_LONG - else if (longlongflag) - len = sprintf(buffer, "%" PY_FORMAT_LONG_LONG "u", - va_arg(*vargs, unsigned PY_LONG_LONG)); -#endif - else if (size_tflag) - len = sprintf(buffer, "%" PY_FORMAT_SIZE_T "u", - va_arg(*vargs, size_t)); - else - len = sprintf(buffer, "%u", - va_arg(*vargs, unsigned int)); - } - else if (*f == 'x') { - len = sprintf(buffer, "%x", va_arg(*vargs, int)); - } - else { - if (longflag) - len = sprintf(buffer, "%li", - va_arg(*vargs, long)); -#ifdef HAVE_LONG_LONG - else if (longlongflag) - len = sprintf(buffer, "%" PY_FORMAT_LONG_LONG "i", - va_arg(*vargs, PY_LONG_LONG)); -#endif - else if (size_tflag) - len = sprintf(buffer, "%" PY_FORMAT_SIZE_T "i", - va_arg(*vargs, Py_ssize_t)); - else - len = sprintf(buffer, "%i", - va_arg(*vargs, int)); - } - assert(len >= 0); - - if (precision < len) - precision = len; - - arglen = Py_MAX(precision, width); - if (_PyUnicodeWriter_Prepare(writer, arglen, 127) == -1) - return NULL; - - if (width > precision) { - Py_UCS4 fillchar; - fill = width - precision; - fillchar = zeropad?'0':' '; - if (PyUnicode_Fill(writer->buffer, writer->pos, fill, fillchar) == -1) - return NULL; - writer->pos += fill; - } - if (precision > len) { - fill = precision - len; - if (PyUnicode_Fill(writer->buffer, writer->pos, fill, '0') == -1) - return NULL; - writer->pos += fill; - } - - if (_PyUnicodeWriter_WriteASCIIString(writer, buffer, len) < 0) - return NULL; - break; - } - - case 'p': - { - char number[MAX_LONG_LONG_CHARS]; - - len = sprintf(number, "%p", va_arg(*vargs, void*)); - assert(len >= 0); - - /* %p is ill-defined: ensure leading 0x. */ - if (number[1] == 'X') - number[1] = 'x'; - else if (number[1] != 'x') { - memmove(number + 2, number, - strlen(number) + 1); - number[0] = '0'; - number[1] = 'x'; - len += 2; - } - - if (_PyUnicodeWriter_WriteASCIIString(writer, number, len) < 0) - return NULL; - break; - } - - case 's': - { - /* UTF-8 */ - const char *s = va_arg(*vargs, const char*); - if (unicode_fromformat_write_cstr(writer, s, width, precision) < 0) - return NULL; - break; - } - - case 'U': - { - PyObject *obj = va_arg(*vargs, PyObject *); - assert(obj && _PyUnicode_CHECK(obj)); - - if (unicode_fromformat_write_str(writer, obj, width, precision) == -1) - return NULL; - break; - } - - case 'V': - { - PyObject *obj = va_arg(*vargs, PyObject *); - const char *str = va_arg(*vargs, const char *); - if (obj) { - assert(_PyUnicode_CHECK(obj)); - if (unicode_fromformat_write_str(writer, obj, width, precision) == -1) - return NULL; - } - else { - assert(str != NULL); - if (unicode_fromformat_write_cstr(writer, str, width, precision) < 0) - return NULL; - } - break; - } - - case 'S': - { - PyObject *obj = va_arg(*vargs, PyObject *); - PyObject *str; - assert(obj); - str = PyObject_Str(obj); - if (!str) - return NULL; - if (unicode_fromformat_write_str(writer, str, width, precision) == -1) { - Py_DECREF(str); - return NULL; - } - Py_DECREF(str); - break; - } - - case 'R': - { - PyObject *obj = va_arg(*vargs, PyObject *); - PyObject *repr; - assert(obj); - repr = PyObject_Repr(obj); - if (!repr) - return NULL; - if (unicode_fromformat_write_str(writer, repr, width, precision) == -1) { - Py_DECREF(repr); - return NULL; - } - Py_DECREF(repr); - break; - } - - case 'A': - { - PyObject *obj = va_arg(*vargs, PyObject *); - PyObject *ascii; - assert(obj); - ascii = PyObject_ASCII(obj); - if (!ascii) - return NULL; - if (unicode_fromformat_write_str(writer, ascii, width, precision) == -1) { - Py_DECREF(ascii); - return NULL; - } - Py_DECREF(ascii); - break; - } - - case '%': - if (_PyUnicodeWriter_WriteCharInline(writer, '%') < 0) - return NULL; - break; - - default: - /* if we stumble upon an unknown formatting code, copy the rest - of the format string to the output string. (we cannot just - skip the code, since there's no way to know what's in the - argument list) */ - len = strlen(p); - if (_PyUnicodeWriter_WriteLatin1String(writer, p, len) == -1) - return NULL; - f = p+len; - return f; - } - - f++; - return f; -} - -PyObject * -PyUnicode_FromFormatV(const char *format, va_list vargs) -{ - va_list vargs2; - const char *f; - _PyUnicodeWriter writer; - - _PyUnicodeWriter_Init(&writer); - writer.min_length = strlen(format) + 100; - writer.overallocate = 1; - - /* va_list may be an array (of 1 item) on some platforms (ex: AMD64). - Copy it to be able to pass a reference to a subfunction. */ - Py_VA_COPY(vargs2, vargs); - - for (f = format; *f; ) { - if (*f == '%') { - f = unicode_fromformat_arg(&writer, f, &vargs2); - if (f == NULL) - goto fail; - } - else { - const char *p; - Py_ssize_t len; - - p = f; - do - { - if ((unsigned char)*p > 127) { - PyErr_Format(PyExc_ValueError, - "PyUnicode_FromFormatV() expects an ASCII-encoded format " - "string, got a non-ASCII byte: 0x%02x", - (unsigned char)*p); - return NULL; - } - p++; - } - while (*p != '\0' && *p != '%'); - len = p - f; - - if (*p == '\0') - writer.overallocate = 0; - - if (_PyUnicodeWriter_WriteASCIIString(&writer, f, len) < 0) - goto fail; - - f = p; - } - } - return _PyUnicodeWriter_Finish(&writer); - - fail: - _PyUnicodeWriter_Dealloc(&writer); - return NULL; -} - -PyObject * -PyUnicode_FromFormat(const char *format, ...) -{ - PyObject* ret; - va_list vargs; - -#ifdef HAVE_STDARG_PROTOTYPES - va_start(vargs, format); -#else - va_start(vargs); -#endif - ret = PyUnicode_FromFormatV(format, vargs); - va_end(vargs); - return ret; -} - -#ifdef HAVE_WCHAR_H - -/* Helper function for PyUnicode_AsWideChar() and PyUnicode_AsWideCharString(): - convert a Unicode object to a wide character string. - - - If w is NULL: return the number of wide characters (including the null - character) required to convert the unicode object. Ignore size argument. - - - Otherwise: return the number of wide characters (excluding the null - character) written into w. Write at most size wide characters (including - the null character). */ -static Py_ssize_t -unicode_aswidechar(PyObject *unicode, - wchar_t *w, - Py_ssize_t size) -{ - Py_ssize_t res; - const wchar_t *wstr; - - wstr = PyUnicode_AsUnicodeAndSize(unicode, &res); - if (wstr == NULL) - return -1; - - if (w != NULL) { - if (size > res) - size = res + 1; - else - res = size; - Py_MEMCPY(w, wstr, size * sizeof(wchar_t)); - return res; - } - else - return res + 1; -} - -Py_ssize_t -PyUnicode_AsWideChar(PyObject *unicode, - wchar_t *w, - Py_ssize_t size) -{ - if (unicode == NULL) { - PyErr_BadInternalCall(); - return -1; - } - return unicode_aswidechar(unicode, w, size); -} - -wchar_t* -PyUnicode_AsWideCharString(PyObject *unicode, - Py_ssize_t *size) -{ - wchar_t* buffer; - Py_ssize_t buflen; - - if (unicode == NULL) { - PyErr_BadInternalCall(); - return NULL; - } - - buflen = unicode_aswidechar(unicode, NULL, 0); - if (buflen == -1) - return NULL; - buffer = PyMem_NEW(wchar_t, buflen); - if (buffer == NULL) { - PyErr_NoMemory(); - return NULL; - } - buflen = unicode_aswidechar(unicode, buffer, buflen); - if (buflen == -1) { - PyMem_FREE(buffer); - return NULL; - } - if (size != NULL) - *size = buflen; - return buffer; -} - -#endif /* HAVE_WCHAR_H */ - -PyObject * -PyUnicode_FromOrdinal(int ordinal) -{ - if (ordinal < 0 || ordinal > MAX_UNICODE) { - PyErr_SetString(PyExc_ValueError, - "chr() arg not in range(0x110000)"); - return NULL; - } - - return unicode_char((Py_UCS4)ordinal); -} - -PyObject * -PyUnicode_FromObject(PyObject *obj) -{ - /* XXX Perhaps we should make this API an alias of - PyObject_Str() instead ?! */ - if (PyUnicode_CheckExact(obj)) { - if (PyUnicode_READY(obj) == -1) - return NULL; - Py_INCREF(obj); - return obj; - } - if (PyUnicode_Check(obj)) { - /* For a Unicode subtype that's not a Unicode object, - return a true Unicode object with the same data. */ - return _PyUnicode_Copy(obj); - } - PyErr_Format(PyExc_TypeError, - "Can't convert '%.100s' object to str implicitly", - Py_TYPE(obj)->tp_name); - return NULL; -} - -PyObject * -PyUnicode_FromEncodedObject(PyObject *obj, - const char *encoding, - const char *errors) -{ - Py_buffer buffer; - PyObject *v; - - if (obj == NULL) { - PyErr_BadInternalCall(); - return NULL; - } - - /* Decoding bytes objects is the most common case and should be fast */ - if (PyBytes_Check(obj)) { - if (PyBytes_GET_SIZE(obj) == 0) - _Py_RETURN_UNICODE_EMPTY(); - v = PyUnicode_Decode( - PyBytes_AS_STRING(obj), PyBytes_GET_SIZE(obj), - encoding, errors); - return v; - } - - if (PyUnicode_Check(obj)) { - PyErr_SetString(PyExc_TypeError, - "decoding str is not supported"); - return NULL; - } - - /* Retrieve a bytes buffer view through the PEP 3118 buffer interface */ - if (PyObject_GetBuffer(obj, &buffer, PyBUF_SIMPLE) < 0) { - PyErr_Format(PyExc_TypeError, - "coercing to str: need a bytes-like object, %.80s found", - Py_TYPE(obj)->tp_name); - return NULL; - } - - if (buffer.len == 0) { - PyBuffer_Release(&buffer); - _Py_RETURN_UNICODE_EMPTY(); - } - - v = PyUnicode_Decode((char*) buffer.buf, buffer.len, encoding, errors); - PyBuffer_Release(&buffer); - return v; -} - -/* Convert encoding to lower case and replace '_' with '-' in order to - catch e.g. UTF_8. Return 0 on error (encoding is longer than lower_len-1), - 1 on success. */ -int -_Py_normalize_encoding(const char *encoding, - char *lower, - size_t lower_len) -{ - const char *e; - char *l; - char *l_end; - - if (encoding == NULL) { - /* 6 == strlen("utf-8") + 1 */ - if (lower_len < 6) - return 0; - strcpy(lower, "utf-8"); - return 1; - } - e = encoding; - l = lower; - l_end = &lower[lower_len - 1]; - while (*e) { - if (l == l_end) - return 0; - if (Py_ISUPPER(*e)) { - *l++ = Py_TOLOWER(*e++); - } - else if (*e == '_') { - *l++ = '-'; - e++; - } - else { - *l++ = *e++; - } - } - *l = '\0'; - return 1; -} - -PyObject * -PyUnicode_Decode(const char *s, - Py_ssize_t size, - const char *encoding, - const char *errors) -{ - PyObject *buffer = NULL, *unicode; - Py_buffer info; - char lower[11]; /* Enough for any encoding shortcut */ - - /* Shortcuts for common default encodings */ - if (_Py_normalize_encoding(encoding, lower, sizeof(lower))) { - if ((strcmp(lower, "utf-8") == 0) || - (strcmp(lower, "utf8") == 0)) - return PyUnicode_DecodeUTF8Stateful(s, size, errors, NULL); - else if ((strcmp(lower, "latin-1") == 0) || - (strcmp(lower, "latin1") == 0) || - (strcmp(lower, "iso-8859-1") == 0) || - (strcmp(lower, "iso8859-1") == 0)) - return PyUnicode_DecodeLatin1(s, size, errors); -#ifdef HAVE_MBCS - else if (strcmp(lower, "mbcs") == 0) - return PyUnicode_DecodeMBCS(s, size, errors); -#endif - else if (strcmp(lower, "ascii") == 0) - return PyUnicode_DecodeASCII(s, size, errors); - else if (strcmp(lower, "utf-16") == 0) - return PyUnicode_DecodeUTF16(s, size, errors, 0); - else if (strcmp(lower, "utf-32") == 0) - return PyUnicode_DecodeUTF32(s, size, errors, 0); - } - - /* Decode via the codec registry */ - buffer = NULL; - if (PyBuffer_FillInfo(&info, NULL, (void *)s, size, 1, PyBUF_FULL_RO) < 0) - goto onError; - buffer = PyMemoryView_FromBuffer(&info); - if (buffer == NULL) - goto onError; - unicode = _PyCodec_DecodeText(buffer, encoding, errors); - if (unicode == NULL) - goto onError; - if (!PyUnicode_Check(unicode)) { - PyErr_Format(PyExc_TypeError, - "'%.400s' decoder returned '%.400s' instead of 'str'; " - "use codecs.decode() to decode to arbitrary types", - encoding, - Py_TYPE(unicode)->tp_name, Py_TYPE(unicode)->tp_name); - Py_DECREF(unicode); - goto onError; - } - Py_DECREF(buffer); - return unicode_result(unicode); - - onError: - Py_XDECREF(buffer); - return NULL; -} - -PyObject * -PyUnicode_AsDecodedObject(PyObject *unicode, - const char *encoding, - const char *errors) -{ - PyObject *v; - - if (!PyUnicode_Check(unicode)) { - PyErr_BadArgument(); - goto onError; - } - - if (encoding == NULL) - encoding = PyUnicode_GetDefaultEncoding(); - - /* Decode via the codec registry */ - v = PyCodec_Decode(unicode, encoding, errors); - if (v == NULL) - goto onError; - return unicode_result(v); - - onError: - return NULL; -} - -PyObject * -PyUnicode_AsDecodedUnicode(PyObject *unicode, - const char *encoding, - const char *errors) -{ - PyObject *v; - - if (!PyUnicode_Check(unicode)) { - PyErr_BadArgument(); - goto onError; - } - - if (encoding == NULL) - encoding = PyUnicode_GetDefaultEncoding(); - - /* Decode via the codec registry */ - v = PyCodec_Decode(unicode, encoding, errors); - if (v == NULL) - goto onError; - if (!PyUnicode_Check(v)) { - PyErr_Format(PyExc_TypeError, - "'%.400s' decoder returned '%.400s' instead of 'str'; " - "use codecs.decode() to decode to arbitrary types", - encoding, - Py_TYPE(unicode)->tp_name, Py_TYPE(unicode)->tp_name); - Py_DECREF(v); - goto onError; - } - return unicode_result(v); - - onError: - return NULL; -} - -PyObject * -PyUnicode_Encode(const Py_UNICODE *s, - Py_ssize_t size, - const char *encoding, - const char *errors) -{ - PyObject *v, *unicode; - - unicode = PyUnicode_FromUnicode(s, size); - if (unicode == NULL) - return NULL; - v = PyUnicode_AsEncodedString(unicode, encoding, errors); - Py_DECREF(unicode); - return v; -} - -PyObject * -PyUnicode_AsEncodedObject(PyObject *unicode, - const char *encoding, - const char *errors) -{ - PyObject *v; - - if (!PyUnicode_Check(unicode)) { - PyErr_BadArgument(); - goto onError; - } - - if (encoding == NULL) - encoding = PyUnicode_GetDefaultEncoding(); - - /* Encode via the codec registry */ - v = PyCodec_Encode(unicode, encoding, errors); - if (v == NULL) - goto onError; - return v; - - onError: - return NULL; -} - -static size_t -wcstombs_errorpos(const wchar_t *wstr) -{ - size_t len; -#if SIZEOF_WCHAR_T == 2 - wchar_t buf[3]; -#else - wchar_t buf[2]; -#endif - char outbuf[MB_LEN_MAX]; - const wchar_t *start, *previous; - -#if SIZEOF_WCHAR_T == 2 - buf[2] = 0; -#else - buf[1] = 0; -#endif - start = wstr; - while (*wstr != L'\0') - { - previous = wstr; -#if SIZEOF_WCHAR_T == 2 - if (Py_UNICODE_IS_HIGH_SURROGATE(wstr[0]) - && Py_UNICODE_IS_LOW_SURROGATE(wstr[1])) - { - buf[0] = wstr[0]; - buf[1] = wstr[1]; - wstr += 2; - } - else { - buf[0] = *wstr; - buf[1] = 0; - wstr++; - } -#else - buf[0] = *wstr; - wstr++; -#endif - len = wcstombs(outbuf, buf, sizeof(outbuf)); - if (len == (size_t)-1) - return previous - start; - } - - /* failed to find the unencodable character */ - return 0; -} - -static int -locale_error_handler(const char *errors, int *surrogateescape) -{ - if (errors == NULL) { - *surrogateescape = 0; - return 0; - } - - if (strcmp(errors, "strict") == 0) { - *surrogateescape = 0; - return 0; - } - if (strcmp(errors, "surrogateescape") == 0) { - *surrogateescape = 1; - return 0; - } - PyErr_Format(PyExc_ValueError, - "only 'strict' and 'surrogateescape' error handlers " - "are supported, not '%s'", - errors); - return -1; -} - -PyObject * -PyUnicode_EncodeLocale(PyObject *unicode, const char *errors) -{ - Py_ssize_t wlen, wlen2; - wchar_t *wstr; - PyObject *bytes = NULL; - char *errmsg; - PyObject *reason = NULL; - PyObject *exc; - size_t error_pos; - int surrogateescape; - - if (locale_error_handler(errors, &surrogateescape) < 0) - return NULL; - - wstr = PyUnicode_AsWideCharString(unicode, &wlen); - if (wstr == NULL) - return NULL; - - wlen2 = wcslen(wstr); - if (wlen2 != wlen) { - PyMem_Free(wstr); - PyErr_SetString(PyExc_ValueError, "embedded null character"); - return NULL; - } - - if (surrogateescape) { - /* "surrogateescape" error handler */ - char *str; - - str = Py_EncodeLocale(wstr, &error_pos); - if (str == NULL) { - if (error_pos == (size_t)-1) { - PyErr_NoMemory(); - PyMem_Free(wstr); - return NULL; - } - else { - goto encode_error; - } - } - PyMem_Free(wstr); - - bytes = PyBytes_FromString(str); - PyMem_Free(str); - } - else { - /* strict mode */ - size_t len, len2; - - len = wcstombs(NULL, wstr, 0); - if (len == (size_t)-1) { - error_pos = (size_t)-1; - goto encode_error; - } - - bytes = PyBytes_FromStringAndSize(NULL, len); - if (bytes == NULL) { - PyMem_Free(wstr); - return NULL; - } - - len2 = wcstombs(PyBytes_AS_STRING(bytes), wstr, len+1); - if (len2 == (size_t)-1 || len2 > len) { - error_pos = (size_t)-1; - goto encode_error; - } - PyMem_Free(wstr); - } - return bytes; - -encode_error: - errmsg = strerror(errno); - assert(errmsg != NULL); - - if (error_pos == (size_t)-1) - error_pos = wcstombs_errorpos(wstr); - - PyMem_Free(wstr); - Py_XDECREF(bytes); - - if (errmsg != NULL) { - size_t errlen; - wstr = Py_DecodeLocale(errmsg, &errlen); - if (wstr != NULL) { - reason = PyUnicode_FromWideChar(wstr, errlen); - PyMem_RawFree(wstr); - } else - errmsg = NULL; - } - if (errmsg == NULL) - reason = PyUnicode_FromString( - "wcstombs() encountered an unencodable " - "wide character"); - if (reason == NULL) - return NULL; - - exc = PyObject_CallFunction(PyExc_UnicodeEncodeError, "sOnnO", - "locale", unicode, - (Py_ssize_t)error_pos, - (Py_ssize_t)(error_pos+1), - reason); - Py_DECREF(reason); - if (exc != NULL) { - PyCodec_StrictErrors(exc); - Py_XDECREF(exc); - } - return NULL; -} - -PyObject * -PyUnicode_EncodeFSDefault(PyObject *unicode) -{ -#ifdef HAVE_MBCS - return PyUnicode_EncodeCodePage(CP_ACP, unicode, NULL); -#elif defined(__APPLE__) - return _PyUnicode_AsUTF8String(unicode, "surrogateescape"); -#else - PyInterpreterState *interp = PyThreadState_GET()->interp; - /* Bootstrap check: if the filesystem codec is implemented in Python, we - cannot use it to encode and decode filenames before it is loaded. Load - the Python codec requires to encode at least its own filename. Use the C - version of the locale codec until the codec registry is initialized and - the Python codec is loaded. - - Py_FileSystemDefaultEncoding is shared between all interpreters, we - cannot only rely on it: check also interp->fscodec_initialized for - subinterpreters. */ - if (Py_FileSystemDefaultEncoding && interp->fscodec_initialized) { - return PyUnicode_AsEncodedString(unicode, - Py_FileSystemDefaultEncoding, - "surrogateescape"); - } - else { - return PyUnicode_EncodeLocale(unicode, "surrogateescape"); - } -#endif -} - -PyObject * -PyUnicode_AsEncodedString(PyObject *unicode, - const char *encoding, - const char *errors) -{ - PyObject *v; - char lower[11]; /* Enough for any encoding shortcut */ - - if (!PyUnicode_Check(unicode)) { - PyErr_BadArgument(); - return NULL; - } - - /* Shortcuts for common default encodings */ - if (_Py_normalize_encoding(encoding, lower, sizeof(lower))) { - if ((strcmp(lower, "utf-8") == 0) || - (strcmp(lower, "utf8") == 0)) - { - if (errors == NULL || strcmp(errors, "strict") == 0) - return _PyUnicode_AsUTF8String(unicode, NULL); - else - return _PyUnicode_AsUTF8String(unicode, errors); - } - else if ((strcmp(lower, "latin-1") == 0) || - (strcmp(lower, "latin1") == 0) || - (strcmp(lower, "iso-8859-1") == 0) || - (strcmp(lower, "iso8859-1") == 0)) - return _PyUnicode_AsLatin1String(unicode, errors); -#ifdef HAVE_MBCS - else if (strcmp(lower, "mbcs") == 0) - return PyUnicode_EncodeCodePage(CP_ACP, unicode, errors); -#endif - else if (strcmp(lower, "ascii") == 0) - return _PyUnicode_AsASCIIString(unicode, errors); - } - - /* Encode via the codec registry */ - v = _PyCodec_EncodeText(unicode, encoding, errors); - if (v == NULL) - return NULL; - - /* The normal path */ - if (PyBytes_Check(v)) - return v; - - /* If the codec returns a buffer, raise a warning and convert to bytes */ - if (PyByteArray_Check(v)) { - int error; - PyObject *b; - - error = PyErr_WarnFormat(PyExc_RuntimeWarning, 1, - "encoder %s returned bytearray instead of bytes; " - "use codecs.encode() to encode to arbitrary types", - encoding); - if (error) { - Py_DECREF(v); - return NULL; - } - - b = PyBytes_FromStringAndSize(PyByteArray_AS_STRING(v), Py_SIZE(v)); - Py_DECREF(v); - return b; - } - - PyErr_Format(PyExc_TypeError, - "'%.400s' encoder returned '%.400s' instead of 'bytes'; " - "use codecs.encode() to encode to arbitrary types", - encoding, - Py_TYPE(v)->tp_name, Py_TYPE(v)->tp_name); - Py_DECREF(v); - return NULL; -} - -PyObject * -PyUnicode_AsEncodedUnicode(PyObject *unicode, - const char *encoding, - const char *errors) -{ - PyObject *v; - - if (!PyUnicode_Check(unicode)) { - PyErr_BadArgument(); - goto onError; - } - - if (encoding == NULL) - encoding = PyUnicode_GetDefaultEncoding(); - - /* Encode via the codec registry */ - v = PyCodec_Encode(unicode, encoding, errors); - if (v == NULL) - goto onError; - if (!PyUnicode_Check(v)) { - PyErr_Format(PyExc_TypeError, - "'%.400s' encoder returned '%.400s' instead of 'str'; " - "use codecs.encode() to encode to arbitrary types", - encoding, - Py_TYPE(v)->tp_name, Py_TYPE(v)->tp_name); - Py_DECREF(v); - goto onError; - } - return v; - - onError: - return NULL; -} - -static size_t -mbstowcs_errorpos(const char *str, size_t len) -{ -#ifdef HAVE_MBRTOWC - const char *start = str; - mbstate_t mbs; - size_t converted; - wchar_t ch; - - memset(&mbs, 0, sizeof mbs); - while (len) - { - converted = mbrtowc(&ch, str, len, &mbs); - if (converted == 0) - /* Reached end of string */ - break; - if (converted == (size_t)-1 || converted == (size_t)-2) { - /* Conversion error or incomplete character */ - return str - start; - } - else { - str += converted; - len -= converted; - } - } - /* failed to find the undecodable byte sequence */ - return 0; -#endif - return 0; -} - -PyObject* -PyUnicode_DecodeLocaleAndSize(const char *str, Py_ssize_t len, - const char *errors) -{ - wchar_t smallbuf[256]; - size_t smallbuf_len = Py_ARRAY_LENGTH(smallbuf); - wchar_t *wstr; - size_t wlen, wlen2; - PyObject *unicode; - int surrogateescape; - size_t error_pos; - char *errmsg; - PyObject *reason = NULL; /* initialize to prevent gcc warning */ - PyObject *exc; - - if (locale_error_handler(errors, &surrogateescape) < 0) - return NULL; - - if (str[len] != '\0' || (size_t)len != strlen(str)) { - PyErr_SetString(PyExc_ValueError, "embedded null byte"); - return NULL; - } - - if (surrogateescape) { - /* "surrogateescape" error handler */ - wstr = Py_DecodeLocale(str, &wlen); - if (wstr == NULL) { - if (wlen == (size_t)-1) - PyErr_NoMemory(); - else - PyErr_SetFromErrno(PyExc_OSError); - return NULL; - } - - unicode = PyUnicode_FromWideChar(wstr, wlen); - PyMem_RawFree(wstr); - } - else { - /* strict mode */ -#ifndef HAVE_BROKEN_MBSTOWCS - wlen = mbstowcs(NULL, str, 0); -#else - wlen = len; -#endif - if (wlen == (size_t)-1) - goto decode_error; - if (wlen+1 <= smallbuf_len) { - wstr = smallbuf; - } - else { - wstr = PyMem_New(wchar_t, wlen+1); - if (!wstr) - return PyErr_NoMemory(); - } - - wlen2 = mbstowcs(wstr, str, wlen+1); - if (wlen2 == (size_t)-1) { - if (wstr != smallbuf) - PyMem_Free(wstr); - goto decode_error; - } -#ifdef HAVE_BROKEN_MBSTOWCS - assert(wlen2 == wlen); -#endif - unicode = PyUnicode_FromWideChar(wstr, wlen2); - if (wstr != smallbuf) - PyMem_Free(wstr); - } - return unicode; - -decode_error: - errmsg = strerror(errno); - assert(errmsg != NULL); - - error_pos = mbstowcs_errorpos(str, len); - if (errmsg != NULL) { - size_t errlen; - wstr = Py_DecodeLocale(errmsg, &errlen); - if (wstr != NULL) { - reason = PyUnicode_FromWideChar(wstr, errlen); - PyMem_RawFree(wstr); - } else - errmsg = NULL; - } - if (errmsg == NULL) - reason = PyUnicode_FromString( - "mbstowcs() encountered an invalid multibyte sequence"); - if (reason == NULL) - return NULL; - - exc = PyObject_CallFunction(PyExc_UnicodeDecodeError, "sy#nnO", - "locale", str, len, - (Py_ssize_t)error_pos, - (Py_ssize_t)(error_pos+1), - reason); - Py_DECREF(reason); - if (exc != NULL) { - PyCodec_StrictErrors(exc); - Py_XDECREF(exc); - } - return NULL; -} - -PyObject* -PyUnicode_DecodeLocale(const char *str, const char *errors) -{ - Py_ssize_t size = (Py_ssize_t)strlen(str); - return PyUnicode_DecodeLocaleAndSize(str, size, errors); -} - - -PyObject* -PyUnicode_DecodeFSDefault(const char *s) { - Py_ssize_t size = (Py_ssize_t)strlen(s); - return PyUnicode_DecodeFSDefaultAndSize(s, size); -} - -PyObject* -PyUnicode_DecodeFSDefaultAndSize(const char *s, Py_ssize_t size) -{ -#ifdef HAVE_MBCS - return PyUnicode_DecodeMBCS(s, size, NULL); -#elif defined(__APPLE__) - return PyUnicode_DecodeUTF8Stateful(s, size, "surrogateescape", NULL); -#else - PyInterpreterState *interp = PyThreadState_GET()->interp; - /* Bootstrap check: if the filesystem codec is implemented in Python, we - cannot use it to encode and decode filenames before it is loaded. Load - the Python codec requires to encode at least its own filename. Use the C - version of the locale codec until the codec registry is initialized and - the Python codec is loaded. - - Py_FileSystemDefaultEncoding is shared between all interpreters, we - cannot only rely on it: check also interp->fscodec_initialized for - subinterpreters. */ - if (Py_FileSystemDefaultEncoding && interp->fscodec_initialized) { - return PyUnicode_Decode(s, size, - Py_FileSystemDefaultEncoding, - "surrogateescape"); - } - else { - return PyUnicode_DecodeLocaleAndSize(s, size, "surrogateescape"); - } -#endif -} - - -int -_PyUnicode_HasNULChars(PyObject* str) -{ - Py_ssize_t pos; - - if (PyUnicode_READY(str) == -1) - return -1; - pos = findchar(PyUnicode_DATA(str), PyUnicode_KIND(str), - PyUnicode_GET_LENGTH(str), '\0', 1); - if (pos == -1) - return 0; - else - return 1; -} - -int -PyUnicode_FSConverter(PyObject* arg, void* addr) -{ - PyObject *output = NULL; - Py_ssize_t size; - void *data; - if (arg == NULL) { - Py_DECREF(*(PyObject**)addr); - return 1; - } - if (PyBytes_Check(arg)) { - output = arg; - Py_INCREF(output); - } - else { - arg = PyUnicode_FromObject(arg); - if (!arg) - return 0; - output = PyUnicode_EncodeFSDefault(arg); - Py_DECREF(arg); - if (!output) - return 0; - if (!PyBytes_Check(output)) { - Py_DECREF(output); - PyErr_SetString(PyExc_TypeError, "encoder failed to return bytes"); - return 0; - } - } - size = PyBytes_GET_SIZE(output); - data = PyBytes_AS_STRING(output); - if ((size_t)size != strlen(data)) { - PyErr_SetString(PyExc_ValueError, "embedded null byte"); - Py_DECREF(output); - return 0; - } - *(PyObject**)addr = output; - return Py_CLEANUP_SUPPORTED; -} - - -int -PyUnicode_FSDecoder(PyObject* arg, void* addr) -{ - PyObject *output = NULL; - if (arg == NULL) { - Py_DECREF(*(PyObject**)addr); - return 1; - } - if (PyUnicode_Check(arg)) { - if (PyUnicode_READY(arg) == -1) - return 0; - output = arg; - Py_INCREF(output); - } - else { - arg = PyBytes_FromObject(arg); - if (!arg) - return 0; - output = PyUnicode_DecodeFSDefaultAndSize(PyBytes_AS_STRING(arg), - PyBytes_GET_SIZE(arg)); - Py_DECREF(arg); - if (!output) - return 0; - if (!PyUnicode_Check(output)) { - Py_DECREF(output); - PyErr_SetString(PyExc_TypeError, "decoder failed to return unicode"); - return 0; - } - } - if (PyUnicode_READY(output) == -1) { - Py_DECREF(output); - return 0; - } - if (findchar(PyUnicode_DATA(output), PyUnicode_KIND(output), - PyUnicode_GET_LENGTH(output), 0, 1) >= 0) { - PyErr_SetString(PyExc_ValueError, "embedded null character"); - Py_DECREF(output); - return 0; - } - *(PyObject**)addr = output; - return Py_CLEANUP_SUPPORTED; -} - - -char* -PyUnicode_AsUTF8AndSize(PyObject *unicode, Py_ssize_t *psize) -{ - PyObject *bytes; - - if (!PyUnicode_Check(unicode)) { - PyErr_BadArgument(); - return NULL; - } - if (PyUnicode_READY(unicode) == -1) - return NULL; - - if (PyUnicode_UTF8(unicode) == NULL) { - assert(!PyUnicode_IS_COMPACT_ASCII(unicode)); - bytes = _PyUnicode_AsUTF8String(unicode, "strict"); - if (bytes == NULL) - return NULL; - _PyUnicode_UTF8(unicode) = PyObject_MALLOC(PyBytes_GET_SIZE(bytes) + 1); - if (_PyUnicode_UTF8(unicode) == NULL) { - PyErr_NoMemory(); - Py_DECREF(bytes); - return NULL; - } - _PyUnicode_UTF8_LENGTH(unicode) = PyBytes_GET_SIZE(bytes); - Py_MEMCPY(_PyUnicode_UTF8(unicode), - PyBytes_AS_STRING(bytes), - _PyUnicode_UTF8_LENGTH(unicode) + 1); - Py_DECREF(bytes); - } - - if (psize) - *psize = PyUnicode_UTF8_LENGTH(unicode); - return PyUnicode_UTF8(unicode); -} - -char* -PyUnicode_AsUTF8(PyObject *unicode) -{ - return PyUnicode_AsUTF8AndSize(unicode, NULL); -} - -Py_UNICODE * -PyUnicode_AsUnicodeAndSize(PyObject *unicode, Py_ssize_t *size) -{ - const unsigned char *one_byte; -#if SIZEOF_WCHAR_T == 4 - const Py_UCS2 *two_bytes; -#else - const Py_UCS4 *four_bytes; - const Py_UCS4 *ucs4_end; - Py_ssize_t num_surrogates; -#endif - wchar_t *w; - wchar_t *wchar_end; - - if (!PyUnicode_Check(unicode)) { - PyErr_BadArgument(); - return NULL; - } - if (_PyUnicode_WSTR(unicode) == NULL) { - /* Non-ASCII compact unicode object */ - assert(_PyUnicode_KIND(unicode) != 0); - assert(PyUnicode_IS_READY(unicode)); - - if (PyUnicode_KIND(unicode) == PyUnicode_4BYTE_KIND) { -#if SIZEOF_WCHAR_T == 2 - four_bytes = PyUnicode_4BYTE_DATA(unicode); - ucs4_end = four_bytes + _PyUnicode_LENGTH(unicode); - num_surrogates = 0; - - for (; four_bytes < ucs4_end; ++four_bytes) { - if (*four_bytes > 0xFFFF) - ++num_surrogates; - } - - _PyUnicode_WSTR(unicode) = (wchar_t *) PyObject_MALLOC( - sizeof(wchar_t) * (_PyUnicode_LENGTH(unicode) + 1 + num_surrogates)); - if (!_PyUnicode_WSTR(unicode)) { - PyErr_NoMemory(); - return NULL; - } - _PyUnicode_WSTR_LENGTH(unicode) = _PyUnicode_LENGTH(unicode) + num_surrogates; - - w = _PyUnicode_WSTR(unicode); - wchar_end = w + _PyUnicode_WSTR_LENGTH(unicode); - four_bytes = PyUnicode_4BYTE_DATA(unicode); - for (; four_bytes < ucs4_end; ++four_bytes, ++w) { - if (*four_bytes > 0xFFFF) { - assert(*four_bytes <= MAX_UNICODE); - /* encode surrogate pair in this case */ - *w++ = Py_UNICODE_HIGH_SURROGATE(*four_bytes); - *w = Py_UNICODE_LOW_SURROGATE(*four_bytes); - } - else - *w = *four_bytes; - - if (w > wchar_end) { - assert(0 && "Miscalculated string end"); - } - } - *w = 0; -#else - /* sizeof(wchar_t) == 4 */ - Py_FatalError("Impossible unicode object state, wstr and str " - "should share memory already."); - return NULL; -#endif - } - else { - if ((size_t)_PyUnicode_LENGTH(unicode) > - PY_SSIZE_T_MAX / sizeof(wchar_t) - 1) { - PyErr_NoMemory(); - return NULL; - } - _PyUnicode_WSTR(unicode) = (wchar_t *) PyObject_MALLOC(sizeof(wchar_t) * - (_PyUnicode_LENGTH(unicode) + 1)); - if (!_PyUnicode_WSTR(unicode)) { - PyErr_NoMemory(); - return NULL; - } - if (!PyUnicode_IS_COMPACT_ASCII(unicode)) - _PyUnicode_WSTR_LENGTH(unicode) = _PyUnicode_LENGTH(unicode); - w = _PyUnicode_WSTR(unicode); - wchar_end = w + _PyUnicode_LENGTH(unicode); - - if (PyUnicode_KIND(unicode) == PyUnicode_1BYTE_KIND) { - one_byte = PyUnicode_1BYTE_DATA(unicode); - for (; w < wchar_end; ++one_byte, ++w) - *w = *one_byte; - /* null-terminate the wstr */ - *w = 0; - } - else if (PyUnicode_KIND(unicode) == PyUnicode_2BYTE_KIND) { -#if SIZEOF_WCHAR_T == 4 - two_bytes = PyUnicode_2BYTE_DATA(unicode); - for (; w < wchar_end; ++two_bytes, ++w) - *w = *two_bytes; - /* null-terminate the wstr */ - *w = 0; -#else - /* sizeof(wchar_t) == 2 */ - PyObject_FREE(_PyUnicode_WSTR(unicode)); - _PyUnicode_WSTR(unicode) = NULL; - Py_FatalError("Impossible unicode object state, wstr " - "and str should share memory already."); - return NULL; -#endif - } - else { - assert(0 && "This should never happen."); - } - } - } - if (size != NULL) - *size = PyUnicode_WSTR_LENGTH(unicode); - return _PyUnicode_WSTR(unicode); -} - -Py_UNICODE * -PyUnicode_AsUnicode(PyObject *unicode) -{ - return PyUnicode_AsUnicodeAndSize(unicode, NULL); -} - - -Py_ssize_t -PyUnicode_GetSize(PyObject *unicode) -{ - if (!PyUnicode_Check(unicode)) { - PyErr_BadArgument(); - goto onError; - } - return PyUnicode_GET_SIZE(unicode); - - onError: - return -1; -} - -Py_ssize_t -PyUnicode_GetLength(PyObject *unicode) -{ - if (!PyUnicode_Check(unicode)) { - PyErr_BadArgument(); - return -1; - } - if (PyUnicode_READY(unicode) == -1) - return -1; - return PyUnicode_GET_LENGTH(unicode); -} - -Py_UCS4 -PyUnicode_ReadChar(PyObject *unicode, Py_ssize_t index) -{ - void *data; - int kind; - - if (!PyUnicode_Check(unicode) || PyUnicode_READY(unicode) == -1) { - PyErr_BadArgument(); - return (Py_UCS4)-1; - } - if (index < 0 || index >= PyUnicode_GET_LENGTH(unicode)) { - PyErr_SetString(PyExc_IndexError, "string index out of range"); - return (Py_UCS4)-1; - } - data = PyUnicode_DATA(unicode); - kind = PyUnicode_KIND(unicode); - return PyUnicode_READ(kind, data, index); -} - -int -PyUnicode_WriteChar(PyObject *unicode, Py_ssize_t index, Py_UCS4 ch) -{ - if (!PyUnicode_Check(unicode) || !PyUnicode_IS_COMPACT(unicode)) { - PyErr_BadArgument(); - return -1; - } - assert(PyUnicode_IS_READY(unicode)); - if (index < 0 || index >= PyUnicode_GET_LENGTH(unicode)) { - PyErr_SetString(PyExc_IndexError, "string index out of range"); - return -1; - } - if (unicode_check_modifiable(unicode)) - return -1; - if (ch > PyUnicode_MAX_CHAR_VALUE(unicode)) { - PyErr_SetString(PyExc_ValueError, "character out of range"); - return -1; - } - PyUnicode_WRITE(PyUnicode_KIND(unicode), PyUnicode_DATA(unicode), - index, ch); - return 0; -} - -const char * -PyUnicode_GetDefaultEncoding(void) -{ - return "utf-8"; -} - -/* create or adjust a UnicodeDecodeError */ -static void -make_decode_exception(PyObject **exceptionObject, - const char *encoding, - const char *input, Py_ssize_t length, - Py_ssize_t startpos, Py_ssize_t endpos, - const char *reason) -{ - if (*exceptionObject == NULL) { - *exceptionObject = PyUnicodeDecodeError_Create( - encoding, input, length, startpos, endpos, reason); - } - else { - if (PyUnicodeDecodeError_SetStart(*exceptionObject, startpos)) - goto onError; - if (PyUnicodeDecodeError_SetEnd(*exceptionObject, endpos)) - goto onError; - if (PyUnicodeDecodeError_SetReason(*exceptionObject, reason)) - goto onError; - } - return; - -onError: - Py_CLEAR(*exceptionObject); -} - -#ifdef HAVE_MBCS -/* error handling callback helper: - build arguments, call the callback and check the arguments, - if no exception occurred, copy the replacement to the output - and adjust various state variables. - return 0 on success, -1 on error -*/ - -static int -unicode_decode_call_errorhandler_wchar( - const char *errors, PyObject **errorHandler, - const char *encoding, const char *reason, - const char **input, const char **inend, Py_ssize_t *startinpos, - Py_ssize_t *endinpos, PyObject **exceptionObject, const char **inptr, - PyObject **output, Py_ssize_t *outpos) -{ - static char *argparse = "O!n;decoding error handler must return (str, int) tuple"; - - PyObject *restuple = NULL; - PyObject *repunicode = NULL; - Py_ssize_t outsize; - Py_ssize_t insize; - Py_ssize_t requiredsize; - Py_ssize_t newpos; - PyObject *inputobj = NULL; - wchar_t *repwstr; - Py_ssize_t repwlen; - - assert (_PyUnicode_KIND(*output) == PyUnicode_WCHAR_KIND); - outsize = _PyUnicode_WSTR_LENGTH(*output); - - if (*errorHandler == NULL) { - *errorHandler = PyCodec_LookupError(errors); - if (*errorHandler == NULL) - goto onError; - } - - make_decode_exception(exceptionObject, - encoding, - *input, *inend - *input, - *startinpos, *endinpos, - reason); - if (*exceptionObject == NULL) - goto onError; - - restuple = PyObject_CallFunctionObjArgs(*errorHandler, *exceptionObject, NULL); - if (restuple == NULL) - goto onError; - if (!PyTuple_Check(restuple)) { - PyErr_SetString(PyExc_TypeError, &argparse[4]); - goto onError; - } - if (!PyArg_ParseTuple(restuple, argparse, &PyUnicode_Type, &repunicode, &newpos)) - goto onError; - - /* Copy back the bytes variables, which might have been modified by the - callback */ - inputobj = PyUnicodeDecodeError_GetObject(*exceptionObject); - if (!inputobj) - goto onError; - if (!PyBytes_Check(inputobj)) { - PyErr_Format(PyExc_TypeError, "exception attribute object must be bytes"); - } - *input = PyBytes_AS_STRING(inputobj); - insize = PyBytes_GET_SIZE(inputobj); - *inend = *input + insize; - /* we can DECREF safely, as the exception has another reference, - so the object won't go away. */ - Py_DECREF(inputobj); - - if (newpos<0) - newpos = insize+newpos; - if (newpos<0 || newpos>insize) { - PyErr_Format(PyExc_IndexError, "position %zd from error handler out of bounds", newpos); - goto onError; - } - - repwstr = PyUnicode_AsUnicodeAndSize(repunicode, &repwlen); - if (repwstr == NULL) - goto onError; - /* need more space? (at least enough for what we - have+the replacement+the rest of the string (starting - at the new input position), so we won't have to check space - when there are no errors in the rest of the string) */ - requiredsize = *outpos; - if (requiredsize > PY_SSIZE_T_MAX - repwlen) - goto overflow; - requiredsize += repwlen; - if (requiredsize > PY_SSIZE_T_MAX - (insize - newpos)) - goto overflow; - requiredsize += insize - newpos; - if (requiredsize > outsize) { - if (outsize <= PY_SSIZE_T_MAX/2 && requiredsize < 2*outsize) - requiredsize = 2*outsize; - if (unicode_resize(output, requiredsize) < 0) - goto onError; - } - wcsncpy(_PyUnicode_WSTR(*output) + *outpos, repwstr, repwlen); - *outpos += repwlen; - *endinpos = newpos; - *inptr = *input + newpos; - - /* we made it! */ - Py_XDECREF(restuple); - return 0; - - overflow: - PyErr_SetString(PyExc_OverflowError, - "decoded result is too long for a Python string"); - - onError: - Py_XDECREF(restuple); - return -1; -} -#endif /* HAVE_MBCS */ - -static int -unicode_decode_call_errorhandler_writer( - const char *errors, PyObject **errorHandler, - const char *encoding, const char *reason, - const char **input, const char **inend, Py_ssize_t *startinpos, - Py_ssize_t *endinpos, PyObject **exceptionObject, const char **inptr, - _PyUnicodeWriter *writer /* PyObject **output, Py_ssize_t *outpos */) -{ - static char *argparse = "O!n;decoding error handler must return (str, int) tuple"; - - PyObject *restuple = NULL; - PyObject *repunicode = NULL; - Py_ssize_t insize; - Py_ssize_t newpos; - Py_ssize_t replen; - PyObject *inputobj = NULL; - - if (*errorHandler == NULL) { - *errorHandler = PyCodec_LookupError(errors); - if (*errorHandler == NULL) - goto onError; - } - - make_decode_exception(exceptionObject, - encoding, - *input, *inend - *input, - *startinpos, *endinpos, - reason); - if (*exceptionObject == NULL) - goto onError; - - restuple = PyObject_CallFunctionObjArgs(*errorHandler, *exceptionObject, NULL); - if (restuple == NULL) - goto onError; - if (!PyTuple_Check(restuple)) { - PyErr_SetString(PyExc_TypeError, &argparse[4]); - goto onError; - } - if (!PyArg_ParseTuple(restuple, argparse, &PyUnicode_Type, &repunicode, &newpos)) - goto onError; - - /* Copy back the bytes variables, which might have been modified by the - callback */ - inputobj = PyUnicodeDecodeError_GetObject(*exceptionObject); - if (!inputobj) - goto onError; - if (!PyBytes_Check(inputobj)) { - PyErr_Format(PyExc_TypeError, "exception attribute object must be bytes"); - } - *input = PyBytes_AS_STRING(inputobj); - insize = PyBytes_GET_SIZE(inputobj); - *inend = *input + insize; - /* we can DECREF safely, as the exception has another reference, - so the object won't go away. */ - Py_DECREF(inputobj); - - if (newpos<0) - newpos = insize+newpos; - if (newpos<0 || newpos>insize) { - PyErr_Format(PyExc_IndexError, "position %zd from error handler out of bounds", newpos); - goto onError; - } - - if (PyUnicode_READY(repunicode) < 0) - goto onError; - replen = PyUnicode_GET_LENGTH(repunicode); - if (replen > 1) { - writer->min_length += replen - 1; - writer->overallocate = 1; - if (_PyUnicodeWriter_Prepare(writer, writer->min_length, - PyUnicode_MAX_CHAR_VALUE(repunicode)) == -1) - goto onError; - } - if (_PyUnicodeWriter_WriteStr(writer, repunicode) == -1) - goto onError; - - *endinpos = newpos; - *inptr = *input + newpos; - - /* we made it! */ - Py_XDECREF(restuple); - return 0; - - onError: - Py_XDECREF(restuple); - return -1; -} - -/* --- UTF-7 Codec -------------------------------------------------------- */ - -/* See RFC2152 for details. We encode conservatively and decode liberally. */ - -/* Three simple macros defining base-64. */ - -/* Is c a base-64 character? */ - -#define IS_BASE64(c) \ - (((c) >= 'A' && (c) <= 'Z') || \ - ((c) >= 'a' && (c) <= 'z') || \ - ((c) >= '0' && (c) <= '9') || \ - (c) == '+' || (c) == '/') - -/* given that c is a base-64 character, what is its base-64 value? */ - -#define FROM_BASE64(c) \ - (((c) >= 'A' && (c) <= 'Z') ? (c) - 'A' : \ - ((c) >= 'a' && (c) <= 'z') ? (c) - 'a' + 26 : \ - ((c) >= '0' && (c) <= '9') ? (c) - '0' + 52 : \ - (c) == '+' ? 62 : 63) - -/* What is the base-64 character of the bottom 6 bits of n? */ - -#define TO_BASE64(n) \ - ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[(n) & 0x3f]) - -/* DECODE_DIRECT: this byte encountered in a UTF-7 string should be - * decoded as itself. We are permissive on decoding; the only ASCII - * byte not decoding to itself is the + which begins a base64 - * string. */ - -#define DECODE_DIRECT(c) \ - ((c) <= 127 && (c) != '+') - -/* The UTF-7 encoder treats ASCII characters differently according to - * whether they are Set D, Set O, Whitespace, or special (i.e. none of - * the above). See RFC2152. This array identifies these different - * sets: - * 0 : "Set D" - * alphanumeric and '(),-./:? - * 1 : "Set O" - * !"#$%&*;<=>@[]^_`{|} - * 2 : "whitespace" - * ht nl cr sp - * 3 : special (must be base64 encoded) - * everything else (i.e. +\~ and non-printing codes 0-8 11-12 14-31 127) - */ - -static -char utf7_category[128] = { -/* nul soh stx etx eot enq ack bel bs ht nl vt np cr so si */ - 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 3, 3, 2, 3, 3, -/* dle dc1 dc2 dc3 dc4 nak syn etb can em sub esc fs gs rs us */ - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, -/* sp ! " # $ % & ' ( ) * + , - . / */ - 2, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 3, 0, 0, 0, 0, -/* 0 1 2 3 4 5 6 7 8 9 : ; < = > ? */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, -/* @ A B C D E F G H I J K L M N O */ - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/* P Q R S T U V W X Y Z [ \ ] ^ _ */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 3, 1, 1, 1, -/* ` a b c d e f g h i j k l m n o */ - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/* p q r s t u v w x y z { | } ~ del */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 3, 3, -}; - -/* ENCODE_DIRECT: this character should be encoded as itself. The - * answer depends on whether we are encoding set O as itself, and also - * on whether we are encoding whitespace as itself. RFC2152 makes it - * clear that the answers to these questions vary between - * applications, so this code needs to be flexible. */ - -#define ENCODE_DIRECT(c, directO, directWS) \ - ((c) < 128 && (c) > 0 && \ - ((utf7_category[(c)] == 0) || \ - (directWS && (utf7_category[(c)] == 2)) || \ - (directO && (utf7_category[(c)] == 1)))) - -PyObject * -PyUnicode_DecodeUTF7(const char *s, - Py_ssize_t size, - const char *errors) -{ - return PyUnicode_DecodeUTF7Stateful(s, size, errors, NULL); -} - -/* The decoder. The only state we preserve is our read position, - * i.e. how many characters we have consumed. So if we end in the - * middle of a shift sequence we have to back off the read position - * and the output to the beginning of the sequence, otherwise we lose - * all the shift state (seen bits, number of bits seen, high - * surrogate). */ - -PyObject * -PyUnicode_DecodeUTF7Stateful(const char *s, - Py_ssize_t size, - const char *errors, - Py_ssize_t *consumed) -{ - const char *starts = s; - Py_ssize_t startinpos; - Py_ssize_t endinpos; - const char *e; - _PyUnicodeWriter writer; - const char *errmsg = ""; - int inShift = 0; - Py_ssize_t shiftOutStart; - unsigned int base64bits = 0; - unsigned long base64buffer = 0; - Py_UCS4 surrogate = 0; - PyObject *errorHandler = NULL; - PyObject *exc = NULL; - - if (size == 0) { - if (consumed) - *consumed = 0; - _Py_RETURN_UNICODE_EMPTY(); - } - - /* Start off assuming it's all ASCII. Widen later as necessary. */ - _PyUnicodeWriter_Init(&writer); - writer.min_length = size; - - shiftOutStart = 0; - e = s + size; - - while (s < e) { - Py_UCS4 ch; - restart: - ch = (unsigned char) *s; - - if (inShift) { /* in a base-64 section */ - if (IS_BASE64(ch)) { /* consume a base-64 character */ - base64buffer = (base64buffer << 6) | FROM_BASE64(ch); - base64bits += 6; - s++; - if (base64bits >= 16) { - /* we have enough bits for a UTF-16 value */ - Py_UCS4 outCh = (Py_UCS4)(base64buffer >> (base64bits-16)); - base64bits -= 16; - base64buffer &= (1 << base64bits) - 1; /* clear high bits */ - assert(outCh <= 0xffff); - if (surrogate) { - /* expecting a second surrogate */ - if (Py_UNICODE_IS_LOW_SURROGATE(outCh)) { - Py_UCS4 ch2 = Py_UNICODE_JOIN_SURROGATES(surrogate, outCh); - if (_PyUnicodeWriter_WriteCharInline(&writer, ch2) < 0) - goto onError; - surrogate = 0; - continue; - } - else { - if (_PyUnicodeWriter_WriteCharInline(&writer, surrogate) < 0) - goto onError; - surrogate = 0; - } - } - if (Py_UNICODE_IS_HIGH_SURROGATE(outCh)) { - /* first surrogate */ - surrogate = outCh; - } - else { - if (_PyUnicodeWriter_WriteCharInline(&writer, outCh) < 0) - goto onError; - } - } - } - else { /* now leaving a base-64 section */ - inShift = 0; - s++; - if (surrogate) { - if (_PyUnicodeWriter_WriteCharInline(&writer, surrogate) < 0) - goto onError; - surrogate = 0; - } - if (base64bits > 0) { /* left-over bits */ - if (base64bits >= 6) { - /* We've seen at least one base-64 character */ - errmsg = "partial character in shift sequence"; - goto utf7Error; - } - else { - /* Some bits remain; they should be zero */ - if (base64buffer != 0) { - errmsg = "non-zero padding bits in shift sequence"; - goto utf7Error; - } - } - } - if (ch != '-') { - /* '-' is absorbed; other terminating - characters are preserved */ - if (_PyUnicodeWriter_WriteCharInline(&writer, ch) < 0) - goto onError; - } - } - } - else if ( ch == '+' ) { - startinpos = s-starts; - s++; /* consume '+' */ - if (s < e && *s == '-') { /* '+-' encodes '+' */ - s++; - if (_PyUnicodeWriter_WriteCharInline(&writer, '+') < 0) - goto onError; - } - else { /* begin base64-encoded section */ - inShift = 1; - shiftOutStart = writer.pos; - base64bits = 0; - base64buffer = 0; - } - } - else if (DECODE_DIRECT(ch)) { /* character decodes as itself */ - s++; - if (_PyUnicodeWriter_WriteCharInline(&writer, ch) < 0) - goto onError; - } - else { - startinpos = s-starts; - s++; - errmsg = "unexpected special character"; - goto utf7Error; - } - continue; -utf7Error: - endinpos = s-starts; - if (unicode_decode_call_errorhandler_writer( - errors, &errorHandler, - "utf7", errmsg, - &starts, &e, &startinpos, &endinpos, &exc, &s, - &writer)) - goto onError; - } - - /* end of string */ - - if (inShift && !consumed) { /* in shift sequence, no more to follow */ - /* if we're in an inconsistent state, that's an error */ - if (surrogate || - (base64bits >= 6) || - (base64bits > 0 && base64buffer != 0)) { - endinpos = size; - if (unicode_decode_call_errorhandler_writer( - errors, &errorHandler, - "utf7", "unterminated shift sequence", - &starts, &e, &startinpos, &endinpos, &exc, &s, - &writer)) - goto onError; - if (s < e) - goto restart; - } - } - - /* return state */ - if (consumed) { - if (inShift) { - *consumed = startinpos; - if (writer.pos != shiftOutStart && writer.maxchar > 127) { - PyObject *result = PyUnicode_FromKindAndData( - writer.kind, writer.data, shiftOutStart); - Py_XDECREF(errorHandler); - Py_XDECREF(exc); - _PyUnicodeWriter_Dealloc(&writer); - return result; - } - writer.pos = shiftOutStart; /* back off output */ - } - else { - *consumed = s-starts; - } - } - - Py_XDECREF(errorHandler); - Py_XDECREF(exc); - return _PyUnicodeWriter_Finish(&writer); - - onError: - Py_XDECREF(errorHandler); - Py_XDECREF(exc); - _PyUnicodeWriter_Dealloc(&writer); - return NULL; -} - - -PyObject * -_PyUnicode_EncodeUTF7(PyObject *str, - int base64SetO, - int base64WhiteSpace, - const char *errors) -{ - int kind; - void *data; - Py_ssize_t len; - PyObject *v; - int inShift = 0; - Py_ssize_t i; - unsigned int base64bits = 0; - unsigned long base64buffer = 0; - char * out; - char * start; - - if (PyUnicode_READY(str) == -1) - return NULL; - kind = PyUnicode_KIND(str); - data = PyUnicode_DATA(str); - len = PyUnicode_GET_LENGTH(str); - - if (len == 0) - return PyBytes_FromStringAndSize(NULL, 0); - - /* It might be possible to tighten this worst case */ - if (len > PY_SSIZE_T_MAX / 8) - return PyErr_NoMemory(); - v = PyBytes_FromStringAndSize(NULL, len * 8); - if (v == NULL) - return NULL; - - start = out = PyBytes_AS_STRING(v); - for (i = 0; i < len; ++i) { - Py_UCS4 ch = PyUnicode_READ(kind, data, i); - - if (inShift) { - if (ENCODE_DIRECT(ch, !base64SetO, !base64WhiteSpace)) { - /* shifting out */ - if (base64bits) { /* output remaining bits */ - *out++ = TO_BASE64(base64buffer << (6-base64bits)); - base64buffer = 0; - base64bits = 0; - } - inShift = 0; - /* Characters not in the BASE64 set implicitly unshift the sequence - so no '-' is required, except if the character is itself a '-' */ - if (IS_BASE64(ch) || ch == '-') { - *out++ = '-'; - } - *out++ = (char) ch; - } - else { - goto encode_char; - } - } - else { /* not in a shift sequence */ - if (ch == '+') { - *out++ = '+'; - *out++ = '-'; - } - else if (ENCODE_DIRECT(ch, !base64SetO, !base64WhiteSpace)) { - *out++ = (char) ch; - } - else { - *out++ = '+'; - inShift = 1; - goto encode_char; - } - } - continue; -encode_char: - if (ch >= 0x10000) { - assert(ch <= MAX_UNICODE); - - /* code first surrogate */ - base64bits += 16; - base64buffer = (base64buffer << 16) | Py_UNICODE_HIGH_SURROGATE(ch); - while (base64bits >= 6) { - *out++ = TO_BASE64(base64buffer >> (base64bits-6)); - base64bits -= 6; - } - /* prepare second surrogate */ - ch = Py_UNICODE_LOW_SURROGATE(ch); - } - base64bits += 16; - base64buffer = (base64buffer << 16) | ch; - while (base64bits >= 6) { - *out++ = TO_BASE64(base64buffer >> (base64bits-6)); - base64bits -= 6; - } - } - if (base64bits) - *out++= TO_BASE64(base64buffer << (6-base64bits) ); - if (inShift) - *out++ = '-'; - if (_PyBytes_Resize(&v, out - start) < 0) - return NULL; - return v; -} -PyObject * -PyUnicode_EncodeUTF7(const Py_UNICODE *s, - Py_ssize_t size, - int base64SetO, - int base64WhiteSpace, - const char *errors) -{ - PyObject *result; - PyObject *tmp = PyUnicode_FromUnicode(s, size); - if (tmp == NULL) - return NULL; - result = _PyUnicode_EncodeUTF7(tmp, base64SetO, - base64WhiteSpace, errors); - Py_DECREF(tmp); - return result; -} - -#undef IS_BASE64 -#undef FROM_BASE64 -#undef TO_BASE64 -#undef DECODE_DIRECT -#undef ENCODE_DIRECT - -/* --- UTF-8 Codec -------------------------------------------------------- */ - -PyObject * -PyUnicode_DecodeUTF8(const char *s, - Py_ssize_t size, - const char *errors) -{ - return PyUnicode_DecodeUTF8Stateful(s, size, errors, NULL); -} - -#include "stringlib/asciilib.h" -#include "stringlib/codecs.h" -#include "stringlib/undef.h" - -#include "stringlib/ucs1lib.h" -#include "stringlib/codecs.h" -#include "stringlib/undef.h" - -#include "stringlib/ucs2lib.h" -#include "stringlib/codecs.h" -#include "stringlib/undef.h" - -#include "stringlib/ucs4lib.h" -#include "stringlib/codecs.h" -#include "stringlib/undef.h" - -/* Mask to quickly check whether a C 'long' contains a - non-ASCII, UTF8-encoded char. */ -#if (SIZEOF_LONG == 8) -# define ASCII_CHAR_MASK 0x8080808080808080UL -#elif (SIZEOF_LONG == 4) -# define ASCII_CHAR_MASK 0x80808080UL -#else -# error C 'long' size should be either 4 or 8! -#endif - -static Py_ssize_t -ascii_decode(const char *start, const char *end, Py_UCS1 *dest) -{ - const char *p = start; - const char *aligned_end = (const char *) _Py_ALIGN_DOWN(end, SIZEOF_LONG); - - /* - * Issue #17237: m68k is a bit different from most architectures in - * that objects do not use "natural alignment" - for example, int and - * long are only aligned at 2-byte boundaries. Therefore the assert() - * won't work; also, tests have shown that skipping the "optimised - * version" will even speed up m68k. - */ -#if !defined(__m68k__) -#if SIZEOF_LONG <= SIZEOF_VOID_P - assert(_Py_IS_ALIGNED(dest, SIZEOF_LONG)); - if (_Py_IS_ALIGNED(p, SIZEOF_LONG)) { - /* Fast path, see in STRINGLIB(utf8_decode) for - an explanation. */ - /* Help allocation */ - const char *_p = p; - Py_UCS1 * q = dest; - while (_p < aligned_end) { - unsigned long value = *(const unsigned long *) _p; - if (value & ASCII_CHAR_MASK) - break; - *((unsigned long *)q) = value; - _p += SIZEOF_LONG; - q += SIZEOF_LONG; - } - p = _p; - while (p < end) { - if ((unsigned char)*p & 0x80) - break; - *q++ = *p++; - } - return p - start; - } -#endif -#endif - while (p < end) { - /* Fast path, see in STRINGLIB(utf8_decode) in stringlib/codecs.h - for an explanation. */ - if (_Py_IS_ALIGNED(p, SIZEOF_LONG)) { - /* Help allocation */ - const char *_p = p; - while (_p < aligned_end) { - unsigned long value = *(unsigned long *) _p; - if (value & ASCII_CHAR_MASK) - break; - _p += SIZEOF_LONG; - } - p = _p; - if (_p == end) - break; - } - if ((unsigned char)*p & 0x80) - break; - ++p; - } - memcpy(dest, start, p - start); - return p - start; -} - -PyObject * -PyUnicode_DecodeUTF8Stateful(const char *s, - Py_ssize_t size, - const char *errors, - Py_ssize_t *consumed) -{ - _PyUnicodeWriter writer; - const char *starts = s; - const char *end = s + size; - - Py_ssize_t startinpos; - Py_ssize_t endinpos; - const char *errmsg = ""; - PyObject *errorHandler = NULL; - PyObject *exc = NULL; - - if (size == 0) { - if (consumed) - *consumed = 0; - _Py_RETURN_UNICODE_EMPTY(); - } - - /* ASCII is equivalent to the first 128 ordinals in Unicode. */ - if (size == 1 && (unsigned char)s[0] < 128) { - if (consumed) - *consumed = 1; - return get_latin1_char((unsigned char)s[0]); - } - - _PyUnicodeWriter_Init(&writer); - writer.min_length = size; - if (_PyUnicodeWriter_Prepare(&writer, writer.min_length, 127) == -1) - goto onError; - - writer.pos = ascii_decode(s, end, writer.data); - s += writer.pos; - while (s < end) { - Py_UCS4 ch; - int kind = writer.kind; - if (kind == PyUnicode_1BYTE_KIND) { - if (PyUnicode_IS_ASCII(writer.buffer)) - ch = asciilib_utf8_decode(&s, end, writer.data, &writer.pos); - else - ch = ucs1lib_utf8_decode(&s, end, writer.data, &writer.pos); - } else if (kind == PyUnicode_2BYTE_KIND) { - ch = ucs2lib_utf8_decode(&s, end, writer.data, &writer.pos); - } else { - assert(kind == PyUnicode_4BYTE_KIND); - ch = ucs4lib_utf8_decode(&s, end, writer.data, &writer.pos); - } - - switch (ch) { - case 0: - if (s == end || consumed) - goto End; - errmsg = "unexpected end of data"; - startinpos = s - starts; - endinpos = end - starts; - break; - case 1: - errmsg = "invalid start byte"; - startinpos = s - starts; - endinpos = startinpos + 1; - break; - case 2: - case 3: - case 4: - errmsg = "invalid continuation byte"; - startinpos = s - starts; - endinpos = startinpos + ch - 1; - break; - default: - if (_PyUnicodeWriter_WriteCharInline(&writer, ch) < 0) - goto onError; - continue; - } - - if (unicode_decode_call_errorhandler_writer( - errors, &errorHandler, - "utf-8", errmsg, - &starts, &end, &startinpos, &endinpos, &exc, &s, - &writer)) - goto onError; - } - -End: - if (consumed) - *consumed = s - starts; - - Py_XDECREF(errorHandler); - Py_XDECREF(exc); - return _PyUnicodeWriter_Finish(&writer); - -onError: - Py_XDECREF(errorHandler); - Py_XDECREF(exc); - _PyUnicodeWriter_Dealloc(&writer); - return NULL; -} - -#ifdef __APPLE__ - -/* Simplified UTF-8 decoder using surrogateescape error handler, - used to decode the command line arguments on Mac OS X. - - Return a pointer to a newly allocated wide character string (use - PyMem_RawFree() to free the memory), or NULL on memory allocation error. */ - -wchar_t* -_Py_DecodeUTF8_surrogateescape(const char *s, Py_ssize_t size) -{ - const char *e; - wchar_t *unicode; - Py_ssize_t outpos; - - /* Note: size will always be longer than the resulting Unicode - character count */ - if (PY_SSIZE_T_MAX / (Py_ssize_t)sizeof(wchar_t) < (size + 1)) - return NULL; - unicode = PyMem_RawMalloc((size + 1) * sizeof(wchar_t)); - if (!unicode) - return NULL; - - /* Unpack UTF-8 encoded data */ - e = s + size; - outpos = 0; - while (s < e) { - Py_UCS4 ch; -#if SIZEOF_WCHAR_T == 4 - ch = ucs4lib_utf8_decode(&s, e, (Py_UCS4 *)unicode, &outpos); -#else - ch = ucs2lib_utf8_decode(&s, e, (Py_UCS2 *)unicode, &outpos); -#endif - if (ch > 0xFF) { -#if SIZEOF_WCHAR_T == 4 - assert(0); -#else - assert(Py_UNICODE_IS_SURROGATE(ch)); - /* compute and append the two surrogates: */ - unicode[outpos++] = (wchar_t)Py_UNICODE_HIGH_SURROGATE(ch); - unicode[outpos++] = (wchar_t)Py_UNICODE_LOW_SURROGATE(ch); -#endif - } - else { - if (!ch && s == e) - break; - /* surrogateescape */ - unicode[outpos++] = 0xDC00 + (unsigned char)*s++; - } - } - unicode[outpos] = L'\0'; - return unicode; -} - -#endif /* __APPLE__ */ - -/* Primary internal function which creates utf8 encoded bytes objects. - - Allocation strategy: if the string is short, convert into a stack buffer - and allocate exactly as much space needed at the end. Else allocate the - maximum possible needed (4 result bytes per Unicode character), and return - the excess memory at the end. -*/ -PyObject * -_PyUnicode_AsUTF8String(PyObject *unicode, const char *errors) -{ - enum PyUnicode_Kind kind; - void *data; - Py_ssize_t size; - - if (!PyUnicode_Check(unicode)) { - PyErr_BadArgument(); - return NULL; - } - - if (PyUnicode_READY(unicode) == -1) - return NULL; - - if (PyUnicode_UTF8(unicode)) - return PyBytes_FromStringAndSize(PyUnicode_UTF8(unicode), - PyUnicode_UTF8_LENGTH(unicode)); - - kind = PyUnicode_KIND(unicode); - data = PyUnicode_DATA(unicode); - size = PyUnicode_GET_LENGTH(unicode); - - switch (kind) { - default: - assert(0); - case PyUnicode_1BYTE_KIND: - /* the string cannot be ASCII, or PyUnicode_UTF8() would be set */ - assert(!PyUnicode_IS_ASCII(unicode)); - return ucs1lib_utf8_encoder(unicode, data, size, errors); - case PyUnicode_2BYTE_KIND: - return ucs2lib_utf8_encoder(unicode, data, size, errors); - case PyUnicode_4BYTE_KIND: - return ucs4lib_utf8_encoder(unicode, data, size, errors); - } -} - -PyObject * -PyUnicode_EncodeUTF8(const Py_UNICODE *s, - Py_ssize_t size, - const char *errors) -{ - PyObject *v, *unicode; - - unicode = PyUnicode_FromUnicode(s, size); - if (unicode == NULL) - return NULL; - v = _PyUnicode_AsUTF8String(unicode, errors); - Py_DECREF(unicode); - return v; -} - -PyObject * -PyUnicode_AsUTF8String(PyObject *unicode) -{ - return _PyUnicode_AsUTF8String(unicode, NULL); -} - -/* --- UTF-32 Codec ------------------------------------------------------- */ - -PyObject * -PyUnicode_DecodeUTF32(const char *s, - Py_ssize_t size, - const char *errors, - int *byteorder) -{ - return PyUnicode_DecodeUTF32Stateful(s, size, errors, byteorder, NULL); -} - -PyObject * -PyUnicode_DecodeUTF32Stateful(const char *s, - Py_ssize_t size, - const char *errors, - int *byteorder, - Py_ssize_t *consumed) -{ - const char *starts = s; - Py_ssize_t startinpos; - Py_ssize_t endinpos; - _PyUnicodeWriter writer; - const unsigned char *q, *e; - int le, bo = 0; /* assume native ordering by default */ - const char *encoding; - const char *errmsg = ""; - PyObject *errorHandler = NULL; - PyObject *exc = NULL; - - q = (unsigned char *)s; - e = q + size; - - if (byteorder) - bo = *byteorder; - - /* Check for BOM marks (U+FEFF) in the input and adjust current - byte order setting accordingly. In native mode, the leading BOM - mark is skipped, in all other modes, it is copied to the output - stream as-is (giving a ZWNBSP character). */ - if (bo == 0 && size >= 4) { - Py_UCS4 bom = (q[3] << 24) | (q[2] << 16) | (q[1] << 8) | q[0]; - if (bom == 0x0000FEFF) { - bo = -1; - q += 4; - } - else if (bom == 0xFFFE0000) { - bo = 1; - q += 4; - } - if (byteorder) - *byteorder = bo; - } - - if (q == e) { - if (consumed) - *consumed = size; - _Py_RETURN_UNICODE_EMPTY(); - } - -#ifdef WORDS_BIGENDIAN - le = bo < 0; -#else - le = bo <= 0; -#endif - encoding = le ? "utf-32-le" : "utf-32-be"; - - _PyUnicodeWriter_Init(&writer); - writer.min_length = (e - q + 3) / 4; - if (_PyUnicodeWriter_Prepare(&writer, writer.min_length, 127) == -1) - goto onError; - - while (1) { - Py_UCS4 ch = 0; - Py_UCS4 maxch = PyUnicode_MAX_CHAR_VALUE(writer.buffer); - - if (e - q >= 4) { - enum PyUnicode_Kind kind = writer.kind; - void *data = writer.data; - const unsigned char *last = e - 4; - Py_ssize_t pos = writer.pos; - if (le) { - do { - ch = (q[3] << 24) | (q[2] << 16) | (q[1] << 8) | q[0]; - if (ch > maxch) - break; - if (kind != PyUnicode_1BYTE_KIND && - Py_UNICODE_IS_SURROGATE(ch)) - break; - PyUnicode_WRITE(kind, data, pos++, ch); - q += 4; - } while (q <= last); - } - else { - do { - ch = (q[0] << 24) | (q[1] << 16) | (q[2] << 8) | q[3]; - if (ch > maxch) - break; - if (kind != PyUnicode_1BYTE_KIND && - Py_UNICODE_IS_SURROGATE(ch)) - break; - PyUnicode_WRITE(kind, data, pos++, ch); - q += 4; - } while (q <= last); - } - writer.pos = pos; - } - - if (Py_UNICODE_IS_SURROGATE(ch)) { - errmsg = "code point in surrogate code point range(0xd800, 0xe000)"; - startinpos = ((const char *)q) - starts; - endinpos = startinpos + 4; - } - else if (ch <= maxch) { - if (q == e || consumed) - break; - /* remaining bytes at the end? (size should be divisible by 4) */ - errmsg = "truncated data"; - startinpos = ((const char *)q) - starts; - endinpos = ((const char *)e) - starts; - } - else { - if (ch < 0x110000) { - if (_PyUnicodeWriter_WriteCharInline(&writer, ch) < 0) - goto onError; - q += 4; - continue; - } - errmsg = "code point not in range(0x110000)"; - startinpos = ((const char *)q) - starts; - endinpos = startinpos + 4; - } - - /* The remaining input chars are ignored if the callback - chooses to skip the input */ - if (unicode_decode_call_errorhandler_writer( - errors, &errorHandler, - encoding, errmsg, - &starts, (const char **)&e, &startinpos, &endinpos, &exc, (const char **)&q, - &writer)) - goto onError; - } - - if (consumed) - *consumed = (const char *)q-starts; - - Py_XDECREF(errorHandler); - Py_XDECREF(exc); - return _PyUnicodeWriter_Finish(&writer); - - onError: - _PyUnicodeWriter_Dealloc(&writer); - Py_XDECREF(errorHandler); - Py_XDECREF(exc); - return NULL; -} - -PyObject * -_PyUnicode_EncodeUTF32(PyObject *str, - const char *errors, - int byteorder) -{ - int kind; - void *data; - Py_ssize_t len; - PyObject *v; - unsigned char *p; - Py_ssize_t nsize, i; - /* Offsets from p for storing byte pairs in the right order. */ -#if PY_LITTLE_ENDIAN - int iorder[] = {0, 1, 2, 3}; -#else - int iorder[] = {3, 2, 1, 0}; -#endif - const char *encoding; - PyObject *errorHandler = NULL; - PyObject *exc = NULL; - PyObject *rep = NULL; - -#define STORECHAR(CH) \ - do { \ - p[iorder[3]] = ((CH) >> 24) & 0xff; \ - p[iorder[2]] = ((CH) >> 16) & 0xff; \ - p[iorder[1]] = ((CH) >> 8) & 0xff; \ - p[iorder[0]] = (CH) & 0xff; \ - p += 4; \ - } while(0) - - if (!PyUnicode_Check(str)) { - PyErr_BadArgument(); - return NULL; - } - if (PyUnicode_READY(str) == -1) - return NULL; - kind = PyUnicode_KIND(str); - data = PyUnicode_DATA(str); - len = PyUnicode_GET_LENGTH(str); - - nsize = len + (byteorder == 0); - if (nsize > PY_SSIZE_T_MAX / 4) - return PyErr_NoMemory(); - v = PyBytes_FromStringAndSize(NULL, nsize * 4); - if (v == NULL) - return NULL; - - p = (unsigned char *)PyBytes_AS_STRING(v); - if (byteorder == 0) - STORECHAR(0xFEFF); - if (len == 0) - return v; - - if (byteorder == -1) { - /* force LE */ - iorder[0] = 0; - iorder[1] = 1; - iorder[2] = 2; - iorder[3] = 3; - encoding = "utf-32-le"; - } - else if (byteorder == 1) { - /* force BE */ - iorder[0] = 3; - iorder[1] = 2; - iorder[2] = 1; - iorder[3] = 0; - encoding = "utf-32-be"; - } - else - encoding = "utf-32"; - - if (kind == PyUnicode_1BYTE_KIND) { - for (i = 0; i < len; i++) - STORECHAR(PyUnicode_READ(kind, data, i)); - return v; - } - - for (i = 0; i < len;) { - Py_ssize_t repsize, moreunits; - Py_UCS4 ch = PyUnicode_READ(kind, data, i); - i++; - assert(ch <= MAX_UNICODE); - if (!Py_UNICODE_IS_SURROGATE(ch)) { - STORECHAR(ch); - continue; - } - - rep = unicode_encode_call_errorhandler( - errors, &errorHandler, - encoding, "surrogates not allowed", - str, &exc, i-1, i, &i); - - if (!rep) - goto error; - - if (PyBytes_Check(rep)) { - repsize = PyBytes_GET_SIZE(rep); - if (repsize & 3) { - raise_encode_exception(&exc, encoding, - str, i - 1, i, - "surrogates not allowed"); - goto error; - } - moreunits = repsize / 4; - } - else { - assert(PyUnicode_Check(rep)); - if (PyUnicode_READY(rep) < 0) - goto error; - moreunits = repsize = PyUnicode_GET_LENGTH(rep); - if (!PyUnicode_IS_ASCII(rep)) { - raise_encode_exception(&exc, encoding, - str, i - 1, i, - "surrogates not allowed"); - goto error; - } - } - - /* four bytes are reserved for each surrogate */ - if (moreunits > 1) { - Py_ssize_t outpos = p - (unsigned char*) PyBytes_AS_STRING(v); - Py_ssize_t morebytes = 4 * (moreunits - 1); - if (PyBytes_GET_SIZE(v) > PY_SSIZE_T_MAX - morebytes) { - /* integer overflow */ - PyErr_NoMemory(); - goto error; - } - if (_PyBytes_Resize(&v, PyBytes_GET_SIZE(v) + morebytes) < 0) - goto error; - p = (unsigned char*) PyBytes_AS_STRING(v) + outpos; - } - - if (PyBytes_Check(rep)) { - Py_MEMCPY(p, PyBytes_AS_STRING(rep), repsize); - p += repsize; - } else /* rep is unicode */ { - const Py_UCS1 *repdata; - assert(PyUnicode_KIND(rep) == PyUnicode_1BYTE_KIND); - repdata = PyUnicode_1BYTE_DATA(rep); - while (repsize--) { - Py_UCS4 ch = *repdata++; - STORECHAR(ch); - } - } - - Py_CLEAR(rep); - } - - /* Cut back to size actually needed. This is necessary for, for example, - encoding of a string containing isolated surrogates and the 'ignore' - handler is used. */ - nsize = p - (unsigned char*) PyBytes_AS_STRING(v); - if (nsize != PyBytes_GET_SIZE(v)) - _PyBytes_Resize(&v, nsize); - Py_XDECREF(errorHandler); - Py_XDECREF(exc); - return v; - error: - Py_XDECREF(rep); - Py_XDECREF(errorHandler); - Py_XDECREF(exc); - Py_XDECREF(v); - return NULL; -#undef STORECHAR -} - -PyObject * -PyUnicode_EncodeUTF32(const Py_UNICODE *s, - Py_ssize_t size, - const char *errors, - int byteorder) -{ - PyObject *result; - PyObject *tmp = PyUnicode_FromUnicode(s, size); - if (tmp == NULL) - return NULL; - result = _PyUnicode_EncodeUTF32(tmp, errors, byteorder); - Py_DECREF(tmp); - return result; -} - -PyObject * -PyUnicode_AsUTF32String(PyObject *unicode) -{ - return _PyUnicode_EncodeUTF32(unicode, NULL, 0); -} - -/* --- UTF-16 Codec ------------------------------------------------------- */ - -PyObject * -PyUnicode_DecodeUTF16(const char *s, - Py_ssize_t size, - const char *errors, - int *byteorder) -{ - return PyUnicode_DecodeUTF16Stateful(s, size, errors, byteorder, NULL); -} - -PyObject * -PyUnicode_DecodeUTF16Stateful(const char *s, - Py_ssize_t size, - const char *errors, - int *byteorder, - Py_ssize_t *consumed) -{ - const char *starts = s; - Py_ssize_t startinpos; - Py_ssize_t endinpos; - _PyUnicodeWriter writer; - const unsigned char *q, *e; - int bo = 0; /* assume native ordering by default */ - int native_ordering; - const char *errmsg = ""; - PyObject *errorHandler = NULL; - PyObject *exc = NULL; - const char *encoding; - - q = (unsigned char *)s; - e = q + size; - - if (byteorder) - bo = *byteorder; - - /* Check for BOM marks (U+FEFF) in the input and adjust current - byte order setting accordingly. In native mode, the leading BOM - mark is skipped, in all other modes, it is copied to the output - stream as-is (giving a ZWNBSP character). */ - if (bo == 0 && size >= 2) { - const Py_UCS4 bom = (q[1] << 8) | q[0]; - if (bom == 0xFEFF) { - q += 2; - bo = -1; - } - else if (bom == 0xFFFE) { - q += 2; - bo = 1; - } - if (byteorder) - *byteorder = bo; - } - - if (q == e) { - if (consumed) - *consumed = size; - _Py_RETURN_UNICODE_EMPTY(); - } - -#if PY_LITTLE_ENDIAN - native_ordering = bo <= 0; - encoding = bo <= 0 ? "utf-16-le" : "utf-16-be"; -#else - native_ordering = bo >= 0; - encoding = bo >= 0 ? "utf-16-be" : "utf-16-le"; -#endif - - /* Note: size will always be longer than the resulting Unicode - character count */ - _PyUnicodeWriter_Init(&writer); - writer.min_length = (e - q + 1) / 2; - if (_PyUnicodeWriter_Prepare(&writer, writer.min_length, 127) == -1) - goto onError; - - while (1) { - Py_UCS4 ch = 0; - if (e - q >= 2) { - int kind = writer.kind; - if (kind == PyUnicode_1BYTE_KIND) { - if (PyUnicode_IS_ASCII(writer.buffer)) - ch = asciilib_utf16_decode(&q, e, - (Py_UCS1*)writer.data, &writer.pos, - native_ordering); - else - ch = ucs1lib_utf16_decode(&q, e, - (Py_UCS1*)writer.data, &writer.pos, - native_ordering); - } else if (kind == PyUnicode_2BYTE_KIND) { - ch = ucs2lib_utf16_decode(&q, e, - (Py_UCS2*)writer.data, &writer.pos, - native_ordering); - } else { - assert(kind == PyUnicode_4BYTE_KIND); - ch = ucs4lib_utf16_decode(&q, e, - (Py_UCS4*)writer.data, &writer.pos, - native_ordering); - } - } - - switch (ch) - { - case 0: - /* remaining byte at the end? (size should be even) */ - if (q == e || consumed) - goto End; - errmsg = "truncated data"; - startinpos = ((const char *)q) - starts; - endinpos = ((const char *)e) - starts; - break; - /* The remaining input chars are ignored if the callback - chooses to skip the input */ - case 1: - q -= 2; - if (consumed) - goto End; - errmsg = "unexpected end of data"; - startinpos = ((const char *)q) - starts; - endinpos = ((const char *)e) - starts; - break; - case 2: - errmsg = "illegal encoding"; - startinpos = ((const char *)q) - 2 - starts; - endinpos = startinpos + 2; - break; - case 3: - errmsg = "illegal UTF-16 surrogate"; - startinpos = ((const char *)q) - 4 - starts; - endinpos = startinpos + 2; - break; - default: - if (_PyUnicodeWriter_WriteCharInline(&writer, ch) < 0) - goto onError; - continue; - } - - if (unicode_decode_call_errorhandler_writer( - errors, - &errorHandler, - encoding, errmsg, - &starts, - (const char **)&e, - &startinpos, - &endinpos, - &exc, - (const char **)&q, - &writer)) - goto onError; - } - -End: - if (consumed) - *consumed = (const char *)q-starts; - - Py_XDECREF(errorHandler); - Py_XDECREF(exc); - return _PyUnicodeWriter_Finish(&writer); - - onError: - _PyUnicodeWriter_Dealloc(&writer); - Py_XDECREF(errorHandler); - Py_XDECREF(exc); - return NULL; -} - -PyObject * -_PyUnicode_EncodeUTF16(PyObject *str, - const char *errors, - int byteorder) -{ - enum PyUnicode_Kind kind; - const void *data; - Py_ssize_t len; - PyObject *v; - unsigned short *out; - Py_ssize_t pairs; -#if PY_BIG_ENDIAN - int native_ordering = byteorder >= 0; -#else - int native_ordering = byteorder <= 0; -#endif - const char *encoding; - Py_ssize_t nsize, pos; - PyObject *errorHandler = NULL; - PyObject *exc = NULL; - PyObject *rep = NULL; - - if (!PyUnicode_Check(str)) { - PyErr_BadArgument(); - return NULL; - } - if (PyUnicode_READY(str) == -1) - return NULL; - kind = PyUnicode_KIND(str); - data = PyUnicode_DATA(str); - len = PyUnicode_GET_LENGTH(str); - - pairs = 0; - if (kind == PyUnicode_4BYTE_KIND) { - const Py_UCS4 *in = (const Py_UCS4 *)data; - const Py_UCS4 *end = in + len; - while (in < end) - if (*in++ >= 0x10000) - pairs++; - } - if (len > PY_SSIZE_T_MAX / 2 - pairs - (byteorder == 0)) - return PyErr_NoMemory(); - nsize = len + pairs + (byteorder == 0); - v = PyBytes_FromStringAndSize(NULL, nsize * 2); - if (v == NULL) - return NULL; - - /* output buffer is 2-bytes aligned */ - assert(_Py_IS_ALIGNED(PyBytes_AS_STRING(v), 2)); - out = (unsigned short *)PyBytes_AS_STRING(v); - if (byteorder == 0) - *out++ = 0xFEFF; - if (len == 0) - goto done; - - if (kind == PyUnicode_1BYTE_KIND) { - ucs1lib_utf16_encode((const Py_UCS1 *)data, len, &out, native_ordering); - goto done; - } - - if (byteorder < 0) - encoding = "utf-16-le"; - else if (byteorder > 0) - encoding = "utf-16-be"; - else - encoding = "utf-16"; - - pos = 0; - while (pos < len) { - Py_ssize_t repsize, moreunits; - - if (kind == PyUnicode_2BYTE_KIND) { - pos += ucs2lib_utf16_encode((const Py_UCS2 *)data + pos, len - pos, - &out, native_ordering); - } - else { - assert(kind == PyUnicode_4BYTE_KIND); - pos += ucs4lib_utf16_encode((const Py_UCS4 *)data + pos, len - pos, - &out, native_ordering); - } - if (pos == len) - break; - - rep = unicode_encode_call_errorhandler( - errors, &errorHandler, - encoding, "surrogates not allowed", - str, &exc, pos, pos + 1, &pos); - if (!rep) - goto error; - - if (PyBytes_Check(rep)) { - repsize = PyBytes_GET_SIZE(rep); - if (repsize & 1) { - raise_encode_exception(&exc, encoding, - str, pos - 1, pos, - "surrogates not allowed"); - goto error; - } - moreunits = repsize / 2; - } - else { - assert(PyUnicode_Check(rep)); - if (PyUnicode_READY(rep) < 0) - goto error; - moreunits = repsize = PyUnicode_GET_LENGTH(rep); - if (!PyUnicode_IS_ASCII(rep)) { - raise_encode_exception(&exc, encoding, - str, pos - 1, pos, - "surrogates not allowed"); - goto error; - } - } - - /* two bytes are reserved for each surrogate */ - if (moreunits > 1) { - Py_ssize_t outpos = out - (unsigned short*) PyBytes_AS_STRING(v); - Py_ssize_t morebytes = 2 * (moreunits - 1); - if (PyBytes_GET_SIZE(v) > PY_SSIZE_T_MAX - morebytes) { - /* integer overflow */ - PyErr_NoMemory(); - goto error; - } - if (_PyBytes_Resize(&v, PyBytes_GET_SIZE(v) + morebytes) < 0) - goto error; - out = (unsigned short*) PyBytes_AS_STRING(v) + outpos; - } - - if (PyBytes_Check(rep)) { - Py_MEMCPY(out, PyBytes_AS_STRING(rep), repsize); - out += moreunits; - } else /* rep is unicode */ { - assert(PyUnicode_KIND(rep) == PyUnicode_1BYTE_KIND); - ucs1lib_utf16_encode(PyUnicode_1BYTE_DATA(rep), repsize, - &out, native_ordering); - } - - Py_CLEAR(rep); - } - - /* Cut back to size actually needed. This is necessary for, for example, - encoding of a string containing isolated surrogates and the 'ignore' handler - is used. */ - nsize = (unsigned char*) out - (unsigned char*) PyBytes_AS_STRING(v); - if (nsize != PyBytes_GET_SIZE(v)) - _PyBytes_Resize(&v, nsize); - Py_XDECREF(errorHandler); - Py_XDECREF(exc); - done: - return v; - error: - Py_XDECREF(rep); - Py_XDECREF(errorHandler); - Py_XDECREF(exc); - Py_XDECREF(v); - return NULL; -#undef STORECHAR -} - -PyObject * -PyUnicode_EncodeUTF16(const Py_UNICODE *s, - Py_ssize_t size, - const char *errors, - int byteorder) -{ - PyObject *result; - PyObject *tmp = PyUnicode_FromUnicode(s, size); - if (tmp == NULL) - return NULL; - result = _PyUnicode_EncodeUTF16(tmp, errors, byteorder); - Py_DECREF(tmp); - return result; -} - -PyObject * -PyUnicode_AsUTF16String(PyObject *unicode) -{ - return _PyUnicode_EncodeUTF16(unicode, NULL, 0); -} - -/* --- Unicode Escape Codec ----------------------------------------------- */ - -/* Helper function for PyUnicode_DecodeUnicodeEscape, determines - if all the escapes in the string make it still a valid ASCII string. - Returns -1 if any escapes were found which cause the string to - pop out of ASCII range. Otherwise returns the length of the - required buffer to hold the string. - */ -static Py_ssize_t -length_of_escaped_ascii_string(const char *s, Py_ssize_t size) -{ - const unsigned char *p = (const unsigned char *)s; - const unsigned char *end = p + size; - Py_ssize_t length = 0; - - if (size < 0) - return -1; - - for (; p < end; ++p) { - if (*p > 127) { - /* Non-ASCII */ - return -1; - } - else if (*p != '\\') { - /* Normal character */ - ++length; - } - else { - /* Backslash-escape, check next char */ - ++p; - /* Escape sequence reaches till end of string or - non-ASCII follow-up. */ - if (p >= end || *p > 127) - return -1; - switch (*p) { - case '\n': - /* backslash + \n result in zero characters */ - break; - case '\\': case '\'': case '\"': - case 'b': case 'f': case 't': - case 'n': case 'r': case 'v': case 'a': - ++length; - break; - case '0': case '1': case '2': case '3': - case '4': case '5': case '6': case '7': - case 'x': case 'u': case 'U': case 'N': - /* these do not guarantee ASCII characters */ - return -1; - default: - /* count the backslash + the other character */ - length += 2; - } - } - } - return length; -} - -static _PyUnicode_Name_CAPI *ucnhash_CAPI = NULL; - -PyObject * -PyUnicode_DecodeUnicodeEscape(const char *s, - Py_ssize_t size, - const char *errors) -{ - const char *starts = s; - Py_ssize_t startinpos; - Py_ssize_t endinpos; - _PyUnicodeWriter writer; - const char *end; - char* message; - Py_UCS4 chr = 0xffffffff; /* in case 'getcode' messes up */ - PyObject *errorHandler = NULL; - PyObject *exc = NULL; - Py_ssize_t len; - - len = length_of_escaped_ascii_string(s, size); - if (len == 0) - _Py_RETURN_UNICODE_EMPTY(); - - /* After length_of_escaped_ascii_string() there are two alternatives, - either the string is pure ASCII with named escapes like \n, etc. - and we determined it's exact size (common case) - or it contains \x, \u, ... escape sequences. then we create a - legacy wchar string and resize it at the end of this function. */ - _PyUnicodeWriter_Init(&writer); - if (len > 0) { - writer.min_length = len; - } - else { - /* Escaped strings will always be longer than the resulting - Unicode string, so we start with size here and then reduce the - length after conversion to the true value. - (but if the error callback returns a long replacement string - we'll have to allocate more space) */ - writer.min_length = size; - } - - if (size == 0) - return _PyUnicodeWriter_Finish(&writer); - end = s + size; - - while (s < end) { - unsigned char c; - Py_UCS4 x; - int digits; - - /* Non-escape characters are interpreted as Unicode ordinals */ - if (*s != '\\') { - x = (unsigned char)*s; - s++; - if (_PyUnicodeWriter_WriteCharInline(&writer, x) < 0) - goto onError; - continue; - } - - startinpos = s-starts; - /* \ - Escapes */ - s++; - c = *s++; - if (s > end) - c = '\0'; /* Invalid after \ */ - - switch (c) { - - /* \x escapes */ -#define WRITECHAR(ch) \ - do { \ - if (_PyUnicodeWriter_WriteCharInline(&writer, (ch)) < 0) \ - goto onError; \ - } while(0) - - case '\n': break; - case '\\': WRITECHAR('\\'); break; - case '\'': WRITECHAR('\''); break; - case '\"': WRITECHAR('\"'); break; - case 'b': WRITECHAR('\b'); break; - /* FF */ - case 'f': WRITECHAR('\014'); break; - case 't': WRITECHAR('\t'); break; - case 'n': WRITECHAR('\n'); break; - case 'r': WRITECHAR('\r'); break; - /* VT */ - case 'v': WRITECHAR('\013'); break; - /* BEL, not classic C */ - case 'a': WRITECHAR('\007'); break; - - /* \OOO (octal) escapes */ - case '0': case '1': case '2': case '3': - case '4': case '5': case '6': case '7': - x = s[-1] - '0'; - if (s < end && '0' <= *s && *s <= '7') { - x = (x<<3) + *s++ - '0'; - if (s < end && '0' <= *s && *s <= '7') - x = (x<<3) + *s++ - '0'; - } - WRITECHAR(x); - break; - - /* hex escapes */ - /* \xXX */ - case 'x': - digits = 2; - message = "truncated \\xXX escape"; - goto hexescape; - - /* \uXXXX */ - case 'u': - digits = 4; - message = "truncated \\uXXXX escape"; - goto hexescape; - - /* \UXXXXXXXX */ - case 'U': - digits = 8; - message = "truncated \\UXXXXXXXX escape"; - hexescape: - chr = 0; - if (end - s < digits) { - /* count only hex digits */ - for (; s < end; ++s) { - c = (unsigned char)*s; - if (!Py_ISXDIGIT(c)) - goto error; - } - goto error; - } - for (; digits--; ++s) { - c = (unsigned char)*s; - if (!Py_ISXDIGIT(c)) - goto error; - chr = (chr<<4) & ~0xF; - if (c >= '0' && c <= '9') - chr += c - '0'; - else if (c >= 'a' && c <= 'f') - chr += 10 + c - 'a'; - else - chr += 10 + c - 'A'; - } - if (chr == 0xffffffff && PyErr_Occurred()) - /* _decoding_error will have already written into the - target buffer. */ - break; - store: - /* when we get here, chr is a 32-bit unicode character */ - message = "illegal Unicode character"; - if (chr > MAX_UNICODE) - goto error; - WRITECHAR(chr); - break; - - /* \N{name} */ - case 'N': - message = "malformed \\N character escape"; - if (ucnhash_CAPI == NULL) { - /* load the unicode data module */ - ucnhash_CAPI = (_PyUnicode_Name_CAPI *)PyCapsule_Import( - PyUnicodeData_CAPSULE_NAME, 1); - if (ucnhash_CAPI == NULL) - goto ucnhashError; - } - if (*s == '{') { - const char *start = s+1; - /* look for the closing brace */ - while (*s != '}' && s < end) - s++; - if (s > start && s < end && *s == '}') { - /* found a name. look it up in the unicode database */ - message = "unknown Unicode character name"; - s++; - if (s - start - 1 <= INT_MAX && - ucnhash_CAPI->getcode(NULL, start, (int)(s-start-1), - &chr, 0)) - goto store; - } - } - goto error; - - default: - if (s > end) { - message = "\\ at end of string"; - s--; - goto error; - } - else { - WRITECHAR('\\'); - WRITECHAR((unsigned char)s[-1]); - } - break; - } - continue; - - error: - endinpos = s-starts; - if (unicode_decode_call_errorhandler_writer( - errors, &errorHandler, - "unicodeescape", message, - &starts, &end, &startinpos, &endinpos, &exc, &s, - &writer)) - goto onError; - continue; - } -#undef WRITECHAR - - Py_XDECREF(errorHandler); - Py_XDECREF(exc); - return _PyUnicodeWriter_Finish(&writer); - - ucnhashError: - PyErr_SetString( - PyExc_UnicodeError, - "\\N escapes not supported (can't load unicodedata module)" - ); - _PyUnicodeWriter_Dealloc(&writer); - Py_XDECREF(errorHandler); - Py_XDECREF(exc); - return NULL; - - onError: - _PyUnicodeWriter_Dealloc(&writer); - Py_XDECREF(errorHandler); - Py_XDECREF(exc); - return NULL; -} - -/* Return a Unicode-Escape string version of the Unicode object. - - If quotes is true, the string is enclosed in u"" or u'' quotes as - appropriate. - -*/ - -PyObject * -PyUnicode_AsUnicodeEscapeString(PyObject *unicode) -{ - Py_ssize_t i, len; - PyObject *repr; - char *p; - int kind; - void *data; - Py_ssize_t expandsize = 0; - - /* Initial allocation is based on the longest-possible character - escape. - - For UCS1 strings it's '\xxx', 4 bytes per source character. - For UCS2 strings it's '\uxxxx', 6 bytes per source character. - For UCS4 strings it's '\U00xxxxxx', 10 bytes per source character. - */ - - if (!PyUnicode_Check(unicode)) { - PyErr_BadArgument(); - return NULL; - } - if (PyUnicode_READY(unicode) == -1) - return NULL; - len = PyUnicode_GET_LENGTH(unicode); - kind = PyUnicode_KIND(unicode); - data = PyUnicode_DATA(unicode); - switch (kind) { - case PyUnicode_1BYTE_KIND: expandsize = 4; break; - case PyUnicode_2BYTE_KIND: expandsize = 6; break; - case PyUnicode_4BYTE_KIND: expandsize = 10; break; - } - - if (len == 0) - return PyBytes_FromStringAndSize(NULL, 0); - - if (len > (PY_SSIZE_T_MAX - 2 - 1) / expandsize) - return PyErr_NoMemory(); - - repr = PyBytes_FromStringAndSize(NULL, - 2 - + expandsize*len - + 1); - if (repr == NULL) - return NULL; - - p = PyBytes_AS_STRING(repr); - - for (i = 0; i < len; i++) { - Py_UCS4 ch = PyUnicode_READ(kind, data, i); - - /* Escape backslashes */ - if (ch == '\\') { - *p++ = '\\'; - *p++ = (char) ch; - continue; - } - - /* Map 21-bit characters to '\U00xxxxxx' */ - else if (ch >= 0x10000) { - assert(ch <= MAX_UNICODE); - *p++ = '\\'; - *p++ = 'U'; - *p++ = Py_hexdigits[(ch >> 28) & 0x0000000F]; - *p++ = Py_hexdigits[(ch >> 24) & 0x0000000F]; - *p++ = Py_hexdigits[(ch >> 20) & 0x0000000F]; - *p++ = Py_hexdigits[(ch >> 16) & 0x0000000F]; - *p++ = Py_hexdigits[(ch >> 12) & 0x0000000F]; - *p++ = Py_hexdigits[(ch >> 8) & 0x0000000F]; - *p++ = Py_hexdigits[(ch >> 4) & 0x0000000F]; - *p++ = Py_hexdigits[ch & 0x0000000F]; - continue; - } - - /* Map 16-bit characters to '\uxxxx' */ - if (ch >= 256) { - *p++ = '\\'; - *p++ = 'u'; - *p++ = Py_hexdigits[(ch >> 12) & 0x000F]; - *p++ = Py_hexdigits[(ch >> 8) & 0x000F]; - *p++ = Py_hexdigits[(ch >> 4) & 0x000F]; - *p++ = Py_hexdigits[ch & 0x000F]; - } - - /* Map special whitespace to '\t', \n', '\r' */ - else if (ch == '\t') { - *p++ = '\\'; - *p++ = 't'; - } - else if (ch == '\n') { - *p++ = '\\'; - *p++ = 'n'; - } - else if (ch == '\r') { - *p++ = '\\'; - *p++ = 'r'; - } - - /* Map non-printable US ASCII to '\xhh' */ - else if (ch < ' ' || ch >= 0x7F) { - *p++ = '\\'; - *p++ = 'x'; - *p++ = Py_hexdigits[(ch >> 4) & 0x000F]; - *p++ = Py_hexdigits[ch & 0x000F]; - } - - /* Copy everything else as-is */ - else - *p++ = (char) ch; - } - - assert(p - PyBytes_AS_STRING(repr) > 0); - if (_PyBytes_Resize(&repr, p - PyBytes_AS_STRING(repr)) < 0) - return NULL; - return repr; -} - -PyObject * -PyUnicode_EncodeUnicodeEscape(const Py_UNICODE *s, - Py_ssize_t size) -{ - PyObject *result; - PyObject *tmp = PyUnicode_FromUnicode(s, size); - if (tmp == NULL) - return NULL; - result = PyUnicode_AsUnicodeEscapeString(tmp); - Py_DECREF(tmp); - return result; -} - -/* --- Raw Unicode Escape Codec ------------------------------------------- */ - -PyObject * -PyUnicode_DecodeRawUnicodeEscape(const char *s, - Py_ssize_t size, - const char *errors) -{ - const char *starts = s; - Py_ssize_t startinpos; - Py_ssize_t endinpos; - _PyUnicodeWriter writer; - const char *end; - const char *bs; - PyObject *errorHandler = NULL; - PyObject *exc = NULL; - - if (size == 0) - _Py_RETURN_UNICODE_EMPTY(); - - /* Escaped strings will always be longer than the resulting - Unicode string, so we start with size here and then reduce the - length after conversion to the true value. (But decoding error - handler might have to resize the string) */ - _PyUnicodeWriter_Init(&writer); - writer.min_length = size; - - end = s + size; - while (s < end) { - unsigned char c; - Py_UCS4 x; - int i; - int count; - - /* Non-escape characters are interpreted as Unicode ordinals */ - if (*s != '\\') { - x = (unsigned char)*s++; - if (_PyUnicodeWriter_WriteCharInline(&writer, x) < 0) - goto onError; - continue; - } - startinpos = s-starts; - - /* \u-escapes are only interpreted iff the number of leading - backslashes if odd */ - bs = s; - for (;s < end;) { - if (*s != '\\') - break; - x = (unsigned char)*s++; - if (_PyUnicodeWriter_WriteCharInline(&writer, x) < 0) - goto onError; - } - if (((s - bs) & 1) == 0 || - s >= end || - (*s != 'u' && *s != 'U')) { - continue; - } - writer.pos--; - count = *s=='u' ? 4 : 8; - s++; - - /* \uXXXX with 4 hex digits, \Uxxxxxxxx with 8 */ - for (x = 0, i = 0; i < count; ++i, ++s) { - c = (unsigned char)*s; - if (!Py_ISXDIGIT(c)) { - endinpos = s-starts; - if (unicode_decode_call_errorhandler_writer( - errors, &errorHandler, - "rawunicodeescape", "truncated \\uXXXX", - &starts, &end, &startinpos, &endinpos, &exc, &s, - &writer)) - goto onError; - goto nextByte; - } - x = (x<<4) & ~0xF; - if (c >= '0' && c <= '9') - x += c - '0'; - else if (c >= 'a' && c <= 'f') - x += 10 + c - 'a'; - else - x += 10 + c - 'A'; - } - if (x <= MAX_UNICODE) { - if (_PyUnicodeWriter_WriteCharInline(&writer, x) < 0) - goto onError; - } - else { - endinpos = s-starts; - if (unicode_decode_call_errorhandler_writer( - errors, &errorHandler, - "rawunicodeescape", "\\Uxxxxxxxx out of range", - &starts, &end, &startinpos, &endinpos, &exc, &s, - &writer)) - goto onError; - } - nextByte: - ; - } - Py_XDECREF(errorHandler); - Py_XDECREF(exc); - return _PyUnicodeWriter_Finish(&writer); - - onError: - _PyUnicodeWriter_Dealloc(&writer); - Py_XDECREF(errorHandler); - Py_XDECREF(exc); - return NULL; -} - - -PyObject * -PyUnicode_AsRawUnicodeEscapeString(PyObject *unicode) -{ - PyObject *repr; - char *p; - char *q; - Py_ssize_t expandsize, pos; - int kind; - void *data; - Py_ssize_t len; - - if (!PyUnicode_Check(unicode)) { - PyErr_BadArgument(); - return NULL; - } - if (PyUnicode_READY(unicode) == -1) - return NULL; - kind = PyUnicode_KIND(unicode); - data = PyUnicode_DATA(unicode); - len = PyUnicode_GET_LENGTH(unicode); - /* 4 byte characters can take up 10 bytes, 2 byte characters can take up 6 - bytes, and 1 byte characters 4. */ - expandsize = kind * 2 + 2; - - if (len > PY_SSIZE_T_MAX / expandsize) - return PyErr_NoMemory(); - - repr = PyBytes_FromStringAndSize(NULL, expandsize * len); - if (repr == NULL) - return NULL; - if (len == 0) - return repr; - - p = q = PyBytes_AS_STRING(repr); - for (pos = 0; pos < len; pos++) { - Py_UCS4 ch = PyUnicode_READ(kind, data, pos); - /* Map 32-bit characters to '\Uxxxxxxxx' */ - if (ch >= 0x10000) { - assert(ch <= MAX_UNICODE); - *p++ = '\\'; - *p++ = 'U'; - *p++ = Py_hexdigits[(ch >> 28) & 0xf]; - *p++ = Py_hexdigits[(ch >> 24) & 0xf]; - *p++ = Py_hexdigits[(ch >> 20) & 0xf]; - *p++ = Py_hexdigits[(ch >> 16) & 0xf]; - *p++ = Py_hexdigits[(ch >> 12) & 0xf]; - *p++ = Py_hexdigits[(ch >> 8) & 0xf]; - *p++ = Py_hexdigits[(ch >> 4) & 0xf]; - *p++ = Py_hexdigits[ch & 15]; - } - /* Map 16-bit characters to '\uxxxx' */ - else if (ch >= 256) { - *p++ = '\\'; - *p++ = 'u'; - *p++ = Py_hexdigits[(ch >> 12) & 0xf]; - *p++ = Py_hexdigits[(ch >> 8) & 0xf]; - *p++ = Py_hexdigits[(ch >> 4) & 0xf]; - *p++ = Py_hexdigits[ch & 15]; - } - /* Copy everything else as-is */ - else - *p++ = (char) ch; - } - - assert(p > q); - if (_PyBytes_Resize(&repr, p - q) < 0) - return NULL; - return repr; -} - -PyObject * -PyUnicode_EncodeRawUnicodeEscape(const Py_UNICODE *s, - Py_ssize_t size) -{ - PyObject *result; - PyObject *tmp = PyUnicode_FromUnicode(s, size); - if (tmp == NULL) - return NULL; - result = PyUnicode_AsRawUnicodeEscapeString(tmp); - Py_DECREF(tmp); - return result; -} - -/* --- Unicode Internal Codec ------------------------------------------- */ - -PyObject * -_PyUnicode_DecodeUnicodeInternal(const char *s, - Py_ssize_t size, - const char *errors) -{ - const char *starts = s; - Py_ssize_t startinpos; - Py_ssize_t endinpos; - _PyUnicodeWriter writer; - const char *end; - const char *reason; - PyObject *errorHandler = NULL; - PyObject *exc = NULL; - - if (PyErr_WarnEx(PyExc_DeprecationWarning, - "unicode_internal codec has been deprecated", - 1)) - return NULL; - - if (size == 0) - _Py_RETURN_UNICODE_EMPTY(); - - _PyUnicodeWriter_Init(&writer); - if (size / Py_UNICODE_SIZE > PY_SSIZE_T_MAX - 1) { - PyErr_NoMemory(); - goto onError; - } - writer.min_length = (size + (Py_UNICODE_SIZE - 1)) / Py_UNICODE_SIZE; - - end = s + size; - while (s < end) { - Py_UNICODE uch; - Py_UCS4 ch; - if (end - s < Py_UNICODE_SIZE) { - endinpos = end-starts; - reason = "truncated input"; - goto error; - } - /* We copy the raw representation one byte at a time because the - pointer may be unaligned (see test_codeccallbacks). */ - ((char *) &uch)[0] = s[0]; - ((char *) &uch)[1] = s[1]; -#ifdef Py_UNICODE_WIDE - ((char *) &uch)[2] = s[2]; - ((char *) &uch)[3] = s[3]; -#endif - ch = uch; -#ifdef Py_UNICODE_WIDE - /* We have to sanity check the raw data, otherwise doom looms for - some malformed UCS-4 data. */ - if (ch > 0x10ffff) { - endinpos = s - starts + Py_UNICODE_SIZE; - reason = "illegal code point (> 0x10FFFF)"; - goto error; - } -#endif - s += Py_UNICODE_SIZE; -#ifndef Py_UNICODE_WIDE - if (Py_UNICODE_IS_HIGH_SURROGATE(ch) && end - s >= Py_UNICODE_SIZE) - { - Py_UNICODE uch2; - ((char *) &uch2)[0] = s[0]; - ((char *) &uch2)[1] = s[1]; - if (Py_UNICODE_IS_LOW_SURROGATE(uch2)) - { - ch = Py_UNICODE_JOIN_SURROGATES(uch, uch2); - s += Py_UNICODE_SIZE; - } - } -#endif - - if (_PyUnicodeWriter_WriteCharInline(&writer, ch) < 0) - goto onError; - continue; - - error: - startinpos = s - starts; - if (unicode_decode_call_errorhandler_writer( - errors, &errorHandler, - "unicode_internal", reason, - &starts, &end, &startinpos, &endinpos, &exc, &s, - &writer)) - goto onError; - } - - Py_XDECREF(errorHandler); - Py_XDECREF(exc); - return _PyUnicodeWriter_Finish(&writer); - - onError: - _PyUnicodeWriter_Dealloc(&writer); - Py_XDECREF(errorHandler); - Py_XDECREF(exc); - return NULL; -} - -/* --- Latin-1 Codec ------------------------------------------------------ */ - -PyObject * -PyUnicode_DecodeLatin1(const char *s, - Py_ssize_t size, - const char *errors) -{ - /* Latin-1 is equivalent to the first 256 ordinals in Unicode. */ - return _PyUnicode_FromUCS1((unsigned char*)s, size); -} - -/* create or adjust a UnicodeEncodeError */ -static void -make_encode_exception(PyObject **exceptionObject, - const char *encoding, - PyObject *unicode, - Py_ssize_t startpos, Py_ssize_t endpos, - const char *reason) -{ - if (*exceptionObject == NULL) { - *exceptionObject = PyObject_CallFunction( - PyExc_UnicodeEncodeError, "sOnns", - encoding, unicode, startpos, endpos, reason); - } - else { - if (PyUnicodeEncodeError_SetStart(*exceptionObject, startpos)) - goto onError; - if (PyUnicodeEncodeError_SetEnd(*exceptionObject, endpos)) - goto onError; - if (PyUnicodeEncodeError_SetReason(*exceptionObject, reason)) - goto onError; - return; - onError: - Py_CLEAR(*exceptionObject); - } -} - -/* raises a UnicodeEncodeError */ -static void -raise_encode_exception(PyObject **exceptionObject, - const char *encoding, - PyObject *unicode, - Py_ssize_t startpos, Py_ssize_t endpos, - const char *reason) -{ - make_encode_exception(exceptionObject, - encoding, unicode, startpos, endpos, reason); - if (*exceptionObject != NULL) - PyCodec_StrictErrors(*exceptionObject); -} - -/* error handling callback helper: - build arguments, call the callback and check the arguments, - put the result into newpos and return the replacement string, which - has to be freed by the caller */ -static PyObject * -unicode_encode_call_errorhandler(const char *errors, - PyObject **errorHandler, - const char *encoding, const char *reason, - PyObject *unicode, PyObject **exceptionObject, - Py_ssize_t startpos, Py_ssize_t endpos, - Py_ssize_t *newpos) -{ - static char *argparse = "On;encoding error handler must return (str/bytes, int) tuple"; - Py_ssize_t len; - PyObject *restuple; - PyObject *resunicode; - - if (*errorHandler == NULL) { - *errorHandler = PyCodec_LookupError(errors); - if (*errorHandler == NULL) - return NULL; - } - - if (PyUnicode_READY(unicode) == -1) - return NULL; - len = PyUnicode_GET_LENGTH(unicode); - - make_encode_exception(exceptionObject, - encoding, unicode, startpos, endpos, reason); - if (*exceptionObject == NULL) - return NULL; - - restuple = PyObject_CallFunctionObjArgs( - *errorHandler, *exceptionObject, NULL); - if (restuple == NULL) - return NULL; - if (!PyTuple_Check(restuple)) { - PyErr_SetString(PyExc_TypeError, &argparse[3]); - Py_DECREF(restuple); - return NULL; - } - if (!PyArg_ParseTuple(restuple, argparse, - &resunicode, newpos)) { - Py_DECREF(restuple); - return NULL; - } - if (!PyUnicode_Check(resunicode) && !PyBytes_Check(resunicode)) { - PyErr_SetString(PyExc_TypeError, &argparse[3]); - Py_DECREF(restuple); - return NULL; - } - if (*newpos<0) - *newpos = len + *newpos; - if (*newpos<0 || *newpos>len) { - PyErr_Format(PyExc_IndexError, "position %zd from error handler out of bounds", *newpos); - Py_DECREF(restuple); - return NULL; - } - Py_INCREF(resunicode); - Py_DECREF(restuple); - return resunicode; -} - -static PyObject * -unicode_encode_ucs1(PyObject *unicode, - const char *errors, - unsigned int limit) -{ - /* input state */ - Py_ssize_t pos=0, size; - int kind; - void *data; - /* output object */ - PyObject *res; - /* pointer into the output */ - char *str; - /* current output position */ - Py_ssize_t ressize; - const char *encoding = (limit == 256) ? "latin-1" : "ascii"; - const char *reason = (limit == 256) ? "ordinal not in range(256)" : "ordinal not in range(128)"; - PyObject *errorHandler = NULL; - PyObject *exc = NULL; - /* the following variable is used for caching string comparisons - * -1=not initialized, 0=unknown, 1=strict, 2=replace, 3=ignore, 4=xmlcharrefreplace */ - int known_errorHandler = -1; - - if (PyUnicode_READY(unicode) == -1) - return NULL; - size = PyUnicode_GET_LENGTH(unicode); - kind = PyUnicode_KIND(unicode); - data = PyUnicode_DATA(unicode); - /* allocate enough for a simple encoding without - replacements, if we need more, we'll resize */ - if (size == 0) - return PyBytes_FromStringAndSize(NULL, 0); - res = PyBytes_FromStringAndSize(NULL, size); - if (res == NULL) - return NULL; - str = PyBytes_AS_STRING(res); - ressize = size; - - while (pos < size) { - Py_UCS4 c = PyUnicode_READ(kind, data, pos); - - /* can we encode this? */ - if (c= limit)) - ++collend; - /* cache callback name lookup (if not done yet, i.e. it's the first error) */ - if (known_errorHandler==-1) { - if ((errors==NULL) || (!strcmp(errors, "strict"))) - known_errorHandler = 1; - else if (!strcmp(errors, "replace")) - known_errorHandler = 2; - else if (!strcmp(errors, "ignore")) - known_errorHandler = 3; - else if (!strcmp(errors, "xmlcharrefreplace")) - known_errorHandler = 4; - else - known_errorHandler = 0; - } - switch (known_errorHandler) { - case 1: /* strict */ - raise_encode_exception(&exc, encoding, unicode, collstart, collend, reason); - goto onError; - case 2: /* replace */ - while (collstart++ < collend) - *str++ = '?'; /* fall through */ - case 3: /* ignore */ - pos = collend; - break; - case 4: /* xmlcharrefreplace */ - respos = str - PyBytes_AS_STRING(res); - requiredsize = respos; - /* determine replacement size */ - for (i = collstart; i < collend; ++i) { - Py_UCS4 ch = PyUnicode_READ(kind, data, i); - Py_ssize_t incr; - if (ch < 10) - incr = 2+1+1; - else if (ch < 100) - incr = 2+2+1; - else if (ch < 1000) - incr = 2+3+1; - else if (ch < 10000) - incr = 2+4+1; - else if (ch < 100000) - incr = 2+5+1; - else if (ch < 1000000) - incr = 2+6+1; - else { - assert(ch <= MAX_UNICODE); - incr = 2+7+1; - } - if (requiredsize > PY_SSIZE_T_MAX - incr) - goto overflow; - requiredsize += incr; - } - if (requiredsize > PY_SSIZE_T_MAX - (size - collend)) - goto overflow; - requiredsize += size - collend; - if (requiredsize > ressize) { - if (ressize <= PY_SSIZE_T_MAX/2 && requiredsize < 2*ressize) - requiredsize = 2*ressize; - if (_PyBytes_Resize(&res, requiredsize)) - goto onError; - str = PyBytes_AS_STRING(res) + respos; - ressize = requiredsize; - } - /* generate replacement */ - for (i = collstart; i < collend; ++i) { - str += sprintf(str, "&#%d;", PyUnicode_READ(kind, data, i)); - } - pos = collend; - break; - default: - repunicode = unicode_encode_call_errorhandler(errors, &errorHandler, - encoding, reason, unicode, &exc, - collstart, collend, &newpos); - if (repunicode == NULL || (PyUnicode_Check(repunicode) && - PyUnicode_READY(repunicode) == -1)) - goto onError; - if (PyBytes_Check(repunicode)) { - /* Directly copy bytes result to output. */ - repsize = PyBytes_Size(repunicode); - if (repsize > 1) { - /* Make room for all additional bytes. */ - respos = str - PyBytes_AS_STRING(res); - if (ressize > PY_SSIZE_T_MAX - repsize - 1) { - Py_DECREF(repunicode); - goto overflow; - } - if (_PyBytes_Resize(&res, ressize+repsize-1)) { - Py_DECREF(repunicode); - goto onError; - } - str = PyBytes_AS_STRING(res) + respos; - ressize += repsize-1; - } - memcpy(str, PyBytes_AsString(repunicode), repsize); - str += repsize; - pos = newpos; - Py_DECREF(repunicode); - break; - } - /* need more space? (at least enough for what we - have+the replacement+the rest of the string, so - we won't have to check space for encodable characters) */ - respos = str - PyBytes_AS_STRING(res); - repsize = PyUnicode_GET_LENGTH(repunicode); - requiredsize = respos; - if (requiredsize > PY_SSIZE_T_MAX - repsize) - goto overflow; - requiredsize += repsize; - if (requiredsize > PY_SSIZE_T_MAX - (size - collend)) - goto overflow; - requiredsize += size - collend; - if (requiredsize > ressize) { - if (ressize <= PY_SSIZE_T_MAX/2 && requiredsize < 2*ressize) - requiredsize = 2*ressize; - if (_PyBytes_Resize(&res, requiredsize)) { - Py_DECREF(repunicode); - goto onError; - } - str = PyBytes_AS_STRING(res) + respos; - ressize = requiredsize; - } - /* check if there is anything unencodable in the replacement - and copy it to the output */ - for (i = 0; repsize-->0; ++i, ++str) { - c = PyUnicode_READ_CHAR(repunicode, i); - if (c >= limit) { - raise_encode_exception(&exc, encoding, unicode, - pos, pos+1, reason); - Py_DECREF(repunicode); - goto onError; - } - *str = (char)c; - } - pos = newpos; - Py_DECREF(repunicode); - } - } - } - /* Resize if we allocated to much */ - size = str - PyBytes_AS_STRING(res); - if (size < ressize) { /* If this falls res will be NULL */ - assert(size >= 0); - if (_PyBytes_Resize(&res, size) < 0) - goto onError; - } - - Py_XDECREF(errorHandler); - Py_XDECREF(exc); - return res; - - overflow: - PyErr_SetString(PyExc_OverflowError, - "encoded result is too long for a Python string"); - - onError: - Py_XDECREF(res); - Py_XDECREF(errorHandler); - Py_XDECREF(exc); - return NULL; -} - -/* Deprecated */ -PyObject * -PyUnicode_EncodeLatin1(const Py_UNICODE *p, - Py_ssize_t size, - const char *errors) -{ - PyObject *result; - PyObject *unicode = PyUnicode_FromUnicode(p, size); - if (unicode == NULL) - return NULL; - result = unicode_encode_ucs1(unicode, errors, 256); - Py_DECREF(unicode); - return result; -} - -PyObject * -_PyUnicode_AsLatin1String(PyObject *unicode, const char *errors) -{ - if (!PyUnicode_Check(unicode)) { - PyErr_BadArgument(); - return NULL; - } - if (PyUnicode_READY(unicode) == -1) - return NULL; - /* Fast path: if it is a one-byte string, construct - bytes object directly. */ - if (PyUnicode_KIND(unicode) == PyUnicode_1BYTE_KIND) - return PyBytes_FromStringAndSize(PyUnicode_DATA(unicode), - PyUnicode_GET_LENGTH(unicode)); - /* Non-Latin-1 characters present. Defer to above function to - raise the exception. */ - return unicode_encode_ucs1(unicode, errors, 256); -} - -PyObject* -PyUnicode_AsLatin1String(PyObject *unicode) -{ - return _PyUnicode_AsLatin1String(unicode, NULL); -} - -/* --- 7-bit ASCII Codec -------------------------------------------------- */ - -PyObject * -PyUnicode_DecodeASCII(const char *s, - Py_ssize_t size, - const char *errors) -{ - const char *starts = s; - _PyUnicodeWriter writer; - int kind; - void *data; - Py_ssize_t startinpos; - Py_ssize_t endinpos; - Py_ssize_t outpos; - const char *e; - PyObject *errorHandler = NULL; - PyObject *exc = NULL; - - if (size == 0) - _Py_RETURN_UNICODE_EMPTY(); - - /* ASCII is equivalent to the first 128 ordinals in Unicode. */ - if (size == 1 && (unsigned char)s[0] < 128) - return get_latin1_char((unsigned char)s[0]); - - _PyUnicodeWriter_Init(&writer); - writer.min_length = size; - if (_PyUnicodeWriter_Prepare(&writer, writer.min_length, 127) < 0) - return NULL; - - e = s + size; - data = writer.data; - outpos = ascii_decode(s, e, (Py_UCS1 *)data); - writer.pos = outpos; - if (writer.pos == size) - return _PyUnicodeWriter_Finish(&writer); - - s += writer.pos; - kind = writer.kind; - while (s < e) { - unsigned char c = (unsigned char)*s; - if (c < 128) { - PyUnicode_WRITE(kind, data, writer.pos, c); - writer.pos++; - ++s; - } - else { - startinpos = s-starts; - endinpos = startinpos + 1; - if (unicode_decode_call_errorhandler_writer( - errors, &errorHandler, - "ascii", "ordinal not in range(128)", - &starts, &e, &startinpos, &endinpos, &exc, &s, - &writer)) - goto onError; - kind = writer.kind; - data = writer.data; - } - } - Py_XDECREF(errorHandler); - Py_XDECREF(exc); - return _PyUnicodeWriter_Finish(&writer); - - onError: - _PyUnicodeWriter_Dealloc(&writer); - Py_XDECREF(errorHandler); - Py_XDECREF(exc); - return NULL; -} - -/* Deprecated */ -PyObject * -PyUnicode_EncodeASCII(const Py_UNICODE *p, - Py_ssize_t size, - const char *errors) -{ - PyObject *result; - PyObject *unicode = PyUnicode_FromUnicode(p, size); - if (unicode == NULL) - return NULL; - result = unicode_encode_ucs1(unicode, errors, 128); - Py_DECREF(unicode); - return result; -} - -PyObject * -_PyUnicode_AsASCIIString(PyObject *unicode, const char *errors) -{ - if (!PyUnicode_Check(unicode)) { - PyErr_BadArgument(); - return NULL; - } - if (PyUnicode_READY(unicode) == -1) - return NULL; - /* Fast path: if it is an ASCII-only string, construct bytes object - directly. Else defer to above function to raise the exception. */ - if (PyUnicode_IS_ASCII(unicode)) - return PyBytes_FromStringAndSize(PyUnicode_DATA(unicode), - PyUnicode_GET_LENGTH(unicode)); - return unicode_encode_ucs1(unicode, errors, 128); -} - -PyObject * -PyUnicode_AsASCIIString(PyObject *unicode) -{ - return _PyUnicode_AsASCIIString(unicode, NULL); -} - -#ifdef HAVE_MBCS - -/* --- MBCS codecs for Windows -------------------------------------------- */ - -#if SIZEOF_INT < SIZEOF_SIZE_T -#define NEED_RETRY -#endif - -#ifndef WC_ERR_INVALID_CHARS -# define WC_ERR_INVALID_CHARS 0x0080 -#endif - -static char* -code_page_name(UINT code_page, PyObject **obj) -{ - *obj = NULL; - if (code_page == CP_ACP) - return "mbcs"; - if (code_page == CP_UTF7) - return "CP_UTF7"; - if (code_page == CP_UTF8) - return "CP_UTF8"; - - *obj = PyBytes_FromFormat("cp%u", code_page); - if (*obj == NULL) - return NULL; - return PyBytes_AS_STRING(*obj); -} - -static DWORD -decode_code_page_flags(UINT code_page) -{ - if (code_page == CP_UTF7) { - /* The CP_UTF7 decoder only supports flags=0 */ - return 0; - } - else - return MB_ERR_INVALID_CHARS; -} - -/* - * Decode a byte string from a Windows code page into unicode object in strict - * mode. - * - * Returns consumed size if succeed, returns -2 on decode error, or raise an - * OSError and returns -1 on other error. - */ -static int -decode_code_page_strict(UINT code_page, - PyObject **v, - const char *in, - int insize) -{ - const DWORD flags = decode_code_page_flags(code_page); - wchar_t *out; - DWORD outsize; - - /* First get the size of the result */ - assert(insize > 0); - outsize = MultiByteToWideChar(code_page, flags, in, insize, NULL, 0); - if (outsize <= 0) - goto error; - - if (*v == NULL) { - /* Create unicode object */ - /* FIXME: don't use _PyUnicode_New(), but allocate a wchar_t* buffer */ - *v = (PyObject*)_PyUnicode_New(outsize); - if (*v == NULL) - return -1; - out = PyUnicode_AS_UNICODE(*v); - } - else { - /* Extend unicode object */ - Py_ssize_t n = PyUnicode_GET_SIZE(*v); - if (unicode_resize(v, n + outsize) < 0) - return -1; - out = PyUnicode_AS_UNICODE(*v) + n; - } - - /* Do the conversion */ - outsize = MultiByteToWideChar(code_page, flags, in, insize, out, outsize); - if (outsize <= 0) - goto error; - return insize; - -error: - if (GetLastError() == ERROR_NO_UNICODE_TRANSLATION) - return -2; - PyErr_SetFromWindowsErr(0); - return -1; -} - -/* - * Decode a byte string from a code page into unicode object with an error - * handler. - * - * Returns consumed size if succeed, or raise an OSError or - * UnicodeDecodeError exception and returns -1 on error. - */ -static int -decode_code_page_errors(UINT code_page, - PyObject **v, - const char *in, const int size, - const char *errors, int final) -{ - const char *startin = in; - const char *endin = in + size; - const DWORD flags = decode_code_page_flags(code_page); - /* Ideally, we should get reason from FormatMessage. This is the Windows - 2000 English version of the message. */ - const char *reason = "No mapping for the Unicode character exists " - "in the target code page."; - /* each step cannot decode more than 1 character, but a character can be - represented as a surrogate pair */ - wchar_t buffer[2], *startout, *out; - int insize; - Py_ssize_t outsize; - PyObject *errorHandler = NULL; - PyObject *exc = NULL; - PyObject *encoding_obj = NULL; - char *encoding; - DWORD err; - int ret = -1; - - assert(size > 0); - - encoding = code_page_name(code_page, &encoding_obj); - if (encoding == NULL) - return -1; - - if ((errors == NULL || strcmp(errors, "strict") == 0) && final) { - /* The last error was ERROR_NO_UNICODE_TRANSLATION, then we raise a - UnicodeDecodeError. */ - make_decode_exception(&exc, encoding, in, size, 0, 0, reason); - if (exc != NULL) { - PyCodec_StrictErrors(exc); - Py_CLEAR(exc); - } - goto error; - } - - if (*v == NULL) { - /* Create unicode object */ - if (size > PY_SSIZE_T_MAX / (Py_ssize_t)Py_ARRAY_LENGTH(buffer)) { - PyErr_NoMemory(); - goto error; - } - /* FIXME: don't use _PyUnicode_New(), but allocate a wchar_t* buffer */ - *v = (PyObject*)_PyUnicode_New(size * Py_ARRAY_LENGTH(buffer)); - if (*v == NULL) - goto error; - startout = PyUnicode_AS_UNICODE(*v); - } - else { - /* Extend unicode object */ - Py_ssize_t n = PyUnicode_GET_SIZE(*v); - if (size > (PY_SSIZE_T_MAX - n) / (Py_ssize_t)Py_ARRAY_LENGTH(buffer)) { - PyErr_NoMemory(); - goto error; - } - if (unicode_resize(v, n + size * Py_ARRAY_LENGTH(buffer)) < 0) - goto error; - startout = PyUnicode_AS_UNICODE(*v) + n; - } - - /* Decode the byte string character per character */ - out = startout; - while (in < endin) - { - /* Decode a character */ - insize = 1; - do - { - outsize = MultiByteToWideChar(code_page, flags, - in, insize, - buffer, Py_ARRAY_LENGTH(buffer)); - if (outsize > 0) - break; - err = GetLastError(); - if (err != ERROR_NO_UNICODE_TRANSLATION - && err != ERROR_INSUFFICIENT_BUFFER) - { - PyErr_SetFromWindowsErr(0); - goto error; - } - insize++; - } - /* 4=maximum length of a UTF-8 sequence */ - while (insize <= 4 && (in + insize) <= endin); - - if (outsize <= 0) { - Py_ssize_t startinpos, endinpos, outpos; - - /* last character in partial decode? */ - if (in + insize >= endin && !final) - break; - - startinpos = in - startin; - endinpos = startinpos + 1; - outpos = out - PyUnicode_AS_UNICODE(*v); - if (unicode_decode_call_errorhandler_wchar( - errors, &errorHandler, - encoding, reason, - &startin, &endin, &startinpos, &endinpos, &exc, &in, - v, &outpos)) - { - goto error; - } - out = PyUnicode_AS_UNICODE(*v) + outpos; - } - else { - in += insize; - memcpy(out, buffer, outsize * sizeof(wchar_t)); - out += outsize; - } - } - - /* write a NUL character at the end */ - *out = 0; - - /* Extend unicode object */ - outsize = out - startout; - assert(outsize <= PyUnicode_WSTR_LENGTH(*v)); - if (unicode_resize(v, outsize) < 0) - goto error; - /* (in - startin) <= size and size is an int */ - ret = Py_SAFE_DOWNCAST(in - startin, Py_ssize_t, int); - -error: - Py_XDECREF(encoding_obj); - Py_XDECREF(errorHandler); - Py_XDECREF(exc); - return ret; -} - -static PyObject * -decode_code_page_stateful(int code_page, - const char *s, Py_ssize_t size, - const char *errors, Py_ssize_t *consumed) -{ - PyObject *v = NULL; - int chunk_size, final, converted, done; - - if (code_page < 0) { - PyErr_SetString(PyExc_ValueError, "invalid code page number"); - return NULL; - } - - if (consumed) - *consumed = 0; - - do - { -#ifdef NEED_RETRY - if (size > INT_MAX) { - chunk_size = INT_MAX; - final = 0; - done = 0; - } - else -#endif - { - chunk_size = (int)size; - final = (consumed == NULL); - done = 1; - } - - if (chunk_size == 0 && done) { - if (v != NULL) - break; - _Py_RETURN_UNICODE_EMPTY(); - } - - converted = decode_code_page_strict(code_page, &v, - s, chunk_size); - if (converted == -2) - converted = decode_code_page_errors(code_page, &v, - s, chunk_size, - errors, final); - assert(converted != 0 || done); - - if (converted < 0) { - Py_XDECREF(v); - return NULL; - } - - if (consumed) - *consumed += converted; - - s += converted; - size -= converted; - } while (!done); - - return unicode_result(v); -} - -PyObject * -PyUnicode_DecodeCodePageStateful(int code_page, - const char *s, - Py_ssize_t size, - const char *errors, - Py_ssize_t *consumed) -{ - return decode_code_page_stateful(code_page, s, size, errors, consumed); -} - -PyObject * -PyUnicode_DecodeMBCSStateful(const char *s, - Py_ssize_t size, - const char *errors, - Py_ssize_t *consumed) -{ - return decode_code_page_stateful(CP_ACP, s, size, errors, consumed); -} - -PyObject * -PyUnicode_DecodeMBCS(const char *s, - Py_ssize_t size, - const char *errors) -{ - return PyUnicode_DecodeMBCSStateful(s, size, errors, NULL); -} - -static DWORD -encode_code_page_flags(UINT code_page, const char *errors) -{ - if (code_page == CP_UTF8) { - return WC_ERR_INVALID_CHARS; - } - else if (code_page == CP_UTF7) { - /* CP_UTF7 only supports flags=0 */ - return 0; - } - else { - if (errors != NULL && strcmp(errors, "replace") == 0) - return 0; - else - return WC_NO_BEST_FIT_CHARS; - } -} - -/* - * Encode a Unicode string to a Windows code page into a byte string in strict - * mode. - * - * Returns consumed characters if succeed, returns -2 on encode error, or raise - * an OSError and returns -1 on other error. - */ -static int -encode_code_page_strict(UINT code_page, PyObject **outbytes, - PyObject *unicode, Py_ssize_t offset, int len, - const char* errors) -{ - BOOL usedDefaultChar = FALSE; - BOOL *pusedDefaultChar = &usedDefaultChar; - int outsize; - PyObject *exc = NULL; - wchar_t *p; - Py_ssize_t size; - const DWORD flags = encode_code_page_flags(code_page, NULL); - char *out; - /* Create a substring so that we can get the UTF-16 representation - of just the slice under consideration. */ - PyObject *substring; - - assert(len > 0); - - if (code_page != CP_UTF8 && code_page != CP_UTF7) - pusedDefaultChar = &usedDefaultChar; - else - pusedDefaultChar = NULL; - - substring = PyUnicode_Substring(unicode, offset, offset+len); - if (substring == NULL) - return -1; - p = PyUnicode_AsUnicodeAndSize(substring, &size); - if (p == NULL) { - Py_DECREF(substring); - return -1; - } - assert(size <= INT_MAX); - - /* First get the size of the result */ - outsize = WideCharToMultiByte(code_page, flags, - p, (int)size, - NULL, 0, - NULL, pusedDefaultChar); - if (outsize <= 0) - goto error; - /* If we used a default char, then we failed! */ - if (pusedDefaultChar && *pusedDefaultChar) { - Py_DECREF(substring); - return -2; - } - - if (*outbytes == NULL) { - /* Create string object */ - *outbytes = PyBytes_FromStringAndSize(NULL, outsize); - if (*outbytes == NULL) { - Py_DECREF(substring); - return -1; - } - out = PyBytes_AS_STRING(*outbytes); - } - else { - /* Extend string object */ - const Py_ssize_t n = PyBytes_Size(*outbytes); - if (outsize > PY_SSIZE_T_MAX - n) { - PyErr_NoMemory(); - Py_DECREF(substring); - return -1; - } - if (_PyBytes_Resize(outbytes, n + outsize) < 0) { - Py_DECREF(substring); - return -1; - } - out = PyBytes_AS_STRING(*outbytes) + n; - } - - /* Do the conversion */ - outsize = WideCharToMultiByte(code_page, flags, - p, (int)size, - out, outsize, - NULL, pusedDefaultChar); - Py_CLEAR(substring); - if (outsize <= 0) - goto error; - if (pusedDefaultChar && *pusedDefaultChar) - return -2; - return 0; - -error: - Py_XDECREF(substring); - if (GetLastError() == ERROR_NO_UNICODE_TRANSLATION) - return -2; - PyErr_SetFromWindowsErr(0); - return -1; -} - -/* - * Encode a Unicode string to a Windows code page into a byte string using a - * error handler. - * - * Returns consumed characters if succeed, or raise an OSError and returns - * -1 on other error. - */ -static int -encode_code_page_errors(UINT code_page, PyObject **outbytes, - PyObject *unicode, Py_ssize_t unicode_offset, - Py_ssize_t insize, const char* errors) -{ - const DWORD flags = encode_code_page_flags(code_page, errors); - Py_ssize_t pos = unicode_offset; - Py_ssize_t endin = unicode_offset + insize; - /* Ideally, we should get reason from FormatMessage. This is the Windows - 2000 English version of the message. */ - const char *reason = "invalid character"; - /* 4=maximum length of a UTF-8 sequence */ - char buffer[4]; - BOOL usedDefaultChar = FALSE, *pusedDefaultChar; - Py_ssize_t outsize; - char *out; - PyObject *errorHandler = NULL; - PyObject *exc = NULL; - PyObject *encoding_obj = NULL; - char *encoding; - Py_ssize_t newpos, newoutsize; - PyObject *rep; - int ret = -1; - - assert(insize > 0); - - encoding = code_page_name(code_page, &encoding_obj); - if (encoding == NULL) - return -1; - - if (errors == NULL || strcmp(errors, "strict") == 0) { - /* The last error was ERROR_NO_UNICODE_TRANSLATION, - then we raise a UnicodeEncodeError. */ - make_encode_exception(&exc, encoding, unicode, 0, 0, reason); - if (exc != NULL) { - PyCodec_StrictErrors(exc); - Py_DECREF(exc); - } - Py_XDECREF(encoding_obj); - return -1; - } - - if (code_page != CP_UTF8 && code_page != CP_UTF7) - pusedDefaultChar = &usedDefaultChar; - else - pusedDefaultChar = NULL; - - if (Py_ARRAY_LENGTH(buffer) > PY_SSIZE_T_MAX / insize) { - PyErr_NoMemory(); - goto error; - } - outsize = insize * Py_ARRAY_LENGTH(buffer); - - if (*outbytes == NULL) { - /* Create string object */ - *outbytes = PyBytes_FromStringAndSize(NULL, outsize); - if (*outbytes == NULL) - goto error; - out = PyBytes_AS_STRING(*outbytes); - } - else { - /* Extend string object */ - Py_ssize_t n = PyBytes_Size(*outbytes); - if (n > PY_SSIZE_T_MAX - outsize) { - PyErr_NoMemory(); - goto error; - } - if (_PyBytes_Resize(outbytes, n + outsize) < 0) - goto error; - out = PyBytes_AS_STRING(*outbytes) + n; - } - - /* Encode the string character per character */ - while (pos < endin) - { - Py_UCS4 ch = PyUnicode_READ_CHAR(unicode, pos); - wchar_t chars[2]; - int charsize; - if (ch < 0x10000) { - chars[0] = (wchar_t)ch; - charsize = 1; - } - else { - chars[0] = Py_UNICODE_HIGH_SURROGATE(ch); - chars[1] = Py_UNICODE_LOW_SURROGATE(ch); - charsize = 2; - } - - outsize = WideCharToMultiByte(code_page, flags, - chars, charsize, - buffer, Py_ARRAY_LENGTH(buffer), - NULL, pusedDefaultChar); - if (outsize > 0) { - if (pusedDefaultChar == NULL || !(*pusedDefaultChar)) - { - pos++; - memcpy(out, buffer, outsize); - out += outsize; - continue; - } - } - else if (GetLastError() != ERROR_NO_UNICODE_TRANSLATION) { - PyErr_SetFromWindowsErr(0); - goto error; - } - - rep = unicode_encode_call_errorhandler( - errors, &errorHandler, encoding, reason, - unicode, &exc, - pos, pos + 1, &newpos); - if (rep == NULL) - goto error; - pos = newpos; - - if (PyBytes_Check(rep)) { - outsize = PyBytes_GET_SIZE(rep); - if (outsize != 1) { - Py_ssize_t offset = out - PyBytes_AS_STRING(*outbytes); - newoutsize = PyBytes_GET_SIZE(*outbytes) + (outsize - 1); - if (_PyBytes_Resize(outbytes, newoutsize) < 0) { - Py_DECREF(rep); - goto error; - } - out = PyBytes_AS_STRING(*outbytes) + offset; - } - memcpy(out, PyBytes_AS_STRING(rep), outsize); - out += outsize; - } - else { - Py_ssize_t i; - enum PyUnicode_Kind kind; - void *data; - - if (PyUnicode_READY(rep) == -1) { - Py_DECREF(rep); - goto error; - } - - outsize = PyUnicode_GET_LENGTH(rep); - if (outsize != 1) { - Py_ssize_t offset = out - PyBytes_AS_STRING(*outbytes); - newoutsize = PyBytes_GET_SIZE(*outbytes) + (outsize - 1); - if (_PyBytes_Resize(outbytes, newoutsize) < 0) { - Py_DECREF(rep); - goto error; - } - out = PyBytes_AS_STRING(*outbytes) + offset; - } - kind = PyUnicode_KIND(rep); - data = PyUnicode_DATA(rep); - for (i=0; i < outsize; i++) { - Py_UCS4 ch = PyUnicode_READ(kind, data, i); - if (ch > 127) { - raise_encode_exception(&exc, - encoding, unicode, - pos, pos + 1, - "unable to encode error handler result to ASCII"); - Py_DECREF(rep); - goto error; - } - *out = (unsigned char)ch; - out++; - } - } - Py_DECREF(rep); - } - /* write a NUL byte */ - *out = 0; - outsize = out - PyBytes_AS_STRING(*outbytes); - assert(outsize <= PyBytes_GET_SIZE(*outbytes)); - if (_PyBytes_Resize(outbytes, outsize) < 0) - goto error; - ret = 0; - -error: - Py_XDECREF(encoding_obj); - Py_XDECREF(errorHandler); - Py_XDECREF(exc); - return ret; -} - -static PyObject * -encode_code_page(int code_page, - PyObject *unicode, - const char *errors) -{ - Py_ssize_t len; - PyObject *outbytes = NULL; - Py_ssize_t offset; - int chunk_len, ret, done; - - if (!PyUnicode_Check(unicode)) { - PyErr_BadArgument(); - return NULL; - } - - if (PyUnicode_READY(unicode) == -1) - return NULL; - len = PyUnicode_GET_LENGTH(unicode); - - if (code_page < 0) { - PyErr_SetString(PyExc_ValueError, "invalid code page number"); - return NULL; - } - - if (len == 0) - return PyBytes_FromStringAndSize(NULL, 0); - - offset = 0; - do - { -#ifdef NEED_RETRY - /* UTF-16 encoding may double the size, so use only INT_MAX/2 - chunks. */ - if (len > INT_MAX/2) { - chunk_len = INT_MAX/2; - done = 0; - } - else -#endif - { - chunk_len = (int)len; - done = 1; - } - - ret = encode_code_page_strict(code_page, &outbytes, - unicode, offset, chunk_len, - errors); - if (ret == -2) - ret = encode_code_page_errors(code_page, &outbytes, - unicode, offset, - chunk_len, errors); - if (ret < 0) { - Py_XDECREF(outbytes); - return NULL; - } - - offset += chunk_len; - len -= chunk_len; - } while (!done); - - return outbytes; -} - -PyObject * -PyUnicode_EncodeMBCS(const Py_UNICODE *p, - Py_ssize_t size, - const char *errors) -{ - PyObject *unicode, *res; - unicode = PyUnicode_FromUnicode(p, size); - if (unicode == NULL) - return NULL; - res = encode_code_page(CP_ACP, unicode, errors); - Py_DECREF(unicode); - return res; -} - -PyObject * -PyUnicode_EncodeCodePage(int code_page, - PyObject *unicode, - const char *errors) -{ - return encode_code_page(code_page, unicode, errors); -} - -PyObject * -PyUnicode_AsMBCSString(PyObject *unicode) -{ - return PyUnicode_EncodeCodePage(CP_ACP, unicode, NULL); -} - -#undef NEED_RETRY - -#endif /* HAVE_MBCS */ - -/* --- Character Mapping Codec -------------------------------------------- */ - -static int -charmap_decode_string(const char *s, - Py_ssize_t size, - PyObject *mapping, - const char *errors, - _PyUnicodeWriter *writer) -{ - const char *starts = s; - const char *e; - Py_ssize_t startinpos, endinpos; - PyObject *errorHandler = NULL, *exc = NULL; - Py_ssize_t maplen; - enum PyUnicode_Kind mapkind; - void *mapdata; - Py_UCS4 x; - unsigned char ch; - - if (PyUnicode_READY(mapping) == -1) - return -1; - - maplen = PyUnicode_GET_LENGTH(mapping); - mapdata = PyUnicode_DATA(mapping); - mapkind = PyUnicode_KIND(mapping); - - e = s + size; - - if (mapkind == PyUnicode_1BYTE_KIND && maplen >= 256) { - /* fast-path for cp037, cp500 and iso8859_1 encodings. iso8859_1 - * is disabled in encoding aliases, latin1 is preferred because - * its implementation is faster. */ - Py_UCS1 *mapdata_ucs1 = (Py_UCS1 *)mapdata; - Py_UCS1 *outdata = (Py_UCS1 *)writer->data; - Py_UCS4 maxchar = writer->maxchar; - - assert (writer->kind == PyUnicode_1BYTE_KIND); - while (s < e) { - ch = *s; - x = mapdata_ucs1[ch]; - if (x > maxchar) { - if (_PyUnicodeWriter_Prepare(writer, 1, 0xff) == -1) - goto onError; - maxchar = writer->maxchar; - outdata = (Py_UCS1 *)writer->data; - } - outdata[writer->pos] = x; - writer->pos++; - ++s; - } - return 0; - } - - while (s < e) { - if (mapkind == PyUnicode_2BYTE_KIND && maplen >= 256) { - enum PyUnicode_Kind outkind = writer->kind; - Py_UCS2 *mapdata_ucs2 = (Py_UCS2 *)mapdata; - if (outkind == PyUnicode_1BYTE_KIND) { - Py_UCS1 *outdata = (Py_UCS1 *)writer->data; - Py_UCS4 maxchar = writer->maxchar; - while (s < e) { - ch = *s; - x = mapdata_ucs2[ch]; - if (x > maxchar) - goto Error; - outdata[writer->pos] = x; - writer->pos++; - ++s; - } - break; - } - else if (outkind == PyUnicode_2BYTE_KIND) { - Py_UCS2 *outdata = (Py_UCS2 *)writer->data; - while (s < e) { - ch = *s; - x = mapdata_ucs2[ch]; - if (x == 0xFFFE) - goto Error; - outdata[writer->pos] = x; - writer->pos++; - ++s; - } - break; - } - } - ch = *s; - - if (ch < maplen) - x = PyUnicode_READ(mapkind, mapdata, ch); - else - x = 0xfffe; /* invalid value */ -Error: - if (x == 0xfffe) - { - /* undefined mapping */ - startinpos = s-starts; - endinpos = startinpos+1; - if (unicode_decode_call_errorhandler_writer( - errors, &errorHandler, - "charmap", "character maps to ", - &starts, &e, &startinpos, &endinpos, &exc, &s, - writer)) { - goto onError; - } - continue; - } - - if (_PyUnicodeWriter_WriteCharInline(writer, x) < 0) - goto onError; - ++s; - } - Py_XDECREF(errorHandler); - Py_XDECREF(exc); - return 0; - -onError: - Py_XDECREF(errorHandler); - Py_XDECREF(exc); - return -1; -} - -static int -charmap_decode_mapping(const char *s, - Py_ssize_t size, - PyObject *mapping, - const char *errors, - _PyUnicodeWriter *writer) -{ - const char *starts = s; - const char *e; - Py_ssize_t startinpos, endinpos; - PyObject *errorHandler = NULL, *exc = NULL; - unsigned char ch; - PyObject *key, *item = NULL; - - e = s + size; - - while (s < e) { - ch = *s; - - /* Get mapping (char ordinal -> integer, Unicode char or None) */ - key = PyLong_FromLong((long)ch); - if (key == NULL) - goto onError; - - item = PyObject_GetItem(mapping, key); - Py_DECREF(key); - if (item == NULL) { - if (PyErr_ExceptionMatches(PyExc_LookupError)) { - /* No mapping found means: mapping is undefined. */ - PyErr_Clear(); - goto Undefined; - } else - goto onError; - } - - /* Apply mapping */ - if (item == Py_None) - goto Undefined; - if (PyLong_Check(item)) { - long value = PyLong_AS_LONG(item); - if (value == 0xFFFE) - goto Undefined; - if (value < 0 || value > MAX_UNICODE) { - PyErr_Format(PyExc_TypeError, - "character mapping must be in range(0x%lx)", - (unsigned long)MAX_UNICODE + 1); - goto onError; - } - - if (_PyUnicodeWriter_WriteCharInline(writer, value) < 0) - goto onError; - } - else if (PyUnicode_Check(item)) { - if (PyUnicode_READY(item) == -1) - goto onError; - if (PyUnicode_GET_LENGTH(item) == 1) { - Py_UCS4 value = PyUnicode_READ_CHAR(item, 0); - if (value == 0xFFFE) - goto Undefined; - if (_PyUnicodeWriter_WriteCharInline(writer, value) < 0) - goto onError; - } - else { - writer->overallocate = 1; - if (_PyUnicodeWriter_WriteStr(writer, item) == -1) - goto onError; - } - } - else { - /* wrong return value */ - PyErr_SetString(PyExc_TypeError, - "character mapping must return integer, None or str"); - goto onError; - } - Py_CLEAR(item); - ++s; - continue; - -Undefined: - /* undefined mapping */ - Py_CLEAR(item); - startinpos = s-starts; - endinpos = startinpos+1; - if (unicode_decode_call_errorhandler_writer( - errors, &errorHandler, - "charmap", "character maps to ", - &starts, &e, &startinpos, &endinpos, &exc, &s, - writer)) { - goto onError; - } - } - Py_XDECREF(errorHandler); - Py_XDECREF(exc); - return 0; - -onError: - Py_XDECREF(item); - Py_XDECREF(errorHandler); - Py_XDECREF(exc); - return -1; -} - -PyObject * -PyUnicode_DecodeCharmap(const char *s, - Py_ssize_t size, - PyObject *mapping, - const char *errors) -{ - _PyUnicodeWriter writer; - - /* Default to Latin-1 */ - if (mapping == NULL) - return PyUnicode_DecodeLatin1(s, size, errors); - - if (size == 0) - _Py_RETURN_UNICODE_EMPTY(); - _PyUnicodeWriter_Init(&writer); - writer.min_length = size; - if (_PyUnicodeWriter_Prepare(&writer, writer.min_length, 127) == -1) - goto onError; - - if (PyUnicode_CheckExact(mapping)) { - if (charmap_decode_string(s, size, mapping, errors, &writer) < 0) - goto onError; - } - else { - if (charmap_decode_mapping(s, size, mapping, errors, &writer) < 0) - goto onError; - } - return _PyUnicodeWriter_Finish(&writer); - - onError: - _PyUnicodeWriter_Dealloc(&writer); - return NULL; -} - -/* Charmap encoding: the lookup table */ - -struct encoding_map { - PyObject_HEAD - unsigned char level1[32]; - int count2, count3; - unsigned char level23[1]; -}; - -static PyObject* -encoding_map_size(PyObject *obj, PyObject* args) -{ - struct encoding_map *map = (struct encoding_map*)obj; - return PyLong_FromLong(sizeof(*map) - 1 + 16*map->count2 + - 128*map->count3); -} - -static PyMethodDef encoding_map_methods[] = { - {"size", encoding_map_size, METH_NOARGS, - PyDoc_STR("Return the size (in bytes) of this object") }, - { 0 } -}; - -static void -encoding_map_dealloc(PyObject* o) -{ - PyObject_FREE(o); -} - -static PyTypeObject EncodingMapType = { - PyVarObject_HEAD_INIT(NULL, 0) - "EncodingMap", /*tp_name*/ - sizeof(struct encoding_map), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - /* methods */ - encoding_map_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_reserved*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash*/ - 0, /*tp_call*/ - 0, /*tp_str*/ - 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*/ - encoding_map_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*/ - 0, /*tp_new*/ - 0, /*tp_free*/ - 0, /*tp_is_gc*/ -}; - -PyObject* -PyUnicode_BuildEncodingMap(PyObject* string) -{ - PyObject *result; - struct encoding_map *mresult; - int i; - int need_dict = 0; - unsigned char level1[32]; - unsigned char level2[512]; - unsigned char *mlevel1, *mlevel2, *mlevel3; - int count2 = 0, count3 = 0; - int kind; - void *data; - Py_ssize_t length; - Py_UCS4 ch; - - if (!PyUnicode_Check(string) || !PyUnicode_GET_LENGTH(string)) { - PyErr_BadArgument(); - return NULL; - } - kind = PyUnicode_KIND(string); - data = PyUnicode_DATA(string); - length = PyUnicode_GET_LENGTH(string); - length = Py_MIN(length, 256); - memset(level1, 0xFF, sizeof level1); - memset(level2, 0xFF, sizeof level2); - - /* If there isn't a one-to-one mapping of NULL to \0, - or if there are non-BMP characters, we need to use - a mapping dictionary. */ - if (PyUnicode_READ(kind, data, 0) != 0) - need_dict = 1; - for (i = 1; i < length; i++) { - int l1, l2; - ch = PyUnicode_READ(kind, data, i); - if (ch == 0 || ch > 0xFFFF) { - need_dict = 1; - break; - } - if (ch == 0xFFFE) - /* unmapped character */ - continue; - l1 = ch >> 11; - l2 = ch >> 7; - if (level1[l1] == 0xFF) - level1[l1] = count2++; - if (level2[l2] == 0xFF) - level2[l2] = count3++; - } - - if (count2 >= 0xFF || count3 >= 0xFF) - need_dict = 1; - - if (need_dict) { - PyObject *result = PyDict_New(); - PyObject *key, *value; - if (!result) - return NULL; - for (i = 0; i < length; i++) { - key = PyLong_FromLong(PyUnicode_READ(kind, data, i)); - value = PyLong_FromLong(i); - if (!key || !value) - goto failed1; - if (PyDict_SetItem(result, key, value) == -1) - goto failed1; - Py_DECREF(key); - Py_DECREF(value); - } - return result; - failed1: - Py_XDECREF(key); - Py_XDECREF(value); - Py_DECREF(result); - return NULL; - } - - /* Create a three-level trie */ - result = PyObject_MALLOC(sizeof(struct encoding_map) + - 16*count2 + 128*count3 - 1); - if (!result) - return PyErr_NoMemory(); - PyObject_Init(result, &EncodingMapType); - mresult = (struct encoding_map*)result; - mresult->count2 = count2; - mresult->count3 = count3; - mlevel1 = mresult->level1; - mlevel2 = mresult->level23; - mlevel3 = mresult->level23 + 16*count2; - memcpy(mlevel1, level1, 32); - memset(mlevel2, 0xFF, 16*count2); - memset(mlevel3, 0, 128*count3); - count3 = 0; - for (i = 1; i < length; i++) { - int o1, o2, o3, i2, i3; - Py_UCS4 ch = PyUnicode_READ(kind, data, i); - if (ch == 0xFFFE) - /* unmapped character */ - continue; - o1 = ch>>11; - o2 = (ch>>7) & 0xF; - i2 = 16*mlevel1[o1] + o2; - if (mlevel2[i2] == 0xFF) - mlevel2[i2] = count3++; - o3 = ch & 0x7F; - i3 = 128*mlevel2[i2] + o3; - mlevel3[i3] = i; - } - return result; -} - -static int -encoding_map_lookup(Py_UCS4 c, PyObject *mapping) -{ - struct encoding_map *map = (struct encoding_map*)mapping; - int l1 = c>>11; - int l2 = (c>>7) & 0xF; - int l3 = c & 0x7F; - int i; - - if (c > 0xFFFF) - return -1; - if (c == 0) - return 0; - /* level 1*/ - i = map->level1[l1]; - if (i == 0xFF) { - return -1; - } - /* level 2*/ - i = map->level23[16*i+l2]; - if (i == 0xFF) { - return -1; - } - /* level 3 */ - i = map->level23[16*map->count2 + 128*i + l3]; - if (i == 0) { - return -1; - } - return i; -} - -/* Lookup the character ch in the mapping. If the character - can't be found, Py_None is returned (or NULL, if another - error occurred). */ -static PyObject * -charmapencode_lookup(Py_UCS4 c, PyObject *mapping) -{ - PyObject *w = PyLong_FromLong((long)c); - PyObject *x; - - if (w == NULL) - return NULL; - x = PyObject_GetItem(mapping, w); - Py_DECREF(w); - if (x == NULL) { - if (PyErr_ExceptionMatches(PyExc_LookupError)) { - /* No mapping found means: mapping is undefined. */ - PyErr_Clear(); - x = Py_None; - Py_INCREF(x); - return x; - } else - return NULL; - } - else if (x == Py_None) - return x; - else if (PyLong_Check(x)) { - long value = PyLong_AS_LONG(x); - if (value < 0 || value > 255) { - PyErr_SetString(PyExc_TypeError, - "character mapping must be in range(256)"); - Py_DECREF(x); - return NULL; - } - return x; - } - else if (PyBytes_Check(x)) - return x; - else { - /* wrong return value */ - PyErr_Format(PyExc_TypeError, - "character mapping must return integer, bytes or None, not %.400s", - x->ob_type->tp_name); - Py_DECREF(x); - return NULL; - } -} - -static int -charmapencode_resize(PyObject **outobj, Py_ssize_t *outpos, Py_ssize_t requiredsize) -{ - Py_ssize_t outsize = PyBytes_GET_SIZE(*outobj); - /* exponentially overallocate to minimize reallocations */ - if (requiredsize < 2*outsize) - requiredsize = 2*outsize; - if (_PyBytes_Resize(outobj, requiredsize)) - return -1; - return 0; -} - -typedef enum charmapencode_result { - enc_SUCCESS, enc_FAILED, enc_EXCEPTION -} charmapencode_result; -/* lookup the character, put the result in the output string and adjust - various state variables. Resize the output bytes object if not enough - space is available. Return a new reference to the object that - was put in the output buffer, or Py_None, if the mapping was undefined - (in which case no character was written) or NULL, if a - reallocation error occurred. The caller must decref the result */ -static charmapencode_result -charmapencode_output(Py_UCS4 c, PyObject *mapping, - PyObject **outobj, Py_ssize_t *outpos) -{ - PyObject *rep; - char *outstart; - Py_ssize_t outsize = PyBytes_GET_SIZE(*outobj); - - if (Py_TYPE(mapping) == &EncodingMapType) { - int res = encoding_map_lookup(c, mapping); - Py_ssize_t requiredsize = *outpos+1; - if (res == -1) - return enc_FAILED; - if (outsize outsize) - /* Make room for all additional bytes. */ - if (charmapencode_resize(res, respos, requiredsize)) { - Py_DECREF(repunicode); - return -1; - } - memcpy(PyBytes_AsString(*res) + *respos, - PyBytes_AsString(repunicode), repsize); - *respos += repsize; - *inpos = newpos; - Py_DECREF(repunicode); - break; - } - /* generate replacement */ - if (PyUnicode_READY(repunicode) == -1) { - Py_DECREF(repunicode); - return -1; - } - repsize = PyUnicode_GET_LENGTH(repunicode); - data = PyUnicode_DATA(repunicode); - kind = PyUnicode_KIND(repunicode); - for (index = 0; index < repsize; index++) { - Py_UCS4 repch = PyUnicode_READ(kind, data, index); - x = charmapencode_output(repch, mapping, res, respos); - if (x==enc_EXCEPTION) { - Py_DECREF(repunicode); - return -1; - } - else if (x==enc_FAILED) { - Py_DECREF(repunicode); - raise_encode_exception(exceptionObject, encoding, unicode, collstartpos, collendpos, reason); - return -1; - } - } - *inpos = newpos; - Py_DECREF(repunicode); - } - return 0; -} - -PyObject * -_PyUnicode_EncodeCharmap(PyObject *unicode, - PyObject *mapping, - const char *errors) -{ - /* output object */ - PyObject *res = NULL; - /* current input position */ - Py_ssize_t inpos = 0; - Py_ssize_t size; - /* current output position */ - Py_ssize_t respos = 0; - PyObject *errorHandler = NULL; - PyObject *exc = NULL; - /* the following variable is used for caching string comparisons - * -1=not initialized, 0=unknown, 1=strict, 2=replace, - * 3=ignore, 4=xmlcharrefreplace */ - int known_errorHandler = -1; - void *data; - int kind; - - if (PyUnicode_READY(unicode) == -1) - return NULL; - size = PyUnicode_GET_LENGTH(unicode); - data = PyUnicode_DATA(unicode); - kind = PyUnicode_KIND(unicode); - - /* Default to Latin-1 */ - if (mapping == NULL) - return unicode_encode_ucs1(unicode, errors, 256); - - /* allocate enough for a simple encoding without - replacements, if we need more, we'll resize */ - res = PyBytes_FromStringAndSize(NULL, size); - if (res == NULL) - goto onError; - if (size == 0) - return res; - - while (inpos adjust input position */ - ++inpos; - } - - /* Resize if we allocated to much */ - if (resposPyUnicode_GET_LENGTH(unicode)) { - PyErr_Format(PyExc_IndexError, "position %zd from error handler out of bounds", *newpos); - Py_DECREF(restuple); - return NULL; - } - Py_INCREF(resunicode); - Py_DECREF(restuple); - return resunicode; -} - -/* Lookup the character ch in the mapping and put the result in result, - which must be decrefed by the caller. - Return 0 on success, -1 on error */ -static int -charmaptranslate_lookup(Py_UCS4 c, PyObject *mapping, PyObject **result) -{ - PyObject *w = PyLong_FromLong((long)c); - PyObject *x; - - if (w == NULL) - return -1; - x = PyObject_GetItem(mapping, w); - Py_DECREF(w); - if (x == NULL) { - if (PyErr_ExceptionMatches(PyExc_LookupError)) { - /* No mapping found means: use 1:1 mapping. */ - PyErr_Clear(); - *result = NULL; - return 0; - } else - return -1; - } - else if (x == Py_None) { - *result = x; - return 0; - } - else if (PyLong_Check(x)) { - long value = PyLong_AS_LONG(x); - if (value < 0 || value > MAX_UNICODE) { - PyErr_Format(PyExc_ValueError, - "character mapping must be in range(0x%x)", - MAX_UNICODE+1); - Py_DECREF(x); - return -1; - } - *result = x; - return 0; - } - else if (PyUnicode_Check(x)) { - *result = x; - return 0; - } - else { - /* wrong return value */ - PyErr_SetString(PyExc_TypeError, - "character mapping must return integer, None or str"); - Py_DECREF(x); - return -1; - } -} - -/* lookup the character, write the result into the writer. - Return 1 if the result was written into the writer, return 0 if the mapping - was undefined, raise an exception return -1 on error. */ -static int -charmaptranslate_output(Py_UCS4 ch, PyObject *mapping, - _PyUnicodeWriter *writer) -{ - PyObject *item; - - if (charmaptranslate_lookup(ch, mapping, &item)) - return -1; - - if (item == NULL) { - /* not found => default to 1:1 mapping */ - if (_PyUnicodeWriter_WriteCharInline(writer, ch) < 0) { - return -1; - } - return 1; - } - - if (item == Py_None) { - Py_DECREF(item); - return 0; - } - - if (PyLong_Check(item)) { - long ch = (Py_UCS4)PyLong_AS_LONG(item); - /* PyLong_AS_LONG() cannot fail, charmaptranslate_lookup() already - used it */ - if (_PyUnicodeWriter_WriteCharInline(writer, ch) < 0) { - Py_DECREF(item); - return -1; - } - Py_DECREF(item); - return 1; - } - - if (!PyUnicode_Check(item)) { - Py_DECREF(item); - return -1; - } - - if (_PyUnicodeWriter_WriteStr(writer, item) < 0) { - Py_DECREF(item); - return -1; - } - - Py_DECREF(item); - return 1; -} - -static int -unicode_fast_translate_lookup(PyObject *mapping, Py_UCS1 ch, - Py_UCS1 *translate) -{ - PyObject *item = NULL; - int ret = 0; - - if (charmaptranslate_lookup(ch, mapping, &item)) { - return -1; - } - - if (item == Py_None) { - /* deletion */ - translate[ch] = 0xfe; - } - else if (item == NULL) { - /* not found => default to 1:1 mapping */ - translate[ch] = ch; - return 1; - } - else if (PyLong_Check(item)) { - long replace = PyLong_AS_LONG(item); - /* PyLong_AS_LONG() cannot fail, charmaptranslate_lookup() already - used it */ - if (127 < replace) { - /* invalid character or character outside ASCII: - skip the fast translate */ - goto exit; - } - translate[ch] = (Py_UCS1)replace; - } - else if (PyUnicode_Check(item)) { - Py_UCS4 replace; - - if (PyUnicode_READY(item) == -1) { - Py_DECREF(item); - return -1; - } - if (PyUnicode_GET_LENGTH(item) != 1) - goto exit; - - replace = PyUnicode_READ_CHAR(item, 0); - if (replace > 127) - goto exit; - translate[ch] = (Py_UCS1)replace; - } - else { - /* not None, NULL, long or unicode */ - goto exit; - } - ret = 1; - - exit: - Py_DECREF(item); - return ret; -} - -/* Fast path for ascii => ascii translation. Return 1 if the whole string - was translated into writer, return 0 if the input string was partially - translated into writer, raise an exception and return -1 on error. */ -static int -unicode_fast_translate(PyObject *input, PyObject *mapping, - _PyUnicodeWriter *writer, int ignore) -{ - Py_UCS1 ascii_table[128], ch, ch2; - Py_ssize_t len; - Py_UCS1 *in, *end, *out; - int res = 0; - - if (PyUnicode_READY(input) == -1) - return -1; - if (!PyUnicode_IS_ASCII(input)) - return 0; - len = PyUnicode_GET_LENGTH(input); - - memset(ascii_table, 0xff, 128); - - in = PyUnicode_1BYTE_DATA(input); - end = in + len; - - assert(PyUnicode_IS_ASCII(writer->buffer)); - assert(PyUnicode_GET_LENGTH(writer->buffer) == len); - out = PyUnicode_1BYTE_DATA(writer->buffer); - - for (; in < end; in++) { - ch = *in; - ch2 = ascii_table[ch]; - if (ch2 == 0xff) { - int translate = unicode_fast_translate_lookup(mapping, ch, - ascii_table); - if (translate < 0) - return -1; - if (translate == 0) - goto exit; - ch2 = ascii_table[ch]; - } - if (ch2 == 0xfe) { - if (ignore) - continue; - goto exit; - } - assert(ch2 < 128); - *out = ch2; - out++; - } - res = 1; - -exit: - writer->pos = out - PyUnicode_1BYTE_DATA(writer->buffer); - return res; -} - -PyObject * -_PyUnicode_TranslateCharmap(PyObject *input, - PyObject *mapping, - const char *errors) -{ - /* input object */ - char *data; - Py_ssize_t size, i; - int kind; - /* output buffer */ - _PyUnicodeWriter writer; - /* error handler */ - char *reason = "character maps to "; - PyObject *errorHandler = NULL; - PyObject *exc = NULL; - int ignore; - int res; - - if (mapping == NULL) { - PyErr_BadArgument(); - return NULL; - } - - if (PyUnicode_READY(input) == -1) - return NULL; - data = (char*)PyUnicode_DATA(input); - kind = PyUnicode_KIND(input); - size = PyUnicode_GET_LENGTH(input); - - if (size == 0) { - Py_INCREF(input); - return input; - } - - /* allocate enough for a simple 1:1 translation without - replacements, if we need more, we'll resize */ - _PyUnicodeWriter_Init(&writer); - if (_PyUnicodeWriter_Prepare(&writer, size, 127) == -1) - goto onError; - - ignore = (errors != NULL && strcmp(errors, "ignore") == 0); - - res = unicode_fast_translate(input, mapping, &writer, ignore); - if (res < 0) { - _PyUnicodeWriter_Dealloc(&writer); - return NULL; - } - if (res == 1) - return _PyUnicodeWriter_Finish(&writer); - - i = writer.pos; - while (i adjust input pointer */ - ++i; - continue; - } - - /* untranslatable character */ - collstart = i; - collend = i+1; - - /* find all untranslatable characters */ - while (collend < size) { - PyObject *x; - ch = PyUnicode_READ(kind, data, collend); - if (charmaptranslate_lookup(ch, mapping, &x)) - goto onError; - Py_XDECREF(x); - if (x != Py_None) - break; - ++collend; - } - - if (ignore) { - i = collend; - } - else { - repunicode = unicode_translate_call_errorhandler(errors, &errorHandler, - reason, input, &exc, - collstart, collend, &newpos); - if (repunicode == NULL) - goto onError; - if (_PyUnicodeWriter_WriteStr(&writer, repunicode) < 0) { - Py_DECREF(repunicode); - goto onError; - } - Py_DECREF(repunicode); - i = newpos; - } - } - Py_XDECREF(exc); - Py_XDECREF(errorHandler); - return _PyUnicodeWriter_Finish(&writer); - - onError: - _PyUnicodeWriter_Dealloc(&writer); - Py_XDECREF(exc); - Py_XDECREF(errorHandler); - return NULL; -} - -/* Deprecated. Use PyUnicode_Translate instead. */ -PyObject * -PyUnicode_TranslateCharmap(const Py_UNICODE *p, - Py_ssize_t size, - PyObject *mapping, - const char *errors) -{ - PyObject *result; - PyObject *unicode = PyUnicode_FromUnicode(p, size); - if (!unicode) - return NULL; - result = _PyUnicode_TranslateCharmap(unicode, mapping, errors); - Py_DECREF(unicode); - return result; -} - -PyObject * -PyUnicode_Translate(PyObject *str, - PyObject *mapping, - const char *errors) -{ - PyObject *result; - - str = PyUnicode_FromObject(str); - if (str == NULL) - return NULL; - result = _PyUnicode_TranslateCharmap(str, mapping, errors); - Py_DECREF(str); - return result; -} - -static Py_UCS4 -fix_decimal_and_space_to_ascii(PyObject *self) -{ - /* No need to call PyUnicode_READY(self) because this function is only - called as a callback from fixup() which does it already. */ - const Py_ssize_t len = PyUnicode_GET_LENGTH(self); - const int kind = PyUnicode_KIND(self); - void *data = PyUnicode_DATA(self); - Py_UCS4 maxchar = 127, ch, fixed; - int modified = 0; - Py_ssize_t i; - - for (i = 0; i < len; ++i) { - ch = PyUnicode_READ(kind, data, i); - fixed = 0; - if (ch > 127) { - if (Py_UNICODE_ISSPACE(ch)) - fixed = ' '; - else { - const int decimal = Py_UNICODE_TODECIMAL(ch); - if (decimal >= 0) - fixed = '0' + decimal; - } - if (fixed != 0) { - modified = 1; - maxchar = Py_MAX(maxchar, fixed); - PyUnicode_WRITE(kind, data, i, fixed); - } - else - maxchar = Py_MAX(maxchar, ch); - } - } - - return (modified) ? maxchar : 0; -} - -PyObject * -_PyUnicode_TransformDecimalAndSpaceToASCII(PyObject *unicode) -{ - if (!PyUnicode_Check(unicode)) { - PyErr_BadInternalCall(); - return NULL; - } - if (PyUnicode_READY(unicode) == -1) - return NULL; - if (PyUnicode_MAX_CHAR_VALUE(unicode) <= 127) { - /* If the string is already ASCII, just return the same string */ - Py_INCREF(unicode); - return unicode; - } - return fixup(unicode, fix_decimal_and_space_to_ascii); -} - -PyObject * -PyUnicode_TransformDecimalToASCII(Py_UNICODE *s, - Py_ssize_t length) -{ - PyObject *decimal; - Py_ssize_t i; - Py_UCS4 maxchar; - enum PyUnicode_Kind kind; - void *data; - - maxchar = 127; - for (i = 0; i < length; i++) { - Py_UCS4 ch = s[i]; - if (ch > 127) { - int decimal = Py_UNICODE_TODECIMAL(ch); - if (decimal >= 0) - ch = '0' + decimal; - maxchar = Py_MAX(maxchar, ch); - } - } - - /* Copy to a new string */ - decimal = PyUnicode_New(length, maxchar); - if (decimal == NULL) - return decimal; - kind = PyUnicode_KIND(decimal); - data = PyUnicode_DATA(decimal); - /* Iterate over code points */ - for (i = 0; i < length; i++) { - Py_UCS4 ch = s[i]; - if (ch > 127) { - int decimal = Py_UNICODE_TODECIMAL(ch); - if (decimal >= 0) - ch = '0' + decimal; - } - PyUnicode_WRITE(kind, data, i, ch); - } - return unicode_result(decimal); -} -/* --- Decimal Encoder ---------------------------------------------------- */ - -int -PyUnicode_EncodeDecimal(Py_UNICODE *s, - Py_ssize_t length, - char *output, - const char *errors) -{ - PyObject *unicode; - Py_ssize_t i; - enum PyUnicode_Kind kind; - void *data; - - if (output == NULL) { - PyErr_BadArgument(); - return -1; - } - - unicode = PyUnicode_FromUnicode(s, length); - if (unicode == NULL) - return -1; - - if (PyUnicode_READY(unicode) == -1) { - Py_DECREF(unicode); - return -1; - } - kind = PyUnicode_KIND(unicode); - data = PyUnicode_DATA(unicode); - - for (i=0; i < length; ) { - PyObject *exc; - Py_UCS4 ch; - int decimal; - Py_ssize_t startpos; - - ch = PyUnicode_READ(kind, data, i); - - if (Py_UNICODE_ISSPACE(ch)) { - *output++ = ' '; - i++; - continue; - } - decimal = Py_UNICODE_TODECIMAL(ch); - if (decimal >= 0) { - *output++ = '0' + decimal; - i++; - continue; - } - if (0 < ch && ch < 256) { - *output++ = (char)ch; - i++; - continue; - } - - startpos = i; - exc = NULL; - raise_encode_exception(&exc, "decimal", unicode, - startpos, startpos+1, - "invalid decimal Unicode string"); - Py_XDECREF(exc); - Py_DECREF(unicode); - return -1; - } - /* 0-terminate the output string */ - *output++ = '\0'; - Py_DECREF(unicode); - return 0; -} - -/* --- Helpers ------------------------------------------------------------ */ - -/* helper macro to fixup start/end slice values */ -#define ADJUST_INDICES(start, end, len) \ - if (end > len) \ - end = len; \ - else if (end < 0) { \ - end += len; \ - if (end < 0) \ - end = 0; \ - } \ - if (start < 0) { \ - start += len; \ - if (start < 0) \ - start = 0; \ - } - -static Py_ssize_t -any_find_slice(int direction, PyObject* s1, PyObject* s2, - Py_ssize_t start, - Py_ssize_t end) -{ - int kind1, kind2; - void *buf1, *buf2; - Py_ssize_t len1, len2, result; - - kind1 = PyUnicode_KIND(s1); - kind2 = PyUnicode_KIND(s2); - if (kind1 < kind2) - return -1; - - len1 = PyUnicode_GET_LENGTH(s1); - len2 = PyUnicode_GET_LENGTH(s2); - ADJUST_INDICES(start, end, len1); - if (end - start < len2) - return -1; - - buf1 = PyUnicode_DATA(s1); - buf2 = PyUnicode_DATA(s2); - if (len2 == 1) { - Py_UCS4 ch = PyUnicode_READ(kind2, buf2, 0); - result = findchar((const char *)buf1 + kind1*start, - kind1, end - start, ch, direction); - if (result == -1) - return -1; - else - return start + result; - } - - if (kind2 != kind1) { - buf2 = _PyUnicode_AsKind(s2, kind1); - if (!buf2) - return -2; - } - - if (direction > 0) { - switch (kind1) { - case PyUnicode_1BYTE_KIND: - if (PyUnicode_IS_ASCII(s1) && PyUnicode_IS_ASCII(s2)) - result = asciilib_find_slice(buf1, len1, buf2, len2, start, end); - else - result = ucs1lib_find_slice(buf1, len1, buf2, len2, start, end); - break; - case PyUnicode_2BYTE_KIND: - result = ucs2lib_find_slice(buf1, len1, buf2, len2, start, end); - break; - case PyUnicode_4BYTE_KIND: - result = ucs4lib_find_slice(buf1, len1, buf2, len2, start, end); - break; - default: - assert(0); result = -2; - } - } - else { - switch (kind1) { - case PyUnicode_1BYTE_KIND: - if (PyUnicode_IS_ASCII(s1) && PyUnicode_IS_ASCII(s2)) - result = asciilib_rfind_slice(buf1, len1, buf2, len2, start, end); - else - result = ucs1lib_rfind_slice(buf1, len1, buf2, len2, start, end); - break; - case PyUnicode_2BYTE_KIND: - result = ucs2lib_rfind_slice(buf1, len1, buf2, len2, start, end); - break; - case PyUnicode_4BYTE_KIND: - result = ucs4lib_rfind_slice(buf1, len1, buf2, len2, start, end); - break; - default: - assert(0); result = -2; - } - } - - if (kind2 != kind1) - PyMem_Free(buf2); - - return result; -} - -Py_ssize_t -_PyUnicode_InsertThousandsGrouping( - PyObject *unicode, Py_ssize_t index, - Py_ssize_t n_buffer, - void *digits, Py_ssize_t n_digits, - Py_ssize_t min_width, - const char *grouping, PyObject *thousands_sep, - Py_UCS4 *maxchar) -{ - unsigned int kind, thousands_sep_kind; - char *data, *thousands_sep_data; - Py_ssize_t thousands_sep_len; - Py_ssize_t len; - - if (unicode != NULL) { - kind = PyUnicode_KIND(unicode); - data = (char *) PyUnicode_DATA(unicode) + index * kind; - } - else { - kind = PyUnicode_1BYTE_KIND; - data = NULL; - } - thousands_sep_kind = PyUnicode_KIND(thousands_sep); - thousands_sep_data = PyUnicode_DATA(thousands_sep); - thousands_sep_len = PyUnicode_GET_LENGTH(thousands_sep); - if (unicode != NULL && thousands_sep_kind != kind) { - if (thousands_sep_kind < kind) { - thousands_sep_data = _PyUnicode_AsKind(thousands_sep, kind); - if (!thousands_sep_data) - return -1; - } - else { - data = _PyUnicode_AsKind(unicode, thousands_sep_kind); - if (!data) - return -1; - } - } - - switch (kind) { - case PyUnicode_1BYTE_KIND: - if (unicode != NULL && PyUnicode_IS_ASCII(unicode)) - len = asciilib_InsertThousandsGrouping( - (Py_UCS1 *) data, n_buffer, (Py_UCS1 *) digits, n_digits, - min_width, grouping, - (Py_UCS1 *) thousands_sep_data, thousands_sep_len); - else - len = ucs1lib_InsertThousandsGrouping( - (Py_UCS1*)data, n_buffer, (Py_UCS1*)digits, n_digits, - min_width, grouping, - (Py_UCS1 *) thousands_sep_data, thousands_sep_len); - break; - case PyUnicode_2BYTE_KIND: - len = ucs2lib_InsertThousandsGrouping( - (Py_UCS2 *) data, n_buffer, (Py_UCS2 *) digits, n_digits, - min_width, grouping, - (Py_UCS2 *) thousands_sep_data, thousands_sep_len); - break; - case PyUnicode_4BYTE_KIND: - len = ucs4lib_InsertThousandsGrouping( - (Py_UCS4 *) data, n_buffer, (Py_UCS4 *) digits, n_digits, - min_width, grouping, - (Py_UCS4 *) thousands_sep_data, thousands_sep_len); - break; - default: - assert(0); - return -1; - } - if (unicode != NULL && thousands_sep_kind != kind) { - if (thousands_sep_kind < kind) - PyMem_Free(thousands_sep_data); - else - PyMem_Free(data); - } - if (unicode == NULL) { - *maxchar = 127; - if (len != n_digits) { - *maxchar = Py_MAX(*maxchar, - PyUnicode_MAX_CHAR_VALUE(thousands_sep)); - } - } - return len; -} - - -Py_ssize_t -PyUnicode_Count(PyObject *str, - PyObject *substr, - Py_ssize_t start, - Py_ssize_t end) -{ - Py_ssize_t result; - PyObject* str_obj; - PyObject* sub_obj; - int kind1, kind2; - void *buf1 = NULL, *buf2 = NULL; - Py_ssize_t len1, len2; - - str_obj = PyUnicode_FromObject(str); - if (!str_obj) - return -1; - sub_obj = PyUnicode_FromObject(substr); - if (!sub_obj) { - Py_DECREF(str_obj); - return -1; - } - if (PyUnicode_READY(sub_obj) == -1 || PyUnicode_READY(str_obj) == -1) { - Py_DECREF(sub_obj); - Py_DECREF(str_obj); - return -1; - } - - kind1 = PyUnicode_KIND(str_obj); - kind2 = PyUnicode_KIND(sub_obj); - if (kind1 < kind2) { - Py_DECREF(sub_obj); - Py_DECREF(str_obj); - return 0; - } - - len1 = PyUnicode_GET_LENGTH(str_obj); - len2 = PyUnicode_GET_LENGTH(sub_obj); - ADJUST_INDICES(start, end, len1); - if (end - start < len2) { - Py_DECREF(sub_obj); - Py_DECREF(str_obj); - return 0; - } - - buf1 = PyUnicode_DATA(str_obj); - buf2 = PyUnicode_DATA(sub_obj); - if (kind2 != kind1) { - buf2 = _PyUnicode_AsKind(sub_obj, kind1); - if (!buf2) - goto onError; - } - - switch (kind1) { - case PyUnicode_1BYTE_KIND: - if (PyUnicode_IS_ASCII(str_obj) && PyUnicode_IS_ASCII(sub_obj)) - result = asciilib_count( - ((Py_UCS1*)buf1) + start, end - start, - buf2, len2, PY_SSIZE_T_MAX - ); - else - result = ucs1lib_count( - ((Py_UCS1*)buf1) + start, end - start, - buf2, len2, PY_SSIZE_T_MAX - ); - break; - case PyUnicode_2BYTE_KIND: - result = ucs2lib_count( - ((Py_UCS2*)buf1) + start, end - start, - buf2, len2, PY_SSIZE_T_MAX - ); - break; - case PyUnicode_4BYTE_KIND: - result = ucs4lib_count( - ((Py_UCS4*)buf1) + start, end - start, - buf2, len2, PY_SSIZE_T_MAX - ); - break; - default: - assert(0); result = 0; - } - - Py_DECREF(sub_obj); - Py_DECREF(str_obj); - - if (kind2 != kind1) - PyMem_Free(buf2); - - return result; - onError: - Py_DECREF(sub_obj); - Py_DECREF(str_obj); - if (kind2 != kind1 && buf2) - PyMem_Free(buf2); - return -1; -} - -Py_ssize_t -PyUnicode_Find(PyObject *str, - PyObject *sub, - Py_ssize_t start, - Py_ssize_t end, - int direction) -{ - Py_ssize_t result; - - str = PyUnicode_FromObject(str); - if (!str) - return -2; - sub = PyUnicode_FromObject(sub); - if (!sub) { - Py_DECREF(str); - return -2; - } - if (PyUnicode_READY(sub) == -1 || PyUnicode_READY(str) == -1) { - Py_DECREF(sub); - Py_DECREF(str); - return -2; - } - - result = any_find_slice(direction, - str, sub, start, end - ); - - Py_DECREF(str); - Py_DECREF(sub); - - return result; -} - -Py_ssize_t -PyUnicode_FindChar(PyObject *str, Py_UCS4 ch, - Py_ssize_t start, Py_ssize_t end, - int direction) -{ - int kind; - Py_ssize_t result; - if (PyUnicode_READY(str) == -1) - return -2; - if (start < 0 || end < 0) { - PyErr_SetString(PyExc_IndexError, "string index out of range"); - return -2; - } - if (end > PyUnicode_GET_LENGTH(str)) - end = PyUnicode_GET_LENGTH(str); - if (start >= end) - return -1; - kind = PyUnicode_KIND(str); - result = findchar(PyUnicode_1BYTE_DATA(str) + kind*start, - kind, end-start, ch, direction); - if (result == -1) - return -1; - else - return start + result; -} - -static int -tailmatch(PyObject *self, - PyObject *substring, - Py_ssize_t start, - Py_ssize_t end, - int direction) -{ - int kind_self; - int kind_sub; - void *data_self; - void *data_sub; - Py_ssize_t offset; - Py_ssize_t i; - Py_ssize_t end_sub; - - if (PyUnicode_READY(self) == -1 || - PyUnicode_READY(substring) == -1) - return -1; - - if (PyUnicode_GET_LENGTH(substring) == 0) - return 1; - - ADJUST_INDICES(start, end, PyUnicode_GET_LENGTH(self)); - end -= PyUnicode_GET_LENGTH(substring); - if (end < start) - return 0; - - kind_self = PyUnicode_KIND(self); - data_self = PyUnicode_DATA(self); - kind_sub = PyUnicode_KIND(substring); - data_sub = PyUnicode_DATA(substring); - end_sub = PyUnicode_GET_LENGTH(substring) - 1; - - if (direction > 0) - offset = end; - else - offset = start; - - if (PyUnicode_READ(kind_self, data_self, offset) == - PyUnicode_READ(kind_sub, data_sub, 0) && - PyUnicode_READ(kind_self, data_self, offset + end_sub) == - PyUnicode_READ(kind_sub, data_sub, end_sub)) { - /* If both are of the same kind, memcmp is sufficient */ - if (kind_self == kind_sub) { - return ! memcmp((char *)data_self + - (offset * PyUnicode_KIND(substring)), - data_sub, - PyUnicode_GET_LENGTH(substring) * - PyUnicode_KIND(substring)); - } - /* otherwise we have to compare each character by first accesing it */ - else { - /* We do not need to compare 0 and len(substring)-1 because - the if statement above ensured already that they are equal - when we end up here. */ - for (i = 1; i < end_sub; ++i) { - if (PyUnicode_READ(kind_self, data_self, offset + i) != - PyUnicode_READ(kind_sub, data_sub, i)) - return 0; - } - return 1; - } - } - - return 0; -} - -Py_ssize_t -PyUnicode_Tailmatch(PyObject *str, - PyObject *substr, - Py_ssize_t start, - Py_ssize_t end, - int direction) -{ - Py_ssize_t result; - - str = PyUnicode_FromObject(str); - if (str == NULL) - return -1; - substr = PyUnicode_FromObject(substr); - if (substr == NULL) { - Py_DECREF(str); - return -1; - } - - result = tailmatch(str, substr, - start, end, direction); - Py_DECREF(str); - Py_DECREF(substr); - return result; -} - -/* Apply fixfct filter to the Unicode object self and return a - reference to the modified object */ - -static PyObject * -fixup(PyObject *self, - Py_UCS4 (*fixfct)(PyObject *s)) -{ - PyObject *u; - Py_UCS4 maxchar_old, maxchar_new = 0; - PyObject *v; - - u = _PyUnicode_Copy(self); - if (u == NULL) - return NULL; - maxchar_old = PyUnicode_MAX_CHAR_VALUE(u); - - /* fix functions return the new maximum character in a string, - if the kind of the resulting unicode object does not change, - everything is fine. Otherwise we need to change the string kind - and re-run the fix function. */ - maxchar_new = fixfct(u); - - if (maxchar_new == 0) { - /* no changes */; - if (PyUnicode_CheckExact(self)) { - Py_DECREF(u); - Py_INCREF(self); - return self; - } - else - return u; - } - - maxchar_new = align_maxchar(maxchar_new); - - if (maxchar_new == maxchar_old) - return u; - - /* In case the maximum character changed, we need to - convert the string to the new category. */ - v = PyUnicode_New(PyUnicode_GET_LENGTH(self), maxchar_new); - if (v == NULL) { - Py_DECREF(u); - return NULL; - } - if (maxchar_new > maxchar_old) { - /* If the maxchar increased so that the kind changed, not all - characters are representable anymore and we need to fix the - string again. This only happens in very few cases. */ - _PyUnicode_FastCopyCharacters(v, 0, - self, 0, PyUnicode_GET_LENGTH(self)); - maxchar_old = fixfct(v); - assert(maxchar_old > 0 && maxchar_old <= maxchar_new); - } - else { - _PyUnicode_FastCopyCharacters(v, 0, - u, 0, PyUnicode_GET_LENGTH(self)); - } - Py_DECREF(u); - assert(_PyUnicode_CheckConsistency(v, 1)); - return v; -} - -static PyObject * -ascii_upper_or_lower(PyObject *self, int lower) -{ - Py_ssize_t len = PyUnicode_GET_LENGTH(self); - char *resdata, *data = PyUnicode_DATA(self); - PyObject *res; - - res = PyUnicode_New(len, 127); - if (res == NULL) - return NULL; - resdata = PyUnicode_DATA(res); - if (lower) - _Py_bytes_lower(resdata, data, len); - else - _Py_bytes_upper(resdata, data, len); - return res; -} - -static Py_UCS4 -handle_capital_sigma(int kind, void *data, Py_ssize_t length, Py_ssize_t i) -{ - Py_ssize_t j; - int final_sigma; - Py_UCS4 c = 0; /* initialize to prevent gcc warning */ - /* U+03A3 is in the Final_Sigma context when, it is found like this: - - \p{cased}\p{case-ignorable}*U+03A3!(\p{case-ignorable}*\p{cased}) - - where ! is a negation and \p{xxx} is a character with property xxx. - */ - for (j = i - 1; j >= 0; j--) { - c = PyUnicode_READ(kind, data, j); - if (!_PyUnicode_IsCaseIgnorable(c)) - break; - } - final_sigma = j >= 0 && _PyUnicode_IsCased(c); - if (final_sigma) { - for (j = i + 1; j < length; j++) { - c = PyUnicode_READ(kind, data, j); - if (!_PyUnicode_IsCaseIgnorable(c)) - break; - } - final_sigma = j == length || !_PyUnicode_IsCased(c); - } - return (final_sigma) ? 0x3C2 : 0x3C3; -} - -static int -lower_ucs4(int kind, void *data, Py_ssize_t length, Py_ssize_t i, - Py_UCS4 c, Py_UCS4 *mapped) -{ - /* Obscure special case. */ - if (c == 0x3A3) { - mapped[0] = handle_capital_sigma(kind, data, length, i); - return 1; - } - return _PyUnicode_ToLowerFull(c, mapped); -} - -static Py_ssize_t -do_capitalize(int kind, void *data, Py_ssize_t length, Py_UCS4 *res, Py_UCS4 *maxchar) -{ - Py_ssize_t i, k = 0; - int n_res, j; - Py_UCS4 c, mapped[3]; - - c = PyUnicode_READ(kind, data, 0); - n_res = _PyUnicode_ToUpperFull(c, mapped); - for (j = 0; j < n_res; j++) { - *maxchar = Py_MAX(*maxchar, mapped[j]); - res[k++] = mapped[j]; - } - for (i = 1; i < length; i++) { - c = PyUnicode_READ(kind, data, i); - n_res = lower_ucs4(kind, data, length, i, c, mapped); - for (j = 0; j < n_res; j++) { - *maxchar = Py_MAX(*maxchar, mapped[j]); - res[k++] = mapped[j]; - } - } - return k; -} - -static Py_ssize_t -do_swapcase(int kind, void *data, Py_ssize_t length, Py_UCS4 *res, Py_UCS4 *maxchar) { - Py_ssize_t i, k = 0; - - for (i = 0; i < length; i++) { - Py_UCS4 c = PyUnicode_READ(kind, data, i), mapped[3]; - int n_res, j; - if (Py_UNICODE_ISUPPER(c)) { - n_res = lower_ucs4(kind, data, length, i, c, mapped); - } - else if (Py_UNICODE_ISLOWER(c)) { - n_res = _PyUnicode_ToUpperFull(c, mapped); - } - else { - n_res = 1; - mapped[0] = c; - } - for (j = 0; j < n_res; j++) { - *maxchar = Py_MAX(*maxchar, mapped[j]); - res[k++] = mapped[j]; - } - } - return k; -} - -static Py_ssize_t -do_upper_or_lower(int kind, void *data, Py_ssize_t length, Py_UCS4 *res, - Py_UCS4 *maxchar, int lower) -{ - Py_ssize_t i, k = 0; - - for (i = 0; i < length; i++) { - Py_UCS4 c = PyUnicode_READ(kind, data, i), mapped[3]; - int n_res, j; - if (lower) - n_res = lower_ucs4(kind, data, length, i, c, mapped); - else - n_res = _PyUnicode_ToUpperFull(c, mapped); - for (j = 0; j < n_res; j++) { - *maxchar = Py_MAX(*maxchar, mapped[j]); - res[k++] = mapped[j]; - } - } - return k; -} - -static Py_ssize_t -do_upper(int kind, void *data, Py_ssize_t length, Py_UCS4 *res, Py_UCS4 *maxchar) -{ - return do_upper_or_lower(kind, data, length, res, maxchar, 0); -} - -static Py_ssize_t -do_lower(int kind, void *data, Py_ssize_t length, Py_UCS4 *res, Py_UCS4 *maxchar) -{ - return do_upper_or_lower(kind, data, length, res, maxchar, 1); -} - -static Py_ssize_t -do_casefold(int kind, void *data, Py_ssize_t length, Py_UCS4 *res, Py_UCS4 *maxchar) -{ - Py_ssize_t i, k = 0; - - for (i = 0; i < length; i++) { - Py_UCS4 c = PyUnicode_READ(kind, data, i); - Py_UCS4 mapped[3]; - int j, n_res = _PyUnicode_ToFoldedFull(c, mapped); - for (j = 0; j < n_res; j++) { - *maxchar = Py_MAX(*maxchar, mapped[j]); - res[k++] = mapped[j]; - } - } - return k; -} - -static Py_ssize_t -do_title(int kind, void *data, Py_ssize_t length, Py_UCS4 *res, Py_UCS4 *maxchar) -{ - Py_ssize_t i, k = 0; - int previous_is_cased; - - previous_is_cased = 0; - for (i = 0; i < length; i++) { - const Py_UCS4 c = PyUnicode_READ(kind, data, i); - Py_UCS4 mapped[3]; - int n_res, j; - - if (previous_is_cased) - n_res = lower_ucs4(kind, data, length, i, c, mapped); - else - n_res = _PyUnicode_ToTitleFull(c, mapped); - - for (j = 0; j < n_res; j++) { - *maxchar = Py_MAX(*maxchar, mapped[j]); - res[k++] = mapped[j]; - } - - previous_is_cased = _PyUnicode_IsCased(c); - } - return k; -} - -static PyObject * -case_operation(PyObject *self, - Py_ssize_t (*perform)(int, void *, Py_ssize_t, Py_UCS4 *, Py_UCS4 *)) -{ - PyObject *res = NULL; - Py_ssize_t length, newlength = 0; - int kind, outkind; - void *data, *outdata; - Py_UCS4 maxchar = 0, *tmp, *tmpend; - - assert(PyUnicode_IS_READY(self)); - - kind = PyUnicode_KIND(self); - data = PyUnicode_DATA(self); - length = PyUnicode_GET_LENGTH(self); - if ((size_t) length > PY_SSIZE_T_MAX / (3 * sizeof(Py_UCS4))) { - PyErr_SetString(PyExc_OverflowError, "string is too long"); - return NULL; - } - tmp = PyMem_MALLOC(sizeof(Py_UCS4) * 3 * length); - if (tmp == NULL) - return PyErr_NoMemory(); - newlength = perform(kind, data, length, tmp, &maxchar); - res = PyUnicode_New(newlength, maxchar); - if (res == NULL) - goto leave; - tmpend = tmp + newlength; - outdata = PyUnicode_DATA(res); - outkind = PyUnicode_KIND(res); - switch (outkind) { - case PyUnicode_1BYTE_KIND: - _PyUnicode_CONVERT_BYTES(Py_UCS4, Py_UCS1, tmp, tmpend, outdata); - break; - case PyUnicode_2BYTE_KIND: - _PyUnicode_CONVERT_BYTES(Py_UCS4, Py_UCS2, tmp, tmpend, outdata); - break; - case PyUnicode_4BYTE_KIND: - memcpy(outdata, tmp, sizeof(Py_UCS4) * newlength); - break; - default: - assert(0); - break; - } - leave: - PyMem_FREE(tmp); - return res; -} - -PyObject * -PyUnicode_Join(PyObject *separator, PyObject *seq) -{ - PyObject *sep = NULL; - Py_ssize_t seplen; - PyObject *res = NULL; /* the result */ - PyObject *fseq; /* PySequence_Fast(seq) */ - Py_ssize_t seqlen; /* len(fseq) -- number of items in sequence */ - PyObject **items; - PyObject *item; - Py_ssize_t sz, i, res_offset; - Py_UCS4 maxchar; - Py_UCS4 item_maxchar; - int use_memcpy; - unsigned char *res_data = NULL, *sep_data = NULL; - PyObject *last_obj; - unsigned int kind = 0; - - fseq = PySequence_Fast(seq, "can only join an iterable"); - if (fseq == NULL) { - return NULL; - } - - /* NOTE: the following code can't call back into Python code, - * so we are sure that fseq won't be mutated. - */ - - seqlen = PySequence_Fast_GET_SIZE(fseq); - /* If empty sequence, return u"". */ - if (seqlen == 0) { - Py_DECREF(fseq); - _Py_RETURN_UNICODE_EMPTY(); - } - - /* If singleton sequence with an exact Unicode, return that. */ - last_obj = NULL; - items = PySequence_Fast_ITEMS(fseq); - if (seqlen == 1) { - if (PyUnicode_CheckExact(items[0])) { - res = items[0]; - Py_INCREF(res); - Py_DECREF(fseq); - return res; - } - seplen = 0; - maxchar = 0; - } - else { - /* Set up sep and seplen */ - if (separator == NULL) { - /* fall back to a blank space separator */ - sep = PyUnicode_FromOrdinal(' '); - if (!sep) - goto onError; - seplen = 1; - maxchar = 32; - } - else { - if (!PyUnicode_Check(separator)) { - PyErr_Format(PyExc_TypeError, - "separator: expected str instance," - " %.80s found", - Py_TYPE(separator)->tp_name); - goto onError; - } - if (PyUnicode_READY(separator)) - goto onError; - sep = separator; - seplen = PyUnicode_GET_LENGTH(separator); - maxchar = PyUnicode_MAX_CHAR_VALUE(separator); - /* inc refcount to keep this code path symmetric with the - above case of a blank separator */ - Py_INCREF(sep); - } - last_obj = sep; - } - - /* There are at least two things to join, or else we have a subclass - * of str in the sequence. - * Do a pre-pass to figure out the total amount of space we'll - * need (sz), and see whether all argument are strings. - */ - sz = 0; -#ifdef Py_DEBUG - use_memcpy = 0; -#else - use_memcpy = 1; -#endif - for (i = 0; i < seqlen; i++) { - const Py_ssize_t old_sz = sz; - item = items[i]; - if (!PyUnicode_Check(item)) { - PyErr_Format(PyExc_TypeError, - "sequence item %zd: expected str instance," - " %.80s found", - i, Py_TYPE(item)->tp_name); - goto onError; - } - if (PyUnicode_READY(item) == -1) - goto onError; - sz += PyUnicode_GET_LENGTH(item); - item_maxchar = PyUnicode_MAX_CHAR_VALUE(item); - maxchar = Py_MAX(maxchar, item_maxchar); - if (i != 0) - sz += seplen; - if (sz < old_sz || sz > PY_SSIZE_T_MAX) { - PyErr_SetString(PyExc_OverflowError, - "join() result is too long for a Python string"); - goto onError; - } - if (use_memcpy && last_obj != NULL) { - if (PyUnicode_KIND(last_obj) != PyUnicode_KIND(item)) - use_memcpy = 0; - } - last_obj = item; - } - - res = PyUnicode_New(sz, maxchar); - if (res == NULL) - goto onError; - - /* Catenate everything. */ -#ifdef Py_DEBUG - use_memcpy = 0; -#else - if (use_memcpy) { - res_data = PyUnicode_1BYTE_DATA(res); - kind = PyUnicode_KIND(res); - if (seplen != 0) - sep_data = PyUnicode_1BYTE_DATA(sep); - } -#endif - if (use_memcpy) { - for (i = 0; i < seqlen; ++i) { - Py_ssize_t itemlen; - item = items[i]; - - /* Copy item, and maybe the separator. */ - if (i && seplen != 0) { - Py_MEMCPY(res_data, - sep_data, - kind * seplen); - res_data += kind * seplen; - } - - itemlen = PyUnicode_GET_LENGTH(item); - if (itemlen != 0) { - Py_MEMCPY(res_data, - PyUnicode_DATA(item), - kind * itemlen); - res_data += kind * itemlen; - } - } - assert(res_data == PyUnicode_1BYTE_DATA(res) - + kind * PyUnicode_GET_LENGTH(res)); - } - else { - for (i = 0, res_offset = 0; i < seqlen; ++i) { - Py_ssize_t itemlen; - item = items[i]; - - /* Copy item, and maybe the separator. */ - if (i && seplen != 0) { - _PyUnicode_FastCopyCharacters(res, res_offset, sep, 0, seplen); - res_offset += seplen; - } - - itemlen = PyUnicode_GET_LENGTH(item); - if (itemlen != 0) { - _PyUnicode_FastCopyCharacters(res, res_offset, item, 0, itemlen); - res_offset += itemlen; - } - } - assert(res_offset == PyUnicode_GET_LENGTH(res)); - } - - Py_DECREF(fseq); - Py_XDECREF(sep); - assert(_PyUnicode_CheckConsistency(res, 1)); - return res; - - onError: - Py_DECREF(fseq); - Py_XDECREF(sep); - Py_XDECREF(res); - return NULL; -} - -#define FILL(kind, data, value, start, length) \ - do { \ - Py_ssize_t i_ = 0; \ - assert(kind != PyUnicode_WCHAR_KIND); \ - switch ((kind)) { \ - case PyUnicode_1BYTE_KIND: { \ - unsigned char * to_ = (unsigned char *)((data)) + (start); \ - memset(to_, (unsigned char)value, (length)); \ - break; \ - } \ - case PyUnicode_2BYTE_KIND: { \ - Py_UCS2 * to_ = (Py_UCS2 *)((data)) + (start); \ - for (; i_ < (length); ++i_, ++to_) *to_ = (value); \ - break; \ - } \ - case PyUnicode_4BYTE_KIND: { \ - Py_UCS4 * to_ = (Py_UCS4 *)((data)) + (start); \ - for (; i_ < (length); ++i_, ++to_) *to_ = (value); \ - break; \ - } \ - default: assert(0); \ - } \ - } while (0) - -void -_PyUnicode_FastFill(PyObject *unicode, Py_ssize_t start, Py_ssize_t length, - Py_UCS4 fill_char) -{ - const enum PyUnicode_Kind kind = PyUnicode_KIND(unicode); - const void *data = PyUnicode_DATA(unicode); - assert(PyUnicode_IS_READY(unicode)); - assert(unicode_modifiable(unicode)); - assert(fill_char <= PyUnicode_MAX_CHAR_VALUE(unicode)); - assert(start >= 0); - assert(start + length <= PyUnicode_GET_LENGTH(unicode)); - FILL(kind, data, fill_char, start, length); -} - -Py_ssize_t -PyUnicode_Fill(PyObject *unicode, Py_ssize_t start, Py_ssize_t length, - Py_UCS4 fill_char) -{ - Py_ssize_t maxlen; - - if (!PyUnicode_Check(unicode)) { - PyErr_BadInternalCall(); - return -1; - } - if (PyUnicode_READY(unicode) == -1) - return -1; - if (unicode_check_modifiable(unicode)) - return -1; - - if (start < 0) { - PyErr_SetString(PyExc_IndexError, "string index out of range"); - return -1; - } - if (fill_char > PyUnicode_MAX_CHAR_VALUE(unicode)) { - PyErr_SetString(PyExc_ValueError, - "fill character is bigger than " - "the string maximum character"); - return -1; - } - - maxlen = PyUnicode_GET_LENGTH(unicode) - start; - length = Py_MIN(maxlen, length); - if (length <= 0) - return 0; - - _PyUnicode_FastFill(unicode, start, length, fill_char); - return length; -} - -static PyObject * -pad(PyObject *self, - Py_ssize_t left, - Py_ssize_t right, - Py_UCS4 fill) -{ - PyObject *u; - Py_UCS4 maxchar; - int kind; - void *data; - - if (left < 0) - left = 0; - if (right < 0) - right = 0; - - if (left == 0 && right == 0) - return unicode_result_unchanged(self); - - if (left > PY_SSIZE_T_MAX - _PyUnicode_LENGTH(self) || - right > PY_SSIZE_T_MAX - (left + _PyUnicode_LENGTH(self))) { - PyErr_SetString(PyExc_OverflowError, "padded string is too long"); - return NULL; - } - maxchar = PyUnicode_MAX_CHAR_VALUE(self); - maxchar = Py_MAX(maxchar, fill); - u = PyUnicode_New(left + _PyUnicode_LENGTH(self) + right, maxchar); - if (!u) - return NULL; - - kind = PyUnicode_KIND(u); - data = PyUnicode_DATA(u); - if (left) - FILL(kind, data, fill, 0, left); - if (right) - FILL(kind, data, fill, left + _PyUnicode_LENGTH(self), right); - _PyUnicode_FastCopyCharacters(u, left, self, 0, _PyUnicode_LENGTH(self)); - assert(_PyUnicode_CheckConsistency(u, 1)); - return u; -} - -PyObject * -PyUnicode_Splitlines(PyObject *string, int keepends) -{ - PyObject *list; - - string = PyUnicode_FromObject(string); - if (string == NULL) - return NULL; - if (PyUnicode_READY(string) == -1) { - Py_DECREF(string); - return NULL; - } - - switch (PyUnicode_KIND(string)) { - case PyUnicode_1BYTE_KIND: - if (PyUnicode_IS_ASCII(string)) - list = asciilib_splitlines( - string, PyUnicode_1BYTE_DATA(string), - PyUnicode_GET_LENGTH(string), keepends); - else - list = ucs1lib_splitlines( - string, PyUnicode_1BYTE_DATA(string), - PyUnicode_GET_LENGTH(string), keepends); - break; - case PyUnicode_2BYTE_KIND: - list = ucs2lib_splitlines( - string, PyUnicode_2BYTE_DATA(string), - PyUnicode_GET_LENGTH(string), keepends); - break; - case PyUnicode_4BYTE_KIND: - list = ucs4lib_splitlines( - string, PyUnicode_4BYTE_DATA(string), - PyUnicode_GET_LENGTH(string), keepends); - break; - default: - assert(0); - list = 0; - } - Py_DECREF(string); - return list; -} - -static PyObject * -split(PyObject *self, - PyObject *substring, - Py_ssize_t maxcount) -{ - int kind1, kind2; - void *buf1, *buf2; - Py_ssize_t len1, len2; - PyObject* out; - - if (maxcount < 0) - maxcount = PY_SSIZE_T_MAX; - - if (PyUnicode_READY(self) == -1) - return NULL; - - if (substring == NULL) - switch (PyUnicode_KIND(self)) { - case PyUnicode_1BYTE_KIND: - if (PyUnicode_IS_ASCII(self)) - return asciilib_split_whitespace( - self, PyUnicode_1BYTE_DATA(self), - PyUnicode_GET_LENGTH(self), maxcount - ); - else - return ucs1lib_split_whitespace( - self, PyUnicode_1BYTE_DATA(self), - PyUnicode_GET_LENGTH(self), maxcount - ); - case PyUnicode_2BYTE_KIND: - return ucs2lib_split_whitespace( - self, PyUnicode_2BYTE_DATA(self), - PyUnicode_GET_LENGTH(self), maxcount - ); - case PyUnicode_4BYTE_KIND: - return ucs4lib_split_whitespace( - self, PyUnicode_4BYTE_DATA(self), - PyUnicode_GET_LENGTH(self), maxcount - ); - default: - assert(0); - return NULL; - } - - if (PyUnicode_READY(substring) == -1) - return NULL; - - kind1 = PyUnicode_KIND(self); - kind2 = PyUnicode_KIND(substring); - len1 = PyUnicode_GET_LENGTH(self); - len2 = PyUnicode_GET_LENGTH(substring); - if (kind1 < kind2 || len1 < len2) { - out = PyList_New(1); - if (out == NULL) - return NULL; - Py_INCREF(self); - PyList_SET_ITEM(out, 0, self); - return out; - } - buf1 = PyUnicode_DATA(self); - buf2 = PyUnicode_DATA(substring); - if (kind2 != kind1) { - buf2 = _PyUnicode_AsKind(substring, kind1); - if (!buf2) - return NULL; - } - - switch (kind1) { - case PyUnicode_1BYTE_KIND: - if (PyUnicode_IS_ASCII(self) && PyUnicode_IS_ASCII(substring)) - out = asciilib_split( - self, buf1, len1, buf2, len2, maxcount); - else - out = ucs1lib_split( - self, buf1, len1, buf2, len2, maxcount); - break; - case PyUnicode_2BYTE_KIND: - out = ucs2lib_split( - self, buf1, len1, buf2, len2, maxcount); - break; - case PyUnicode_4BYTE_KIND: - out = ucs4lib_split( - self, buf1, len1, buf2, len2, maxcount); - break; - default: - out = NULL; - } - if (kind2 != kind1) - PyMem_Free(buf2); - return out; -} - -static PyObject * -rsplit(PyObject *self, - PyObject *substring, - Py_ssize_t maxcount) -{ - int kind1, kind2; - void *buf1, *buf2; - Py_ssize_t len1, len2; - PyObject* out; - - if (maxcount < 0) - maxcount = PY_SSIZE_T_MAX; - - if (PyUnicode_READY(self) == -1) - return NULL; - - if (substring == NULL) - switch (PyUnicode_KIND(self)) { - case PyUnicode_1BYTE_KIND: - if (PyUnicode_IS_ASCII(self)) - return asciilib_rsplit_whitespace( - self, PyUnicode_1BYTE_DATA(self), - PyUnicode_GET_LENGTH(self), maxcount - ); - else - return ucs1lib_rsplit_whitespace( - self, PyUnicode_1BYTE_DATA(self), - PyUnicode_GET_LENGTH(self), maxcount - ); - case PyUnicode_2BYTE_KIND: - return ucs2lib_rsplit_whitespace( - self, PyUnicode_2BYTE_DATA(self), - PyUnicode_GET_LENGTH(self), maxcount - ); - case PyUnicode_4BYTE_KIND: - return ucs4lib_rsplit_whitespace( - self, PyUnicode_4BYTE_DATA(self), - PyUnicode_GET_LENGTH(self), maxcount - ); - default: - assert(0); - return NULL; - } - - if (PyUnicode_READY(substring) == -1) - return NULL; - - kind1 = PyUnicode_KIND(self); - kind2 = PyUnicode_KIND(substring); - len1 = PyUnicode_GET_LENGTH(self); - len2 = PyUnicode_GET_LENGTH(substring); - if (kind1 < kind2 || len1 < len2) { - out = PyList_New(1); - if (out == NULL) - return NULL; - Py_INCREF(self); - PyList_SET_ITEM(out, 0, self); - return out; - } - buf1 = PyUnicode_DATA(self); - buf2 = PyUnicode_DATA(substring); - if (kind2 != kind1) { - buf2 = _PyUnicode_AsKind(substring, kind1); - if (!buf2) - return NULL; - } - - switch (kind1) { - case PyUnicode_1BYTE_KIND: - if (PyUnicode_IS_ASCII(self) && PyUnicode_IS_ASCII(substring)) - out = asciilib_rsplit( - self, buf1, len1, buf2, len2, maxcount); - else - out = ucs1lib_rsplit( - self, buf1, len1, buf2, len2, maxcount); - break; - case PyUnicode_2BYTE_KIND: - out = ucs2lib_rsplit( - self, buf1, len1, buf2, len2, maxcount); - break; - case PyUnicode_4BYTE_KIND: - out = ucs4lib_rsplit( - self, buf1, len1, buf2, len2, maxcount); - break; - default: - out = NULL; - } - if (kind2 != kind1) - PyMem_Free(buf2); - return out; -} - -static Py_ssize_t -anylib_find(int kind, PyObject *str1, void *buf1, Py_ssize_t len1, - PyObject *str2, void *buf2, Py_ssize_t len2, Py_ssize_t offset) -{ - switch (kind) { - case PyUnicode_1BYTE_KIND: - if (PyUnicode_IS_ASCII(str1) && PyUnicode_IS_ASCII(str2)) - return asciilib_find(buf1, len1, buf2, len2, offset); - else - return ucs1lib_find(buf1, len1, buf2, len2, offset); - case PyUnicode_2BYTE_KIND: - return ucs2lib_find(buf1, len1, buf2, len2, offset); - case PyUnicode_4BYTE_KIND: - return ucs4lib_find(buf1, len1, buf2, len2, offset); - } - assert(0); - return -1; -} - -static Py_ssize_t -anylib_count(int kind, PyObject *sstr, void* sbuf, Py_ssize_t slen, - PyObject *str1, void *buf1, Py_ssize_t len1, Py_ssize_t maxcount) -{ - switch (kind) { - case PyUnicode_1BYTE_KIND: - if (PyUnicode_IS_ASCII(sstr) && PyUnicode_IS_ASCII(str1)) - return asciilib_count(sbuf, slen, buf1, len1, maxcount); - else - return ucs1lib_count(sbuf, slen, buf1, len1, maxcount); - case PyUnicode_2BYTE_KIND: - return ucs2lib_count(sbuf, slen, buf1, len1, maxcount); - case PyUnicode_4BYTE_KIND: - return ucs4lib_count(sbuf, slen, buf1, len1, maxcount); - } - assert(0); - return 0; -} - -static void -replace_1char_inplace(PyObject *u, Py_ssize_t pos, - Py_UCS4 u1, Py_UCS4 u2, Py_ssize_t maxcount) -{ - int kind = PyUnicode_KIND(u); - void *data = PyUnicode_DATA(u); - Py_ssize_t len = PyUnicode_GET_LENGTH(u); - if (kind == PyUnicode_1BYTE_KIND) { - ucs1lib_replace_1char_inplace((Py_UCS1 *)data + pos, - (Py_UCS1 *)data + len, - u1, u2, maxcount); - } - else if (kind == PyUnicode_2BYTE_KIND) { - ucs2lib_replace_1char_inplace((Py_UCS2 *)data + pos, - (Py_UCS2 *)data + len, - u1, u2, maxcount); - } - else { - assert(kind == PyUnicode_4BYTE_KIND); - ucs4lib_replace_1char_inplace((Py_UCS4 *)data + pos, - (Py_UCS4 *)data + len, - u1, u2, maxcount); - } -} - -static PyObject * -replace(PyObject *self, PyObject *str1, - PyObject *str2, Py_ssize_t maxcount) -{ - PyObject *u; - char *sbuf = PyUnicode_DATA(self); - char *buf1 = PyUnicode_DATA(str1); - char *buf2 = PyUnicode_DATA(str2); - int srelease = 0, release1 = 0, release2 = 0; - int skind = PyUnicode_KIND(self); - int kind1 = PyUnicode_KIND(str1); - int kind2 = PyUnicode_KIND(str2); - Py_ssize_t slen = PyUnicode_GET_LENGTH(self); - Py_ssize_t len1 = PyUnicode_GET_LENGTH(str1); - Py_ssize_t len2 = PyUnicode_GET_LENGTH(str2); - int mayshrink; - Py_UCS4 maxchar, maxchar_str1, maxchar_str2; - - if (maxcount < 0) - maxcount = PY_SSIZE_T_MAX; - else if (maxcount == 0 || slen == 0) - goto nothing; - - if (str1 == str2) - goto nothing; - - maxchar = PyUnicode_MAX_CHAR_VALUE(self); - maxchar_str1 = PyUnicode_MAX_CHAR_VALUE(str1); - if (maxchar < maxchar_str1) - /* substring too wide to be present */ - goto nothing; - maxchar_str2 = PyUnicode_MAX_CHAR_VALUE(str2); - /* Replacing str1 with str2 may cause a maxchar reduction in the - result string. */ - mayshrink = (maxchar_str2 < maxchar_str1) && (maxchar == maxchar_str1); - maxchar = Py_MAX(maxchar, maxchar_str2); - - if (len1 == len2) { - /* same length */ - if (len1 == 0) - goto nothing; - if (len1 == 1) { - /* replace characters */ - Py_UCS4 u1, u2; - Py_ssize_t pos; - - u1 = PyUnicode_READ(kind1, buf1, 0); - pos = findchar(sbuf, skind, slen, u1, 1); - if (pos < 0) - goto nothing; - u2 = PyUnicode_READ(kind2, buf2, 0); - u = PyUnicode_New(slen, maxchar); - if (!u) - goto error; - - _PyUnicode_FastCopyCharacters(u, 0, self, 0, slen); - replace_1char_inplace(u, pos, u1, u2, maxcount); - } - else { - int rkind = skind; - char *res; - Py_ssize_t i; - - if (kind1 < rkind) { - /* widen substring */ - buf1 = _PyUnicode_AsKind(str1, rkind); - if (!buf1) goto error; - release1 = 1; - } - i = anylib_find(rkind, self, sbuf, slen, str1, buf1, len1, 0); - if (i < 0) - goto nothing; - if (rkind > kind2) { - /* widen replacement */ - buf2 = _PyUnicode_AsKind(str2, rkind); - if (!buf2) goto error; - release2 = 1; - } - else if (rkind < kind2) { - /* widen self and buf1 */ - rkind = kind2; - if (release1) PyMem_Free(buf1); - release1 = 0; - sbuf = _PyUnicode_AsKind(self, rkind); - if (!sbuf) goto error; - srelease = 1; - buf1 = _PyUnicode_AsKind(str1, rkind); - if (!buf1) goto error; - release1 = 1; - } - u = PyUnicode_New(slen, maxchar); - if (!u) - goto error; - assert(PyUnicode_KIND(u) == rkind); - res = PyUnicode_DATA(u); - - memcpy(res, sbuf, rkind * slen); - /* change everything in-place, starting with this one */ - memcpy(res + rkind * i, - buf2, - rkind * len2); - i += len1; - - while ( --maxcount > 0) { - i = anylib_find(rkind, self, - sbuf+rkind*i, slen-i, - str1, buf1, len1, i); - if (i == -1) - break; - memcpy(res + rkind * i, - buf2, - rkind * len2); - i += len1; - } - } - } - else { - Py_ssize_t n, i, j, ires; - Py_ssize_t new_size; - int rkind = skind; - char *res; - - if (kind1 < rkind) { - /* widen substring */ - buf1 = _PyUnicode_AsKind(str1, rkind); - if (!buf1) goto error; - release1 = 1; - } - n = anylib_count(rkind, self, sbuf, slen, str1, buf1, len1, maxcount); - if (n == 0) - goto nothing; - if (kind2 < rkind) { - /* widen replacement */ - buf2 = _PyUnicode_AsKind(str2, rkind); - if (!buf2) goto error; - release2 = 1; - } - else if (kind2 > rkind) { - /* widen self and buf1 */ - rkind = kind2; - sbuf = _PyUnicode_AsKind(self, rkind); - if (!sbuf) goto error; - srelease = 1; - if (release1) PyMem_Free(buf1); - release1 = 0; - buf1 = _PyUnicode_AsKind(str1, rkind); - if (!buf1) goto error; - release1 = 1; - } - /* new_size = PyUnicode_GET_LENGTH(self) + n * (PyUnicode_GET_LENGTH(str2) - - PyUnicode_GET_LENGTH(str1))); */ - if (len1 < len2 && len2 - len1 > (PY_SSIZE_T_MAX - slen) / n) { - PyErr_SetString(PyExc_OverflowError, - "replace string is too long"); - goto error; - } - new_size = slen + n * (len2 - len1); - if (new_size == 0) { - _Py_INCREF_UNICODE_EMPTY(); - if (!unicode_empty) - goto error; - u = unicode_empty; - goto done; - } - if (new_size > (PY_SSIZE_T_MAX >> (rkind-1))) { - PyErr_SetString(PyExc_OverflowError, - "replace string is too long"); - goto error; - } - u = PyUnicode_New(new_size, maxchar); - if (!u) - goto error; - assert(PyUnicode_KIND(u) == rkind); - res = PyUnicode_DATA(u); - ires = i = 0; - if (len1 > 0) { - while (n-- > 0) { - /* look for next match */ - j = anylib_find(rkind, self, - sbuf + rkind * i, slen-i, - str1, buf1, len1, i); - if (j == -1) - break; - else if (j > i) { - /* copy unchanged part [i:j] */ - memcpy(res + rkind * ires, - sbuf + rkind * i, - rkind * (j-i)); - ires += j - i; - } - /* copy substitution string */ - if (len2 > 0) { - memcpy(res + rkind * ires, - buf2, - rkind * len2); - ires += len2; - } - i = j + len1; - } - if (i < slen) - /* copy tail [i:] */ - memcpy(res + rkind * ires, - sbuf + rkind * i, - rkind * (slen-i)); - } - else { - /* interleave */ - while (n > 0) { - memcpy(res + rkind * ires, - buf2, - rkind * len2); - ires += len2; - if (--n <= 0) - break; - memcpy(res + rkind * ires, - sbuf + rkind * i, - rkind); - ires++; - i++; - } - memcpy(res + rkind * ires, - sbuf + rkind * i, - rkind * (slen-i)); - } - } - - if (mayshrink) { - unicode_adjust_maxchar(&u); - if (u == NULL) - goto error; - } - - done: - if (srelease) - PyMem_FREE(sbuf); - if (release1) - PyMem_FREE(buf1); - if (release2) - PyMem_FREE(buf2); - assert(_PyUnicode_CheckConsistency(u, 1)); - return u; - - nothing: - /* nothing to replace; return original string (when possible) */ - if (srelease) - PyMem_FREE(sbuf); - if (release1) - PyMem_FREE(buf1); - if (release2) - PyMem_FREE(buf2); - return unicode_result_unchanged(self); - - error: - if (srelease && sbuf) - PyMem_FREE(sbuf); - if (release1 && buf1) - PyMem_FREE(buf1); - if (release2 && buf2) - PyMem_FREE(buf2); - return NULL; -} - -/* --- Unicode Object Methods --------------------------------------------- */ - -PyDoc_STRVAR(title__doc__, - "S.title() -> str\n\ -\n\ -Return a titlecased version of S, i.e. words start with title case\n\ -characters, all remaining cased characters have lower case."); - -static PyObject* -unicode_title(PyObject *self) -{ - if (PyUnicode_READY(self) == -1) - return NULL; - return case_operation(self, do_title); -} - -PyDoc_STRVAR(capitalize__doc__, - "S.capitalize() -> str\n\ -\n\ -Return a capitalized version of S, i.e. make the first character\n\ -have upper case and the rest lower case."); - -static PyObject* -unicode_capitalize(PyObject *self) -{ - if (PyUnicode_READY(self) == -1) - return NULL; - if (PyUnicode_GET_LENGTH(self) == 0) - return unicode_result_unchanged(self); - return case_operation(self, do_capitalize); -} - -PyDoc_STRVAR(casefold__doc__, - "S.casefold() -> str\n\ -\n\ -Return a version of S suitable for caseless comparisons."); - -static PyObject * -unicode_casefold(PyObject *self) -{ - if (PyUnicode_READY(self) == -1) - return NULL; - if (PyUnicode_IS_ASCII(self)) - return ascii_upper_or_lower(self, 1); - return case_operation(self, do_casefold); -} - - -/* Argument converter. Coerces to a single unicode character */ - -static int -convert_uc(PyObject *obj, void *addr) -{ - Py_UCS4 *fillcharloc = (Py_UCS4 *)addr; - PyObject *uniobj; - - uniobj = PyUnicode_FromObject(obj); - if (uniobj == NULL) { - PyErr_SetString(PyExc_TypeError, - "The fill character cannot be converted to Unicode"); - return 0; - } - if (PyUnicode_GET_LENGTH(uniobj) != 1) { - PyErr_SetString(PyExc_TypeError, - "The fill character must be exactly one character long"); - Py_DECREF(uniobj); - return 0; - } - *fillcharloc = PyUnicode_READ_CHAR(uniobj, 0); - Py_DECREF(uniobj); - return 1; -} - -PyDoc_STRVAR(center__doc__, - "S.center(width[, fillchar]) -> str\n\ -\n\ -Return S centered in a string of length width. Padding is\n\ -done using the specified fill character (default is a space)"); - -static PyObject * -unicode_center(PyObject *self, PyObject *args) -{ - Py_ssize_t marg, left; - Py_ssize_t width; - Py_UCS4 fillchar = ' '; - - if (!PyArg_ParseTuple(args, "n|O&:center", &width, convert_uc, &fillchar)) - return NULL; - - if (PyUnicode_READY(self) == -1) - return NULL; - - if (PyUnicode_GET_LENGTH(self) >= width) - return unicode_result_unchanged(self); - - marg = width - PyUnicode_GET_LENGTH(self); - left = marg / 2 + (marg & width & 1); - - return pad(self, left, marg - left, fillchar); -} - -/* This function assumes that str1 and str2 are readied by the caller. */ - -static int -unicode_compare(PyObject *str1, PyObject *str2) -{ -#define COMPARE(TYPE1, TYPE2) \ - do { \ - TYPE1* p1 = (TYPE1 *)data1; \ - TYPE2* p2 = (TYPE2 *)data2; \ - TYPE1* end = p1 + len; \ - Py_UCS4 c1, c2; \ - for (; p1 != end; p1++, p2++) { \ - c1 = *p1; \ - c2 = *p2; \ - if (c1 != c2) \ - return (c1 < c2) ? -1 : 1; \ - } \ - } \ - while (0) - - int kind1, kind2; - void *data1, *data2; - Py_ssize_t len1, len2, len; - - kind1 = PyUnicode_KIND(str1); - kind2 = PyUnicode_KIND(str2); - data1 = PyUnicode_DATA(str1); - data2 = PyUnicode_DATA(str2); - len1 = PyUnicode_GET_LENGTH(str1); - len2 = PyUnicode_GET_LENGTH(str2); - len = Py_MIN(len1, len2); - - switch(kind1) { - case PyUnicode_1BYTE_KIND: - { - switch(kind2) { - case PyUnicode_1BYTE_KIND: - { - int cmp = memcmp(data1, data2, len); - /* normalize result of memcmp() into the range [-1; 1] */ - if (cmp < 0) - return -1; - if (cmp > 0) - return 1; - break; - } - case PyUnicode_2BYTE_KIND: - COMPARE(Py_UCS1, Py_UCS2); - break; - case PyUnicode_4BYTE_KIND: - COMPARE(Py_UCS1, Py_UCS4); - break; - default: - assert(0); - } - break; - } - case PyUnicode_2BYTE_KIND: - { - switch(kind2) { - case PyUnicode_1BYTE_KIND: - COMPARE(Py_UCS2, Py_UCS1); - break; - case PyUnicode_2BYTE_KIND: - { - COMPARE(Py_UCS2, Py_UCS2); - break; - } - case PyUnicode_4BYTE_KIND: - COMPARE(Py_UCS2, Py_UCS4); - break; - default: - assert(0); - } - break; - } - case PyUnicode_4BYTE_KIND: - { - switch(kind2) { - case PyUnicode_1BYTE_KIND: - COMPARE(Py_UCS4, Py_UCS1); - break; - case PyUnicode_2BYTE_KIND: - COMPARE(Py_UCS4, Py_UCS2); - break; - case PyUnicode_4BYTE_KIND: - { -#if defined(HAVE_WMEMCMP) && SIZEOF_WCHAR_T == 4 - int cmp = wmemcmp((wchar_t *)data1, (wchar_t *)data2, len); - /* normalize result of wmemcmp() into the range [-1; 1] */ - if (cmp < 0) - return -1; - if (cmp > 0) - return 1; -#else - COMPARE(Py_UCS4, Py_UCS4); -#endif - break; - } - default: - assert(0); - } - break; - } - default: - assert(0); - } - - if (len1 == len2) - return 0; - if (len1 < len2) - return -1; - else - return 1; - -#undef COMPARE -} - -Py_LOCAL(int) -unicode_compare_eq(PyObject *str1, PyObject *str2) -{ - int kind; - void *data1, *data2; - Py_ssize_t len; - int cmp; - - len = PyUnicode_GET_LENGTH(str1); - if (PyUnicode_GET_LENGTH(str2) != len) - return 0; - kind = PyUnicode_KIND(str1); - if (PyUnicode_KIND(str2) != kind) - return 0; - data1 = PyUnicode_DATA(str1); - data2 = PyUnicode_DATA(str2); - - cmp = memcmp(data1, data2, len * kind); - return (cmp == 0); -} - - -int -PyUnicode_Compare(PyObject *left, PyObject *right) -{ - if (PyUnicode_Check(left) && PyUnicode_Check(right)) { - if (PyUnicode_READY(left) == -1 || - PyUnicode_READY(right) == -1) - return -1; - - /* a string is equal to itself */ - if (left == right) - return 0; - - return unicode_compare(left, right); - } - PyErr_Format(PyExc_TypeError, - "Can't compare %.100s and %.100s", - left->ob_type->tp_name, - right->ob_type->tp_name); - return -1; -} - -int -_PyUnicode_CompareWithId(PyObject *left, _Py_Identifier *right) -{ - PyObject *right_str = _PyUnicode_FromId(right); /* borrowed */ - if (right_str == NULL) - return -1; - return PyUnicode_Compare(left, right_str); -} - -int -PyUnicode_CompareWithASCIIString(PyObject* uni, const char* str) -{ - Py_ssize_t i; - int kind; - Py_UCS4 chr; - - assert(_PyUnicode_CHECK(uni)); - if (PyUnicode_READY(uni) == -1) - return -1; - kind = PyUnicode_KIND(uni); - if (kind == PyUnicode_1BYTE_KIND) { - const void *data = PyUnicode_1BYTE_DATA(uni); - size_t len1 = (size_t)PyUnicode_GET_LENGTH(uni); - size_t len, len2 = strlen(str); - int cmp; - - len = Py_MIN(len1, len2); - cmp = memcmp(data, str, len); - if (cmp != 0) { - if (cmp < 0) - return -1; - else - return 1; - } - if (len1 > len2) - return 1; /* uni is longer */ - if (len1 < len2) - return -1; /* str is longer */ - return 0; - } - else { - void *data = PyUnicode_DATA(uni); - /* Compare Unicode string and source character set string */ - for (i = 0; (chr = PyUnicode_READ(kind, data, i)) && str[i]; i++) - if (chr != (unsigned char)str[i]) - return (chr < (unsigned char)(str[i])) ? -1 : 1; - /* This check keeps Python strings that end in '\0' from comparing equal - to C strings identical up to that point. */ - if (PyUnicode_GET_LENGTH(uni) != i || chr) - return 1; /* uni is longer */ - if (str[i]) - return -1; /* str is longer */ - return 0; - } -} - - -#define TEST_COND(cond) \ - ((cond) ? Py_True : Py_False) - -PyObject * -PyUnicode_RichCompare(PyObject *left, PyObject *right, int op) -{ - int result; - PyObject *v; - - if (!PyUnicode_Check(left) || !PyUnicode_Check(right)) - Py_RETURN_NOTIMPLEMENTED; - - if (PyUnicode_READY(left) == -1 || - PyUnicode_READY(right) == -1) - return NULL; - - if (left == right) { - switch (op) { - case Py_EQ: - case Py_LE: - case Py_GE: - /* a string is equal to itself */ - v = Py_True; - break; - case Py_NE: - case Py_LT: - case Py_GT: - v = Py_False; - break; - default: - PyErr_BadArgument(); - return NULL; - } - } - else if (op == Py_EQ || op == Py_NE) { - result = unicode_compare_eq(left, right); - result ^= (op == Py_NE); - v = TEST_COND(result); - } - else { - result = unicode_compare(left, right); - - /* Convert the return value to a Boolean */ - switch (op) { - case Py_LE: - v = TEST_COND(result <= 0); - break; - case Py_GE: - v = TEST_COND(result >= 0); - break; - case Py_LT: - v = TEST_COND(result == -1); - break; - case Py_GT: - v = TEST_COND(result == 1); - break; - default: - PyErr_BadArgument(); - return NULL; - } - } - Py_INCREF(v); - return v; -} - -int -PyUnicode_Contains(PyObject *container, PyObject *element) -{ - PyObject *str, *sub; - int kind1, kind2; - void *buf1, *buf2; - Py_ssize_t len1, len2; - int result; - - /* Coerce the two arguments */ - sub = PyUnicode_FromObject(element); - if (!sub) { - PyErr_Format(PyExc_TypeError, - "'in ' requires string as left operand, not %s", - element->ob_type->tp_name); - return -1; - } - - str = PyUnicode_FromObject(container); - if (!str) { - Py_DECREF(sub); - return -1; - } - - kind1 = PyUnicode_KIND(str); - kind2 = PyUnicode_KIND(sub); - if (kind1 < kind2) { - Py_DECREF(sub); - Py_DECREF(str); - return 0; - } - len1 = PyUnicode_GET_LENGTH(str); - len2 = PyUnicode_GET_LENGTH(sub); - if (len1 < len2) { - Py_DECREF(sub); - Py_DECREF(str); - return 0; - } - buf1 = PyUnicode_DATA(str); - buf2 = PyUnicode_DATA(sub); - if (len2 == 1) { - Py_UCS4 ch = PyUnicode_READ(kind2, buf2, 0); - result = findchar((const char *)buf1, kind1, len1, ch, 1) != -1; - Py_DECREF(sub); - Py_DECREF(str); - return result; - } - if (kind2 != kind1) { - buf2 = _PyUnicode_AsKind(sub, kind1); - if (!buf2) { - Py_DECREF(sub); - Py_DECREF(str); - return -1; - } - } - - switch (kind1) { - case PyUnicode_1BYTE_KIND: - result = ucs1lib_find(buf1, len1, buf2, len2, 0) != -1; - break; - case PyUnicode_2BYTE_KIND: - result = ucs2lib_find(buf1, len1, buf2, len2, 0) != -1; - break; - case PyUnicode_4BYTE_KIND: - result = ucs4lib_find(buf1, len1, buf2, len2, 0) != -1; - break; - default: - result = -1; - assert(0); - } - - Py_DECREF(str); - Py_DECREF(sub); - - if (kind2 != kind1) - PyMem_Free(buf2); - - return result; -} - -/* Concat to string or Unicode object giving a new Unicode object. */ - -PyObject * -PyUnicode_Concat(PyObject *left, PyObject *right) -{ - PyObject *u = NULL, *v = NULL, *w; - Py_UCS4 maxchar, maxchar2; - Py_ssize_t u_len, v_len, new_len; - - /* Coerce the two arguments */ - u = PyUnicode_FromObject(left); - if (u == NULL) - goto onError; - v = PyUnicode_FromObject(right); - if (v == NULL) - goto onError; - - /* Shortcuts */ - if (v == unicode_empty) { - Py_DECREF(v); - return u; - } - if (u == unicode_empty) { - Py_DECREF(u); - return v; - } - - u_len = PyUnicode_GET_LENGTH(u); - v_len = PyUnicode_GET_LENGTH(v); - if (u_len > PY_SSIZE_T_MAX - v_len) { - PyErr_SetString(PyExc_OverflowError, - "strings are too large to concat"); - goto onError; - } - new_len = u_len + v_len; - - maxchar = PyUnicode_MAX_CHAR_VALUE(u); - maxchar2 = PyUnicode_MAX_CHAR_VALUE(v); - maxchar = Py_MAX(maxchar, maxchar2); - - /* Concat the two Unicode strings */ - w = PyUnicode_New(new_len, maxchar); - if (w == NULL) - goto onError; - _PyUnicode_FastCopyCharacters(w, 0, u, 0, u_len); - _PyUnicode_FastCopyCharacters(w, u_len, v, 0, v_len); - Py_DECREF(u); - Py_DECREF(v); - assert(_PyUnicode_CheckConsistency(w, 1)); - return w; - - onError: - Py_XDECREF(u); - Py_XDECREF(v); - return NULL; -} - -void -PyUnicode_Append(PyObject **p_left, PyObject *right) -{ - PyObject *left, *res; - Py_UCS4 maxchar, maxchar2; - Py_ssize_t left_len, right_len, new_len; - - if (p_left == NULL) { - if (!PyErr_Occurred()) - PyErr_BadInternalCall(); - return; - } - left = *p_left; - if (right == NULL || left == NULL - || !PyUnicode_Check(left) || !PyUnicode_Check(right)) { - if (!PyErr_Occurred()) - PyErr_BadInternalCall(); - goto error; - } - - if (PyUnicode_READY(left) == -1) - goto error; - if (PyUnicode_READY(right) == -1) - goto error; - - /* Shortcuts */ - if (left == unicode_empty) { - Py_DECREF(left); - Py_INCREF(right); - *p_left = right; - return; - } - if (right == unicode_empty) - return; - - left_len = PyUnicode_GET_LENGTH(left); - right_len = PyUnicode_GET_LENGTH(right); - if (left_len > PY_SSIZE_T_MAX - right_len) { - PyErr_SetString(PyExc_OverflowError, - "strings are too large to concat"); - goto error; - } - new_len = left_len + right_len; - - if (unicode_modifiable(left) - && PyUnicode_CheckExact(right) - && PyUnicode_KIND(right) <= PyUnicode_KIND(left) - /* Don't resize for ascii += latin1. Convert ascii to latin1 requires - to change the structure size, but characters are stored just after - the structure, and so it requires to move all characters which is - not so different than duplicating the string. */ - && !(PyUnicode_IS_ASCII(left) && !PyUnicode_IS_ASCII(right))) - { - /* append inplace */ - if (unicode_resize(p_left, new_len) != 0) - goto error; - - /* copy 'right' into the newly allocated area of 'left' */ - _PyUnicode_FastCopyCharacters(*p_left, left_len, right, 0, right_len); - } - else { - maxchar = PyUnicode_MAX_CHAR_VALUE(left); - maxchar2 = PyUnicode_MAX_CHAR_VALUE(right); - maxchar = Py_MAX(maxchar, maxchar2); - - /* Concat the two Unicode strings */ - res = PyUnicode_New(new_len, maxchar); - if (res == NULL) - goto error; - _PyUnicode_FastCopyCharacters(res, 0, left, 0, left_len); - _PyUnicode_FastCopyCharacters(res, left_len, right, 0, right_len); - Py_DECREF(left); - *p_left = res; - } - assert(_PyUnicode_CheckConsistency(*p_left, 1)); - return; - -error: - Py_CLEAR(*p_left); -} - -void -PyUnicode_AppendAndDel(PyObject **pleft, PyObject *right) -{ - PyUnicode_Append(pleft, right); - Py_XDECREF(right); -} - -PyDoc_STRVAR(count__doc__, - "S.count(sub[, start[, end]]) -> int\n\ -\n\ -Return the number of non-overlapping occurrences of substring sub in\n\ -string S[start:end]. Optional arguments start and end are\n\ -interpreted as in slice notation."); - -static PyObject * -unicode_count(PyObject *self, PyObject *args) -{ - PyObject *substring = NULL; /* initialize to fix a compiler warning */ - Py_ssize_t start = 0; - Py_ssize_t end = PY_SSIZE_T_MAX; - PyObject *result; - int kind1, kind2; - void *buf1, *buf2; - Py_ssize_t len1, len2, iresult; - - if (!stringlib_parse_args_finds_unicode("count", args, &substring, - &start, &end)) - return NULL; - - kind1 = PyUnicode_KIND(self); - kind2 = PyUnicode_KIND(substring); - if (kind1 < kind2) { - Py_DECREF(substring); - return PyLong_FromLong(0); - } - len1 = PyUnicode_GET_LENGTH(self); - len2 = PyUnicode_GET_LENGTH(substring); - ADJUST_INDICES(start, end, len1); - if (end - start < len2) { - Py_DECREF(substring); - return PyLong_FromLong(0); - } - buf1 = PyUnicode_DATA(self); - buf2 = PyUnicode_DATA(substring); - if (kind2 != kind1) { - buf2 = _PyUnicode_AsKind(substring, kind1); - if (!buf2) { - Py_DECREF(substring); - return NULL; - } - } - switch (kind1) { - case PyUnicode_1BYTE_KIND: - iresult = ucs1lib_count( - ((Py_UCS1*)buf1) + start, end - start, - buf2, len2, PY_SSIZE_T_MAX - ); - break; - case PyUnicode_2BYTE_KIND: - iresult = ucs2lib_count( - ((Py_UCS2*)buf1) + start, end - start, - buf2, len2, PY_SSIZE_T_MAX - ); - break; - case PyUnicode_4BYTE_KIND: - iresult = ucs4lib_count( - ((Py_UCS4*)buf1) + start, end - start, - buf2, len2, PY_SSIZE_T_MAX - ); - break; - default: - assert(0); iresult = 0; - } - - result = PyLong_FromSsize_t(iresult); - - if (kind2 != kind1) - PyMem_Free(buf2); - - Py_DECREF(substring); - - return result; -} - -PyDoc_STRVAR(encode__doc__, - "S.encode(encoding='utf-8', errors='strict') -> bytes\n\ -\n\ -Encode S using the codec registered for encoding. Default encoding\n\ -is 'utf-8'. errors may be given to set a different error\n\ -handling scheme. Default is 'strict' meaning that encoding errors raise\n\ -a UnicodeEncodeError. Other possible values are 'ignore', 'replace' and\n\ -'xmlcharrefreplace' as well as any other name registered with\n\ -codecs.register_error that can handle UnicodeEncodeErrors."); - -static PyObject * -unicode_encode(PyObject *self, PyObject *args, PyObject *kwargs) -{ - static char *kwlist[] = {"encoding", "errors", 0}; - char *encoding = NULL; - char *errors = NULL; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|ss:encode", - kwlist, &encoding, &errors)) - return NULL; - return PyUnicode_AsEncodedString(self, encoding, errors); -} - -PyDoc_STRVAR(expandtabs__doc__, - "S.expandtabs(tabsize=8) -> str\n\ -\n\ -Return a copy of S where all tab characters are expanded using spaces.\n\ -If tabsize is not given, a tab size of 8 characters is assumed."); - -static PyObject* -unicode_expandtabs(PyObject *self, PyObject *args, PyObject *kwds) -{ - Py_ssize_t i, j, line_pos, src_len, incr; - Py_UCS4 ch; - PyObject *u; - void *src_data, *dest_data; - static char *kwlist[] = {"tabsize", 0}; - int tabsize = 8; - int kind; - int found; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|i:expandtabs", - kwlist, &tabsize)) - return NULL; - - if (PyUnicode_READY(self) == -1) - return NULL; - - /* First pass: determine size of output string */ - src_len = PyUnicode_GET_LENGTH(self); - i = j = line_pos = 0; - kind = PyUnicode_KIND(self); - src_data = PyUnicode_DATA(self); - found = 0; - for (; i < src_len; i++) { - ch = PyUnicode_READ(kind, src_data, i); - if (ch == '\t') { - found = 1; - if (tabsize > 0) { - incr = tabsize - (line_pos % tabsize); /* cannot overflow */ - if (j > PY_SSIZE_T_MAX - incr) - goto overflow; - line_pos += incr; - j += incr; - } - } - else { - if (j > PY_SSIZE_T_MAX - 1) - goto overflow; - line_pos++; - j++; - if (ch == '\n' || ch == '\r') - line_pos = 0; - } - } - if (!found) - return unicode_result_unchanged(self); - - /* Second pass: create output string and fill it */ - u = PyUnicode_New(j, PyUnicode_MAX_CHAR_VALUE(self)); - if (!u) - return NULL; - dest_data = PyUnicode_DATA(u); - - i = j = line_pos = 0; - - for (; i < src_len; i++) { - ch = PyUnicode_READ(kind, src_data, i); - if (ch == '\t') { - if (tabsize > 0) { - incr = tabsize - (line_pos % tabsize); - line_pos += incr; - FILL(kind, dest_data, ' ', j, incr); - j += incr; - } - } - else { - line_pos++; - PyUnicode_WRITE(kind, dest_data, j, ch); - j++; - if (ch == '\n' || ch == '\r') - line_pos = 0; - } - } - assert (j == PyUnicode_GET_LENGTH(u)); - return unicode_result(u); - - overflow: - PyErr_SetString(PyExc_OverflowError, "new string is too long"); - return NULL; -} - -PyDoc_STRVAR(find__doc__, - "S.find(sub[, start[, end]]) -> int\n\ -\n\ -Return the lowest index in S where substring sub is found,\n\ -such that sub is contained within S[start:end]. Optional\n\ -arguments start and end are interpreted as in slice notation.\n\ -\n\ -Return -1 on failure."); - -static PyObject * -unicode_find(PyObject *self, PyObject *args) -{ - /* initialize variables to prevent gcc warning */ - PyObject *substring = NULL; - Py_ssize_t start = 0; - Py_ssize_t end = 0; - Py_ssize_t result; - - if (!stringlib_parse_args_finds_unicode("find", args, &substring, - &start, &end)) - return NULL; - - if (PyUnicode_READY(self) == -1) { - Py_DECREF(substring); - return NULL; - } - if (PyUnicode_READY(substring) == -1) { - Py_DECREF(substring); - return NULL; - } - - result = any_find_slice(1, self, substring, start, end); - - Py_DECREF(substring); - - if (result == -2) - return NULL; - - return PyLong_FromSsize_t(result); -} - -static PyObject * -unicode_getitem(PyObject *self, Py_ssize_t index) -{ - void *data; - enum PyUnicode_Kind kind; - Py_UCS4 ch; - - if (!PyUnicode_Check(self) || PyUnicode_READY(self) == -1) { - PyErr_BadArgument(); - return NULL; - } - if (index < 0 || index >= PyUnicode_GET_LENGTH(self)) { - PyErr_SetString(PyExc_IndexError, "string index out of range"); - return NULL; - } - kind = PyUnicode_KIND(self); - data = PyUnicode_DATA(self); - ch = PyUnicode_READ(kind, data, index); - return unicode_char(ch); -} - -/* Believe it or not, this produces the same value for ASCII strings - as bytes_hash(). */ -static Py_hash_t -unicode_hash(PyObject *self) -{ - Py_ssize_t len; - Py_uhash_t x; /* Unsigned for defined overflow behavior. */ - -#ifdef Py_DEBUG - assert(_Py_HashSecret_Initialized); -#endif - if (_PyUnicode_HASH(self) != -1) - return _PyUnicode_HASH(self); - if (PyUnicode_READY(self) == -1) - return -1; - len = PyUnicode_GET_LENGTH(self); - /* - We make the hash of the empty string be 0, rather than using - (prefix ^ suffix), since this slightly obfuscates the hash secret - */ - if (len == 0) { - _PyUnicode_HASH(self) = 0; - return 0; - } - x = _Py_HashBytes(PyUnicode_DATA(self), - PyUnicode_GET_LENGTH(self) * PyUnicode_KIND(self)); - _PyUnicode_HASH(self) = x; - return x; -} - -PyDoc_STRVAR(index__doc__, - "S.index(sub[, start[, end]]) -> int\n\ -\n\ -Like S.find() but raise ValueError when the substring is not found."); - -static PyObject * -unicode_index(PyObject *self, PyObject *args) -{ - /* initialize variables to prevent gcc warning */ - Py_ssize_t result; - PyObject *substring = NULL; - Py_ssize_t start = 0; - Py_ssize_t end = 0; - - if (!stringlib_parse_args_finds_unicode("index", args, &substring, - &start, &end)) - return NULL; - - if (PyUnicode_READY(self) == -1) { - Py_DECREF(substring); - return NULL; - } - if (PyUnicode_READY(substring) == -1) { - Py_DECREF(substring); - return NULL; - } - - result = any_find_slice(1, self, substring, start, end); - - Py_DECREF(substring); - - if (result == -2) - return NULL; - - if (result < 0) { - PyErr_SetString(PyExc_ValueError, "substring not found"); - return NULL; - } - - return PyLong_FromSsize_t(result); -} - -PyDoc_STRVAR(islower__doc__, - "S.islower() -> bool\n\ -\n\ -Return True if all cased characters in S are lowercase and there is\n\ -at least one cased character in S, False otherwise."); - -static PyObject* -unicode_islower(PyObject *self) -{ - Py_ssize_t i, length; - int kind; - void *data; - int cased; - - if (PyUnicode_READY(self) == -1) - return NULL; - length = PyUnicode_GET_LENGTH(self); - kind = PyUnicode_KIND(self); - data = PyUnicode_DATA(self); - - /* Shortcut for single character strings */ - if (length == 1) - return PyBool_FromLong( - Py_UNICODE_ISLOWER(PyUnicode_READ(kind, data, 0))); - - /* Special case for empty strings */ - if (length == 0) - return PyBool_FromLong(0); - - cased = 0; - for (i = 0; i < length; i++) { - const Py_UCS4 ch = PyUnicode_READ(kind, data, i); - - if (Py_UNICODE_ISUPPER(ch) || Py_UNICODE_ISTITLE(ch)) - return PyBool_FromLong(0); - else if (!cased && Py_UNICODE_ISLOWER(ch)) - cased = 1; - } - return PyBool_FromLong(cased); -} - -PyDoc_STRVAR(isupper__doc__, - "S.isupper() -> bool\n\ -\n\ -Return True if all cased characters in S are uppercase and there is\n\ -at least one cased character in S, False otherwise."); - -static PyObject* -unicode_isupper(PyObject *self) -{ - Py_ssize_t i, length; - int kind; - void *data; - int cased; - - if (PyUnicode_READY(self) == -1) - return NULL; - length = PyUnicode_GET_LENGTH(self); - kind = PyUnicode_KIND(self); - data = PyUnicode_DATA(self); - - /* Shortcut for single character strings */ - if (length == 1) - return PyBool_FromLong( - Py_UNICODE_ISUPPER(PyUnicode_READ(kind, data, 0)) != 0); - - /* Special case for empty strings */ - if (length == 0) - return PyBool_FromLong(0); - - cased = 0; - for (i = 0; i < length; i++) { - const Py_UCS4 ch = PyUnicode_READ(kind, data, i); - - if (Py_UNICODE_ISLOWER(ch) || Py_UNICODE_ISTITLE(ch)) - return PyBool_FromLong(0); - else if (!cased && Py_UNICODE_ISUPPER(ch)) - cased = 1; - } - return PyBool_FromLong(cased); -} - -PyDoc_STRVAR(istitle__doc__, - "S.istitle() -> bool\n\ -\n\ -Return True if S is a titlecased string and there is at least one\n\ -character in S, i.e. upper- and titlecase characters may only\n\ -follow uncased characters and lowercase characters only cased ones.\n\ -Return False otherwise."); - -static PyObject* -unicode_istitle(PyObject *self) -{ - Py_ssize_t i, length; - int kind; - void *data; - int cased, previous_is_cased; - - if (PyUnicode_READY(self) == -1) - return NULL; - length = PyUnicode_GET_LENGTH(self); - kind = PyUnicode_KIND(self); - data = PyUnicode_DATA(self); - - /* Shortcut for single character strings */ - if (length == 1) { - Py_UCS4 ch = PyUnicode_READ(kind, data, 0); - return PyBool_FromLong((Py_UNICODE_ISTITLE(ch) != 0) || - (Py_UNICODE_ISUPPER(ch) != 0)); - } - - /* Special case for empty strings */ - if (length == 0) - return PyBool_FromLong(0); - - cased = 0; - previous_is_cased = 0; - for (i = 0; i < length; i++) { - const Py_UCS4 ch = PyUnicode_READ(kind, data, i); - - if (Py_UNICODE_ISUPPER(ch) || Py_UNICODE_ISTITLE(ch)) { - if (previous_is_cased) - return PyBool_FromLong(0); - previous_is_cased = 1; - cased = 1; - } - else if (Py_UNICODE_ISLOWER(ch)) { - if (!previous_is_cased) - return PyBool_FromLong(0); - previous_is_cased = 1; - cased = 1; - } - else - previous_is_cased = 0; - } - return PyBool_FromLong(cased); -} - -PyDoc_STRVAR(isspace__doc__, - "S.isspace() -> bool\n\ -\n\ -Return True if all characters in S are whitespace\n\ -and there is at least one character in S, False otherwise."); - -static PyObject* -unicode_isspace(PyObject *self) -{ - Py_ssize_t i, length; - int kind; - void *data; - - if (PyUnicode_READY(self) == -1) - return NULL; - length = PyUnicode_GET_LENGTH(self); - kind = PyUnicode_KIND(self); - data = PyUnicode_DATA(self); - - /* Shortcut for single character strings */ - if (length == 1) - return PyBool_FromLong( - Py_UNICODE_ISSPACE(PyUnicode_READ(kind, data, 0))); - - /* Special case for empty strings */ - if (length == 0) - return PyBool_FromLong(0); - - for (i = 0; i < length; i++) { - const Py_UCS4 ch = PyUnicode_READ(kind, data, i); - if (!Py_UNICODE_ISSPACE(ch)) - return PyBool_FromLong(0); - } - return PyBool_FromLong(1); -} - -PyDoc_STRVAR(isalpha__doc__, - "S.isalpha() -> bool\n\ -\n\ -Return True if all characters in S are alphabetic\n\ -and there is at least one character in S, False otherwise."); - -static PyObject* -unicode_isalpha(PyObject *self) -{ - Py_ssize_t i, length; - int kind; - void *data; - - if (PyUnicode_READY(self) == -1) - return NULL; - length = PyUnicode_GET_LENGTH(self); - kind = PyUnicode_KIND(self); - data = PyUnicode_DATA(self); - - /* Shortcut for single character strings */ - if (length == 1) - return PyBool_FromLong( - Py_UNICODE_ISALPHA(PyUnicode_READ(kind, data, 0))); - - /* Special case for empty strings */ - if (length == 0) - return PyBool_FromLong(0); - - for (i = 0; i < length; i++) { - if (!Py_UNICODE_ISALPHA(PyUnicode_READ(kind, data, i))) - return PyBool_FromLong(0); - } - return PyBool_FromLong(1); -} - -PyDoc_STRVAR(isalnum__doc__, - "S.isalnum() -> bool\n\ -\n\ -Return True if all characters in S are alphanumeric\n\ -and there is at least one character in S, False otherwise."); - -static PyObject* -unicode_isalnum(PyObject *self) -{ - int kind; - void *data; - Py_ssize_t len, i; - - if (PyUnicode_READY(self) == -1) - return NULL; - - kind = PyUnicode_KIND(self); - data = PyUnicode_DATA(self); - len = PyUnicode_GET_LENGTH(self); - - /* Shortcut for single character strings */ - if (len == 1) { - const Py_UCS4 ch = PyUnicode_READ(kind, data, 0); - return PyBool_FromLong(Py_UNICODE_ISALNUM(ch)); - } - - /* Special case for empty strings */ - if (len == 0) - return PyBool_FromLong(0); - - for (i = 0; i < len; i++) { - const Py_UCS4 ch = PyUnicode_READ(kind, data, i); - if (!Py_UNICODE_ISALNUM(ch)) - return PyBool_FromLong(0); - } - return PyBool_FromLong(1); -} - -PyDoc_STRVAR(isdecimal__doc__, - "S.isdecimal() -> bool\n\ -\n\ -Return True if there are only decimal characters in S,\n\ -False otherwise."); - -static PyObject* -unicode_isdecimal(PyObject *self) -{ - Py_ssize_t i, length; - int kind; - void *data; - - if (PyUnicode_READY(self) == -1) - return NULL; - length = PyUnicode_GET_LENGTH(self); - kind = PyUnicode_KIND(self); - data = PyUnicode_DATA(self); - - /* Shortcut for single character strings */ - if (length == 1) - return PyBool_FromLong( - Py_UNICODE_ISDECIMAL(PyUnicode_READ(kind, data, 0))); - - /* Special case for empty strings */ - if (length == 0) - return PyBool_FromLong(0); - - for (i = 0; i < length; i++) { - if (!Py_UNICODE_ISDECIMAL(PyUnicode_READ(kind, data, i))) - return PyBool_FromLong(0); - } - return PyBool_FromLong(1); -} - -PyDoc_STRVAR(isdigit__doc__, - "S.isdigit() -> bool\n\ -\n\ -Return True if all characters in S are digits\n\ -and there is at least one character in S, False otherwise."); - -static PyObject* -unicode_isdigit(PyObject *self) -{ - Py_ssize_t i, length; - int kind; - void *data; - - if (PyUnicode_READY(self) == -1) - return NULL; - length = PyUnicode_GET_LENGTH(self); - kind = PyUnicode_KIND(self); - data = PyUnicode_DATA(self); - - /* Shortcut for single character strings */ - if (length == 1) { - const Py_UCS4 ch = PyUnicode_READ(kind, data, 0); - return PyBool_FromLong(Py_UNICODE_ISDIGIT(ch)); - } - - /* Special case for empty strings */ - if (length == 0) - return PyBool_FromLong(0); - - for (i = 0; i < length; i++) { - if (!Py_UNICODE_ISDIGIT(PyUnicode_READ(kind, data, i))) - return PyBool_FromLong(0); - } - return PyBool_FromLong(1); -} - -PyDoc_STRVAR(isnumeric__doc__, - "S.isnumeric() -> bool\n\ -\n\ -Return True if there are only numeric characters in S,\n\ -False otherwise."); - -static PyObject* -unicode_isnumeric(PyObject *self) -{ - Py_ssize_t i, length; - int kind; - void *data; - - if (PyUnicode_READY(self) == -1) - return NULL; - length = PyUnicode_GET_LENGTH(self); - kind = PyUnicode_KIND(self); - data = PyUnicode_DATA(self); - - /* Shortcut for single character strings */ - if (length == 1) - return PyBool_FromLong( - Py_UNICODE_ISNUMERIC(PyUnicode_READ(kind, data, 0))); - - /* Special case for empty strings */ - if (length == 0) - return PyBool_FromLong(0); - - for (i = 0; i < length; i++) { - if (!Py_UNICODE_ISNUMERIC(PyUnicode_READ(kind, data, i))) - return PyBool_FromLong(0); - } - return PyBool_FromLong(1); -} - -int -PyUnicode_IsIdentifier(PyObject *self) -{ - int kind; - void *data; - Py_ssize_t i; - Py_UCS4 first; - - if (PyUnicode_READY(self) == -1) { - Py_FatalError("identifier not ready"); - return 0; - } - - /* Special case for empty strings */ - if (PyUnicode_GET_LENGTH(self) == 0) - return 0; - kind = PyUnicode_KIND(self); - data = PyUnicode_DATA(self); - - /* PEP 3131 says that the first character must be in - XID_Start and subsequent characters in XID_Continue, - and for the ASCII range, the 2.x rules apply (i.e - start with letters and underscore, continue with - letters, digits, underscore). However, given the current - definition of XID_Start and XID_Continue, it is sufficient - to check just for these, except that _ must be allowed - as starting an identifier. */ - first = PyUnicode_READ(kind, data, 0); - if (!_PyUnicode_IsXidStart(first) && first != 0x5F /* LOW LINE */) - return 0; - - for (i = 1; i < PyUnicode_GET_LENGTH(self); i++) - if (!_PyUnicode_IsXidContinue(PyUnicode_READ(kind, data, i))) - return 0; - return 1; -} - -PyDoc_STRVAR(isidentifier__doc__, - "S.isidentifier() -> bool\n\ -\n\ -Return True if S is a valid identifier according\n\ -to the language definition.\n\ -\n\ -Use keyword.iskeyword() to test for reserved identifiers\n\ -such as \"def\" and \"class\".\n"); - -static PyObject* -unicode_isidentifier(PyObject *self) -{ - return PyBool_FromLong(PyUnicode_IsIdentifier(self)); -} - -PyDoc_STRVAR(isprintable__doc__, - "S.isprintable() -> bool\n\ -\n\ -Return True if all characters in S are considered\n\ -printable in repr() or S is empty, False otherwise."); - -static PyObject* -unicode_isprintable(PyObject *self) -{ - Py_ssize_t i, length; - int kind; - void *data; - - if (PyUnicode_READY(self) == -1) - return NULL; - length = PyUnicode_GET_LENGTH(self); - kind = PyUnicode_KIND(self); - data = PyUnicode_DATA(self); - - /* Shortcut for single character strings */ - if (length == 1) - return PyBool_FromLong( - Py_UNICODE_ISPRINTABLE(PyUnicode_READ(kind, data, 0))); - - for (i = 0; i < length; i++) { - if (!Py_UNICODE_ISPRINTABLE(PyUnicode_READ(kind, data, i))) { - Py_RETURN_FALSE; - } - } - Py_RETURN_TRUE; -} - -PyDoc_STRVAR(join__doc__, - "S.join(iterable) -> str\n\ -\n\ -Return a string which is the concatenation of the strings in the\n\ -iterable. The separator between elements is S."); - -static PyObject* -unicode_join(PyObject *self, PyObject *data) -{ - return PyUnicode_Join(self, data); -} - -static Py_ssize_t -unicode_length(PyObject *self) -{ - if (PyUnicode_READY(self) == -1) - return -1; - return PyUnicode_GET_LENGTH(self); -} - -PyDoc_STRVAR(ljust__doc__, - "S.ljust(width[, fillchar]) -> str\n\ -\n\ -Return S left-justified in a Unicode string of length width. Padding is\n\ -done using the specified fill character (default is a space)."); - -static PyObject * -unicode_ljust(PyObject *self, PyObject *args) -{ - Py_ssize_t width; - Py_UCS4 fillchar = ' '; - - if (!PyArg_ParseTuple(args, "n|O&:ljust", &width, convert_uc, &fillchar)) - return NULL; - - if (PyUnicode_READY(self) == -1) - return NULL; - - if (PyUnicode_GET_LENGTH(self) >= width) - return unicode_result_unchanged(self); - - return pad(self, 0, width - PyUnicode_GET_LENGTH(self), fillchar); -} - -PyDoc_STRVAR(lower__doc__, - "S.lower() -> str\n\ -\n\ -Return a copy of the string S converted to lowercase."); - -static PyObject* -unicode_lower(PyObject *self) -{ - if (PyUnicode_READY(self) == -1) - return NULL; - if (PyUnicode_IS_ASCII(self)) - return ascii_upper_or_lower(self, 1); - return case_operation(self, do_lower); -} - -#define LEFTSTRIP 0 -#define RIGHTSTRIP 1 -#define BOTHSTRIP 2 - -/* Arrays indexed by above */ -static const char *stripformat[] = {"|O:lstrip", "|O:rstrip", "|O:strip"}; - -#define STRIPNAME(i) (stripformat[i]+3) - -/* externally visible for str.strip(unicode) */ -PyObject * -_PyUnicode_XStrip(PyObject *self, int striptype, PyObject *sepobj) -{ - void *data; - int kind; - Py_ssize_t i, j, len; - BLOOM_MASK sepmask; - Py_ssize_t seplen; - - if (PyUnicode_READY(self) == -1 || PyUnicode_READY(sepobj) == -1) - return NULL; - - kind = PyUnicode_KIND(self); - data = PyUnicode_DATA(self); - len = PyUnicode_GET_LENGTH(self); - seplen = PyUnicode_GET_LENGTH(sepobj); - sepmask = make_bloom_mask(PyUnicode_KIND(sepobj), - PyUnicode_DATA(sepobj), - seplen); - - i = 0; - if (striptype != RIGHTSTRIP) { - while (i < len) { - Py_UCS4 ch = PyUnicode_READ(kind, data, i); - if (!BLOOM(sepmask, ch)) - break; - if (PyUnicode_FindChar(sepobj, ch, 0, seplen, 1) < 0) - break; - i++; - } - } - - j = len; - if (striptype != LEFTSTRIP) { - j--; - while (j >= i) { - Py_UCS4 ch = PyUnicode_READ(kind, data, j); - if (!BLOOM(sepmask, ch)) - break; - if (PyUnicode_FindChar(sepobj, ch, 0, seplen, 1) < 0) - break; - j--; - } - - j++; - } - - return PyUnicode_Substring(self, i, j); -} - -PyObject* -PyUnicode_Substring(PyObject *self, Py_ssize_t start, Py_ssize_t end) -{ - unsigned char *data; - int kind; - Py_ssize_t length; - - if (PyUnicode_READY(self) == -1) - return NULL; - - length = PyUnicode_GET_LENGTH(self); - end = Py_MIN(end, length); - - if (start == 0 && end == length) - return unicode_result_unchanged(self); - - if (start < 0 || end < 0) { - PyErr_SetString(PyExc_IndexError, "string index out of range"); - return NULL; - } - if (start >= length || end < start) - _Py_RETURN_UNICODE_EMPTY(); - - length = end - start; - if (PyUnicode_IS_ASCII(self)) { - data = PyUnicode_1BYTE_DATA(self); - return _PyUnicode_FromASCII((char*)(data + start), length); - } - else { - kind = PyUnicode_KIND(self); - data = PyUnicode_1BYTE_DATA(self); - return PyUnicode_FromKindAndData(kind, - data + kind * start, - length); - } -} - -static PyObject * -do_strip(PyObject *self, int striptype) -{ - Py_ssize_t len, i, j; - - if (PyUnicode_READY(self) == -1) - return NULL; - - len = PyUnicode_GET_LENGTH(self); - - if (PyUnicode_IS_ASCII(self)) { - Py_UCS1 *data = PyUnicode_1BYTE_DATA(self); - - i = 0; - if (striptype != RIGHTSTRIP) { - while (i < len) { - Py_UCS1 ch = data[i]; - if (!_Py_ascii_whitespace[ch]) - break; - i++; - } - } - - j = len; - if (striptype != LEFTSTRIP) { - j--; - while (j >= i) { - Py_UCS1 ch = data[j]; - if (!_Py_ascii_whitespace[ch]) - break; - j--; - } - j++; - } - } - else { - int kind = PyUnicode_KIND(self); - void *data = PyUnicode_DATA(self); - - i = 0; - if (striptype != RIGHTSTRIP) { - while (i < len) { - Py_UCS4 ch = PyUnicode_READ(kind, data, i); - if (!Py_UNICODE_ISSPACE(ch)) - break; - i++; - } - } - - j = len; - if (striptype != LEFTSTRIP) { - j--; - while (j >= i) { - Py_UCS4 ch = PyUnicode_READ(kind, data, j); - if (!Py_UNICODE_ISSPACE(ch)) - break; - j--; - } - j++; - } - } - - return PyUnicode_Substring(self, i, j); -} - - -static PyObject * -do_argstrip(PyObject *self, int striptype, PyObject *args) -{ - PyObject *sep = NULL; - - if (!PyArg_ParseTuple(args, stripformat[striptype], &sep)) - return NULL; - - if (sep != NULL && sep != Py_None) { - if (PyUnicode_Check(sep)) - return _PyUnicode_XStrip(self, striptype, sep); - else { - PyErr_Format(PyExc_TypeError, - "%s arg must be None or str", - STRIPNAME(striptype)); - return NULL; - } - } - - return do_strip(self, striptype); -} - - -PyDoc_STRVAR(strip__doc__, - "S.strip([chars]) -> str\n\ -\n\ -Return a copy of the string S with leading and trailing\n\ -whitespace removed.\n\ -If chars is given and not None, remove characters in chars instead."); - -static PyObject * -unicode_strip(PyObject *self, PyObject *args) -{ - if (PyTuple_GET_SIZE(args) == 0) - return do_strip(self, BOTHSTRIP); /* Common case */ - else - return do_argstrip(self, BOTHSTRIP, args); -} - - -PyDoc_STRVAR(lstrip__doc__, - "S.lstrip([chars]) -> str\n\ -\n\ -Return a copy of the string S with leading whitespace removed.\n\ -If chars is given and not None, remove characters in chars instead."); - -static PyObject * -unicode_lstrip(PyObject *self, PyObject *args) -{ - if (PyTuple_GET_SIZE(args) == 0) - return do_strip(self, LEFTSTRIP); /* Common case */ - else - return do_argstrip(self, LEFTSTRIP, args); -} - - -PyDoc_STRVAR(rstrip__doc__, - "S.rstrip([chars]) -> str\n\ -\n\ -Return a copy of the string S with trailing whitespace removed.\n\ -If chars is given and not None, remove characters in chars instead."); - -static PyObject * -unicode_rstrip(PyObject *self, PyObject *args) -{ - if (PyTuple_GET_SIZE(args) == 0) - return do_strip(self, RIGHTSTRIP); /* Common case */ - else - return do_argstrip(self, RIGHTSTRIP, args); -} - - -static PyObject* -unicode_repeat(PyObject *str, Py_ssize_t len) -{ - PyObject *u; - Py_ssize_t nchars, n; - - if (len < 1) - _Py_RETURN_UNICODE_EMPTY(); - - /* no repeat, return original string */ - if (len == 1) - return unicode_result_unchanged(str); - - if (PyUnicode_READY(str) == -1) - return NULL; - - if (PyUnicode_GET_LENGTH(str) > PY_SSIZE_T_MAX / len) { - PyErr_SetString(PyExc_OverflowError, - "repeated string is too long"); - return NULL; - } - nchars = len * PyUnicode_GET_LENGTH(str); - - u = PyUnicode_New(nchars, PyUnicode_MAX_CHAR_VALUE(str)); - if (!u) - return NULL; - assert(PyUnicode_KIND(u) == PyUnicode_KIND(str)); - - if (PyUnicode_GET_LENGTH(str) == 1) { - const int kind = PyUnicode_KIND(str); - const Py_UCS4 fill_char = PyUnicode_READ(kind, PyUnicode_DATA(str), 0); - if (kind == PyUnicode_1BYTE_KIND) { - void *to = PyUnicode_DATA(u); - memset(to, (unsigned char)fill_char, len); - } - else if (kind == PyUnicode_2BYTE_KIND) { - Py_UCS2 *ucs2 = PyUnicode_2BYTE_DATA(u); - for (n = 0; n < len; ++n) - ucs2[n] = fill_char; - } else { - Py_UCS4 *ucs4 = PyUnicode_4BYTE_DATA(u); - assert(kind == PyUnicode_4BYTE_KIND); - for (n = 0; n < len; ++n) - ucs4[n] = fill_char; - } - } - else { - /* number of characters copied this far */ - Py_ssize_t done = PyUnicode_GET_LENGTH(str); - const Py_ssize_t char_size = PyUnicode_KIND(str); - char *to = (char *) PyUnicode_DATA(u); - Py_MEMCPY(to, PyUnicode_DATA(str), - PyUnicode_GET_LENGTH(str) * char_size); - while (done < nchars) { - n = (done <= nchars-done) ? done : nchars-done; - Py_MEMCPY(to + (done * char_size), to, n * char_size); - done += n; - } - } - - assert(_PyUnicode_CheckConsistency(u, 1)); - return u; -} - -PyObject * -PyUnicode_Replace(PyObject *obj, - PyObject *subobj, - PyObject *replobj, - Py_ssize_t maxcount) -{ - PyObject *self; - PyObject *str1; - PyObject *str2; - PyObject *result; - - self = PyUnicode_FromObject(obj); - if (self == NULL) - return NULL; - str1 = PyUnicode_FromObject(subobj); - if (str1 == NULL) { - Py_DECREF(self); - return NULL; - } - str2 = PyUnicode_FromObject(replobj); - if (str2 == NULL) { - Py_DECREF(self); - Py_DECREF(str1); - return NULL; - } - if (PyUnicode_READY(self) == -1 || - PyUnicode_READY(str1) == -1 || - PyUnicode_READY(str2) == -1) - result = NULL; - else - result = replace(self, str1, str2, maxcount); - Py_DECREF(self); - Py_DECREF(str1); - Py_DECREF(str2); - return result; -} - -PyDoc_STRVAR(replace__doc__, - "S.replace(old, new[, count]) -> str\n\ -\n\ -Return a copy of S with all occurrences of substring\n\ -old replaced by new. If the optional argument count is\n\ -given, only the first count occurrences are replaced."); - -static PyObject* -unicode_replace(PyObject *self, PyObject *args) -{ - PyObject *str1; - PyObject *str2; - Py_ssize_t maxcount = -1; - PyObject *result; - - if (!PyArg_ParseTuple(args, "OO|n:replace", &str1, &str2, &maxcount)) - return NULL; - if (PyUnicode_READY(self) == -1) - return NULL; - str1 = PyUnicode_FromObject(str1); - if (str1 == NULL) - return NULL; - str2 = PyUnicode_FromObject(str2); - if (str2 == NULL) { - Py_DECREF(str1); - return NULL; - } - if (PyUnicode_READY(str1) == -1 || PyUnicode_READY(str2) == -1) - result = NULL; - else - result = replace(self, str1, str2, maxcount); - - Py_DECREF(str1); - Py_DECREF(str2); - return result; -} - -static PyObject * -unicode_repr(PyObject *unicode) -{ - PyObject *repr; - Py_ssize_t isize; - Py_ssize_t osize, squote, dquote, i, o; - Py_UCS4 max, quote; - int ikind, okind, unchanged; - void *idata, *odata; - - if (PyUnicode_READY(unicode) == -1) - return NULL; - - isize = PyUnicode_GET_LENGTH(unicode); - idata = PyUnicode_DATA(unicode); - - /* Compute length of output, quote characters, and - maximum character */ - osize = 0; - max = 127; - squote = dquote = 0; - ikind = PyUnicode_KIND(unicode); - for (i = 0; i < isize; i++) { - Py_UCS4 ch = PyUnicode_READ(ikind, idata, i); - Py_ssize_t incr = 1; - switch (ch) { - case '\'': squote++; break; - case '"': dquote++; break; - case '\\': case '\t': case '\r': case '\n': - incr = 2; - break; - default: - /* Fast-path ASCII */ - if (ch < ' ' || ch == 0x7f) - incr = 4; /* \xHH */ - else if (ch < 0x7f) - ; - else if (Py_UNICODE_ISPRINTABLE(ch)) - max = ch > max ? ch : max; - else if (ch < 0x100) - incr = 4; /* \xHH */ - else if (ch < 0x10000) - incr = 6; /* \uHHHH */ - else - incr = 10; /* \uHHHHHHHH */ - } - if (osize > PY_SSIZE_T_MAX - incr) { - PyErr_SetString(PyExc_OverflowError, - "string is too long to generate repr"); - return NULL; - } - osize += incr; - } - - quote = '\''; - unchanged = (osize == isize); - if (squote) { - unchanged = 0; - if (dquote) - /* Both squote and dquote present. Use squote, - and escape them */ - osize += squote; - else - quote = '"'; - } - osize += 2; /* quotes */ - - repr = PyUnicode_New(osize, max); - if (repr == NULL) - return NULL; - okind = PyUnicode_KIND(repr); - odata = PyUnicode_DATA(repr); - - PyUnicode_WRITE(okind, odata, 0, quote); - PyUnicode_WRITE(okind, odata, osize-1, quote); - if (unchanged) { - _PyUnicode_FastCopyCharacters(repr, 1, - unicode, 0, - isize); - } - else { - for (i = 0, o = 1; i < isize; i++) { - Py_UCS4 ch = PyUnicode_READ(ikind, idata, i); - - /* Escape quotes and backslashes */ - if ((ch == quote) || (ch == '\\')) { - PyUnicode_WRITE(okind, odata, o++, '\\'); - PyUnicode_WRITE(okind, odata, o++, ch); - continue; - } - - /* Map special whitespace to '\t', \n', '\r' */ - if (ch == '\t') { - PyUnicode_WRITE(okind, odata, o++, '\\'); - PyUnicode_WRITE(okind, odata, o++, 't'); - } - else if (ch == '\n') { - PyUnicode_WRITE(okind, odata, o++, '\\'); - PyUnicode_WRITE(okind, odata, o++, 'n'); - } - else if (ch == '\r') { - PyUnicode_WRITE(okind, odata, o++, '\\'); - PyUnicode_WRITE(okind, odata, o++, 'r'); - } - - /* Map non-printable US ASCII to '\xhh' */ - else if (ch < ' ' || ch == 0x7F) { - PyUnicode_WRITE(okind, odata, o++, '\\'); - PyUnicode_WRITE(okind, odata, o++, 'x'); - PyUnicode_WRITE(okind, odata, o++, Py_hexdigits[(ch >> 4) & 0x000F]); - PyUnicode_WRITE(okind, odata, o++, Py_hexdigits[ch & 0x000F]); - } - - /* Copy ASCII characters as-is */ - else if (ch < 0x7F) { - PyUnicode_WRITE(okind, odata, o++, ch); - } - - /* Non-ASCII characters */ - else { - /* Map Unicode whitespace and control characters - (categories Z* and C* except ASCII space) - */ - if (!Py_UNICODE_ISPRINTABLE(ch)) { - PyUnicode_WRITE(okind, odata, o++, '\\'); - /* Map 8-bit characters to '\xhh' */ - if (ch <= 0xff) { - PyUnicode_WRITE(okind, odata, o++, 'x'); - PyUnicode_WRITE(okind, odata, o++, Py_hexdigits[(ch >> 4) & 0x000F]); - PyUnicode_WRITE(okind, odata, o++, Py_hexdigits[ch & 0x000F]); - } - /* Map 16-bit characters to '\uxxxx' */ - else if (ch <= 0xffff) { - PyUnicode_WRITE(okind, odata, o++, 'u'); - PyUnicode_WRITE(okind, odata, o++, Py_hexdigits[(ch >> 12) & 0xF]); - PyUnicode_WRITE(okind, odata, o++, Py_hexdigits[(ch >> 8) & 0xF]); - PyUnicode_WRITE(okind, odata, o++, Py_hexdigits[(ch >> 4) & 0xF]); - PyUnicode_WRITE(okind, odata, o++, Py_hexdigits[ch & 0xF]); - } - /* Map 21-bit characters to '\U00xxxxxx' */ - else { - PyUnicode_WRITE(okind, odata, o++, 'U'); - PyUnicode_WRITE(okind, odata, o++, Py_hexdigits[(ch >> 28) & 0xF]); - PyUnicode_WRITE(okind, odata, o++, Py_hexdigits[(ch >> 24) & 0xF]); - PyUnicode_WRITE(okind, odata, o++, Py_hexdigits[(ch >> 20) & 0xF]); - PyUnicode_WRITE(okind, odata, o++, Py_hexdigits[(ch >> 16) & 0xF]); - PyUnicode_WRITE(okind, odata, o++, Py_hexdigits[(ch >> 12) & 0xF]); - PyUnicode_WRITE(okind, odata, o++, Py_hexdigits[(ch >> 8) & 0xF]); - PyUnicode_WRITE(okind, odata, o++, Py_hexdigits[(ch >> 4) & 0xF]); - PyUnicode_WRITE(okind, odata, o++, Py_hexdigits[ch & 0xF]); - } - } - /* Copy characters as-is */ - else { - PyUnicode_WRITE(okind, odata, o++, ch); - } - } - } - } - /* Closing quote already added at the beginning */ - assert(_PyUnicode_CheckConsistency(repr, 1)); - return repr; -} - -PyDoc_STRVAR(rfind__doc__, - "S.rfind(sub[, start[, end]]) -> int\n\ -\n\ -Return the highest index in S where substring sub is found,\n\ -such that sub is contained within S[start:end]. Optional\n\ -arguments start and end are interpreted as in slice notation.\n\ -\n\ -Return -1 on failure."); - -static PyObject * -unicode_rfind(PyObject *self, PyObject *args) -{ - /* initialize variables to prevent gcc warning */ - PyObject *substring = NULL; - Py_ssize_t start = 0; - Py_ssize_t end = 0; - Py_ssize_t result; - - if (!stringlib_parse_args_finds_unicode("rfind", args, &substring, - &start, &end)) - return NULL; - - if (PyUnicode_READY(self) == -1) { - Py_DECREF(substring); - return NULL; - } - if (PyUnicode_READY(substring) == -1) { - Py_DECREF(substring); - return NULL; - } - - result = any_find_slice(-1, self, substring, start, end); - - Py_DECREF(substring); - - if (result == -2) - return NULL; - - return PyLong_FromSsize_t(result); -} - -PyDoc_STRVAR(rindex__doc__, - "S.rindex(sub[, start[, end]]) -> int\n\ -\n\ -Like S.rfind() but raise ValueError when the substring is not found."); - -static PyObject * -unicode_rindex(PyObject *self, PyObject *args) -{ - /* initialize variables to prevent gcc warning */ - PyObject *substring = NULL; - Py_ssize_t start = 0; - Py_ssize_t end = 0; - Py_ssize_t result; - - if (!stringlib_parse_args_finds_unicode("rindex", args, &substring, - &start, &end)) - return NULL; - - if (PyUnicode_READY(self) == -1) { - Py_DECREF(substring); - return NULL; - } - if (PyUnicode_READY(substring) == -1) { - Py_DECREF(substring); - return NULL; - } - - result = any_find_slice(-1, self, substring, start, end); - - Py_DECREF(substring); - - if (result == -2) - return NULL; - - if (result < 0) { - PyErr_SetString(PyExc_ValueError, "substring not found"); - return NULL; - } - - return PyLong_FromSsize_t(result); -} - -PyDoc_STRVAR(rjust__doc__, - "S.rjust(width[, fillchar]) -> str\n\ -\n\ -Return S right-justified in a string of length width. Padding is\n\ -done using the specified fill character (default is a space)."); - -static PyObject * -unicode_rjust(PyObject *self, PyObject *args) -{ - Py_ssize_t width; - Py_UCS4 fillchar = ' '; - - if (!PyArg_ParseTuple(args, "n|O&:rjust", &width, convert_uc, &fillchar)) - return NULL; - - if (PyUnicode_READY(self) == -1) - return NULL; - - if (PyUnicode_GET_LENGTH(self) >= width) - return unicode_result_unchanged(self); - - return pad(self, width - PyUnicode_GET_LENGTH(self), 0, fillchar); -} - -PyObject * -PyUnicode_Split(PyObject *s, PyObject *sep, Py_ssize_t maxsplit) -{ - PyObject *result; - - s = PyUnicode_FromObject(s); - if (s == NULL) - return NULL; - if (sep != NULL) { - sep = PyUnicode_FromObject(sep); - if (sep == NULL) { - Py_DECREF(s); - return NULL; - } - } - - result = split(s, sep, maxsplit); - - Py_DECREF(s); - Py_XDECREF(sep); - return result; -} - -PyDoc_STRVAR(split__doc__, - "S.split(sep=None, maxsplit=-1) -> list of strings\n\ -\n\ -Return a list of the words in S, using sep as the\n\ -delimiter string. If maxsplit is given, at most maxsplit\n\ -splits are done. If sep is not specified or is None, any\n\ -whitespace string is a separator and empty strings are\n\ -removed from the result."); - -static PyObject* -unicode_split(PyObject *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"sep", "maxsplit", 0}; - PyObject *substring = Py_None; - Py_ssize_t maxcount = -1; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|On:split", - kwlist, &substring, &maxcount)) - return NULL; - - if (substring == Py_None) - return split(self, NULL, maxcount); - else if (PyUnicode_Check(substring)) - return split(self, substring, maxcount); - else - return PyUnicode_Split(self, substring, maxcount); -} - -PyObject * -PyUnicode_Partition(PyObject *str_in, PyObject *sep_in) -{ - PyObject* str_obj; - PyObject* sep_obj; - PyObject* out; - int kind1, kind2; - void *buf1, *buf2; - Py_ssize_t len1, len2; - - str_obj = PyUnicode_FromObject(str_in); - if (!str_obj) - return NULL; - sep_obj = PyUnicode_FromObject(sep_in); - if (!sep_obj) { - Py_DECREF(str_obj); - return NULL; - } - if (PyUnicode_READY(sep_obj) == -1 || PyUnicode_READY(str_obj) == -1) { - Py_DECREF(sep_obj); - Py_DECREF(str_obj); - return NULL; - } - - kind1 = PyUnicode_KIND(str_obj); - kind2 = PyUnicode_KIND(sep_obj); - len1 = PyUnicode_GET_LENGTH(str_obj); - len2 = PyUnicode_GET_LENGTH(sep_obj); - if (kind1 < kind2 || len1 < len2) { - _Py_INCREF_UNICODE_EMPTY(); - if (!unicode_empty) - out = NULL; - else { - out = PyTuple_Pack(3, str_obj, unicode_empty, unicode_empty); - Py_DECREF(unicode_empty); - } - Py_DECREF(sep_obj); - Py_DECREF(str_obj); - return out; - } - buf1 = PyUnicode_DATA(str_obj); - buf2 = PyUnicode_DATA(sep_obj); - if (kind2 != kind1) { - buf2 = _PyUnicode_AsKind(sep_obj, kind1); - if (!buf2) - goto onError; - } - - switch (kind1) { - case PyUnicode_1BYTE_KIND: - if (PyUnicode_IS_ASCII(str_obj) && PyUnicode_IS_ASCII(sep_obj)) - out = asciilib_partition(str_obj, buf1, len1, sep_obj, buf2, len2); - else - out = ucs1lib_partition(str_obj, buf1, len1, sep_obj, buf2, len2); - break; - case PyUnicode_2BYTE_KIND: - out = ucs2lib_partition(str_obj, buf1, len1, sep_obj, buf2, len2); - break; - case PyUnicode_4BYTE_KIND: - out = ucs4lib_partition(str_obj, buf1, len1, sep_obj, buf2, len2); - break; - default: - assert(0); - out = 0; - } - - Py_DECREF(sep_obj); - Py_DECREF(str_obj); - if (kind2 != kind1) - PyMem_Free(buf2); - - return out; - onError: - Py_DECREF(sep_obj); - Py_DECREF(str_obj); - if (kind2 != kind1 && buf2) - PyMem_Free(buf2); - return NULL; -} - - -PyObject * -PyUnicode_RPartition(PyObject *str_in, PyObject *sep_in) -{ - PyObject* str_obj; - PyObject* sep_obj; - PyObject* out; - int kind1, kind2; - void *buf1, *buf2; - Py_ssize_t len1, len2; - - str_obj = PyUnicode_FromObject(str_in); - if (!str_obj) - return NULL; - sep_obj = PyUnicode_FromObject(sep_in); - if (!sep_obj) { - Py_DECREF(str_obj); - return NULL; - } - - kind1 = PyUnicode_KIND(str_obj); - kind2 = PyUnicode_KIND(sep_obj); - len1 = PyUnicode_GET_LENGTH(str_obj); - len2 = PyUnicode_GET_LENGTH(sep_obj); - if (kind1 < kind2 || len1 < len2) { - _Py_INCREF_UNICODE_EMPTY(); - if (!unicode_empty) - out = NULL; - else { - out = PyTuple_Pack(3, unicode_empty, unicode_empty, str_obj); - Py_DECREF(unicode_empty); - } - Py_DECREF(sep_obj); - Py_DECREF(str_obj); - return out; - } - buf1 = PyUnicode_DATA(str_obj); - buf2 = PyUnicode_DATA(sep_obj); - if (kind2 != kind1) { - buf2 = _PyUnicode_AsKind(sep_obj, kind1); - if (!buf2) - goto onError; - } - - switch (kind1) { - case PyUnicode_1BYTE_KIND: - if (PyUnicode_IS_ASCII(str_obj) && PyUnicode_IS_ASCII(sep_obj)) - out = asciilib_rpartition(str_obj, buf1, len1, sep_obj, buf2, len2); - else - out = ucs1lib_rpartition(str_obj, buf1, len1, sep_obj, buf2, len2); - break; - case PyUnicode_2BYTE_KIND: - out = ucs2lib_rpartition(str_obj, buf1, len1, sep_obj, buf2, len2); - break; - case PyUnicode_4BYTE_KIND: - out = ucs4lib_rpartition(str_obj, buf1, len1, sep_obj, buf2, len2); - break; - default: - assert(0); - out = 0; - } - - Py_DECREF(sep_obj); - Py_DECREF(str_obj); - if (kind2 != kind1) - PyMem_Free(buf2); - - return out; - onError: - Py_DECREF(sep_obj); - Py_DECREF(str_obj); - if (kind2 != kind1 && buf2) - PyMem_Free(buf2); - return NULL; -} - -PyDoc_STRVAR(partition__doc__, - "S.partition(sep) -> (head, sep, tail)\n\ -\n\ -Search for the separator sep in S, and return the part before it,\n\ -the separator itself, and the part after it. If the separator is not\n\ -found, return S and two empty strings."); - -static PyObject* -unicode_partition(PyObject *self, PyObject *separator) -{ - return PyUnicode_Partition(self, separator); -} - -PyDoc_STRVAR(rpartition__doc__, - "S.rpartition(sep) -> (head, sep, tail)\n\ -\n\ -Search for the separator sep in S, starting at the end of S, and return\n\ -the part before it, the separator itself, and the part after it. If the\n\ -separator is not found, return two empty strings and S."); - -static PyObject* -unicode_rpartition(PyObject *self, PyObject *separator) -{ - return PyUnicode_RPartition(self, separator); -} - -PyObject * -PyUnicode_RSplit(PyObject *s, PyObject *sep, Py_ssize_t maxsplit) -{ - PyObject *result; - - s = PyUnicode_FromObject(s); - if (s == NULL) - return NULL; - if (sep != NULL) { - sep = PyUnicode_FromObject(sep); - if (sep == NULL) { - Py_DECREF(s); - return NULL; - } - } - - result = rsplit(s, sep, maxsplit); - - Py_DECREF(s); - Py_XDECREF(sep); - return result; -} - -PyDoc_STRVAR(rsplit__doc__, - "S.rsplit(sep=None, maxsplit=-1) -> list of strings\n\ -\n\ -Return a list of the words in S, using sep as the\n\ -delimiter string, starting at the end of the string and\n\ -working to the front. If maxsplit is given, at most maxsplit\n\ -splits are done. If sep is not specified, any whitespace string\n\ -is a separator."); - -static PyObject* -unicode_rsplit(PyObject *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"sep", "maxsplit", 0}; - PyObject *substring = Py_None; - Py_ssize_t maxcount = -1; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|On:rsplit", - kwlist, &substring, &maxcount)) - return NULL; - - if (substring == Py_None) - return rsplit(self, NULL, maxcount); - else if (PyUnicode_Check(substring)) - return rsplit(self, substring, maxcount); - else - return PyUnicode_RSplit(self, substring, maxcount); -} - -PyDoc_STRVAR(splitlines__doc__, - "S.splitlines([keepends]) -> list of strings\n\ -\n\ -Return a list of the lines in S, breaking at line boundaries.\n\ -Line breaks are not included in the resulting list unless keepends\n\ -is given and true."); - -static PyObject* -unicode_splitlines(PyObject *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"keepends", 0}; - int keepends = 0; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|i:splitlines", - kwlist, &keepends)) - return NULL; - - return PyUnicode_Splitlines(self, keepends); -} - -static -PyObject *unicode_str(PyObject *self) -{ - return unicode_result_unchanged(self); -} - -PyDoc_STRVAR(swapcase__doc__, - "S.swapcase() -> str\n\ -\n\ -Return a copy of S with uppercase characters converted to lowercase\n\ -and vice versa."); - -static PyObject* -unicode_swapcase(PyObject *self) -{ - if (PyUnicode_READY(self) == -1) - return NULL; - return case_operation(self, do_swapcase); -} - -/*[clinic input] - - at staticmethod -str.maketrans as unicode_maketrans - - x: object - - y: unicode=NULL - - z: unicode=NULL - - / - -Return a translation table usable for str.translate(). - -If there is only one argument, it must be a dictionary mapping Unicode -ordinals (integers) or characters to Unicode ordinals, strings or None. -Character keys will be then converted to ordinals. -If there are two arguments, they must be strings of equal length, and -in the resulting dictionary, each character in x will be mapped to the -character at the same position in y. If there is a third argument, it -must be a string, whose characters will be mapped to None in the result. +preserve [clinic start generated code]*/ PyDoc_STRVAR(unicode_maketrans__doc__, @@ -12992,2486 +39,4 @@ exit: return return_value; } - -static PyObject * -unicode_maketrans_impl(PyObject *x, PyObject *y, PyObject *z) -/*[clinic end generated code: output=566edf630f77436a input=7bfbf529a293c6c5]*/ -{ - PyObject *new = NULL, *key, *value; - Py_ssize_t i = 0; - int res; - - new = PyDict_New(); - if (!new) - return NULL; - if (y != NULL) { - int x_kind, y_kind, z_kind; - void *x_data, *y_data, *z_data; - - /* x must be a string too, of equal length */ - if (!PyUnicode_Check(x)) { - PyErr_SetString(PyExc_TypeError, "first maketrans argument must " - "be a string if there is a second argument"); - goto err; - } - if (PyUnicode_GET_LENGTH(x) != PyUnicode_GET_LENGTH(y)) { - PyErr_SetString(PyExc_ValueError, "the first two maketrans " - "arguments must have equal length"); - goto err; - } - /* create entries for translating chars in x to those in y */ - x_kind = PyUnicode_KIND(x); - y_kind = PyUnicode_KIND(y); - x_data = PyUnicode_DATA(x); - y_data = PyUnicode_DATA(y); - for (i = 0; i < PyUnicode_GET_LENGTH(x); i++) { - key = PyLong_FromLong(PyUnicode_READ(x_kind, x_data, i)); - if (!key) - goto err; - value = PyLong_FromLong(PyUnicode_READ(y_kind, y_data, i)); - if (!value) { - Py_DECREF(key); - goto err; - } - res = PyDict_SetItem(new, key, value); - Py_DECREF(key); - Py_DECREF(value); - if (res < 0) - goto err; - } - /* create entries for deleting chars in z */ - if (z != NULL) { - z_kind = PyUnicode_KIND(z); - z_data = PyUnicode_DATA(z); - for (i = 0; i < PyUnicode_GET_LENGTH(z); i++) { - key = PyLong_FromLong(PyUnicode_READ(z_kind, z_data, i)); - if (!key) - goto err; - res = PyDict_SetItem(new, key, Py_None); - Py_DECREF(key); - if (res < 0) - goto err; - } - } - } else { - int kind; - void *data; - - /* x must be a dict */ - if (!PyDict_CheckExact(x)) { - PyErr_SetString(PyExc_TypeError, "if you give only one argument " - "to maketrans it must be a dict"); - goto err; - } - /* copy entries into the new dict, converting string keys to int keys */ - while (PyDict_Next(x, &i, &key, &value)) { - if (PyUnicode_Check(key)) { - /* convert string keys to integer keys */ - PyObject *newkey; - if (PyUnicode_GET_LENGTH(key) != 1) { - PyErr_SetString(PyExc_ValueError, "string keys in translate " - "table must be of length 1"); - goto err; - } - kind = PyUnicode_KIND(key); - data = PyUnicode_DATA(key); - newkey = PyLong_FromLong(PyUnicode_READ(kind, data, 0)); - if (!newkey) - goto err; - res = PyDict_SetItem(new, newkey, value); - Py_DECREF(newkey); - if (res < 0) - goto err; - } else if (PyLong_Check(key)) { - /* just keep integer keys */ - if (PyDict_SetItem(new, key, value) < 0) - goto err; - } else { - PyErr_SetString(PyExc_TypeError, "keys in translate table must " - "be strings or integers"); - goto err; - } - } - } - return new; - err: - Py_DECREF(new); - return NULL; -} - -PyDoc_STRVAR(translate__doc__, - "S.translate(table) -> str\n\ -\n\ -Return a copy of the string S, where all characters have been mapped\n\ -through the given translation table, which must be a mapping of\n\ -Unicode ordinals to Unicode ordinals, strings, or None.\n\ -Unmapped characters are left untouched. Characters mapped to None\n\ -are deleted."); - -static PyObject* -unicode_translate(PyObject *self, PyObject *table) -{ - return _PyUnicode_TranslateCharmap(self, table, "ignore"); -} - -PyDoc_STRVAR(upper__doc__, - "S.upper() -> str\n\ -\n\ -Return a copy of S converted to uppercase."); - -static PyObject* -unicode_upper(PyObject *self) -{ - if (PyUnicode_READY(self) == -1) - return NULL; - if (PyUnicode_IS_ASCII(self)) - return ascii_upper_or_lower(self, 0); - return case_operation(self, do_upper); -} - -PyDoc_STRVAR(zfill__doc__, - "S.zfill(width) -> str\n\ -\n\ -Pad a numeric string S with zeros on the left, to fill a field\n\ -of the specified width. The string S is never truncated."); - -static PyObject * -unicode_zfill(PyObject *self, PyObject *args) -{ - Py_ssize_t fill; - PyObject *u; - Py_ssize_t width; - int kind; - void *data; - Py_UCS4 chr; - - if (!PyArg_ParseTuple(args, "n:zfill", &width)) - return NULL; - - if (PyUnicode_READY(self) == -1) - return NULL; - - if (PyUnicode_GET_LENGTH(self) >= width) - return unicode_result_unchanged(self); - - fill = width - PyUnicode_GET_LENGTH(self); - - u = pad(self, fill, 0, '0'); - - if (u == NULL) - return NULL; - - kind = PyUnicode_KIND(u); - data = PyUnicode_DATA(u); - chr = PyUnicode_READ(kind, data, fill); - - if (chr == '+' || chr == '-') { - /* move sign to beginning of string */ - PyUnicode_WRITE(kind, data, 0, chr); - PyUnicode_WRITE(kind, data, fill, '0'); - } - - assert(_PyUnicode_CheckConsistency(u, 1)); - return u; -} - -#if 0 -static PyObject * -unicode__decimal2ascii(PyObject *self) -{ - return PyUnicode_TransformDecimalAndSpaceToASCII(self); -} -#endif - -PyDoc_STRVAR(startswith__doc__, - "S.startswith(prefix[, start[, end]]) -> bool\n\ -\n\ -Return True if S starts with the specified prefix, False otherwise.\n\ -With optional start, test S beginning at that position.\n\ -With optional end, stop comparing S at that position.\n\ -prefix can also be a tuple of strings to try."); - -static PyObject * -unicode_startswith(PyObject *self, - PyObject *args) -{ - PyObject *subobj; - PyObject *substring; - Py_ssize_t start = 0; - Py_ssize_t end = PY_SSIZE_T_MAX; - int result; - - if (!stringlib_parse_args_finds("startswith", args, &subobj, &start, &end)) - return NULL; - if (PyTuple_Check(subobj)) { - Py_ssize_t i; - for (i = 0; i < PyTuple_GET_SIZE(subobj); i++) { - substring = PyUnicode_FromObject(PyTuple_GET_ITEM(subobj, i)); - if (substring == NULL) - return NULL; - result = tailmatch(self, substring, start, end, -1); - Py_DECREF(substring); - if (result == -1) - return NULL; - if (result) { - Py_RETURN_TRUE; - } - } - /* nothing matched */ - Py_RETURN_FALSE; - } - substring = PyUnicode_FromObject(subobj); - if (substring == NULL) { - if (PyErr_ExceptionMatches(PyExc_TypeError)) - PyErr_Format(PyExc_TypeError, "startswith first arg must be str or " - "a tuple of str, not %s", Py_TYPE(subobj)->tp_name); - return NULL; - } - result = tailmatch(self, substring, start, end, -1); - Py_DECREF(substring); - if (result == -1) - return NULL; - return PyBool_FromLong(result); -} - - -PyDoc_STRVAR(endswith__doc__, - "S.endswith(suffix[, start[, end]]) -> bool\n\ -\n\ -Return True if S ends with the specified suffix, False otherwise.\n\ -With optional start, test S beginning at that position.\n\ -With optional end, stop comparing S at that position.\n\ -suffix can also be a tuple of strings to try."); - -static PyObject * -unicode_endswith(PyObject *self, - PyObject *args) -{ - PyObject *subobj; - PyObject *substring; - Py_ssize_t start = 0; - Py_ssize_t end = PY_SSIZE_T_MAX; - int result; - - if (!stringlib_parse_args_finds("endswith", args, &subobj, &start, &end)) - return NULL; - if (PyTuple_Check(subobj)) { - Py_ssize_t i; - for (i = 0; i < PyTuple_GET_SIZE(subobj); i++) { - substring = PyUnicode_FromObject( - PyTuple_GET_ITEM(subobj, i)); - if (substring == NULL) - return NULL; - result = tailmatch(self, substring, start, end, +1); - Py_DECREF(substring); - if (result == -1) - return NULL; - if (result) { - Py_RETURN_TRUE; - } - } - Py_RETURN_FALSE; - } - substring = PyUnicode_FromObject(subobj); - if (substring == NULL) { - if (PyErr_ExceptionMatches(PyExc_TypeError)) - PyErr_Format(PyExc_TypeError, "endswith first arg must be str or " - "a tuple of str, not %s", Py_TYPE(subobj)->tp_name); - return NULL; - } - result = tailmatch(self, substring, start, end, +1); - Py_DECREF(substring); - if (result == -1) - return NULL; - return PyBool_FromLong(result); -} - -Py_LOCAL_INLINE(void) -_PyUnicodeWriter_Update(_PyUnicodeWriter *writer) -{ - if (!writer->readonly) - writer->size = PyUnicode_GET_LENGTH(writer->buffer); - else { - /* Copy-on-write mode: set buffer size to 0 so - * _PyUnicodeWriter_Prepare() will copy (and enlarge) the buffer on - * next write. */ - writer->size = 0; - } - writer->maxchar = PyUnicode_MAX_CHAR_VALUE(writer->buffer); - writer->data = PyUnicode_DATA(writer->buffer); - writer->kind = PyUnicode_KIND(writer->buffer); -} - -void -_PyUnicodeWriter_Init(_PyUnicodeWriter *writer) -{ - memset(writer, 0, sizeof(*writer)); -#ifdef Py_DEBUG - writer->kind = 5; /* invalid kind */ -#endif - writer->min_char = 127; -} - -int -_PyUnicodeWriter_PrepareInternal(_PyUnicodeWriter *writer, - Py_ssize_t length, Py_UCS4 maxchar) -{ -#ifdef MS_WINDOWS - /* On Windows, overallocate by 50% is the best factor */ -# define OVERALLOCATE_FACTOR 2 -#else - /* On Linux, overallocate by 25% is the best factor */ -# define OVERALLOCATE_FACTOR 4 -#endif - Py_ssize_t newlen; - PyObject *newbuffer; - - assert(length > 0); - - if (length > PY_SSIZE_T_MAX - writer->pos) { - PyErr_NoMemory(); - return -1; - } - newlen = writer->pos + length; - - maxchar = Py_MAX(maxchar, writer->min_char); - - if (writer->buffer == NULL) { - assert(!writer->readonly); - if (writer->overallocate - && newlen <= (PY_SSIZE_T_MAX - newlen / OVERALLOCATE_FACTOR)) { - /* overallocate to limit the number of realloc() */ - newlen += newlen / OVERALLOCATE_FACTOR; - } - if (newlen < writer->min_length) - newlen = writer->min_length; - - writer->buffer = PyUnicode_New(newlen, maxchar); - if (writer->buffer == NULL) - return -1; - } - else if (newlen > writer->size) { - if (writer->overallocate - && newlen <= (PY_SSIZE_T_MAX - newlen / OVERALLOCATE_FACTOR)) { - /* overallocate to limit the number of realloc() */ - newlen += newlen / OVERALLOCATE_FACTOR; - } - if (newlen < writer->min_length) - newlen = writer->min_length; - - if (maxchar > writer->maxchar || writer->readonly) { - /* resize + widen */ - newbuffer = PyUnicode_New(newlen, maxchar); - if (newbuffer == NULL) - return -1; - _PyUnicode_FastCopyCharacters(newbuffer, 0, - writer->buffer, 0, writer->pos); - Py_DECREF(writer->buffer); - writer->readonly = 0; - } - else { - newbuffer = resize_compact(writer->buffer, newlen); - if (newbuffer == NULL) - return -1; - } - writer->buffer = newbuffer; - } - else if (maxchar > writer->maxchar) { - assert(!writer->readonly); - newbuffer = PyUnicode_New(writer->size, maxchar); - if (newbuffer == NULL) - return -1; - _PyUnicode_FastCopyCharacters(newbuffer, 0, - writer->buffer, 0, writer->pos); - Py_DECREF(writer->buffer); - writer->buffer = newbuffer; - } - _PyUnicodeWriter_Update(writer); - return 0; - -#undef OVERALLOCATE_FACTOR -} - -Py_LOCAL_INLINE(int) -_PyUnicodeWriter_WriteCharInline(_PyUnicodeWriter *writer, Py_UCS4 ch) -{ - if (_PyUnicodeWriter_Prepare(writer, 1, ch) < 0) - return -1; - PyUnicode_WRITE(writer->kind, writer->data, writer->pos, ch); - writer->pos++; - return 0; -} - -int -_PyUnicodeWriter_WriteChar(_PyUnicodeWriter *writer, Py_UCS4 ch) -{ - return _PyUnicodeWriter_WriteCharInline(writer, ch); -} - -int -_PyUnicodeWriter_WriteStr(_PyUnicodeWriter *writer, PyObject *str) -{ - Py_UCS4 maxchar; - Py_ssize_t len; - - if (PyUnicode_READY(str) == -1) - return -1; - len = PyUnicode_GET_LENGTH(str); - if (len == 0) - return 0; - maxchar = PyUnicode_MAX_CHAR_VALUE(str); - if (maxchar > writer->maxchar || len > writer->size - writer->pos) { - if (writer->buffer == NULL && !writer->overallocate) { - assert(_PyUnicode_CheckConsistency(str, 1)); - writer->readonly = 1; - Py_INCREF(str); - writer->buffer = str; - _PyUnicodeWriter_Update(writer); - writer->pos += len; - return 0; - } - if (_PyUnicodeWriter_PrepareInternal(writer, len, maxchar) == -1) - return -1; - } - _PyUnicode_FastCopyCharacters(writer->buffer, writer->pos, - str, 0, len); - writer->pos += len; - return 0; -} - -int -_PyUnicodeWriter_WriteSubstring(_PyUnicodeWriter *writer, PyObject *str, - Py_ssize_t start, Py_ssize_t end) -{ - Py_UCS4 maxchar; - Py_ssize_t len; - - if (PyUnicode_READY(str) == -1) - return -1; - - assert(0 <= start); - assert(end <= PyUnicode_GET_LENGTH(str)); - assert(start <= end); - - if (end == 0) - return 0; - - if (start == 0 && end == PyUnicode_GET_LENGTH(str)) - return _PyUnicodeWriter_WriteStr(writer, str); - - if (PyUnicode_MAX_CHAR_VALUE(str) > writer->maxchar) - maxchar = _PyUnicode_FindMaxChar(str, start, end); - else - maxchar = writer->maxchar; - len = end - start; - - if (_PyUnicodeWriter_Prepare(writer, len, maxchar) < 0) - return -1; - - _PyUnicode_FastCopyCharacters(writer->buffer, writer->pos, - str, start, len); - writer->pos += len; - return 0; -} - -int -_PyUnicodeWriter_WriteASCIIString(_PyUnicodeWriter *writer, - const char *ascii, Py_ssize_t len) -{ - if (len == -1) - len = strlen(ascii); - - assert(ucs1lib_find_max_char((Py_UCS1*)ascii, (Py_UCS1*)ascii + len) < 128); - - if (writer->buffer == NULL && !writer->overallocate) { - PyObject *str; - - str = _PyUnicode_FromASCII(ascii, len); - if (str == NULL) - return -1; - - writer->readonly = 1; - writer->buffer = str; - _PyUnicodeWriter_Update(writer); - writer->pos += len; - return 0; - } - - if (_PyUnicodeWriter_Prepare(writer, len, 127) == -1) - return -1; - - switch (writer->kind) - { - case PyUnicode_1BYTE_KIND: - { - const Py_UCS1 *str = (const Py_UCS1 *)ascii; - Py_UCS1 *data = writer->data; - - Py_MEMCPY(data + writer->pos, str, len); - break; - } - case PyUnicode_2BYTE_KIND: - { - _PyUnicode_CONVERT_BYTES( - Py_UCS1, Py_UCS2, - ascii, ascii + len, - (Py_UCS2 *)writer->data + writer->pos); - break; - } - case PyUnicode_4BYTE_KIND: - { - _PyUnicode_CONVERT_BYTES( - Py_UCS1, Py_UCS4, - ascii, ascii + len, - (Py_UCS4 *)writer->data + writer->pos); - break; - } - default: - assert(0); - } - - writer->pos += len; - return 0; -} - -int -_PyUnicodeWriter_WriteLatin1String(_PyUnicodeWriter *writer, - const char *str, Py_ssize_t len) -{ - Py_UCS4 maxchar; - - maxchar = ucs1lib_find_max_char((Py_UCS1*)str, (Py_UCS1*)str + len); - if (_PyUnicodeWriter_Prepare(writer, len, maxchar) == -1) - return -1; - unicode_write_cstr(writer->buffer, writer->pos, str, len); - writer->pos += len; - return 0; -} - -PyObject * -_PyUnicodeWriter_Finish(_PyUnicodeWriter *writer) -{ - PyObject *str; - if (writer->pos == 0) { - Py_CLEAR(writer->buffer); - _Py_RETURN_UNICODE_EMPTY(); - } - if (writer->readonly) { - str = writer->buffer; - writer->buffer = NULL; - assert(PyUnicode_GET_LENGTH(str) == writer->pos); - return str; - } - if (PyUnicode_GET_LENGTH(writer->buffer) != writer->pos) { - PyObject *newbuffer; - newbuffer = resize_compact(writer->buffer, writer->pos); - if (newbuffer == NULL) { - Py_CLEAR(writer->buffer); - return NULL; - } - writer->buffer = newbuffer; - } - str = writer->buffer; - writer->buffer = NULL; - assert(_PyUnicode_CheckConsistency(str, 1)); - return unicode_result_ready(str); -} - -void -_PyUnicodeWriter_Dealloc(_PyUnicodeWriter *writer) -{ - Py_CLEAR(writer->buffer); -} - -#include "stringlib/unicode_format.h" - -PyDoc_STRVAR(format__doc__, - "S.format(*args, **kwargs) -> str\n\ -\n\ -Return a formatted version of S, using substitutions from args and kwargs.\n\ -The substitutions are identified by braces ('{' and '}')."); - -PyDoc_STRVAR(format_map__doc__, - "S.format_map(mapping) -> str\n\ -\n\ -Return a formatted version of S, using substitutions from mapping.\n\ -The substitutions are identified by braces ('{' and '}')."); - -static PyObject * -unicode__format__(PyObject* self, PyObject* args) -{ - PyObject *format_spec; - _PyUnicodeWriter writer; - int ret; - - if (!PyArg_ParseTuple(args, "U:__format__", &format_spec)) - return NULL; - - if (PyUnicode_READY(self) == -1) - return NULL; - _PyUnicodeWriter_Init(&writer); - ret = _PyUnicode_FormatAdvancedWriter(&writer, - self, format_spec, 0, - PyUnicode_GET_LENGTH(format_spec)); - if (ret == -1) { - _PyUnicodeWriter_Dealloc(&writer); - return NULL; - } - return _PyUnicodeWriter_Finish(&writer); -} - -PyDoc_STRVAR(p_format__doc__, - "S.__format__(format_spec) -> str\n\ -\n\ -Return a formatted version of S as described by format_spec."); - -static PyObject * -unicode__sizeof__(PyObject *v) -{ - Py_ssize_t size; - - /* If it's a compact object, account for base structure + - character data. */ - if (PyUnicode_IS_COMPACT_ASCII(v)) - size = sizeof(PyASCIIObject) + PyUnicode_GET_LENGTH(v) + 1; - else if (PyUnicode_IS_COMPACT(v)) - size = sizeof(PyCompactUnicodeObject) + - (PyUnicode_GET_LENGTH(v) + 1) * PyUnicode_KIND(v); - else { - /* If it is a two-block object, account for base object, and - for character block if present. */ - size = sizeof(PyUnicodeObject); - if (_PyUnicode_DATA_ANY(v)) - size += (PyUnicode_GET_LENGTH(v) + 1) * - PyUnicode_KIND(v); - } - /* If the wstr pointer is present, account for it unless it is shared - with the data pointer. Check if the data is not shared. */ - if (_PyUnicode_HAS_WSTR_MEMORY(v)) - size += (PyUnicode_WSTR_LENGTH(v) + 1) * sizeof(wchar_t); - if (_PyUnicode_HAS_UTF8_MEMORY(v)) - size += PyUnicode_UTF8_LENGTH(v) + 1; - - return PyLong_FromSsize_t(size); -} - -PyDoc_STRVAR(sizeof__doc__, - "S.__sizeof__() -> size of S in memory, in bytes"); - -static PyObject * -unicode_getnewargs(PyObject *v) -{ - PyObject *copy = _PyUnicode_Copy(v); - if (!copy) - return NULL; - return Py_BuildValue("(N)", copy); -} - -static PyMethodDef unicode_methods[] = { - {"encode", (PyCFunction) unicode_encode, METH_VARARGS | METH_KEYWORDS, encode__doc__}, - {"replace", (PyCFunction) unicode_replace, METH_VARARGS, replace__doc__}, - {"split", (PyCFunction) unicode_split, METH_VARARGS | METH_KEYWORDS, split__doc__}, - {"rsplit", (PyCFunction) unicode_rsplit, METH_VARARGS | METH_KEYWORDS, rsplit__doc__}, - {"join", (PyCFunction) unicode_join, METH_O, join__doc__}, - {"capitalize", (PyCFunction) unicode_capitalize, METH_NOARGS, capitalize__doc__}, - {"casefold", (PyCFunction) unicode_casefold, METH_NOARGS, casefold__doc__}, - {"title", (PyCFunction) unicode_title, METH_NOARGS, title__doc__}, - {"center", (PyCFunction) unicode_center, METH_VARARGS, center__doc__}, - {"count", (PyCFunction) unicode_count, METH_VARARGS, count__doc__}, - {"expandtabs", (PyCFunction) unicode_expandtabs, - METH_VARARGS | METH_KEYWORDS, expandtabs__doc__}, - {"find", (PyCFunction) unicode_find, METH_VARARGS, find__doc__}, - {"partition", (PyCFunction) unicode_partition, METH_O, partition__doc__}, - {"index", (PyCFunction) unicode_index, METH_VARARGS, index__doc__}, - {"ljust", (PyCFunction) unicode_ljust, METH_VARARGS, ljust__doc__}, - {"lower", (PyCFunction) unicode_lower, METH_NOARGS, lower__doc__}, - {"lstrip", (PyCFunction) unicode_lstrip, METH_VARARGS, lstrip__doc__}, - {"rfind", (PyCFunction) unicode_rfind, METH_VARARGS, rfind__doc__}, - {"rindex", (PyCFunction) unicode_rindex, METH_VARARGS, rindex__doc__}, - {"rjust", (PyCFunction) unicode_rjust, METH_VARARGS, rjust__doc__}, - {"rstrip", (PyCFunction) unicode_rstrip, METH_VARARGS, rstrip__doc__}, - {"rpartition", (PyCFunction) unicode_rpartition, METH_O, rpartition__doc__}, - {"splitlines", (PyCFunction) unicode_splitlines, - METH_VARARGS | METH_KEYWORDS, splitlines__doc__}, - {"strip", (PyCFunction) unicode_strip, METH_VARARGS, strip__doc__}, - {"swapcase", (PyCFunction) unicode_swapcase, METH_NOARGS, swapcase__doc__}, - {"translate", (PyCFunction) unicode_translate, METH_O, translate__doc__}, - {"upper", (PyCFunction) unicode_upper, METH_NOARGS, upper__doc__}, - {"startswith", (PyCFunction) unicode_startswith, METH_VARARGS, startswith__doc__}, - {"endswith", (PyCFunction) unicode_endswith, METH_VARARGS, endswith__doc__}, - {"islower", (PyCFunction) unicode_islower, METH_NOARGS, islower__doc__}, - {"isupper", (PyCFunction) unicode_isupper, METH_NOARGS, isupper__doc__}, - {"istitle", (PyCFunction) unicode_istitle, METH_NOARGS, istitle__doc__}, - {"isspace", (PyCFunction) unicode_isspace, METH_NOARGS, isspace__doc__}, - {"isdecimal", (PyCFunction) unicode_isdecimal, METH_NOARGS, isdecimal__doc__}, - {"isdigit", (PyCFunction) unicode_isdigit, METH_NOARGS, isdigit__doc__}, - {"isnumeric", (PyCFunction) unicode_isnumeric, METH_NOARGS, isnumeric__doc__}, - {"isalpha", (PyCFunction) unicode_isalpha, METH_NOARGS, isalpha__doc__}, - {"isalnum", (PyCFunction) unicode_isalnum, METH_NOARGS, isalnum__doc__}, - {"isidentifier", (PyCFunction) unicode_isidentifier, METH_NOARGS, isidentifier__doc__}, - {"isprintable", (PyCFunction) unicode_isprintable, METH_NOARGS, isprintable__doc__}, - {"zfill", (PyCFunction) unicode_zfill, METH_VARARGS, zfill__doc__}, - {"format", (PyCFunction) do_string_format, METH_VARARGS | METH_KEYWORDS, format__doc__}, - {"format_map", (PyCFunction) do_string_format_map, METH_O, format_map__doc__}, - {"__format__", (PyCFunction) unicode__format__, METH_VARARGS, p_format__doc__}, - UNICODE_MAKETRANS_METHODDEF - {"__sizeof__", (PyCFunction) unicode__sizeof__, METH_NOARGS, sizeof__doc__}, -#if 0 - /* These methods are just used for debugging the implementation. */ - {"_decimal2ascii", (PyCFunction) unicode__decimal2ascii, METH_NOARGS}, -#endif - - {"__getnewargs__", (PyCFunction)unicode_getnewargs, METH_NOARGS}, - {NULL, NULL} -}; - -static PyObject * -unicode_mod(PyObject *v, PyObject *w) -{ - if (!PyUnicode_Check(v)) - Py_RETURN_NOTIMPLEMENTED; - return PyUnicode_Format(v, w); -} - -static PyNumberMethods unicode_as_number = { - 0, /*nb_add*/ - 0, /*nb_subtract*/ - 0, /*nb_multiply*/ - unicode_mod, /*nb_remainder*/ -}; - -static PySequenceMethods unicode_as_sequence = { - (lenfunc) unicode_length, /* sq_length */ - PyUnicode_Concat, /* sq_concat */ - (ssizeargfunc) unicode_repeat, /* sq_repeat */ - (ssizeargfunc) unicode_getitem, /* sq_item */ - 0, /* sq_slice */ - 0, /* sq_ass_item */ - 0, /* sq_ass_slice */ - PyUnicode_Contains, /* sq_contains */ -}; - -static PyObject* -unicode_subscript(PyObject* self, PyObject* item) -{ - if (PyUnicode_READY(self) == -1) - return NULL; - - if (PyIndex_Check(item)) { - Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError); - if (i == -1 && PyErr_Occurred()) - return NULL; - if (i < 0) - i += PyUnicode_GET_LENGTH(self); - return unicode_getitem(self, i); - } else if (PySlice_Check(item)) { - Py_ssize_t start, stop, step, slicelength, cur, i; - PyObject *result; - void *src_data, *dest_data; - int src_kind, dest_kind; - Py_UCS4 ch, max_char, kind_limit; - - if (PySlice_GetIndicesEx(item, PyUnicode_GET_LENGTH(self), - &start, &stop, &step, &slicelength) < 0) { - return NULL; - } - - if (slicelength <= 0) { - _Py_RETURN_UNICODE_EMPTY(); - } else if (start == 0 && step == 1 && - slicelength == PyUnicode_GET_LENGTH(self)) { - return unicode_result_unchanged(self); - } else if (step == 1) { - return PyUnicode_Substring(self, - start, start + slicelength); - } - /* General case */ - src_kind = PyUnicode_KIND(self); - src_data = PyUnicode_DATA(self); - if (!PyUnicode_IS_ASCII(self)) { - kind_limit = kind_maxchar_limit(src_kind); - max_char = 0; - for (cur = start, i = 0; i < slicelength; cur += step, i++) { - ch = PyUnicode_READ(src_kind, src_data, cur); - if (ch > max_char) { - max_char = ch; - if (max_char >= kind_limit) - break; - } - } - } - else - max_char = 127; - result = PyUnicode_New(slicelength, max_char); - if (result == NULL) - return NULL; - dest_kind = PyUnicode_KIND(result); - dest_data = PyUnicode_DATA(result); - - for (cur = start, i = 0; i < slicelength; cur += step, i++) { - Py_UCS4 ch = PyUnicode_READ(src_kind, src_data, cur); - PyUnicode_WRITE(dest_kind, dest_data, i, ch); - } - assert(_PyUnicode_CheckConsistency(result, 1)); - return result; - } else { - PyErr_SetString(PyExc_TypeError, "string indices must be integers"); - return NULL; - } -} - -static PyMappingMethods unicode_as_mapping = { - (lenfunc)unicode_length, /* mp_length */ - (binaryfunc)unicode_subscript, /* mp_subscript */ - (objobjargproc)0, /* mp_ass_subscript */ -}; - - -/* Helpers for PyUnicode_Format() */ - -struct unicode_formatter_t { - PyObject *args; - int args_owned; - Py_ssize_t arglen, argidx; - PyObject *dict; - - enum PyUnicode_Kind fmtkind; - Py_ssize_t fmtcnt, fmtpos; - void *fmtdata; - PyObject *fmtstr; - - _PyUnicodeWriter writer; -}; - -struct unicode_format_arg_t { - Py_UCS4 ch; - int flags; - Py_ssize_t width; - int prec; - int sign; -}; - -static PyObject * -unicode_format_getnextarg(struct unicode_formatter_t *ctx) -{ - Py_ssize_t argidx = ctx->argidx; - - if (argidx < ctx->arglen) { - ctx->argidx++; - if (ctx->arglen < 0) - return ctx->args; - else - return PyTuple_GetItem(ctx->args, argidx); - } - PyErr_SetString(PyExc_TypeError, - "not enough arguments for format string"); - return NULL; -} - -/* Returns a new reference to a PyUnicode object, or NULL on failure. */ - -/* Format a float into the writer if the writer is not NULL, or into *p_output - otherwise. - - Return 0 on success, raise an exception and return -1 on error. */ -static int -formatfloat(PyObject *v, struct unicode_format_arg_t *arg, - PyObject **p_output, - _PyUnicodeWriter *writer) -{ - char *p; - double x; - Py_ssize_t len; - int prec; - int dtoa_flags; - - x = PyFloat_AsDouble(v); - if (x == -1.0 && PyErr_Occurred()) - return -1; - - prec = arg->prec; - if (prec < 0) - prec = 6; - - if (arg->flags & F_ALT) - dtoa_flags = Py_DTSF_ALT; - else - dtoa_flags = 0; - p = PyOS_double_to_string(x, arg->ch, prec, dtoa_flags, NULL); - if (p == NULL) - return -1; - len = strlen(p); - if (writer) { - if (_PyUnicodeWriter_WriteASCIIString(writer, p, len) < 0) { - PyMem_Free(p); - return -1; - } - } - else - *p_output = _PyUnicode_FromASCII(p, len); - PyMem_Free(p); - return 0; -} - -/* 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. - */ -PyObject * -_PyUnicode_FormatLong(PyObject *val, int alt, int prec, int type) -{ - 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; - } - - assert(PyLong_Check(val)); - - switch (type) { - default: - assert(!"'type' not in [diuoxX]"); - case 'd': - case 'i': - case 'u': - /* int and int subclasses should print numerically when a numeric */ - /* format code is used (see issue18780) */ - result = PyNumber_ToBase(val, 10); - break; - case 'o': - numnondigits = 2; - result = PyNumber_ToBase(val, 8); - break; - case 'x': - case 'X': - numnondigits = 2; - result = PyNumber_ToBase(val, 16); - break; - } - 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) { - Py_DECREF(result); - PyErr_BadInternalCall(); - return NULL; - } - buf = PyUnicode_DATA(result); - llen = PyUnicode_GET_LENGTH(result); - if (llen > INT_MAX) { - Py_DECREF(result); - PyErr_SetString(PyExc_ValueError, - "string too large in _PyUnicode_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 (((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) - || buf != PyUnicode_DATA(result)) { - PyObject *unicode; - unicode = _PyUnicode_FromASCII(buf, len); - Py_DECREF(result); - result = unicode; - } - else if (len != PyUnicode_GET_LENGTH(result)) { - if (PyUnicode_Resize(&result, len) < 0) - Py_CLEAR(result); - } - return result; -} - -/* Format an integer or a float as an integer. - * Return 1 if the number has been formatted into the writer, - * 0 if the number has been formatted into *p_output - * -1 and raise an exception on error */ -static int -mainformatlong(PyObject *v, - struct unicode_format_arg_t *arg, - PyObject **p_output, - _PyUnicodeWriter *writer) -{ - PyObject *iobj, *res; - char type = (char)arg->ch; - - if (!PyNumber_Check(v)) - goto wrongtype; - - /* make sure number is a type of integer for o, x, and X */ - if (!PyLong_Check(v)) { - if (type == 'o' || type == 'x' || type == 'X') { - iobj = PyNumber_Index(v); - if (iobj == NULL) { - if (PyErr_ExceptionMatches(PyExc_TypeError)) - goto wrongtype; - return -1; - } - } - else { - iobj = PyNumber_Long(v); - if (iobj == NULL ) { - if (PyErr_ExceptionMatches(PyExc_TypeError)) - goto wrongtype; - return -1; - } - } - assert(PyLong_Check(iobj)); - } - else { - iobj = v; - Py_INCREF(iobj); - } - - if (PyLong_CheckExact(v) - && arg->width == -1 && arg->prec == -1 - && !(arg->flags & (F_SIGN | F_BLANK)) - && type != 'X') - { - /* Fast path */ - int alternate = arg->flags & F_ALT; - int base; - - switch(type) - { - default: - assert(0 && "'type' not in [diuoxX]"); - case 'd': - case 'i': - case 'u': - base = 10; - break; - case 'o': - base = 8; - break; - case 'x': - case 'X': - base = 16; - break; - } - - if (_PyLong_FormatWriter(writer, v, base, alternate) == -1) { - Py_DECREF(iobj); - return -1; - } - Py_DECREF(iobj); - return 1; - } - - res = _PyUnicode_FormatLong(iobj, arg->flags & F_ALT, arg->prec, type); - Py_DECREF(iobj); - if (res == NULL) - return -1; - *p_output = res; - return 0; - -wrongtype: - switch(type) - { - case 'o': - case 'x': - case 'X': - PyErr_Format(PyExc_TypeError, - "%%%c format: an integer is required, " - "not %.200s", - type, Py_TYPE(v)->tp_name); - break; - default: - PyErr_Format(PyExc_TypeError, - "%%%c format: a number is required, " - "not %.200s", - type, Py_TYPE(v)->tp_name); - break; - } - return -1; -} - -static Py_UCS4 -formatchar(PyObject *v) -{ - /* presume that the buffer is at least 3 characters long */ - if (PyUnicode_Check(v)) { - if (PyUnicode_GET_LENGTH(v) == 1) { - return PyUnicode_READ_CHAR(v, 0); - } - goto onError; - } - else { - PyObject *iobj; - long x; - /* make sure number is a type of integer */ - if (!PyLong_Check(v)) { - iobj = PyNumber_Index(v); - if (iobj == NULL) { - goto onError; - } - v = iobj; - Py_DECREF(iobj); - } - /* Integer input truncated to a character */ - x = PyLong_AsLong(v); - if (x == -1 && PyErr_Occurred()) - goto onError; - - if (x < 0 || x > MAX_UNICODE) { - PyErr_SetString(PyExc_OverflowError, - "%c arg not in range(0x110000)"); - return (Py_UCS4) -1; - } - - return (Py_UCS4) x; - } - - onError: - PyErr_SetString(PyExc_TypeError, - "%c requires int or char"); - return (Py_UCS4) -1; -} - -/* Parse options of an argument: flags, width, precision. - Handle also "%(name)" syntax. - - Return 0 if the argument has been formatted into arg->str. - Return 1 if the argument has been written into ctx->writer, - Raise an exception and return -1 on error. */ -static int -unicode_format_arg_parse(struct unicode_formatter_t *ctx, - struct unicode_format_arg_t *arg) -{ -#define FORMAT_READ(ctx) \ - PyUnicode_READ((ctx)->fmtkind, (ctx)->fmtdata, (ctx)->fmtpos) - - PyObject *v; - - if (arg->ch == '(') { - /* Get argument value from a dictionary. Example: "%(name)s". */ - Py_ssize_t keystart; - Py_ssize_t keylen; - PyObject *key; - int pcount = 1; - - if (ctx->dict == NULL) { - PyErr_SetString(PyExc_TypeError, - "format requires a mapping"); - return -1; - } - ++ctx->fmtpos; - --ctx->fmtcnt; - keystart = ctx->fmtpos; - /* Skip over balanced parentheses */ - while (pcount > 0 && --ctx->fmtcnt >= 0) { - arg->ch = FORMAT_READ(ctx); - if (arg->ch == ')') - --pcount; - else if (arg->ch == '(') - ++pcount; - ctx->fmtpos++; - } - keylen = ctx->fmtpos - keystart - 1; - if (ctx->fmtcnt < 0 || pcount > 0) { - PyErr_SetString(PyExc_ValueError, - "incomplete format key"); - return -1; - } - key = PyUnicode_Substring(ctx->fmtstr, - keystart, keystart + keylen); - if (key == NULL) - return -1; - if (ctx->args_owned) { - Py_DECREF(ctx->args); - ctx->args_owned = 0; - } - ctx->args = PyObject_GetItem(ctx->dict, key); - Py_DECREF(key); - if (ctx->args == NULL) - return -1; - ctx->args_owned = 1; - ctx->arglen = -1; - ctx->argidx = -2; - } - - /* Parse flags. Example: "%+i" => flags=F_SIGN. */ - while (--ctx->fmtcnt >= 0) { - arg->ch = FORMAT_READ(ctx); - ctx->fmtpos++; - switch (arg->ch) { - case '-': arg->flags |= F_LJUST; continue; - case '+': arg->flags |= F_SIGN; continue; - case ' ': arg->flags |= F_BLANK; continue; - case '#': arg->flags |= F_ALT; continue; - case '0': arg->flags |= F_ZERO; continue; - } - break; - } - - /* Parse width. Example: "%10s" => width=10 */ - if (arg->ch == '*') { - v = unicode_format_getnextarg(ctx); - if (v == NULL) - return -1; - if (!PyLong_Check(v)) { - PyErr_SetString(PyExc_TypeError, - "* wants int"); - return -1; - } - arg->width = PyLong_AsSsize_t(v); - if (arg->width == -1 && PyErr_Occurred()) - return -1; - if (arg->width < 0) { - arg->flags |= F_LJUST; - arg->width = -arg->width; - } - if (--ctx->fmtcnt >= 0) { - arg->ch = FORMAT_READ(ctx); - ctx->fmtpos++; - } - } - else if (arg->ch >= '0' && arg->ch <= '9') { - arg->width = arg->ch - '0'; - while (--ctx->fmtcnt >= 0) { - arg->ch = FORMAT_READ(ctx); - ctx->fmtpos++; - if (arg->ch < '0' || arg->ch > '9') - break; - /* Since arg->ch is unsigned, the RHS would end up as unsigned, - mixing signed and unsigned comparison. Since arg->ch is between - '0' and '9', casting to int is safe. */ - if (arg->width > (PY_SSIZE_T_MAX - ((int)arg->ch - '0')) / 10) { - PyErr_SetString(PyExc_ValueError, - "width too big"); - return -1; - } - arg->width = arg->width*10 + (arg->ch - '0'); - } - } - - /* Parse precision. Example: "%.3f" => prec=3 */ - if (arg->ch == '.') { - arg->prec = 0; - if (--ctx->fmtcnt >= 0) { - arg->ch = FORMAT_READ(ctx); - ctx->fmtpos++; - } - if (arg->ch == '*') { - v = unicode_format_getnextarg(ctx); - if (v == NULL) - return -1; - if (!PyLong_Check(v)) { - PyErr_SetString(PyExc_TypeError, - "* wants int"); - return -1; - } - arg->prec = _PyLong_AsInt(v); - if (arg->prec == -1 && PyErr_Occurred()) - return -1; - if (arg->prec < 0) - arg->prec = 0; - if (--ctx->fmtcnt >= 0) { - arg->ch = FORMAT_READ(ctx); - ctx->fmtpos++; - } - } - else if (arg->ch >= '0' && arg->ch <= '9') { - arg->prec = arg->ch - '0'; - while (--ctx->fmtcnt >= 0) { - arg->ch = FORMAT_READ(ctx); - ctx->fmtpos++; - if (arg->ch < '0' || arg->ch > '9') - break; - if (arg->prec > (INT_MAX - ((int)arg->ch - '0')) / 10) { - PyErr_SetString(PyExc_ValueError, - "precision too big"); - return -1; - } - arg->prec = arg->prec*10 + (arg->ch - '0'); - } - } - } - - /* Ignore "h", "l" and "L" format prefix (ex: "%hi" or "%ls") */ - if (ctx->fmtcnt >= 0) { - if (arg->ch == 'h' || arg->ch == 'l' || arg->ch == 'L') { - if (--ctx->fmtcnt >= 0) { - arg->ch = FORMAT_READ(ctx); - ctx->fmtpos++; - } - } - } - if (ctx->fmtcnt < 0) { - PyErr_SetString(PyExc_ValueError, - "incomplete format"); - return -1; - } - return 0; - -#undef FORMAT_READ -} - -/* Format one argument. Supported conversion specifiers: - - - "s", "r", "a": any type - - "i", "d", "u": int or float - - "o", "x", "X": int - - "e", "E", "f", "F", "g", "G": float - - "c": int or str (1 character) - - When possible, the output is written directly into the Unicode writer - (ctx->writer). A string is created when padding is required. - - Return 0 if the argument has been formatted into *p_str, - 1 if the argument has been written into ctx->writer, - -1 on error. */ -static int -unicode_format_arg_format(struct unicode_formatter_t *ctx, - struct unicode_format_arg_t *arg, - PyObject **p_str) -{ - PyObject *v; - _PyUnicodeWriter *writer = &ctx->writer; - - if (ctx->fmtcnt == 0) - ctx->writer.overallocate = 0; - - if (arg->ch == '%') { - if (_PyUnicodeWriter_WriteCharInline(writer, '%') < 0) - return -1; - return 1; - } - - v = unicode_format_getnextarg(ctx); - if (v == NULL) - return -1; - - - switch (arg->ch) { - case 's': - case 'r': - case 'a': - if (PyLong_CheckExact(v) && arg->width == -1 && arg->prec == -1) { - /* Fast path */ - if (_PyLong_FormatWriter(writer, v, 10, arg->flags & F_ALT) == -1) - return -1; - return 1; - } - - if (PyUnicode_CheckExact(v) && arg->ch == 's') { - *p_str = v; - Py_INCREF(*p_str); - } - else { - if (arg->ch == 's') - *p_str = PyObject_Str(v); - else if (arg->ch == 'r') - *p_str = PyObject_Repr(v); - else - *p_str = PyObject_ASCII(v); - } - break; - - case 'i': - case 'd': - case 'u': - case 'o': - case 'x': - case 'X': - { - int ret = mainformatlong(v, arg, p_str, writer); - if (ret != 0) - return ret; - arg->sign = 1; - break; - } - - case 'e': - case 'E': - case 'f': - case 'F': - case 'g': - case 'G': - if (arg->width == -1 && arg->prec == -1 - && !(arg->flags & (F_SIGN | F_BLANK))) - { - /* Fast path */ - if (formatfloat(v, arg, NULL, writer) == -1) - return -1; - return 1; - } - - arg->sign = 1; - if (formatfloat(v, arg, p_str, NULL) == -1) - return -1; - break; - - case 'c': - { - Py_UCS4 ch = formatchar(v); - if (ch == (Py_UCS4) -1) - return -1; - if (arg->width == -1 && arg->prec == -1) { - /* Fast path */ - if (_PyUnicodeWriter_WriteCharInline(writer, ch) < 0) - return -1; - return 1; - } - *p_str = PyUnicode_FromOrdinal(ch); - break; - } - - default: - PyErr_Format(PyExc_ValueError, - "unsupported format character '%c' (0x%x) " - "at index %zd", - (31<=arg->ch && arg->ch<=126) ? (char)arg->ch : '?', - (int)arg->ch, - ctx->fmtpos - 1); - return -1; - } - if (*p_str == NULL) - return -1; - assert (PyUnicode_Check(*p_str)); - return 0; -} - -static int -unicode_format_arg_output(struct unicode_formatter_t *ctx, - struct unicode_format_arg_t *arg, - PyObject *str) -{ - Py_ssize_t len; - enum PyUnicode_Kind kind; - void *pbuf; - Py_ssize_t pindex; - Py_UCS4 signchar; - Py_ssize_t buflen; - Py_UCS4 maxchar; - Py_ssize_t sublen; - _PyUnicodeWriter *writer = &ctx->writer; - Py_UCS4 fill; - - fill = ' '; - if (arg->sign && arg->flags & F_ZERO) - fill = '0'; - - if (PyUnicode_READY(str) == -1) - return -1; - - len = PyUnicode_GET_LENGTH(str); - if ((arg->width == -1 || arg->width <= len) - && (arg->prec == -1 || arg->prec >= len) - && !(arg->flags & (F_SIGN | F_BLANK))) - { - /* Fast path */ - if (_PyUnicodeWriter_WriteStr(writer, str) == -1) - return -1; - return 0; - } - - /* Truncate the string for "s", "r" and "a" formats - if the precision is set */ - if (arg->ch == 's' || arg->ch == 'r' || arg->ch == 'a') { - if (arg->prec >= 0 && len > arg->prec) - len = arg->prec; - } - - /* Adjust sign and width */ - kind = PyUnicode_KIND(str); - pbuf = PyUnicode_DATA(str); - pindex = 0; - signchar = '\0'; - if (arg->sign) { - Py_UCS4 ch = PyUnicode_READ(kind, pbuf, pindex); - if (ch == '-' || ch == '+') { - signchar = ch; - len--; - pindex++; - } - else if (arg->flags & F_SIGN) - signchar = '+'; - else if (arg->flags & F_BLANK) - signchar = ' '; - else - arg->sign = 0; - } - if (arg->width < len) - arg->width = len; - - /* Prepare the writer */ - maxchar = writer->maxchar; - if (!(arg->flags & F_LJUST)) { - if (arg->sign) { - if ((arg->width-1) > len) - maxchar = Py_MAX(maxchar, fill); - } - else { - if (arg->width > len) - maxchar = Py_MAX(maxchar, fill); - } - } - if (PyUnicode_MAX_CHAR_VALUE(str) > maxchar) { - Py_UCS4 strmaxchar = _PyUnicode_FindMaxChar(str, 0, pindex+len); - maxchar = Py_MAX(maxchar, strmaxchar); - } - - buflen = arg->width; - if (arg->sign && len == arg->width) - buflen++; - if (_PyUnicodeWriter_Prepare(writer, buflen, maxchar) == -1) - return -1; - - /* Write the sign if needed */ - if (arg->sign) { - if (fill != ' ') { - PyUnicode_WRITE(writer->kind, writer->data, writer->pos, signchar); - writer->pos += 1; - } - if (arg->width > len) - arg->width--; - } - - /* Write the numeric prefix for "x", "X" and "o" formats - if the alternate form is used. - For example, write "0x" for the "%#x" format. */ - if ((arg->flags & F_ALT) && (arg->ch == 'x' || arg->ch == 'X' || arg->ch == 'o')) { - assert(PyUnicode_READ(kind, pbuf, pindex) == '0'); - assert(PyUnicode_READ(kind, pbuf, pindex + 1) == arg->ch); - if (fill != ' ') { - PyUnicode_WRITE(writer->kind, writer->data, writer->pos, '0'); - PyUnicode_WRITE(writer->kind, writer->data, writer->pos+1, arg->ch); - writer->pos += 2; - pindex += 2; - } - arg->width -= 2; - if (arg->width < 0) - arg->width = 0; - len -= 2; - } - - /* Pad left with the fill character if needed */ - if (arg->width > len && !(arg->flags & F_LJUST)) { - sublen = arg->width - len; - FILL(writer->kind, writer->data, fill, writer->pos, sublen); - writer->pos += sublen; - arg->width = len; - } - - /* If padding with spaces: write sign if needed and/or numeric prefix if - the alternate form is used */ - if (fill == ' ') { - if (arg->sign) { - PyUnicode_WRITE(writer->kind, writer->data, writer->pos, signchar); - writer->pos += 1; - } - if ((arg->flags & F_ALT) && (arg->ch == 'x' || arg->ch == 'X' || arg->ch == 'o')) { - assert(PyUnicode_READ(kind, pbuf, pindex) == '0'); - assert(PyUnicode_READ(kind, pbuf, pindex+1) == arg->ch); - PyUnicode_WRITE(writer->kind, writer->data, writer->pos, '0'); - PyUnicode_WRITE(writer->kind, writer->data, writer->pos+1, arg->ch); - writer->pos += 2; - pindex += 2; - } - } - - /* Write characters */ - if (len) { - _PyUnicode_FastCopyCharacters(writer->buffer, writer->pos, - str, pindex, len); - writer->pos += len; - } - - /* Pad right with the fill character if needed */ - if (arg->width > len) { - sublen = arg->width - len; - FILL(writer->kind, writer->data, ' ', writer->pos, sublen); - writer->pos += sublen; - } - return 0; -} - -/* Helper of PyUnicode_Format(): format one arg. - Return 0 on success, raise an exception and return -1 on error. */ -static int -unicode_format_arg(struct unicode_formatter_t *ctx) -{ - struct unicode_format_arg_t arg; - PyObject *str; - int ret; - - arg.ch = PyUnicode_READ(ctx->fmtkind, ctx->fmtdata, ctx->fmtpos); - arg.flags = 0; - arg.width = -1; - arg.prec = -1; - arg.sign = 0; - str = NULL; - - ret = unicode_format_arg_parse(ctx, &arg); - if (ret == -1) - return -1; - - ret = unicode_format_arg_format(ctx, &arg, &str); - if (ret == -1) - return -1; - - if (ret != 1) { - ret = unicode_format_arg_output(ctx, &arg, str); - Py_DECREF(str); - if (ret == -1) - return -1; - } - - if (ctx->dict && (ctx->argidx < ctx->arglen) && arg.ch != '%') { - PyErr_SetString(PyExc_TypeError, - "not all arguments converted during string formatting"); - return -1; - } - return 0; -} - -PyObject * -PyUnicode_Format(PyObject *format, PyObject *args) -{ - struct unicode_formatter_t ctx; - - if (format == NULL || args == NULL) { - PyErr_BadInternalCall(); - return NULL; - } - - ctx.fmtstr = PyUnicode_FromObject(format); - if (ctx.fmtstr == NULL) - return NULL; - if (PyUnicode_READY(ctx.fmtstr) == -1) { - Py_DECREF(ctx.fmtstr); - return NULL; - } - ctx.fmtdata = PyUnicode_DATA(ctx.fmtstr); - ctx.fmtkind = PyUnicode_KIND(ctx.fmtstr); - ctx.fmtcnt = PyUnicode_GET_LENGTH(ctx.fmtstr); - ctx.fmtpos = 0; - - _PyUnicodeWriter_Init(&ctx.writer); - ctx.writer.min_length = ctx.fmtcnt + 100; - ctx.writer.overallocate = 1; - - if (PyTuple_Check(args)) { - ctx.arglen = PyTuple_Size(args); - ctx.argidx = 0; - } - else { - ctx.arglen = -1; - ctx.argidx = -2; - } - ctx.args_owned = 0; - if (PyMapping_Check(args) && !PyTuple_Check(args) && !PyUnicode_Check(args)) - ctx.dict = args; - else - ctx.dict = NULL; - ctx.args = args; - - while (--ctx.fmtcnt >= 0) { - if (PyUnicode_READ(ctx.fmtkind, ctx.fmtdata, ctx.fmtpos) != '%') { - Py_ssize_t nonfmtpos; - - nonfmtpos = ctx.fmtpos++; - while (ctx.fmtcnt >= 0 && - PyUnicode_READ(ctx.fmtkind, ctx.fmtdata, ctx.fmtpos) != '%') { - ctx.fmtpos++; - ctx.fmtcnt--; - } - if (ctx.fmtcnt < 0) { - ctx.fmtpos--; - ctx.writer.overallocate = 0; - } - - if (_PyUnicodeWriter_WriteSubstring(&ctx.writer, ctx.fmtstr, - nonfmtpos, ctx.fmtpos) < 0) - goto onError; - } - else { - ctx.fmtpos++; - if (unicode_format_arg(&ctx) == -1) - goto onError; - } - } - - if (ctx.argidx < ctx.arglen && !ctx.dict) { - PyErr_SetString(PyExc_TypeError, - "not all arguments converted during string formatting"); - goto onError; - } - - if (ctx.args_owned) { - Py_DECREF(ctx.args); - } - Py_DECREF(ctx.fmtstr); - return _PyUnicodeWriter_Finish(&ctx.writer); - - onError: - Py_DECREF(ctx.fmtstr); - _PyUnicodeWriter_Dealloc(&ctx.writer); - if (ctx.args_owned) { - Py_DECREF(ctx.args); - } - return NULL; -} - -static PyObject * -unicode_subtype_new(PyTypeObject *type, PyObject *args, PyObject *kwds); - -static PyObject * -unicode_new(PyTypeObject *type, PyObject *args, PyObject *kwds) -{ - PyObject *x = NULL; - static char *kwlist[] = {"object", "encoding", "errors", 0}; - char *encoding = NULL; - char *errors = NULL; - - if (type != &PyUnicode_Type) - return unicode_subtype_new(type, args, kwds); - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|Oss:str", - kwlist, &x, &encoding, &errors)) - return NULL; - if (x == NULL) - _Py_RETURN_UNICODE_EMPTY(); - if (encoding == NULL && errors == NULL) - return PyObject_Str(x); - else - return PyUnicode_FromEncodedObject(x, encoding, errors); -} - -static PyObject * -unicode_subtype_new(PyTypeObject *type, PyObject *args, PyObject *kwds) -{ - PyObject *unicode, *self; - Py_ssize_t length, char_size; - int share_wstr, share_utf8; - unsigned int kind; - void *data; - - assert(PyType_IsSubtype(type, &PyUnicode_Type)); - - unicode = unicode_new(&PyUnicode_Type, args, kwds); - if (unicode == NULL) - return NULL; - assert(_PyUnicode_CHECK(unicode)); - if (PyUnicode_READY(unicode) == -1) { - Py_DECREF(unicode); - return NULL; - } - - self = type->tp_alloc(type, 0); - if (self == NULL) { - Py_DECREF(unicode); - return NULL; - } - kind = PyUnicode_KIND(unicode); - length = PyUnicode_GET_LENGTH(unicode); - - _PyUnicode_LENGTH(self) = length; -#ifdef Py_DEBUG - _PyUnicode_HASH(self) = -1; -#else - _PyUnicode_HASH(self) = _PyUnicode_HASH(unicode); -#endif - _PyUnicode_STATE(self).interned = 0; - _PyUnicode_STATE(self).kind = kind; - _PyUnicode_STATE(self).compact = 0; - _PyUnicode_STATE(self).ascii = _PyUnicode_STATE(unicode).ascii; - _PyUnicode_STATE(self).ready = 1; - _PyUnicode_WSTR(self) = NULL; - _PyUnicode_UTF8_LENGTH(self) = 0; - _PyUnicode_UTF8(self) = NULL; - _PyUnicode_WSTR_LENGTH(self) = 0; - _PyUnicode_DATA_ANY(self) = NULL; - - share_utf8 = 0; - share_wstr = 0; - if (kind == PyUnicode_1BYTE_KIND) { - char_size = 1; - if (PyUnicode_MAX_CHAR_VALUE(unicode) < 128) - share_utf8 = 1; - } - else if (kind == PyUnicode_2BYTE_KIND) { - char_size = 2; - if (sizeof(wchar_t) == 2) - share_wstr = 1; - } - else { - assert(kind == PyUnicode_4BYTE_KIND); - char_size = 4; - if (sizeof(wchar_t) == 4) - share_wstr = 1; - } - - /* Ensure we won't overflow the length. */ - if (length > (PY_SSIZE_T_MAX / char_size - 1)) { - PyErr_NoMemory(); - goto onError; - } - data = PyObject_MALLOC((length + 1) * char_size); - if (data == NULL) { - PyErr_NoMemory(); - goto onError; - } - - _PyUnicode_DATA_ANY(self) = data; - if (share_utf8) { - _PyUnicode_UTF8_LENGTH(self) = length; - _PyUnicode_UTF8(self) = data; - } - if (share_wstr) { - _PyUnicode_WSTR_LENGTH(self) = length; - _PyUnicode_WSTR(self) = (wchar_t *)data; - } - - Py_MEMCPY(data, PyUnicode_DATA(unicode), - kind * (length + 1)); - assert(_PyUnicode_CheckConsistency(self, 1)); -#ifdef Py_DEBUG - _PyUnicode_HASH(self) = _PyUnicode_HASH(unicode); -#endif - Py_DECREF(unicode); - return self; - -onError: - Py_DECREF(unicode); - Py_DECREF(self); - return NULL; -} - -PyDoc_STRVAR(unicode_doc, -"str(object='') -> str\n\ -str(bytes_or_buffer[, encoding[, errors]]) -> str\n\ -\n\ -Create a new string object from the given object. If encoding or\n\ -errors is specified, then the object must expose a data buffer\n\ -that will be decoded using the given encoding and error handler.\n\ -Otherwise, returns the result of object.__str__() (if defined)\n\ -or repr(object).\n\ -encoding defaults to sys.getdefaultencoding().\n\ -errors defaults to 'strict'."); - -static PyObject *unicode_iter(PyObject *seq); - -PyTypeObject PyUnicode_Type = { - PyVarObject_HEAD_INIT(&PyType_Type, 0) - "str", /* tp_name */ - sizeof(PyUnicodeObject), /* tp_size */ - 0, /* tp_itemsize */ - /* Slots */ - (destructor)unicode_dealloc, /* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_reserved */ - unicode_repr, /* tp_repr */ - &unicode_as_number, /* tp_as_number */ - &unicode_as_sequence, /* tp_as_sequence */ - &unicode_as_mapping, /* tp_as_mapping */ - (hashfunc) unicode_hash, /* tp_hash*/ - 0, /* tp_call*/ - (reprfunc) unicode_str, /* tp_str */ - PyObject_GenericGetAttr, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | - Py_TPFLAGS_UNICODE_SUBCLASS, /* tp_flags */ - unicode_doc, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - PyUnicode_RichCompare, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - unicode_iter, /* tp_iter */ - 0, /* tp_iternext */ - unicode_methods, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - &PyBaseObject_Type, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - unicode_new, /* tp_new */ - PyObject_Del, /* tp_free */ -}; - -/* Initialize the Unicode implementation */ - -int _PyUnicode_Init(void) -{ - /* XXX - move this array to unicodectype.c ? */ - Py_UCS2 linebreak[] = { - 0x000A, /* LINE FEED */ - 0x000D, /* CARRIAGE RETURN */ - 0x001C, /* FILE SEPARATOR */ - 0x001D, /* GROUP SEPARATOR */ - 0x001E, /* RECORD SEPARATOR */ - 0x0085, /* NEXT LINE */ - 0x2028, /* LINE SEPARATOR */ - 0x2029, /* PARAGRAPH SEPARATOR */ - }; - - /* Init the implementation */ - _Py_INCREF_UNICODE_EMPTY(); - if (!unicode_empty) - Py_FatalError("Can't create empty string"); - Py_DECREF(unicode_empty); - - if (PyType_Ready(&PyUnicode_Type) < 0) - Py_FatalError("Can't initialize 'unicode'"); - - /* initialize the linebreak bloom filter */ - bloom_linebreak = make_bloom_mask( - PyUnicode_2BYTE_KIND, linebreak, - Py_ARRAY_LENGTH(linebreak)); - - if (PyType_Ready(&EncodingMapType) < 0) - Py_FatalError("Can't initialize encoding map type"); - - if (PyType_Ready(&PyFieldNameIter_Type) < 0) - Py_FatalError("Can't initialize field name iterator type"); - - if (PyType_Ready(&PyFormatterIter_Type) < 0) - Py_FatalError("Can't initialize formatter iter type"); - - return 0; -} - -/* Finalize the Unicode implementation */ - -int -PyUnicode_ClearFreeList(void) -{ - return 0; -} - -void -_PyUnicode_Fini(void) -{ - int i; - - Py_CLEAR(unicode_empty); - - for (i = 0; i < 256; i++) - Py_CLEAR(unicode_latin1[i]); - _PyUnicode_ClearStaticStrings(); - (void)PyUnicode_ClearFreeList(); -} - -void -PyUnicode_InternInPlace(PyObject **p) -{ - PyObject *s = *p; - PyObject *t; -#ifdef Py_DEBUG - assert(s != NULL); - assert(_PyUnicode_CHECK(s)); -#else - if (s == NULL || !PyUnicode_Check(s)) - return; -#endif - /* If it's a subclass, we don't really know what putting - it in the interned dict might do. */ - if (!PyUnicode_CheckExact(s)) - return; - if (PyUnicode_CHECK_INTERNED(s)) - return; - if (interned == NULL) { - interned = PyDict_New(); - if (interned == NULL) { - PyErr_Clear(); /* Don't leave an exception */ - return; - } - } - /* It might be that the GetItem call fails even - though the key is present in the dictionary, - namely when this happens during a stack overflow. */ - Py_ALLOW_RECURSION - t = PyDict_GetItem(interned, s); - Py_END_ALLOW_RECURSION - - if (t) { - Py_INCREF(t); - Py_DECREF(*p); - *p = t; - return; - } - - PyThreadState_GET()->recursion_critical = 1; - if (PyDict_SetItem(interned, s, s) < 0) { - PyErr_Clear(); - PyThreadState_GET()->recursion_critical = 0; - return; - } - PyThreadState_GET()->recursion_critical = 0; - /* The two references in interned are not counted by refcnt. - The deallocator will take care of this */ - Py_REFCNT(s) -= 2; - _PyUnicode_STATE(s).interned = SSTATE_INTERNED_MORTAL; -} - -void -PyUnicode_InternImmortal(PyObject **p) -{ - PyUnicode_InternInPlace(p); - if (PyUnicode_CHECK_INTERNED(*p) != SSTATE_INTERNED_IMMORTAL) { - _PyUnicode_STATE(*p).interned = SSTATE_INTERNED_IMMORTAL; - Py_INCREF(*p); - } -} - -PyObject * -PyUnicode_InternFromString(const char *cp) -{ - PyObject *s = PyUnicode_FromString(cp); - if (s == NULL) - return NULL; - PyUnicode_InternInPlace(&s); - return s; -} - -void -_Py_ReleaseInternedUnicodeStrings(void) -{ - PyObject *keys; - PyObject *s; - Py_ssize_t i, n; - Py_ssize_t immortal_size = 0, mortal_size = 0; - - if (interned == NULL || !PyDict_Check(interned)) - return; - keys = PyDict_Keys(interned); - if (keys == NULL || !PyList_Check(keys)) { - PyErr_Clear(); - return; - } - - /* Since _Py_ReleaseInternedUnicodeStrings() is intended to help a leak - detector, interned unicode strings are not forcibly deallocated; - rather, we give them their stolen references back, and then clear - and DECREF the interned dict. */ - - n = PyList_GET_SIZE(keys); - fprintf(stderr, "releasing %" PY_FORMAT_SIZE_T "d interned strings\n", - n); - for (i = 0; i < n; i++) { - s = PyList_GET_ITEM(keys, i); - if (PyUnicode_READY(s) == -1) { - assert(0 && "could not ready string"); - fprintf(stderr, "could not ready string\n"); - } - switch (PyUnicode_CHECK_INTERNED(s)) { - case SSTATE_NOT_INTERNED: - /* XXX Shouldn't happen */ - break; - case SSTATE_INTERNED_IMMORTAL: - Py_REFCNT(s) += 1; - immortal_size += PyUnicode_GET_LENGTH(s); - break; - case SSTATE_INTERNED_MORTAL: - Py_REFCNT(s) += 2; - mortal_size += PyUnicode_GET_LENGTH(s); - break; - default: - Py_FatalError("Inconsistent interned string state."); - } - _PyUnicode_STATE(s).interned = SSTATE_NOT_INTERNED; - } - fprintf(stderr, "total size of all interned strings: " - "%" PY_FORMAT_SIZE_T "d/%" PY_FORMAT_SIZE_T "d " - "mortal/immortal\n", mortal_size, immortal_size); - Py_DECREF(keys); - PyDict_Clear(interned); - Py_CLEAR(interned); -} - - -/********************* Unicode Iterator **************************/ - -typedef struct { - PyObject_HEAD - Py_ssize_t it_index; - PyObject *it_seq; /* Set to NULL when iterator is exhausted */ -} unicodeiterobject; - -static void -unicodeiter_dealloc(unicodeiterobject *it) -{ - _PyObject_GC_UNTRACK(it); - Py_XDECREF(it->it_seq); - PyObject_GC_Del(it); -} - -static int -unicodeiter_traverse(unicodeiterobject *it, visitproc visit, void *arg) -{ - Py_VISIT(it->it_seq); - return 0; -} - -static PyObject * -unicodeiter_next(unicodeiterobject *it) -{ - PyObject *seq, *item; - - assert(it != NULL); - seq = it->it_seq; - if (seq == NULL) - return NULL; - assert(_PyUnicode_CHECK(seq)); - - if (it->it_index < PyUnicode_GET_LENGTH(seq)) { - int kind = PyUnicode_KIND(seq); - void *data = PyUnicode_DATA(seq); - Py_UCS4 chr = PyUnicode_READ(kind, data, it->it_index); - item = PyUnicode_FromOrdinal(chr); - if (item != NULL) - ++it->it_index; - return item; - } - - Py_DECREF(seq); - it->it_seq = NULL; - return NULL; -} - -static PyObject * -unicodeiter_len(unicodeiterobject *it) -{ - Py_ssize_t len = 0; - if (it->it_seq) - len = PyUnicode_GET_LENGTH(it->it_seq) - it->it_index; - return PyLong_FromSsize_t(len); -} - -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 (it->it_seq != NULL) { - if (index < 0) - index = 0; - else if (index > PyUnicode_GET_LENGTH(it->it_seq)) - index = PyUnicode_GET_LENGTH(it->it_seq); /* iterator truncated */ - 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 */ -}; - -PyTypeObject PyUnicodeIter_Type = { - PyVarObject_HEAD_INIT(&PyType_Type, 0) - "str_iterator", /* tp_name */ - sizeof(unicodeiterobject), /* tp_basicsize */ - 0, /* tp_itemsize */ - /* methods */ - (destructor)unicodeiter_dealloc, /* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_reserved */ - 0, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - PyObject_GenericGetAttr, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */ - 0, /* tp_doc */ - (traverseproc)unicodeiter_traverse, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - PyObject_SelfIter, /* tp_iter */ - (iternextfunc)unicodeiter_next, /* tp_iternext */ - unicodeiter_methods, /* tp_methods */ - 0, -}; - -static PyObject * -unicode_iter(PyObject *seq) -{ - unicodeiterobject *it; - - if (!PyUnicode_Check(seq)) { - PyErr_BadInternalCall(); - return NULL; - } - if (PyUnicode_READY(seq) == -1) - return NULL; - it = PyObject_GC_New(unicodeiterobject, &PyUnicodeIter_Type); - if (it == NULL) - return NULL; - it->it_index = 0; - Py_INCREF(seq); - it->it_seq = seq; - _PyObject_GC_TRACK(it); - return (PyObject *)it; -} - - -size_t -Py_UNICODE_strlen(const Py_UNICODE *u) -{ - int res = 0; - while(*u++) - res++; - return res; -} - -Py_UNICODE* -Py_UNICODE_strcpy(Py_UNICODE *s1, const Py_UNICODE *s2) -{ - Py_UNICODE *u = s1; - while ((*u++ = *s2++)); - return s1; -} - -Py_UNICODE* -Py_UNICODE_strncpy(Py_UNICODE *s1, const Py_UNICODE *s2, size_t n) -{ - Py_UNICODE *u = s1; - while ((*u++ = *s2++)) - if (n-- == 0) - break; - return s1; -} - -Py_UNICODE* -Py_UNICODE_strcat(Py_UNICODE *s1, const Py_UNICODE *s2) -{ - Py_UNICODE *u1 = s1; - u1 += Py_UNICODE_strlen(u1); - Py_UNICODE_strcpy(u1, s2); - return s1; -} - -int -Py_UNICODE_strcmp(const Py_UNICODE *s1, const Py_UNICODE *s2) -{ - while (*s1 && *s2 && *s1 == *s2) - s1++, s2++; - if (*s1 && *s2) - return (*s1 < *s2) ? -1 : +1; - if (*s1) - return 1; - if (*s2) - return -1; - return 0; -} - -int -Py_UNICODE_strncmp(const Py_UNICODE *s1, const Py_UNICODE *s2, size_t n) -{ - Py_UNICODE u1, u2; - for (; n != 0; n--) { - u1 = *s1; - u2 = *s2; - if (u1 != u2) - return (u1 < u2) ? -1 : +1; - if (u1 == '\0') - return 0; - s1++; - s2++; - } - return 0; -} - -Py_UNICODE* -Py_UNICODE_strchr(const Py_UNICODE *s, Py_UNICODE c) -{ - const Py_UNICODE *p; - for (p = s; *p; p++) - if (*p == c) - return (Py_UNICODE*)p; - return NULL; -} - -Py_UNICODE* -Py_UNICODE_strrchr(const Py_UNICODE *s, Py_UNICODE c) -{ - const Py_UNICODE *p; - p = s + Py_UNICODE_strlen(s); - while (p != s) { - p--; - if (*p == c) - return (Py_UNICODE*)p; - } - return NULL; -} - -Py_UNICODE* -PyUnicode_AsUnicodeCopy(PyObject *unicode) -{ - Py_UNICODE *u, *copy; - Py_ssize_t len, size; - - if (!PyUnicode_Check(unicode)) { - PyErr_BadArgument(); - return NULL; - } - u = PyUnicode_AsUnicodeAndSize(unicode, &len); - if (u == NULL) - return NULL; - /* Ensure we won't overflow the size. */ - if (len > ((PY_SSIZE_T_MAX / (Py_ssize_t)sizeof(Py_UNICODE)) - 1)) { - PyErr_NoMemory(); - return NULL; - } - size = len + 1; /* copy the null character */ - size *= sizeof(Py_UNICODE); - copy = PyMem_Malloc(size); - if (copy == NULL) { - PyErr_NoMemory(); - return NULL; - } - memcpy(copy, u, size); - return copy; -} - -/* A _string module, to export formatter_parser and formatter_field_name_split - to the string.Formatter class implemented in Python. */ - -static PyMethodDef _string_methods[] = { - {"formatter_field_name_split", (PyCFunction) formatter_field_name_split, - METH_O, PyDoc_STR("split the argument as a field name")}, - {"formatter_parser", (PyCFunction) formatter_parser, - METH_O, PyDoc_STR("parse the argument as a format string")}, - {NULL, NULL} -}; - -static struct PyModuleDef _string_module = { - PyModuleDef_HEAD_INIT, - "_string", - PyDoc_STR("string helper module"), - 0, - _string_methods, - NULL, - NULL, - NULL, - NULL -}; - -PyMODINIT_FUNC -PyInit__string(void) -{ - return PyModule_Create(&_string_module); -} - - -#ifdef __cplusplus -} -#endif +/*[clinic end generated code: output=4670413843c53055 input=a9049054013a1b77]*/ diff --git a/Objects/dictobject.c b/Objects/dictobject.c --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -233,6 +233,8 @@ static PyDictObject *free_list[PyDict_MAXFREELIST]; static int numfree = 0; +#include "clinic/dictobject.c.h" + int PyDict_ClearFreeList(void) { @@ -1757,38 +1759,9 @@ Returns a new dict with keys from iterable and values equal to value. [clinic start generated code]*/ -PyDoc_STRVAR(dict_fromkeys__doc__, -"fromkeys($type, iterable, value=None, /)\n" -"--\n" -"\n" -"Returns a new dict with keys from iterable and values equal to value."); - -#define DICT_FROMKEYS_METHODDEF \ - {"fromkeys", (PyCFunction)dict_fromkeys, METH_VARARGS|METH_CLASS, dict_fromkeys__doc__}, - -static PyObject * -dict_fromkeys_impl(PyTypeObject *type, PyObject *iterable, PyObject *value); - -static PyObject * -dict_fromkeys(PyTypeObject *type, PyObject *args) -{ - PyObject *return_value = NULL; - PyObject *iterable; - PyObject *value = Py_None; - - if (!PyArg_UnpackTuple(args, "fromkeys", - 1, 2, - &iterable, &value)) - goto exit; - return_value = dict_fromkeys_impl(type, iterable, value); - -exit: - return return_value; -} - static PyObject * dict_fromkeys_impl(PyTypeObject *type, PyObject *iterable, PyObject *value) -/*[clinic end generated code: output=55f8dc0ffa87406f input=b85a667f9bf4669d]*/ +/*[clinic end generated code: output=8fb98e4b10384999 input=b85a667f9bf4669d]*/ { PyObject *it; /* iter(seq) */ PyObject *key; @@ -2266,18 +2239,9 @@ True if D has a key k, else False. [clinic start generated code]*/ -PyDoc_STRVAR(dict___contains____doc__, -"__contains__($self, key, /)\n" -"--\n" -"\n" -"True if D has a key k, else False."); - -#define DICT___CONTAINS___METHODDEF \ - {"__contains__", (PyCFunction)dict___contains__, METH_O|METH_COEXIST, dict___contains____doc__}, - static PyObject * dict___contains__(PyDictObject *self, PyObject *key) -/*[clinic end generated code: output=3cf3f8aaf2cc5cc3 input=b852b2a19b51ab24]*/ +/*[clinic end generated code: output=a3d03db709ed6e6b input=b852b2a19b51ab24]*/ { register PyDictObject *mp = self; Py_hash_t hash; diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -290,6 +290,8 @@ 0, 0, 0, 0, 0, 0, 0, 0 }; +#include "clinic/unicodeobject.c.h" + /* The max unicode value is always 0x10FFFF while using the PEP-393 API. This function is kept for backward compatibility with the old API. */ Py_UNICODE @@ -12955,47 +12957,9 @@ must be a string, whose characters will be mapped to None in the result. [clinic start generated code]*/ -PyDoc_STRVAR(unicode_maketrans__doc__, -"maketrans(x, y=None, z=None, /)\n" -"--\n" -"\n" -"Return a translation table usable for str.translate().\n" -"\n" -"If there is only one argument, it must be a dictionary mapping Unicode\n" -"ordinals (integers) or characters to Unicode ordinals, strings or None.\n" -"Character keys will be then converted to ordinals.\n" -"If there are two arguments, they must be strings of equal length, and\n" -"in the resulting dictionary, each character in x will be mapped to the\n" -"character at the same position in y. If there is a third argument, it\n" -"must be a string, whose characters will be mapped to None in the result."); - -#define UNICODE_MAKETRANS_METHODDEF \ - {"maketrans", (PyCFunction)unicode_maketrans, METH_VARARGS|METH_STATIC, unicode_maketrans__doc__}, - -static PyObject * -unicode_maketrans_impl(PyObject *x, PyObject *y, PyObject *z); - -static PyObject * -unicode_maketrans(void *null, PyObject *args) -{ - PyObject *return_value = NULL; - PyObject *x; - PyObject *y = NULL; - PyObject *z = NULL; - - if (!PyArg_ParseTuple(args, - "O|UU:maketrans", - &x, &y, &z)) - goto exit; - return_value = unicode_maketrans_impl(x, y, z); - -exit: - return return_value; -} - static PyObject * unicode_maketrans_impl(PyObject *x, PyObject *y, PyObject *z) -/*[clinic end generated code: output=566edf630f77436a input=7bfbf529a293c6c5]*/ +/*[clinic end generated code: output=a925c89452bd5881 input=7bfbf529a293c6c5]*/ { PyObject *new = NULL, *key, *value; Py_ssize_t i = 0; diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -46,6 +46,8 @@ _Py_IDENTIFIER(stdout); _Py_IDENTIFIER(stderr); +#include "clinic/bltinmodule.c.h" + /* AC: cannot convert yet, waiting for *args support */ static PyObject * builtin___build_class__(PyObject *self, PyObject *args, PyObject *kwds) @@ -239,18 +241,9 @@ Return the absolute value of the argument. [clinic start generated code]*/ -PyDoc_STRVAR(builtin_abs__doc__, -"abs($module, x, /)\n" -"--\n" -"\n" -"Return the absolute value of the argument."); - -#define BUILTIN_ABS_METHODDEF \ - {"abs", (PyCFunction)builtin_abs, METH_O, builtin_abs__doc__}, - static PyObject * builtin_abs(PyModuleDef *module, PyObject *x) -/*[clinic end generated code: output=f85095528ce7e2e5 input=aa29cc07869b4732]*/ +/*[clinic end generated code: output=6833047c493ecea2 input=aa29cc07869b4732]*/ { return PyNumber_Absolute(x); } @@ -266,20 +259,9 @@ If the iterable is empty, return True. [clinic start generated code]*/ -PyDoc_STRVAR(builtin_all__doc__, -"all($module, iterable, /)\n" -"--\n" -"\n" -"Return True if bool(x) is True for all values x in the iterable.\n" -"\n" -"If the iterable is empty, return True."); - -#define BUILTIN_ALL_METHODDEF \ - {"all", (PyCFunction)builtin_all, METH_O, builtin_all__doc__}, - static PyObject * builtin_all(PyModuleDef *module, PyObject *iterable) -/*[clinic end generated code: output=d001db739ba83b46 input=dd506dc9998d42bd]*/ +/*[clinic end generated code: output=089e6d1b7bde27b1 input=dd506dc9998d42bd]*/ { PyObject *it, *item; PyObject *(*iternext)(PyObject *); @@ -326,20 +308,9 @@ If the iterable is empty, return False. [clinic start generated code]*/ -PyDoc_STRVAR(builtin_any__doc__, -"any($module, iterable, /)\n" -"--\n" -"\n" -"Return True if bool(x) is True for any x in the iterable.\n" -"\n" -"If the iterable is empty, return False."); - -#define BUILTIN_ANY_METHODDEF \ - {"any", (PyCFunction)builtin_any, METH_O, builtin_any__doc__}, - static PyObject * builtin_any(PyModuleDef *module, PyObject *iterable) -/*[clinic end generated code: output=3a4b6dbe6a0d6f61 input=8fe8460f3fbbced8]*/ +/*[clinic end generated code: output=1be994b2c2307492 input=8fe8460f3fbbced8]*/ { PyObject *it, *item; PyObject *(*iternext)(PyObject *); @@ -389,23 +360,9 @@ to that returned by repr() in Python 2. [clinic start generated code]*/ -PyDoc_STRVAR(builtin_ascii__doc__, -"ascii($module, obj, /)\n" -"--\n" -"\n" -"Return an ASCII-only representation of an object.\n" -"\n" -"As repr(), return a string containing a printable representation of an\n" -"object, but escape the non-ASCII characters in the string returned by\n" -"repr() using \\\\x, \\\\u or \\\\U escapes. This generates a string similar\n" -"to that returned by repr() in Python 2."); - -#define BUILTIN_ASCII_METHODDEF \ - {"ascii", (PyCFunction)builtin_ascii, METH_O, builtin_ascii__doc__}, - static PyObject * builtin_ascii(PyModuleDef *module, PyObject *obj) -/*[clinic end generated code: output=f0e6754154c2d30b input=0cbdc1420a306325]*/ +/*[clinic end generated code: output=d4e862c48af2a933 input=0cbdc1420a306325]*/ { return PyObject_ASCII(obj); } @@ -423,21 +380,9 @@ '0b1010101010101010101010' [clinic start generated code]*/ -PyDoc_STRVAR(builtin_bin__doc__, -"bin($module, number, /)\n" -"--\n" -"\n" -"Return the binary representation of an integer.\n" -"\n" -" >>> bin(2796202)\n" -" \'0b1010101010101010101010\'"); - -#define BUILTIN_BIN_METHODDEF \ - {"bin", (PyCFunction)builtin_bin, METH_O, builtin_bin__doc__}, - static PyObject * builtin_bin(PyModuleDef *module, PyObject *number) -/*[clinic end generated code: output=18fed0e943650da1 input=2a6362ae9a9c9203]*/ +/*[clinic end generated code: output=25ee26c6cf3bbb54 input=2a6362ae9a9c9203]*/ { return PyNumber_ToBase(number, 2); } @@ -455,21 +400,9 @@ __call__() method. [clinic start generated code]*/ -PyDoc_STRVAR(builtin_callable__doc__, -"callable($module, obj, /)\n" -"--\n" -"\n" -"Return whether the object is callable (i.e., some kind of function).\n" -"\n" -"Note that classes are callable, as are instances of classes with a\n" -"__call__() method."); - -#define BUILTIN_CALLABLE_METHODDEF \ - {"callable", (PyCFunction)builtin_callable, METH_O, builtin_callable__doc__}, - static PyObject * builtin_callable(PyModuleDef *module, PyObject *obj) -/*[clinic end generated code: output=b3a92cbe635f32af input=bb3bb528fffdade4]*/ +/*[clinic end generated code: output=f4df2ce92364b656 input=bb3bb528fffdade4]*/ { return PyBool_FromLong((long)PyCallable_Check(obj)); } @@ -640,40 +573,9 @@ format_spec defaults to the empty string [clinic start generated code]*/ -PyDoc_STRVAR(builtin_format__doc__, -"format($module, value, format_spec=\'\', /)\n" -"--\n" -"\n" -"Return value.__format__(format_spec)\n" -"\n" -"format_spec defaults to the empty string"); - -#define BUILTIN_FORMAT_METHODDEF \ - {"format", (PyCFunction)builtin_format, METH_VARARGS, builtin_format__doc__}, - -static PyObject * -builtin_format_impl(PyModuleDef *module, PyObject *value, PyObject *format_spec); - -static PyObject * -builtin_format(PyModuleDef *module, PyObject *args) -{ - PyObject *return_value = NULL; - PyObject *value; - PyObject *format_spec = NULL; - - if (!PyArg_ParseTuple(args, - "O|U:format", - &value, &format_spec)) - goto exit; - return_value = builtin_format_impl(module, value, format_spec); - -exit: - return return_value; -} - static PyObject * builtin_format_impl(PyModuleDef *module, PyObject *value, PyObject *format_spec) -/*[clinic end generated code: output=39723a58c72e8871 input=e23f2f11e0098c64]*/ +/*[clinic end generated code: output=fae3e927cc715466 input=e23f2f11e0098c64]*/ { return PyObject_Format(value, format_spec); } @@ -687,37 +589,9 @@ Return a Unicode string of one character with ordinal i; 0 <= i <= 0x10ffff. [clinic start generated code]*/ -PyDoc_STRVAR(builtin_chr__doc__, -"chr($module, i, /)\n" -"--\n" -"\n" -"Return a Unicode string of one character with ordinal i; 0 <= i <= 0x10ffff."); - -#define BUILTIN_CHR_METHODDEF \ - {"chr", (PyCFunction)builtin_chr, METH_VARARGS, builtin_chr__doc__}, - -static PyObject * -builtin_chr_impl(PyModuleDef *module, int i); - -static PyObject * -builtin_chr(PyModuleDef *module, PyObject *args) -{ - PyObject *return_value = NULL; - int i; - - if (!PyArg_ParseTuple(args, - "i:chr", - &i)) - goto exit; - return_value = builtin_chr_impl(module, i); - -exit: - return return_value; -} - static PyObject * builtin_chr_impl(PyModuleDef *module, int i) -/*[clinic end generated code: output=4d6bbe948f56e2ae input=9b1ced29615adf66]*/ +/*[clinic end generated code: output=67fe4d87e690f373 input=9b1ced29615adf66]*/ { return PyUnicode_FromOrdinal(i); } @@ -779,55 +653,9 @@ in addition to any features explicitly specified. [clinic start generated code]*/ -PyDoc_STRVAR(builtin_compile__doc__, -"compile($module, /, source, filename, mode, flags=0, dont_inherit=0,\n" -" optimize=-1)\n" -"--\n" -"\n" -"Compile source into a code object that can be executed by exec() or eval().\n" -"\n" -"The source code may represent a Python module, statement or expression.\n" -"The filename will be used for run-time error messages.\n" -"The mode must be \'exec\' to compile a module, \'single\' to compile a\n" -"single (interactive) statement, or \'eval\' to compile an expression.\n" -"The flags argument, if present, controls which future statements influence\n" -"the compilation of the code.\n" -"The dont_inherit argument, if non-zero, stops the compilation inheriting\n" -"the effects of any future statements in effect in the code calling\n" -"compile; if absent or zero these statements do influence the compilation,\n" -"in addition to any features explicitly specified."); - -#define BUILTIN_COMPILE_METHODDEF \ - {"compile", (PyCFunction)builtin_compile, METH_VARARGS|METH_KEYWORDS, builtin_compile__doc__}, - -static PyObject * -builtin_compile_impl(PyModuleDef *module, PyObject *source, PyObject *filename, const char *mode, int flags, int dont_inherit, int optimize); - -static PyObject * -builtin_compile(PyModuleDef *module, PyObject *args, PyObject *kwargs) -{ - PyObject *return_value = NULL; - static char *_keywords[] = {"source", "filename", "mode", "flags", "dont_inherit", "optimize", NULL}; - PyObject *source; - PyObject *filename; - const char *mode; - int flags = 0; - int dont_inherit = 0; - int optimize = -1; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "OO&s|iii:compile", _keywords, - &source, PyUnicode_FSDecoder, &filename, &mode, &flags, &dont_inherit, &optimize)) - goto exit; - return_value = builtin_compile_impl(module, source, filename, mode, flags, dont_inherit, optimize); - -exit: - return return_value; -} - static PyObject * builtin_compile_impl(PyModuleDef *module, PyObject *source, PyObject *filename, const char *mode, int flags, int dont_inherit, int optimize) -/*[clinic end generated code: output=c72d197809d178fc input=c6212a9d21472f7e]*/ +/*[clinic end generated code: output=4f41a315386bab9f input=c6212a9d21472f7e]*/ { Py_buffer view = {NULL, NULL}; const char *str; @@ -951,38 +779,9 @@ Return the tuple ((x-x%y)/y, x%y). Invariant: div*y + mod == x. [clinic start generated code]*/ -PyDoc_STRVAR(builtin_divmod__doc__, -"divmod($module, x, y, /)\n" -"--\n" -"\n" -"Return the tuple ((x-x%y)/y, x%y). Invariant: div*y + mod == x."); - -#define BUILTIN_DIVMOD_METHODDEF \ - {"divmod", (PyCFunction)builtin_divmod, METH_VARARGS, builtin_divmod__doc__}, - -static PyObject * -builtin_divmod_impl(PyModuleDef *module, PyObject *x, PyObject *y); - -static PyObject * -builtin_divmod(PyModuleDef *module, PyObject *args) -{ - PyObject *return_value = NULL; - PyObject *x; - PyObject *y; - - if (!PyArg_UnpackTuple(args, "divmod", - 2, 2, - &x, &y)) - goto exit; - return_value = builtin_divmod_impl(module, x, y); - -exit: - return return_value; -} - static PyObject * builtin_divmod_impl(PyModuleDef *module, PyObject *x, PyObject *y) -/*[clinic end generated code: output=77e8d408b1338886 input=c9c617b7bb74c615]*/ +/*[clinic end generated code: output=9ad0076120ebf9ac input=c9c617b7bb74c615]*/ { return PyNumber_Divmod(x, y); } @@ -1005,45 +804,9 @@ If only globals is given, locals defaults to it. [clinic start generated code]*/ -PyDoc_STRVAR(builtin_eval__doc__, -"eval($module, source, globals=None, locals=None, /)\n" -"--\n" -"\n" -"Evaluate the given source in the context of globals and locals.\n" -"\n" -"The source may be a string representing a Python expression\n" -"or a code object as returned by compile().\n" -"The globals must be a dictionary and locals can be any mapping,\n" -"defaulting to the current globals and locals.\n" -"If only globals is given, locals defaults to it."); - -#define BUILTIN_EVAL_METHODDEF \ - {"eval", (PyCFunction)builtin_eval, METH_VARARGS, builtin_eval__doc__}, - -static PyObject * -builtin_eval_impl(PyModuleDef *module, PyObject *source, PyObject *globals, PyObject *locals); - -static PyObject * -builtin_eval(PyModuleDef *module, PyObject *args) -{ - PyObject *return_value = NULL; - PyObject *source; - PyObject *globals = Py_None; - PyObject *locals = Py_None; - - if (!PyArg_UnpackTuple(args, "eval", - 1, 3, - &source, &globals, &locals)) - goto exit; - return_value = builtin_eval_impl(module, source, globals, locals); - -exit: - return return_value; -} - static PyObject * builtin_eval_impl(PyModuleDef *module, PyObject *source, PyObject *globals, PyObject *locals) -/*[clinic end generated code: output=644fd59012538ce6 input=31e42c1d2125b50b]*/ +/*[clinic end generated code: output=90642b79dd8b08d6 input=31e42c1d2125b50b]*/ { PyObject *result, *tmp = NULL; Py_buffer view = {NULL, NULL}; @@ -1125,45 +888,9 @@ If only globals is given, locals defaults to it. [clinic start generated code]*/ -PyDoc_STRVAR(builtin_exec__doc__, -"exec($module, source, globals=None, locals=None, /)\n" -"--\n" -"\n" -"Execute the given source in the context of globals and locals.\n" -"\n" -"The source may be a string representing one or more Python statements\n" -"or a code object as returned by compile().\n" -"The globals must be a dictionary and locals can be any mapping,\n" -"defaulting to the current globals and locals.\n" -"If only globals is given, locals defaults to it."); - -#define BUILTIN_EXEC_METHODDEF \ - {"exec", (PyCFunction)builtin_exec, METH_VARARGS, builtin_exec__doc__}, - -static PyObject * -builtin_exec_impl(PyModuleDef *module, PyObject *source, PyObject *globals, PyObject *locals); - -static PyObject * -builtin_exec(PyModuleDef *module, PyObject *args) -{ - PyObject *return_value = NULL; - PyObject *source; - PyObject *globals = Py_None; - PyObject *locals = Py_None; - - if (!PyArg_UnpackTuple(args, "exec", - 1, 3, - &source, &globals, &locals)) - goto exit; - return_value = builtin_exec_impl(module, source, globals, locals); - -exit: - return return_value; -} - static PyObject * builtin_exec_impl(PyModuleDef *module, PyObject *source, PyObject *globals, PyObject *locals) -/*[clinic end generated code: output=0281b48bfa8e3c87 input=536e057b5e00d89e]*/ +/*[clinic end generated code: output=e8e0bbcde826a048 input=536e057b5e00d89e]*/ { PyObject *v; @@ -1275,30 +1002,9 @@ global scope and vice-versa. [clinic start generated code]*/ -PyDoc_STRVAR(builtin_globals__doc__, -"globals($module, /)\n" -"--\n" -"\n" -"Return the dictionary containing the current scope\'s global variables.\n" -"\n" -"NOTE: Updates to this dictionary *will* affect name lookups in the current\n" -"global scope and vice-versa."); - -#define BUILTIN_GLOBALS_METHODDEF \ - {"globals", (PyCFunction)builtin_globals, METH_NOARGS, builtin_globals__doc__}, - -static PyObject * -builtin_globals_impl(PyModuleDef *module); - -static PyObject * -builtin_globals(PyModuleDef *module, PyObject *Py_UNUSED(ignored)) -{ - return builtin_globals_impl(module); -} - static PyObject * builtin_globals_impl(PyModuleDef *module) -/*[clinic end generated code: output=048640f58b1f20ad input=9327576f92bb48ba]*/ +/*[clinic end generated code: output=4958645e96dd8138 input=9327576f92bb48ba]*/ { PyObject *d; @@ -1320,40 +1026,9 @@ This is done by calling getattr(obj, name) and catching AttributeError. [clinic start generated code]*/ -PyDoc_STRVAR(builtin_hasattr__doc__, -"hasattr($module, obj, name, /)\n" -"--\n" -"\n" -"Return whether the object has an attribute with the given name.\n" -"\n" -"This is done by calling getattr(obj, name) and catching AttributeError."); - -#define BUILTIN_HASATTR_METHODDEF \ - {"hasattr", (PyCFunction)builtin_hasattr, METH_VARARGS, builtin_hasattr__doc__}, - -static PyObject * -builtin_hasattr_impl(PyModuleDef *module, PyObject *obj, PyObject *name); - -static PyObject * -builtin_hasattr(PyModuleDef *module, PyObject *args) -{ - PyObject *return_value = NULL; - PyObject *obj; - PyObject *name; - - if (!PyArg_UnpackTuple(args, "hasattr", - 2, 2, - &obj, &name)) - goto exit; - return_value = builtin_hasattr_impl(module, obj, name); - -exit: - return return_value; -} - static PyObject * builtin_hasattr_impl(PyModuleDef *module, PyObject *obj, PyObject *name) -/*[clinic end generated code: output=e0bd996ef73d1217 input=b50bad5f739ea10d]*/ +/*[clinic end generated code: output=81154fdd63634696 input=b50bad5f739ea10d]*/ { PyObject *v; @@ -1392,21 +1067,9 @@ (CPython uses the object's memory address.) [clinic start generated code]*/ -PyDoc_STRVAR(builtin_id__doc__, -"id($module, obj, /)\n" -"--\n" -"\n" -"Return the identity of an object.\n" -"\n" -"This is guaranteed to be unique among simultaneously existing objects.\n" -"(CPython uses the object\'s memory address.)"); - -#define BUILTIN_ID_METHODDEF \ - {"id", (PyCFunction)builtin_id, METH_O, builtin_id__doc__}, - static PyObject * builtin_id(PyModuleDef *self, PyObject *v) -/*[clinic end generated code: output=f54da09c91992e63 input=a1f988d98357341d]*/ +/*[clinic end generated code: output=0aa640785f697f65 input=a1f988d98357341d]*/ { return PyLong_FromVoidPtr(v); } @@ -1639,41 +1302,9 @@ setattr(x, 'y', v) is equivalent to ``x.y = v'' [clinic start generated code]*/ -PyDoc_STRVAR(builtin_setattr__doc__, -"setattr($module, obj, name, value, /)\n" -"--\n" -"\n" -"Sets the named attribute on the given object to the specified value.\n" -"\n" -"setattr(x, \'y\', v) is equivalent to ``x.y = v\'\'"); - -#define BUILTIN_SETATTR_METHODDEF \ - {"setattr", (PyCFunction)builtin_setattr, METH_VARARGS, builtin_setattr__doc__}, - -static PyObject * -builtin_setattr_impl(PyModuleDef *module, PyObject *obj, PyObject *name, PyObject *value); - -static PyObject * -builtin_setattr(PyModuleDef *module, PyObject *args) -{ - PyObject *return_value = NULL; - PyObject *obj; - PyObject *name; - PyObject *value; - - if (!PyArg_UnpackTuple(args, "setattr", - 3, 3, - &obj, &name, &value)) - goto exit; - return_value = builtin_setattr_impl(module, obj, name, value); - -exit: - return return_value; -} - static PyObject * builtin_setattr_impl(PyModuleDef *module, PyObject *obj, PyObject *name, PyObject *value) -/*[clinic end generated code: output=4336dcbbf7691d2d input=fbe7e53403116b93]*/ +/*[clinic end generated code: output=c5e0a3a3971333ed input=fbe7e53403116b93]*/ { if (PyObject_SetAttr(obj, name, value) != 0) return NULL; @@ -1694,40 +1325,9 @@ delattr(x, 'y') is equivalent to ``del x.y'' [clinic start generated code]*/ -PyDoc_STRVAR(builtin_delattr__doc__, -"delattr($module, obj, name, /)\n" -"--\n" -"\n" -"Deletes the named attribute from the given object.\n" -"\n" -"delattr(x, \'y\') is equivalent to ``del x.y\'\'"); - -#define BUILTIN_DELATTR_METHODDEF \ - {"delattr", (PyCFunction)builtin_delattr, METH_VARARGS, builtin_delattr__doc__}, - -static PyObject * -builtin_delattr_impl(PyModuleDef *module, PyObject *obj, PyObject *name); - -static PyObject * -builtin_delattr(PyModuleDef *module, PyObject *args) -{ - PyObject *return_value = NULL; - PyObject *obj; - PyObject *name; - - if (!PyArg_UnpackTuple(args, "delattr", - 2, 2, - &obj, &name)) - goto exit; - return_value = builtin_delattr_impl(module, obj, name); - -exit: - return return_value; -} - static PyObject * builtin_delattr_impl(PyModuleDef *module, PyObject *obj, PyObject *name) -/*[clinic end generated code: output=319c2d884aa769cf input=647af2ce9183a823]*/ +/*[clinic end generated code: output=ef653e698a0b4187 input=647af2ce9183a823]*/ { if (PyObject_SetAttr(obj, name, (PyObject *)NULL) != 0) return NULL; @@ -1748,21 +1348,9 @@ reverse is not necessarily true. [clinic start generated code]*/ -PyDoc_STRVAR(builtin_hash__doc__, -"hash($module, obj, /)\n" -"--\n" -"\n" -"Return the hash value for the given object.\n" -"\n" -"Two objects that compare equal must also have the same hash value, but the\n" -"reverse is not necessarily true."); - -#define BUILTIN_HASH_METHODDEF \ - {"hash", (PyCFunction)builtin_hash, METH_O, builtin_hash__doc__}, - static PyObject * builtin_hash(PyModuleDef *module, PyObject *obj) -/*[clinic end generated code: output=1ec467611c13468b input=ccc4d2b9a351df4e]*/ +/*[clinic end generated code: output=1f32ff154c1f751a input=ccc4d2b9a351df4e]*/ { Py_hash_t x; @@ -1785,21 +1373,9 @@ '0xc0ffee' [clinic start generated code]*/ -PyDoc_STRVAR(builtin_hex__doc__, -"hex($module, number, /)\n" -"--\n" -"\n" -"Return the hexadecimal representation of an integer.\n" -"\n" -" >>> hex(12648430)\n" -" \'0xc0ffee\'"); - -#define BUILTIN_HEX_METHODDEF \ - {"hex", (PyCFunction)builtin_hex, METH_O, builtin_hex__doc__}, - static PyObject * builtin_hex(PyModuleDef *module, PyObject *number) -/*[clinic end generated code: output=f18e9439aeaa2c6c input=e816200b0a728ebe]*/ +/*[clinic end generated code: output=618489ce3cbc5858 input=e816200b0a728ebe]*/ { return PyNumber_ToBase(number, 16); } @@ -1841,18 +1417,9 @@ Return the number of items in a container. [clinic start generated code]*/ -PyDoc_STRVAR(builtin_len__doc__, -"len($module, obj, /)\n" -"--\n" -"\n" -"Return the number of items in a container."); - -#define BUILTIN_LEN_METHODDEF \ - {"len", (PyCFunction)builtin_len, METH_O, builtin_len__doc__}, - static PyObject * builtin_len(PyModuleDef *module, PyObject *obj) -/*[clinic end generated code: output=5a38b0db40761705 input=2e5ff15db9a2de22]*/ +/*[clinic end generated code: output=8e5837b6f81d915b input=2e5ff15db9a2de22]*/ { Py_ssize_t res; @@ -1873,31 +1440,9 @@ covered by any backwards compatibility guarantees. [clinic start generated code]*/ -PyDoc_STRVAR(builtin_locals__doc__, -"locals($module, /)\n" -"--\n" -"\n" -"Return a dictionary containing the current scope\'s local variables.\n" -"\n" -"NOTE: Whether or not updates to this dictionary will affect name lookups in\n" -"the local scope and vice-versa is *implementation dependent* and not\n" -"covered by any backwards compatibility guarantees."); - -#define BUILTIN_LOCALS_METHODDEF \ - {"locals", (PyCFunction)builtin_locals, METH_NOARGS, builtin_locals__doc__}, - -static PyObject * -builtin_locals_impl(PyModuleDef *module); - -static PyObject * -builtin_locals(PyModuleDef *module, PyObject *Py_UNUSED(ignored)) -{ - return builtin_locals_impl(module); -} - static PyObject * builtin_locals_impl(PyModuleDef *module) -/*[clinic end generated code: output=8ac52522924346e2 input=7874018d478d5c4b]*/ +/*[clinic end generated code: output=8b5a41f12e19d13a input=7874018d478d5c4b]*/ { PyObject *d; @@ -2054,21 +1599,9 @@ '0o1234567' [clinic start generated code]*/ -PyDoc_STRVAR(builtin_oct__doc__, -"oct($module, number, /)\n" -"--\n" -"\n" -"Return the octal representation of an integer.\n" -"\n" -" >>> oct(342391)\n" -" \'0o1234567\'"); - -#define BUILTIN_OCT_METHODDEF \ - {"oct", (PyCFunction)builtin_oct, METH_O, builtin_oct__doc__}, - static PyObject * builtin_oct(PyModuleDef *module, PyObject *number) -/*[clinic end generated code: output=b99234d1d70a6673 input=a3a372b521b3dd13]*/ +/*[clinic end generated code: output=18f701bc6d8f804a input=a3a372b521b3dd13]*/ { return PyNumber_ToBase(number, 8); } @@ -2083,18 +1616,9 @@ Return the Unicode code point for a one-character string. [clinic start generated code]*/ -PyDoc_STRVAR(builtin_ord__doc__, -"ord($module, c, /)\n" -"--\n" -"\n" -"Return the Unicode code point for a one-character string."); - -#define BUILTIN_ORD_METHODDEF \ - {"ord", (PyCFunction)builtin_ord, METH_O, builtin_ord__doc__}, - static PyObject * builtin_ord(PyModuleDef *module, PyObject *c) -/*[clinic end generated code: output=a8466d23bd76db3f input=762355f87451efa3]*/ +/*[clinic end generated code: output=04fd27272d9462f6 input=762355f87451efa3]*/ { long ord; Py_ssize_t size; @@ -2152,42 +1676,9 @@ invoked using the three argument form. [clinic start generated code]*/ -PyDoc_STRVAR(builtin_pow__doc__, -"pow($module, x, y, z=None, /)\n" -"--\n" -"\n" -"Equivalent to x**y (with two arguments) or x**y % z (with three arguments)\n" -"\n" -"Some types, such as ints, are able to use a more efficient algorithm when\n" -"invoked using the three argument form."); - -#define BUILTIN_POW_METHODDEF \ - {"pow", (PyCFunction)builtin_pow, METH_VARARGS, builtin_pow__doc__}, - -static PyObject * -builtin_pow_impl(PyModuleDef *module, PyObject *x, PyObject *y, PyObject *z); - -static PyObject * -builtin_pow(PyModuleDef *module, PyObject *args) -{ - PyObject *return_value = NULL; - PyObject *x; - PyObject *y; - PyObject *z = Py_None; - - if (!PyArg_UnpackTuple(args, "pow", - 2, 3, - &x, &y, &z)) - goto exit; - return_value = builtin_pow_impl(module, x, y, z); - -exit: - return return_value; -} - static PyObject * builtin_pow_impl(PyModuleDef *module, PyObject *x, PyObject *y, PyObject *z) -/*[clinic end generated code: output=d0cdf314311dedba input=561a942d5f5c1899]*/ +/*[clinic end generated code: output=1fba268adba9b45f input=561a942d5f5c1899]*/ { return PyNumber_Power(x, y, z); } @@ -2304,43 +1795,9 @@ On *nix systems, readline is used if available. [clinic start generated code]*/ -PyDoc_STRVAR(builtin_input__doc__, -"input($module, prompt=None, /)\n" -"--\n" -"\n" -"Read a string from standard input. The trailing newline is stripped.\n" -"\n" -"The prompt string, if given, is printed to standard output without a\n" -"trailing newline before reading input.\n" -"\n" -"If the user hits EOF (*nix: Ctrl-D, Windows: Ctrl-Z+Return), raise EOFError.\n" -"On *nix systems, readline is used if available."); - -#define BUILTIN_INPUT_METHODDEF \ - {"input", (PyCFunction)builtin_input, METH_VARARGS, builtin_input__doc__}, - -static PyObject * -builtin_input_impl(PyModuleDef *module, PyObject *prompt); - -static PyObject * -builtin_input(PyModuleDef *module, PyObject *args) -{ - PyObject *return_value = NULL; - PyObject *prompt = NULL; - - if (!PyArg_UnpackTuple(args, "input", - 0, 1, - &prompt)) - goto exit; - return_value = builtin_input_impl(module, prompt); - -exit: - return return_value; -} - static PyObject * builtin_input_impl(PyModuleDef *module, PyObject *prompt) -/*[clinic end generated code: output=69323bf5695f7c9c input=5e8bb70c2908fe3c]*/ +/*[clinic end generated code: output=b77731f59e1515c4 input=5e8bb70c2908fe3c]*/ { PyObject *fin = _PySys_GetObjectId(&PyId_stdin); PyObject *fout = _PySys_GetObjectId(&PyId_stdout); @@ -2523,20 +1980,9 @@ For many object types, including most builtins, eval(repr(obj)) == obj. [clinic start generated code]*/ -PyDoc_STRVAR(builtin_repr__doc__, -"repr($module, obj, /)\n" -"--\n" -"\n" -"Return the canonical string representation of the object.\n" -"\n" -"For many object types, including most builtins, eval(repr(obj)) == obj."); - -#define BUILTIN_REPR_METHODDEF \ - {"repr", (PyCFunction)builtin_repr, METH_O, builtin_repr__doc__}, - static PyObject * builtin_repr(PyModuleDef *module, PyObject *obj) -/*[clinic end generated code: output=988980120f39e2fa input=a2bca0f38a5a924d]*/ +/*[clinic end generated code: output=dc41784fa4341834 input=a2bca0f38a5a924d]*/ { return PyObject_Repr(obj); } @@ -2704,42 +2150,9 @@ reject non-numeric types. [clinic start generated code]*/ -PyDoc_STRVAR(builtin_sum__doc__, -"sum($module, iterable, start=0, /)\n" -"--\n" -"\n" -"Return the sum of a \'start\' value (default: 0) plus an iterable of numbers\n" -"\n" -"When the iterable is empty, return the start value.\n" -"This function is intended specifically for use with numeric values and may\n" -"reject non-numeric types."); - -#define BUILTIN_SUM_METHODDEF \ - {"sum", (PyCFunction)builtin_sum, METH_VARARGS, builtin_sum__doc__}, - -static PyObject * -builtin_sum_impl(PyModuleDef *module, PyObject *iterable, PyObject *start); - -static PyObject * -builtin_sum(PyModuleDef *module, PyObject *args) -{ - PyObject *return_value = NULL; - PyObject *iterable; - PyObject *start = NULL; - - if (!PyArg_UnpackTuple(args, "sum", - 1, 2, - &iterable, &start)) - goto exit; - return_value = builtin_sum_impl(module, iterable, start); - -exit: - return return_value; -} - static PyObject * builtin_sum_impl(PyModuleDef *module, PyObject *iterable, PyObject *start) -/*[clinic end generated code: output=b42652a0d5f64f6b input=90ae7a242cfcf025]*/ +/*[clinic end generated code: output=33655b248b21d581 input=90ae7a242cfcf025]*/ { PyObject *result = start; PyObject *temp, *item, *iter; @@ -2914,42 +2327,9 @@ or ...`` etc. [clinic start generated code]*/ -PyDoc_STRVAR(builtin_isinstance__doc__, -"isinstance($module, obj, class_or_tuple, /)\n" -"--\n" -"\n" -"Return whether an object is an instance of a class or of a subclass thereof.\n" -"\n" -"A tuple, as in ``isinstance(x, (A, B, ...))``, may be given as the target to\n" -"check against. This is equivalent to ``isinstance(x, A) or isinstance(x, B)\n" -"or ...`` etc."); - -#define BUILTIN_ISINSTANCE_METHODDEF \ - {"isinstance", (PyCFunction)builtin_isinstance, METH_VARARGS, builtin_isinstance__doc__}, - -static PyObject * -builtin_isinstance_impl(PyModuleDef *module, PyObject *obj, PyObject *class_or_tuple); - -static PyObject * -builtin_isinstance(PyModuleDef *module, PyObject *args) -{ - PyObject *return_value = NULL; - PyObject *obj; - PyObject *class_or_tuple; - - if (!PyArg_UnpackTuple(args, "isinstance", - 2, 2, - &obj, &class_or_tuple)) - goto exit; - return_value = builtin_isinstance_impl(module, obj, class_or_tuple); - -exit: - return return_value; -} - static PyObject * builtin_isinstance_impl(PyModuleDef *module, PyObject *obj, PyObject *class_or_tuple) -/*[clinic end generated code: output=847df57fef8ddea7 input=cf9eb0ad6bb9bad6]*/ +/*[clinic end generated code: output=5e234dc3872d75a2 input=cf9eb0ad6bb9bad6]*/ { int retval; @@ -2974,42 +2354,9 @@ or ...`` etc. [clinic start generated code]*/ -PyDoc_STRVAR(builtin_issubclass__doc__, -"issubclass($module, cls, class_or_tuple, /)\n" -"--\n" -"\n" -"Return whether \'cls\' is a derived from another class or is the same class.\n" -"\n" -"A tuple, as in ``issubclass(x, (A, B, ...))``, may be given as the target to\n" -"check against. This is equivalent to ``issubclass(x, A) or issubclass(x, B)\n" -"or ...`` etc."); - -#define BUILTIN_ISSUBCLASS_METHODDEF \ - {"issubclass", (PyCFunction)builtin_issubclass, METH_VARARGS, builtin_issubclass__doc__}, - -static PyObject * -builtin_issubclass_impl(PyModuleDef *module, PyObject *cls, PyObject *class_or_tuple); - -static PyObject * -builtin_issubclass(PyModuleDef *module, PyObject *args) -{ - PyObject *return_value = NULL; - PyObject *cls; - PyObject *class_or_tuple; - - if (!PyArg_UnpackTuple(args, "issubclass", - 2, 2, - &cls, &class_or_tuple)) - goto exit; - return_value = builtin_issubclass_impl(module, cls, class_or_tuple); - -exit: - return return_value; -} - static PyObject * builtin_issubclass_impl(PyModuleDef *module, PyObject *cls, PyObject *class_or_tuple) -/*[clinic end generated code: output=a0f8c03692e35474 input=923d03fa41fc352a]*/ +/*[clinic end generated code: output=6346a85ba15dbd7d input=923d03fa41fc352a]*/ { int retval; diff --git a/Python/bltinmodule.c b/Python/clinic/bltinmodule.c.h copy from Python/bltinmodule.c copy to Python/clinic/bltinmodule.c.h --- a/Python/bltinmodule.c +++ b/Python/clinic/bltinmodule.c.h @@ -1,242 +1,5 @@ -/* Built-in functions */ - -#include "Python.h" -#include "Python-ast.h" - -#include "node.h" -#include "code.h" - -#include "asdl.h" -#include "ast.h" - -#include - -#ifdef HAVE_LANGINFO_H -#include /* CODESET */ -#endif - -/* The default encoding used by the platform file system APIs - Can remain NULL for all platforms that don't have such a concept - - Don't forget to modify PyUnicode_DecodeFSDefault() if you touch any of the - values for Py_FileSystemDefaultEncoding! -*/ -#ifdef HAVE_MBCS -const char *Py_FileSystemDefaultEncoding = "mbcs"; -int Py_HasFileSystemDefaultEncoding = 1; -#elif defined(__APPLE__) -const char *Py_FileSystemDefaultEncoding = "utf-8"; -int Py_HasFileSystemDefaultEncoding = 1; -#else -const char *Py_FileSystemDefaultEncoding = NULL; /* set by initfsencoding() */ -int Py_HasFileSystemDefaultEncoding = 0; -#endif - -_Py_IDENTIFIER(__builtins__); -_Py_IDENTIFIER(__dict__); -_Py_IDENTIFIER(__prepare__); -_Py_IDENTIFIER(__round__); -_Py_IDENTIFIER(encoding); -_Py_IDENTIFIER(errors); -_Py_IDENTIFIER(fileno); -_Py_IDENTIFIER(flush); -_Py_IDENTIFIER(metaclass); -_Py_IDENTIFIER(sort); -_Py_IDENTIFIER(stdin); -_Py_IDENTIFIER(stdout); -_Py_IDENTIFIER(stderr); - -/* AC: cannot convert yet, waiting for *args support */ -static PyObject * -builtin___build_class__(PyObject *self, PyObject *args, PyObject *kwds) -{ - PyObject *func, *name, *bases, *mkw, *meta, *winner, *prep, *ns, *cell; - PyObject *cls = NULL; - Py_ssize_t nargs; - int isclass = 0; /* initialize to prevent gcc warning */ - - assert(args != NULL); - if (!PyTuple_Check(args)) { - PyErr_SetString(PyExc_TypeError, - "__build_class__: args is not a tuple"); - return NULL; - } - nargs = PyTuple_GET_SIZE(args); - if (nargs < 2) { - PyErr_SetString(PyExc_TypeError, - "__build_class__: not enough arguments"); - return NULL; - } - func = PyTuple_GET_ITEM(args, 0); /* Better be callable */ - if (!PyFunction_Check(func)) { - PyErr_SetString(PyExc_TypeError, - "__build_class__: func must be a function"); - return NULL; - } - name = PyTuple_GET_ITEM(args, 1); - if (!PyUnicode_Check(name)) { - PyErr_SetString(PyExc_TypeError, - "__build_class__: name is not a string"); - return NULL; - } - bases = PyTuple_GetSlice(args, 2, nargs); - if (bases == NULL) - return NULL; - - if (kwds == NULL) { - meta = NULL; - mkw = NULL; - } - else { - mkw = PyDict_Copy(kwds); /* Don't modify kwds passed in! */ - if (mkw == NULL) { - Py_DECREF(bases); - return NULL; - } - meta = _PyDict_GetItemId(mkw, &PyId_metaclass); - if (meta != NULL) { - Py_INCREF(meta); - if (_PyDict_DelItemId(mkw, &PyId_metaclass) < 0) { - Py_DECREF(meta); - Py_DECREF(mkw); - Py_DECREF(bases); - return NULL; - } - /* metaclass is explicitly given, check if it's indeed a class */ - isclass = PyType_Check(meta); - } - } - if (meta == NULL) { - /* if there are no bases, use type: */ - if (PyTuple_GET_SIZE(bases) == 0) { - meta = (PyObject *) (&PyType_Type); - } - /* else get the type of the first base */ - else { - PyObject *base0 = PyTuple_GET_ITEM(bases, 0); - meta = (PyObject *) (base0->ob_type); - } - Py_INCREF(meta); - isclass = 1; /* meta is really a class */ - } - - if (isclass) { - /* meta is really a class, so check for a more derived - metaclass, or possible metaclass conflicts: */ - winner = (PyObject *)_PyType_CalculateMetaclass((PyTypeObject *)meta, - bases); - if (winner == NULL) { - Py_DECREF(meta); - Py_XDECREF(mkw); - Py_DECREF(bases); - return NULL; - } - if (winner != meta) { - Py_DECREF(meta); - meta = winner; - Py_INCREF(meta); - } - } - /* else: meta is not a class, so we cannot do the metaclass - calculation, so we will use the explicitly given object as it is */ - prep = _PyObject_GetAttrId(meta, &PyId___prepare__); - if (prep == NULL) { - if (PyErr_ExceptionMatches(PyExc_AttributeError)) { - PyErr_Clear(); - ns = PyDict_New(); - } - else { - Py_DECREF(meta); - Py_XDECREF(mkw); - Py_DECREF(bases); - return NULL; - } - } - else { - PyObject *pargs = PyTuple_Pack(2, name, bases); - if (pargs == NULL) { - Py_DECREF(prep); - Py_DECREF(meta); - Py_XDECREF(mkw); - Py_DECREF(bases); - return NULL; - } - ns = PyEval_CallObjectWithKeywords(prep, pargs, mkw); - Py_DECREF(pargs); - Py_DECREF(prep); - } - if (ns == NULL) { - Py_DECREF(meta); - Py_XDECREF(mkw); - Py_DECREF(bases); - return NULL; - } - cell = PyEval_EvalCodeEx(PyFunction_GET_CODE(func), PyFunction_GET_GLOBALS(func), ns, - NULL, 0, NULL, 0, NULL, 0, NULL, - PyFunction_GET_CLOSURE(func)); - if (cell != NULL) { - PyObject *margs; - margs = PyTuple_Pack(3, name, bases, ns); - if (margs != NULL) { - cls = PyEval_CallObjectWithKeywords(meta, margs, mkw); - Py_DECREF(margs); - } - if (cls != NULL && PyCell_Check(cell)) - PyCell_Set(cell, cls); - Py_DECREF(cell); - } - Py_DECREF(ns); - Py_DECREF(meta); - Py_XDECREF(mkw); - Py_DECREF(bases); - return cls; -} - -PyDoc_STRVAR(build_class_doc, -"__build_class__(func, name, *bases, metaclass=None, **kwds) -> class\n\ -\n\ -Internal helper function used by the class statement."); - -static PyObject * -builtin___import__(PyObject *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"name", "globals", "locals", "fromlist", - "level", 0}; - PyObject *name, *globals = NULL, *locals = NULL, *fromlist = NULL; - int level = 0; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "U|OOOi:__import__", - kwlist, &name, &globals, &locals, &fromlist, &level)) - return NULL; - return PyImport_ImportModuleLevelObject(name, globals, locals, - fromlist, level); -} - -PyDoc_STRVAR(import_doc, -"__import__(name, globals=None, locals=None, fromlist=(), level=0) -> module\n\ -\n\ -Import a module. Because this function is meant for use by the Python\n\ -interpreter and not for general use it is better to use\n\ -importlib.import_module() to programmatically import a module.\n\ -\n\ -The globals argument is only used to determine the context;\n\ -they are not modified. The locals argument is unused. The fromlist\n\ -should be a list of names to emulate ``from name import ...'', or an\n\ -empty list to emulate ``import name''.\n\ -When importing a module from a package, note that __import__('A.B', ...)\n\ -returns package A when fromlist is empty, but its submodule B when\n\ -fromlist is not empty. Level is used to determine whether to perform \n\ -absolute or relative imports. 0 is absolute while a positive number\n\ -is the number of parent directories to search relative to the current module."); - - /*[clinic input] -abs as builtin_abs - - x: 'O' - / - -Return the absolute value of the argument. +preserve [clinic start generated code]*/ PyDoc_STRVAR(builtin_abs__doc__, @@ -248,24 +11,6 @@ #define BUILTIN_ABS_METHODDEF \ {"abs", (PyCFunction)builtin_abs, METH_O, builtin_abs__doc__}, -static PyObject * -builtin_abs(PyModuleDef *module, PyObject *x) -/*[clinic end generated code: output=f85095528ce7e2e5 input=aa29cc07869b4732]*/ -{ - return PyNumber_Absolute(x); -} - -/*[clinic input] -all as builtin_all - - iterable: 'O' - / - -Return True if bool(x) is True for all values x in the iterable. - -If the iterable is empty, return True. -[clinic start generated code]*/ - PyDoc_STRVAR(builtin_all__doc__, "all($module, iterable, /)\n" "--\n" @@ -277,55 +22,6 @@ #define BUILTIN_ALL_METHODDEF \ {"all", (PyCFunction)builtin_all, METH_O, builtin_all__doc__}, -static PyObject * -builtin_all(PyModuleDef *module, PyObject *iterable) -/*[clinic end generated code: output=d001db739ba83b46 input=dd506dc9998d42bd]*/ -{ - PyObject *it, *item; - PyObject *(*iternext)(PyObject *); - int cmp; - - it = PyObject_GetIter(iterable); - if (it == NULL) - return NULL; - iternext = *Py_TYPE(it)->tp_iternext; - - for (;;) { - item = iternext(it); - if (item == NULL) - break; - cmp = PyObject_IsTrue(item); - Py_DECREF(item); - if (cmp < 0) { - Py_DECREF(it); - return NULL; - } - if (cmp == 0) { - Py_DECREF(it); - Py_RETURN_FALSE; - } - } - Py_DECREF(it); - if (PyErr_Occurred()) { - if (PyErr_ExceptionMatches(PyExc_StopIteration)) - PyErr_Clear(); - else - return NULL; - } - Py_RETURN_TRUE; -} - -/*[clinic input] -any as builtin_any - - iterable: 'O' - / - -Return True if bool(x) is True for any x in the iterable. - -If the iterable is empty, return False. -[clinic start generated code]*/ - PyDoc_STRVAR(builtin_any__doc__, "any($module, iterable, /)\n" "--\n" @@ -337,58 +33,6 @@ #define BUILTIN_ANY_METHODDEF \ {"any", (PyCFunction)builtin_any, METH_O, builtin_any__doc__}, -static PyObject * -builtin_any(PyModuleDef *module, PyObject *iterable) -/*[clinic end generated code: output=3a4b6dbe6a0d6f61 input=8fe8460f3fbbced8]*/ -{ - PyObject *it, *item; - PyObject *(*iternext)(PyObject *); - int cmp; - - it = PyObject_GetIter(iterable); - if (it == NULL) - return NULL; - iternext = *Py_TYPE(it)->tp_iternext; - - for (;;) { - item = iternext(it); - if (item == NULL) - break; - cmp = PyObject_IsTrue(item); - Py_DECREF(item); - if (cmp < 0) { - Py_DECREF(it); - return NULL; - } - if (cmp == 1) { - Py_DECREF(it); - Py_RETURN_TRUE; - } - } - Py_DECREF(it); - if (PyErr_Occurred()) { - if (PyErr_ExceptionMatches(PyExc_StopIteration)) - PyErr_Clear(); - else - return NULL; - } - Py_RETURN_FALSE; -} - -/*[clinic input] -ascii as builtin_ascii - - obj: 'O' - / - -Return an ASCII-only representation of an object. - -As repr(), return a string containing a printable representation of an -object, but escape the non-ASCII characters in the string returned by -repr() using \\x, \\u or \\U escapes. This generates a string similar -to that returned by repr() in Python 2. -[clinic start generated code]*/ - PyDoc_STRVAR(builtin_ascii__doc__, "ascii($module, obj, /)\n" "--\n" @@ -403,26 +47,6 @@ #define BUILTIN_ASCII_METHODDEF \ {"ascii", (PyCFunction)builtin_ascii, METH_O, builtin_ascii__doc__}, -static PyObject * -builtin_ascii(PyModuleDef *module, PyObject *obj) -/*[clinic end generated code: output=f0e6754154c2d30b input=0cbdc1420a306325]*/ -{ - return PyObject_ASCII(obj); -} - - -/*[clinic input] -bin as builtin_bin - - number: 'O' - / - -Return the binary representation of an integer. - - >>> bin(2796202) - '0b1010101010101010101010' -[clinic start generated code]*/ - PyDoc_STRVAR(builtin_bin__doc__, "bin($module, number, /)\n" "--\n" @@ -435,26 +59,6 @@ #define BUILTIN_BIN_METHODDEF \ {"bin", (PyCFunction)builtin_bin, METH_O, builtin_bin__doc__}, -static PyObject * -builtin_bin(PyModuleDef *module, PyObject *number) -/*[clinic end generated code: output=18fed0e943650da1 input=2a6362ae9a9c9203]*/ -{ - return PyNumber_ToBase(number, 2); -} - - -/*[clinic input] -callable as builtin_callable - - obj: 'O' - / - -Return whether the object is callable (i.e., some kind of function). - -Note that classes are callable, as are instances of classes with a -__call__() method. -[clinic start generated code]*/ - PyDoc_STRVAR(builtin_callable__doc__, "callable($module, obj, /)\n" "--\n" @@ -467,179 +71,6 @@ #define BUILTIN_CALLABLE_METHODDEF \ {"callable", (PyCFunction)builtin_callable, METH_O, builtin_callable__doc__}, -static PyObject * -builtin_callable(PyModuleDef *module, PyObject *obj) -/*[clinic end generated code: output=b3a92cbe635f32af input=bb3bb528fffdade4]*/ -{ - return PyBool_FromLong((long)PyCallable_Check(obj)); -} - - -typedef struct { - PyObject_HEAD - PyObject *func; - PyObject *it; -} filterobject; - -static PyObject * -filter_new(PyTypeObject *type, PyObject *args, PyObject *kwds) -{ - PyObject *func, *seq; - PyObject *it; - filterobject *lz; - - if (type == &PyFilter_Type && !_PyArg_NoKeywords("filter()", kwds)) - return NULL; - - if (!PyArg_UnpackTuple(args, "filter", 2, 2, &func, &seq)) - return NULL; - - /* Get iterator. */ - it = PyObject_GetIter(seq); - if (it == NULL) - return NULL; - - /* create filterobject structure */ - lz = (filterobject *)type->tp_alloc(type, 0); - if (lz == NULL) { - Py_DECREF(it); - return NULL; - } - Py_INCREF(func); - lz->func = func; - lz->it = it; - - return (PyObject *)lz; -} - -static void -filter_dealloc(filterobject *lz) -{ - PyObject_GC_UnTrack(lz); - Py_XDECREF(lz->func); - Py_XDECREF(lz->it); - Py_TYPE(lz)->tp_free(lz); -} - -static int -filter_traverse(filterobject *lz, visitproc visit, void *arg) -{ - Py_VISIT(lz->it); - Py_VISIT(lz->func); - return 0; -} - -static PyObject * -filter_next(filterobject *lz) -{ - PyObject *item; - PyObject *it = lz->it; - long ok; - PyObject *(*iternext)(PyObject *); - - iternext = *Py_TYPE(it)->tp_iternext; - for (;;) { - item = iternext(it); - if (item == NULL) - return NULL; - - if (lz->func == Py_None || lz->func == (PyObject *)&PyBool_Type) { - ok = PyObject_IsTrue(item); - } else { - PyObject *good; - good = PyObject_CallFunctionObjArgs(lz->func, - item, NULL); - if (good == NULL) { - Py_DECREF(item); - return NULL; - } - ok = PyObject_IsTrue(good); - Py_DECREF(good); - } - if (ok > 0) - return item; - Py_DECREF(item); - if (ok < 0) - return NULL; - } -} - -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\ -Return an iterator yielding those items of iterable for which function(item)\n\ -is true. If function is None, return the items that are true."); - -PyTypeObject PyFilter_Type = { - PyVarObject_HEAD_INIT(&PyType_Type, 0) - "filter", /* tp_name */ - sizeof(filterobject), /* tp_basicsize */ - 0, /* tp_itemsize */ - /* methods */ - (destructor)filter_dealloc, /* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_reserved */ - 0, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - PyObject_GenericGetAttr, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | - Py_TPFLAGS_BASETYPE, /* tp_flags */ - filter_doc, /* tp_doc */ - (traverseproc)filter_traverse, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - PyObject_SelfIter, /* tp_iter */ - (iternextfunc)filter_next, /* tp_iternext */ - filter_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 */ - PyType_GenericAlloc, /* tp_alloc */ - filter_new, /* tp_new */ - PyObject_GC_Del, /* tp_free */ -}; - - -/*[clinic input] -format as builtin_format - - value: 'O' - format_spec: unicode(c_default="NULL") = '' - / - -Return value.__format__(format_spec) - -format_spec defaults to the empty string -[clinic start generated code]*/ - PyDoc_STRVAR(builtin_format__doc__, "format($module, value, format_spec=\'\', /)\n" "--\n" @@ -671,22 +102,6 @@ return return_value; } -static PyObject * -builtin_format_impl(PyModuleDef *module, PyObject *value, PyObject *format_spec) -/*[clinic end generated code: output=39723a58c72e8871 input=e23f2f11e0098c64]*/ -{ - return PyObject_Format(value, format_spec); -} - -/*[clinic input] -chr as builtin_chr - - i: 'i' - / - -Return a Unicode string of one character with ordinal i; 0 <= i <= 0x10ffff. -[clinic start generated code]*/ - PyDoc_STRVAR(builtin_chr__doc__, "chr($module, i, /)\n" "--\n" @@ -715,70 +130,6 @@ return return_value; } -static PyObject * -builtin_chr_impl(PyModuleDef *module, int i) -/*[clinic end generated code: output=4d6bbe948f56e2ae input=9b1ced29615adf66]*/ -{ - return PyUnicode_FromOrdinal(i); -} - - -static const char * -source_as_string(PyObject *cmd, const char *funcname, const char *what, PyCompilerFlags *cf, Py_buffer *view) -{ - const char *str; - Py_ssize_t size; - - if (PyUnicode_Check(cmd)) { - cf->cf_flags |= PyCF_IGNORE_COOKIE; - str = PyUnicode_AsUTF8AndSize(cmd, &size); - if (str == NULL) - return NULL; - } - else if (PyObject_GetBuffer(cmd, view, PyBUF_SIMPLE) == 0) { - str = (const char *)view->buf; - size = view->len; - } - else { - PyErr_Format(PyExc_TypeError, - "%s() arg 1 must be a %s object", - funcname, what); - return NULL; - } - - if (strlen(str) != (size_t)size) { - PyErr_SetString(PyExc_ValueError, - "source code string cannot contain null bytes"); - PyBuffer_Release(view); - return NULL; - } - return str; -} - -/*[clinic input] -compile as builtin_compile - - source: 'O' - filename: object(converter="PyUnicode_FSDecoder") - mode: 's' - flags: 'i' = 0 - dont_inherit: 'i' = 0 - optimize: 'i' = -1 - -Compile source into a code object that can be executed by exec() or eval(). - -The source code may represent a Python module, statement or expression. -The filename will be used for run-time error messages. -The mode must be 'exec' to compile a module, 'single' to compile a -single (interactive) statement, or 'eval' to compile an expression. -The flags argument, if present, controls which future statements influence -the compilation of the code. -The dont_inherit argument, if non-zero, stops the compilation inheriting -the effects of any future statements in effect in the code calling -compile; if absent or zero these statements do influence the compilation, -in addition to any features explicitly specified. -[clinic start generated code]*/ - PyDoc_STRVAR(builtin_compile__doc__, "compile($module, /, source, filename, mode, flags=0, dont_inherit=0,\n" " optimize=-1)\n" @@ -825,132 +176,6 @@ return return_value; } -static PyObject * -builtin_compile_impl(PyModuleDef *module, PyObject *source, PyObject *filename, const char *mode, int flags, int dont_inherit, int optimize) -/*[clinic end generated code: output=c72d197809d178fc input=c6212a9d21472f7e]*/ -{ - Py_buffer view = {NULL, NULL}; - const char *str; - int compile_mode = -1; - int is_ast; - PyCompilerFlags cf; - int start[] = {Py_file_input, Py_eval_input, Py_single_input}; - PyObject *result; - - cf.cf_flags = flags | PyCF_SOURCE_IS_UTF8; - - if (flags & - ~(PyCF_MASK | PyCF_MASK_OBSOLETE | PyCF_DONT_IMPLY_DEDENT | PyCF_ONLY_AST)) - { - PyErr_SetString(PyExc_ValueError, - "compile(): unrecognised flags"); - goto error; - } - /* XXX Warn if (supplied_flags & PyCF_MASK_OBSOLETE) != 0? */ - - if (optimize < -1 || optimize > 2) { - PyErr_SetString(PyExc_ValueError, - "compile(): invalid optimize value"); - goto error; - } - - if (!dont_inherit) { - PyEval_MergeCompilerFlags(&cf); - } - - if (strcmp(mode, "exec") == 0) - compile_mode = 0; - else if (strcmp(mode, "eval") == 0) - compile_mode = 1; - else if (strcmp(mode, "single") == 0) - compile_mode = 2; - else { - PyErr_SetString(PyExc_ValueError, - "compile() mode must be 'exec', 'eval' or 'single'"); - goto error; - } - - is_ast = PyAST_Check(source); - if (is_ast == -1) - goto error; - if (is_ast) { - if (flags & PyCF_ONLY_AST) { - Py_INCREF(source); - result = source; - } - else { - PyArena *arena; - mod_ty mod; - - arena = PyArena_New(); - if (arena == NULL) - goto error; - mod = PyAST_obj2mod(source, arena, compile_mode); - if (mod == NULL) { - PyArena_Free(arena); - goto error; - } - if (!PyAST_Validate(mod)) { - PyArena_Free(arena); - goto error; - } - result = (PyObject*)PyAST_CompileObject(mod, filename, - &cf, optimize, arena); - PyArena_Free(arena); - } - goto finally; - } - - str = source_as_string(source, "compile", "string, bytes or AST", &cf, &view); - if (str == NULL) - goto error; - - result = Py_CompileStringObject(str, filename, start[compile_mode], &cf, optimize); - PyBuffer_Release(&view); - goto finally; - -error: - result = NULL; -finally: - Py_DECREF(filename); - return result; -} - -/* AC: cannot convert yet, as needs PEP 457 group support in inspect */ -static PyObject * -builtin_dir(PyObject *self, PyObject *args) -{ - PyObject *arg = NULL; - - if (!PyArg_UnpackTuple(args, "dir", 0, 1, &arg)) - return NULL; - return PyObject_Dir(arg); -} - -PyDoc_STRVAR(dir_doc, -"dir([object]) -> list of strings\n" -"\n" -"If called without an argument, return the names in the current scope.\n" -"Else, return an alphabetized list of names comprising (some of) the attributes\n" -"of the given object, and of attributes reachable from it.\n" -"If the object supplies a method named __dir__, it will be used; otherwise\n" -"the default dir() logic is used and returns:\n" -" for a module object: the module's attributes.\n" -" for a class object: its attributes, and recursively the attributes\n" -" of its bases.\n" -" for any other object: its attributes, its class's attributes, and\n" -" recursively the attributes of its class's base classes."); - -/*[clinic input] -divmod as builtin_divmod - - x: 'O' - y: 'O' - / - -Return the tuple ((x-x%y)/y, x%y). Invariant: div*y + mod == x. -[clinic start generated code]*/ - PyDoc_STRVAR(builtin_divmod__doc__, "divmod($module, x, y, /)\n" "--\n" @@ -980,31 +205,6 @@ return return_value; } -static PyObject * -builtin_divmod_impl(PyModuleDef *module, PyObject *x, PyObject *y) -/*[clinic end generated code: output=77e8d408b1338886 input=c9c617b7bb74c615]*/ -{ - return PyNumber_Divmod(x, y); -} - - -/*[clinic input] -eval as builtin_eval - - source: 'O' - globals: 'O' = None - locals: 'O' = None - / - -Evaluate the given source in the context of globals and locals. - -The source may be a string representing a Python expression -or a code object as returned by compile(). -The globals must be a dictionary and locals can be any mapping, -defaulting to the current globals and locals. -If only globals is given, locals defaults to it. -[clinic start generated code]*/ - PyDoc_STRVAR(builtin_eval__doc__, "eval($module, source, globals=None, locals=None, /)\n" "--\n" @@ -1041,90 +241,6 @@ return return_value; } -static PyObject * -builtin_eval_impl(PyModuleDef *module, PyObject *source, PyObject *globals, PyObject *locals) -/*[clinic end generated code: output=644fd59012538ce6 input=31e42c1d2125b50b]*/ -{ - PyObject *result, *tmp = NULL; - Py_buffer view = {NULL, NULL}; - const char *str; - PyCompilerFlags cf; - - if (locals != Py_None && !PyMapping_Check(locals)) { - PyErr_SetString(PyExc_TypeError, "locals must be a mapping"); - return NULL; - } - if (globals != Py_None && !PyDict_Check(globals)) { - PyErr_SetString(PyExc_TypeError, PyMapping_Check(globals) ? - "globals must be a real dict; try eval(expr, {}, mapping)" - : "globals must be a dict"); - return NULL; - } - if (globals == Py_None) { - globals = PyEval_GetGlobals(); - if (locals == Py_None) { - locals = PyEval_GetLocals(); - if (locals == NULL) - return NULL; - } - } - else if (locals == Py_None) - locals = globals; - - if (globals == NULL || locals == NULL) { - PyErr_SetString(PyExc_TypeError, - "eval must be given globals and locals " - "when called without a frame"); - return NULL; - } - - if (_PyDict_GetItemId(globals, &PyId___builtins__) == NULL) { - if (_PyDict_SetItemId(globals, &PyId___builtins__, - PyEval_GetBuiltins()) != 0) - return NULL; - } - - if (PyCode_Check(source)) { - if (PyCode_GetNumFree((PyCodeObject *)source) > 0) { - PyErr_SetString(PyExc_TypeError, - "code object passed to eval() may not contain free variables"); - return NULL; - } - return PyEval_EvalCode(source, globals, locals); - } - - cf.cf_flags = PyCF_SOURCE_IS_UTF8; - str = source_as_string(source, "eval", "string, bytes or code", &cf, &view); - if (str == NULL) - return NULL; - - while (*str == ' ' || *str == '\t') - str++; - - (void)PyEval_MergeCompilerFlags(&cf); - result = PyRun_StringFlags(str, Py_eval_input, globals, locals, &cf); - PyBuffer_Release(&view); - Py_XDECREF(tmp); - return result; -} - -/*[clinic input] -exec as builtin_exec - - source: 'O' - globals: 'O' = None - locals: 'O' = None - / - -Execute the given source in the context of globals and locals. - -The source may be a string representing one or more Python statements -or a code object as returned by compile(). -The globals must be a dictionary and locals can be any mapping, -defaulting to the current globals and locals. -If only globals is given, locals defaults to it. -[clinic start generated code]*/ - PyDoc_STRVAR(builtin_exec__doc__, "exec($module, source, globals=None, locals=None, /)\n" "--\n" @@ -1161,120 +277,6 @@ return return_value; } -static PyObject * -builtin_exec_impl(PyModuleDef *module, PyObject *source, PyObject *globals, PyObject *locals) -/*[clinic end generated code: output=0281b48bfa8e3c87 input=536e057b5e00d89e]*/ -{ - PyObject *v; - - if (globals == Py_None) { - globals = PyEval_GetGlobals(); - if (locals == Py_None) { - locals = PyEval_GetLocals(); - if (locals == NULL) - return NULL; - } - if (!globals || !locals) { - PyErr_SetString(PyExc_SystemError, - "globals and locals cannot be NULL"); - return NULL; - } - } - else if (locals == Py_None) - locals = globals; - - if (!PyDict_Check(globals)) { - PyErr_Format(PyExc_TypeError, "exec() globals must be a dict, not %.100s", - globals->ob_type->tp_name); - return NULL; - } - if (!PyMapping_Check(locals)) { - PyErr_Format(PyExc_TypeError, - "locals must be a mapping or None, not %.100s", - locals->ob_type->tp_name); - return NULL; - } - if (_PyDict_GetItemId(globals, &PyId___builtins__) == NULL) { - if (_PyDict_SetItemId(globals, &PyId___builtins__, - PyEval_GetBuiltins()) != 0) - return NULL; - } - - if (PyCode_Check(source)) { - if (PyCode_GetNumFree((PyCodeObject *)source) > 0) { - PyErr_SetString(PyExc_TypeError, - "code object passed to exec() may not " - "contain free variables"); - return NULL; - } - v = PyEval_EvalCode(source, globals, locals); - } - else { - Py_buffer view = {NULL, NULL}; - const char *str; - PyCompilerFlags cf; - cf.cf_flags = PyCF_SOURCE_IS_UTF8; - str = source_as_string(source, "exec", - "string, bytes or code", &cf, &view); - if (str == NULL) - return NULL; - if (PyEval_MergeCompilerFlags(&cf)) - v = PyRun_StringFlags(str, Py_file_input, globals, - locals, &cf); - else - v = PyRun_String(str, Py_file_input, globals, locals); - PyBuffer_Release(&view); - } - if (v == NULL) - return NULL; - Py_DECREF(v); - Py_RETURN_NONE; -} - - -/* AC: cannot convert yet, as needs PEP 457 group support in inspect */ -static PyObject * -builtin_getattr(PyObject *self, PyObject *args) -{ - PyObject *v, *result, *dflt = NULL; - PyObject *name; - - if (!PyArg_UnpackTuple(args, "getattr", 2, 3, &v, &name, &dflt)) - return NULL; - - if (!PyUnicode_Check(name)) { - PyErr_SetString(PyExc_TypeError, - "getattr(): attribute name must be string"); - return NULL; - } - result = PyObject_GetAttr(v, name); - if (result == NULL && dflt != NULL && - PyErr_ExceptionMatches(PyExc_AttributeError)) - { - PyErr_Clear(); - Py_INCREF(dflt); - result = dflt; - } - return result; -} - -PyDoc_STRVAR(getattr_doc, -"getattr(object, name[, default]) -> value\n\ -\n\ -Get a named attribute from an object; getattr(x, 'y') is equivalent to x.y.\n\ -When a default argument is given, it is returned when the attribute doesn't\n\ -exist; without it, an exception is raised in that case."); - - -/*[clinic input] -globals as builtin_globals - -Return the dictionary containing the current scope's global variables. - -NOTE: Updates to this dictionary *will* affect name lookups in the current -global scope and vice-versa. -[clinic start generated code]*/ - PyDoc_STRVAR(builtin_globals__doc__, "globals($module, /)\n" "--\n" @@ -1296,30 +298,6 @@ return builtin_globals_impl(module); } -static PyObject * -builtin_globals_impl(PyModuleDef *module) -/*[clinic end generated code: output=048640f58b1f20ad input=9327576f92bb48ba]*/ -{ - PyObject *d; - - d = PyEval_GetGlobals(); - Py_XINCREF(d); - return d; -} - - -/*[clinic input] -hasattr as builtin_hasattr - - obj: 'O' - name: 'O' - / - -Return whether the object has an attribute with the given name. - -This is done by calling getattr(obj, name) and catching AttributeError. -[clinic start generated code]*/ - PyDoc_STRVAR(builtin_hasattr__doc__, "hasattr($module, obj, name, /)\n" "--\n" @@ -1351,47 +329,6 @@ return return_value; } -static PyObject * -builtin_hasattr_impl(PyModuleDef *module, PyObject *obj, PyObject *name) -/*[clinic end generated code: output=e0bd996ef73d1217 input=b50bad5f739ea10d]*/ -{ - PyObject *v; - - if (!PyUnicode_Check(name)) { - PyErr_SetString(PyExc_TypeError, - "hasattr(): attribute name must be string"); - return NULL; - } - v = PyObject_GetAttr(obj, name); - if (v == NULL) { - if (PyErr_ExceptionMatches(PyExc_AttributeError)) { - PyErr_Clear(); - Py_RETURN_FALSE; - } - return NULL; - } - Py_DECREF(v); - Py_RETURN_TRUE; -} - - -/* AC: gdb's integration with CPython relies on builtin_id having - * the *exact* parameter names of "self" and "v", so we ensure we - * preserve those name rather than using the AC defaults. - */ -/*[clinic input] -id as builtin_id - - self: self(type="PyModuleDef *") - obj as v: 'O' - / - -Return the identity of an object. - -This is guaranteed to be unique among simultaneously existing objects. -(CPython uses the object's memory address.) -[clinic start generated code]*/ - PyDoc_STRVAR(builtin_id__doc__, "id($module, obj, /)\n" "--\n" @@ -1404,241 +341,6 @@ #define BUILTIN_ID_METHODDEF \ {"id", (PyCFunction)builtin_id, METH_O, builtin_id__doc__}, -static PyObject * -builtin_id(PyModuleDef *self, PyObject *v) -/*[clinic end generated code: output=f54da09c91992e63 input=a1f988d98357341d]*/ -{ - return PyLong_FromVoidPtr(v); -} - - -/* map object ************************************************************/ - -typedef struct { - PyObject_HEAD - PyObject *iters; - PyObject *func; -} mapobject; - -static PyObject * -map_new(PyTypeObject *type, PyObject *args, PyObject *kwds) -{ - PyObject *it, *iters, *func; - mapobject *lz; - Py_ssize_t numargs, i; - - if (type == &PyMap_Type && !_PyArg_NoKeywords("map()", kwds)) - return NULL; - - numargs = PyTuple_Size(args); - if (numargs < 2) { - PyErr_SetString(PyExc_TypeError, - "map() must have at least two arguments."); - return NULL; - } - - iters = PyTuple_New(numargs-1); - if (iters == NULL) - return NULL; - - for (i=1 ; itp_alloc(type, 0); - if (lz == NULL) { - Py_DECREF(iters); - return NULL; - } - lz->iters = iters; - func = PyTuple_GET_ITEM(args, 0); - Py_INCREF(func); - lz->func = func; - - return (PyObject *)lz; -} - -static void -map_dealloc(mapobject *lz) -{ - PyObject_GC_UnTrack(lz); - Py_XDECREF(lz->iters); - Py_XDECREF(lz->func); - Py_TYPE(lz)->tp_free(lz); -} - -static int -map_traverse(mapobject *lz, visitproc visit, void *arg) -{ - Py_VISIT(lz->iters); - Py_VISIT(lz->func); - return 0; -} - -static PyObject * -map_next(mapobject *lz) -{ - PyObject *val; - PyObject *argtuple; - PyObject *result; - Py_ssize_t numargs, i; - - numargs = PyTuple_Size(lz->iters); - argtuple = PyTuple_New(numargs); - if (argtuple == NULL) - return NULL; - - for (i=0 ; iiters, i)); - if (val == NULL) { - Py_DECREF(argtuple); - return NULL; - } - PyTuple_SET_ITEM(argtuple, i, val); - } - result = PyObject_Call(lz->func, argtuple, NULL); - Py_DECREF(argtuple); - 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\ -Make an iterator that computes the function using arguments from\n\ -each of the iterables. Stops when the shortest iterable is exhausted."); - -PyTypeObject PyMap_Type = { - PyVarObject_HEAD_INIT(&PyType_Type, 0) - "map", /* tp_name */ - sizeof(mapobject), /* tp_basicsize */ - 0, /* tp_itemsize */ - /* methods */ - (destructor)map_dealloc, /* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_reserved */ - 0, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - PyObject_GenericGetAttr, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | - Py_TPFLAGS_BASETYPE, /* tp_flags */ - map_doc, /* tp_doc */ - (traverseproc)map_traverse, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - PyObject_SelfIter, /* tp_iter */ - (iternextfunc)map_next, /* tp_iternext */ - map_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 */ - PyType_GenericAlloc, /* tp_alloc */ - map_new, /* tp_new */ - PyObject_GC_Del, /* tp_free */ -}; - - -/* AC: cannot convert yet, as needs PEP 457 group support in inspect */ -static PyObject * -builtin_next(PyObject *self, PyObject *args) -{ - PyObject *it, *res; - PyObject *def = NULL; - - if (!PyArg_UnpackTuple(args, "next", 1, 2, &it, &def)) - return NULL; - if (!PyIter_Check(it)) { - PyErr_Format(PyExc_TypeError, - "'%.200s' object is not an iterator", - it->ob_type->tp_name); - return NULL; - } - - res = (*it->ob_type->tp_iternext)(it); - if (res != NULL) { - return res; - } else if (def != NULL) { - if (PyErr_Occurred()) { - if(!PyErr_ExceptionMatches(PyExc_StopIteration)) - return NULL; - PyErr_Clear(); - } - Py_INCREF(def); - return def; - } else if (PyErr_Occurred()) { - return NULL; - } else { - PyErr_SetNone(PyExc_StopIteration); - return NULL; - } -} - -PyDoc_STRVAR(next_doc, -"next(iterator[, default])\n\ -\n\ -Return the next item from the iterator. If default is given and the iterator\n\ -is exhausted, it is returned instead of raising StopIteration."); - - -/*[clinic input] -setattr as builtin_setattr - - obj: 'O' - name: 'O' - value: 'O' - / - -Sets the named attribute on the given object to the specified value. - -setattr(x, 'y', v) is equivalent to ``x.y = v'' -[clinic start generated code]*/ - PyDoc_STRVAR(builtin_setattr__doc__, "setattr($module, obj, name, value, /)\n" "--\n" @@ -1671,29 +373,6 @@ return return_value; } -static PyObject * -builtin_setattr_impl(PyModuleDef *module, PyObject *obj, PyObject *name, PyObject *value) -/*[clinic end generated code: output=4336dcbbf7691d2d input=fbe7e53403116b93]*/ -{ - if (PyObject_SetAttr(obj, name, value) != 0) - return NULL; - Py_INCREF(Py_None); - return Py_None; -} - - -/*[clinic input] -delattr as builtin_delattr - - obj: 'O' - name: 'O' - / - -Deletes the named attribute from the given object. - -delattr(x, 'y') is equivalent to ``del x.y'' -[clinic start generated code]*/ - PyDoc_STRVAR(builtin_delattr__doc__, "delattr($module, obj, name, /)\n" "--\n" @@ -1725,29 +404,6 @@ return return_value; } -static PyObject * -builtin_delattr_impl(PyModuleDef *module, PyObject *obj, PyObject *name) -/*[clinic end generated code: output=319c2d884aa769cf input=647af2ce9183a823]*/ -{ - if (PyObject_SetAttr(obj, name, (PyObject *)NULL) != 0) - return NULL; - Py_INCREF(Py_None); - return Py_None; -} - - -/*[clinic input] -hash as builtin_hash - - obj: 'O' - / - -Return the hash value for the given object. - -Two objects that compare equal must also have the same hash value, but the -reverse is not necessarily true. -[clinic start generated code]*/ - PyDoc_STRVAR(builtin_hash__doc__, "hash($module, obj, /)\n" "--\n" @@ -1760,31 +416,6 @@ #define BUILTIN_HASH_METHODDEF \ {"hash", (PyCFunction)builtin_hash, METH_O, builtin_hash__doc__}, -static PyObject * -builtin_hash(PyModuleDef *module, PyObject *obj) -/*[clinic end generated code: output=1ec467611c13468b input=ccc4d2b9a351df4e]*/ -{ - Py_hash_t x; - - x = PyObject_Hash(obj); - if (x == -1) - return NULL; - return PyLong_FromSsize_t(x); -} - - -/*[clinic input] -hex as builtin_hex - - number: 'O' - / - -Return the hexadecimal representation of an integer. - - >>> hex(12648430) - '0xc0ffee' -[clinic start generated code]*/ - PyDoc_STRVAR(builtin_hex__doc__, "hex($module, number, /)\n" "--\n" @@ -1797,50 +428,6 @@ #define BUILTIN_HEX_METHODDEF \ {"hex", (PyCFunction)builtin_hex, METH_O, builtin_hex__doc__}, -static PyObject * -builtin_hex(PyModuleDef *module, PyObject *number) -/*[clinic end generated code: output=f18e9439aeaa2c6c input=e816200b0a728ebe]*/ -{ - return PyNumber_ToBase(number, 16); -} - - -/* AC: cannot convert yet, as needs PEP 457 group support in inspect */ -static PyObject * -builtin_iter(PyObject *self, PyObject *args) -{ - PyObject *v, *w = NULL; - - if (!PyArg_UnpackTuple(args, "iter", 1, 2, &v, &w)) - return NULL; - if (w == NULL) - return PyObject_GetIter(v); - if (!PyCallable_Check(v)) { - PyErr_SetString(PyExc_TypeError, - "iter(v, w): v must be callable"); - return NULL; - } - return PyCallIter_New(v, w); -} - -PyDoc_STRVAR(iter_doc, -"iter(iterable) -> iterator\n\ -iter(callable, sentinel) -> iterator\n\ -\n\ -Get an iterator from an object. In the first form, the argument must\n\ -supply its own iterator, or be a sequence.\n\ -In the second form, the callable is called until it returns the sentinel."); - - -/*[clinic input] -len as builtin_len - - obj: 'O' - / - -Return the number of items in a container. -[clinic start generated code]*/ - PyDoc_STRVAR(builtin_len__doc__, "len($module, obj, /)\n" "--\n" @@ -1850,29 +437,6 @@ #define BUILTIN_LEN_METHODDEF \ {"len", (PyCFunction)builtin_len, METH_O, builtin_len__doc__}, -static PyObject * -builtin_len(PyModuleDef *module, PyObject *obj) -/*[clinic end generated code: output=5a38b0db40761705 input=2e5ff15db9a2de22]*/ -{ - Py_ssize_t res; - - res = PyObject_Size(obj); - if (res < 0 && PyErr_Occurred()) - return NULL; - return PyLong_FromSsize_t(res); -} - - -/*[clinic input] -locals as builtin_locals - -Return a dictionary containing the current scope's local variables. - -NOTE: Whether or not updates to this dictionary will affect name lookups in -the local scope and vice-versa is *implementation dependent* and not -covered by any backwards compatibility guarantees. -[clinic start generated code]*/ - PyDoc_STRVAR(builtin_locals__doc__, "locals($module, /)\n" "--\n" @@ -1895,165 +459,6 @@ return builtin_locals_impl(module); } -static PyObject * -builtin_locals_impl(PyModuleDef *module) -/*[clinic end generated code: output=8ac52522924346e2 input=7874018d478d5c4b]*/ -{ - PyObject *d; - - d = PyEval_GetLocals(); - Py_XINCREF(d); - return d; -} - - -static PyObject * -min_max(PyObject *args, PyObject *kwds, int op) -{ - PyObject *v, *it, *item, *val, *maxitem, *maxval, *keyfunc=NULL; - PyObject *emptytuple, *defaultval = NULL; - static char *kwlist[] = {"key", "default", NULL}; - const char *name = op == Py_LT ? "min" : "max"; - const int positional = PyTuple_Size(args) > 1; - int ret; - - if (positional) - v = args; - else if (!PyArg_UnpackTuple(args, name, 1, 1, &v)) - return NULL; - - emptytuple = PyTuple_New(0); - if (emptytuple == NULL) - return NULL; - ret = PyArg_ParseTupleAndKeywords(emptytuple, kwds, "|$OO", kwlist, - &keyfunc, &defaultval); - Py_DECREF(emptytuple); - if (!ret) - return NULL; - - if (positional && defaultval != NULL) { - PyErr_Format(PyExc_TypeError, - "Cannot specify a default for %s() with multiple " - "positional arguments", name); - return NULL; - } - - it = PyObject_GetIter(v); - if (it == NULL) { - return NULL; - } - - maxitem = NULL; /* the result */ - maxval = NULL; /* the value associated with the result */ - while (( item = PyIter_Next(it) )) { - /* get the value from the key function */ - if (keyfunc != NULL) { - val = PyObject_CallFunctionObjArgs(keyfunc, item, NULL); - if (val == NULL) - goto Fail_it_item; - } - /* no key function; the value is the item */ - else { - val = item; - Py_INCREF(val); - } - - /* maximum value and item are unset; set them */ - if (maxval == NULL) { - maxitem = item; - maxval = val; - } - /* maximum value and item are set; update them as necessary */ - else { - int cmp = PyObject_RichCompareBool(val, maxval, op); - if (cmp < 0) - goto Fail_it_item_and_val; - else if (cmp > 0) { - Py_DECREF(maxval); - Py_DECREF(maxitem); - maxval = val; - maxitem = item; - } - else { - Py_DECREF(item); - Py_DECREF(val); - } - } - } - if (PyErr_Occurred()) - goto Fail_it; - if (maxval == NULL) { - assert(maxitem == NULL); - if (defaultval != NULL) { - Py_INCREF(defaultval); - maxitem = defaultval; - } else { - PyErr_Format(PyExc_ValueError, - "%s() arg is an empty sequence", name); - } - } - else - Py_DECREF(maxval); - Py_DECREF(it); - return maxitem; - -Fail_it_item_and_val: - Py_DECREF(val); -Fail_it_item: - Py_DECREF(item); -Fail_it: - Py_XDECREF(maxval); - Py_XDECREF(maxitem); - Py_DECREF(it); - return NULL; -} - -/* AC: cannot convert yet, waiting for *args support */ -static PyObject * -builtin_min(PyObject *self, PyObject *args, PyObject *kwds) -{ - return min_max(args, kwds, Py_LT); -} - -PyDoc_STRVAR(min_doc, -"min(iterable, *[, default=obj, key=func]) -> value\n\ -min(arg1, arg2, *args, *[, key=func]) -> value\n\ -\n\ -With a single iterable argument, return its smallest item. The\n\ -default keyword-only argument specifies an object to return if\n\ -the provided iterable is empty.\n\ -With two or more arguments, return the smallest argument."); - - -/* AC: cannot convert yet, waiting for *args support */ -static PyObject * -builtin_max(PyObject *self, PyObject *args, PyObject *kwds) -{ - return min_max(args, kwds, Py_GT); -} - -PyDoc_STRVAR(max_doc, -"max(iterable, *[, default=obj, key=func]) -> value\n\ -max(arg1, arg2, *args, *[, key=func]) -> value\n\ -\n\ -With a single iterable argument, return its biggest item. The\n\ -default keyword-only argument specifies an object to return if\n\ -the provided iterable is empty.\n\ -With two or more arguments, return the largest argument."); - - -/*[clinic input] -oct as builtin_oct - - number: 'O' - / - -Return the octal representation of an integer. - - >>> oct(342391) - '0o1234567' -[clinic start generated code]*/ - PyDoc_STRVAR(builtin_oct__doc__, "oct($module, number, /)\n" "--\n" @@ -2066,23 +471,6 @@ #define BUILTIN_OCT_METHODDEF \ {"oct", (PyCFunction)builtin_oct, METH_O, builtin_oct__doc__}, -static PyObject * -builtin_oct(PyModuleDef *module, PyObject *number) -/*[clinic end generated code: output=b99234d1d70a6673 input=a3a372b521b3dd13]*/ -{ - return PyNumber_ToBase(number, 8); -} - - -/*[clinic input] -ord as builtin_ord - - c: 'O' - / - -Return the Unicode code point for a one-character string. -[clinic start generated code]*/ - PyDoc_STRVAR(builtin_ord__doc__, "ord($module, c, /)\n" "--\n" @@ -2092,66 +480,6 @@ #define BUILTIN_ORD_METHODDEF \ {"ord", (PyCFunction)builtin_ord, METH_O, builtin_ord__doc__}, -static PyObject * -builtin_ord(PyModuleDef *module, PyObject *c) -/*[clinic end generated code: output=a8466d23bd76db3f input=762355f87451efa3]*/ -{ - long ord; - Py_ssize_t size; - - if (PyBytes_Check(c)) { - size = PyBytes_GET_SIZE(c); - if (size == 1) { - ord = (long)((unsigned char)*PyBytes_AS_STRING(c)); - return PyLong_FromLong(ord); - } - } - else if (PyUnicode_Check(c)) { - if (PyUnicode_READY(c) == -1) - return NULL; - size = PyUnicode_GET_LENGTH(c); - if (size == 1) { - ord = (long)PyUnicode_READ_CHAR(c, 0); - return PyLong_FromLong(ord); - } - } - else if (PyByteArray_Check(c)) { - /* XXX Hopefully this is temporary */ - size = PyByteArray_GET_SIZE(c); - if (size == 1) { - ord = (long)((unsigned char)*PyByteArray_AS_STRING(c)); - return PyLong_FromLong(ord); - } - } - else { - PyErr_Format(PyExc_TypeError, - "ord() expected string of length 1, but " \ - "%.200s found", c->ob_type->tp_name); - return NULL; - } - - PyErr_Format(PyExc_TypeError, - "ord() expected a character, " - "but string of length %zd found", - size); - return NULL; -} - - -/*[clinic input] -pow as builtin_pow - - x: 'O' - y: 'O' - z: 'O' = None - / - -Equivalent to x**y (with two arguments) or x**y % z (with three arguments) - -Some types, such as ints, are able to use a more efficient algorithm when -invoked using the three argument form. -[clinic start generated code]*/ - PyDoc_STRVAR(builtin_pow__doc__, "pow($module, x, y, z=None, /)\n" "--\n" @@ -2185,125 +513,6 @@ return return_value; } -static PyObject * -builtin_pow_impl(PyModuleDef *module, PyObject *x, PyObject *y, PyObject *z) -/*[clinic end generated code: output=d0cdf314311dedba input=561a942d5f5c1899]*/ -{ - return PyNumber_Power(x, y, z); -} - - -/* AC: cannot convert yet, waiting for *args support */ -static PyObject * -builtin_print(PyObject *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"sep", "end", "file", "flush", 0}; - static PyObject *dummy_args; - PyObject *sep = NULL, *end = NULL, *file = NULL, *flush = NULL; - int i, err; - - if (dummy_args == NULL && !(dummy_args = PyTuple_New(0))) - return NULL; - if (!PyArg_ParseTupleAndKeywords(dummy_args, kwds, "|OOOO:print", - kwlist, &sep, &end, &file, &flush)) - return NULL; - if (file == NULL || file == Py_None) { - file = _PySys_GetObjectId(&PyId_stdout); - if (file == NULL) { - PyErr_SetString(PyExc_RuntimeError, "lost sys.stdout"); - return NULL; - } - - /* sys.stdout may be None when FILE* stdout isn't connected */ - if (file == Py_None) - Py_RETURN_NONE; - } - - if (sep == Py_None) { - sep = NULL; - } - else if (sep && !PyUnicode_Check(sep)) { - PyErr_Format(PyExc_TypeError, - "sep must be None or a string, not %.200s", - sep->ob_type->tp_name); - return NULL; - } - if (end == Py_None) { - end = NULL; - } - else if (end && !PyUnicode_Check(end)) { - PyErr_Format(PyExc_TypeError, - "end must be None or a string, not %.200s", - end->ob_type->tp_name); - return NULL; - } - - for (i = 0; i < PyTuple_Size(args); i++) { - if (i > 0) { - if (sep == NULL) - err = PyFile_WriteString(" ", file); - else - err = PyFile_WriteObject(sep, file, - Py_PRINT_RAW); - if (err) - return NULL; - } - err = PyFile_WriteObject(PyTuple_GetItem(args, i), file, - Py_PRINT_RAW); - if (err) - return NULL; - } - - if (end == NULL) - err = PyFile_WriteString("\n", file); - else - err = PyFile_WriteObject(end, file, Py_PRINT_RAW); - if (err) - return NULL; - - if (flush != NULL) { - PyObject *tmp; - int do_flush = PyObject_IsTrue(flush); - if (do_flush == -1) - return NULL; - else if (do_flush) { - tmp = _PyObject_CallMethodId(file, &PyId_flush, ""); - if (tmp == NULL) - return NULL; - else - Py_DECREF(tmp); - } - } - - Py_RETURN_NONE; -} - -PyDoc_STRVAR(print_doc, -"print(value, ..., sep=' ', end='\\n', file=sys.stdout, flush=False)\n\ -\n\ -Prints the values to a stream, or to sys.stdout by default.\n\ -Optional keyword arguments:\n\ -file: a file-like object (stream); defaults to the current sys.stdout.\n\ -sep: string inserted between values, default a space.\n\ -end: string appended after the last value, default a newline.\n\ -flush: whether to forcibly flush the stream."); - - -/*[clinic input] -input as builtin_input - - prompt: object(c_default="NULL") = None - / - -Read a string from standard input. The trailing newline is stripped. - -The prompt string, if given, is printed to standard output without a -trailing newline before reading input. - -If the user hits EOF (*nix: Ctrl-D, Windows: Ctrl-Z+Return), raise EOFError. -On *nix systems, readline is used if available. -[clinic start generated code]*/ - PyDoc_STRVAR(builtin_input__doc__, "input($module, prompt=None, /)\n" "--\n" @@ -2338,191 +547,6 @@ return return_value; } -static PyObject * -builtin_input_impl(PyModuleDef *module, PyObject *prompt) -/*[clinic end generated code: output=69323bf5695f7c9c input=5e8bb70c2908fe3c]*/ -{ - PyObject *fin = _PySys_GetObjectId(&PyId_stdin); - PyObject *fout = _PySys_GetObjectId(&PyId_stdout); - PyObject *ferr = _PySys_GetObjectId(&PyId_stderr); - PyObject *tmp; - long fd; - int tty; - - /* Check that stdin/out/err are intact */ - if (fin == NULL || fin == Py_None) { - PyErr_SetString(PyExc_RuntimeError, - "input(): lost sys.stdin"); - return NULL; - } - if (fout == NULL || fout == Py_None) { - PyErr_SetString(PyExc_RuntimeError, - "input(): lost sys.stdout"); - return NULL; - } - if (ferr == NULL || ferr == Py_None) { - PyErr_SetString(PyExc_RuntimeError, - "input(): lost sys.stderr"); - return NULL; - } - - /* First of all, flush stderr */ - tmp = _PyObject_CallMethodId(ferr, &PyId_flush, ""); - if (tmp == NULL) - PyErr_Clear(); - else - Py_DECREF(tmp); - - /* We should only use (GNU) readline if Python's sys.stdin and - sys.stdout are the same as C's stdin and stdout, because we - need to pass it those. */ - tmp = _PyObject_CallMethodId(fin, &PyId_fileno, ""); - if (tmp == NULL) { - PyErr_Clear(); - tty = 0; - } - else { - fd = PyLong_AsLong(tmp); - Py_DECREF(tmp); - if (fd < 0 && PyErr_Occurred()) - return NULL; - tty = fd == fileno(stdin) && isatty(fd); - } - if (tty) { - tmp = _PyObject_CallMethodId(fout, &PyId_fileno, ""); - if (tmp == NULL) - PyErr_Clear(); - else { - fd = PyLong_AsLong(tmp); - Py_DECREF(tmp); - if (fd < 0 && PyErr_Occurred()) - return NULL; - tty = fd == fileno(stdout) && isatty(fd); - } - } - - /* If we're interactive, use (GNU) readline */ - if (tty) { - PyObject *po = NULL; - char *promptstr; - char *s = NULL; - PyObject *stdin_encoding = NULL, *stdin_errors = NULL; - PyObject *stdout_encoding = NULL, *stdout_errors = NULL; - char *stdin_encoding_str, *stdin_errors_str; - PyObject *result; - size_t len; - - stdin_encoding = _PyObject_GetAttrId(fin, &PyId_encoding); - stdin_errors = _PyObject_GetAttrId(fin, &PyId_errors); - if (!stdin_encoding || !stdin_errors) - /* stdin is a text stream, so it must have an - encoding. */ - goto _readline_errors; - stdin_encoding_str = _PyUnicode_AsString(stdin_encoding); - stdin_errors_str = _PyUnicode_AsString(stdin_errors); - if (!stdin_encoding_str || !stdin_errors_str) - goto _readline_errors; - tmp = _PyObject_CallMethodId(fout, &PyId_flush, ""); - if (tmp == NULL) - PyErr_Clear(); - else - Py_DECREF(tmp); - if (prompt != NULL) { - /* We have a prompt, encode it as stdout would */ - char *stdout_encoding_str, *stdout_errors_str; - PyObject *stringpo; - stdout_encoding = _PyObject_GetAttrId(fout, &PyId_encoding); - stdout_errors = _PyObject_GetAttrId(fout, &PyId_errors); - if (!stdout_encoding || !stdout_errors) - goto _readline_errors; - stdout_encoding_str = _PyUnicode_AsString(stdout_encoding); - stdout_errors_str = _PyUnicode_AsString(stdout_errors); - if (!stdout_encoding_str || !stdout_errors_str) - goto _readline_errors; - stringpo = PyObject_Str(prompt); - if (stringpo == NULL) - goto _readline_errors; - po = PyUnicode_AsEncodedString(stringpo, - stdout_encoding_str, stdout_errors_str); - Py_CLEAR(stdout_encoding); - Py_CLEAR(stdout_errors); - Py_CLEAR(stringpo); - if (po == NULL) - goto _readline_errors; - promptstr = PyBytes_AsString(po); - if (promptstr == NULL) - goto _readline_errors; - } - else { - po = NULL; - promptstr = ""; - } - s = PyOS_Readline(stdin, stdout, promptstr); - if (s == NULL) { - PyErr_CheckSignals(); - if (!PyErr_Occurred()) - PyErr_SetNone(PyExc_KeyboardInterrupt); - goto _readline_errors; - } - - len = strlen(s); - if (len == 0) { - PyErr_SetNone(PyExc_EOFError); - result = NULL; - } - else { - if (len > PY_SSIZE_T_MAX) { - PyErr_SetString(PyExc_OverflowError, - "input: input too long"); - result = NULL; - } - else { - len--; /* strip trailing '\n' */ - if (len != 0 && s[len-1] == '\r') - len--; /* strip trailing '\r' */ - result = PyUnicode_Decode(s, len, stdin_encoding_str, - stdin_errors_str); - } - } - Py_DECREF(stdin_encoding); - Py_DECREF(stdin_errors); - Py_XDECREF(po); - PyMem_FREE(s); - return result; - _readline_errors: - Py_XDECREF(stdin_encoding); - Py_XDECREF(stdout_encoding); - Py_XDECREF(stdin_errors); - Py_XDECREF(stdout_errors); - Py_XDECREF(po); - return NULL; - } - - /* Fallback if we're not interactive */ - if (prompt != NULL) { - if (PyFile_WriteObject(prompt, fout, Py_PRINT_RAW) != 0) - return NULL; - } - tmp = _PyObject_CallMethodId(fout, &PyId_flush, ""); - if (tmp == NULL) - PyErr_Clear(); - else - Py_DECREF(tmp); - return PyFile_GetLine(fin, -1); -} - - -/*[clinic input] -repr as builtin_repr - - obj: 'O' - / - -Return the canonical string representation of the object. - -For many object types, including most builtins, eval(repr(obj)) == obj. -[clinic start generated code]*/ - PyDoc_STRVAR(builtin_repr__doc__, "repr($module, obj, /)\n" "--\n" @@ -2534,176 +558,6 @@ #define BUILTIN_REPR_METHODDEF \ {"repr", (PyCFunction)builtin_repr, METH_O, builtin_repr__doc__}, -static PyObject * -builtin_repr(PyModuleDef *module, PyObject *obj) -/*[clinic end generated code: output=988980120f39e2fa input=a2bca0f38a5a924d]*/ -{ - return PyObject_Repr(obj); -} - - -/* AC: cannot convert yet, as needs PEP 457 group support in inspect - * or a semantic change to accept None for "ndigits" - */ -static PyObject * -builtin_round(PyObject *self, PyObject *args, PyObject *kwds) -{ - PyObject *ndigits = NULL; - static char *kwlist[] = {"number", "ndigits", 0}; - PyObject *number, *round, *result; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O:round", - kwlist, &number, &ndigits)) - return NULL; - - if (Py_TYPE(number)->tp_dict == NULL) { - if (PyType_Ready(Py_TYPE(number)) < 0) - return NULL; - } - - round = _PyObject_LookupSpecial(number, &PyId___round__); - if (round == NULL) { - if (!PyErr_Occurred()) - PyErr_Format(PyExc_TypeError, - "type %.100s doesn't define __round__ method", - Py_TYPE(number)->tp_name); - return NULL; - } - - if (ndigits == NULL) - result = PyObject_CallFunctionObjArgs(round, NULL); - else - result = PyObject_CallFunctionObjArgs(round, ndigits, NULL); - Py_DECREF(round); - return result; -} - -PyDoc_STRVAR(round_doc, -"round(number[, ndigits]) -> number\n\ -\n\ -Round a number to a given precision in decimal digits (default 0 digits).\n\ -This returns an int when called with one argument, otherwise the\n\ -same type as the number. ndigits may be negative."); - - -/*AC: we need to keep the kwds dict intact to easily call into the - * list.sort method, which isn't currently supported in AC. So we just use - * the initially generated signature with a custom implementation. - */ -/* [disabled clinic input] -sorted as builtin_sorted - - iterable as seq: 'O' - key as keyfunc: 'O' = None - reverse: 'O' = False - -Return a new list containing all items from the iterable in ascending order. - -A custom key function can be supplied to customise the sort order, and the -reverse flag can be set to request the result in descending order. -[end disabled clinic input]*/ - -PyDoc_STRVAR(builtin_sorted__doc__, -"sorted($module, iterable, key=None, reverse=False)\n" -"--\n" -"\n" -"Return a new list containing all items from the iterable in ascending order.\n" -"\n" -"A custom key function can be supplied to customise the sort order, and the\n" -"reverse flag can be set to request the result in descending order."); - -#define BUILTIN_SORTED_METHODDEF \ - {"sorted", (PyCFunction)builtin_sorted, METH_VARARGS|METH_KEYWORDS, builtin_sorted__doc__}, - -static PyObject * -builtin_sorted(PyObject *self, PyObject *args, PyObject *kwds) -{ - PyObject *newlist, *v, *seq, *keyfunc=NULL, *newargs; - PyObject *callable; - static char *kwlist[] = {"iterable", "key", "reverse", 0}; - int reverse; - - /* args 1-3 should match listsort in Objects/listobject.c */ - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|Oi:sorted", - kwlist, &seq, &keyfunc, &reverse)) - return NULL; - - newlist = PySequence_List(seq); - if (newlist == NULL) - return NULL; - - callable = _PyObject_GetAttrId(newlist, &PyId_sort); - if (callable == NULL) { - Py_DECREF(newlist); - return NULL; - } - - newargs = PyTuple_GetSlice(args, 1, 4); - if (newargs == NULL) { - Py_DECREF(newlist); - Py_DECREF(callable); - return NULL; - } - - v = PyObject_Call(callable, newargs, kwds); - Py_DECREF(newargs); - Py_DECREF(callable); - if (v == NULL) { - Py_DECREF(newlist); - return NULL; - } - Py_DECREF(v); - return newlist; -} - - -/* AC: cannot convert yet, as needs PEP 457 group support in inspect */ -static PyObject * -builtin_vars(PyObject *self, PyObject *args) -{ - PyObject *v = NULL; - PyObject *d; - - if (!PyArg_UnpackTuple(args, "vars", 0, 1, &v)) - return NULL; - if (v == NULL) { - d = PyEval_GetLocals(); - if (d == NULL) - return NULL; - Py_INCREF(d); - } - else { - d = _PyObject_GetAttrId(v, &PyId___dict__); - if (d == NULL) { - PyErr_SetString(PyExc_TypeError, - "vars() argument must have __dict__ attribute"); - return NULL; - } - } - return d; -} - -PyDoc_STRVAR(vars_doc, -"vars([object]) -> dictionary\n\ -\n\ -Without arguments, equivalent to locals().\n\ -With an argument, equivalent to object.__dict__."); - - -/*[clinic input] -sum as builtin_sum - - iterable: 'O' - start: object(c_default="NULL") = 0 - / - -Return the sum of a 'start' value (default: 0) plus an iterable of numbers - -When the iterable is empty, return the start value. -This function is intended specifically for use with numeric values and may -reject non-numeric types. -[clinic start generated code]*/ - PyDoc_STRVAR(builtin_sum__doc__, "sum($module, iterable, start=0, /)\n" "--\n" @@ -2737,183 +591,6 @@ return return_value; } -static PyObject * -builtin_sum_impl(PyModuleDef *module, PyObject *iterable, PyObject *start) -/*[clinic end generated code: output=b42652a0d5f64f6b input=90ae7a242cfcf025]*/ -{ - PyObject *result = start; - PyObject *temp, *item, *iter; - - iter = PyObject_GetIter(iterable); - if (iter == NULL) - return NULL; - - if (result == NULL) { - result = PyLong_FromLong(0); - if (result == NULL) { - Py_DECREF(iter); - return NULL; - } - } else { - /* reject string values for 'start' parameter */ - if (PyUnicode_Check(result)) { - PyErr_SetString(PyExc_TypeError, - "sum() can't sum strings [use ''.join(seq) instead]"); - Py_DECREF(iter); - return NULL; - } - if (PyBytes_Check(result)) { - PyErr_SetString(PyExc_TypeError, - "sum() can't sum bytes [use b''.join(seq) instead]"); - Py_DECREF(iter); - return NULL; - } - if (PyByteArray_Check(result)) { - PyErr_SetString(PyExc_TypeError, - "sum() can't sum bytearray [use b''.join(seq) instead]"); - Py_DECREF(iter); - return NULL; - } - Py_INCREF(result); - } - -#ifndef SLOW_SUM - /* Fast addition by keeping temporary sums in C instead of new Python objects. - Assumes all inputs are the same type. If the assumption fails, default - to the more general routine. - */ - if (PyLong_CheckExact(result)) { - int overflow; - long i_result = PyLong_AsLongAndOverflow(result, &overflow); - /* If this already overflowed, don't even enter the loop. */ - if (overflow == 0) { - Py_DECREF(result); - result = NULL; - } - while(result == NULL) { - item = PyIter_Next(iter); - if (item == NULL) { - Py_DECREF(iter); - if (PyErr_Occurred()) - return NULL; - return PyLong_FromLong(i_result); - } - if (PyLong_CheckExact(item)) { - long b = PyLong_AsLongAndOverflow(item, &overflow); - long x = i_result + b; - if (overflow == 0 && ((x^i_result) >= 0 || (x^b) >= 0)) { - i_result = x; - Py_DECREF(item); - continue; - } - } - /* Either overflowed or is not an int. Restore real objects and process normally */ - result = PyLong_FromLong(i_result); - if (result == NULL) { - Py_DECREF(item); - Py_DECREF(iter); - return NULL; - } - temp = PyNumber_Add(result, item); - Py_DECREF(result); - Py_DECREF(item); - result = temp; - if (result == NULL) { - Py_DECREF(iter); - return NULL; - } - } - } - - if (PyFloat_CheckExact(result)) { - double f_result = PyFloat_AS_DOUBLE(result); - Py_DECREF(result); - result = NULL; - while(result == NULL) { - item = PyIter_Next(iter); - if (item == NULL) { - Py_DECREF(iter); - if (PyErr_Occurred()) - return NULL; - return PyFloat_FromDouble(f_result); - } - if (PyFloat_CheckExact(item)) { - PyFPE_START_PROTECT("add", Py_DECREF(item); Py_DECREF(iter); return 0) - f_result += PyFloat_AS_DOUBLE(item); - PyFPE_END_PROTECT(f_result) - Py_DECREF(item); - continue; - } - if (PyLong_CheckExact(item)) { - long value; - int overflow; - value = PyLong_AsLongAndOverflow(item, &overflow); - if (!overflow) { - PyFPE_START_PROTECT("add", Py_DECREF(item); Py_DECREF(iter); return 0) - f_result += (double)value; - PyFPE_END_PROTECT(f_result) - Py_DECREF(item); - continue; - } - } - result = PyFloat_FromDouble(f_result); - temp = PyNumber_Add(result, item); - Py_DECREF(result); - Py_DECREF(item); - result = temp; - if (result == NULL) { - Py_DECREF(iter); - return NULL; - } - } - } -#endif - - for(;;) { - item = PyIter_Next(iter); - if (item == NULL) { - /* error, or end-of-sequence */ - if (PyErr_Occurred()) { - Py_DECREF(result); - result = NULL; - } - break; - } - /* It's tempting to use PyNumber_InPlaceAdd instead of - PyNumber_Add here, to avoid quadratic running time - when doing 'sum(list_of_lists, [])'. However, this - would produce a change in behaviour: a snippet like - - empty = [] - sum([[x] for x in range(10)], empty) - - would change the value of empty. */ - temp = PyNumber_Add(result, item); - Py_DECREF(result); - Py_DECREF(item); - result = temp; - if (result == NULL) - break; - } - Py_DECREF(iter); - return result; -} - - -/*[clinic input] -isinstance as builtin_isinstance - - obj: 'O' - class_or_tuple: 'O' - / - -Return whether an object is an instance of a class or of a subclass thereof. - -A tuple, as in ``isinstance(x, (A, B, ...))``, may be given as the target to -check against. This is equivalent to ``isinstance(x, A) or isinstance(x, B) -or ...`` etc. -[clinic start generated code]*/ - PyDoc_STRVAR(builtin_isinstance__doc__, "isinstance($module, obj, class_or_tuple, /)\n" "--\n" @@ -2947,33 +624,6 @@ return return_value; } -static PyObject * -builtin_isinstance_impl(PyModuleDef *module, PyObject *obj, PyObject *class_or_tuple) -/*[clinic end generated code: output=847df57fef8ddea7 input=cf9eb0ad6bb9bad6]*/ -{ - int retval; - - retval = PyObject_IsInstance(obj, class_or_tuple); - if (retval < 0) - return NULL; - return PyBool_FromLong(retval); -} - - -/*[clinic input] -issubclass as builtin_issubclass - - cls: 'O' - class_or_tuple: 'O' - / - -Return whether 'cls' is a derived from another class or is the same class. - -A tuple, as in ``issubclass(x, (A, B, ...))``, may be given as the target to -check against. This is equivalent to ``issubclass(x, A) or issubclass(x, B) -or ...`` etc. -[clinic start generated code]*/ - PyDoc_STRVAR(builtin_issubclass__doc__, "issubclass($module, cls, class_or_tuple, /)\n" "--\n" @@ -3006,344 +656,4 @@ exit: return return_value; } - -static PyObject * -builtin_issubclass_impl(PyModuleDef *module, PyObject *cls, PyObject *class_or_tuple) -/*[clinic end generated code: output=a0f8c03692e35474 input=923d03fa41fc352a]*/ -{ - int retval; - - retval = PyObject_IsSubclass(cls, class_or_tuple); - if (retval < 0) - return NULL; - return PyBool_FromLong(retval); -} - - -typedef struct { - PyObject_HEAD - Py_ssize_t tuplesize; - PyObject *ittuple; /* tuple of iterators */ - PyObject *result; -} zipobject; - -static PyObject * -zip_new(PyTypeObject *type, PyObject *args, PyObject *kwds) -{ - zipobject *lz; - Py_ssize_t i; - PyObject *ittuple; /* tuple of iterators */ - PyObject *result; - Py_ssize_t tuplesize = PySequence_Length(args); - - if (type == &PyZip_Type && !_PyArg_NoKeywords("zip()", kwds)) - return NULL; - - /* args must be a tuple */ - assert(PyTuple_Check(args)); - - /* obtain iterators */ - ittuple = PyTuple_New(tuplesize); - if (ittuple == NULL) - return NULL; - for (i=0; i < tuplesize; ++i) { - PyObject *item = PyTuple_GET_ITEM(args, i); - PyObject *it = PyObject_GetIter(item); - if (it == NULL) { - if (PyErr_ExceptionMatches(PyExc_TypeError)) - PyErr_Format(PyExc_TypeError, - "zip argument #%zd must support iteration", - i+1); - Py_DECREF(ittuple); - return NULL; - } - PyTuple_SET_ITEM(ittuple, i, it); - } - - /* create a result holder */ - result = PyTuple_New(tuplesize); - if (result == NULL) { - Py_DECREF(ittuple); - return NULL; - } - for (i=0 ; i < tuplesize ; i++) { - Py_INCREF(Py_None); - PyTuple_SET_ITEM(result, i, Py_None); - } - - /* create zipobject structure */ - lz = (zipobject *)type->tp_alloc(type, 0); - if (lz == NULL) { - Py_DECREF(ittuple); - Py_DECREF(result); - return NULL; - } - lz->ittuple = ittuple; - lz->tuplesize = tuplesize; - lz->result = result; - - return (PyObject *)lz; -} - -static void -zip_dealloc(zipobject *lz) -{ - PyObject_GC_UnTrack(lz); - Py_XDECREF(lz->ittuple); - Py_XDECREF(lz->result); - Py_TYPE(lz)->tp_free(lz); -} - -static int -zip_traverse(zipobject *lz, visitproc visit, void *arg) -{ - Py_VISIT(lz->ittuple); - Py_VISIT(lz->result); - return 0; -} - -static PyObject * -zip_next(zipobject *lz) -{ - Py_ssize_t i; - Py_ssize_t tuplesize = lz->tuplesize; - PyObject *result = lz->result; - PyObject *it; - PyObject *item; - PyObject *olditem; - - if (tuplesize == 0) - return NULL; - if (Py_REFCNT(result) == 1) { - Py_INCREF(result); - for (i=0 ; i < tuplesize ; i++) { - it = PyTuple_GET_ITEM(lz->ittuple, i); - item = (*Py_TYPE(it)->tp_iternext)(it); - if (item == NULL) { - Py_DECREF(result); - return NULL; - } - olditem = PyTuple_GET_ITEM(result, i); - PyTuple_SET_ITEM(result, i, item); - Py_DECREF(olditem); - } - } else { - result = PyTuple_New(tuplesize); - if (result == NULL) - return NULL; - for (i=0 ; i < tuplesize ; i++) { - it = PyTuple_GET_ITEM(lz->ittuple, i); - item = (*Py_TYPE(it)->tp_iternext)(it); - if (item == NULL) { - Py_DECREF(result); - return NULL; - } - PyTuple_SET_ITEM(result, i, item); - } - } - 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\ -Return a zip object whose .__next__() method returns a tuple where\n\ -the i-th element comes from the i-th iterable argument. The .__next__()\n\ -method continues until the shortest iterable in the argument sequence\n\ -is exhausted and then it raises StopIteration."); - -PyTypeObject PyZip_Type = { - PyVarObject_HEAD_INIT(&PyType_Type, 0) - "zip", /* tp_name */ - sizeof(zipobject), /* tp_basicsize */ - 0, /* tp_itemsize */ - /* methods */ - (destructor)zip_dealloc, /* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_reserved */ - 0, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - PyObject_GenericGetAttr, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | - Py_TPFLAGS_BASETYPE, /* tp_flags */ - zip_doc, /* tp_doc */ - (traverseproc)zip_traverse, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - PyObject_SelfIter, /* tp_iter */ - (iternextfunc)zip_next, /* tp_iternext */ - zip_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 */ - PyType_GenericAlloc, /* tp_alloc */ - zip_new, /* tp_new */ - PyObject_GC_Del, /* tp_free */ -}; - - -static PyMethodDef builtin_methods[] = { - {"__build_class__", (PyCFunction)builtin___build_class__, - METH_VARARGS | METH_KEYWORDS, build_class_doc}, - {"__import__", (PyCFunction)builtin___import__, METH_VARARGS | METH_KEYWORDS, import_doc}, - BUILTIN_ABS_METHODDEF - BUILTIN_ALL_METHODDEF - BUILTIN_ANY_METHODDEF - BUILTIN_ASCII_METHODDEF - BUILTIN_BIN_METHODDEF - BUILTIN_CALLABLE_METHODDEF - BUILTIN_CHR_METHODDEF - BUILTIN_COMPILE_METHODDEF - BUILTIN_DELATTR_METHODDEF - {"dir", builtin_dir, METH_VARARGS, dir_doc}, - BUILTIN_DIVMOD_METHODDEF - BUILTIN_EVAL_METHODDEF - BUILTIN_EXEC_METHODDEF - BUILTIN_FORMAT_METHODDEF - {"getattr", builtin_getattr, METH_VARARGS, getattr_doc}, - BUILTIN_GLOBALS_METHODDEF - BUILTIN_HASATTR_METHODDEF - BUILTIN_HASH_METHODDEF - BUILTIN_HEX_METHODDEF - BUILTIN_ID_METHODDEF - BUILTIN_INPUT_METHODDEF - BUILTIN_ISINSTANCE_METHODDEF - BUILTIN_ISSUBCLASS_METHODDEF - {"iter", builtin_iter, METH_VARARGS, iter_doc}, - BUILTIN_LEN_METHODDEF - BUILTIN_LOCALS_METHODDEF - {"max", (PyCFunction)builtin_max, METH_VARARGS | METH_KEYWORDS, max_doc}, - {"min", (PyCFunction)builtin_min, METH_VARARGS | METH_KEYWORDS, min_doc}, - {"next", (PyCFunction)builtin_next, METH_VARARGS, next_doc}, - BUILTIN_OCT_METHODDEF - BUILTIN_ORD_METHODDEF - BUILTIN_POW_METHODDEF - {"print", (PyCFunction)builtin_print, METH_VARARGS | METH_KEYWORDS, print_doc}, - BUILTIN_REPR_METHODDEF - {"round", (PyCFunction)builtin_round, METH_VARARGS | METH_KEYWORDS, round_doc}, - BUILTIN_SETATTR_METHODDEF - BUILTIN_SORTED_METHODDEF - BUILTIN_SUM_METHODDEF - {"vars", builtin_vars, METH_VARARGS, vars_doc}, - {NULL, NULL}, -}; - -PyDoc_STRVAR(builtin_doc, -"Built-in functions, exceptions, and other objects.\n\ -\n\ -Noteworthy: None is the `nil' object; Ellipsis represents `...' in slices."); - -static struct PyModuleDef builtinsmodule = { - PyModuleDef_HEAD_INIT, - "builtins", - builtin_doc, - -1, /* multiple "initialization" just copies the module dict. */ - builtin_methods, - NULL, - NULL, - NULL, - NULL -}; - - -PyObject * -_PyBuiltin_Init(void) -{ - PyObject *mod, *dict, *debug; - - if (PyType_Ready(&PyFilter_Type) < 0 || - PyType_Ready(&PyMap_Type) < 0 || - PyType_Ready(&PyZip_Type) < 0) - return NULL; - - mod = PyModule_Create(&builtinsmodule); - if (mod == NULL) - return NULL; - dict = PyModule_GetDict(mod); - -#ifdef Py_TRACE_REFS - /* "builtins" exposes a number of statically allocated objects - * that, before this code was added in 2.3, never showed up in - * the list of "all objects" maintained by Py_TRACE_REFS. As a - * result, programs leaking references to None and False (etc) - * couldn't be diagnosed by examining sys.getobjects(0). - */ -#define ADD_TO_ALL(OBJECT) _Py_AddToAllObjects((PyObject *)(OBJECT), 0) -#else -#define ADD_TO_ALL(OBJECT) (void)0 -#endif - -#define SETBUILTIN(NAME, OBJECT) \ - if (PyDict_SetItemString(dict, NAME, (PyObject *)OBJECT) < 0) \ - return NULL; \ - ADD_TO_ALL(OBJECT) - - SETBUILTIN("None", Py_None); - SETBUILTIN("Ellipsis", Py_Ellipsis); - SETBUILTIN("NotImplemented", Py_NotImplemented); - SETBUILTIN("False", Py_False); - SETBUILTIN("True", Py_True); - SETBUILTIN("bool", &PyBool_Type); - SETBUILTIN("memoryview", &PyMemoryView_Type); - SETBUILTIN("bytearray", &PyByteArray_Type); - SETBUILTIN("bytes", &PyBytes_Type); - SETBUILTIN("classmethod", &PyClassMethod_Type); - SETBUILTIN("complex", &PyComplex_Type); - SETBUILTIN("dict", &PyDict_Type); - SETBUILTIN("enumerate", &PyEnum_Type); - SETBUILTIN("filter", &PyFilter_Type); - SETBUILTIN("float", &PyFloat_Type); - SETBUILTIN("frozenset", &PyFrozenSet_Type); - SETBUILTIN("property", &PyProperty_Type); - SETBUILTIN("int", &PyLong_Type); - SETBUILTIN("list", &PyList_Type); - SETBUILTIN("map", &PyMap_Type); - SETBUILTIN("object", &PyBaseObject_Type); - SETBUILTIN("range", &PyRange_Type); - SETBUILTIN("reversed", &PyReversed_Type); - SETBUILTIN("set", &PySet_Type); - SETBUILTIN("slice", &PySlice_Type); - SETBUILTIN("staticmethod", &PyStaticMethod_Type); - SETBUILTIN("str", &PyUnicode_Type); - SETBUILTIN("super", &PySuper_Type); - SETBUILTIN("tuple", &PyTuple_Type); - SETBUILTIN("type", &PyType_Type); - SETBUILTIN("zip", &PyZip_Type); - debug = PyBool_FromLong(Py_OptimizeFlag == 0); - if (PyDict_SetItemString(dict, "__debug__", debug) < 0) { - Py_XDECREF(debug); - return NULL; - } - Py_XDECREF(debug); - - return mod; -#undef ADD_TO_ALL -#undef SETBUILTIN -} +/*[clinic end generated code: output=2da46de189e48d26 input=a9049054013a1b77]*/ diff --git a/Python/import.c b/Python/import.c --- a/Python/import.c +++ b/Python/import.c @@ -32,10 +32,9 @@ static PyObject *initstr = NULL; /*[clinic input] -output preset file module _imp [clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=98c38221164579d5]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=9c332475d8686284]*/ #include "clinic/import.c.h" diff --git a/Tools/clinic/clinic.py b/Tools/clinic/clinic.py --- a/Tools/clinic/clinic.py +++ b/Tools/clinic/clinic.py @@ -1590,15 +1590,15 @@ d = self.get_destination_buffer self.destination_buffers = collections.OrderedDict(( - ('cpp_if', d('suppress')), + ('cpp_if', d('file')), ('docstring_prototype', d('suppress')), - ('docstring_definition', d('block')), - ('methoddef_define', d('block')), - ('impl_prototype', d('block')), + ('docstring_definition', d('file')), + ('methoddef_define', d('file')), + ('impl_prototype', d('file')), ('parser_prototype', d('suppress')), - ('parser_definition', d('block')), - ('cpp_endif', d('suppress')), - ('methoddef_ifndef', d('buffer', 1)), + ('parser_definition', d('file')), + ('cpp_endif', d('file')), + ('methoddef_ifndef', d('file', 1)), ('impl_definition', d('block')), )) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Apr 3 23:12:32 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Fri, 03 Apr 2015 21:12:32 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2323492=3A_Argument?= =?utf-8?q?_Clinic_now_generates_argument_parsing_code_with?= Message-ID: <20150403211232.15199.8975@psf.io> https://hg.python.org/cpython/rev/e10ad4d4d490 changeset: 95424:e10ad4d4d490 user: Serhiy Storchaka date: Sat Apr 04 00:12:11 2015 +0300 summary: Issue #23492: Argument Clinic now generates argument parsing code with PyArg_Parse instead of PyArg_ParseTuple if possible. files: Misc/NEWS | 14 +- Modules/clinic/_bz2module.c.h | 8 +- Modules/clinic/_codecsmodule.c.h | 8 +- Modules/clinic/_lzmamodule.c.h | 20 +- Modules/clinic/arraymodule.c.h | 20 +- Modules/clinic/binascii.c.h | 74 +++--- Modules/clinic/cmathmodule.c.h | 122 +++++----- Modules/clinic/posixmodule.c.h | 176 ++++++++-------- Modules/clinic/pwdmodule.c.h | 8 +- Modules/clinic/pyexpat.c.h | 20 +- Modules/clinic/spwdmodule.c.h | 8 +- Modules/clinic/zlibmodule.c.h | 8 +- Objects/clinic/bytearrayobject.c.h | 20 +- Objects/clinic/bytesobject.c.h | 20 +- Python/clinic/bltinmodule.c.h | 8 +- Python/clinic/import.c.h | 38 +- Tools/clinic/clinic.py | 52 +++- 17 files changed, 321 insertions(+), 303 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -63,7 +63,7 @@ Build ----- -- Issue #23501: Argumen Clinic now generates code into separate files by default. +- Issue #23501: Argument Clinic now generates code into separate files by default. Tests ----- @@ -71,6 +71,13 @@ Tools/Demos ----------- +- Issue #23492: Argument Clinic now generates argument parsing code with + PyArg_Parse instead of PyArg_ParseTuple if possible. + +- Issue #23500: Argument Clinic is now smarter about generating the "#ifndef" + (empty) definition of the methoddef macro: it's only generated once, even + if Argument Clinic processes the same symbol multiple times, and it's emitted + at the end of all processing rather than immediately after the first use. What's New in Python 3.5.0 alpha 3? @@ -270,11 +277,6 @@ Tools/Demos ----------- -- Issue #23500: Argument Clinic is now smarter about generating the "#ifndef" - (empty) definition of the methoddef macro: it's only generated once, even - if Argument Clinic processes the same symbol multiple times, and it's emitted - at the end of all processing rather than immediately after the first use. - - Issue #22826: The result of open() in Tools/freeze/bkfile.py is now better compatible with regular files (in particular it now supports the context management protocol). diff --git a/Modules/clinic/_bz2module.c.h b/Modules/clinic/_bz2module.c.h --- a/Modules/clinic/_bz2module.c.h +++ b/Modules/clinic/_bz2module.c.h @@ -14,18 +14,18 @@ "flush() method to finish the compression process."); #define _BZ2_BZ2COMPRESSOR_COMPRESS_METHODDEF \ - {"compress", (PyCFunction)_bz2_BZ2Compressor_compress, METH_VARARGS, _bz2_BZ2Compressor_compress__doc__}, + {"compress", (PyCFunction)_bz2_BZ2Compressor_compress, METH_O, _bz2_BZ2Compressor_compress__doc__}, static PyObject * _bz2_BZ2Compressor_compress_impl(BZ2Compressor *self, Py_buffer *data); static PyObject * -_bz2_BZ2Compressor_compress(BZ2Compressor *self, PyObject *args) +_bz2_BZ2Compressor_compress(BZ2Compressor *self, PyObject *arg) { PyObject *return_value = NULL; Py_buffer data = {NULL, NULL}; - if (!PyArg_ParseTuple(args, + if (!PyArg_Parse(arg, "y*:compress", &data)) goto exit; @@ -168,4 +168,4 @@ exit: return return_value; } -/*[clinic end generated code: output=8e65e3953430bc3d input=a9049054013a1b77]*/ +/*[clinic end generated code: output=3565d163a360af01 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_codecsmodule.c.h b/Modules/clinic/_codecsmodule.c.h --- a/Modules/clinic/_codecsmodule.c.h +++ b/Modules/clinic/_codecsmodule.c.h @@ -9,18 +9,18 @@ "Purge the named codec from the internal codec lookup cache"); #define _CODECS__FORGET_CODEC_METHODDEF \ - {"_forget_codec", (PyCFunction)_codecs__forget_codec, METH_VARARGS, _codecs__forget_codec__doc__}, + {"_forget_codec", (PyCFunction)_codecs__forget_codec, METH_O, _codecs__forget_codec__doc__}, static PyObject * _codecs__forget_codec_impl(PyModuleDef *module, const char *encoding); static PyObject * -_codecs__forget_codec(PyModuleDef *module, PyObject *args) +_codecs__forget_codec(PyModuleDef *module, PyObject *arg) { PyObject *return_value = NULL; const char *encoding; - if (!PyArg_ParseTuple(args, + if (!PyArg_Parse(arg, "s:_forget_codec", &encoding)) goto exit; @@ -29,4 +29,4 @@ exit: return return_value; } -/*[clinic end generated code: output=cdea83e21d76a900 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=fc5ce4d3166f7d96 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_lzmamodule.c.h b/Modules/clinic/_lzmamodule.c.h --- a/Modules/clinic/_lzmamodule.c.h +++ b/Modules/clinic/_lzmamodule.c.h @@ -14,18 +14,18 @@ "flush() method to finish the compression process."); #define _LZMA_LZMACOMPRESSOR_COMPRESS_METHODDEF \ - {"compress", (PyCFunction)_lzma_LZMACompressor_compress, METH_VARARGS, _lzma_LZMACompressor_compress__doc__}, + {"compress", (PyCFunction)_lzma_LZMACompressor_compress, METH_O, _lzma_LZMACompressor_compress__doc__}, static PyObject * _lzma_LZMACompressor_compress_impl(Compressor *self, Py_buffer *data); static PyObject * -_lzma_LZMACompressor_compress(Compressor *self, PyObject *args) +_lzma_LZMACompressor_compress(Compressor *self, PyObject *arg) { PyObject *return_value = NULL; Py_buffer data = {NULL, NULL}; - if (!PyArg_ParseTuple(args, + if (!PyArg_Parse(arg, "y*:compress", &data)) goto exit; @@ -162,18 +162,18 @@ "Always returns True for CHECK_NONE and CHECK_CRC32."); #define _LZMA_IS_CHECK_SUPPORTED_METHODDEF \ - {"is_check_supported", (PyCFunction)_lzma_is_check_supported, METH_VARARGS, _lzma_is_check_supported__doc__}, + {"is_check_supported", (PyCFunction)_lzma_is_check_supported, METH_O, _lzma_is_check_supported__doc__}, static PyObject * _lzma_is_check_supported_impl(PyModuleDef *module, int check_id); static PyObject * -_lzma_is_check_supported(PyModuleDef *module, PyObject *args) +_lzma_is_check_supported(PyModuleDef *module, PyObject *arg) { PyObject *return_value = NULL; int check_id; - if (!PyArg_ParseTuple(args, + if (!PyArg_Parse(arg, "i:is_check_supported", &check_id)) goto exit; @@ -192,18 +192,18 @@ "The result does not include the filter ID itself, only the options."); #define _LZMA__ENCODE_FILTER_PROPERTIES_METHODDEF \ - {"_encode_filter_properties", (PyCFunction)_lzma__encode_filter_properties, METH_VARARGS, _lzma__encode_filter_properties__doc__}, + {"_encode_filter_properties", (PyCFunction)_lzma__encode_filter_properties, METH_O, _lzma__encode_filter_properties__doc__}, static PyObject * _lzma__encode_filter_properties_impl(PyModuleDef *module, lzma_filter filter); static PyObject * -_lzma__encode_filter_properties(PyModuleDef *module, PyObject *args) +_lzma__encode_filter_properties(PyModuleDef *module, PyObject *arg) { PyObject *return_value = NULL; lzma_filter filter = {LZMA_VLI_UNKNOWN, NULL}; - if (!PyArg_ParseTuple(args, + if (!PyArg_Parse(arg, "O&:_encode_filter_properties", lzma_filter_converter, &filter)) goto exit; @@ -251,4 +251,4 @@ return return_value; } -/*[clinic end generated code: output=dc42b73890609369 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=ea7f2b2c4019fe86 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/arraymodule.c.h b/Modules/clinic/arraymodule.c.h --- a/Modules/clinic/arraymodule.c.h +++ b/Modules/clinic/arraymodule.c.h @@ -267,18 +267,18 @@ "This method is deprecated. Use frombytes instead."); #define ARRAY_ARRAY_FROMSTRING_METHODDEF \ - {"fromstring", (PyCFunction)array_array_fromstring, METH_VARARGS, array_array_fromstring__doc__}, + {"fromstring", (PyCFunction)array_array_fromstring, METH_O, array_array_fromstring__doc__}, static PyObject * array_array_fromstring_impl(arrayobject *self, Py_buffer *buffer); static PyObject * -array_array_fromstring(arrayobject *self, PyObject *args) +array_array_fromstring(arrayobject *self, PyObject *arg) { PyObject *return_value = NULL; Py_buffer buffer = {NULL, NULL}; - if (!PyArg_ParseTuple(args, + if (!PyArg_Parse(arg, "s*:fromstring", &buffer)) goto exit; @@ -299,18 +299,18 @@ "Appends items from the string, interpreting it as an array of machine values, as if it had been read from a file using the fromfile() method)."); #define ARRAY_ARRAY_FROMBYTES_METHODDEF \ - {"frombytes", (PyCFunction)array_array_frombytes, METH_VARARGS, array_array_frombytes__doc__}, + {"frombytes", (PyCFunction)array_array_frombytes, METH_O, array_array_frombytes__doc__}, static PyObject * array_array_frombytes_impl(arrayobject *self, Py_buffer *buffer); static PyObject * -array_array_frombytes(arrayobject *self, PyObject *args) +array_array_frombytes(arrayobject *self, PyObject *arg) { PyObject *return_value = NULL; Py_buffer buffer = {NULL, NULL}; - if (!PyArg_ParseTuple(args, + if (!PyArg_Parse(arg, "y*:frombytes", &buffer)) goto exit; @@ -373,19 +373,19 @@ "some other type."); #define ARRAY_ARRAY_FROMUNICODE_METHODDEF \ - {"fromunicode", (PyCFunction)array_array_fromunicode, METH_VARARGS, array_array_fromunicode__doc__}, + {"fromunicode", (PyCFunction)array_array_fromunicode, METH_O, array_array_fromunicode__doc__}, static PyObject * array_array_fromunicode_impl(arrayobject *self, Py_UNICODE *ustr, Py_ssize_clean_t ustr_length); static PyObject * -array_array_fromunicode(arrayobject *self, PyObject *args) +array_array_fromunicode(arrayobject *self, PyObject *arg) { PyObject *return_value = NULL; Py_UNICODE *ustr; Py_ssize_clean_t ustr_length; - if (!PyArg_ParseTuple(args, + if (!PyArg_Parse(arg, "u#:fromunicode", &ustr, &ustr_length)) goto exit; @@ -502,4 +502,4 @@ #define ARRAY_ARRAYITERATOR___SETSTATE___METHODDEF \ {"__setstate__", (PyCFunction)array_arrayiterator___setstate__, METH_O, array_arrayiterator___setstate____doc__}, -/*[clinic end generated code: output=e1deb61c6a3bc8c8 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=a8fbe83c2026fa83 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/binascii.c.h b/Modules/clinic/binascii.c.h --- a/Modules/clinic/binascii.c.h +++ b/Modules/clinic/binascii.c.h @@ -9,18 +9,18 @@ "Decode a line of uuencoded data."); #define BINASCII_A2B_UU_METHODDEF \ - {"a2b_uu", (PyCFunction)binascii_a2b_uu, METH_VARARGS, binascii_a2b_uu__doc__}, + {"a2b_uu", (PyCFunction)binascii_a2b_uu, METH_O, binascii_a2b_uu__doc__}, static PyObject * binascii_a2b_uu_impl(PyModuleDef *module, Py_buffer *data); static PyObject * -binascii_a2b_uu(PyModuleDef *module, PyObject *args) +binascii_a2b_uu(PyModuleDef *module, PyObject *arg) { PyObject *return_value = NULL; Py_buffer data = {NULL, NULL}; - if (!PyArg_ParseTuple(args, + if (!PyArg_Parse(arg, "O&:a2b_uu", ascii_buffer_converter, &data)) goto exit; @@ -41,18 +41,18 @@ "Uuencode line of data."); #define BINASCII_B2A_UU_METHODDEF \ - {"b2a_uu", (PyCFunction)binascii_b2a_uu, METH_VARARGS, binascii_b2a_uu__doc__}, + {"b2a_uu", (PyCFunction)binascii_b2a_uu, METH_O, binascii_b2a_uu__doc__}, static PyObject * binascii_b2a_uu_impl(PyModuleDef *module, Py_buffer *data); static PyObject * -binascii_b2a_uu(PyModuleDef *module, PyObject *args) +binascii_b2a_uu(PyModuleDef *module, PyObject *arg) { PyObject *return_value = NULL; Py_buffer data = {NULL, NULL}; - if (!PyArg_ParseTuple(args, + if (!PyArg_Parse(arg, "y*:b2a_uu", &data)) goto exit; @@ -73,18 +73,18 @@ "Decode a line of base64 data."); #define BINASCII_A2B_BASE64_METHODDEF \ - {"a2b_base64", (PyCFunction)binascii_a2b_base64, METH_VARARGS, binascii_a2b_base64__doc__}, + {"a2b_base64", (PyCFunction)binascii_a2b_base64, METH_O, binascii_a2b_base64__doc__}, static PyObject * binascii_a2b_base64_impl(PyModuleDef *module, Py_buffer *data); static PyObject * -binascii_a2b_base64(PyModuleDef *module, PyObject *args) +binascii_a2b_base64(PyModuleDef *module, PyObject *arg) { PyObject *return_value = NULL; Py_buffer data = {NULL, NULL}; - if (!PyArg_ParseTuple(args, + if (!PyArg_Parse(arg, "O&:a2b_base64", ascii_buffer_converter, &data)) goto exit; @@ -105,18 +105,18 @@ "Base64-code line of data."); #define BINASCII_B2A_BASE64_METHODDEF \ - {"b2a_base64", (PyCFunction)binascii_b2a_base64, METH_VARARGS, binascii_b2a_base64__doc__}, + {"b2a_base64", (PyCFunction)binascii_b2a_base64, METH_O, binascii_b2a_base64__doc__}, static PyObject * binascii_b2a_base64_impl(PyModuleDef *module, Py_buffer *data); static PyObject * -binascii_b2a_base64(PyModuleDef *module, PyObject *args) +binascii_b2a_base64(PyModuleDef *module, PyObject *arg) { PyObject *return_value = NULL; Py_buffer data = {NULL, NULL}; - if (!PyArg_ParseTuple(args, + if (!PyArg_Parse(arg, "y*:b2a_base64", &data)) goto exit; @@ -137,18 +137,18 @@ "Decode .hqx coding."); #define BINASCII_A2B_HQX_METHODDEF \ - {"a2b_hqx", (PyCFunction)binascii_a2b_hqx, METH_VARARGS, binascii_a2b_hqx__doc__}, + {"a2b_hqx", (PyCFunction)binascii_a2b_hqx, METH_O, binascii_a2b_hqx__doc__}, static PyObject * binascii_a2b_hqx_impl(PyModuleDef *module, Py_buffer *data); static PyObject * -binascii_a2b_hqx(PyModuleDef *module, PyObject *args) +binascii_a2b_hqx(PyModuleDef *module, PyObject *arg) { PyObject *return_value = NULL; Py_buffer data = {NULL, NULL}; - if (!PyArg_ParseTuple(args, + if (!PyArg_Parse(arg, "O&:a2b_hqx", ascii_buffer_converter, &data)) goto exit; @@ -169,18 +169,18 @@ "Binhex RLE-code binary data."); #define BINASCII_RLECODE_HQX_METHODDEF \ - {"rlecode_hqx", (PyCFunction)binascii_rlecode_hqx, METH_VARARGS, binascii_rlecode_hqx__doc__}, + {"rlecode_hqx", (PyCFunction)binascii_rlecode_hqx, METH_O, binascii_rlecode_hqx__doc__}, static PyObject * binascii_rlecode_hqx_impl(PyModuleDef *module, Py_buffer *data); static PyObject * -binascii_rlecode_hqx(PyModuleDef *module, PyObject *args) +binascii_rlecode_hqx(PyModuleDef *module, PyObject *arg) { PyObject *return_value = NULL; Py_buffer data = {NULL, NULL}; - if (!PyArg_ParseTuple(args, + if (!PyArg_Parse(arg, "y*:rlecode_hqx", &data)) goto exit; @@ -201,18 +201,18 @@ "Encode .hqx data."); #define BINASCII_B2A_HQX_METHODDEF \ - {"b2a_hqx", (PyCFunction)binascii_b2a_hqx, METH_VARARGS, binascii_b2a_hqx__doc__}, + {"b2a_hqx", (PyCFunction)binascii_b2a_hqx, METH_O, binascii_b2a_hqx__doc__}, static PyObject * binascii_b2a_hqx_impl(PyModuleDef *module, Py_buffer *data); static PyObject * -binascii_b2a_hqx(PyModuleDef *module, PyObject *args) +binascii_b2a_hqx(PyModuleDef *module, PyObject *arg) { PyObject *return_value = NULL; Py_buffer data = {NULL, NULL}; - if (!PyArg_ParseTuple(args, + if (!PyArg_Parse(arg, "y*:b2a_hqx", &data)) goto exit; @@ -233,18 +233,18 @@ "Decode hexbin RLE-coded string."); #define BINASCII_RLEDECODE_HQX_METHODDEF \ - {"rledecode_hqx", (PyCFunction)binascii_rledecode_hqx, METH_VARARGS, binascii_rledecode_hqx__doc__}, + {"rledecode_hqx", (PyCFunction)binascii_rledecode_hqx, METH_O, binascii_rledecode_hqx__doc__}, static PyObject * binascii_rledecode_hqx_impl(PyModuleDef *module, Py_buffer *data); static PyObject * -binascii_rledecode_hqx(PyModuleDef *module, PyObject *args) +binascii_rledecode_hqx(PyModuleDef *module, PyObject *arg) { PyObject *return_value = NULL; Py_buffer data = {NULL, NULL}; - if (!PyArg_ParseTuple(args, + if (!PyArg_Parse(arg, "y*:rledecode_hqx", &data)) goto exit; @@ -342,18 +342,18 @@ "available as \"hexlify()\"."); #define BINASCII_B2A_HEX_METHODDEF \ - {"b2a_hex", (PyCFunction)binascii_b2a_hex, METH_VARARGS, binascii_b2a_hex__doc__}, + {"b2a_hex", (PyCFunction)binascii_b2a_hex, METH_O, binascii_b2a_hex__doc__}, static PyObject * binascii_b2a_hex_impl(PyModuleDef *module, Py_buffer *data); static PyObject * -binascii_b2a_hex(PyModuleDef *module, PyObject *args) +binascii_b2a_hex(PyModuleDef *module, PyObject *arg) { PyObject *return_value = NULL; Py_buffer data = {NULL, NULL}; - if (!PyArg_ParseTuple(args, + if (!PyArg_Parse(arg, "y*:b2a_hex", &data)) goto exit; @@ -376,18 +376,18 @@ "The return value is a bytes object."); #define BINASCII_HEXLIFY_METHODDEF \ - {"hexlify", (PyCFunction)binascii_hexlify, METH_VARARGS, binascii_hexlify__doc__}, + {"hexlify", (PyCFunction)binascii_hexlify, METH_O, binascii_hexlify__doc__}, static PyObject * binascii_hexlify_impl(PyModuleDef *module, Py_buffer *data); static PyObject * -binascii_hexlify(PyModuleDef *module, PyObject *args) +binascii_hexlify(PyModuleDef *module, PyObject *arg) { PyObject *return_value = NULL; Py_buffer data = {NULL, NULL}; - if (!PyArg_ParseTuple(args, + if (!PyArg_Parse(arg, "y*:hexlify", &data)) goto exit; @@ -411,18 +411,18 @@ "This function is also available as \"unhexlify()\"."); #define BINASCII_A2B_HEX_METHODDEF \ - {"a2b_hex", (PyCFunction)binascii_a2b_hex, METH_VARARGS, binascii_a2b_hex__doc__}, + {"a2b_hex", (PyCFunction)binascii_a2b_hex, METH_O, binascii_a2b_hex__doc__}, static PyObject * binascii_a2b_hex_impl(PyModuleDef *module, Py_buffer *hexstr); static PyObject * -binascii_a2b_hex(PyModuleDef *module, PyObject *args) +binascii_a2b_hex(PyModuleDef *module, PyObject *arg) { PyObject *return_value = NULL; Py_buffer hexstr = {NULL, NULL}; - if (!PyArg_ParseTuple(args, + if (!PyArg_Parse(arg, "O&:a2b_hex", ascii_buffer_converter, &hexstr)) goto exit; @@ -445,18 +445,18 @@ "hexstr must contain an even number of hex digits (upper or lower case)."); #define BINASCII_UNHEXLIFY_METHODDEF \ - {"unhexlify", (PyCFunction)binascii_unhexlify, METH_VARARGS, binascii_unhexlify__doc__}, + {"unhexlify", (PyCFunction)binascii_unhexlify, METH_O, binascii_unhexlify__doc__}, static PyObject * binascii_unhexlify_impl(PyModuleDef *module, Py_buffer *hexstr); static PyObject * -binascii_unhexlify(PyModuleDef *module, PyObject *args) +binascii_unhexlify(PyModuleDef *module, PyObject *arg) { PyObject *return_value = NULL; Py_buffer hexstr = {NULL, NULL}; - if (!PyArg_ParseTuple(args, + if (!PyArg_Parse(arg, "O&:unhexlify", ascii_buffer_converter, &hexstr)) goto exit; @@ -543,4 +543,4 @@ return return_value; } -/*[clinic end generated code: output=771126f8f53e84e7 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=31ccbd5fddc8fd75 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/cmathmodule.c.h b/Modules/clinic/cmathmodule.c.h --- a/Modules/clinic/cmathmodule.c.h +++ b/Modules/clinic/cmathmodule.c.h @@ -9,19 +9,19 @@ "Return the arc cosine of z."); #define CMATH_ACOS_METHODDEF \ - {"acos", (PyCFunction)cmath_acos, METH_VARARGS, cmath_acos__doc__}, + {"acos", (PyCFunction)cmath_acos, METH_O, cmath_acos__doc__}, static Py_complex cmath_acos_impl(PyModuleDef *module, Py_complex z); static PyObject * -cmath_acos(PyModuleDef *module, PyObject *args) +cmath_acos(PyModuleDef *module, PyObject *arg) { PyObject *return_value = NULL; Py_complex z; Py_complex _return_value; - if (!PyArg_ParseTuple(args, + if (!PyArg_Parse(arg, "D:acos", &z)) goto exit; @@ -52,19 +52,19 @@ "Return the inverse hyperbolic cosine of z."); #define CMATH_ACOSH_METHODDEF \ - {"acosh", (PyCFunction)cmath_acosh, METH_VARARGS, cmath_acosh__doc__}, + {"acosh", (PyCFunction)cmath_acosh, METH_O, cmath_acosh__doc__}, static Py_complex cmath_acosh_impl(PyModuleDef *module, Py_complex z); static PyObject * -cmath_acosh(PyModuleDef *module, PyObject *args) +cmath_acosh(PyModuleDef *module, PyObject *arg) { PyObject *return_value = NULL; Py_complex z; Py_complex _return_value; - if (!PyArg_ParseTuple(args, + if (!PyArg_Parse(arg, "D:acosh", &z)) goto exit; @@ -95,19 +95,19 @@ "Return the arc sine of z."); #define CMATH_ASIN_METHODDEF \ - {"asin", (PyCFunction)cmath_asin, METH_VARARGS, cmath_asin__doc__}, + {"asin", (PyCFunction)cmath_asin, METH_O, cmath_asin__doc__}, static Py_complex cmath_asin_impl(PyModuleDef *module, Py_complex z); static PyObject * -cmath_asin(PyModuleDef *module, PyObject *args) +cmath_asin(PyModuleDef *module, PyObject *arg) { PyObject *return_value = NULL; Py_complex z; Py_complex _return_value; - if (!PyArg_ParseTuple(args, + if (!PyArg_Parse(arg, "D:asin", &z)) goto exit; @@ -138,19 +138,19 @@ "Return the inverse hyperbolic sine of z."); #define CMATH_ASINH_METHODDEF \ - {"asinh", (PyCFunction)cmath_asinh, METH_VARARGS, cmath_asinh__doc__}, + {"asinh", (PyCFunction)cmath_asinh, METH_O, cmath_asinh__doc__}, static Py_complex cmath_asinh_impl(PyModuleDef *module, Py_complex z); static PyObject * -cmath_asinh(PyModuleDef *module, PyObject *args) +cmath_asinh(PyModuleDef *module, PyObject *arg) { PyObject *return_value = NULL; Py_complex z; Py_complex _return_value; - if (!PyArg_ParseTuple(args, + if (!PyArg_Parse(arg, "D:asinh", &z)) goto exit; @@ -181,19 +181,19 @@ "Return the arc tangent of z."); #define CMATH_ATAN_METHODDEF \ - {"atan", (PyCFunction)cmath_atan, METH_VARARGS, cmath_atan__doc__}, + {"atan", (PyCFunction)cmath_atan, METH_O, cmath_atan__doc__}, static Py_complex cmath_atan_impl(PyModuleDef *module, Py_complex z); static PyObject * -cmath_atan(PyModuleDef *module, PyObject *args) +cmath_atan(PyModuleDef *module, PyObject *arg) { PyObject *return_value = NULL; Py_complex z; Py_complex _return_value; - if (!PyArg_ParseTuple(args, + if (!PyArg_Parse(arg, "D:atan", &z)) goto exit; @@ -224,19 +224,19 @@ "Return the inverse hyperbolic tangent of z."); #define CMATH_ATANH_METHODDEF \ - {"atanh", (PyCFunction)cmath_atanh, METH_VARARGS, cmath_atanh__doc__}, + {"atanh", (PyCFunction)cmath_atanh, METH_O, cmath_atanh__doc__}, static Py_complex cmath_atanh_impl(PyModuleDef *module, Py_complex z); static PyObject * -cmath_atanh(PyModuleDef *module, PyObject *args) +cmath_atanh(PyModuleDef *module, PyObject *arg) { PyObject *return_value = NULL; Py_complex z; Py_complex _return_value; - if (!PyArg_ParseTuple(args, + if (!PyArg_Parse(arg, "D:atanh", &z)) goto exit; @@ -267,19 +267,19 @@ "Return the cosine of z."); #define CMATH_COS_METHODDEF \ - {"cos", (PyCFunction)cmath_cos, METH_VARARGS, cmath_cos__doc__}, + {"cos", (PyCFunction)cmath_cos, METH_O, cmath_cos__doc__}, static Py_complex cmath_cos_impl(PyModuleDef *module, Py_complex z); static PyObject * -cmath_cos(PyModuleDef *module, PyObject *args) +cmath_cos(PyModuleDef *module, PyObject *arg) { PyObject *return_value = NULL; Py_complex z; Py_complex _return_value; - if (!PyArg_ParseTuple(args, + if (!PyArg_Parse(arg, "D:cos", &z)) goto exit; @@ -310,19 +310,19 @@ "Return the hyperbolic cosine of z."); #define CMATH_COSH_METHODDEF \ - {"cosh", (PyCFunction)cmath_cosh, METH_VARARGS, cmath_cosh__doc__}, + {"cosh", (PyCFunction)cmath_cosh, METH_O, cmath_cosh__doc__}, static Py_complex cmath_cosh_impl(PyModuleDef *module, Py_complex z); static PyObject * -cmath_cosh(PyModuleDef *module, PyObject *args) +cmath_cosh(PyModuleDef *module, PyObject *arg) { PyObject *return_value = NULL; Py_complex z; Py_complex _return_value; - if (!PyArg_ParseTuple(args, + if (!PyArg_Parse(arg, "D:cosh", &z)) goto exit; @@ -353,19 +353,19 @@ "Return the exponential value e**z."); #define CMATH_EXP_METHODDEF \ - {"exp", (PyCFunction)cmath_exp, METH_VARARGS, cmath_exp__doc__}, + {"exp", (PyCFunction)cmath_exp, METH_O, cmath_exp__doc__}, static Py_complex cmath_exp_impl(PyModuleDef *module, Py_complex z); static PyObject * -cmath_exp(PyModuleDef *module, PyObject *args) +cmath_exp(PyModuleDef *module, PyObject *arg) { PyObject *return_value = NULL; Py_complex z; Py_complex _return_value; - if (!PyArg_ParseTuple(args, + if (!PyArg_Parse(arg, "D:exp", &z)) goto exit; @@ -396,19 +396,19 @@ "Return the base-10 logarithm of z."); #define CMATH_LOG10_METHODDEF \ - {"log10", (PyCFunction)cmath_log10, METH_VARARGS, cmath_log10__doc__}, + {"log10", (PyCFunction)cmath_log10, METH_O, cmath_log10__doc__}, static Py_complex cmath_log10_impl(PyModuleDef *module, Py_complex z); static PyObject * -cmath_log10(PyModuleDef *module, PyObject *args) +cmath_log10(PyModuleDef *module, PyObject *arg) { PyObject *return_value = NULL; Py_complex z; Py_complex _return_value; - if (!PyArg_ParseTuple(args, + if (!PyArg_Parse(arg, "D:log10", &z)) goto exit; @@ -439,19 +439,19 @@ "Return the sine of z."); #define CMATH_SIN_METHODDEF \ - {"sin", (PyCFunction)cmath_sin, METH_VARARGS, cmath_sin__doc__}, + {"sin", (PyCFunction)cmath_sin, METH_O, cmath_sin__doc__}, static Py_complex cmath_sin_impl(PyModuleDef *module, Py_complex z); static PyObject * -cmath_sin(PyModuleDef *module, PyObject *args) +cmath_sin(PyModuleDef *module, PyObject *arg) { PyObject *return_value = NULL; Py_complex z; Py_complex _return_value; - if (!PyArg_ParseTuple(args, + if (!PyArg_Parse(arg, "D:sin", &z)) goto exit; @@ -482,19 +482,19 @@ "Return the hyperbolic sine of z."); #define CMATH_SINH_METHODDEF \ - {"sinh", (PyCFunction)cmath_sinh, METH_VARARGS, cmath_sinh__doc__}, + {"sinh", (PyCFunction)cmath_sinh, METH_O, cmath_sinh__doc__}, static Py_complex cmath_sinh_impl(PyModuleDef *module, Py_complex z); static PyObject * -cmath_sinh(PyModuleDef *module, PyObject *args) +cmath_sinh(PyModuleDef *module, PyObject *arg) { PyObject *return_value = NULL; Py_complex z; Py_complex _return_value; - if (!PyArg_ParseTuple(args, + if (!PyArg_Parse(arg, "D:sinh", &z)) goto exit; @@ -525,19 +525,19 @@ "Return the square root of z."); #define CMATH_SQRT_METHODDEF \ - {"sqrt", (PyCFunction)cmath_sqrt, METH_VARARGS, cmath_sqrt__doc__}, + {"sqrt", (PyCFunction)cmath_sqrt, METH_O, cmath_sqrt__doc__}, static Py_complex cmath_sqrt_impl(PyModuleDef *module, Py_complex z); static PyObject * -cmath_sqrt(PyModuleDef *module, PyObject *args) +cmath_sqrt(PyModuleDef *module, PyObject *arg) { PyObject *return_value = NULL; Py_complex z; Py_complex _return_value; - if (!PyArg_ParseTuple(args, + if (!PyArg_Parse(arg, "D:sqrt", &z)) goto exit; @@ -568,19 +568,19 @@ "Return the tangent of z."); #define CMATH_TAN_METHODDEF \ - {"tan", (PyCFunction)cmath_tan, METH_VARARGS, cmath_tan__doc__}, + {"tan", (PyCFunction)cmath_tan, METH_O, cmath_tan__doc__}, static Py_complex cmath_tan_impl(PyModuleDef *module, Py_complex z); static PyObject * -cmath_tan(PyModuleDef *module, PyObject *args) +cmath_tan(PyModuleDef *module, PyObject *arg) { PyObject *return_value = NULL; Py_complex z; Py_complex _return_value; - if (!PyArg_ParseTuple(args, + if (!PyArg_Parse(arg, "D:tan", &z)) goto exit; @@ -611,19 +611,19 @@ "Return the hyperbolic tangent of z."); #define CMATH_TANH_METHODDEF \ - {"tanh", (PyCFunction)cmath_tanh, METH_VARARGS, cmath_tanh__doc__}, + {"tanh", (PyCFunction)cmath_tanh, METH_O, cmath_tanh__doc__}, static Py_complex cmath_tanh_impl(PyModuleDef *module, Py_complex z); static PyObject * -cmath_tanh(PyModuleDef *module, PyObject *args) +cmath_tanh(PyModuleDef *module, PyObject *arg) { PyObject *return_value = NULL; Py_complex z; Py_complex _return_value; - if (!PyArg_ParseTuple(args, + if (!PyArg_Parse(arg, "D:tanh", &z)) goto exit; @@ -685,18 +685,18 @@ "Return argument, also known as the phase angle, of a complex."); #define CMATH_PHASE_METHODDEF \ - {"phase", (PyCFunction)cmath_phase, METH_VARARGS, cmath_phase__doc__}, + {"phase", (PyCFunction)cmath_phase, METH_O, cmath_phase__doc__}, static PyObject * cmath_phase_impl(PyModuleDef *module, Py_complex z); static PyObject * -cmath_phase(PyModuleDef *module, PyObject *args) +cmath_phase(PyModuleDef *module, PyObject *arg) { PyObject *return_value = NULL; Py_complex z; - if (!PyArg_ParseTuple(args, + if (!PyArg_Parse(arg, "D:phase", &z)) goto exit; @@ -715,18 +715,18 @@ "r is the distance from 0 and phi the phase angle."); #define CMATH_POLAR_METHODDEF \ - {"polar", (PyCFunction)cmath_polar, METH_VARARGS, cmath_polar__doc__}, + {"polar", (PyCFunction)cmath_polar, METH_O, cmath_polar__doc__}, static PyObject * cmath_polar_impl(PyModuleDef *module, Py_complex z); static PyObject * -cmath_polar(PyModuleDef *module, PyObject *args) +cmath_polar(PyModuleDef *module, PyObject *arg) { PyObject *return_value = NULL; Py_complex z; - if (!PyArg_ParseTuple(args, + if (!PyArg_Parse(arg, "D:polar", &z)) goto exit; @@ -772,18 +772,18 @@ "Return True if both the real and imaginary parts of z are finite, else False."); #define CMATH_ISFINITE_METHODDEF \ - {"isfinite", (PyCFunction)cmath_isfinite, METH_VARARGS, cmath_isfinite__doc__}, + {"isfinite", (PyCFunction)cmath_isfinite, METH_O, cmath_isfinite__doc__}, static PyObject * cmath_isfinite_impl(PyModuleDef *module, Py_complex z); static PyObject * -cmath_isfinite(PyModuleDef *module, PyObject *args) +cmath_isfinite(PyModuleDef *module, PyObject *arg) { PyObject *return_value = NULL; Py_complex z; - if (!PyArg_ParseTuple(args, + if (!PyArg_Parse(arg, "D:isfinite", &z)) goto exit; @@ -800,18 +800,18 @@ "Checks if the real or imaginary part of z not a number (NaN)."); #define CMATH_ISNAN_METHODDEF \ - {"isnan", (PyCFunction)cmath_isnan, METH_VARARGS, cmath_isnan__doc__}, + {"isnan", (PyCFunction)cmath_isnan, METH_O, cmath_isnan__doc__}, static PyObject * cmath_isnan_impl(PyModuleDef *module, Py_complex z); static PyObject * -cmath_isnan(PyModuleDef *module, PyObject *args) +cmath_isnan(PyModuleDef *module, PyObject *arg) { PyObject *return_value = NULL; Py_complex z; - if (!PyArg_ParseTuple(args, + if (!PyArg_Parse(arg, "D:isnan", &z)) goto exit; @@ -828,18 +828,18 @@ "Checks if the real or imaginary part of z is infinite."); #define CMATH_ISINF_METHODDEF \ - {"isinf", (PyCFunction)cmath_isinf, METH_VARARGS, cmath_isinf__doc__}, + {"isinf", (PyCFunction)cmath_isinf, METH_O, cmath_isinf__doc__}, static PyObject * cmath_isinf_impl(PyModuleDef *module, Py_complex z); static PyObject * -cmath_isinf(PyModuleDef *module, PyObject *args) +cmath_isinf(PyModuleDef *module, PyObject *arg) { PyObject *return_value = NULL; Py_complex z; - if (!PyArg_ParseTuple(args, + if (!PyArg_Parse(arg, "D:isinf", &z)) goto exit; @@ -848,4 +848,4 @@ exit: return return_value; } -/*[clinic end generated code: output=9b6d81711e4e3c4b input=a9049054013a1b77]*/ +/*[clinic end generated code: output=9143b8dcc8069024 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/posixmodule.c.h b/Modules/clinic/posixmodule.c.h --- a/Modules/clinic/posixmodule.c.h +++ b/Modules/clinic/posixmodule.c.h @@ -168,19 +168,19 @@ " Integer file descriptor handle."); #define OS_TTYNAME_METHODDEF \ - {"ttyname", (PyCFunction)os_ttyname, METH_VARARGS, os_ttyname__doc__}, + {"ttyname", (PyCFunction)os_ttyname, METH_O, os_ttyname__doc__}, static char * os_ttyname_impl(PyModuleDef *module, int fd); static PyObject * -os_ttyname(PyModuleDef *module, PyObject *args) +os_ttyname(PyModuleDef *module, PyObject *arg) { PyObject *return_value = NULL; int fd; char *_return_value; - if (!PyArg_ParseTuple(args, + if (!PyArg_Parse(arg, "i:ttyname", &fd)) goto exit; @@ -911,18 +911,18 @@ "A helper function for samepath on windows."); #define OS__GETFINALPATHNAME_METHODDEF \ - {"_getfinalpathname", (PyCFunction)os__getfinalpathname, METH_VARARGS, os__getfinalpathname__doc__}, + {"_getfinalpathname", (PyCFunction)os__getfinalpathname, METH_O, os__getfinalpathname__doc__}, static PyObject * os__getfinalpathname_impl(PyModuleDef *module, PyObject *path); static PyObject * -os__getfinalpathname(PyModuleDef *module, PyObject *args) +os__getfinalpathname(PyModuleDef *module, PyObject *arg) { PyObject *return_value = NULL; PyObject *path; - if (!PyArg_ParseTuple(args, + if (!PyArg_Parse(arg, "U:_getfinalpathname", &path)) goto exit; @@ -1017,18 +1017,18 @@ "Add increment to the priority of process and return the new priority."); #define OS_NICE_METHODDEF \ - {"nice", (PyCFunction)os_nice, METH_VARARGS, os_nice__doc__}, + {"nice", (PyCFunction)os_nice, METH_O, os_nice__doc__}, static PyObject * os_nice_impl(PyModuleDef *module, int increment); static PyObject * -os_nice(PyModuleDef *module, PyObject *args) +os_nice(PyModuleDef *module, PyObject *arg) { PyObject *return_value = NULL; int increment; - if (!PyArg_ParseTuple(args, + if (!PyArg_Parse(arg, "i:nice", &increment)) goto exit; @@ -1317,18 +1317,18 @@ "Set the current numeric umask and return the previous umask."); #define OS_UMASK_METHODDEF \ - {"umask", (PyCFunction)os_umask, METH_VARARGS, os_umask__doc__}, + {"umask", (PyCFunction)os_umask, METH_O, os_umask__doc__}, static PyObject * os_umask_impl(PyModuleDef *module, int mask); static PyObject * -os_umask(PyModuleDef *module, PyObject *args) +os_umask(PyModuleDef *module, PyObject *arg) { PyObject *return_value = NULL; int mask; - if (!PyArg_ParseTuple(args, + if (!PyArg_Parse(arg, "i:umask", &mask)) goto exit; @@ -1829,18 +1829,18 @@ "Passing 0 for pid returns the scheduling policy for the calling process."); #define OS_SCHED_GETSCHEDULER_METHODDEF \ - {"sched_getscheduler", (PyCFunction)os_sched_getscheduler, METH_VARARGS, os_sched_getscheduler__doc__}, + {"sched_getscheduler", (PyCFunction)os_sched_getscheduler, METH_O, os_sched_getscheduler__doc__}, static PyObject * os_sched_getscheduler_impl(PyModuleDef *module, pid_t pid); static PyObject * -os_sched_getscheduler(PyModuleDef *module, PyObject *args) +os_sched_getscheduler(PyModuleDef *module, PyObject *arg) { PyObject *return_value = NULL; pid_t pid; - if (!PyArg_ParseTuple(args, + if (!PyArg_Parse(arg, "" _Py_PARSE_PID ":sched_getscheduler", &pid)) goto exit; @@ -1934,18 +1934,18 @@ "Return value is an instance of sched_param."); #define OS_SCHED_GETPARAM_METHODDEF \ - {"sched_getparam", (PyCFunction)os_sched_getparam, METH_VARARGS, os_sched_getparam__doc__}, + {"sched_getparam", (PyCFunction)os_sched_getparam, METH_O, os_sched_getparam__doc__}, static PyObject * os_sched_getparam_impl(PyModuleDef *module, pid_t pid); static PyObject * -os_sched_getparam(PyModuleDef *module, PyObject *args) +os_sched_getparam(PyModuleDef *module, PyObject *arg) { PyObject *return_value = NULL; pid_t pid; - if (!PyArg_ParseTuple(args, + if (!PyArg_Parse(arg, "" _Py_PARSE_PID ":sched_getparam", &pid)) goto exit; @@ -2004,19 +2004,19 @@ "Value returned is a float."); #define OS_SCHED_RR_GET_INTERVAL_METHODDEF \ - {"sched_rr_get_interval", (PyCFunction)os_sched_rr_get_interval, METH_VARARGS, os_sched_rr_get_interval__doc__}, + {"sched_rr_get_interval", (PyCFunction)os_sched_rr_get_interval, METH_O, os_sched_rr_get_interval__doc__}, static double os_sched_rr_get_interval_impl(PyModuleDef *module, pid_t pid); static PyObject * -os_sched_rr_get_interval(PyModuleDef *module, PyObject *args) +os_sched_rr_get_interval(PyModuleDef *module, PyObject *arg) { PyObject *return_value = NULL; pid_t pid; double _return_value; - if (!PyArg_ParseTuple(args, + if (!PyArg_Parse(arg, "" _Py_PARSE_PID ":sched_rr_get_interval", &pid)) goto exit; @@ -2099,18 +2099,18 @@ "The affinity is returned as a set of CPU identifiers."); #define OS_SCHED_GETAFFINITY_METHODDEF \ - {"sched_getaffinity", (PyCFunction)os_sched_getaffinity, METH_VARARGS, os_sched_getaffinity__doc__}, + {"sched_getaffinity", (PyCFunction)os_sched_getaffinity, METH_O, os_sched_getaffinity__doc__}, static PyObject * os_sched_getaffinity_impl(PyModuleDef *module, pid_t pid); static PyObject * -os_sched_getaffinity(PyModuleDef *module, PyObject *args) +os_sched_getaffinity(PyModuleDef *module, PyObject *arg) { PyObject *return_value = NULL; pid_t pid; - if (!PyArg_ParseTuple(args, + if (!PyArg_Parse(arg, "" _Py_PARSE_PID ":sched_getaffinity", &pid)) goto exit; @@ -2501,18 +2501,18 @@ "Lock program segments into memory.\");"); #define OS_PLOCK_METHODDEF \ - {"plock", (PyCFunction)os_plock, METH_VARARGS, os_plock__doc__}, + {"plock", (PyCFunction)os_plock, METH_O, os_plock__doc__}, static PyObject * os_plock_impl(PyModuleDef *module, int op); static PyObject * -os_plock(PyModuleDef *module, PyObject *args) +os_plock(PyModuleDef *module, PyObject *arg) { PyObject *return_value = NULL; int op; - if (!PyArg_ParseTuple(args, + if (!PyArg_Parse(arg, "i:plock", &op)) goto exit; @@ -2533,18 +2533,18 @@ "Set the current process\'s user id."); #define OS_SETUID_METHODDEF \ - {"setuid", (PyCFunction)os_setuid, METH_VARARGS, os_setuid__doc__}, + {"setuid", (PyCFunction)os_setuid, METH_O, os_setuid__doc__}, static PyObject * os_setuid_impl(PyModuleDef *module, uid_t uid); static PyObject * -os_setuid(PyModuleDef *module, PyObject *args) +os_setuid(PyModuleDef *module, PyObject *arg) { PyObject *return_value = NULL; uid_t uid; - if (!PyArg_ParseTuple(args, + if (!PyArg_Parse(arg, "O&:setuid", _Py_Uid_Converter, &uid)) goto exit; @@ -2565,18 +2565,18 @@ "Set the current process\'s effective user id."); #define OS_SETEUID_METHODDEF \ - {"seteuid", (PyCFunction)os_seteuid, METH_VARARGS, os_seteuid__doc__}, + {"seteuid", (PyCFunction)os_seteuid, METH_O, os_seteuid__doc__}, static PyObject * os_seteuid_impl(PyModuleDef *module, uid_t euid); static PyObject * -os_seteuid(PyModuleDef *module, PyObject *args) +os_seteuid(PyModuleDef *module, PyObject *arg) { PyObject *return_value = NULL; uid_t euid; - if (!PyArg_ParseTuple(args, + if (!PyArg_Parse(arg, "O&:seteuid", _Py_Uid_Converter, &euid)) goto exit; @@ -2597,18 +2597,18 @@ "Set the current process\'s effective group id."); #define OS_SETEGID_METHODDEF \ - {"setegid", (PyCFunction)os_setegid, METH_VARARGS, os_setegid__doc__}, + {"setegid", (PyCFunction)os_setegid, METH_O, os_setegid__doc__}, static PyObject * os_setegid_impl(PyModuleDef *module, gid_t egid); static PyObject * -os_setegid(PyModuleDef *module, PyObject *args) +os_setegid(PyModuleDef *module, PyObject *arg) { PyObject *return_value = NULL; gid_t egid; - if (!PyArg_ParseTuple(args, + if (!PyArg_Parse(arg, "O&:setegid", _Py_Gid_Converter, &egid)) goto exit; @@ -2695,18 +2695,18 @@ "Set the current process\'s group id."); #define OS_SETGID_METHODDEF \ - {"setgid", (PyCFunction)os_setgid, METH_VARARGS, os_setgid__doc__}, + {"setgid", (PyCFunction)os_setgid, METH_O, os_setgid__doc__}, static PyObject * os_setgid_impl(PyModuleDef *module, gid_t gid); static PyObject * -os_setgid(PyModuleDef *module, PyObject *args) +os_setgid(PyModuleDef *module, PyObject *arg) { PyObject *return_value = NULL; gid_t gid; - if (!PyArg_ParseTuple(args, + if (!PyArg_Parse(arg, "O&:setgid", _Py_Gid_Converter, &gid)) goto exit; @@ -3036,18 +3036,18 @@ "Call the system call getsid(pid) and return the result."); #define OS_GETSID_METHODDEF \ - {"getsid", (PyCFunction)os_getsid, METH_VARARGS, os_getsid__doc__}, + {"getsid", (PyCFunction)os_getsid, METH_O, os_getsid__doc__}, static PyObject * os_getsid_impl(PyModuleDef *module, pid_t pid); static PyObject * -os_getsid(PyModuleDef *module, PyObject *args) +os_getsid(PyModuleDef *module, PyObject *arg) { PyObject *return_value = NULL; pid_t pid; - if (!PyArg_ParseTuple(args, + if (!PyArg_Parse(arg, "" _Py_PARSE_PID ":getsid", &pid)) goto exit; @@ -3123,18 +3123,18 @@ "Return the process group associated with the terminal specified by fd."); #define OS_TCGETPGRP_METHODDEF \ - {"tcgetpgrp", (PyCFunction)os_tcgetpgrp, METH_VARARGS, os_tcgetpgrp__doc__}, + {"tcgetpgrp", (PyCFunction)os_tcgetpgrp, METH_O, os_tcgetpgrp__doc__}, static PyObject * os_tcgetpgrp_impl(PyModuleDef *module, int fd); static PyObject * -os_tcgetpgrp(PyModuleDef *module, PyObject *args) +os_tcgetpgrp(PyModuleDef *module, PyObject *arg) { PyObject *return_value = NULL; int fd; - if (!PyArg_ParseTuple(args, + if (!PyArg_Parse(arg, "i:tcgetpgrp", &fd)) goto exit; @@ -3288,19 +3288,19 @@ "Return a duplicate of a file descriptor."); #define OS_DUP_METHODDEF \ - {"dup", (PyCFunction)os_dup, METH_VARARGS, os_dup__doc__}, + {"dup", (PyCFunction)os_dup, METH_O, os_dup__doc__}, static int os_dup_impl(PyModuleDef *module, int fd); static PyObject * -os_dup(PyModuleDef *module, PyObject *args) +os_dup(PyModuleDef *module, PyObject *arg) { PyObject *return_value = NULL; int fd; int _return_value; - if (!PyArg_ParseTuple(args, + if (!PyArg_Parse(arg, "i:dup", &fd)) goto exit; @@ -3612,19 +3612,19 @@ "connected to the slave end of a terminal."); #define OS_ISATTY_METHODDEF \ - {"isatty", (PyCFunction)os_isatty, METH_VARARGS, os_isatty__doc__}, + {"isatty", (PyCFunction)os_isatty, METH_O, os_isatty__doc__}, static int os_isatty_impl(PyModuleDef *module, int fd); static PyObject * -os_isatty(PyModuleDef *module, PyObject *args) +os_isatty(PyModuleDef *module, PyObject *arg) { PyObject *return_value = NULL; int fd; int _return_value; - if (!PyArg_ParseTuple(args, + if (!PyArg_Parse(arg, "i:isatty", &fd)) goto exit; @@ -3677,18 +3677,18 @@ "O_NONBLOCK, O_CLOEXEC."); #define OS_PIPE2_METHODDEF \ - {"pipe2", (PyCFunction)os_pipe2, METH_VARARGS, os_pipe2__doc__}, + {"pipe2", (PyCFunction)os_pipe2, METH_O, os_pipe2__doc__}, static PyObject * os_pipe2_impl(PyModuleDef *module, int flags); static PyObject * -os_pipe2(PyModuleDef *module, PyObject *args) +os_pipe2(PyModuleDef *module, PyObject *arg) { PyObject *return_value = NULL; int flags; - if (!PyArg_ParseTuple(args, + if (!PyArg_Parse(arg, "i:pipe2", &flags)) goto exit; @@ -3889,19 +3889,19 @@ "Extracts a device major number from a raw device number."); #define OS_MAJOR_METHODDEF \ - {"major", (PyCFunction)os_major, METH_VARARGS, os_major__doc__}, + {"major", (PyCFunction)os_major, METH_O, os_major__doc__}, static unsigned int os_major_impl(PyModuleDef *module, dev_t device); static PyObject * -os_major(PyModuleDef *module, PyObject *args) +os_major(PyModuleDef *module, PyObject *arg) { PyObject *return_value = NULL; dev_t device; unsigned int _return_value; - if (!PyArg_ParseTuple(args, + if (!PyArg_Parse(arg, "O&:major", _Py_Dev_Converter, &device)) goto exit; @@ -3925,19 +3925,19 @@ "Extracts a device minor number from a raw device number."); #define OS_MINOR_METHODDEF \ - {"minor", (PyCFunction)os_minor, METH_VARARGS, os_minor__doc__}, + {"minor", (PyCFunction)os_minor, METH_O, os_minor__doc__}, static unsigned int os_minor_impl(PyModuleDef *module, dev_t device); static PyObject * -os_minor(PyModuleDef *module, PyObject *args) +os_minor(PyModuleDef *module, PyObject *arg) { PyObject *return_value = NULL; dev_t device; unsigned int _return_value; - if (!PyArg_ParseTuple(args, + if (!PyArg_Parse(arg, "O&:minor", _Py_Dev_Converter, &device)) goto exit; @@ -4222,18 +4222,18 @@ "Delete an environment variable."); #define OS_UNSETENV_METHODDEF \ - {"unsetenv", (PyCFunction)os_unsetenv, METH_VARARGS, os_unsetenv__doc__}, + {"unsetenv", (PyCFunction)os_unsetenv, METH_O, os_unsetenv__doc__}, static PyObject * os_unsetenv_impl(PyModuleDef *module, PyObject *name); static PyObject * -os_unsetenv(PyModuleDef *module, PyObject *args) +os_unsetenv(PyModuleDef *module, PyObject *arg) { PyObject *return_value = NULL; PyObject *name = NULL; - if (!PyArg_ParseTuple(args, + if (!PyArg_Parse(arg, "O&:unsetenv", PyUnicode_FSConverter, &name)) goto exit; @@ -4255,18 +4255,18 @@ "Translate an error code to a message string."); #define OS_STRERROR_METHODDEF \ - {"strerror", (PyCFunction)os_strerror, METH_VARARGS, os_strerror__doc__}, + {"strerror", (PyCFunction)os_strerror, METH_O, os_strerror__doc__}, static PyObject * os_strerror_impl(PyModuleDef *module, int code); static PyObject * -os_strerror(PyModuleDef *module, PyObject *args) +os_strerror(PyModuleDef *module, PyObject *arg) { PyObject *return_value = NULL; int code; - if (!PyArg_ParseTuple(args, + if (!PyArg_Parse(arg, "i:strerror", &code)) goto exit; @@ -4285,19 +4285,19 @@ "Return True if the process returning status was dumped to a core file."); #define OS_WCOREDUMP_METHODDEF \ - {"WCOREDUMP", (PyCFunction)os_WCOREDUMP, METH_VARARGS, os_WCOREDUMP__doc__}, + {"WCOREDUMP", (PyCFunction)os_WCOREDUMP, METH_O, os_WCOREDUMP__doc__}, static int os_WCOREDUMP_impl(PyModuleDef *module, int status); static PyObject * -os_WCOREDUMP(PyModuleDef *module, PyObject *args) +os_WCOREDUMP(PyModuleDef *module, PyObject *arg) { PyObject *return_value = NULL; int status; int _return_value; - if (!PyArg_ParseTuple(args, + if (!PyArg_Parse(arg, "i:WCOREDUMP", &status)) goto exit; @@ -4585,18 +4585,18 @@ "Equivalent to statvfs(fd)."); #define OS_FSTATVFS_METHODDEF \ - {"fstatvfs", (PyCFunction)os_fstatvfs, METH_VARARGS, os_fstatvfs__doc__}, + {"fstatvfs", (PyCFunction)os_fstatvfs, METH_O, os_fstatvfs__doc__}, static PyObject * os_fstatvfs_impl(PyModuleDef *module, int fd); static PyObject * -os_fstatvfs(PyModuleDef *module, PyObject *args) +os_fstatvfs(PyModuleDef *module, PyObject *arg) { PyObject *return_value = NULL; int fd; - if (!PyArg_ParseTuple(args, + if (!PyArg_Parse(arg, "i:fstatvfs", &fd)) goto exit; @@ -4774,18 +4774,18 @@ "Return a string-valued system configuration variable."); #define OS_CONFSTR_METHODDEF \ - {"confstr", (PyCFunction)os_confstr, METH_VARARGS, os_confstr__doc__}, + {"confstr", (PyCFunction)os_confstr, METH_O, os_confstr__doc__}, static PyObject * os_confstr_impl(PyModuleDef *module, int name); static PyObject * -os_confstr(PyModuleDef *module, PyObject *args) +os_confstr(PyModuleDef *module, PyObject *arg) { PyObject *return_value = NULL; int name; - if (!PyArg_ParseTuple(args, + if (!PyArg_Parse(arg, "O&:confstr", conv_confstr_confname, &name)) goto exit; @@ -4806,19 +4806,19 @@ "Return an integer-valued system configuration variable."); #define OS_SYSCONF_METHODDEF \ - {"sysconf", (PyCFunction)os_sysconf, METH_VARARGS, os_sysconf__doc__}, + {"sysconf", (PyCFunction)os_sysconf, METH_O, os_sysconf__doc__}, static long os_sysconf_impl(PyModuleDef *module, int name); static PyObject * -os_sysconf(PyModuleDef *module, PyObject *args) +os_sysconf(PyModuleDef *module, PyObject *arg) { PyObject *return_value = NULL; int name; long _return_value; - if (!PyArg_ParseTuple(args, + if (!PyArg_Parse(arg, "O&:sysconf", conv_sysconf_confname, &name)) goto exit; @@ -5215,18 +5215,18 @@ "Return a bytes object containing random bytes suitable for cryptographic use."); #define OS_URANDOM_METHODDEF \ - {"urandom", (PyCFunction)os_urandom, METH_VARARGS, os_urandom__doc__}, + {"urandom", (PyCFunction)os_urandom, METH_O, os_urandom__doc__}, static PyObject * os_urandom_impl(PyModuleDef *module, Py_ssize_t size); static PyObject * -os_urandom(PyModuleDef *module, PyObject *args) +os_urandom(PyModuleDef *module, PyObject *arg) { PyObject *return_value = NULL; Py_ssize_t size; - if (!PyArg_ParseTuple(args, + if (!PyArg_Parse(arg, "n:urandom", &size)) goto exit; @@ -5261,19 +5261,19 @@ "Get the close-on-exe flag of the specified file descriptor."); #define OS_GET_INHERITABLE_METHODDEF \ - {"get_inheritable", (PyCFunction)os_get_inheritable, METH_VARARGS, os_get_inheritable__doc__}, + {"get_inheritable", (PyCFunction)os_get_inheritable, METH_O, os_get_inheritable__doc__}, static int os_get_inheritable_impl(PyModuleDef *module, int fd); static PyObject * -os_get_inheritable(PyModuleDef *module, PyObject *args) +os_get_inheritable(PyModuleDef *module, PyObject *arg) { PyObject *return_value = NULL; int fd; int _return_value; - if (!PyArg_ParseTuple(args, + if (!PyArg_Parse(arg, "i:get_inheritable", &fd)) goto exit; @@ -5324,19 +5324,19 @@ "Get the close-on-exe flag of the specified file descriptor."); #define OS_GET_HANDLE_INHERITABLE_METHODDEF \ - {"get_handle_inheritable", (PyCFunction)os_get_handle_inheritable, METH_VARARGS, os_get_handle_inheritable__doc__}, + {"get_handle_inheritable", (PyCFunction)os_get_handle_inheritable, METH_O, os_get_handle_inheritable__doc__}, static int os_get_handle_inheritable_impl(PyModuleDef *module, Py_intptr_t handle); static PyObject * -os_get_handle_inheritable(PyModuleDef *module, PyObject *args) +os_get_handle_inheritable(PyModuleDef *module, PyObject *arg) { PyObject *return_value = NULL; Py_intptr_t handle; int _return_value; - if (!PyArg_ParseTuple(args, + if (!PyArg_Parse(arg, "" _Py_PARSE_INTPTR ":get_handle_inheritable", &handle)) goto exit; @@ -5847,4 +5847,4 @@ #ifndef OS_SET_HANDLE_INHERITABLE_METHODDEF #define OS_SET_HANDLE_INHERITABLE_METHODDEF #endif /* !defined(OS_SET_HANDLE_INHERITABLE_METHODDEF) */ -/*[clinic end generated code: output=d17c625afa72886b input=a9049054013a1b77]*/ +/*[clinic end generated code: output=b15ceac3a8ff0eae input=a9049054013a1b77]*/ diff --git a/Modules/clinic/pwdmodule.c.h b/Modules/clinic/pwdmodule.c.h --- a/Modules/clinic/pwdmodule.c.h +++ b/Modules/clinic/pwdmodule.c.h @@ -22,18 +22,18 @@ "See `help(pwd)` for more on password database entries."); #define PWD_GETPWNAM_METHODDEF \ - {"getpwnam", (PyCFunction)pwd_getpwnam, METH_VARARGS, pwd_getpwnam__doc__}, + {"getpwnam", (PyCFunction)pwd_getpwnam, METH_O, pwd_getpwnam__doc__}, static PyObject * pwd_getpwnam_impl(PyModuleDef *module, PyObject *arg); static PyObject * -pwd_getpwnam(PyModuleDef *module, PyObject *args) +pwd_getpwnam(PyModuleDef *module, PyObject *arg_) { PyObject *return_value = NULL; PyObject *arg; - if (!PyArg_ParseTuple(args, + if (!PyArg_Parse(arg_, "U:getpwnam", &arg)) goto exit; @@ -70,4 +70,4 @@ #ifndef PWD_GETPWALL_METHODDEF #define PWD_GETPWALL_METHODDEF #endif /* !defined(PWD_GETPWALL_METHODDEF) */ -/*[clinic end generated code: output=2e23f920020a750a input=a9049054013a1b77]*/ +/*[clinic end generated code: output=e7d5ac24b20e91ae input=a9049054013a1b77]*/ diff --git a/Modules/clinic/pyexpat.c.h b/Modules/clinic/pyexpat.c.h --- a/Modules/clinic/pyexpat.c.h +++ b/Modules/clinic/pyexpat.c.h @@ -49,18 +49,18 @@ "Set the base URL for the parser."); #define PYEXPAT_XMLPARSER_SETBASE_METHODDEF \ - {"SetBase", (PyCFunction)pyexpat_xmlparser_SetBase, METH_VARARGS, pyexpat_xmlparser_SetBase__doc__}, + {"SetBase", (PyCFunction)pyexpat_xmlparser_SetBase, METH_O, pyexpat_xmlparser_SetBase__doc__}, static PyObject * pyexpat_xmlparser_SetBase_impl(xmlparseobject *self, const char *base); static PyObject * -pyexpat_xmlparser_SetBase(xmlparseobject *self, PyObject *args) +pyexpat_xmlparser_SetBase(xmlparseobject *self, PyObject *arg) { PyObject *return_value = NULL; const char *base; - if (!PyArg_ParseTuple(args, + if (!PyArg_Parse(arg, "s:SetBase", &base)) goto exit; @@ -150,18 +150,18 @@ "was successful."); #define PYEXPAT_XMLPARSER_SETPARAMENTITYPARSING_METHODDEF \ - {"SetParamEntityParsing", (PyCFunction)pyexpat_xmlparser_SetParamEntityParsing, METH_VARARGS, pyexpat_xmlparser_SetParamEntityParsing__doc__}, + {"SetParamEntityParsing", (PyCFunction)pyexpat_xmlparser_SetParamEntityParsing, METH_O, pyexpat_xmlparser_SetParamEntityParsing__doc__}, static PyObject * pyexpat_xmlparser_SetParamEntityParsing_impl(xmlparseobject *self, int flag); static PyObject * -pyexpat_xmlparser_SetParamEntityParsing(xmlparseobject *self, PyObject *args) +pyexpat_xmlparser_SetParamEntityParsing(xmlparseobject *self, PyObject *arg) { PyObject *return_value = NULL; int flag; - if (!PyArg_ParseTuple(args, + if (!PyArg_Parse(arg, "i:SetParamEntityParsing", &flag)) goto exit; @@ -262,18 +262,18 @@ "Returns string error for given number."); #define PYEXPAT_ERRORSTRING_METHODDEF \ - {"ErrorString", (PyCFunction)pyexpat_ErrorString, METH_VARARGS, pyexpat_ErrorString__doc__}, + {"ErrorString", (PyCFunction)pyexpat_ErrorString, METH_O, pyexpat_ErrorString__doc__}, static PyObject * pyexpat_ErrorString_impl(PyModuleDef *module, long code); static PyObject * -pyexpat_ErrorString(PyModuleDef *module, PyObject *args) +pyexpat_ErrorString(PyModuleDef *module, PyObject *arg) { PyObject *return_value = NULL; long code; - if (!PyArg_ParseTuple(args, + if (!PyArg_Parse(arg, "l:ErrorString", &code)) goto exit; @@ -286,4 +286,4 @@ #ifndef PYEXPAT_XMLPARSER_USEFOREIGNDTD_METHODDEF #define PYEXPAT_XMLPARSER_USEFOREIGNDTD_METHODDEF #endif /* !defined(PYEXPAT_XMLPARSER_USEFOREIGNDTD_METHODDEF) */ -/*[clinic end generated code: output=0198390005e40e1c input=a9049054013a1b77]*/ +/*[clinic end generated code: output=9715b916f2d618fa input=a9049054013a1b77]*/ diff --git a/Modules/clinic/spwdmodule.c.h b/Modules/clinic/spwdmodule.c.h --- a/Modules/clinic/spwdmodule.c.h +++ b/Modules/clinic/spwdmodule.c.h @@ -13,18 +13,18 @@ "See `help(spwd)` for more on shadow password database entries."); #define SPWD_GETSPNAM_METHODDEF \ - {"getspnam", (PyCFunction)spwd_getspnam, METH_VARARGS, spwd_getspnam__doc__}, + {"getspnam", (PyCFunction)spwd_getspnam, METH_O, spwd_getspnam__doc__}, static PyObject * spwd_getspnam_impl(PyModuleDef *module, PyObject *arg); static PyObject * -spwd_getspnam(PyModuleDef *module, PyObject *args) +spwd_getspnam(PyModuleDef *module, PyObject *arg_) { PyObject *return_value = NULL; PyObject *arg; - if (!PyArg_ParseTuple(args, + if (!PyArg_Parse(arg_, "U:getspnam", &arg)) goto exit; @@ -67,4 +67,4 @@ #ifndef SPWD_GETSPALL_METHODDEF #define SPWD_GETSPALL_METHODDEF #endif /* !defined(SPWD_GETSPALL_METHODDEF) */ -/*[clinic end generated code: output=ab16125c5e5f2b1b input=a9049054013a1b77]*/ +/*[clinic end generated code: output=67a4f8c47008f28f input=a9049054013a1b77]*/ diff --git a/Modules/clinic/zlibmodule.c.h b/Modules/clinic/zlibmodule.c.h --- a/Modules/clinic/zlibmodule.c.h +++ b/Modules/clinic/zlibmodule.c.h @@ -189,18 +189,18 @@ "Call the flush() method to clear these buffers."); #define ZLIB_COMPRESS_COMPRESS_METHODDEF \ - {"compress", (PyCFunction)zlib_Compress_compress, METH_VARARGS, zlib_Compress_compress__doc__}, + {"compress", (PyCFunction)zlib_Compress_compress, METH_O, zlib_Compress_compress__doc__}, static PyObject * zlib_Compress_compress_impl(compobject *self, Py_buffer *data); static PyObject * -zlib_Compress_compress(compobject *self, PyObject *args) +zlib_Compress_compress(compobject *self, PyObject *arg) { PyObject *return_value = NULL; Py_buffer data = {NULL, NULL}; - if (!PyArg_ParseTuple(args, + if (!PyArg_Parse(arg, "y*:compress", &data)) goto exit; @@ -446,4 +446,4 @@ #ifndef ZLIB_COMPRESS_COPY_METHODDEF #define ZLIB_COMPRESS_COPY_METHODDEF #endif /* !defined(ZLIB_COMPRESS_COPY_METHODDEF) */ -/*[clinic end generated code: output=901c18189767dc08 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=0743b1aa908f0b68 input=a9049054013a1b77]*/ diff --git a/Objects/clinic/bytearrayobject.c.h b/Objects/clinic/bytearrayobject.c.h --- a/Objects/clinic/bytearrayobject.c.h +++ b/Objects/clinic/bytearrayobject.c.h @@ -339,18 +339,18 @@ " The item to be appended."); #define BYTEARRAY_APPEND_METHODDEF \ - {"append", (PyCFunction)bytearray_append, METH_VARARGS, bytearray_append__doc__}, + {"append", (PyCFunction)bytearray_append, METH_O, bytearray_append__doc__}, static PyObject * bytearray_append_impl(PyByteArrayObject *self, int item); static PyObject * -bytearray_append(PyByteArrayObject *self, PyObject *args) +bytearray_append(PyByteArrayObject *self, PyObject *arg) { PyObject *return_value = NULL; int item; - if (!PyArg_ParseTuple(args, + if (!PyArg_Parse(arg, "O&:append", _getbytevalue, &item)) goto exit; @@ -416,18 +416,18 @@ " The value to remove."); #define BYTEARRAY_REMOVE_METHODDEF \ - {"remove", (PyCFunction)bytearray_remove, METH_VARARGS, bytearray_remove__doc__}, + {"remove", (PyCFunction)bytearray_remove, METH_O, bytearray_remove__doc__}, static PyObject * bytearray_remove_impl(PyByteArrayObject *self, int value); static PyObject * -bytearray_remove(PyByteArrayObject *self, PyObject *args) +bytearray_remove(PyByteArrayObject *self, PyObject *arg) { PyObject *return_value = NULL; int value; - if (!PyArg_ParseTuple(args, + if (!PyArg_Parse(arg, "O&:remove", _getbytevalue, &value)) goto exit; @@ -621,18 +621,18 @@ "Example: bytearray.fromhex(\'B9 01EF\') -> bytearray(b\'\\\\xb9\\\\x01\\\\xef\')"); #define BYTEARRAY_FROMHEX_METHODDEF \ - {"fromhex", (PyCFunction)bytearray_fromhex, METH_VARARGS|METH_CLASS, bytearray_fromhex__doc__}, + {"fromhex", (PyCFunction)bytearray_fromhex, METH_O|METH_CLASS, bytearray_fromhex__doc__}, static PyObject * bytearray_fromhex_impl(PyObject*cls, PyObject *string); static PyObject * -bytearray_fromhex(PyTypeObject *cls, PyObject *args) +bytearray_fromhex(PyTypeObject *cls, PyObject *arg) { PyObject *return_value = NULL; PyObject *string; - if (!PyArg_ParseTuple(args, + if (!PyArg_Parse(arg, "U:fromhex", &string)) goto exit; @@ -705,4 +705,4 @@ { return bytearray_sizeof_impl(self); } -/*[clinic end generated code: output=70ea384faeca8d16 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=d763876718a66fc3 input=a9049054013a1b77]*/ diff --git a/Objects/clinic/bytesobject.c.h b/Objects/clinic/bytesobject.c.h --- a/Objects/clinic/bytesobject.c.h +++ b/Objects/clinic/bytesobject.c.h @@ -54,18 +54,18 @@ "object and two empty bytes objects."); #define BYTES_PARTITION_METHODDEF \ - {"partition", (PyCFunction)bytes_partition, METH_VARARGS, bytes_partition__doc__}, + {"partition", (PyCFunction)bytes_partition, METH_O, bytes_partition__doc__}, static PyObject * bytes_partition_impl(PyBytesObject *self, Py_buffer *sep); static PyObject * -bytes_partition(PyBytesObject *self, PyObject *args) +bytes_partition(PyBytesObject *self, PyObject *arg) { PyObject *return_value = NULL; Py_buffer sep = {NULL, NULL}; - if (!PyArg_ParseTuple(args, + if (!PyArg_Parse(arg, "y*:partition", &sep)) goto exit; @@ -93,18 +93,18 @@ "objects and the original bytes object."); #define BYTES_RPARTITION_METHODDEF \ - {"rpartition", (PyCFunction)bytes_rpartition, METH_VARARGS, bytes_rpartition__doc__}, + {"rpartition", (PyCFunction)bytes_rpartition, METH_O, bytes_rpartition__doc__}, static PyObject * bytes_rpartition_impl(PyBytesObject *self, Py_buffer *sep); static PyObject * -bytes_rpartition(PyBytesObject *self, PyObject *args) +bytes_rpartition(PyBytesObject *self, PyObject *arg) { PyObject *return_value = NULL; Py_buffer sep = {NULL, NULL}; - if (!PyArg_ParseTuple(args, + if (!PyArg_Parse(arg, "y*:rpartition", &sep)) goto exit; @@ -473,18 +473,18 @@ "Example: bytes.fromhex(\'B9 01EF\') -> b\'\\\\xb9\\\\x01\\\\xef\'."); #define BYTES_FROMHEX_METHODDEF \ - {"fromhex", (PyCFunction)bytes_fromhex, METH_VARARGS|METH_CLASS, bytes_fromhex__doc__}, + {"fromhex", (PyCFunction)bytes_fromhex, METH_O|METH_CLASS, bytes_fromhex__doc__}, static PyObject * bytes_fromhex_impl(PyTypeObject *type, PyObject *string); static PyObject * -bytes_fromhex(PyTypeObject *type, PyObject *args) +bytes_fromhex(PyTypeObject *type, PyObject *arg) { PyObject *return_value = NULL; PyObject *string; - if (!PyArg_ParseTuple(args, + if (!PyArg_Parse(arg, "U:fromhex", &string)) goto exit; @@ -493,4 +493,4 @@ exit: return return_value; } -/*[clinic end generated code: output=dfe5c9a317b99f49 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=b9e69e1f7c8ccd14 input=a9049054013a1b77]*/ diff --git a/Python/clinic/bltinmodule.c.h b/Python/clinic/bltinmodule.c.h --- a/Python/clinic/bltinmodule.c.h +++ b/Python/clinic/bltinmodule.c.h @@ -109,18 +109,18 @@ "Return a Unicode string of one character with ordinal i; 0 <= i <= 0x10ffff."); #define BUILTIN_CHR_METHODDEF \ - {"chr", (PyCFunction)builtin_chr, METH_VARARGS, builtin_chr__doc__}, + {"chr", (PyCFunction)builtin_chr, METH_O, builtin_chr__doc__}, static PyObject * builtin_chr_impl(PyModuleDef *module, int i); static PyObject * -builtin_chr(PyModuleDef *module, PyObject *args) +builtin_chr(PyModuleDef *module, PyObject *arg) { PyObject *return_value = NULL; int i; - if (!PyArg_ParseTuple(args, + if (!PyArg_Parse(arg, "i:chr", &i)) goto exit; @@ -656,4 +656,4 @@ exit: return return_value; } -/*[clinic end generated code: output=2da46de189e48d26 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=12db4cde92eb11b3 input=a9049054013a1b77]*/ diff --git a/Python/clinic/import.c.h b/Python/clinic/import.c.h --- a/Python/clinic/import.c.h +++ b/Python/clinic/import.c.h @@ -122,18 +122,18 @@ "Initializes a built-in module."); #define _IMP_INIT_BUILTIN_METHODDEF \ - {"init_builtin", (PyCFunction)_imp_init_builtin, METH_VARARGS, _imp_init_builtin__doc__}, + {"init_builtin", (PyCFunction)_imp_init_builtin, METH_O, _imp_init_builtin__doc__}, static PyObject * _imp_init_builtin_impl(PyModuleDef *module, PyObject *name); static PyObject * -_imp_init_builtin(PyModuleDef *module, PyObject *args) +_imp_init_builtin(PyModuleDef *module, PyObject *arg) { PyObject *return_value = NULL; PyObject *name; - if (!PyArg_ParseTuple(args, + if (!PyArg_Parse(arg, "U:init_builtin", &name)) goto exit; @@ -150,18 +150,18 @@ "Initializes a frozen module."); #define _IMP_INIT_FROZEN_METHODDEF \ - {"init_frozen", (PyCFunction)_imp_init_frozen, METH_VARARGS, _imp_init_frozen__doc__}, + {"init_frozen", (PyCFunction)_imp_init_frozen, METH_O, _imp_init_frozen__doc__}, static PyObject * _imp_init_frozen_impl(PyModuleDef *module, PyObject *name); static PyObject * -_imp_init_frozen(PyModuleDef *module, PyObject *args) +_imp_init_frozen(PyModuleDef *module, PyObject *arg) { PyObject *return_value = NULL; PyObject *name; - if (!PyArg_ParseTuple(args, + if (!PyArg_Parse(arg, "U:init_frozen", &name)) goto exit; @@ -178,18 +178,18 @@ "Create a code object for a frozen module."); #define _IMP_GET_FROZEN_OBJECT_METHODDEF \ - {"get_frozen_object", (PyCFunction)_imp_get_frozen_object, METH_VARARGS, _imp_get_frozen_object__doc__}, + {"get_frozen_object", (PyCFunction)_imp_get_frozen_object, METH_O, _imp_get_frozen_object__doc__}, static PyObject * _imp_get_frozen_object_impl(PyModuleDef *module, PyObject *name); static PyObject * -_imp_get_frozen_object(PyModuleDef *module, PyObject *args) +_imp_get_frozen_object(PyModuleDef *module, PyObject *arg) { PyObject *return_value = NULL; PyObject *name; - if (!PyArg_ParseTuple(args, + if (!PyArg_Parse(arg, "U:get_frozen_object", &name)) goto exit; @@ -206,18 +206,18 @@ "Returns True if the module name is of a frozen package."); #define _IMP_IS_FROZEN_PACKAGE_METHODDEF \ - {"is_frozen_package", (PyCFunction)_imp_is_frozen_package, METH_VARARGS, _imp_is_frozen_package__doc__}, + {"is_frozen_package", (PyCFunction)_imp_is_frozen_package, METH_O, _imp_is_frozen_package__doc__}, static PyObject * _imp_is_frozen_package_impl(PyModuleDef *module, PyObject *name); static PyObject * -_imp_is_frozen_package(PyModuleDef *module, PyObject *args) +_imp_is_frozen_package(PyModuleDef *module, PyObject *arg) { PyObject *return_value = NULL; PyObject *name; - if (!PyArg_ParseTuple(args, + if (!PyArg_Parse(arg, "U:is_frozen_package", &name)) goto exit; @@ -234,18 +234,18 @@ "Returns True if the module name corresponds to a built-in module."); #define _IMP_IS_BUILTIN_METHODDEF \ - {"is_builtin", (PyCFunction)_imp_is_builtin, METH_VARARGS, _imp_is_builtin__doc__}, + {"is_builtin", (PyCFunction)_imp_is_builtin, METH_O, _imp_is_builtin__doc__}, static PyObject * _imp_is_builtin_impl(PyModuleDef *module, PyObject *name); static PyObject * -_imp_is_builtin(PyModuleDef *module, PyObject *args) +_imp_is_builtin(PyModuleDef *module, PyObject *arg) { PyObject *return_value = NULL; PyObject *name; - if (!PyArg_ParseTuple(args, + if (!PyArg_Parse(arg, "U:is_builtin", &name)) goto exit; @@ -262,18 +262,18 @@ "Returns True if the module name corresponds to a frozen module."); #define _IMP_IS_FROZEN_METHODDEF \ - {"is_frozen", (PyCFunction)_imp_is_frozen, METH_VARARGS, _imp_is_frozen__doc__}, + {"is_frozen", (PyCFunction)_imp_is_frozen, METH_O, _imp_is_frozen__doc__}, static PyObject * _imp_is_frozen_impl(PyModuleDef *module, PyObject *name); static PyObject * -_imp_is_frozen(PyModuleDef *module, PyObject *args) +_imp_is_frozen(PyModuleDef *module, PyObject *arg) { PyObject *return_value = NULL; PyObject *name; - if (!PyArg_ParseTuple(args, + if (!PyArg_Parse(arg, "U:is_frozen", &name)) goto exit; @@ -320,4 +320,4 @@ #ifndef _IMP_LOAD_DYNAMIC_METHODDEF #define _IMP_LOAD_DYNAMIC_METHODDEF #endif /* !defined(_IMP_LOAD_DYNAMIC_METHODDEF) */ -/*[clinic end generated code: output=087a1f22e9febcc7 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=d41c392510815c5b input=a9049054013a1b77]*/ diff --git a/Tools/clinic/clinic.py b/Tools/clinic/clinic.py --- a/Tools/clinic/clinic.py +++ b/Tools/clinic/clinic.py @@ -593,8 +593,6 @@ meth_o = (len(parameters) == 1 and parameters[0].kind == inspect.Parameter.POSITIONAL_ONLY and not converters[0].is_optional() and - isinstance(converters[0], object_converter) and - converters[0].format_unit == 'O' and not new_or_init) # we have to set these things before we're done: @@ -700,22 +698,40 @@ elif meth_o: flags = "METH_O" - meth_o_prototype = normalize_snippet(""" - static PyObject * - {c_basename}({impl_parameters}) - """) - - if default_return_converter: - # maps perfectly to METH_O, doesn't need a return converter. - # so we skip making a parse function - # and call directly into the impl function. - impl_prototype = parser_prototype = parser_definition = '' - impl_definition = meth_o_prototype + if (isinstance(converters[0], object_converter) and + converters[0].format_unit == 'O'): + meth_o_prototype = normalize_snippet(""" + static PyObject * + {c_basename}({impl_parameters}) + """) + + if default_return_converter: + # maps perfectly to METH_O, doesn't need a return converter. + # so we skip making a parse function + # and call directly into the impl function. + impl_prototype = parser_prototype = parser_definition = '' + impl_definition = meth_o_prototype + else: + # SLIGHT HACK + # use impl_parameters for the parser here! + parser_prototype = meth_o_prototype + parser_definition = parser_body(parser_prototype) + else: - # SLIGHT HACK - # use impl_parameters for the parser here! - parser_prototype = meth_o_prototype - parser_definition = parser_body(parser_prototype) + argname = 'arg' + if parameters[0].name == argname: + argname += '_' + parser_prototype = normalize_snippet(""" + static PyObject * + {c_basename}({self_type}{self_name}, PyObject *%s) + """ % argname) + + parser_definition = parser_body(parser_prototype, normalize_snippet(""" + if (!PyArg_Parse(%s, + "{format_units}:{name}", + {parse_arguments})) + goto exit; + """ % argname, indent=4)) elif has_option_groups: # positional parameters with option groups @@ -1025,7 +1041,7 @@ # METH_O, we have exactly one anyway, so we know exactly # where it is. if ("METH_O" in templates['methoddef_define'] and - not default_return_converter): + '{impl_parameters}' in templates['parser_prototype']): data.declarations.pop(0) template_dict = {} -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Apr 4 08:50:38 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Sat, 04 Apr 2015 06:50:38 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzIzODI1?= =?utf-8?q?=3A_Fixed_test=5Fidle_under_-OO=2E?= Message-ID: <20150404065038.15207.23735@psf.io> https://hg.python.org/cpython/rev/912719dd684f changeset: 95426:912719dd684f branch: 2.7 parent: 95416:fe34dfea16b0 user: Serhiy Storchaka date: Sat Apr 04 09:47:18 2015 +0300 summary: Issue #23825: Fixed test_idle under -OO. files: Lib/idlelib/idle_test/test_calltips.py | 19 ++++++++----- 1 files changed, 12 insertions(+), 7 deletions(-) diff --git a/Lib/idlelib/idle_test/test_calltips.py b/Lib/idlelib/idle_test/test_calltips.py --- a/Lib/idlelib/idle_test/test_calltips.py +++ b/Lib/idlelib/idle_test/test_calltips.py @@ -55,7 +55,8 @@ def gtest(obj, out): self.assertEqual(signature(obj), out) - gtest(List, '()\n' + List.__doc__) + if List.__doc__ is not None: + gtest(List, '()\n' + List.__doc__) gtest(list.__new__, 'T.__new__(S, ...) -> a new object with type S, a subtype of T') gtest(list.__init__, @@ -70,7 +71,8 @@ def test_signature_wrap(self): # This is also a test of an old-style class - self.assertEqual(signature(textwrap.TextWrapper), '''\ + if textwrap.TextWrapper.__doc__ is not None: + self.assertEqual(signature(textwrap.TextWrapper), '''\ (width=70, initial_indent='', subsequent_indent='', expand_tabs=True, replace_whitespace=True, fix_sentence_endings=False, break_long_words=True, drop_whitespace=True, break_on_hyphens=True)''') @@ -106,20 +108,23 @@ def t5(a, b=None, *args, **kwds): 'doc' t5.tip = "(a, b=None, *args, **kwargs)" + doc = '\ndoc' if t1.__doc__ is not None else '' for func in (t1, t2, t3, t4, t5, TC): - self.assertEqual(signature(func), func.tip + '\ndoc') + self.assertEqual(signature(func), func.tip + doc) def test_methods(self): + doc = '\ndoc' if TC.__doc__ is not None else '' for meth in (TC.t1, TC.t2, TC.t3, TC.t4, TC.t5, TC.t6, TC.__call__): - self.assertEqual(signature(meth), meth.tip + "\ndoc") - self.assertEqual(signature(TC.cm), "(a)\ndoc") - self.assertEqual(signature(TC.sm), "(b)\ndoc") + self.assertEqual(signature(meth), meth.tip + doc) + self.assertEqual(signature(TC.cm), "(a)" + doc) + self.assertEqual(signature(TC.sm), "(b)" + doc) def test_bound_methods(self): # test that first parameter is correctly removed from argspec + doc = '\ndoc' if TC.__doc__ is not None else '' for meth, mtip in ((tc.t1, "()"), (tc.t4, "(*args)"), (tc.t6, "(self)"), (tc.__call__, '(ci)'), (tc, '(ci)'), (TC.cm, "(a)"),): - self.assertEqual(signature(meth), mtip + "\ndoc") + self.assertEqual(signature(meth), mtip + doc) def test_starred_parameter(self): # test that starred first parameter is *not* removed from argspec -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Apr 4 08:50:39 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Sat, 04 Apr 2015 06:50:39 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzIzODI1?= =?utf-8?q?=3A_Fixed_test=5Fidle_under_-OO=2E?= Message-ID: <20150404065038.34663.34607@psf.io> https://hg.python.org/cpython/rev/657ebef5b291 changeset: 95427:657ebef5b291 branch: 3.4 parent: 95417:e855bde79795 user: Serhiy Storchaka date: Sat Apr 04 09:47:31 2015 +0300 summary: Issue #23825: Fixed test_idle under -OO. files: Lib/idlelib/idle_test/test_calltips.py | 19 ++++++++----- 1 files changed, 12 insertions(+), 7 deletions(-) diff --git a/Lib/idlelib/idle_test/test_calltips.py b/Lib/idlelib/idle_test/test_calltips.py --- a/Lib/idlelib/idle_test/test_calltips.py +++ b/Lib/idlelib/idle_test/test_calltips.py @@ -52,7 +52,8 @@ def gtest(obj, out): self.assertEqual(signature(obj), out) - gtest(List, List.__doc__) + if List.__doc__ is not None: + gtest(List, List.__doc__) gtest(list.__new__, 'Create and return a new object. See help(type) for accurate signature.') gtest(list.__init__, @@ -66,7 +67,8 @@ gtest(SB(), default_tip) def test_signature_wrap(self): - self.assertEqual(signature(textwrap.TextWrapper), '''\ + if textwrap.TextWrapper.__doc__ is not None: + self.assertEqual(signature(textwrap.TextWrapper), '''\ (width=70, initial_indent='', subsequent_indent='', expand_tabs=True, replace_whitespace=True, fix_sentence_endings=False, break_long_words=True, drop_whitespace=True, break_on_hyphens=True, tabsize=8, *, max_lines=None, @@ -108,20 +110,23 @@ def t5(a, b=None, *args, **kw): 'doc' t5.tip = "(a, b=None, *args, **kw)" + doc = '\ndoc' if t1.__doc__ is not None else '' for func in (t1, t2, t3, t4, t5, TC): - self.assertEqual(signature(func), func.tip + '\ndoc') + self.assertEqual(signature(func), func.tip + doc) def test_methods(self): + doc = '\ndoc' if TC.__doc__ is not None else '' for meth in (TC.t1, TC.t2, TC.t3, TC.t4, TC.t5, TC.t6, TC.__call__): - self.assertEqual(signature(meth), meth.tip + "\ndoc") - self.assertEqual(signature(TC.cm), "(a)\ndoc") - self.assertEqual(signature(TC.sm), "(b)\ndoc") + self.assertEqual(signature(meth), meth.tip + doc) + self.assertEqual(signature(TC.cm), "(a)" + doc) + self.assertEqual(signature(TC.sm), "(b)" + doc) def test_bound_methods(self): # test that first parameter is correctly removed from argspec + doc = '\ndoc' if TC.__doc__ is not None else '' for meth, mtip in ((tc.t1, "()"), (tc.t4, "(*args)"), (tc.t6, "(self)"), (tc.__call__, '(ci)'), (tc, '(ci)'), (TC.cm, "(a)"),): - self.assertEqual(signature(meth), mtip + "\ndoc") + self.assertEqual(signature(meth), mtip + doc) def test_starred_parameter(self): # test that starred first parameter is *not* removed from argspec -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Apr 4 08:50:38 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Sat, 04 Apr 2015 06:50:38 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Moved_Misc/NEWS_entries_no?= =?utf-8?q?t_included_in_3=2E5=2E0_alpha_3_to_correct_section=2E?= Message-ID: <20150404065038.27432.40949@psf.io> https://hg.python.org/cpython/rev/c8688cd73983 changeset: 95425:c8688cd73983 user: Serhiy Storchaka date: Sat Apr 04 09:38:17 2015 +0300 summary: Moved Misc/NEWS entries not included in 3.5.0 alpha 3 to correct section. files: Misc/NEWS | 38 ++++++++++++++++++++------------------ 1 files changed, 20 insertions(+), 18 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -13,6 +13,9 @@ - Issue #22977: Fixed formatting Windows error messages on Wine. Patch by Martin Panter. +- Issue #23466: %c, %o, %x, and %X in bytes formatting now raise TypeError on + non-integer input. + Library ------- @@ -60,6 +63,17 @@ only calls fstat() once. Before fstat() was called twice, which was not necessary. +- Issue #23704: collections.deque() objects now support __add__, __mul__, and + __imul__(). + +- Issue #23171: csv.Writer.writerow() now supports arbitrary iterables. + +- Issue #23745: The new email header parser now handles duplicate MIME + parameter names without error, similar to how get_param behaves. + +- Issue #22117: Fix os.utime(), it now rounds the timestamp towards minus + infinity (-inf) instead of rounding towards zero. + Build ----- @@ -68,6 +82,12 @@ Tests ----- +- Issue #23799: Added test.support.start_threads() for running and + cleaning up multiple threads. + +- Issue #22390: test.regrtest now emits a warning if temporary files or + directories are left after running a test. + Tools/Demos ----------- @@ -88,9 +108,6 @@ Core and Builtins ----------------- -- Issue #23466: %c, %o, %x, and %X in bytes formatting now raise TypeError on - non-integer input. - - Issue #23573: Increased performance of string search operations (str.find, str.index, str.count, the in operator, str.split, str.partition) with arguments of different kinds (UCS1, UCS2, UCS4). @@ -111,14 +128,6 @@ Library ------- -- Issue #23171: csv.Writer.writerow() now supports arbitrary iterables. - -- Issue #23745: The new email header parser now handles duplicate MIME - parameter names without error, similar to how get_param behaves. - -- Issue #22117: Fix os.utime(), it now rounds the timestamp towards minus - infinity (-inf) instead of rounding towards zero. - - Issue #14260: The groupindex attribute of regular expression pattern object now is non-modifiable mapping. @@ -186,7 +195,6 @@ - Issue #23704: collections.deque() objects now support methods for index(), insert(), and copy(). This allows deques to be registered as a MutableSequence and it improves their substitutablity for lists. - Deques now also support __add__, __mul__, and __imul__(). - Issue #23715: :func:`signal.sigwaitinfo` and :func:`signal.sigtimedwait` are now retried when interrupted by a signal not in the *sigset* parameter, if @@ -264,12 +272,6 @@ Tests ----- -- Issue #23799: Added test.support.start_threads() for running and - cleaning up multiple threads. - -- Issue #22390: test.regrtest now emits a warning if temporary files or - directories are left after running a test. - - Issue #23583: Added tests for standard IO streams in IDLE. - Issue #22289: Prevent test_urllib2net failures due to ftp connection timeout. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Apr 4 08:50:39 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Sat, 04 Apr 2015 06:50:39 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2323825=3A_Fixed_test=5Fidle_under_-OO=2E?= Message-ID: <20150404065039.64679.45808@psf.io> https://hg.python.org/cpython/rev/e6654af0fc93 changeset: 95428:e6654af0fc93 parent: 95425:c8688cd73983 parent: 95427:657ebef5b291 user: Serhiy Storchaka date: Sat Apr 04 09:48:17 2015 +0300 summary: Issue #23825: Fixed test_idle under -OO. files: Lib/idlelib/idle_test/test_calltips.py | 19 ++++++++----- 1 files changed, 12 insertions(+), 7 deletions(-) diff --git a/Lib/idlelib/idle_test/test_calltips.py b/Lib/idlelib/idle_test/test_calltips.py --- a/Lib/idlelib/idle_test/test_calltips.py +++ b/Lib/idlelib/idle_test/test_calltips.py @@ -52,7 +52,8 @@ def gtest(obj, out): self.assertEqual(signature(obj), out) - gtest(List, List.__doc__) + if List.__doc__ is not None: + gtest(List, List.__doc__) gtest(list.__new__, 'Create and return a new object. See help(type) for accurate signature.') gtest(list.__init__, @@ -66,7 +67,8 @@ gtest(SB(), default_tip) def test_signature_wrap(self): - self.assertEqual(signature(textwrap.TextWrapper), '''\ + if textwrap.TextWrapper.__doc__ is not None: + self.assertEqual(signature(textwrap.TextWrapper), '''\ (width=70, initial_indent='', subsequent_indent='', expand_tabs=True, replace_whitespace=True, fix_sentence_endings=False, break_long_words=True, drop_whitespace=True, break_on_hyphens=True, tabsize=8, *, max_lines=None, @@ -108,20 +110,23 @@ def t5(a, b=None, *args, **kw): 'doc' t5.tip = "(a, b=None, *args, **kw)" + doc = '\ndoc' if t1.__doc__ is not None else '' for func in (t1, t2, t3, t4, t5, TC): - self.assertEqual(signature(func), func.tip + '\ndoc') + self.assertEqual(signature(func), func.tip + doc) def test_methods(self): + doc = '\ndoc' if TC.__doc__ is not None else '' for meth in (TC.t1, TC.t2, TC.t3, TC.t4, TC.t5, TC.t6, TC.__call__): - self.assertEqual(signature(meth), meth.tip + "\ndoc") - self.assertEqual(signature(TC.cm), "(a)\ndoc") - self.assertEqual(signature(TC.sm), "(b)\ndoc") + self.assertEqual(signature(meth), meth.tip + doc) + self.assertEqual(signature(TC.cm), "(a)" + doc) + self.assertEqual(signature(TC.sm), "(b)" + doc) def test_bound_methods(self): # test that first parameter is correctly removed from argspec + doc = '\ndoc' if TC.__doc__ is not None else '' for meth, mtip in ((tc.t1, "()"), (tc.t4, "(*args)"), (tc.t6, "(self)"), (tc.__call__, '(ci)'), (tc, '(ci)'), (TC.cm, "(a)"),): - self.assertEqual(signature(meth), mtip + "\ndoc") + self.assertEqual(signature(meth), mtip + doc) def test_starred_parameter(self): # test that starred first parameter is *not* removed from argspec -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Apr 4 09:07:43 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Sat, 04 Apr 2015 07:07:43 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzIzMzM4?= =?utf-8?q?=3A_Fixed_formatting_ctypes_error_messages_on_Cygwin=2E?= Message-ID: <20150404070743.16256.50115@psf.io> https://hg.python.org/cpython/rev/1f28c8cca671 changeset: 95429:1f28c8cca671 branch: 2.7 parent: 95426:912719dd684f user: Serhiy Storchaka date: Sat Apr 04 10:05:35 2015 +0300 summary: Issue #23338: Fixed formatting ctypes error messages on Cygwin. Patch by Makoto Kato. files: Misc/ACKS | 1 + Misc/NEWS | 3 +++ Modules/_ctypes/_ctypes.c | 4 ++-- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -685,6 +685,7 @@ Per ?yvind Karlsen Anton Kasyanov Lou Kates +Makoto Kato Hiroaki Kawai Brian Kearns Sebastien Keim diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -21,6 +21,9 @@ Library ------- +- Issue #23338: Fixed formatting ctypes error messages on Cygwin. + Patch by Makoto Kato. + - Issue #16840: Tkinter now supports 64-bit integers added in Tcl 8.4 and arbitrary precision integers added in Tcl 8.5. diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -642,7 +642,7 @@ #ifdef __CYGWIN__ /* dlerror() isn't very helpful on cygwin */ PyErr_Format(PyExc_ValueError, - "symbol '%s' not found (%s) ", + "symbol '%s' not found", name); #else PyErr_SetString(PyExc_ValueError, ctypes_dlerror()); @@ -3393,7 +3393,7 @@ #ifdef __CYGWIN__ /* dlerror() isn't very helpful on cygwin */ PyErr_Format(PyExc_AttributeError, - "function '%s' not found (%s) ", + "function '%s' not found", name); #else PyErr_SetString(PyExc_AttributeError, ctypes_dlerror()); -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Apr 4 09:07:43 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Sat, 04 Apr 2015 07:07:43 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzIzMzM4?= =?utf-8?q?=3A_Fixed_formatting_ctypes_error_messages_on_Cygwin=2E?= Message-ID: <20150404070743.75238.59954@psf.io> https://hg.python.org/cpython/rev/36eca0b259e2 changeset: 95430:36eca0b259e2 branch: 3.4 parent: 95427:657ebef5b291 user: Serhiy Storchaka date: Sat Apr 04 10:05:48 2015 +0300 summary: Issue #23338: Fixed formatting ctypes error messages on Cygwin. Patch by Makoto Kato. files: Misc/ACKS | 1 + Misc/NEWS | 3 +++ Modules/_ctypes/_ctypes.c | 4 ++-- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -692,6 +692,7 @@ Per ?yvind Karlsen Anton Kasyanov Lou Kates +Makoto Kato Hiroaki Kawai Sebastien Keim Ryan Kelly diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -24,6 +24,9 @@ Library ------- +- Issue #23338: Fixed formatting ctypes error messages on Cygwin. + Patch by Makoto Kato. + - Issue #16840: Tkinter now supports 64-bit integers added in Tcl 8.4 and arbitrary precision integers added in Tcl 8.5. diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -593,7 +593,7 @@ #ifdef __CYGWIN__ /* dlerror() isn't very helpful on cygwin */ PyErr_Format(PyExc_ValueError, - "symbol '%s' not found (%s) ", + "symbol '%s' not found", name); #else PyErr_SetString(PyExc_ValueError, ctypes_dlerror()); @@ -3279,7 +3279,7 @@ #ifdef __CYGWIN__ /* dlerror() isn't very helpful on cygwin */ PyErr_Format(PyExc_AttributeError, - "function '%s' not found (%s) ", + "function '%s' not found", name); #else PyErr_SetString(PyExc_AttributeError, ctypes_dlerror()); -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Apr 4 09:07:43 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Sat, 04 Apr 2015 07:07:43 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2323338=3A_Fixed_formatting_ctypes_error_messages?= =?utf-8?q?_on_Cygwin=2E?= Message-ID: <20150404070743.16513.30019@psf.io> https://hg.python.org/cpython/rev/3eb3a6d45251 changeset: 95431:3eb3a6d45251 parent: 95428:e6654af0fc93 parent: 95430:36eca0b259e2 user: Serhiy Storchaka date: Sat Apr 04 10:06:58 2015 +0300 summary: Issue #23338: Fixed formatting ctypes error messages on Cygwin. Patch by Makoto Kato. files: Misc/ACKS | 1 + Misc/NEWS | 3 +++ Modules/_ctypes/_ctypes.c | 4 ++-- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -703,6 +703,7 @@ Per ?yvind Karlsen Anton Kasyanov Lou Kates +Makoto Kato Hiroaki Kawai Brian Kearns Sebastien Keim diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -19,6 +19,9 @@ Library ------- +- Issue #23338: Fixed formatting ctypes error messages on Cygwin. + Patch by Makoto Kato. + - Issue #15582: inspect.getdoc() now follows inheritance chains. - Issue #2175: SAX parsers now support a character stream of InputSource object. diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -593,7 +593,7 @@ #ifdef __CYGWIN__ /* dlerror() isn't very helpful on cygwin */ PyErr_Format(PyExc_ValueError, - "symbol '%s' not found (%s) ", + "symbol '%s' not found", name); #else PyErr_SetString(PyExc_ValueError, ctypes_dlerror()); @@ -3280,7 +3280,7 @@ #ifdef __CYGWIN__ /* dlerror() isn't very helpful on cygwin */ PyErr_Format(PyExc_AttributeError, - "function '%s' not found (%s) ", + "function '%s' not found", name); #else PyErr_SetString(PyExc_AttributeError, ctypes_dlerror()); -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Apr 4 09:13:58 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Sat, 04 Apr 2015 07:13:58 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2310590=3A_xml=2Esa?= =?utf-8?q?x=2EparseString=28=29_now_supports_string_argument=2E?= Message-ID: <20150404071358.16248.90325@psf.io> https://hg.python.org/cpython/rev/fca669149d8a changeset: 95432:fca669149d8a user: Serhiy Storchaka date: Sat Apr 04 10:12:26 2015 +0300 summary: Issue #10590: xml.sax.parseString() now supports string argument. files: Doc/library/xml.sax.rst | 6 +++++- Lib/test/test_sax.py | 7 +++++++ Lib/xml/sax/__init__.py | 8 +++++--- Misc/NEWS | 2 ++ 4 files changed, 19 insertions(+), 4 deletions(-) diff --git a/Doc/library/xml.sax.rst b/Doc/library/xml.sax.rst --- a/Doc/library/xml.sax.rst +++ b/Doc/library/xml.sax.rst @@ -47,7 +47,11 @@ .. function:: parseString(string, handler, error_handler=handler.ErrorHandler()) Similar to :func:`parse`, but parses from a buffer *string* received as a - parameter. + parameter. *string* must be a :class:`str` instance or a + :term:`bytes-like object`. + + .. versionchanged:: 3.5 + Added support of :class:`str` instances. A typical SAX application uses three kinds of objects: readers, handlers and input sources. "Reader" in this context is another term for parser, i.e. some diff --git a/Lib/test/test_sax.py b/Lib/test/test_sax.py --- a/Lib/test/test_sax.py +++ b/Lib/test/test_sax.py @@ -200,6 +200,13 @@ parseString(s, XMLGenerator(result, 'utf-8')) self.assertEqual(result.getvalue(), xml_str(self.data, 'utf-8')) + def test_parseString_text(self): + encodings = ('us-ascii', 'iso-8859-1', 'utf-8', + 'utf-16', 'utf-16le', 'utf-16be') + for encoding in encodings: + self.check_parseString(xml_str(self.data, encoding)) + self.check_parseString(self.data) + def test_parseString_bytes(self): # UTF-8 is default encoding, US-ASCII is compatible with UTF-8, # UTF-16 is autodetected diff --git a/Lib/xml/sax/__init__.py b/Lib/xml/sax/__init__.py --- a/Lib/xml/sax/__init__.py +++ b/Lib/xml/sax/__init__.py @@ -33,8 +33,7 @@ parser.parse(source) def parseString(string, handler, errorHandler=ErrorHandler()): - from io import BytesIO - + import io if errorHandler is None: errorHandler = ErrorHandler() parser = make_parser() @@ -42,7 +41,10 @@ parser.setErrorHandler(errorHandler) inpsrc = InputSource() - inpsrc.setByteStream(BytesIO(string)) + if isinstance(string, str): + inpsrc.setCharacterStream(io.StringIO(string)) + else: + inpsrc.setByteStream(io.BytesIO(string)) parser.parse(inpsrc) # this is the parser list used by the make_parser function if no diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -19,6 +19,8 @@ Library ------- +- Issue #10590: xml.sax.parseString() now supports string argument. + - Issue #23338: Fixed formatting ctypes error messages on Cygwin. Patch by Makoto Kato. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Apr 4 09:37:48 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Sat, 04 Apr 2015 07:37:48 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_Open_files_in_?= =?utf-8?q?binary_mode_to_avoid_newlines_transformation=2E?= Message-ID: <20150404073748.98396.14521@psf.io> https://hg.python.org/cpython/rev/20c348914b22 changeset: 95433:20c348914b22 branch: 2.7 parent: 95429:1f28c8cca671 user: Serhiy Storchaka date: Sat Apr 04 10:36:15 2015 +0300 summary: Open files in binary mode to avoid newlines transformation. files: Lib/test/test_doctest.py | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_doctest.py b/Lib/test/test_doctest.py --- a/Lib/test/test_doctest.py +++ b/Lib/test/test_doctest.py @@ -2580,7 +2580,7 @@ >>> import tempfile, os >>> fn = tempfile.mktemp() - >>> with open(fn, 'w') as f: + >>> with open(fn, 'wb') as f: ... f.write('Test:\r\n\r\n >>> x = 1 + 1\r\n\r\nDone.\r\n') >>> doctest.testfile(fn, False) TestResults(failed=0, attempted=1) @@ -2589,7 +2589,7 @@ And now *nix line endings: >>> fn = tempfile.mktemp() - >>> with open(fn, 'w') as f: + >>> with open(fn, 'wb') as f: ... f.write('Test:\n\n >>> x = 1 + 1\n\nDone.\n') >>> doctest.testfile(fn, False) TestResults(failed=0, attempted=1) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Apr 4 09:37:48 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Sat, 04 Apr 2015 07:37:48 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E4=29=3A_Open_files_in_?= =?utf-8?q?binary_mode_to_avoid_newlines_transformation=2E?= Message-ID: <20150404073748.98378.54102@psf.io> https://hg.python.org/cpython/rev/f3fe5e9ee7e4 changeset: 95434:f3fe5e9ee7e4 branch: 3.4 parent: 95430:36eca0b259e2 user: Serhiy Storchaka date: Sat Apr 04 10:36:25 2015 +0300 summary: Open files in binary mode to avoid newlines transformation. files: Lib/test/test_doctest.py | 8 ++++---- 1 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Lib/test/test_doctest.py b/Lib/test/test_doctest.py --- a/Lib/test/test_doctest.py +++ b/Lib/test/test_doctest.py @@ -2624,8 +2624,8 @@ >>> import tempfile, os >>> fn = tempfile.mktemp() - >>> with open(fn, 'w') as f: - ... f.write('Test:\r\n\r\n >>> x = 1 + 1\r\n\r\nDone.\r\n') + >>> with open(fn, 'wb') as f: + ... f.write(b'Test:\r\n\r\n >>> x = 1 + 1\r\n\r\nDone.\r\n') 35 >>> doctest.testfile(fn, False) TestResults(failed=0, attempted=1) @@ -2634,8 +2634,8 @@ And now *nix line endings: >>> fn = tempfile.mktemp() - >>> with open(fn, 'w') as f: - ... f.write('Test:\n\n >>> x = 1 + 1\n\nDone.\n') + >>> with open(fn, 'wb') as f: + ... f.write(b'Test:\n\n >>> x = 1 + 1\n\nDone.\n') 30 >>> doctest.testfile(fn, False) TestResults(failed=0, attempted=1) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Apr 4 09:37:48 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Sat, 04 Apr 2015 07:37:48 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Open_files_in_binary_mode_to_avoid_newlines_transformati?= =?utf-8?b?b24u?= Message-ID: <20150404073748.15197.46494@psf.io> https://hg.python.org/cpython/rev/9db237815042 changeset: 95435:9db237815042 parent: 95432:fca669149d8a parent: 95434:f3fe5e9ee7e4 user: Serhiy Storchaka date: Sat Apr 04 10:36:50 2015 +0300 summary: Open files in binary mode to avoid newlines transformation. files: Lib/test/test_doctest.py | 8 ++++---- 1 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Lib/test/test_doctest.py b/Lib/test/test_doctest.py --- a/Lib/test/test_doctest.py +++ b/Lib/test/test_doctest.py @@ -2644,8 +2644,8 @@ >>> import tempfile, os >>> fn = tempfile.mktemp() - >>> with open(fn, 'w') as f: - ... f.write('Test:\r\n\r\n >>> x = 1 + 1\r\n\r\nDone.\r\n') + >>> with open(fn, 'wb') as f: + ... f.write(b'Test:\r\n\r\n >>> x = 1 + 1\r\n\r\nDone.\r\n') 35 >>> doctest.testfile(fn, False) TestResults(failed=0, attempted=1) @@ -2654,8 +2654,8 @@ And now *nix line endings: >>> fn = tempfile.mktemp() - >>> with open(fn, 'w') as f: - ... f.write('Test:\n\n >>> x = 1 + 1\n\nDone.\n') + >>> with open(fn, 'wb') as f: + ... f.write(b'Test:\n\n >>> x = 1 + 1\n\nDone.\n') 30 >>> doctest.testfile(fn, False) TestResults(failed=0, attempted=1) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Apr 4 10:03:46 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Sat, 04 Apr 2015 08:03:46 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2322831=3A_Use_=22w?= =?utf-8?q?ith=22_to_avoid_possible_fd_leaks=2E?= Message-ID: <20150404080346.16505.60986@psf.io> https://hg.python.org/cpython/rev/ea94f6c87f5d changeset: 95436:ea94f6c87f5d user: Serhiy Storchaka date: Sat Apr 04 11:01:02 2015 +0300 summary: Issue #22831: Use "with" to avoid possible fd leaks. files: Lib/binhex.py | 28 ++++++------- Lib/cgitb.py | 5 +- Lib/dbm/__init__.py | 6 +- Lib/http/cookiejar.py | 1 - Lib/platform.py | 65 +++++++++++++++--------------- Lib/pydoc.py | 5 +- Lib/sre_constants.py | 37 ++++++++--------- Lib/token.py | 12 ++-- Lib/trace.py | 40 +++++++++--------- Lib/xmlrpc/client.py | 28 +++++-------- 10 files changed, 107 insertions(+), 120 deletions(-) diff --git a/Lib/binhex.py b/Lib/binhex.py --- a/Lib/binhex.py +++ b/Lib/binhex.py @@ -229,14 +229,13 @@ finfo = getfileinfo(inp) ofp = BinHex(finfo, out) - ifp = io.open(inp, 'rb') - # XXXX Do textfile translation on non-mac systems - while True: - d = ifp.read(128000) - if not d: break - ofp.write(d) - ofp.close_data() - ifp.close() + with io.open(inp, 'rb') as ifp: + # XXXX Do textfile translation on non-mac systems + while True: + d = ifp.read(128000) + if not d: break + ofp.write(d) + ofp.close_data() ifp = openrsrc(inp, 'rb') while True: @@ -449,13 +448,12 @@ if not out: out = ifp.FName - ofp = io.open(out, 'wb') - # XXXX Do translation on non-mac systems - while True: - d = ifp.read(128000) - if not d: break - ofp.write(d) - ofp.close() + with io.open(out, 'wb') as ofp: + # XXXX Do translation on non-mac systems + while True: + d = ifp.read(128000) + if not d: break + ofp.write(d) ifp.close_data() d = ifp.read_rsrc(128000) diff --git a/Lib/cgitb.py b/Lib/cgitb.py --- a/Lib/cgitb.py +++ b/Lib/cgitb.py @@ -294,9 +294,8 @@ (fd, path) = tempfile.mkstemp(suffix=suffix, dir=self.logdir) try: - file = os.fdopen(fd, 'w') - file.write(doc) - file.close() + with os.fdopen(fd, 'w') as file: + file.write(doc) msg = '%s contains the description of this error.' % path except: msg = 'Tried to save traceback to %s, but failed.' % path diff --git a/Lib/dbm/__init__.py b/Lib/dbm/__init__.py --- a/Lib/dbm/__init__.py +++ b/Lib/dbm/__init__.py @@ -153,9 +153,9 @@ except OSError: return None - # Read the start of the file -- the magic number - s16 = f.read(16) - f.close() + with f: + # Read the start of the file -- the magic number + s16 = f.read(16) s = s16[0:4] # Return "" if not at least 4 bytes diff --git a/Lib/http/cookiejar.py b/Lib/http/cookiejar.py --- a/Lib/http/cookiejar.py +++ b/Lib/http/cookiejar.py @@ -1999,7 +1999,6 @@ magic = f.readline() if not self.magic_re.search(magic): - f.close() raise LoadError( "%r does not look like a Netscape format cookies file" % filename) diff --git a/Lib/platform.py b/Lib/platform.py --- a/Lib/platform.py +++ b/Lib/platform.py @@ -163,40 +163,39 @@ # here to work around problems with Cygwin not being # able to open symlinks for reading executable = os.path.realpath(executable) - f = open(executable, 'rb') - binary = f.read(chunksize) - pos = 0 - while 1: - if b'libc' in binary or b'GLIBC' in binary: - m = _libc_search.search(binary, pos) - else: - m = None - if not m: - binary = f.read(chunksize) - if not binary: - break - pos = 0 - continue - libcinit, glibc, glibcversion, so, threads, soversion = [ - s.decode('latin1') if s is not None else s - for s in m.groups()] - if libcinit and not lib: - lib = 'libc' - elif glibc: - if lib != 'glibc': - lib = 'glibc' - version = glibcversion - elif glibcversion > version: - version = glibcversion - elif so: - if lib != 'glibc': + with open(executable, 'rb') as f: + binary = f.read(chunksize) + pos = 0 + while 1: + if b'libc' in binary or b'GLIBC' in binary: + m = _libc_search.search(binary, pos) + else: + m = None + if not m: + binary = f.read(chunksize) + if not binary: + break + pos = 0 + continue + libcinit, glibc, glibcversion, so, threads, soversion = [ + s.decode('latin1') if s is not None else s + for s in m.groups()] + if libcinit and not lib: lib = 'libc' - if soversion and soversion > version: - version = soversion - if threads and version[-len(threads):] != threads: - version = version + threads - pos = m.end() - f.close() + elif glibc: + if lib != 'glibc': + lib = 'glibc' + version = glibcversion + elif glibcversion > version: + version = glibcversion + elif so: + if lib != 'glibc': + lib = 'libc' + if soversion and soversion > version: + version = soversion + if threads and version[-len(threads):] != threads: + version = version + threads + pos = m.end() return lib, version def _dist_try_harder(distname, version, id): diff --git a/Lib/pydoc.py b/Lib/pydoc.py --- a/Lib/pydoc.py +++ b/Lib/pydoc.py @@ -1639,9 +1639,8 @@ try: object, name = resolve(thing, forceload) page = html.page(describe(object), html.document(object, name)) - file = open(name + '.html', 'w', encoding='utf-8') - file.write(page) - file.close() + with open(name + '.html', 'w', encoding='utf-8') as file: + file.write(page) print('wrote', name + '.html') except (ImportError, ErrorDuringImport) as value: print(value) diff --git a/Lib/sre_constants.py b/Lib/sre_constants.py --- a/Lib/sre_constants.py +++ b/Lib/sre_constants.py @@ -182,8 +182,8 @@ items = sorted(d) for item in items: f.write("#define %s_%s %d\n" % (prefix, item, item)) - f = open("sre_constants.h", "w") - f.write("""\ + with open("sre_constants.h", "w") as f: + f.write("""\ /* * Secret Labs' Regular Expression Engine * @@ -199,25 +199,24 @@ """) - f.write("#define SRE_MAGIC %d\n" % MAGIC) + f.write("#define SRE_MAGIC %d\n" % MAGIC) - dump(f, OPCODES, "SRE_OP") - dump(f, ATCODES, "SRE") - dump(f, CHCODES, "SRE") + dump(f, OPCODES, "SRE_OP") + dump(f, ATCODES, "SRE") + dump(f, CHCODES, "SRE") - f.write("#define SRE_FLAG_TEMPLATE %d\n" % SRE_FLAG_TEMPLATE) - f.write("#define SRE_FLAG_IGNORECASE %d\n" % SRE_FLAG_IGNORECASE) - f.write("#define SRE_FLAG_LOCALE %d\n" % SRE_FLAG_LOCALE) - f.write("#define SRE_FLAG_MULTILINE %d\n" % SRE_FLAG_MULTILINE) - f.write("#define SRE_FLAG_DOTALL %d\n" % SRE_FLAG_DOTALL) - f.write("#define SRE_FLAG_UNICODE %d\n" % SRE_FLAG_UNICODE) - f.write("#define SRE_FLAG_VERBOSE %d\n" % SRE_FLAG_VERBOSE) - f.write("#define SRE_FLAG_DEBUG %d\n" % SRE_FLAG_DEBUG) - f.write("#define SRE_FLAG_ASCII %d\n" % SRE_FLAG_ASCII) + f.write("#define SRE_FLAG_TEMPLATE %d\n" % SRE_FLAG_TEMPLATE) + f.write("#define SRE_FLAG_IGNORECASE %d\n" % SRE_FLAG_IGNORECASE) + f.write("#define SRE_FLAG_LOCALE %d\n" % SRE_FLAG_LOCALE) + f.write("#define SRE_FLAG_MULTILINE %d\n" % SRE_FLAG_MULTILINE) + f.write("#define SRE_FLAG_DOTALL %d\n" % SRE_FLAG_DOTALL) + f.write("#define SRE_FLAG_UNICODE %d\n" % SRE_FLAG_UNICODE) + f.write("#define SRE_FLAG_VERBOSE %d\n" % SRE_FLAG_VERBOSE) + f.write("#define SRE_FLAG_DEBUG %d\n" % SRE_FLAG_DEBUG) + f.write("#define SRE_FLAG_ASCII %d\n" % SRE_FLAG_ASCII) - f.write("#define SRE_INFO_PREFIX %d\n" % SRE_INFO_PREFIX) - f.write("#define SRE_INFO_LITERAL %d\n" % SRE_INFO_LITERAL) - f.write("#define SRE_INFO_CHARSET %d\n" % SRE_INFO_CHARSET) + f.write("#define SRE_INFO_PREFIX %d\n" % SRE_INFO_PREFIX) + f.write("#define SRE_INFO_LITERAL %d\n" % SRE_INFO_LITERAL) + f.write("#define SRE_INFO_CHARSET %d\n" % SRE_INFO_CHARSET) - f.close() print("done") diff --git a/Lib/token.py b/Lib/token.py --- a/Lib/token.py +++ b/Lib/token.py @@ -97,8 +97,8 @@ except OSError as err: sys.stdout.write("I/O error: %s\n" % str(err)) sys.exit(1) - lines = fp.read().split("\n") - fp.close() + with fp: + lines = fp.read().split("\n") prog = re.compile( "#define[ \t][ \t]*([A-Z0-9][A-Z0-9_]*)[ \t][ \t]*([0-9][0-9]*)", re.IGNORECASE) @@ -116,8 +116,8 @@ except OSError as err: sys.stderr.write("I/O error: %s\n" % str(err)) sys.exit(2) - format = fp.read().split("\n") - fp.close() + with fp: + format = fp.read().split("\n") try: start = format.index("#--start constants--") + 1 end = format.index("#--end constants--") @@ -133,8 +133,8 @@ except OSError as err: sys.stderr.write("I/O error: %s\n" % str(err)) sys.exit(4) - fp.write("\n".join(format)) - fp.close() + with fp: + fp.write("\n".join(format)) if __name__ == "__main__": diff --git a/Lib/trace.py b/Lib/trace.py --- a/Lib/trace.py +++ b/Lib/trace.py @@ -232,8 +232,8 @@ if self.infile: # Try to merge existing counts file. try: - counts, calledfuncs, callers = \ - pickle.load(open(self.infile, 'rb')) + with open(self.infile, 'rb') as f: + counts, calledfuncs, callers = pickle.load(f) self.update(self.__class__(counts, calledfuncs, callers)) except (OSError, EOFError, ValueError) as err: print(("Skipping counts file %r: %s" @@ -361,26 +361,26 @@ n_lines = 0 n_hits = 0 - for lineno, line in enumerate(lines, 1): - # do the blank/comment match to try to mark more lines - # (help the reader find stuff that hasn't been covered) - if lineno in lines_hit: - outfile.write("%5d: " % lines_hit[lineno]) - n_hits += 1 - n_lines += 1 - elif rx_blank.match(line): - outfile.write(" ") - else: - # lines preceded by no marks weren't hit - # Highlight them if so indicated, unless the line contains - # #pragma: NO COVER - if lineno in lnotab and not PRAGMA_NOCOVER in line: - outfile.write(">>>>>> ") + with outfile: + for lineno, line in enumerate(lines, 1): + # do the blank/comment match to try to mark more lines + # (help the reader find stuff that hasn't been covered) + if lineno in lines_hit: + outfile.write("%5d: " % lines_hit[lineno]) + n_hits += 1 n_lines += 1 + elif rx_blank.match(line): + outfile.write(" ") else: - outfile.write(" ") - outfile.write(line.expandtabs(8)) - outfile.close() + # lines preceded by no marks weren't hit + # Highlight them if so indicated, unless the line contains + # #pragma: NO COVER + if lineno in lnotab and not PRAGMA_NOCOVER in line: + outfile.write(">>>>>> ") + n_lines += 1 + else: + outfile.write(" ") + outfile.write(line.expandtabs(8)) return n_hits, n_lines diff --git a/Lib/xmlrpc/client.py b/Lib/xmlrpc/client.py --- a/Lib/xmlrpc/client.py +++ b/Lib/xmlrpc/client.py @@ -1010,12 +1010,9 @@ if not gzip: raise NotImplementedError f = BytesIO() - gzf = gzip.GzipFile(mode="wb", fileobj=f, compresslevel=1) - gzf.write(data) - gzf.close() - encoded = f.getvalue() - f.close() - return encoded + with gzip.GzipFile(mode="wb", fileobj=f, compresslevel=1) as gzf: + gzf.write(data) + return f.getvalue() ## # Decode a string using the gzip content encoding such as specified by the @@ -1036,17 +1033,14 @@ """ if not gzip: raise NotImplementedError - f = BytesIO(data) - gzf = gzip.GzipFile(mode="rb", fileobj=f) - try: - if max_decode < 0: # no limit - decoded = gzf.read() - else: - decoded = gzf.read(max_decode + 1) - except OSError: - raise ValueError("invalid data") - f.close() - gzf.close() + with gzip.GzipFile(mode="rb", fileobj=BytesIO(data)) as gzf: + try: + if max_decode < 0: # no limit + decoded = gzf.read() + else: + decoded = gzf.read(max_decode + 1) + except OSError: + raise ValueError("invalid data") if max_decode >= 0 and len(decoded) > max_decode: raise ValueError("max gzipped payload length exceeded") return decoded -- Repository URL: https://hg.python.org/cpython From solipsis at pitrou.net Sat Apr 4 10:47:59 2015 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Sat, 04 Apr 2015 08:47:59 +0000 Subject: [Python-checkins] Daily reference leaks (e10ad4d4d490): sum=333 Message-ID: <20150404084759.15211.4930@psf.io> results for e10ad4d4d490 on branch "default" -------------------------------------------- test_collections leaked [0, -4, 0] references, sum=-4 test_collections leaked [0, -2, 0] memory blocks, sum=-2 test_deque leaked [91, 91, 91] references, sum=273 test_deque leaked [21, 21, 21] memory blocks, sum=63 test_functools leaked [0, 0, 3] memory blocks, sum=3 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogK5OSop', '--timeout', '7200'] From python-checkins at python.org Sat Apr 4 11:49:17 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Sat, 04 Apr 2015 09:49:17 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Fixed_test=5Fenum_for_issu?= =?utf-8?b?ZSAjMTU1ODIu?= Message-ID: <20150404094917.16513.54156@psf.io> https://hg.python.org/cpython/rev/47a61a1c97b3 changeset: 95440:47a61a1c97b3 user: Serhiy Storchaka date: Sat Apr 04 12:48:04 2015 +0300 summary: Fixed test_enum for issue #15582. files: Lib/test/test_enum.py | 4 ++++ 1 files changed, 4 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_enum.py b/Lib/test/test_enum.py --- a/Lib/test/test_enum.py +++ b/Lib/test/test_enum.py @@ -1560,6 +1560,10 @@ Help on class Color in module %s: class Color(enum.Enum) + | Generic enumeration. + |\x20\x20 + | Derive from this class to define new enumerations. + |\x20\x20 | Method resolution order: | Color | enum.Enum -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Apr 4 11:49:17 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Sat, 04 Apr 2015 09:49:17 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?b?KTogSXNzdWUgIzE1MTMzOiBfdGtpbnRlci50a2FwcC5nZXRib29sZWFuKCkg?= =?utf-8?q?now_supports_Tcl=5FObj_and_always?= Message-ID: <20150404094917.75264.55431@psf.io> https://hg.python.org/cpython/rev/38747f32fa7b changeset: 95439:38747f32fa7b parent: 95436:ea94f6c87f5d parent: 95438:117f45749359 user: Serhiy Storchaka date: Sat Apr 04 12:44:30 2015 +0300 summary: Issue #15133: _tkinter.tkapp.getboolean() now supports Tcl_Obj and always returns bool. tkinter.BooleanVar now validates input values (accepted bool, int, str, and Tcl_Obj). tkinter.BooleanVar.get() now always returns bool. files: Lib/test/test_tcl.py | 3 +- Lib/tkinter/__init__.py | 5 + Lib/tkinter/test/test_tkinter/test_variables.py | 34 ++++++++- Lib/tkinter/ttk.py | 6 +- Misc/NEWS | 4 + Modules/_tkinter.c | 23 ++++-- 6 files changed, 58 insertions(+), 17 deletions(-) diff --git a/Lib/test/test_tcl.py b/Lib/test/test_tcl.py --- a/Lib/test/test_tcl.py +++ b/Lib/test/test_tcl.py @@ -179,7 +179,8 @@ tcl = self.interp.tk self.assertIs(tcl.getboolean('on'), True) self.assertIs(tcl.getboolean('1'), True) - self.assertEqual(tcl.getboolean(42), 42) + self.assertIs(tcl.getboolean(42), True) + self.assertIs(tcl.getboolean(0), False) self.assertRaises(TypeError, tcl.getboolean) self.assertRaises(TypeError, tcl.getboolean, 'on', '1') self.assertRaises(TypeError, tcl.getboolean, b'on') diff --git a/Lib/tkinter/__init__.py b/Lib/tkinter/__init__.py --- a/Lib/tkinter/__init__.py +++ b/Lib/tkinter/__init__.py @@ -391,6 +391,11 @@ """ Variable.__init__(self, master, value, name) + def set(self, value): + """Set the variable to VALUE.""" + return self._tk.globalsetvar(self._name, self._tk.getboolean(value)) + initialize = set + def get(self): """Return the value of the variable as a bool.""" try: diff --git a/Lib/tkinter/test/test_tkinter/test_variables.py b/Lib/tkinter/test/test_tkinter/test_variables.py --- a/Lib/tkinter/test/test_tkinter/test_variables.py +++ b/Lib/tkinter/test/test_tkinter/test_variables.py @@ -1,6 +1,7 @@ import unittest -from tkinter import Variable, StringVar, IntVar, DoubleVar, BooleanVar, Tcl +from tkinter import (Variable, StringVar, IntVar, DoubleVar, BooleanVar, Tcl, + TclError) class Var(Variable): @@ -159,16 +160,41 @@ def test_default(self): v = BooleanVar(self.root) - self.assertEqual(False, v.get()) + self.assertIs(v.get(), False) def test_get(self): v = BooleanVar(self.root, True, "name") - self.assertAlmostEqual(True, v.get()) + self.assertIs(v.get(), True) self.root.globalsetvar("name", "0") - self.assertAlmostEqual(False, v.get()) + self.assertIs(v.get(), False) + self.root.globalsetvar("name", 42 if self.root.wantobjects() else 1) + self.assertIs(v.get(), True) + self.root.globalsetvar("name", 0) + self.assertIs(v.get(), False) + self.root.globalsetvar("name", "on") + self.assertIs(v.get(), True) + + def test_set(self): + true = 1 if self.root.wantobjects() else "1" + false = 0 if self.root.wantobjects() else "0" + v = BooleanVar(self.root, name="name") + v.set(True) + self.assertEqual(self.root.globalgetvar("name"), true) + v.set("0") + self.assertEqual(self.root.globalgetvar("name"), false) + v.set(42) + self.assertEqual(self.root.globalgetvar("name"), true) + v.set(0) + self.assertEqual(self.root.globalgetvar("name"), false) + v.set("on") + self.assertEqual(self.root.globalgetvar("name"), true) def test_invalid_value_domain(self): + false = 0 if self.root.wantobjects() else "0" v = BooleanVar(self.root, name="name") + with self.assertRaises(TclError): + v.set("value") + self.assertEqual(self.root.globalgetvar("name"), false) self.root.globalsetvar("name", "value") with self.assertRaises(ValueError): v.get() diff --git a/Lib/tkinter/ttk.py b/Lib/tkinter/ttk.py --- a/Lib/tkinter/ttk.py +++ b/Lib/tkinter/ttk.py @@ -573,7 +573,7 @@ if ret and callback: return callback(*args, **kw) - return bool(ret) + return ret def state(self, statespec=None): @@ -681,7 +681,7 @@ """Force revalidation, independent of the conditions specified by the validate option. Returns False if validation fails, True if it succeeds. Sets or clears the invalid state accordingly.""" - return bool(self.tk.getboolean(self.tk.call(self._w, "validate"))) + return self.tk.getboolean(self.tk.call(self._w, "validate")) class Combobox(Entry): @@ -1231,7 +1231,7 @@ def exists(self, item): """Returns True if the specified item is present in the tree, False otherwise.""" - return bool(self.tk.getboolean(self.tk.call(self._w, "exists", item))) + return self.tk.getboolean(self.tk.call(self._w, "exists", item)) def focus(self, item=None): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -19,6 +19,10 @@ Library ------- +- Issue #15133: _tkinter.tkapp.getboolean() now supports Tcl_Obj and always + returns bool. tkinter.BooleanVar now validates input values (accepted bool, + int, str, and Tcl_Obj). tkinter.BooleanVar.get() now always returns bool. + - Issue #10590: xml.sax.parseString() now supports string argument. - Issue #23338: Fixed formatting ctypes error messages on Cygwin. diff --git a/Modules/_tkinter.c b/Modules/_tkinter.c --- a/Modules/_tkinter.c +++ b/Modules/_tkinter.c @@ -1934,19 +1934,24 @@ } static PyObject * -Tkapp_GetBoolean(PyObject *self, PyObject *args) +Tkapp_GetBoolean(PyObject *self, PyObject *arg) { char *s; int v; - if (PyTuple_Size(args) == 1) { - PyObject *o = PyTuple_GetItem(args, 0); - if (PyLong_Check(o)) { - Py_INCREF(o); - return o; - } + if (PyLong_Check(arg)) { /* int or bool */ + return PyBool_FromLong(Py_SIZE(arg) != 0); } - if (!PyArg_ParseTuple(args, "s:getboolean", &s)) + + if (PyTclObject_Check(arg)) { + if (Tcl_GetBooleanFromObj(Tkapp_Interp(self), + ((PyTclObject*)arg)->value, + &v) == TCL_ERROR) + return Tkinter_Error(self); + return PyBool_FromLong(v); + } + + if (!PyArg_Parse(arg, "s:getboolean", &s)) return NULL; CHECK_STRING_LENGTH(s); if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR) @@ -2862,7 +2867,7 @@ {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS}, {"getint", Tkapp_GetInt, METH_VARARGS}, {"getdouble", Tkapp_GetDouble, METH_VARARGS}, - {"getboolean", Tkapp_GetBoolean, METH_VARARGS}, + {"getboolean", Tkapp_GetBoolean, METH_O}, {"exprstring", Tkapp_ExprString, METH_VARARGS}, {"exprlong", Tkapp_ExprLong, METH_VARARGS}, {"exprdouble", Tkapp_ExprDouble, METH_VARARGS}, -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Apr 4 11:49:16 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Sat, 04 Apr 2015 09:49:16 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzE1MTMz?= =?utf-8?q?=3A_=5Ftkinter=2Etkapp=2Egetboolean=28=29_now_supports_Tcl=5FOb?= =?utf-8?q?j_and_always?= Message-ID: <20150404094916.29541.1747@psf.io> https://hg.python.org/cpython/rev/117f45749359 changeset: 95438:117f45749359 branch: 3.4 parent: 95434:f3fe5e9ee7e4 user: Serhiy Storchaka date: Sat Apr 04 12:43:01 2015 +0300 summary: Issue #15133: _tkinter.tkapp.getboolean() now supports Tcl_Obj and always returns bool. tkinter.BooleanVar now validates input values (accepted bool, int, str, and Tcl_Obj). tkinter.BooleanVar.get() now always returns bool. files: Lib/test/test_tcl.py | 3 +- Lib/tkinter/__init__.py | 5 + Lib/tkinter/test/test_tkinter/test_variables.py | 34 ++++++++- Lib/tkinter/ttk.py | 6 +- Misc/NEWS | 4 + Modules/_tkinter.c | 23 ++++-- 6 files changed, 58 insertions(+), 17 deletions(-) diff --git a/Lib/test/test_tcl.py b/Lib/test/test_tcl.py --- a/Lib/test/test_tcl.py +++ b/Lib/test/test_tcl.py @@ -181,7 +181,8 @@ tcl = self.interp.tk self.assertIs(tcl.getboolean('on'), True) self.assertIs(tcl.getboolean('1'), True) - self.assertEqual(tcl.getboolean(42), 42) + self.assertIs(tcl.getboolean(42), True) + self.assertIs(tcl.getboolean(0), False) self.assertRaises(TypeError, tcl.getboolean) self.assertRaises(TypeError, tcl.getboolean, 'on', '1') self.assertRaises(TypeError, tcl.getboolean, b'on') diff --git a/Lib/tkinter/__init__.py b/Lib/tkinter/__init__.py --- a/Lib/tkinter/__init__.py +++ b/Lib/tkinter/__init__.py @@ -391,6 +391,11 @@ """ Variable.__init__(self, master, value, name) + def set(self, value): + """Set the variable to VALUE.""" + return self._tk.globalsetvar(self._name, self._tk.getboolean(value)) + initialize = set + def get(self): """Return the value of the variable as a bool.""" try: diff --git a/Lib/tkinter/test/test_tkinter/test_variables.py b/Lib/tkinter/test/test_tkinter/test_variables.py --- a/Lib/tkinter/test/test_tkinter/test_variables.py +++ b/Lib/tkinter/test/test_tkinter/test_variables.py @@ -1,6 +1,7 @@ import unittest -from tkinter import Variable, StringVar, IntVar, DoubleVar, BooleanVar, Tcl +from tkinter import (Variable, StringVar, IntVar, DoubleVar, BooleanVar, Tcl, + TclError) class Var(Variable): @@ -159,16 +160,41 @@ def test_default(self): v = BooleanVar(self.root) - self.assertEqual(False, v.get()) + self.assertIs(v.get(), False) def test_get(self): v = BooleanVar(self.root, True, "name") - self.assertAlmostEqual(True, v.get()) + self.assertIs(v.get(), True) self.root.globalsetvar("name", "0") - self.assertAlmostEqual(False, v.get()) + self.assertIs(v.get(), False) + self.root.globalsetvar("name", 42 if self.root.wantobjects() else 1) + self.assertIs(v.get(), True) + self.root.globalsetvar("name", 0) + self.assertIs(v.get(), False) + self.root.globalsetvar("name", "on") + self.assertIs(v.get(), True) + + def test_set(self): + true = 1 if self.root.wantobjects() else "1" + false = 0 if self.root.wantobjects() else "0" + v = BooleanVar(self.root, name="name") + v.set(True) + self.assertEqual(self.root.globalgetvar("name"), true) + v.set("0") + self.assertEqual(self.root.globalgetvar("name"), false) + v.set(42) + self.assertEqual(self.root.globalgetvar("name"), true) + v.set(0) + self.assertEqual(self.root.globalgetvar("name"), false) + v.set("on") + self.assertEqual(self.root.globalgetvar("name"), true) def test_invalid_value_domain(self): + false = 0 if self.root.wantobjects() else "0" v = BooleanVar(self.root, name="name") + with self.assertRaises(TclError): + v.set("value") + self.assertEqual(self.root.globalgetvar("name"), false) self.root.globalsetvar("name", "value") with self.assertRaises(ValueError): v.get() diff --git a/Lib/tkinter/ttk.py b/Lib/tkinter/ttk.py --- a/Lib/tkinter/ttk.py +++ b/Lib/tkinter/ttk.py @@ -573,7 +573,7 @@ if ret and callback: return callback(*args, **kw) - return bool(ret) + return ret def state(self, statespec=None): @@ -681,7 +681,7 @@ """Force revalidation, independent of the conditions specified by the validate option. Returns False if validation fails, True if it succeeds. Sets or clears the invalid state accordingly.""" - return bool(self.tk.getboolean(self.tk.call(self._w, "validate"))) + return self.tk.getboolean(self.tk.call(self._w, "validate")) class Combobox(Entry): @@ -1231,7 +1231,7 @@ def exists(self, item): """Returns True if the specified item is present in the tree, False otherwise.""" - return bool(self.tk.getboolean(self.tk.call(self._w, "exists", item))) + return self.tk.getboolean(self.tk.call(self._w, "exists", item)) def focus(self, item=None): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -24,6 +24,10 @@ Library ------- +- Issue #15133: _tkinter.tkapp.getboolean() now supports Tcl_Obj and always + returns bool. tkinter.BooleanVar now validates input values (accepted bool, + int, str, and Tcl_Obj). tkinter.BooleanVar.get() now always returns bool. + - Issue #23338: Fixed formatting ctypes error messages on Cygwin. Patch by Makoto Kato. diff --git a/Modules/_tkinter.c b/Modules/_tkinter.c --- a/Modules/_tkinter.c +++ b/Modules/_tkinter.c @@ -1929,19 +1929,24 @@ } static PyObject * -Tkapp_GetBoolean(PyObject *self, PyObject *args) +Tkapp_GetBoolean(PyObject *self, PyObject *arg) { char *s; int v; - if (PyTuple_Size(args) == 1) { - PyObject *o = PyTuple_GetItem(args, 0); - if (PyLong_Check(o)) { - Py_INCREF(o); - return o; - } + if (PyLong_Check(arg)) { /* int or bool */ + return PyBool_FromLong(Py_SIZE(arg) != 0); } - if (!PyArg_ParseTuple(args, "s:getboolean", &s)) + + if (PyTclObject_Check(arg)) { + if (Tcl_GetBooleanFromObj(Tkapp_Interp(self), + ((PyTclObject*)arg)->value, + &v) == TCL_ERROR) + return Tkinter_Error(self); + return PyBool_FromLong(v); + } + + if (!PyArg_Parse(arg, "s:getboolean", &s)) return NULL; CHECK_STRING_LENGTH(s); if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR) @@ -2854,7 +2859,7 @@ {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS}, {"getint", Tkapp_GetInt, METH_VARARGS}, {"getdouble", Tkapp_GetDouble, METH_VARARGS}, - {"getboolean", Tkapp_GetBoolean, METH_VARARGS}, + {"getboolean", Tkapp_GetBoolean, METH_O}, {"exprstring", Tkapp_ExprString, METH_VARARGS}, {"exprlong", Tkapp_ExprLong, METH_VARARGS}, {"exprdouble", Tkapp_ExprDouble, METH_VARARGS}, -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Apr 4 11:49:16 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Sat, 04 Apr 2015 09:49:16 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzE1MTMz?= =?utf-8?q?=3A_=5Ftkinter=2Etkapp=2Egetboolean=28=29_now_supports_long_and?= =?utf-8?q?_Tcl=5FObj_and?= Message-ID: <20150404094916.64729.34171@psf.io> https://hg.python.org/cpython/rev/dedf481ec2be changeset: 95437:dedf481ec2be branch: 2.7 parent: 95433:20c348914b22 user: Serhiy Storchaka date: Sat Apr 04 12:42:25 2015 +0300 summary: Issue #15133: _tkinter.tkapp.getboolean() now supports long and Tcl_Obj and always returns bool. tkinter.BooleanVar now validates input values (accepted bool, int, long, str, unicode, and Tcl_Obj). tkinter.BooleanVar.get() now always returns bool. files: Lib/lib-tk/Tkinter.py | 4 + Lib/lib-tk/test/test_tkinter/test_variables.py | 50 +++++++++- Lib/lib-tk/ttk.py | 6 +- Lib/test/test_tcl.py | 7 +- Misc/NEWS | 5 + Modules/_tkinter.c | 25 +++- 6 files changed, 80 insertions(+), 17 deletions(-) diff --git a/Lib/lib-tk/Tkinter.py b/Lib/lib-tk/Tkinter.py --- a/Lib/lib-tk/Tkinter.py +++ b/Lib/lib-tk/Tkinter.py @@ -401,6 +401,10 @@ """ Variable.__init__(self, master, value, name) + def set(self, value): + """Set the variable to VALUE.""" + return self._tk.globalsetvar(self._name, self._tk.getboolean(value)) + def get(self): """Return the value of the variable as a bool.""" return self._tk.getboolean(self._tk.globalgetvar(self._name)) diff --git a/Lib/lib-tk/test/test_tkinter/test_variables.py b/Lib/lib-tk/test/test_tkinter/test_variables.py --- a/Lib/lib-tk/test/test_tkinter/test_variables.py +++ b/Lib/lib-tk/test/test_tkinter/test_variables.py @@ -1,6 +1,7 @@ import unittest -from Tkinter import Variable, StringVar, IntVar, DoubleVar, BooleanVar, Tcl, TclError +from Tkinter import (Variable, StringVar, IntVar, DoubleVar, BooleanVar, Tcl, + TclError) class TestBase(unittest.TestCase): @@ -139,16 +140,57 @@ def test_default(self): v = BooleanVar(self.root) - self.assertEqual(False, v.get()) + self.assertIs(v.get(), False) def test_get(self): v = BooleanVar(self.root, True, "name") - self.assertAlmostEqual(True, v.get()) + self.assertIs(v.get(), True) self.root.globalsetvar("name", "0") - self.assertAlmostEqual(False, v.get()) + self.assertIs(v.get(), False) + self.root.globalsetvar("name", 42 if self.root.wantobjects() else 1) + self.assertIs(v.get(), True) + self.root.globalsetvar("name", 0) + self.assertIs(v.get(), False) + self.root.globalsetvar("name", 42L if self.root.wantobjects() else 1L) + self.assertIs(v.get(), True) + self.root.globalsetvar("name", 0L) + self.assertIs(v.get(), False) + self.root.globalsetvar("name", "on") + self.assertIs(v.get(), True) + self.root.globalsetvar("name", u"0") + self.assertIs(v.get(), False) + self.root.globalsetvar("name", u"on") + self.assertIs(v.get(), True) + + def test_set(self): + true = 1 if self.root.wantobjects() else "1" + false = 0 if self.root.wantobjects() else "0" + v = BooleanVar(self.root, name="name") + v.set(True) + self.assertEqual(self.root.globalgetvar("name"), true) + v.set("0") + self.assertEqual(self.root.globalgetvar("name"), false) + v.set(42) + self.assertEqual(self.root.globalgetvar("name"), true) + v.set(0) + self.assertEqual(self.root.globalgetvar("name"), false) + v.set(42L) + self.assertEqual(self.root.globalgetvar("name"), true) + v.set(0L) + self.assertEqual(self.root.globalgetvar("name"), false) + v.set("on") + self.assertEqual(self.root.globalgetvar("name"), true) + v.set(u"0") + self.assertEqual(self.root.globalgetvar("name"), false) + v.set(u"on") + self.assertEqual(self.root.globalgetvar("name"), true) def test_invalid_value_domain(self): + false = 0 if self.root.wantobjects() else "0" v = BooleanVar(self.root, name="name") + with self.assertRaises(TclError): + v.set("value") + self.assertEqual(self.root.globalgetvar("name"), false) self.root.globalsetvar("name", "value") with self.assertRaises(TclError): v.get() 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 @@ -575,7 +575,7 @@ if ret and callback: return callback(*args, **kw) - return bool(ret) + return ret def state(self, statespec=None): @@ -683,7 +683,7 @@ """Force revalidation, independent of the conditions specified by the validate option. Returns False if validation fails, True if it succeeds. Sets or clears the invalid state accordingly.""" - return bool(self.tk.getboolean(self.tk.call(self._w, "validate"))) + return self.tk.getboolean(self.tk.call(self._w, "validate")) class Combobox(Entry): @@ -1233,7 +1233,7 @@ def exists(self, item): """Returns True if the specified item is present in the tree, False otherwise.""" - return bool(self.tk.getboolean(self.tk.call(self._w, "exists", item))) + return self.tk.getboolean(self.tk.call(self._w, "exists", item)) def focus(self, item=None): diff --git a/Lib/test/test_tcl.py b/Lib/test/test_tcl.py --- a/Lib/test/test_tcl.py +++ b/Lib/test/test_tcl.py @@ -182,7 +182,12 @@ tcl = self.interp.tk self.assertIs(tcl.getboolean('on'), True) self.assertIs(tcl.getboolean('1'), True) - self.assertEqual(tcl.getboolean(42), 42) + self.assertIs(tcl.getboolean(u'on'), True) + self.assertIs(tcl.getboolean(u'1'), True) + self.assertIs(tcl.getboolean(42), True) + self.assertIs(tcl.getboolean(0), False) + self.assertIs(tcl.getboolean(42L), True) + self.assertIs(tcl.getboolean(0L), False) self.assertRaises(TypeError, tcl.getboolean) self.assertRaises(TypeError, tcl.getboolean, 'on', '1') self.assertRaises(TypeError, tcl.getboolean, 1.0) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -21,6 +21,11 @@ Library ------- +- Issue #15133: _tkinter.tkapp.getboolean() now supports long and Tcl_Obj and + always returns bool. tkinter.BooleanVar now validates input values (accepted + bool, int, long, str, unicode, and Tcl_Obj). tkinter.BooleanVar.get() now + always returns bool. + - Issue #23338: Fixed formatting ctypes error messages on Cygwin. Patch by Makoto Kato. diff --git a/Modules/_tkinter.c b/Modules/_tkinter.c --- a/Modules/_tkinter.c +++ b/Modules/_tkinter.c @@ -2163,19 +2163,26 @@ } static PyObject * -Tkapp_GetBoolean(PyObject *self, PyObject *args) +Tkapp_GetBoolean(PyObject *self, PyObject *arg) { char *s; int v; - if (PyTuple_Size(args) == 1) { - PyObject *o = PyTuple_GetItem(args, 0); - if (PyInt_Check(o)) { - Py_INCREF(o); - return o; - } + if (PyInt_Check(arg)) /* int or bool */ + return PyBool_FromLong(PyInt_AS_LONG(arg)); + + if (PyLong_Check(arg)) + return PyBool_FromLong(Py_SIZE(arg) != 0); + + if (PyTclObject_Check(arg)) { + if (Tcl_GetBooleanFromObj(Tkapp_Interp(self), + ((PyTclObject*)arg)->value, + &v) == TCL_ERROR) + return Tkinter_Error(self); + return PyBool_FromLong(v); } - if (!PyArg_ParseTuple(args, "s:getboolean", &s)) + + if (!PyArg_Parse(arg, "s:getboolean", &s)) return NULL; CHECK_STRING_LENGTH(s); if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR) @@ -3236,7 +3243,7 @@ {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS}, {"getint", Tkapp_GetInt, METH_VARARGS}, {"getdouble", Tkapp_GetDouble, METH_VARARGS}, - {"getboolean", Tkapp_GetBoolean, METH_VARARGS}, + {"getboolean", Tkapp_GetBoolean, METH_O}, {"exprstring", Tkapp_ExprString, METH_VARARGS}, {"exprlong", Tkapp_ExprLong, METH_VARARGS}, {"exprdouble", Tkapp_ExprDouble, METH_VARARGS}, -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Apr 4 16:07:56 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Sat, 04 Apr 2015 14:07:56 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Fixed_the_array_module_bro?= =?utf-8?q?ken_in_issue_=2323492=2E?= Message-ID: <20150404140755.105426.24026@psf.io> https://hg.python.org/cpython/rev/973c9ec53bbb changeset: 95441:973c9ec53bbb user: Serhiy Storchaka date: Sat Apr 04 17:06:55 2015 +0300 summary: Fixed the array module broken in issue #23492. array_array_frombytes() is used in other functions, but it's signature was changed. Closes issue #23866. files: Modules/arraymodule.c | 19 ++++--------------- 1 files changed, 4 insertions(+), 15 deletions(-) diff --git a/Modules/arraymodule.c b/Modules/arraymodule.c --- a/Modules/arraymodule.c +++ b/Modules/arraymodule.c @@ -1403,7 +1403,7 @@ array_array_fromfile_impl(arrayobject *self, PyObject *f, Py_ssize_t n) /*[clinic end generated code: output=ec9f600e10f53510 input=e188afe8e58adf40]*/ { - PyObject *args, *b, *res; + PyObject *b, *res; Py_ssize_t itemsize = self->ob_descr->itemsize; Py_ssize_t nbytes; _Py_IDENTIFIER(read); @@ -1432,13 +1432,8 @@ not_enough_bytes = (PyBytes_GET_SIZE(b) != nbytes); - args = Py_BuildValue("(O)", b); + res = array_array_frombytes(self, b); Py_DECREF(b); - if (args == NULL) - return NULL; - - res = array_array_frombytes(self, args); - Py_DECREF(args); if (res == NULL) return NULL; @@ -2672,15 +2667,9 @@ } else if (initial != NULL && (PyByteArray_Check(initial) || PyBytes_Check(initial))) { - PyObject *t_initial, *v; - t_initial = PyTuple_Pack(1, initial); - if (t_initial == NULL) { - Py_DECREF(a); - return NULL; - } + PyObject *v; v = array_array_frombytes((arrayobject *)a, - t_initial); - Py_DECREF(t_initial); + initial); if (v == NULL) { Py_DECREF(a); return NULL; -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Apr 4 16:30:12 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Sat, 04 Apr 2015 14:30:12 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2323466=3A_Fixed_ex?= =?utf-8?q?pected_error_message_in_test=5Fformat=2E?= Message-ID: <20150404143011.29535.20746@psf.io> https://hg.python.org/cpython/rev/11e6986c794d changeset: 95442:11e6986c794d user: Serhiy Storchaka date: Sat Apr 04 17:29:28 2015 +0300 summary: Issue #23466: Fixed expected error message in test_format. files: Lib/test/test_format.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_format.py b/Lib/test/test_format.py --- a/Lib/test/test_format.py +++ b/Lib/test/test_format.py @@ -272,7 +272,7 @@ #test_exc(unicode('abc %\u3000','raw-unicode-escape'), 1, ValueError, # "unsupported format character '?' (0x3000) at index 5") test_exc('%d', '1', TypeError, "%d format: a number is required, not str") - test_exc('%x', '1', TypeError, "%x format: a number is required, not str") + test_exc('%x', '1', TypeError, "%x format: an integer is required, not str") test_exc('%x', 3.14, TypeError, "%x format: an integer is required, not float") test_exc('%g', '1', TypeError, "a float is required") test_exc('no format', '1', TypeError, -- Repository URL: https://hg.python.org/cpython From bcannon at gmail.com Sat Apr 4 16:33:57 2015 From: bcannon at gmail.com (Brett Cannon) Date: Sat, 04 Apr 2015 14:33:57 +0000 Subject: [Python-checkins] Daily reference leaks (e10ad4d4d490): sum=333 In-Reply-To: <20150404084759.15211.4930@psf.io> References: <20150404084759.15211.4930@psf.io> Message-ID: Anyone know what is causing the deque leakage? On Sat, Apr 4, 2015, 04:48 wrote: > results for e10ad4d4d490 on branch "default" > -------------------------------------------- > > test_collections leaked [0, -4, 0] references, sum=-4 > test_collections leaked [0, -2, 0] memory blocks, sum=-2 > test_deque leaked [91, 91, 91] references, sum=273 > test_deque leaked [21, 21, 21] memory blocks, sum=63 > test_functools leaked [0, 0, 3] memory blocks, sum=3 > > > Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', > '3:3:/home/psf-users/antoine/refleaks/reflogK5OSop', '--timeout', '7200'] > _______________________________________________ > Python-checkins mailing list > Python-checkins at python.org > https://mail.python.org/mailman/listinfo/python-checkins > -------------- next part -------------- An HTML attachment was scrubbed... URL: From python-checkins at python.org Sat Apr 4 16:52:58 2015 From: python-checkins at python.org (benjamin.peterson) Date: Sat, 04 Apr 2015 14:52:58 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_fix_refleak_in_deque=5Fcon?= =?utf-8?q?cat?= Message-ID: <20150404145257.105436.6243@psf.io> https://hg.python.org/cpython/rev/3409f4d945e8 changeset: 95443:3409f4d945e8 user: Benjamin Peterson date: Sat Apr 04 10:52:36 2015 -0400 summary: fix refleak in deque_concat files: Modules/_collectionsmodule.c | 10 ++++++++-- 1 files changed, 8 insertions(+), 2 deletions(-) diff --git a/Modules/_collectionsmodule.c b/Modules/_collectionsmodule.c --- a/Modules/_collectionsmodule.c +++ b/Modules/_collectionsmodule.c @@ -507,7 +507,7 @@ static PyObject * deque_concat(dequeobject *deque, PyObject *other) { - PyObject *new_deque; + PyObject *new_deque, *result; int rv; rv = PyObject_IsInstance(other, (PyObject *)&deque_type); @@ -523,7 +523,13 @@ new_deque = deque_copy((PyObject *)deque); if (new_deque == NULL) return NULL; - return deque_inplace_concat((dequeobject *)new_deque, other); + result = deque_extend((dequeobject *)new_deque, other); + if (result == NULL) { + Py_DECREF(new_deque); + return NULL; + } + Py_DECREF(result); + return new_deque; } static void deque_clear(dequeobject *deque); -- Repository URL: https://hg.python.org/cpython From benjamin at python.org Sat Apr 4 16:53:18 2015 From: benjamin at python.org (Benjamin Peterson) Date: Sat, 04 Apr 2015 10:53:18 -0400 Subject: [Python-checkins] Daily reference leaks (e10ad4d4d490): sum=333 In-Reply-To: References: <20150404084759.15211.4930@psf.io> Message-ID: <1428159198.3969075.249273981.63788F29@webmail.messagingengine.com> On Sat, Apr 4, 2015, at 10:33, Brett Cannon wrote: > Anyone know what is causing the deque leakage? https://hg.python.org/cpython/rev/3409f4d945e8 From brett at python.org Sat Apr 4 18:37:52 2015 From: brett at python.org (Brett Cannon) Date: Sat, 04 Apr 2015 16:37:52 +0000 Subject: [Python-checkins] [Python-Dev] Daily reference leaks (e10ad4d4d490): sum=333 In-Reply-To: <1428159198.3969075.249273981.63788F29@webmail.messagingengine.com> References: <20150404084759.15211.4930@psf.io> <1428159198.3969075.249273981.63788F29@webmail.messagingengine.com> Message-ID: Thanks for fixing it! On Sat, Apr 4, 2015, 10:53 Benjamin Peterson wrote: > > > On Sat, Apr 4, 2015, at 10:33, Brett Cannon wrote: > > Anyone know what is causing the deque leakage? > > https://hg.python.org/cpython/rev/3409f4d945e8 > _______________________________________________ > Python-Dev mailing list > Python-Dev at python.org > https://mail.python.org/mailman/listinfo/python-dev > Unsubscribe: https://mail.python.org/mailman/options/python-dev/ > brett%40python.org > -------------- next part -------------- An HTML attachment was scrubbed... URL: From python-checkins at python.org Sat Apr 4 22:36:22 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Sat, 04 Apr 2015 20:36:22 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2323501=3A_=23inclu?= =?utf-8?q?de_=22clinic/posixmodule=2Ec=2Eh=22_was_in_the_section_skipped_?= =?utf-8?q?on?= Message-ID: <20150404203622.75268.46626@psf.io> https://hg.python.org/cpython/rev/17eb29faebde changeset: 95444:17eb29faebde user: Serhiy Storchaka date: Sat Apr 04 23:35:52 2015 +0300 summary: Issue #23501: #include "clinic/posixmodule.c.h" was in the section skipped on Windows. files: Modules/posixmodule.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -10327,8 +10327,6 @@ / sizeof(struct constdef)); } -#include "clinic/posixmodule.c.h" - /*[clinic input] os.sysconf -> long @@ -12071,6 +12069,8 @@ } +#include "clinic/posixmodule.c.h" + /*[clinic input] dump buffer [clinic start generated code]*/ -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Apr 5 07:24:40 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Sun, 05 Apr 2015 05:24:40 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Updated_pprint_examples_in?= =?utf-8?q?_according_to_issue_=2319105=2E?= Message-ID: <20150405052440.16499.7421@psf.io> https://hg.python.org/cpython/rev/6d9520e2223f changeset: 95445:6d9520e2223f user: Serhiy Storchaka date: Sun Apr 05 08:22:41 2015 +0300 summary: Updated pprint examples in according to issue #19105. files: Doc/library/pprint.rst | 35 ++++++++++++++--------------- 1 files changed, 17 insertions(+), 18 deletions(-) diff --git a/Doc/library/pprint.rst b/Doc/library/pprint.rst --- a/Doc/library/pprint.rst +++ b/Doc/library/pprint.rst @@ -235,10 +235,10 @@ 'classifiers': ['Programming Language :: Python :: 2.6', 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 2 :: Only'], - 'description': 'An extensible framework for Python programming, ' - 'with special focus\r\n' - 'on event-based network programming and ' - 'multiprotocol integration.', + 'description': 'An extensible framework for Python programming, with ' + 'special focus\r\n' + 'on event-based network programming and multiprotocol ' + 'integration.', 'docs_url': '', 'download_url': 'UNKNOWN', 'home_page': 'http://twistedmatrix.com/', @@ -288,10 +288,10 @@ 'cheesecake_documentation_id': None, 'cheesecake_installability_id': None, 'classifiers': [...], - 'description': 'An extensible framework for Python programming, ' - 'with special focus\r\n' - 'on event-based network programming and ' - 'multiprotocol integration.', + 'description': 'An extensible framework for Python programming, with ' + 'special focus\r\n' + 'on event-based network programming and multiprotocol ' + 'integration.', 'docs_url': '', 'download_url': 'UNKNOWN', 'home_page': 'http://twistedmatrix.com/', @@ -323,13 +323,12 @@ 'cheesecake_installability_id': None, 'classifiers': [...], 'description': 'An extensible ' - 'framework for ' - 'Python programming, ' - 'with special ' - 'focus\r\n' - 'on event-based ' - 'network programming ' - 'and multiprotocol ' + 'framework for Python ' + 'programming, with ' + 'special focus\r\n' + 'on event-based network ' + 'programming and ' + 'multiprotocol ' 'integration.', 'docs_url': '', 'download_url': 'UNKNOWN', @@ -344,8 +343,8 @@ 'release_url': 'http://pypi.python.org/pypi/Twisted/12.3.0', 'requires_python': None, 'stable_version': None, - 'summary': 'An asynchronous ' - 'networking framework ' - 'written in Python', + 'summary': 'An asynchronous networking ' + 'framework written in ' + 'Python', 'version': '12.3.0'}, 'urls': [{...}, {...}]} -- Repository URL: https://hg.python.org/cpython From solipsis at pitrou.net Sun Apr 5 11:04:01 2015 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Sun, 05 Apr 2015 09:04:01 +0000 Subject: [Python-checkins] Daily reference leaks (6d9520e2223f): sum=3 Message-ID: <20150405090400.64671.97463@psf.io> results for 6d9520e2223f on branch "default" -------------------------------------------- test_functools leaked [0, 0, 3] memory blocks, sum=3 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogdQvUXm', '--timeout', '7200'] From python-checkins at python.org Sun Apr 5 16:03:28 2015 From: python-checkins at python.org (benjamin.peterson) Date: Sun, 05 Apr 2015 14:03:28 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?b?KTogbWVyZ2UgMy40ICgjMjM4NzIp?= Message-ID: <20150405140328.75264.21818@psf.io> https://hg.python.org/cpython/rev/2c89c1c34e19 changeset: 95447:2c89c1c34e19 parent: 95445:6d9520e2223f parent: 95446:cc2c7aa2d7a6 user: Benjamin Peterson date: Sun Apr 05 10:03:23 2015 -0400 summary: merge 3.4 (#23872) files: Lib/smtpd.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/smtpd.py b/Lib/smtpd.py --- a/Lib/smtpd.py +++ b/Lib/smtpd.py @@ -462,7 +462,7 @@ def smtp_HELP(self, arg): if arg: - extended = ' [SP https://hg.python.org/cpython/rev/cc2c7aa2d7a6 changeset: 95446:cc2c7aa2d7a6 branch: 3.4 parent: 95438:117f45749359 user: Benjamin Peterson date: Sun Apr 05 10:01:48 2015 -0400 summary: fix extended command syntax (closes #23872) files: Lib/smtpd.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/smtpd.py b/Lib/smtpd.py --- a/Lib/smtpd.py +++ b/Lib/smtpd.py @@ -413,7 +413,7 @@ def smtp_HELP(self, arg): if arg: - extended = ' [SP https://hg.python.org/cpython/rev/eba80326ba53 changeset: 95448:eba80326ba53 user: R David Murray date: Sun Apr 05 19:26:29 2015 -0400 summary: #3566: Clean up handling of remote server disconnects. This changeset does two things: introduces a new RemoteDisconnected exception (that subclasses ConnectionResetError and BadStatusLine) so that a remote server disconnection can be detected by client code (and provides a better error message for debugging purposes), and ensures that the client socket is closed if a ConnectionError happens, so that the automatic re-connection code can work if the application handles the error and continues on. Tests are added that confirm that a connection is re-used or not re-used as appropriate to the various combinations of protocol version and headers. Patch by Martin Panter, reviewed by Demian Brecht. (Tweaked only slightly by me.) files: Doc/library/http.client.rst | 20 +++++- Lib/http/client.py | 27 +++++- Lib/test/test_httplib.py | 92 ++++++++++++++++++++++++- Lib/xmlrpc/client.py | 2 +- 4 files changed, 131 insertions(+), 10 deletions(-) diff --git a/Doc/library/http.client.rst b/Doc/library/http.client.rst --- a/Doc/library/http.client.rst +++ b/Doc/library/http.client.rst @@ -175,6 +175,17 @@ is received in the HTTP protocol from the server. +.. exception:: RemoteDisconnected + + A subclass of :exc:`ConnectionResetError` and :exc:`BadStatusLine`. Raised + by :meth:`HTTPConnection.getresponse` when the attempt to read the response + results in no data read from the connection, indicating that the remote end + has closed the connection. + + .. versionadded:: 3.5 + Previously, :exc:`BadStatusLine`\ ``('')`` was raised. + + The constants defined in this module are: .. data:: HTTP_PORT @@ -247,6 +258,11 @@ Note that you must have read the whole response before you can send a new request to the server. + .. versionchanged:: 3.5 + If a :exc:`ConnectionError` or subclass is raised, the + :class:`HTTPConnection` object will be ready to reconnect when + a new request is sent. + .. method:: HTTPConnection.set_debuglevel(level) @@ -285,7 +301,9 @@ .. method:: HTTPConnection.connect() - Connect to the server specified when the object was created. + Connect to the server specified when the object was created. By default, + this is called automatically when making a request if the client does not + already have a connection. .. method:: HTTPConnection.close() diff --git a/Lib/http/client.py b/Lib/http/client.py --- a/Lib/http/client.py +++ b/Lib/http/client.py @@ -20,10 +20,12 @@ | ( putheader() )* endheaders() v Request-sent - | - | response = getresponse() - v - Unread-response [Response-headers-read] + |\_____________________________ + | | getresponse() raises + | response = getresponse() | ConnectionError + v v + Unread-response Idle + [Response-headers-read] |\____________________ | | | response.read() | putrequest() @@ -83,7 +85,8 @@ "UnknownTransferEncoding", "UnimplementedFileMode", "IncompleteRead", "InvalidURL", "ImproperConnectionState", "CannotSendRequest", "CannotSendHeader", "ResponseNotReady", - "BadStatusLine", "LineTooLong", "error", "responses"] + "BadStatusLine", "LineTooLong", "RemoteDisconnected", "error", + "responses"] HTTP_PORT = 80 HTTPS_PORT = 443 @@ -245,7 +248,8 @@ if not line: # Presumably, the server closed the connection before # sending a valid response. - raise BadStatusLine(line) + raise RemoteDisconnected("Remote end closed connection without" + " response") try: version, status, reason = line.split(None, 2) except ValueError: @@ -1160,7 +1164,11 @@ response = self.response_class(self.sock, method=self._method) try: - response.begin() + try: + response.begin() + except ConnectionError: + self.close() + raise assert response.will_close != _UNKNOWN self.__state = _CS_IDLE @@ -1292,5 +1300,10 @@ HTTPException.__init__(self, "got more than %d bytes when reading %s" % (_MAXLINE, line_type)) +class RemoteDisconnected(ConnectionResetError, BadStatusLine): + def __init__(self, *pos, **kw): + BadStatusLine.__init__(self, "") + ConnectionResetError.__init__(self, *pos, **kw) + # for backwards compatibility error = HTTPException 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 @@ -107,6 +107,23 @@ raise AssertionError('caller tried to read past EOF') return data +class FakeSocketHTTPConnection(client.HTTPConnection): + """HTTPConnection subclass using FakeSocket; counts connect() calls""" + + def __init__(self, *args): + self.connections = 0 + super().__init__('example.com') + self.fake_socket_args = args + self._create_connection = self.create_connection + + def connect(self): + """Count the number of times connect() is invoked""" + self.connections += 1 + return super().connect() + + def create_connection(self, *pos, **kw): + return FakeSocket(*self.fake_socket_args) + class HeaderTests(TestCase): def test_auto_headers(self): # Some headers are added automatically, but should not be added by @@ -777,7 +794,7 @@ response = self # Avoid garbage collector closing the socket client.HTTPResponse.__init__(self, *pos, **kw) conn.response_class = Response - conn.sock = FakeSocket('') # Emulate server dropping connection + conn.sock = FakeSocket('Invalid status line') conn.request('GET', '/') self.assertRaises(client.BadStatusLine, conn.getresponse) self.assertTrue(response.closed) @@ -1174,6 +1191,78 @@ httpConn.close() +class PersistenceTest(TestCase): + + def test_reuse_reconnect(self): + # Should reuse or reconnect depending on header from server + tests = ( + ('1.0', '', False), + ('1.0', 'Connection: keep-alive\r\n', True), + ('1.1', '', True), + ('1.1', 'Connection: close\r\n', False), + ('1.0', 'Connection: keep-ALIVE\r\n', True), + ('1.1', 'Connection: cloSE\r\n', False), + ) + for version, header, reuse in tests: + with self.subTest(version=version, header=header): + msg = ( + 'HTTP/{} 200 OK\r\n' + '{}' + 'Content-Length: 12\r\n' + '\r\n' + 'Dummy body\r\n' + ).format(version, header) + conn = FakeSocketHTTPConnection(msg) + self.assertIsNone(conn.sock) + conn.request('GET', '/open-connection') + with conn.getresponse() as response: + self.assertEqual(conn.sock is None, not reuse) + response.read() + self.assertEqual(conn.sock is None, not reuse) + self.assertEqual(conn.connections, 1) + conn.request('GET', '/subsequent-request') + self.assertEqual(conn.connections, 1 if reuse else 2) + + def test_disconnected(self): + + def make_reset_reader(text): + """Return BufferedReader that raises ECONNRESET at EOF""" + stream = io.BytesIO(text) + def readinto(buffer): + size = io.BytesIO.readinto(stream, buffer) + if size == 0: + raise ConnectionResetError() + return size + stream.readinto = readinto + return io.BufferedReader(stream) + + tests = ( + (io.BytesIO, client.RemoteDisconnected), + (make_reset_reader, ConnectionResetError), + ) + for stream_factory, exception in tests: + with self.subTest(exception=exception): + conn = FakeSocketHTTPConnection(b'', stream_factory) + conn.request('GET', '/eof-response') + self.assertRaises(exception, conn.getresponse) + self.assertIsNone(conn.sock) + # HTTPConnection.connect() should be automatically invoked + conn.request('GET', '/reconnect') + self.assertEqual(conn.connections, 2) + + def test_100_close(self): + conn = FakeSocketHTTPConnection( + b'HTTP/1.1 100 Continue\r\n' + b'\r\n' + # Missing final response + ) + conn.request('GET', '/', headers={'Expect': '100-continue'}) + self.assertRaises(client.RemoteDisconnected, conn.getresponse) + self.assertIsNone(conn.sock) + conn.request('GET', '/reconnect') + self.assertEqual(conn.connections, 2) + + class HTTPSTest(TestCase): def setUp(self): @@ -1513,6 +1602,7 @@ @support.reap_threads def test_main(verbose=None): support.run_unittest(HeaderTests, OfflineTest, BasicTest, TimeoutTest, + PersistenceTest, HTTPSTest, RequestBodyTest, SourceAddressTest, HTTPResponseTest, ExtendedReadTest, ExtendedReadTestChunked, TunnelTests) diff --git a/Lib/xmlrpc/client.py b/Lib/xmlrpc/client.py --- a/Lib/xmlrpc/client.py +++ b/Lib/xmlrpc/client.py @@ -1128,7 +1128,7 @@ if i or e.errno not in (errno.ECONNRESET, errno.ECONNABORTED, errno.EPIPE): raise - except http.client.BadStatusLine: #close after we sent request + except http.client.RemoteDisconnected: if i: raise -- Repository URL: https://hg.python.org/cpython From solipsis at pitrou.net Mon Apr 6 10:57:22 2015 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Mon, 06 Apr 2015 08:57:22 +0000 Subject: [Python-checkins] Daily reference leaks (eba80326ba53): sum=3 Message-ID: <20150406085722.29521.53105@psf.io> results for eba80326ba53 on branch "default" -------------------------------------------- test_functools leaked [0, 0, 3] memory blocks, sum=3 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogoz4Q4C', '--timeout', '7200'] From python-checkins at python.org Mon Apr 6 12:11:12 2015 From: python-checkins at python.org (tim.golden) Date: Mon, 06 Apr 2015 10:11:12 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E4=29=3A_Added_missing_?= =?utf-8?q?right_bracket_=28reported_by_Daryl_Klakouski=29?= Message-ID: <20150406101112.105440.30455@psf.io> https://hg.python.org/cpython/rev/dde831bcb361 changeset: 95449:dde831bcb361 branch: 3.4 parent: 95446:cc2c7aa2d7a6 user: Tim Golden date: Mon Apr 06 11:04:49 2015 +0100 summary: Added missing right bracket (reported by Daryl Klakouski) 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 @@ -2008,7 +2008,7 @@ .. method:: str.zfill(width) Return a copy of the string left filled with ASCII ``'0'`` digits to - make a string of length *width*. A leading sign prefix (``'+'``/``'-'`` + make a string of length *width*. A leading sign prefix (``'+'``/``'-'``) is handled by inserting the padding *after* the sign character rather than before. The original string is returned if *width* is less than or equal to ``len(s)``. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Apr 6 12:11:12 2015 From: python-checkins at python.org (tim.golden) Date: Mon, 06 Apr 2015 10:11:12 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Merge_doc_change_from_3=2E4?= Message-ID: <20150406101112.16497.3881@psf.io> https://hg.python.org/cpython/rev/83f64bdd2ced changeset: 95450:83f64bdd2ced parent: 95448:eba80326ba53 parent: 95449:dde831bcb361 user: Tim Golden date: Mon Apr 06 11:06:18 2015 +0100 summary: Merge doc change from 3.4 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 @@ -2008,7 +2008,7 @@ .. method:: str.zfill(width) Return a copy of the string left filled with ASCII ``'0'`` digits to - make a string of length *width*. A leading sign prefix (``'+'``/``'-'`` + make a string of length *width*. A leading sign prefix (``'+'``/``'-'``) is handled by inserting the padding *after* the sign character rather than before. The original string is returned if *width* is less than or equal to ``len(s)``. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Apr 6 15:59:30 2015 From: python-checkins at python.org (benjamin.peterson) Date: Mon, 06 Apr 2015 13:59:30 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_fix_building_without_threa?= =?utf-8?q?ds_=28closes_=2323877=29?= Message-ID: <20150406135929.34661.52152@psf.io> https://hg.python.org/cpython/rev/29f51c4ae11a changeset: 95451:29f51c4ae11a user: Benjamin Peterson date: Mon Apr 06 09:59:23 2015 -0400 summary: fix building without threads (closes #23877) files: Python/pylifecycle.c | 4 ++++ 1 files changed, 4 insertions(+), 0 deletions(-) diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -1299,8 +1299,12 @@ return; display_stack: +#ifdef WITH_THREAD /* PyGILState_GetThisThreadState() works even if the GIL was released */ tstate = PyGILState_GetThisThreadState(); +#else + tstate = PyThreadState_GET(); +#endif if (tstate == NULL) { /* _Py_DumpTracebackThreads() requires the thread state to display * frames */ -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Apr 6 19:06:44 2015 From: python-checkins at python.org (benjamin.peterson) Date: Mon, 06 Apr 2015 17:06:44 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?b?KTogbWVyZ2UgMy40ICgjMjM4NzUp?= Message-ID: <20150406170634.15217.69229@psf.io> https://hg.python.org/cpython/rev/c9b9fb86d3fa changeset: 95454:c9b9fb86d3fa parent: 95451:29f51c4ae11a parent: 95452:e0ba8d3bed7e user: Benjamin Peterson date: Mon Apr 06 13:06:21 2015 -0400 summary: merge 3.4 (#23875) files: Modules/_ssl.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Modules/_ssl.c b/Modules/_ssl.c --- a/Modules/_ssl.c +++ b/Modules/_ssl.c @@ -4047,7 +4047,7 @@ PyObject *keyusage = NULL, *cert = NULL, *enc = NULL, *tup = NULL; PyObject *result = NULL; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|s:enum_certificates", + if (!PyArg_ParseTupleAndKeywords(args, kwds, "s:enum_certificates", kwlist, &store_name)) { return NULL; } @@ -4135,7 +4135,7 @@ PyObject *crl = NULL, *enc = NULL, *tup = NULL; PyObject *result = NULL; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|s:enum_crls", + if (!PyArg_ParseTupleAndKeywords(args, kwds, "s:enum_crls", kwlist, &store_name)) { return NULL; } -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Apr 6 19:08:42 2015 From: python-checkins at python.org (benjamin.peterson) Date: Mon, 06 Apr 2015 17:08:42 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E4=29=3A_remove_extra_a?= =?utf-8?q?rguments_in_arg_parsing_format_codes_=28closes_=2323875=29?= Message-ID: <20150406170634.34647.31258@psf.io> https://hg.python.org/cpython/rev/e0ba8d3bed7e changeset: 95452:e0ba8d3bed7e branch: 3.4 parent: 95449:dde831bcb361 user: Benjamin Peterson date: Mon Apr 06 13:05:22 2015 -0400 summary: remove extra arguments in arg parsing format codes (closes #23875) files: Modules/_ssl.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Modules/_ssl.c b/Modules/_ssl.c --- a/Modules/_ssl.c +++ b/Modules/_ssl.c @@ -3588,7 +3588,7 @@ PyObject *keyusage = NULL, *cert = NULL, *enc = NULL, *tup = NULL; PyObject *result = NULL; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|s:enum_certificates", + if (!PyArg_ParseTupleAndKeywords(args, kwds, "s:enum_certificates", kwlist, &store_name)) { return NULL; } @@ -3676,7 +3676,7 @@ PyObject *crl = NULL, *enc = NULL, *tup = NULL; PyObject *result = NULL; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|s:enum_crls", + if (!PyArg_ParseTupleAndKeywords(args, kwds, "s:enum_crls", kwlist, &store_name)) { return NULL; } -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Apr 6 19:08:42 2015 From: python-checkins at python.org (benjamin.peterson) Date: Mon, 06 Apr 2015 17:08:42 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_remove_extra_a?= =?utf-8?q?rguments_in_arg_parsing_format_codes_=28closes_=2323875=29?= Message-ID: <20150406170634.98374.27096@psf.io> https://hg.python.org/cpython/rev/5f27e13faae2 changeset: 95453:5f27e13faae2 branch: 2.7 parent: 95437:dedf481ec2be user: Benjamin Peterson date: Mon Apr 06 13:05:22 2015 -0400 summary: remove extra arguments in arg parsing format codes (closes #23875) files: Modules/_ssl.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Modules/_ssl.c b/Modules/_ssl.c --- a/Modules/_ssl.c +++ b/Modules/_ssl.c @@ -3645,7 +3645,7 @@ PyObject *keyusage = NULL, *cert = NULL, *enc = NULL, *tup = NULL; PyObject *result = NULL; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|s:enum_certificates", + if (!PyArg_ParseTupleAndKeywords(args, kwds, "s:enum_certificates", kwlist, &store_name)) { return NULL; } @@ -3733,7 +3733,7 @@ PyObject *crl = NULL, *enc = NULL, *tup = NULL; PyObject *result = NULL; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|s:enum_crls", + if (!PyArg_ParseTupleAndKeywords(args, kwds, "s:enum_crls", kwlist, &store_name)) { return NULL; } -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Apr 6 19:37:53 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Mon, 06 Apr 2015 17:37:53 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzIyOTc3?= =?utf-8?q?=3A_Remove_unconditional_import_of_ctypes=2E?= Message-ID: <20150406173753.16513.29495@psf.io> https://hg.python.org/cpython/rev/5cc0a090829a changeset: 95455:5cc0a090829a branch: 3.4 parent: 95452:e0ba8d3bed7e user: Serhiy Storchaka date: Mon Apr 06 20:37:16 2015 +0300 summary: Issue #22977: Remove unconditional import of ctypes. files: Lib/test/test_exceptions.py | 1 - 1 files changed, 0 insertions(+), 1 deletions(-) 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 @@ -6,7 +6,6 @@ import pickle import weakref import errno -import ctypes from test.support import (TESTFN, captured_output, check_impl_detail, check_warnings, cpython_only, gc_collect, run_unittest, -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Apr 6 19:37:54 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Mon, 06 Apr 2015 17:37:54 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2322977=3A_Remove_unconditional_import_of_ctypes?= =?utf-8?q?=2E?= Message-ID: <20150406173753.75258.74970@psf.io> https://hg.python.org/cpython/rev/f46454229cf5 changeset: 95456:f46454229cf5 parent: 95454:c9b9fb86d3fa parent: 95455:5cc0a090829a user: Serhiy Storchaka date: Mon Apr 06 20:37:34 2015 +0300 summary: Issue #22977: Remove unconditional import of ctypes. files: Lib/test/test_exceptions.py | 1 - 1 files changed, 0 insertions(+), 1 deletions(-) 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 @@ -6,7 +6,6 @@ import pickle import weakref import errno -import ctypes from test.support import (TESTFN, captured_output, check_impl_detail, check_warnings, cpython_only, gc_collect, run_unittest, -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Apr 6 21:53:06 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Mon, 06 Apr 2015 19:53:06 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2322721=3A_An_order?= =?utf-8?q?_of_multiline_pprint_output_of_set_or_dict_containing?= Message-ID: <20150406195305.105420.33259@psf.io> https://hg.python.org/cpython/rev/c8815035116b changeset: 95457:c8815035116b user: Serhiy Storchaka date: Mon Apr 06 22:52:44 2015 +0300 summary: Issue #22721: An order of multiline pprint output of set or dict containing orderable and non-orderable elements no longer depends on iteration order of set or dict. files: Lib/pprint.py | 10 ++----- Lib/test/test_pprint.py | 39 +++++++++++++++++++++++++++++ Misc/NEWS | 4 ++ 3 files changed, 46 insertions(+), 7 deletions(-) diff --git a/Lib/pprint.py b/Lib/pprint.py --- a/Lib/pprint.py +++ b/Lib/pprint.py @@ -86,14 +86,10 @@ def __lt__(self, other): try: - rv = self.obj.__lt__(other.obj) + return self.obj < other.obj except TypeError: - rv = NotImplemented - - if rv is NotImplemented: - rv = (str(type(self.obj)), id(self.obj)) < \ - (str(type(other.obj)), id(other.obj)) - return rv + return ((str(type(self.obj)), id(self.obj)) < \ + (str(type(other.obj)), id(other.obj))) def _safe_tuple(t): "Helper function for comparing 2-tuples" 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 @@ -50,6 +50,25 @@ def __repr__(self): return str(id(self)) +# Class Orderable is orderable with any type +class Orderable: + def __init__(self, hash): + self._hash = hash + def __lt__(self, other): + return False + def __gt__(self, other): + return self != other + def __le__(self, other): + return self == other + def __ge__(self, other): + return True + def __eq__(self, other): + return self is other + def __ne__(self, other): + return self is not other + def __hash__(self): + return self._hash + class QueryTestCase(unittest.TestCase): def setUp(self): @@ -620,6 +639,26 @@ self.assertEqual(pprint.pformat(dict.fromkeys(keys, 0)), '{%r: 0, %r: 0}' % tuple(sorted(keys, key=id))) + def test_sort_orderable_and_unorderable_values(self): + # Issue 22721: sorted pprints is not stable + a = Unorderable() + b = Orderable(hash(a)) # should have the same hash value + # self-test + self.assertLess(a, b) + self.assertLess(str(type(b)), str(type(a))) + self.assertEqual(sorted([b, a]), [a, b]) + self.assertEqual(sorted([a, b]), [a, b]) + # set + self.assertEqual(pprint.pformat(set([b, a]), width=1), + '{%r,\n %r}' % (a, b)) + self.assertEqual(pprint.pformat(set([a, b]), width=1), + '{%r,\n %r}' % (a, b)) + # dict + self.assertEqual(pprint.pformat(dict.fromkeys([b, a]), width=1), + '{%r: None,\n %r: None}' % (a, b)) + self.assertEqual(pprint.pformat(dict.fromkeys([a, b]), width=1), + '{%r: None,\n %r: None}' % (a, b)) + def test_str_wrap(self): # pprint tries to wrap strings intelligently fox = 'the quick brown fox jumped over a lazy dog' diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -19,6 +19,10 @@ Library ------- +- Issue #22721: An order of multiline pprint output of set or dict containing + orderable and non-orderable elements no longer depends on iteration order of + set or dict. + - Issue #15133: _tkinter.tkapp.getboolean() now supports Tcl_Obj and always returns bool. tkinter.BooleanVar now validates input values (accepted bool, int, str, and Tcl_Obj). tkinter.BooleanVar.get() now always returns bool. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Apr 6 23:25:09 2015 From: python-checkins at python.org (victor.stinner) Date: Mon, 06 Apr 2015 21:25:09 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2323853=3A_socket?= =?utf-8?q?=2Esocket=2Esendall=28=29_does_no_more_reset_the_socket_timeout?= Message-ID: <20150406212509.27430.16977@psf.io> https://hg.python.org/cpython/rev/cdc83da0b0f8 changeset: 95459:cdc83da0b0f8 user: Victor Stinner date: Mon Apr 06 23:16:34 2015 +0200 summary: Issue #23853: socket.socket.sendall() does no more reset the socket timeout each time data is sent successfuly. The socket timeout is now the maximum total duration to send all data. files: Doc/library/socket.rst | 4 ++ Misc/NEWS | 4 ++ Modules/socketmodule.c | 57 +++++++++++++++++++++-------- 3 files changed, 49 insertions(+), 16 deletions(-) diff --git a/Doc/library/socket.rst b/Doc/library/socket.rst --- a/Doc/library/socket.rst +++ b/Doc/library/socket.rst @@ -1156,6 +1156,10 @@ much data, if any, was successfully sent. .. versionchanged:: 3.5 + The socket timeout is no more reset each time data is sent successfuly. + The socket timeout is now the maximum total duration to send all data. + + .. versionchanged:: 3.5 If the system call is interrupted and the signal handler does not raise an exception, the method now retries the system call instead of raising an :exc:`InterruptedError` exception (see :pep:`475` for the rationale). diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -19,6 +19,10 @@ Library ------- +- Issue #23853: :meth:`socket.socket.sendall` does no more reset the socket + timeout each time data is sent successfuly. The socket timeout is now the + maximum total duration to send all data. + - Issue #22721: An order of multiline pprint output of set or dict containing orderable and non-orderable elements no longer depends on iteration order of set or dict. diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -706,9 +706,10 @@ int (*sock_func) (PySocketSockObject *s, void *data), void *data, int connect, - int *err) + int *err, + _PyTime_t timeout) { - int has_timeout = (s->sock_timeout > 0); + int has_timeout = (timeout > 0); _PyTime_t deadline = 0; int deadline_initialized = 0; int res; @@ -731,8 +732,8 @@ } else { deadline_initialized = 1; - deadline = _PyTime_GetMonotonicClock() + s->sock_timeout; - interval = s->sock_timeout; + deadline = _PyTime_GetMonotonicClock() + timeout; + interval = timeout; } if (interval >= 0) @@ -832,7 +833,7 @@ int (*func) (PySocketSockObject *s, void *data), void *data) { - return sock_call_ex(s, writing, func, data, 0, NULL); + return sock_call_ex(s, writing, func, data, 0, NULL, s->sock_timeout); } @@ -2636,12 +2637,14 @@ if (raise) { /* socket.connect() raises an exception on error */ - if (sock_call_ex(s, 1, sock_connect_impl, NULL, 1, NULL) < 0) + if (sock_call_ex(s, 1, sock_connect_impl, NULL, + 1, NULL, s->sock_timeout) < 0) return -1; } else { /* socket.connect_ex() returns the error code on error */ - if (sock_call_ex(s, 1, sock_connect_impl, NULL, 1, &err) < 0) + if (sock_call_ex(s, 1, sock_connect_impl, NULL, + 1, &err, s->sock_timeout) < 0) return err; } return 0; @@ -3550,6 +3553,11 @@ int flags = 0; Py_buffer pbuf; struct sock_send ctx; + int has_timeout = (s->sock_timeout > 0); + _PyTime_t interval = s->sock_timeout; + _PyTime_t deadline = 0; + int deadline_initialized = 0; + PyObject *res = NULL; if (!PyArg_ParseTuple(args, "y*|i:sendall", &pbuf, &flags)) return NULL; @@ -3562,13 +3570,27 @@ } do { + if (has_timeout) { + if (deadline_initialized) { + /* recompute the timeout */ + interval = deadline - _PyTime_GetMonotonicClock(); + } + else { + deadline_initialized = 1; + deadline = _PyTime_GetMonotonicClock() + s->sock_timeout; + } + + if (interval <= 0) { + PyErr_SetString(socket_timeout, "timed out"); + goto done; + } + } + ctx.buf = buf; ctx.len = len; ctx.flags = flags; - if (sock_call(s, 1, sock_send_impl, &ctx) < 0) { - PyBuffer_Release(&pbuf); - return NULL; - } + if (sock_call_ex(s, 1, sock_send_impl, &ctx, 0, NULL, interval) < 0) + goto done; n = ctx.result; assert(n >= 0); @@ -3578,14 +3600,17 @@ /* We must run our signal handlers before looping again. send() can return a successful partial write when it is interrupted, so we can't restrict ourselves to EINTR. */ - if (PyErr_CheckSignals()) { - PyBuffer_Release(&pbuf); - return NULL; - } + if (PyErr_CheckSignals()) + goto done; } while (len > 0); PyBuffer_Release(&pbuf); - Py_RETURN_NONE; + Py_INCREF(Py_None); + res = Py_None; + +done: + PyBuffer_Release(&pbuf); + return res; } PyDoc_STRVAR(sendall_doc, -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Apr 6 23:25:10 2015 From: python-checkins at python.org (victor.stinner) Date: Mon, 06 Apr 2015 21:25:10 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2323834=3A_Fix_init?= =?utf-8?q?ial_value_of_the_socket_timeout?= Message-ID: <20150406212509.64725.96618@psf.io> https://hg.python.org/cpython/rev/7f54676348d3 changeset: 95458:7f54676348d3 user: Victor Stinner date: Mon Apr 06 23:06:01 2015 +0200 summary: Issue #23834: Fix initial value of the socket timeout Use _PyTime_FromSeconds() to initialize the default socket timeout to -1 second, instead of -1 nanosecond which causes rounding issues in internal_select(). files: Modules/socketmodule.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -2292,7 +2292,7 @@ if (block == -1 && PyErr_Occurred()) return NULL; - s->sock_timeout = block ? -1 : 0; + s->sock_timeout = _PyTime_FromSeconds(block ? -1 : 0); internal_setblocking(s, block); Py_INCREF(Py_None); @@ -4162,7 +4162,7 @@ new = type->tp_alloc(type, 0); if (new != NULL) { ((PySocketSockObject *)new)->sock_fd = -1; - ((PySocketSockObject *)new)->sock_timeout = -1; + ((PySocketSockObject *)new)->sock_timeout = _PyTime_FromSeconds(-1); ((PySocketSockObject *)new)->errorhandler = &set_error; } return new; -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Apr 6 23:25:15 2015 From: python-checkins at python.org (victor.stinner) Date: Mon, 06 Apr 2015 21:25:15 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2322117=3A_Fix_sock?= =?utf-8?q?=5Fcall=5Fex=28=29_for_non-blocking_socket?= Message-ID: <20150406212515.64679.24288@psf.io> https://hg.python.org/cpython/rev/af664f48b9b8 changeset: 95460:af664f48b9b8 user: Victor Stinner date: Mon Apr 06 22:30:41 2015 +0200 summary: Issue #22117: Fix sock_call_ex() for non-blocking socket Call internal_select() with a timeout of 0 second, not a timeout of -1 second (blocking)! files: Modules/socketmodule.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -742,7 +742,7 @@ res = 1; } else { - res = internal_select(s, writing, -1, connect); + res = internal_select(s, writing, timeout, connect); } if (res == -1) { -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Apr 6 23:25:15 2015 From: python-checkins at python.org (victor.stinner) Date: Mon, 06 Apr 2015 21:25:15 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2323853=3A_Methods_?= =?utf-8?q?of_SSL_socket_don=27t_reset_the_socket_timeout_anymore_each?= Message-ID: <20150406212515.64749.25235@psf.io> https://hg.python.org/cpython/rev/5983f3fdacdb changeset: 95461:5983f3fdacdb user: Victor Stinner date: Mon Apr 06 22:46:13 2015 +0200 summary: Issue #23853: Methods of SSL socket don't reset the socket timeout anymore each time bytes are received or sent. The socket timeout is now the maximum total duration of the method. This change fixes a denial of service if the application is regulary interrupted by a signal and the signal handler does not raise an exception. files: Doc/library/ssl.rst | 18 +++++++ Modules/_ssl.c | 82 ++++++++++++++++++++++++++------ 2 files changed, 83 insertions(+), 17 deletions(-) diff --git a/Doc/library/ssl.rst b/Doc/library/ssl.rst --- a/Doc/library/ssl.rst +++ b/Doc/library/ssl.rst @@ -830,6 +830,11 @@ .. versionchanged:: 3.5 The :meth:`sendfile` method was added. + .. versionchanged:: 3.5 + The :meth:`shutdown` does not reset the socket timeout each time bytes + are received or sent. The socket timeout is now to maximum total duration + of the shutdown. + SSL sockets also have the following additional methods and attributes: @@ -845,6 +850,11 @@ As at any time a re-negotiation is possible, a call to :meth:`read` can also cause write operations. + .. versionchanged:: 3.5 + The socket timeout is no more reset each time bytes are received or sent. + The socket timeout is now to maximum total duration to read up to *len* + bytes. + .. method:: SSLSocket.write(buf) Write *buf* to the SSL socket and return the number of bytes written. The @@ -856,6 +866,10 @@ As at any time a re-negotiation is possible, a call to :meth:`write` can also cause read operations. + .. versionchanged:: 3.5 + The socket timeout is no more reset each time bytes are received or sent. + The socket timeout is now to maximum total duration to write *buf*. + .. note:: The :meth:`~SSLSocket.read` and :meth:`~SSLSocket.write` methods are the @@ -877,6 +891,10 @@ :attr:`~SSLContext.check_hostname` attribute of the socket's :attr:`~SSLSocket.context` is true. + .. versionchanged:: 3.5 + The socket timeout is no more reset each time bytes are received or sent. + The socket timeout is now to maximum total duration of the handshake. + .. method:: SSLSocket.getpeercert(binary_form=False) If there is no certificate for the peer on the other end of the connection, diff --git a/Modules/_ssl.c b/Modules/_ssl.c --- a/Modules/_ssl.c +++ b/Modules/_ssl.c @@ -223,7 +223,7 @@ static PyObject *PySSL_SSLwrite(PySSLSocket *self, PyObject *args); static PyObject *PySSL_SSLread(PySSLSocket *self, PyObject *args); -static int PySSL_select(PySocketSockObject *s, int writing); +static int PySSL_select(PySocketSockObject *s, int writing, _PyTime_t timeout); static PyObject *PySSL_peercert(PySSLSocket *self, PyObject *args); static PyObject *PySSL_cipher(PySSLSocket *self); @@ -248,6 +248,10 @@ #define GET_SOCKET(obj) ((obj)->Socket ? \ (PySocketSockObject *) PyWeakref_GetObject((obj)->Socket) : NULL) +/* If sock is NULL, use a timeout of 0 second */ +#define GET_SOCKET_TIMEOUT(sock) \ + ((sock != NULL) ? (sock)->sock_timeout : 0) + /* * SSL errors. */ @@ -565,6 +569,8 @@ int err; int sockstate, nonblocking; PySocketSockObject *sock = GET_SOCKET(self); + _PyTime_t timeout, deadline = 0; + int has_timeout; if (sock) { if (((PyObject*)sock) == Py_None) { @@ -580,6 +586,11 @@ BIO_set_nbio(SSL_get_wbio(self->ssl), nonblocking); } + timeout = GET_SOCKET_TIMEOUT(sock); + has_timeout = (timeout > 0); + if (has_timeout) + deadline = _PyTime_GetMonotonicClock() + timeout; + /* Actually negotiate SSL connection */ /* XXX If SSL_do_handshake() returns 0, it's also a failure. */ do { @@ -591,10 +602,13 @@ if (PyErr_CheckSignals()) goto error; + if (has_timeout) + timeout = deadline - _PyTime_GetMonotonicClock(); + if (err == SSL_ERROR_WANT_READ) { - sockstate = PySSL_select(sock, 0); + sockstate = PySSL_select(sock, 0, timeout); } else if (err == SSL_ERROR_WANT_WRITE) { - sockstate = PySSL_select(sock, 1); + sockstate = PySSL_select(sock, 1, timeout); } else { sockstate = SOCKET_OPERATION_OK; } @@ -1611,7 +1625,7 @@ */ static int -PySSL_select(PySocketSockObject *s, int writing) +PySSL_select(PySocketSockObject *s, int writing, _PyTime_t timeout) { int rc; #ifdef HAVE_POLL @@ -1624,10 +1638,14 @@ #endif /* Nothing to do unless we're in timeout mode (not non-blocking) */ - if ((s == NULL) || (s->sock_timeout == 0)) + if ((s == NULL) || (timeout == 0)) return SOCKET_IS_NONBLOCKING; - else if (s->sock_timeout < 0) - return SOCKET_IS_BLOCKING; + else if (timeout < 0) { + if (s->sock_timeout > 0) + return SOCKET_HAS_TIMED_OUT; + else + return SOCKET_IS_BLOCKING; + } /* Guard against closed socket */ if (s->sock_fd < 0) @@ -1639,8 +1657,8 @@ pollfd.fd = s->sock_fd; pollfd.events = writing ? POLLOUT : POLLIN; - /* s->sock_timeout is in seconds, timeout in ms */ - ms = (int)_PyTime_AsMilliseconds(s->sock_timeout, _PyTime_ROUND_CEILING); + /* timeout is in seconds, poll() uses milliseconds */ + ms = (int)_PyTime_AsMilliseconds(timeout, _PyTime_ROUND_CEILING); assert(ms <= INT_MAX); PySSL_BEGIN_ALLOW_THREADS @@ -1651,7 +1669,7 @@ if (!_PyIsSelectable_fd(s->sock_fd)) return SOCKET_TOO_LARGE_FOR_SELECT; - _PyTime_AsTimeval_noraise(s->sock_timeout, &tv, _PyTime_ROUND_CEILING); + _PyTime_AsTimeval_noraise(timeout, &tv, _PyTime_ROUND_CEILING); FD_ZERO(&fds); FD_SET(s->sock_fd, &fds); @@ -1679,6 +1697,8 @@ int err; int nonblocking; PySocketSockObject *sock = GET_SOCKET(self); + _PyTime_t timeout, deadline = 0; + int has_timeout; if (sock != NULL) { if (((PyObject*)sock) == Py_None) { @@ -1707,7 +1727,12 @@ BIO_set_nbio(SSL_get_wbio(self->ssl), nonblocking); } - sockstate = PySSL_select(sock, 1); + timeout = GET_SOCKET_TIMEOUT(sock); + has_timeout = (timeout > 0); + if (has_timeout) + deadline = _PyTime_GetMonotonicClock() + timeout; + + sockstate = PySSL_select(sock, 1, timeout); if (sockstate == SOCKET_HAS_TIMED_OUT) { PyErr_SetString(PySocketModule.timeout_error, "The write operation timed out"); @@ -1731,10 +1756,13 @@ if (PyErr_CheckSignals()) goto error; + if (has_timeout) + timeout = deadline - _PyTime_GetMonotonicClock(); + if (err == SSL_ERROR_WANT_READ) { - sockstate = PySSL_select(sock, 0); + sockstate = PySSL_select(sock, 0, timeout); } else if (err == SSL_ERROR_WANT_WRITE) { - sockstate = PySSL_select(sock, 1); + sockstate = PySSL_select(sock, 1, timeout); } else { sockstate = SOCKET_OPERATION_OK; } @@ -1801,6 +1829,8 @@ int err; int nonblocking; PySocketSockObject *sock = GET_SOCKET(self); + _PyTime_t timeout, deadline = 0; + int has_timeout; if (sock != NULL) { if (((PyObject*)sock) == Py_None) { @@ -1842,6 +1872,11 @@ BIO_set_nbio(SSL_get_wbio(self->ssl), nonblocking); } + timeout = GET_SOCKET_TIMEOUT(sock); + has_timeout = (timeout > 0); + if (has_timeout) + deadline = _PyTime_GetMonotonicClock() + timeout; + do { PySSL_BEGIN_ALLOW_THREADS count = SSL_read(self->ssl, mem, len); @@ -1851,10 +1886,13 @@ if (PyErr_CheckSignals()) goto error; + if (has_timeout) + timeout = deadline - _PyTime_GetMonotonicClock(); + if (err == SSL_ERROR_WANT_READ) { - sockstate = PySSL_select(sock, 0); + sockstate = PySSL_select(sock, 0, timeout); } else if (err == SSL_ERROR_WANT_WRITE) { - sockstate = PySSL_select(sock, 1); + sockstate = PySSL_select(sock, 1, timeout); } else if (err == SSL_ERROR_ZERO_RETURN && SSL_get_shutdown(self->ssl) == SSL_RECEIVED_SHUTDOWN) { @@ -1908,6 +1946,8 @@ int err, ssl_err, sockstate, nonblocking; int zeros = 0; PySocketSockObject *sock = GET_SOCKET(self); + _PyTime_t timeout, deadline = 0; + int has_timeout; if (sock != NULL) { /* Guard against closed socket */ @@ -1924,6 +1964,11 @@ BIO_set_nbio(SSL_get_wbio(self->ssl), nonblocking); } + timeout = GET_SOCKET_TIMEOUT(sock); + has_timeout = (timeout > 0); + if (has_timeout) + deadline = _PyTime_GetMonotonicClock() + timeout; + while (1) { PySSL_BEGIN_ALLOW_THREADS /* Disable read-ahead so that unwrap can work correctly. @@ -1953,12 +1998,15 @@ continue; } + if (has_timeout) + timeout = deadline - _PyTime_GetMonotonicClock(); + /* Possibly retry shutdown until timeout or failure */ ssl_err = SSL_get_error(self->ssl, err); if (ssl_err == SSL_ERROR_WANT_READ) - sockstate = PySSL_select(sock, 0); + sockstate = PySSL_select(sock, 0, timeout); else if (ssl_err == SSL_ERROR_WANT_WRITE) - sockstate = PySSL_select(sock, 1); + sockstate = PySSL_select(sock, 1, timeout); else break; -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Apr 6 23:41:20 2015 From: python-checkins at python.org (victor.stinner) Date: Mon, 06 Apr 2015 21:41:20 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzIzNDU4?= =?utf-8?q?=3A_Remove_test=5Fos=2Etest=5Furandom=5Ffd=5Fnon=5Finheritable?= =?utf-8?b?KCk=?= Message-ID: <20150406214120.16523.88889@psf.io> https://hg.python.org/cpython/rev/1b509a7e3b99 changeset: 95462:1b509a7e3b99 branch: 2.7 parent: 95453:5f27e13faae2 user: Victor Stinner date: Mon Apr 06 23:39:47 2015 +0200 summary: Issue #23458: Remove test_os.test_urandom_fd_non_inheritable() os.urandom() only tries to make the os.random() file descriptor non inheritable, but there is no guarantee. The test fails on too many operating systems: Windows, OS X 10.5, OpenIndiana. This issue is correctly fixed in Python 3.4 with the PEP 446. Upgrade to Python 3.4 is you need stronger guarantees. files: Lib/test/subprocessdata/fd_status.py | 32 ---------------- Lib/test/test_os.py | 31 --------------- 2 files changed, 0 insertions(+), 63 deletions(-) diff --git a/Lib/test/subprocessdata/fd_status.py b/Lib/test/subprocessdata/fd_status.py deleted file mode 100644 --- a/Lib/test/subprocessdata/fd_status.py +++ /dev/null @@ -1,32 +0,0 @@ -"""When called as a script, print a comma-separated list of the open -file descriptors on stdout. - -Usage: -fd_stats.py: check all file descriptors -fd_status.py fd1 fd2 ...: check only specified file descriptors -""" - -import errno -import os -import stat -import sys - -if __name__ == "__main__": - fds = [] - if len(sys.argv) == 1: - try: - _MAXFD = os.sysconf("SC_OPEN_MAX") - except: - _MAXFD = 256 - test_fds = range(0, _MAXFD) - else: - test_fds = map(int, sys.argv[1:]) - for fd in test_fds: - try: - st = os.fstat(fd) - except OSError as e: - if e.errno == errno.EBADF: - continue - raise - fds.append(fd) - print(','.join(map(str, fds))) 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 @@ -569,37 +569,6 @@ data2 = self.get_urandom_subprocess(16) self.assertNotEqual(data1, data2) - # os.urandom() doesn't use a file descriptor on Windows - @unittest.skipIf(sys.platform == "win32", "POSIX specific tests") - # FD_CLOEXEC is first supported on OS X 10.5 - @test_support.requires_mac_ver(10, 5) - def test_urandom_fd_non_inheritable(self): - # Issue #23458: os.urandom() keeps a file descriptor open, but it - # must be non inheritable - fd_status = test_support.findfile("fd_status.py", subdir="subprocessdata") - - # Need a two subprocesses because the Python test suite opens other - # inheritable file descriptors, whereas the test is specific to - # os.urandom() file descriptor - code = textwrap.dedent(""" - import os - import subprocess - import sys - - # Ensure that the /dev/urandom file descriptor is open - os.urandom(1) - - exitcode = subprocess.call([sys.executable, %r], - close_fds=False) - sys.exit(exitcode) - """ % fd_status) - - proc = subprocess.Popen([sys.executable, "-c", code], - stdout=subprocess.PIPE, close_fds=True) - output, error = proc.communicate() - open_fds = set(map(int, output.rstrip().split(','))) - self.assertEqual(open_fds - set(range(3)), set()) - HAVE_GETENTROPY = (sysconfig.get_config_var('HAVE_GETENTROPY') == 1) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Apr 7 03:07:23 2015 From: python-checkins at python.org (guido.van.rossum) Date: Tue, 07 Apr 2015 01:07:23 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_Describe_an_old_but_good_rule?= =?utf-8?q?_for_consistent_return_statements=2E?= Message-ID: <20150407010723.29531.95209@psf.io> https://hg.python.org/peps/rev/dcca553d365d changeset: 5749:dcca553d365d user: Guido van Rossum date: Mon Apr 06 18:07:10 2015 -0700 summary: Describe an old but good rule for consistent return statements. files: pep-0008.txt | 31 +++++++++++++++++++++++++++++++ 1 files changed, 31 insertions(+), 0 deletions(-) diff --git a/pep-0008.txt b/pep-0008.txt --- a/pep-0008.txt +++ b/pep-0008.txt @@ -1151,6 +1151,37 @@ closing the connection after a transaction. Being explicit is important in this case. +- Be consistent in return statements. Either all return statements in + a function should return an expression, or none of them should. If + any return statement returns an expression, any return statements + where no value is returned should explicitly state this as ``return + None``, and an explicit return statement should be present at the + end of the function (if reachable). + + Yes:: + + def foo(x): + if x >= 0: + return math.sqrt(x) + else: + return None + + def bar(x): + if x < 0: + return None + return math.sqrt(x) + + No:: + + def foo(x): + if x >= 0: + return math.sqrt(x) + + def bar(x): + if x < 0: + return + return math.sqrt(x) + - Use string methods instead of the string module. String methods are always much faster and share the same API with -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Tue Apr 7 04:54:30 2015 From: python-checkins at python.org (guido.van.rossum) Date: Tue, 07 Apr 2015 02:54:30 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_Small_edits=3B_added_Tuple=5B?= =?utf-8?b?dCwgLi4uXSBhbmQgQ2FsbGFibGVbLi4uLCB0cl0u?= Message-ID: <20150407025430.15215.22769@psf.io> https://hg.python.org/peps/rev/1bf45611af7c changeset: 5750:1bf45611af7c user: Guido van Rossum date: Mon Apr 06 19:54:09 2015 -0700 summary: Small edits; added Tuple[t, ...] and Callable[..., tr]. files: pep-0483.txt | 61 ++++++++++++++++++++------------------- 1 files changed, 31 insertions(+), 30 deletions(-) diff --git a/pep-0483.txt b/pep-0483.txt --- a/pep-0483.txt +++ b/pep-0483.txt @@ -27,7 +27,7 @@ We start by explaining gradual typing; then we state some conventions and general rules; then we define the new special types (such as Union) that can be used in annotations; and finally we define the approach to -generic types. (The latter section needs more fleshing out; sorry!) +generic types. (TODO: The latter section needs more fleshing out; sorry!) Specification @@ -82,7 +82,7 @@ type Manager: - m = Manager() # type: Manager -- m = Employee() # Fails static check +- m = Employee() # Fails static check However, suppose we have a variable whose type is **Any**: @@ -103,7 +103,7 @@ - t1, t2 etc. and u1, u2 etc. are types or classes. Sometimes we write ti or tj to refer to "any of t1, t2, etc." -- X, Y etc. are type variables (defined with Var(), see below). +- X, Y etc. are type variables (defined with TypeVar(), see below). - C, D etc. are classes defined with a class statement. - x, y etc. are objects or instances. - We use the terms type and class interchangeably, and we assume @@ -147,15 +147,15 @@ first is an int, the second a float; e.g., (42, 3.14). Tuple[u1, u2, ..., um] is a subclass of Tuple[t1, t2, ..., tn] if they have the same length (n==m) and each ui is a subclass of ti. To spell the type - of the empty tuple, use Tuple[()]. There is no way to define a - variadic tuple type. (TODO: Maybe Tuple[t1, ...] with literal - ellipsis?) + of the empty tuple, use Tuple[()]. A variadic homogeneous tuple type + can be written Tuple[t1, ...]. (That's three dots, a literal ellipsis; + and yes, that's a valid token in Python's syntax.) - **Callable[[t1, t2, ..., tn], tr]**. A function with positional argument types t1 etc., and return type tr. The argument list may be empty (n==0). There is no way to indicate optional or keyword - arguments, nor varargs (we don't need to spell those often enough to - complicate the syntax - however, Reticulated Python has a useful idea - here). This is covariant in the return type, but contravariant in the + arguments, nor varargs, but you can say the argument list is entirely + unchecked by writing Callable[..., tr] (again, a literal ellipsis). + This is covariant in the return type, but contravariant in the arguments. "Covariant" here means that for two callable types that differ only in the return type, the subclass relationship for the callable types follows that of the return types. (Example: @@ -197,33 +197,37 @@ - Type aliases, e.g. - * point = Tuple[float, float] - * def distance(p: point) -> float: ... + * Point = Tuple[float, float] + * def distance(p: Point) -> float: ... - Forward references via strings, e.g. * class C: - + def compare(self, other: "C") -> int: ... + + def compare(self, other: 'C') -> int: ... -- If a default of None is specified, the type is implicitly optional, e.g. +- If a default of None is specified, the type is implicitly Optional, e.g. * def get(key: KT, default: VT = None) -> VT: ... - Don't use dynamic type expressions; use builtins and imported types only. No 'if'. - * def display(message: str if WINDOWS else bytes): # NOT OK + * def display(message: str if WINDOWS else bytes): # NOT OK - Type declaration in comments, e.g. - * x = [] # type: Sequence[int] + * x = [] # type: Sequence[int] - Type declarations using Undefined, e.g. * x = Undefined(str) -- Other things, e.g. casts, overloading and stub modules; best left to an +- Casts using cast(T, x), e.g. + + * x = cast(Any, frobozz()) + +- Other things, e.g. overloading and stub modules; best left to an actual PEP. @@ -233,25 +237,25 @@ (TODO: Explain more. See also the `mypy docs on generics `_.) -- **X = Var('X')**. Declares a unique type variable. The name must match +- **X = TypeVar('X')**. Declares a unique type variable. The name must match the variable name. -- **Y = Var('Y', t1, t2, ...).** Ditto, constrained to t1 etc. Behaves +- **Y = TypeVar('Y', t1, t2, ...).** Ditto, constrained to t1 etc. Behaves like Union[t1, t2, ...] for most purposes, but when used as a type variable, subclasses of t1 etc. are replaced by the most-derived base class among t1 etc. - Example of constrained type variables: - * AnyStr = Var('AnyStr', str, bytes) + * AnyStr = TypeVar('AnyStr', str, bytes) * def longest(a: AnyStr, b: AnyStr) -> AnyStr: - return a if len(a) >= len(b) else b - * x = longest('a', 'abc') # The inferred type for x is str + * x = longest('a', 'abc') # The inferred type for x is str - * y = longest('a', b'abc') # Fails static type check + * y = longest('a', b'abc') # Fails static type check * In this example, both arguments to longest() must have the same type (str or bytes), and moreover, even if the arguments are instances of a @@ -261,7 +265,7 @@ - For comparison, if the type variable was unconstrained, the common subclass would be chosen as the return type, e.g.: - * S = Var('S') + * S = TypeVar('S') * def longest(a: S, b: S) -> S: @@ -297,20 +301,17 @@ Think about co\*variance. No gimmicks like deriving from Sequence[Union[int, str]] or Sequence[Union[int, X]]. -- **Protocol**. Similar to Generic but uses structural equivalence. (TODO: - Explain, and think about co\*variance.) - Predefined generic types and Protocols in typing.py --------------------------------------------------- -(See also the `mypy typing.py -module `_.) +(See also the `typing.py module +`_.) - Everything from collections.abc (but Set renamed to AbstractSet). -- Dict, List, Set, a few more. (FrozenSet?) -- Pattern, Match. (Why?) -- IO, TextIO, BinaryIO. (Why?) +- Dict, List, Set, FrozenSet, a few more. +- re.Pattern[AnyStr], re.Match[AnyStr]. +- re.IO[AnyStr], re.TextIO ~ re.IO[str], re.BinaryIO ~ re.IO[bytes]. Copyright -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Tue Apr 7 07:29:40 2015 From: python-checkins at python.org (donald.stufft) Date: Tue, 07 Apr 2015 05:29:40 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E4=29=3A_Upgrade_pip_to?= =?utf-8?q?_6=2E1=2E0_and_setuptools_to_15=2E0?= Message-ID: <20150407052940.27432.60279@psf.io> https://hg.python.org/cpython/rev/7e2a7de211b4 changeset: 95463:7e2a7de211b4 branch: 3.4 parent: 95455:5cc0a090829a user: Donald Stufft date: Tue Apr 07 01:29:33 2015 -0400 summary: Upgrade pip to 6.1.0 and setuptools to 15.0 files: Lib/ensurepip/__init__.py | 4 ++-- Lib/ensurepip/_bundled/pip-6.0.8-py2.py3-none-any.whl | Bin Lib/ensurepip/_bundled/pip-6.1.0-py2.py3-none-any.whl | Bin Lib/ensurepip/_bundled/setuptools-12.0.5-py2.py3-none-any.whl | Bin Lib/ensurepip/_bundled/setuptools-15.0-py2.py3-none-any.whl | Bin 5 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/ensurepip/__init__.py b/Lib/ensurepip/__init__.py --- a/Lib/ensurepip/__init__.py +++ b/Lib/ensurepip/__init__.py @@ -8,9 +8,9 @@ __all__ = ["version", "bootstrap"] -_SETUPTOOLS_VERSION = "12.0.5" +_SETUPTOOLS_VERSION = "15.0" -_PIP_VERSION = "6.0.8" +_PIP_VERSION = "6.1.0" # pip currently requires ssl support, so we try to provide a nicer # error message when that is missing (http://bugs.python.org/issue19744) diff --git a/Lib/ensurepip/_bundled/pip-6.0.8-py2.py3-none-any.whl b/Lib/ensurepip/_bundled/pip-6.0.8-py2.py3-none-any.whl deleted file mode 100644 index be9238d94c10081b4450aad01851f4c4eda1897c..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 GIT binary patch [stripped] diff --git a/Lib/ensurepip/_bundled/pip-6.1.0-py2.py3-none-any.whl b/Lib/ensurepip/_bundled/pip-6.1.0-py2.py3-none-any.whl new file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..2d075df9f0a002d8d3e08c2d5eb08cfb7e837290 GIT binary patch [stripped] diff --git a/Lib/ensurepip/_bundled/setuptools-12.0.5-py2.py3-none-any.whl b/Lib/ensurepip/_bundled/setuptools-12.0.5-py2.py3-none-any.whl deleted file mode 100644 index 978cf6c43442faecdb4e8b84a3c2c0bc1bc0ec01..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 GIT binary patch [stripped] diff --git a/Lib/ensurepip/_bundled/setuptools-15.0-py2.py3-none-any.whl b/Lib/ensurepip/_bundled/setuptools-15.0-py2.py3-none-any.whl new file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..578ff3c31c7db40f8777aa1272566362a3793956 GIT binary patch [stripped] -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Apr 7 07:30:40 2015 From: python-checkins at python.org (donald.stufft) Date: Tue, 07 Apr 2015 05:30:40 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Merged_update_of_pip_to_6=2E1=2E0_and_setuptools_to_15?= =?utf-8?q?=2E0?= Message-ID: <20150407053040.105281.94118@psf.io> https://hg.python.org/cpython/rev/9a0caf6e7a16 changeset: 95464:9a0caf6e7a16 parent: 95461:5983f3fdacdb parent: 95463:7e2a7de211b4 user: Donald Stufft date: Tue Apr 07 01:30:33 2015 -0400 summary: Merged update of pip to 6.1.0 and setuptools to 15.0 files: Lib/ensurepip/__init__.py | 4 ++-- Lib/ensurepip/_bundled/pip-6.0.8-py2.py3-none-any.whl | Bin Lib/ensurepip/_bundled/pip-6.1.0-py2.py3-none-any.whl | Bin Lib/ensurepip/_bundled/setuptools-12.0.5-py2.py3-none-any.whl | Bin Lib/ensurepip/_bundled/setuptools-15.0-py2.py3-none-any.whl | Bin 5 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/ensurepip/__init__.py b/Lib/ensurepip/__init__.py --- a/Lib/ensurepip/__init__.py +++ b/Lib/ensurepip/__init__.py @@ -8,9 +8,9 @@ __all__ = ["version", "bootstrap"] -_SETUPTOOLS_VERSION = "12.0.5" +_SETUPTOOLS_VERSION = "15.0" -_PIP_VERSION = "6.0.8" +_PIP_VERSION = "6.1.0" # pip currently requires ssl support, so we try to provide a nicer # error message when that is missing (http://bugs.python.org/issue19744) diff --git a/Lib/ensurepip/_bundled/pip-6.0.8-py2.py3-none-any.whl b/Lib/ensurepip/_bundled/pip-6.0.8-py2.py3-none-any.whl deleted file mode 100644 index be9238d94c10081b4450aad01851f4c4eda1897c..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 GIT binary patch [stripped] diff --git a/Lib/ensurepip/_bundled/pip-6.1.0-py2.py3-none-any.whl b/Lib/ensurepip/_bundled/pip-6.1.0-py2.py3-none-any.whl new file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..2d075df9f0a002d8d3e08c2d5eb08cfb7e837290 GIT binary patch [stripped] diff --git a/Lib/ensurepip/_bundled/setuptools-12.0.5-py2.py3-none-any.whl b/Lib/ensurepip/_bundled/setuptools-12.0.5-py2.py3-none-any.whl deleted file mode 100644 index 978cf6c43442faecdb4e8b84a3c2c0bc1bc0ec01..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 GIT binary patch [stripped] diff --git a/Lib/ensurepip/_bundled/setuptools-15.0-py2.py3-none-any.whl b/Lib/ensurepip/_bundled/setuptools-15.0-py2.py3-none-any.whl new file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..578ff3c31c7db40f8777aa1272566362a3793956 GIT binary patch [stripped] -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Apr 7 07:32:35 2015 From: python-checkins at python.org (donald.stufft) Date: Tue, 07 Apr 2015 05:32:35 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_Upgrade_pip_to?= =?utf-8?q?_6=2E1=2E0_and_setuptools_to_15=2E0?= Message-ID: <20150407053235.16242.21169@psf.io> https://hg.python.org/cpython/rev/be8b1895897c changeset: 95465:be8b1895897c branch: 2.7 parent: 95462:1b509a7e3b99 user: Donald Stufft date: Tue Apr 07 01:32:24 2015 -0400 summary: Upgrade pip to 6.1.0 and setuptools to 15.0 files: Lib/ensurepip/__init__.py | 4 ++-- Lib/ensurepip/_bundled/pip-6.0.8-py2.py3-none-any.whl | Bin Lib/ensurepip/_bundled/pip-6.1.0-py2.py3-none-any.whl | Bin Lib/ensurepip/_bundled/setuptools-12.0.5-py2.py3-none-any.whl | Bin Lib/ensurepip/_bundled/setuptools-15.0-py2.py3-none-any.whl | Bin 5 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/ensurepip/__init__.py b/Lib/ensurepip/__init__.py --- a/Lib/ensurepip/__init__.py +++ b/Lib/ensurepip/__init__.py @@ -12,9 +12,9 @@ __all__ = ["version", "bootstrap"] -_SETUPTOOLS_VERSION = "12.0.5" +_SETUPTOOLS_VERSION = "15.0" -_PIP_VERSION = "6.0.8" +_PIP_VERSION = "6.1.0" # pip currently requires ssl support, so we try to provide a nicer # error message when that is missing (http://bugs.python.org/issue19744) diff --git a/Lib/ensurepip/_bundled/pip-6.0.8-py2.py3-none-any.whl b/Lib/ensurepip/_bundled/pip-6.0.8-py2.py3-none-any.whl deleted file mode 100644 index be9238d94c10081b4450aad01851f4c4eda1897c..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 GIT binary patch [stripped] diff --git a/Lib/ensurepip/_bundled/pip-6.1.0-py2.py3-none-any.whl b/Lib/ensurepip/_bundled/pip-6.1.0-py2.py3-none-any.whl new file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..2d075df9f0a002d8d3e08c2d5eb08cfb7e837290 GIT binary patch [stripped] diff --git a/Lib/ensurepip/_bundled/setuptools-12.0.5-py2.py3-none-any.whl b/Lib/ensurepip/_bundled/setuptools-12.0.5-py2.py3-none-any.whl deleted file mode 100644 index 978cf6c43442faecdb4e8b84a3c2c0bc1bc0ec01..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 GIT binary patch [stripped] diff --git a/Lib/ensurepip/_bundled/setuptools-15.0-py2.py3-none-any.whl b/Lib/ensurepip/_bundled/setuptools-15.0-py2.py3-none-any.whl new file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..578ff3c31c7db40f8777aa1272566362a3793956 GIT binary patch [stripped] -- Repository URL: https://hg.python.org/cpython From solipsis at pitrou.net Tue Apr 7 11:11:26 2015 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Tue, 07 Apr 2015 09:11:26 +0000 Subject: [Python-checkins] Daily reference leaks (9a0caf6e7a16): sum=3 Message-ID: <20150407091126.105279.65189@psf.io> results for 9a0caf6e7a16 on branch "default" -------------------------------------------- test_collections leaked [0, -2, 2] references, sum=0 test_functools leaked [0, 0, 3] memory blocks, sum=3 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogPzsr5V', '--timeout', '7200'] From python-checkins at python.org Tue Apr 7 12:50:48 2015 From: python-checkins at python.org (victor.stinner) Date: Tue, 07 Apr 2015 10:50:48 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzIzODgx?= =?utf-8?q?=3A_urllib=2Eftpwrapper_constructor_now_closes_the_socket_if_th?= =?utf-8?q?e_FTP?= Message-ID: <20150407105048.16248.26902@psf.io> https://hg.python.org/cpython/rev/69d4e199b88e changeset: 95466:69d4e199b88e branch: 2.7 user: Victor Stinner date: Tue Apr 07 12:47:57 2015 +0200 summary: Issue #23881: urllib.ftpwrapper constructor now closes the socket if the FTP connection failed. files: Lib/urllib.py | 6 +++++- Misc/NEWS | 3 +++ 2 files changed, 8 insertions(+), 1 deletions(-) diff --git a/Lib/urllib.py b/Lib/urllib.py --- a/Lib/urllib.py +++ b/Lib/urllib.py @@ -871,7 +871,11 @@ self.timeout = timeout self.refcount = 0 self.keepalive = persistent - self.init() + try: + self.init() + except: + self.close() + raise def init(self): import ftplib diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -21,6 +21,9 @@ Library ------- +- Issue #23881: urllib.ftpwrapper constructor now closes the socket if the FTP + connection failed. + - Issue #15133: _tkinter.tkapp.getboolean() now supports long and Tcl_Obj and always returns bool. tkinter.BooleanVar now validates input values (accepted bool, int, long, str, unicode, and Tcl_Obj). tkinter.BooleanVar.get() now -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Apr 7 12:50:48 2015 From: python-checkins at python.org (victor.stinner) Date: Tue, 07 Apr 2015 10:50:48 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzIzODgx?= =?utf-8?q?=3A_urllib=2Erequest=2Eftpwrapper_constructor_now_closes_the_so?= =?utf-8?q?cket_if?= Message-ID: <20150407105048.16246.97991@psf.io> https://hg.python.org/cpython/rev/7b168db16e67 changeset: 95467:7b168db16e67 branch: 3.4 parent: 95463:7e2a7de211b4 user: Victor Stinner date: Tue Apr 07 12:49:27 2015 +0200 summary: Issue #23881: urllib.request.ftpwrapper constructor now closes the socket if the FTP connection failed to fix a ResourceWarning. files: Lib/urllib/request.py | 6 +++++- Misc/NEWS | 3 +++ 2 files changed, 8 insertions(+), 1 deletions(-) diff --git a/Lib/urllib/request.py b/Lib/urllib/request.py --- a/Lib/urllib/request.py +++ b/Lib/urllib/request.py @@ -2240,7 +2240,11 @@ self.timeout = timeout self.refcount = 0 self.keepalive = persistent - self.init() + try: + self.init() + except: + self.close() + raise def init(self): import ftplib diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -24,6 +24,9 @@ Library ------- +- Issue #23881: urllib.request.ftpwrapper constructor now closes the socket if + the FTP connection failed to fix a ResourceWarning. + - Issue #15133: _tkinter.tkapp.getboolean() now supports Tcl_Obj and always returns bool. tkinter.BooleanVar now validates input values (accepted bool, int, str, and Tcl_Obj). tkinter.BooleanVar.get() now always returns bool. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Apr 7 12:50:48 2015 From: python-checkins at python.org (victor.stinner) Date: Tue, 07 Apr 2015 10:50:48 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?b?KTogKE1lcmdlIDMuNCkgSXNzdWUgIzIzODgxOiB1cmxsaWIucmVxdWVzdC5m?= =?utf-8?q?tpwrapper_constructor_now_closes_the?= Message-ID: <20150407105048.80917.28069@psf.io> https://hg.python.org/cpython/rev/1a72c0a1a50f changeset: 95468:1a72c0a1a50f parent: 95464:9a0caf6e7a16 parent: 95467:7b168db16e67 user: Victor Stinner date: Tue Apr 07 12:50:24 2015 +0200 summary: (Merge 3.4) Issue #23881: urllib.request.ftpwrapper constructor now closes the socket if the FTP connection failed to fix a ResourceWarning. files: Lib/urllib/request.py | 6 +++++- Misc/NEWS | 3 +++ 2 files changed, 8 insertions(+), 1 deletions(-) diff --git a/Lib/urllib/request.py b/Lib/urllib/request.py --- a/Lib/urllib/request.py +++ b/Lib/urllib/request.py @@ -2255,7 +2255,11 @@ self.timeout = timeout self.refcount = 0 self.keepalive = persistent - self.init() + try: + self.init() + except: + self.close() + raise def init(self): import ftplib diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -19,6 +19,9 @@ Library ------- +- Issue #23881: urllib.request.ftpwrapper constructor now closes the socket if + the FTP connection failed to fix a ResourceWarning. + - Issue #23853: :meth:`socket.socket.sendall` does no more reset the socket timeout each time data is sent successfuly. The socket timeout is now the maximum total duration to send all data. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Apr 7 13:00:27 2015 From: python-checkins at python.org (victor.stinner) Date: Tue, 07 Apr 2015 11:00:27 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzIzODgx?= =?utf-8?q?=3A_ftp=3A//gatekeeper=2Eresearch=2Ecompaq=2Ecom/_and_ftp=3A//f?= =?utf-8?q?tp=2Edebian=2Eorg/?= Message-ID: <20150407110024.117499.97248@psf.io> https://hg.python.org/cpython/rev/40ddcd785f7b changeset: 95469:40ddcd785f7b branch: 3.4 parent: 95467:7b168db16e67 user: Victor Stinner date: Tue Apr 07 12:52:50 2015 +0200 summary: Issue #23881: ftp://gatekeeper.research.compaq.com/ and ftp://ftp.debian.org/ are down, don't use anymore in test_urllib2net files: Lib/test/test_urllib2net.py | 4 +--- 1 files changed, 1 insertions(+), 3 deletions(-) diff --git a/Lib/test/test_urllib2net.py b/Lib/test/test_urllib2net.py --- a/Lib/test/test_urllib2net.py +++ b/Lib/test/test_urllib2net.py @@ -102,8 +102,6 @@ 'ftp://ftp.debian.org/debian/README', ('ftp://ftp.debian.org/debian/non-existent-file', None, urllib.error.URLError), - 'ftp://gatekeeper.research.compaq.com/pub/DEC/SRC' - '/research-reports/00README-Legal-Rules-Regs', ] self._test_urls(urls, self._extra_handlers()) @@ -291,7 +289,7 @@ self.addCleanup(u.close) self.assertEqual(u.fp.raw._sock.gettimeout(), 120) - FTP_HOST = "ftp://ftp.mirror.nl/pub/gnu/" + FTP_HOST = 'ftp://ftp.debian.org/debian/' def test_ftp_basic(self): self.assertIsNone(socket.getdefaulttimeout()) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Apr 7 13:00:33 2015 From: python-checkins at python.org (victor.stinner) Date: Tue, 07 Apr 2015 11:00:33 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?b?KTogTWVyZ2UgMy40ICh0ZXN0X3VybGxpYjJuZXQp?= Message-ID: <20150407110024.16505.73544@psf.io> https://hg.python.org/cpython/rev/6ed381537e6c changeset: 95470:6ed381537e6c parent: 95468:1a72c0a1a50f parent: 95469:40ddcd785f7b user: Victor Stinner date: Tue Apr 07 12:53:07 2015 +0200 summary: Merge 3.4 (test_urllib2net) files: Lib/test/test_urllib2net.py | 4 +--- 1 files changed, 1 insertions(+), 3 deletions(-) diff --git a/Lib/test/test_urllib2net.py b/Lib/test/test_urllib2net.py --- a/Lib/test/test_urllib2net.py +++ b/Lib/test/test_urllib2net.py @@ -102,8 +102,6 @@ 'ftp://ftp.debian.org/debian/README', ('ftp://ftp.debian.org/debian/non-existent-file', None, urllib.error.URLError), - 'ftp://gatekeeper.research.compaq.com/pub/DEC/SRC' - '/research-reports/00README-Legal-Rules-Regs', ] self._test_urls(urls, self._extra_handlers()) @@ -291,7 +289,7 @@ self.addCleanup(u.close) self.assertEqual(u.fp.raw._sock.gettimeout(), 120) - FTP_HOST = "ftp://ftp.mirror.nl/pub/gnu/" + FTP_HOST = 'ftp://ftp.debian.org/debian/' def test_ftp_basic(self): self.assertIsNone(socket.getdefaulttimeout()) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Apr 7 13:00:33 2015 From: python-checkins at python.org (victor.stinner) Date: Tue, 07 Apr 2015 11:00:33 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogc3N1ZSAjMjM4ODE6?= =?utf-8?q?_ftp=3A//gatekeeper=2Eresearch=2Ecompaq=2Ecom/_and_ftp=3A//ftp?= =?utf-8?q?=2Edebian=2Eorg/?= Message-ID: <20150407110024.29545.99391@psf.io> https://hg.python.org/cpython/rev/225be6be3893 changeset: 95471:225be6be3893 branch: 2.7 parent: 95466:69d4e199b88e user: Victor Stinner date: Tue Apr 07 12:59:14 2015 +0200 summary: ssue #23881: ftp://gatekeeper.research.compaq.com/ and ftp://ftp.debian.org/ are down, don't use anymore in test_urllib2net ftp.kernel.org is also slow or down, so reuse the same FTP servers than Python 3.4 and 3.5: use ftp.debian.org instead. files: Lib/test/test_urllib2net.py | 10 ++++------ 1 files changed, 4 insertions(+), 6 deletions(-) diff --git a/Lib/test/test_urllib2net.py b/Lib/test/test_urllib2net.py --- a/Lib/test/test_urllib2net.py +++ b/Lib/test/test_urllib2net.py @@ -102,11 +102,9 @@ def test_ftp(self): urls = [ - 'ftp://ftp.kernel.org/pub/linux/kernel/README', - 'ftp://ftp.kernel.org/pub/linux/kernel/non-existent-file', - #'ftp://ftp.kernel.org/pub/leenox/kernel/test', - 'ftp://gatekeeper.research.compaq.com/pub/DEC/SRC' - '/research-reports/00README-Legal-Rules-Regs', + 'ftp://ftp.debian.org/debian/README', + ('ftp://ftp.debian.org/debian/non-existent-file', + None, urllib2.URLError), ] self._test_urls(urls, self._extra_handlers()) @@ -284,7 +282,7 @@ u = _urlopen_with_retry(url, timeout=120) self.assertEqual(u.fp._sock.fp._sock.gettimeout(), 120) - FTP_HOST = "ftp://ftp.mirror.nl/pub/gnu/" + FTP_HOST = 'ftp://ftp.debian.org/debian/' def test_ftp_basic(self): self.assertIsNone(socket.getdefaulttimeout()) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Apr 7 13:09:18 2015 From: python-checkins at python.org (donald.stufft) Date: Tue, 07 Apr 2015 11:09:18 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_Update_pip_to_?= =?utf-8?b?Ni4xLjE=?= Message-ID: <20150407110914.80907.65095@psf.io> https://hg.python.org/cpython/rev/6bce7c6d0502 changeset: 95472:6bce7c6d0502 branch: 2.7 user: Donald Stufft date: Tue Apr 07 07:09:06 2015 -0400 summary: Update pip to 6.1.1 files: Lib/ensurepip/__init__.py | 2 +- Lib/ensurepip/_bundled/pip-6.1.0-py2.py3-none-any.whl | Bin Lib/ensurepip/_bundled/pip-6.1.1-py2.py3-none-any.whl | Bin 3 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/ensurepip/__init__.py b/Lib/ensurepip/__init__.py --- a/Lib/ensurepip/__init__.py +++ b/Lib/ensurepip/__init__.py @@ -14,7 +14,7 @@ _SETUPTOOLS_VERSION = "15.0" -_PIP_VERSION = "6.1.0" +_PIP_VERSION = "6.1.1" # pip currently requires ssl support, so we try to provide a nicer # error message when that is missing (http://bugs.python.org/issue19744) diff --git a/Lib/ensurepip/_bundled/pip-6.1.0-py2.py3-none-any.whl b/Lib/ensurepip/_bundled/pip-6.1.0-py2.py3-none-any.whl deleted file mode 100644 index 2d075df9f0a002d8d3e08c2d5eb08cfb7e837290..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 GIT binary patch [stripped] diff --git a/Lib/ensurepip/_bundled/pip-6.1.1-py2.py3-none-any.whl b/Lib/ensurepip/_bundled/pip-6.1.1-py2.py3-none-any.whl new file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..e59694a019051d58b9a378a1adfc9461b8cec9c3 GIT binary patch [stripped] -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Apr 7 13:10:05 2015 From: python-checkins at python.org (donald.stufft) Date: Tue, 07 Apr 2015 11:10:05 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E4=29=3A_Update_pip_to_?= =?utf-8?b?Ni4xLjE=?= Message-ID: <20150407111005.27432.43863@psf.io> https://hg.python.org/cpython/rev/597768629c2e changeset: 95473:597768629c2e branch: 3.4 parent: 95469:40ddcd785f7b user: Donald Stufft date: Tue Apr 07 07:09:59 2015 -0400 summary: Update pip to 6.1.1 files: Lib/ensurepip/__init__.py | 2 +- Lib/ensurepip/_bundled/pip-6.1.0-py2.py3-none-any.whl | Bin Lib/ensurepip/_bundled/pip-6.1.1-py2.py3-none-any.whl | Bin 3 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/ensurepip/__init__.py b/Lib/ensurepip/__init__.py --- a/Lib/ensurepip/__init__.py +++ b/Lib/ensurepip/__init__.py @@ -10,7 +10,7 @@ _SETUPTOOLS_VERSION = "15.0" -_PIP_VERSION = "6.1.0" +_PIP_VERSION = "6.1.1" # pip currently requires ssl support, so we try to provide a nicer # error message when that is missing (http://bugs.python.org/issue19744) diff --git a/Lib/ensurepip/_bundled/pip-6.1.0-py2.py3-none-any.whl b/Lib/ensurepip/_bundled/pip-6.1.0-py2.py3-none-any.whl deleted file mode 100644 index 2d075df9f0a002d8d3e08c2d5eb08cfb7e837290..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 GIT binary patch [stripped] diff --git a/Lib/ensurepip/_bundled/pip-6.1.1-py2.py3-none-any.whl b/Lib/ensurepip/_bundled/pip-6.1.1-py2.py3-none-any.whl new file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..e59694a019051d58b9a378a1adfc9461b8cec9c3 GIT binary patch [stripped] -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Apr 7 13:10:49 2015 From: python-checkins at python.org (donald.stufft) Date: Tue, 07 Apr 2015 11:10:49 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_update_pip_to_6=2E1=2E1?= Message-ID: <20150407111044.117475.36685@psf.io> https://hg.python.org/cpython/rev/b01e69847321 changeset: 95474:b01e69847321 parent: 95470:6ed381537e6c parent: 95473:597768629c2e user: Donald Stufft date: Tue Apr 07 07:10:38 2015 -0400 summary: update pip to 6.1.1 files: Lib/ensurepip/__init__.py | 2 +- Lib/ensurepip/_bundled/pip-6.1.0-py2.py3-none-any.whl | Bin Lib/ensurepip/_bundled/pip-6.1.1-py2.py3-none-any.whl | Bin 3 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/ensurepip/__init__.py b/Lib/ensurepip/__init__.py --- a/Lib/ensurepip/__init__.py +++ b/Lib/ensurepip/__init__.py @@ -10,7 +10,7 @@ _SETUPTOOLS_VERSION = "15.0" -_PIP_VERSION = "6.1.0" +_PIP_VERSION = "6.1.1" # pip currently requires ssl support, so we try to provide a nicer # error message when that is missing (http://bugs.python.org/issue19744) diff --git a/Lib/ensurepip/_bundled/pip-6.1.0-py2.py3-none-any.whl b/Lib/ensurepip/_bundled/pip-6.1.0-py2.py3-none-any.whl deleted file mode 100644 index 2d075df9f0a002d8d3e08c2d5eb08cfb7e837290..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 GIT binary patch [stripped] diff --git a/Lib/ensurepip/_bundled/pip-6.1.1-py2.py3-none-any.whl b/Lib/ensurepip/_bundled/pip-6.1.1-py2.py3-none-any.whl new file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..e59694a019051d58b9a378a1adfc9461b8cec9c3 GIT binary patch [stripped] -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Apr 7 18:01:49 2015 From: python-checkins at python.org (benjamin.peterson) Date: Tue, 07 Apr 2015 16:01:49 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?b?KTogbWVyZ2UgMy40ICgjMjM4NzMp?= Message-ID: <20150407160041.29525.78778@psf.io> https://hg.python.org/cpython/rev/ea21b99d002e changeset: 95476:ea21b99d002e parent: 95474:b01e69847321 parent: 95475:81ce9d412a4c user: Benjamin Peterson date: Tue Apr 07 12:00:37 2015 -0400 summary: merge 3.4 (#23873) files: Lib/smtpd.py | 9 --------- 1 files changed, 0 insertions(+), 9 deletions(-) diff --git a/Lib/smtpd.py b/Lib/smtpd.py --- a/Lib/smtpd.py +++ b/Lib/smtpd.py @@ -525,9 +525,6 @@ if not self.extended_smtp and params: self.push(syntaxerr) return - if not address: - self.push(syntaxerr) - return if self.mailfrom: self.push('503 Error: nested MAIL command') return @@ -586,15 +583,9 @@ else: self.push(syntaxerr) return - if not address: - self.push(syntaxerr) - return if params and len(params.keys()) > 0: self.push('555 RCPT TO parameters not recognized or not implemented') return - if not address: - self.push('501 Syntax: RCPT TO:
') - return self.rcpttos.append(address) print('recips:', self.rcpttos, file=DEBUGSTREAM) self.push('250 OK') -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Apr 7 18:01:49 2015 From: python-checkins at python.org (benjamin.peterson) Date: Tue, 07 Apr 2015 16:01:49 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E4=29=3A_remove_smtpd_d?= =?utf-8?q?ead_code_=28closes_=2323873=29?= Message-ID: <20150407160041.27438.13576@psf.io> https://hg.python.org/cpython/rev/81ce9d412a4c changeset: 95475:81ce9d412a4c branch: 3.4 parent: 95473:597768629c2e user: Benjamin Peterson date: Tue Apr 07 11:59:06 2015 -0400 summary: remove smtpd dead code (closes #23873) Patch by Hoolean. files: Lib/smtpd.py | 9 --------- 1 files changed, 0 insertions(+), 9 deletions(-) diff --git a/Lib/smtpd.py b/Lib/smtpd.py --- a/Lib/smtpd.py +++ b/Lib/smtpd.py @@ -476,9 +476,6 @@ if not self.extended_smtp and params: self.push(syntaxerr) return - if not address: - self.push(syntaxerr) - return if self.mailfrom: self.push('503 Error: nested MAIL command') return @@ -529,15 +526,9 @@ else: self.push(syntaxerr) return - if not address: - self.push(syntaxerr) - return if params and len(params.keys()) > 0: self.push('555 RCPT TO parameters not recognized or not implemented') return - if not address: - self.push('501 Syntax: RCPT TO:
') - return self.rcpttos.append(address) print('recips:', self.rcpttos, file=DEBUGSTREAM) self.push('250 OK') -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Apr 7 18:09:28 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Tue, 07 Apr 2015 16:09:28 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2323411=3A_Added_De?= =?utf-8?q?fragResult=2C_ParseResult=2C_SplitResult=2C_DefragResultBytes?= =?utf-8?q?=2C?= Message-ID: <20150407160926.16513.69897@psf.io> https://hg.python.org/cpython/rev/a48e76252952 changeset: 95477:a48e76252952 user: Serhiy Storchaka date: Tue Apr 07 19:09:01 2015 +0300 summary: Issue #23411: Added DefragResult, ParseResult, SplitResult, DefragResultBytes, ParseResultBytes, and SplitResultBytes to urllib.parse.__all__. Patch by Martin Panter. files: Lib/test/test_urlparse.py | 16 ++++++++++++++++ Lib/urllib/parse.py | 4 +++- Misc/NEWS | 4 ++++ 3 files changed, 23 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_urlparse.py b/Lib/test/test_urlparse.py --- a/Lib/test/test_urlparse.py +++ b/Lib/test/test_urlparse.py @@ -840,6 +840,22 @@ quoter = urllib.parse.Quoter(urllib.parse._ALWAYS_SAFE) self.assertIn('Quoter', repr(quoter)) + def test_all(self): + expected = [] + undocumented = { + 'splitattr', 'splithost', 'splitnport', 'splitpasswd', + 'splitport', 'splitquery', 'splittag', 'splittype', 'splituser', + 'splitvalue', + 'Quoter', 'ResultBase', 'clear_cache', 'to_bytes', 'unwrap', + } + for name in dir(urllib.parse): + if name.startswith('_') or name in undocumented: + continue + object = getattr(urllib.parse, name) + if getattr(object, '__module__', None) == 'urllib.parse': + expected.append(name) + self.assertCountEqual(urllib.parse.__all__, expected) + class Utility_Tests(unittest.TestCase): """Testcase to test the various utility functions in the urllib.""" diff --git a/Lib/urllib/parse.py b/Lib/urllib/parse.py --- a/Lib/urllib/parse.py +++ b/Lib/urllib/parse.py @@ -34,7 +34,9 @@ __all__ = ["urlparse", "urlunparse", "urljoin", "urldefrag", "urlsplit", "urlunsplit", "urlencode", "parse_qs", "parse_qsl", "quote", "quote_plus", "quote_from_bytes", - "unquote", "unquote_plus", "unquote_to_bytes"] + "unquote", "unquote_plus", "unquote_to_bytes", + "DefragResult", "ParseResult", "SplitResult", + "DefragResultBytes", "ParseResultBytes", "SplitResultBytes"] # A classification of schemes ('' means apply by default) uses_relative = ['ftp', 'http', 'gopher', 'nntp', 'imap', diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -19,6 +19,10 @@ Library ------- +- Issue #23411: Added DefragResult, ParseResult, SplitResult, DefragResultBytes, + ParseResultBytes, and SplitResultBytes to urllib.parse.__all__. + Patch by Martin Panter. + - Issue #23881: urllib.request.ftpwrapper constructor now closes the socket if the FTP connection failed to fix a ResourceWarning. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Apr 7 21:40:42 2015 From: python-checkins at python.org (victor.stinner) Date: Tue, 07 Apr 2015 19:40:42 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzIzODc5?= =?utf-8?q?=2C_asyncio=3A_SelectorEventLoop=2Esock=5Fconnect=28=29_must_no?= =?utf-8?q?t_call_connect=28=29?= Message-ID: <20150407194042.29549.35057@psf.io> https://hg.python.org/cpython/rev/eca51493c770 changeset: 95478:eca51493c770 branch: 3.4 parent: 95475:81ce9d412a4c user: Victor Stinner date: Tue Apr 07 21:38:04 2015 +0200 summary: Issue #23879, asyncio: SelectorEventLoop.sock_connect() must not call connect() again if the first call to connect() raises an InterruptedError. When the C function connect() fails with EINTR, the connection runs in background. We have to wait until the socket becomes writable to be notified when the connection succeed or fails. files: Lib/asyncio/selector_events.py | 14 ++++++-------- 1 files changed, 6 insertions(+), 8 deletions(-) diff --git a/Lib/asyncio/selector_events.py b/Lib/asyncio/selector_events.py --- a/Lib/asyncio/selector_events.py +++ b/Lib/asyncio/selector_events.py @@ -408,14 +408,12 @@ def _sock_connect(self, fut, sock, address): fd = sock.fileno() try: - while True: - try: - sock.connect(address) - except InterruptedError: - continue - else: - break - except BlockingIOError: + sock.connect(address) + except (BlockingIOError, InterruptedError): + # Issue #23618: When the C function connect() fails with EINTR, the + # connection runs in background. We have to wait until the socket + # becomes writable to be notified when the connection succeed or + # fails. fut.add_done_callback(functools.partial(self._sock_connect_done, fd)) self.add_writer(fd, self._sock_connect_cb, fut, sock, address) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Apr 7 21:40:43 2015 From: python-checkins at python.org (victor.stinner) Date: Tue, 07 Apr 2015 19:40:43 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Merge_3=2E4_=28asyncio=29?= Message-ID: <20150407194042.117485.69829@psf.io> https://hg.python.org/cpython/rev/85a5265909cb changeset: 95479:85a5265909cb parent: 95477:a48e76252952 parent: 95478:eca51493c770 user: Victor Stinner date: Tue Apr 07 21:38:36 2015 +0200 summary: Merge 3.4 (asyncio) files: Lib/asyncio/selector_events.py | 14 ++++++-------- 1 files changed, 6 insertions(+), 8 deletions(-) diff --git a/Lib/asyncio/selector_events.py b/Lib/asyncio/selector_events.py --- a/Lib/asyncio/selector_events.py +++ b/Lib/asyncio/selector_events.py @@ -408,14 +408,12 @@ def _sock_connect(self, fut, sock, address): fd = sock.fileno() try: - while True: - try: - sock.connect(address) - except InterruptedError: - continue - else: - break - except BlockingIOError: + sock.connect(address) + except (BlockingIOError, InterruptedError): + # Issue #23618: When the C function connect() fails with EINTR, the + # connection runs in background. We have to wait until the socket + # becomes writable to be notified when the connection succeed or + # fails. fut.add_done_callback(functools.partial(self._sock_connect_done, fd)) self.add_writer(fd, self._sock_connect_cb, fut, sock, address) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Apr 8 00:58:06 2015 From: python-checkins at python.org (gregory.p.smith) Date: Tue, 07 Apr 2015 22:58:06 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Addresses_Issue_=2310838?= =?utf-8?q?=3A_The_subprocess_now_module_includes?= Message-ID: <20150407225806.117481.81146@psf.io> https://hg.python.org/cpython/rev/10b0a8076be8 changeset: 95480:10b0a8076be8 user: Gregory P. Smith date: Tue Apr 07 15:57:54 2015 -0700 summary: Addresses Issue #10838: The subprocess now module includes SubprocessError and TimeoutError in its list of exported names for the users wild enough to use "from subprocess import *". MAXFD, mswindows and list2cmdline should be dealt with (renamed or moved) in separate commits. Committed at 35,000ft. Thanks chromebook free gogo wifi passes! files: Lib/subprocess.py | 5 ++++- Lib/test/test_subprocess.py | 15 +++++++++++++++ Misc/NEWS | 4 ++++ 3 files changed, 23 insertions(+), 1 deletions(-) diff --git a/Lib/subprocess.py b/Lib/subprocess.py --- a/Lib/subprocess.py +++ b/Lib/subprocess.py @@ -433,7 +433,10 @@ __all__ = ["Popen", "PIPE", "STDOUT", "call", "check_call", "getstatusoutput", - "getoutput", "check_output", "CalledProcessError", "DEVNULL"] + "getoutput", "check_output", "CalledProcessError", "DEVNULL", + "SubprocessError", "TimeoutExpired"] + # NOTE: We intentionally exclude list2cmdline as it is + # considered an internal implementation detail. issue10838. if mswindows: from _winapi import (CREATE_NEW_CONSOLE, CREATE_NEW_PROCESS_GROUP, diff --git a/Lib/test/test_subprocess.py b/Lib/test/test_subprocess.py --- a/Lib/test/test_subprocess.py +++ b/Lib/test/test_subprocess.py @@ -2420,6 +2420,21 @@ subprocess._PopenSelector = self.orig_selector ProcessTestCase.tearDown(self) + def test__all__(self): + """Ensure that __all__ is populated properly.""" + intentionally_excluded = set(("list2cmdline", "mswindows", "MAXFD")) + exported = set(subprocess.__all__) + possible_exports = set() + import types + for name, value in subprocess.__dict__.items(): + if name.startswith('_'): + continue + if isinstance(value, (types.ModuleType,)): + continue + possible_exports.add(name) + self.assertEqual(exported, possible_exports - intentionally_excluded) + + @unittest.skipUnless(mswindows, "Windows-specific tests") class CommandsWithSpaces (BaseTestCase): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -19,6 +19,10 @@ Library ------- +- Issue #10838: The subprocess now module includes SubprocessError and + TimeoutError in its list of exported names for the users wild enough + to use "from subprocess import *". + - Issue #23411: Added DefragResult, ParseResult, SplitResult, DefragResultBytes, ParseResultBytes, and SplitResultBytes to urllib.parse.__all__. Patch by Martin Panter. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Apr 8 01:11:43 2015 From: python-checkins at python.org (gregory.p.smith) Date: Tue, 07 Apr 2015 23:11:43 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_issue10838=3A_Rename_the_s?= =?utf-8?q?ubprocess=2Emswindows_internal_global_to_=5Fmswindows=2E?= Message-ID: <20150407231142.117493.80122@psf.io> https://hg.python.org/cpython/rev/4c14afc3f931 changeset: 95481:4c14afc3f931 user: Gregory P. Smith date: Tue Apr 07 16:11:33 2015 -0700 summary: issue10838: Rename the subprocess.mswindows internal global to _mswindows. It is internal only, not a documented API. files: Lib/subprocess.py | 12 ++++++------ Lib/test/test_subprocess.py | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Lib/subprocess.py b/Lib/subprocess.py --- a/Lib/subprocess.py +++ b/Lib/subprocess.py @@ -356,7 +356,7 @@ """ import sys -mswindows = (sys.platform == "win32") +_mswindows = (sys.platform == "win32") import io import os @@ -399,7 +399,7 @@ (self.cmd, self.timeout)) -if mswindows: +if _mswindows: import threading import msvcrt import _winapi @@ -438,7 +438,7 @@ # NOTE: We intentionally exclude list2cmdline as it is # considered an internal implementation detail. issue10838. -if mswindows: +if _mswindows: from _winapi import (CREATE_NEW_CONSOLE, CREATE_NEW_PROCESS_GROUP, STD_INPUT_HANDLE, STD_OUTPUT_HANDLE, STD_ERROR_HANDLE, SW_HIDE, @@ -765,7 +765,7 @@ if not isinstance(bufsize, int): raise TypeError("bufsize must be an integer") - if mswindows: + if _mswindows: if preexec_fn is not None: raise ValueError("preexec_fn is not supported on Windows " "platforms") @@ -825,7 +825,7 @@ # quickly terminating child could make our fds unwrappable # (see #8458). - if mswindows: + if _mswindows: if p2cwrite != -1: p2cwrite = msvcrt.open_osfhandle(p2cwrite.Detach(), 0) if c2pread != -1: @@ -1002,7 +1002,7 @@ raise TimeoutExpired(self.args, orig_timeout) - if mswindows: + if _mswindows: # # Windows methods # diff --git a/Lib/test/test_subprocess.py b/Lib/test/test_subprocess.py --- a/Lib/test/test_subprocess.py +++ b/Lib/test/test_subprocess.py @@ -2422,7 +2422,7 @@ def test__all__(self): """Ensure that __all__ is populated properly.""" - intentionally_excluded = set(("list2cmdline", "mswindows", "MAXFD")) + intentionally_excluded = set(("list2cmdline",)) exported = set(subprocess.__all__) possible_exports = set() import types -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Apr 8 08:46:58 2015 From: python-checkins at python.org (berker.peksag) Date: Wed, 08 Apr 2015 06:46:58 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2323883=3A_Add_miss?= =?utf-8?b?aW5nIGVudHJpZXMgdG8gdHJhY2ViYWNrLl9fYWxsX18u?= Message-ID: <20150408064658.92268.14040@psf.io> https://hg.python.org/cpython/rev/ebf3e6332a44 changeset: 95482:ebf3e6332a44 user: Berker Peksag date: Wed Apr 08 09:47:14 2015 +0300 summary: Issue #23883: Add missing entries to traceback.__all__. files: Lib/test/test_traceback.py | 23 ++++++++++++++++------- Lib/traceback.py | 5 +++-- 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/Lib/test/test_traceback.py b/Lib/test/test_traceback.py --- a/Lib/test/test_traceback.py +++ b/Lib/test/test_traceback.py @@ -6,8 +6,7 @@ import sys import unittest import re -from test.support import run_unittest, Error, captured_output -from test.support import TESTFN, unlink, cpython_only +from test.support import TESTFN, Error, captured_output, unlink, cpython_only from test.script_helper import assert_python_ok import textwrap @@ -593,7 +592,7 @@ traceback.walk_stack(None), capture_locals=True, limit=1) s = some_inner(3, 4) self.assertEqual( - [' File "' + __file__ + '", line 593, ' + [' File "' + __file__ + '", line 592, ' 'in some_inner\n' ' traceback.walk_stack(None), capture_locals=True, limit=1)\n' ' a = 1\n' @@ -603,7 +602,6 @@ ], s.format()) - class TestTracebackException(unittest.TestCase): def test_smoke(self): @@ -732,8 +730,19 @@ self.assertEqual(exc.stack[0].locals, None) -def test_main(): - run_unittest(__name__) +class MiscTest(unittest.TestCase): + + def test_all(self): + expected = set() + blacklist = {'print_list'} + for name in dir(traceback): + if name.startswith('_') or name in blacklist: + continue + module_object = getattr(traceback, name) + if getattr(module_object, '__module__', None) == 'traceback': + expected.add(name) + self.assertCountEqual(traceback.__all__, expected) + if __name__ == "__main__": - test_main() + unittest.main() diff --git a/Lib/traceback.py b/Lib/traceback.py --- a/Lib/traceback.py +++ b/Lib/traceback.py @@ -7,8 +7,9 @@ __all__ = ['extract_stack', 'extract_tb', 'format_exception', 'format_exception_only', 'format_list', 'format_stack', 'format_tb', 'print_exc', 'format_exc', 'print_exception', - 'print_last', 'print_stack', 'print_tb', - 'clear_frames'] + 'print_last', 'print_stack', 'print_tb', 'clear_frames', + 'FrameSummary', 'StackSummary', 'TracebackException', + 'walk_stack', 'walk_tb'] # # Formatting and printing lists of traceback lines. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Apr 8 10:24:36 2015 From: python-checkins at python.org (berker.peksag) Date: Wed, 08 Apr 2015 08:24:36 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E4=29=3A_Skip_nntplib_t?= =?utf-8?q?ests_when_transient_errors_captured=2E?= Message-ID: <20150408082436.27424.5146@psf.io> https://hg.python.org/cpython/rev/2b62f8954566 changeset: 95483:2b62f8954566 branch: 3.4 parent: 95478:eca51493c770 user: Berker Peksag date: Wed Apr 08 11:24:27 2015 +0300 summary: Skip nntplib tests when transient errors captured. files: Lib/test/support/__init__.py | 5 +++++ 1 files changed, 5 insertions(+), 0 deletions(-) diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py --- a/Lib/test/support/__init__.py +++ b/Lib/test/support/__init__.py @@ -13,6 +13,7 @@ import importlib import importlib.util import logging.handlers +import nntplib import os import platform import re @@ -1340,6 +1341,10 @@ if timeout is not None: socket.setdefaulttimeout(timeout) yield + except nntplib.NNTPTemporaryError as err: + if verbose: + sys.stderr.write(denied.args[0] + "\n") + raise denied from err except OSError as err: # urllib can wrap original socket errors multiple times (!), we must # unwrap to get at the original error. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Apr 8 10:24:36 2015 From: python-checkins at python.org (berker.peksag) Date: Wed, 08 Apr 2015 08:24:36 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Skip_nntplib_tests_when_transient_errors_captured=2E?= Message-ID: <20150408082436.48117.13230@psf.io> https://hg.python.org/cpython/rev/162743b7f59b changeset: 95484:162743b7f59b parent: 95482:ebf3e6332a44 parent: 95483:2b62f8954566 user: Berker Peksag date: Wed Apr 08 11:24:51 2015 +0300 summary: Skip nntplib tests when transient errors captured. files: Lib/test/support/__init__.py | 5 +++++ 1 files changed, 5 insertions(+), 0 deletions(-) diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py --- a/Lib/test/support/__init__.py +++ b/Lib/test/support/__init__.py @@ -13,6 +13,7 @@ import importlib import importlib.util import logging.handlers +import nntplib import os import platform import re @@ -1341,6 +1342,10 @@ if timeout is not None: socket.setdefaulttimeout(timeout) yield + except nntplib.NNTPTemporaryError as err: + if verbose: + sys.stderr.write(denied.args[0] + "\n") + raise denied from err except OSError as err: # urllib can wrap original socket errors multiple times (!), we must # unwrap to get at the original error. -- Repository URL: https://hg.python.org/cpython From solipsis at pitrou.net Wed Apr 8 10:35:57 2015 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Wed, 08 Apr 2015 08:35:57 +0000 Subject: [Python-checkins] Daily reference leaks (4c14afc3f931): sum=1 Message-ID: <20150408083556.48127.67424@psf.io> results for 4c14afc3f931 on branch "default" -------------------------------------------- test_collections leaked [-2, 0, 0] references, sum=-2 test_functools leaked [0, 0, 3] memory blocks, sum=3 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogSQccSC', '--timeout', '7200'] From python-checkins at python.org Wed Apr 8 16:38:22 2015 From: python-checkins at python.org (berker.peksag) Date: Wed, 08 Apr 2015 14:38:22 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2323027=3A_test=5Fw?= =?utf-8?q?arnings_now_passes_all_tests_when_run_it_with_-Werror=2E?= Message-ID: <20150408143821.23604.49629@psf.io> https://hg.python.org/cpython/rev/e64197dad303 changeset: 95485:e64197dad303 user: Berker Peksag date: Wed Apr 08 17:38:39 2015 +0300 summary: Issue #23027: test_warnings now passes all tests when run it with -Werror. files: Lib/test/test_warnings.py | 21 ++++++++++++--------- 1 files changed, 12 insertions(+), 9 deletions(-) diff --git a/Lib/test/test_warnings.py b/Lib/test/test_warnings.py --- a/Lib/test/test_warnings.py +++ b/Lib/test/test_warnings.py @@ -456,17 +456,20 @@ self.assertIn('category must be a Warning subclass, not ', str(cm.exception)) - with self.assertWarns(MyWarningClass) as cm: - self.module.warn('good warning category', MyWarningClass) - self.assertEqual('good warning category', str(cm.warning)) + with original_warnings.catch_warnings(module=self.module): + self.module.resetwarnings() + self.module.filterwarnings('default') + with self.assertWarns(MyWarningClass) as cm: + self.module.warn('good warning category', MyWarningClass) + self.assertEqual('good warning category', str(cm.warning)) - with self.assertWarns(UserWarning) as cm: - self.module.warn('good warning category', None) - self.assertEqual('good warning category', str(cm.warning)) + with self.assertWarns(UserWarning) as cm: + self.module.warn('good warning category', None) + self.assertEqual('good warning category', str(cm.warning)) - with self.assertWarns(MyWarningClass) as cm: - self.module.warn('good warning category', MyWarningClass) - self.assertIsInstance(cm.warning, Warning) + with self.assertWarns(MyWarningClass) as cm: + self.module.warn('good warning category', MyWarningClass) + self.assertIsInstance(cm.warning, Warning) class CWarnTests(WarnTests, unittest.TestCase): module = c_warnings -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Apr 8 16:57:30 2015 From: python-checkins at python.org (berker.peksag) Date: Wed, 08 Apr 2015 14:57:30 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzIzNDAw?= =?utf-8?q?=3A_Raise_same_exception_on_both_Python_2_and_3_if_sem=5Fopen_i?= =?utf-8?q?s_not?= Message-ID: <20150408145730.15225.67023@psf.io> https://hg.python.org/cpython/rev/749fd043de95 changeset: 95486:749fd043de95 branch: 3.4 parent: 95483:2b62f8954566 user: Berker Peksag date: Wed Apr 08 17:56:30 2015 +0300 summary: Issue #23400: Raise same exception on both Python 2 and 3 if sem_open is not available. Patch by Davin Potts. files: Doc/library/multiprocessing.rst | 24 ++++++++++++++------- Lib/multiprocessing/queues.py | 3 +- Misc/NEWS | 3 ++ 3 files changed, 21 insertions(+), 9 deletions(-) diff --git a/Doc/library/multiprocessing.rst b/Doc/library/multiprocessing.rst --- a/Doc/library/multiprocessing.rst +++ b/Doc/library/multiprocessing.rst @@ -262,14 +262,6 @@ Without using the lock output from the different processes is liable to get all mixed up. -.. note:: - - Some of this package's functionality requires a functioning shared semaphore - implementation on the host operating system. Without one, the - :mod:`multiprocessing.synchronize` module will be disabled, and attempts to - import it will result in an :exc:`ImportError`. See - :issue:`3770` for additional information. - Sharing state between processes ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -808,6 +800,14 @@ immediately without waiting to flush enqueued data to the underlying pipe, and you don't care about lost data. + .. note:: + + This class's functionality requires a functioning shared semaphore + implementation on the host operating system. Without one, the + functionality in this class will be disabled, and attempts to + instantiate a :class:`Queue` will result in an :exc:`ImportError`. See + :issue:`3770` for additional information. The same holds true for any + of the specialized queue types listed below. .. class:: SimpleQueue() @@ -1183,6 +1183,14 @@ This differs from the behaviour of :mod:`threading` where SIGINT will be ignored while the equivalent blocking calls are in progress. +.. note:: + + Some of this package's functionality requires a functioning shared semaphore + implementation on the host operating system. Without one, the + :mod:`multiprocessing.synchronize` module will be disabled, and attempts to + import it will result in an :exc:`ImportError`. See + :issue:`3770` for additional information. + Shared :mod:`ctypes` Objects ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/Lib/multiprocessing/queues.py b/Lib/multiprocessing/queues.py --- a/Lib/multiprocessing/queues.py +++ b/Lib/multiprocessing/queues.py @@ -35,7 +35,8 @@ def __init__(self, maxsize=0, *, ctx): if maxsize <= 0: - maxsize = _multiprocessing.SemLock.SEM_VALUE_MAX + # Can raise ImportError (see issues #3770 and #23400) + from .synchronize import SEM_VALUE_MAX as maxsize self._maxsize = maxsize self._reader, self._writer = connection.Pipe(duplex=False) self._rlock = ctx.Lock() diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -27,6 +27,9 @@ - Issue #23881: urllib.request.ftpwrapper constructor now closes the socket if the FTP connection failed to fix a ResourceWarning. +- Issue #23400: Raise same exception on both Python 2 and 3 if sem_open is not + available. Patch by Davin Potts. + - Issue #15133: _tkinter.tkapp.getboolean() now supports Tcl_Obj and always returns bool. tkinter.BooleanVar now validates input values (accepted bool, int, str, and Tcl_Obj). tkinter.BooleanVar.get() now always returns bool. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Apr 8 16:57:30 2015 From: python-checkins at python.org (berker.peksag) Date: Wed, 08 Apr 2015 14:57:30 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2323400=3A_Raise_same_exception_on_both_Python_2_?= =?utf-8?q?and_3_if_sem=5Fopen_is_not?= Message-ID: <20150408145730.27430.2611@psf.io> https://hg.python.org/cpython/rev/a49737bd6086 changeset: 95487:a49737bd6086 parent: 95485:e64197dad303 parent: 95486:749fd043de95 user: Berker Peksag date: Wed Apr 08 17:57:44 2015 +0300 summary: Issue #23400: Raise same exception on both Python 2 and 3 if sem_open is not available. Patch by Davin Potts. files: Doc/library/multiprocessing.rst | 24 ++++++++++++++------- Lib/multiprocessing/queues.py | 3 +- Misc/NEWS | 3 ++ 3 files changed, 21 insertions(+), 9 deletions(-) diff --git a/Doc/library/multiprocessing.rst b/Doc/library/multiprocessing.rst --- a/Doc/library/multiprocessing.rst +++ b/Doc/library/multiprocessing.rst @@ -262,14 +262,6 @@ Without using the lock output from the different processes is liable to get all mixed up. -.. note:: - - Some of this package's functionality requires a functioning shared semaphore - implementation on the host operating system. Without one, the - :mod:`multiprocessing.synchronize` module will be disabled, and attempts to - import it will result in an :exc:`ImportError`. See - :issue:`3770` for additional information. - Sharing state between processes ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -808,6 +800,14 @@ immediately without waiting to flush enqueued data to the underlying pipe, and you don't care about lost data. + .. note:: + + This class's functionality requires a functioning shared semaphore + implementation on the host operating system. Without one, the + functionality in this class will be disabled, and attempts to + instantiate a :class:`Queue` will result in an :exc:`ImportError`. See + :issue:`3770` for additional information. The same holds true for any + of the specialized queue types listed below. .. class:: SimpleQueue() @@ -1183,6 +1183,14 @@ This differs from the behaviour of :mod:`threading` where SIGINT will be ignored while the equivalent blocking calls are in progress. +.. note:: + + Some of this package's functionality requires a functioning shared semaphore + implementation on the host operating system. Without one, the + :mod:`multiprocessing.synchronize` module will be disabled, and attempts to + import it will result in an :exc:`ImportError`. See + :issue:`3770` for additional information. + Shared :mod:`ctypes` Objects ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/Lib/multiprocessing/queues.py b/Lib/multiprocessing/queues.py --- a/Lib/multiprocessing/queues.py +++ b/Lib/multiprocessing/queues.py @@ -35,7 +35,8 @@ def __init__(self, maxsize=0, *, ctx): if maxsize <= 0: - maxsize = _multiprocessing.SemLock.SEM_VALUE_MAX + # Can raise ImportError (see issues #3770 and #23400) + from .synchronize import SEM_VALUE_MAX as maxsize self._maxsize = maxsize self._reader, self._writer = connection.Pipe(duplex=False) self._rlock = ctx.Lock() diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -19,6 +19,9 @@ Library ------- +- Issue #23400: Raise same exception on both Python 2 and 3 if sem_open is not + available. Patch by Davin Potts. + - Issue #10838: The subprocess now module includes SubprocessError and TimeoutError in its list of exported names for the users wild enough to use "from subprocess import *". -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Apr 8 17:11:50 2015 From: python-checkins at python.org (benjamin.peterson) Date: Wed, 08 Apr 2015 15:11:50 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E4=29=3A_actually_ssl3_?= =?utf-8?q?is_just_completely_broken?= Message-ID: <20150408151149.15221.40594@psf.io> https://hg.python.org/cpython/rev/4eb197bfffb6 changeset: 95488:4eb197bfffb6 branch: 3.4 parent: 95486:749fd043de95 user: Benjamin Peterson date: Wed Apr 08 11:11:00 2015 -0400 summary: actually ssl3 is just completely broken files: Doc/library/ssl.rst | 14 +++++++------- 1 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Doc/library/ssl.rst b/Doc/library/ssl.rst --- a/Doc/library/ssl.rst +++ b/Doc/library/ssl.rst @@ -263,13 +263,13 @@ .. note:: If you find that when certain older clients or servers attempt to connect - with a :class:`SSLContext` created by this function that they get an - error stating "Protocol or cipher suite mismatch", it may be that they - only support SSL3.0 which this function excludes using the - :data:`OP_NO_SSLv3`. SSL3.0 has problematic security due to a number of - poor implementations and it's reliance on MD5 within the protocol. If you - wish to continue to use this function but still allow SSL 3.0 connections - you can re-enable them using:: + with a :class:`SSLContext` created by this function that they get an error + stating "Protocol or cipher suite mismatch", it may be that they only + support SSL3.0 which this function excludes using the + :data:`OP_NO_SSLv3`. SSL3.0 is widely considered to be `completely broken + `_. If you still wish to continue to + use this function but still allow SSL 3.0 connections you can re-enable + them using:: ctx = ssl.create_default_context(Purpose.CLIENT_AUTH) ctx.options &= ~ssl.OP_NO_SSLv3 -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Apr 8 17:11:49 2015 From: python-checkins at python.org (benjamin.peterson) Date: Wed, 08 Apr 2015 15:11:49 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_actually_ssl3_?= =?utf-8?q?is_just_completely_broken?= Message-ID: <20150408151149.29531.80716@psf.io> https://hg.python.org/cpython/rev/e52571aad42f changeset: 95489:e52571aad42f branch: 2.7 parent: 95472:6bce7c6d0502 user: Benjamin Peterson date: Wed Apr 08 11:11:00 2015 -0400 summary: actually ssl3 is just completely broken files: Doc/library/ssl.rst | 14 +++++++------- 1 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Doc/library/ssl.rst b/Doc/library/ssl.rst --- a/Doc/library/ssl.rst +++ b/Doc/library/ssl.rst @@ -263,13 +263,13 @@ .. note:: If you find that when certain older clients or servers attempt to connect - with a :class:`SSLContext` created by this function that they get an - error stating "Protocol or cipher suite mismatch", it may be that they - only support SSL3.0 which this function excludes using the - :data:`OP_NO_SSLv3`. SSL3.0 has problematic security due to a number of - poor implementations and it's reliance on MD5 within the protocol. If you - wish to continue to use this function but still allow SSL 3.0 connections - you can re-enable them using:: + with a :class:`SSLContext` created by this function that they get an error + stating "Protocol or cipher suite mismatch", it may be that they only + support SSL3.0 which this function excludes using the + :data:`OP_NO_SSLv3`. SSL3.0 is widely considered to be `completely broken + `_. If you still wish to continue to + use this function but still allow SSL 3.0 connections you can re-enable + them using:: ctx = ssl.create_default_context(Purpose.CLIENT_AUTH) ctx.options &= ~ssl.OP_NO_SSLv3 -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Apr 8 17:11:51 2015 From: python-checkins at python.org (benjamin.peterson) Date: Wed, 08 Apr 2015 15:11:51 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?b?KTogbWVyZ2UgMy40?= Message-ID: <20150408151149.23602.31563@psf.io> https://hg.python.org/cpython/rev/c7dbb5e7423d changeset: 95490:c7dbb5e7423d parent: 95487:a49737bd6086 parent: 95488:4eb197bfffb6 user: Benjamin Peterson date: Wed Apr 08 11:11:45 2015 -0400 summary: merge 3.4 files: Doc/library/ssl.rst | 14 +++++++------- 1 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Doc/library/ssl.rst b/Doc/library/ssl.rst --- a/Doc/library/ssl.rst +++ b/Doc/library/ssl.rst @@ -263,13 +263,13 @@ .. note:: If you find that when certain older clients or servers attempt to connect - with a :class:`SSLContext` created by this function that they get an - error stating "Protocol or cipher suite mismatch", it may be that they - only support SSL3.0 which this function excludes using the - :data:`OP_NO_SSLv3`. SSL3.0 has problematic security due to a number of - poor implementations and it's reliance on MD5 within the protocol. If you - wish to continue to use this function but still allow SSL 3.0 connections - you can re-enable them using:: + with a :class:`SSLContext` created by this function that they get an error + stating "Protocol or cipher suite mismatch", it may be that they only + support SSL3.0 which this function excludes using the + :data:`OP_NO_SSLv3`. SSL3.0 is widely considered to be `completely broken + `_. If you still wish to continue to + use this function but still allow SSL 3.0 connections you can re-enable + them using:: ctx = ssl.create_default_context(Purpose.CLIENT_AUTH) ctx.options &= ~ssl.OP_NO_SSLv3 -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Apr 8 17:12:41 2015 From: python-checkins at python.org (berker.peksag) Date: Wed, 08 Apr 2015 15:12:41 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzIzNDAw?= =?utf-8?q?=3A_Add_notes_about_the_sem=5Fopen_support_of_the_host_OS_to?= Message-ID: <20150408151240.84813.73642@psf.io> https://hg.python.org/cpython/rev/c2f6b3677630 changeset: 95491:c2f6b3677630 branch: 2.7 parent: 95489:e52571aad42f user: Berker Peksag date: Wed Apr 08 18:12:53 2015 +0300 summary: Issue #23400: Add notes about the sem_open support of the host OS to "Pipes and Queues" and "Synchronization between processes" subsections. Patch by Davin Potts. files: Doc/library/multiprocessing.rst | 25 ++++++++++++++------ 1 files changed, 17 insertions(+), 8 deletions(-) diff --git a/Doc/library/multiprocessing.rst b/Doc/library/multiprocessing.rst --- a/Doc/library/multiprocessing.rst +++ b/Doc/library/multiprocessing.rst @@ -160,14 +160,6 @@ Without using the lock output from the different processes is liable to get all mixed up. -.. warning:: - - Some of this package's functionality requires a functioning shared semaphore - implementation on the host operating system. Without one, the - :mod:`multiprocessing.synchronize` module will be disabled, and attempts to - import it will result in an :exc:`ImportError`. See - :issue:`3770` for additional information. - Sharing state between processes ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -659,6 +651,15 @@ immediately without waiting to flush enqueued data to the underlying pipe, and you don't care about lost data. + .. note:: + + This class's functionality requires a functioning shared semaphore + implementation on the host operating system. Without one, the + functionality in this class will be disabled, and attempts to + instantiate a :class:`Queue` will result in an :exc:`ImportError`. See + :issue:`3770` for additional information. The same holds true for any + of the specialized queue types listed below. + .. class:: multiprocessing.queues.SimpleQueue() @@ -965,6 +966,14 @@ This differs from the behaviour of :mod:`threading` where SIGINT will be ignored while the equivalent blocking calls are in progress. +.. note:: + + Some of this package's functionality requires a functioning shared semaphore + implementation on the host operating system. Without one, the + :mod:`multiprocessing.synchronize` module will be disabled, and attempts to + import it will result in an :exc:`ImportError`. See + :issue:`3770` for additional information. + Shared :mod:`ctypes` Objects ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Apr 8 17:54:13 2015 From: python-checkins at python.org (tim.golden) Date: Wed, 08 Apr 2015 15:54:13 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E4=29=3A_Fix_typo_in_te?= =?utf-8?q?lnet_docs_=28reported_by_Keith_Briggs=29?= Message-ID: <20150408155336.29527.57086@psf.io> https://hg.python.org/cpython/rev/283036fe48e2 changeset: 95492:283036fe48e2 branch: 3.4 parent: 95488:4eb197bfffb6 user: Tim Golden date: Wed Apr 08 16:52:27 2015 +0100 summary: Fix typo in telnet docs (reported by Keith Briggs) files: Doc/library/telnetlib.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/library/telnetlib.rst b/Doc/library/telnetlib.rst --- a/Doc/library/telnetlib.rst +++ b/Doc/library/telnetlib.rst @@ -31,7 +31,7 @@ :class:`Telnet` represents a connection to a Telnet server. The instance is initially not connected by default; the :meth:`open` method must be used to establish a connection. Alternatively, the host name and optional port - number can be passed to the constructor, to, in which case the connection to + number can be passed to the constructor too, in which case the connection to the server will be established before the constructor returns. The optional *timeout* parameter specifies a timeout in seconds for blocking operations like the connection attempt (if not specified, the global default timeout -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Apr 8 17:54:13 2015 From: python-checkins at python.org (tim.golden) Date: Wed, 08 Apr 2015 15:54:13 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Merge_from_3=2E4?= Message-ID: <20150408155336.29539.32051@psf.io> https://hg.python.org/cpython/rev/0ca028765488 changeset: 95493:0ca028765488 parent: 95490:c7dbb5e7423d parent: 95492:283036fe48e2 user: Tim Golden date: Wed Apr 08 16:53:21 2015 +0100 summary: Merge from 3.4 files: Doc/library/telnetlib.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/library/telnetlib.rst b/Doc/library/telnetlib.rst --- a/Doc/library/telnetlib.rst +++ b/Doc/library/telnetlib.rst @@ -31,7 +31,7 @@ :class:`Telnet` represents a connection to a Telnet server. The instance is initially not connected by default; the :meth:`open` method must be used to establish a connection. Alternatively, the host name and optional port - number can be passed to the constructor, to, in which case the connection to + number can be passed to the constructor too, in which case the connection to the server will be established before the constructor returns. The optional *timeout* parameter specifies a timeout in seconds for blocking operations like the connection attempt (if not specified, the global default timeout -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Apr 9 10:32:55 2015 From: python-checkins at python.org (victor.stinner) Date: Thu, 09 Apr 2015 08:32:55 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2323618=3A_Fix_inte?= =?utf-8?q?rnal=5Fselect=28=29_for_negative_timeout_=28blocking_socket=29_?= =?utf-8?q?when?= Message-ID: <20150409083255.25161.31386@psf.io> https://hg.python.org/cpython/rev/bff88c866886 changeset: 95495:bff88c866886 user: Victor Stinner date: Thu Apr 09 10:27:25 2015 +0200 summary: Issue #23618: Fix internal_select() for negative timeout (blocking socket) when poll() is not available. select() doesn't accept negative timeout, the timeout parameter must be NULL to block on select(). files: Modules/socketmodule.c | 13 +++++++++---- 1 files changed, 9 insertions(+), 4 deletions(-) diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -614,7 +614,7 @@ _PyTime_t ms; #else fd_set fds, efds; - struct timeval tv; + struct timeval tv, *tvp; #endif #ifdef WITH_THREAD @@ -650,7 +650,12 @@ n = poll(&pollfd, 1, (int)ms); Py_END_ALLOW_THREADS; #else - _PyTime_AsTimeval_noraise(interval, &tv, _PyTime_ROUND_CEILING); + if (interval >= 0) { + _PyTime_AsTimeval_noraise(interval, &tv, _PyTime_ROUND_CEILING); + tvp = &tv; + } + else + tvp = NULL; FD_ZERO(&fds); FD_SET(s->sock_fd, &fds); @@ -667,10 +672,10 @@ Py_BEGIN_ALLOW_THREADS; if (writing) n = select(Py_SAFE_DOWNCAST(s->sock_fd+1, SOCKET_T, int), - NULL, &fds, &efds, &tv); + NULL, &fds, &efds, tvp); else n = select(Py_SAFE_DOWNCAST(s->sock_fd+1, SOCKET_T, int), - &fds, NULL, &efds, &tv); + &fds, NULL, &efds, tvp); Py_END_ALLOW_THREADS; #endif -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Apr 9 10:32:56 2015 From: python-checkins at python.org (victor.stinner) Date: Thu, 09 Apr 2015 08:32:56 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2323834=3A_Fix_the_?= =?utf-8?q?default_socket_timeout?= Message-ID: <20150409083255.93216.19193@psf.io> https://hg.python.org/cpython/rev/462680f4e8af changeset: 95494:462680f4e8af user: Victor Stinner date: Thu Apr 09 10:23:12 2015 +0200 summary: Issue #23834: Fix the default socket timeout Use -1 second by default, not -1 nanosecond. files: Include/pytime.h | 7 ++++++- Modules/socketmodule.c | 3 ++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/Include/pytime.h b/Include/pytime.h --- a/Include/pytime.h +++ b/Include/pytime.h @@ -67,7 +67,12 @@ /* Create a timestamp from a number of seconds. */ -PyAPI_FUNC(_PyTime_t) _PyTime_FromSeconds(int ns); +PyAPI_FUNC(_PyTime_t) _PyTime_FromSeconds(int seconds); + +/* Macro to create a timestamp from a number of seconds, no integer overflow. + Only use the macro for small values, prefer _PyTime_FromSeconds(). */ +#define _PYTIME_FROMSECONDS(seconds) \ + ((_PyTime_t)(seconds) * (1000 * 1000 * 1000)) /* Create a timestamp from a number of nanoseconds. */ PyAPI_FUNC(_PyTime_t) _PyTime_FromNanoseconds(PY_LONG_LONG ns); diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -839,7 +839,8 @@ /* Initialize a new socket object. */ -static _PyTime_t defaulttimeout = -1; /* Default timeout for new sockets */ +/* Default timeout for new sockets */ +static _PyTime_t defaulttimeout = _PYTIME_FROMSECONDS(-1); static void init_sockobject(PySocketSockObject *s, -- Repository URL: https://hg.python.org/cpython From solipsis at pitrou.net Thu Apr 9 10:40:14 2015 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Thu, 09 Apr 2015 08:40:14 +0000 Subject: [Python-checkins] Daily reference leaks (0ca028765488): sum=3 Message-ID: <20150409084013.11917.97901@psf.io> results for 0ca028765488 on branch "default" -------------------------------------------- test_collections leaked [2, -2, 0] references, sum=0 test_functools leaked [0, 0, 3] memory blocks, sum=3 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogytegB3', '--timeout', '7200'] From python-checkins at python.org Thu Apr 9 21:46:30 2015 From: python-checkins at python.org (zach.ware) Date: Thu, 09 Apr 2015 19:46:30 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzIzNjg2?= =?utf-8?q?=3A_Update_Windows_build_to_use_OpenSSL_1=2E0=2E2a?= Message-ID: <20150409194629.26869.61007@psf.io> https://hg.python.org/cpython/rev/05a502da108f changeset: 95496:05a502da108f branch: 2.7 parent: 95491:c2f6b3677630 user: Zachary Ware date: Tue Apr 07 20:33:54 2015 -0500 summary: Issue #23686: Update Windows build to use OpenSSL 1.0.2a files: Misc/NEWS | 3 ++- PCbuild/pyproject.vsprops | 2 +- PCbuild/readme.txt | 2 +- Tools/buildbot/external-common.bat | 5 +++-- 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -248,7 +248,8 @@ - Issue #23032: Fix installer build failures on OS X 10.4 Tiger by disabling assembly code in the OpenSSL build. -- Issue #23686: Update OS X 10.5 installer build to use OpenSSL 1.0.2a. +- Issue #23686: Update OS X 10.5 installer and Windows builds to use + OpenSSL 1.0.2a. C API ----- diff --git a/PCbuild/pyproject.vsprops b/PCbuild/pyproject.vsprops --- a/PCbuild/pyproject.vsprops +++ b/PCbuild/pyproject.vsprops @@ -82,7 +82,7 @@ /> https://hg.python.org/cpython/rev/354ca4911b6c changeset: 95499:354ca4911b6c parent: 95498:6578b978a39e parent: 95497:404e4adf492c user: Zachary Ware date: Thu Apr 09 14:44:18 2015 -0500 summary: Null merge from 3.4 files: -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Apr 9 21:46:31 2015 From: python-checkins at python.org (zach.ware) Date: Thu, 09 Apr 2015 19:46:31 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzIzNjg2?= =?utf-8?q?=3A_Update_Windows_build_to_use_OpenSSL_1=2E0=2E2a=2E?= Message-ID: <20150409194630.10602.60257@psf.io> https://hg.python.org/cpython/rev/404e4adf492c changeset: 95497:404e4adf492c branch: 3.4 parent: 95492:283036fe48e2 user: Zachary Ware date: Tue Apr 07 19:59:37 2015 -0500 summary: Issue #23686: Update Windows build to use OpenSSL 1.0.2a. files: Misc/NEWS | 3 ++- PCbuild/pyproject.props | 2 +- PCbuild/readme.txt | 2 +- Tools/buildbot/external-common.bat | 8 ++++---- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -178,7 +178,8 @@ - Issue #23445: pydebug builds now use "gcc -Og" where possible, to make the resulting executable faster. -- Issue #23686: Update OS X 10.5 installer build to use OpenSSL 1.0.2a. +- Issue #23686: Update OS X 10.5 installer and Windows builds to use + OpenSSL 1.0.2a. What's New in Python 3.4.3? diff --git a/PCbuild/pyproject.props b/PCbuild/pyproject.props --- a/PCbuild/pyproject.props +++ b/PCbuild/pyproject.props @@ -20,7 +20,7 @@ $(externalsDir)\sqlite-3.8.3.1 $(externalsDir)\bzip2-1.0.6 $(externalsDir)\xz-5.0.5 - $(externalsDir)\openssl-1.0.1l + $(externalsDir)\openssl-1.0.2a $(externalsDir)\tcltk $(externalsDir)\tcltk64 $(tcltkDir)\lib\tcl86t.lib;$(tcltkDir)\lib\tk86t.lib diff --git a/PCbuild/readme.txt b/PCbuild/readme.txt --- a/PCbuild/readme.txt +++ b/PCbuild/readme.txt @@ -171,7 +171,7 @@ Homepage: http://tukaani.org/xz/ _ssl - Python wrapper for version 1.0.1j of the OpenSSL secure sockets + Python wrapper for version 1.0.2a of the OpenSSL secure sockets library, which is built by ssl.vcxproj Homepage: http://www.openssl.org/ diff --git a/Tools/buildbot/external-common.bat b/Tools/buildbot/external-common.bat --- a/Tools/buildbot/external-common.bat +++ b/Tools/buildbot/external-common.bat @@ -14,7 +14,7 @@ @rem if exist tk-8.6.1.0 rd /s/q tk-8.6.1.0 @rem if exist tix-8.4.3.4 rd /s/q tix-8.4.3.4 @rem if exist db-4.4.20 rd /s/q db-4.4.20 - at rem if exist openssl-1.0.1l rd /s/q openssl-1.0.1l + at rem if exist openssl-1.0.2a rd /s/q openssl-1.0.2a @rem if exist sqlite-3.7.12 rd /s/q sqlite-3.7.12 @rem bzip @@ -28,9 +28,9 @@ if not exist nasm-2.11.06 svn export %SVNROOT%nasm-2.11.06 @rem OpenSSL -if not exist openssl-1.0.1l ( - rd /s/q openssl-1.0.1j - svn export %SVNROOT%openssl-1.0.1l +if not exist openssl-1.0.2a ( + rd /s/q openssl-1.0.1l + svn export %SVNROOT%openssl-1.0.2a ) @rem tcl/tk -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Apr 9 21:46:31 2015 From: python-checkins at python.org (zach.ware) Date: Thu, 09 Apr 2015 19:46:31 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Fix_prepare=5Fssl=2Epy_for?= =?utf-8?q?_OpenSSL_1=2E0=2E2a_builds_without_Perl_=28using_old_system=29?= =?utf-8?q?=2E?= Message-ID: <20150409194630.10610.87465@psf.io> https://hg.python.org/cpython/rev/6578b978a39e changeset: 95498:6578b978a39e parent: 95495:bff88c866886 user: Zachary Ware date: Tue Apr 07 20:38:53 2015 -0500 summary: Fix prepare_ssl.py for OpenSSL 1.0.2a builds without Perl (using old system). This change affects the makefiles checked into svn.python.org, which the 3.5 build no longer uses. 3.4 and 2.7 both still use those makefiles, but their build_ssl.py scripts don't require an update; if the script is running the 'fix_makefiles' method it already has Perl available anyway. files: PCbuild/prepare_ssl.py | 3 +++ 1 files changed, 3 insertions(+), 0 deletions(-) diff --git a/PCbuild/prepare_ssl.py b/PCbuild/prepare_ssl.py --- a/PCbuild/prepare_ssl.py +++ b/PCbuild/prepare_ssl.py @@ -132,6 +132,9 @@ if noalgo not in line: line = line + noalgo line = line + '\n' + if r'$(SRC_D)\util\copy-if-different.pl' in line: + line = line.replace(r'$(SRC_D)\util\copy-if-different.pl', + 'copy /Y') fout.write(line) def run_configure(configure, do_script): -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Apr 9 22:22:30 2015 From: python-checkins at python.org (steve.dower) Date: Thu, 09 Apr 2015 20:22:30 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Updates_Windows_release_sc?= =?utf-8?q?ripts_to_generate_and_upload_GPG_signatures=2E?= Message-ID: <20150409202229.24668.15903@psf.io> https://hg.python.org/cpython/rev/579db1976e6d changeset: 95500:579db1976e6d user: Steve Dower date: Sun Apr 05 18:42:37 2015 -0700 summary: Updates Windows release scripts to generate and upload GPG signatures. files: Tools/msi/generate_md5.py | 27 ++++++++++++++++++++++++ Tools/msi/uploadrelease.bat | 9 ++++++++ Tools/msi/uploadrelease.proj | 21 +++++++++++++++++- 3 files changed, 56 insertions(+), 1 deletions(-) diff --git a/Tools/msi/generate_md5.py b/Tools/msi/generate_md5.py new file mode 100644 --- /dev/null +++ b/Tools/msi/generate_md5.py @@ -0,0 +1,27 @@ +import hashlib +import os +import sys + +def main(): + filenames, hashes, sizes = [], [], [] + + for file in sys.argv[1:]: + if not os.path.isfile(file): + continue + + with open(file, 'rb') as f: + data = f.read() + md5 = hashlib.md5() + md5.update(data) + filenames.append(os.path.split(file)[1]) + hashes.append(md5.hexdigest()) + sizes.append(str(len(data))) + + print('{:40s} {:<32s} {:<9s}'.format('File', 'MD5', 'Size')) + for f, h, s in zip(filenames, hashes, sizes): + print('{:40s} {:>32s} {:>9s}'.format(f, h, s)) + + + +if __name__ == "__main__": + sys.exit(int(main() or 0)) diff --git a/Tools/msi/uploadrelease.bat b/Tools/msi/uploadrelease.bat --- a/Tools/msi/uploadrelease.bat +++ b/Tools/msi/uploadrelease.bat @@ -20,19 +20,28 @@ if "%1" EQU "--dry-run" (set DRYRUN=true) && shift && goto CheckOpts if not defined PLINK where plink > "%TEMP%\plink.loc" 2> nul && set /P PLINK= < "%TEMP%\plink.loc" & del "%TEMP%\plink.loc" +if not defined PLINK where /R "%ProgramFiles(x86)%\PuTTY" plink > "%TEMP%\plink.loc" 2> nul && set /P PLINK= < "%TEMP%\plink.loc" & del "%TEMP%\plink.loc" if not defined PLINK where /R "%ProgramFiles(x86)%" plink > "%TEMP%\plink.loc" 2> nul && set /P PLINK= < "%TEMP%\plink.loc" & del "%TEMP%\plink.loc" if not defined PLINK echo Cannot locate plink.exe & exit /B 1 echo Found plink.exe at %PLINK% if not defined PSCP where pscp > "%TEMP%\pscp.loc" 2> nul && set /P pscp= < "%TEMP%\pscp.loc" & del "%TEMP%\pscp.loc" +if not defined PSCP where /R "%ProgramFiles(x86)%\PuTTY" pscp > "%TEMP%\pscp.loc" 2> nul && set /P pscp= < "%TEMP%\pscp.loc" & del "%TEMP%\pscp.loc" if not defined PSCP where /R "%ProgramFiles(x86)%" pscp > "%TEMP%\pscp.loc" 2> nul && set /P pscp= < "%TEMP%\pscp.loc" & del "%TEMP%\pscp.loc" if not defined PSCP echo Cannot locate pscp.exe & exit /B 1 echo Found pscp.exe at %PSCP% +if not defined GPG where gpg2 > "%TEMP%\gpg.loc" 2> nul && set /P GPG= < "%TEMP%\gpg.loc" & del "%TEMP%\gpg.loc" +if not defined GPG where /R "%PCBUILD%..\externals" gpg2 > "%TEMP%\gpg.loc" 2> nul && set /P GPG= < "%TEMP%\gpg.loc" & del "%TEMP%\gpg.loc" +if not defined GPG echo Cannot locate gpg2.exe. Signatures will not be uploaded & pause +echo Found gpg2.exe at %GPG% + call "%PCBUILD%env.bat" > nul 2> nul pushd "%D%" msbuild /v:m /nologo uploadrelease.proj /t:Upload /p:Platform=x86 msbuild /v:m /nologo uploadrelease.proj /t:Upload /p:Platform=x64 /p:IncludeDoc=false +msbuild /v:m /nologo uploadrelease.proj /t:ShowHashes /p:Platform=x86 +msbuild /v:m /nologo uploadrelease.proj /t:ShowHashes /p:Platform=x64 /p:IncludeDoc=false popd exit /B 0 diff --git a/Tools/msi/uploadrelease.proj b/Tools/msi/uploadrelease.proj --- a/Tools/msi/uploadrelease.proj +++ b/Tools/msi/uploadrelease.proj @@ -38,6 +38,17 @@ + + + + + + + %(File.CopyTo) + + + + - + + + + + + + + + -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Apr 9 22:29:59 2015 From: python-checkins at python.org (victor.stinner) Date: Thu, 09 Apr 2015 20:29:59 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2323817=3A_FreeBSD_?= =?utf-8?q?now_uses_=221=2E0=22_the_the_SOVERSION_as_other_operating?= Message-ID: <20150409202959.21073.6392@psf.io> https://hg.python.org/cpython/rev/7444ac6d93c3 changeset: 95501:7444ac6d93c3 user: Victor Stinner date: Thu Apr 09 22:29:52 2015 +0200 summary: Issue #23817: FreeBSD now uses "1.0" the the SOVERSION as other operating systems, instead of just "1". files: Misc/NEWS | 3 +++ configure.ac | 5 ----- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -108,6 +108,9 @@ Build ----- +- Issue #23817: FreeBSD now uses "1.0" the the SOVERSION as other operating + systems, instead of just "1". + - Issue #23501: Argument Clinic now generates code into separate files by default. Tests diff --git a/configure.ac b/configure.ac --- a/configure.ac +++ b/configure.ac @@ -960,11 +960,6 @@ LDLIBRARY='libpython$(LDVERSION).so' BLDLIBRARY='-L. -lpython$(LDVERSION)' RUNSHARED=LD_LIBRARY_PATH=`pwd`${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}} - case $ac_sys_system in - FreeBSD*) - SOVERSION=`echo $SOVERSION|cut -d "." -f 1` - ;; - esac INSTSONAME="$LDLIBRARY".$SOVERSION if test "$with_pydebug" != yes then -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Apr 9 22:51:54 2015 From: python-checkins at python.org (zach.ware) Date: Thu, 09 Apr 2015 20:51:54 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_Refresh_OpenSS?= =?utf-8?q?L_sources_on_the_buildbots?= Message-ID: <20150409205154.21097.69427@psf.io> https://hg.python.org/cpython/rev/7b1ceb925471 changeset: 95502:7b1ceb925471 branch: 2.7 parent: 95496:05a502da108f user: Zachary Ware date: Thu Apr 09 15:50:08 2015 -0500 summary: Refresh OpenSSL sources on the buildbots files: Tools/buildbot/external-common.bat | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Tools/buildbot/external-common.bat b/Tools/buildbot/external-common.bat --- a/Tools/buildbot/external-common.bat +++ b/Tools/buildbot/external-common.bat @@ -29,7 +29,7 @@ @rem if exist openssl-1.0.1i rd /s/q openssl-1.0.1i @rem if exist openssl-1.0.1j rd /s/q openssl-1.0.1j @rem if exist openssl-1.0.1l rd /s/q openssl-1.0.1l - at rem if exist openssl-1.0.2a rd /s/q openssl-1.0.2a +if exist openssl-1.0.2a rd /s/q openssl-1.0.2a @rem if exist sqlite-3.6.21 rd /s/q sqlite-3.6.21 @rem bzip -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Apr 9 22:51:54 2015 From: python-checkins at python.org (zach.ware) Date: Thu, 09 Apr 2015 20:51:54 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Fix_prepare=5Fssl=2Epy_scr?= =?utf-8?q?ipt?= Message-ID: <20150409205154.8633.62003@psf.io> https://hg.python.org/cpython/rev/b87aadc61fd1 changeset: 95503:b87aadc61fd1 parent: 95501:7444ac6d93c3 user: Zachary Ware date: Thu Apr 09 15:48:32 2015 -0500 summary: Fix prepare_ssl.py script Builds using prepared sources that had Perl available anyway were broken by the previous fix to this script (oops). files: PCbuild/prepare_ssl.py | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) diff --git a/PCbuild/prepare_ssl.py b/PCbuild/prepare_ssl.py --- a/PCbuild/prepare_ssl.py +++ b/PCbuild/prepare_ssl.py @@ -115,6 +115,7 @@ """ if not os.path.isfile(makefile): return + copy_if_different = r'$(PERL) $(SRC_D)\util\copy-if-different.pl' with open(makefile) as fin: lines = fin.readlines() with open(makefile, 'w') as fout: @@ -132,9 +133,8 @@ if noalgo not in line: line = line + noalgo line = line + '\n' - if r'$(SRC_D)\util\copy-if-different.pl' in line: - line = line.replace(r'$(SRC_D)\util\copy-if-different.pl', - 'copy /Y') + if copy_if_different in line: + line = line.replace(copy_if_different, 'copy /Y') fout.write(line) def run_configure(configure, do_script): -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Apr 9 22:51:55 2015 From: python-checkins at python.org (zach.ware) Date: Thu, 09 Apr 2015 20:51:55 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E4=29=3A_Refresh_OpenSS?= =?utf-8?q?L_sources_on_the_buildbots?= Message-ID: <20150409205154.92405.78034@psf.io> https://hg.python.org/cpython/rev/bc41a4d6c58f changeset: 95504:bc41a4d6c58f branch: 3.4 parent: 95497:404e4adf492c user: Zachary Ware date: Thu Apr 09 15:51:17 2015 -0500 summary: Refresh OpenSSL sources on the buildbots files: Tools/buildbot/external-common.bat | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Tools/buildbot/external-common.bat b/Tools/buildbot/external-common.bat --- a/Tools/buildbot/external-common.bat +++ b/Tools/buildbot/external-common.bat @@ -14,7 +14,7 @@ @rem if exist tk-8.6.1.0 rd /s/q tk-8.6.1.0 @rem if exist tix-8.4.3.4 rd /s/q tix-8.4.3.4 @rem if exist db-4.4.20 rd /s/q db-4.4.20 - at rem if exist openssl-1.0.2a rd /s/q openssl-1.0.2a +if exist openssl-1.0.2a rd /s/q openssl-1.0.2a @rem if exist sqlite-3.7.12 rd /s/q sqlite-3.7.12 @rem bzip -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Apr 9 23:41:08 2015 From: python-checkins at python.org (zach.ware) Date: Thu, 09 Apr 2015 21:41:08 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_Backed_out_cha?= =?utf-8?q?ngeset_7b1ceb925471_after_buildbots_have_new_OpenSSL_source=2E?= Message-ID: <20150409214108.818.5269@psf.io> https://hg.python.org/cpython/rev/a6a8dd33914e changeset: 95505:a6a8dd33914e branch: 2.7 parent: 95502:7b1ceb925471 user: Zachary Ware date: Thu Apr 09 15:55:33 2015 -0500 summary: Backed out changeset 7b1ceb925471 after buildbots have new OpenSSL source. files: Tools/buildbot/external-common.bat | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Tools/buildbot/external-common.bat b/Tools/buildbot/external-common.bat --- a/Tools/buildbot/external-common.bat +++ b/Tools/buildbot/external-common.bat @@ -29,7 +29,7 @@ @rem if exist openssl-1.0.1i rd /s/q openssl-1.0.1i @rem if exist openssl-1.0.1j rd /s/q openssl-1.0.1j @rem if exist openssl-1.0.1l rd /s/q openssl-1.0.1l -if exist openssl-1.0.2a rd /s/q openssl-1.0.2a + at rem if exist openssl-1.0.2a rd /s/q openssl-1.0.2a @rem if exist sqlite-3.6.21 rd /s/q sqlite-3.6.21 @rem bzip -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Apr 9 23:41:08 2015 From: python-checkins at python.org (zach.ware) Date: Thu, 09 Apr 2015 21:41:08 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Null_merge_with_3=2E4?= Message-ID: <20150409214108.51501.33244@psf.io> https://hg.python.org/cpython/rev/73965ffae982 changeset: 95507:73965ffae982 parent: 95503:b87aadc61fd1 parent: 95506:ce29f3f9271c user: Zachary Ware date: Thu Apr 09 15:56:22 2015 -0500 summary: Null merge with 3.4 files: -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Apr 9 23:41:08 2015 From: python-checkins at python.org (zach.ware) Date: Thu, 09 Apr 2015 21:41:08 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E4=29=3A_Backed_out_cha?= =?utf-8?q?ngeset_bc41a4d6c58f_after_buildbots_have_new_OpenSSL_source=2E?= Message-ID: <20150409214108.21285.91561@psf.io> https://hg.python.org/cpython/rev/ce29f3f9271c changeset: 95506:ce29f3f9271c branch: 3.4 parent: 95504:bc41a4d6c58f user: Zachary Ware date: Thu Apr 09 15:55:56 2015 -0500 summary: Backed out changeset bc41a4d6c58f after buildbots have new OpenSSL source. files: Tools/buildbot/external-common.bat | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Tools/buildbot/external-common.bat b/Tools/buildbot/external-common.bat --- a/Tools/buildbot/external-common.bat +++ b/Tools/buildbot/external-common.bat @@ -14,7 +14,7 @@ @rem if exist tk-8.6.1.0 rd /s/q tk-8.6.1.0 @rem if exist tix-8.4.3.4 rd /s/q tix-8.4.3.4 @rem if exist db-4.4.20 rd /s/q db-4.4.20 -if exist openssl-1.0.2a rd /s/q openssl-1.0.2a + at rem if exist openssl-1.0.2a rd /s/q openssl-1.0.2a @rem if exist sqlite-3.7.12 rd /s/q sqlite-3.7.12 @rem bzip -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Apr 10 01:20:40 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Thu, 09 Apr 2015 23:20:40 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogUmVwbGFjZWQgInN0?= =?utf-8?q?ring=22_with_=22bytes_object=22_in_docstrings_of_binary_I/O_obj?= =?utf-8?q?ects=2E?= Message-ID: <20150409232040.62507.69951@psf.io> https://hg.python.org/cpython/rev/98b4450f0a0a changeset: 95508:98b4450f0a0a branch: 3.4 parent: 95506:ce29f3f9271c user: Serhiy Storchaka date: Fri Apr 10 02:18:44 2015 +0300 summary: Replaced "string" with "bytes object" in docstrings of binary I/O objects. files: Modules/_io/bytesio.c | 20 ++++++++++---------- Modules/_io/fileio.c | 6 +++--- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/Modules/_io/bytesio.c b/Modules/_io/bytesio.c --- a/Modules/_io/bytesio.c +++ b/Modules/_io/bytesio.c @@ -258,10 +258,10 @@ } PyDoc_STRVAR(read_doc, -"read([size]) -> read at most size bytes, returned as a string.\n" +"read([size]) -> read at most size bytes, returned as a bytes object.\n" "\n" "If the size argument is negative, read until EOF is reached.\n" -"Return an empty string at EOF."); +"Return an empty bytes object at EOF."); static PyObject * bytesio_read(bytesio *self, PyObject *args) @@ -307,10 +307,10 @@ PyDoc_STRVAR(read1_doc, -"read1(size) -> read at most size bytes, returned as a string.\n" +"read1(size) -> read at most size bytes, returned as a bytes object.\n" "\n" "If the size argument is negative or omitted, read until EOF is reached.\n" -"Return an empty string at EOF."); +"Return an empty bytes object at EOF."); static PyObject * bytesio_read1(bytesio *self, PyObject *n) @@ -326,11 +326,11 @@ } PyDoc_STRVAR(readline_doc, -"readline([size]) -> next line from the file, as a string.\n" +"readline([size]) -> next line from the file, as a bytes object.\n" "\n" "Retain newline. A non-negative size argument limits the maximum\n" "number of bytes to return (an incomplete line may be returned then).\n" -"Return an empty string at EOF.\n"); +"Return an empty bytes object at EOF.\n"); static PyObject * bytesio_readline(bytesio *self, PyObject *args) @@ -615,11 +615,11 @@ } PyDoc_STRVAR(writelines_doc, -"writelines(sequence_of_strings) -> None. Write strings to the file.\n" +"writelines(lines) -> None. Write bytes objects to the file.\n" "\n" -"Note that newlines are not added. The sequence can be any iterable\n" -"object producing strings. This is equivalent to calling write() for\n" -"each string."); +"Note that newlines are not added. The argument can be any iterable\n" +"object producing bytes objects. This is equivalent to calling write() for\n" +"each bytes object."); static PyObject * bytesio_writelines(bytesio *self, PyObject *v) diff --git a/Modules/_io/fileio.c b/Modules/_io/fileio.c --- a/Modules/_io/fileio.c +++ b/Modules/_io/fileio.c @@ -667,7 +667,7 @@ if (bufsize > PY_SSIZE_T_MAX || bufsize <= 0) { PyErr_SetString(PyExc_OverflowError, "unbounded read returned more bytes " - "than a Python string can hold"); + "than a Python bytes object can hold"); Py_DECREF(result); return NULL; } @@ -1111,13 +1111,13 @@ "\n" "Only makes one system call, so less data may be returned than requested\n" "In non-blocking mode, returns None if no data is available.\n" -"On end-of-file, returns ''."); +"Return an empty bytes object at EOF."); PyDoc_STRVAR(readall_doc, "readall() -> bytes. read all data from the file, returned as bytes.\n" "\n" "In non-blocking mode, returns as much as is immediately available,\n" -"or None if no data is available. On end-of-file, returns ''."); +"or None if no data is available. Return an empty bytes object at EOF."); PyDoc_STRVAR(write_doc, "write(b: bytes) -> int. Write bytes b to file, return number written.\n" -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Apr 10 01:20:40 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Thu, 09 Apr 2015 23:20:40 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Replaced_=22string=22_with_=22bytes_object=22_in_docstri?= =?utf-8?q?ngs_of_binary_I/O_objects=2E?= Message-ID: <20150409232040.62517.78273@psf.io> https://hg.python.org/cpython/rev/4e40fafc95e3 changeset: 95509:4e40fafc95e3 parent: 95507:73965ffae982 parent: 95508:98b4450f0a0a user: Serhiy Storchaka date: Fri Apr 10 02:19:57 2015 +0300 summary: Replaced "string" with "bytes object" in docstrings of binary I/O objects. files: Modules/_io/bytesio.c | 20 ++++++++++---------- Modules/_io/fileio.c | 6 +++--- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/Modules/_io/bytesio.c b/Modules/_io/bytesio.c --- a/Modules/_io/bytesio.c +++ b/Modules/_io/bytesio.c @@ -325,10 +325,10 @@ } PyDoc_STRVAR(read_doc, -"read([size]) -> read at most size bytes, returned as a string.\n" +"read([size]) -> read at most size bytes, returned as a bytes object.\n" "\n" "If the size argument is negative, read until EOF is reached.\n" -"Return an empty string at EOF."); +"Return an empty bytes object at EOF."); static PyObject * bytesio_read(bytesio *self, PyObject *args) @@ -369,10 +369,10 @@ PyDoc_STRVAR(read1_doc, -"read1(size) -> read at most size bytes, returned as a string.\n" +"read1(size) -> read at most size bytes, returned as a bytes object.\n" "\n" "If the size argument is negative or omitted, read until EOF is reached.\n" -"Return an empty string at EOF."); +"Return an empty bytes object at EOF."); static PyObject * bytesio_read1(bytesio *self, PyObject *n) @@ -388,11 +388,11 @@ } PyDoc_STRVAR(readline_doc, -"readline([size]) -> next line from the file, as a string.\n" +"readline([size]) -> next line from the file, as a bytes object.\n" "\n" "Retain newline. A non-negative size argument limits the maximum\n" "number of bytes to return (an incomplete line may be returned then).\n" -"Return an empty string at EOF.\n"); +"Return an empty bytes object at EOF.\n"); static PyObject * bytesio_readline(bytesio *self, PyObject *args) @@ -672,11 +672,11 @@ } PyDoc_STRVAR(writelines_doc, -"writelines(sequence_of_strings) -> None. Write strings to the file.\n" +"writelines(lines) -> None. Write bytes objects to the file.\n" "\n" -"Note that newlines are not added. The sequence can be any iterable\n" -"object producing strings. This is equivalent to calling write() for\n" -"each string."); +"Note that newlines are not added. The argument can be any iterable\n" +"object producing bytes objects. This is equivalent to calling write() for\n" +"each bytes object."); static PyObject * bytesio_writelines(bytesio *self, PyObject *v) diff --git a/Modules/_io/fileio.c b/Modules/_io/fileio.c --- a/Modules/_io/fileio.c +++ b/Modules/_io/fileio.c @@ -629,7 +629,7 @@ if (bufsize > PY_SSIZE_T_MAX || bufsize <= 0) { PyErr_SetString(PyExc_OverflowError, "unbounded read returned more bytes " - "than a Python string can hold"); + "than a Python bytes object can hold"); Py_DECREF(result); return NULL; } @@ -1031,13 +1031,13 @@ "\n" "Only makes one system call, so less data may be returned than requested\n" "In non-blocking mode, returns None if no data is available.\n" -"On end-of-file, returns ''."); +"Return an empty bytes object at EOF."); PyDoc_STRVAR(readall_doc, "readall() -> bytes. read all data from the file, returned as bytes.\n" "\n" "In non-blocking mode, returns as much as is immediately available,\n" -"or None if no data is available. On end-of-file, returns ''."); +"or None if no data is available. Return an empty bytes object at EOF."); PyDoc_STRVAR(write_doc, "write(b: bytes) -> int. Write bytes b to file, return number written.\n" -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Apr 10 03:22:16 2015 From: python-checkins at python.org (zach.ware) Date: Fri, 10 Apr 2015 01:22:16 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?b?KTogTWVyZ2Ugd2l0aCAzLjQu?= Message-ID: <20150410012216.62525.40951@psf.io> https://hg.python.org/cpython/rev/76ed5454b09d changeset: 95512:76ed5454b09d parent: 95509:4e40fafc95e3 parent: 95511:f0e2caad4200 user: Zachary Ware date: Thu Apr 09 20:20:55 2015 -0500 summary: Merge with 3.4. The fix has moved in this branch. Also, the opt-in is already available on this branch; just set nasmDir when building. files: PCbuild/openssl.props | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/PCbuild/openssl.props b/PCbuild/openssl.props --- a/PCbuild/openssl.props +++ b/PCbuild/openssl.props @@ -65,7 +65,7 @@ -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Apr 10 03:22:16 2015 From: python-checkins at python.org (zach.ware) Date: Fri, 10 Apr 2015 01:22:16 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E4=29=3A_Put_the_NASM_p?= =?utf-8?q?ulled_from_svn=2Epython=2Eorg_at_the_front_of_the_PATH=2E?= Message-ID: <20150410012215.21087.84925@psf.io> https://hg.python.org/cpython/rev/f0e2caad4200 changeset: 95511:f0e2caad4200 branch: 3.4 parent: 95508:98b4450f0a0a user: Zachary Ware date: Thu Apr 09 20:16:05 2015 -0500 summary: Put the NASM pulled from svn.python.org at the front of the PATH. This will prevent failures from the version of NASM installed on buildbots, if the ability to override the version used is desired again later, we can figure out a way to opt in. files: PCbuild/build_ssl.py | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) diff --git a/PCbuild/build_ssl.py b/PCbuild/build_ssl.py --- a/PCbuild/build_ssl.py +++ b/PCbuild/build_ssl.py @@ -187,7 +187,8 @@ if dir.startswith('nasm'): nasm_dir = os.path.join(ssl_dir, os.pardir, dir) nasm_dir = os.path.abspath(nasm_dir) - os.environ['PATH'] += os.pathsep.join(['', nasm_dir]) + old_path = os.environ['PATH'] + os.environ['PATH'] = os.pathsep.join([nasm_dir, old_path]) break else: print('NASM was not found, make sure it is on PATH') -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Apr 10 03:22:15 2015 From: python-checkins at python.org (zach.ware) Date: Fri, 10 Apr 2015 01:22:15 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_Put_the_NASM_p?= =?utf-8?q?ulled_from_svn=2Epython=2Eorg_at_the_front_of_the_PATH=2E?= Message-ID: <20150410012215.21095.41725@psf.io> https://hg.python.org/cpython/rev/50ed581fea04 changeset: 95510:50ed581fea04 branch: 2.7 parent: 95505:a6a8dd33914e user: Zachary Ware date: Thu Apr 09 20:16:05 2015 -0500 summary: Put the NASM pulled from svn.python.org at the front of the PATH. This will prevent failures from the version of NASM installed on buildbots, if the ability to override the version used is desired again later, we can figure out a way to opt in. files: PCbuild/build_ssl.py | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) diff --git a/PCbuild/build_ssl.py b/PCbuild/build_ssl.py --- a/PCbuild/build_ssl.py +++ b/PCbuild/build_ssl.py @@ -175,7 +175,8 @@ if dir.startswith('nasm'): nasm_dir = os.path.join(ssl_dir, os.pardir, dir) nasm_dir = os.path.abspath(nasm_dir) - os.environ['PATH'] += os.pathsep.join(['', nasm_dir]) + old_path = os.environ['PATH'] + os.environ['PATH'] = os.pathsep.join([nasm_dir, old_path]) break else: print('NASM was not found, make sure it is on PATH') -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Apr 10 06:22:55 2015 From: python-checkins at python.org (zach.ware) Date: Fri, 10 Apr 2015 04:22:55 +0000 Subject: [Python-checkins] =?utf-8?q?devguide=3A_Update_VS_2015_recommenda?= =?utf-8?q?tion=2E?= Message-ID: <20150410042255.41542.38535@psf.io> https://hg.python.org/devguide/rev/c43d87755ade changeset: 735:c43d87755ade user: Zachary Ware date: Thu Apr 09 23:22:25 2015 -0500 summary: Update VS 2015 recommendation. VS2015 Preview doesn't have a particular new function that we use. files: setup.rst | 8 ++++---- 1 files changed, 4 insertions(+), 4 deletions(-) diff --git a/setup.rst b/setup.rst --- a/setup.rst +++ b/setup.rst @@ -227,10 +227,10 @@ software is required to build which parts of Python. **Python 3.5** and later use Microsoft Visual Studio 2015. You can download -`Microsoft Visual Studio 2015 Ultimate Preview -`_, or you can -continue to use Visual Studio 2010 SP1 until Microsoft releases the final -version of Visual Studio 2015. +`Microsoft Visual Studio 2015 CTP 6 or newer +`_, +or you can continue to use Visual Studio 2010 SP1 until Microsoft releases +the final version of Visual Studio 2015. Python 3.3 and 3.4 use Microsoft Visual Studio 2010. You can download Microsoft Visual C++ 2010 Express `from Microsoft's site -- Repository URL: https://hg.python.org/devguide From solipsis at pitrou.net Fri Apr 10 10:38:49 2015 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Fri, 10 Apr 2015 08:38:49 +0000 Subject: [Python-checkins] Daily reference leaks (76ed5454b09d): sum=3 Message-ID: <20150410083849.8629.30835@psf.io> results for 76ed5454b09d on branch "default" -------------------------------------------- test_collections leaked [-2, 0, 2] references, sum=0 test_functools leaked [0, 0, 3] memory blocks, sum=3 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogPXqn7l', '--timeout', '7200'] From python-checkins at python.org Fri Apr 10 12:30:54 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Fri, 10 Apr 2015 10:30:54 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Use_assertRaisesRegex_instead_of_deprecated_assertRaises?= =?utf-8?q?Regexp=2E?= Message-ID: <20150410103054.62519.98573@psf.io> https://hg.python.org/cpython/rev/04ce9da70f61 changeset: 95514:04ce9da70f61 parent: 95512:76ed5454b09d parent: 95513:edc5b77dc29a user: Serhiy Storchaka date: Fri Apr 10 12:54:19 2015 +0300 summary: Use assertRaisesRegex instead of deprecated assertRaisesRegexp. files: Lib/test/test_xmlrpc.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_xmlrpc.py b/Lib/test/test_xmlrpc.py --- a/Lib/test/test_xmlrpc.py +++ b/Lib/test/test_xmlrpc.py @@ -909,7 +909,7 @@ encoded = xmlrpclib.gzip_encode(data) with self.assertRaisesRegex(ValueError, - "max gzipped payload length exceeded"): + "max gzipped payload length exceeded"): xmlrpclib.gzip_decode(encoded) xmlrpclib.gzip_decode(encoded, max_decode=-1) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Apr 10 12:30:54 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Fri, 10 Apr 2015 10:30:54 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E4=29=3A_Use_assertRais?= =?utf-8?q?esRegex_instead_of_deprecated_assertRaisesRegexp=2E?= Message-ID: <20150410103054.37458.70267@psf.io> https://hg.python.org/cpython/rev/edc5b77dc29a changeset: 95513:edc5b77dc29a branch: 3.4 parent: 95511:f0e2caad4200 user: Serhiy Storchaka date: Fri Apr 10 12:52:09 2015 +0300 summary: Use assertRaisesRegex instead of deprecated assertRaisesRegexp. files: Lib/test/test_xmlrpc.py | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_xmlrpc.py b/Lib/test/test_xmlrpc.py --- a/Lib/test/test_xmlrpc.py +++ b/Lib/test/test_xmlrpc.py @@ -891,8 +891,8 @@ data = b'\0' * (max_gzip_decode + 1) encoded = xmlrpclib.gzip_encode(data) - with self.assertRaisesRegexp(ValueError, - "max gzipped payload length exceeded"): + with self.assertRaisesRegex(ValueError, + "max gzipped payload length exceeded"): xmlrpclib.gzip_decode(encoded) xmlrpclib.gzip_decode(encoded, max_decode=-1) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Apr 10 12:30:59 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Fri, 10 Apr 2015 10:30:59 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E4=29=3A_Suppress_a_cou?= =?utf-8?q?ple_more_DeprecationWarnings_in_the_test_suite=2E?= Message-ID: <20150410103059.21285.82138@psf.io> https://hg.python.org/cpython/rev/e40f5ef53819 changeset: 95515:e40f5ef53819 branch: 3.4 parent: 95513:edc5b77dc29a user: R David Murray date: Wed Jun 11 17:09:43 2014 -0400 summary: Suppress a couple more DeprecationWarnings in the test suite. files: Lib/test/test_urllibnet.py | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_urllibnet.py b/Lib/test/test_urllibnet.py --- a/Lib/test/test_urllibnet.py +++ b/Lib/test/test_urllibnet.py @@ -91,7 +91,8 @@ # test getcode() with the fancy opener to get 404 error codes URL = "http://www.example.com/XXXinvalidXXX" with support.transient_internet(URL): - open_url = urllib.request.FancyURLopener().open(URL) + with self.assertWarns(DeprecationWarning): + open_url = urllib.request.FancyURLopener().open(URL) try: code = open_url.getcode() finally: -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Apr 10 12:31:00 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Fri, 10 Apr 2015 10:31:00 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Null_merge?= Message-ID: <20150410103059.113205.53692@psf.io> https://hg.python.org/cpython/rev/cbcd37ae1a2a changeset: 95516:cbcd37ae1a2a parent: 95514:04ce9da70f61 parent: 95515:e40f5ef53819 user: Serhiy Storchaka date: Fri Apr 10 13:03:05 2015 +0300 summary: Null merge files: -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Apr 10 12:31:00 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Fri, 10 Apr 2015 10:31:00 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzIzODY1?= =?utf-8?q?=3A_close=28=29_methods_in_multiple_modules_now_are_idempotent_?= =?utf-8?q?and_more?= Message-ID: <20150410103059.21079.92653@psf.io> https://hg.python.org/cpython/rev/e826940911c8 changeset: 95518:e826940911c8 branch: 3.4 parent: 95515:e40f5ef53819 user: Serhiy Storchaka date: Fri Apr 10 13:24:41 2015 +0300 summary: Issue #23865: close() methods in multiple modules now are idempotent and more robust at shutdown. If needs to release multiple resources, they are released even if errors are occured. files: Lib/aifc.py | 5 +- Lib/binhex.py | 42 ++++++++---- Lib/chunk.py | 6 +- Lib/dbm/dumb.py | 6 +- Lib/distutils/text_file.py | 3 +- Lib/fileinput.py | 40 ++++++----- Lib/ftplib.py | 15 +++- Lib/gzip.py | 26 ++++--- Lib/http/client.py | 24 ++++-- Lib/logging/__init__.py | 21 ++++-- Lib/logging/handlers.py | 23 ++++-- Lib/mailbox.py | 12 ++- Lib/multiprocessing/connection.py | 15 +++- Lib/multiprocessing/queues.py | 10 ++- Lib/poplib.py | 29 +++++--- Lib/selectors.py | 12 ++- Lib/shelve.py | 24 ++++--- Lib/smtplib.py | 16 +++- Lib/sunau.py | 13 ++- Lib/tarfile.py | 61 +++++++++--------- Lib/telnetlib.py | 5 +- Lib/tempfile.py | 8 +- Lib/urllib/response.py | 14 ++- Lib/wave.py | 22 +++--- Lib/xml/sax/expatreader.py | 20 +++-- Lib/xmlrpc/client.py | 20 ++++- Misc/NEWS | 4 + 27 files changed, 299 insertions(+), 197 deletions(-) diff --git a/Lib/aifc.py b/Lib/aifc.py --- a/Lib/aifc.py +++ b/Lib/aifc.py @@ -356,7 +356,10 @@ self._soundpos = 0 def close(self): - self._file.close() + file = self._file + if file is not None: + self._file = None + file.close() def tell(self): return self._soundpos diff --git a/Lib/binhex.py b/Lib/binhex.py --- a/Lib/binhex.py +++ b/Lib/binhex.py @@ -32,7 +32,8 @@ pass # States (what have we written) -[_DID_HEADER, _DID_DATA, _DID_RSRC] = range(3) +_DID_HEADER = 0 +_DID_DATA = 1 # Various constants REASONABLY_LARGE = 32768 # Minimal amount we pass the rle-coder @@ -213,16 +214,21 @@ self._write(data) def close(self): - if self.state < _DID_DATA: - self.close_data() - if self.state != _DID_DATA: - raise Error('Close at the wrong time') - if self.rlen != 0: - raise Error("Incorrect resource-datasize, diff=%r" % (self.rlen,)) - self._writecrc() - self.ofp.close() - self.state = None - del self.ofp + if self.state is None: + return + try: + if self.state < _DID_DATA: + self.close_data() + if self.state != _DID_DATA: + raise Error('Close at the wrong time') + if self.rlen != 0: + raise Error("Incorrect resource-datasize, diff=%r" % (self.rlen,)) + self._writecrc() + finally: + self.state = None + ofp = self.ofp + del self.ofp + ofp.close() def binhex(inp, out): """binhex(infilename, outfilename): create binhex-encoded copy of a file""" @@ -436,11 +442,15 @@ return self._read(n) def close(self): - if self.rlen: - dummy = self.read_rsrc(self.rlen) - self._checkcrc() - self.state = _DID_RSRC - self.ifp.close() + if self.state is None: + return + try: + if self.rlen: + dummy = self.read_rsrc(self.rlen) + self._checkcrc() + finally: + self.state = None + self.ifp.close() def hexbin(inp, out): """hexbin(infilename, outfilename) - Decode binhexed file""" diff --git a/Lib/chunk.py b/Lib/chunk.py --- a/Lib/chunk.py +++ b/Lib/chunk.py @@ -85,8 +85,10 @@ def close(self): if not self.closed: - self.skip() - self.closed = True + try: + self.skip() + finally: + self.closed = True def isatty(self): if self.closed: diff --git a/Lib/dbm/dumb.py b/Lib/dbm/dumb.py --- a/Lib/dbm/dumb.py +++ b/Lib/dbm/dumb.py @@ -248,8 +248,10 @@ raise error('DBM object has already been closed') from None def close(self): - self._commit() - self._index = self._datfile = self._dirfile = self._bakfile = None + try: + self._commit() + finally: + self._index = self._datfile = self._dirfile = self._bakfile = None __del__ = close diff --git a/Lib/distutils/text_file.py b/Lib/distutils/text_file.py --- a/Lib/distutils/text_file.py +++ b/Lib/distutils/text_file.py @@ -118,10 +118,11 @@ def close(self): """Close the current file and forget everything we know about it (filename, current line number).""" - self.file.close() + file = self.file self.file = None self.filename = None self.current_line = None + file.close() def gen_error(self, msg, line=None): outmsg = [] diff --git a/Lib/fileinput.py b/Lib/fileinput.py --- a/Lib/fileinput.py +++ b/Lib/fileinput.py @@ -238,8 +238,10 @@ self.close() def close(self): - self.nextfile() - self._files = () + try: + self.nextfile() + finally: + self._files = () def __enter__(self): return self @@ -281,23 +283,25 @@ output = self._output self._output = 0 - if output: - output.close() + try: + if output: + output.close() + finally: + file = self._file + self._file = 0 + try: + if file and not self._isstdin: + file.close() + finally: + backupfilename = self._backupfilename + self._backupfilename = 0 + if backupfilename and not self._backup: + try: os.unlink(backupfilename) + except OSError: pass - file = self._file - self._file = 0 - if file and not self._isstdin: - file.close() - - backupfilename = self._backupfilename - self._backupfilename = 0 - if backupfilename and not self._backup: - try: os.unlink(backupfilename) - except OSError: pass - - self._isstdin = False - self._buffer = [] - self._bufindex = 0 + self._isstdin = False + self._buffer = [] + self._bufindex = 0 def readline(self): try: diff --git a/Lib/ftplib.py b/Lib/ftplib.py --- a/Lib/ftplib.py +++ b/Lib/ftplib.py @@ -667,11 +667,16 @@ def close(self): '''Close the connection without assuming anything about it.''' - if self.file is not None: - self.file.close() - if self.sock is not None: - self.sock.close() - self.file = self.sock = None + try: + file = self.file + self.file = None + if file is not None: + file.close() + finally: + sock = self.sock + self.sock = None + if sock is not None: + sock.close() try: import ssl diff --git a/Lib/gzip.py b/Lib/gzip.py --- a/Lib/gzip.py +++ b/Lib/gzip.py @@ -500,19 +500,21 @@ return self.fileobj is None def close(self): - if self.fileobj is None: + fileobj = self.fileobj + if fileobj is None: return - if self.mode == WRITE: - self.fileobj.write(self.compress.flush()) - write32u(self.fileobj, self.crc) - # self.size may exceed 2GB, or even 4GB - write32u(self.fileobj, self.size & 0xffffffff) - self.fileobj = None - elif self.mode == READ: - self.fileobj = None - if self.myfileobj: - self.myfileobj.close() - self.myfileobj = None + self.fileobj = None + try: + if self.mode == WRITE: + fileobj.write(self.compress.flush()) + write32u(fileobj, self.crc) + # self.size may exceed 2GB, or even 4GB + write32u(fileobj, self.size & 0xffffffff) + finally: + myfileobj = self.myfileobj + if myfileobj: + self.myfileobj = None + myfileobj.close() def flush(self,zlib_mode=zlib.Z_SYNC_FLUSH): self._check_closed() diff --git a/Lib/http/client.py b/Lib/http/client.py --- a/Lib/http/client.py +++ b/Lib/http/client.py @@ -492,9 +492,11 @@ fp.close() def close(self): - super().close() # set "closed" flag - if self.fp: - self._close_conn() + try: + super().close() # set "closed" flag + finally: + if self.fp: + self._close_conn() # These implementations are for the benefit of io.BufferedReader. @@ -873,13 +875,17 @@ def close(self): """Close the connection to the HTTP server.""" - if self.sock: - self.sock.close() # close it manually... there may be other refs - self.sock = None - if self.__response: - self.__response.close() - self.__response = None self.__state = _CS_IDLE + try: + sock = self.sock + if sock: + self.sock = None + sock.close() # close it manually... there may be other refs + finally: + response = self.__response + if response: + self.__response = None + response.close() def send(self, data): """Send `data' to the server. diff --git a/Lib/logging/__init__.py b/Lib/logging/__init__.py --- a/Lib/logging/__init__.py +++ b/Lib/logging/__init__.py @@ -1011,14 +1011,19 @@ """ self.acquire() try: - if self.stream: - self.flush() - if hasattr(self.stream, "close"): - self.stream.close() - self.stream = None - # Issue #19523: call unconditionally to - # prevent a handler leak when delay is set - StreamHandler.close(self) + try: + if self.stream: + try: + self.flush() + finally: + stream = self.stream + self.stream = None + if hasattr(stream, "close"): + stream.close() + finally: + # Issue #19523: call unconditionally to + # prevent a handler leak when delay is set + StreamHandler.close(self) finally: self.release() diff --git a/Lib/logging/handlers.py b/Lib/logging/handlers.py --- a/Lib/logging/handlers.py +++ b/Lib/logging/handlers.py @@ -627,9 +627,10 @@ """ self.acquire() try: - if self.sock: - self.sock.close() + sock = self.sock + if sock: self.sock = None + sock.close() logging.Handler.close(self) finally: self.release() @@ -1213,8 +1214,10 @@ This version just flushes and chains to the parent class' close(). """ - self.flush() - logging.Handler.close(self) + try: + self.flush() + finally: + logging.Handler.close(self) class MemoryHandler(BufferingHandler): """ @@ -1268,13 +1271,15 @@ """ Flush, set the target to None and lose the buffer. """ - self.flush() - self.acquire() try: - self.target = None - BufferingHandler.close(self) + self.flush() finally: - self.release() + self.acquire() + try: + self.target = None + BufferingHandler.close(self) + finally: + self.release() class QueueHandler(logging.Handler): diff --git a/Lib/mailbox.py b/Lib/mailbox.py --- a/Lib/mailbox.py +++ b/Lib/mailbox.py @@ -722,10 +722,14 @@ def close(self): """Flush and close the mailbox.""" - self.flush() - if self._locked: - self.unlock() - self._file.close() # Sync has been done by self.flush() above. + try: + self.flush() + finally: + try: + if self._locked: + self.unlock() + finally: + self._file.close() # Sync has been done by self.flush() above. def _lookup(self, key=None): """Return (start, stop) or raise KeyError.""" diff --git a/Lib/multiprocessing/connection.py b/Lib/multiprocessing/connection.py --- a/Lib/multiprocessing/connection.py +++ b/Lib/multiprocessing/connection.py @@ -469,9 +469,10 @@ ''' Close the bound socket or named pipe of `self`. ''' - if self._listener is not None: - self._listener.close() + listener = self._listener + if listener is not None: self._listener = None + listener.close() address = property(lambda self: self._listener._address) last_accepted = property(lambda self: self._listener._last_accepted) @@ -609,9 +610,13 @@ return Connection(s.detach()) def close(self): - self._socket.close() - if self._unlink is not None: - self._unlink() + try: + self._socket.close() + finally: + unlink = self._unlink + if unlink is not None: + self._unlink = None + unlink() def SocketClient(address): diff --git a/Lib/multiprocessing/queues.py b/Lib/multiprocessing/queues.py --- a/Lib/multiprocessing/queues.py +++ b/Lib/multiprocessing/queues.py @@ -133,9 +133,13 @@ def close(self): self._closed = True - self._reader.close() - if self._close: - self._close() + try: + self._reader.close() + finally: + close = self._close + if close: + self._close = None + close() def join_thread(self): debug('Queue.join_thread()') diff --git a/Lib/poplib.py b/Lib/poplib.py --- a/Lib/poplib.py +++ b/Lib/poplib.py @@ -276,18 +276,23 @@ def close(self): """Close the connection without assuming anything about it.""" - if self.file is not None: - self.file.close() - if self.sock is not None: - try: - self.sock.shutdown(socket.SHUT_RDWR) - except OSError as e: - # The server might already have closed the connection - if e.errno != errno.ENOTCONN: - raise - finally: - self.sock.close() - self.file = self.sock = None + try: + file = self.file + self.file = None + if file is not None: + file.close() + finally: + sock = self.sock + self.sock = None + if sock is not None: + try: + sock.shutdown(socket.SHUT_RDWR) + except OSError as e: + # The server might already have closed the connection + if e.errno != errno.ENOTCONN: + raise + finally: + sock.close() #__del__ = quit diff --git a/Lib/selectors.py b/Lib/selectors.py --- a/Lib/selectors.py +++ b/Lib/selectors.py @@ -445,8 +445,10 @@ return ready def close(self): - self._epoll.close() - super().close() + try: + self._epoll.close() + finally: + super().close() if hasattr(select, 'kqueue'): @@ -517,8 +519,10 @@ return ready def close(self): - self._kqueue.close() - super().close() + try: + self._kqueue.close() + finally: + super().close() # Choose the best implementation: roughly, epoll|kqueue > poll > select. diff --git a/Lib/shelve.py b/Lib/shelve.py --- a/Lib/shelve.py +++ b/Lib/shelve.py @@ -138,17 +138,21 @@ self.close() def close(self): - self.sync() + if self.dict is None: + return try: - self.dict.close() - except AttributeError: - pass - # Catch errors that may happen when close is called from __del__ - # because CPython is in interpreter shutdown. - try: - self.dict = _ClosedDict() - except (NameError, TypeError): - self.dict = None + self.sync() + try: + self.dict.close() + except AttributeError: + pass + finally: + # Catch errors that may happen when close is called from __del__ + # because CPython is in interpreter shutdown. + try: + self.dict = _ClosedDict() + except: + self.dict = None def __del__(self): if not hasattr(self, 'writeback'): diff --git a/Lib/smtplib.py b/Lib/smtplib.py --- a/Lib/smtplib.py +++ b/Lib/smtplib.py @@ -855,12 +855,16 @@ def close(self): """Close the connection to the SMTP server.""" - if self.file: - self.file.close() - self.file = None - if self.sock: - self.sock.close() - self.sock = None + try: + file = self.file + self.file = None + if file: + file.close() + finally: + sock = self.sock + self.sock = None + if sock: + sock.close() def quit(self): """Terminate the SMTP session.""" diff --git a/Lib/sunau.py b/Lib/sunau.py --- a/Lib/sunau.py +++ b/Lib/sunau.py @@ -295,9 +295,11 @@ self._soundpos = pos def close(self): - if self._opened and self._file: - self._file.close() - self._file = None + file = self._file + if file: + self._file = None + if self._opened: + file.close() class Au_write: @@ -438,9 +440,10 @@ self._patchheader() self._file.flush() finally: - if self._opened and self._file: - self._file.close() + file = self._file self._file = None + if self._opened: + file.close() # # private methods diff --git a/Lib/tarfile.py b/Lib/tarfile.py --- a/Lib/tarfile.py +++ b/Lib/tarfile.py @@ -449,26 +449,26 @@ if self.closed: return - if self.mode == "w" and self.comptype != "tar": - self.buf += self.cmp.flush() + self.closed = True + try: + if self.mode == "w" and self.comptype != "tar": + self.buf += self.cmp.flush() - if self.mode == "w" and self.buf: - self.fileobj.write(self.buf) - self.buf = b"" - if self.comptype == "gz": - # The native zlib crc is an unsigned 32-bit integer, but - # the Python wrapper implicitly casts that to a signed C - # long. So, on a 32-bit box self.crc may "look negative", - # while the same crc on a 64-bit box may "look positive". - # To avoid irksome warnings from the `struct` module, force - # it to look positive on all boxes. - self.fileobj.write(struct.pack(" 0: - self.fileobj.write(NUL * (RECORDSIZE - remainder)) - - if not self._extfileobj: - self.fileobj.close() self.closed = True + try: + if self.mode in "aw": + self.fileobj.write(NUL * (BLOCKSIZE * 2)) + self.offset += (BLOCKSIZE * 2) + # fill up the end with zero-blocks + # (like option -b20 for tar does) + blocks, remainder = divmod(self.offset, RECORDSIZE) + if remainder > 0: + self.fileobj.write(NUL * (RECORDSIZE - remainder)) + finally: + if not self._extfileobj: + self.fileobj.close() def getmember(self, name): """Return a TarInfo object for member `name'. If `name' can not be diff --git a/Lib/telnetlib.py b/Lib/telnetlib.py --- a/Lib/telnetlib.py +++ b/Lib/telnetlib.py @@ -264,12 +264,13 @@ def close(self): """Close the connection.""" - if self.sock: - self.sock.close() + sock = self.sock self.sock = 0 self.eof = 1 self.iacseq = b'' self.sb = 0 + if sock: + sock.close() def get_socket(self): """Return the socket object used internally.""" diff --git a/Lib/tempfile.py b/Lib/tempfile.py --- a/Lib/tempfile.py +++ b/Lib/tempfile.py @@ -357,9 +357,11 @@ def close(self, unlink=_os.unlink): if not self.close_called and self.file is not None: self.close_called = True - self.file.close() - if self.delete: - unlink(self.name) + try: + self.file.close() + finally: + if self.delete: + unlink(self.name) # Need to ensure the file is deleted on __del__ def __del__(self): diff --git a/Lib/urllib/response.py b/Lib/urllib/response.py --- a/Lib/urllib/response.py +++ b/Lib/urllib/response.py @@ -43,11 +43,15 @@ self.hookargs = hookargs def close(self): - if self.closehook: - self.closehook(*self.hookargs) - self.closehook = None - self.hookargs = None - super(addclosehook, self).close() + try: + closehook = self.closehook + hookargs = self.hookargs + if closehook: + self.closehook = None + self.hookargs = None + closehook(*hookargs) + finally: + super(addclosehook, self).close() class addinfo(addbase): diff --git a/Lib/wave.py b/Lib/wave.py --- a/Lib/wave.py +++ b/Lib/wave.py @@ -186,10 +186,11 @@ self._soundpos = 0 def close(self): - if self._i_opened_the_file: - self._i_opened_the_file.close() + self._file = None + file = self._i_opened_the_file + if file: self._i_opened_the_file = None - self._file = None + file.close() def tell(self): return self._soundpos @@ -428,17 +429,18 @@ self._patchheader() def close(self): - if self._file: - try: + try: + if self._file: self._ensure_header_written(0) if self._datalength != self._datawritten: self._patchheader() self._file.flush() - finally: - self._file = None - if self._i_opened_the_file: - self._i_opened_the_file.close() - self._i_opened_the_file = None + finally: + self._file = None + file = self._i_opened_the_file + if file: + self._i_opened_the_file = None + file.close() # # Internal methods. diff --git a/Lib/xml/sax/expatreader.py b/Lib/xml/sax/expatreader.py --- a/Lib/xml/sax/expatreader.py +++ b/Lib/xml/sax/expatreader.py @@ -211,17 +211,19 @@ self._err_handler.fatalError(exc) def close(self): - if self._entity_stack: + if self._entity_stack or self._parser is None: # If we are completing an external entity, do nothing here return - self.feed("", isFinal = 1) - self._cont_handler.endDocument() - self._parsing = 0 - # break cycle created by expat handlers pointing to our methods - self._parser = None - bs = self._source.getByteStream() - if bs is not None: - bs.close() + try: + self.feed("", isFinal = 1) + self._cont_handler.endDocument() + finally: + self._parsing = 0 + # break cycle created by expat handlers pointing to our methods + self._parser = None + bs = self._source.getByteStream() + if bs is not None: + bs.close() def _reset_cont_handler(self): self._parser.ProcessingInstructionHandler = \ diff --git a/Lib/xmlrpc/client.py b/Lib/xmlrpc/client.py --- a/Lib/xmlrpc/client.py +++ b/Lib/xmlrpc/client.py @@ -446,8 +446,13 @@ self._parser.Parse(data, 0) def close(self): - self._parser.Parse("", 1) # end of data - del self._target, self._parser # get rid of circular references + try: + parser = self._parser + except AttributeError: + pass + else: + del self._target, self._parser # get rid of circular references + parser.Parse(b"", True) # end of data # -------------------------------------------------------------------- # XML-RPC marshalling and unmarshalling code @@ -1079,8 +1084,10 @@ gzip.GzipFile.__init__(self, mode="rb", fileobj=self.io) def close(self): - gzip.GzipFile.close(self) - self.io.close() + try: + gzip.GzipFile.close(self) + finally: + self.io.close() # -------------------------------------------------------------------- @@ -1235,9 +1242,10 @@ # Used in the event of socket errors. # def close(self): - if self._connection[1]: - self._connection[1].close() + host, connection = self._connection + if connection: self._connection = (None, None) + connection.close() ## # Send HTTP request. diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -24,6 +24,10 @@ Library ------- +- Issue #23865: close() methods in multiple modules now are idempotent and more + robust at shutdown. If needs to release multiple resources, they are released + even if errors are occured. + - Issue #23881: urllib.request.ftpwrapper constructor now closes the socket if the FTP connection failed to fix a ResourceWarning. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Apr 10 12:31:00 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Fri, 10 Apr 2015 10:31:00 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzIzODY1?= =?utf-8?q?=3A_close=28=29_methods_in_multiple_modules_now_are_idempotent_?= =?utf-8?q?and_more?= Message-ID: <20150410103059.129696.88719@psf.io> https://hg.python.org/cpython/rev/f7ddec2e9e93 changeset: 95517:f7ddec2e9e93 branch: 2.7 parent: 95510:50ed581fea04 user: Serhiy Storchaka date: Fri Apr 10 13:24:10 2015 +0300 summary: Issue #23865: close() methods in multiple modules now are idempotent and more robust at shutdown. If needs to release multiple resources, they are released even if errors are occured. files: Lib/aifc.py | 11 ++- Lib/binhex.py | 44 ++++++++----- Lib/chunk.py | 6 +- Lib/distutils/text_file.py | 4 +- Lib/dumbdbm.py | 6 +- Lib/fileinput.py | 40 ++++++----- Lib/ftplib.py | 15 +++- Lib/gzip.py | 26 ++++--- Lib/httplib.py | 21 ++++-- Lib/logging/__init__.py | 21 ++++-- Lib/logging/handlers.py | 23 ++++-- Lib/mailbox.py | 12 ++- Lib/multiprocessing/connection.py | 10 ++- Lib/multiprocessing/queues.py | 10 ++- Lib/shelve.py | 24 ++++--- Lib/smtplib.py | 16 +++- Lib/tarfile.py | 61 +++++++++--------- Lib/telnetlib.py | 5 +- Lib/tempfile.py | 8 +- Lib/urllib.py | 15 +++- Lib/wave.py | 22 +++--- Lib/xml/sax/expatreader.py | 14 ++- Lib/xmlrpclib.py | 20 ++++- Misc/NEWS | 4 + 24 files changed, 263 insertions(+), 175 deletions(-) diff --git a/Lib/aifc.py b/Lib/aifc.py --- a/Lib/aifc.py +++ b/Lib/aifc.py @@ -357,10 +357,13 @@ self._soundpos = 0 def close(self): - if self._decomp: - self._decomp.CloseDecompressor() - self._decomp = None - self._file.close() + decomp = self._decomp + try: + if decomp: + self._decomp = None + decomp.CloseDecompressor() + finally: + self._file.close() def tell(self): return self._soundpos diff --git a/Lib/binhex.py b/Lib/binhex.py --- a/Lib/binhex.py +++ b/Lib/binhex.py @@ -32,7 +32,8 @@ pass # States (what have we written) -[_DID_HEADER, _DID_DATA, _DID_RSRC] = range(3) +_DID_HEADER = 0 +_DID_DATA = 1 # Various constants REASONABLY_LARGE=32768 # Minimal amount we pass the rle-coder @@ -235,17 +236,22 @@ self._write(data) def close(self): - if self.state < _DID_DATA: - self.close_data() - if self.state != _DID_DATA: - raise Error, 'Close at the wrong time' - if self.rlen != 0: - raise Error, \ - "Incorrect resource-datasize, diff=%r" % (self.rlen,) - self._writecrc() - self.ofp.close() - self.state = None - del self.ofp + if self.state is None: + return + try: + if self.state < _DID_DATA: + self.close_data() + if self.state != _DID_DATA: + raise Error, 'Close at the wrong time' + if self.rlen != 0: + raise Error, \ + "Incorrect resource-datasize, diff=%r" % (self.rlen,) + self._writecrc() + finally: + self.state = None + ofp = self.ofp + del self.ofp + ofp.close() def binhex(inp, out): """(infilename, outfilename) - Create binhex-encoded copy of a file""" @@ -463,11 +469,15 @@ return self._read(n) def close(self): - if self.rlen: - dummy = self.read_rsrc(self.rlen) - self._checkcrc() - self.state = _DID_RSRC - self.ifp.close() + if self.state is None: + return + try: + if self.rlen: + dummy = self.read_rsrc(self.rlen) + self._checkcrc() + finally: + self.state = None + self.ifp.close() def hexbin(inp, out): """(infilename, outfilename) - Decode binhexed file""" diff --git a/Lib/chunk.py b/Lib/chunk.py --- a/Lib/chunk.py +++ b/Lib/chunk.py @@ -85,8 +85,10 @@ def close(self): if not self.closed: - self.skip() - self.closed = True + try: + self.skip() + finally: + self.closed = True def isatty(self): if self.closed: diff --git a/Lib/distutils/text_file.py b/Lib/distutils/text_file.py --- a/Lib/distutils/text_file.py +++ b/Lib/distutils/text_file.py @@ -124,11 +124,11 @@ def close (self): """Close the current file and forget everything we know about it (filename, current line number).""" - - self.file.close () + file = self.file self.file = None self.filename = None self.current_line = None + file.close() def gen_error (self, msg, line=None): diff --git a/Lib/dumbdbm.py b/Lib/dumbdbm.py --- a/Lib/dumbdbm.py +++ b/Lib/dumbdbm.py @@ -209,8 +209,10 @@ return len(self._index) def close(self): - self._commit() - self._index = self._datfile = self._dirfile = self._bakfile = None + try: + self._commit() + finally: + self._index = self._datfile = self._dirfile = self._bakfile = None __del__ = close diff --git a/Lib/fileinput.py b/Lib/fileinput.py --- a/Lib/fileinput.py +++ b/Lib/fileinput.py @@ -233,8 +233,10 @@ self.close() def close(self): - self.nextfile() - self._files = () + try: + self.nextfile() + finally: + self._files = () def __iter__(self): return self @@ -270,23 +272,25 @@ output = self._output self._output = 0 - if output: - output.close() + try: + if output: + output.close() + finally: + file = self._file + self._file = 0 + try: + if file and not self._isstdin: + file.close() + finally: + backupfilename = self._backupfilename + self._backupfilename = 0 + if backupfilename and not self._backup: + try: os.unlink(backupfilename) + except OSError: pass - file = self._file - self._file = 0 - if file and not self._isstdin: - file.close() - - backupfilename = self._backupfilename - self._backupfilename = 0 - if backupfilename and not self._backup: - try: os.unlink(backupfilename) - except OSError: pass - - self._isstdin = False - self._buffer = [] - self._bufindex = 0 + self._isstdin = False + self._buffer = [] + self._bufindex = 0 def readline(self): try: diff --git a/Lib/ftplib.py b/Lib/ftplib.py --- a/Lib/ftplib.py +++ b/Lib/ftplib.py @@ -594,11 +594,16 @@ def close(self): '''Close the connection without assuming anything about it.''' - if self.file is not None: - self.file.close() - if self.sock is not None: - self.sock.close() - self.file = self.sock = None + try: + file = self.file + self.file = None + if file is not None: + file.close() + finally: + sock = self.sock + self.sock = None + if sock is not None: + sock.close() try: import ssl diff --git a/Lib/gzip.py b/Lib/gzip.py --- a/Lib/gzip.py +++ b/Lib/gzip.py @@ -369,19 +369,21 @@ return self.fileobj is None def close(self): - if self.fileobj is None: + fileobj = self.fileobj + if fileobj is None: return - if self.mode == WRITE: - self.fileobj.write(self.compress.flush()) - write32u(self.fileobj, self.crc) - # self.size may exceed 2GB, or even 4GB - write32u(self.fileobj, self.size & 0xffffffffL) - self.fileobj = None - elif self.mode == READ: - self.fileobj = None - if self.myfileobj: - self.myfileobj.close() - self.myfileobj = None + self.fileobj = None + try: + if self.mode == WRITE: + fileobj.write(self.compress.flush()) + write32u(fileobj, self.crc) + # self.size may exceed 2GB, or even 4GB + write32u(fileobj, self.size & 0xffffffffL) + finally: + myfileobj = self.myfileobj + if myfileobj: + self.myfileobj = None + myfileobj.close() def flush(self,zlib_mode=zlib.Z_SYNC_FLUSH): self._check_closed() diff --git a/Lib/httplib.py b/Lib/httplib.py --- a/Lib/httplib.py +++ b/Lib/httplib.py @@ -560,9 +560,10 @@ return True def close(self): - if self.fp: - self.fp.close() + fp = self.fp + if fp: self.fp = None + fp.close() def isclosed(self): # NOTE: it is possible that we will not ever call self.close(). This @@ -835,13 +836,17 @@ def close(self): """Close the connection to the HTTP server.""" - if self.sock: - self.sock.close() # close it manually... there may be other refs - self.sock = None - if self.__response: - self.__response.close() - self.__response = None self.__state = _CS_IDLE + try: + sock = self.sock + if sock: + self.sock = None + sock.close() # close it manually... there may be other refs + finally: + response = self.__response + if response: + self.__response = None + response.close() def send(self, data): """Send `data' to the server.""" diff --git a/Lib/logging/__init__.py b/Lib/logging/__init__.py --- a/Lib/logging/__init__.py +++ b/Lib/logging/__init__.py @@ -916,14 +916,19 @@ """ self.acquire() try: - if self.stream: - self.flush() - if hasattr(self.stream, "close"): - self.stream.close() - self.stream = None - # Issue #19523: call unconditionally to - # prevent a handler leak when delay is set - StreamHandler.close(self) + try: + if self.stream: + try: + self.flush() + finally: + stream = self.stream + self.stream = None + if hasattr(stream, "close"): + stream.close() + finally: + # Issue #19523: call unconditionally to + # prevent a handler leak when delay is set + StreamHandler.close(self) finally: self.release() diff --git a/Lib/logging/handlers.py b/Lib/logging/handlers.py --- a/Lib/logging/handlers.py +++ b/Lib/logging/handlers.py @@ -588,9 +588,10 @@ """ self.acquire() try: - if self.sock: - self.sock.close() + sock = self.sock + if sock: self.sock = None + sock.close() finally: self.release() logging.Handler.close(self) @@ -1160,8 +1161,10 @@ This version just flushes and chains to the parent class' close(). """ - self.flush() - logging.Handler.close(self) + try: + self.flush() + finally: + logging.Handler.close(self) class MemoryHandler(BufferingHandler): """ @@ -1213,10 +1216,12 @@ """ Flush, set the target to None and lose the buffer. """ - self.flush() - self.acquire() try: - self.target = None - BufferingHandler.close(self) + self.flush() finally: - self.release() + self.acquire() + try: + self.target = None + BufferingHandler.close(self) + finally: + self.release() diff --git a/Lib/mailbox.py b/Lib/mailbox.py --- a/Lib/mailbox.py +++ b/Lib/mailbox.py @@ -719,10 +719,14 @@ def close(self): """Flush and close the mailbox.""" - self.flush() - if self._locked: - self.unlock() - self._file.close() # Sync has been done by self.flush() above. + try: + self.flush() + finally: + try: + if self._locked: + self.unlock() + finally: + self._file.close() # Sync has been done by self.flush() above. def _lookup(self, key=None): """Return (start, stop) or raise KeyError.""" diff --git a/Lib/multiprocessing/connection.py b/Lib/multiprocessing/connection.py --- a/Lib/multiprocessing/connection.py +++ b/Lib/multiprocessing/connection.py @@ -285,9 +285,13 @@ return conn def close(self): - self._socket.close() - if self._unlink is not None: - self._unlink() + try: + self._socket.close() + finally: + unlink = self._unlink + if unlink is not None: + self._unlink = None + unlink() def SocketClient(address): diff --git a/Lib/multiprocessing/queues.py b/Lib/multiprocessing/queues.py --- a/Lib/multiprocessing/queues.py +++ b/Lib/multiprocessing/queues.py @@ -156,9 +156,13 @@ def close(self): self._closed = True - self._reader.close() - if self._close: - self._close() + try: + self._reader.close() + finally: + close = self._close + if close: + self._close = None + close() def join_thread(self): debug('Queue.join_thread()') diff --git a/Lib/shelve.py b/Lib/shelve.py --- a/Lib/shelve.py +++ b/Lib/shelve.py @@ -140,17 +140,21 @@ pass def close(self): - self.sync() + if self.dict is None: + return try: - self.dict.close() - except AttributeError: - pass - # Catch errors that may happen when close is called from __del__ - # because CPython is in interpreter shutdown. - try: - self.dict = _ClosedDict() - except (NameError, TypeError): - self.dict = None + self.sync() + try: + self.dict.close() + except AttributeError: + pass + finally: + # Catch errors that may happen when close is called from __del__ + # because CPython is in interpreter shutdown. + try: + self.dict = _ClosedDict() + except: + self.dict = None def __del__(self): if not hasattr(self, 'writeback'): diff --git a/Lib/smtplib.py b/Lib/smtplib.py --- a/Lib/smtplib.py +++ b/Lib/smtplib.py @@ -750,12 +750,16 @@ def close(self): """Close the connection to the SMTP server.""" - if self.file: - self.file.close() - self.file = None - if self.sock: - self.sock.close() - self.sock = None + try: + file = self.file + self.file = None + if file: + file.close() + finally: + sock = self.sock + self.sock = None + if sock: + sock.close() def quit(self): diff --git a/Lib/tarfile.py b/Lib/tarfile.py --- a/Lib/tarfile.py +++ b/Lib/tarfile.py @@ -492,26 +492,26 @@ if self.closed: return - if self.mode == "w" and self.comptype != "tar": - self.buf += self.cmp.flush() + self.closed = True + try: + if self.mode == "w" and self.comptype != "tar": + self.buf += self.cmp.flush() - if self.mode == "w" and self.buf: - self.fileobj.write(self.buf) - self.buf = "" - if self.comptype == "gz": - # The native zlib crc is an unsigned 32-bit integer, but - # the Python wrapper implicitly casts that to a signed C - # long. So, on a 32-bit box self.crc may "look negative", - # while the same crc on a 64-bit box may "look positive". - # To avoid irksome warnings from the `struct` module, force - # it to look positive on all boxes. - self.fileobj.write(struct.pack(" 0: - self.fileobj.write(NUL * (RECORDSIZE - remainder)) - - if not self._extfileobj: - self.fileobj.close() self.closed = True + try: + if self.mode in "aw": + self.fileobj.write(NUL * (BLOCKSIZE * 2)) + self.offset += (BLOCKSIZE * 2) + # fill up the end with zero-blocks + # (like option -b20 for tar does) + blocks, remainder = divmod(self.offset, RECORDSIZE) + if remainder > 0: + self.fileobj.write(NUL * (RECORDSIZE - remainder)) + finally: + if not self._extfileobj: + self.fileobj.close() def getmember(self, name): """Return a TarInfo object for member `name'. If `name' can not be diff --git a/Lib/telnetlib.py b/Lib/telnetlib.py --- a/Lib/telnetlib.py +++ b/Lib/telnetlib.py @@ -254,12 +254,13 @@ def close(self): """Close the connection.""" - if self.sock: - self.sock.close() + sock = self.sock self.sock = 0 self.eof = 1 self.iacseq = '' self.sb = 0 + if sock: + sock.close() def get_socket(self): """Return the socket object used internally.""" diff --git a/Lib/tempfile.py b/Lib/tempfile.py --- a/Lib/tempfile.py +++ b/Lib/tempfile.py @@ -413,9 +413,11 @@ def close(self): if not self.close_called: self.close_called = True - self.file.close() - if self.delete: - self.unlink(self.name) + try: + self.file.close() + finally: + if self.delete: + self.unlink(self.name) def __del__(self): self.close() diff --git a/Lib/urllib.py b/Lib/urllib.py --- a/Lib/urllib.py +++ b/Lib/urllib.py @@ -994,11 +994,16 @@ self.hookargs = hookargs def close(self): - if self.closehook: - self.closehook(*self.hookargs) - self.closehook = None - self.hookargs = None - addbase.close(self) + try: + closehook = self.closehook + hookargs = self.hookargs + if closehook: + self.closehook = None + self.hookargs = None + closehook(*hookargs) + finally: + addbase.close(self) + class addinfo(addbase): """class to add an info() method to an open file.""" diff --git a/Lib/wave.py b/Lib/wave.py --- a/Lib/wave.py +++ b/Lib/wave.py @@ -180,10 +180,11 @@ self._soundpos = 0 def close(self): - if self._i_opened_the_file: - self._i_opened_the_file.close() + self._file = None + file = self._i_opened_the_file + if file: self._i_opened_the_file = None - self._file = None + file.close() def tell(self): return self._soundpos @@ -444,17 +445,18 @@ self._patchheader() def close(self): - if self._file: - try: + try: + if self._file: self._ensure_header_written(0) if self._datalength != self._datawritten: self._patchheader() self._file.flush() - finally: - self._file = None - if self._i_opened_the_file: - self._i_opened_the_file.close() - self._i_opened_the_file = None + finally: + self._file = None + file = self._i_opened_the_file + if file: + self._i_opened_the_file = None + file.close() # # Internal methods. diff --git a/Lib/xml/sax/expatreader.py b/Lib/xml/sax/expatreader.py --- a/Lib/xml/sax/expatreader.py +++ b/Lib/xml/sax/expatreader.py @@ -214,14 +214,16 @@ self._err_handler.fatalError(exc) def close(self): - if self._entity_stack: + if self._entity_stack or self._parser is None: # If we are completing an external entity, do nothing here return - self.feed("", isFinal = 1) - self._cont_handler.endDocument() - self._parsing = 0 - # break cycle created by expat handlers pointing to our methods - self._parser = None + try: + self.feed("", isFinal = 1) + self._cont_handler.endDocument() + finally: + self._parsing = 0 + # break cycle created by expat handlers pointing to our methods + self._parser = None def _reset_cont_handler(self): self._parser.ProcessingInstructionHandler = \ diff --git a/Lib/xmlrpclib.py b/Lib/xmlrpclib.py --- a/Lib/xmlrpclib.py +++ b/Lib/xmlrpclib.py @@ -558,8 +558,13 @@ self._parser.Parse(data, 0) def close(self): - self._parser.Parse("", 1) # end of data - del self._target, self._parser # get rid of circular references + try: + parser = self._parser + except AttributeError: + pass + else: + del self._target, self._parser # get rid of circular references + parser.Parse("", 1) # end of data class SlowParser: """Default XML parser (based on xmllib.XMLParser).""" @@ -1214,8 +1219,10 @@ gzip.GzipFile.__init__(self, mode="rb", fileobj=self.stringio) def close(self): - gzip.GzipFile.close(self) - self.stringio.close() + try: + gzip.GzipFile.close(self) + finally: + self.stringio.close() # -------------------------------------------------------------------- @@ -1384,9 +1391,10 @@ # Used in the event of socket errors. # def close(self): - if self._connection[1]: - self._connection[1].close() + host, connection = self._connection + if connection: self._connection = (None, None) + connection.close() ## # Send request header. diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -21,6 +21,10 @@ Library ------- +- Issue #23865: close() methods in multiple modules now are idempotent and more + robust at shutdown. If needs to release multiple resources, they are released + even if errors are occured. + - Issue #23881: urllib.ftpwrapper constructor now closes the socket if the FTP connection failed. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Apr 10 12:31:00 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Fri, 10 Apr 2015 10:31:00 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2323865=3A_close=28=29_methods_in_multiple_module?= =?utf-8?q?s_now_are_idempotent_and_more?= Message-ID: <20150410103100.21287.33054@psf.io> https://hg.python.org/cpython/rev/4ddec11b5faf changeset: 95519:4ddec11b5faf parent: 95516:cbcd37ae1a2a parent: 95518:e826940911c8 user: Serhiy Storchaka date: Fri Apr 10 13:29:28 2015 +0300 summary: Issue #23865: close() methods in multiple modules now are idempotent and more robust at shutdown. If needs to release multiple resources, they are released even if errors are occured. files: Lib/aifc.py | 5 +- Lib/binhex.py | 42 ++++++++---- Lib/chunk.py | 6 +- Lib/dbm/dumb.py | 6 +- Lib/distutils/text_file.py | 3 +- Lib/fileinput.py | 44 +++++++------ Lib/ftplib.py | 15 +++- Lib/gzip.py | 26 ++++--- Lib/http/client.py | 24 ++++-- Lib/logging/__init__.py | 21 ++++-- Lib/logging/handlers.py | 23 ++++-- Lib/mailbox.py | 20 ++++-- Lib/multiprocessing/connection.py | 15 +++- Lib/multiprocessing/queues.py | 10 ++- Lib/poplib.py | 29 +++++--- Lib/selectors.py | 18 +++- Lib/shelve.py | 24 ++++--- Lib/smtplib.py | 16 +++- Lib/sunau.py | 13 ++- Lib/tarfile.py | 61 +++++++++--------- Lib/telnetlib.py | 9 +- Lib/tempfile.py | 8 +- Lib/urllib/response.py | 14 ++- Lib/wave.py | 22 +++--- Lib/xml/sax/expatreader.py | 26 ++++--- Lib/xmlrpc/client.py | 20 ++++- Misc/NEWS | 4 + 27 files changed, 315 insertions(+), 209 deletions(-) diff --git a/Lib/aifc.py b/Lib/aifc.py --- a/Lib/aifc.py +++ b/Lib/aifc.py @@ -356,7 +356,10 @@ self._soundpos = 0 def close(self): - self._file.close() + file = self._file + if file is not None: + self._file = None + file.close() def tell(self): return self._soundpos diff --git a/Lib/binhex.py b/Lib/binhex.py --- a/Lib/binhex.py +++ b/Lib/binhex.py @@ -32,7 +32,8 @@ pass # States (what have we written) -[_DID_HEADER, _DID_DATA, _DID_RSRC] = range(3) +_DID_HEADER = 0 +_DID_DATA = 1 # Various constants REASONABLY_LARGE = 32768 # Minimal amount we pass the rle-coder @@ -213,16 +214,21 @@ self._write(data) def close(self): - if self.state < _DID_DATA: - self.close_data() - if self.state != _DID_DATA: - raise Error('Close at the wrong time') - if self.rlen != 0: - raise Error("Incorrect resource-datasize, diff=%r" % (self.rlen,)) - self._writecrc() - self.ofp.close() - self.state = None - del self.ofp + if self.state is None: + return + try: + if self.state < _DID_DATA: + self.close_data() + if self.state != _DID_DATA: + raise Error('Close at the wrong time') + if self.rlen != 0: + raise Error("Incorrect resource-datasize, diff=%r" % (self.rlen,)) + self._writecrc() + finally: + self.state = None + ofp = self.ofp + del self.ofp + ofp.close() def binhex(inp, out): """binhex(infilename, outfilename): create binhex-encoded copy of a file""" @@ -435,11 +441,15 @@ return self._read(n) def close(self): - if self.rlen: - dummy = self.read_rsrc(self.rlen) - self._checkcrc() - self.state = _DID_RSRC - self.ifp.close() + if self.state is None: + return + try: + if self.rlen: + dummy = self.read_rsrc(self.rlen) + self._checkcrc() + finally: + self.state = None + self.ifp.close() def hexbin(inp, out): """hexbin(infilename, outfilename) - Decode binhexed file""" diff --git a/Lib/chunk.py b/Lib/chunk.py --- a/Lib/chunk.py +++ b/Lib/chunk.py @@ -85,8 +85,10 @@ def close(self): if not self.closed: - self.skip() - self.closed = True + try: + self.skip() + finally: + self.closed = True def isatty(self): if self.closed: diff --git a/Lib/dbm/dumb.py b/Lib/dbm/dumb.py --- a/Lib/dbm/dumb.py +++ b/Lib/dbm/dumb.py @@ -258,8 +258,10 @@ raise error('DBM object has already been closed') from None def close(self): - self._commit() - self._index = self._datfile = self._dirfile = self._bakfile = None + try: + self._commit() + finally: + self._index = self._datfile = self._dirfile = self._bakfile = None __del__ = close diff --git a/Lib/distutils/text_file.py b/Lib/distutils/text_file.py --- a/Lib/distutils/text_file.py +++ b/Lib/distutils/text_file.py @@ -118,10 +118,11 @@ def close(self): """Close the current file and forget everything we know about it (filename, current line number).""" - self.file.close() + file = self.file self.file = None self.filename = None self.current_line = None + file.close() def gen_error(self, msg, line=None): outmsg = [] diff --git a/Lib/fileinput.py b/Lib/fileinput.py --- a/Lib/fileinput.py +++ b/Lib/fileinput.py @@ -238,8 +238,10 @@ self.close() def close(self): - self.nextfile() - self._files = () + try: + self.nextfile() + finally: + self._files = () def __enter__(self): return self @@ -275,29 +277,31 @@ def nextfile(self): savestdout = self._savestdout - self._savestdout = 0 + self._savestdout = None if savestdout: sys.stdout = savestdout output = self._output - self._output = 0 - if output: - output.close() + self._output = None + try: + if output: + output.close() + finally: + file = self._file + self._file = None + try: + if file and not self._isstdin: + file.close() + finally: + backupfilename = self._backupfilename + self._backupfilename = None + if backupfilename and not self._backup: + try: os.unlink(backupfilename) + except OSError: pass - file = self._file - self._file = 0 - if file and not self._isstdin: - file.close() - - backupfilename = self._backupfilename - self._backupfilename = 0 - if backupfilename and not self._backup: - try: os.unlink(backupfilename) - except OSError: pass - - self._isstdin = False - self._buffer = [] - self._bufindex = 0 + self._isstdin = False + self._buffer = [] + self._bufindex = 0 def readline(self): try: diff --git a/Lib/ftplib.py b/Lib/ftplib.py --- a/Lib/ftplib.py +++ b/Lib/ftplib.py @@ -667,11 +667,16 @@ def close(self): '''Close the connection without assuming anything about it.''' - if self.file is not None: - self.file.close() - if self.sock is not None: - self.sock.close() - self.file = self.sock = None + try: + file = self.file + self.file = None + if file is not None: + file.close() + finally: + sock = self.sock + self.sock = None + if sock is not None: + sock.close() try: import ssl diff --git a/Lib/gzip.py b/Lib/gzip.py --- a/Lib/gzip.py +++ b/Lib/gzip.py @@ -503,19 +503,21 @@ return self.fileobj is None def close(self): - if self.fileobj is None: + fileobj = self.fileobj + if fileobj is None: return - if self.mode == WRITE: - self.fileobj.write(self.compress.flush()) - write32u(self.fileobj, self.crc) - # self.size may exceed 2GB, or even 4GB - write32u(self.fileobj, self.size & 0xffffffff) - self.fileobj = None - elif self.mode == READ: - self.fileobj = None - if self.myfileobj: - self.myfileobj.close() - self.myfileobj = None + self.fileobj = None + try: + if self.mode == WRITE: + fileobj.write(self.compress.flush()) + write32u(fileobj, self.crc) + # self.size may exceed 2GB, or even 4GB + write32u(fileobj, self.size & 0xffffffff) + finally: + myfileobj = self.myfileobj + if myfileobj: + self.myfileobj = None + myfileobj.close() def flush(self,zlib_mode=zlib.Z_SYNC_FLUSH): self._check_closed() diff --git a/Lib/http/client.py b/Lib/http/client.py --- a/Lib/http/client.py +++ b/Lib/http/client.py @@ -388,9 +388,11 @@ fp.close() def close(self): - super().close() # set "closed" flag - if self.fp: - self._close_conn() + try: + super().close() # set "closed" flag + finally: + if self.fp: + self._close_conn() # These implementations are for the benefit of io.BufferedReader. @@ -829,13 +831,17 @@ def close(self): """Close the connection to the HTTP server.""" - if self.sock: - self.sock.close() # close it manually... there may be other refs - self.sock = None - if self.__response: - self.__response.close() - self.__response = None self.__state = _CS_IDLE + try: + sock = self.sock + if sock: + self.sock = None + sock.close() # close it manually... there may be other refs + finally: + response = self.__response + if response: + self.__response = None + response.close() def send(self, data): """Send `data' to the server. diff --git a/Lib/logging/__init__.py b/Lib/logging/__init__.py --- a/Lib/logging/__init__.py +++ b/Lib/logging/__init__.py @@ -1013,14 +1013,19 @@ """ self.acquire() try: - if self.stream: - self.flush() - if hasattr(self.stream, "close"): - self.stream.close() - self.stream = None - # Issue #19523: call unconditionally to - # prevent a handler leak when delay is set - StreamHandler.close(self) + try: + if self.stream: + try: + self.flush() + finally: + stream = self.stream + self.stream = None + if hasattr(stream, "close"): + stream.close() + finally: + # Issue #19523: call unconditionally to + # prevent a handler leak when delay is set + StreamHandler.close(self) finally: self.release() diff --git a/Lib/logging/handlers.py b/Lib/logging/handlers.py --- a/Lib/logging/handlers.py +++ b/Lib/logging/handlers.py @@ -627,9 +627,10 @@ """ self.acquire() try: - if self.sock: - self.sock.close() + sock = self.sock + if sock: self.sock = None + sock.close() logging.Handler.close(self) finally: self.release() @@ -1213,8 +1214,10 @@ This version just flushes and chains to the parent class' close(). """ - self.flush() - logging.Handler.close(self) + try: + self.flush() + finally: + logging.Handler.close(self) class MemoryHandler(BufferingHandler): """ @@ -1268,13 +1271,15 @@ """ Flush, set the target to None and lose the buffer. """ - self.flush() - self.acquire() try: - self.target = None - BufferingHandler.close(self) + self.flush() finally: - self.release() + self.acquire() + try: + self.target = None + BufferingHandler.close(self) + finally: + self.release() class QueueHandler(logging.Handler): diff --git a/Lib/mailbox.py b/Lib/mailbox.py --- a/Lib/mailbox.py +++ b/Lib/mailbox.py @@ -722,10 +722,14 @@ def close(self): """Flush and close the mailbox.""" - self.flush() - if self._locked: - self.unlock() - self._file.close() # Sync has been done by self.flush() above. + try: + self.flush() + finally: + try: + if self._locked: + self.unlock() + finally: + self._file.close() # Sync has been done by self.flush() above. def _lookup(self, key=None): """Return (start, stop) or raise KeyError.""" @@ -1966,9 +1970,11 @@ def close(self): """Close the file.""" if hasattr(self, '_file'): - if hasattr(self._file, 'close'): - self._file.close() - del self._file + try: + if hasattr(self._file, 'close'): + self._file.close() + finally: + del self._file def _read(self, size, read_method): """Read size bytes using read_method.""" diff --git a/Lib/multiprocessing/connection.py b/Lib/multiprocessing/connection.py --- a/Lib/multiprocessing/connection.py +++ b/Lib/multiprocessing/connection.py @@ -460,9 +460,10 @@ ''' Close the bound socket or named pipe of `self`. ''' - if self._listener is not None: - self._listener.close() + listener = self._listener + if listener is not None: self._listener = None + listener.close() address = property(lambda self: self._listener._address) last_accepted = property(lambda self: self._listener._last_accepted) @@ -594,9 +595,13 @@ return Connection(s.detach()) def close(self): - self._socket.close() - if self._unlink is not None: - self._unlink() + try: + self._socket.close() + finally: + unlink = self._unlink + if unlink is not None: + self._unlink = None + unlink() def SocketClient(address): diff --git a/Lib/multiprocessing/queues.py b/Lib/multiprocessing/queues.py --- a/Lib/multiprocessing/queues.py +++ b/Lib/multiprocessing/queues.py @@ -130,9 +130,13 @@ def close(self): self._closed = True - self._reader.close() - if self._close: - self._close() + try: + self._reader.close() + finally: + close = self._close + if close: + self._close = None + close() def join_thread(self): debug('Queue.join_thread()') diff --git a/Lib/poplib.py b/Lib/poplib.py --- a/Lib/poplib.py +++ b/Lib/poplib.py @@ -276,18 +276,23 @@ def close(self): """Close the connection without assuming anything about it.""" - if self.file is not None: - self.file.close() - if self.sock is not None: - try: - self.sock.shutdown(socket.SHUT_RDWR) - except OSError as e: - # The server might already have closed the connection - if e.errno != errno.ENOTCONN: - raise - finally: - self.sock.close() - self.file = self.sock = None + try: + file = self.file + self.file = None + if file is not None: + file.close() + finally: + sock = self.sock + self.sock = None + if sock is not None: + try: + sock.shutdown(socket.SHUT_RDWR) + except OSError as e: + # The server might already have closed the connection + if e.errno != errno.ENOTCONN: + raise + finally: + sock.close() #__del__ = quit diff --git a/Lib/selectors.py b/Lib/selectors.py --- a/Lib/selectors.py +++ b/Lib/selectors.py @@ -439,8 +439,10 @@ return ready def close(self): - self._epoll.close() - super().close() + try: + self._epoll.close() + finally: + super().close() if hasattr(select, 'devpoll'): @@ -496,8 +498,10 @@ return ready def close(self): - self._devpoll.close() - super().close() + try: + self._devpoll.close() + finally: + super().close() if hasattr(select, 'kqueue'): @@ -566,8 +570,10 @@ return ready def close(self): - self._kqueue.close() - super().close() + try: + self._kqueue.close() + finally: + super().close() # Choose the best implementation, roughly: diff --git a/Lib/shelve.py b/Lib/shelve.py --- a/Lib/shelve.py +++ b/Lib/shelve.py @@ -138,17 +138,21 @@ self.close() def close(self): - self.sync() + if self.dict is None: + return try: - self.dict.close() - except AttributeError: - pass - # Catch errors that may happen when close is called from __del__ - # because CPython is in interpreter shutdown. - try: - self.dict = _ClosedDict() - except (NameError, TypeError): - self.dict = None + self.sync() + try: + self.dict.close() + except AttributeError: + pass + finally: + # Catch errors that may happen when close is called from __del__ + # because CPython is in interpreter shutdown. + try: + self.dict = _ClosedDict() + except: + self.dict = None def __del__(self): if not hasattr(self, 'writeback'): diff --git a/Lib/smtplib.py b/Lib/smtplib.py --- a/Lib/smtplib.py +++ b/Lib/smtplib.py @@ -880,12 +880,16 @@ def close(self): """Close the connection to the SMTP server.""" - if self.file: - self.file.close() - self.file = None - if self.sock: - self.sock.close() - self.sock = None + try: + file = self.file + self.file = None + if file: + file.close() + finally: + sock = self.sock + self.sock = None + if sock: + sock.close() def quit(self): """Terminate the SMTP session.""" diff --git a/Lib/sunau.py b/Lib/sunau.py --- a/Lib/sunau.py +++ b/Lib/sunau.py @@ -295,9 +295,11 @@ self._soundpos = pos def close(self): - if self._opened and self._file: - self._file.close() - self._file = None + file = self._file + if file: + self._file = None + if self._opened: + file.close() class Au_write: @@ -438,9 +440,10 @@ self._patchheader() self._file.flush() finally: - if self._opened and self._file: - self._file.close() + file = self._file self._file = None + if self._opened: + file.close() # # private methods diff --git a/Lib/tarfile.py b/Lib/tarfile.py --- a/Lib/tarfile.py +++ b/Lib/tarfile.py @@ -449,26 +449,26 @@ if self.closed: return - if self.mode == "w" and self.comptype != "tar": - self.buf += self.cmp.flush() + self.closed = True + try: + if self.mode == "w" and self.comptype != "tar": + self.buf += self.cmp.flush() - if self.mode == "w" and self.buf: - self.fileobj.write(self.buf) - self.buf = b"" - if self.comptype == "gz": - # The native zlib crc is an unsigned 32-bit integer, but - # the Python wrapper implicitly casts that to a signed C - # long. So, on a 32-bit box self.crc may "look negative", - # while the same crc on a 64-bit box may "look positive". - # To avoid irksome warnings from the `struct` module, force - # it to look positive on all boxes. - self.fileobj.write(struct.pack(" 0: - self.fileobj.write(NUL * (RECORDSIZE - remainder)) - - if not self._extfileobj: - self.fileobj.close() self.closed = True + try: + if self.mode in "aw": + self.fileobj.write(NUL * (BLOCKSIZE * 2)) + self.offset += (BLOCKSIZE * 2) + # fill up the end with zero-blocks + # (like option -b20 for tar does) + blocks, remainder = divmod(self.offset, RECORDSIZE) + if remainder > 0: + self.fileobj.write(NUL * (RECORDSIZE - remainder)) + finally: + if not self._extfileobj: + self.fileobj.close() def getmember(self, name): """Return a TarInfo object for member `name'. If `name' can not be diff --git a/Lib/telnetlib.py b/Lib/telnetlib.py --- a/Lib/telnetlib.py +++ b/Lib/telnetlib.py @@ -261,12 +261,13 @@ def close(self): """Close the connection.""" - if self.sock: - self.sock.close() - self.sock = 0 - self.eof = 1 + sock = self.sock + self.sock = None + self.eof = True self.iacseq = b'' self.sb = 0 + if sock: + sock.close() def get_socket(self): """Return the socket object used internally.""" diff --git a/Lib/tempfile.py b/Lib/tempfile.py --- a/Lib/tempfile.py +++ b/Lib/tempfile.py @@ -357,9 +357,11 @@ def close(self, unlink=_os.unlink): if not self.close_called and self.file is not None: self.close_called = True - self.file.close() - if self.delete: - unlink(self.name) + try: + self.file.close() + finally: + if self.delete: + unlink(self.name) # Need to ensure the file is deleted on __del__ def __del__(self): diff --git a/Lib/urllib/response.py b/Lib/urllib/response.py --- a/Lib/urllib/response.py +++ b/Lib/urllib/response.py @@ -43,11 +43,15 @@ self.hookargs = hookargs def close(self): - if self.closehook: - self.closehook(*self.hookargs) - self.closehook = None - self.hookargs = None - super(addclosehook, self).close() + try: + closehook = self.closehook + hookargs = self.hookargs + if closehook: + self.closehook = None + self.hookargs = None + closehook(*hookargs) + finally: + super(addclosehook, self).close() class addinfo(addbase): diff --git a/Lib/wave.py b/Lib/wave.py --- a/Lib/wave.py +++ b/Lib/wave.py @@ -186,10 +186,11 @@ self._soundpos = 0 def close(self): - if self._i_opened_the_file: - self._i_opened_the_file.close() + self._file = None + file = self._i_opened_the_file + if file: self._i_opened_the_file = None - self._file = None + file.close() def tell(self): return self._soundpos @@ -428,17 +429,18 @@ self._patchheader() def close(self): - if self._file: - try: + try: + if self._file: self._ensure_header_written(0) if self._datalength != self._datawritten: self._patchheader() self._file.flush() - finally: - self._file = None - if self._i_opened_the_file: - self._i_opened_the_file.close() - self._i_opened_the_file = None + finally: + self._file = None + file = self._i_opened_the_file + if file: + self._i_opened_the_file = None + file.close() # # Internal methods. diff --git a/Lib/xml/sax/expatreader.py b/Lib/xml/sax/expatreader.py --- a/Lib/xml/sax/expatreader.py +++ b/Lib/xml/sax/expatreader.py @@ -211,22 +211,24 @@ self._err_handler.fatalError(exc) def close(self): - if self._entity_stack: + if self._entity_stack or self._parser is None: # If we are completing an external entity, do nothing here return - self.feed("", isFinal = 1) - self._cont_handler.endDocument() - self._parsing = 0 - # break cycle created by expat handlers pointing to our methods - self._parser = None try: - file = self._source.getCharacterStream() - if file is not None: - file.close() + self.feed("", isFinal = 1) + self._cont_handler.endDocument() finally: - file = self._source.getByteStream() - if file is not None: - file.close() + self._parsing = 0 + # break cycle created by expat handlers pointing to our methods + self._parser = None + try: + file = self._source.getCharacterStream() + if file is not None: + file.close() + finally: + file = self._source.getByteStream() + if file is not None: + file.close() def _reset_cont_handler(self): self._parser.ProcessingInstructionHandler = \ diff --git a/Lib/xmlrpc/client.py b/Lib/xmlrpc/client.py --- a/Lib/xmlrpc/client.py +++ b/Lib/xmlrpc/client.py @@ -438,8 +438,13 @@ self._parser.Parse(data, 0) def close(self): - self._parser.Parse("", 1) # end of data - del self._target, self._parser # get rid of circular references + try: + parser = self._parser + except AttributeError: + pass + else: + del self._target, self._parser # get rid of circular references + parser.Parse(b"", True) # end of data # -------------------------------------------------------------------- # XML-RPC marshalling and unmarshalling code @@ -1065,8 +1070,10 @@ gzip.GzipFile.__init__(self, mode="rb", fileobj=self.io) def close(self): - gzip.GzipFile.close(self) - self.io.close() + try: + gzip.GzipFile.close(self) + finally: + self.io.close() # -------------------------------------------------------------------- @@ -1221,9 +1228,10 @@ # Used in the event of socket errors. # def close(self): - if self._connection[1]: - self._connection[1].close() + host, connection = self._connection + if connection: self._connection = (None, None) + connection.close() ## # Send HTTP request. diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -19,6 +19,10 @@ Library ------- +- Issue #23865: close() methods in multiple modules now are idempotent and more + robust at shutdown. If needs to release multiple resources, they are released + even if errors are occured. + - Issue #23400: Raise same exception on both Python 2 and 3 if sem_open is not available. Patch by Davin Potts. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Apr 10 15:11:18 2015 From: python-checkins at python.org (berker.peksag) Date: Fri, 10 Apr 2015 13:11:18 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2323062=3A_Add_a_test_for_suppressing_--version_w?= =?utf-8?q?ith_argparse=2ESUPPRESS=2E?= Message-ID: <20150410131118.41562.63645@psf.io> https://hg.python.org/cpython/rev/157b59609cbd changeset: 95521:157b59609cbd parent: 95519:4ddec11b5faf parent: 95520:5b728310edac user: Berker Peksag date: Fri Apr 10 16:11:45 2015 +0300 summary: Issue #23062: Add a test for suppressing --version with argparse.SUPPRESS. TestHelpVersionOptional was redundant. files: Lib/test/test_argparse.py | 54 +++++++++++++-------------- 1 files changed, 26 insertions(+), 28 deletions(-) diff --git a/Lib/test/test_argparse.py b/Lib/test/test_argparse.py --- a/Lib/test/test_argparse.py +++ b/Lib/test/test_argparse.py @@ -3852,34 +3852,6 @@ version = '' -class TestHelpVersionOptional(HelpTestCase): - """Test that the --version argument can be suppressed help messages""" - - parser_signature = Sig(prog='PROG') - argument_signatures = [ - Sig('-v', '--version', action='version', version='1.0'), - Sig('--foo', help='foo help'), - Sig('spam', help='spam help'), - ] - argument_group_signatures = [] - usage = '''\ - usage: PROG [-h] [-v] [--foo FOO] spam - ''' - help = usage + '''\ - - positional arguments: - spam spam help - - optional arguments: - -h, --help show this help message and exit - -v, --version show program's version number and exit - --foo FOO foo help - ''' - version = '''\ - 1.0 - ''' - - class TestHelpNone(HelpTestCase): """Test that no errors occur if no help is specified""" @@ -4087,6 +4059,32 @@ ''' version = '' + +class TestHelpVersionActionSuppress(HelpTestCase): + """Test that the --version argument can be suppressed in help messages""" + + parser_signature = Sig(prog='PROG') + argument_signatures = [ + Sig('-v', '--version', action='version', version='1.0', + help=argparse.SUPPRESS), + Sig('--foo', help='foo help'), + Sig('spam', help='spam help'), + ] + argument_group_signatures = [] + usage = '''\ + usage: PROG [-h] [--foo FOO] spam + ''' + help = usage + '''\ + + positional arguments: + spam spam help + + optional arguments: + -h, --help show this help message and exit + --foo FOO foo help + ''' + + class TestHelpSubparsersOrdering(HelpTestCase): """Test ordering of subcommands in help matches the code""" parser_signature = Sig(prog='PROG', -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Apr 10 15:11:17 2015 From: python-checkins at python.org (berker.peksag) Date: Fri, 10 Apr 2015 13:11:17 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzIzMDYy?= =?utf-8?q?=3A_Add_a_test_for_suppressing_--version_with_argparse=2ESUPPRE?= =?utf-8?b?U1Mu?= Message-ID: <20150410131117.26853.7435@psf.io> https://hg.python.org/cpython/rev/5b728310edac changeset: 95520:5b728310edac branch: 3.4 parent: 95518:e826940911c8 user: Berker Peksag date: Fri Apr 10 16:11:12 2015 +0300 summary: Issue #23062: Add a test for suppressing --version with argparse.SUPPRESS. TestHelpVersionOptional was redundant. files: Lib/test/test_argparse.py | 54 +++++++++++++-------------- 1 files changed, 26 insertions(+), 28 deletions(-) diff --git a/Lib/test/test_argparse.py b/Lib/test/test_argparse.py --- a/Lib/test/test_argparse.py +++ b/Lib/test/test_argparse.py @@ -3845,34 +3845,6 @@ version = '' -class TestHelpVersionOptional(HelpTestCase): - """Test that the --version argument can be suppressed help messages""" - - parser_signature = Sig(prog='PROG') - argument_signatures = [ - Sig('-v', '--version', action='version', version='1.0'), - Sig('--foo', help='foo help'), - Sig('spam', help='spam help'), - ] - argument_group_signatures = [] - usage = '''\ - usage: PROG [-h] [-v] [--foo FOO] spam - ''' - help = usage + '''\ - - positional arguments: - spam spam help - - optional arguments: - -h, --help show this help message and exit - -v, --version show program's version number and exit - --foo FOO foo help - ''' - version = '''\ - 1.0 - ''' - - class TestHelpNone(HelpTestCase): """Test that no errors occur if no help is specified""" @@ -4080,6 +4052,32 @@ ''' version = '' + +class TestHelpVersionActionSuppress(HelpTestCase): + """Test that the --version argument can be suppressed in help messages""" + + parser_signature = Sig(prog='PROG') + argument_signatures = [ + Sig('-v', '--version', action='version', version='1.0', + help=argparse.SUPPRESS), + Sig('--foo', help='foo help'), + Sig('spam', help='spam help'), + ] + argument_group_signatures = [] + usage = '''\ + usage: PROG [-h] [--foo FOO] spam + ''' + help = usage + '''\ + + positional arguments: + spam spam help + + optional arguments: + -h, --help show this help message and exit + --foo FOO foo help + ''' + + class TestHelpSubparsersOrdering(HelpTestCase): """Test ordering of subcommands in help matches the code""" parser_signature = Sig(prog='PROG', -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Apr 10 15:19:17 2015 From: python-checkins at python.org (berker.peksag) Date: Fri, 10 Apr 2015 13:19:17 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2323025=3A_Add_a_mention_of_os=2Eurandom_to_RAND?= =?utf-8?q?=5Fbytes_and_RAND=5Fpseudo=5Fbytes?= Message-ID: <20150410131917.62517.6735@psf.io> https://hg.python.org/cpython/rev/7aa42cea8968 changeset: 95523:7aa42cea8968 parent: 95521:157b59609cbd parent: 95522:f85ac33b12a1 user: Berker Peksag date: Fri Apr 10 16:19:44 2015 +0300 summary: Issue #23025: Add a mention of os.urandom to RAND_bytes and RAND_pseudo_bytes docs. Patch by Alex Gaynor. files: Doc/library/ssl.rst | 4 ++++ 1 files changed, 4 insertions(+), 0 deletions(-) diff --git a/Doc/library/ssl.rst b/Doc/library/ssl.rst --- a/Doc/library/ssl.rst +++ b/Doc/library/ssl.rst @@ -292,6 +292,8 @@ can be used to check the status of the PRNG and :func:`RAND_add` can be used to seed the PRNG. + For almost all applications :func:`os.urandom` is preferable. + Read the Wikipedia article, `Cryptographically secure pseudorandom number generator (CSPRNG) `_, @@ -311,6 +313,8 @@ for non-cryptographic purposes and for certain purposes in cryptographic protocols, but usually not for key generation etc. + For almost all applications :func:`os.urandom` is preferable. + .. versionadded:: 3.3 .. function:: RAND_status() -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Apr 10 15:19:17 2015 From: python-checkins at python.org (berker.peksag) Date: Fri, 10 Apr 2015 13:19:17 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzIzMDI1?= =?utf-8?q?=3A_Add_a_mention_of_os=2Eurandom_to_RAND=5Fbytes_and_RAND=5Fps?= =?utf-8?q?eudo=5Fbytes?= Message-ID: <20150410131917.113193.38027@psf.io> https://hg.python.org/cpython/rev/f85ac33b12a1 changeset: 95522:f85ac33b12a1 branch: 3.4 parent: 95520:5b728310edac user: Berker Peksag date: Fri Apr 10 16:19:13 2015 +0300 summary: Issue #23025: Add a mention of os.urandom to RAND_bytes and RAND_pseudo_bytes docs. Patch by Alex Gaynor. files: Doc/library/ssl.rst | 4 ++++ 1 files changed, 4 insertions(+), 0 deletions(-) diff --git a/Doc/library/ssl.rst b/Doc/library/ssl.rst --- a/Doc/library/ssl.rst +++ b/Doc/library/ssl.rst @@ -292,6 +292,8 @@ can be used to check the status of the PRNG and :func:`RAND_add` can be used to seed the PRNG. + For almost all applications :func:`os.urandom` is preferable. + Read the Wikipedia article, `Cryptographically secure pseudorandom number generator (CSPRNG) `_, @@ -311,6 +313,8 @@ for non-cryptographic purposes and for certain purposes in cryptographic protocols, but usually not for key generation etc. + For almost all applications :func:`os.urandom` is preferable. + .. versionadded:: 3.3 .. function:: RAND_status() -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Apr 10 15:23:08 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Fri, 10 Apr 2015 13:23:08 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzIxODU5?= =?utf-8?q?=3A_Corrected_FileIO_docstrings=2E?= Message-ID: <20150410132308.21071.4673@psf.io> https://hg.python.org/cpython/rev/0db36098b908 changeset: 95524:0db36098b908 branch: 2.7 parent: 95517:f7ddec2e9e93 user: Serhiy Storchaka date: Fri Apr 10 16:08:33 2015 +0300 summary: Issue #21859: Corrected FileIO docstrings. files: Modules/_io/fileio.c | 31 +++++++++++++++++-------------- 1 files changed, 17 insertions(+), 14 deletions(-) diff --git a/Modules/_io/fileio.c b/Modules/_io/fileio.c --- a/Modules/_io/fileio.c +++ b/Modules/_io/fileio.c @@ -217,7 +217,7 @@ if (fd < 0) { if (!PyErr_Occurred()) { PyErr_SetString(PyExc_ValueError, - "Negative filedescriptor"); + "negative file descriptor"); return -1; } PyErr_Clear(); @@ -949,7 +949,7 @@ PyDoc_STRVAR(fileio_doc, "file(name: str[, mode: str]) -> file IO object\n" "\n" -"Open a file. The mode can be 'r', 'w' or 'a' for reading (default),\n" +"Open a file. The mode can be 'r' (default), 'w' or 'a' for reading,\n" "writing or appending. The file will be created if it doesn't exist\n" "when opened for writing or appending; it will be truncated when\n" "opened for writing. Add a '+' to the mode to allow simultaneous\n" @@ -972,22 +972,22 @@ "write(b: bytes) -> int. Write bytes b to file, return number written.\n" "\n" "Only makes one system call, so not all of the data may be written.\n" -"The number of bytes actually written is returned."); +"The number of bytes actually written is returned. In non-blocking mode,\n" +"returns None if the write would block." +); PyDoc_STRVAR(fileno_doc, -"fileno() -> int. \"file descriptor\".\n" -"\n" -"This is needed for lower-level file interfaces, such the fcntl module."); +"fileno() -> int. Return the underlying file descriptor (an integer)."); PyDoc_STRVAR(seek_doc, "seek(offset: int[, whence: int]) -> int. Move to new file position\n" "and return the file position.\n" "\n" "Argument offset is a byte count. Optional argument whence defaults to\n" -"0 (offset from start of file, offset should be >= 0); other values are 1\n" -"(move relative to current position, positive or negative), and 2 (move\n" -"relative to end of file, usually negative, although many platforms allow\n" -"seeking beyond the end of a file)." +"SEEK_SET or 0 (offset from start of file, offset should be >= 0); other values\n" +"are SEEK_CUR or 1 (move relative to current position, positive or negative),\n" +"and SEEK_END or 2 (move relative to end of file, usually negative, although\n" +"many platforms allow seeking beyond the end of a file).\n" "\n" "Note that not all file objects are seekable."); @@ -1001,7 +1001,10 @@ #endif PyDoc_STRVAR(tell_doc, -"tell() -> int. Current file position"); +"tell() -> int. Current file position.\n" +"\n" +"Can raise OSError for non seekable files." +); PyDoc_STRVAR(readinto_doc, "readinto() -> Same as RawIOBase.readinto()."); @@ -1010,10 +1013,10 @@ "close() -> None. Close the file.\n" "\n" "A closed file cannot be used for further I/O operations. close() may be\n" -"called more than once without error. Changes the fileno to -1."); +"called more than once without error."); PyDoc_STRVAR(isatty_doc, -"isatty() -> bool. True if the file is connected to a tty device."); +"isatty() -> bool. True if the file is connected to a TTY device."); PyDoc_STRVAR(seekable_doc, "seekable() -> bool. True if file supports random-access."); @@ -1066,7 +1069,7 @@ static PyGetSetDef fileio_getsetlist[] = { {"closed", (getter)get_closed, NULL, "True if the file is closed"}, {"closefd", (getter)get_closefd, NULL, - "True if the file descriptor will be closed"}, + "True if the file descriptor will be closed by close()."}, {"mode", (getter)get_mode, NULL, "String giving the file mode"}, {NULL}, }; -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Apr 10 15:23:08 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Fri, 10 Apr 2015 13:23:08 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2321859=3A_Corrected_FileIO_docstrings=2E?= Message-ID: <20150410132308.21285.55864@psf.io> https://hg.python.org/cpython/rev/330910697e23 changeset: 95526:330910697e23 parent: 95519:4ddec11b5faf parent: 95525:d080f5ecdcd3 user: Serhiy Storchaka date: Fri Apr 10 16:09:13 2015 +0300 summary: Issue #21859: Corrected FileIO docstrings. files: Modules/_io/fileio.c | 33 +++++++++++++++++-------------- 1 files changed, 18 insertions(+), 15 deletions(-) diff --git a/Modules/_io/fileio.c b/Modules/_io/fileio.c --- a/Modules/_io/fileio.c +++ b/Modules/_io/fileio.c @@ -233,7 +233,7 @@ if (fd < 0) { if (!PyErr_Occurred()) { PyErr_SetString(PyExc_ValueError, - "Negative filedescriptor"); + "negative file descriptor"); return -1; } PyErr_Clear(); @@ -1014,10 +1014,10 @@ PyDoc_STRVAR(fileio_doc, "file(name: str[, mode: str][, opener: None]) -> file IO object\n" "\n" -"Open a file. The mode can be 'r', 'w', 'x' or 'a' for reading (default),\n" +"Open a file. The mode can be 'r' (default), 'w', 'x' or 'a' for reading,\n" "writing, exclusive creation or appending. The file will be created if it\n" "doesn't exist when opened for writing or appending; it will be truncated\n" -"when opened for writing. A `FileExistsError` will be raised if it already\n" +"when opened for writing. A FileExistsError will be raised if it already\n" "exists when opened for creating. Opening a file for creating implies\n" "writing so this mode behaves in a similar way to 'w'.Add a '+' to the mode\n" "to allow simultaneous reading and writing. A custom opener can be used by\n" @@ -1043,22 +1043,22 @@ "write(b: bytes) -> int. Write bytes b to file, return number written.\n" "\n" "Only makes one system call, so not all of the data may be written.\n" -"The number of bytes actually written is returned."); +"The number of bytes actually written is returned. In non-blocking mode,\n" +"returns None if the write would block." +); PyDoc_STRVAR(fileno_doc, -"fileno() -> int. \"file descriptor\".\n" -"\n" -"This is needed for lower-level file interfaces, such the fcntl module."); +"fileno() -> int. Return the underlying file descriptor (an integer)."); PyDoc_STRVAR(seek_doc, "seek(offset: int[, whence: int]) -> int. Move to new file position and\n" "return the file position.\n" "\n" "Argument offset is a byte count. Optional argument whence defaults to\n" -"0 (offset from start of file, offset should be >= 0); other values are 1\n" -"(move relative to current position, positive or negative), and 2 (move\n" -"relative to end of file, usually negative, although many platforms allow\n" -"seeking beyond the end of a file)." +"SEEK_SET or 0 (offset from start of file, offset should be >= 0); other values\n" +"are SEEK_CUR or 1 (move relative to current position, positive or negative),\n" +"and SEEK_END or 2 (move relative to end of file, usually negative, although\n" +"many platforms allow seeking beyond the end of a file).\n" "\n" "Note that not all file objects are seekable."); @@ -1072,7 +1072,10 @@ #endif PyDoc_STRVAR(tell_doc, -"tell() -> int. Current file position"); +"tell() -> int. Current file position.\n" +"\n" +"Can raise OSError for non seekable files." +); PyDoc_STRVAR(readinto_doc, "readinto() -> Same as RawIOBase.readinto()."); @@ -1081,10 +1084,10 @@ "close() -> None. Close the file.\n" "\n" "A closed file cannot be used for further I/O operations. close() may be\n" -"called more than once without error. Changes the fileno to -1."); +"called more than once without error."); PyDoc_STRVAR(isatty_doc, -"isatty() -> bool. True if the file is connected to a tty device."); +"isatty() -> bool. True if the file is connected to a TTY device."); PyDoc_STRVAR(seekable_doc, "seekable() -> bool. True if file supports random-access."); @@ -1139,7 +1142,7 @@ static PyGetSetDef fileio_getsetlist[] = { {"closed", (getter)get_closed, NULL, "True if the file is closed"}, {"closefd", (getter)get_closefd, NULL, - "True if the file descriptor will be closed"}, + "True if the file descriptor will be closed by close()."}, {"mode", (getter)get_mode, NULL, "String giving the file mode"}, {NULL}, }; -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Apr 10 15:23:08 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Fri, 10 Apr 2015 13:23:08 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNCk6?= =?utf-8?q?_Merge_heads?= Message-ID: <20150410132308.21299.24173@psf.io> https://hg.python.org/cpython/rev/51a7e35833e1 changeset: 95528:51a7e35833e1 branch: 3.4 parent: 95525:d080f5ecdcd3 parent: 95520:5b728310edac user: Serhiy Storchaka date: Fri Apr 10 16:18:33 2015 +0300 summary: Merge heads files: Lib/test/test_argparse.py | 54 +++++++++++++-------------- 1 files changed, 26 insertions(+), 28 deletions(-) diff --git a/Lib/test/test_argparse.py b/Lib/test/test_argparse.py --- a/Lib/test/test_argparse.py +++ b/Lib/test/test_argparse.py @@ -3845,34 +3845,6 @@ version = '' -class TestHelpVersionOptional(HelpTestCase): - """Test that the --version argument can be suppressed help messages""" - - parser_signature = Sig(prog='PROG') - argument_signatures = [ - Sig('-v', '--version', action='version', version='1.0'), - Sig('--foo', help='foo help'), - Sig('spam', help='spam help'), - ] - argument_group_signatures = [] - usage = '''\ - usage: PROG [-h] [-v] [--foo FOO] spam - ''' - help = usage + '''\ - - positional arguments: - spam spam help - - optional arguments: - -h, --help show this help message and exit - -v, --version show program's version number and exit - --foo FOO foo help - ''' - version = '''\ - 1.0 - ''' - - class TestHelpNone(HelpTestCase): """Test that no errors occur if no help is specified""" @@ -4080,6 +4052,32 @@ ''' version = '' + +class TestHelpVersionActionSuppress(HelpTestCase): + """Test that the --version argument can be suppressed in help messages""" + + parser_signature = Sig(prog='PROG') + argument_signatures = [ + Sig('-v', '--version', action='version', version='1.0', + help=argparse.SUPPRESS), + Sig('--foo', help='foo help'), + Sig('spam', help='spam help'), + ] + argument_group_signatures = [] + usage = '''\ + usage: PROG [-h] [--foo FOO] spam + ''' + help = usage + '''\ + + positional arguments: + spam spam help + + optional arguments: + -h, --help show this help message and exit + --foo FOO foo help + ''' + + class TestHelpSubparsersOrdering(HelpTestCase): """Test ordering of subcommands in help matches the code""" parser_signature = Sig(prog='PROG', -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Apr 10 15:23:14 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Fri, 10 Apr 2015 13:23:14 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_default_-=3E_default?= =?utf-8?q?=29=3A_Merge_heads?= Message-ID: <20150410132314.21305.73112@psf.io> https://hg.python.org/cpython/rev/96d9a2a48907 changeset: 95532:96d9a2a48907 parent: 95530:a3e7f1d0b6d9 parent: 95523:7aa42cea8968 user: Serhiy Storchaka date: Fri Apr 10 16:22:03 2015 +0300 summary: Merge heads files: Doc/library/ssl.rst | 4 ++++ 1 files changed, 4 insertions(+), 0 deletions(-) diff --git a/Doc/library/ssl.rst b/Doc/library/ssl.rst --- a/Doc/library/ssl.rst +++ b/Doc/library/ssl.rst @@ -292,6 +292,8 @@ can be used to check the status of the PRNG and :func:`RAND_add` can be used to seed the PRNG. + For almost all applications :func:`os.urandom` is preferable. + Read the Wikipedia article, `Cryptographically secure pseudorandom number generator (CSPRNG) `_, @@ -311,6 +313,8 @@ for non-cryptographic purposes and for certain purposes in cryptographic protocols, but usually not for key generation etc. + For almost all applications :func:`os.urandom` is preferable. + .. versionadded:: 3.3 .. function:: RAND_status() -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Apr 10 15:23:16 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Fri, 10 Apr 2015 13:23:16 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_default_-=3E_default?= =?utf-8?q?=29=3A_Merge_heads?= Message-ID: <20150410132313.62515.96753@psf.io> https://hg.python.org/cpython/rev/271ce5e08255 changeset: 95529:271ce5e08255 parent: 95527:9ef5765d56b7 parent: 95521:157b59609cbd user: Serhiy Storchaka date: Fri Apr 10 16:18:58 2015 +0300 summary: Merge heads files: Lib/test/test_argparse.py | 54 +++++++++++++-------------- 1 files changed, 26 insertions(+), 28 deletions(-) diff --git a/Lib/test/test_argparse.py b/Lib/test/test_argparse.py --- a/Lib/test/test_argparse.py +++ b/Lib/test/test_argparse.py @@ -3852,34 +3852,6 @@ version = '' -class TestHelpVersionOptional(HelpTestCase): - """Test that the --version argument can be suppressed help messages""" - - parser_signature = Sig(prog='PROG') - argument_signatures = [ - Sig('-v', '--version', action='version', version='1.0'), - Sig('--foo', help='foo help'), - Sig('spam', help='spam help'), - ] - argument_group_signatures = [] - usage = '''\ - usage: PROG [-h] [-v] [--foo FOO] spam - ''' - help = usage + '''\ - - positional arguments: - spam spam help - - optional arguments: - -h, --help show this help message and exit - -v, --version show program's version number and exit - --foo FOO foo help - ''' - version = '''\ - 1.0 - ''' - - class TestHelpNone(HelpTestCase): """Test that no errors occur if no help is specified""" @@ -4087,6 +4059,32 @@ ''' version = '' + +class TestHelpVersionActionSuppress(HelpTestCase): + """Test that the --version argument can be suppressed in help messages""" + + parser_signature = Sig(prog='PROG') + argument_signatures = [ + Sig('-v', '--version', action='version', version='1.0', + help=argparse.SUPPRESS), + Sig('--foo', help='foo help'), + Sig('spam', help='spam help'), + ] + argument_group_signatures = [] + usage = '''\ + usage: PROG [-h] [--foo FOO] spam + ''' + help = usage + '''\ + + positional arguments: + spam spam help + + optional arguments: + -h, --help show this help message and exit + --foo FOO foo help + ''' + + class TestHelpSubparsersOrdering(HelpTestCase): """Test ordering of subcommands in help matches the code""" parser_signature = Sig(prog='PROG', -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Apr 10 15:23:16 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Fri, 10 Apr 2015 13:23:16 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Null_merge?= Message-ID: <20150410132314.62497.39708@psf.io> https://hg.python.org/cpython/rev/a3e7f1d0b6d9 changeset: 95530:a3e7f1d0b6d9 parent: 95529:271ce5e08255 parent: 95528:51a7e35833e1 user: Serhiy Storchaka date: Fri Apr 10 16:19:42 2015 +0300 summary: Null merge files: -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Apr 10 15:23:16 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Fri, 10 Apr 2015 13:23:16 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzIxODU5?= =?utf-8?q?=3A_Corrected_FileIO_docstrings=2E?= Message-ID: <20150410132308.129714.99764@psf.io> https://hg.python.org/cpython/rev/d080f5ecdcd3 changeset: 95525:d080f5ecdcd3 branch: 3.4 parent: 95518:e826940911c8 user: Serhiy Storchaka date: Fri Apr 10 16:08:43 2015 +0300 summary: Issue #21859: Corrected FileIO docstrings. files: Modules/_io/fileio.c | 33 +++++++++++++++++-------------- 1 files changed, 18 insertions(+), 15 deletions(-) diff --git a/Modules/_io/fileio.c b/Modules/_io/fileio.c --- a/Modules/_io/fileio.c +++ b/Modules/_io/fileio.c @@ -267,7 +267,7 @@ if (fd < 0) { if (!PyErr_Occurred()) { PyErr_SetString(PyExc_ValueError, - "Negative filedescriptor"); + "negative file descriptor"); return -1; } PyErr_Clear(); @@ -1094,10 +1094,10 @@ PyDoc_STRVAR(fileio_doc, "file(name: str[, mode: str][, opener: None]) -> file IO object\n" "\n" -"Open a file. The mode can be 'r', 'w', 'x' or 'a' for reading (default),\n" +"Open a file. The mode can be 'r' (default), 'w', 'x' or 'a' for reading,\n" "writing, exclusive creation or appending. The file will be created if it\n" "doesn't exist when opened for writing or appending; it will be truncated\n" -"when opened for writing. A `FileExistsError` will be raised if it already\n" +"when opened for writing. A FileExistsError will be raised if it already\n" "exists when opened for creating. Opening a file for creating implies\n" "writing so this mode behaves in a similar way to 'w'.Add a '+' to the mode\n" "to allow simultaneous reading and writing. A custom opener can be used by\n" @@ -1123,22 +1123,22 @@ "write(b: bytes) -> int. Write bytes b to file, return number written.\n" "\n" "Only makes one system call, so not all of the data may be written.\n" -"The number of bytes actually written is returned."); +"The number of bytes actually written is returned. In non-blocking mode,\n" +"returns None if the write would block." +); PyDoc_STRVAR(fileno_doc, -"fileno() -> int. \"file descriptor\".\n" -"\n" -"This is needed for lower-level file interfaces, such the fcntl module."); +"fileno() -> int. Return the underlying file descriptor (an integer)."); PyDoc_STRVAR(seek_doc, "seek(offset: int[, whence: int]) -> int. Move to new file position and\n" "return the file position.\n" "\n" "Argument offset is a byte count. Optional argument whence defaults to\n" -"0 (offset from start of file, offset should be >= 0); other values are 1\n" -"(move relative to current position, positive or negative), and 2 (move\n" -"relative to end of file, usually negative, although many platforms allow\n" -"seeking beyond the end of a file)." +"SEEK_SET or 0 (offset from start of file, offset should be >= 0); other values\n" +"are SEEK_CUR or 1 (move relative to current position, positive or negative),\n" +"and SEEK_END or 2 (move relative to end of file, usually negative, although\n" +"many platforms allow seeking beyond the end of a file).\n" "\n" "Note that not all file objects are seekable."); @@ -1152,7 +1152,10 @@ #endif PyDoc_STRVAR(tell_doc, -"tell() -> int. Current file position"); +"tell() -> int. Current file position.\n" +"\n" +"Can raise OSError for non seekable files." +); PyDoc_STRVAR(readinto_doc, "readinto() -> Same as RawIOBase.readinto()."); @@ -1161,10 +1164,10 @@ "close() -> None. Close the file.\n" "\n" "A closed file cannot be used for further I/O operations. close() may be\n" -"called more than once without error. Changes the fileno to -1."); +"called more than once without error."); PyDoc_STRVAR(isatty_doc, -"isatty() -> bool. True if the file is connected to a tty device."); +"isatty() -> bool. True if the file is connected to a TTY device."); PyDoc_STRVAR(seekable_doc, "seekable() -> bool. True if file supports random-access."); @@ -1219,7 +1222,7 @@ static PyGetSetDef fileio_getsetlist[] = { {"closed", (getter)get_closed, NULL, "True if the file is closed"}, {"closefd", (getter)get_closefd, NULL, - "True if the file descriptor will be closed"}, + "True if the file descriptor will be closed by close()."}, {"mode", (getter)get_mode, NULL, "String giving the file mode"}, {NULL}, }; -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Apr 10 15:23:16 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Fri, 10 Apr 2015 13:23:16 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2321859=3A_Added_Py?= =?utf-8?q?thon_implementation_of_io=2EFileIO=2E?= Message-ID: <20150410132308.37460.3952@psf.io> https://hg.python.org/cpython/rev/9ef5765d56b7 changeset: 95527:9ef5765d56b7 user: Serhiy Storchaka date: Fri Apr 10 16:16:16 2015 +0300 summary: Issue #21859: Added Python implementation of io.FileIO. files: Lib/_pyio.py | 344 ++++++++++++++++++++++++ Lib/test/test_file_eintr.py | 40 ++- Lib/test/test_fileio.py | 180 ++++++++---- Misc/NEWS | 2 + 4 files changed, 500 insertions(+), 66 deletions(-) diff --git a/Lib/_pyio.py b/Lib/_pyio.py --- a/Lib/_pyio.py +++ b/Lib/_pyio.py @@ -7,11 +7,16 @@ import codecs import errno import array +import stat # Import _thread instead of threading to reduce startup cost try: from _thread import allocate_lock as Lock except ImportError: from _dummy_thread import allocate_lock as Lock +if os.name == 'win32': + from msvcrt import setmode as _setmode +else: + _setmode = None import io from io import (__all__, SEEK_SET, SEEK_CUR, SEEK_END) @@ -1378,6 +1383,345 @@ return BufferedWriter.write(self, b) +class FileIO(RawIOBase): + _fd = -1 + _created = False + _readable = False + _writable = False + _appending = False + _seekable = None + _closefd = True + + def __init__(self, file, mode='r', closefd=True, opener=None): + """Open a file. The mode can be 'r' (default), 'w', 'x' or 'a' for reading, + writing, exclusive creation or appending. The file will be created if it + doesn't exist when opened for writing or appending; it will be truncated + when opened for writing. A FileExistsError will be raised if it already + exists when opened for creating. Opening a file for creating implies + writing so this mode behaves in a similar way to 'w'. Add a '+' to the mode + to allow simultaneous reading and writing. A custom opener can be used by + passing a callable as *opener*. The underlying file descriptor for the file + object is then obtained by calling opener with (*name*, *flags*). + *opener* must return an open file descriptor (passing os.open as *opener* + results in functionality similar to passing None). + """ + if self._fd >= 0: + # Have to close the existing file first. + try: + if self._closefd: + os.close(self._fd) + finally: + self._fd = -1 + + if isinstance(file, float): + raise TypeError('integer argument expected, got float') + if isinstance(file, int): + fd = file + if fd < 0: + raise ValueError('negative file descriptor') + else: + fd = -1 + + if not isinstance(mode, str): + raise TypeError('invalid mode: %s' % (mode,)) + if not set(mode) <= set('xrwab+'): + raise ValueError('invalid mode: %s' % (mode,)) + if sum(c in 'rwax' for c in mode) != 1 or mode.count('+') > 1: + raise ValueError('Must have exactly one of create/read/write/append ' + 'mode and at most one plus') + + if 'x' in mode: + self._created = True + self._writable = True + flags = os.O_EXCL | os.O_CREAT + elif 'r' in mode: + self._readable = True + flags = 0 + elif 'w' in mode: + self._writable = True + flags = os.O_CREAT | os.O_TRUNC + elif 'a' in mode: + self._writable = True + self._appending = True + flags = os.O_APPEND | os.O_CREAT + + if '+' in mode: + self._readable = True + self._writable = True + + if self._readable and self._writable: + flags |= os.O_RDWR + elif self._readable: + flags |= os.O_RDONLY + else: + flags |= os.O_WRONLY + + flags |= getattr(os, 'O_BINARY', 0) + + noinherit_flag = (getattr(os, 'O_NOINHERIT', 0) or + getattr(os, 'O_CLOEXEC', 0)) + flags |= noinherit_flag + + owned_fd = None + try: + if fd < 0: + if not closefd: + raise ValueError('Cannot use closefd=False with file name') + if opener is None: + fd = os.open(file, flags, 0o666) + else: + fd = opener(file, flags) + if not isinstance(fd, int): + raise TypeError('expected integer from opener') + if fd < 0: + raise OSError('Negative file descriptor') + owned_fd = fd + if not noinherit_flag: + os.set_inheritable(fd, False) + + self._closefd = closefd + fdfstat = os.fstat(fd) + try: + if stat.S_ISDIR(fdfstat.st_mode): + raise IsADirectoryError(errno.EISDIR, + os.strerror(errno.EISDIR), file) + except AttributeError: + # Ignore the AttribueError if stat.S_ISDIR or errno.EISDIR + # don't exist. + pass + self._blksize = getattr(fdfstat, 'st_blksize', 0) + if self._blksize <= 1: + self._blksize = DEFAULT_BUFFER_SIZE + + if _setmode: + # don't translate newlines (\r\n <=> \n) + _setmode(fd, os.O_BINARY) + + self.name = file + if self._appending: + # For consistent behaviour, we explicitly seek to the + # end of file (otherwise, it might be done only on the + # first write()). + os.lseek(fd, 0, SEEK_END) + except: + if owned_fd is not None: + os.close(owned_fd) + raise + self._fd = fd + + def __del__(self): + if self._fd >= 0 and self._closefd and not self.closed: + import warnings + warnings.warn('unclosed file %r' % (self,), ResourceWarning, + stacklevel=2) + self.close() + + def __getstate__(self): + raise TypeError("cannot serialize '%s' object", self.__class__.__name__) + + def __repr__(self): + class_name = '%s.%s' % (self.__class__.__module__, + self.__class__.__qualname__) + if self.closed: + return '<%s [closed]>' % class_name + try: + name = self.name + except AttributeError: + return ('<%s fd=%d mode=%r closefd=%r>' % + (class_name, self._fd, self.mode, self._closefd)) + else: + return ('<%s name=%r mode=%r closefd=%r>' % + (class_name, name, self.mode, self._closefd)) + + def _checkReadable(self): + if not self._readable: + raise UnsupportedOperation('File not open for reading') + + def _checkWritable(self, msg=None): + if not self._writable: + raise UnsupportedOperation('File not open for writing') + + def read(self, size=None): + """Read at most size bytes, returned as bytes. + + Only makes one system call, so less data may be returned than requested + In non-blocking mode, returns None if no data is available. + Return an empty bytes object at EOF. + """ + self._checkClosed() + self._checkReadable() + if size is None or size < 0: + return self.readall() + try: + return os.read(self._fd, size) + except BlockingIOError: + return None + + def readall(self): + """Read all data from the file, returned as bytes. + + In non-blocking mode, returns as much as is immediately available, + or None if no data is available. Return an empty bytes object at EOF. + """ + self._checkClosed() + self._checkReadable() + bufsize = DEFAULT_BUFFER_SIZE + try: + pos = os.lseek(self._fd, 0, SEEK_CUR) + end = os.fstat(self._fd).st_size + if end >= pos: + bufsize = end - pos + 1 + except OSError: + pass + + result = bytearray() + while True: + if len(result) >= bufsize: + bufsize = len(result) + bufsize += max(bufsize, DEFAULT_BUFFER_SIZE) + n = bufsize - len(result) + try: + chunk = os.read(self._fd, n) + except BlockingIOError: + if result: + break + return None + if not chunk: # reached the end of the file + break + result += chunk + + return bytes(result) + + def readinto(self, b): + """Same as RawIOBase.readinto().""" + m = memoryview(b).cast('B') + data = self.read(len(m)) + n = len(data) + m[:n] = data + return n + + def write(self, b): + """Write bytes b to file, return number written. + + Only makes one system call, so not all of the data may be written. + The number of bytes actually written is returned. In non-blocking mode, + returns None if the write would block. + """ + self._checkClosed() + self._checkWritable() + try: + return os.write(self._fd, b) + except BlockingIOError: + return None + + def seek(self, pos, whence=SEEK_SET): + """Move to new file position. + + Argument offset is a byte count. Optional argument whence defaults to + SEEK_SET or 0 (offset from start of file, offset should be >= 0); other values + are SEEK_CUR or 1 (move relative to current position, positive or negative), + and SEEK_END or 2 (move relative to end of file, usually negative, although + many platforms allow seeking beyond the end of a file). + + Note that not all file objects are seekable. + """ + if isinstance(pos, float): + raise TypeError('an integer is required') + self._checkClosed() + return os.lseek(self._fd, pos, whence) + + def tell(self): + """tell() -> int. Current file position. + + Can raise OSError for non seekable files.""" + self._checkClosed() + return os.lseek(self._fd, 0, SEEK_CUR) + + def truncate(self, size=None): + """Truncate the file to at most size bytes. + + Size defaults to the current file position, as returned by tell(). + The current file position is changed to the value of size. + """ + self._checkClosed() + self._checkWritable() + if size is None: + size = self.tell() + os.ftruncate(self._fd, size) + return size + + def close(self): + """Close the file. + + A closed file cannot be used for further I/O operations. close() may be + called more than once without error. + """ + if not self.closed: + try: + if self._closefd: + os.close(self._fd) + finally: + super().close() + + def seekable(self): + """True if file supports random-access.""" + self._checkClosed() + if self._seekable is None: + try: + self.tell() + except OSError: + self._seekable = False + else: + self._seekable = True + return self._seekable + + def readable(self): + """True if file was opened in a read mode.""" + self._checkClosed() + return self._readable + + def writable(self): + """True if file was opened in a write mode.""" + self._checkClosed() + return self._writable + + def fileno(self): + """Return the underlying file descriptor (an integer).""" + self._checkClosed() + return self._fd + + def isatty(self): + """True if the file is connected to a TTY device.""" + self._checkClosed() + return os.isatty(self._fd) + + @property + def closefd(self): + """True if the file descriptor will be closed by close().""" + return self._closefd + + @property + def mode(self): + """String giving the file mode""" + if self._created: + if self._readable: + return 'xb+' + else: + return 'xb' + elif self._appending: + if self._readable: + return 'ab+' + else: + return 'ab' + elif self._readable: + if self._writable: + return 'rb+' + else: + return 'rb' + else: + return 'wb' + + class TextIOBase(IOBase): """Base class for text I/O. diff --git a/Lib/test/test_file_eintr.py b/Lib/test/test_file_eintr.py --- a/Lib/test/test_file_eintr.py +++ b/Lib/test/test_file_eintr.py @@ -18,11 +18,12 @@ import unittest # Test import all of the things we're about to try testing up front. -from _io import FileIO +import _io +import _pyio @unittest.skipUnless(os.name == 'posix', 'tests requires a posix system.') -class TestFileIOSignalInterrupt(unittest.TestCase): +class TestFileIOSignalInterrupt: def setUp(self): self._process = None @@ -38,8 +39,9 @@ subclasseses should override this to test different IO objects. """ - return ('import _io ;' - 'infile = _io.FileIO(sys.stdin.fileno(), "rb")') + return ('import %s as io ;' + 'infile = io.FileIO(sys.stdin.fileno(), "rb")' % + self.modname) def fail_with_process_info(self, why, stdout=b'', stderr=b'', communicate=True): @@ -179,11 +181,19 @@ expected=b'hello\nworld!\n')) +class CTestFileIOSignalInterrupt(TestFileIOSignalInterrupt, unittest.TestCase): + modname = '_io' + +class PyTestFileIOSignalInterrupt(TestFileIOSignalInterrupt, unittest.TestCase): + modname = '_pyio' + + class TestBufferedIOSignalInterrupt(TestFileIOSignalInterrupt): def _generate_infile_setup_code(self): """Returns the infile = ... line of code to make a BufferedReader.""" - return ('infile = open(sys.stdin.fileno(), "rb") ;' - 'import _io ;assert isinstance(infile, _io.BufferedReader)') + return ('import %s as io ;infile = io.open(sys.stdin.fileno(), "rb") ;' + 'assert isinstance(infile, io.BufferedReader)' % + self.modname) def test_readall(self): """BufferedReader.read() must handle signals and not lose data.""" @@ -193,12 +203,20 @@ read_method_name='read', expected=b'hello\nworld!\n')) +class CTestBufferedIOSignalInterrupt(TestBufferedIOSignalInterrupt, unittest.TestCase): + modname = '_io' + +class PyTestBufferedIOSignalInterrupt(TestBufferedIOSignalInterrupt, unittest.TestCase): + modname = '_pyio' + class TestTextIOSignalInterrupt(TestFileIOSignalInterrupt): def _generate_infile_setup_code(self): """Returns the infile = ... line of code to make a TextIOWrapper.""" - return ('infile = open(sys.stdin.fileno(), "rt", newline=None) ;' - 'import _io ;assert isinstance(infile, _io.TextIOWrapper)') + return ('import %s as io ;' + 'infile = io.open(sys.stdin.fileno(), "rt", newline=None) ;' + 'assert isinstance(infile, io.TextIOWrapper)' % + self.modname) def test_readline(self): """readline() must handle signals and not lose data.""" @@ -224,6 +242,12 @@ read_method_name='read', expected="hello\nworld!\n")) +class CTestTextIOSignalInterrupt(TestTextIOSignalInterrupt, unittest.TestCase): + modname = '_io' + +class PyTestTextIOSignalInterrupt(TestTextIOSignalInterrupt, unittest.TestCase): + modname = '_pyio' + def test_main(): test_cases = [ diff --git a/Lib/test/test_fileio.py b/Lib/test/test_fileio.py --- a/Lib/test/test_fileio.py +++ b/Lib/test/test_fileio.py @@ -12,13 +12,15 @@ from test.support import TESTFN, check_warnings, run_unittest, make_bad_fd, cpython_only from collections import UserList -from _io import FileIO as _FileIO +import _io # C implementation of io +import _pyio # Python implementation of io -class AutoFileTests(unittest.TestCase): + +class AutoFileTests: # file tests for which a test file is automatically set up def setUp(self): - self.f = _FileIO(TESTFN, 'w') + self.f = self.FileIO(TESTFN, 'w') def tearDown(self): if self.f: @@ -69,20 +71,60 @@ blksize = getattr(fst, 'st_blksize', blksize) self.assertEqual(self.f._blksize, blksize) - def testReadinto(self): - # verify readinto - self.f.write(bytes([1, 2])) + # verify readinto + def testReadintoByteArray(self): + self.f.write(bytes([1, 2, 0, 255])) self.f.close() - a = array('b', b'x'*10) - self.f = _FileIO(TESTFN, 'r') - n = self.f.readinto(a) - self.assertEqual(array('b', [1, 2]), a[:n]) + + ba = bytearray(b'abcdefgh') + with self.FileIO(TESTFN, 'r') as f: + n = f.readinto(ba) + self.assertEqual(ba, b'\x01\x02\x00\xffefgh') + self.assertEqual(n, 4) + + def _testReadintoMemoryview(self): + self.f.write(bytes([1, 2, 0, 255])) + self.f.close() + + m = memoryview(bytearray(b'abcdefgh')) + with self.FileIO(TESTFN, 'r') as f: + n = f.readinto(m) + self.assertEqual(m, b'\x01\x02\x00\xffefgh') + self.assertEqual(n, 4) + + m = memoryview(bytearray(b'abcdefgh')).cast('H', shape=[2, 2]) + with self.FileIO(TESTFN, 'r') as f: + n = f.readinto(m) + self.assertEqual(bytes(m), b'\x01\x02\x00\xffefgh') + self.assertEqual(n, 4) + + def _testReadintoArray(self): + self.f.write(bytes([1, 2, 0, 255])) + self.f.close() + + a = array('B', b'abcdefgh') + with self.FileIO(TESTFN, 'r') as f: + n = f.readinto(a) + self.assertEqual(a, array('B', [1, 2, 0, 255, 101, 102, 103, 104])) + self.assertEqual(n, 4) + + a = array('b', b'abcdefgh') + with self.FileIO(TESTFN, 'r') as f: + n = f.readinto(a) + self.assertEqual(a, array('b', [1, 2, 0, -1, 101, 102, 103, 104])) + self.assertEqual(n, 4) + + a = array('I', b'abcdefgh') + with self.FileIO(TESTFN, 'r') as f: + n = f.readinto(a) + self.assertEqual(a, array('I', b'\x01\x02\x00\xffefgh')) + self.assertEqual(n, 4) def testWritelinesList(self): l = [b'123', b'456'] self.f.writelines(l) self.f.close() - self.f = _FileIO(TESTFN, 'rb') + self.f = self.FileIO(TESTFN, 'rb') buf = self.f.read() self.assertEqual(buf, b'123456') @@ -90,7 +132,7 @@ l = UserList([b'123', b'456']) self.f.writelines(l) self.f.close() - self.f = _FileIO(TESTFN, 'rb') + self.f = self.FileIO(TESTFN, 'rb') buf = self.f.read() self.assertEqual(buf, b'123456') @@ -102,7 +144,7 @@ def test_none_args(self): self.f.write(b"hi\nbye\nabc") self.f.close() - self.f = _FileIO(TESTFN, 'r') + self.f = self.FileIO(TESTFN, 'r') self.assertEqual(self.f.read(None), b"hi\nbye\nabc") self.f.seek(0) self.assertEqual(self.f.readline(None), b"hi\n") @@ -112,23 +154,24 @@ self.assertRaises(TypeError, self.f.write, "Hello!") def testRepr(self): - self.assertEqual( - repr(self.f), "<_io.FileIO name=%r mode=%r closefd=True>" - % (self.f.name, self.f.mode)) + self.assertEqual(repr(self.f), + "<%s.FileIO name=%r mode=%r closefd=True>" % + (self.modulename, self.f.name, self.f.mode)) del self.f.name - self.assertEqual( - repr(self.f), "<_io.FileIO fd=%r mode=%r closefd=True>" - % (self.f.fileno(), self.f.mode)) + self.assertEqual(repr(self.f), + "<%s.FileIO fd=%r mode=%r closefd=True>" % + (self.modulename, self.f.fileno(), self.f.mode)) self.f.close() - self.assertEqual(repr(self.f), "<_io.FileIO [closed]>") + self.assertEqual(repr(self.f), + "<%s.FileIO [closed]>" % (self.modulename,)) def testReprNoCloseFD(self): fd = os.open(TESTFN, os.O_RDONLY) try: - with _FileIO(fd, 'r', closefd=False) as f: + with self.FileIO(fd, 'r', closefd=False) as f: self.assertEqual(repr(f), - "<_io.FileIO name=%r mode=%r closefd=False>" - % (f.name, f.mode)) + "<%s.FileIO name=%r mode=%r closefd=False>" % + (self.modulename, f.name, f.mode)) finally: os.close(fd) @@ -140,15 +183,15 @@ self.assertRaises(ValueError, f.read, 10) # Open for reading f.close() self.assertTrue(f.closed) - f = _FileIO(TESTFN, 'r') + f = self.FileIO(TESTFN, 'r') self.assertRaises(TypeError, f.readinto, "") self.assertTrue(not f.closed) f.close() self.assertTrue(f.closed) def testMethods(self): - methods = ['fileno', 'isatty', 'read', 'readinto', - 'seek', 'tell', 'truncate', 'write', 'seekable', + methods = ['fileno', 'isatty', 'read', + 'tell', 'truncate', 'seekable', 'readable', 'writable'] self.f.close() @@ -158,13 +201,16 @@ method = getattr(self.f, methodname) # should raise on closed file self.assertRaises(ValueError, method) + self.assertRaises(ValueError, self.f.readinto, bytearray()) + self.assertRaises(ValueError, self.f.seek, 0, os.SEEK_CUR) + self.assertRaises(ValueError, self.f.write, b'') def testOpendir(self): # Issue 3703: opening a directory should fill the errno # Windows always returns "[Errno 13]: Permission denied # Unix uses fstat and returns "[Errno 21]: Is a directory" try: - _FileIO('.', 'r') + self.FileIO('.', 'r') except OSError as e: self.assertNotEqual(e.errno, 0) self.assertEqual(e.filename, ".") @@ -175,7 +221,7 @@ def testOpenDirFD(self): fd = os.open('.', os.O_RDONLY) with self.assertRaises(OSError) as cm: - _FileIO(fd, 'r') + self.FileIO(fd, 'r') os.close(fd) self.assertEqual(cm.exception.errno, errno.EISDIR) @@ -260,7 +306,7 @@ self.f.close() except OSError: pass - self.f = _FileIO(TESTFN, 'r') + self.f = self.FileIO(TESTFN, 'r') os.close(self.f.fileno()) return self.f @@ -280,23 +326,32 @@ a = array('b', b'x'*10) f.readinto(a) -class OtherFileTests(unittest.TestCase): +class CAutoFileTests(AutoFileTests, unittest.TestCase): + FileIO = _io.FileIO + modulename = '_io' + +class PyAutoFileTests(AutoFileTests, unittest.TestCase): + FileIO = _pyio.FileIO + modulename = '_pyio' + + +class OtherFileTests: def testAbles(self): try: - f = _FileIO(TESTFN, "w") + f = self.FileIO(TESTFN, "w") self.assertEqual(f.readable(), False) self.assertEqual(f.writable(), True) self.assertEqual(f.seekable(), True) f.close() - f = _FileIO(TESTFN, "r") + f = self.FileIO(TESTFN, "r") self.assertEqual(f.readable(), True) self.assertEqual(f.writable(), False) self.assertEqual(f.seekable(), True) f.close() - f = _FileIO(TESTFN, "a+") + f = self.FileIO(TESTFN, "a+") self.assertEqual(f.readable(), True) self.assertEqual(f.writable(), True) self.assertEqual(f.seekable(), True) @@ -305,7 +360,7 @@ if sys.platform != "win32": try: - f = _FileIO("/dev/tty", "a") + f = self.FileIO("/dev/tty", "a") except OSError: # When run in a cron job there just aren't any # ttys, so skip the test. This also handles other @@ -328,7 +383,7 @@ # check invalid mode strings for mode in ("", "aU", "wU+", "rw", "rt"): try: - f = _FileIO(TESTFN, mode) + f = self.FileIO(TESTFN, mode) except ValueError: pass else: @@ -344,7 +399,7 @@ ('ab+', 'ab+'), ('a+b', 'ab+'), ('r', 'rb'), ('rb', 'rb'), ('rb+', 'rb+'), ('r+b', 'rb+')]: # read modes are last so that TESTFN will exist first - with _FileIO(TESTFN, modes[0]) as f: + with self.FileIO(TESTFN, modes[0]) as f: self.assertEqual(f.mode, modes[1]) finally: if os.path.exists(TESTFN): @@ -352,7 +407,7 @@ def testUnicodeOpen(self): # verify repr works for unicode too - f = _FileIO(str(TESTFN), "w") + f = self.FileIO(str(TESTFN), "w") f.close() os.unlink(TESTFN) @@ -362,7 +417,7 @@ fn = TESTFN.encode("ascii") except UnicodeEncodeError: self.skipTest('could not encode %r to ascii' % TESTFN) - f = _FileIO(fn, "w") + f = self.FileIO(fn, "w") try: f.write(b"abc") f.close() @@ -373,28 +428,21 @@ def testConstructorHandlesNULChars(self): fn_with_NUL = 'foo\0bar' - self.assertRaises(ValueError, _FileIO, fn_with_NUL, 'w') - self.assertRaises(ValueError, _FileIO, bytes(fn_with_NUL, 'ascii'), 'w') + self.assertRaises(ValueError, self.FileIO, fn_with_NUL, 'w') + self.assertRaises(ValueError, self.FileIO, bytes(fn_with_NUL, 'ascii'), 'w') def testInvalidFd(self): - self.assertRaises(ValueError, _FileIO, -10) - self.assertRaises(OSError, _FileIO, make_bad_fd()) + self.assertRaises(ValueError, self.FileIO, -10) + self.assertRaises(OSError, self.FileIO, make_bad_fd()) if sys.platform == 'win32': import msvcrt self.assertRaises(OSError, msvcrt.get_osfhandle, make_bad_fd()) - @cpython_only - def testInvalidFd_overflow(self): - # Issue 15989 - import _testcapi - self.assertRaises(TypeError, _FileIO, _testcapi.INT_MAX + 1) - self.assertRaises(TypeError, _FileIO, _testcapi.INT_MIN - 1) - def testBadModeArgument(self): # verify that we get a sensible error message for bad mode argument bad_mode = "qwerty" try: - f = _FileIO(TESTFN, bad_mode) + f = self.FileIO(TESTFN, bad_mode) except ValueError as msg: if msg.args[0] != 0: s = str(msg) @@ -407,7 +455,7 @@ self.fail("no error for invalid mode: %s" % bad_mode) def testTruncate(self): - f = _FileIO(TESTFN, 'w') + f = self.FileIO(TESTFN, 'w') f.write(bytes(bytearray(range(10)))) self.assertEqual(f.tell(), 10) f.truncate(5) @@ -422,11 +470,11 @@ def bug801631(): # SF bug # "file.truncate fault on windows" - f = _FileIO(TESTFN, 'w') + f = self.FileIO(TESTFN, 'w') f.write(bytes(range(11))) f.close() - f = _FileIO(TESTFN,'r+') + f = self.FileIO(TESTFN,'r+') data = f.read(5) if data != bytes(range(5)): self.fail("Read on file opened for update failed %r" % data) @@ -466,19 +514,19 @@ pass def testInvalidInit(self): - self.assertRaises(TypeError, _FileIO, "1", 0, 0) + self.assertRaises(TypeError, self.FileIO, "1", 0, 0) def testWarnings(self): with check_warnings(quiet=True) as w: self.assertEqual(w.warnings, []) - self.assertRaises(TypeError, _FileIO, []) + self.assertRaises(TypeError, self.FileIO, []) self.assertEqual(w.warnings, []) - self.assertRaises(ValueError, _FileIO, "/some/invalid/name", "rt") + self.assertRaises(ValueError, self.FileIO, "/some/invalid/name", "rt") self.assertEqual(w.warnings, []) def testUnclosedFDOnException(self): class MyException(Exception): pass - class MyFileIO(_FileIO): + class MyFileIO(self.FileIO): def __setattr__(self, name, value): if name == "name": raise MyException("blocked setting name") @@ -487,12 +535,28 @@ self.assertRaises(MyException, MyFileIO, fd) os.close(fd) # should not raise OSError(EBADF) +class COtherFileTests(OtherFileTests, unittest.TestCase): + FileIO = _io.FileIO + modulename = '_io' + + @cpython_only + def testInvalidFd_overflow(self): + # Issue 15989 + import _testcapi + self.assertRaises(TypeError, self.FileIO, _testcapi.INT_MAX + 1) + self.assertRaises(TypeError, self.FileIO, _testcapi.INT_MIN - 1) + +class PyOtherFileTests(OtherFileTests, unittest.TestCase): + FileIO = _pyio.FileIO + modulename = '_pyio' + def test_main(): # Historically, these tests have been sloppy about removing TESTFN. # So get rid of it no matter what. try: - run_unittest(AutoFileTests, OtherFileTests) + run_unittest(CAutoFileTests, PyAutoFileTests, + COtherFileTests, PyOtherFileTests) finally: if os.path.exists(TESTFN): os.unlink(TESTFN) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -19,6 +19,8 @@ Library ------- +- Issue #21859: Added Python implementation of io.FileIO. + - Issue #23865: close() methods in multiple modules now are idempotent and more robust at shutdown. If needs to release multiple resources, they are released even if errors are occured. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Apr 10 15:23:16 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Fri, 10 Apr 2015 13:23:16 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNCk6?= =?utf-8?q?_Merge_heads?= Message-ID: <20150410132314.37466.59497@psf.io> https://hg.python.org/cpython/rev/4232eb53a036 changeset: 95531:4232eb53a036 branch: 3.4 parent: 95528:51a7e35833e1 parent: 95522:f85ac33b12a1 user: Serhiy Storchaka date: Fri Apr 10 16:21:58 2015 +0300 summary: Merge heads files: Doc/library/ssl.rst | 4 ++++ 1 files changed, 4 insertions(+), 0 deletions(-) diff --git a/Doc/library/ssl.rst b/Doc/library/ssl.rst --- a/Doc/library/ssl.rst +++ b/Doc/library/ssl.rst @@ -292,6 +292,8 @@ can be used to check the status of the PRNG and :func:`RAND_add` can be used to seed the PRNG. + For almost all applications :func:`os.urandom` is preferable. + Read the Wikipedia article, `Cryptographically secure pseudorandom number generator (CSPRNG) `_, @@ -311,6 +313,8 @@ for non-cryptographic purposes and for certain purposes in cryptographic protocols, but usually not for key generation etc. + For almost all applications :func:`os.urandom` is preferable. + .. versionadded:: 3.3 .. function:: RAND_status() -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Apr 10 15:23:16 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Fri, 10 Apr 2015 13:23:16 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Null_merge?= Message-ID: <20150410132314.37458.95692@psf.io> https://hg.python.org/cpython/rev/3ebeeed1eb28 changeset: 95533:3ebeeed1eb28 parent: 95532:96d9a2a48907 parent: 95531:4232eb53a036 user: Serhiy Storchaka date: Fri Apr 10 16:22:14 2015 +0300 summary: Null merge files: Doc/library/ssl.rst | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-) diff --git a/Doc/library/ssl.rst b/Doc/library/ssl.rst --- a/Doc/library/ssl.rst +++ b/Doc/library/ssl.rst @@ -315,6 +315,8 @@ For almost all applications :func:`os.urandom` is preferable. + For almost all applications :func:`os.urandom` is preferable. + .. versionadded:: 3.3 .. function:: RAND_status() -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Apr 10 20:13:47 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Fri, 10 Apr 2015 18:13:47 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzE2ODQw?= =?utf-8?q?=3A_Fixed_Tcl_test_on_2=2E7_with_Tcl_8=2E4=2E19=2E?= Message-ID: <20150410181347.26884.80368@psf.io> https://hg.python.org/cpython/rev/350c78a92046 changeset: 95534:350c78a92046 branch: 2.7 parent: 95524:0db36098b908 user: Serhiy Storchaka date: Fri Apr 10 21:12:18 2015 +0300 summary: Issue #16840: Fixed Tcl test on 2.7 with Tcl 8.4.19. In some Tcl versions -2147483648 is wide integer. files: Lib/test/test_tcl.py | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_tcl.py b/Lib/test/test_tcl.py --- a/Lib/test/test_tcl.py +++ b/Lib/test/test_tcl.py @@ -440,7 +440,8 @@ if self.wantobjects: self.assertEqual(result, i) self.assertIsInstance(result, (int, long)) - self.assertIsInstance(result, type(int(result))) + if abs(result) < 2**31: + self.assertIsInstance(result, int) else: self.assertEqual(result, str(i)) self.assertIsInstance(result, str) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Apr 11 00:33:05 2015 From: python-checkins at python.org (antoine.pitrou) Date: Fri, 10 Apr 2015 22:33:05 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2323529=3A_Limit_th?= =?utf-8?q?e_size_of_decompressed_data_when_reading_from?= Message-ID: <20150410223304.810.7653@psf.io> https://hg.python.org/cpython/rev/62723172412c changeset: 95535:62723172412c parent: 95533:3ebeeed1eb28 user: Antoine Pitrou date: Sat Apr 11 00:31:01 2015 +0200 summary: Issue #23529: Limit the size of decompressed data when reading from GzipFile, BZ2File or LZMAFile. This defeats denial of service attacks using compressed bombs (i.e. compressed payloads which decompress to a huge size). Patch by Martin Panter and Nikolaus Rath. files: Doc/library/bz2.rst | 4 + Doc/library/gzip.rst | 30 +- Doc/library/lzma.rst | 4 + Lib/_compression.py | 152 +++++++++ Lib/bz2.py | 235 ++------------ Lib/gzip.py | 477 +++++++++++------------------ Lib/lzma.py | 224 +------------ Lib/test/test_bz2.py | 30 +- Lib/test/test_gzip.py | 23 +- Lib/test/test_lzma.py | 25 +- Misc/NEWS | 5 + 11 files changed, 497 insertions(+), 712 deletions(-) diff --git a/Doc/library/bz2.rst b/Doc/library/bz2.rst --- a/Doc/library/bz2.rst +++ b/Doc/library/bz2.rst @@ -120,6 +120,10 @@ .. versionchanged:: 3.4 The ``'x'`` (exclusive creation) mode was added. + .. versionchanged:: 3.5 + The :meth:`~io.BufferedIOBase.read` method now accepts an argument of + ``None``. + Incremental (de)compression --------------------------- diff --git a/Doc/library/gzip.rst b/Doc/library/gzip.rst --- a/Doc/library/gzip.rst +++ b/Doc/library/gzip.rst @@ -90,13 +90,9 @@ is no compression. The default is ``9``. The *mtime* argument is an optional numeric timestamp to be written to - the stream when compressing. All :program:`gzip` compressed streams are - required to contain a timestamp. If omitted or ``None``, the current - time is used. This module ignores the timestamp when decompressing; - however, some programs, such as :program:`gunzip`\ , make use of it. - The format of the timestamp is the same as that of the return value of - ``time.time()`` and of the ``st_mtime`` attribute of the object returned - by ``os.stat()``. + the last modification time field in the stream when compressing. It + should only be provided in compression mode. If omitted or ``None``, the + current time is used. See the :attr:`mtime` attribute for more details. Calling a :class:`GzipFile` object's :meth:`close` method does not close *fileobj*, since you might wish to append more material after the compressed @@ -108,9 +104,9 @@ including iteration and the :keyword:`with` statement. Only the :meth:`truncate` method isn't implemented. - :class:`GzipFile` also provides the following method: + :class:`GzipFile` also provides the following method and attribute: - .. method:: peek([n]) + .. method:: peek(n) Read *n* uncompressed bytes without advancing the file position. At most one single read on the compressed stream is done to satisfy @@ -124,9 +120,21 @@ .. versionadded:: 3.2 + .. attribute:: mtime + + When decompressing, the value of the last modification time field in + the most recently read header may be read from this attribute, as an + integer. The initial value before reading any headers is ``None``. + + All :program:`gzip` compressed streams are required to contain this + timestamp field. Some programs, such as :program:`gunzip`\ , make use + of the timestamp. The format is the same as the return value of + :func:`time.time` and the :attr:`~os.stat_result.st_mtime` attribute of + the object returned by :func:`os.stat`. + .. versionchanged:: 3.1 Support for the :keyword:`with` statement was added, along with the - *mtime* argument. + *mtime* constructor argument and :attr:`mtime` attribute. .. versionchanged:: 3.2 Support for zero-padded and unseekable files was added. @@ -140,6 +148,8 @@ .. versionchanged:: 3.5 Added support for writing arbitrary :term:`bytes-like objects `. + The :meth:`~io.BufferedIOBase.read` method now accepts an argument of + ``None``. .. function:: compress(data, compresslevel=9) diff --git a/Doc/library/lzma.rst b/Doc/library/lzma.rst --- a/Doc/library/lzma.rst +++ b/Doc/library/lzma.rst @@ -110,6 +110,10 @@ .. versionchanged:: 3.4 Added support for the ``"x"`` and ``"xb"`` modes. + .. versionchanged:: 3.5 + The :meth:`~io.BufferedIOBase.read` method now accepts an argument of + ``None``. + Compressing and decompressing data in memory -------------------------------------------- diff --git a/Lib/_compression.py b/Lib/_compression.py new file mode 100644 --- /dev/null +++ b/Lib/_compression.py @@ -0,0 +1,152 @@ +"""Internal classes used by the gzip, lzma and bz2 modules""" + +import io + + +BUFFER_SIZE = io.DEFAULT_BUFFER_SIZE # Compressed data read chunk size + + +class BaseStream(io.BufferedIOBase): + """Mode-checking helper functions.""" + + def _check_not_closed(self): + if self.closed: + raise ValueError("I/O operation on closed file") + + def _check_can_read(self): + if not self.readable(): + raise io.UnsupportedOperation("File not open for reading") + + def _check_can_write(self): + if not self.writable(): + raise io.UnsupportedOperation("File not open for writing") + + def _check_can_seek(self): + if not self.readable(): + raise io.UnsupportedOperation("Seeking is only supported " + "on files open for reading") + if not self.seekable(): + raise io.UnsupportedOperation("The underlying file object " + "does not support seeking") + + +class DecompressReader(io.RawIOBase): + """Adapts the decompressor API to a RawIOBase reader API""" + + def readable(self): + return True + + def __init__(self, fp, decomp_factory, trailing_error=(), **decomp_args): + self._fp = fp + self._eof = False + self._pos = 0 # Current offset in decompressed stream + + # Set to size of decompressed stream once it is known, for SEEK_END + self._size = -1 + + # Save the decompressor factory and arguments. + # If the file contains multiple compressed streams, each + # stream will need a separate decompressor object. A new decompressor + # object is also needed when implementing a backwards seek(). + self._decomp_factory = decomp_factory + self._decomp_args = decomp_args + self._decompressor = self._decomp_factory(**self._decomp_args) + + # Exception class to catch from decompressor signifying invalid + # trailing data to ignore + self._trailing_error = trailing_error + + def close(self): + self._decompressor = None + return super().close() + + def seekable(self): + return self._fp.seekable() + + def readinto(self, b): + with memoryview(b) as view, view.cast("B") as byte_view: + data = self.read(len(byte_view)) + byte_view[:len(data)] = data + return len(data) + + def read(self, size=-1): + if size < 0: + return self.readall() + + if not size or self._eof: + return b"" + data = None # Default if EOF is encountered + # Depending on the input data, our call to the decompressor may not + # return any data. In this case, try again after reading another block. + while True: + if self._decompressor.eof: + rawblock = (self._decompressor.unused_data or + self._fp.read(BUFFER_SIZE)) + if not rawblock: + break + # Continue to next stream. + self._decompressor = self._decomp_factory( + **self._decomp_args) + try: + data = self._decompressor.decompress(rawblock, size) + except self._trailing_error: + # Trailing data isn't a valid compressed stream; ignore it. + break + else: + if self._decompressor.needs_input: + rawblock = self._fp.read(BUFFER_SIZE) + if not rawblock: + raise EOFError("Compressed file ended before the " + "end-of-stream marker was reached") + else: + rawblock = b"" + data = self._decompressor.decompress(rawblock, size) + if data: + break + if not data: + self._eof = True + self._size = self._pos + return b"" + self._pos += len(data) + return data + + # Rewind the file to the beginning of the data stream. + def _rewind(self): + self._fp.seek(0) + self._eof = False + self._pos = 0 + self._decompressor = self._decomp_factory(**self._decomp_args) + + def seek(self, offset, whence=io.SEEK_SET): + # Recalculate offset as an absolute file position. + if whence == io.SEEK_SET: + pass + elif whence == io.SEEK_CUR: + offset = self._pos + offset + elif whence == io.SEEK_END: + # Seeking relative to EOF - we need to know the file's size. + if self._size < 0: + while self.read(io.DEFAULT_BUFFER_SIZE): + pass + offset = self._size + offset + else: + raise ValueError("Invalid value for whence: {}".format(whence)) + + # Make it so that offset is the number of bytes to skip forward. + if offset < self._pos: + self._rewind() + else: + offset -= self._pos + + # Read and discard data until we reach the desired position. + while offset > 0: + data = self.read(min(io.DEFAULT_BUFFER_SIZE, offset)) + if not data: + break + offset -= len(data) + + return self._pos + + def tell(self): + """Return the current file position.""" + return self._pos diff --git a/Lib/bz2.py b/Lib/bz2.py --- a/Lib/bz2.py +++ b/Lib/bz2.py @@ -12,6 +12,7 @@ from builtins import open as _builtin_open import io import warnings +import _compression try: from threading import RLock @@ -23,13 +24,11 @@ _MODE_CLOSED = 0 _MODE_READ = 1 -_MODE_READ_EOF = 2 +# Value 2 no longer used _MODE_WRITE = 3 -_BUFFER_SIZE = 8192 - -class BZ2File(io.BufferedIOBase): +class BZ2File(_compression.BaseStream): """A file object providing transparent bzip2 (de)compression. @@ -61,13 +60,11 @@ multiple compressed streams. """ # This lock must be recursive, so that BufferedIOBase's - # readline(), readlines() and writelines() don't deadlock. + # writelines() does not deadlock. self._lock = RLock() self._fp = None self._closefp = False self._mode = _MODE_CLOSED - self._pos = 0 - self._size = -1 if buffering is not None: warnings.warn("Use of 'buffering' argument is deprecated", @@ -79,9 +76,6 @@ if mode in ("", "r", "rb"): mode = "rb" mode_code = _MODE_READ - self._decompressor = BZ2Decompressor() - self._buffer = b"" - self._buffer_offset = 0 elif mode in ("w", "wb"): mode = "wb" mode_code = _MODE_WRITE @@ -107,6 +101,13 @@ else: raise TypeError("filename must be a str or bytes object, or a file") + if self._mode == _MODE_READ: + raw = _compression.DecompressReader(self._fp, + BZ2Decompressor, trailing_error=OSError) + self._buffer = io.BufferedReader(raw) + else: + self._pos = 0 + def close(self): """Flush and close the file. @@ -117,8 +118,8 @@ if self._mode == _MODE_CLOSED: return try: - if self._mode in (_MODE_READ, _MODE_READ_EOF): - self._decompressor = None + if self._mode == _MODE_READ: + self._buffer.close() elif self._mode == _MODE_WRITE: self._fp.write(self._compressor.flush()) self._compressor = None @@ -130,8 +131,7 @@ self._fp = None self._closefp = False self._mode = _MODE_CLOSED - self._buffer = b"" - self._buffer_offset = 0 + self._buffer = None @property def closed(self): @@ -145,125 +145,18 @@ def seekable(self): """Return whether the file supports seeking.""" - return self.readable() and self._fp.seekable() + return self.readable() and self._buffer.seekable() def readable(self): """Return whether the file was opened for reading.""" self._check_not_closed() - return self._mode in (_MODE_READ, _MODE_READ_EOF) + return self._mode == _MODE_READ def writable(self): """Return whether the file was opened for writing.""" self._check_not_closed() return self._mode == _MODE_WRITE - # Mode-checking helper functions. - - def _check_not_closed(self): - if self.closed: - raise ValueError("I/O operation on closed file") - - def _check_can_read(self): - if self._mode not in (_MODE_READ, _MODE_READ_EOF): - self._check_not_closed() - raise io.UnsupportedOperation("File not open for reading") - - def _check_can_write(self): - if self._mode != _MODE_WRITE: - self._check_not_closed() - raise io.UnsupportedOperation("File not open for writing") - - def _check_can_seek(self): - if self._mode not in (_MODE_READ, _MODE_READ_EOF): - self._check_not_closed() - raise io.UnsupportedOperation("Seeking is only supported " - "on files open for reading") - if not self._fp.seekable(): - raise io.UnsupportedOperation("The underlying file object " - "does not support seeking") - - # Fill the readahead buffer if it is empty. Returns False on EOF. - def _fill_buffer(self): - if self._mode == _MODE_READ_EOF: - return False - # Depending on the input data, our call to the decompressor may not - # return any data. In this case, try again after reading another block. - while self._buffer_offset == len(self._buffer): - rawblock = (self._decompressor.unused_data or - self._fp.read(_BUFFER_SIZE)) - - if not rawblock: - if self._decompressor.eof: - # End-of-stream marker and end of file. We're good. - self._mode = _MODE_READ_EOF - self._size = self._pos - return False - else: - # Problem - we were expecting more compressed data. - raise EOFError("Compressed file ended before the " - "end-of-stream marker was reached") - - if self._decompressor.eof: - # Continue to next stream. - self._decompressor = BZ2Decompressor() - try: - self._buffer = self._decompressor.decompress(rawblock) - except OSError: - # Trailing data isn't a valid bzip2 stream. We're done here. - self._mode = _MODE_READ_EOF - self._size = self._pos - return False - else: - self._buffer = self._decompressor.decompress(rawblock) - self._buffer_offset = 0 - return True - - # Read data until EOF. - # If return_data is false, consume the data without returning it. - def _read_all(self, return_data=True): - # The loop assumes that _buffer_offset is 0. Ensure that this is true. - self._buffer = self._buffer[self._buffer_offset:] - self._buffer_offset = 0 - - blocks = [] - while self._fill_buffer(): - if return_data: - blocks.append(self._buffer) - self._pos += len(self._buffer) - self._buffer = b"" - if return_data: - return b"".join(blocks) - - # Read a block of up to n bytes. - # If return_data is false, consume the data without returning it. - def _read_block(self, n, return_data=True): - # If we have enough data buffered, return immediately. - end = self._buffer_offset + n - if end <= len(self._buffer): - data = self._buffer[self._buffer_offset : end] - self._buffer_offset = end - self._pos += len(data) - return data if return_data else None - - # The loop assumes that _buffer_offset is 0. Ensure that this is true. - self._buffer = self._buffer[self._buffer_offset:] - self._buffer_offset = 0 - - blocks = [] - while n > 0 and self._fill_buffer(): - if n < len(self._buffer): - data = self._buffer[:n] - self._buffer_offset = n - else: - data = self._buffer - self._buffer = b"" - if return_data: - blocks.append(data) - self._pos += len(data) - n -= len(data) - if return_data: - return b"".join(blocks) - def peek(self, n=0): """Return buffered data without advancing the file position. @@ -272,9 +165,10 @@ """ with self._lock: self._check_can_read() - if not self._fill_buffer(): - return b"" - return self._buffer[self._buffer_offset:] + # Relies on the undocumented fact that BufferedReader.peek() + # always returns at least one byte (except at EOF), independent + # of the value of n + return self._buffer.peek(n) def read(self, size=-1): """Read up to size uncompressed bytes from the file. @@ -284,47 +178,29 @@ """ with self._lock: self._check_can_read() - if size == 0: - return b"" - elif size < 0: - return self._read_all() - else: - return self._read_block(size) + return self._buffer.read(size) def read1(self, size=-1): """Read up to size uncompressed bytes, while trying to avoid - making multiple reads from the underlying stream. + making multiple reads from the underlying stream. Reads up to a + buffer's worth of data if size is negative. Returns b'' if the file is at EOF. """ - # Usually, read1() calls _fp.read() at most once. However, sometimes - # this does not give enough data for the decompressor to make progress. - # In this case we make multiple reads, to avoid returning b"". with self._lock: self._check_can_read() - if (size == 0 or - # Only call _fill_buffer() if the buffer is actually empty. - # This gives a significant speedup if *size* is small. - (self._buffer_offset == len(self._buffer) and not self._fill_buffer())): - return b"" - if size > 0: - data = self._buffer[self._buffer_offset : - self._buffer_offset + size] - self._buffer_offset += len(data) - else: - data = self._buffer[self._buffer_offset:] - self._buffer = b"" - self._buffer_offset = 0 - self._pos += len(data) - return data + if size < 0: + size = io.DEFAULT_BUFFER_SIZE + return self._buffer.read1(size) def readinto(self, b): - """Read up to len(b) bytes into b. + """Read bytes into b. Returns the number of bytes read (0 for EOF). """ with self._lock: - return io.BufferedIOBase.readinto(self, b) + self._check_can_read() + return self._buffer.readinto(b) def readline(self, size=-1): """Read a line of uncompressed bytes from the file. @@ -339,15 +215,7 @@ size = size.__index__() with self._lock: self._check_can_read() - # Shortcut for the common case - the whole line is in the buffer. - if size < 0: - end = self._buffer.find(b"\n", self._buffer_offset) + 1 - if end > 0: - line = self._buffer[self._buffer_offset : end] - self._buffer_offset = end - self._pos += len(line) - return line - return io.BufferedIOBase.readline(self, size) + return self._buffer.readline(size) def readlines(self, size=-1): """Read a list of lines of uncompressed bytes from the file. @@ -361,7 +229,8 @@ raise TypeError("Integer argument expected") size = size.__index__() with self._lock: - return io.BufferedIOBase.readlines(self, size) + self._check_can_read() + return self._buffer.readlines(size) def write(self, data): """Write a byte string to the file. @@ -386,18 +255,9 @@ Line separators are not added between the written byte strings. """ with self._lock: - return io.BufferedIOBase.writelines(self, seq) + return _compression.BaseStream.writelines(self, seq) - # Rewind the file to the beginning of the data stream. - def _rewind(self): - self._fp.seek(0, 0) - self._mode = _MODE_READ - self._pos = 0 - self._decompressor = BZ2Decompressor() - self._buffer = b"" - self._buffer_offset = 0 - - def seek(self, offset, whence=0): + def seek(self, offset, whence=io.SEEK_SET): """Change the file position. The new position is specified by offset, relative to the @@ -414,35 +274,14 @@ """ with self._lock: self._check_can_seek() - - # Recalculate offset as an absolute file position. - if whence == 0: - pass - elif whence == 1: - offset = self._pos + offset - elif whence == 2: - # Seeking relative to EOF - we need to know the file's size. - if self._size < 0: - self._read_all(return_data=False) - offset = self._size + offset - else: - raise ValueError("Invalid value for whence: %s" % (whence,)) - - # Make it so that offset is the number of bytes to skip forward. - if offset < self._pos: - self._rewind() - else: - offset -= self._pos - - # Read and discard data until we reach the desired position. - self._read_block(offset, return_data=False) - - return self._pos + return self._buffer.seek(offset, whence) def tell(self): """Return the current file position.""" with self._lock: self._check_not_closed() + if self._mode == _MODE_READ: + return self._buffer.tell() return self._pos diff --git a/Lib/gzip.py b/Lib/gzip.py --- a/Lib/gzip.py +++ b/Lib/gzip.py @@ -9,6 +9,7 @@ import zlib import builtins import io +import _compression __all__ = ["GzipFile", "open", "compress", "decompress"] @@ -89,49 +90,35 @@ return self._buffer[read:] + \ self.file.read(size-self._length+read) - def prepend(self, prepend=b'', readprevious=False): + def prepend(self, prepend=b''): if self._read is None: self._buffer = prepend - elif readprevious and len(prepend) <= self._read: + else: # Assume data was read since the last prepend() call self._read -= len(prepend) return - else: - self._buffer = self._buffer[self._read:] + prepend self._length = len(self._buffer) self._read = 0 - def unused(self): - if self._read is None: - return b'' - return self._buffer[self._read:] - - def seek(self, offset, whence=0): - # This is only ever called with offset=whence=0 - if whence == 1 and self._read is not None: - if 0 <= offset + self._read <= self._length: - self._read += offset - return - else: - offset += self._length - self._read + def seek(self, off): self._read = None self._buffer = None - return self.file.seek(offset, whence) + return self.file.seek(off) - def __getattr__(self, name): - return getattr(self.file, name) + def seekable(self): + return True # Allows fast-forwarding even in unseekable streams - -class GzipFile(io.BufferedIOBase): +class GzipFile(_compression.BaseStream): """The GzipFile class simulates most of the methods of a file object with - the exception of the readinto() and truncate() methods. + the exception of the truncate() method. This class only supports opening files in binary mode. If you need to open a compressed file in text mode, use the gzip.open() function. """ + # Overridden with internal file object to be closed, if only a filename + # is passed in myfileobj = None - max_read_chunk = 10 * 1024 * 1024 # 10Mb def __init__(self, filename=None, mode=None, compresslevel=9, fileobj=None, mtime=None): @@ -163,13 +150,8 @@ at all. The default is 9. The mtime argument is an optional numeric timestamp to be written - to the stream when compressing. All gzip compressed streams - are required to contain a timestamp. If omitted or None, the - current time is used. This module ignores the timestamp when - decompressing; however, some programs, such as gunzip, make use - of it. The format of the timestamp is the same as that of the - return value of time.time() and of the st_mtime member of the - object returned by os.stat(). + to the last modification time field in the stream when compressing. + If omitted or None, the current time is used. """ @@ -188,18 +170,9 @@ if mode.startswith('r'): self.mode = READ - # Set flag indicating start of a new member - self._new_member = True - # Buffer data read from gzip file. extrastart is offset in - # stream where buffer starts. extrasize is number of - # bytes remaining in buffer from current stream position. - self.extrabuf = b"" - self.extrasize = 0 - self.extrastart = 0 + raw = _GzipReader(fileobj) + self._buffer = io.BufferedReader(raw) self.name = filename - # Starts small, scales exponentially - self.min_readsize = 100 - fileobj = _PaddedFile(fileobj) elif mode.startswith(('w', 'a', 'x')): self.mode = WRITE @@ -209,12 +182,11 @@ -zlib.MAX_WBITS, zlib.DEF_MEM_LEVEL, 0) + self._write_mtime = mtime else: raise ValueError("Invalid mode: {!r}".format(mode)) self.fileobj = fileobj - self.offset = 0 - self.mtime = mtime if self.mode == WRITE: self._write_gzip_header() @@ -227,26 +199,22 @@ return self.name + ".gz" return self.name + @property + def mtime(self): + """Last modification time read from stream, or None""" + return self._buffer.raw._last_mtime + def __repr__(self): - fileobj = self.fileobj - if isinstance(fileobj, _PaddedFile): - fileobj = fileobj.file - s = repr(fileobj) + s = repr(self.fileobj) return '' - def _check_closed(self): - """Raises a ValueError if the underlying file object has been closed. - - """ - if self.closed: - raise ValueError('I/O operation on closed file.') - def _init_write(self, filename): self.name = filename self.crc = zlib.crc32(b"") & 0xffffffff self.size = 0 self.writebuf = [] self.bufsize = 0 + self.offset = 0 # Current file offset for seek(), tell(), etc def _write_gzip_header(self): self.fileobj.write(b'\037\213') # magic header @@ -265,7 +233,7 @@ if fname: flags = FNAME self.fileobj.write(chr(flags).encode('latin-1')) - mtime = self.mtime + mtime = self._write_mtime if mtime is None: mtime = time.time() write32u(self.fileobj, int(mtime)) @@ -274,59 +242,8 @@ if fname: self.fileobj.write(fname + b'\000') - def _init_read(self): - self.crc = zlib.crc32(b"") & 0xffffffff - self.size = 0 - - def _read_exact(self, n): - data = self.fileobj.read(n) - while len(data) < n: - b = self.fileobj.read(n - len(data)) - if not b: - raise EOFError("Compressed file ended before the " - "end-of-stream marker was reached") - data += b - return data - - def _read_gzip_header(self): - magic = self.fileobj.read(2) - if magic == b'': - return False - - if magic != b'\037\213': - raise OSError('Not a gzipped file') - - method, flag, self.mtime = struct.unpack(" self.extrasize: - if not self._read(readsize): - if size > self.extrasize: - size = self.extrasize - break - readsize = min(self.max_read_chunk, readsize * 2) - - offset = self.offset - self.extrastart - chunk = self.extrabuf[offset: offset + size] - self.extrasize = self.extrasize - size - - self.offset += size - return chunk + return self._buffer.read(size) def read1(self, size=-1): - self._check_closed() + """Implements BufferedIOBase.read1() + + Reads up to a buffer's worth of data is size is negative.""" + self._check_not_closed() if self.mode != READ: import errno raise OSError(errno.EBADF, "read1() on write-only GzipFile object") - if self.extrasize <= 0 and self.fileobj is None: - return b'' - - # For certain input data, a single call to _read() may not return - # any data. In this case, retry until we get some data or reach EOF. - while self.extrasize <= 0 and self._read(): - pass - if size < 0 or size > self.extrasize: - size = self.extrasize - - offset = self.offset - self.extrastart - chunk = self.extrabuf[offset: offset + size] - self.extrasize -= size - self.offset += size - return chunk + if size < 0: + size = io.DEFAULT_BUFFER_SIZE + return self._buffer.read1(size) def peek(self, n): + self._check_not_closed() if self.mode != READ: import errno raise OSError(errno.EBADF, "peek() on write-only GzipFile object") - - # Do not return ridiculously small buffers, for one common idiom - # is to call peek(1) and expect more bytes in return. - if n < 100: - n = 100 - if self.extrasize == 0: - if self.fileobj is None: - return b'' - # Ensure that we don't return b"" if we haven't reached EOF. - # 1024 is the same buffering heuristic used in read() - while self.extrasize == 0 and self._read(max(n, 1024)): - pass - offset = self.offset - self.extrastart - remaining = self.extrasize - assert remaining == len(self.extrabuf) - offset - return self.extrabuf[offset:offset + n] - - def _unread(self, buf): - self.extrasize = len(buf) + self.extrasize - self.offset -= len(buf) - - def _read(self, size=1024): - if self.fileobj is None: - return False - - if self._new_member: - # If the _new_member flag is set, we have to - # jump to the next member, if there is one. - self._init_read() - if not self._read_gzip_header(): - return False - self.decompress = zlib.decompressobj(-zlib.MAX_WBITS) - self._new_member = False - - # Read a chunk of data from the file - buf = self.fileobj.read(size) - - # If the EOF has been reached, flush the decompression object - # and mark this object as finished. - - if buf == b"": - uncompress = self.decompress.flush() - # Prepend the already read bytes to the fileobj to they can be - # seen by _read_eof() - self.fileobj.prepend(self.decompress.unused_data, True) - self._read_eof() - self._add_read_data( uncompress ) - return False - - uncompress = self.decompress.decompress(buf) - self._add_read_data( uncompress ) - - if self.decompress.unused_data != b"": - # Ending case: we've come to the end of a member in the file, - # so seek back to the start of the unused data, finish up - # this member, and read a new gzip header. - # Prepend the already read bytes to the fileobj to they can be - # seen by _read_eof() and _read_gzip_header() - self.fileobj.prepend(self.decompress.unused_data, True) - # Check the CRC and file size, and set the flag so we read - # a new member on the next call - self._read_eof() - self._new_member = True - return True - - def _add_read_data(self, data): - self.crc = zlib.crc32(data, self.crc) & 0xffffffff - offset = self.offset - self.extrastart - self.extrabuf = self.extrabuf[offset:] + data - self.extrasize = self.extrasize + len(data) - self.extrastart = self.offset - self.size = self.size + len(data) - - def _read_eof(self): - # We've read to the end of the file - # We check the that the computed CRC and size of the - # uncompressed data matches the stored values. Note that the size - # stored is the true file size mod 2**32. - crc32, isize = struct.unpack(" 0: - self.extrasize -= i - offset - self.offset += i - offset - return self.extrabuf[offset: i] + return self.readall() + # size=0 is special because decompress(max_length=0) is not supported + if not size: + return b"" - size = sys.maxsize - readsize = self.min_readsize - else: - readsize = size - bufs = [] - while size != 0: - c = self.read(readsize) - i = c.find(b'\n') + # For certain input data, a single + # call to decompress() may not return + # any data. In this case, retry until we get some data or reach EOF. + while True: + if self._decompressor.eof: + # Ending case: we've come to the end of a member in the file, + # so finish up this member, and read a new gzip header. + # Check the CRC and file size, and set the flag so we read + # a new member + self._read_eof() + self._new_member = True + self._decompressor = self._decomp_factory( + **self._decomp_args) - # We set i=size to break out of the loop under two - # conditions: 1) there's no newline, and the chunk is - # larger than size, or 2) there is a newline, but the - # resulting line would be longer than 'size'. - if (size <= i) or (i == -1 and len(c) > size): - i = size - 1 + if self._new_member: + # If the _new_member flag is set, we have to + # jump to the next member, if there is one. + self._init_read() + if not self._read_gzip_header(): + self._size = self._pos + return b"" + self._new_member = False - if i >= 0 or c == b'': - bufs.append(c[:i + 1]) # Add portion of last chunk - self._unread(c[i + 1:]) # Push back rest of chunk + # Read a chunk of data from the file + buf = self._fp.read(io.DEFAULT_BUFFER_SIZE) + + uncompress = self._decompressor.decompress(buf, size) + if self._decompressor.unconsumed_tail != b"": + self._fp.prepend(self._decompressor.unconsumed_tail) + elif self._decompressor.unused_data != b"": + # Prepend the already read bytes to the fileobj so they can + # be seen by _read_eof() and _read_gzip_header() + self._fp.prepend(self._decompressor.unused_data) + + if uncompress != b"": break + if buf == b"": + raise EOFError("Compressed file ended before the " + "end-of-stream marker was reached") - # Append chunk to list, decrease 'size', - bufs.append(c) - size = size - len(c) - readsize = min(size, readsize * 2) - if readsize > self.min_readsize: - self.min_readsize = min(readsize, self.min_readsize * 2, 512) - return b''.join(bufs) # Return resulting line + self._add_read_data( uncompress ) + self._pos += len(uncompress) + return uncompress + def _add_read_data(self, data): + self._crc = zlib.crc32(data, self._crc) & 0xffffffff + self._stream_size = self._stream_size + len(data) + + def _read_eof(self): + # We've read to the end of the file + # We check the that the computed CRC and size of the + # uncompressed data matches the stored values. Note that the size + # stored is the true file size mod 2**32. + crc32, isize = struct.unpack(" 0 and self._fill_buffer(): - if n < len(self._buffer): - data = self._buffer[:n] - self._buffer_offset = n - else: - data = self._buffer - self._buffer = b"" - if return_data: - blocks.append(data) - self._pos += len(data) - n -= len(data) - if return_data: - return b"".join(blocks) - def peek(self, size=-1): """Return buffered data without advancing the file position. @@ -293,9 +184,9 @@ The exact number of bytes returned is unspecified. """ self._check_can_read() - if not self._fill_buffer(): - return b"" - return self._buffer[self._buffer_offset:] + # Relies on the undocumented fact that BufferedReader.peek() always + # returns at least one byte (except at EOF) + return self._buffer.peek(size) def read(self, size=-1): """Read up to size uncompressed bytes from the file. @@ -304,38 +195,19 @@ Returns b"" if the file is already at EOF. """ self._check_can_read() - if size == 0: - return b"" - elif size < 0: - return self._read_all() - else: - return self._read_block(size) + return self._buffer.read(size) def read1(self, size=-1): """Read up to size uncompressed bytes, while trying to avoid - making multiple reads from the underlying stream. + making multiple reads from the underlying stream. Reads up to a + buffer's worth of data if size is negative. Returns b"" if the file is at EOF. """ - # Usually, read1() calls _fp.read() at most once. However, sometimes - # this does not give enough data for the decompressor to make progress. - # In this case we make multiple reads, to avoid returning b"". self._check_can_read() - if (size == 0 or - # Only call _fill_buffer() if the buffer is actually empty. - # This gives a significant speedup if *size* is small. - (self._buffer_offset == len(self._buffer) and not self._fill_buffer())): - return b"" - if size > 0: - data = self._buffer[self._buffer_offset : - self._buffer_offset + size] - self._buffer_offset += len(data) - else: - data = self._buffer[self._buffer_offset:] - self._buffer = b"" - self._buffer_offset = 0 - self._pos += len(data) - return data + if size < 0: + size = io.DEFAULT_BUFFER_SIZE + return self._buffer.read1(size) def readline(self, size=-1): """Read a line of uncompressed bytes from the file. @@ -345,15 +217,7 @@ case the line may be incomplete). Returns b'' if already at EOF. """ self._check_can_read() - # Shortcut for the common case - the whole line is in the buffer. - if size < 0: - end = self._buffer.find(b"\n", self._buffer_offset) + 1 - if end > 0: - line = self._buffer[self._buffer_offset : end] - self._buffer_offset = end - self._pos += len(line) - return line - return io.BufferedIOBase.readline(self, size) + return self._buffer.readline(size) def write(self, data): """Write a bytes object to the file. @@ -368,16 +232,7 @@ self._pos += len(data) return len(data) - # Rewind the file to the beginning of the data stream. - def _rewind(self): - self._fp.seek(0, 0) - self._mode = _MODE_READ - self._pos = 0 - self._decompressor = LZMADecompressor(**self._init_args) - self._buffer = b"" - self._buffer_offset = 0 - - def seek(self, offset, whence=0): + def seek(self, offset, whence=io.SEEK_SET): """Change the file position. The new position is specified by offset, relative to the @@ -389,38 +244,17 @@ Returns the new file position. - Note that seeking is emulated, sp depending on the parameters, + Note that seeking is emulated, so depending on the parameters, this operation may be extremely slow. """ self._check_can_seek() - - # Recalculate offset as an absolute file position. - if whence == 0: - pass - elif whence == 1: - offset = self._pos + offset - elif whence == 2: - # Seeking relative to EOF - we need to know the file's size. - if self._size < 0: - self._read_all(return_data=False) - offset = self._size + offset - else: - raise ValueError("Invalid value for whence: {}".format(whence)) - - # Make it so that offset is the number of bytes to skip forward. - if offset < self._pos: - self._rewind() - else: - offset -= self._pos - - # Read and discard data until we reach the desired position. - self._read_block(offset, return_data=False) - - return self._pos + return self._buffer.seek(offset, whence) def tell(self): """Return the current file position.""" self._check_not_closed() + if self._mode == _MODE_READ: + return self._buffer.tell() return self._pos diff --git a/Lib/test/test_bz2.py b/Lib/test/test_bz2.py --- a/Lib/test/test_bz2.py +++ b/Lib/test/test_bz2.py @@ -2,7 +2,7 @@ from test.support import bigmemtest, _4G import unittest -from io import BytesIO +from io import BytesIO, DEFAULT_BUFFER_SIZE import os import pickle import glob @@ -10,6 +10,7 @@ import subprocess import sys from test.support import unlink +import _compression try: import threading @@ -110,7 +111,7 @@ def testRead(self): self.createTempFile() with BZ2File(self.filename) as bz2f: - self.assertRaises(TypeError, bz2f.read, None) + self.assertRaises(TypeError, bz2f.read, float()) self.assertEqual(bz2f.read(), self.TEXT) def testReadBadFile(self): @@ -121,21 +122,21 @@ def testReadMultiStream(self): self.createTempFile(streams=5) with BZ2File(self.filename) as bz2f: - self.assertRaises(TypeError, bz2f.read, None) + self.assertRaises(TypeError, bz2f.read, float()) self.assertEqual(bz2f.read(), self.TEXT * 5) def testReadMonkeyMultiStream(self): # Test BZ2File.read() on a multi-stream archive where a stream # boundary coincides with the end of the raw read buffer. - buffer_size = bz2._BUFFER_SIZE - bz2._BUFFER_SIZE = len(self.DATA) + buffer_size = _compression.BUFFER_SIZE + _compression.BUFFER_SIZE = len(self.DATA) try: self.createTempFile(streams=5) with BZ2File(self.filename) as bz2f: - self.assertRaises(TypeError, bz2f.read, None) + self.assertRaises(TypeError, bz2f.read, float()) self.assertEqual(bz2f.read(), self.TEXT * 5) finally: - bz2._BUFFER_SIZE = buffer_size + _compression.BUFFER_SIZE = buffer_size def testReadTrailingJunk(self): self.createTempFile(suffix=self.BAD_DATA) @@ -150,7 +151,7 @@ def testRead0(self): self.createTempFile() with BZ2File(self.filename) as bz2f: - self.assertRaises(TypeError, bz2f.read, None) + self.assertRaises(TypeError, bz2f.read, float()) self.assertEqual(bz2f.read(0), b"") def testReadChunk10(self): @@ -559,13 +560,24 @@ with BZ2File(str_filename, "rb") as f: self.assertEqual(f.read(), self.DATA) + def testDecompressLimited(self): + """Decompressed data buffering should be limited""" + bomb = bz2.compress(bytes(int(2e6)), compresslevel=9) + self.assertLess(len(bomb), _compression.BUFFER_SIZE) + + decomp = BZ2File(BytesIO(bomb)) + self.assertEqual(bytes(1), decomp.read(1)) + max_decomp = 1 + DEFAULT_BUFFER_SIZE + self.assertLessEqual(decomp._buffer.raw.tell(), max_decomp, + "Excessive amount of data was decompressed") + # Tests for a BZ2File wrapping another file object: def testReadBytesIO(self): with BytesIO(self.DATA) as bio: with BZ2File(bio) as bz2f: - self.assertRaises(TypeError, bz2f.read, None) + self.assertRaises(TypeError, bz2f.read, float()) self.assertEqual(bz2f.read(), self.TEXT) self.assertFalse(bio.closed) diff --git a/Lib/test/test_gzip.py b/Lib/test/test_gzip.py --- a/Lib/test/test_gzip.py +++ b/Lib/test/test_gzip.py @@ -123,7 +123,10 @@ # Write to a file, open it for reading, then close it. self.test_write() f = gzip.GzipFile(self.filename, 'r') + fileobj = f.fileobj + self.assertFalse(fileobj.closed) f.close() + self.assertTrue(fileobj.closed) with self.assertRaises(ValueError): f.read(1) with self.assertRaises(ValueError): @@ -132,7 +135,10 @@ f.tell() # Open the file for writing, then close it. f = gzip.GzipFile(self.filename, 'w') + fileobj = f.fileobj + self.assertFalse(fileobj.closed) f.close() + self.assertTrue(fileobj.closed) with self.assertRaises(ValueError): f.write(b'') with self.assertRaises(ValueError): @@ -271,9 +277,10 @@ with gzip.GzipFile(self.filename, 'w', mtime = mtime) as fWrite: fWrite.write(data1) with gzip.GzipFile(self.filename) as fRead: + self.assertTrue(hasattr(fRead, 'mtime')) + self.assertIsNone(fRead.mtime) dataRead = fRead.read() self.assertEqual(dataRead, data1) - self.assertTrue(hasattr(fRead, 'mtime')) self.assertEqual(fRead.mtime, mtime) def test_metadata(self): @@ -416,6 +423,18 @@ with gzip.GzipFile(str_filename, "rb") as f: self.assertEqual(f.read(), data1 * 50) + def test_decompress_limited(self): + """Decompressed data buffering should be limited""" + bomb = gzip.compress(bytes(int(2e6)), compresslevel=9) + self.assertLess(len(bomb), io.DEFAULT_BUFFER_SIZE) + + bomb = io.BytesIO(bomb) + decomp = gzip.GzipFile(fileobj=bomb) + self.assertEqual(bytes(1), decomp.read(1)) + max_decomp = 1 + io.DEFAULT_BUFFER_SIZE + self.assertLessEqual(decomp._buffer.raw.tell(), max_decomp, + "Excessive amount of data was decompressed") + # Testing compress/decompress shortcut functions def test_compress(self): @@ -463,7 +482,7 @@ with gzip.open(self.filename, "wb") as f: f.write(data1) with gzip.open(self.filename, "rb") as f: - f.fileobj.prepend() + f._buffer.raw._fp.prepend() class TestOpen(BaseTest): def test_binary_modes(self): diff --git a/Lib/test/test_lzma.py b/Lib/test/test_lzma.py --- a/Lib/test/test_lzma.py +++ b/Lib/test/test_lzma.py @@ -1,4 +1,5 @@ -from io import BytesIO, UnsupportedOperation +import _compression +from io import BytesIO, UnsupportedOperation, DEFAULT_BUFFER_SIZE import os import pickle import random @@ -772,13 +773,13 @@ def test_read_multistream_buffer_size_aligned(self): # Test the case where a stream boundary coincides with the end # of the raw read buffer. - saved_buffer_size = lzma._BUFFER_SIZE - lzma._BUFFER_SIZE = len(COMPRESSED_XZ) + saved_buffer_size = _compression.BUFFER_SIZE + _compression.BUFFER_SIZE = len(COMPRESSED_XZ) try: with LZMAFile(BytesIO(COMPRESSED_XZ * 5)) as f: self.assertEqual(f.read(), INPUT * 5) finally: - lzma._BUFFER_SIZE = saved_buffer_size + _compression.BUFFER_SIZE = saved_buffer_size def test_read_trailing_junk(self): with LZMAFile(BytesIO(COMPRESSED_XZ + COMPRESSED_BOGUS)) as f: @@ -829,7 +830,7 @@ with LZMAFile(BytesIO(), "w") as f: self.assertRaises(ValueError, f.read) with LZMAFile(BytesIO(COMPRESSED_XZ)) as f: - self.assertRaises(TypeError, f.read, None) + self.assertRaises(TypeError, f.read, float()) def test_read_bad_data(self): with LZMAFile(BytesIO(COMPRESSED_BOGUS)) as f: @@ -925,6 +926,17 @@ with LZMAFile(BytesIO(COMPRESSED_XZ)) as f: self.assertListEqual(f.readlines(), lines) + def test_decompress_limited(self): + """Decompressed data buffering should be limited""" + bomb = lzma.compress(bytes(int(2e6)), preset=6) + self.assertLess(len(bomb), _compression.BUFFER_SIZE) + + decomp = LZMAFile(BytesIO(bomb)) + self.assertEqual(bytes(1), decomp.read(1)) + max_decomp = 1 + DEFAULT_BUFFER_SIZE + self.assertLessEqual(decomp._buffer.raw.tell(), max_decomp, + "Excessive amount of data was decompressed") + def test_write(self): with BytesIO() as dst: with LZMAFile(dst, "w") as f: @@ -1090,7 +1102,8 @@ self.assertRaises(ValueError, f.seek, 0) with LZMAFile(BytesIO(COMPRESSED_XZ)) as f: self.assertRaises(ValueError, f.seek, 0, 3) - self.assertRaises(ValueError, f.seek, 9, ()) + # io.BufferedReader raises TypeError instead of ValueError + self.assertRaises((TypeError, ValueError), f.seek, 9, ()) self.assertRaises(TypeError, f.seek, None) self.assertRaises(TypeError, f.seek, b"derp") diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -19,6 +19,11 @@ Library ------- +- Issue #23529: Limit the size of decompressed data when reading from + GzipFile, BZ2File or LZMAFile. This defeats denial of service attacks + using compressed bombs (i.e. compressed payloads which decompress to a huge + size). Patch by Martin Panter and Nikolaus Rath. + - Issue #21859: Added Python implementation of io.FileIO. - Issue #23865: close() methods in multiple modules now are idempotent and more -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Apr 11 00:40:29 2015 From: python-checkins at python.org (benjamin.peterson) Date: Fri, 10 Apr 2015 22:40:29 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_highlight_is_n?= =?utf-8?q?ow_highlighted_=28closes_=2323909=29?= Message-ID: <20150410224029.21311.66712@psf.io> https://hg.python.org/cpython/rev/89d47911209b changeset: 95536:89d47911209b branch: 2.7 parent: 95534:350c78a92046 user: Benjamin Peterson date: Fri Apr 10 18:40:21 2015 -0400 summary: highlight is now highlighted (closes #23909) files: Doc/tools/static/basic.css | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/tools/static/basic.css b/Doc/tools/static/basic.css --- a/Doc/tools/static/basic.css +++ b/Doc/tools/static/basic.css @@ -306,7 +306,7 @@ margin-left: 30px; } -dt:target, .highlight { +dt:target, .highlighted { background-color: #fbe54e; } -- Repository URL: https://hg.python.org/cpython From solipsis at pitrou.net Sat Apr 11 10:49:13 2015 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Sat, 11 Apr 2015 08:49:13 +0000 Subject: [Python-checkins] Daily reference leaks (62723172412c): sum=3 Message-ID: <20150411084913.62499.5939@psf.io> results for 62723172412c on branch "default" -------------------------------------------- test_functools leaked [0, 0, 3] memory blocks, sum=3 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflognJPAZ_', '--timeout', '7200'] From python-checkins at python.org Sat Apr 11 13:44:51 2015 From: python-checkins at python.org (benjamin.peterson) Date: Sat, 11 Apr 2015 11:44:51 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E4=29=3A_use_imperative?= Message-ID: <20150411114451.21303.24869@psf.io> https://hg.python.org/cpython/rev/2d7a4121a0c8 changeset: 95537:2d7a4121a0c8 branch: 3.4 parent: 95531:4232eb53a036 user: Benjamin Peterson date: Sat Apr 11 07:42:42 2015 -0400 summary: use imperative files: Doc/library/ssl.rst | 14 +++++++------- 1 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Doc/library/ssl.rst b/Doc/library/ssl.rst --- a/Doc/library/ssl.rst +++ b/Doc/library/ssl.rst @@ -286,7 +286,7 @@ .. function:: RAND_bytes(num) - Returns *num* cryptographically strong pseudo-random bytes. Raises an + Return *num* cryptographically strong pseudo-random bytes. Raises an :class:`SSLError` if the PRNG has not been seeded with enough data or if the operation is not supported by the current RAND method. :func:`RAND_status` can be used to check the status of the PRNG and :func:`RAND_add` can be used @@ -303,7 +303,7 @@ .. function:: RAND_pseudo_bytes(num) - Returns (bytes, is_cryptographic): bytes are *num* pseudo-random bytes, + Return (bytes, is_cryptographic): bytes are *num* pseudo-random bytes, is_cryptographic is ``True`` if the bytes generated are cryptographically strong. Raises an :class:`SSLError` if the operation is not supported by the current RAND method. @@ -319,10 +319,10 @@ .. function:: RAND_status() - Returns ``True`` if the SSL pseudo-random number generator has been seeded with - 'enough' randomness, and ``False`` otherwise. You can use :func:`ssl.RAND_egd` - and :func:`ssl.RAND_add` to increase the randomness of the pseudo-random - number generator. + Return ``True`` if the SSL pseudo-random number generator has been seeded + with 'enough' randomness, and ``False`` otherwise. You can use + :func:`ssl.RAND_egd` and :func:`ssl.RAND_add` to increase the randomness of + the pseudo-random number generator. .. function:: RAND_egd(path) @@ -337,7 +337,7 @@ .. function:: RAND_add(bytes, entropy) - Mixes the given *bytes* into the SSL pseudo-random number generator. The + Mix the given *bytes* into the SSL pseudo-random number generator. The parameter *entropy* (a float) is a lower bound on the entropy contained in string (so you can always use :const:`0.0`). See :rfc:`1750` for more information on sources of entropy. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Apr 11 13:44:51 2015 From: python-checkins at python.org (benjamin.peterson) Date: Sat, 11 Apr 2015 11:44:51 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?b?KTogbWVyZ2UgMy40?= Message-ID: <20150411114451.21081.57266@psf.io> https://hg.python.org/cpython/rev/b60f42842f30 changeset: 95539:b60f42842f30 parent: 95535:62723172412c parent: 95537:2d7a4121a0c8 user: Benjamin Peterson date: Sat Apr 11 07:44:45 2015 -0400 summary: merge 3.4 files: Doc/library/ssl.rst | 14 +++++++------- 1 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Doc/library/ssl.rst b/Doc/library/ssl.rst --- a/Doc/library/ssl.rst +++ b/Doc/library/ssl.rst @@ -286,7 +286,7 @@ .. function:: RAND_bytes(num) - Returns *num* cryptographically strong pseudo-random bytes. Raises an + Return *num* cryptographically strong pseudo-random bytes. Raises an :class:`SSLError` if the PRNG has not been seeded with enough data or if the operation is not supported by the current RAND method. :func:`RAND_status` can be used to check the status of the PRNG and :func:`RAND_add` can be used @@ -303,7 +303,7 @@ .. function:: RAND_pseudo_bytes(num) - Returns (bytes, is_cryptographic): bytes are *num* pseudo-random bytes, + Return (bytes, is_cryptographic): bytes are *num* pseudo-random bytes, is_cryptographic is ``True`` if the bytes generated are cryptographically strong. Raises an :class:`SSLError` if the operation is not supported by the current RAND method. @@ -321,10 +321,10 @@ .. function:: RAND_status() - Returns ``True`` if the SSL pseudo-random number generator has been seeded with - 'enough' randomness, and ``False`` otherwise. You can use :func:`ssl.RAND_egd` - and :func:`ssl.RAND_add` to increase the randomness of the pseudo-random - number generator. + Return ``True`` if the SSL pseudo-random number generator has been seeded + with 'enough' randomness, and ``False`` otherwise. You can use + :func:`ssl.RAND_egd` and :func:`ssl.RAND_add` to increase the randomness of + the pseudo-random number generator. .. function:: RAND_egd(path) @@ -341,7 +341,7 @@ .. function:: RAND_add(bytes, entropy) - Mixes the given *bytes* into the SSL pseudo-random number generator. The + Mix the given *bytes* into the SSL pseudo-random number generator. The parameter *entropy* (a float) is a lower bound on the entropy contained in string (so you can always use :const:`0.0`). See :rfc:`1750` for more information on sources of entropy. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Apr 11 13:44:52 2015 From: python-checkins at python.org (benjamin.peterson) Date: Sat, 11 Apr 2015 11:44:52 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_use_imperative?= Message-ID: <20150411114451.41560.65196@psf.io> https://hg.python.org/cpython/rev/c7a6a11a5013 changeset: 95538:c7a6a11a5013 branch: 2.7 parent: 95536:89d47911209b user: Benjamin Peterson date: Sat Apr 11 07:42:42 2015 -0400 summary: use imperative files: Doc/library/ssl.rst | 10 +++++----- 1 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Doc/library/ssl.rst b/Doc/library/ssl.rst --- a/Doc/library/ssl.rst +++ b/Doc/library/ssl.rst @@ -286,10 +286,10 @@ .. function:: RAND_status() - Returns ``True`` if the SSL pseudo-random number generator has been seeded with - 'enough' randomness, and ``False`` otherwise. You can use :func:`ssl.RAND_egd` - and :func:`ssl.RAND_add` to increase the randomness of the pseudo-random - number generator. + Return ``True`` if the SSL pseudo-random number generator has been seeded + with 'enough' randomness, and ``False`` otherwise. You can use + :func:`ssl.RAND_egd` and :func:`ssl.RAND_add` to increase the randomness of + the pseudo-random number generator. .. function:: RAND_egd(path) @@ -306,7 +306,7 @@ .. function:: RAND_add(bytes, entropy) - Mixes the given *bytes* into the SSL pseudo-random number generator. The + Mix the given *bytes* into the SSL pseudo-random number generator. The parameter *entropy* (a float) is a lower bound on the entropy contained in string (so you can always use :const:`0.0`). See :rfc:`1750` for more information on sources of entropy. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Apr 11 13:59:19 2015 From: python-checkins at python.org (berker.peksag) Date: Sat, 11 Apr 2015 11:59:19 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzIzOTEy?= =?utf-8?q?=3A_Fix_code_formatting_in_datamodel=2Erst=2E?= Message-ID: <20150411115919.804.71652@psf.io> https://hg.python.org/cpython/rev/714b7b684610 changeset: 95540:714b7b684610 branch: 3.4 parent: 95537:2d7a4121a0c8 user: Berker Peksag date: Sat Apr 11 14:59:30 2015 +0300 summary: Issue #23912: Fix code formatting in datamodel.rst. Patch by James Edwards. files: Doc/reference/datamodel.rst | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Doc/reference/datamodel.rst b/Doc/reference/datamodel.rst --- a/Doc/reference/datamodel.rst +++ b/Doc/reference/datamodel.rst @@ -2222,9 +2222,9 @@ :meth:`__getattribute__` method even of the object's metaclass:: >>> class Meta(type): - ... def __getattribute__(*args): - ... print("Metaclass getattribute invoked") - ... return type.__getattribute__(*args) + ... def __getattribute__(*args): + ... print("Metaclass getattribute invoked") + ... return type.__getattribute__(*args) ... >>> class C(object, metaclass=Meta): ... def __len__(self): -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Apr 11 13:59:19 2015 From: python-checkins at python.org (berker.peksag) Date: Sat, 11 Apr 2015 11:59:19 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2323912=3A_Fix_code_formatting_in_datamodel=2Erst?= =?utf-8?q?=2E?= Message-ID: <20150411115919.62521.77539@psf.io> https://hg.python.org/cpython/rev/5cd072882051 changeset: 95541:5cd072882051 parent: 95539:b60f42842f30 parent: 95540:714b7b684610 user: Berker Peksag date: Sat Apr 11 14:59:50 2015 +0300 summary: Issue #23912: Fix code formatting in datamodel.rst. Patch by James Edwards. files: Doc/reference/datamodel.rst | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Doc/reference/datamodel.rst b/Doc/reference/datamodel.rst --- a/Doc/reference/datamodel.rst +++ b/Doc/reference/datamodel.rst @@ -2226,9 +2226,9 @@ :meth:`__getattribute__` method even of the object's metaclass:: >>> class Meta(type): - ... def __getattribute__(*args): - ... print("Metaclass getattribute invoked") - ... return type.__getattribute__(*args) + ... def __getattribute__(*args): + ... print("Metaclass getattribute invoked") + ... return type.__getattribute__(*args) ... >>> class C(object, metaclass=Meta): ... def __len__(self): -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Apr 11 18:40:25 2015 From: python-checkins at python.org (ethan.furman) Date: Sat, 11 Apr 2015 16:40:25 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue23826=3A_fix_doc_test?= =?utf-8?q?_for_-OO_runs?= Message-ID: <20150411164025.21075.68294@psf.io> https://hg.python.org/cpython/rev/a5530207b003 changeset: 95542:a5530207b003 user: Ethan Furman date: Sat Apr 11 09:39:59 2015 -0700 summary: Issue23826: fix doc test for -OO runs files: Lib/test/test_enum.py | 39 +++++++++++++++++++++++++++--- 1 files changed, 35 insertions(+), 4 deletions(-) diff --git a/Lib/test/test_enum.py b/Lib/test/test_enum.py --- a/Lib/test/test_enum.py +++ b/Lib/test/test_enum.py @@ -1556,7 +1556,7 @@ turkey = 3 -expected_help_output = """ +expected_help_output_with_docs = """\ Help on class Color in module %s: class Color(enum.Enum) @@ -1593,8 +1593,36 @@ | Returns a mapping of member name->value. |\x20\x20\x20\x20\x20\x20 | This mapping lists all enum members, including aliases. Note that this - | is a read-only view of the internal mapping. -""".strip() + | is a read-only view of the internal mapping.""" + +expected_help_output_without_docs = """\ +Help on class Color in module %s: + +class Color(enum.Enum) + | Method resolution order: + | Color + | enum.Enum + | builtins.object + |\x20\x20 + | Data and other attributes defined here: + |\x20\x20 + | blue = + |\x20\x20 + | green = + |\x20\x20 + | red = + |\x20\x20 + | ---------------------------------------------------------------------- + | Data descriptors inherited from enum.Enum: + |\x20\x20 + | name + |\x20\x20 + | value + |\x20\x20 + | ---------------------------------------------------------------------- + | Data descriptors inherited from enum.EnumMeta: + |\x20\x20 + | __members__""" class TestStdLib(unittest.TestCase): @@ -1605,7 +1633,10 @@ def test_pydoc(self): # indirectly test __objclass__ - expected_text = expected_help_output % __name__ + if StrEnum.__doc__ is None: + expected_text = expected_help_output_without_docs % __name__ + else: + expected_text = expected_help_output_with_docs % __name__ output = StringIO() helper = pydoc.Helper(output=output) helper(self.Color) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Apr 11 23:46:07 2015 From: python-checkins at python.org (guido.van.rossum) Date: Sat, 11 Apr 2015 21:46:07 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E4=29=3A_Unittest_for_I?= =?utf-8?q?ssue_21511_by_Christie_Wilson_bobcatfish=40gmail=2Ecom=2E?= Message-ID: <20150411214607.113199.77324@psf.io> https://hg.python.org/cpython/rev/2582962ccf17 changeset: 95543:2582962ccf17 branch: 3.4 parent: 95540:714b7b684610 user: Guido van Rossum date: Sat Apr 11 17:44:01 2015 -0400 summary: Unittest for Issue 21511 by Christie Wilson bobcatfish at gmail.com. files: Lib/test/test_quopri.py | 7 +++++++ 1 files changed, 7 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_quopri.py b/Lib/test/test_quopri.py --- a/Lib/test/test_quopri.py +++ b/Lib/test/test_quopri.py @@ -138,6 +138,13 @@ self.assertEqual(quopri.decodestring(e), p) @withpythonimplementation + def test_decodestring_double_equals(self): + # Issue 21511 - Ensure that byte string is compared to byte string + # instead of int byte value + decoded_value, encoded_value = (b"123=four", b"123==four") + self.assertEqual(quopri.decodestring(encoded_value), decoded_value) + + @withpythonimplementation def test_idempotent_string(self): for p, e in self.STRINGS: self.assertEqual(quopri.decodestring(quopri.encodestring(e)), e) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Apr 11 23:46:07 2015 From: python-checkins at python.org (guido.van.rossum) Date: Sat, 11 Apr 2015 21:46:07 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Unittest_for_Issue_21511_by_Christie_Wilson_bobcatfish?= =?utf-8?q?=40gmail=2Ecom_=28merge_from?= Message-ID: <20150411214607.37460.79535@psf.io> https://hg.python.org/cpython/rev/23d37a147051 changeset: 95544:23d37a147051 parent: 95542:a5530207b003 parent: 95543:2582962ccf17 user: Guido van Rossum date: Sat Apr 11 17:45:56 2015 -0400 summary: Unittest for Issue 21511 by Christie Wilson bobcatfish at gmail.com (merge from 3.4). files: Lib/test/test_quopri.py | 7 +++++++ 1 files changed, 7 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_quopri.py b/Lib/test/test_quopri.py --- a/Lib/test/test_quopri.py +++ b/Lib/test/test_quopri.py @@ -138,6 +138,13 @@ self.assertEqual(quopri.decodestring(e), p) @withpythonimplementation + def test_decodestring_double_equals(self): + # Issue 21511 - Ensure that byte string is compared to byte string + # instead of int byte value + decoded_value, encoded_value = (b"123=four", b"123==four") + self.assertEqual(quopri.decodestring(encoded_value), decoded_value) + + @withpythonimplementation def test_idempotent_string(self): for p, e in self.STRINGS: self.assertEqual(quopri.decodestring(quopri.encodestring(e)), e) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Apr 12 00:08:43 2015 From: python-checkins at python.org (antoine.pitrou) Date: Sat, 11 Apr 2015 22:08:43 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Close_=2323904=3A_fix_pathlib_documentation_misleadingly?= =?utf-8?q?_mentioning_that_bytes?= Message-ID: <20150411220843.21083.60959@psf.io> https://hg.python.org/cpython/rev/386732087dfb changeset: 95546:386732087dfb parent: 95544:23d37a147051 parent: 95545:7463c06f6e87 user: Antoine Pitrou date: Sun Apr 12 00:08:35 2015 +0200 summary: Close #23904: fix pathlib documentation misleadingly mentioning that bytes objects are accepted in the PurePath constructor files: Doc/library/pathlib.rst | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/library/pathlib.rst b/Doc/library/pathlib.rst --- a/Doc/library/pathlib.rst +++ b/Doc/library/pathlib.rst @@ -106,8 +106,8 @@ >>> PurePath('setup.py') # Running on a Unix machine PurePosixPath('setup.py') - Each element of *pathsegments* can be either a string or bytes object - representing a path segment; it can also be another path object:: + Each element of *pathsegments* can be either a string representing a + path segment, or another path object:: >>> PurePath('foo', 'some/path', 'bar') PurePosixPath('foo/some/path/bar') -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Apr 12 00:08:43 2015 From: python-checkins at python.org (antoine.pitrou) Date: Sat, 11 Apr 2015 22:08:43 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogQ2xvc2UgIzIzOTA0?= =?utf-8?q?=3A_fix_pathlib_documentation_misleadingly_mentioning_that_byte?= =?utf-8?q?s?= Message-ID: <20150411220843.62501.40161@psf.io> https://hg.python.org/cpython/rev/7463c06f6e87 changeset: 95545:7463c06f6e87 branch: 3.4 parent: 95543:2582962ccf17 user: Antoine Pitrou date: Sun Apr 12 00:08:02 2015 +0200 summary: Close #23904: fix pathlib documentation misleadingly mentioning that bytes objects are accepted in the PurePath constructor files: Doc/library/pathlib.rst | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/library/pathlib.rst b/Doc/library/pathlib.rst --- a/Doc/library/pathlib.rst +++ b/Doc/library/pathlib.rst @@ -106,8 +106,8 @@ >>> PurePath('setup.py') # Running on a Unix machine PurePosixPath('setup.py') - Each element of *pathsegments* can be either a string or bytes object - representing a path segment; it can also be another path object:: + Each element of *pathsegments* can be either a string representing a + path segment, or another path object:: >>> PurePath('foo', 'some/path', 'bar') PurePosixPath('foo/some/path/bar') -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Apr 12 00:14:04 2015 From: python-checkins at python.org (matthias.klose) Date: Sat, 11 Apr 2015 22:14:04 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A__-_Modules/Setup=2Edist=3A?= =?utf-8?q?_remove_time_extension_duplicate=2C_introduced_by_the_fix?= Message-ID: <20150411221404.41556.37795@psf.io> https://hg.python.org/cpython/rev/fc28c67fbbd3 changeset: 95547:fc28c67fbbd3 user: doko at ubuntu.com date: Sun Apr 12 00:13:52 2015 +0200 summary: - Modules/Setup.dist: remove time extension duplicate, introduced by the fix for #5309. files: Modules/Setup.dist | 3 +-- 1 files changed, 1 insertions(+), 2 deletions(-) diff --git a/Modules/Setup.dist b/Modules/Setup.dist --- a/Modules/Setup.dist +++ b/Modules/Setup.dist @@ -118,7 +118,7 @@ itertools itertoolsmodule.c # Functions creating iterators for efficient looping atexit atexitmodule.c # Register functions to be run at interpreter-shutdown _stat _stat.c # stat.h interface -time timemodule.c # time module +time timemodule.c # -lm # time operations and variables # access to ISO C locale support _locale _localemodule.c # -lintl @@ -172,7 +172,6 @@ #cmath cmathmodule.c _math.c # -lm # complex math library functions #math mathmodule.c _math.c # -lm # math library functions, e.g. sin() #_struct _struct.c # binary structure packing/unpacking -#time timemodule.c # -lm # time operations and variables #_weakref _weakref.c # basic weak reference support #_testcapi _testcapimodule.c # Python C API test module #_random _randommodule.c # Random number generator -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Apr 12 01:01:15 2015 From: python-checkins at python.org (ned.deily) Date: Sat, 11 Apr 2015 23:01:15 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2323817=3A_run_auto?= =?utf-8?q?reconf_to_update_configure=2E?= Message-ID: <20150411230114.62521.43424@psf.io> https://hg.python.org/cpython/rev/0b3027a2abbc changeset: 95548:0b3027a2abbc user: Ned Deily date: Sat Apr 11 16:00:38 2015 -0700 summary: Issue #23817: run autoreconf to update configure. files: configure | 5 ----- 1 files changed, 0 insertions(+), 5 deletions(-) diff --git a/configure b/configure --- a/configure +++ b/configure @@ -5654,11 +5654,6 @@ LDLIBRARY='libpython$(LDVERSION).so' BLDLIBRARY='-L. -lpython$(LDVERSION)' RUNSHARED=LD_LIBRARY_PATH=`pwd`${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}} - case $ac_sys_system in - FreeBSD*) - SOVERSION=`echo $SOVERSION|cut -d "." -f 1` - ;; - esac INSTSONAME="$LDLIBRARY".$SOVERSION if test "$with_pydebug" != yes then -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Apr 12 02:03:59 2015 From: python-checkins at python.org (matthias.klose) Date: Sun, 12 Apr 2015 00:03:59 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A__-_fix_file_permission_for?= =?utf-8?q?_Lib/test/test=5Fscript=5Fhelper=2Epy?= Message-ID: <20150412000359.21095.57320@psf.io> https://hg.python.org/cpython/rev/d8eca0a96a9e changeset: 95549:d8eca0a96a9e user: doko at ubuntu.com date: Sun Apr 12 02:03:50 2015 +0200 summary: - fix file permission for Lib/test/test_script_helper.py files: Lib/test/test_script_helper.py | 0 1 files changed, 0 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_script_helper.py b/Lib/test/test_script_helper.py old mode 100755 new mode 100644 -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Apr 12 05:36:21 2015 From: python-checkins at python.org (steve.dower) Date: Sun, 12 Apr 2015 03:36:21 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Closes_=2323686=3A_Update_?= =?utf-8?q?Windows_installer_OpenSSL_to_1=2E0=2E2a?= Message-ID: <20150412033621.8613.19136@psf.io> https://hg.python.org/cpython/rev/1e64d57422ee changeset: 95550:1e64d57422ee user: Steve Dower date: Sat Apr 11 23:36:04 2015 -0400 summary: Closes #23686: Update Windows installer OpenSSL to 1.0.2a files: PCbuild/get_externals.bat | 2 +- PCbuild/libeay.vcxproj | 31 ++++++++++++++++++++------ PCbuild/python.props | 2 +- PCbuild/ssleay.vcxproj | 2 +- 4 files changed, 27 insertions(+), 10 deletions(-) diff --git a/PCbuild/get_externals.bat b/PCbuild/get_externals.bat --- a/PCbuild/get_externals.bat +++ b/PCbuild/get_externals.bat @@ -54,7 +54,7 @@ for %%e in ( bzip2-1.0.6 nasm-2.11.06 - openssl-1.0.1l + openssl-1.0.2a tcl-core-8.6.3.1 tk-8.6.3.1 tix-8.4.3.4 diff --git a/PCbuild/libeay.vcxproj b/PCbuild/libeay.vcxproj --- a/PCbuild/libeay.vcxproj +++ b/PCbuild/libeay.vcxproj @@ -181,9 +181,7 @@ - + @@ -271,6 +271,7 @@ --> + @@ -334,12 +335,14 @@ --> + + + - - diff --git a/PCbuild/ssleay.vcxproj b/PCbuild/ssleay.vcxproj --- a/PCbuild/ssleay.vcxproj +++ b/PCbuild/ssleay.vcxproj @@ -56,8 +56,8 @@ - - + -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Apr 14 18:02:22 2015 From: python-checkins at python.org (berker.peksag) Date: Tue, 14 Apr 2015 16:02:22 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzIzODEx?= =?utf-8?q?=3A_Add_missing_newline_to_the_PyCompileError_error_message=2E?= Message-ID: <20150414160221.814.37964@psf.io> https://hg.python.org/cpython/rev/22790c4f3b16 changeset: 95644:22790c4f3b16 branch: 2.7 parent: 95636:31c8b57f1197 user: Berker Peksag date: Tue Apr 14 19:03:06 2015 +0300 summary: Issue #23811: Add missing newline to the PyCompileError error message. Patch by Alex Shkop. files: Lib/py_compile.py | 2 +- Misc/NEWS | 3 +++ 2 files changed, 4 insertions(+), 1 deletions(-) diff --git a/Lib/py_compile.py b/Lib/py_compile.py --- a/Lib/py_compile.py +++ b/Lib/py_compile.py @@ -163,7 +163,7 @@ except PyCompileError as error: # return value to indicate at least one failure rv = 1 - sys.stderr.write(error.msg) + sys.stderr.write("%s\n" % error.msg) return rv if __name__ == "__main__": diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -21,6 +21,9 @@ Library ------- +- Issue #23811: Add missing newline to the PyCompileError error message. + Patch by Alex Shkop. + - Issue #17898: Fix exception in gettext.py when parsing certain plural forms. - Issue #23865: close() methods in multiple modules now are idempotent and more -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Apr 14 18:24:03 2015 From: python-checkins at python.org (brett.cannon) Date: Tue, 14 Apr 2015 16:24:03 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_Fix_syntax_error?= Message-ID: <20150414162403.26878.44357@psf.io> https://hg.python.org/peps/rev/09228a7fe574 changeset: 5754:09228a7fe574 user: Brett Cannon date: Tue Apr 14 12:23:59 2015 -0400 summary: Fix syntax error files: pep-0474.txt | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) diff --git a/pep-0474.txt b/pep-0474.txt --- a/pep-0474.txt +++ b/pep-0474.txt @@ -142,7 +142,8 @@ Even with its current workflow, CPython itself remains one of the largest open source projects in the world (in the -`top 2% ` +`top 2% +`__ of projects tracked on OpenHub). Unfortunately, we have been significantly less effective at encouraging contributions to the projects that make up CPython's workflow infrastructure, including ensuring that our installations -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Tue Apr 14 18:38:44 2015 From: python-checkins at python.org (brett.cannon) Date: Tue, 14 Apr 2015 16:38:44 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_Fix_syntax_error?= Message-ID: <20150414163844.26878.59322@psf.io> https://hg.python.org/peps/rev/3a9c67a4f65f changeset: 5755:3a9c67a4f65f user: Brett Cannon date: Tue Apr 14 12:38:41 2015 -0400 summary: Fix syntax error files: pep-0474.txt | 9 ++++----- 1 files changed, 4 insertions(+), 5 deletions(-) diff --git a/pep-0474.txt b/pep-0474.txt --- a/pep-0474.txt +++ b/pep-0474.txt @@ -177,11 +177,10 @@ in deploying Kallithea using the PSF's Salt based infrastructure automation. * Graham Dumpleton and I have been working on `making it easy - - `__ to deploy - demonstration Kallithea instances to the free tier of Red Hat's open source - hosting service, OpenShift Online. (See the comments on that post, or the - `quickstart issue tracker + `__ + to deploy demonstration Kallithea instances to the free tier of Red Hat's open + source hosting service, OpenShift Online. (See the comments on that post, or + the `quickstart issue tracker `__ for links to Graham's follow on work) -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Tue Apr 14 18:53:46 2015 From: python-checkins at python.org (zach.ware) Date: Tue, 14 Apr 2015 16:53:46 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Update_Tcl/Tk_to_8=2E6=2E4?= =?utf-8?q?=2E?= Message-ID: <20150414165345.119996.62742@psf.io> https://hg.python.org/cpython/rev/e21a26db931c changeset: 95645:e21a26db931c parent: 95643:a5a2b33993e3 user: Zachary Ware date: Tue Apr 14 11:53:03 2015 -0500 summary: Update Tcl/Tk to 8.6.4. The new version of Tcl/Tk plays nice(r) with VS2015 CTP 6+. files: PCbuild/get_externals.bat | 4 ++-- PCbuild/tcltk.props | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/PCbuild/get_externals.bat b/PCbuild/get_externals.bat --- a/PCbuild/get_externals.bat +++ b/PCbuild/get_externals.bat @@ -55,8 +55,8 @@ bzip2-1.0.6 nasm-2.11.06 openssl-1.0.2a - tcl-core-8.6.3.1 - tk-8.6.3.1 + tcl-core-8.6.4.1 + tk-8.6.4.1 tix-8.4.3.4 sqlite-3.8.3.1 xz-5.0.5 diff --git a/PCbuild/tcltk.props b/PCbuild/tcltk.props --- a/PCbuild/tcltk.props +++ b/PCbuild/tcltk.props @@ -4,7 +4,7 @@ 8 6 - 3 + 4 1 $(TclMajorVersion) $(TclMinorVersion) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Apr 14 19:05:16 2015 From: python-checkins at python.org (gregory.p.smith) Date: Tue, 14 Apr 2015 17:05:16 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogaXNzdWUyMjA0Njog?= =?utf-8?q?mention_that_zipfile_can_raise_NotImplementedError_on_unsupport?= =?utf-8?q?ed?= Message-ID: <20150414170516.46656.48616@psf.io> https://hg.python.org/cpython/rev/3e8047ee9bbb changeset: 95646:3e8047ee9bbb branch: 3.4 parent: 95641:1e139b3c489e user: Gregory P. Smith date: Tue Apr 14 10:02:20 2015 -0700 summary: issue22046: mention that zipfile can raise NotImplementedError on unsupported compression algorithms. files: Doc/library/zipfile.rst | 6 +++++- 1 files changed, 5 insertions(+), 1 deletions(-) diff --git a/Doc/library/zipfile.rst b/Doc/library/zipfile.rst --- a/Doc/library/zipfile.rst +++ b/Doc/library/zipfile.rst @@ -298,7 +298,11 @@ file in the archive, or a :class:`ZipInfo` object. The archive must be open for read or append. *pwd* is the password used for encrypted files and, if specified, it will override the default password set with :meth:`setpassword`. Calling - :meth:`read` on a closed ZipFile will raise a :exc:`RuntimeError`. + :meth:`read` on a closed ZipFile will raise a :exc:`RuntimeError`. Calling + :meth:`read` on a ZipFile that uses a compression method other than + :const:`ZIP_STORED`, :const:`ZIP_DEFLATED`, :const:`ZIP_BZIP2` or + :const:`ZIP_LZMA` will raise a :exc:`NotImplementedError`. An error will also + be raised if the corresponding compression module is not available. .. method:: ZipFile.testzip() -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Apr 14 19:05:16 2015 From: python-checkins at python.org (gregory.p.smith) Date: Tue, 14 Apr 2015 17:05:16 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E4=29=3A_remove_trailin?= =?utf-8?q?g_space_=3A=29?= Message-ID: <20150414170516.814.59480@psf.io> https://hg.python.org/cpython/rev/33bac609be8e changeset: 95648:33bac609be8e branch: 3.4 parent: 95646:3e8047ee9bbb user: Gregory P. Smith date: Tue Apr 14 10:04:30 2015 -0700 summary: remove trailing space :) files: Doc/library/zipfile.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/library/zipfile.rst b/Doc/library/zipfile.rst --- a/Doc/library/zipfile.rst +++ b/Doc/library/zipfile.rst @@ -300,7 +300,7 @@ it will override the default password set with :meth:`setpassword`. Calling :meth:`read` on a closed ZipFile will raise a :exc:`RuntimeError`. Calling :meth:`read` on a ZipFile that uses a compression method other than - :const:`ZIP_STORED`, :const:`ZIP_DEFLATED`, :const:`ZIP_BZIP2` or + :const:`ZIP_STORED`, :const:`ZIP_DEFLATED`, :const:`ZIP_BZIP2` or :const:`ZIP_LZMA` will raise a :exc:`NotImplementedError`. An error will also be raised if the corresponding compression module is not available. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Apr 14 19:05:17 2015 From: python-checkins at python.org (gregory.p.smith) Date: Tue, 14 Apr 2015 17:05:17 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_issue22046=3A_mention_that_zipfile_can_raise_NotImplemen?= =?utf-8?q?tedError_on_unsupported?= Message-ID: <20150414170516.96129.89773@psf.io> https://hg.python.org/cpython/rev/4b9deb7e6f2b changeset: 95647:4b9deb7e6f2b parent: 95645:e21a26db931c parent: 95646:3e8047ee9bbb user: Gregory P. Smith date: Tue Apr 14 10:02:49 2015 -0700 summary: issue22046: mention that zipfile can raise NotImplementedError on unsupported compression algorithms. files: Doc/library/zipfile.rst | 6 +++++- 1 files changed, 5 insertions(+), 1 deletions(-) diff --git a/Doc/library/zipfile.rst b/Doc/library/zipfile.rst --- a/Doc/library/zipfile.rst +++ b/Doc/library/zipfile.rst @@ -300,7 +300,11 @@ file in the archive, or a :class:`ZipInfo` object. The archive must be open for read or append. *pwd* is the password used for encrypted files and, if specified, it will override the default password set with :meth:`setpassword`. Calling - :meth:`read` on a closed ZipFile will raise a :exc:`RuntimeError`. + :meth:`read` on a closed ZipFile will raise a :exc:`RuntimeError`. Calling + :meth:`read` on a ZipFile that uses a compression method other than + :const:`ZIP_STORED`, :const:`ZIP_DEFLATED`, :const:`ZIP_BZIP2` or + :const:`ZIP_LZMA` will raise a :exc:`NotImplementedError`. An error will also + be raised if the corresponding compression module is not available. .. method:: ZipFile.testzip() -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Apr 14 19:05:21 2015 From: python-checkins at python.org (gregory.p.smith) Date: Tue, 14 Apr 2015 17:05:21 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_remove_trailing_space?= Message-ID: <20150414170521.798.15868@psf.io> https://hg.python.org/cpython/rev/8963ceb7a6b1 changeset: 95649:8963ceb7a6b1 parent: 95647:4b9deb7e6f2b parent: 95648:33bac609be8e user: Gregory P. Smith date: Tue Apr 14 10:05:02 2015 -0700 summary: remove trailing space files: Doc/library/zipfile.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/library/zipfile.rst b/Doc/library/zipfile.rst --- a/Doc/library/zipfile.rst +++ b/Doc/library/zipfile.rst @@ -302,7 +302,7 @@ it will override the default password set with :meth:`setpassword`. Calling :meth:`read` on a closed ZipFile will raise a :exc:`RuntimeError`. Calling :meth:`read` on a ZipFile that uses a compression method other than - :const:`ZIP_STORED`, :const:`ZIP_DEFLATED`, :const:`ZIP_BZIP2` or + :const:`ZIP_STORED`, :const:`ZIP_DEFLATED`, :const:`ZIP_BZIP2` or :const:`ZIP_LZMA` will raise a :exc:`NotImplementedError`. An error will also be raised if the corresponding compression module is not available. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Apr 14 20:13:31 2015 From: python-checkins at python.org (gregory.p.smith) Date: Tue, 14 Apr 2015 18:13:31 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogaXNzdWU5MDE0OiBQ?= =?utf-8?q?roperly_document_PyObject=5FHEAD_and_friends_post-PEP-3123=2E?= Message-ID: <20150414181331.21097.96570@psf.io> https://hg.python.org/cpython/rev/760c5cfacbaa changeset: 95650:760c5cfacbaa branch: 3.4 parent: 95648:33bac609be8e user: Gregory P. Smith date: Tue Apr 14 11:12:53 2015 -0700 summary: issue9014: Properly document PyObject_HEAD and friends post-PEP-3123. files: Doc/c-api/structures.rst | 70 ++++++++++++++++----------- 1 files changed, 41 insertions(+), 29 deletions(-) diff --git a/Doc/c-api/structures.rst b/Doc/c-api/structures.rst --- a/Doc/c-api/structures.rst +++ b/Doc/c-api/structures.rst @@ -21,53 +21,65 @@ All object types are extensions of this type. This is a type which contains the information Python needs to treat a pointer to an object as an object. In a normal "release" build, it contains only the object's - reference count and a pointer to the corresponding type object. It - corresponds to the fields defined by the expansion of the ``PyObject_HEAD`` - macro. + reference count and a pointer to the corresponding type object. + Nothing is actually declared to be a PyObject, but every pointer to a + Python object can be cast to a PyObject*. Access to the members + must be done by using the macros :c:macro:`Py_REFCNT` and + :c:macro:`Py_TYPE`. .. c:type:: PyVarObject This is an extension of :c:type:`PyObject` that adds the :attr:`ob_size` field. This is only used for objects that have some notion of *length*. - This type does not often appear in the Python/C API. It corresponds to the - fields defined by the expansion of the ``PyObject_VAR_HEAD`` macro. + This type does not often appear in the Python/C API. + Access to the members must be done by using the macros + :c:macro:`Py_REFCNT`, :c:macro:`Py_TYPE`, and :c:macro:`Py_SIZE`. -These macros are used in the definition of :c:type:`PyObject` and -:c:type:`PyVarObject`: - -.. XXX need to document PEP 3123 changes here .. c:macro:: PyObject_HEAD - This is a macro which expands to the declarations of the fields of the - :c:type:`PyObject` type; it is used when declaring new types which represent - objects without a varying length. The specific fields it expands to depend - on the definition of :c:macro:`Py_TRACE_REFS`. By default, that macro is - not defined, and :c:macro:`PyObject_HEAD` expands to:: + This is a macro used when declaring new types which represent objects + without a varying length. The PyObject_HEAD macro expands to:: - Py_ssize_t ob_refcnt; - PyTypeObject *ob_type; + PyObject ob_base; - When :c:macro:`Py_TRACE_REFS` is defined, it expands to:: - - PyObject *_ob_next, *_ob_prev; - Py_ssize_t ob_refcnt; - PyTypeObject *ob_type; + See documentation of :c:type::`PyObject` above. .. c:macro:: PyObject_VAR_HEAD - This is a macro which expands to the declarations of the fields of the - :c:type:`PyVarObject` type; it is used when declaring new types which - represent objects with a length that varies from instance to instance. - This macro always expands to:: + This is a macro used when declaring new types which represent objects + with a length that varies from instance to instance. + The PyObject_VAR_HEAD macro expands to:: - PyObject_HEAD - Py_ssize_t ob_size; + PyVarObject ob_base; - Note that :c:macro:`PyObject_HEAD` is part of the expansion, and that its own - expansion varies depending on the definition of :c:macro:`Py_TRACE_REFS`. + See documentation of :c:type:`PyVarObject` above. + + +.. c:macro:: Py_TYPE(o) + + This macro is used to access the `ob_type` member of a Python object. + It expands to:: + + (((PyObject*)(o))->ob_type) + + +.. c:macro:: Py_REFCNT(o) + + This macro is used to access the `ob_refcnt` member of a Python object. + It expands to:: + + (((PyObject*)(o))->ob_refcnt) + + +.. c:macro:: Py_SIZE(o) + + This macro is used to access the `ob_size` member of a Python object. + It expands to:: + + (((PyVarObject*)(o))->ob_size) .. c:macro:: PyObject_HEAD_INIT(type) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Apr 14 20:13:31 2015 From: python-checkins at python.org (gregory.p.smith) Date: Tue, 14 Apr 2015 18:13:31 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_issue9014=3A_Properly_document_PyObject=5FHEAD_and_frien?= =?utf-8?q?ds_post-PEP-3123=2E?= Message-ID: <20150414181331.119992.73598@psf.io> https://hg.python.org/cpython/rev/7dc8f0075d60 changeset: 95651:7dc8f0075d60 parent: 95649:8963ceb7a6b1 parent: 95650:760c5cfacbaa user: Gregory P. Smith date: Tue Apr 14 11:13:14 2015 -0700 summary: issue9014: Properly document PyObject_HEAD and friends post-PEP-3123. files: Doc/c-api/structures.rst | 70 ++++++++++++++++----------- 1 files changed, 41 insertions(+), 29 deletions(-) diff --git a/Doc/c-api/structures.rst b/Doc/c-api/structures.rst --- a/Doc/c-api/structures.rst +++ b/Doc/c-api/structures.rst @@ -21,53 +21,65 @@ All object types are extensions of this type. This is a type which contains the information Python needs to treat a pointer to an object as an object. In a normal "release" build, it contains only the object's - reference count and a pointer to the corresponding type object. It - corresponds to the fields defined by the expansion of the ``PyObject_HEAD`` - macro. + reference count and a pointer to the corresponding type object. + Nothing is actually declared to be a PyObject, but every pointer to a + Python object can be cast to a PyObject*. Access to the members + must be done by using the macros :c:macro:`Py_REFCNT` and + :c:macro:`Py_TYPE`. .. c:type:: PyVarObject This is an extension of :c:type:`PyObject` that adds the :attr:`ob_size` field. This is only used for objects that have some notion of *length*. - This type does not often appear in the Python/C API. It corresponds to the - fields defined by the expansion of the ``PyObject_VAR_HEAD`` macro. + This type does not often appear in the Python/C API. + Access to the members must be done by using the macros + :c:macro:`Py_REFCNT`, :c:macro:`Py_TYPE`, and :c:macro:`Py_SIZE`. -These macros are used in the definition of :c:type:`PyObject` and -:c:type:`PyVarObject`: - -.. XXX need to document PEP 3123 changes here .. c:macro:: PyObject_HEAD - This is a macro which expands to the declarations of the fields of the - :c:type:`PyObject` type; it is used when declaring new types which represent - objects without a varying length. The specific fields it expands to depend - on the definition of :c:macro:`Py_TRACE_REFS`. By default, that macro is - not defined, and :c:macro:`PyObject_HEAD` expands to:: + This is a macro used when declaring new types which represent objects + without a varying length. The PyObject_HEAD macro expands to:: - Py_ssize_t ob_refcnt; - PyTypeObject *ob_type; + PyObject ob_base; - When :c:macro:`Py_TRACE_REFS` is defined, it expands to:: - - PyObject *_ob_next, *_ob_prev; - Py_ssize_t ob_refcnt; - PyTypeObject *ob_type; + See documentation of :c:type::`PyObject` above. .. c:macro:: PyObject_VAR_HEAD - This is a macro which expands to the declarations of the fields of the - :c:type:`PyVarObject` type; it is used when declaring new types which - represent objects with a length that varies from instance to instance. - This macro always expands to:: + This is a macro used when declaring new types which represent objects + with a length that varies from instance to instance. + The PyObject_VAR_HEAD macro expands to:: - PyObject_HEAD - Py_ssize_t ob_size; + PyVarObject ob_base; - Note that :c:macro:`PyObject_HEAD` is part of the expansion, and that its own - expansion varies depending on the definition of :c:macro:`Py_TRACE_REFS`. + See documentation of :c:type:`PyVarObject` above. + + +.. c:macro:: Py_TYPE(o) + + This macro is used to access the `ob_type` member of a Python object. + It expands to:: + + (((PyObject*)(o))->ob_type) + + +.. c:macro:: Py_REFCNT(o) + + This macro is used to access the `ob_refcnt` member of a Python object. + It expands to:: + + (((PyObject*)(o))->ob_refcnt) + + +.. c:macro:: Py_SIZE(o) + + This macro is used to access the `ob_size` member of a Python object. + It expands to:: + + (((PyVarObject*)(o))->ob_size) .. c:macro:: PyObject_HEAD_INIT(type) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Apr 14 20:21:37 2015 From: python-checkins at python.org (gregory.p.smith) Date: Tue, 14 Apr 2015 18:21:37 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_issue9014=3A_Include_more_formatting_on_=3Ac=3Atype=3A?= =?utf-8?b?YFB5T2JqZWN0YCBldGMu?= Message-ID: <20150414182137.21069.66461@psf.io> https://hg.python.org/cpython/rev/78a2d1169be1 changeset: 95653:78a2d1169be1 parent: 95651:7dc8f0075d60 parent: 95652:752ea0acc37e user: Gregory P. Smith date: Tue Apr 14 11:21:26 2015 -0700 summary: issue9014: Include more formatting on :c:type:`PyObject` etc. files: Doc/c-api/structures.rst | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Doc/c-api/structures.rst b/Doc/c-api/structures.rst --- a/Doc/c-api/structures.rst +++ b/Doc/c-api/structures.rst @@ -22,9 +22,9 @@ contains the information Python needs to treat a pointer to an object as an object. In a normal "release" build, it contains only the object's reference count and a pointer to the corresponding type object. - Nothing is actually declared to be a PyObject, but every pointer to a - Python object can be cast to a PyObject*. Access to the members - must be done by using the macros :c:macro:`Py_REFCNT` and + Nothing is actually declared to be a :c:type:`PyObject`, but every pointer + to a Python object can be cast to a :c:type:`PyObject*`. Access to the + members must be done by using the macros :c:macro:`Py_REFCNT` and :c:macro:`Py_TYPE`. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Apr 14 20:21:38 2015 From: python-checkins at python.org (gregory.p.smith) Date: Tue, 14 Apr 2015 18:21:38 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogaXNzdWU5MDE0OiBJ?= =?utf-8?q?nclude_more_formatting_on_=3Ac=3Atype=3A=60PyObject=60_etc=2E?= Message-ID: <20150414182137.66507.75548@psf.io> https://hg.python.org/cpython/rev/752ea0acc37e changeset: 95652:752ea0acc37e branch: 3.4 parent: 95650:760c5cfacbaa user: Gregory P. Smith date: Tue Apr 14 11:21:05 2015 -0700 summary: issue9014: Include more formatting on :c:type:`PyObject` etc. files: Doc/c-api/structures.rst | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Doc/c-api/structures.rst b/Doc/c-api/structures.rst --- a/Doc/c-api/structures.rst +++ b/Doc/c-api/structures.rst @@ -22,9 +22,9 @@ contains the information Python needs to treat a pointer to an object as an object. In a normal "release" build, it contains only the object's reference count and a pointer to the corresponding type object. - Nothing is actually declared to be a PyObject, but every pointer to a - Python object can be cast to a PyObject*. Access to the members - must be done by using the macros :c:macro:`Py_REFCNT` and + Nothing is actually declared to be a :c:type:`PyObject`, but every pointer + to a Python object can be cast to a :c:type:`PyObject*`. Access to the + members must be done by using the macros :c:macro:`Py_REFCNT` and :c:macro:`Py_TYPE`. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Apr 14 21:58:55 2015 From: python-checkins at python.org (gregory.p.smith) Date: Tue, 14 Apr 2015 19:58:55 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_issue9859=3A_Adds_a_test?= =?utf-8?q?=2Esupport=2Edetect=5Fapi=5Fmismatch_function_useful_to?= Message-ID: <20150414195855.47383.25594@psf.io> https://hg.python.org/cpython/rev/b42d1f2aa7a2 changeset: 95654:b42d1f2aa7a2 user: Gregory P. Smith date: Tue Apr 14 12:56:53 2015 -0700 summary: issue9859: Adds a test.support.detect_api_mismatch function useful to compare the public APIs of two modules or classes. files: Lib/test/support/__init__.py | 17 +++++++++- Lib/test/test_support.py | 42 ++++++++++++++++++++++++ 2 files changed, 58 insertions(+), 1 deletions(-) diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py --- a/Lib/test/support/__init__.py +++ b/Lib/test/support/__init__.py @@ -88,7 +88,7 @@ "skip_unless_symlink", "requires_gzip", "requires_bz2", "requires_lzma", "bigmemtest", "bigaddrspacetest", "cpython_only", "get_attribute", "requires_IEEE_754", "skip_unless_xattr", "requires_zlib", - "anticipate_failure", "load_package_tests", + "anticipate_failure", "load_package_tests", "detect_api_mismatch", # sys "is_jython", "check_impl_detail", # network @@ -2184,6 +2184,21 @@ return False +def detect_api_mismatch(ref_api, other_api, *, ignore=None): + """Returns the set of items in ref_api not in other_api, except for a + defined list of items to be ignored in this check. + + By default this skips private attributes beginning with '_' but + includes all magic methods, i.e. those starting and ending in '__'. + """ + missing_items = set(dir(ref_api)) - set(dir(other_api)) + if ignore: + missing_items -= set(ignore) + missing_items = set(m for m in missing_items + if not m.startswith('_') or m.endswith('__')) + return missing_items + + class SuppressCrashReport: """Try to prevent a crash report from popping up. 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 @@ -280,6 +280,48 @@ self.assertEqual(D["item"], 5) self.assertEqual(D["item"], 1) + def test_detect_api_mismatch(self): + class RefClass: + attribute1 = None + attribute2 = None + _hidden_attribute1 = None + __magic_1__ = None + + class OtherClass: + attribute2 = None + attribute3 = None + __magic_1__ = None + __magic_2__ = None + + missing_items = support.detect_api_mismatch(RefClass, OtherClass) + self.assertEqual({'attribute1'}, missing_items) + + missing_items = support.detect_api_mismatch(OtherClass, RefClass) + self.assertEqual({'attribute3', '__magic_2__'}, missing_items) + + def test_detect_api_mismatch__ignore(self): + class RefClass: + attribute1 = None + attribute2 = None + _hidden_attribute1 = None + __magic_1__ = None + + class OtherClass: + attribute2 = None + attribute3 = None + __magic_1__ = None + __magic_2__ = None + + ignore = ['attribute1', 'attribute3', '__magic_2__', 'not_in_either'] + + missing_items = support.detect_api_mismatch(RefClass, OtherClass, + ignore=ignore) + self.assertEqual(set(), missing_items) + + missing_items = support.detect_api_mismatch(OtherClass, RefClass, + ignore=ignore) + self.assertEqual(set(), missing_items) + # XXX -follows a list of untested API # make_legacy_pyc # is_resource_enabled -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Apr 14 21:58:55 2015 From: python-checkins at python.org (gregory.p.smith) Date: Tue, 14 Apr 2015 19:58:55 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_issue9859=3A_Adds_a_CPyMat?= =?utf-8?q?chTest_test_case_to_compare_the_exposed_APIs?= Message-ID: <20150414195855.8621.47781@psf.io> https://hg.python.org/cpython/rev/0b6c894c3c96 changeset: 95655:0b6c894c3c96 user: Gregory P. Smith date: Tue Apr 14 12:58:05 2015 -0700 summary: issue9859: Adds a CPyMatchTest test case to compare the exposed APIs of the Python io module and the C io module. They do not currently match so the failing test is marked with @unittest.skip. files: Lib/test/test_io.py | 16 +++++++++++++++- 1 files changed, 15 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_io.py b/Lib/test/test_io.py --- a/Lib/test/test_io.py +++ b/Lib/test/test_io.py @@ -719,6 +719,20 @@ pass +class CPyMatchTest(unittest.TestCase): + + @unittest.skip('test to be fixed by issue 9858') + def test_RawIOBase_io_in_pyio_match(self): + """Test that pyio RawIOBase class has all c RawIOBase methods""" + mismatch = support.detect_api_mismatch(pyio.RawIOBase, io.RawIOBase) + self.assertEqual(mismatch, set(), msg='Python RawIOBase does not have all C RawIOBase methods') + + def test_RawIOBase_pyio_in_io_match(self): + """Test that c RawIOBase class has all pyio RawIOBase methods""" + mismatch = support.detect_api_mismatch(io.RawIOBase, pyio.RawIOBase) + self.assertEqual(mismatch, set(), msg='C RawIOBase does not have all Python RawIOBase methods') + + class CommonBufferedTests: # Tests common to BufferedReader, BufferedWriter and BufferedRandom @@ -3719,7 +3733,7 @@ def load_tests(*args): - tests = (CIOTest, PyIOTest, + tests = (CIOTest, PyIOTest, CPyMatchTest, CBufferedReaderTest, PyBufferedReaderTest, CBufferedWriterTest, PyBufferedWriterTest, CBufferedRWPairTest, PyBufferedRWPairTest, -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Apr 14 22:26:44 2015 From: python-checkins at python.org (gregory.p.smith) Date: Tue, 14 Apr 2015 20:26:44 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_issue9859=3A_rename_CPyMat?= =?utf-8?q?chTest_to_APIMismatchTest_and_add_=40support=2Ecpython=5Fonly?= =?utf-8?q?=2E?= Message-ID: <20150414202644.26865.37161@psf.io> https://hg.python.org/cpython/rev/9903368b9d7b changeset: 95656:9903368b9d7b user: Gregory P. Smith date: Tue Apr 14 13:24:34 2015 -0700 summary: issue9859: rename CPyMatchTest to APIMismatchTest and add @support.cpython_only. files: Lib/test/test_io.py | 5 +++-- 1 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_io.py b/Lib/test/test_io.py --- a/Lib/test/test_io.py +++ b/Lib/test/test_io.py @@ -719,7 +719,8 @@ pass -class CPyMatchTest(unittest.TestCase): + at support.cpython_only +class APIMismatchTest(unittest.TestCase): @unittest.skip('test to be fixed by issue 9858') def test_RawIOBase_io_in_pyio_match(self): @@ -3733,7 +3734,7 @@ def load_tests(*args): - tests = (CIOTest, PyIOTest, CPyMatchTest, + tests = (CIOTest, PyIOTest, APIMismatchTest, CBufferedReaderTest, PyBufferedReaderTest, CBufferedWriterTest, PyBufferedWriterTest, CBufferedRWPairTest, PyBufferedRWPairTest, -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Apr 14 22:26:45 2015 From: python-checkins at python.org (gregory.p.smith) Date: Tue, 14 Apr 2015 20:26:45 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_issue9859=3A_Document_test?= =?utf-8?q?=2Esupport=2Edetect=5Fapi=5Fmismatch=28=29_and_simplify_its_tes?= =?utf-8?q?t=2E?= Message-ID: <20150414202644.29190.55916@psf.io> https://hg.python.org/cpython/rev/cbdd56d07123 changeset: 95657:cbdd56d07123 user: Gregory P. Smith date: Tue Apr 14 13:26:06 2015 -0700 summary: issue9859: Document test.support.detect_api_mismatch() and simplify its test. files: Doc/library/test.rst | 9 ++++ Lib/test/support/__init__.py | 2 +- Lib/test/test_support.py | 50 +++++++++-------------- 3 files changed, 30 insertions(+), 31 deletions(-) diff --git a/Doc/library/test.rst b/Doc/library/test.rst --- a/Doc/library/test.rst +++ b/Doc/library/test.rst @@ -568,6 +568,15 @@ def load_tests(*args): return load_package_tests(os.path.dirname(__file__), *args) +.. function:: detect_api_mismatch(ref_api, other_api, *, ignore=()): + + Returns the set of attributes, functions or methods of `ref_api` not + found on `other_api`, except for a defined list of items to be + ignored in this check specified in `ignore`. + + By default this skips private attributes beginning with '_' but + includes all magic methods, i.e. those starting and ending in '__'. + The :mod:`test.support` module defines the following classes: diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py --- a/Lib/test/support/__init__.py +++ b/Lib/test/support/__init__.py @@ -2184,7 +2184,7 @@ return False -def detect_api_mismatch(ref_api, other_api, *, ignore=None): +def detect_api_mismatch(ref_api, other_api, *, ignore=()): """Returns the set of items in ref_api not in other_api, except for a defined list of items to be ignored in this check. 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 @@ -280,46 +280,36 @@ self.assertEqual(D["item"], 5) self.assertEqual(D["item"], 1) + class RefClass: + attribute1 = None + attribute2 = None + _hidden_attribute1 = None + __magic_1__ = None + + class OtherClass: + attribute2 = None + attribute3 = None + __magic_1__ = None + __magic_2__ = None + def test_detect_api_mismatch(self): - class RefClass: - attribute1 = None - attribute2 = None - _hidden_attribute1 = None - __magic_1__ = None - - class OtherClass: - attribute2 = None - attribute3 = None - __magic_1__ = None - __magic_2__ = None - - missing_items = support.detect_api_mismatch(RefClass, OtherClass) + missing_items = support.detect_api_mismatch(self.RefClass, + self.OtherClass) self.assertEqual({'attribute1'}, missing_items) - missing_items = support.detect_api_mismatch(OtherClass, RefClass) + missing_items = support.detect_api_mismatch(self.OtherClass, + self.RefClass) self.assertEqual({'attribute3', '__magic_2__'}, missing_items) def test_detect_api_mismatch__ignore(self): - class RefClass: - attribute1 = None - attribute2 = None - _hidden_attribute1 = None - __magic_1__ = None - - class OtherClass: - attribute2 = None - attribute3 = None - __magic_1__ = None - __magic_2__ = None - ignore = ['attribute1', 'attribute3', '__magic_2__', 'not_in_either'] - missing_items = support.detect_api_mismatch(RefClass, OtherClass, - ignore=ignore) + missing_items = support.detect_api_mismatch( + self.RefClass, self.OtherClass, ignore=ignore) self.assertEqual(set(), missing_items) - missing_items = support.detect_api_mismatch(OtherClass, RefClass, - ignore=ignore) + missing_items = support.detect_api_mismatch( + self.OtherClass, self.RefClass, ignore=ignore) self.assertEqual(set(), missing_items) # XXX -follows a list of untested API -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Apr 14 22:35:05 2015 From: python-checkins at python.org (barry.warsaw) Date: Tue, 14 Apr 2015 20:35:05 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_Add_myself=2E?= Message-ID: <20150414203505.21293.1735@psf.io> https://hg.python.org/peps/rev/73f63d96e77f changeset: 5756:73f63d96e77f user: Barry Warsaw date: Tue Apr 14 16:35:03 2015 -0400 summary: Add myself. files: pep-0394.txt | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) diff --git a/pep-0394.txt b/pep-0394.txt --- a/pep-0394.txt +++ b/pep-0394.txt @@ -3,7 +3,8 @@ Version: $Revision$ Last-Modified: $Date$ Author: Kerrick Staley , - Nick Coghlan + Nick Coghlan , + Barry Warsaw Status: Active Type: Informational Content-Type: text/x-rst -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Tue Apr 14 22:43:13 2015 From: python-checkins at python.org (r.david.murray) Date: Tue, 14 Apr 2015 20:43:13 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogIzIzOTU3OiBmaXgg?= =?utf-8?q?typo=2E?= Message-ID: <20150414204313.16127.23638@psf.io> https://hg.python.org/cpython/rev/ef58fc2e7b06 changeset: 95658:ef58fc2e7b06 branch: 3.4 parent: 95652:752ea0acc37e user: R David Murray date: Tue Apr 14 16:42:08 2015 -0400 summary: #23957: fix typo. files: Doc/c-api/memory.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/c-api/memory.rst b/Doc/c-api/memory.rst --- a/Doc/c-api/memory.rst +++ b/Doc/c-api/memory.rst @@ -272,7 +272,7 @@ :c:func:`PyObject_Free` Newly allocated memory is filled with the byte ``0xCB``, freed memory is - filled with the byte ``0xDB``. Additionnal checks: + filled with the byte ``0xDB``. Additional checks: - detect API violations, ex: :c:func:`PyObject_Free` called on a buffer allocated by :c:func:`PyMem_Malloc` -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Apr 14 22:43:13 2015 From: python-checkins at python.org (r.david.murray) Date: Tue, 14 Apr 2015 20:43:13 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?b?KTogTWVyZ2U6ICMyMzk1NzogZml4IHR5cG8u?= Message-ID: <20150414204313.26878.81706@psf.io> https://hg.python.org/cpython/rev/4286afa7b63e changeset: 95659:4286afa7b63e parent: 95657:cbdd56d07123 parent: 95658:ef58fc2e7b06 user: R David Murray date: Tue Apr 14 16:42:49 2015 -0400 summary: Merge: #23957: fix typo. files: Doc/c-api/memory.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/c-api/memory.rst b/Doc/c-api/memory.rst --- a/Doc/c-api/memory.rst +++ b/Doc/c-api/memory.rst @@ -302,7 +302,7 @@ :c:func:`PyObject_Free` Newly allocated memory is filled with the byte ``0xCB``, freed memory is - filled with the byte ``0xDB``. Additionnal checks: + filled with the byte ``0xDB``. Additional checks: - detect API violations, ex: :c:func:`PyObject_Free` called on a buffer allocated by :c:func:`PyMem_Malloc` -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Apr 14 22:46:32 2015 From: python-checkins at python.org (zach.ware) Date: Tue, 14 Apr 2015 20:46:32 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzIzOTU2?= =?utf-8?q?=3A_Fix_typo_in_imp=2Epy_docstring=2E?= Message-ID: <20150414204632.21075.55074@psf.io> https://hg.python.org/cpython/rev/08400c64af93 changeset: 95660:08400c64af93 branch: 3.4 parent: 95658:ef58fc2e7b06 user: Zachary Ware date: Tue Apr 14 15:43:00 2015 -0500 summary: Issue #23956: Fix typo in imp.py docstring. Patch by Jacinda Shelly. 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 @@ -130,7 +130,7 @@ class _HackedGetData: - """Compatibiilty support for 'file' arguments of various load_*() + """Compatibility support for 'file' arguments of various load_*() functions.""" def __init__(self, fullname, path, file=None): -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Apr 14 22:46:32 2015 From: python-checkins at python.org (zach.ware) Date: Tue, 14 Apr 2015 20:46:32 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Closes_=2323956=3A_Merge_with_3=2E4?= Message-ID: <20150414204632.8619.75507@psf.io> https://hg.python.org/cpython/rev/5586d4a4402e changeset: 95661:5586d4a4402e parent: 95659:4286afa7b63e parent: 95660:08400c64af93 user: Zachary Ware date: Tue Apr 14 15:46:22 2015 -0500 summary: Closes #23956: Merge with 3.4 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 @@ -131,7 +131,7 @@ class _HackedGetData: - """Compatibiilty support for 'file' arguments of various load_*() + """Compatibility support for 'file' arguments of various load_*() functions.""" def __init__(self, fullname, path, file=None): -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Apr 14 22:54:17 2015 From: python-checkins at python.org (gregory.p.smith) Date: Tue, 14 Apr 2015 20:54:17 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_issue9859=3A_Use_an_expect?= =?utf-8?q?ed_failure_rather_than_a_skip=2E?= Message-ID: <20150414205417.64479.67300@psf.io> https://hg.python.org/cpython/rev/c6df85e1d42e changeset: 95662:c6df85e1d42e user: Gregory P. Smith date: Tue Apr 14 13:54:09 2015 -0700 summary: issue9859: Use an expected failure rather than a skip. files: Lib/test/test_io.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_io.py b/Lib/test/test_io.py --- a/Lib/test/test_io.py +++ b/Lib/test/test_io.py @@ -722,7 +722,7 @@ @support.cpython_only class APIMismatchTest(unittest.TestCase): - @unittest.skip('test to be fixed by issue 9858') + @unittest.expectedFailure # Test to be fixed by issue9858. def test_RawIOBase_io_in_pyio_match(self): """Test that pyio RawIOBase class has all c RawIOBase methods""" mismatch = support.detect_api_mismatch(pyio.RawIOBase, io.RawIOBase) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Apr 14 23:58:58 2015 From: python-checkins at python.org (r.david.murray) Date: Tue, 14 Apr 2015 21:58:58 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Merge=3A_=2323925=3A_stop_=28eg=29_PYTHONSTARTUP_from_ca?= =?utf-8?q?using_test=5Fcmd=5Fline_failure=2E?= Message-ID: <20150414215858.21311.12294@psf.io> https://hg.python.org/cpython/rev/3a3dc86a5b6e changeset: 95664:3a3dc86a5b6e parent: 95662:c6df85e1d42e parent: 95663:d0819a8fda1b user: R David Murray date: Tue Apr 14 17:58:40 2015 -0400 summary: Merge: #23925: stop (eg) PYTHONSTARTUP from causing test_cmd_line failure. files: Lib/test/test_cmd_line.py | 6 +++++- 1 files changed, 5 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_cmd_line.py b/Lib/test/test_cmd_line.py --- a/Lib/test/test_cmd_line.py +++ b/Lib/test/test_cmd_line.py @@ -271,7 +271,11 @@ def test_displayhook_unencodable(self): for encoding in ('ascii', 'latin-1', 'utf-8'): - env = os.environ.copy() + # We are testing a PYTHON environment variable here, so we can't + # use -E, -I, or script_helper (which uses them). So instead we do + # poor-man's isolation by deleting the PYTHON vars from env. + env = {key:value for (key,value) in os.environ.copy().items() + if not key.startswith('PYTHON')} env['PYTHONIOENCODING'] = encoding p = subprocess.Popen( [sys.executable, '-i'], -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Apr 14 23:58:58 2015 From: python-checkins at python.org (r.david.murray) Date: Tue, 14 Apr 2015 21:58:58 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogIzIzOTI1OiBzdG9w?= =?utf-8?q?_=28eg=29_PYTHONSTARTUP_from_causing_test=5Fcmd=5Fline_failure?= =?utf-8?q?=2E?= Message-ID: <20150414215858.21287.27326@psf.io> https://hg.python.org/cpython/rev/d0819a8fda1b changeset: 95663:d0819a8fda1b branch: 3.4 parent: 95660:08400c64af93 user: R David Murray date: Tue Apr 14 17:57:41 2015 -0400 summary: #23925: stop (eg) PYTHONSTARTUP from causing test_cmd_line failure. Patch by Jamiel Almeida. files: Lib/test/test_cmd_line.py | 6 +++++- 1 files changed, 5 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_cmd_line.py b/Lib/test/test_cmd_line.py --- a/Lib/test/test_cmd_line.py +++ b/Lib/test/test_cmd_line.py @@ -271,7 +271,11 @@ def test_displayhook_unencodable(self): for encoding in ('ascii', 'latin-1', 'utf-8'): - env = os.environ.copy() + # We are testing a PYTHON environment variable here, so we can't + # use -E, -I, or script_helper (which uses them). So instead we do + # poor-man's isolation by deleting the PYTHON vars from env. + env = {key:value for (key,value) in os.environ.copy().items() + if not key.startswith('PYTHON')} env['PYTHONIOENCODING'] = encoding p = subprocess.Popen( [sys.executable, '-i'], -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Apr 15 00:09:00 2015 From: python-checkins at python.org (larry.hastings) Date: Tue, 14 Apr 2015 22:09:00 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2323944=3A_Argument?= =?utf-8?q?_Clinic_now_wraps_long_impl_prototypes_at_column_78=2E?= Message-ID: <20150414220900.29309.95376@psf.io> https://hg.python.org/cpython/rev/c99ca3d7052d changeset: 95665:c99ca3d7052d user: Larry Hastings date: Tue Apr 14 18:07:59 2015 -0400 summary: Issue #23944: Argument Clinic now wraps long impl prototypes at column 78. files: Misc/NEWS | 2 + Modules/_bz2module.c | 5 +- Modules/_cursesmodule.c | 5 +- Modules/_dbmmodule.c | 10 +- Modules/_lzmamodule.c | 15 +- Modules/_pickle.c | 37 ++- Modules/arraymodule.c | 12 +- Modules/audioop.c | 66 +++-- Modules/binascii.c | 5 +- Modules/cjkcodecs/clinic/multibytecodec.c.h | 27 +- Modules/cjkcodecs/multibytecodec.c | 49 ++- Modules/clinic/_bz2module.c.h | 5 +- Modules/clinic/_cursesmodule.c.h | 5 +- Modules/clinic/_dbmmodule.c.h | 8 +- Modules/clinic/_lzmamodule.c.h | 11 +- Modules/clinic/_pickle.c.h | 25 +- Modules/clinic/arraymodule.c.h | 10 +- Modules/clinic/audioop.c.h | 42 ++- Modules/clinic/binascii.c.h | 5 +- Modules/clinic/fcntlmodule.c.h | 8 +- Modules/clinic/posixmodule.c.h | 71 ++++-- Modules/clinic/pyexpat.c.h | 12 +- Modules/clinic/unicodedata.c.h | 6 +- Modules/clinic/zlibmodule.c.h | 11 +- Modules/fcntlmodule.c | 10 +- Modules/posixmodule.c | 115 ++++++---- Modules/pyexpat.c | 16 +- Modules/unicodedata.c | 6 +- Modules/zlibmodule.c | 15 +- Objects/bytearrayobject.c | 25 +- Objects/bytesobject.c | 15 +- Objects/clinic/bytearrayobject.c.h | 17 +- Objects/clinic/bytesobject.c.h | 11 +- Python/bltinmodule.c | 36 +- Python/clinic/bltinmodule.c.h | 24 +- Python/clinic/import.c.h | 8 +- Python/import.c | 10 +- Tools/clinic/clinic.py | 57 ++++ 38 files changed, 537 insertions(+), 280 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -162,6 +162,8 @@ Tools/Demos ----------- +- Issue #23944: Argument Clinic now wraps long impl prototypes at column 78. + - Issue #20586: Argument Clinic now ensures that functions without docstrings have signatures. diff --git a/Modules/_bz2module.c b/Modules/_bz2module.c --- a/Modules/_bz2module.c +++ b/Modules/_bz2module.c @@ -614,8 +614,9 @@ [clinic start generated code]*/ static PyObject * -_bz2_BZ2Decompressor_decompress_impl(BZ2Decompressor *self, Py_buffer *data, Py_ssize_t max_length) -/*[clinic end generated code: output=7eeb5794035a2ca3 input=9558b424c8b00516]*/ +_bz2_BZ2Decompressor_decompress_impl(BZ2Decompressor *self, Py_buffer *data, + Py_ssize_t max_length) +/*[clinic end generated code: output=23e41045deb240a3 input=9558b424c8b00516]*/ { PyObject *result = NULL; diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c --- a/Modules/_cursesmodule.c +++ b/Modules/_cursesmodule.c @@ -586,8 +586,9 @@ [clinic start generated code]*/ static PyObject * -curses_window_addch_impl(PyCursesWindowObject *self, int group_left_1, int y, int x, PyObject *ch, int group_right_1, long attr) -/*[clinic end generated code: output=9fa34a5d80151f1a input=5a41efb34a2de338]*/ +curses_window_addch_impl(PyCursesWindowObject *self, int group_left_1, int y, + int x, PyObject *ch, int group_right_1, long attr) +/*[clinic end generated code: output=99f7f85078ec06c3 input=5a41efb34a2de338]*/ { PyCursesWindowObject *cwself = (PyCursesWindowObject *)self; int coordinates_group = group_left_1; diff --git a/Modules/_dbmmodule.c b/Modules/_dbmmodule.c --- a/Modules/_dbmmodule.c +++ b/Modules/_dbmmodule.c @@ -280,8 +280,9 @@ [clinic start generated code]*/ static PyObject * -dbm_dbm_get_impl(dbmobject *dp, const char *key, Py_ssize_clean_t key_length, PyObject *default_value) -/*[clinic end generated code: output=c2bdccaa734ad349 input=aecf5efd2f2b1a3b]*/ +dbm_dbm_get_impl(dbmobject *dp, const char *key, Py_ssize_clean_t key_length, + PyObject *default_value) +/*[clinic end generated code: output=4f5c0e523eaf1251 input=aecf5efd2f2b1a3b]*/ { datum dbm_key, val; @@ -422,8 +423,9 @@ [clinic start generated code]*/ static PyObject * -dbmopen_impl(PyModuleDef *module, const char *filename, const char *flags, int mode) -/*[clinic end generated code: output=8b618fe06b92bf86 input=6499ab0fab1333ac]*/ +dbmopen_impl(PyModuleDef *module, const char *filename, const char *flags, + int mode) +/*[clinic end generated code: output=e8d4b36f25c733fd input=6499ab0fab1333ac]*/ { int iflags; diff --git a/Modules/_lzmamodule.c b/Modules/_lzmamodule.c --- a/Modules/_lzmamodule.c +++ b/Modules/_lzmamodule.c @@ -1085,8 +1085,9 @@ [clinic start generated code]*/ static PyObject * -_lzma_LZMADecompressor_decompress_impl(Decompressor *self, Py_buffer *data, Py_ssize_t max_length) -/*[clinic end generated code: output=1532a5bb23629001 input=f2bb902cc1caf203]*/ +_lzma_LZMADecompressor_decompress_impl(Decompressor *self, Py_buffer *data, + Py_ssize_t max_length) +/*[clinic end generated code: output=ef4e20ec7122241d input=f2bb902cc1caf203]*/ { PyObject *result = NULL; @@ -1150,8 +1151,9 @@ [clinic start generated code]*/ static int -_lzma_LZMADecompressor___init___impl(Decompressor *self, int format, PyObject *memlimit, PyObject *filters) -/*[clinic end generated code: output=9b119f6f2cc2d7a8 input=458ca6132ef29801]*/ +_lzma_LZMADecompressor___init___impl(Decompressor *self, int format, + PyObject *memlimit, PyObject *filters) +/*[clinic end generated code: output=3e1821f8aa36564c input=458ca6132ef29801]*/ { const uint32_t decoder_flags = LZMA_TELL_ANY_CHECK | LZMA_TELL_NO_CHECK; uint64_t memlimit_ = UINT64_MAX; @@ -1399,8 +1401,9 @@ [clinic start generated code]*/ static PyObject * -_lzma__decode_filter_properties_impl(PyModuleDef *module, lzma_vli filter_id, Py_buffer *encoded_props) -/*[clinic end generated code: output=235f7f5345d48744 input=246410800782160c]*/ +_lzma__decode_filter_properties_impl(PyModuleDef *module, lzma_vli filter_id, + Py_buffer *encoded_props) +/*[clinic end generated code: output=af248f570746668b input=246410800782160c]*/ { lzma_filter filter; lzma_ret lzret; diff --git a/Modules/_pickle.c b/Modules/_pickle.c --- a/Modules/_pickle.c +++ b/Modules/_pickle.c @@ -4106,8 +4106,9 @@ [clinic start generated code]*/ static int -_pickle_Pickler___init___impl(PicklerObject *self, PyObject *file, PyObject *protocol, int fix_imports) -/*[clinic end generated code: output=56e229f3b1f4332f input=b8cdeb7e3f5ee674]*/ +_pickle_Pickler___init___impl(PicklerObject *self, PyObject *file, + PyObject *protocol, int fix_imports) +/*[clinic end generated code: output=b5f31078dab17fb0 input=b8cdeb7e3f5ee674]*/ { _Py_IDENTIFIER(persistent_id); _Py_IDENTIFIER(dispatch_table); @@ -6302,8 +6303,10 @@ [clinic start generated code]*/ static PyObject * -_pickle_Unpickler_find_class_impl(UnpicklerObject *self, PyObject *module_name, PyObject *global_name) -/*[clinic end generated code: output=64c77437e088e188 input=e2e6a865de093ef4]*/ +_pickle_Unpickler_find_class_impl(UnpicklerObject *self, + PyObject *module_name, + PyObject *global_name) +/*[clinic end generated code: output=becc08d7f9ed41e3 input=e2e6a865de093ef4]*/ { PyObject *global; PyObject *modules_dict; @@ -6514,8 +6517,10 @@ [clinic start generated code]*/ static int -_pickle_Unpickler___init___impl(UnpicklerObject *self, PyObject *file, int fix_imports, const char *encoding, const char *errors) -/*[clinic end generated code: output=b9ed1d84d315f3b5 input=30b4dc9e976b890c]*/ +_pickle_Unpickler___init___impl(UnpicklerObject *self, PyObject *file, + int fix_imports, const char *encoding, + const char *errors) +/*[clinic end generated code: output=e2c8ce748edc57b0 input=30b4dc9e976b890c]*/ { _Py_IDENTIFIER(persistent_load); @@ -6943,8 +6948,9 @@ [clinic start generated code]*/ static PyObject * -_pickle_dump_impl(PyModuleDef *module, PyObject *obj, PyObject *file, PyObject *protocol, int fix_imports) -/*[clinic end generated code: output=a606e626d553850d input=e9e5fdd48de92eae]*/ +_pickle_dump_impl(PyModuleDef *module, PyObject *obj, PyObject *file, + PyObject *protocol, int fix_imports) +/*[clinic end generated code: output=0de7dff89c406816 input=e9e5fdd48de92eae]*/ { PicklerObject *pickler = _Pickler_New(); @@ -6996,8 +7002,9 @@ [clinic start generated code]*/ static PyObject * -_pickle_dumps_impl(PyModuleDef *module, PyObject *obj, PyObject *protocol, int fix_imports) -/*[clinic end generated code: output=777f0deefe5b88ee input=293dbeda181580b7]*/ +_pickle_dumps_impl(PyModuleDef *module, PyObject *obj, PyObject *protocol, + int fix_imports) +/*[clinic end generated code: output=daa380db56fe07b9 input=293dbeda181580b7]*/ { PyObject *result; PicklerObject *pickler = _Pickler_New(); @@ -7056,8 +7063,9 @@ [clinic start generated code]*/ static PyObject * -_pickle_load_impl(PyModuleDef *module, PyObject *file, int fix_imports, const char *encoding, const char *errors) -/*[clinic end generated code: output=568c61356c172654 input=da97372e38e510a6]*/ +_pickle_load_impl(PyModuleDef *module, PyObject *file, int fix_imports, + const char *encoding, const char *errors) +/*[clinic end generated code: output=798f1c57cb2b4eb1 input=da97372e38e510a6]*/ { PyObject *result; UnpicklerObject *unpickler = _Unpickler_New(); @@ -7109,8 +7117,9 @@ [clinic start generated code]*/ static PyObject * -_pickle_loads_impl(PyModuleDef *module, PyObject *data, int fix_imports, const char *encoding, const char *errors) -/*[clinic end generated code: output=0b3845ad110b2522 input=f57f0fdaa2b4cb8b]*/ +_pickle_loads_impl(PyModuleDef *module, PyObject *data, int fix_imports, + const char *encoding, const char *errors) +/*[clinic end generated code: output=61e9cdb01e36a736 input=f57f0fdaa2b4cb8b]*/ { PyObject *result; UnpicklerObject *unpickler = _Unpickler_New(); diff --git a/Modules/arraymodule.c b/Modules/arraymodule.c --- a/Modules/arraymodule.c +++ b/Modules/arraymodule.c @@ -1684,8 +1684,9 @@ [clinic start generated code]*/ static PyObject * -array_array_fromunicode_impl(arrayobject *self, Py_UNICODE *ustr, Py_ssize_clean_t ustr_length) -/*[clinic end generated code: output=3b3f4f133bac725e input=56bcedb5ef70139f]*/ +array_array_fromunicode_impl(arrayobject *self, Py_UNICODE *ustr, + Py_ssize_clean_t ustr_length) +/*[clinic end generated code: output=ebb72fc16975e06d input=56bcedb5ef70139f]*/ { char typecode; @@ -1937,8 +1938,11 @@ [clinic start generated code]*/ static PyObject * -array__array_reconstructor_impl(PyModuleDef *module, PyTypeObject *arraytype, int typecode, enum machine_format_code mformat_code, PyObject *items) -/*[clinic end generated code: output=c51081ec91caf7e9 input=f72492708c0a1d50]*/ +array__array_reconstructor_impl(PyModuleDef *module, PyTypeObject *arraytype, + int typecode, + enum machine_format_code mformat_code, + PyObject *items) +/*[clinic end generated code: output=6ecbf0e8e4d92ab9 input=f72492708c0a1d50]*/ { PyObject *converted_items; PyObject *result; diff --git a/Modules/audioop.c b/Modules/audioop.c --- a/Modules/audioop.c +++ b/Modules/audioop.c @@ -407,8 +407,9 @@ [clinic start generated code]*/ static PyObject * -audioop_getsample_impl(PyModuleDef *module, Py_buffer *fragment, int width, Py_ssize_t index) -/*[clinic end generated code: output=f4482497e6f6e78f input=88edbe2871393549]*/ +audioop_getsample_impl(PyModuleDef *module, Py_buffer *fragment, int width, + Py_ssize_t index) +/*[clinic end generated code: output=3995e189fdc8ec16 input=88edbe2871393549]*/ { int val; @@ -593,8 +594,9 @@ [clinic start generated code]*/ static PyObject * -audioop_findfit_impl(PyModuleDef *module, Py_buffer *fragment, Py_buffer *reference) -/*[clinic end generated code: output=505fd04d4244db31 input=62c305605e183c9a]*/ +audioop_findfit_impl(PyModuleDef *module, Py_buffer *fragment, + Py_buffer *reference) +/*[clinic end generated code: output=609eedf5d823d6dd input=62c305605e183c9a]*/ { const short *cp1, *cp2; Py_ssize_t len1, len2; @@ -661,8 +663,9 @@ [clinic start generated code]*/ static PyObject * -audioop_findfactor_impl(PyModuleDef *module, Py_buffer *fragment, Py_buffer *reference) -/*[clinic end generated code: output=ddf35a1e57575ce4 input=816680301d012b21]*/ +audioop_findfactor_impl(PyModuleDef *module, Py_buffer *fragment, + Py_buffer *reference) +/*[clinic end generated code: output=5566a8c55de54f99 input=816680301d012b21]*/ { const short *cp1, *cp2; Py_ssize_t len; @@ -702,8 +705,9 @@ [clinic start generated code]*/ static PyObject * -audioop_findmax_impl(PyModuleDef *module, Py_buffer *fragment, Py_ssize_t length) -/*[clinic end generated code: output=21d0c2a1e5655134 input=2f304801ed42383c]*/ +audioop_findmax_impl(PyModuleDef *module, Py_buffer *fragment, + Py_ssize_t length) +/*[clinic end generated code: output=01fe796fad2573bb input=2f304801ed42383c]*/ { const short *cp1; Py_ssize_t len1; @@ -896,8 +900,9 @@ [clinic start generated code]*/ static PyObject * -audioop_mul_impl(PyModuleDef *module, Py_buffer *fragment, int width, double factor) -/*[clinic end generated code: output=a697ebbd5852d38f input=c726667baa157d3c]*/ +audioop_mul_impl(PyModuleDef *module, Py_buffer *fragment, int width, + double factor) +/*[clinic end generated code: output=1c7c31191ac86b10 input=c726667baa157d3c]*/ { signed char *ncp; Py_ssize_t i; @@ -937,8 +942,9 @@ [clinic start generated code]*/ static PyObject * -audioop_tomono_impl(PyModuleDef *module, Py_buffer *fragment, int width, double lfactor, double rfactor) -/*[clinic end generated code: output=436e7710521661dd input=c4ec949b3f4dddfa]*/ +audioop_tomono_impl(PyModuleDef *module, Py_buffer *fragment, int width, + double lfactor, double rfactor) +/*[clinic end generated code: output=553f547c5e29e3b6 input=c4ec949b3f4dddfa]*/ { signed char *cp, *ncp; Py_ssize_t len, i; @@ -985,8 +991,9 @@ [clinic start generated code]*/ static PyObject * -audioop_tostereo_impl(PyModuleDef *module, Py_buffer *fragment, int width, double lfactor, double rfactor) -/*[clinic end generated code: output=6ff50681c87f4c1c input=27b6395ebfdff37a]*/ +audioop_tostereo_impl(PyModuleDef *module, Py_buffer *fragment, int width, + double lfactor, double rfactor) +/*[clinic end generated code: output=697bb6ba41e9dd2c input=27b6395ebfdff37a]*/ { signed char *ncp; Py_ssize_t i; @@ -1032,8 +1039,9 @@ [clinic start generated code]*/ static PyObject * -audioop_add_impl(PyModuleDef *module, Py_buffer *fragment1, Py_buffer *fragment2, int width) -/*[clinic end generated code: output=f9218bf9ea75c3f1 input=4a8d4bae4c1605c7]*/ +audioop_add_impl(PyModuleDef *module, Py_buffer *fragment1, + Py_buffer *fragment2, int width) +/*[clinic end generated code: output=fe6c12f143e0b027 input=4a8d4bae4c1605c7]*/ { signed char *ncp; Py_ssize_t i; @@ -1090,8 +1098,9 @@ [clinic start generated code]*/ static PyObject * -audioop_bias_impl(PyModuleDef *module, Py_buffer *fragment, int width, int bias) -/*[clinic end generated code: output=8ec80b3f5d510a51 input=2b5cce5c3bb4838c]*/ +audioop_bias_impl(PyModuleDef *module, Py_buffer *fragment, int width, + int bias) +/*[clinic end generated code: output=ac1f4dda20a01c26 input=2b5cce5c3bb4838c]*/ { signed char *ncp; Py_ssize_t i; @@ -1217,8 +1226,9 @@ [clinic start generated code]*/ static PyObject * -audioop_lin2lin_impl(PyModuleDef *module, Py_buffer *fragment, int width, int newwidth) -/*[clinic end generated code: output=3f9468a74472a93e input=5ce08c8aa2f24d96]*/ +audioop_lin2lin_impl(PyModuleDef *module, Py_buffer *fragment, int width, + int newwidth) +/*[clinic end generated code: output=cb6ca950d1df9898 input=5ce08c8aa2f24d96]*/ { unsigned char *ncp; Py_ssize_t i, j; @@ -1274,8 +1284,10 @@ [clinic start generated code]*/ static PyObject * -audioop_ratecv_impl(PyModuleDef *module, Py_buffer *fragment, int width, int nchannels, int inrate, int outrate, PyObject *state, int weightA, int weightB) -/*[clinic end generated code: output=5585dddc4b5ff236 input=aff3acdc94476191]*/ +audioop_ratecv_impl(PyModuleDef *module, Py_buffer *fragment, int width, + int nchannels, int inrate, int outrate, PyObject *state, + int weightA, int weightB) +/*[clinic end generated code: output=59e1787bfa49b9d9 input=aff3acdc94476191]*/ { char *cp, *ncp; Py_ssize_t len; @@ -1601,8 +1613,9 @@ [clinic start generated code]*/ static PyObject * -audioop_lin2adpcm_impl(PyModuleDef *module, Py_buffer *fragment, int width, PyObject *state) -/*[clinic end generated code: output=4654c29d2731fafe input=12919d549b90c90a]*/ +audioop_lin2adpcm_impl(PyModuleDef *module, Py_buffer *fragment, int width, + PyObject *state) +/*[clinic end generated code: output=93f0996f592b5ce5 input=12919d549b90c90a]*/ { signed char *ncp; Py_ssize_t i; @@ -1723,8 +1736,9 @@ [clinic start generated code]*/ static PyObject * -audioop_adpcm2lin_impl(PyModuleDef *module, Py_buffer *fragment, int width, PyObject *state) -/*[clinic end generated code: output=371965cdcc0aa69b input=f5221144f5ca9ef0]*/ +audioop_adpcm2lin_impl(PyModuleDef *module, Py_buffer *fragment, int width, + PyObject *state) +/*[clinic end generated code: output=236cf6dc2c829181 input=f5221144f5ca9ef0]*/ { signed char *cp; signed char *ncp; diff --git a/Modules/binascii.c b/Modules/binascii.c --- a/Modules/binascii.c +++ b/Modules/binascii.c @@ -1381,8 +1381,9 @@ [clinic start generated code]*/ static PyObject * -binascii_b2a_qp_impl(PyModuleDef *module, Py_buffer *data, int quotetabs, int istext, int header) -/*[clinic end generated code: output=ff2991ba640fff3e input=7f2a9aaa008e92b2]*/ +binascii_b2a_qp_impl(PyModuleDef *module, Py_buffer *data, int quotetabs, + int istext, int header) +/*[clinic end generated code: output=a87ca9ccb94e2a9f input=7f2a9aaa008e92b2]*/ { Py_ssize_t in, out; unsigned char *databuf, *odata; diff --git a/Modules/cjkcodecs/clinic/multibytecodec.c.h b/Modules/cjkcodecs/clinic/multibytecodec.c.h --- a/Modules/cjkcodecs/clinic/multibytecodec.c.h +++ b/Modules/cjkcodecs/clinic/multibytecodec.c.h @@ -17,7 +17,9 @@ {"encode", (PyCFunction)_multibytecodec_MultibyteCodec_encode, METH_VARARGS|METH_KEYWORDS, _multibytecodec_MultibyteCodec_encode__doc__}, static PyObject * -_multibytecodec_MultibyteCodec_encode_impl(MultibyteCodecObject *self, PyObject *input, const char *errors); +_multibytecodec_MultibyteCodec_encode_impl(MultibyteCodecObject *self, + PyObject *input, + const char *errors); static PyObject * _multibytecodec_MultibyteCodec_encode(MultibyteCodecObject *self, PyObject *args, PyObject *kwargs) @@ -52,7 +54,9 @@ {"decode", (PyCFunction)_multibytecodec_MultibyteCodec_decode, METH_VARARGS|METH_KEYWORDS, _multibytecodec_MultibyteCodec_decode__doc__}, static PyObject * -_multibytecodec_MultibyteCodec_decode_impl(MultibyteCodecObject *self, Py_buffer *input, const char *errors); +_multibytecodec_MultibyteCodec_decode_impl(MultibyteCodecObject *self, + Py_buffer *input, + const char *errors); static PyObject * _multibytecodec_MultibyteCodec_decode(MultibyteCodecObject *self, PyObject *args, PyObject *kwargs) @@ -85,7 +89,9 @@ {"encode", (PyCFunction)_multibytecodec_MultibyteIncrementalEncoder_encode, METH_VARARGS|METH_KEYWORDS, _multibytecodec_MultibyteIncrementalEncoder_encode__doc__}, static PyObject * -_multibytecodec_MultibyteIncrementalEncoder_encode_impl(MultibyteIncrementalEncoderObject *self, PyObject *input, int final); +_multibytecodec_MultibyteIncrementalEncoder_encode_impl(MultibyteIncrementalEncoderObject *self, + PyObject *input, + int final); static PyObject * _multibytecodec_MultibyteIncrementalEncoder_encode(MultibyteIncrementalEncoderObject *self, PyObject *args, PyObject *kwargs) @@ -131,7 +137,9 @@ {"decode", (PyCFunction)_multibytecodec_MultibyteIncrementalDecoder_decode, METH_VARARGS|METH_KEYWORDS, _multibytecodec_MultibyteIncrementalDecoder_decode__doc__}, static PyObject * -_multibytecodec_MultibyteIncrementalDecoder_decode_impl(MultibyteIncrementalDecoderObject *self, Py_buffer *input, int final); +_multibytecodec_MultibyteIncrementalDecoder_decode_impl(MultibyteIncrementalDecoderObject *self, + Py_buffer *input, + int final); static PyObject * _multibytecodec_MultibyteIncrementalDecoder_decode(MultibyteIncrementalDecoderObject *self, PyObject *args, PyObject *kwargs) @@ -181,7 +189,8 @@ {"read", (PyCFunction)_multibytecodec_MultibyteStreamReader_read, METH_VARARGS, _multibytecodec_MultibyteStreamReader_read__doc__}, static PyObject * -_multibytecodec_MultibyteStreamReader_read_impl(MultibyteStreamReaderObject *self, PyObject *sizeobj); +_multibytecodec_MultibyteStreamReader_read_impl(MultibyteStreamReaderObject *self, + PyObject *sizeobj); static PyObject * _multibytecodec_MultibyteStreamReader_read(MultibyteStreamReaderObject *self, PyObject *args) @@ -208,7 +217,8 @@ {"readline", (PyCFunction)_multibytecodec_MultibyteStreamReader_readline, METH_VARARGS, _multibytecodec_MultibyteStreamReader_readline__doc__}, static PyObject * -_multibytecodec_MultibyteStreamReader_readline_impl(MultibyteStreamReaderObject *self, PyObject *sizeobj); +_multibytecodec_MultibyteStreamReader_readline_impl(MultibyteStreamReaderObject *self, + PyObject *sizeobj); static PyObject * _multibytecodec_MultibyteStreamReader_readline(MultibyteStreamReaderObject *self, PyObject *args) @@ -235,7 +245,8 @@ {"readlines", (PyCFunction)_multibytecodec_MultibyteStreamReader_readlines, METH_VARARGS, _multibytecodec_MultibyteStreamReader_readlines__doc__}, static PyObject * -_multibytecodec_MultibyteStreamReader_readlines_impl(MultibyteStreamReaderObject *self, PyObject *sizehintobj); +_multibytecodec_MultibyteStreamReader_readlines_impl(MultibyteStreamReaderObject *self, + PyObject *sizehintobj); static PyObject * _multibytecodec_MultibyteStreamReader_readlines(MultibyteStreamReaderObject *self, PyObject *args) @@ -310,4 +321,4 @@ #define _MULTIBYTECODEC___CREATE_CODEC_METHODDEF \ {"__create_codec", (PyCFunction)_multibytecodec___create_codec, METH_O, _multibytecodec___create_codec__doc__}, -/*[clinic end generated code: output=0ea29cd57f7cbc1a input=a9049054013a1b77]*/ +/*[clinic end generated code: output=0fe582cb941024c1 input=a9049054013a1b77]*/ diff --git a/Modules/cjkcodecs/multibytecodec.c b/Modules/cjkcodecs/multibytecodec.c --- a/Modules/cjkcodecs/multibytecodec.c +++ b/Modules/cjkcodecs/multibytecodec.c @@ -555,8 +555,10 @@ [clinic start generated code]*/ static PyObject * -_multibytecodec_MultibyteCodec_encode_impl(MultibyteCodecObject *self, PyObject *input, const char *errors) -/*[clinic end generated code: output=a36bfa08783a0d0b input=252e7ee695867b2d]*/ +_multibytecodec_MultibyteCodec_encode_impl(MultibyteCodecObject *self, + PyObject *input, + const char *errors) +/*[clinic end generated code: output=7b26652045ba56a9 input=252e7ee695867b2d]*/ { MultibyteCodec_State state; PyObject *errorcb, *r, *ucvt; @@ -622,8 +624,10 @@ [clinic start generated code]*/ static PyObject * -_multibytecodec_MultibyteCodec_decode_impl(MultibyteCodecObject *self, Py_buffer *input, const char *errors) -/*[clinic end generated code: output=4c8ee8b2931b014e input=37e1d9236e3ce8f3]*/ +_multibytecodec_MultibyteCodec_decode_impl(MultibyteCodecObject *self, + Py_buffer *input, + const char *errors) +/*[clinic end generated code: output=ff419f65bad6cc77 input=37e1d9236e3ce8f3]*/ { MultibyteCodec_State state; MultibyteDecodeBuffer buf; @@ -884,8 +888,10 @@ [clinic start generated code]*/ static PyObject * -_multibytecodec_MultibyteIncrementalEncoder_encode_impl(MultibyteIncrementalEncoderObject *self, PyObject *input, int final) -/*[clinic end generated code: output=3cd8780c8a719bbf input=456b76d73e464661]*/ +_multibytecodec_MultibyteIncrementalEncoder_encode_impl(MultibyteIncrementalEncoderObject *self, + PyObject *input, + int final) +/*[clinic end generated code: output=123361b6c505e2c1 input=456b76d73e464661]*/ { return encoder_encode_stateful(STATEFUL_ECTX(self), input, final); } @@ -1039,8 +1045,10 @@ [clinic start generated code]*/ static PyObject * -_multibytecodec_MultibyteIncrementalDecoder_decode_impl(MultibyteIncrementalDecoderObject *self, Py_buffer *input, int final) -/*[clinic end generated code: output=a0f3f92aa7303cf7 input=eb18c2f6e83589e1]*/ +_multibytecodec_MultibyteIncrementalDecoder_decode_impl(MultibyteIncrementalDecoderObject *self, + Py_buffer *input, + int final) +/*[clinic end generated code: output=b9b9090e8a9ce2ba input=eb18c2f6e83589e1]*/ { MultibyteDecodeBuffer buf; char *data, *wdata = NULL; @@ -1360,8 +1368,9 @@ [clinic start generated code]*/ static PyObject * -_multibytecodec_MultibyteStreamReader_read_impl(MultibyteStreamReaderObject *self, PyObject *sizeobj) -/*[clinic end generated code: output=f298ea6e1bd2083c input=015b0d3ff2fca485]*/ +_multibytecodec_MultibyteStreamReader_read_impl(MultibyteStreamReaderObject *self, + PyObject *sizeobj) +/*[clinic end generated code: output=35621eb75355d5b8 input=015b0d3ff2fca485]*/ { Py_ssize_t size; @@ -1388,8 +1397,9 @@ [clinic start generated code]*/ static PyObject * -_multibytecodec_MultibyteStreamReader_readline_impl(MultibyteStreamReaderObject *self, PyObject *sizeobj) -/*[clinic end generated code: output=e5ac302a6d0999de input=41ccc64f9bb0cec3]*/ +_multibytecodec_MultibyteStreamReader_readline_impl(MultibyteStreamReaderObject *self, + PyObject *sizeobj) +/*[clinic end generated code: output=4fbfaae1ed457a11 input=41ccc64f9bb0cec3]*/ { Py_ssize_t size; @@ -1416,8 +1426,9 @@ [clinic start generated code]*/ static PyObject * -_multibytecodec_MultibyteStreamReader_readlines_impl(MultibyteStreamReaderObject *self, PyObject *sizehintobj) -/*[clinic end generated code: output=68f024178b77cb0f input=54932f5d4d88e880]*/ +_multibytecodec_MultibyteStreamReader_readlines_impl(MultibyteStreamReaderObject *self, + PyObject *sizehintobj) +/*[clinic end generated code: output=e7c4310768ed2ad4 input=54932f5d4d88e880]*/ { PyObject *r, *sr; Py_ssize_t sizehint; @@ -1618,8 +1629,9 @@ [clinic start generated code]*/ static PyObject * -_multibytecodec_MultibyteStreamWriter_write(MultibyteStreamWriterObject *self, PyObject *strobj) -/*[clinic end generated code: output=44e9eb0db0374cb1 input=551dc4c018c10a2b]*/ +_multibytecodec_MultibyteStreamWriter_write(MultibyteStreamWriterObject *self, + PyObject *strobj) +/*[clinic end generated code: output=e13ae841c895251e input=551dc4c018c10a2b]*/ { if (mbstreamwriter_iwrite(self, strobj)) return NULL; @@ -1635,8 +1647,9 @@ [clinic start generated code]*/ static PyObject * -_multibytecodec_MultibyteStreamWriter_writelines(MultibyteStreamWriterObject *self, PyObject *lines) -/*[clinic end generated code: output=4facbb0638dde172 input=57797fe7008d4e96]*/ +_multibytecodec_MultibyteStreamWriter_writelines(MultibyteStreamWriterObject *self, + PyObject *lines) +/*[clinic end generated code: output=e5c4285ac8e7d522 input=57797fe7008d4e96]*/ { PyObject *strobj; int i, r; diff --git a/Modules/clinic/_bz2module.c.h b/Modules/clinic/_bz2module.c.h --- a/Modules/clinic/_bz2module.c.h +++ b/Modules/clinic/_bz2module.c.h @@ -117,7 +117,8 @@ {"decompress", (PyCFunction)_bz2_BZ2Decompressor_decompress, METH_VARARGS|METH_KEYWORDS, _bz2_BZ2Decompressor_decompress__doc__}, static PyObject * -_bz2_BZ2Decompressor_decompress_impl(BZ2Decompressor *self, Py_buffer *data, Py_ssize_t max_length); +_bz2_BZ2Decompressor_decompress_impl(BZ2Decompressor *self, Py_buffer *data, + Py_ssize_t max_length); static PyObject * _bz2_BZ2Decompressor_decompress(BZ2Decompressor *self, PyObject *args, PyObject *kwargs) @@ -168,4 +169,4 @@ exit: return return_value; } -/*[clinic end generated code: output=3565d163a360af01 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=e8a48a949969c355 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_cursesmodule.c.h b/Modules/clinic/_cursesmodule.c.h --- a/Modules/clinic/_cursesmodule.c.h +++ b/Modules/clinic/_cursesmodule.c.h @@ -24,7 +24,8 @@ {"addch", (PyCFunction)curses_window_addch, METH_VARARGS, curses_window_addch__doc__}, static PyObject * -curses_window_addch_impl(PyCursesWindowObject *self, int group_left_1, int y, int x, PyObject *ch, int group_right_1, long attr); +curses_window_addch_impl(PyCursesWindowObject *self, int group_left_1, int y, + int x, PyObject *ch, int group_right_1, long attr); static PyObject * curses_window_addch(PyCursesWindowObject *self, PyObject *args) @@ -67,4 +68,4 @@ exit: return return_value; } -/*[clinic end generated code: output=660ab0ae6d8fbdda input=a9049054013a1b77]*/ +/*[clinic end generated code: output=982b1e709577f3ec input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_dbmmodule.c.h b/Modules/clinic/_dbmmodule.c.h --- a/Modules/clinic/_dbmmodule.c.h +++ b/Modules/clinic/_dbmmodule.c.h @@ -12,7 +12,8 @@ {"get", (PyCFunction)dbm_dbm_get, METH_VARARGS, dbm_dbm_get__doc__}, static PyObject * -dbm_dbm_get_impl(dbmobject *dp, const char *key, Py_ssize_clean_t key_length, PyObject *default_value); +dbm_dbm_get_impl(dbmobject *dp, const char *key, Py_ssize_clean_t key_length, + PyObject *default_value); static PyObject * dbm_dbm_get(dbmobject *dp, PyObject *args) @@ -50,7 +51,8 @@ {"open", (PyCFunction)dbmopen, METH_VARARGS, dbmopen__doc__}, static PyObject * -dbmopen_impl(PyModuleDef *module, const char *filename, const char *flags, int mode); +dbmopen_impl(PyModuleDef *module, const char *filename, const char *flags, + int mode); static PyObject * dbmopen(PyModuleDef *module, PyObject *args) @@ -69,4 +71,4 @@ exit: return return_value; } -/*[clinic end generated code: output=78d62d1aa3ddd13c input=a9049054013a1b77]*/ +/*[clinic end generated code: output=d6ec55c6c5d0b19d input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_lzmamodule.c.h b/Modules/clinic/_lzmamodule.c.h --- a/Modules/clinic/_lzmamodule.c.h +++ b/Modules/clinic/_lzmamodule.c.h @@ -84,7 +84,8 @@ {"decompress", (PyCFunction)_lzma_LZMADecompressor_decompress, METH_VARARGS|METH_KEYWORDS, _lzma_LZMADecompressor_decompress__doc__}, static PyObject * -_lzma_LZMADecompressor_decompress_impl(Decompressor *self, Py_buffer *data, Py_ssize_t max_length); +_lzma_LZMADecompressor_decompress_impl(Decompressor *self, Py_buffer *data, + Py_ssize_t max_length); static PyObject * _lzma_LZMADecompressor_decompress(Decompressor *self, PyObject *args, PyObject *kwargs) @@ -132,7 +133,8 @@ "For one-shot decompression, use the decompress() function instead."); static int -_lzma_LZMADecompressor___init___impl(Decompressor *self, int format, PyObject *memlimit, PyObject *filters); +_lzma_LZMADecompressor___init___impl(Decompressor *self, int format, + PyObject *memlimit, PyObject *filters); static int _lzma_LZMADecompressor___init__(PyObject *self, PyObject *args, PyObject *kwargs) @@ -229,7 +231,8 @@ {"_decode_filter_properties", (PyCFunction)_lzma__decode_filter_properties, METH_VARARGS, _lzma__decode_filter_properties__doc__}, static PyObject * -_lzma__decode_filter_properties_impl(PyModuleDef *module, lzma_vli filter_id, Py_buffer *encoded_props); +_lzma__decode_filter_properties_impl(PyModuleDef *module, lzma_vli filter_id, + Py_buffer *encoded_props); static PyObject * _lzma__decode_filter_properties(PyModuleDef *module, PyObject *args) @@ -251,4 +254,4 @@ return return_value; } -/*[clinic end generated code: output=ea7f2b2c4019fe86 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=8981089cde080b54 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_pickle.c.h b/Modules/clinic/_pickle.c.h --- a/Modules/clinic/_pickle.c.h +++ b/Modules/clinic/_pickle.c.h @@ -85,7 +85,8 @@ "2, so that the pickle data stream is readable with Python 2."); static int -_pickle_Pickler___init___impl(PicklerObject *self, PyObject *file, PyObject *protocol, int fix_imports); +_pickle_Pickler___init___impl(PicklerObject *self, PyObject *file, + PyObject *protocol, int fix_imports); static int _pickle_Pickler___init__(PyObject *self, PyObject *args, PyObject *kwargs) @@ -199,7 +200,9 @@ {"find_class", (PyCFunction)_pickle_Unpickler_find_class, METH_VARARGS, _pickle_Unpickler_find_class__doc__}, static PyObject * -_pickle_Unpickler_find_class_impl(UnpicklerObject *self, PyObject *module_name, PyObject *global_name); +_pickle_Unpickler_find_class_impl(UnpicklerObject *self, + PyObject *module_name, + PyObject *global_name); static PyObject * _pickle_Unpickler_find_class(UnpicklerObject *self, PyObject *args) @@ -271,7 +274,9 @@ "string instances as bytes objects."); static int -_pickle_Unpickler___init___impl(UnpicklerObject *self, PyObject *file, int fix_imports, const char *encoding, const char *errors); +_pickle_Unpickler___init___impl(UnpicklerObject *self, PyObject *file, + int fix_imports, const char *encoding, + const char *errors); static int _pickle_Unpickler___init__(PyObject *self, PyObject *args, PyObject *kwargs) @@ -377,7 +382,8 @@ {"dump", (PyCFunction)_pickle_dump, METH_VARARGS|METH_KEYWORDS, _pickle_dump__doc__}, static PyObject * -_pickle_dump_impl(PyModuleDef *module, PyObject *obj, PyObject *file, PyObject *protocol, int fix_imports); +_pickle_dump_impl(PyModuleDef *module, PyObject *obj, PyObject *file, + PyObject *protocol, int fix_imports); static PyObject * _pickle_dump(PyModuleDef *module, PyObject *args, PyObject *kwargs) @@ -421,7 +427,8 @@ {"dumps", (PyCFunction)_pickle_dumps, METH_VARARGS|METH_KEYWORDS, _pickle_dumps__doc__}, static PyObject * -_pickle_dumps_impl(PyModuleDef *module, PyObject *obj, PyObject *protocol, int fix_imports); +_pickle_dumps_impl(PyModuleDef *module, PyObject *obj, PyObject *protocol, + int fix_imports); static PyObject * _pickle_dumps(PyModuleDef *module, PyObject *args, PyObject *kwargs) @@ -475,7 +482,8 @@ {"load", (PyCFunction)_pickle_load, METH_VARARGS|METH_KEYWORDS, _pickle_load__doc__}, static PyObject * -_pickle_load_impl(PyModuleDef *module, PyObject *file, int fix_imports, const char *encoding, const char *errors); +_pickle_load_impl(PyModuleDef *module, PyObject *file, int fix_imports, + const char *encoding, const char *errors); static PyObject * _pickle_load(PyModuleDef *module, PyObject *args, PyObject *kwargs) @@ -521,7 +529,8 @@ {"loads", (PyCFunction)_pickle_loads, METH_VARARGS|METH_KEYWORDS, _pickle_loads__doc__}, static PyObject * -_pickle_loads_impl(PyModuleDef *module, PyObject *data, int fix_imports, const char *encoding, const char *errors); +_pickle_loads_impl(PyModuleDef *module, PyObject *data, int fix_imports, + const char *encoding, const char *errors); static PyObject * _pickle_loads(PyModuleDef *module, PyObject *args, PyObject *kwargs) @@ -542,4 +551,4 @@ exit: return return_value; } -/*[clinic end generated code: output=3aba79576e240c62 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=2c413ecc2ec74f7c input=a9049054013a1b77]*/ diff --git a/Modules/clinic/arraymodule.c.h b/Modules/clinic/arraymodule.c.h --- a/Modules/clinic/arraymodule.c.h +++ b/Modules/clinic/arraymodule.c.h @@ -376,7 +376,8 @@ {"fromunicode", (PyCFunction)array_array_fromunicode, METH_O, array_array_fromunicode__doc__}, static PyObject * -array_array_fromunicode_impl(arrayobject *self, Py_UNICODE *ustr, Py_ssize_clean_t ustr_length); +array_array_fromunicode_impl(arrayobject *self, Py_UNICODE *ustr, + Py_ssize_clean_t ustr_length); static PyObject * array_array_fromunicode(arrayobject *self, PyObject *arg) @@ -446,7 +447,10 @@ {"_array_reconstructor", (PyCFunction)array__array_reconstructor, METH_VARARGS, array__array_reconstructor__doc__}, static PyObject * -array__array_reconstructor_impl(PyModuleDef *module, PyTypeObject *arraytype, int typecode, enum machine_format_code mformat_code, PyObject *items); +array__array_reconstructor_impl(PyModuleDef *module, PyTypeObject *arraytype, + int typecode, + enum machine_format_code mformat_code, + PyObject *items); static PyObject * array__array_reconstructor(PyModuleDef *module, PyObject *args) @@ -502,4 +506,4 @@ #define ARRAY_ARRAYITERATOR___SETSTATE___METHODDEF \ {"__setstate__", (PyCFunction)array_arrayiterator___setstate__, METH_O, array_arrayiterator___setstate____doc__}, -/*[clinic end generated code: output=a8fbe83c2026fa83 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=48e8198c8087cd00 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/audioop.c.h b/Modules/clinic/audioop.c.h --- a/Modules/clinic/audioop.c.h +++ b/Modules/clinic/audioop.c.h @@ -12,7 +12,8 @@ {"getsample", (PyCFunction)audioop_getsample, METH_VARARGS, audioop_getsample__doc__}, static PyObject * -audioop_getsample_impl(PyModuleDef *module, Py_buffer *fragment, int width, Py_ssize_t index); +audioop_getsample_impl(PyModuleDef *module, Py_buffer *fragment, int width, + Py_ssize_t index); static PyObject * audioop_getsample(PyModuleDef *module, PyObject *args) @@ -178,7 +179,8 @@ {"findfit", (PyCFunction)audioop_findfit, METH_VARARGS, audioop_findfit__doc__}, static PyObject * -audioop_findfit_impl(PyModuleDef *module, Py_buffer *fragment, Py_buffer *reference); +audioop_findfit_impl(PyModuleDef *module, Py_buffer *fragment, + Py_buffer *reference); static PyObject * audioop_findfit(PyModuleDef *module, PyObject *args) @@ -214,7 +216,8 @@ {"findfactor", (PyCFunction)audioop_findfactor, METH_VARARGS, audioop_findfactor__doc__}, static PyObject * -audioop_findfactor_impl(PyModuleDef *module, Py_buffer *fragment, Py_buffer *reference); +audioop_findfactor_impl(PyModuleDef *module, Py_buffer *fragment, + Py_buffer *reference); static PyObject * audioop_findfactor(PyModuleDef *module, PyObject *args) @@ -250,7 +253,8 @@ {"findmax", (PyCFunction)audioop_findmax, METH_VARARGS, audioop_findmax__doc__}, static PyObject * -audioop_findmax_impl(PyModuleDef *module, Py_buffer *fragment, Py_ssize_t length); +audioop_findmax_impl(PyModuleDef *module, Py_buffer *fragment, + Py_ssize_t length); static PyObject * audioop_findmax(PyModuleDef *module, PyObject *args) @@ -382,7 +386,8 @@ {"mul", (PyCFunction)audioop_mul, METH_VARARGS, audioop_mul__doc__}, static PyObject * -audioop_mul_impl(PyModuleDef *module, Py_buffer *fragment, int width, double factor); +audioop_mul_impl(PyModuleDef *module, Py_buffer *fragment, int width, + double factor); static PyObject * audioop_mul(PyModuleDef *module, PyObject *args) @@ -416,7 +421,8 @@ {"tomono", (PyCFunction)audioop_tomono, METH_VARARGS, audioop_tomono__doc__}, static PyObject * -audioop_tomono_impl(PyModuleDef *module, Py_buffer *fragment, int width, double lfactor, double rfactor); +audioop_tomono_impl(PyModuleDef *module, Py_buffer *fragment, int width, + double lfactor, double rfactor); static PyObject * audioop_tomono(PyModuleDef *module, PyObject *args) @@ -451,7 +457,8 @@ {"tostereo", (PyCFunction)audioop_tostereo, METH_VARARGS, audioop_tostereo__doc__}, static PyObject * -audioop_tostereo_impl(PyModuleDef *module, Py_buffer *fragment, int width, double lfactor, double rfactor); +audioop_tostereo_impl(PyModuleDef *module, Py_buffer *fragment, int width, + double lfactor, double rfactor); static PyObject * audioop_tostereo(PyModuleDef *module, PyObject *args) @@ -486,7 +493,8 @@ {"add", (PyCFunction)audioop_add, METH_VARARGS, audioop_add__doc__}, static PyObject * -audioop_add_impl(PyModuleDef *module, Py_buffer *fragment1, Py_buffer *fragment2, int width); +audioop_add_impl(PyModuleDef *module, Py_buffer *fragment1, + Py_buffer *fragment2, int width); static PyObject * audioop_add(PyModuleDef *module, PyObject *args) @@ -523,7 +531,8 @@ {"bias", (PyCFunction)audioop_bias, METH_VARARGS, audioop_bias__doc__}, static PyObject * -audioop_bias_impl(PyModuleDef *module, Py_buffer *fragment, int width, int bias); +audioop_bias_impl(PyModuleDef *module, Py_buffer *fragment, int width, + int bias); static PyObject * audioop_bias(PyModuleDef *module, PyObject *args) @@ -623,7 +632,8 @@ {"lin2lin", (PyCFunction)audioop_lin2lin, METH_VARARGS, audioop_lin2lin__doc__}, static PyObject * -audioop_lin2lin_impl(PyModuleDef *module, Py_buffer *fragment, int width, int newwidth); +audioop_lin2lin_impl(PyModuleDef *module, Py_buffer *fragment, int width, + int newwidth); static PyObject * audioop_lin2lin(PyModuleDef *module, PyObject *args) @@ -658,7 +668,9 @@ {"ratecv", (PyCFunction)audioop_ratecv, METH_VARARGS, audioop_ratecv__doc__}, static PyObject * -audioop_ratecv_impl(PyModuleDef *module, Py_buffer *fragment, int width, int nchannels, int inrate, int outrate, PyObject *state, int weightA, int weightB); +audioop_ratecv_impl(PyModuleDef *module, Py_buffer *fragment, int width, + int nchannels, int inrate, int outrate, PyObject *state, + int weightA, int weightB); static PyObject * audioop_ratecv(PyModuleDef *module, PyObject *args) @@ -829,7 +841,8 @@ {"lin2adpcm", (PyCFunction)audioop_lin2adpcm, METH_VARARGS, audioop_lin2adpcm__doc__}, static PyObject * -audioop_lin2adpcm_impl(PyModuleDef *module, Py_buffer *fragment, int width, PyObject *state); +audioop_lin2adpcm_impl(PyModuleDef *module, Py_buffer *fragment, int width, + PyObject *state); static PyObject * audioop_lin2adpcm(PyModuleDef *module, PyObject *args) @@ -863,7 +876,8 @@ {"adpcm2lin", (PyCFunction)audioop_adpcm2lin, METH_VARARGS, audioop_adpcm2lin__doc__}, static PyObject * -audioop_adpcm2lin_impl(PyModuleDef *module, Py_buffer *fragment, int width, PyObject *state); +audioop_adpcm2lin_impl(PyModuleDef *module, Py_buffer *fragment, int width, + PyObject *state); static PyObject * audioop_adpcm2lin(PyModuleDef *module, PyObject *args) @@ -886,4 +900,4 @@ return return_value; } -/*[clinic end generated code: output=be840bba5d40c2ce input=a9049054013a1b77]*/ +/*[clinic end generated code: output=9b01aafef50425ae input=a9049054013a1b77]*/ diff --git a/Modules/clinic/binascii.c.h b/Modules/clinic/binascii.c.h --- a/Modules/clinic/binascii.c.h +++ b/Modules/clinic/binascii.c.h @@ -518,7 +518,8 @@ {"b2a_qp", (PyCFunction)binascii_b2a_qp, METH_VARARGS|METH_KEYWORDS, binascii_b2a_qp__doc__}, static PyObject * -binascii_b2a_qp_impl(PyModuleDef *module, Py_buffer *data, int quotetabs, int istext, int header); +binascii_b2a_qp_impl(PyModuleDef *module, Py_buffer *data, int quotetabs, + int istext, int header); static PyObject * binascii_b2a_qp(PyModuleDef *module, PyObject *args, PyObject *kwargs) @@ -543,4 +544,4 @@ return return_value; } -/*[clinic end generated code: output=31ccbd5fddc8fd75 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=175025a8a94fbdd1 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/fcntlmodule.c.h b/Modules/clinic/fcntlmodule.c.h --- a/Modules/clinic/fcntlmodule.c.h +++ b/Modules/clinic/fcntlmodule.c.h @@ -79,7 +79,8 @@ {"ioctl", (PyCFunction)fcntl_ioctl, METH_VARARGS, fcntl_ioctl__doc__}, static PyObject * -fcntl_ioctl_impl(PyModuleDef *module, int fd, unsigned int code, PyObject *ob_arg, int mutate_arg); +fcntl_ioctl_impl(PyModuleDef *module, int fd, unsigned int code, + PyObject *ob_arg, int mutate_arg); static PyObject * fcntl_ioctl(PyModuleDef *module, PyObject *args) @@ -163,7 +164,8 @@ {"lockf", (PyCFunction)fcntl_lockf, METH_VARARGS, fcntl_lockf__doc__}, static PyObject * -fcntl_lockf_impl(PyModuleDef *module, int fd, int code, PyObject *lenobj, PyObject *startobj, int whence); +fcntl_lockf_impl(PyModuleDef *module, int fd, int code, PyObject *lenobj, + PyObject *startobj, int whence); static PyObject * fcntl_lockf(PyModuleDef *module, PyObject *args) @@ -184,4 +186,4 @@ exit: return return_value; } -/*[clinic end generated code: output=ec482672292aab0c input=a9049054013a1b77]*/ +/*[clinic end generated code: output=badaa968eb04410d input=a9049054013a1b77]*/ diff --git a/Modules/clinic/posixmodule.c.h b/Modules/clinic/posixmodule.c.h --- a/Modules/clinic/posixmodule.c.h +++ b/Modules/clinic/posixmodule.c.h @@ -30,7 +30,8 @@ {"stat", (PyCFunction)os_stat, METH_VARARGS|METH_KEYWORDS, os_stat__doc__}, static PyObject * -os_stat_impl(PyModuleDef *module, path_t *path, int dir_fd, int follow_symlinks); +os_stat_impl(PyModuleDef *module, path_t *path, int dir_fd, + int follow_symlinks); static PyObject * os_stat(PyModuleDef *module, PyObject *args, PyObject *kwargs) @@ -126,7 +127,8 @@ {"access", (PyCFunction)os_access, METH_VARARGS|METH_KEYWORDS, os_access__doc__}, static int -os_access_impl(PyModuleDef *module, path_t *path, int mode, int dir_fd, int effective_ids, int follow_symlinks); +os_access_impl(PyModuleDef *module, path_t *path, int mode, int dir_fd, + int effective_ids, int follow_symlinks); static PyObject * os_access(PyModuleDef *module, PyObject *args, PyObject *kwargs) @@ -319,7 +321,8 @@ {"chmod", (PyCFunction)os_chmod, METH_VARARGS|METH_KEYWORDS, os_chmod__doc__}, static PyObject * -os_chmod_impl(PyModuleDef *module, path_t *path, int mode, int dir_fd, int follow_symlinks); +os_chmod_impl(PyModuleDef *module, path_t *path, int mode, int dir_fd, + int follow_symlinks); static PyObject * os_chmod(PyModuleDef *module, PyObject *args, PyObject *kwargs) @@ -438,7 +441,8 @@ {"chflags", (PyCFunction)os_chflags, METH_VARARGS|METH_KEYWORDS, os_chflags__doc__}, static PyObject * -os_chflags_impl(PyModuleDef *module, path_t *path, unsigned long flags, int follow_symlinks); +os_chflags_impl(PyModuleDef *module, path_t *path, unsigned long flags, + int follow_symlinks); static PyObject * os_chflags(PyModuleDef *module, PyObject *args, PyObject *kwargs) @@ -664,7 +668,8 @@ {"chown", (PyCFunction)os_chown, METH_VARARGS|METH_KEYWORDS, os_chown__doc__}, static PyObject * -os_chown_impl(PyModuleDef *module, path_t *path, uid_t uid, gid_t gid, int dir_fd, int follow_symlinks); +os_chown_impl(PyModuleDef *module, path_t *path, uid_t uid, gid_t gid, + int dir_fd, int follow_symlinks); static PyObject * os_chown(PyModuleDef *module, PyObject *args, PyObject *kwargs) @@ -829,7 +834,8 @@ {"link", (PyCFunction)os_link, METH_VARARGS|METH_KEYWORDS, os_link__doc__}, static PyObject * -os_link_impl(PyModuleDef *module, path_t *src, path_t *dst, int src_dir_fd, int dst_dir_fd, int follow_symlinks); +os_link_impl(PyModuleDef *module, path_t *src, path_t *dst, int src_dir_fd, + int dst_dir_fd, int follow_symlinks); static PyObject * os_link(PyModuleDef *module, PyObject *args, PyObject *kwargs) @@ -1125,7 +1131,8 @@ {"rename", (PyCFunction)os_rename, METH_VARARGS|METH_KEYWORDS, os_rename__doc__}, static PyObject * -os_rename_impl(PyModuleDef *module, path_t *src, path_t *dst, int src_dir_fd, int dst_dir_fd); +os_rename_impl(PyModuleDef *module, path_t *src, path_t *dst, int src_dir_fd, + int dst_dir_fd); static PyObject * os_rename(PyModuleDef *module, PyObject *args, PyObject *kwargs) @@ -1168,7 +1175,8 @@ {"replace", (PyCFunction)os_replace, METH_VARARGS|METH_KEYWORDS, os_replace__doc__}, static PyObject * -os_replace_impl(PyModuleDef *module, path_t *src, path_t *dst, int src_dir_fd, int dst_dir_fd); +os_replace_impl(PyModuleDef *module, path_t *src, path_t *dst, + int src_dir_fd, int dst_dir_fd); static PyObject * os_replace(PyModuleDef *module, PyObject *args, PyObject *kwargs) @@ -1472,7 +1480,8 @@ {"utime", (PyCFunction)os_utime, METH_VARARGS|METH_KEYWORDS, os_utime__doc__}, static PyObject * -os_utime_impl(PyModuleDef *module, path_t *path, PyObject *times, PyObject *ns, int dir_fd, int follow_symlinks); +os_utime_impl(PyModuleDef *module, path_t *path, PyObject *times, + PyObject *ns, int dir_fd, int follow_symlinks); static PyObject * os_utime(PyModuleDef *module, PyObject *args, PyObject *kwargs) @@ -1587,7 +1596,8 @@ {"execve", (PyCFunction)os_execve, METH_VARARGS|METH_KEYWORDS, os_execve__doc__}, static PyObject * -os_execve_impl(PyModuleDef *module, path_t *path, PyObject *argv, PyObject *env); +os_execve_impl(PyModuleDef *module, path_t *path, PyObject *argv, + PyObject *env); static PyObject * os_execve(PyModuleDef *module, PyObject *args, PyObject *kwargs) @@ -1678,7 +1688,8 @@ {"spawnve", (PyCFunction)os_spawnve, METH_VARARGS, os_spawnve__doc__}, static PyObject * -os_spawnve_impl(PyModuleDef *module, int mode, PyObject *path, PyObject *argv, PyObject *env); +os_spawnve_impl(PyModuleDef *module, int mode, PyObject *path, + PyObject *argv, PyObject *env); static PyObject * os_spawnve(PyModuleDef *module, PyObject *args) @@ -1900,7 +1911,8 @@ {"sched_setscheduler", (PyCFunction)os_sched_setscheduler, METH_VARARGS, os_sched_setscheduler__doc__}, static PyObject * -os_sched_setscheduler_impl(PyModuleDef *module, pid_t pid, int policy, struct sched_param *param); +os_sched_setscheduler_impl(PyModuleDef *module, pid_t pid, int policy, + struct sched_param *param); static PyObject * os_sched_setscheduler(PyModuleDef *module, PyObject *args) @@ -1972,7 +1984,8 @@ {"sched_setparam", (PyCFunction)os_sched_setparam, METH_VARARGS, os_sched_setparam__doc__}, static PyObject * -os_sched_setparam_impl(PyModuleDef *module, pid_t pid, struct sched_param *param); +os_sched_setparam_impl(PyModuleDef *module, pid_t pid, + struct sched_param *param); static PyObject * os_sched_setparam(PyModuleDef *module, PyObject *args) @@ -2972,7 +2985,8 @@ {"symlink", (PyCFunction)os_symlink, METH_VARARGS|METH_KEYWORDS, os_symlink__doc__}, static PyObject * -os_symlink_impl(PyModuleDef *module, path_t *src, path_t *dst, int target_is_directory, int dir_fd); +os_symlink_impl(PyModuleDef *module, path_t *src, path_t *dst, + int target_is_directory, int dir_fd); static PyObject * os_symlink(PyModuleDef *module, PyObject *args, PyObject *kwargs) @@ -3194,7 +3208,8 @@ {"open", (PyCFunction)os_open, METH_VARARGS|METH_KEYWORDS, os_open__doc__}, static int -os_open_impl(PyModuleDef *module, path_t *path, int flags, int mode, int dir_fd); +os_open_impl(PyModuleDef *module, path_t *path, int flags, int mode, + int dir_fd); static PyObject * os_open(PyModuleDef *module, PyObject *args, PyObject *kwargs) @@ -3756,7 +3771,8 @@ {"pwrite", (PyCFunction)os_pwrite, METH_VARARGS, os_pwrite__doc__}, static Py_ssize_t -os_pwrite_impl(PyModuleDef *module, int fd, Py_buffer *buffer, Py_off_t offset); +os_pwrite_impl(PyModuleDef *module, int fd, Py_buffer *buffer, + Py_off_t offset); static PyObject * os_pwrite(PyModuleDef *module, PyObject *args) @@ -3853,7 +3869,8 @@ {"mknod", (PyCFunction)os_mknod, METH_VARARGS|METH_KEYWORDS, os_mknod__doc__}, static PyObject * -os_mknod_impl(PyModuleDef *module, path_t *path, int mode, dev_t device, int dir_fd); +os_mknod_impl(PyModuleDef *module, path_t *path, int mode, dev_t device, + int dir_fd); static PyObject * os_mknod(PyModuleDef *module, PyObject *args, PyObject *kwargs) @@ -4077,7 +4094,8 @@ {"posix_fallocate", (PyCFunction)os_posix_fallocate, METH_VARARGS, os_posix_fallocate__doc__}, static PyObject * -os_posix_fallocate_impl(PyModuleDef *module, int fd, Py_off_t offset, Py_off_t length); +os_posix_fallocate_impl(PyModuleDef *module, int fd, Py_off_t offset, + Py_off_t length); static PyObject * os_posix_fallocate(PyModuleDef *module, PyObject *args) @@ -4119,7 +4137,8 @@ {"posix_fadvise", (PyCFunction)os_posix_fadvise, METH_VARARGS, os_posix_fadvise__doc__}, static PyObject * -os_posix_fadvise_impl(PyModuleDef *module, int fd, Py_off_t offset, Py_off_t length, int advice); +os_posix_fadvise_impl(PyModuleDef *module, int fd, Py_off_t offset, + Py_off_t length, int advice); static PyObject * os_posix_fadvise(PyModuleDef *module, PyObject *args) @@ -5041,7 +5060,8 @@ {"getxattr", (PyCFunction)os_getxattr, METH_VARARGS|METH_KEYWORDS, os_getxattr__doc__}, static PyObject * -os_getxattr_impl(PyModuleDef *module, path_t *path, path_t *attribute, int follow_symlinks); +os_getxattr_impl(PyModuleDef *module, path_t *path, path_t *attribute, + int follow_symlinks); static PyObject * os_getxattr(PyModuleDef *module, PyObject *args, PyObject *kwargs) @@ -5087,7 +5107,8 @@ {"setxattr", (PyCFunction)os_setxattr, METH_VARARGS|METH_KEYWORDS, os_setxattr__doc__}, static PyObject * -os_setxattr_impl(PyModuleDef *module, path_t *path, path_t *attribute, Py_buffer *value, int flags, int follow_symlinks); +os_setxattr_impl(PyModuleDef *module, path_t *path, path_t *attribute, + Py_buffer *value, int flags, int follow_symlinks); static PyObject * os_setxattr(PyModuleDef *module, PyObject *args, PyObject *kwargs) @@ -5137,7 +5158,8 @@ {"removexattr", (PyCFunction)os_removexattr, METH_VARARGS|METH_KEYWORDS, os_removexattr__doc__}, static PyObject * -os_removexattr_impl(PyModuleDef *module, path_t *path, path_t *attribute, int follow_symlinks); +os_removexattr_impl(PyModuleDef *module, path_t *path, path_t *attribute, + int follow_symlinks); static PyObject * os_removexattr(PyModuleDef *module, PyObject *args, PyObject *kwargs) @@ -5363,7 +5385,8 @@ {"set_handle_inheritable", (PyCFunction)os_set_handle_inheritable, METH_VARARGS, os_set_handle_inheritable__doc__}, static PyObject * -os_set_handle_inheritable_impl(PyModuleDef *module, Py_intptr_t handle, int inheritable); +os_set_handle_inheritable_impl(PyModuleDef *module, Py_intptr_t handle, + int inheritable); static PyObject * os_set_handle_inheritable(PyModuleDef *module, PyObject *args) @@ -5847,4 +5870,4 @@ #ifndef OS_SET_HANDLE_INHERITABLE_METHODDEF #define OS_SET_HANDLE_INHERITABLE_METHODDEF #endif /* !defined(OS_SET_HANDLE_INHERITABLE_METHODDEF) */ -/*[clinic end generated code: output=22f405f79f87ba20 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=0e3fb3bb5df25fea input=a9049054013a1b77]*/ diff --git a/Modules/clinic/pyexpat.c.h b/Modules/clinic/pyexpat.c.h --- a/Modules/clinic/pyexpat.c.h +++ b/Modules/clinic/pyexpat.c.h @@ -14,7 +14,8 @@ {"Parse", (PyCFunction)pyexpat_xmlparser_Parse, METH_VARARGS, pyexpat_xmlparser_Parse__doc__}, static PyObject * -pyexpat_xmlparser_Parse_impl(xmlparseobject *self, PyObject *data, int isFinal); +pyexpat_xmlparser_Parse_impl(xmlparseobject *self, PyObject *data, + int isFinal); static PyObject * pyexpat_xmlparser_Parse(xmlparseobject *self, PyObject *args) @@ -119,7 +120,9 @@ {"ExternalEntityParserCreate", (PyCFunction)pyexpat_xmlparser_ExternalEntityParserCreate, METH_VARARGS, pyexpat_xmlparser_ExternalEntityParserCreate__doc__}, static PyObject * -pyexpat_xmlparser_ExternalEntityParserCreate_impl(xmlparseobject *self, const char *context, const char *encoding); +pyexpat_xmlparser_ExternalEntityParserCreate_impl(xmlparseobject *self, + const char *context, + const char *encoding); static PyObject * pyexpat_xmlparser_ExternalEntityParserCreate(xmlparseobject *self, PyObject *args) @@ -235,7 +238,8 @@ {"ParserCreate", (PyCFunction)pyexpat_ParserCreate, METH_VARARGS|METH_KEYWORDS, pyexpat_ParserCreate__doc__}, static PyObject * -pyexpat_ParserCreate_impl(PyModuleDef *module, const char *encoding, const char *namespace_separator, PyObject *intern); +pyexpat_ParserCreate_impl(PyModuleDef *module, const char *encoding, + const char *namespace_separator, PyObject *intern); static PyObject * pyexpat_ParserCreate(PyModuleDef *module, PyObject *args, PyObject *kwargs) @@ -287,4 +291,4 @@ #ifndef PYEXPAT_XMLPARSER_USEFOREIGNDTD_METHODDEF #define PYEXPAT_XMLPARSER_USEFOREIGNDTD_METHODDEF #endif /* !defined(PYEXPAT_XMLPARSER_USEFOREIGNDTD_METHODDEF) */ -/*[clinic end generated code: output=e5993de4e9dd2236 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=abdf05a21dae98c7 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/unicodedata.c.h b/Modules/clinic/unicodedata.c.h --- a/Modules/clinic/unicodedata.c.h +++ b/Modules/clinic/unicodedata.c.h @@ -16,7 +16,9 @@ {"decimal", (PyCFunction)unicodedata_UCD_decimal, METH_VARARGS, unicodedata_UCD_decimal__doc__}, static PyObject * -unicodedata_UCD_decimal_impl(PreviousDBVersion *self, PyUnicodeObject *unichr, PyObject *default_value); +unicodedata_UCD_decimal_impl(PreviousDBVersion *self, + PyUnicodeObject *unichr, + PyObject *default_value); static PyObject * unicodedata_UCD_decimal(PreviousDBVersion *self, PyObject *args) @@ -34,4 +36,4 @@ exit: return return_value; } -/*[clinic end generated code: output=15b82651419cc823 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=33b488251c4fd143 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/zlibmodule.c.h b/Modules/clinic/zlibmodule.c.h --- a/Modules/clinic/zlibmodule.c.h +++ b/Modules/clinic/zlibmodule.c.h @@ -57,7 +57,8 @@ {"decompress", (PyCFunction)zlib_decompress, METH_VARARGS, zlib_decompress__doc__}, static PyObject * -zlib_decompress_impl(PyModuleDef *module, Py_buffer *data, int wbits, unsigned int bufsize); +zlib_decompress_impl(PyModuleDef *module, Py_buffer *data, int wbits, + unsigned int bufsize); static PyObject * zlib_decompress(PyModuleDef *module, PyObject *args) @@ -111,7 +112,8 @@ {"compressobj", (PyCFunction)zlib_compressobj, METH_VARARGS|METH_KEYWORDS, zlib_compressobj__doc__}, static PyObject * -zlib_compressobj_impl(PyModuleDef *module, int level, int method, int wbits, int memLevel, int strategy, Py_buffer *zdict); +zlib_compressobj_impl(PyModuleDef *module, int level, int method, int wbits, + int memLevel, int strategy, Py_buffer *zdict); static PyObject * zlib_compressobj(PyModuleDef *module, PyObject *args, PyObject *kwargs) @@ -235,7 +237,8 @@ {"decompress", (PyCFunction)zlib_Decompress_decompress, METH_VARARGS, zlib_Decompress_decompress__doc__}, static PyObject * -zlib_Decompress_decompress_impl(compobject *self, Py_buffer *data, unsigned int max_length); +zlib_Decompress_decompress_impl(compobject *self, Py_buffer *data, + unsigned int max_length); static PyObject * zlib_Decompress_decompress(compobject *self, PyObject *args) @@ -446,4 +449,4 @@ #ifndef ZLIB_COMPRESS_COPY_METHODDEF #define ZLIB_COMPRESS_COPY_METHODDEF #endif /* !defined(ZLIB_COMPRESS_COPY_METHODDEF) */ -/*[clinic end generated code: output=0743b1aa908f0b68 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=6cdeb624bebfe11f input=a9049054013a1b77]*/ diff --git a/Modules/fcntlmodule.c b/Modules/fcntlmodule.c --- a/Modules/fcntlmodule.c +++ b/Modules/fcntlmodule.c @@ -146,8 +146,9 @@ [clinic start generated code]*/ static PyObject * -fcntl_ioctl_impl(PyModuleDef *module, int fd, unsigned int code, PyObject *ob_arg, int mutate_arg) -/*[clinic end generated code: output=ad47738c118622bf input=ede70c433cccbbb2]*/ +fcntl_ioctl_impl(PyModuleDef *module, int fd, unsigned int code, + PyObject *ob_arg, int mutate_arg) +/*[clinic end generated code: output=102faa0f7ebe2210 input=ede70c433cccbbb2]*/ { #define IOCTL_BUFSZ 1024 /* We use the unsigned non-checked 'I' format for the 'code' parameter @@ -357,8 +358,9 @@ [clinic start generated code]*/ static PyObject * -fcntl_lockf_impl(PyModuleDef *module, int fd, int code, PyObject *lenobj, PyObject *startobj, int whence) -/*[clinic end generated code: output=5536df2892bf3ce9 input=9c594391de821f24]*/ +fcntl_lockf_impl(PyModuleDef *module, int fd, int code, PyObject *lenobj, + PyObject *startobj, int whence) +/*[clinic end generated code: output=31af35eba08b9af7 input=9c594391de821f24]*/ { int ret; diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -2476,8 +2476,9 @@ [clinic start generated code]*/ static PyObject * -os_stat_impl(PyModuleDef *module, path_t *path, int dir_fd, int follow_symlinks) -/*[clinic end generated code: output=708c225f94fcfc8e input=099d356c306fa24a]*/ +os_stat_impl(PyModuleDef *module, path_t *path, int dir_fd, + int follow_symlinks) +/*[clinic end generated code: output=e4f7569f95d523ca input=099d356c306fa24a]*/ { return posix_do_stat("stat", path, dir_fd, follow_symlinks); } @@ -2547,8 +2548,9 @@ [clinic start generated code]*/ static int -os_access_impl(PyModuleDef *module, path_t *path, int mode, int dir_fd, int effective_ids, int follow_symlinks) -/*[clinic end generated code: output=f9e734db3d88b767 input=b75a756797af45ec]*/ +os_access_impl(PyModuleDef *module, path_t *path, int mode, int dir_fd, + int effective_ids, int follow_symlinks) +/*[clinic end generated code: output=abaa53340210088d input=b75a756797af45ec]*/ { int return_value; @@ -2775,8 +2777,9 @@ [clinic start generated code]*/ static PyObject * -os_chmod_impl(PyModuleDef *module, path_t *path, int mode, int dir_fd, int follow_symlinks) -/*[clinic end generated code: output=96063c976f23106a input=7f1618e5e15cc196]*/ +os_chmod_impl(PyModuleDef *module, path_t *path, int mode, int dir_fd, + int follow_symlinks) +/*[clinic end generated code: output=05e7f73b1a843ba2 input=7f1618e5e15cc196]*/ { int result; @@ -2956,8 +2959,9 @@ [clinic start generated code]*/ static PyObject * -os_chflags_impl(PyModuleDef *module, path_t *path, unsigned long flags, int follow_symlinks) -/*[clinic end generated code: output=9e5f9417afc20c4b input=0327e29feb876236]*/ +os_chflags_impl(PyModuleDef *module, path_t *path, unsigned long flags, + int follow_symlinks) +/*[clinic end generated code: output=ff2d6e73534a95b9 input=0327e29feb876236]*/ { int result; @@ -3136,8 +3140,9 @@ [clinic start generated code]*/ static PyObject * -os_chown_impl(PyModuleDef *module, path_t *path, uid_t uid, gid_t gid, int dir_fd, int follow_symlinks) -/*[clinic end generated code: output=59a8db91897fb46c input=a61cc35574814d5d]*/ +os_chown_impl(PyModuleDef *module, path_t *path, uid_t uid, gid_t gid, + int dir_fd, int follow_symlinks) +/*[clinic end generated code: output=e0a4559f394dbd91 input=a61cc35574814d5d]*/ { int result; @@ -3365,8 +3370,9 @@ [clinic start generated code]*/ static PyObject * -os_link_impl(PyModuleDef *module, path_t *src, path_t *dst, int src_dir_fd, int dst_dir_fd, int follow_symlinks) -/*[clinic end generated code: output=c0a9ded8111d2a79 input=b0095ebbcbaa7e04]*/ +os_link_impl(PyModuleDef *module, path_t *src, path_t *dst, int src_dir_fd, + int dst_dir_fd, int follow_symlinks) +/*[clinic end generated code: output=f47a7e88f7b391b6 input=b0095ebbcbaa7e04]*/ { #ifdef MS_WINDOWS BOOL result; @@ -4162,8 +4168,9 @@ [clinic start generated code]*/ static PyObject * -os_rename_impl(PyModuleDef *module, path_t *src, path_t *dst, int src_dir_fd, int dst_dir_fd) -/*[clinic end generated code: output=1bb520bf2fad186d input=faa61c847912c850]*/ +os_rename_impl(PyModuleDef *module, path_t *src, path_t *dst, int src_dir_fd, + int dst_dir_fd) +/*[clinic end generated code: output=08033bb2ec27fb5f input=faa61c847912c850]*/ { return internal_rename(src, dst, src_dir_fd, dst_dir_fd, 0); } @@ -4182,8 +4189,9 @@ [clinic start generated code]*/ static PyObject * -os_replace_impl(PyModuleDef *module, path_t *src, path_t *dst, int src_dir_fd, int dst_dir_fd) -/*[clinic end generated code: output=aa9ddad55fdef8e3 input=25515dfb107c8421]*/ +os_replace_impl(PyModuleDef *module, path_t *src, path_t *dst, + int src_dir_fd, int dst_dir_fd) +/*[clinic end generated code: output=131d012eed8d3b8b input=25515dfb107c8421]*/ { return internal_rename(src, dst, src_dir_fd, dst_dir_fd, 1); } @@ -4697,8 +4705,9 @@ [clinic start generated code]*/ static PyObject * -os_utime_impl(PyModuleDef *module, path_t *path, PyObject *times, PyObject *ns, int dir_fd, int follow_symlinks) -/*[clinic end generated code: output=c52d8fd0d1067f0b input=1f18c17d5941aa82]*/ +os_utime_impl(PyModuleDef *module, path_t *path, PyObject *times, + PyObject *ns, int dir_fd, int follow_symlinks) +/*[clinic end generated code: output=31f3434e560ba2f0 input=1f18c17d5941aa82]*/ { #ifdef MS_WINDOWS HANDLE hFile; @@ -5072,8 +5081,9 @@ [clinic start generated code]*/ static PyObject * -os_execve_impl(PyModuleDef *module, path_t *path, PyObject *argv, PyObject *env) -/*[clinic end generated code: output=7758d4f230d8aac6 input=626804fa092606d9]*/ +os_execve_impl(PyModuleDef *module, path_t *path, PyObject *argv, + PyObject *env) +/*[clinic end generated code: output=181884fcdb21508e input=626804fa092606d9]*/ { char **argvlist = NULL; char **envlist; @@ -5219,8 +5229,9 @@ [clinic start generated code]*/ static PyObject * -os_spawnve_impl(PyModuleDef *module, int mode, PyObject *path, PyObject *argv, PyObject *env) -/*[clinic end generated code: output=1c52955789461be8 input=02362fd937963f8f]*/ +os_spawnve_impl(PyModuleDef *module, int mode, PyObject *path, + PyObject *argv, PyObject *env) +/*[clinic end generated code: output=e7f5f0703610531f input=02362fd937963f8f]*/ { char *path_char; char **argvlist; @@ -5521,8 +5532,9 @@ [clinic start generated code]*/ static PyObject * -os_sched_setscheduler_impl(PyModuleDef *module, pid_t pid, int policy, struct sched_param *param) -/*[clinic end generated code: output=97f40f8384e554b0 input=c581f9469a5327dd]*/ +os_sched_setscheduler_impl(PyModuleDef *module, pid_t pid, int policy, + struct sched_param *param) +/*[clinic end generated code: output=37053e5c528c35c9 input=c581f9469a5327dd]*/ { /* ** sched_setscheduler() returns 0 in Linux, but the previous @@ -5584,8 +5596,9 @@ [clinic start generated code]*/ static PyObject * -os_sched_setparam_impl(PyModuleDef *module, pid_t pid, struct sched_param *param) -/*[clinic end generated code: output=c6560b34395bb343 input=6b8d6dfcecdc21bd]*/ +os_sched_setparam_impl(PyModuleDef *module, pid_t pid, + struct sched_param *param) +/*[clinic end generated code: output=b7a3c589436cec9b input=6b8d6dfcecdc21bd]*/ { if (sched_setparam(pid, param)) return posix_error(); @@ -7353,8 +7366,9 @@ [clinic start generated code]*/ static PyObject * -os_symlink_impl(PyModuleDef *module, path_t *src, path_t *dst, int target_is_directory, int dir_fd) -/*[clinic end generated code: output=11aa03f278bb2c8a input=e820ec4472547bc3]*/ +os_symlink_impl(PyModuleDef *module, path_t *src, path_t *dst, + int target_is_directory, int dir_fd) +/*[clinic end generated code: output=a01b4bcf32403ccd input=e820ec4472547bc3]*/ { #ifdef MS_WINDOWS DWORD result; @@ -7677,8 +7691,9 @@ [clinic start generated code]*/ static int -os_open_impl(PyModuleDef *module, path_t *path, int flags, int mode, int dir_fd) -/*[clinic end generated code: output=c95a64f0e62f199b input=ad8623b29acd2934]*/ +os_open_impl(PyModuleDef *module, path_t *path, int flags, int mode, + int dir_fd) +/*[clinic end generated code: output=47e8cc63559f5ddd input=ad8623b29acd2934]*/ { int fd; int async_err = 0; @@ -8606,8 +8621,9 @@ [clinic start generated code]*/ static Py_ssize_t -os_pwrite_impl(PyModuleDef *module, int fd, Py_buffer *buffer, Py_off_t offset) -/*[clinic end generated code: output=95225f3b496feaf3 input=19903f1b3dd26377]*/ +os_pwrite_impl(PyModuleDef *module, int fd, Py_buffer *buffer, + Py_off_t offset) +/*[clinic end generated code: output=93aabdb40e17d325 input=19903f1b3dd26377]*/ { Py_ssize_t size; int async_err = 0; @@ -8701,8 +8717,9 @@ [clinic start generated code]*/ static PyObject * -os_mknod_impl(PyModuleDef *module, path_t *path, int mode, dev_t device, int dir_fd) -/*[clinic end generated code: output=f7f813e8847de12f input=ee44531551a4d83b]*/ +os_mknod_impl(PyModuleDef *module, path_t *path, int mode, dev_t device, + int dir_fd) +/*[clinic end generated code: output=5151a8a9f754d272 input=ee44531551a4d83b]*/ { int result; int async_err = 0; @@ -8897,8 +8914,9 @@ [clinic start generated code]*/ static PyObject * -os_posix_fallocate_impl(PyModuleDef *module, int fd, Py_off_t offset, Py_off_t length) -/*[clinic end generated code: output=8ae5f7837004d454 input=d7a2ef0ab2ca52fb]*/ +os_posix_fallocate_impl(PyModuleDef *module, int fd, Py_off_t offset, + Py_off_t length) +/*[clinic end generated code: output=7f6f87a8c751e1b4 input=d7a2ef0ab2ca52fb]*/ { int result; int async_err = 0; @@ -8938,8 +8956,9 @@ [clinic start generated code]*/ static PyObject * -os_posix_fadvise_impl(PyModuleDef *module, int fd, Py_off_t offset, Py_off_t length, int advice) -/*[clinic end generated code: output=0e3f09f651661257 input=0fbe554edc2f04b5]*/ +os_posix_fadvise_impl(PyModuleDef *module, int fd, Py_off_t offset, + Py_off_t length, int advice) +/*[clinic end generated code: output=457ce6a67189e10d input=0fbe554edc2f04b5]*/ { int result; int async_err = 0; @@ -10785,8 +10804,9 @@ [clinic start generated code]*/ static PyObject * -os_getxattr_impl(PyModuleDef *module, path_t *path, path_t *attribute, int follow_symlinks) -/*[clinic end generated code: output=d90086b314859f8b input=8c8ea3bab78d89c2]*/ +os_getxattr_impl(PyModuleDef *module, path_t *path, path_t *attribute, + int follow_symlinks) +/*[clinic end generated code: output=cf2cede74bd5d412 input=8c8ea3bab78d89c2]*/ { Py_ssize_t i; PyObject *buffer = NULL; @@ -10856,8 +10876,9 @@ [clinic start generated code]*/ static PyObject * -os_setxattr_impl(PyModuleDef *module, path_t *path, path_t *attribute, Py_buffer *value, int flags, int follow_symlinks) -/*[clinic end generated code: output=e3defa5c4b1ad0ae input=f0d26833992015c2]*/ +os_setxattr_impl(PyModuleDef *module, path_t *path, path_t *attribute, + Py_buffer *value, int flags, int follow_symlinks) +/*[clinic end generated code: output=1b395ef82880fea0 input=f0d26833992015c2]*/ { ssize_t result; @@ -10903,8 +10924,9 @@ [clinic start generated code]*/ static PyObject * -os_removexattr_impl(PyModuleDef *module, path_t *path, path_t *attribute, int follow_symlinks) -/*[clinic end generated code: output=4870ec90249af875 input=cdb54834161e3329]*/ +os_removexattr_impl(PyModuleDef *module, path_t *path, path_t *attribute, + int follow_symlinks) +/*[clinic end generated code: output=f92bb39ab992650d input=cdb54834161e3329]*/ { ssize_t result; @@ -11293,8 +11315,9 @@ [clinic start generated code]*/ static PyObject * -os_set_handle_inheritable_impl(PyModuleDef *module, Py_intptr_t handle, int inheritable) -/*[clinic end generated code: output=627aa5b158b69338 input=e64b2b2730469def]*/ +os_set_handle_inheritable_impl(PyModuleDef *module, Py_intptr_t handle, + int inheritable) +/*[clinic end generated code: output=d2e111a96c9eb296 input=e64b2b2730469def]*/ { DWORD flags = inheritable ? HANDLE_FLAG_INHERIT : 0; if (!SetHandleInformation((HANDLE)handle, HANDLE_FLAG_INHERIT, flags)) { diff --git a/Modules/pyexpat.c b/Modules/pyexpat.c --- a/Modules/pyexpat.c +++ b/Modules/pyexpat.c @@ -716,8 +716,9 @@ [clinic start generated code]*/ static PyObject * -pyexpat_xmlparser_Parse_impl(xmlparseobject *self, PyObject *data, int isFinal) -/*[clinic end generated code: output=2d4dc77f4d434854 input=e37b81b8948ca7e0]*/ +pyexpat_xmlparser_Parse_impl(xmlparseobject *self, PyObject *data, + int isFinal) +/*[clinic end generated code: output=37e105d55645b0f2 input=e37b81b8948ca7e0]*/ { const char *s; Py_ssize_t slen; @@ -918,8 +919,10 @@ [clinic start generated code]*/ static PyObject * -pyexpat_xmlparser_ExternalEntityParserCreate_impl(xmlparseobject *self, const char *context, const char *encoding) -/*[clinic end generated code: output=942f300ed0e56054 input=283206575d960272]*/ +pyexpat_xmlparser_ExternalEntityParserCreate_impl(xmlparseobject *self, + const char *context, + const char *encoding) +/*[clinic end generated code: output=535cda9d7a0fbcd6 input=283206575d960272]*/ { xmlparseobject *new_parser; int i; @@ -1551,8 +1554,9 @@ [clinic start generated code]*/ static PyObject * -pyexpat_ParserCreate_impl(PyModuleDef *module, const char *encoding, const char *namespace_separator, PyObject *intern) -/*[clinic end generated code: output=b839b60992d8ce71 input=71b9f471aa6f8f86]*/ +pyexpat_ParserCreate_impl(PyModuleDef *module, const char *encoding, + const char *namespace_separator, PyObject *intern) +/*[clinic end generated code: output=81fccd233e1743a8 input=71b9f471aa6f8f86]*/ { PyObject *result; int intern_decref = 0; diff --git a/Modules/unicodedata.c b/Modules/unicodedata.c --- a/Modules/unicodedata.c +++ b/Modules/unicodedata.c @@ -133,8 +133,10 @@ [clinic start generated code]*/ static PyObject * -unicodedata_UCD_decimal_impl(PreviousDBVersion *self, PyUnicodeObject *unichr, PyObject *default_value) -/*[clinic end generated code: output=d285215533b58b28 input=c25c9d2b4de076b1]*/ +unicodedata_UCD_decimal_impl(PreviousDBVersion *self, + PyUnicodeObject *unichr, + PyObject *default_value) +/*[clinic end generated code: output=bf853108f246ba19 input=c25c9d2b4de076b1]*/ { int have_old = 0; long rc; diff --git a/Modules/zlibmodule.c b/Modules/zlibmodule.c --- a/Modules/zlibmodule.c +++ b/Modules/zlibmodule.c @@ -280,8 +280,9 @@ [clinic start generated code]*/ static PyObject * -zlib_decompress_impl(PyModuleDef *module, Py_buffer *data, int wbits, unsigned int bufsize) -/*[clinic end generated code: output=9e5464e72df9cb5f input=0f4b9abb7103f50e]*/ +zlib_decompress_impl(PyModuleDef *module, Py_buffer *data, int wbits, + unsigned int bufsize) +/*[clinic end generated code: output=444d0987f3429574 input=0f4b9abb7103f50e]*/ { PyObject *result_str = NULL; Byte *input; @@ -410,8 +411,9 @@ [clinic start generated code]*/ static PyObject * -zlib_compressobj_impl(PyModuleDef *module, int level, int method, int wbits, int memLevel, int strategy, Py_buffer *zdict) -/*[clinic end generated code: output=89e5a6c1449caa9e input=b034847f8821f6af]*/ +zlib_compressobj_impl(PyModuleDef *module, int level, int method, int wbits, + int memLevel, int strategy, Py_buffer *zdict) +/*[clinic end generated code: output=2949bbb9a5723ccd input=b034847f8821f6af]*/ { compobject *self = NULL; int err; @@ -703,8 +705,9 @@ [clinic start generated code]*/ static PyObject * -zlib_Decompress_decompress_impl(compobject *self, Py_buffer *data, unsigned int max_length) -/*[clinic end generated code: output=755cccc9087bfe55 input=02cfc047377cec86]*/ +zlib_Decompress_decompress_impl(compobject *self, Py_buffer *data, + unsigned int max_length) +/*[clinic end generated code: output=b82e2a2c19f5fe7b input=02cfc047377cec86]*/ { int err; unsigned int old_length, length = DEF_BUF_SIZE; diff --git a/Objects/bytearrayobject.c b/Objects/bytearrayobject.c --- a/Objects/bytearrayobject.c +++ b/Objects/bytearrayobject.c @@ -1524,8 +1524,9 @@ [clinic start generated code]*/ static PyObject * -bytearray_translate_impl(PyByteArrayObject *self, PyObject *table, int group_right_1, PyObject *deletechars) -/*[clinic end generated code: output=fa3ea4f9a8d58bc7 input=b749ad85f4860824]*/ +bytearray_translate_impl(PyByteArrayObject *self, PyObject *table, + int group_right_1, PyObject *deletechars) +/*[clinic end generated code: output=2bebc86a9a1ff083 input=b749ad85f4860824]*/ { char *input, *output; const char *table_chars; @@ -2142,8 +2143,9 @@ [clinic start generated code]*/ static PyObject * -bytearray_replace_impl(PyByteArrayObject *self, Py_buffer *old, Py_buffer *new, Py_ssize_t count) -/*[clinic end generated code: output=3fc105c8232d7b3f input=aa379d988637c7fb]*/ +bytearray_replace_impl(PyByteArrayObject *self, Py_buffer *old, + Py_buffer *new, Py_ssize_t count) +/*[clinic end generated code: output=d39884c4dc59412a input=aa379d988637c7fb]*/ { return (PyObject *)replace((PyByteArrayObject *) self, old->buf, old->len, @@ -2165,8 +2167,9 @@ [clinic start generated code]*/ static PyObject * -bytearray_split_impl(PyByteArrayObject *self, PyObject *sep, Py_ssize_t maxsplit) -/*[clinic end generated code: output=cdccf5a29dbf7eb5 input=24f82669f41bf523]*/ +bytearray_split_impl(PyByteArrayObject *self, PyObject *sep, + Py_ssize_t maxsplit) +/*[clinic end generated code: output=833e2cf385d9a04d input=24f82669f41bf523]*/ { Py_ssize_t len = PyByteArray_GET_SIZE(self), n; const char *s = PyByteArray_AS_STRING(self), *sub; @@ -2276,8 +2279,9 @@ [clinic start generated code]*/ static PyObject * -bytearray_rsplit_impl(PyByteArrayObject *self, PyObject *sep, Py_ssize_t maxsplit) -/*[clinic end generated code: output=4d648cf3ac65c9e9 input=a68286e4dd692ffe]*/ +bytearray_rsplit_impl(PyByteArrayObject *self, PyObject *sep, + Py_ssize_t maxsplit) +/*[clinic end generated code: output=a55e0b5a03cb6190 input=a68286e4dd692ffe]*/ { Py_ssize_t len = PyByteArray_GET_SIZE(self), n; const char *s = PyByteArray_AS_STRING(self), *sub; @@ -2730,8 +2734,9 @@ [clinic start generated code]*/ static PyObject * -bytearray_decode_impl(PyByteArrayObject *self, const char *encoding, const char *errors) -/*[clinic end generated code: output=7e64e2cc91573b26 input=f28d8f903020257b]*/ +bytearray_decode_impl(PyByteArrayObject *self, const char *encoding, + const char *errors) +/*[clinic end generated code: output=f57d43f4a00b42c5 input=f28d8f903020257b]*/ { if (encoding == NULL) encoding = PyUnicode_GetDefaultEncoding(); diff --git a/Objects/bytesobject.c b/Objects/bytesobject.c --- a/Objects/bytesobject.c +++ b/Objects/bytesobject.c @@ -2113,8 +2113,9 @@ [clinic start generated code]*/ static PyObject * -bytes_translate_impl(PyBytesObject *self, PyObject *table, int group_right_1, PyObject *deletechars) -/*[clinic end generated code: output=0ddd2cef4f4918f2 input=d8fa5519d7cc4be7]*/ +bytes_translate_impl(PyBytesObject *self, PyObject *table, int group_right_1, + PyObject *deletechars) +/*[clinic end generated code: output=233df850eb50bf8d input=d8fa5519d7cc4be7]*/ { char *input, *output; Py_buffer table_view = {NULL, NULL}; @@ -2761,8 +2762,9 @@ [clinic start generated code]*/ static PyObject * -bytes_replace_impl(PyBytesObject*self, Py_buffer *old, Py_buffer *new, Py_ssize_t count) -/*[clinic end generated code: output=3fe052c3c60cffc2 input=b2fbbf0bf04de8e5]*/ +bytes_replace_impl(PyBytesObject*self, Py_buffer *old, Py_buffer *new, + Py_ssize_t count) +/*[clinic end generated code: output=403dc9d7a83c5a1d input=b2fbbf0bf04de8e5]*/ { return (PyObject *)replace((PyBytesObject *) self, (const char *)old->buf, old->len, @@ -2929,8 +2931,9 @@ [clinic start generated code]*/ static PyObject * -bytes_decode_impl(PyBytesObject*self, const char *encoding, const char *errors) -/*[clinic end generated code: output=8038751c823b9038 input=958174769d2a40ca]*/ +bytes_decode_impl(PyBytesObject*self, const char *encoding, + const char *errors) +/*[clinic end generated code: output=2d2016ff8e0bb176 input=958174769d2a40ca]*/ { return PyUnicode_FromEncodedObject((PyObject*)self, encoding, errors); } diff --git a/Objects/clinic/bytearrayobject.c.h b/Objects/clinic/bytearrayobject.c.h --- a/Objects/clinic/bytearrayobject.c.h +++ b/Objects/clinic/bytearrayobject.c.h @@ -52,7 +52,8 @@ {"translate", (PyCFunction)bytearray_translate, METH_VARARGS, bytearray_translate__doc__}, static PyObject * -bytearray_translate_impl(PyByteArrayObject *self, PyObject *table, int group_right_1, PyObject *deletechars); +bytearray_translate_impl(PyByteArrayObject *self, PyObject *table, + int group_right_1, PyObject *deletechars); static PyObject * bytearray_translate(PyByteArrayObject *self, PyObject *args) @@ -140,7 +141,8 @@ {"replace", (PyCFunction)bytearray_replace, METH_VARARGS, bytearray_replace__doc__}, static PyObject * -bytearray_replace_impl(PyByteArrayObject *self, Py_buffer *old, Py_buffer *new, Py_ssize_t count); +bytearray_replace_impl(PyByteArrayObject *self, Py_buffer *old, + Py_buffer *new, Py_ssize_t count); static PyObject * bytearray_replace(PyByteArrayObject *self, PyObject *args) @@ -185,7 +187,8 @@ {"split", (PyCFunction)bytearray_split, METH_VARARGS|METH_KEYWORDS, bytearray_split__doc__}, static PyObject * -bytearray_split_impl(PyByteArrayObject *self, PyObject *sep, Py_ssize_t maxsplit); +bytearray_split_impl(PyByteArrayObject *self, PyObject *sep, + Py_ssize_t maxsplit); static PyObject * bytearray_split(PyByteArrayObject *self, PyObject *args, PyObject *kwargs) @@ -257,7 +260,8 @@ {"rsplit", (PyCFunction)bytearray_rsplit, METH_VARARGS|METH_KEYWORDS, bytearray_rsplit__doc__}, static PyObject * -bytearray_rsplit_impl(PyByteArrayObject *self, PyObject *sep, Py_ssize_t maxsplit); +bytearray_rsplit_impl(PyByteArrayObject *self, PyObject *sep, + Py_ssize_t maxsplit); static PyObject * bytearray_rsplit(PyByteArrayObject *self, PyObject *args, PyObject *kwargs) @@ -546,7 +550,8 @@ {"decode", (PyCFunction)bytearray_decode, METH_VARARGS|METH_KEYWORDS, bytearray_decode__doc__}, static PyObject * -bytearray_decode_impl(PyByteArrayObject *self, const char *encoding, const char *errors); +bytearray_decode_impl(PyByteArrayObject *self, const char *encoding, + const char *errors); static PyObject * bytearray_decode(PyByteArrayObject *self, PyObject *args, PyObject *kwargs) @@ -705,4 +710,4 @@ { return bytearray_sizeof_impl(self); } -/*[clinic end generated code: output=d763876718a66fc3 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=2a698741a4f14047 input=a9049054013a1b77]*/ diff --git a/Objects/clinic/bytesobject.c.h b/Objects/clinic/bytesobject.c.h --- a/Objects/clinic/bytesobject.c.h +++ b/Objects/clinic/bytesobject.c.h @@ -277,7 +277,8 @@ {"translate", (PyCFunction)bytes_translate, METH_VARARGS, bytes_translate__doc__}, static PyObject * -bytes_translate_impl(PyBytesObject *self, PyObject *table, int group_right_1, PyObject *deletechars); +bytes_translate_impl(PyBytesObject *self, PyObject *table, int group_right_1, + PyObject *deletechars); static PyObject * bytes_translate(PyBytesObject *self, PyObject *args) @@ -365,7 +366,8 @@ {"replace", (PyCFunction)bytes_replace, METH_VARARGS, bytes_replace__doc__}, static PyObject * -bytes_replace_impl(PyBytesObject*self, Py_buffer *old, Py_buffer *new, Py_ssize_t count); +bytes_replace_impl(PyBytesObject*self, Py_buffer *old, Py_buffer *new, + Py_ssize_t count); static PyObject * bytes_replace(PyBytesObject*self, PyObject *args) @@ -411,7 +413,8 @@ {"decode", (PyCFunction)bytes_decode, METH_VARARGS|METH_KEYWORDS, bytes_decode__doc__}, static PyObject * -bytes_decode_impl(PyBytesObject*self, const char *encoding, const char *errors); +bytes_decode_impl(PyBytesObject*self, const char *encoding, + const char *errors); static PyObject * bytes_decode(PyBytesObject*self, PyObject *args, PyObject *kwargs) @@ -493,4 +496,4 @@ exit: return return_value; } -/*[clinic end generated code: output=b9e69e1f7c8ccd14 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=deaf886e15270679 input=a9049054013a1b77]*/ diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -574,8 +574,9 @@ [clinic start generated code]*/ static PyObject * -builtin_format_impl(PyModuleDef *module, PyObject *value, PyObject *format_spec) -/*[clinic end generated code: output=fae3e927cc715466 input=e23f2f11e0098c64]*/ +builtin_format_impl(PyModuleDef *module, PyObject *value, + PyObject *format_spec) +/*[clinic end generated code: output=4341fd78a5f01764 input=e23f2f11e0098c64]*/ { return PyObject_Format(value, format_spec); } @@ -654,8 +655,10 @@ [clinic start generated code]*/ static PyObject * -builtin_compile_impl(PyModuleDef *module, PyObject *source, PyObject *filename, const char *mode, int flags, int dont_inherit, int optimize) -/*[clinic end generated code: output=4f41a315386bab9f input=c6212a9d21472f7e]*/ +builtin_compile_impl(PyModuleDef *module, PyObject *source, + PyObject *filename, const char *mode, int flags, + int dont_inherit, int optimize) +/*[clinic end generated code: output=31881762c1bb90c4 input=c6212a9d21472f7e]*/ { Py_buffer view = {NULL, NULL}; const char *str; @@ -805,8 +808,9 @@ [clinic start generated code]*/ static PyObject * -builtin_eval_impl(PyModuleDef *module, PyObject *source, PyObject *globals, PyObject *locals) -/*[clinic end generated code: output=90642b79dd8b08d6 input=31e42c1d2125b50b]*/ +builtin_eval_impl(PyModuleDef *module, PyObject *source, PyObject *globals, + PyObject *locals) +/*[clinic end generated code: output=7284501fb7b4d666 input=31e42c1d2125b50b]*/ { PyObject *result, *tmp = NULL; Py_buffer view = {NULL, NULL}; @@ -889,8 +893,9 @@ [clinic start generated code]*/ static PyObject * -builtin_exec_impl(PyModuleDef *module, PyObject *source, PyObject *globals, PyObject *locals) -/*[clinic end generated code: output=e8e0bbcde826a048 input=536e057b5e00d89e]*/ +builtin_exec_impl(PyModuleDef *module, PyObject *source, PyObject *globals, + PyObject *locals) +/*[clinic end generated code: output=83d574ef9d5d0b46 input=536e057b5e00d89e]*/ { PyObject *v; @@ -1303,8 +1308,9 @@ [clinic start generated code]*/ static PyObject * -builtin_setattr_impl(PyModuleDef *module, PyObject *obj, PyObject *name, PyObject *value) -/*[clinic end generated code: output=c5e0a3a3971333ed input=fbe7e53403116b93]*/ +builtin_setattr_impl(PyModuleDef *module, PyObject *obj, PyObject *name, + PyObject *value) +/*[clinic end generated code: output=d881c655c0f7e34f input=fbe7e53403116b93]*/ { if (PyObject_SetAttr(obj, name, value) != 0) return NULL; @@ -2328,8 +2334,9 @@ [clinic start generated code]*/ static PyObject * -builtin_isinstance_impl(PyModuleDef *module, PyObject *obj, PyObject *class_or_tuple) -/*[clinic end generated code: output=5e234dc3872d75a2 input=cf9eb0ad6bb9bad6]*/ +builtin_isinstance_impl(PyModuleDef *module, PyObject *obj, + PyObject *class_or_tuple) +/*[clinic end generated code: output=f960b7c12dbbeda0 input=cf9eb0ad6bb9bad6]*/ { int retval; @@ -2355,8 +2362,9 @@ [clinic start generated code]*/ static PyObject * -builtin_issubclass_impl(PyModuleDef *module, PyObject *cls, PyObject *class_or_tuple) -/*[clinic end generated code: output=6346a85ba15dbd7d input=923d03fa41fc352a]*/ +builtin_issubclass_impl(PyModuleDef *module, PyObject *cls, + PyObject *class_or_tuple) +/*[clinic end generated code: output=8b012a151940bbf2 input=923d03fa41fc352a]*/ { int retval; diff --git a/Python/clinic/bltinmodule.c.h b/Python/clinic/bltinmodule.c.h --- a/Python/clinic/bltinmodule.c.h +++ b/Python/clinic/bltinmodule.c.h @@ -83,7 +83,8 @@ {"format", (PyCFunction)builtin_format, METH_VARARGS, builtin_format__doc__}, static PyObject * -builtin_format_impl(PyModuleDef *module, PyObject *value, PyObject *format_spec); +builtin_format_impl(PyModuleDef *module, PyObject *value, + PyObject *format_spec); static PyObject * builtin_format(PyModuleDef *module, PyObject *args) @@ -152,7 +153,9 @@ {"compile", (PyCFunction)builtin_compile, METH_VARARGS|METH_KEYWORDS, builtin_compile__doc__}, static PyObject * -builtin_compile_impl(PyModuleDef *module, PyObject *source, PyObject *filename, const char *mode, int flags, int dont_inherit, int optimize); +builtin_compile_impl(PyModuleDef *module, PyObject *source, + PyObject *filename, const char *mode, int flags, + int dont_inherit, int optimize); static PyObject * builtin_compile(PyModuleDef *module, PyObject *args, PyObject *kwargs) @@ -221,7 +224,8 @@ {"eval", (PyCFunction)builtin_eval, METH_VARARGS, builtin_eval__doc__}, static PyObject * -builtin_eval_impl(PyModuleDef *module, PyObject *source, PyObject *globals, PyObject *locals); +builtin_eval_impl(PyModuleDef *module, PyObject *source, PyObject *globals, + PyObject *locals); static PyObject * builtin_eval(PyModuleDef *module, PyObject *args) @@ -257,7 +261,8 @@ {"exec", (PyCFunction)builtin_exec, METH_VARARGS, builtin_exec__doc__}, static PyObject * -builtin_exec_impl(PyModuleDef *module, PyObject *source, PyObject *globals, PyObject *locals); +builtin_exec_impl(PyModuleDef *module, PyObject *source, PyObject *globals, + PyObject *locals); static PyObject * builtin_exec(PyModuleDef *module, PyObject *args) @@ -353,7 +358,8 @@ {"setattr", (PyCFunction)builtin_setattr, METH_VARARGS, builtin_setattr__doc__}, static PyObject * -builtin_setattr_impl(PyModuleDef *module, PyObject *obj, PyObject *name, PyObject *value); +builtin_setattr_impl(PyModuleDef *module, PyObject *obj, PyObject *name, + PyObject *value); static PyObject * builtin_setattr(PyModuleDef *module, PyObject *args) @@ -605,7 +611,8 @@ {"isinstance", (PyCFunction)builtin_isinstance, METH_VARARGS, builtin_isinstance__doc__}, static PyObject * -builtin_isinstance_impl(PyModuleDef *module, PyObject *obj, PyObject *class_or_tuple); +builtin_isinstance_impl(PyModuleDef *module, PyObject *obj, + PyObject *class_or_tuple); static PyObject * builtin_isinstance(PyModuleDef *module, PyObject *args) @@ -638,7 +645,8 @@ {"issubclass", (PyCFunction)builtin_issubclass, METH_VARARGS, builtin_issubclass__doc__}, static PyObject * -builtin_issubclass_impl(PyModuleDef *module, PyObject *cls, PyObject *class_or_tuple); +builtin_issubclass_impl(PyModuleDef *module, PyObject *cls, + PyObject *class_or_tuple); static PyObject * builtin_issubclass(PyModuleDef *module, PyObject *args) @@ -656,4 +664,4 @@ exit: return return_value; } -/*[clinic end generated code: output=12db4cde92eb11b3 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=b308ab64aa4d4ff8 input=a9049054013a1b77]*/ diff --git a/Python/clinic/import.c.h b/Python/clinic/import.c.h --- a/Python/clinic/import.c.h +++ b/Python/clinic/import.c.h @@ -78,7 +78,8 @@ {"_fix_co_filename", (PyCFunction)_imp__fix_co_filename, METH_VARARGS, _imp__fix_co_filename__doc__}, static PyObject * -_imp__fix_co_filename_impl(PyModuleDef *module, PyCodeObject *code, PyObject *path); +_imp__fix_co_filename_impl(PyModuleDef *module, PyCodeObject *code, + PyObject *path); static PyObject * _imp__fix_co_filename(PyModuleDef *module, PyObject *args) @@ -295,7 +296,8 @@ {"load_dynamic", (PyCFunction)_imp_load_dynamic, METH_VARARGS, _imp_load_dynamic__doc__}, static PyObject * -_imp_load_dynamic_impl(PyModuleDef *module, PyObject *name, PyObject *path, PyObject *file); +_imp_load_dynamic_impl(PyModuleDef *module, PyObject *name, PyObject *path, + PyObject *file); static PyObject * _imp_load_dynamic(PyModuleDef *module, PyObject *args) @@ -320,4 +322,4 @@ #ifndef _IMP_LOAD_DYNAMIC_METHODDEF #define _IMP_LOAD_DYNAMIC_METHODDEF #endif /* !defined(_IMP_LOAD_DYNAMIC_METHODDEF) */ -/*[clinic end generated code: output=d41c392510815c5b input=a9049054013a1b77]*/ +/*[clinic end generated code: output=b64fe33fe76591cf input=a9049054013a1b77]*/ diff --git a/Python/import.c b/Python/import.c --- a/Python/import.c +++ b/Python/import.c @@ -904,8 +904,9 @@ [clinic start generated code]*/ static PyObject * -_imp__fix_co_filename_impl(PyModuleDef *module, PyCodeObject *code, PyObject *path) -/*[clinic end generated code: output=7afe5ba6b9d383e4 input=895ba50e78b82f05]*/ +_imp__fix_co_filename_impl(PyModuleDef *module, PyCodeObject *code, + PyObject *path) +/*[clinic end generated code: output=f4db56aac0a1327f input=895ba50e78b82f05]*/ { update_compiled_module(code, path); @@ -1934,8 +1935,9 @@ [clinic start generated code]*/ static PyObject * -_imp_load_dynamic_impl(PyModuleDef *module, PyObject *name, PyObject *path, PyObject *file) -/*[clinic end generated code: output=8b7ae431d795e1ba input=af64f06e4bad3526]*/ +_imp_load_dynamic_impl(PyModuleDef *module, PyObject *name, PyObject *path, + PyObject *file) +/*[clinic end generated code: output=e84e5f7f0f39bc54 input=af64f06e4bad3526]*/ { PyObject *mod; FILE *fp; diff --git a/Tools/clinic/clinic.py b/Tools/clinic/clinic.py --- a/Tools/clinic/clinic.py +++ b/Tools/clinic/clinic.py @@ -527,6 +527,58 @@ return s +def wrap_declarations(text, length=78): + """ + A simple-minded text wrapper for C function declarations. + + It views a declaration line as looking like this: + xxxxxxxx(xxxxxxxxx,xxxxxxxxx) + If called with length=30, it would wrap that line into + xxxxxxxx(xxxxxxxxx, + xxxxxxxxx) + (If the declaration has zero or one parameters, this + function won't wrap it.) + + If this doesn't work properly, it's probably better to + start from scratch with a more sophisticated algorithm, + rather than try and improve/debug this dumb little function. + """ + lines = [] + for line in text.split('\n'): + prefix, _, after_l_paren = line.partition('(') + if not after_l_paren: + lines.append(line) + continue + parameters, _, after_r_paren = after_l_paren.partition(')') + if not _: + lines.append(line) + continue + if ',' not in parameters: + lines.append(line) + continue + parameters = [x.strip() + ", " for x in parameters.split(',')] + prefix += "(" + if len(prefix) < length: + spaces = " " * len(prefix) + else: + spaces = " " * 4 + + while parameters: + line = prefix + first = True + while parameters: + if (not first and + (len(line) + len(parameters[0]) > length)): + break + line += parameters.pop(0) + first = False + if not parameters: + line = line.rstrip(", ") + ")" + after_r_paren + lines.append(line.rstrip()) + prefix = spaces + return "\n".join(lines) + + class CLanguage(Language): body_prefix = "#" @@ -1129,6 +1181,11 @@ s = template.format_map(template_dict) + # mild hack: + # reflow long impl declarations + if name in {"impl_prototype", "impl_definition"}: + s = wrap_declarations(s) + if clinic.line_prefix: s = indent_all_lines(s, clinic.line_prefix) if clinic.line_suffix: -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Apr 15 00:25:16 2015 From: python-checkins at python.org (gregory.p.smith) Date: Tue, 14 Apr 2015 22:25:16 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_issue9859=3A_add_the_missi?= =?utf-8?q?ng_versionadded_tag_to_the_documentation=2E?= Message-ID: <20150414222516.65842.5282@psf.io> https://hg.python.org/cpython/rev/0316811f33b2 changeset: 95666:0316811f33b2 user: Gregory P. Smith date: Tue Apr 14 15:25:01 2015 -0700 summary: issue9859: add the missing versionadded tag to the documentation. files: Doc/library/test.rst | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-) diff --git a/Doc/library/test.rst b/Doc/library/test.rst --- a/Doc/library/test.rst +++ b/Doc/library/test.rst @@ -577,6 +577,8 @@ By default this skips private attributes beginning with '_' but includes all magic methods, i.e. those starting and ending in '__'. + .. versionadded:: 3.5 + The :mod:`test.support` module defines the following classes: -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Apr 15 00:40:17 2015 From: python-checkins at python.org (steve.dower) Date: Tue, 14 Apr 2015 22:40:17 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Updates_Windows_installer_?= =?utf-8?q?to_promote_per-user_installs_over_all-users=2E?= Message-ID: <20150414224017.804.17180@psf.io> https://hg.python.org/cpython/rev/966f3b22a67b changeset: 95668:966f3b22a67b user: Steve Dower date: Tue Apr 14 18:34:04 2015 -0400 summary: Updates Windows installer to promote per-user installs over all-users. files: Tools/msi/bundle/Default.thm | 11 ++++----- Tools/msi/bundle/Default.wxl | 10 ++++---- Tools/msi/bundle/bootstrap/PythonBootstrapperApplication.cpp | 5 ++++ Tools/msi/bundle/bundle.wxs | 2 +- 4 files changed, 16 insertions(+), 12 deletions(-) diff --git a/Tools/msi/bundle/Default.thm b/Tools/msi/bundle/Default.thm --- a/Tools/msi/bundle/Default.thm +++ b/Tools/msi/bundle/Default.thm @@ -21,8 +21,7 @@ #(loc.InstallMessage) - - + #(loc.ShortPrependPathLabel) @@ -64,9 +63,9 @@ #(loc.Custom2Header) - #(loc.AssociateFilesLabel) - #(loc.PrependPathLabel) - #(loc.InstallAllUsersLabel) + #(loc.InstallAllUsersLabel) + #(loc.AssociateFilesLabel) + #(loc.PrependPathLabel) #(loc.PrecompileLabel) #(loc.Include_symbolsLabel) #(loc.Include_debugLabel) @@ -74,7 +73,7 @@ #(loc.CustomLocationLabel) - #(loc.CustomLocationHelpLabel) + #(loc.CustomLocationHelpLabel) diff --git a/Tools/msi/bundle/Default.wxl b/Tools/msi/bundle/Default.wxl --- a/Tools/msi/bundle/Default.wxl +++ b/Tools/msi/bundle/Default.wxl @@ -40,10 +40,10 @@ Logs to a specific file. By default, log files are created in %TEMP%. [WixBundleName] <a href="#">license terms</a>. I &agree to the license terms and conditions - Install for &All Users - [DefaultAllUsersTargetDir] - Install &Just for Me - [DefaultJustForMeTargetDir] + &Install Now + [DefaultJustForMeTargetDir] +Includes IDLE and pip +Creates shortcuts and file associations C&ustomize installation Choose location and features &Install @@ -51,7 +51,7 @@ Optional Features Advanced Options Customize install location - If not installing as administrator, you will require write permissions for this location. + You will require write permissions for the selected location. &Install &Next &Back diff --git a/Tools/msi/bundle/bootstrap/PythonBootstrapperApplication.cpp b/Tools/msi/bundle/bootstrap/PythonBootstrapperApplication.cpp --- a/Tools/msi/bundle/bootstrap/PythonBootstrapperApplication.cpp +++ b/Tools/msi/bundle/bootstrap/PythonBootstrapperApplication.cpp @@ -90,6 +90,7 @@ ID_CUSTOM_ASSOCIATE_FILES_CHECKBOX, ID_CUSTOM_INSTALL_ALL_USERS_CHECKBOX, ID_CUSTOM_BROWSE_BUTTON, + ID_CUSTOM_BROWSE_BUTTON_LABEL, ID_CUSTOM_INSTALL_BUTTON, ID_CUSTOM_NEXT_BUTTON, ID_CUSTOM1_BACK_BUTTON, @@ -149,6 +150,7 @@ { ID_CUSTOM_ASSOCIATE_FILES_CHECKBOX, L"AssociateFiles" }, { ID_CUSTOM_INSTALL_ALL_USERS_CHECKBOX, L"InstallAllUsers" }, { ID_CUSTOM_BROWSE_BUTTON, L"CustomBrowseButton" }, + { ID_CUSTOM_BROWSE_BUTTON_LABEL, L"CustomBrowseButtonLabel" }, { ID_CUSTOM_INSTALL_BUTTON, L"CustomInstallButton" }, { ID_CUSTOM_NEXT_BUTTON, L"CustomNextButton" }, { ID_CUSTOM1_BACK_BUTTON, L"Custom1BackButton" }, @@ -366,6 +368,7 @@ hr = BalGetNumericVariable(L"WixBundleElevated", &elevated); checked = ThemeIsControlChecked(_theme, ID_CUSTOM_INSTALL_ALL_USERS_CHECKBOX); ThemeControlElevates(_theme, ID_CUSTOM_INSTALL_BUTTON, checked && (FAILED(hr) || !elevated)); + ThemeShowControl(_theme, ID_CUSTOM_BROWSE_BUTTON_LABEL, checked ? SW_HIDE : SW_SHOW); ThemeGetTextControl(_theme, ID_TARGETDIR_EDITBOX, &targetDir); if (targetDir) { // Check the current value against the default to see @@ -467,8 +470,10 @@ } if (SUCCEEDED(BalGetNumericVariable(L"InstallAllUsers", &installAll))) { ThemeControlElevates(_theme, ID_CUSTOM_INSTALL_BUTTON, installAll && !elevated); + ThemeShowControl(_theme, ID_CUSTOM_BROWSE_BUTTON_LABEL, SW_HIDE); } else { installAll = 0; + ThemeShowControl(_theme, ID_CUSTOM_BROWSE_BUTTON_LABEL, SW_SHOW); } if (SUCCEEDED(BalGetNumericVariable(L"Include_launcher", &includeLauncher)) && includeLauncher) { diff --git a/Tools/msi/bundle/bundle.wxs b/Tools/msi/bundle/bundle.wxs --- a/Tools/msi/bundle/bundle.wxs +++ b/Tools/msi/bundle/bundle.wxs @@ -59,7 +59,7 @@ - + -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Apr 15 00:40:18 2015 From: python-checkins at python.org (steve.dower) Date: Tue, 14 Apr 2015 22:40:18 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Generates_and_signs_a_self?= =?utf-8?q?-extracting_executable_containing_an_embedded_Python=2E?= Message-ID: <20150414224017.56441.45191@psf.io> https://hg.python.org/cpython/rev/3da709cc631d changeset: 95667:3da709cc631d user: Steve Dower date: Tue Apr 14 18:34:04 2015 -0400 summary: Generates and signs a self-extracting executable containing an embedded Python. files: Tools/msi/buildrelease.bat | 9 + Tools/msi/make_zip.proj | 37 +++++ Tools/msi/make_zip.py | 160 +++++++++++++++++++++++++ 3 files changed, 206 insertions(+), 0 deletions(-) diff --git a/Tools/msi/buildrelease.bat b/Tools/msi/buildrelease.bat --- a/Tools/msi/buildrelease.bat +++ b/Tools/msi/buildrelease.bat @@ -64,6 +64,13 @@ set _DLLTOOL_PATH= :skipdlltoolsearch +where rar /q && goto skiprarsearch +set _RAR_PATH= +where /R "%ProgramFiles%\WinRAR" rar > "%TEMP%\rar.loc" 2> nul && set /P _RAR_PATH= < "%TEMP%\rar.loc" & del "%TEMP%\rar.loc" +where /R "%ProgramFiles(x86)%\WinRAR" rar > "%TEMP%\rar.loc" 2> nul && set /P _RAR_PATH= < "%TEMP%\rar.loc" & del "%TEMP%\rar.loc" +if not exist "%_RAR_PATH%" echo Cannot find WinRAR on PATH or in external && pause +:skiprarsearch + if defined BUILDX86 ( call :build x86 if errorlevel 1 exit /B @@ -135,6 +142,8 @@ msbuild "%D%bundle\releaseweb.wixproj" /t:Rebuild %BUILDOPTS% %CERTOPTS% /p:RebuildAll=false if errorlevel 1 exit /B +if defined _RAR_PATH msbuild "%D%make_zip.proj" /t:Build %BUILDOPTS% %CERTOPTS% "/p:RAR=%_RAR_PATH%" + if not "%OUTDIR%" EQU "" ( mkdir "%OUTDIR%\%OUTDIR_PLAT%" copy /Y "%BUILD%en-us\*.cab" "%OUTDIR%\%OUTDIR_PLAT%" diff --git a/Tools/msi/make_zip.proj b/Tools/msi/make_zip.proj new file mode 100644 --- /dev/null +++ b/Tools/msi/make_zip.proj @@ -0,0 +1,37 @@ + + + + {10487945-15D1-4092-A214-338395C4116B} + python + + + + + + + python-$(PythonVersion)-embed-$(ArchName) + .exe + $(OutputPath)\en-us\$(TargetName)$(TargetExt) + "$(PythonExe)" "$(MSBuildThisFileDirectory)\make_zip.py" + $(Arguments) -e -o "$(TargetPath)" -t "$(IntermediateOutputPath)\zip_$(ArchName)" -a $(ArchName) + $(Arguments) --rar "$(RAR)" + set DOC_FILENAME=python$(PythonVersion).chm + + + + + + + + + + + + + + + + + diff --git a/Tools/msi/make_zip.py b/Tools/msi/make_zip.py new file mode 100644 --- /dev/null +++ b/Tools/msi/make_zip.py @@ -0,0 +1,160 @@ +import argparse +import re +import sys +import shutil +import os +import tempfile + +from pathlib import Path +from zipfile import ZipFile, ZIP_DEFLATED +import subprocess + +TKTCL_RE = re.compile(r'^(_?tk|tcl).+\.(pyd|dll)', re.IGNORECASE) +DEBUG_RE = re.compile(r'_d\.(pyd|dll|exe)$', re.IGNORECASE) +PYTHON_DLL_RE = re.compile(r'python\d\d?\.dll$', re.IGNORECASE) + +def is_not_debug(p): + return not DEBUG_RE.search(p.name) and not TKTCL_RE.search(p.name) + +def is_not_debug_or_python(p): + return is_not_debug(p) and not PYTHON_DLL_RE.search(p.name) + +def include_in_lib(p): + name = p.name.lower() + if p.is_dir(): + if name in {'__pycache__', 'ensurepip', 'idlelib', 'pydoc_data', 'tkinter', 'turtledemo'}: + return False + if name.startswith('plat-'): + return False + if name == 'test' and p.parts[-2].lower() == 'lib': + return False + return True + + if name in {'_ctypes_test.pyd', '_testbuffer.pyd', '_testcapi.pyd', '_testimportmultiple.pyd', 'xxlimited.pyd'}: + return False + return p.suffix.lower() not in {'.pyc', '.pyo'} + +def include_in_tools(p): + if p.is_dir() and p.name.lower() in {'scripts', 'i18n', 'pynche', 'demo', 'parser'}: + return True + + return p.suffix.lower() in {'.py', '.pyw', '.txt'} + +FULL_LAYOUT = [ + ('/', 'PCBuild/$arch', 'python*.exe', is_not_debug), + ('/', 'PCBuild/$arch', 'python*.dll', is_not_debug), + ('DLLs/', 'PCBuild/$arch', '*.pyd', is_not_debug), + ('DLLs/', 'PCBuild/$arch', '*.dll', is_not_debug), + ('include/', 'include', '*.h', None), + ('include/', 'PC', 'pyconfig.h', None), + ('Lib/', 'Lib', '**/*', include_in_lib), + ('Tools/', 'Tools', '**/*', include_in_tools), +] + +if os.getenv('DOC_FILENAME'): + FULL_LAYOUT.append(('Doc/', 'Doc/build/htmlhelp', os.getenv('DOC_FILENAME'), None)) + +EMBED_LAYOUT = [ + ('/', 'PCBuild/$arch', 'python*.exe', is_not_debug), + ('/', 'PCBuild/$arch', '*.pyd', is_not_debug), + ('/', 'PCBuild/$arch', '*.dll', is_not_debug), + ('python35.zip', 'Lib', '**/*', include_in_lib), +] + +def copy_to_layout(target, source, rel_sources): + count = 0 + + if target.suffix.lower() == '.zip': + if target.exists(): + target.unlink() + + with ZipFile(str(target), 'w', ZIP_DEFLATED) as f: + for s, rel in rel_sources: + f.write(str(s), str(rel)) + count += 1 + + else: + for s, rel in rel_sources: + try: + (target / rel).parent.mkdir(parents=True) + except FileExistsError: + pass + shutil.copy(str(s), str(target / rel)) + count += 1 + + return count + +def rglob(root, pattern, condition): + dirs = [root] + recurse = pattern[:3] in {'**/', '**\\'} + while dirs: + d = dirs.pop(0) + for f in d.glob(pattern[3:] if recurse else pattern): + if recurse and f.is_dir() and (not condition or condition(f)): + dirs.append(f) + elif f.is_file() and (not condition or condition(f)): + yield f, f.relative_to(root) + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument('-s', '--source', metavar='dir', help='The directory containing the repository root', type=Path) + parser.add_argument('-o', '--out', metavar='file', help='The name of the output self-extracting archive', type=Path, required=True) + parser.add_argument('-t', '--temp', metavar='dir', help='A directory to temporarily extract files into', type=Path, default=None) + parser.add_argument('-e', '--embed', help='Create an embedding layout', action='store_true', default=False) + parser.add_argument('-a', '--arch', help='Specify the architecture to use (win32/amd64)', type=str, default="win32") + parser.add_argument('--rar', help='Full path to WinRAR compressor (rar.exe)', type=Path, default=Path("rar.exe")) + ns = parser.parse_args() + + source = ns.source or (Path(__file__).parent.parent.parent) + out = ns.out + arch = ns.arch + rar = getattr(ns, 'rar') + assert isinstance(source, Path) + assert isinstance(out, Path) + assert isinstance(arch, str) + assert isinstance(rar, Path) + + if ns.temp: + temp = ns.temp + delete_temp = False + else: + temp = Path(tempfile.mkdtemp()) + delete_temp = True + + try: + out.parent.mkdir(parents=True) + except FileExistsError: + pass + try: + temp.mkdir(parents=True) + except FileExistsError: + pass + + layout = EMBED_LAYOUT if ns.embed else FULL_LAYOUT + + try: + for t, s, p, c in layout: + s = source / s.replace("$arch", arch) + copied = copy_to_layout( + temp / t.rstrip('/'), + source, + rglob(s, p, c) + ) + print('Copied {} files'.format(copied)) + + if rar and rar.is_file(): + subprocess.check_call([ + str(rar), + "a", + "-m5", "-ed", "-ep1", "-s", "-r", + "-sfxwincon.sfx", + str(out), + str(temp / '*') + ]) + finally: + if delete_temp: + shutil.rmtree(temp, True) + + +if __name__ == "__main__": + sys.exit(int(main() or 0)) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Apr 15 00:42:07 2015 From: python-checkins at python.org (antoine.pitrou) Date: Tue, 14 Apr 2015 22:42:07 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2321217=3A_inspect?= =?utf-8?q?=2Egetsourcelines=28=29_now_tries_to_compute_the_start_and?= Message-ID: <20150414224207.8639.48579@psf.io> https://hg.python.org/cpython/rev/ac86e5b2d45b changeset: 95669:ac86e5b2d45b user: Antoine Pitrou date: Wed Apr 15 00:41:29 2015 +0200 summary: Issue #21217: inspect.getsourcelines() now tries to compute the start and end lines from the code object, fixing an issue when a lambda function is used as decorator argument. Patch by Thomas Ballinger. files: Lib/inspect.py | 37 +++++++++++++++--------- Lib/test/inspect_fodder2.py | 10 ++++++- Lib/test/test_inspect.py | 11 ++++++- Misc/ACKS | 1 + Misc/NEWS | 7 ++++- 5 files changed, 49 insertions(+), 17 deletions(-) diff --git a/Lib/inspect.py b/Lib/inspect.py --- a/Lib/inspect.py +++ b/Lib/inspect.py @@ -32,6 +32,7 @@ 'Yury Selivanov ') import ast +import dis import enum import importlib.machinery import itertools @@ -49,18 +50,10 @@ from collections import namedtuple, OrderedDict # Create constants for the compiler flags in Include/code.h -# We try to get them from dis to avoid duplication, but fall -# back to hard-coding so the dependency is optional -try: - from dis import COMPILER_FLAG_NAMES as _flag_names -except ImportError: - CO_OPTIMIZED, CO_NEWLOCALS = 0x1, 0x2 - CO_VARARGS, CO_VARKEYWORDS = 0x4, 0x8 - CO_NESTED, CO_GENERATOR, CO_NOFREE = 0x10, 0x20, 0x40 -else: - mod_dict = globals() - for k, v in _flag_names.items(): - mod_dict["CO_" + v] = k +# We try to get them from dis to avoid duplication +mod_dict = globals() +for k, v in dis.COMPILER_FLAG_NAMES.items(): + mod_dict["CO_" + v] = k # See Include/object.h TPFLAGS_IS_ABSTRACT = 1 << 20 @@ -888,6 +881,14 @@ pass return lines[:blockfinder.last] +def _line_number_helper(code_obj, lines, lnum): + """Return a list of source lines and starting line number for a code object. + + The arguments must be a code object with lines and lnum from findsource. + """ + _, end_line = list(dis.findlinestarts(code_obj))[-1] + return lines[lnum:end_line], lnum + 1 + def getsourcelines(object): """Return a list of source lines and starting line number for an object. @@ -899,8 +900,16 @@ object = unwrap(object) lines, lnum = findsource(object) - if ismodule(object): return lines, 0 - else: return getblock(lines[lnum:]), lnum + 1 + if ismodule(object): + return lines, 0 + elif iscode(object): + return _line_number_helper(object, lines, lnum) + elif isfunction(object): + return _line_number_helper(object.__code__, lines, lnum) + elif ismethod(object): + return _line_number_helper(object.__func__.__code__, lines, lnum) + else: + return getblock(lines[lnum:]), lnum + 1 def getsource(object): """Return the text of the source code for an object. diff --git a/Lib/test/inspect_fodder2.py b/Lib/test/inspect_fodder2.py --- a/Lib/test/inspect_fodder2.py +++ b/Lib/test/inspect_fodder2.py @@ -110,6 +110,14 @@ def keyword_only_arg(*, arg): pass + at wrap(lambda: None) +def func114(): + return 115 + +class ClassWithMethod: + def method(self): + pass + from functools import wraps def decorator(func): @@ -118,7 +126,7 @@ return 42 return fake -#line 121 +#line 129 @decorator def real(): return 20 diff --git a/Lib/test/test_inspect.py b/Lib/test/test_inspect.py --- a/Lib/test/test_inspect.py +++ b/Lib/test/test_inspect.py @@ -392,6 +392,9 @@ finally: linecache.getlines = getlines + def test_getsource_on_code_object(self): + self.assertSourceEqual(mod.eggs.__code__, 12, 18) + class TestDecorators(GetSourceBase): fodderModule = mod2 @@ -402,7 +405,10 @@ self.assertSourceEqual(mod2.gone, 9, 10) def test_getsource_unwrap(self): - self.assertSourceEqual(mod2.real, 122, 124) + self.assertSourceEqual(mod2.real, 130, 132) + + def test_decorator_with_lambda(self): + self.assertSourceEqual(mod2.func114, 113, 115) class TestOneliners(GetSourceBase): fodderModule = mod2 @@ -497,6 +503,9 @@ self.assertRaises(IOError, inspect.findsource, co) self.assertRaises(IOError, inspect.getsource, co) + def test_getsource_on_method(self): + self.assertSourceEqual(mod2.ClassWithMethod.method, 118, 119) + class TestNoEOL(GetSourceBase): def __init__(self, *args, **kwargs): self.tempdir = TESTFN + '_dir' diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -72,6 +72,7 @@ Stig Bakken Greg Ball Luigi Ballabio +Thomas Ballinger Jeff Balogh Manuel Balsera Matt Bandy diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -1,4 +1,4 @@ -+++++++++++ +?+++++++++++ Python News +++++++++++ @@ -9,6 +9,7 @@ Core and Builtins ----------------- + - Issue #22631: Added Linux-specific socket constant CAN_RAW_FD_FRAMES. Patch courtesy of Joe Jevnik. @@ -31,6 +32,10 @@ Library ------- +- Issue #21217: inspect.getsourcelines() now tries to compute the start and + end lines from the code object, fixing an issue when a lambda function is + used as decorator argument. Patch by Thomas Ballinger. + - Issue #23811: Add missing newline to the PyCompileError error message. Patch by Alex Shkop. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Apr 15 01:14:40 2015 From: python-checkins at python.org (gregory.p.smith) Date: Tue, 14 Apr 2015 23:14:40 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Add_a_subprocess=2Erun=28?= =?utf-8?q?=29_function_than_returns_a_CalledProcess_instance_for_a?= Message-ID: <20150414231440.64477.74446@psf.io> https://hg.python.org/cpython/rev/f0a00ee094ff changeset: 95670:f0a00ee094ff user: Gregory P. Smith date: Tue Apr 14 16:14:25 2015 -0700 summary: Add a subprocess.run() function than returns a CalledProcess instance for a more consistent API than the existing call* functions. (enhancement from issue 23342) files: Doc/library/subprocess.rst | 295 ++++++++++++++--------- Doc/whatsnew/3.5.rst | 8 + Lib/subprocess.py | 124 ++++++++- Lib/test/test_subprocess.py | 97 +++++++ Misc/NEWS | 3 + 5 files changed, 389 insertions(+), 138 deletions(-) diff --git a/Doc/library/subprocess.rst b/Doc/library/subprocess.rst --- a/Doc/library/subprocess.rst +++ b/Doc/library/subprocess.rst @@ -25,104 +25,32 @@ Using the :mod:`subprocess` Module ---------------------------------- -The recommended approach to invoking subprocesses is to use the following -convenience functions for all use cases they can handle. For more advanced +The recommended approach to invoking subprocesses is to use the :func:`run` +function for all use cases it can handle. For more advanced use cases, the underlying :class:`Popen` interface can be used directly. +The :func:`run` function was added in Python 3.5; if you need to retain +compatibility with older versions, see the :ref:`call-function-trio` section. -.. function:: call(args, *, stdin=None, stdout=None, stderr=None, shell=False, timeout=None) + +.. function:: run(args, *, stdin=None, input=None, stdout=None, stderr=None,\ + shell=False, timeout=None, check=False) Run the command described by *args*. Wait for command to complete, then - return the :attr:`returncode` attribute. + return a :class:`CompletedProcess` instance. The arguments shown above are merely the most common ones, described below in :ref:`frequently-used-arguments` (hence the use of keyword-only notation in the abbreviated signature). The full function signature is largely the - same as that of the :class:`Popen` constructor - this function passes all - supplied arguments other than *timeout* directly through to that interface. + same as that of the :class:`Popen` constructor - apart from *timeout*, + *input* and *check*, all the arguments to this function are passed through to + that interface. - The *timeout* argument is passed to :meth:`Popen.wait`. If the timeout - expires, the child process will be killed and then waited for again. The - :exc:`TimeoutExpired` exception will be re-raised after the child process - has terminated. + This does not capture stdout or stderr by default. To do so, pass + :data:`PIPE` for the *stdout* and/or *stderr* arguments. - Examples:: - - >>> subprocess.call(["ls", "-l"]) - 0 - - >>> subprocess.call("exit 1", shell=True) - 1 - - .. note:: - - Do not use ``stdout=PIPE`` or ``stderr=PIPE`` with this - function. The child process will block if it generates enough - output to a pipe to fill up the OS pipe buffer as the pipes are - not being read from. - - .. versionchanged:: 3.3 - *timeout* was added. - - -.. function:: check_call(args, *, stdin=None, stdout=None, stderr=None, shell=False, timeout=None) - - Run command with arguments. Wait for command to complete. If the return - code was zero then return, otherwise raise :exc:`CalledProcessError`. The - :exc:`CalledProcessError` object will have the return code in the - :attr:`~CalledProcessError.returncode` attribute. - - The arguments shown above are merely the most common ones, described below - in :ref:`frequently-used-arguments` (hence the use of keyword-only notation - in the abbreviated signature). The full function signature is largely the - same as that of the :class:`Popen` constructor - this function passes all - supplied arguments other than *timeout* directly through to that interface. - - The *timeout* argument is passed to :meth:`Popen.wait`. If the timeout - expires, the child process will be killed and then waited for again. The - :exc:`TimeoutExpired` exception will be re-raised after the child process - has terminated. - - Examples:: - - >>> subprocess.check_call(["ls", "-l"]) - 0 - - >>> subprocess.check_call("exit 1", shell=True) - Traceback (most recent call last): - ... - subprocess.CalledProcessError: Command 'exit 1' returned non-zero exit status 1 - - .. note:: - - Do not use ``stdout=PIPE`` or ``stderr=PIPE`` with this - function. The child process will block if it generates enough - output to a pipe to fill up the OS pipe buffer as the pipes are - not being read from. - - .. versionchanged:: 3.3 - *timeout* was added. - - -.. function:: check_output(args, *, input=None, stdin=None, stderr=None, shell=False, universal_newlines=False, timeout=None) - - Run command with arguments and return its output. - - If the return code was non-zero it raises a :exc:`CalledProcessError`. The - :exc:`CalledProcessError` object will have the return code in the - :attr:`~CalledProcessError.returncode` attribute and any output in the - :attr:`~CalledProcessError.output` attribute. - - The arguments shown above are merely the most common ones, described below - in :ref:`frequently-used-arguments` (hence the use of keyword-only notation - in the abbreviated signature). The full function signature is largely the - same as that of the :class:`Popen` constructor - this functions passes all - supplied arguments other than *input* and *timeout* directly through to - that interface. In addition, *stdout* is not permitted as an argument, as - it is used internally to collect the output from the subprocess. - - The *timeout* argument is passed to :meth:`Popen.wait`. If the timeout - expires, the child process will be killed and then waited for again. The + The *timeout* argument is passed to :meth:`Popen.communicate`. If the timeout + expires, the child process will be killed and waited for. The :exc:`TimeoutExpired` exception will be re-raised after the child process has terminated. @@ -132,53 +60,64 @@ is automatically created with ``stdin=PIPE``, and the *stdin* argument may not be used as well. + If *check* is True, and the process exits with a non-zero exit code, a + :exc:`CalledProcessError` exception will be raised. Attributes of that + exception hold the arguments, the exit code, and stdout and stderr if they + were captured. + Examples:: - >>> subprocess.check_output(["echo", "Hello World!"]) - b'Hello World!\n' + >>> subprocess.run(["ls", "-l"]) # doesn't capture output + CompletedProcess(args=['ls', '-l'], returncode=0) - >>> subprocess.check_output(["echo", "Hello World!"], universal_newlines=True) - 'Hello World!\n' - - >>> subprocess.check_output(["sed", "-e", "s/foo/bar/"], - ... input=b"when in the course of fooman events\n") - b'when in the course of barman events\n' - - >>> subprocess.check_output("exit 1", shell=True) + >>> subprocess.run("exit 1", shell=True, check=True) Traceback (most recent call last): - ... + ... subprocess.CalledProcessError: Command 'exit 1' returned non-zero exit status 1 - By default, this function will return the data as encoded bytes. The actual - encoding of the output data may depend on the command being invoked, so the - decoding to text will often need to be handled at the application level. + >>> subprocess.run(["ls", "-l", "/dev/null"], stdout=subprocess.PIPE) + CompletedProcess(args=['ls', '-l', '/dev/null'], returncode=0, + stdout=b'crw-rw-rw- 1 root root 1, 3 Jan 23 16:23 /dev/null\n') - This behaviour may be overridden by setting *universal_newlines* to - ``True`` as described below in :ref:`frequently-used-arguments`. + .. versionadded:: 3.5 - To also capture standard error in the result, use - ``stderr=subprocess.STDOUT``:: +.. class:: CompletedProcess - >>> subprocess.check_output( - ... "ls non_existent_file; exit 0", - ... stderr=subprocess.STDOUT, - ... shell=True) - 'ls: non_existent_file: No such file or directory\n' + The return value from :func:`run`, representing a process that has finished. - .. note:: + .. attribute:: args - Do not use ``stdout=PIPE`` or ``stderr=PIPE`` with this - function. The child process will block if it generates enough - output to a pipe to fill up the OS pipe buffer as the pipes are - not being read from. + The arguments used to launch the process. This may be a list or a string. - .. versionadded:: 3.1 + .. attribute:: returncode - .. versionchanged:: 3.3 - *timeout* was added. + Exit status of the child process. Typically, an exit status of 0 indicates + that it ran successfully. - .. versionchanged:: 3.4 - *input* was added. + A negative value ``-N`` indicates that the child was terminated by signal + ``N`` (POSIX only). + + .. attribute:: stdout + + Captured stdout from the child process. A bytes sequence, or a string if + :func:`run` was called with ``universal_newlines=True``. None if stdout + was not captured. + + If you ran the process with ``stderr=subprocess.STDOUT``, stdout and + stderr will be combined in this attribute, and :attr:`stderr` will be + None. + + .. attribute:: stderr + + Captured stderr from the child process. A bytes sequence, or a string if + :func:`run` was called with ``universal_newlines=True``. None if stderr + was not captured. + + .. method:: check_returncode() + + If :attr:`returncode` is non-zero, raise a :exc:`CalledProcessError`. + + .. versionadded:: 3.5 .. data:: DEVNULL @@ -225,11 +164,22 @@ .. attribute:: output - Output of the child process if this exception is raised by + Output of the child process if it was captured by :func:`run` or :func:`check_output`. Otherwise, ``None``. + .. attribute:: stdout + + Alias for output, for symmetry with :attr:`stderr`. + + .. attribute:: stderr + + Stderr output of the child process if it was captured by :func:`run`. + Otherwise, ``None``. + .. versionadded:: 3.3 + .. versionchanged:: 3.5 + *stdout* and *stderr* attributes added .. exception:: CalledProcessError @@ -246,9 +196,20 @@ .. attribute:: output - Output of the child process if this exception is raised by + Output of the child process if it was captured by :func:`run` or :func:`check_output`. Otherwise, ``None``. + .. attribute:: stdout + + Alias for output, for symmetry with :attr:`stderr`. + + .. attribute:: stderr + + Stderr output of the child process if it was captured by :func:`run`. + Otherwise, ``None``. + + .. versionchanged:: 3.5 + *stdout* and *stderr* attributes added .. _frequently-used-arguments: @@ -852,6 +813,96 @@ This flag is ignored if :data:`CREATE_NEW_CONSOLE` is specified. +.. _call-function-trio: + +Older high-level API +-------------------- + +Prior to Python 3.5, these three functions comprised the high level API to +subprocess. You can now use :func:`run` in many cases, but lots of existing code +calls these functions. + +.. function:: call(args, *, stdin=None, stdout=None, stderr=None, shell=False, timeout=None) + + Run the command described by *args*. Wait for command to complete, then + return the :attr:`returncode` attribute. + + This is equivalent to:: + + run(...).returncode + + (except that the *input* and *check* parameters are not supported) + + .. note:: + + Do not use ``stdout=PIPE`` or ``stderr=PIPE`` with this + function. The child process will block if it generates enough + output to a pipe to fill up the OS pipe buffer as the pipes are + not being read from. + + .. versionchanged:: 3.3 + *timeout* was added. + +.. function:: check_call(args, *, stdin=None, stdout=None, stderr=None, shell=False, timeout=None) + + Run command with arguments. Wait for command to complete. If the return + code was zero then return, otherwise raise :exc:`CalledProcessError`. The + :exc:`CalledProcessError` object will have the return code in the + :attr:`~CalledProcessError.returncode` attribute. + + This is equivalent to:: + + run(..., check=True) + + (except that the *input* parameter is not supported) + + .. note:: + + Do not use ``stdout=PIPE`` or ``stderr=PIPE`` with this + function. The child process will block if it generates enough + output to a pipe to fill up the OS pipe buffer as the pipes are + not being read from. + + .. versionchanged:: 3.3 + *timeout* was added. + + +.. function:: check_output(args, *, input=None, stdin=None, stderr=None, shell=False, universal_newlines=False, timeout=None) + + Run command with arguments and return its output. + + If the return code was non-zero it raises a :exc:`CalledProcessError`. The + :exc:`CalledProcessError` object will have the return code in the + :attr:`~CalledProcessError.returncode` attribute and any output in the + :attr:`~CalledProcessError.output` attribute. + + This is equivalent to:: + + run(..., check=True, stdout=PIPE).stdout + + By default, this function will return the data as encoded bytes. The actual + encoding of the output data may depend on the command being invoked, so the + decoding to text will often need to be handled at the application level. + + This behaviour may be overridden by setting *universal_newlines* to + ``True`` as described above in :ref:`frequently-used-arguments`. + + To also capture standard error in the result, use + ``stderr=subprocess.STDOUT``:: + + >>> subprocess.check_output( + ... "ls non_existent_file; exit 0", + ... stderr=subprocess.STDOUT, + ... shell=True) + 'ls: non_existent_file: No such file or directory\n' + + .. versionadded:: 3.1 + + .. versionchanged:: 3.3 + *timeout* was added. + + .. versionchanged:: 3.4 + *input* was added. .. _subprocess-replacements: diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -492,6 +492,14 @@ * The :func:`tarfile.open` function now supports ``'x'`` (exclusive creation) mode. (Contributed by Berker Peksag in :issue:`21717`.) +subprocess +---------- + +* The new :func:`subprocess.run` function runs subprocesses and returns a + :class:`subprocess.CompletedProcess` object. It Provides a more consistent + API than :func:`~subprocess.call`, :func:`~subprocess.check_call` and + :func:`~subprocess.check_output`. + time ---- diff --git a/Lib/subprocess.py b/Lib/subprocess.py --- a/Lib/subprocess.py +++ b/Lib/subprocess.py @@ -377,27 +377,51 @@ The exit status will be stored in the returncode attribute; check_output() will also store the output in the output attribute. """ - def __init__(self, returncode, cmd, output=None): + def __init__(self, returncode, cmd, output=None, stderr=None): self.returncode = returncode self.cmd = cmd self.output = output + self.stderr = stderr + def __str__(self): return "Command '%s' returned non-zero exit status %d" % (self.cmd, self.returncode) + @property + def stdout(self): + """Alias for output attribute, to match stderr""" + return self.output + + @stdout.setter + def stdout(self, value): + # There's no obvious reason to set this, but allow it anyway so + # .stdout is a transparent alias for .output + self.output = value + class TimeoutExpired(SubprocessError): """This exception is raised when the timeout expires while waiting for a child process. """ - def __init__(self, cmd, timeout, output=None): + def __init__(self, cmd, timeout, output=None, stderr=None): self.cmd = cmd self.timeout = timeout self.output = output + self.stderr = stderr def __str__(self): return ("Command '%s' timed out after %s seconds" % (self.cmd, self.timeout)) + @property + def stdout(self): + return self.output + + @stdout.setter + def stdout(self, value): + # There's no obvious reason to set this, but allow it anyway so + # .stdout is a transparent alias for .output + self.output = value + if _mswindows: import threading @@ -433,8 +457,8 @@ __all__ = ["Popen", "PIPE", "STDOUT", "call", "check_call", "getstatusoutput", - "getoutput", "check_output", "CalledProcessError", "DEVNULL", - "SubprocessError", "TimeoutExpired"] + "getoutput", "check_output", "run", "CalledProcessError", "DEVNULL", + "SubprocessError", "TimeoutExpired", "CompletedProcess"] # NOTE: We intentionally exclude list2cmdline as it is # considered an internal implementation detail. issue10838. @@ -595,29 +619,97 @@ """ if 'stdout' in kwargs: raise ValueError('stdout argument not allowed, it will be overridden.') - if 'input' in kwargs: + + if 'input' in kwargs and kwargs['input'] is None: + # Explicitly passing input=None was previously equivalent to passing an + # empty string. That is maintained here for backwards compatibility. + kwargs['input'] = '' if kwargs.get('universal_newlines', False) else b'' + + return run(*popenargs, stdout=PIPE, timeout=timeout, check=True, + **kwargs).stdout + + +class CompletedProcess(object): + """A process that has finished running. + + This is returned by run(). + + Attributes: + args: The list or str args passed to run(). + returncode: The exit code of the process, negative for signals. + stdout: The standard output (None if not captured). + stderr: The standard error (None if not captured). + """ + def __init__(self, args, returncode, stdout=None, stderr=None): + self.args = args + self.returncode = returncode + self.stdout = stdout + self.stderr = stderr + + def __repr__(self): + args = ['args={!r}'.format(self.args), + 'returncode={!r}'.format(self.returncode)] + if self.stdout is not None: + args.append('stdout={!r}'.format(self.stdout)) + if self.stderr is not None: + args.append('stderr={!r}'.format(self.stderr)) + return "{}({})".format(type(self).__name__, ', '.join(args)) + + def check_returncode(self): + """Raise CalledProcessError if the exit code is non-zero.""" + if self.returncode: + raise CalledProcessError(self.returncode, self.args, self.stdout, + self.stderr) + + +def run(*popenargs, input=None, timeout=None, check=False, **kwargs): + """Run command with arguments and return a CompletedProcess instance. + + The returned instance will have attributes args, returncode, stdout and + stderr. By default, stdout and stderr are not captured, and those attributes + will be None. Pass stdout=PIPE and/or stderr=PIPE in order to capture them. + + If check is True and the exit code was non-zero, it raises a + CalledProcessError. The CalledProcessError object will have the return code + in the returncode attribute, and output & stderr attributes if those streams + were captured. + + If timeout is given, and the process takes too long, a TimeoutExpired + exception will be raised. + + There is an optional argument "input", allowing you to + pass a string to the subprocess's stdin. If you use this argument + you may not also use the Popen constructor's "stdin" argument, as + it will be used internally. + + The other arguments are the same as for the Popen constructor. + + If universal_newlines=True is passed, the "input" argument must be a + string and stdout/stderr in the returned object will be strings rather than + bytes. + """ + if input is not None: if 'stdin' in kwargs: raise ValueError('stdin and input arguments may not both be used.') - inputdata = kwargs['input'] - del kwargs['input'] kwargs['stdin'] = PIPE - else: - inputdata = None - with Popen(*popenargs, stdout=PIPE, **kwargs) as process: + + with Popen(*popenargs, **kwargs) as process: try: - output, unused_err = process.communicate(inputdata, timeout=timeout) + stdout, stderr = process.communicate(input, timeout=timeout) except TimeoutExpired: process.kill() - output, unused_err = process.communicate() - raise TimeoutExpired(process.args, timeout, output=output) + stdout, stderr = process.communicate() + raise TimeoutExpired(process.args, timeout, output=stdout, + stderr=stderr) except: process.kill() process.wait() raise retcode = process.poll() - if retcode: - raise CalledProcessError(retcode, process.args, output=output) - return output + if check and retcode: + raise CalledProcessError(retcode, process.args, + output=stdout, stderr=stderr) + return CompletedProcess(process.args, retcode, stdout, stderr) def list2cmdline(seq): diff --git a/Lib/test/test_subprocess.py b/Lib/test/test_subprocess.py --- a/Lib/test/test_subprocess.py +++ b/Lib/test/test_subprocess.py @@ -1232,6 +1232,102 @@ fds_after_exception = os.listdir(fd_directory) self.assertEqual(fds_before_popen, fds_after_exception) + +class RunFuncTestCase(BaseTestCase): + def run_python(self, code, **kwargs): + """Run Python code in a subprocess using subprocess.run""" + argv = [sys.executable, "-c", code] + return subprocess.run(argv, **kwargs) + + def test_returncode(self): + # call() function with sequence argument + cp = self.run_python("import sys; sys.exit(47)") + self.assertEqual(cp.returncode, 47) + with self.assertRaises(subprocess.CalledProcessError): + cp.check_returncode() + + def test_check(self): + with self.assertRaises(subprocess.CalledProcessError) as c: + self.run_python("import sys; sys.exit(47)", check=True) + self.assertEqual(c.exception.returncode, 47) + + def test_check_zero(self): + # check_returncode shouldn't raise when returncode is zero + cp = self.run_python("import sys; sys.exit(0)", check=True) + self.assertEqual(cp.returncode, 0) + + def test_timeout(self): + # run() function with timeout argument; we want to test that the child + # process gets killed when the timeout expires. If the child isn't + # killed, this call will deadlock since subprocess.run waits for the + # child. + with self.assertRaises(subprocess.TimeoutExpired): + self.run_python("while True: pass", timeout=0.0001) + + def test_capture_stdout(self): + # capture stdout with zero return code + cp = self.run_python("print('BDFL')", stdout=subprocess.PIPE) + self.assertIn(b'BDFL', cp.stdout) + + def test_capture_stderr(self): + cp = self.run_python("import sys; sys.stderr.write('BDFL')", + stderr=subprocess.PIPE) + self.assertIn(b'BDFL', cp.stderr) + + def test_check_output_stdin_arg(self): + # run() can be called with stdin set to a file + tf = tempfile.TemporaryFile() + self.addCleanup(tf.close) + tf.write(b'pear') + tf.seek(0) + cp = self.run_python( + "import sys; sys.stdout.write(sys.stdin.read().upper())", + stdin=tf, stdout=subprocess.PIPE) + self.assertIn(b'PEAR', cp.stdout) + + def test_check_output_input_arg(self): + # check_output() can be called with input set to a string + cp = self.run_python( + "import sys; sys.stdout.write(sys.stdin.read().upper())", + input=b'pear', stdout=subprocess.PIPE) + self.assertIn(b'PEAR', cp.stdout) + + def test_check_output_stdin_with_input_arg(self): + # run() refuses to accept 'stdin' with 'input' + tf = tempfile.TemporaryFile() + self.addCleanup(tf.close) + tf.write(b'pear') + tf.seek(0) + with self.assertRaises(ValueError, + msg="Expected ValueError when stdin and input args supplied.") as c: + output = self.run_python("print('will not be run')", + stdin=tf, input=b'hare') + self.assertIn('stdin', c.exception.args[0]) + self.assertIn('input', c.exception.args[0]) + + def test_check_output_timeout(self): + with self.assertRaises(subprocess.TimeoutExpired) as c: + cp = self.run_python(( + "import sys, time\n" + "sys.stdout.write('BDFL')\n" + "sys.stdout.flush()\n" + "time.sleep(3600)"), + # Some heavily loaded buildbots (sparc Debian 3.x) require + # this much time to start and print. + timeout=3, stdout=subprocess.PIPE) + self.assertEqual(c.exception.output, b'BDFL') + # output is aliased to stdout + self.assertEqual(c.exception.stdout, b'BDFL') + + def test_run_kwargs(self): + newenv = os.environ.copy() + newenv["FRUIT"] = "banana" + cp = self.run_python(('import sys, os;' + 'sys.exit(33 if os.getenv("FRUIT")=="banana" else 31)'), + env=newenv) + self.assertEqual(cp.returncode, 33) + + @unittest.skipIf(mswindows, "POSIX specific tests") class POSIXProcessTestCase(BaseTestCase): @@ -2542,6 +2638,7 @@ ProcessTestCaseNoPoll, CommandsWithSpaces, ContextManagerTests, + RunFuncTestCase, ) support.run_unittest(*unit_tests) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -32,6 +32,9 @@ Library ------- +- Issue #23342: Add a subprocess.run() function than returns a CalledProcess + instance for a more consistent API than the existing call* functions. + - Issue #21217: inspect.getsourcelines() now tries to compute the start and end lines from the code object, fixing an issue when a lambda function is used as decorator argument. Patch by Thomas Ballinger. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Apr 15 04:12:17 2015 From: python-checkins at python.org (benjamin.peterson) Date: Wed, 15 Apr 2015 02:12:17 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_properly_wrap?= Message-ID: <20150415021217.794.84246@psf.io> https://hg.python.org/cpython/rev/ec93e07f6872 changeset: 95671:ec93e07f6872 user: Benjamin Peterson date: Tue Apr 14 22:12:14 2015 -0400 summary: properly wrap files: Doc/library/subprocess.rst | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/library/subprocess.rst b/Doc/library/subprocess.rst --- a/Doc/library/subprocess.rst +++ b/Doc/library/subprocess.rst @@ -26,8 +26,8 @@ ---------------------------------- The recommended approach to invoking subprocesses is to use the :func:`run` -function for all use cases it can handle. For more advanced -use cases, the underlying :class:`Popen` interface can be used directly. +function for all use cases it can handle. For more advanced use cases, the +underlying :class:`Popen` interface can be used directly. The :func:`run` function was added in Python 3.5; if you need to retain compatibility with older versions, see the :ref:`call-function-trio` section. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Apr 15 06:00:48 2015 From: python-checkins at python.org (benjamin.peterson) Date: Wed, 15 Apr 2015 04:00:48 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_add_Allison_Kaptur_=28=232?= =?utf-8?q?1217=29?= Message-ID: <20150415040047.65838.68228@psf.io> https://hg.python.org/cpython/rev/582e8e71f635 changeset: 95672:582e8e71f635 user: Benjamin Peterson date: Wed Apr 15 00:00:41 2015 -0400 summary: add Allison Kaptur (#21217) files: Misc/ACKS | 1 + Misc/NEWS | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -704,6 +704,7 @@ Jan Kanis Rafe Kaplan Jacob Kaplan-Moss +Allison Kaptur Janne Karila Per ?yvind Karlsen Anton Kasyanov diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -35,9 +35,9 @@ - Issue #23342: Add a subprocess.run() function than returns a CalledProcess instance for a more consistent API than the existing call* functions. -- Issue #21217: inspect.getsourcelines() now tries to compute the start and - end lines from the code object, fixing an issue when a lambda function is - used as decorator argument. Patch by Thomas Ballinger. +- Issue #21217: inspect.getsourcelines() now tries to compute the start and end + lines from the code object, fixing an issue when a lambda function is used as + decorator argument. Patch by Thomas Ballinger and Allison Kaptur. - Issue #23811: Add missing newline to the PyCompileError error message. Patch by Alex Shkop. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Apr 15 08:09:07 2015 From: python-checkins at python.org (ned.deily) Date: Wed, 15 Apr 2015 06:09:07 +0000 Subject: [Python-checkins] =?utf-8?q?devguide=3A_Issue_=2316405=3A_Explain?= =?utf-8?q?_how_to_set_up_the_whitespace_commit_hook_locally=2E?= Message-ID: <20150415060907.65830.73023@psf.io> https://hg.python.org/devguide/rev/b494a25915a9 changeset: 741:b494a25915a9 user: Ned Deily date: Tue Apr 14 23:05:25 2015 -0700 summary: Issue #16405: Explain how to set up the whitespace commit hook locally. Original patch by Carol Willing. files: committing.rst | 23 +++++++++++++++++++++++ 1 files changed, 23 insertions(+), 0 deletions(-) diff --git a/committing.rst b/committing.rst --- a/committing.rst +++ b/committing.rst @@ -304,10 +304,33 @@ will reject all changesets having the wrong line endings, so enabling this extension on your local computer is in your best interest. +As a core developer, it can be very helpful to set up the same commit checks +locally that the main repo enforces for incoming patch sets. This can save a +great deal of frustration with the server rejecting ``hg push`` for changes +(which can be especially time consuming if you have already merged changes +across branches). + +Configuring and using the whitespace checking hook found in the `hooks +repository`_ will help check incoming patch sets. To configure a hook, +add configuration settings to ``~/.hgrc`` for the relevant repo(s) (remember +to adjust the path appropriately for the checked out location of the +`hooks repository`_). To configure a "pretxncommit" hook that will check +whitespace before the changeset is committed and can thus abort the commit +if whitespace is found, add:: + + [hooks] + pretxncommit.whitespace = python:~/path/to/checkwhitespace.py:check_whitespace_single + +Another option is to configure it as a "commit" hook; if used, a warning +will still be issued but the changeset will be applied anyway:: + + [hooks] + commit = python:~/path/to/checkwhitespace.py:check_whitespace_single .. _configuration file: http://www.selenic.com/mercurial/hgrc.5.html#files .. _extended diff format: http://www.selenic.com/mercurial/hg.1.html#diffs .. _eol extension: http://mercurial.selenic.com/wiki/EolExtension +.. _hooks repository: https://hg.python.org/hooks Clones Setup -- Repository URL: https://hg.python.org/devguide From solipsis at pitrou.net Wed Apr 15 10:38:37 2015 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Wed, 15 Apr 2015 08:38:37 +0000 Subject: [Python-checkins] Daily reference leaks (582e8e71f635): sum=61 Message-ID: <20150415083837.8621.75647@psf.io> results for 582e8e71f635 on branch "default" -------------------------------------------- test_collections leaked [0, 0, 2] references, sum=2 test_functools leaked [0, 0, 3] memory blocks, sum=3 test_multiprocessing_fork leaked [38, 0, 0] references, sum=38 test_multiprocessing_fork leaked [18, 0, 0] memory blocks, sum=18 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogHZ4gm4', '--timeout', '7200'] From python-checkins at python.org Wed Apr 15 16:27:51 2015 From: python-checkins at python.org (eric.smith) Date: Wed, 15 Apr 2015 14:27:51 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_23193=3A_Add_numeric?= =?utf-8?q?=5Fowner_to_tarfile=2ETarFile=2Eextract=28=29_and?= Message-ID: <20150415142750.65822.48505@psf.io> https://hg.python.org/cpython/rev/6b70f16d585a changeset: 95673:6b70f16d585a user: Eric V. Smith date: Wed Apr 15 10:27:58 2015 -0400 summary: Issue 23193: Add numeric_owner to tarfile.TarFile.extract() and tarfile.TarFile.extractall(). files: Doc/library/tarfile.rst | 19 +++- Doc/whatsnew/3.5.rst | 22 ++- Lib/tarfile.py | 45 +++++--- Lib/test/test_tarfile.py | 132 +++++++++++++++++++++++++++ Misc/ACKS | 1 + Misc/NEWS | 4 + 6 files changed, 195 insertions(+), 28 deletions(-) diff --git a/Doc/library/tarfile.rst b/Doc/library/tarfile.rst --- a/Doc/library/tarfile.rst +++ b/Doc/library/tarfile.rst @@ -367,7 +367,7 @@ available. -.. method:: TarFile.extractall(path=".", members=None) +.. method:: TarFile.extractall(path=".", members=None, *, numeric_owner=False) Extract all members from the archive to the current working directory or directory *path*. If optional *members* is given, it must be a subset of the @@ -377,6 +377,10 @@ reset each time a file is created in it. And, if a directory's permissions do not allow writing, extracting files to it will fail. + If *numeric_owner* is :const:`True`, the uid and gid numbers from the tarfile + are used to set the owner/group for the extracted files. Otherwise, the named + values from the tarfile are used. + .. warning:: Never extract archives from untrusted sources without prior inspection. @@ -384,8 +388,11 @@ that have absolute filenames starting with ``"/"`` or filenames with two dots ``".."``. + .. versionchanged:: 3.5 + Added the *numeric_only* parameter. -.. method:: TarFile.extract(member, path="", set_attrs=True) + +.. method:: TarFile.extract(member, path="", set_attrs=True, *, numeric_owner=False) Extract a member from the archive to the current working directory, using its full name. Its file information is extracted as accurately as possible. *member* @@ -393,6 +400,10 @@ directory using *path*. File attributes (owner, mtime, mode) are set unless *set_attrs* is false. + If *numeric_owner* is :const:`True`, the uid and gid numbers from the tarfile + are used to set the owner/group for the extracted files. Otherwise, the named + values from the tarfile are used. + .. note:: The :meth:`extract` method does not take care of several extraction issues. @@ -405,6 +416,9 @@ .. versionchanged:: 3.2 Added the *set_attrs* parameter. + .. versionchanged:: 3.5 + Added the *numeric_only* parameter. + .. method:: TarFile.extractfile(member) Extract a member from the archive as a file object. *member* may be a filename @@ -827,4 +841,3 @@ because all the metadata is stored using *UTF-8*. *encoding* is only used in the rare cases when binary pax headers are decoded or when strings with surrogate characters are stored. - diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -479,26 +479,32 @@ :meth:`socket.socket.send`. (Contributed by Giampaolo Rodola' in :issue:`17552`.) +subprocess +---------- + +* The new :func:`subprocess.run` function runs subprocesses and returns a + :class:`subprocess.CompletedProcess` object. It Provides a more consistent + API than :func:`~subprocess.call`, :func:`~subprocess.check_call` and + :func:`~subprocess.check_output`. + sysconfig --------- * The user scripts directory on Windows is now versioned. (Contributed by Paul Moore in :issue:`23437`.) - tarfile ------- * The :func:`tarfile.open` function now supports ``'x'`` (exclusive creation) mode. (Contributed by Berker Peksag in :issue:`21717`.) -subprocess ----------- - -* The new :func:`subprocess.run` function runs subprocesses and returns a - :class:`subprocess.CompletedProcess` object. It Provides a more consistent - API than :func:`~subprocess.call`, :func:`~subprocess.check_call` and - :func:`~subprocess.check_output`. +* The :meth:`~tarfile.TarFile.extractall` and :meth:`~tarfile.TarFile.extract` + methods now take a keyword parameter *numeric_only*. If set to ``True``, + the extracted files and directories will be owned by the numeric uid and gid + from the tarfile. If set to ``False`` (the default, and the behavior in + versions prior to 3.5), they will be owned bythe named user and group in the + tarfile. (Contributed by Michael Vogt and Eric Smith in :issue:`23193`.) time ---- diff --git a/Lib/tarfile.py b/Lib/tarfile.py --- a/Lib/tarfile.py +++ b/Lib/tarfile.py @@ -1972,12 +1972,13 @@ self.members.append(tarinfo) - def extractall(self, path=".", members=None): + def extractall(self, path=".", members=None, *, numeric_owner=False): """Extract all members from the archive to the current working directory and set owner, modification time and permissions on directories afterwards. `path' specifies a different directory to extract to. `members' is optional and must be a subset of the - list returned by getmembers(). + list returned by getmembers(). If `numeric_owner` is True, only + the numbers for user/group names are used and not the names. """ directories = [] @@ -1991,7 +1992,8 @@ tarinfo = copy.copy(tarinfo) tarinfo.mode = 0o700 # Do not set_attrs directories, as we will do that further down - self.extract(tarinfo, path, set_attrs=not tarinfo.isdir()) + self.extract(tarinfo, path, set_attrs=not tarinfo.isdir(), + numeric_owner=numeric_owner) # Reverse sort directories. directories.sort(key=lambda a: a.name) @@ -2001,7 +2003,7 @@ for tarinfo in directories: dirpath = os.path.join(path, tarinfo.name) try: - self.chown(tarinfo, dirpath) + self.chown(tarinfo, dirpath, numeric_owner=numeric_owner) self.utime(tarinfo, dirpath) self.chmod(tarinfo, dirpath) except ExtractError as e: @@ -2010,12 +2012,14 @@ else: self._dbg(1, "tarfile: %s" % e) - def extract(self, member, path="", set_attrs=True): + def extract(self, member, path="", set_attrs=True, *, numeric_owner=False): """Extract a member from the archive to the current working directory, using its full name. Its file information is extracted as accurately as possible. `member' may be a filename or a TarInfo object. You can specify a different directory using `path'. File attributes (owner, - mtime, mode) are set unless `set_attrs' is False. + mtime, mode) are set unless `set_attrs' is False. If `numeric_owner` + is True, only the numbers for user/group names are used and not + the names. """ self._check("r") @@ -2030,7 +2034,8 @@ try: self._extract_member(tarinfo, os.path.join(path, tarinfo.name), - set_attrs=set_attrs) + set_attrs=set_attrs, + numeric_owner=numeric_owner) except OSError as e: if self.errorlevel > 0: raise @@ -2076,7 +2081,8 @@ # blkdev, etc.), return None instead of a file object. return None - def _extract_member(self, tarinfo, targetpath, set_attrs=True): + def _extract_member(self, tarinfo, targetpath, set_attrs=True, + numeric_owner=False): """Extract the TarInfo object tarinfo to a physical file called targetpath. """ @@ -2114,7 +2120,7 @@ self.makefile(tarinfo, targetpath) if set_attrs: - self.chown(tarinfo, targetpath) + self.chown(tarinfo, targetpath, numeric_owner) if not tarinfo.issym(): self.chmod(tarinfo, targetpath) self.utime(tarinfo, targetpath) @@ -2203,19 +2209,24 @@ except KeyError: raise ExtractError("unable to resolve link inside archive") - def chown(self, tarinfo, targetpath): - """Set owner of targetpath according to tarinfo. + def chown(self, tarinfo, targetpath, numeric_owner): + """Set owner of targetpath according to tarinfo. If numeric_owner + is True, use .gid/.uid instead of .gname/.uname. """ if pwd and hasattr(os, "geteuid") and os.geteuid() == 0: # We have to be root to do so. - try: - g = grp.getgrnam(tarinfo.gname)[2] - except KeyError: + if numeric_owner: g = tarinfo.gid - try: - u = pwd.getpwnam(tarinfo.uname)[2] - except KeyError: u = tarinfo.uid + else: + try: + g = grp.getgrnam(tarinfo.gname)[2] + except KeyError: + g = tarinfo.gid + try: + u = pwd.getpwnam(tarinfo.uname)[2] + except KeyError: + u = tarinfo.uid try: if tarinfo.issym() and hasattr(os, "lchown"): os.lchown(targetpath, u, g) 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 @@ -2,8 +2,10 @@ import os import io from hashlib import md5 +from contextlib import contextmanager import unittest +import unittest.mock import tarfile from test import support, script_helper @@ -2264,6 +2266,136 @@ self._test_partial_input("r:bz2") +def root_is_uid_gid_0(): + try: + import pwd, grp + except ImportError: + return False + if pwd.getpwuid(0)[0] != 'root': + return False + if grp.getgrgid(0)[0] != 'root': + return False + return True + + +class NumericOwnerTest(unittest.TestCase): + # mock the following: + # os.chown: so we can test what's being called + # os.chmod: so the modes are not actually changed. if they are, we can't + # delete the files/directories + # os.geteuid: so we can lie and say we're root (uid = 0) + + @staticmethod + def _make_test_archive(filename_1, dirname_1, filename_2): + # the file contents to write + fobj = io.BytesIO(b"content") + + # create a tar file with a file, a directory, and a file within that + # directory. Assign various .uid/.gid values to them + items = [(filename_1, 99, 98, tarfile.REGTYPE, fobj), + (dirname_1, 77, 76, tarfile.DIRTYPE, None), + (filename_2, 88, 87, tarfile.REGTYPE, fobj), + ] + with tarfile.open(tmpname, 'w') as tarfl: + for name, uid, gid, typ, contents in items: + t = tarfile.TarInfo(name) + t.uid = uid + t.gid = gid + t.uname = 'root' + t.gname = 'root' + t.type = typ + tarfl.addfile(t, contents) + + # return the full pathname to the tar file + return tmpname + + @staticmethod + @contextmanager + def _setup_test(mock_geteuid): + mock_geteuid.return_value = 0 # lie and say we're root + fname = 'numeric-owner-testfile' + dirname = 'dir' + + # the names we want stored in the tarfile + filename_1 = fname + dirname_1 = dirname + filename_2 = os.path.join(dirname, fname) + + # create the tarfile with the contents we're after + tar_filename = NumericOwnerTest._make_test_archive(filename_1, + dirname_1, + filename_2) + + # open the tarfile for reading. yield it and the names of the items + # we stored into the file + with tarfile.open(tar_filename) as tarfl: + yield tarfl, filename_1, dirname_1, filename_2 + + @unittest.mock.patch('os.chown') + @unittest.mock.patch('os.chmod') + @unittest.mock.patch('os.geteuid') + def test_extract_with_numeric_owner(self, mock_geteuid, mock_chmod, + mock_chown): + with self._setup_test(mock_geteuid) as (tarfl, filename_1, _, + filename_2): + tarfl.extract(filename_1, TEMPDIR, numeric_owner=True) + tarfl.extract(filename_2 , TEMPDIR, numeric_owner=True) + + # convert to filesystem paths + f_filename_1 = os.path.join(TEMPDIR, filename_1) + f_filename_2 = os.path.join(TEMPDIR, filename_2) + + mock_chown.assert_has_calls([unittest.mock.call(f_filename_1, 99, 98), + unittest.mock.call(f_filename_2, 88, 87), + ], + any_order=True) + + @unittest.mock.patch('os.chown') + @unittest.mock.patch('os.chmod') + @unittest.mock.patch('os.geteuid') + def test_extractall_with_numeric_owner(self, mock_geteuid, mock_chmod, + mock_chown): + with self._setup_test(mock_geteuid) as (tarfl, filename_1, dirname_1, + filename_2): + tarfl.extractall(TEMPDIR, numeric_owner=True) + + # convert to filesystem paths + f_filename_1 = os.path.join(TEMPDIR, filename_1) + f_dirname_1 = os.path.join(TEMPDIR, dirname_1) + f_filename_2 = os.path.join(TEMPDIR, filename_2) + + mock_chown.assert_has_calls([unittest.mock.call(f_filename_1, 99, 98), + unittest.mock.call(f_dirname_1, 77, 76), + unittest.mock.call(f_filename_2, 88, 87), + ], + any_order=True) + + # this test requires that uid=0 and gid=0 really be named 'root'. that's + # because the uname and gname in the test file are 'root', and extract() + # will look them up using pwd and grp to find their uid and gid, which we + # test here to be 0. + @unittest.skipUnless(root_is_uid_gid_0(), + 'uid=0,gid=0 must be named "root"') + @unittest.mock.patch('os.chown') + @unittest.mock.patch('os.chmod') + @unittest.mock.patch('os.geteuid') + def test_extract_without_numeric_owner(self, mock_geteuid, mock_chmod, + mock_chown): + with self._setup_test(mock_geteuid) as (tarfl, filename_1, _, _): + tarfl.extract(filename_1, TEMPDIR, numeric_owner=False) + + # convert to filesystem paths + f_filename_1 = os.path.join(TEMPDIR, filename_1) + + mock_chown.assert_called_with(f_filename_1, 0, 0) + + @unittest.mock.patch('os.geteuid') + def test_keyword_only(self, mock_geteuid): + with self._setup_test(mock_geteuid) as (tarfl, filename_1, _, _): + self.assertRaises(TypeError, + tarfl.extract, filename_1, TEMPDIR, False, True) + + def setUpModule(): support.unlink(TEMPDIR) os.makedirs(TEMPDIR) diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -1458,6 +1458,7 @@ Pauli Virtanen Frank Visser Johannes Vogel +Michael Vogt Radu Voicilas Alex Volkov Martijn Vries diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -32,6 +32,10 @@ Library ------- +- Issue #23193: Add a numeric_owner parameter to + tarfile.TarFile.extract and tarfile.TarFile.extractall. Patch by + Michael Vogt and Eric Smith. + - Issue #23342: Add a subprocess.run() function than returns a CalledProcess instance for a more consistent API than the existing call* functions. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Apr 15 20:23:21 2015 From: python-checkins at python.org (matthias.klose) Date: Wed, 15 Apr 2015 18:23:21 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_-_Issue_=2322980=3A_Under_?= =?utf-8?q?Linux=2C_GNU/KFreeBSD_and_the_Hurd=2C_C_extensions_now_include?= Message-ID: <20150415182321.29305.28418@psf.io> https://hg.python.org/cpython/rev/11c4f3f936e7 changeset: 95674:11c4f3f936e7 user: doko at ubuntu.com date: Wed Apr 15 20:23:14 2015 +0200 summary: - Issue #22980: Under Linux, GNU/KFreeBSD and the Hurd, C extensions now include the architecture triplet in the extension name, to make it easy to test builds for different ABIs in the same working tree. files: Lib/test/test_sysconfig.py | 15 +- Misc/NEWS | 8 +- configure | 1206 +++++++++++++---------- configure.ac | 144 ++- 4 files changed, 808 insertions(+), 565 deletions(-) diff --git a/Lib/test/test_sysconfig.py b/Lib/test/test_sysconfig.py --- a/Lib/test/test_sysconfig.py +++ b/Lib/test/test_sysconfig.py @@ -390,10 +390,19 @@ self.assertEqual(vars['SO'], vars['EXT_SUFFIX']) @unittest.skipUnless(sys.platform == 'linux', 'Linux-specific test') - def test_bitness_in_ext_suffix(self): + def test_triplet_in_ext_suffix(self): + import ctypes, platform, re + machine = platform.machine() suffix = sysconfig.get_config_var('EXT_SUFFIX') - bitness = '-32b' if sys.maxsize < 2**32 else '-64b' - self.assertTrue(suffix.endswith(bitness + '.so'), suffix) + if re.match('(aarch64|arm|mips|ppc|powerpc|s390|sparc)', machine): + self.assertTrue('linux' in suffix, suffix) + if re.match('(i[3-6]86|x86_64)$', 'x86_64'): + if ctypes.sizeof(ctypes.c_char_p()) == 4: + self.assertTrue(suffix.endswith('i386-linux-gnu.so') \ + or suffix.endswith('x86_64-linux-gnux32.so'), + suffix) + else: # 8 byte pointer size + self.assertTrue(suffix.endswith('x86_64-linux-gnu.so'), suffix) class MakefileTests(unittest.TestCase): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,10 @@ Core and Builtins ----------------- +- Issue #22980: Under Linux, GNU/KFreeBSD and the Hurd, C extensions now include + the architecture triplet in the extension name, to make it easy to test builds + for different ABIs in the same working tree. + - Issue #22631: Added Linux-specific socket constant CAN_RAW_FD_FRAMES. Patch courtesy of Joe Jevnik. @@ -382,10 +386,6 @@ Core and Builtins ----------------- -- Issue #22980: Under Linux, C extensions now include bitness in the file - name, to make it easy to test 32-bit and 64-bit builds in the same - working tree. - - Issue #23571: PyObject_Call() and PyCFunction_Call() now raise a SystemError if a function returns a result and raises an exception. The SystemError is chained to the previous exception. diff --git a/configure b/configure --- a/configure +++ b/configure @@ -694,15 +694,16 @@ DLLLIBRARY LDLIBRARY LIBRARY -MULTIARCH BUILDEXEEXT EGREP -GREP -CPP NO_AS_NEEDED +PLATFORM_TRIPLET +MULTIARCH ac_ct_CXX MAINCC CXX +GREP +CPP OBJEXT EXEEXT ac_ct_CC @@ -1648,6 +1649,43 @@ } # ac_fn_c_try_compile +# ac_fn_c_try_cpp LINENO +# ---------------------- +# Try to preprocess conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_cpp () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } > conftest.i && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_cpp + # ac_fn_c_try_link LINENO # ----------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. @@ -1694,43 +1732,6 @@ } # ac_fn_c_try_link -# ac_fn_c_try_cpp LINENO -# ---------------------- -# Try to preprocess conftest.$ac_ext, and return whether this succeeded. -ac_fn_c_try_cpp () -{ - as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - if { { ac_try="$ac_cpp conftest.$ac_ext" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err - ac_status=$? - if test -s conftest.err; then - grep -v '^ *+' conftest.err >conftest.er1 - cat conftest.er1 >&5 - mv -f conftest.er1 conftest.err - fi - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } > conftest.i && { - test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || - test ! -s conftest.err - }; then : - ac_retval=0 -else - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_retval=1 -fi - eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno - as_fn_set_status $ac_retval - -} # ac_fn_c_try_cpp - # ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists, giving a warning if it cannot be compiled using @@ -4407,496 +4408,6 @@ ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu - - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for --with-cxx-main=" >&5 -$as_echo_n "checking for --with-cxx-main=... " >&6; } - -# Check whether --with-cxx_main was given. -if test "${with_cxx_main+set}" = set; then : - withval=$with_cxx_main; - - case $withval in - no) with_cxx_main=no - MAINCC='$(CC)';; - yes) with_cxx_main=yes - MAINCC='$(CXX)';; - *) with_cxx_main=yes - MAINCC=$withval - if test -z "$CXX" - then - CXX=$withval - fi;; - esac -else - - with_cxx_main=no - MAINCC='$(CC)' - -fi - -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_cxx_main" >&5 -$as_echo "$with_cxx_main" >&6; } - -preset_cxx="$CXX" -if test -z "$CXX" -then - case "$CC" in - gcc) if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}g++", so it can be a program name with args. -set dummy ${ac_tool_prefix}g++; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_path_CXX+:} false; then : - $as_echo_n "(cached) " >&6 -else - case $CXX in - [\\/]* | ?:[\\/]*) - ac_cv_path_CXX="$CXX" # Let the user override the test with a path. - ;; - *) - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in notfound -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_path_CXX="$as_dir/$ac_word$ac_exec_ext" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - - ;; -esac -fi -CXX=$ac_cv_path_CXX -if test -n "$CXX"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXX" >&5 -$as_echo "$CXX" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - -fi -if test -z "$ac_cv_path_CXX"; then - ac_pt_CXX=$CXX - # Extract the first word of "g++", so it can be a program name with args. -set dummy g++; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_path_ac_pt_CXX+:} false; then : - $as_echo_n "(cached) " >&6 -else - case $ac_pt_CXX in - [\\/]* | ?:[\\/]*) - ac_cv_path_ac_pt_CXX="$ac_pt_CXX" # Let the user override the test with a path. - ;; - *) - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in notfound -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_path_ac_pt_CXX="$as_dir/$ac_word$ac_exec_ext" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - - ;; -esac -fi -ac_pt_CXX=$ac_cv_path_ac_pt_CXX -if test -n "$ac_pt_CXX"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_CXX" >&5 -$as_echo "$ac_pt_CXX" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - if test "x$ac_pt_CXX" = x; then - CXX="g++" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; -esac - CXX=$ac_pt_CXX - fi -else - CXX="$ac_cv_path_CXX" -fi - ;; - cc) if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}c++", so it can be a program name with args. -set dummy ${ac_tool_prefix}c++; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_path_CXX+:} false; then : - $as_echo_n "(cached) " >&6 -else - case $CXX in - [\\/]* | ?:[\\/]*) - ac_cv_path_CXX="$CXX" # Let the user override the test with a path. - ;; - *) - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in notfound -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_path_CXX="$as_dir/$ac_word$ac_exec_ext" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - - ;; -esac -fi -CXX=$ac_cv_path_CXX -if test -n "$CXX"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXX" >&5 -$as_echo "$CXX" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - -fi -if test -z "$ac_cv_path_CXX"; then - ac_pt_CXX=$CXX - # Extract the first word of "c++", so it can be a program name with args. -set dummy c++; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_path_ac_pt_CXX+:} false; then : - $as_echo_n "(cached) " >&6 -else - case $ac_pt_CXX in - [\\/]* | ?:[\\/]*) - ac_cv_path_ac_pt_CXX="$ac_pt_CXX" # Let the user override the test with a path. - ;; - *) - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in notfound -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_path_ac_pt_CXX="$as_dir/$ac_word$ac_exec_ext" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - - ;; -esac -fi -ac_pt_CXX=$ac_cv_path_ac_pt_CXX -if test -n "$ac_pt_CXX"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_CXX" >&5 -$as_echo "$ac_pt_CXX" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - if test "x$ac_pt_CXX" = x; then - CXX="c++" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; -esac - CXX=$ac_pt_CXX - fi -else - CXX="$ac_cv_path_CXX" -fi - ;; - clang|*/clang) if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}clang++", so it can be a program name with args. -set dummy ${ac_tool_prefix}clang++; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_path_CXX+:} false; then : - $as_echo_n "(cached) " >&6 -else - case $CXX in - [\\/]* | ?:[\\/]*) - ac_cv_path_CXX="$CXX" # Let the user override the test with a path. - ;; - *) - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in notfound -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_path_CXX="$as_dir/$ac_word$ac_exec_ext" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - - ;; -esac -fi -CXX=$ac_cv_path_CXX -if test -n "$CXX"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXX" >&5 -$as_echo "$CXX" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - -fi -if test -z "$ac_cv_path_CXX"; then - ac_pt_CXX=$CXX - # Extract the first word of "clang++", so it can be a program name with args. -set dummy clang++; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_path_ac_pt_CXX+:} false; then : - $as_echo_n "(cached) " >&6 -else - case $ac_pt_CXX in - [\\/]* | ?:[\\/]*) - ac_cv_path_ac_pt_CXX="$ac_pt_CXX" # Let the user override the test with a path. - ;; - *) - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in notfound -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_path_ac_pt_CXX="$as_dir/$ac_word$ac_exec_ext" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - - ;; -esac -fi -ac_pt_CXX=$ac_cv_path_ac_pt_CXX -if test -n "$ac_pt_CXX"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_CXX" >&5 -$as_echo "$ac_pt_CXX" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - if test "x$ac_pt_CXX" = x; then - CXX="clang++" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; -esac - CXX=$ac_pt_CXX - fi -else - CXX="$ac_cv_path_CXX" -fi - ;; - esac - if test "$CXX" = "notfound" - then - CXX="" - fi -fi -if test -z "$CXX" -then - if test -n "$ac_tool_prefix"; then - for ac_prog in $CCC c++ g++ gcc CC cxx cc++ cl - do - # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. -set dummy $ac_tool_prefix$ac_prog; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_CXX+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$CXX"; then - ac_cv_prog_CXX="$CXX" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_CXX="$ac_tool_prefix$ac_prog" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -CXX=$ac_cv_prog_CXX -if test -n "$CXX"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXX" >&5 -$as_echo "$CXX" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - test -n "$CXX" && break - done -fi -if test -z "$CXX"; then - ac_ct_CXX=$CXX - for ac_prog in $CCC c++ g++ gcc CC cxx cc++ cl -do - # Extract the first word of "$ac_prog", so it can be a program name with args. -set dummy $ac_prog; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_ac_ct_CXX+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$ac_ct_CXX"; then - ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_CXX="$ac_prog" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -ac_ct_CXX=$ac_cv_prog_ac_ct_CXX -if test -n "$ac_ct_CXX"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CXX" >&5 -$as_echo "$ac_ct_CXX" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - test -n "$ac_ct_CXX" && break -done - - if test "x$ac_ct_CXX" = x; then - CXX="notfound" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; -esac - CXX=$ac_ct_CXX - fi -fi - - if test "$CXX" = "notfound" - then - CXX="" - fi -fi -if test "$preset_cxx" != "$CXX" -then - { $as_echo "$as_me:${as_lineno-$LINENO}: - - By default, distutils will build C++ extension modules with \"$CXX\". - If this is not intended, then set CXX on the configure command line. - " >&5 -$as_echo "$as_me: - - By default, distutils will build C++ extension modules with \"$CXX\". - If this is not intended, then set CXX on the configure command line. - " >&6;} -fi - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for -Wl,--no-as-needed" >&5 -$as_echo_n "checking for -Wl,--no-as-needed... " >&6; } -save_LDFLAGS="$LDFLAGS" -LDFLAGS="$LDFLAGS -Wl,--no-as-needed" - -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - NO_AS_NEEDED="-Wl,--no-as-needed" - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } -else - NO_AS_NEEDED="" - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LDFLAGS="$save_LDFLAGS" - - - -# checks for UNIX variants that set C preprocessor variables ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' @@ -5034,7 +4545,6 @@ ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 $as_echo_n "checking for grep that handles long lines and -e... " >&6; } if ${ac_cv_path_GREP+:} false; then : @@ -5098,6 +4608,626 @@ GREP="$ac_cv_path_GREP" + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for --with-cxx-main=" >&5 +$as_echo_n "checking for --with-cxx-main=... " >&6; } + +# Check whether --with-cxx_main was given. +if test "${with_cxx_main+set}" = set; then : + withval=$with_cxx_main; + + case $withval in + no) with_cxx_main=no + MAINCC='$(CC)';; + yes) with_cxx_main=yes + MAINCC='$(CXX)';; + *) with_cxx_main=yes + MAINCC=$withval + if test -z "$CXX" + then + CXX=$withval + fi;; + esac +else + + with_cxx_main=no + MAINCC='$(CC)' + +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_cxx_main" >&5 +$as_echo "$with_cxx_main" >&6; } + +preset_cxx="$CXX" +if test -z "$CXX" +then + case "$CC" in + gcc) if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}g++", so it can be a program name with args. +set dummy ${ac_tool_prefix}g++; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_CXX+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $CXX in + [\\/]* | ?:[\\/]*) + ac_cv_path_CXX="$CXX" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in notfound +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_CXX="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +CXX=$ac_cv_path_CXX +if test -n "$CXX"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXX" >&5 +$as_echo "$CXX" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_path_CXX"; then + ac_pt_CXX=$CXX + # Extract the first word of "g++", so it can be a program name with args. +set dummy g++; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_ac_pt_CXX+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $ac_pt_CXX in + [\\/]* | ?:[\\/]*) + ac_cv_path_ac_pt_CXX="$ac_pt_CXX" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in notfound +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_ac_pt_CXX="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +ac_pt_CXX=$ac_cv_path_ac_pt_CXX +if test -n "$ac_pt_CXX"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_CXX" >&5 +$as_echo "$ac_pt_CXX" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_pt_CXX" = x; then + CXX="g++" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CXX=$ac_pt_CXX + fi +else + CXX="$ac_cv_path_CXX" +fi + ;; + cc) if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}c++", so it can be a program name with args. +set dummy ${ac_tool_prefix}c++; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_CXX+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $CXX in + [\\/]* | ?:[\\/]*) + ac_cv_path_CXX="$CXX" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in notfound +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_CXX="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +CXX=$ac_cv_path_CXX +if test -n "$CXX"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXX" >&5 +$as_echo "$CXX" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_path_CXX"; then + ac_pt_CXX=$CXX + # Extract the first word of "c++", so it can be a program name with args. +set dummy c++; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_ac_pt_CXX+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $ac_pt_CXX in + [\\/]* | ?:[\\/]*) + ac_cv_path_ac_pt_CXX="$ac_pt_CXX" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in notfound +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_ac_pt_CXX="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +ac_pt_CXX=$ac_cv_path_ac_pt_CXX +if test -n "$ac_pt_CXX"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_CXX" >&5 +$as_echo "$ac_pt_CXX" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_pt_CXX" = x; then + CXX="c++" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CXX=$ac_pt_CXX + fi +else + CXX="$ac_cv_path_CXX" +fi + ;; + clang|*/clang) if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}clang++", so it can be a program name with args. +set dummy ${ac_tool_prefix}clang++; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_CXX+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $CXX in + [\\/]* | ?:[\\/]*) + ac_cv_path_CXX="$CXX" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in notfound +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_CXX="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +CXX=$ac_cv_path_CXX +if test -n "$CXX"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXX" >&5 +$as_echo "$CXX" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_path_CXX"; then + ac_pt_CXX=$CXX + # Extract the first word of "clang++", so it can be a program name with args. +set dummy clang++; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_ac_pt_CXX+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $ac_pt_CXX in + [\\/]* | ?:[\\/]*) + ac_cv_path_ac_pt_CXX="$ac_pt_CXX" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in notfound +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_ac_pt_CXX="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +ac_pt_CXX=$ac_cv_path_ac_pt_CXX +if test -n "$ac_pt_CXX"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_CXX" >&5 +$as_echo "$ac_pt_CXX" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_pt_CXX" = x; then + CXX="clang++" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CXX=$ac_pt_CXX + fi +else + CXX="$ac_cv_path_CXX" +fi + ;; + esac + if test "$CXX" = "notfound" + then + CXX="" + fi +fi +if test -z "$CXX" +then + if test -n "$ac_tool_prefix"; then + for ac_prog in $CCC c++ g++ gcc CC cxx cc++ cl + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CXX+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CXX"; then + ac_cv_prog_CXX="$CXX" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CXX="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CXX=$ac_cv_prog_CXX +if test -n "$CXX"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXX" >&5 +$as_echo "$CXX" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$CXX" && break + done +fi +if test -z "$CXX"; then + ac_ct_CXX=$CXX + for ac_prog in $CCC c++ g++ gcc CC cxx cc++ cl +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CXX+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CXX"; then + ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CXX="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CXX=$ac_cv_prog_ac_ct_CXX +if test -n "$ac_ct_CXX"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CXX" >&5 +$as_echo "$ac_ct_CXX" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_CXX" && break +done + + if test "x$ac_ct_CXX" = x; then + CXX="notfound" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CXX=$ac_ct_CXX + fi +fi + + if test "$CXX" = "notfound" + then + CXX="" + fi +fi +if test "$preset_cxx" != "$CXX" +then + { $as_echo "$as_me:${as_lineno-$LINENO}: + + By default, distutils will build C++ extension modules with \"$CXX\". + If this is not intended, then set CXX on the configure command line. + " >&5 +$as_echo "$as_me: + + By default, distutils will build C++ extension modules with \"$CXX\". + If this is not intended, then set CXX on the configure command line. + " >&6;} +fi + + +MULTIARCH=$($CC --print-multiarch 2>/dev/null) + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for the platform triplet based on compiler characteristics" >&5 +$as_echo_n "checking for the platform triplet based on compiler characteristics... " >&6; } +cat >> conftest.c <conftest.out 2>/dev/null; then + PLATFORM_TRIPLET=`grep -v '^#' conftest.out | grep -v '^ *$' | tr -d ' '` + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PLATFORM_TRIPLET" >&5 +$as_echo "$PLATFORM_TRIPLET" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5 +$as_echo "none" >&6; } +fi +rm -f conftest.c conftest.out + +if test x$PLATFORM_TRIPLET != x && test x$MULTIARCH != x; then + if test x$PLATFORM_TRIPLET != x$MULTIARCH; then + as_fn_error $? "internal configure error for the platform triplet, please file a bug report" "$LINENO" 5 + fi +fi +PLATDIR=plat-$MACHDEP + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for -Wl,--no-as-needed" >&5 +$as_echo_n "checking for -Wl,--no-as-needed... " >&6; } +save_LDFLAGS="$LDFLAGS" +LDFLAGS="$LDFLAGS -Wl,--no-as-needed" + +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + NO_AS_NEEDED="-Wl,--no-as-needed" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else + NO_AS_NEEDED="" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LDFLAGS="$save_LDFLAGS" + + + +# checks for UNIX variants that set C preprocessor variables + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 $as_echo_n "checking for egrep... " >&6; } if ${ac_cv_path_EGREP+:} false; then : @@ -5416,10 +5546,6 @@ esac;; esac -MULTIARCH=$($CC --print-multiarch 2>/dev/null) - - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking LIBRARY" >&5 $as_echo_n "checking LIBRARY... " >&6; } @@ -14229,15 +14355,7 @@ $as_echo "$ABIFLAGS" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking SOABI" >&5 $as_echo_n "checking SOABI... " >&6; } - -case $ac_sys_system in - Linux*|GNU*) - BITNESS_SUFFIX=-$(($ac_cv_sizeof_void_p * 8))b;; - *) - BITNESS_SUFFIX=;; -esac -SOABI='cpython-'`echo $VERSION | tr -d .`${ABIFLAGS}${BITNESS_SUFFIX} - +SOABI='cpython-'`echo $VERSION | tr -d .`${ABIFLAGS}${PLATFORM_TRIPLET:+-$PLATFORM_TRIPLET} { $as_echo "$as_me:${as_lineno-$LINENO}: result: $SOABI" >&5 $as_echo "$SOABI" >&6; } diff --git a/configure.ac b/configure.ac --- a/configure.ac +++ b/configure.ac @@ -425,7 +425,7 @@ esac _PYTHON_HOST_PLATFORM="$MACHDEP${_host_cpu:+-$_host_cpu}" fi - + # Some systems cannot stand _XOPEN_SOURCE being defined at all; they # disable features if it is defined, without any means to access these # features as extensions. For these systems, we skip the definition of @@ -667,6 +667,8 @@ fi fi AC_PROG_CC +AC_PROG_CPP +AC_PROG_GREP AC_SUBST(CXX) AC_SUBST(MAINCC) @@ -724,6 +726,132 @@ fi +MULTIARCH=$($CC --print-multiarch 2>/dev/null) +AC_SUBST(MULTIARCH) + +AC_MSG_CHECKING([for the platform triplet based on compiler characteristics]) +cat >> conftest.c <conftest.out 2>/dev/null; then + PLATFORM_TRIPLET=`grep -v '^#' conftest.out | grep -v '^ *$' | tr -d ' '` + AC_MSG_RESULT([$PLATFORM_TRIPLET]) +else + AC_MSG_RESULT([none]) +fi +rm -f conftest.c conftest.out + +if test x$PLATFORM_TRIPLET != x && test x$MULTIARCH != x; then + if test x$PLATFORM_TRIPLET != x$MULTIARCH; then + AC_MSG_ERROR([internal configure error for the platform triplet, please file a bug report]) + fi +fi +PLATDIR=plat-$MACHDEP +AC_SUBST(PLATDIR) +AC_SUBST(PLATFORM_TRIPLET) + + AC_MSG_CHECKING([for -Wl,--no-as-needed]) save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS -Wl,--no-as-needed" @@ -791,10 +919,6 @@ esac;; esac -MULTIARCH=$($CC --print-multiarch 2>/dev/null) -AC_SUBST(MULTIARCH) - - AC_SUBST(LIBRARY) AC_MSG_CHECKING(LIBRARY) if test -z "$LIBRARY" @@ -4183,15 +4307,7 @@ AC_MSG_CHECKING(ABIFLAGS) AC_MSG_RESULT($ABIFLAGS) AC_MSG_CHECKING(SOABI) - -case $ac_sys_system in - Linux*|GNU*) - BITNESS_SUFFIX=-$(($ac_cv_sizeof_void_p * 8))b;; - *) - BITNESS_SUFFIX=;; -esac -SOABI='cpython-'`echo $VERSION | tr -d .`${ABIFLAGS}${BITNESS_SUFFIX} - +SOABI='cpython-'`echo $VERSION | tr -d .`${ABIFLAGS}${PLATFORM_TRIPLET:+-$PLATFORM_TRIPLET} AC_MSG_RESULT($SOABI) AC_SUBST(EXT_SUFFIX) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Apr 15 20:30:55 2015 From: python-checkins at python.org (charles-francois.natali) Date: Wed, 15 Apr 2015 18:30:55 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_Fix_PyGILState?= =?utf-8?q?=5FGetThisThreadState=28=29_prototype_in_the_API_documentation?= =?utf-8?q?=2E?= Message-ID: <20150415183054.29305.81262@psf.io> https://hg.python.org/cpython/rev/5576c8240963 changeset: 95675:5576c8240963 branch: 2.7 parent: 95644:22790c4f3b16 user: Charles-Fran?ois Natali date: Wed Apr 15 19:30:38 2015 +0100 summary: Fix PyGILState_GetThisThreadState() prototype in the API documentation. files: Doc/c-api/init.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/c-api/init.rst b/Doc/c-api/init.rst --- a/Doc/c-api/init.rst +++ b/Doc/c-api/init.rst @@ -642,7 +642,7 @@ .. versionadded:: 2.3 -.. c:function:: PyThreadState PyGILState_GetThisThreadState() +.. c:function:: PyThreadState* PyGILState_GetThisThreadState() Get the current thread state for this thread. May return ``NULL`` if no GILState API has been used on the current thread. Note that the main thread -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Apr 15 20:45:40 2015 From: python-checkins at python.org (matthias.klose) Date: Wed, 15 Apr 2015 18:45:40 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A__-_configure=2Eac=3A_remov?= =?utf-8?q?e_duplicate_PLATDIR_definition?= Message-ID: <20150415184539.56548.29511@psf.io> https://hg.python.org/cpython/rev/334b34377be0 changeset: 95676:334b34377be0 parent: 95674:11c4f3f936e7 user: doko at ubuntu.com date: Wed Apr 15 20:45:33 2015 +0200 summary: - configure.ac: remove duplicate PLATDIR definition files: configure | 5 +---- configure.ac | 3 --- 2 files changed, 1 insertions(+), 7 deletions(-) diff --git a/configure b/configure --- a/configure +++ b/configure @@ -698,6 +698,7 @@ EGREP NO_AS_NEEDED PLATFORM_TRIPLET +PLATDIR MULTIARCH ac_ct_CXX MAINCC @@ -713,7 +714,6 @@ CC EXPORT_MACOSX_DEPLOYMENT_TARGET CONFIGURE_MACOSX_DEPLOYMENT_TARGET -PLATDIR SGI_ABI _PYTHON_HOST_PLATFORM MACHDEP @@ -3499,9 +3499,6 @@ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MACHDEP" >&5 $as_echo "$MACHDEP" >&6; } - -PLATDIR=plat-$MACHDEP - # Record the configure-time value of MACOSX_DEPLOYMENT_TARGET, # it may influence the way we can build extensions, so distutils # needs to check it diff --git a/configure.ac b/configure.ac --- a/configure.ac +++ b/configure.ac @@ -556,9 +556,6 @@ fi AC_MSG_RESULT($MACHDEP) -AC_SUBST(PLATDIR) -PLATDIR=plat-$MACHDEP - # Record the configure-time value of MACOSX_DEPLOYMENT_TARGET, # it may influence the way we can build extensions, so distutils # needs to check it -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Apr 15 20:52:45 2015 From: python-checkins at python.org (matthias.klose) Date: Wed, 15 Apr 2015 18:52:45 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A__-_=2322980=3A_fix_typo_in?= =?utf-8?q?_Lib/test/test=5Fsysconfig=2Epy_triplet_test?= Message-ID: <20150415185245.802.98891@psf.io> https://hg.python.org/cpython/rev/df6c73f0e375 changeset: 95677:df6c73f0e375 user: doko at ubuntu.com date: Wed Apr 15 20:52:39 2015 +0200 summary: - #22980: fix typo in Lib/test/test_sysconfig.py triplet test files: Lib/test/test_sysconfig.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_sysconfig.py b/Lib/test/test_sysconfig.py --- a/Lib/test/test_sysconfig.py +++ b/Lib/test/test_sysconfig.py @@ -396,7 +396,7 @@ suffix = sysconfig.get_config_var('EXT_SUFFIX') if re.match('(aarch64|arm|mips|ppc|powerpc|s390|sparc)', machine): self.assertTrue('linux' in suffix, suffix) - if re.match('(i[3-6]86|x86_64)$', 'x86_64'): + if re.match('(i[3-6]86|x86_64)$', machine): if ctypes.sizeof(ctypes.c_char_p()) == 4: self.assertTrue(suffix.endswith('i386-linux-gnu.so') \ or suffix.endswith('x86_64-linux-gnux32.so'), -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Apr 15 22:16:17 2015 From: python-checkins at python.org (steve.dower) Date: Wed, 15 Apr 2015 20:16:17 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_19933=3A_Provide_def?= =?utf-8?q?ault_argument_for_ndigits_in_round=2E_Patch_by_Vajrasky?= Message-ID: <20150415201617.46275.82295@psf.io> https://hg.python.org/cpython/rev/e3cc75b1000b changeset: 95678:e3cc75b1000b user: Steve Dower date: Wed Apr 15 16:10:59 2015 -0400 summary: Issue 19933: Provide default argument for ndigits in round. Patch by Vajrasky Kok. files: Doc/library/functions.rst | 4 ++-- Lib/test/test_float.py | 8 ++++++++ Misc/NEWS | 3 +++ Objects/floatobject.c | 5 +++-- 4 files changed, 16 insertions(+), 4 deletions(-) diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst --- a/Doc/library/functions.rst +++ b/Doc/library/functions.rst @@ -1225,8 +1225,8 @@ .. function:: round(number[, ndigits]) Return the floating point value *number* rounded to *ndigits* digits after - the decimal point. If *ndigits* is omitted, it defaults to zero. Delegates - to ``number.__round__(ndigits)``. + the decimal point. If *ndigits* is omitted, it returns the nearest integer + to its input. Delegates to ``number.__round__(ndigits)``. For the built-in types supporting :func:`round`, values are rounded to the closest multiple of 10 to the power minus *ndigits*; if two multiples are 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 @@ -773,6 +773,14 @@ test(sfmt, NAN, ' nan') test(sfmt, -NAN, ' nan') + def test_None_ndigits(self): + for x in round(1.23), round(1.23, None), round(1.23, ndigits=None): + self.assertEqual(x, 1) + self.assertIsInstance(x, int) + for x in round(1.78), round(1.78, None), round(1.78, ndigits=None): + self.assertEqual(x, 2) + self.assertIsInstance(x, int) + # Beginning with Python 2.6 float has cross platform compatible # ways to create and represent inf and nan diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -36,6 +36,9 @@ Library ------- +- Issue 19933: Provide default argument for ndigits in round. Patch by + Vajrasky Kok. + - Issue #23193: Add a numeric_owner parameter to tarfile.TarFile.extract and tarfile.TarFile.extractall. Patch by Michael Vogt and Eric Smith. diff --git a/Objects/floatobject.c b/Objects/floatobject.c --- a/Objects/floatobject.c +++ b/Objects/floatobject.c @@ -986,8 +986,9 @@ x = PyFloat_AsDouble(v); if (!PyArg_ParseTuple(args, "|O", &o_ndigits)) return NULL; - if (o_ndigits == NULL) { - /* single-argument round: round to nearest integer */ + if (o_ndigits == NULL || o_ndigits == Py_None) { + /* single-argument round or with None ndigits: + * round to nearest integer */ rounded = round(x); if (fabs(x-rounded) == 0.5) /* halfway case: round to even */ -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Apr 15 22:19:08 2015 From: python-checkins at python.org (steve.dower) Date: Wed, 15 Apr 2015 20:19:08 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Updates_layout_of_some_tex?= =?utf-8?q?t_in_the_Windows_installer=2E?= Message-ID: <20150415201908.31470.50051@psf.io> https://hg.python.org/cpython/rev/4f4062267660 changeset: 95679:4f4062267660 user: Steve Dower date: Wed Apr 15 16:18:58 2015 -0400 summary: Updates layout of some text in the Windows installer. files: Tools/msi/bundle/Default.thm | 8 ++++---- 1 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Tools/msi/bundle/Default.thm b/Tools/msi/bundle/Default.thm --- a/Tools/msi/bundle/Default.thm +++ b/Tools/msi/bundle/Default.thm @@ -104,7 +104,7 @@ - #(loc.SuccessRestartText) + #(loc.SuccessRestartText) @@ -113,9 +113,9 @@ #(loc.FailureHeader) - #(loc.FailureHyperlinkLogText) - - #(loc.FailureRestartText) + #(loc.FailureHyperlinkLogText) + + #(loc.FailureRestartText) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Apr 15 23:09:10 2015 From: python-checkins at python.org (r.david.murray) Date: Wed, 15 Apr 2015 21:09:10 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_=2323949=3A_Improve_tuple_?= =?utf-8?q?unpacking_error_messages=2E?= Message-ID: <20150415210910.12164.43981@psf.io> https://hg.python.org/cpython/rev/e55cc0834e9c changeset: 95680:e55cc0834e9c user: R David Murray date: Wed Apr 15 17:08:45 2015 -0400 summary: #23949: Improve tuple unpacking error messages. Patch by Arnon Yaari. files: Lib/test/test_unpack.py | 2 +- Lib/test/test_unpack_ex.py | 9 ++++++++- Python/ceval.c | 24 +++++++++++++++++------- 3 files changed, 26 insertions(+), 9 deletions(-) diff --git a/Lib/test/test_unpack.py b/Lib/test/test_unpack.py --- a/Lib/test/test_unpack.py +++ b/Lib/test/test_unpack.py @@ -76,7 +76,7 @@ >>> a, b, c, d = Seq() Traceback (most recent call last): ... - ValueError: need more than 3 values to unpack + ValueError: not enough values to unpack (expected 4, got 3) Unpacking sequence too long diff --git a/Lib/test/test_unpack_ex.py b/Lib/test/test_unpack_ex.py --- a/Lib/test/test_unpack_ex.py +++ b/Lib/test/test_unpack_ex.py @@ -85,7 +85,14 @@ >>> a, *b, c, d, e = Seq() Traceback (most recent call last): ... - ValueError: need more than 3 values to unpack + ValueError: not enough values to unpack (expected at least 4, got 3) + +Unpacking sequence too short and target appears last + + >>> a, b, c, d, *e = Seq() + Traceback (most recent call last): + ... + ValueError: not enough values to unpack (expected at least 4, got 3) Unpacking a sequence where the test for too long raises a different kind of error diff --git a/Python/ceval.c b/Python/ceval.c --- a/Python/ceval.c +++ b/Python/ceval.c @@ -3825,9 +3825,17 @@ if (w == NULL) { /* Iterator done, via error or exhaustion. */ if (!PyErr_Occurred()) { - PyErr_Format(PyExc_ValueError, - "need more than %d value%s to unpack", - i, i == 1 ? "" : "s"); + if (argcntafter == -1) { + PyErr_Format(PyExc_ValueError, + "not enough values to unpack (expected %d, got %d)", + argcnt, i); + } + else { + PyErr_Format(PyExc_ValueError, + "not enough values to unpack " + "(expected at least %d, got %d)", + argcnt + argcntafter, i); + } } goto Error; } @@ -3844,8 +3852,9 @@ return 1; } Py_DECREF(w); - PyErr_Format(PyExc_ValueError, "too many values to unpack " - "(expected %d)", argcnt); + PyErr_Format(PyExc_ValueError, + "too many values to unpack (expected %d)", + argcnt); goto Error; } @@ -3857,8 +3866,9 @@ ll = PyList_GET_SIZE(l); if (ll < argcntafter) { - PyErr_Format(PyExc_ValueError, "need more than %zd values to unpack", - argcnt + ll); + PyErr_Format(PyExc_ValueError, + "not enough values to unpack (expected at least %d, got %zd)", + argcnt + argcntafter, argcnt + ll); goto Error; } -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Apr 15 23:31:07 2015 From: python-checkins at python.org (matthias.klose) Date: Wed, 15 Apr 2015 21:31:07 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_=2322980=3A_fix_triplet_co?= =?utf-8?q?nfigure_test_for_powerpc-linux-gnu?= Message-ID: <20150415213107.19869.8674@psf.io> https://hg.python.org/cpython/rev/948745d0d9cf changeset: 95681:948745d0d9cf user: doko at ubuntu.com date: Wed Apr 15 23:31:02 2015 +0200 summary: #22980: fix triplet configure test for powerpc-linux-gnu files: configure | 1 + configure.ac | 1 + 2 files changed, 2 insertions(+), 0 deletions(-) diff --git a/configure b/configure --- a/configure +++ b/configure @@ -5071,6 +5071,7 @@ cat >> conftest.c <> conftest.c < https://hg.python.org/cpython/rev/132b5376bf34 changeset: 95682:132b5376bf34 user: Steve Dower date: Wed Apr 15 18:06:05 2015 -0400 summary: Issue #4254: Adds _curses.update_lines_cols() Patch by Arnon Yaari files: Doc/library/curses.rst | 7 +++++++ Doc/whatsnew/3.5.rst | 5 +++++ Lib/test/test_curses.py | 7 +++++++ Misc/NEWS | 2 ++ Modules/_cursesmodule.c | 10 ++++++++++ 5 files changed, 31 insertions(+), 0 deletions(-) diff --git a/Doc/library/curses.rst b/Doc/library/curses.rst --- a/Doc/library/curses.rst +++ b/Doc/library/curses.rst @@ -599,6 +599,13 @@ Only one *ch* can be pushed before :meth:`getch` is called. +.. function:: update_lines_cols() + + Update :envvar:`LINES` and :envvar:`COLS`. Useful for detecting manual screen resize. + + .. versionadded:: 3.5 + + .. function:: unget_wch(ch) Push *ch* so the next :meth:`get_wch` will return it. diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -289,6 +289,11 @@ don't provide any options to redirect it. (Contributed by Berker Peksag in :issue:`22389`.) +curses +------ +* The new :func:`curses.update_lines_cols` function updates the variables + :envvar:`curses.LINES` and :envvar:`curses.COLS`. + difflib ------- diff --git a/Lib/test/test_curses.py b/Lib/test/test_curses.py --- a/Lib/test/test_curses.py +++ b/Lib/test/test_curses.py @@ -370,6 +370,13 @@ offset = human_readable_signature.find("[y, x,]") assert offset >= 0, "" + def test_update_lines_cols(self): + # this doesn't actually test that LINES and COLS are updated, + # because we can't automate changing them. See Issue #4254 for + # a manual test script. We can only test that the function + # can be called. + curses.update_lines_cols() + if __name__ == '__main__': unittest.main() diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -36,6 +36,8 @@ Library ------- +- Issue #4254: Adds _curses.update_lines_cols() Patch by Arnon Yaari + - Issue 19933: Provide default argument for ndigits in round. Patch by Vajrasky Kok. diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c --- a/Modules/_cursesmodule.c +++ b/Modules/_cursesmodule.c @@ -2866,6 +2866,13 @@ Py_DECREF(m); return 1; } + +static PyObject * +PyCurses_update_lines_cols(PyObject *self) +{ + return PyLong_FromLong((long) update_lines_cols()); +} + #endif #ifdef HAVE_CURSES_RESIZETERM @@ -3268,6 +3275,9 @@ {"typeahead", (PyCFunction)PyCurses_TypeAhead, METH_VARARGS}, {"unctrl", (PyCFunction)PyCurses_UnCtrl, METH_VARARGS}, {"ungetch", (PyCFunction)PyCurses_UngetCh, METH_VARARGS}, +#if defined(HAVE_CURSES_RESIZETERM) || defined(HAVE_CURSES_RESIZE_TERM) + {"update_lines_cols", (PyCFunction)PyCurses_update_lines_cols, METH_NOARGS}, +#endif #ifdef HAVE_NCURSESW {"unget_wch", (PyCFunction)PyCurses_Unget_Wch, METH_VARARGS}, #endif -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Apr 16 01:06:11 2015 From: python-checkins at python.org (nick.coghlan) Date: Wed, 15 Apr 2015 23:06:11 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_PEP_440=3A_Clarify_admonition?= =?utf-8?q?s_are_for_releases=2C_not_local_builds?= Message-ID: <20150415230609.108180.20700@psf.io> https://hg.python.org/peps/rev/bf4ffb364faf changeset: 5757:bf4ffb364faf user: Nick Coghlan date: Wed Apr 15 19:05:55 2015 -0400 summary: PEP 440: Clarify admonitions are for releases, not local builds files: pep-0440.txt | 16 ++++++++++------ 1 files changed, 10 insertions(+), 6 deletions(-) diff --git a/pep-0440.txt b/pep-0440.txt --- a/pep-0440.txt +++ b/pep-0440.txt @@ -159,8 +159,10 @@ potentially backporting security and bug fixes from later versions of the upstream project. -Local version identifiers SHOULD NOT be used for upstream projects. Local -version identifiers SHOULD be used by dowstream projects when releasing a +Local version identifiers SHOULD NOT be used when publishing upstream +projects to a public index server, but MAY be used to identify private +builds created directly from the project source. Local +version identifiers SHOULD be used by downstream projects when releasing a version that is API compatible with the version of the upstream project identified by the public version identifier, but contains additional changes (such as bug fixes). As the Python Package Index is intended solely for @@ -338,10 +340,12 @@ .. note:: - Creating developmental releases of pre-releases is strongly - discouraged, as it makes the version identifier difficult to parse for - human readers. In general, it is substantially clearer to simply create - additional pre-releases by incrementing the numeric component. + While they may be useful for continuous integration purposes, publishing + developmental releases of pre-releases to general purpose public index + servers is strongly discouraged, as it makes the version identifier + difficult to parse for human readers. If such a release needs to be + published, it is substantially clearer to instead create a new + pre-release by incrementing the numeric component. Developmental releases of post-releases are also strongly discouraged, but they may be appropriate for projects which use the post-release -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Thu Apr 16 01:31:35 2015 From: python-checkins at python.org (berker.peksag) Date: Wed, 15 Apr 2015 23:31:35 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2323703=3A_Fix_a_re?= =?utf-8?q?gression_in_urljoin=28=29_introduced_in_901e4e52b20a=2E?= Message-ID: <20150415233135.4311.57488@psf.io> https://hg.python.org/cpython/rev/fc0e79387a3a changeset: 95683:fc0e79387a3a user: Berker Peksag date: Thu Apr 16 02:31:14 2015 +0300 summary: Issue #23703: Fix a regression in urljoin() introduced in 901e4e52b20a. Patch by Demian Brecht. files: Lib/test/test_urlparse.py | 3 +++ Lib/urllib/parse.py | 3 +-- Misc/NEWS | 3 +++ 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_urlparse.py b/Lib/test/test_urlparse.py --- a/Lib/test/test_urlparse.py +++ b/Lib/test/test_urlparse.py @@ -391,6 +391,9 @@ self.checkJoin('http://a/b/c/d/e/', '../../f/g', 'http://a/b/c/f/g') self.checkJoin('http://a/b/', '../../f/g/', 'http://a/f/g/') + # issue 23703: don't duplicate filename + self.checkJoin('a', 'b', 'b') + def test_RFC2732(self): str_cases = [ ('http://Test.python.org:5432/foo/', 'test.python.org', 5432), diff --git a/Lib/urllib/parse.py b/Lib/urllib/parse.py --- a/Lib/urllib/parse.py +++ b/Lib/urllib/parse.py @@ -447,8 +447,7 @@ segments = base_parts + path.split('/') # filter out elements that would cause redundant slashes on re-joining # the resolved_path - segments = segments[0:1] + [ - s for s in segments[1:-1] if len(s) > 0] + segments[-1:] + segments[1:-1] = filter(None, segments[1:-1]) resolved_path = [] diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -36,6 +36,9 @@ Library ------- +- Issue #23703: Fix a regression in urljoin() introduced in 901e4e52b20a. + Patch by Demian Brecht. + - Issue #4254: Adds _curses.update_lines_cols() Patch by Arnon Yaari - Issue 19933: Provide default argument for ndigits in round. Patch by -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Apr 16 02:12:56 2015 From: python-checkins at python.org (ned.deily) Date: Thu, 16 Apr 2015 00:12:56 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issues_=2322980=2C_23969?= =?utf-8?q?=3A_For_OS_X=2C_use_PEP_3149-style_file_names_for_extension?= Message-ID: <20150416001256.31478.27498@psf.io> https://hg.python.org/cpython/rev/32c24eec035f changeset: 95684:32c24eec035f user: Ned Deily date: Wed Apr 15 17:11:47 2015 -0700 summary: Issues #22980, 23969: For OS X, use PEP 3149-style file names for extension module binaries, with a platform triple of just "darwin", resulting in file names like: _ssl.cpython-35m-darwin.so rather than just _ssl.so as previously. Instead of attempting to encode differences in CPU architecture and OS X deployment targets in the file name as is done on other platforms, these continue to be managed by the use of Apple multi-architecture ("fat") files, by the system dynamic loader, and by logic in higher-levels like sysconfig.get_platform() and pip. files: Lib/test/test_sysconfig.py | 4 ++++ Misc/NEWS | 3 ++- configure | 4 +++- configure.ac | 4 +++- 4 files changed, 12 insertions(+), 3 deletions(-) diff --git a/Lib/test/test_sysconfig.py b/Lib/test/test_sysconfig.py --- a/Lib/test/test_sysconfig.py +++ b/Lib/test/test_sysconfig.py @@ -404,6 +404,10 @@ else: # 8 byte pointer size self.assertTrue(suffix.endswith('x86_64-linux-gnu.so'), suffix) + @unittest.skipUnless(sys.platform == 'darwin', 'OS X-specific test') + def test_osx_ext_suffix(self): + suffix = sysconfig.get_config_var('EXT_SUFFIX') + self.assertTrue(suffix.endswith('-darwin.so'), suffix) class MakefileTests(unittest.TestCase): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -12,7 +12,8 @@ - Issue #22980: Under Linux, GNU/KFreeBSD and the Hurd, C extensions now include the architecture triplet in the extension name, to make it easy to test builds - for different ABIs in the same working tree. + for different ABIs in the same working tree. Under OS X, the extension name + now includes PEP 3149-style information. - Issue #22631: Added Linux-specific socket constant CAN_RAW_FD_FRAMES. Patch courtesy of Joe Jevnik. diff --git a/configure b/configure --- a/configure +++ b/configure @@ -5167,6 +5167,8 @@ # endif #elif defined(__gnu_hurd__) i386-gnu +#elif defined(__APPLE__) + darwin #else # error unknown platform triplet #endif @@ -14359,7 +14361,7 @@ case $ac_sys_system in - Linux*|GNU*) + Linux*|GNU*|Darwin) EXT_SUFFIX=.${SOABI}${SHLIB_SUFFIX};; *) EXT_SUFFIX=${SHLIB_SUFFIX};; diff --git a/configure.ac b/configure.ac --- a/configure.ac +++ b/configure.ac @@ -826,6 +826,8 @@ # endif #elif defined(__gnu_hurd__) i386-gnu +#elif defined(__APPLE__) + darwin #else # error unknown platform triplet #endif @@ -4310,7 +4312,7 @@ AC_SUBST(EXT_SUFFIX) case $ac_sys_system in - Linux*|GNU*) + Linux*|GNU*|Darwin) EXT_SUFFIX=.${SOABI}${SHLIB_SUFFIX};; *) EXT_SUFFIX=${SHLIB_SUFFIX};; -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Apr 16 05:02:26 2015 From: python-checkins at python.org (larry.hastings) Date: Thu, 16 Apr 2015 03:02:26 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2323935=3A_Argument?= =?utf-8?q?_Clinic=27s_understanding_of_format_units?= Message-ID: <20150416030226.43337.38146@psf.io> https://hg.python.org/cpython/rev/4f74452a11e5 changeset: 95685:4f74452a11e5 user: Larry Hastings date: Wed Apr 15 23:02:12 2015 -0400 summary: Issue #23935: Argument Clinic's understanding of format units accepting bytes, bytearrays, and buffers is now consistent with both the documentation and the implementation. files: Misc/NEWS | 4 + Modules/_dbmmodule.c | 4 +- Modules/arraymodule.c | 8 +- Tools/clinic/clinic.py | 109 +++++++++++++--------------- 4 files changed, 59 insertions(+), 66 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -187,6 +187,10 @@ Tools/Demos ----------- +- Issue #23935: Argument Clinic's understanding of format units + accepting bytes, bytearrays, and buffers is now consistent with + both the documentation and the implementation. + - Issue #23944: Argument Clinic now wraps long impl prototypes at column 78. - Issue #20586: Argument Clinic now ensures that functions without docstrings diff --git a/Modules/_dbmmodule.c b/Modules/_dbmmodule.c --- a/Modules/_dbmmodule.c +++ b/Modules/_dbmmodule.c @@ -272,7 +272,7 @@ self: dbmobject - key: str(length=True) + key: str(types={'str', 'robuffer'}, length=True) default: object = None / @@ -282,7 +282,7 @@ static PyObject * dbm_dbm_get_impl(dbmobject *dp, const char *key, Py_ssize_clean_t key_length, PyObject *default_value) -/*[clinic end generated code: output=4f5c0e523eaf1251 input=aecf5efd2f2b1a3b]*/ +/*[clinic end generated code: output=4f5c0e523eaf1251 input=f81478bc211895ef]*/ { datum dbm_key, val; diff --git a/Modules/arraymodule.c b/Modules/arraymodule.c --- a/Modules/arraymodule.c +++ b/Modules/arraymodule.c @@ -1600,7 +1600,7 @@ /*[clinic input] array.array.fromstring - buffer: Py_buffer(types='str bytes bytearray buffer') + buffer: Py_buffer(types={'str', 'buffer'}) / Appends items from the string, interpreting it as an array of machine values, as if it had been read from a file using the fromfile() method). @@ -1610,7 +1610,7 @@ static PyObject * array_array_fromstring_impl(arrayobject *self, Py_buffer *buffer) -/*[clinic end generated code: output=31c4baa779df84ce input=1302d94c97696b84]*/ +/*[clinic end generated code: output=31c4baa779df84ce input=fdde1a56cbe2b05b]*/ { if (PyErr_WarnEx(PyExc_DeprecationWarning, "fromstring() is deprecated. Use frombytes() instead.", 2) != 0) @@ -1929,7 +1929,7 @@ array._array_reconstructor arraytype: object(type="PyTypeObject *") - typecode: int(types='str') + typecode: int(types={'str'}) mformat_code: int(type="enum machine_format_code") items: object / @@ -1942,7 +1942,7 @@ int typecode, enum machine_format_code mformat_code, PyObject *items) -/*[clinic end generated code: output=6ecbf0e8e4d92ab9 input=f72492708c0a1d50]*/ +/*[clinic end generated code: output=6ecbf0e8e4d92ab9 input=a9ae223306d7b262]*/ { PyObject *converted_items; PyObject *result; diff --git a/Tools/clinic/clinic.py b/Tools/clinic/clinic.py --- a/Tools/clinic/clinic.py +++ b/Tools/clinic/clinic.py @@ -2493,12 +2493,12 @@ class char_converter(CConverter): type = 'char' - default_type = str + default_type = (bytes, bytearray) format_unit = 'c' c_ignored_default = "'\0'" def converter_init(self): - if isinstance(self.default, str) and (len(self.default) != 1): + if isinstance(self.default, self.default_type) and (len(self.default) != 1): fail("char_converter: illegal default value " + repr(self.default)) @@ -2531,18 +2531,18 @@ if not bitwise: fail("Unsigned shorts must be bitwise (for now).") - at add_legacy_c_converter('C', types='str') + at add_legacy_c_converter('C', types={'str'}) class int_converter(CConverter): type = 'int' default_type = int format_unit = 'i' c_ignored_default = "0" - def converter_init(self, *, types='int', type=None): - if types == 'str': + def converter_init(self, *, types={'int'}, type=None): + if types == {'str'}: self.format_unit = 'C' - elif types != 'int': - fail("int_converter: illegal 'types' argument") + elif types != {'int'}: + fail("int_converter: illegal 'types' argument " + repr(types)) if type != None: self.type = type @@ -2633,63 +2633,64 @@ self.type = type - at add_legacy_c_converter('s#', length=True) - at add_legacy_c_converter('y', types="bytes") - at add_legacy_c_converter('y#', types="bytes", length=True) +# +# We define three string conventions for buffer types in the 'types' argument: +# 'buffer' : any object supporting the buffer interface +# 'rwbuffer': any object supporting the buffer interface, but must be writeable +# 'robuffer': any object supporting the buffer interface, but must not be writeable +# + + at add_legacy_c_converter('s#', types={"str", "robuffer"}, length=True) + at add_legacy_c_converter('y', types={"robuffer"}) + at add_legacy_c_converter('y#', types={"robuffer"}, length=True) @add_legacy_c_converter('z', nullable=True) - at add_legacy_c_converter('z#', nullable=True, length=True) + at add_legacy_c_converter('z#', types={"str", "robuffer"}, nullable=True, length=True) +# add_legacy_c_converter not supported for es, es#, et, et# +# because of their extra encoding argument class str_converter(CConverter): type = 'const char *' default_type = (str, Null, NoneType) format_unit = 's' - def converter_init(self, *, encoding=None, types="str", + def converter_init(self, *, encoding=None, types={"str"}, length=False, nullable=False, zeroes=False): - types = set(types.strip().split()) - bytes_type = {"bytes"} - str_type = {"str"} - all_3_type = {"bytearray"} | bytes_type | str_type - is_bytes = types == bytes_type - is_str = types == str_type - is_all_3 = types == all_3_type - self.length = bool(length) + + is_b_or_ba = types == {"bytes", "bytearray"} + is_str = types == {"str"} + is_robuffer = types == {"robuffer"} + is_str_or_robuffer = types == {"str", "robuffer"} + format_unit = None if encoding: self.encoding = encoding - if is_str and not (length or zeroes or nullable): + if is_str and not length and not zeroes and not nullable: format_unit = 'es' - elif is_all_3 and not (length or zeroes or nullable): + elif is_str and length and zeroes and nullable: + format_unit = 'es#' + elif is_b_or_ba and not length and not zeroes and not nullable: format_unit = 'et' - elif is_str and length and zeroes and not nullable: - format_unit = 'es#' - elif is_all_3 and length and not (nullable or zeroes): + elif is_b_or_ba and length and zeroes and nullable: format_unit = 'et#' - if format_unit.endswith('#'): - fail("Sorry: code using format unit ", repr(format_unit), "probably doesn't work properly yet.\nGive Larry your test case and he'll it.") - # TODO set pointer to NULL - # TODO add cleanup for buffer - pass - else: if zeroes: fail("str_converter: illegal combination of arguments (zeroes is only legal with an encoding)") - if is_bytes and not (nullable or length): + if is_str and not length and not nullable: + format_unit = 's' + elif is_str and not length and nullable: + format_unit = 'z' + elif is_robuffer and not length and not nullable: format_unit = 'y' - elif is_bytes and length and not nullable: + elif is_robuffer and length and not nullable: format_unit = 'y#' - elif is_str and not (nullable or length): - format_unit = 's' - elif is_str and length and not nullable: + elif is_str_or_robuffer and length and not nullable: format_unit = 's#' - elif is_str and nullable and not length: - format_unit = 'z' - elif is_str and nullable and length: + elif is_str_or_robuffer and length and nullable: format_unit = 'z#' if not format_unit: @@ -2700,10 +2701,12 @@ class PyBytesObject_converter(CConverter): type = 'PyBytesObject *' format_unit = 'S' + # types = {'bytes'} class PyByteArrayObject_converter(CConverter): type = 'PyByteArrayObject *' format_unit = 'Y' + # types = {'bytearray'} class unicode_converter(CConverter): type = 'PyObject *' @@ -2725,43 +2728,29 @@ self.length = True self.format_unit = format_unit -# -# We define three string conventions for buffer types in the 'types' argument: -# 'buffer' : any object supporting the buffer interface -# 'rwbuffer': any object supporting the buffer interface, but must be writeable -# 'robuffer': any object supporting the buffer interface, but must not be writeable -# - at add_legacy_c_converter('s*', types='str bytes bytearray buffer') - at add_legacy_c_converter('z*', types='str bytes bytearray buffer', nullable=True) - at add_legacy_c_converter('w*', types='bytearray rwbuffer') + at add_legacy_c_converter('s*', types={'str', 'buffer'}) + at add_legacy_c_converter('z*', types={'str', 'buffer'}, nullable=True) + at add_legacy_c_converter('w*', types={'rwbuffer'}) class Py_buffer_converter(CConverter): type = 'Py_buffer' format_unit = 'y*' impl_by_reference = True c_ignored_default = "{NULL, NULL}" - def converter_init(self, *, types='bytes bytearray buffer', nullable=False): + def converter_init(self, *, types={'buffer'}, nullable=False): if self.default not in (unspecified, None): fail("The only legal default value for Py_buffer is None.") self.c_default = self.c_ignored_default - types = set(types.strip().split()) - bytes_type = {'bytes'} - bytearray_type = {'bytearray'} - buffer_type = {'buffer'} - rwbuffer_type = {'rwbuffer'} - robuffer_type = {'robuffer'} - str_type = {'str'} - bytes_bytearray_buffer_type = bytes_type | bytearray_type | buffer_type format_unit = None - if types == (str_type | bytes_bytearray_buffer_type): + if types == {'str', 'buffer'}: format_unit = 's*' if not nullable else 'z*' else: if nullable: fail('Py_buffer_converter: illegal combination of arguments (nullable=True)') - elif types == (bytes_bytearray_buffer_type): + elif types == {'buffer'}: format_unit = 'y*' - elif types == (bytearray_type | rwbuffer_type): + elif types == {'rwbuffer'}: format_unit = 'w*' if not format_unit: fail("Py_buffer_converter: illegal combination of arguments") -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Apr 16 10:26:39 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Thu, 16 Apr 2015 08:26:39 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2320175=3A_Converte?= =?utf-8?q?d_the_=5Fio_module_to_Argument_Clinic=2E?= Message-ID: <20150416082639.30343.36121@psf.io> https://hg.python.org/cpython/rev/49007ed1a1a5 changeset: 95686:49007ed1a1a5 user: Serhiy Storchaka date: Thu Apr 16 11:19:43 2015 +0300 summary: Issue #20175: Converted the _io module to Argument Clinic. files: Lib/test/test_fileio.py | 16 +- Lib/test/test_io.py | 13 +- Modules/_io/_iomodule.c | 278 +- Modules/_io/bufferedio.c | 997 ++++--- Modules/_io/bytesio.c | 429 ++- Modules/_io/_iomodule.c | 745 +----- Modules/_io/bufferedio.c | 3032 +++--------------------- Modules/_io/bytesio.c | 1284 ++-------- Modules/_io/fileio.c | 1448 ++--------- Modules/_io/iobase.c | 1102 +------- Modules/_io/stringio.c | 1210 +-------- Modules/_io/textio.c | 3113 +++---------------------- Modules/_io/fileio.c | 359 +- Modules/_io/iobase.c | 248 +- Modules/_io/stringio.c | 267 +- Modules/_io/textio.c | 472 ++- 16 files changed, 3636 insertions(+), 11377 deletions(-) diff --git a/Lib/test/test_fileio.py b/Lib/test/test_fileio.py --- a/Lib/test/test_fileio.py +++ b/Lib/test/test_fileio.py @@ -190,9 +190,9 @@ self.assertTrue(f.closed) def testMethods(self): - methods = ['fileno', 'isatty', 'read', - 'tell', 'truncate', 'seekable', - 'readable', 'writable'] + methods = ['fileno', 'isatty', 'seekable', 'readable', 'writable', + 'read', 'readall', 'readline', 'readlines', + 'tell', 'truncate', 'flush'] self.f.close() self.assertTrue(self.f.closed) @@ -201,9 +201,15 @@ method = getattr(self.f, methodname) # should raise on closed file self.assertRaises(ValueError, method) - self.assertRaises(ValueError, self.f.readinto, bytearray()) - self.assertRaises(ValueError, self.f.seek, 0, os.SEEK_CUR) + + self.assertRaises(TypeError, self.f.readinto) + self.assertRaises(ValueError, self.f.readinto, bytearray(1)) + self.assertRaises(TypeError, self.f.seek) + self.assertRaises(ValueError, self.f.seek, 0) + self.assertRaises(TypeError, self.f.write) self.assertRaises(ValueError, self.f.write, b'') + self.assertRaises(TypeError, self.f.writelines) + self.assertRaises(ValueError, self.f.writelines, b'') def testOpendir(self): # Issue 3703: opening a directory should fill the errno diff --git a/Lib/test/test_io.py b/Lib/test/test_io.py --- a/Lib/test/test_io.py +++ b/Lib/test/test_io.py @@ -2163,6 +2163,17 @@ self.assertRaises(TypeError, t.__init__, b, newline=42) self.assertRaises(ValueError, t.__init__, b, newline='xyzzy') + def test_uninitialized(self): + t = self.TextIOWrapper.__new__(self.TextIOWrapper) + del t + t = self.TextIOWrapper.__new__(self.TextIOWrapper) + self.assertRaises(Exception, repr, t) + self.assertRaisesRegex((ValueError, AttributeError), + 'uninitialized|has no attribute', + t.read, 0) + t.__init__(self.MockRawIO()) + self.assertEqual(t.read(0), '') + def test_non_text_encoding_codecs_are_rejected(self): # Ensure the constructor complains if passed a codec that isn't # marked as a text encoding @@ -3024,8 +3035,6 @@ r = self.BytesIO(b"\xc3\xa9\n\n") b = self.BufferedReader(r, 1000) t = self.TextIOWrapper(b) - self.assertRaises(TypeError, t.__init__, b, newline=42) - self.assertRaises(ValueError, t.read) self.assertRaises(ValueError, t.__init__, b, newline='xyzzy') self.assertRaises(ValueError, t.read) diff --git a/Modules/_io/_iomodule.c b/Modules/_io/_iomodule.c --- a/Modules/_io/_iomodule.c +++ b/Modules/_io/_iomodule.c @@ -93,140 +93,145 @@ /* * The main open() function */ -PyDoc_STRVAR(open_doc, -"open(file, mode='r', buffering=-1, encoding=None,\n" -" errors=None, newline=None, closefd=True, opener=None) -> file object\n" -"\n" -"Open file and return a stream. Raise IOError upon failure.\n" -"\n" -"file is either a text or byte string giving the name (and the path\n" -"if the file isn't in the current working directory) of the file to\n" -"be opened or an integer file descriptor of the file to be\n" -"wrapped. (If a file descriptor is given, it is closed when the\n" -"returned I/O object is closed, unless closefd is set to False.)\n" -"\n" -"mode is an optional string that specifies the mode in which the file\n" -"is opened. It defaults to 'r' which means open for reading in text\n" -"mode. Other common values are 'w' for writing (truncating the file if\n" -"it already exists), 'x' for creating and writing to a new file, and\n" -"'a' for appending (which on some Unix systems, means that all writes\n" -"append to the end of the file regardless of the current seek position).\n" -"In text mode, if encoding is not specified the encoding used is platform\n" -"dependent: locale.getpreferredencoding(False) is called to get the\n" -"current locale encoding. (For reading and writing raw bytes use binary\n" -"mode and leave encoding unspecified.) The available modes are:\n" -"\n" -"========= ===============================================================\n" -"Character Meaning\n" -"--------- ---------------------------------------------------------------\n" -"'r' open for reading (default)\n" -"'w' open for writing, truncating the file first\n" -"'x' create a new file and open it for writing\n" -"'a' open for writing, appending to the end of the file if it exists\n" -"'b' binary mode\n" -"'t' text mode (default)\n" -"'+' open a disk file for updating (reading and writing)\n" -"'U' universal newline mode (deprecated)\n" -"========= ===============================================================\n" -"\n" -"The default mode is 'rt' (open for reading text). For binary random\n" -"access, the mode 'w+b' opens and truncates the file to 0 bytes, while\n" -"'r+b' opens the file without truncation. The 'x' mode implies 'w' and\n" -"raises an `FileExistsError` if the file already exists.\n" -"\n" -"Python distinguishes between files opened in binary and text modes,\n" -"even when the underlying operating system doesn't. Files opened in\n" -"binary mode (appending 'b' to the mode argument) return contents as\n" -"bytes objects without any decoding. In text mode (the default, or when\n" -"'t' is appended to the mode argument), the contents of the file are\n" -"returned as strings, the bytes having been first decoded using a\n" -"platform-dependent encoding or using the specified encoding if given.\n" -"\n" -"'U' mode is deprecated and will raise an exception in future versions\n" -"of Python. It has no effect in Python 3. Use newline to control\n" -"universal newlines mode.\n" -"\n" -"buffering is an optional integer used to set the buffering policy.\n" -"Pass 0 to switch buffering off (only allowed in binary mode), 1 to select\n" -"line buffering (only usable in text mode), and an integer > 1 to indicate\n" -"the size of a fixed-size chunk buffer. When no buffering argument is\n" -"given, the default buffering policy works as follows:\n" -"\n" -"* Binary files are buffered in fixed-size chunks; the size of the buffer\n" -" is chosen using a heuristic trying to determine the underlying device's\n" -" \"block size\" and falling back on `io.DEFAULT_BUFFER_SIZE`.\n" -" On many systems, the buffer will typically be 4096 or 8192 bytes long.\n" -"\n" -"* \"Interactive\" text files (files for which isatty() returns True)\n" -" use line buffering. Other text files use the policy described above\n" -" for binary files.\n" -"\n" -"encoding is the name of the encoding used to decode or encode the\n" -"file. This should only be used in text mode. The default encoding is\n" -"platform dependent, but any encoding supported by Python can be\n" -"passed. See the codecs module for the list of supported encodings.\n" -"\n" -"errors is an optional string that specifies how encoding errors are to\n" -"be handled---this argument should not be used in binary mode. Pass\n" -"'strict' to raise a ValueError exception if there is an encoding error\n" -"(the default of None has the same effect), or pass 'ignore' to ignore\n" -"errors. (Note that ignoring encoding errors can lead to data loss.)\n" -"See the documentation for codecs.register or run 'help(codecs.Codec)'\n" -"for a list of the permitted encoding error strings.\n" -"\n" -"newline controls how universal newlines works (it only applies to text\n" -"mode). It can be None, '', '\\n', '\\r', and '\\r\\n'. It works as\n" -"follows:\n" -"\n" -"* On input, if newline is None, universal newlines mode is\n" -" enabled. Lines in the input can end in '\\n', '\\r', or '\\r\\n', and\n" -" these are translated into '\\n' before being returned to the\n" -" caller. If it is '', universal newline mode is enabled, but line\n" -" endings are returned to the caller untranslated. If it has any of\n" -" the other legal values, input lines are only terminated by the given\n" -" string, and the line ending is returned to the caller untranslated.\n" -"\n" -"* On output, if newline is None, any '\\n' characters written are\n" -" translated to the system default line separator, os.linesep. If\n" -" newline is '' or '\\n', no translation takes place. If newline is any\n" -" of the other legal values, any '\\n' characters written are translated\n" -" to the given string.\n" -"\n" -"If closefd is False, the underlying file descriptor will be kept open\n" -"when the file is closed. This does not work when a file name is given\n" -"and must be True in that case.\n" -"\n" -"A custom opener can be used by passing a callable as *opener*. The\n" -"underlying file descriptor for the file object is then obtained by\n" -"calling *opener* with (*file*, *flags*). *opener* must return an open\n" -"file descriptor (passing os.open as *opener* results in functionality\n" -"similar to passing None).\n" -"\n" -"open() returns a file object whose type depends on the mode, and\n" -"through which the standard file operations such as reading and writing\n" -"are performed. When open() is used to open a file in a text mode ('w',\n" -"'r', 'wt', 'rt', etc.), it returns a TextIOWrapper. When used to open\n" -"a file in a binary mode, the returned class varies: in read binary\n" -"mode, it returns a BufferedReader; in write binary and append binary\n" -"modes, it returns a BufferedWriter, and in read/write mode, it returns\n" -"a BufferedRandom.\n" -"\n" -"It is also possible to use a string or bytearray as a file for both\n" -"reading and writing. For strings StringIO can be used like a file\n" -"opened in a text mode, and for bytes a BytesIO can be used like a file\n" -"opened in a binary mode.\n" - ); +/*[clinic input] +module _io + +_io.open + file: object + mode: str = "r" + buffering: int = -1 + encoding: str(nullable=True) = NULL + errors: str(nullable=True) = NULL + newline: str(nullable=True) = NULL + closefd: int(c_default="1") = True + opener: object = None + +Open file and return a stream. Raise IOError upon failure. + +file is either a text or byte string giving the name (and the path +if the file isn't in the current working directory) of the file to +be opened or an integer file descriptor of the file to be +wrapped. (If a file descriptor is given, it is closed when the +returned I/O object is closed, unless closefd is set to False.) + +mode is an optional string that specifies the mode in which the file +is opened. It defaults to 'r' which means open for reading in text +mode. Other common values are 'w' for writing (truncating the file if +it already exists), 'x' for creating and writing to a new file, and +'a' for appending (which on some Unix systems, means that all writes +append to the end of the file regardless of the current seek position). +In text mode, if encoding is not specified the encoding used is platform +dependent: locale.getpreferredencoding(False) is called to get the +current locale encoding. (For reading and writing raw bytes use binary +mode and leave encoding unspecified.) The available modes are: + +========= =============================================================== +Character Meaning +--------- --------------------------------------------------------------- +'r' open for reading (default) +'w' open for writing, truncating the file first +'x' create a new file and open it for writing +'a' open for writing, appending to the end of the file if it exists +'b' binary mode +'t' text mode (default) +'+' open a disk file for updating (reading and writing) +'U' universal newline mode (deprecated) +========= =============================================================== + +The default mode is 'rt' (open for reading text). For binary random +access, the mode 'w+b' opens and truncates the file to 0 bytes, while +'r+b' opens the file without truncation. The 'x' mode implies 'w' and +raises an `FileExistsError` if the file already exists. + +Python distinguishes between files opened in binary and text modes, +even when the underlying operating system doesn't. Files opened in +binary mode (appending 'b' to the mode argument) return contents as +bytes objects without any decoding. In text mode (the default, or when +'t' is appended to the mode argument), the contents of the file are +returned as strings, the bytes having been first decoded using a +platform-dependent encoding or using the specified encoding if given. + +'U' mode is deprecated and will raise an exception in future versions +of Python. It has no effect in Python 3. Use newline to control +universal newlines mode. + +buffering is an optional integer used to set the buffering policy. +Pass 0 to switch buffering off (only allowed in binary mode), 1 to select +line buffering (only usable in text mode), and an integer > 1 to indicate +the size of a fixed-size chunk buffer. When no buffering argument is +given, the default buffering policy works as follows: + +* Binary files are buffered in fixed-size chunks; the size of the buffer + is chosen using a heuristic trying to determine the underlying device's + "block size" and falling back on `io.DEFAULT_BUFFER_SIZE`. + On many systems, the buffer will typically be 4096 or 8192 bytes long. + +* "Interactive" text files (files for which isatty() returns True) + use line buffering. Other text files use the policy described above + for binary files. + +encoding is the name of the encoding used to decode or encode the +file. This should only be used in text mode. The default encoding is +platform dependent, but any encoding supported by Python can be +passed. See the codecs module for the list of supported encodings. + +errors is an optional string that specifies how encoding errors are to +be handled---this argument should not be used in binary mode. Pass +'strict' to raise a ValueError exception if there is an encoding error +(the default of None has the same effect), or pass 'ignore' to ignore +errors. (Note that ignoring encoding errors can lead to data loss.) +See the documentation for codecs.register or run 'help(codecs.Codec)' +for a list of the permitted encoding error strings. + +newline controls how universal newlines works (it only applies to text +mode). It can be None, '', '\n', '\r', and '\r\n'. It works as +follows: + +* On input, if newline is None, universal newlines mode is + enabled. Lines in the input can end in '\n', '\r', or '\r\n', and + these are translated into '\n' before being returned to the + caller. If it is '', universal newline mode is enabled, but line + endings are returned to the caller untranslated. If it has any of + the other legal values, input lines are only terminated by the given + string, and the line ending is returned to the caller untranslated. + +* On output, if newline is None, any '\n' characters written are + translated to the system default line separator, os.linesep. If + newline is '' or '\n', no translation takes place. If newline is any + of the other legal values, any '\n' characters written are translated + to the given string. + +If closefd is False, the underlying file descriptor will be kept open +when the file is closed. This does not work when a file name is given +and must be True in that case. + +A custom opener can be used by passing a callable as *opener*. The +underlying file descriptor for the file object is then obtained by +calling *opener* with (*file*, *flags*). *opener* must return an open +file descriptor (passing os.open as *opener* results in functionality +similar to passing None). + +open() returns a file object whose type depends on the mode, and +through which the standard file operations such as reading and writing +are performed. When open() is used to open a file in a text mode ('w', +'r', 'wt', 'rt', etc.), it returns a TextIOWrapper. When used to open +a file in a binary mode, the returned class varies: in read binary +mode, it returns a BufferedReader; in write binary and append binary +modes, it returns a BufferedWriter, and in read/write mode, it returns +a BufferedRandom. + +It is also possible to use a string or bytearray as a file for both +reading and writing. For strings StringIO can be used like a file +opened in a text mode, and for bytes a BytesIO can be used like a file +opened in a binary mode. +[clinic start generated code]*/ static PyObject * -io_open(PyObject *self, PyObject *args, PyObject *kwds) +_io_open_impl(PyModuleDef *module, PyObject *file, const char *mode, + int buffering, const char *encoding, const char *errors, + const char *newline, int closefd, PyObject *opener) +/*[clinic end generated code: output=7615d0d746eb14d2 input=0541ce15691a82f2]*/ { - char *kwlist[] = {"file", "mode", "buffering", - "encoding", "errors", "newline", - "closefd", "opener", NULL}; - PyObject *file, *opener = Py_None; - char *mode = "r"; - int buffering = -1, closefd = 1; - char *encoding = NULL, *errors = NULL, *newline = NULL; unsigned i; int creating = 0, reading = 0, writing = 0, appending = 0, updating = 0; @@ -242,13 +247,6 @@ _Py_IDENTIFIER(mode); _Py_IDENTIFIER(close); - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|sizzziO:open", kwlist, - &file, &mode, &buffering, - &encoding, &errors, &newline, - &closefd, &opener)) { - return NULL; - } - if (!PyUnicode_Check(file) && !PyBytes_Check(file) && !PyNumber_Check(file)) { @@ -611,8 +609,10 @@ * Module definition */ +#include "clinic/_iomodule.c.h" + static PyMethodDef module_methods[] = { - {"open", (PyCFunction)io_open, METH_VARARGS|METH_KEYWORDS, open_doc}, + _IO_OPEN_METHODDEF {NULL, NULL} }; diff --git a/Modules/_io/bufferedio.c b/Modules/_io/bufferedio.c --- a/Modules/_io/bufferedio.c +++ b/Modules/_io/bufferedio.c @@ -13,6 +13,24 @@ #include "pythread.h" #include "_iomodule.h" +/*[clinic input] +module _io +class _io._BufferedIOBase "PyObject *" "&PyBufferedIOBase_Type" +class _io._Buffered "buffered *" "&PyBufferedIOBase_Type" +class _io.BufferedReader "buffered *" "&PyBufferedReader_Type" +class _io.BufferedWriter "buffered *" "&PyBufferedWriter_Type" +class _io.BufferedRWPair "rwpair *" "&PyBufferedRWPair_Type" +class _io.BufferedRandom "buffered *" "&PyBufferedRandom_Type" +[clinic start generated code]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=59460b9c5639984d]*/ + +/*[python input] +class io_ssize_t_converter(CConverter): + type = 'Py_ssize_t' + converter = '_PyIO_ConvertSsize_t' +[python start generated code]*/ +/*[python end generated code: output=da39a3ee5e6b4b0d input=d0a811d3cbfd1b33]*/ + _Py_IDENTIFIER(close); _Py_IDENTIFIER(_dealloc_warn); _Py_IDENTIFIER(flush); @@ -48,61 +66,63 @@ ); static PyObject * -_bufferediobase_readinto_generic(PyObject *self, PyObject *args, char readinto1) +_bufferediobase_readinto_generic(PyObject *self, Py_buffer *buffer, char readinto1) { - Py_buffer buf; Py_ssize_t len; PyObject *data; - if (!PyArg_ParseTuple(args, - readinto1 ? "w*:readinto1" : "w*:readinto", - &buf)) { - return NULL; - } - data = _PyObject_CallMethodId(self, readinto1 ? &PyId_read1 : &PyId_read, - "n", buf.len); + "n", buffer->len); if (data == NULL) - goto error; + return NULL; if (!PyBytes_Check(data)) { Py_DECREF(data); PyErr_SetString(PyExc_TypeError, "read() should return bytes"); - goto error; + return NULL; } len = Py_SIZE(data); - if (len > buf.len) { + if (len > buffer->len) { PyErr_Format(PyExc_ValueError, "read() returned too much data: " "%zd bytes requested, %zd returned", - buf.len, len); + buffer->len, len); Py_DECREF(data); - goto error; + return NULL; } - memcpy(buf.buf, PyBytes_AS_STRING(data), len); + memcpy(buffer->buf, PyBytes_AS_STRING(data), len); - PyBuffer_Release(&buf); Py_DECREF(data); return PyLong_FromSsize_t(len); - - error: - PyBuffer_Release(&buf); - return NULL; } +/*[clinic input] +_io._BufferedIOBase.readinto + buffer: Py_buffer(types={'rwbuffer'}) + / +[clinic start generated code]*/ + static PyObject * -bufferediobase_readinto(PyObject *self, PyObject *args) +_io__BufferedIOBase_readinto_impl(PyObject *self, Py_buffer *buffer) +/*[clinic end generated code: output=8c8cda6684af8038 input=f8242a06c21763a0]*/ { - return _bufferediobase_readinto_generic(self, args, 0); + return _bufferediobase_readinto_generic(self, buffer, 0); } +/*[clinic input] +_io._BufferedIOBase.readinto1 + buffer: Py_buffer(types={'rwbuffer'}) + / +[clinic start generated code]*/ + static PyObject * -bufferediobase_readinto1(PyObject *self, PyObject *args) +_io__BufferedIOBase_readinto1_impl(PyObject *self, Py_buffer *buffer) +/*[clinic end generated code: output=358623e4fd2b69d3 input=2003e706c730bd21]*/ { - return _bufferediobase_readinto_generic(self, args, 1); + return _bufferediobase_readinto_generic(self, buffer, 1); } static PyObject * @@ -114,14 +134,18 @@ return NULL; } -PyDoc_STRVAR(bufferediobase_detach_doc, - "Disconnect this buffer from its underlying raw stream and return it.\n" - "\n" - "After the raw stream has been detached, the buffer is in an unusable\n" - "state.\n"); +/*[clinic input] +_io._BufferedIOBase.detach + +Disconnect this buffer from its underlying raw stream and return it. + +After the raw stream has been detached, the buffer is in an unusable +state. +[clinic start generated code]*/ static PyObject * -bufferediobase_detach(PyObject *self) +_io__BufferedIOBase_detach_impl(PyObject *self) +/*[clinic end generated code: output=754977c8d10ed88c input=822427fb58fe4169]*/ { return bufferediobase_unsupported("detach"); } @@ -179,69 +203,6 @@ } -static PyMethodDef bufferediobase_methods[] = { - {"detach", (PyCFunction)bufferediobase_detach, METH_NOARGS, bufferediobase_detach_doc}, - {"read", bufferediobase_read, METH_VARARGS, bufferediobase_read_doc}, - {"read1", bufferediobase_read1, METH_VARARGS, bufferediobase_read1_doc}, - {"readinto", bufferediobase_readinto, METH_VARARGS, NULL}, - {"readinto1", bufferediobase_readinto1, METH_VARARGS, NULL}, - {"write", bufferediobase_write, METH_VARARGS, bufferediobase_write_doc}, - {NULL, NULL} -}; - -PyTypeObject PyBufferedIOBase_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "_io._BufferedIOBase", /*tp_name*/ - 0, /*tp_basicsize*/ - 0, /*tp_itemsize*/ - 0, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare */ - 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 | Py_TPFLAGS_BASETYPE - | Py_TPFLAGS_HAVE_FINALIZE, /*tp_flags*/ - bufferediobase_doc, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - bufferediobase_methods, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - &PyIOBase_Type, /* 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, /* tp_free */ - 0, /* tp_is_gc */ - 0, /* tp_bases */ - 0, /* tp_mro */ - 0, /* tp_cache */ - 0, /* tp_subclasses */ - 0, /* tp_weaklist */ - 0, /* tp_del */ - 0, /* tp_version_tag */ - 0, /* tp_finalize */ -}; - - typedef struct { PyObject_HEAD @@ -896,17 +857,20 @@ return res; } +/*[clinic input] +_io._Buffered.peek + size: Py_ssize_t = 0 + / + +[clinic start generated code]*/ + static PyObject * -buffered_peek(buffered *self, PyObject *args) +_io__Buffered_peek_impl(buffered *self, Py_ssize_t size) +/*[clinic end generated code: output=ba7a097ca230102b input=37ffb97d06ff4adb]*/ { - Py_ssize_t n = 0; PyObject *res = NULL; CHECK_INITIALIZED(self) - if (!PyArg_ParseTuple(args, "|n:peek", &n)) { - return NULL; - } - if (!ENTER_BUFFERED(self)) return NULL; @@ -923,16 +887,19 @@ return res; } +/*[clinic input] +_io._Buffered.read + size as n: io_ssize_t = -1 + / +[clinic start generated code]*/ + static PyObject * -buffered_read(buffered *self, PyObject *args) +_io__Buffered_read_impl(buffered *self, Py_ssize_t n) +/*[clinic end generated code: output=f41c78bb15b9bbe9 input=c0939ec7f9e9354f]*/ { - Py_ssize_t n = -1; PyObject *res; CHECK_INITIALIZED(self) - if (!PyArg_ParseTuple(args, "|O&:read", &_PyIO_ConvertSsize_t, &n)) { - return NULL; - } if (n < -1) { PyErr_SetString(PyExc_ValueError, "read length must be positive or -1"); @@ -961,17 +928,20 @@ return res; } +/*[clinic input] +_io._Buffered.read1 + size as n: Py_ssize_t + / +[clinic start generated code]*/ + static PyObject * -buffered_read1(buffered *self, PyObject *args) +_io__Buffered_read1_impl(buffered *self, Py_ssize_t n) +/*[clinic end generated code: output=bcc4fb4e54d103a3 input=8d2869c18b983184]*/ { - Py_ssize_t n, have, r; + Py_ssize_t have, r; PyObject *res = NULL; CHECK_INITIALIZED(self) - if (!PyArg_ParseTuple(args, "n:read1", &n)) { - return NULL; - } - if (n < 0) { PyErr_SetString(PyExc_ValueError, "read length must be positive"); @@ -1012,34 +982,27 @@ } static PyObject * -_buffered_readinto_generic(buffered *self, PyObject *args, char readinto1) +_buffered_readinto_generic(buffered *self, Py_buffer *buffer, char readinto1) { - Py_buffer buf; Py_ssize_t n, written = 0, remaining; PyObject *res = NULL; CHECK_INITIALIZED(self) - if (!PyArg_ParseTuple(args, - readinto1 ? "w*:readinto1" : "w*:readinto", - &buf)) - return NULL; - n = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t); if (n > 0) { - if (n >= buf.len) { - memcpy(buf.buf, self->buffer + self->pos, buf.len); - self->pos += buf.len; - res = PyLong_FromSsize_t(buf.len); - goto end_unlocked; + if (n >= buffer->len) { + memcpy(buffer->buf, self->buffer + self->pos, buffer->len); + self->pos += buffer->len; + return PyLong_FromSsize_t(buffer->len); } - memcpy(buf.buf, self->buffer + self->pos, n); + memcpy(buffer->buf, self->buffer + self->pos, n); self->pos += n; written = n; } if (!ENTER_BUFFERED(self)) - goto end_unlocked; + return NULL; if (self->writable) { res = buffered_flush_and_rewind_unlocked(self); @@ -1051,13 +1014,13 @@ _bufferedreader_reset_buf(self); self->pos = 0; - for (remaining = buf.len - written; + for (remaining = buffer->len - written; remaining > 0; written += n, remaining -= n) { /* If remaining bytes is larger than internal buffer size, copy * directly into caller's buffer. */ if (remaining > self->buffer_size) { - n = _bufferedreader_raw_read(self, (char *) buf.buf + written, + n = _bufferedreader_raw_read(self, (char *) buffer->buf + written, remaining); } @@ -1068,7 +1031,7 @@ if (n > 0) { if (n > remaining) n = remaining; - memcpy((char *) buf.buf + written, + memcpy((char *) buffer->buf + written, self->buffer + self->pos, n); self->pos += n; continue; /* short circuit */ @@ -1097,21 +1060,33 @@ end: LEAVE_BUFFERED(self); -end_unlocked: - PyBuffer_Release(&buf); return res; } +/*[clinic input] +_io._Buffered.readinto + buffer: Py_buffer(types={'rwbuffer'}) + / +[clinic start generated code]*/ + static PyObject * -buffered_readinto(buffered *self, PyObject *args) +_io__Buffered_readinto_impl(buffered *self, Py_buffer *buffer) +/*[clinic end generated code: output=bcb376580b1d8170 input=962b7496eac38b3a]*/ { - return _buffered_readinto_generic(self, args, 0); + return _buffered_readinto_generic(self, buffer, 0); } +/*[clinic input] +_io._Buffered.readinto1 + buffer: Py_buffer(types={'rwbuffer'}) + / +[clinic start generated code]*/ + static PyObject * -buffered_readinto1(buffered *self, PyObject *args) +_io__Buffered_readinto1_impl(buffered *self, Py_buffer *buffer) +/*[clinic end generated code: output=6e5c6ac5868205d6 input=834614d93f0adeb5]*/ { - return _buffered_readinto_generic(self, args, 1); + return _buffered_readinto_generic(self, buffer, 1); } @@ -1226,15 +1201,18 @@ return res; } +/*[clinic input] +_io._Buffered.readline + size: io_ssize_t = -1 + / +[clinic start generated code]*/ + static PyObject * -buffered_readline(buffered *self, PyObject *args) +_io__Buffered_readline_impl(buffered *self, Py_ssize_t size) +/*[clinic end generated code: output=24dd2aa6e33be83c input=ff1e0df821cb4e5c]*/ { - Py_ssize_t limit = -1; - CHECK_INITIALIZED(self) - if (!PyArg_ParseTuple(args, "|O&:readline", &_PyIO_ConvertSsize_t, &limit)) - return NULL; - return _buffered_readline(self, limit); + return _buffered_readline(self, size); } @@ -1252,17 +1230,21 @@ return PyLong_FromOff_t(pos); } +/*[clinic input] +_io._Buffered.seek + target as targetobj: object + whence: int = 0 + / +[clinic start generated code]*/ + static PyObject * -buffered_seek(buffered *self, PyObject *args) +_io__Buffered_seek_impl(buffered *self, PyObject *targetobj, int whence) +/*[clinic end generated code: output=7ae0e8dc46efdefb input=a9c4920bfcba6163]*/ { Py_off_t target, n; - int whence = 0; - PyObject *targetobj, *res = NULL; + PyObject *res = NULL; CHECK_INITIALIZED(self) - 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. @@ -1344,17 +1326,19 @@ return res; } +/*[clinic input] +_io._Buffered.truncate + pos: object = None + / +[clinic start generated code]*/ + static PyObject * -buffered_truncate(buffered *self, PyObject *args) +_io__Buffered_truncate_impl(buffered *self, PyObject *pos) +/*[clinic end generated code: output=667ca03c60c270de input=8a1be34d57cca2d3]*/ { - PyObject *pos = Py_None; PyObject *res = NULL; CHECK_INITIALIZED(self) - if (!PyArg_ParseTuple(args, "|O:truncate", &pos)) { - return NULL; - } - if (!ENTER_BUFFERED(self)) return NULL; @@ -1439,29 +1423,27 @@ * class BufferedReader */ -PyDoc_STRVAR(bufferedreader_doc, - "Create a new buffered reader using the given readable raw IO object."); - static void _bufferedreader_reset_buf(buffered *self) { self->read_end = -1; } +/*[clinic input] +_io.BufferedReader.__init__ + raw: object + buffer_size: Py_ssize_t(c_default="DEFAULT_BUFFER_SIZE") = DEFAULT_BUFFER_SIZE + +Create a new buffered reader using the given readable raw IO object. +[clinic start generated code]*/ + static int -bufferedreader_init(buffered *self, PyObject *args, PyObject *kwds) +_io_BufferedReader___init___impl(buffered *self, PyObject *raw, + Py_ssize_t buffer_size) +/*[clinic end generated code: output=cddcfefa0ed294c4 input=fb887e06f11b4e48]*/ { - char *kwlist[] = {"raw", "buffer_size", NULL}; - Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE; - PyObject *raw; - self->ok = 0; self->detached = 0; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|n:BufferedReader", kwlist, - &raw, &buffer_size)) { - return -1; - } - if (_PyIOBase_check_readable(raw, Py_True) == NULL) return -1; @@ -1782,112 +1764,12 @@ self->pos = 0; return PyBytes_FromStringAndSize(self->buffer, r); } - -static PyMethodDef bufferedreader_methods[] = { - /* BufferedIOMixin methods */ - {"detach", (PyCFunction)buffered_detach, METH_NOARGS}, - {"flush", (PyCFunction)buffered_simple_flush, METH_NOARGS}, - {"close", (PyCFunction)buffered_close, METH_NOARGS}, - {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS}, - {"readable", (PyCFunction)buffered_readable, METH_NOARGS}, - {"writable", (PyCFunction)buffered_writable, METH_NOARGS}, - {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS}, - {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS}, - {"_dealloc_warn", (PyCFunction)buffered_dealloc_warn, METH_O}, - {"__getstate__", (PyCFunction)buffered_getstate, METH_NOARGS}, - - {"read", (PyCFunction)buffered_read, METH_VARARGS}, - {"peek", (PyCFunction)buffered_peek, METH_VARARGS}, - {"read1", (PyCFunction)buffered_read1, METH_VARARGS}, - {"readinto", (PyCFunction)buffered_readinto, METH_VARARGS}, - {"readinto1", (PyCFunction)buffered_readinto1, METH_VARARGS}, - {"readline", (PyCFunction)buffered_readline, METH_VARARGS}, - {"seek", (PyCFunction)buffered_seek, METH_VARARGS}, - {"tell", (PyCFunction)buffered_tell, METH_NOARGS}, - {"truncate", (PyCFunction)buffered_truncate, METH_VARARGS}, - {"__sizeof__", (PyCFunction)buffered_sizeof, METH_NOARGS}, - {NULL, NULL} -}; - -static PyMemberDef bufferedreader_members[] = { - {"raw", T_OBJECT, offsetof(buffered, raw), READONLY}, - {"_finalizing", T_BOOL, offsetof(buffered, finalizing), 0}, - {NULL} -}; - -static PyGetSetDef bufferedreader_getset[] = { - {"closed", (getter)buffered_closed_get, NULL, NULL}, - {"name", (getter)buffered_name_get, NULL, NULL}, - {"mode", (getter)buffered_mode_get, NULL, NULL}, - {NULL} -}; - - -PyTypeObject PyBufferedReader_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "_io.BufferedReader", /*tp_name*/ - sizeof(buffered), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - (destructor)buffered_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare */ - (reprfunc)buffered_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 | Py_TPFLAGS_BASETYPE - | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_FINALIZE, /*tp_flags*/ - bufferedreader_doc, /* tp_doc */ - (traverseproc)buffered_traverse, /* tp_traverse */ - (inquiry)buffered_clear, /* tp_clear */ - 0, /* tp_richcompare */ - offsetof(buffered, weakreflist), /*tp_weaklistoffset*/ - 0, /* tp_iter */ - (iternextfunc)buffered_iternext, /* tp_iternext */ - bufferedreader_methods, /* tp_methods */ - bufferedreader_members, /* tp_members */ - bufferedreader_getset, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - offsetof(buffered, dict), /* tp_dictoffset */ - (initproc)bufferedreader_init, /* tp_init */ - 0, /* tp_alloc */ - PyType_GenericNew, /* tp_new */ - 0, /* tp_free */ - 0, /* tp_is_gc */ - 0, /* tp_bases */ - 0, /* tp_mro */ - 0, /* tp_cache */ - 0, /* tp_subclasses */ - 0, /* tp_weaklist */ - 0, /* tp_del */ - 0, /* tp_version_tag */ - 0, /* tp_finalize */ -}; /* * class BufferedWriter */ -PyDoc_STRVAR(bufferedwriter_doc, - "A buffer for a writeable sequential RawIO object.\n" - "\n" - "The constructor creates a BufferedWriter for the given writeable raw\n" - "stream. If the buffer_size is not given, it defaults to\n" - "DEFAULT_BUFFER_SIZE.\n" - ); - static void _bufferedwriter_reset_buf(buffered *self) { @@ -1895,21 +1777,26 @@ self->write_end = -1; } +/*[clinic input] +_io.BufferedWriter.__init__ + raw: object + buffer_size: Py_ssize_t(c_default="DEFAULT_BUFFER_SIZE") = DEFAULT_BUFFER_SIZE + +A buffer for a writeable sequential RawIO object. + +The constructor creates a BufferedWriter for the given writeable raw +stream. If the buffer_size is not given, it defaults to +DEFAULT_BUFFER_SIZE. +[clinic start generated code]*/ + static int -bufferedwriter_init(buffered *self, PyObject *args, PyObject *kwds) +_io_BufferedWriter___init___impl(buffered *self, PyObject *raw, + Py_ssize_t buffer_size) +/*[clinic end generated code: output=c8942a020c0dee64 input=914be9b95e16007b]*/ { - char *kwlist[] = {"raw", "buffer_size", NULL}; - Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE; - PyObject *raw; - self->ok = 0; self->detached = 0; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|n:BufferedWriter", kwlist, - &raw, &buffer_size)) { - return -1; - } - if (_PyIOBase_check_writable(raw, Py_True) == NULL) return -1; @@ -2030,29 +1917,28 @@ return NULL; } +/*[clinic input] +_io.BufferedWriter.write + buffer: Py_buffer + / +[clinic start generated code]*/ + static PyObject * -bufferedwriter_write(buffered *self, PyObject *args) +_io_BufferedWriter_write_impl(buffered *self, Py_buffer *buffer) +/*[clinic end generated code: output=7f8d1365759bfc6b input=dd87dd85fc7f8850]*/ { PyObject *res = NULL; - Py_buffer buf; Py_ssize_t written, avail, remaining; Py_off_t offset; CHECK_INITIALIZED(self) - if (!PyArg_ParseTuple(args, "y*:write", &buf)) { + if (IS_CLOSED(self)) { + PyErr_SetString(PyExc_ValueError, "write to closed file"); return NULL; } - if (IS_CLOSED(self)) { - PyErr_SetString(PyExc_ValueError, "write to closed file"); - PyBuffer_Release(&buf); + if (!ENTER_BUFFERED(self)) return NULL; - } - - if (!ENTER_BUFFERED(self)) { - PyBuffer_Release(&buf); - return NULL; - } /* Fast path: the data to write can be fully buffered. */ if (!VALID_READ_BUFFER(self) && !VALID_WRITE_BUFFER(self)) { @@ -2060,15 +1946,15 @@ self->raw_pos = 0; } avail = Py_SAFE_DOWNCAST(self->buffer_size - self->pos, Py_off_t, Py_ssize_t); - if (buf.len <= avail) { - memcpy(self->buffer + self->pos, buf.buf, buf.len); + if (buffer->len <= avail) { + memcpy(self->buffer + self->pos, buffer->buf, buffer->len); if (!VALID_WRITE_BUFFER(self) || self->write_pos > self->pos) { self->write_pos = self->pos; } - ADJUST_POSITION(self, self->pos + buf.len); + ADJUST_POSITION(self, self->pos + buffer->len); if (self->pos > self->write_end) self->write_end = self->pos; - written = buf.len; + written = buffer->len; goto end; } @@ -2091,17 +1977,17 @@ self->write_pos = 0; avail = Py_SAFE_DOWNCAST(self->buffer_size - self->write_end, Py_off_t, Py_ssize_t); - if (buf.len <= avail) { + if (buffer->len <= avail) { /* Everything can be buffered */ PyErr_Clear(); - memcpy(self->buffer + self->write_end, buf.buf, buf.len); - self->write_end += buf.len; - self->pos += buf.len; - written = buf.len; + memcpy(self->buffer + self->write_end, buffer->buf, buffer->len); + self->write_end += buffer->len; + self->pos += buffer->len; + written = buffer->len; goto end; } /* Buffer as much as possible. */ - memcpy(self->buffer + self->write_end, buf.buf, avail); + memcpy(self->buffer + self->write_end, buffer->buf, avail); self->write_end += avail; self->pos += avail; /* XXX Modifying the existing exception e using the pointer w @@ -2127,11 +2013,11 @@ } /* Then write buf itself. At this point the buffer has been emptied. */ - remaining = buf.len; + remaining = buffer->len; written = 0; while (remaining > self->buffer_size) { Py_ssize_t n = _bufferedwriter_raw_write( - self, (char *) buf.buf + written, buf.len - written); + self, (char *) buffer->buf + written, buffer->len - written); if (n == -1) { goto error; } else if (n == -2) { @@ -2139,7 +2025,7 @@ if (remaining > self->buffer_size) { /* Can't buffer everything, still buffer as much as possible */ memcpy(self->buffer, - (char *) buf.buf + written, self->buffer_size); + (char *) buffer->buf + written, self->buffer_size); self->raw_pos = 0; ADJUST_POSITION(self, self->buffer_size); self->write_end = self->buffer_size; @@ -2162,7 +2048,7 @@ if (self->readable) _bufferedreader_reset_buf(self); if (remaining > 0) { - memcpy(self->buffer, (char *) buf.buf + written, remaining); + memcpy(self->buffer, (char *) buffer->buf + written, remaining); written += remaining; } self->write_pos = 0; @@ -2176,96 +2062,8 @@ error: LEAVE_BUFFERED(self) - PyBuffer_Release(&buf); return res; } - -static PyMethodDef bufferedwriter_methods[] = { - /* BufferedIOMixin methods */ - {"close", (PyCFunction)buffered_close, METH_NOARGS}, - {"detach", (PyCFunction)buffered_detach, METH_NOARGS}, - {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS}, - {"readable", (PyCFunction)buffered_readable, METH_NOARGS}, - {"writable", (PyCFunction)buffered_writable, METH_NOARGS}, - {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS}, - {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS}, - {"_dealloc_warn", (PyCFunction)buffered_dealloc_warn, METH_O}, - {"__getstate__", (PyCFunction)buffered_getstate, METH_NOARGS}, - - {"write", (PyCFunction)bufferedwriter_write, METH_VARARGS}, - {"truncate", (PyCFunction)buffered_truncate, METH_VARARGS}, - {"flush", (PyCFunction)buffered_flush, METH_NOARGS}, - {"seek", (PyCFunction)buffered_seek, METH_VARARGS}, - {"tell", (PyCFunction)buffered_tell, METH_NOARGS}, - {"__sizeof__", (PyCFunction)buffered_sizeof, METH_NOARGS}, - {NULL, NULL} -}; - -static PyMemberDef bufferedwriter_members[] = { - {"raw", T_OBJECT, offsetof(buffered, raw), READONLY}, - {"_finalizing", T_BOOL, offsetof(buffered, finalizing), 0}, - {NULL} -}; - -static PyGetSetDef bufferedwriter_getset[] = { - {"closed", (getter)buffered_closed_get, NULL, NULL}, - {"name", (getter)buffered_name_get, NULL, NULL}, - {"mode", (getter)buffered_mode_get, NULL, NULL}, - {NULL} -}; - - -PyTypeObject PyBufferedWriter_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "_io.BufferedWriter", /*tp_name*/ - sizeof(buffered), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - (destructor)buffered_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare */ - (reprfunc)buffered_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 | Py_TPFLAGS_BASETYPE - | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_FINALIZE, /*tp_flags*/ - bufferedwriter_doc, /* tp_doc */ - (traverseproc)buffered_traverse, /* tp_traverse */ - (inquiry)buffered_clear, /* tp_clear */ - 0, /* tp_richcompare */ - offsetof(buffered, weakreflist), /*tp_weaklistoffset*/ - 0, /* tp_iter */ - 0, /* tp_iternext */ - bufferedwriter_methods, /* tp_methods */ - bufferedwriter_members, /* tp_members */ - bufferedwriter_getset, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - offsetof(buffered, dict), /* tp_dictoffset */ - (initproc)bufferedwriter_init, /* tp_init */ - 0, /* tp_alloc */ - PyType_GenericNew, /* tp_new */ - 0, /* tp_free */ - 0, /* tp_is_gc */ - 0, /* tp_bases */ - 0, /* tp_mro */ - 0, /* tp_cache */ - 0, /* tp_subclasses */ - 0, /* tp_weaklist */ - 0, /* tp_del */ - 0, /* tp_version_tag */ - 0, /* tp_finalize */ -}; @@ -2273,18 +2071,6 @@ * BufferedRWPair */ -PyDoc_STRVAR(bufferedrwpair_doc, - "A buffered reader and writer object together.\n" - "\n" - "A buffered reader object and buffered writer object put together to\n" - "form a sequential IO object that can read and write. This is typically\n" - "used with a socket or two-way pipe.\n" - "\n" - "reader and writer are RawIOBase objects that are readable and\n" - "writeable respectively. If the buffer_size is omitted it defaults to\n" - "DEFAULT_BUFFER_SIZE.\n" - ); - /* XXX The usefulness of this (compared to having two separate IO objects) is * questionable. */ @@ -2297,17 +2083,29 @@ PyObject *weakreflist; } rwpair; +/*[clinic input] +_io.BufferedRWPair.__init__ + reader: object + writer: object + buffer_size: Py_ssize_t(c_default="DEFAULT_BUFFER_SIZE") = DEFAULT_BUFFER_SIZE + / + +A buffered reader and writer object together. + +A buffered reader object and buffered writer object put together to +form a sequential IO object that can read and write. This is typically +used with a socket or two-way pipe. + +reader and writer are RawIOBase objects that are readable and +writeable respectively. If the buffer_size is omitted it defaults to +DEFAULT_BUFFER_SIZE. +[clinic start generated code]*/ + static int -bufferedrwpair_init(rwpair *self, PyObject *args, PyObject *kwds) +_io_BufferedRWPair___init___impl(rwpair *self, PyObject *reader, + PyObject *writer, Py_ssize_t buffer_size) +/*[clinic end generated code: output=327e73d1aee8f984 input=620d42d71f33a031]*/ { - PyObject *reader, *writer; - Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE; - - if (!PyArg_ParseTuple(args, "OO|n:BufferedRWPair", &reader, &writer, - &buffer_size)) { - return -1; - } - if (_PyIOBase_check_readable(reader, Py_True) == NULL) return -1; if (_PyIOBase_check_writable(writer, Py_True) == NULL) @@ -2472,6 +2270,306 @@ } return PyObject_GetAttr((PyObject *) self->writer, _PyIO_str_closed); } + + + +/* + * BufferedRandom + */ + +/*[clinic input] +_io.BufferedRandom.__init__ + raw: object + buffer_size: Py_ssize_t(c_default="DEFAULT_BUFFER_SIZE") = DEFAULT_BUFFER_SIZE + +A buffered interface to random access streams. + +The constructor creates a reader and writer for a seekable stream, +raw, given in the first argument. If the buffer_size is omitted it +defaults to DEFAULT_BUFFER_SIZE. +[clinic start generated code]*/ + +static int +_io_BufferedRandom___init___impl(buffered *self, PyObject *raw, + Py_ssize_t buffer_size) +/*[clinic end generated code: output=d3d64eb0f64e64a3 input=a4e818fb86d0e50c]*/ +{ + self->ok = 0; + self->detached = 0; + + if (_PyIOBase_check_seekable(raw, Py_True) == NULL) + return -1; + if (_PyIOBase_check_readable(raw, Py_True) == NULL) + return -1; + if (_PyIOBase_check_writable(raw, Py_True) == NULL) + return -1; + + Py_CLEAR(self->raw); + Py_INCREF(raw); + self->raw = raw; + self->buffer_size = buffer_size; + self->readable = 1; + self->writable = 1; + + if (_buffered_init(self) < 0) + return -1; + _bufferedreader_reset_buf(self); + _bufferedwriter_reset_buf(self); + self->pos = 0; + + self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedRandom_Type && + Py_TYPE(raw) == &PyFileIO_Type); + + self->ok = 1; + return 0; +} + +#include "clinic/bufferedio.c.h" + + +static PyMethodDef bufferediobase_methods[] = { + _IO__BUFFEREDIOBASE_DETACH_METHODDEF + {"read", bufferediobase_read, METH_VARARGS, bufferediobase_read_doc}, + {"read1", bufferediobase_read1, METH_VARARGS, bufferediobase_read1_doc}, + _IO__BUFFEREDIOBASE_READINTO_METHODDEF + _IO__BUFFEREDIOBASE_READINTO1_METHODDEF + {"write", bufferediobase_write, METH_VARARGS, bufferediobase_write_doc}, + {NULL, NULL} +}; + +PyTypeObject PyBufferedIOBase_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "_io._BufferedIOBase", /*tp_name*/ + 0, /*tp_basicsize*/ + 0, /*tp_itemsize*/ + 0, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare */ + 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 | Py_TPFLAGS_BASETYPE + | Py_TPFLAGS_HAVE_FINALIZE, /*tp_flags*/ + bufferediobase_doc, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + bufferediobase_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + &PyIOBase_Type, /* 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, /* tp_free */ + 0, /* tp_is_gc */ + 0, /* tp_bases */ + 0, /* tp_mro */ + 0, /* tp_cache */ + 0, /* tp_subclasses */ + 0, /* tp_weaklist */ + 0, /* tp_del */ + 0, /* tp_version_tag */ + 0, /* tp_finalize */ +}; + + +static PyMethodDef bufferedreader_methods[] = { + /* BufferedIOMixin methods */ + {"detach", (PyCFunction)buffered_detach, METH_NOARGS}, + {"flush", (PyCFunction)buffered_simple_flush, METH_NOARGS}, + {"close", (PyCFunction)buffered_close, METH_NOARGS}, + {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS}, + {"readable", (PyCFunction)buffered_readable, METH_NOARGS}, + {"writable", (PyCFunction)buffered_writable, METH_NOARGS}, + {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS}, + {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS}, + {"_dealloc_warn", (PyCFunction)buffered_dealloc_warn, METH_O}, + {"__getstate__", (PyCFunction)buffered_getstate, METH_NOARGS}, + + _IO__BUFFERED_READ_METHODDEF + _IO__BUFFERED_PEEK_METHODDEF + _IO__BUFFERED_READ1_METHODDEF + _IO__BUFFERED_READINTO_METHODDEF + _IO__BUFFERED_READINTO1_METHODDEF + _IO__BUFFERED_READLINE_METHODDEF + _IO__BUFFERED_SEEK_METHODDEF + {"tell", (PyCFunction)buffered_tell, METH_NOARGS}, + _IO__BUFFERED_TRUNCATE_METHODDEF + {"__sizeof__", (PyCFunction)buffered_sizeof, METH_NOARGS}, + {NULL, NULL} +}; + +static PyMemberDef bufferedreader_members[] = { + {"raw", T_OBJECT, offsetof(buffered, raw), READONLY}, + {"_finalizing", T_BOOL, offsetof(buffered, finalizing), 0}, + {NULL} +}; + +static PyGetSetDef bufferedreader_getset[] = { + {"closed", (getter)buffered_closed_get, NULL, NULL}, + {"name", (getter)buffered_name_get, NULL, NULL}, + {"mode", (getter)buffered_mode_get, NULL, NULL}, + {NULL} +}; + + +PyTypeObject PyBufferedReader_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "_io.BufferedReader", /*tp_name*/ + sizeof(buffered), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + (destructor)buffered_dealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare */ + (reprfunc)buffered_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 | Py_TPFLAGS_BASETYPE + | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_FINALIZE, /*tp_flags*/ + _io_BufferedReader___init____doc__, /* tp_doc */ + (traverseproc)buffered_traverse, /* tp_traverse */ + (inquiry)buffered_clear, /* tp_clear */ + 0, /* tp_richcompare */ + offsetof(buffered, weakreflist), /*tp_weaklistoffset*/ + 0, /* tp_iter */ + (iternextfunc)buffered_iternext, /* tp_iternext */ + bufferedreader_methods, /* tp_methods */ + bufferedreader_members, /* tp_members */ + bufferedreader_getset, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + offsetof(buffered, dict), /* tp_dictoffset */ + _io_BufferedReader___init__, /* tp_init */ + 0, /* tp_alloc */ + PyType_GenericNew, /* tp_new */ + 0, /* tp_free */ + 0, /* tp_is_gc */ + 0, /* tp_bases */ + 0, /* tp_mro */ + 0, /* tp_cache */ + 0, /* tp_subclasses */ + 0, /* tp_weaklist */ + 0, /* tp_del */ + 0, /* tp_version_tag */ + 0, /* tp_finalize */ +}; + + +static PyMethodDef bufferedwriter_methods[] = { + /* BufferedIOMixin methods */ + {"close", (PyCFunction)buffered_close, METH_NOARGS}, + {"detach", (PyCFunction)buffered_detach, METH_NOARGS}, + {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS}, + {"readable", (PyCFunction)buffered_readable, METH_NOARGS}, + {"writable", (PyCFunction)buffered_writable, METH_NOARGS}, + {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS}, + {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS}, + {"_dealloc_warn", (PyCFunction)buffered_dealloc_warn, METH_O}, + {"__getstate__", (PyCFunction)buffered_getstate, METH_NOARGS}, + + _IO_BUFFEREDWRITER_WRITE_METHODDEF + _IO__BUFFERED_TRUNCATE_METHODDEF + {"flush", (PyCFunction)buffered_flush, METH_NOARGS}, + _IO__BUFFERED_SEEK_METHODDEF + {"tell", (PyCFunction)buffered_tell, METH_NOARGS}, + {"__sizeof__", (PyCFunction)buffered_sizeof, METH_NOARGS}, + {NULL, NULL} +}; + +static PyMemberDef bufferedwriter_members[] = { + {"raw", T_OBJECT, offsetof(buffered, raw), READONLY}, + {"_finalizing", T_BOOL, offsetof(buffered, finalizing), 0}, + {NULL} +}; + +static PyGetSetDef bufferedwriter_getset[] = { + {"closed", (getter)buffered_closed_get, NULL, NULL}, + {"name", (getter)buffered_name_get, NULL, NULL}, + {"mode", (getter)buffered_mode_get, NULL, NULL}, + {NULL} +}; + + +PyTypeObject PyBufferedWriter_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "_io.BufferedWriter", /*tp_name*/ + sizeof(buffered), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + (destructor)buffered_dealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare */ + (reprfunc)buffered_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 | Py_TPFLAGS_BASETYPE + | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_FINALIZE, /*tp_flags*/ + _io_BufferedWriter___init____doc__, /* tp_doc */ + (traverseproc)buffered_traverse, /* tp_traverse */ + (inquiry)buffered_clear, /* tp_clear */ + 0, /* tp_richcompare */ + offsetof(buffered, weakreflist), /*tp_weaklistoffset*/ + 0, /* tp_iter */ + 0, /* tp_iternext */ + bufferedwriter_methods, /* tp_methods */ + bufferedwriter_members, /* tp_members */ + bufferedwriter_getset, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + offsetof(buffered, dict), /* tp_dictoffset */ + _io_BufferedWriter___init__, /* tp_init */ + 0, /* tp_alloc */ + PyType_GenericNew, /* tp_new */ + 0, /* tp_free */ + 0, /* tp_is_gc */ + 0, /* tp_bases */ + 0, /* tp_mro */ + 0, /* tp_cache */ + 0, /* tp_subclasses */ + 0, /* tp_weaklist */ + 0, /* tp_del */ + 0, /* tp_version_tag */ + 0, /* tp_finalize */ +}; + static PyMethodDef bufferedrwpair_methods[] = { {"read", (PyCFunction)bufferedrwpair_read, METH_VARARGS}, @@ -2521,7 +2619,7 @@ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_FINALIZE, /* tp_flags */ - bufferedrwpair_doc, /* tp_doc */ + _io_BufferedRWPair___init____doc__, /* tp_doc */ (traverseproc)bufferedrwpair_traverse, /* tp_traverse */ (inquiry)bufferedrwpair_clear, /* tp_clear */ 0, /* tp_richcompare */ @@ -2536,7 +2634,7 @@ 0, /* tp_descr_get */ 0, /* tp_descr_set */ offsetof(rwpair, dict), /* tp_dictoffset */ - (initproc)bufferedrwpair_init, /* tp_init */ + _io_BufferedRWPair___init__, /* tp_init */ 0, /* tp_alloc */ PyType_GenericNew, /* tp_new */ 0, /* tp_free */ @@ -2550,63 +2648,8 @@ 0, /* tp_version_tag */ 0, /* tp_finalize */ }; - -/* - * BufferedRandom - */ - -PyDoc_STRVAR(bufferedrandom_doc, - "A buffered interface to random access streams.\n" - "\n" - "The constructor creates a reader and writer for a seekable stream,\n" - "raw, given in the first argument. If the buffer_size is omitted it\n" - "defaults to DEFAULT_BUFFER_SIZE.\n" - ); - -static int -bufferedrandom_init(buffered *self, PyObject *args, PyObject *kwds) -{ - char *kwlist[] = {"raw", "buffer_size", NULL}; - Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE; - PyObject *raw; - - self->ok = 0; - self->detached = 0; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|n:BufferedRandom", kwlist, - &raw, &buffer_size)) { - return -1; - } - - if (_PyIOBase_check_seekable(raw, Py_True) == NULL) - return -1; - if (_PyIOBase_check_readable(raw, Py_True) == NULL) - return -1; - if (_PyIOBase_check_writable(raw, Py_True) == NULL) - return -1; - - Py_CLEAR(self->raw); - Py_INCREF(raw); - self->raw = raw; - self->buffer_size = buffer_size; - self->readable = 1; - self->writable = 1; - - if (_buffered_init(self) < 0) - return -1; - _bufferedreader_reset_buf(self); - _bufferedwriter_reset_buf(self); - self->pos = 0; - - self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedRandom_Type && - Py_TYPE(raw) == &PyFileIO_Type); - - self->ok = 1; - return 0; -} - static PyMethodDef bufferedrandom_methods[] = { /* BufferedIOMixin methods */ {"close", (PyCFunction)buffered_close, METH_NOARGS}, @@ -2621,16 +2664,16 @@ {"flush", (PyCFunction)buffered_flush, METH_NOARGS}, - {"seek", (PyCFunction)buffered_seek, METH_VARARGS}, + _IO__BUFFERED_SEEK_METHODDEF {"tell", (PyCFunction)buffered_tell, METH_NOARGS}, - {"truncate", (PyCFunction)buffered_truncate, METH_VARARGS}, - {"read", (PyCFunction)buffered_read, METH_VARARGS}, - {"read1", (PyCFunction)buffered_read1, METH_VARARGS}, - {"readinto", (PyCFunction)buffered_readinto, METH_VARARGS}, - {"readinto1", (PyCFunction)buffered_readinto1, METH_VARARGS}, - {"readline", (PyCFunction)buffered_readline, METH_VARARGS}, - {"peek", (PyCFunction)buffered_peek, METH_VARARGS}, - {"write", (PyCFunction)bufferedwriter_write, METH_VARARGS}, + _IO__BUFFERED_TRUNCATE_METHODDEF + _IO__BUFFERED_READ_METHODDEF + _IO__BUFFERED_READ1_METHODDEF + _IO__BUFFERED_READINTO_METHODDEF + _IO__BUFFERED_READINTO1_METHODDEF + _IO__BUFFERED_READLINE_METHODDEF + _IO__BUFFERED_PEEK_METHODDEF + _IO_BUFFEREDWRITER_WRITE_METHODDEF {"__sizeof__", (PyCFunction)buffered_sizeof, METH_NOARGS}, {NULL, NULL} }; @@ -2671,7 +2714,7 @@ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_FINALIZE, /*tp_flags*/ - bufferedrandom_doc, /* tp_doc */ + _io_BufferedRandom___init____doc__, /* tp_doc */ (traverseproc)buffered_traverse, /* tp_traverse */ (inquiry)buffered_clear, /* tp_clear */ 0, /* tp_richcompare */ @@ -2686,7 +2729,7 @@ 0, /* tp_descr_get */ 0, /* tp_descr_set */ offsetof(buffered, dict), /*tp_dictoffset*/ - (initproc)bufferedrandom_init, /* tp_init */ + _io_BufferedRandom___init__, /* tp_init */ 0, /* tp_alloc */ PyType_GenericNew, /* tp_new */ 0, /* tp_free */ diff --git a/Modules/_io/bytesio.c b/Modules/_io/bytesio.c --- a/Modules/_io/bytesio.c +++ b/Modules/_io/bytesio.c @@ -2,6 +2,12 @@ #include "structmember.h" /* for offsetof() */ #include "_iomodule.h" +/*[clinic input] +module _io +class _io.BytesIO "bytesio *" "&PyBytesIO_Type" +[clinic start generated code]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=7f50ec034f5c0b26]*/ + typedef struct { PyObject_HEAD PyObject *buf; @@ -203,40 +209,71 @@ } } -PyDoc_STRVAR(readable_doc, -"readable() -> bool. Returns True if the IO object can be read."); +/*[clinic input] +_io.BytesIO.readable -PyDoc_STRVAR(writable_doc, -"writable() -> bool. Returns True if the IO object can be written."); +Returns True if the IO object can be read. +[clinic start generated code]*/ -PyDoc_STRVAR(seekable_doc, -"seekable() -> bool. Returns True if the IO object can be seeked."); - -/* Generic getter for the writable, readable and seekable properties */ static PyObject * -return_not_closed(bytesio *self) +_io_BytesIO_readable_impl(bytesio *self) +/*[clinic end generated code: output=4e93822ad5b62263 input=96c5d0cccfb29f5c]*/ { CHECK_CLOSED(self); Py_RETURN_TRUE; } -PyDoc_STRVAR(flush_doc, -"flush() -> None. Does nothing."); +/*[clinic input] +_io.BytesIO.writable + +Returns True if the IO object can be written. +[clinic start generated code]*/ static PyObject * -bytesio_flush(bytesio *self) +_io_BytesIO_writable_impl(bytesio *self) +/*[clinic end generated code: output=64ff6a254b1150b8 input=700eed808277560a]*/ +{ + CHECK_CLOSED(self); + Py_RETURN_TRUE; +} + +/*[clinic input] +_io.BytesIO.seekable + +Returns True if the IO object can be seeked. +[clinic start generated code]*/ + +static PyObject * +_io_BytesIO_seekable_impl(bytesio *self) +/*[clinic end generated code: output=6b417f46dcc09b56 input=9421f65627a344dd]*/ +{ + CHECK_CLOSED(self); + Py_RETURN_TRUE; +} + +/*[clinic input] +_io.BytesIO.flush + +Does nothing. +[clinic start generated code]*/ + +static PyObject * +_io_BytesIO_flush_impl(bytesio *self) +/*[clinic end generated code: output=187e3d781ca134a0 input=561ea490be4581a7]*/ { CHECK_CLOSED(self); Py_RETURN_NONE; } -PyDoc_STRVAR(getbuffer_doc, -"getbuffer() -> bytes.\n" -"\n" -"Get a read-write view over the contents of the BytesIO object."); +/*[clinic input] +_io.BytesIO.getbuffer + +Get a read-write view over the contents of the BytesIO object. +[clinic start generated code]*/ static PyObject * -bytesio_getbuffer(bytesio *self) +_io_BytesIO_getbuffer_impl(bytesio *self) +/*[clinic end generated code: output=72cd7c6e13aa09ed input=8f738ef615865176]*/ { PyTypeObject *type = &_PyBytesIOBuffer_Type; bytesiobuf *buf; @@ -254,13 +291,15 @@ return view; } -PyDoc_STRVAR(getval_doc, -"getvalue() -> bytes.\n" -"\n" -"Retrieve the entire contents of the BytesIO object."); +/*[clinic input] +_io.BytesIO.getvalue + +Retrieve the entire contents of the BytesIO object. +[clinic start generated code]*/ static PyObject * -bytesio_getvalue(bytesio *self) +_io_BytesIO_getvalue_impl(bytesio *self) +/*[clinic end generated code: output=b3f6a3233c8fd628 input=4b403ac0af3973ed]*/ { CHECK_CLOSED(self); if (self->string_size <= 1 || self->exports > 0) @@ -281,24 +320,31 @@ return self->buf; } -PyDoc_STRVAR(isatty_doc, -"isatty() -> False.\n" -"\n" -"Always returns False since BytesIO objects are not connected\n" -"to a tty-like device."); +/*[clinic input] +_io.BytesIO.isatty + +Always returns False. + +BytesIO objects are not connected to a TTY-like device. +[clinic start generated code]*/ static PyObject * -bytesio_isatty(bytesio *self) +_io_BytesIO_isatty_impl(bytesio *self) +/*[clinic end generated code: output=df67712e669f6c8f input=6f97f0985d13f827]*/ { CHECK_CLOSED(self); Py_RETURN_FALSE; } -PyDoc_STRVAR(tell_doc, -"tell() -> current file position, an integer\n"); +/*[clinic input] +_io.BytesIO.tell + +Current file position, an integer. +[clinic start generated code]*/ static PyObject * -bytesio_tell(bytesio *self) +_io_BytesIO_tell_impl(bytesio *self) +/*[clinic end generated code: output=b54b0f93cd0e5e1d input=b106adf099cb3657]*/ { CHECK_CLOSED(self); return PyLong_FromSsize_t(self->pos); @@ -324,23 +370,25 @@ return PyBytes_FromStringAndSize(output, size); } -PyDoc_STRVAR(read_doc, -"read([size]) -> read at most size bytes, returned as a bytes object.\n" -"\n" -"If the size argument is negative, read until EOF is reached.\n" -"Return an empty bytes object at EOF."); +/*[clinic input] +_io.BytesIO.read + size as arg: object = None + / + +Read at most size bytes, returned as a bytes object. + +If the size argument is negative, read until EOF is reached. +Return an empty bytes object at EOF. +[clinic start generated code]*/ static PyObject * -bytesio_read(bytesio *self, PyObject *args) +_io_BytesIO_read_impl(bytesio *self, PyObject *arg) +/*[clinic end generated code: output=85dacb535c1e1781 input=cc7ba4a797bb1555]*/ { Py_ssize_t size, n; - PyObject *arg = Py_None; CHECK_CLOSED(self); - if (!PyArg_ParseTuple(args, "|O:read", &arg)) - return NULL; - if (PyLong_Check(arg)) { size = PyLong_AsSsize_t(arg); if (size == -1 && PyErr_Occurred()) @@ -368,43 +416,44 @@ } -PyDoc_STRVAR(read1_doc, -"read1(size) -> read at most size bytes, returned as a bytes object.\n" -"\n" -"If the size argument is negative or omitted, read until EOF is reached.\n" -"Return an empty bytes object at EOF."); +/*[clinic input] +_io.BytesIO.read1 + size: object + / + +Read at most size bytes, returned as a bytes object. + +If the size argument is negative or omitted, read until EOF is reached. +Return an empty bytes object at EOF. +[clinic start generated code]*/ static PyObject * -bytesio_read1(bytesio *self, PyObject *n) +_io_BytesIO_read1(bytesio *self, PyObject *size) +/*[clinic end generated code: output=16021f5d0ac3d4e2 input=d4f40bb8f2f99418]*/ { - PyObject *arg, *res; - - arg = PyTuple_Pack(1, n); - if (arg == NULL) - return NULL; - res = bytesio_read(self, arg); - Py_DECREF(arg); - return res; + return _io_BytesIO_read_impl(self, size); } -PyDoc_STRVAR(readline_doc, -"readline([size]) -> next line from the file, as a bytes object.\n" -"\n" -"Retain newline. A non-negative size argument limits the maximum\n" -"number of bytes to return (an incomplete line may be returned then).\n" -"Return an empty bytes object at EOF.\n"); +/*[clinic input] +_io.BytesIO.readline + size as arg: object = None + / + +Next line from the file, as a bytes object. + +Retain newline. A non-negative size argument limits the maximum +number of bytes to return (an incomplete line may be returned then). +Return an empty bytes object at EOF. +[clinic start generated code]*/ static PyObject * -bytesio_readline(bytesio *self, PyObject *args) +_io_BytesIO_readline_impl(bytesio *self, PyObject *arg) +/*[clinic end generated code: output=1c2115534a4f9276 input=ca31f06de6eab257]*/ { Py_ssize_t size, n; - PyObject *arg = Py_None; CHECK_CLOSED(self); - if (!PyArg_ParseTuple(args, "|O:readline", &arg)) - return NULL; - if (PyLong_Check(arg)) { size = PyLong_AsSsize_t(arg); if (size == -1 && PyErr_Occurred()) @@ -425,26 +474,28 @@ return read_bytes(self, n); } -PyDoc_STRVAR(readlines_doc, -"readlines([size]) -> list of strings, each a line from the file.\n" -"\n" -"Call readline() repeatedly and return a list of the lines so read.\n" -"The optional size argument, if given, is an approximate bound on the\n" -"total number of bytes in the lines returned.\n"); +/*[clinic input] +_io.BytesIO.readlines + size as arg: object = None + / + +List of bytes objects, each a line from the file. + +Call readline() repeatedly and return a list of the lines so read. +The optional size argument, if given, is an approximate bound on the +total number of bytes in the lines returned. +[clinic start generated code]*/ static PyObject * -bytesio_readlines(bytesio *self, PyObject *args) +_io_BytesIO_readlines_impl(bytesio *self, PyObject *arg) +/*[clinic end generated code: output=09b8e34c880808ff input=691aa1314f2c2a87]*/ { Py_ssize_t maxsize, size, n; PyObject *result, *line; char *output; - PyObject *arg = Py_None; CHECK_CLOSED(self); - if (!PyArg_ParseTuple(args, "|O:readlines", &arg)) - return NULL; - if (PyLong_Check(arg)) { maxsize = PyLong_AsSsize_t(arg); if (maxsize == -1 && PyErr_Occurred()) @@ -488,25 +539,27 @@ return NULL; } -PyDoc_STRVAR(readinto_doc, -"readinto(bytearray) -> int. Read up to len(b) bytes into b.\n" -"\n" -"Returns number of bytes read (0 for EOF), or None if the object\n" -"is set not to block as has no data to read."); +/*[clinic input] +_io.BytesIO.readinto + buffer: Py_buffer(types={'rwbuffer'}) + / + +Read up to len(buffer) bytes into buffer. + +Returns number of bytes read (0 for EOF), or None if the object +is set not to block as has no data to read. +[clinic start generated code]*/ static PyObject * -bytesio_readinto(bytesio *self, PyObject *arg) +_io_BytesIO_readinto_impl(bytesio *self, Py_buffer *buffer) +/*[clinic end generated code: output=a5d407217dcf0639 input=d289da851c7c4159]*/ { - Py_buffer buffer; Py_ssize_t len, n; CHECK_CLOSED(self); - if (!PyArg_Parse(arg, "w*", &buffer)) - return NULL; - /* adjust invalid sizes */ - len = buffer.len; + len = buffer->len; n = self->string_size - self->pos; if (len > n) { len = n; @@ -514,33 +567,34 @@ len = 0; } - memcpy(buffer.buf, PyBytes_AS_STRING(self->buf) + self->pos, len); + memcpy(buffer->buf, PyBytes_AS_STRING(self->buf) + self->pos, len); assert(self->pos + len < PY_SSIZE_T_MAX); assert(len >= 0); self->pos += len; - PyBuffer_Release(&buffer); return PyLong_FromSsize_t(len); } -PyDoc_STRVAR(truncate_doc, -"truncate([size]) -> int. Truncate the file to at most size bytes.\n" -"\n" -"Size defaults to the current file position, as returned by tell().\n" -"The current file position is unchanged. Returns the new size.\n"); +/*[clinic input] +_io.BytesIO.truncate + size as arg: object = None + / + +Truncate the file to at most size bytes. + +Size defaults to the current file position, as returned by tell(). +The current file position is unchanged. Returns the new size. +[clinic start generated code]*/ static PyObject * -bytesio_truncate(bytesio *self, PyObject *args) +_io_BytesIO_truncate_impl(bytesio *self, PyObject *arg) +/*[clinic end generated code: output=81e6be60e67ddd66 input=11ed1966835462ba]*/ { Py_ssize_t size; - PyObject *arg = Py_None; CHECK_CLOSED(self); CHECK_EXPORTS(self); - if (!PyArg_ParseTuple(args, "|O:truncate", &arg)) - return NULL; - if (PyLong_Check(arg)) { size = PyLong_AsSsize_t(arg); if (size == -1 && PyErr_Occurred()) @@ -586,36 +640,37 @@ return read_bytes(self, n); } -PyDoc_STRVAR(seek_doc, -"seek(pos, whence=0) -> int. Change stream position.\n" -"\n" -"Seek to byte offset pos relative to position indicated by whence:\n" -" 0 Start of stream (the default). pos should be >= 0;\n" -" 1 Current position - pos may be negative;\n" -" 2 End of stream - pos usually negative.\n" -"Returns the new absolute position."); +/*[clinic input] +_io.BytesIO.seek + pos: Py_ssize_t + whence: int = 0 + / + +Change stream position. + +Seek to byte offset pos relative to position indicated by whence: + 0 Start of stream (the default). pos should be >= 0; + 1 Current position - pos may be negative; + 2 End of stream - pos usually negative. +Returns the new absolute position. +[clinic start generated code]*/ static PyObject * -bytesio_seek(bytesio *self, PyObject *args) +_io_BytesIO_seek_impl(bytesio *self, Py_ssize_t pos, int whence) +/*[clinic end generated code: output=c26204a68e9190e4 input=1e875e6ebc652948]*/ { - Py_ssize_t pos; - int mode = 0; - CHECK_CLOSED(self); - if (!PyArg_ParseTuple(args, "n|i:seek", &pos, &mode)) - return NULL; - - if (pos < 0 && mode == 0) { + if (pos < 0 && whence == 0) { PyErr_Format(PyExc_ValueError, "negative seek value %zd", pos); return NULL; } - /* mode 0: offset relative to beginning of the string. - mode 1: offset relative to current position. - mode 2: offset relative the end of the string. */ - if (mode == 1) { + /* whence = 0: offset relative to beginning of the string. + whence = 1: offset relative to current position. + whence = 2: offset relative the end of the string. */ + if (whence == 1) { if (pos > PY_SSIZE_T_MAX - self->pos) { PyErr_SetString(PyExc_OverflowError, "new position too large"); @@ -623,7 +678,7 @@ } pos += self->pos; } - else if (mode == 2) { + else if (whence == 2) { if (pos > PY_SSIZE_T_MAX - self->string_size) { PyErr_SetString(PyExc_OverflowError, "new position too large"); @@ -631,9 +686,9 @@ } pos += self->string_size; } - else if (mode != 0) { + else if (whence != 0) { PyErr_Format(PyExc_ValueError, - "invalid whence (%i, should be 0, 1 or 2)", mode); + "invalid whence (%i, should be 0, 1 or 2)", whence); return NULL; } @@ -644,54 +699,63 @@ return PyLong_FromSsize_t(self->pos); } -PyDoc_STRVAR(write_doc, -"write(bytes) -> int. Write bytes to file.\n" -"\n" -"Return the number of bytes written."); +/*[clinic input] +_io.BytesIO.write + b: object + / + +Write bytes to file. + +Return the number of bytes written. +[clinic start generated code]*/ static PyObject * -bytesio_write(bytesio *self, PyObject *obj) +_io_BytesIO_write(bytesio *self, PyObject *b) +/*[clinic end generated code: output=53316d99800a0b95 input=f5ec7c8c64ed720a]*/ { Py_ssize_t n = 0; Py_buffer buf; - PyObject *result = NULL; CHECK_CLOSED(self); CHECK_EXPORTS(self); - if (PyObject_GetBuffer(obj, &buf, PyBUF_CONTIG_RO) < 0) + if (PyObject_GetBuffer(b, &buf, PyBUF_CONTIG_RO) < 0) return NULL; if (buf.len != 0) n = write_bytes(self, buf.buf, buf.len); - if (n >= 0) - result = PyLong_FromSsize_t(n); PyBuffer_Release(&buf); - return result; + return n >= 0 ? PyLong_FromSsize_t(n) : NULL; } -PyDoc_STRVAR(writelines_doc, -"writelines(lines) -> None. Write bytes objects to the file.\n" -"\n" -"Note that newlines are not added. The argument can be any iterable\n" -"object producing bytes objects. This is equivalent to calling write() for\n" -"each bytes object."); +/*[clinic input] +_io.BytesIO.writelines + lines: object + / + +Write lines to the file. + +Note that newlines are not added. lines can be any iterable object +producing bytes-like objects. This is equivalent to calling write() for +each element. +[clinic start generated code]*/ static PyObject * -bytesio_writelines(bytesio *self, PyObject *v) +_io_BytesIO_writelines(bytesio *self, PyObject *lines) +/*[clinic end generated code: output=7f33aa3271c91752 input=e972539176fc8fc1]*/ { PyObject *it, *item; PyObject *ret; CHECK_CLOSED(self); - it = PyObject_GetIter(v); + it = PyObject_GetIter(lines); if (it == NULL) return NULL; while ((item = PyIter_Next(it)) != NULL) { - ret = bytesio_write(self, item); + ret = _io_BytesIO_write(self, item); Py_DECREF(item); if (ret == NULL) { Py_DECREF(it); @@ -708,11 +772,15 @@ Py_RETURN_NONE; } -PyDoc_STRVAR(close_doc, -"close() -> None. Disable all I/O operations."); +/*[clinic input] +_io.BytesIO.close + +Disable all I/O operations. +[clinic start generated code]*/ static PyObject * -bytesio_close(bytesio *self) +_io_BytesIO_close_impl(bytesio *self) +/*[clinic end generated code: output=1471bb9411af84a0 input=37e1f55556e61f60]*/ { CHECK_EXPORTS(self); Py_CLEAR(self->buf); @@ -737,7 +805,7 @@ static PyObject * bytesio_getstate(bytesio *self) { - PyObject *initvalue = bytesio_getvalue(self); + PyObject *initvalue = _io_BytesIO_getvalue_impl(self); PyObject *dict; PyObject *state; @@ -787,7 +855,7 @@ /* Set the value of the internal buffer. If state[0] does not support the buffer protocol, bytesio_write will raise the appropriate TypeError. */ - result = bytesio_write(self, PyTuple_GET_ITEM(state, 0)); + result = _io_BytesIO_write(self, PyTuple_GET_ITEM(state, 0)); if (result == NULL) return NULL; Py_DECREF(result); @@ -874,16 +942,17 @@ return (PyObject *)self; } +/*[clinic input] +_io.BytesIO.__init__ + initial_bytes as initvalue: object(c_default="NULL") = b'' + +Buffered I/O implementation using an in-memory bytes buffer. +[clinic start generated code]*/ + static int -bytesio_init(bytesio *self, PyObject *args, PyObject *kwds) +_io_BytesIO___init___impl(bytesio *self, PyObject *initvalue) +/*[clinic end generated code: output=65c0c51e24c5b621 input=aac7f31b67bf0fb6]*/ { - char *kwlist[] = {"initial_bytes", NULL}; - PyObject *initvalue = NULL; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O:BytesIO", kwlist, - &initvalue)) - return -1; - /* In case, __init__ is called multiple times. */ self->string_size = 0; self->pos = 0; @@ -902,7 +971,7 @@ } else { PyObject *res; - res = bytesio_write(self, initvalue); + res = _io_BytesIO_write(self, initvalue); if (res == NULL) return -1; Py_DECREF(res); @@ -939,6 +1008,8 @@ } +#include "clinic/bytesio.c.h" + static PyGetSetDef bytesio_getsetlist[] = { {"closed", (getter)bytesio_get_closed, NULL, "True if the file is closed."}, @@ -946,36 +1017,30 @@ }; static struct PyMethodDef bytesio_methods[] = { - {"readable", (PyCFunction)return_not_closed, METH_NOARGS, readable_doc}, - {"seekable", (PyCFunction)return_not_closed, METH_NOARGS, seekable_doc}, - {"writable", (PyCFunction)return_not_closed, METH_NOARGS, writable_doc}, - {"close", (PyCFunction)bytesio_close, METH_NOARGS, close_doc}, - {"flush", (PyCFunction)bytesio_flush, METH_NOARGS, flush_doc}, - {"isatty", (PyCFunction)bytesio_isatty, METH_NOARGS, isatty_doc}, - {"tell", (PyCFunction)bytesio_tell, METH_NOARGS, tell_doc}, - {"write", (PyCFunction)bytesio_write, METH_O, write_doc}, - {"writelines", (PyCFunction)bytesio_writelines, METH_O, writelines_doc}, - {"read1", (PyCFunction)bytesio_read1, METH_O, read1_doc}, - {"readinto", (PyCFunction)bytesio_readinto, METH_O, readinto_doc}, - {"readline", (PyCFunction)bytesio_readline, METH_VARARGS, readline_doc}, - {"readlines", (PyCFunction)bytesio_readlines, METH_VARARGS, readlines_doc}, - {"read", (PyCFunction)bytesio_read, METH_VARARGS, read_doc}, - {"getbuffer", (PyCFunction)bytesio_getbuffer, METH_NOARGS, getbuffer_doc}, - {"getvalue", (PyCFunction)bytesio_getvalue, METH_NOARGS, getval_doc}, - {"seek", (PyCFunction)bytesio_seek, METH_VARARGS, seek_doc}, - {"truncate", (PyCFunction)bytesio_truncate, METH_VARARGS, truncate_doc}, + _IO_BYTESIO_READABLE_METHODDEF + _IO_BYTESIO_SEEKABLE_METHODDEF + _IO_BYTESIO_WRITABLE_METHODDEF + _IO_BYTESIO_CLOSE_METHODDEF + _IO_BYTESIO_FLUSH_METHODDEF + _IO_BYTESIO_ISATTY_METHODDEF + _IO_BYTESIO_TELL_METHODDEF + _IO_BYTESIO_WRITE_METHODDEF + _IO_BYTESIO_WRITELINES_METHODDEF + _IO_BYTESIO_READ1_METHODDEF + _IO_BYTESIO_READINTO_METHODDEF + _IO_BYTESIO_READLINE_METHODDEF + _IO_BYTESIO_READLINES_METHODDEF + _IO_BYTESIO_READ_METHODDEF + _IO_BYTESIO_GETBUFFER_METHODDEF + _IO_BYTESIO_GETVALUE_METHODDEF + _IO_BYTESIO_SEEK_METHODDEF + _IO_BYTESIO_TRUNCATE_METHODDEF {"__getstate__", (PyCFunction)bytesio_getstate, METH_NOARGS, NULL}, {"__setstate__", (PyCFunction)bytesio_setstate, METH_O, NULL}, {"__sizeof__", (PyCFunction)bytesio_sizeof, METH_NOARGS, NULL}, {NULL, NULL} /* sentinel */ }; -PyDoc_STRVAR(bytesio_doc, -"BytesIO([buffer]) -> object\n" -"\n" -"Create a buffered I/O implementation using an in-memory bytes\n" -"buffer, ready for reading and writing."); - PyTypeObject PyBytesIO_Type = { PyVarObject_HEAD_INIT(NULL, 0) "_io.BytesIO", /*tp_name*/ @@ -998,7 +1063,7 @@ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /*tp_flags*/ - bytesio_doc, /*tp_doc*/ + _io_BytesIO___init____doc__, /*tp_doc*/ (traverseproc)bytesio_traverse, /*tp_traverse*/ (inquiry)bytesio_clear, /*tp_clear*/ 0, /*tp_richcompare*/ @@ -1013,7 +1078,7 @@ 0, /*tp_descr_get*/ 0, /*tp_descr_set*/ offsetof(bytesio, dict), /*tp_dictoffset*/ - (initproc)bytesio_init, /*tp_init*/ + _io_BytesIO___init__, /*tp_init*/ 0, /*tp_alloc*/ bytesio_new, /*tp_new*/ }; diff --git a/Modules/_io/_iomodule.c b/Modules/_io/clinic/_iomodule.c.h copy from Modules/_io/_iomodule.c copy to Modules/_io/clinic/_iomodule.c.h --- a/Modules/_io/_iomodule.c +++ b/Modules/_io/clinic/_iomodule.c.h @@ -1,115 +1,25 @@ -/* - An implementation of the new I/O lib as defined by PEP 3116 - "New I/O" +/*[clinic input] +preserve +[clinic start generated code]*/ - Classes defined here: UnsupportedOperation, BlockingIOError. - Functions defined here: open(). - - Mostly written by Amaury Forgeot d'Arc -*/ - -#define PY_SSIZE_T_CLEAN -#include "Python.h" -#include "structmember.h" -#include "_iomodule.h" - -#ifdef HAVE_SYS_TYPES_H -#include -#endif /* HAVE_SYS_TYPES_H */ - -#ifdef HAVE_SYS_STAT_H -#include -#endif /* HAVE_SYS_STAT_H */ - - -/* Various interned strings */ - -PyObject *_PyIO_str_close; -PyObject *_PyIO_str_closed; -PyObject *_PyIO_str_decode; -PyObject *_PyIO_str_encode; -PyObject *_PyIO_str_fileno; -PyObject *_PyIO_str_flush; -PyObject *_PyIO_str_getstate; -PyObject *_PyIO_str_isatty; -PyObject *_PyIO_str_newlines; -PyObject *_PyIO_str_nl; -PyObject *_PyIO_str_read; -PyObject *_PyIO_str_read1; -PyObject *_PyIO_str_readable; -PyObject *_PyIO_str_readall; -PyObject *_PyIO_str_readinto; -PyObject *_PyIO_str_readline; -PyObject *_PyIO_str_reset; -PyObject *_PyIO_str_seek; -PyObject *_PyIO_str_seekable; -PyObject *_PyIO_str_setstate; -PyObject *_PyIO_str_tell; -PyObject *_PyIO_str_truncate; -PyObject *_PyIO_str_writable; -PyObject *_PyIO_str_write; - -PyObject *_PyIO_empty_str; -PyObject *_PyIO_empty_bytes; -PyObject *_PyIO_zero; - - -PyDoc_STRVAR(module_doc, -"The io module provides the Python interfaces to stream handling. The\n" -"builtin open function is defined in this module.\n" -"\n" -"At the top of the I/O hierarchy is the abstract base class IOBase. It\n" -"defines the basic interface to a stream. Note, however, that there is no\n" -"separation between reading and writing to streams; implementations are\n" -"allowed to raise an IOError if they do not support a given operation.\n" -"\n" -"Extending IOBase is RawIOBase which deals simply with the reading and\n" -"writing of raw bytes to a stream. FileIO subclasses RawIOBase to provide\n" -"an interface to OS files.\n" -"\n" -"BufferedIOBase deals with buffering on a raw byte stream (RawIOBase). Its\n" -"subclasses, BufferedWriter, BufferedReader, and BufferedRWPair buffer\n" -"streams that are readable, writable, and both respectively.\n" -"BufferedRandom provides a buffered interface to random access\n" -"streams. BytesIO is a simple stream of in-memory bytes.\n" -"\n" -"Another IOBase subclass, TextIOBase, deals with the encoding and decoding\n" -"of streams into text. TextIOWrapper, which extends it, is a buffered text\n" -"interface to a buffered raw stream (`BufferedIOBase`). Finally, StringIO\n" -"is a in-memory stream for text.\n" -"\n" -"Argument names are not part of the specification, and only the arguments\n" -"of open() are intended to be used as keyword arguments.\n" -"\n" -"data:\n" -"\n" -"DEFAULT_BUFFER_SIZE\n" -"\n" -" An int containing the default buffer size used by the module's buffered\n" -" I/O classes. open() uses the file's blksize (as obtained by os.stat) if\n" -" possible.\n" - ); - - -/* - * The main open() function - */ -PyDoc_STRVAR(open_doc, -"open(file, mode='r', buffering=-1, encoding=None,\n" -" errors=None, newline=None, closefd=True, opener=None) -> file object\n" +PyDoc_STRVAR(_io_open__doc__, +"open($module, /, file, mode=\'r\', buffering=-1, encoding=None,\n" +" errors=None, newline=None, closefd=True, opener=None)\n" +"--\n" "\n" "Open file and return a stream. Raise IOError upon failure.\n" "\n" "file is either a text or byte string giving the name (and the path\n" -"if the file isn't in the current working directory) of the file to\n" +"if the file isn\'t in the current working directory) of the file to\n" "be opened or an integer file descriptor of the file to be\n" "wrapped. (If a file descriptor is given, it is closed when the\n" "returned I/O object is closed, unless closefd is set to False.)\n" "\n" "mode is an optional string that specifies the mode in which the file\n" -"is opened. It defaults to 'r' which means open for reading in text\n" -"mode. Other common values are 'w' for writing (truncating the file if\n" -"it already exists), 'x' for creating and writing to a new file, and\n" -"'a' for appending (which on some Unix systems, means that all writes\n" +"is opened. It defaults to \'r\' which means open for reading in text\n" +"mode. Other common values are \'w\' for writing (truncating the file if\n" +"it already exists), \'x\' for creating and writing to a new file, and\n" +"\'a\' for appending (which on some Unix systems, means that all writes\n" "append to the end of the file regardless of the current seek position).\n" "In text mode, if encoding is not specified the encoding used is platform\n" "dependent: locale.getpreferredencoding(False) is called to get the\n" @@ -119,30 +29,30 @@ "========= ===============================================================\n" "Character Meaning\n" "--------- ---------------------------------------------------------------\n" -"'r' open for reading (default)\n" -"'w' open for writing, truncating the file first\n" -"'x' create a new file and open it for writing\n" -"'a' open for writing, appending to the end of the file if it exists\n" -"'b' binary mode\n" -"'t' text mode (default)\n" -"'+' open a disk file for updating (reading and writing)\n" -"'U' universal newline mode (deprecated)\n" +"\'r\' open for reading (default)\n" +"\'w\' open for writing, truncating the file first\n" +"\'x\' create a new file and open it for writing\n" +"\'a\' open for writing, appending to the end of the file if it exists\n" +"\'b\' binary mode\n" +"\'t\' text mode (default)\n" +"\'+\' open a disk file for updating (reading and writing)\n" +"\'U\' universal newline mode (deprecated)\n" "========= ===============================================================\n" "\n" -"The default mode is 'rt' (open for reading text). For binary random\n" -"access, the mode 'w+b' opens and truncates the file to 0 bytes, while\n" -"'r+b' opens the file without truncation. The 'x' mode implies 'w' and\n" +"The default mode is \'rt\' (open for reading text). For binary random\n" +"access, the mode \'w+b\' opens and truncates the file to 0 bytes, while\n" +"\'r+b\' opens the file without truncation. The \'x\' mode implies \'w\' and\n" "raises an `FileExistsError` if the file already exists.\n" "\n" "Python distinguishes between files opened in binary and text modes,\n" -"even when the underlying operating system doesn't. Files opened in\n" -"binary mode (appending 'b' to the mode argument) return contents as\n" +"even when the underlying operating system doesn\'t. Files opened in\n" +"binary mode (appending \'b\' to the mode argument) return contents as\n" "bytes objects without any decoding. In text mode (the default, or when\n" -"'t' is appended to the mode argument), the contents of the file are\n" +"\'t\' is appended to the mode argument), the contents of the file are\n" "returned as strings, the bytes having been first decoded using a\n" "platform-dependent encoding or using the specified encoding if given.\n" "\n" -"'U' mode is deprecated and will raise an exception in future versions\n" +"\'U\' mode is deprecated and will raise an exception in future versions\n" "of Python. It has no effect in Python 3. Use newline to control\n" "universal newlines mode.\n" "\n" @@ -153,7 +63,7 @@ "given, the default buffering policy works as follows:\n" "\n" "* Binary files are buffered in fixed-size chunks; the size of the buffer\n" -" is chosen using a heuristic trying to determine the underlying device's\n" +" is chosen using a heuristic trying to determine the underlying device\'s\n" " \"block size\" and falling back on `io.DEFAULT_BUFFER_SIZE`.\n" " On many systems, the buffer will typically be 4096 or 8192 bytes long.\n" "\n" @@ -168,28 +78,28 @@ "\n" "errors is an optional string that specifies how encoding errors are to\n" "be handled---this argument should not be used in binary mode. Pass\n" -"'strict' to raise a ValueError exception if there is an encoding error\n" -"(the default of None has the same effect), or pass 'ignore' to ignore\n" +"\'strict\' to raise a ValueError exception if there is an encoding error\n" +"(the default of None has the same effect), or pass \'ignore\' to ignore\n" "errors. (Note that ignoring encoding errors can lead to data loss.)\n" -"See the documentation for codecs.register or run 'help(codecs.Codec)'\n" +"See the documentation for codecs.register or run \'help(codecs.Codec)\'\n" "for a list of the permitted encoding error strings.\n" "\n" "newline controls how universal newlines works (it only applies to text\n" -"mode). It can be None, '', '\\n', '\\r', and '\\r\\n'. It works as\n" +"mode). It can be None, \'\', \'\\n\', \'\\r\', and \'\\r\\n\'. It works as\n" "follows:\n" "\n" "* On input, if newline is None, universal newlines mode is\n" -" enabled. Lines in the input can end in '\\n', '\\r', or '\\r\\n', and\n" -" these are translated into '\\n' before being returned to the\n" -" caller. If it is '', universal newline mode is enabled, but line\n" +" enabled. Lines in the input can end in \'\\n\', \'\\r\', or \'\\r\\n\', and\n" +" these are translated into \'\\n\' before being returned to the\n" +" caller. If it is \'\', universal newline mode is enabled, but line\n" " endings are returned to the caller untranslated. If it has any of\n" " the other legal values, input lines are only terminated by the given\n" " string, and the line ending is returned to the caller untranslated.\n" "\n" -"* On output, if newline is None, any '\\n' characters written are\n" +"* On output, if newline is None, any \'\\n\' characters written are\n" " translated to the system default line separator, os.linesep. If\n" -" newline is '' or '\\n', no translation takes place. If newline is any\n" -" of the other legal values, any '\\n' characters written are translated\n" +" newline is \'\' or \'\\n\', no translation takes place. If newline is any\n" +" of the other legal values, any \'\\n\' characters written are translated\n" " to the given string.\n" "\n" "If closefd is False, the underlying file descriptor will be kept open\n" @@ -204,8 +114,8 @@ "\n" "open() returns a file object whose type depends on the mode, and\n" "through which the standard file operations such as reading and writing\n" -"are performed. When open() is used to open a file in a text mode ('w',\n" -"'r', 'wt', 'rt', etc.), it returns a TextIOWrapper. When used to open\n" +"are performed. When open() is used to open a file in a text mode (\'w\',\n" +"\'r\', \'wt\', \'rt\', etc.), it returns a TextIOWrapper. When used to open\n" "a file in a binary mode, the returned class varies: in read binary\n" "mode, it returns a BufferedReader; in write binary and append binary\n" "modes, it returns a BufferedWriter, and in read/write mode, it returns\n" @@ -214,556 +124,37 @@ "It is also possible to use a string or bytearray as a file for both\n" "reading and writing. For strings StringIO can be used like a file\n" "opened in a text mode, and for bytes a BytesIO can be used like a file\n" -"opened in a binary mode.\n" - ); +"opened in a binary mode."); + +#define _IO_OPEN_METHODDEF \ + {"open", (PyCFunction)_io_open, METH_VARARGS|METH_KEYWORDS, _io_open__doc__}, static PyObject * -io_open(PyObject *self, PyObject *args, PyObject *kwds) +_io_open_impl(PyModuleDef *module, PyObject *file, const char *mode, + int buffering, const char *encoding, const char *errors, + const char *newline, int closefd, PyObject *opener); + +static PyObject * +_io_open(PyModuleDef *module, PyObject *args, PyObject *kwargs) { - char *kwlist[] = {"file", "mode", "buffering", - "encoding", "errors", "newline", - "closefd", "opener", NULL}; - PyObject *file, *opener = Py_None; - char *mode = "r"; - int buffering = -1, closefd = 1; - char *encoding = NULL, *errors = NULL, *newline = NULL; - unsigned i; + PyObject *return_value = NULL; + static char *_keywords[] = {"file", "mode", "buffering", "encoding", "errors", "newline", "closefd", "opener", NULL}; + PyObject *file; + const char *mode = "r"; + int buffering = -1; + const char *encoding = NULL; + const char *errors = NULL; + const char *newline = NULL; + int closefd = 1; + PyObject *opener = Py_None; - int creating = 0, reading = 0, writing = 0, appending = 0, updating = 0; - int text = 0, binary = 0, universal = 0; + if (!PyArg_ParseTupleAndKeywords(args, kwargs, + "O|sizzziO:open", _keywords, + &file, &mode, &buffering, &encoding, &errors, &newline, &closefd, &opener)) + goto exit; + return_value = _io_open_impl(module, file, mode, buffering, encoding, errors, newline, closefd, opener); - char rawmode[6], *m; - int line_buffering, isatty; - - PyObject *raw, *modeobj = NULL, *buffer, *wrapper, *result = NULL; - - _Py_IDENTIFIER(_blksize); - _Py_IDENTIFIER(isatty); - _Py_IDENTIFIER(mode); - _Py_IDENTIFIER(close); - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|sizzziO:open", kwlist, - &file, &mode, &buffering, - &encoding, &errors, &newline, - &closefd, &opener)) { - return NULL; - } - - if (!PyUnicode_Check(file) && - !PyBytes_Check(file) && - !PyNumber_Check(file)) { - PyErr_Format(PyExc_TypeError, "invalid file: %R", file); - return NULL; - } - - /* Decode mode */ - for (i = 0; i < strlen(mode); i++) { - char c = mode[i]; - - switch (c) { - case 'x': - creating = 1; - break; - case 'r': - reading = 1; - break; - case 'w': - writing = 1; - break; - case 'a': - appending = 1; - break; - case '+': - updating = 1; - break; - case 't': - text = 1; - break; - case 'b': - binary = 1; - break; - case 'U': - universal = 1; - reading = 1; - break; - default: - goto invalid_mode; - } - - /* c must not be duplicated */ - if (strchr(mode+i+1, c)) { - invalid_mode: - PyErr_Format(PyExc_ValueError, "invalid mode: '%s'", mode); - return NULL; - } - - } - - m = rawmode; - if (creating) *(m++) = 'x'; - if (reading) *(m++) = 'r'; - if (writing) *(m++) = 'w'; - if (appending) *(m++) = 'a'; - if (updating) *(m++) = '+'; - *m = '\0'; - - /* Parameters validation */ - if (universal) { - if (writing || appending) { - PyErr_SetString(PyExc_ValueError, - "can't use U and writing mode at once"); - return NULL; - } - if (PyErr_WarnEx(PyExc_DeprecationWarning, - "'U' mode is deprecated", 1) < 0) - return NULL; - reading = 1; - } - - if (text && binary) { - PyErr_SetString(PyExc_ValueError, - "can't have text and binary mode at once"); - return NULL; - } - - if (creating + reading + writing + appending > 1) { - PyErr_SetString(PyExc_ValueError, - "must have exactly one of create/read/write/append mode"); - return NULL; - } - - if (binary && encoding != NULL) { - PyErr_SetString(PyExc_ValueError, - "binary mode doesn't take an encoding argument"); - return NULL; - } - - if (binary && errors != NULL) { - PyErr_SetString(PyExc_ValueError, - "binary mode doesn't take an errors argument"); - return NULL; - } - - if (binary && newline != NULL) { - PyErr_SetString(PyExc_ValueError, - "binary mode doesn't take a newline argument"); - return NULL; - } - - /* Create the Raw file stream */ - raw = PyObject_CallFunction((PyObject *)&PyFileIO_Type, - "OsiO", file, rawmode, closefd, opener); - if (raw == NULL) - return NULL; - result = raw; - - modeobj = PyUnicode_FromString(mode); - if (modeobj == NULL) - goto error; - - /* buffering */ - { - PyObject *res = _PyObject_CallMethodId(raw, &PyId_isatty, NULL); - if (res == NULL) - goto error; - isatty = PyLong_AsLong(res); - Py_DECREF(res); - if (isatty == -1 && PyErr_Occurred()) - goto error; - } - - if (buffering == 1 || (buffering < 0 && isatty)) { - buffering = -1; - line_buffering = 1; - } - else - line_buffering = 0; - - if (buffering < 0) { - PyObject *blksize_obj; - blksize_obj = _PyObject_GetAttrId(raw, &PyId__blksize); - if (blksize_obj == NULL) - goto error; - buffering = PyLong_AsLong(blksize_obj); - Py_DECREF(blksize_obj); - if (buffering == -1 && PyErr_Occurred()) - goto error; - } - if (buffering < 0) { - PyErr_SetString(PyExc_ValueError, - "invalid buffering size"); - goto error; - } - - /* if not buffering, returns the raw file object */ - if (buffering == 0) { - if (!binary) { - PyErr_SetString(PyExc_ValueError, - "can't have unbuffered text I/O"); - goto error; - } - - Py_DECREF(modeobj); - return result; - } - - /* wraps into a buffered file */ - { - PyObject *Buffered_class; - - if (updating) - Buffered_class = (PyObject *)&PyBufferedRandom_Type; - else if (creating || writing || appending) - Buffered_class = (PyObject *)&PyBufferedWriter_Type; - else if (reading) - Buffered_class = (PyObject *)&PyBufferedReader_Type; - else { - PyErr_Format(PyExc_ValueError, - "unknown mode: '%s'", mode); - goto error; - } - - buffer = PyObject_CallFunction(Buffered_class, "Oi", raw, buffering); - } - if (buffer == NULL) - goto error; - result = buffer; - Py_DECREF(raw); - - - /* if binary, returns the buffered file */ - if (binary) { - Py_DECREF(modeobj); - return result; - } - - /* wraps into a TextIOWrapper */ - wrapper = PyObject_CallFunction((PyObject *)&PyTextIOWrapper_Type, - "Osssi", - buffer, - encoding, errors, newline, - line_buffering); - if (wrapper == NULL) - goto error; - result = wrapper; - Py_DECREF(buffer); - - if (_PyObject_SetAttrId(wrapper, &PyId_mode, modeobj) < 0) - goto error; - Py_DECREF(modeobj); - return result; - - error: - if (result != NULL) { - PyObject *exc, *val, *tb, *close_result; - PyErr_Fetch(&exc, &val, &tb); - close_result = _PyObject_CallMethodId(result, &PyId_close, NULL); - _PyErr_ChainExceptions(exc, val, tb); - Py_XDECREF(close_result); - Py_DECREF(result); - } - Py_XDECREF(modeobj); - return NULL; +exit: + return return_value; } - -/* - * Private helpers for the io module. - */ - -Py_off_t -PyNumber_AsOff_t(PyObject *item, PyObject *err) -{ - Py_off_t result; - PyObject *runerr; - PyObject *value = PyNumber_Index(item); - if (value == NULL) - return -1; - - /* We're done if PyLong_AsSsize_t() returns without error. */ - result = PyLong_AsOff_t(value); - if (result != -1 || !(runerr = PyErr_Occurred())) - goto finish; - - /* Error handling code -- only manage OverflowError differently */ - if (!PyErr_GivenExceptionMatches(runerr, PyExc_OverflowError)) - goto finish; - - PyErr_Clear(); - /* If no error-handling desired then the default clipping - is sufficient. - */ - if (!err) { - assert(PyLong_Check(value)); - /* Whether or not it is less than or equal to - zero is determined by the sign of ob_size - */ - if (_PyLong_Sign(value) < 0) - result = PY_OFF_T_MIN; - else - result = PY_OFF_T_MAX; - } - else { - /* Otherwise replace the error with caller's error object. */ - PyErr_Format(err, - "cannot fit '%.200s' into an offset-sized integer", - item->ob_type->tp_name); - } - - finish: - Py_DECREF(value); - return result; -} - - -/* Basically the "n" format code with the ability to turn None into -1. */ -int -_PyIO_ConvertSsize_t(PyObject *obj, void *result) { - Py_ssize_t limit; - if (obj == Py_None) { - limit = -1; - } - else if (PyNumber_Check(obj)) { - limit = PyNumber_AsSsize_t(obj, PyExc_OverflowError); - if (limit == -1 && PyErr_Occurred()) - return 0; - } - else { - PyErr_Format(PyExc_TypeError, - "integer argument expected, got '%.200s'", - Py_TYPE(obj)->tp_name); - return 0; - } - *((Py_ssize_t *)result) = limit; - return 1; -} - - -_PyIO_State * -_PyIO_get_module_state(void) -{ - PyObject *mod = PyState_FindModule(&_PyIO_Module); - _PyIO_State *state; - if (mod == NULL || (state = IO_MOD_STATE(mod)) == NULL) { - PyErr_SetString(PyExc_RuntimeError, - "could not find io module state " - "(interpreter shutdown?)"); - return NULL; - } - return state; -} - -PyObject * -_PyIO_get_locale_module(_PyIO_State *state) -{ - PyObject *mod; - if (state->locale_module != NULL) { - assert(PyWeakref_CheckRef(state->locale_module)); - mod = PyWeakref_GET_OBJECT(state->locale_module); - if (mod != Py_None) { - Py_INCREF(mod); - return mod; - } - Py_CLEAR(state->locale_module); - } - mod = PyImport_ImportModule("_bootlocale"); - if (mod == NULL) - return NULL; - state->locale_module = PyWeakref_NewRef(mod, NULL); - if (state->locale_module == NULL) { - Py_DECREF(mod); - return NULL; - } - return mod; -} - - -static int -iomodule_traverse(PyObject *mod, visitproc visit, void *arg) { - _PyIO_State *state = IO_MOD_STATE(mod); - if (!state->initialized) - return 0; - if (state->locale_module != NULL) { - Py_VISIT(state->locale_module); - } - Py_VISIT(state->unsupported_operation); - return 0; -} - - -static int -iomodule_clear(PyObject *mod) { - _PyIO_State *state = IO_MOD_STATE(mod); - if (!state->initialized) - return 0; - if (state->locale_module != NULL) - Py_CLEAR(state->locale_module); - Py_CLEAR(state->unsupported_operation); - return 0; -} - -static void -iomodule_free(PyObject *mod) { - iomodule_clear(mod); -} - - -/* - * Module definition - */ - -static PyMethodDef module_methods[] = { - {"open", (PyCFunction)io_open, METH_VARARGS|METH_KEYWORDS, open_doc}, - {NULL, NULL} -}; - -struct PyModuleDef _PyIO_Module = { - PyModuleDef_HEAD_INIT, - "io", - module_doc, - sizeof(_PyIO_State), - module_methods, - NULL, - iomodule_traverse, - iomodule_clear, - (freefunc)iomodule_free, -}; - -PyMODINIT_FUNC -PyInit__io(void) -{ - PyObject *m = PyModule_Create(&_PyIO_Module); - _PyIO_State *state = NULL; - if (m == NULL) - return NULL; - state = IO_MOD_STATE(m); - state->initialized = 0; - -#define ADD_TYPE(type, name) \ - if (PyType_Ready(type) < 0) \ - goto fail; \ - Py_INCREF(type); \ - if (PyModule_AddObject(m, name, (PyObject *)type) < 0) { \ - Py_DECREF(type); \ - goto fail; \ - } - - /* DEFAULT_BUFFER_SIZE */ - if (PyModule_AddIntMacro(m, DEFAULT_BUFFER_SIZE) < 0) - goto fail; - - /* UnsupportedOperation inherits from ValueError and IOError */ - state->unsupported_operation = PyObject_CallFunction( - (PyObject *)&PyType_Type, "s(OO){}", - "UnsupportedOperation", PyExc_ValueError, PyExc_IOError); - if (state->unsupported_operation == NULL) - goto fail; - Py_INCREF(state->unsupported_operation); - if (PyModule_AddObject(m, "UnsupportedOperation", - state->unsupported_operation) < 0) - goto fail; - - /* BlockingIOError, for compatibility */ - Py_INCREF(PyExc_BlockingIOError); - if (PyModule_AddObject(m, "BlockingIOError", - (PyObject *) PyExc_BlockingIOError) < 0) - goto fail; - - /* Concrete base types of the IO ABCs. - (the ABCs themselves are declared through inheritance in io.py) - */ - ADD_TYPE(&PyIOBase_Type, "_IOBase"); - ADD_TYPE(&PyRawIOBase_Type, "_RawIOBase"); - ADD_TYPE(&PyBufferedIOBase_Type, "_BufferedIOBase"); - ADD_TYPE(&PyTextIOBase_Type, "_TextIOBase"); - - /* Implementation of concrete IO objects. */ - /* FileIO */ - PyFileIO_Type.tp_base = &PyRawIOBase_Type; - ADD_TYPE(&PyFileIO_Type, "FileIO"); - - /* BytesIO */ - PyBytesIO_Type.tp_base = &PyBufferedIOBase_Type; - ADD_TYPE(&PyBytesIO_Type, "BytesIO"); - if (PyType_Ready(&_PyBytesIOBuffer_Type) < 0) - goto fail; - - /* StringIO */ - PyStringIO_Type.tp_base = &PyTextIOBase_Type; - ADD_TYPE(&PyStringIO_Type, "StringIO"); - - /* BufferedReader */ - PyBufferedReader_Type.tp_base = &PyBufferedIOBase_Type; - ADD_TYPE(&PyBufferedReader_Type, "BufferedReader"); - - /* BufferedWriter */ - PyBufferedWriter_Type.tp_base = &PyBufferedIOBase_Type; - ADD_TYPE(&PyBufferedWriter_Type, "BufferedWriter"); - - /* BufferedRWPair */ - PyBufferedRWPair_Type.tp_base = &PyBufferedIOBase_Type; - ADD_TYPE(&PyBufferedRWPair_Type, "BufferedRWPair"); - - /* BufferedRandom */ - PyBufferedRandom_Type.tp_base = &PyBufferedIOBase_Type; - ADD_TYPE(&PyBufferedRandom_Type, "BufferedRandom"); - - /* TextIOWrapper */ - PyTextIOWrapper_Type.tp_base = &PyTextIOBase_Type; - ADD_TYPE(&PyTextIOWrapper_Type, "TextIOWrapper"); - - /* IncrementalNewlineDecoder */ - ADD_TYPE(&PyIncrementalNewlineDecoder_Type, "IncrementalNewlineDecoder"); - - /* Interned strings */ -#define ADD_INTERNED(name) \ - if (!_PyIO_str_ ## name && \ - !(_PyIO_str_ ## name = PyUnicode_InternFromString(# name))) \ - goto fail; - - ADD_INTERNED(close) - ADD_INTERNED(closed) - ADD_INTERNED(decode) - ADD_INTERNED(encode) - ADD_INTERNED(fileno) - ADD_INTERNED(flush) - ADD_INTERNED(getstate) - ADD_INTERNED(isatty) - ADD_INTERNED(newlines) - ADD_INTERNED(read) - ADD_INTERNED(read1) - ADD_INTERNED(readable) - ADD_INTERNED(readall) - ADD_INTERNED(readinto) - ADD_INTERNED(readline) - ADD_INTERNED(reset) - ADD_INTERNED(seek) - ADD_INTERNED(seekable) - ADD_INTERNED(setstate) - ADD_INTERNED(tell) - ADD_INTERNED(truncate) - ADD_INTERNED(write) - ADD_INTERNED(writable) - - if (!_PyIO_str_nl && - !(_PyIO_str_nl = PyUnicode_InternFromString("\n"))) - goto fail; - - if (!_PyIO_empty_str && - !(_PyIO_empty_str = PyUnicode_FromStringAndSize(NULL, 0))) - goto fail; - if (!_PyIO_empty_bytes && - !(_PyIO_empty_bytes = PyBytes_FromStringAndSize(NULL, 0))) - goto fail; - if (!_PyIO_zero && - !(_PyIO_zero = PyLong_FromLong(0L))) - goto fail; - - state->initialized = 1; - - return m; - - fail: - Py_XDECREF(state->unsupported_operation); - Py_DECREF(m); - return NULL; -} +/*[clinic end generated code: output=c51a5a443c11f02b input=a9049054013a1b77]*/ diff --git a/Modules/_io/bufferedio.c b/Modules/_io/clinic/bufferedio.c.h copy from Modules/_io/bufferedio.c copy to Modules/_io/clinic/bufferedio.c.h --- a/Modules/_io/bufferedio.c +++ b/Modules/_io/clinic/bufferedio.c.h @@ -1,2702 +1,474 @@ -/* - An implementation of Buffered I/O as defined by PEP 3116 - "New I/O" +/*[clinic input] +preserve +[clinic start generated code]*/ - Classes defined here: BufferedIOBase, BufferedReader, BufferedWriter, - BufferedRandom. +PyDoc_STRVAR(_io__BufferedIOBase_readinto__doc__, +"readinto($self, buffer, /)\n" +"--\n" +"\n"); - Written by Amaury Forgeot d'Arc and Antoine Pitrou -*/ - -#define PY_SSIZE_T_CLEAN -#include "Python.h" -#include "structmember.h" -#include "pythread.h" -#include "_iomodule.h" - -_Py_IDENTIFIER(close); -_Py_IDENTIFIER(_dealloc_warn); -_Py_IDENTIFIER(flush); -_Py_IDENTIFIER(isatty); -_Py_IDENTIFIER(mode); -_Py_IDENTIFIER(name); -_Py_IDENTIFIER(peek); -_Py_IDENTIFIER(read); -_Py_IDENTIFIER(read1); -_Py_IDENTIFIER(readable); -_Py_IDENTIFIER(readinto); -_Py_IDENTIFIER(readinto1); -_Py_IDENTIFIER(writable); -_Py_IDENTIFIER(write); - -/* - * BufferedIOBase class, inherits from IOBase. - */ -PyDoc_STRVAR(bufferediobase_doc, - "Base class for buffered IO objects.\n" - "\n" - "The main difference with RawIOBase is that the read() method\n" - "supports omitting the size argument, and does not have a default\n" - "implementation that defers to readinto().\n" - "\n" - "In addition, read(), readinto() and write() may raise\n" - "BlockingIOError if the underlying raw stream is in non-blocking\n" - "mode and not ready; unlike their raw counterparts, they will never\n" - "return None.\n" - "\n" - "A typical implementation should not inherit from a RawIOBase\n" - "implementation, but wrap one.\n" - ); +#define _IO__BUFFEREDIOBASE_READINTO_METHODDEF \ + {"readinto", (PyCFunction)_io__BufferedIOBase_readinto, METH_O, _io__BufferedIOBase_readinto__doc__}, static PyObject * -_bufferediobase_readinto_generic(PyObject *self, PyObject *args, char readinto1) +_io__BufferedIOBase_readinto_impl(PyObject *self, Py_buffer *buffer); + +static PyObject * +_io__BufferedIOBase_readinto(PyObject *self, PyObject *arg) { - Py_buffer buf; - Py_ssize_t len; - PyObject *data; + PyObject *return_value = NULL; + Py_buffer buffer = {NULL, NULL}; + + if (!PyArg_Parse(arg, + "w*:readinto", + &buffer)) + goto exit; + return_value = _io__BufferedIOBase_readinto_impl(self, &buffer); + +exit: + /* Cleanup for buffer */ + if (buffer.obj) + PyBuffer_Release(&buffer); + + return return_value; +} + +PyDoc_STRVAR(_io__BufferedIOBase_readinto1__doc__, +"readinto1($self, buffer, /)\n" +"--\n" +"\n"); + +#define _IO__BUFFEREDIOBASE_READINTO1_METHODDEF \ + {"readinto1", (PyCFunction)_io__BufferedIOBase_readinto1, METH_O, _io__BufferedIOBase_readinto1__doc__}, + +static PyObject * +_io__BufferedIOBase_readinto1_impl(PyObject *self, Py_buffer *buffer); + +static PyObject * +_io__BufferedIOBase_readinto1(PyObject *self, PyObject *arg) +{ + PyObject *return_value = NULL; + Py_buffer buffer = {NULL, NULL}; + + if (!PyArg_Parse(arg, + "w*:readinto1", + &buffer)) + goto exit; + return_value = _io__BufferedIOBase_readinto1_impl(self, &buffer); + +exit: + /* Cleanup for buffer */ + if (buffer.obj) + PyBuffer_Release(&buffer); + + return return_value; +} + +PyDoc_STRVAR(_io__BufferedIOBase_detach__doc__, +"detach($self, /)\n" +"--\n" +"\n" +"Disconnect this buffer from its underlying raw stream and return it.\n" +"\n" +"After the raw stream has been detached, the buffer is in an unusable\n" +"state."); + +#define _IO__BUFFEREDIOBASE_DETACH_METHODDEF \ + {"detach", (PyCFunction)_io__BufferedIOBase_detach, METH_NOARGS, _io__BufferedIOBase_detach__doc__}, + +static PyObject * +_io__BufferedIOBase_detach_impl(PyObject *self); + +static PyObject * +_io__BufferedIOBase_detach(PyObject *self, PyObject *Py_UNUSED(ignored)) +{ + return _io__BufferedIOBase_detach_impl(self); +} + +PyDoc_STRVAR(_io__Buffered_peek__doc__, +"peek($self, size=0, /)\n" +"--\n" +"\n"); + +#define _IO__BUFFERED_PEEK_METHODDEF \ + {"peek", (PyCFunction)_io__Buffered_peek, METH_VARARGS, _io__Buffered_peek__doc__}, + +static PyObject * +_io__Buffered_peek_impl(buffered *self, Py_ssize_t size); + +static PyObject * +_io__Buffered_peek(buffered *self, PyObject *args) +{ + PyObject *return_value = NULL; + Py_ssize_t size = 0; if (!PyArg_ParseTuple(args, - readinto1 ? "w*:readinto1" : "w*:readinto", - &buf)) { - return NULL; - } + "|n:peek", + &size)) + goto exit; + return_value = _io__Buffered_peek_impl(self, size); - data = _PyObject_CallMethodId(self, - readinto1 ? &PyId_read1 : &PyId_read, - "n", buf.len); - if (data == NULL) - goto error; - - if (!PyBytes_Check(data)) { - Py_DECREF(data); - PyErr_SetString(PyExc_TypeError, "read() should return bytes"); - goto error; - } - - len = Py_SIZE(data); - if (len > buf.len) { - PyErr_Format(PyExc_ValueError, - "read() returned too much data: " - "%zd bytes requested, %zd returned", - buf.len, len); - Py_DECREF(data); - goto error; - } - memcpy(buf.buf, PyBytes_AS_STRING(data), len); - - PyBuffer_Release(&buf); - Py_DECREF(data); - - return PyLong_FromSsize_t(len); - - error: - PyBuffer_Release(&buf); - return NULL; +exit: + return return_value; } +PyDoc_STRVAR(_io__Buffered_read__doc__, +"read($self, size=-1, /)\n" +"--\n" +"\n"); + +#define _IO__BUFFERED_READ_METHODDEF \ + {"read", (PyCFunction)_io__Buffered_read, METH_VARARGS, _io__Buffered_read__doc__}, + static PyObject * -bufferediobase_readinto(PyObject *self, PyObject *args) +_io__Buffered_read_impl(buffered *self, Py_ssize_t n); + +static PyObject * +_io__Buffered_read(buffered *self, PyObject *args) { - return _bufferediobase_readinto_generic(self, args, 0); + PyObject *return_value = NULL; + Py_ssize_t n = -1; + + if (!PyArg_ParseTuple(args, + "|O&:read", + _PyIO_ConvertSsize_t, &n)) + goto exit; + return_value = _io__Buffered_read_impl(self, n); + +exit: + return return_value; } +PyDoc_STRVAR(_io__Buffered_read1__doc__, +"read1($self, size, /)\n" +"--\n" +"\n"); + +#define _IO__BUFFERED_READ1_METHODDEF \ + {"read1", (PyCFunction)_io__Buffered_read1, METH_O, _io__Buffered_read1__doc__}, + static PyObject * -bufferediobase_readinto1(PyObject *self, PyObject *args) +_io__Buffered_read1_impl(buffered *self, Py_ssize_t n); + +static PyObject * +_io__Buffered_read1(buffered *self, PyObject *arg) { - return _bufferediobase_readinto_generic(self, args, 1); + PyObject *return_value = NULL; + Py_ssize_t n; + + if (!PyArg_Parse(arg, + "n:read1", + &n)) + goto exit; + return_value = _io__Buffered_read1_impl(self, n); + +exit: + return return_value; } +PyDoc_STRVAR(_io__Buffered_readinto__doc__, +"readinto($self, buffer, /)\n" +"--\n" +"\n"); + +#define _IO__BUFFERED_READINTO_METHODDEF \ + {"readinto", (PyCFunction)_io__Buffered_readinto, METH_O, _io__Buffered_readinto__doc__}, + static PyObject * -bufferediobase_unsupported(const char *message) +_io__Buffered_readinto_impl(buffered *self, Py_buffer *buffer); + +static PyObject * +_io__Buffered_readinto(buffered *self, PyObject *arg) { - _PyIO_State *state = IO_STATE(); - if (state != NULL) - PyErr_SetString(state->unsupported_operation, message); - return NULL; + PyObject *return_value = NULL; + Py_buffer buffer = {NULL, NULL}; + + if (!PyArg_Parse(arg, + "w*:readinto", + &buffer)) + goto exit; + return_value = _io__Buffered_readinto_impl(self, &buffer); + +exit: + /* Cleanup for buffer */ + if (buffer.obj) + PyBuffer_Release(&buffer); + + return return_value; } -PyDoc_STRVAR(bufferediobase_detach_doc, - "Disconnect this buffer from its underlying raw stream and return it.\n" - "\n" - "After the raw stream has been detached, the buffer is in an unusable\n" - "state.\n"); +PyDoc_STRVAR(_io__Buffered_readinto1__doc__, +"readinto1($self, buffer, /)\n" +"--\n" +"\n"); + +#define _IO__BUFFERED_READINTO1_METHODDEF \ + {"readinto1", (PyCFunction)_io__Buffered_readinto1, METH_O, _io__Buffered_readinto1__doc__}, static PyObject * -bufferediobase_detach(PyObject *self) +_io__Buffered_readinto1_impl(buffered *self, Py_buffer *buffer); + +static PyObject * +_io__Buffered_readinto1(buffered *self, PyObject *arg) { - return bufferediobase_unsupported("detach"); + PyObject *return_value = NULL; + Py_buffer buffer = {NULL, NULL}; + + if (!PyArg_Parse(arg, + "w*:readinto1", + &buffer)) + goto exit; + return_value = _io__Buffered_readinto1_impl(self, &buffer); + +exit: + /* Cleanup for buffer */ + if (buffer.obj) + PyBuffer_Release(&buffer); + + return return_value; } -PyDoc_STRVAR(bufferediobase_read_doc, - "Read and return up to n bytes.\n" - "\n" - "If the argument is omitted, None, or negative, reads and\n" - "returns all data until EOF.\n" - "\n" - "If the argument is positive, and the underlying raw stream is\n" - "not 'interactive', multiple raw reads may be issued to satisfy\n" - "the byte count (unless EOF is reached first). But for\n" - "interactive raw streams (as well as sockets and pipes), at most\n" - "one raw read will be issued, and a short result does not imply\n" - "that EOF is imminent.\n" - "\n" - "Returns an empty bytes object on EOF.\n" - "\n" - "Returns None if the underlying raw stream was open in non-blocking\n" - "mode and no data is available at the moment.\n"); +PyDoc_STRVAR(_io__Buffered_readline__doc__, +"readline($self, size=-1, /)\n" +"--\n" +"\n"); + +#define _IO__BUFFERED_READLINE_METHODDEF \ + {"readline", (PyCFunction)_io__Buffered_readline, METH_VARARGS, _io__Buffered_readline__doc__}, static PyObject * -bufferediobase_read(PyObject *self, PyObject *args) +_io__Buffered_readline_impl(buffered *self, Py_ssize_t size); + +static PyObject * +_io__Buffered_readline(buffered *self, PyObject *args) { - return bufferediobase_unsupported("read"); + PyObject *return_value = NULL; + Py_ssize_t size = -1; + + if (!PyArg_ParseTuple(args, + "|O&:readline", + _PyIO_ConvertSsize_t, &size)) + goto exit; + return_value = _io__Buffered_readline_impl(self, size); + +exit: + return return_value; } -PyDoc_STRVAR(bufferediobase_read1_doc, - "Read and return up to n bytes, with at most one read() call\n" - "to the underlying raw stream. A short result does not imply\n" - "that EOF is imminent.\n" - "\n" - "Returns an empty bytes object on EOF.\n"); +PyDoc_STRVAR(_io__Buffered_seek__doc__, +"seek($self, target, whence=0, /)\n" +"--\n" +"\n"); + +#define _IO__BUFFERED_SEEK_METHODDEF \ + {"seek", (PyCFunction)_io__Buffered_seek, METH_VARARGS, _io__Buffered_seek__doc__}, static PyObject * -bufferediobase_read1(PyObject *self, PyObject *args) +_io__Buffered_seek_impl(buffered *self, PyObject *targetobj, int whence); + +static PyObject * +_io__Buffered_seek(buffered *self, PyObject *args) { - return bufferediobase_unsupported("read1"); + PyObject *return_value = NULL; + PyObject *targetobj; + int whence = 0; + + if (!PyArg_ParseTuple(args, + "O|i:seek", + &targetobj, &whence)) + goto exit; + return_value = _io__Buffered_seek_impl(self, targetobj, whence); + +exit: + return return_value; } -PyDoc_STRVAR(bufferediobase_write_doc, - "Write the given buffer to the IO stream.\n" - "\n" - "Returns the number of bytes written, which is never less than\n" - "len(b).\n" - "\n" - "Raises BlockingIOError if the buffer is full and the\n" - "underlying raw stream cannot accept more data at the moment.\n"); +PyDoc_STRVAR(_io__Buffered_truncate__doc__, +"truncate($self, pos=None, /)\n" +"--\n" +"\n"); + +#define _IO__BUFFERED_TRUNCATE_METHODDEF \ + {"truncate", (PyCFunction)_io__Buffered_truncate, METH_VARARGS, _io__Buffered_truncate__doc__}, static PyObject * -bufferediobase_write(PyObject *self, PyObject *args) +_io__Buffered_truncate_impl(buffered *self, PyObject *pos); + +static PyObject * +_io__Buffered_truncate(buffered *self, PyObject *args) { - return bufferediobase_unsupported("write"); + PyObject *return_value = NULL; + PyObject *pos = Py_None; + + if (!PyArg_UnpackTuple(args, "truncate", + 0, 1, + &pos)) + goto exit; + return_value = _io__Buffered_truncate_impl(self, pos); + +exit: + return return_value; } - -static PyMethodDef bufferediobase_methods[] = { - {"detach", (PyCFunction)bufferediobase_detach, METH_NOARGS, bufferediobase_detach_doc}, - {"read", bufferediobase_read, METH_VARARGS, bufferediobase_read_doc}, - {"read1", bufferediobase_read1, METH_VARARGS, bufferediobase_read1_doc}, - {"readinto", bufferediobase_readinto, METH_VARARGS, NULL}, - {"readinto1", bufferediobase_readinto1, METH_VARARGS, NULL}, - {"write", bufferediobase_write, METH_VARARGS, bufferediobase_write_doc}, - {NULL, NULL} -}; - -PyTypeObject PyBufferedIOBase_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "_io._BufferedIOBase", /*tp_name*/ - 0, /*tp_basicsize*/ - 0, /*tp_itemsize*/ - 0, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare */ - 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 | Py_TPFLAGS_BASETYPE - | Py_TPFLAGS_HAVE_FINALIZE, /*tp_flags*/ - bufferediobase_doc, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - bufferediobase_methods, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - &PyIOBase_Type, /* 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, /* tp_free */ - 0, /* tp_is_gc */ - 0, /* tp_bases */ - 0, /* tp_mro */ - 0, /* tp_cache */ - 0, /* tp_subclasses */ - 0, /* tp_weaklist */ - 0, /* tp_del */ - 0, /* tp_version_tag */ - 0, /* tp_finalize */ -}; - - -typedef struct { - PyObject_HEAD - - PyObject *raw; - int ok; /* Initialized? */ - int detached; - int readable; - int writable; - char finalizing; - - /* True if this is a vanilla Buffered object (rather than a user derived - class) *and* the raw stream is a vanilla FileIO object. */ - int fast_closed_checks; - - /* Absolute position inside the raw stream (-1 if unknown). */ - Py_off_t abs_pos; - - /* A static buffer of size `buffer_size` */ - char *buffer; - /* Current logical position in the buffer. */ - Py_off_t pos; - /* Position of the raw stream in the buffer. */ - Py_off_t raw_pos; - - /* Just after the last buffered byte in the buffer, or -1 if the buffer - isn't ready for reading. */ - Py_off_t read_end; - - /* Just after the last byte actually written */ - Py_off_t write_pos; - /* Just after the last byte waiting to be written, or -1 if the buffer - isn't ready for writing. */ - Py_off_t write_end; - -#ifdef WITH_THREAD - PyThread_type_lock lock; - volatile long owner; -#endif - - Py_ssize_t buffer_size; - Py_ssize_t buffer_mask; - - PyObject *dict; - PyObject *weakreflist; -} buffered; - -/* - Implementation notes: - - * BufferedReader, BufferedWriter and BufferedRandom try to share most - methods (this is helped by the members `readable` and `writable`, which - are initialized in the respective constructors) - * They also share a single buffer for reading and writing. This enables - interleaved reads and writes without flushing. It also makes the logic - a bit trickier to get right. - * The absolute position of the raw stream is cached, if possible, in the - `abs_pos` member. It must be updated every time an operation is done - on the raw stream. If not sure, it can be reinitialized by calling - _buffered_raw_tell(), which queries the raw stream (_buffered_raw_seek() - also does it). To read it, use RAW_TELL(). - * Three helpers, _bufferedreader_raw_read, _bufferedwriter_raw_write and - _bufferedwriter_flush_unlocked do a lot of useful housekeeping. - - NOTE: we should try to maintain block alignment of reads and writes to the - raw stream (according to the buffer size), but for now it is only done - in read() and friends. - -*/ - -/* These macros protect the buffered object against concurrent operations. */ - -#ifdef WITH_THREAD +PyDoc_STRVAR(_io_BufferedReader___init____doc__, +"BufferedReader(raw, buffer_size=DEFAULT_BUFFER_SIZE)\n" +"--\n" +"\n" +"Create a new buffered reader using the given readable raw IO object."); static int -_enter_buffered_busy(buffered *self) +_io_BufferedReader___init___impl(buffered *self, PyObject *raw, + Py_ssize_t buffer_size); + +static int +_io_BufferedReader___init__(PyObject *self, PyObject *args, PyObject *kwargs) { - int relax_locking; - PyLockStatus st; - if (self->owner == PyThread_get_thread_ident()) { - PyErr_Format(PyExc_RuntimeError, - "reentrant call inside %R", self); - return 0; - } - relax_locking = (_Py_Finalizing != NULL); - Py_BEGIN_ALLOW_THREADS - if (!relax_locking) - st = PyThread_acquire_lock(self->lock, 1); - else { - /* When finalizing, we don't want a deadlock to happen with daemon - * threads abruptly shut down while they owned the lock. - * Therefore, only wait for a grace period (1 s.). - * Note that non-daemon threads have already exited here, so this - * shouldn't affect carefully written threaded I/O code. - */ - st = PyThread_acquire_lock_timed(self->lock, 1e6, 0); - } - Py_END_ALLOW_THREADS - if (relax_locking && st != PY_LOCK_ACQUIRED) { - PyObject *msgobj = PyUnicode_FromFormat( - "could not acquire lock for %A at interpreter " - "shutdown, possibly due to daemon threads", - (PyObject *) self); - char *msg = PyUnicode_AsUTF8(msgobj); - Py_FatalError(msg); - } - return 1; + int return_value = -1; + static char *_keywords[] = {"raw", "buffer_size", NULL}; + PyObject *raw; + Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, + "O|n:BufferedReader", _keywords, + &raw, &buffer_size)) + goto exit; + return_value = _io_BufferedReader___init___impl((buffered *)self, raw, buffer_size); + +exit: + return return_value; } -#define ENTER_BUFFERED(self) \ - ( (PyThread_acquire_lock(self->lock, 0) ? \ - 1 : _enter_buffered_busy(self)) \ - && (self->owner = PyThread_get_thread_ident(), 1) ) +PyDoc_STRVAR(_io_BufferedWriter___init____doc__, +"BufferedWriter(raw, buffer_size=DEFAULT_BUFFER_SIZE)\n" +"--\n" +"\n" +"A buffer for a writeable sequential RawIO object.\n" +"\n" +"The constructor creates a BufferedWriter for the given writeable raw\n" +"stream. If the buffer_size is not given, it defaults to\n" +"DEFAULT_BUFFER_SIZE."); -#define LEAVE_BUFFERED(self) \ - do { \ - self->owner = 0; \ - PyThread_release_lock(self->lock); \ - } while(0); +static int +_io_BufferedWriter___init___impl(buffered *self, PyObject *raw, + Py_ssize_t buffer_size); -#else -#define ENTER_BUFFERED(self) 1 -#define LEAVE_BUFFERED(self) -#endif +static int +_io_BufferedWriter___init__(PyObject *self, PyObject *args, PyObject *kwargs) +{ + int return_value = -1; + static char *_keywords[] = {"raw", "buffer_size", NULL}; + PyObject *raw; + Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE; -#define CHECK_INITIALIZED(self) \ - if (self->ok <= 0) { \ - if (self->detached) { \ - PyErr_SetString(PyExc_ValueError, \ - "raw stream has been detached"); \ - } else { \ - PyErr_SetString(PyExc_ValueError, \ - "I/O operation on uninitialized object"); \ - } \ - return NULL; \ - } + if (!PyArg_ParseTupleAndKeywords(args, kwargs, + "O|n:BufferedWriter", _keywords, + &raw, &buffer_size)) + goto exit; + return_value = _io_BufferedWriter___init___impl((buffered *)self, raw, buffer_size); -#define CHECK_INITIALIZED_INT(self) \ - if (self->ok <= 0) { \ - if (self->detached) { \ - PyErr_SetString(PyExc_ValueError, \ - "raw stream has been detached"); \ - } else { \ - PyErr_SetString(PyExc_ValueError, \ - "I/O operation on uninitialized object"); \ - } \ - return -1; \ - } - -#define IS_CLOSED(self) \ - (self->fast_closed_checks \ - ? _PyFileIO_closed(self->raw) \ - : buffered_closed(self)) - -#define CHECK_CLOSED(self, error_msg) \ - if (IS_CLOSED(self)) { \ - PyErr_SetString(PyExc_ValueError, error_msg); \ - return NULL; \ - } - - -#define VALID_READ_BUFFER(self) \ - (self->readable && self->read_end != -1) - -#define VALID_WRITE_BUFFER(self) \ - (self->writable && self->write_end != -1) - -#define ADJUST_POSITION(self, _new_pos) \ - do { \ - self->pos = _new_pos; \ - if (VALID_READ_BUFFER(self) && self->read_end < self->pos) \ - self->read_end = self->pos; \ - } while(0) - -#define READAHEAD(self) \ - ((self->readable && VALID_READ_BUFFER(self)) \ - ? (self->read_end - self->pos) : 0) - -#define RAW_OFFSET(self) \ - (((VALID_READ_BUFFER(self) || VALID_WRITE_BUFFER(self)) \ - && self->raw_pos >= 0) ? self->raw_pos - self->pos : 0) - -#define RAW_TELL(self) \ - (self->abs_pos != -1 ? self->abs_pos : _buffered_raw_tell(self)) - -#define MINUS_LAST_BLOCK(self, size) \ - (self->buffer_mask ? \ - (size & ~self->buffer_mask) : \ - (self->buffer_size * (size / self->buffer_size))) - - -static void -buffered_dealloc(buffered *self) -{ - self->finalizing = 1; - if (_PyIOBase_finalize((PyObject *) self) < 0) - return; - _PyObject_GC_UNTRACK(self); - self->ok = 0; - if (self->weakreflist != NULL) - PyObject_ClearWeakRefs((PyObject *)self); - Py_CLEAR(self->raw); - if (self->buffer) { - PyMem_Free(self->buffer); - self->buffer = NULL; - } -#ifdef WITH_THREAD - if (self->lock) { - PyThread_free_lock(self->lock); - self->lock = NULL; - } -#endif - Py_CLEAR(self->dict); - Py_TYPE(self)->tp_free((PyObject *)self); +exit: + return return_value; } +PyDoc_STRVAR(_io_BufferedWriter_write__doc__, +"write($self, buffer, /)\n" +"--\n" +"\n"); + +#define _IO_BUFFEREDWRITER_WRITE_METHODDEF \ + {"write", (PyCFunction)_io_BufferedWriter_write, METH_O, _io_BufferedWriter_write__doc__}, + static PyObject * -buffered_sizeof(buffered *self, void *unused) +_io_BufferedWriter_write_impl(buffered *self, Py_buffer *buffer); + +static PyObject * +_io_BufferedWriter_write(buffered *self, PyObject *arg) { - Py_ssize_t res; + PyObject *return_value = NULL; + Py_buffer buffer = {NULL, NULL}; - res = sizeof(buffered); - if (self->buffer) - res += self->buffer_size; - return PyLong_FromSsize_t(res); + if (!PyArg_Parse(arg, + "y*:write", + &buffer)) + goto exit; + return_value = _io_BufferedWriter_write_impl(self, &buffer); + +exit: + /* Cleanup for buffer */ + if (buffer.obj) + PyBuffer_Release(&buffer); + + return return_value; } +PyDoc_STRVAR(_io_BufferedRWPair___init____doc__, +"BufferedRWPair(reader, writer, buffer_size=DEFAULT_BUFFER_SIZE, /)\n" +"--\n" +"\n" +"A buffered reader and writer object together.\n" +"\n" +"A buffered reader object and buffered writer object put together to\n" +"form a sequential IO object that can read and write. This is typically\n" +"used with a socket or two-way pipe.\n" +"\n" +"reader and writer are RawIOBase objects that are readable and\n" +"writeable respectively. If the buffer_size is omitted it defaults to\n" +"DEFAULT_BUFFER_SIZE."); + static int -buffered_traverse(buffered *self, visitproc visit, void *arg) +_io_BufferedRWPair___init___impl(rwpair *self, PyObject *reader, + PyObject *writer, Py_ssize_t buffer_size); + +static int +_io_BufferedRWPair___init__(PyObject *self, PyObject *args, PyObject *kwargs) { - Py_VISIT(self->raw); - Py_VISIT(self->dict); - return 0; + int return_value = -1; + PyObject *reader; + PyObject *writer; + Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE; + + if ((Py_TYPE(self) == &PyBufferedRWPair_Type) && + !_PyArg_NoKeywords("BufferedRWPair", kwargs)) + goto exit; + if (!PyArg_ParseTuple(args, + "OO|n:BufferedRWPair", + &reader, &writer, &buffer_size)) + goto exit; + return_value = _io_BufferedRWPair___init___impl((rwpair *)self, reader, writer, buffer_size); + +exit: + return return_value; } -static int -buffered_clear(buffered *self) -{ - self->ok = 0; - Py_CLEAR(self->raw); - Py_CLEAR(self->dict); - return 0; -} - -/* Because this can call arbitrary code, it shouldn't be called when - the refcount is 0 (that is, not directly from tp_dealloc unless - the refcount has been temporarily re-incremented). */ -static PyObject * -buffered_dealloc_warn(buffered *self, PyObject *source) -{ - if (self->ok && self->raw) { - PyObject *r; - r = _PyObject_CallMethodId(self->raw, &PyId__dealloc_warn, "O", source); - if (r) - Py_DECREF(r); - else - PyErr_Clear(); - } - Py_RETURN_NONE; -} - -/* - * _BufferedIOMixin methods - * This is not a class, just a collection of methods that will be reused - * by BufferedReader and BufferedWriter - */ - -/* Flush and close */ - -static PyObject * -buffered_simple_flush(buffered *self, PyObject *args) -{ - CHECK_INITIALIZED(self) - return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_flush, NULL); -} +PyDoc_STRVAR(_io_BufferedRandom___init____doc__, +"BufferedRandom(raw, buffer_size=DEFAULT_BUFFER_SIZE)\n" +"--\n" +"\n" +"A buffered interface to random access streams.\n" +"\n" +"The constructor creates a reader and writer for a seekable stream,\n" +"raw, given in the first argument. If the buffer_size is omitted it\n" +"defaults to DEFAULT_BUFFER_SIZE."); static int -buffered_closed(buffered *self) -{ - int closed; - PyObject *res; - CHECK_INITIALIZED_INT(self) - res = PyObject_GetAttr(self->raw, _PyIO_str_closed); - if (res == NULL) - return -1; - closed = PyObject_IsTrue(res); - Py_DECREF(res); - return closed; -} - -static PyObject * -buffered_closed_get(buffered *self, void *context) -{ - CHECK_INITIALIZED(self) - return PyObject_GetAttr(self->raw, _PyIO_str_closed); -} - -static PyObject * -buffered_close(buffered *self, PyObject *args) -{ - PyObject *res = NULL, *exc = NULL, *val, *tb; - int r; - - CHECK_INITIALIZED(self) - if (!ENTER_BUFFERED(self)) - return NULL; - - r = buffered_closed(self); - if (r < 0) - goto end; - if (r > 0) { - res = Py_None; - Py_INCREF(res); - goto end; - } - - if (self->finalizing) { - PyObject *r = buffered_dealloc_warn(self, (PyObject *) self); - if (r) - Py_DECREF(r); - else - PyErr_Clear(); - } - /* flush() will most probably re-take the lock, so drop it first */ - LEAVE_BUFFERED(self) - res = PyObject_CallMethodObjArgs((PyObject *)self, _PyIO_str_flush, NULL); - if (!ENTER_BUFFERED(self)) - return NULL; - if (res == NULL) - PyErr_Fetch(&exc, &val, &tb); - else - Py_DECREF(res); - - res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_close, NULL); - - if (self->buffer) { - PyMem_Free(self->buffer); - self->buffer = NULL; - } - - if (exc != NULL) { - _PyErr_ChainExceptions(exc, val, tb); - Py_CLEAR(res); - } - -end: - LEAVE_BUFFERED(self) - return res; -} - -/* detach */ - -static PyObject * -buffered_detach(buffered *self, PyObject *args) -{ - PyObject *raw, *res; - CHECK_INITIALIZED(self) - res = PyObject_CallMethodObjArgs((PyObject *)self, _PyIO_str_flush, NULL); - if (res == NULL) - return NULL; - Py_DECREF(res); - raw = self->raw; - self->raw = NULL; - self->detached = 1; - self->ok = 0; - return raw; -} - -/* Inquiries */ - -static PyObject * -buffered_seekable(buffered *self, PyObject *args) -{ - CHECK_INITIALIZED(self) - return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_seekable, NULL); -} - -static PyObject * -buffered_readable(buffered *self, PyObject *args) -{ - CHECK_INITIALIZED(self) - return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_readable, NULL); -} - -static PyObject * -buffered_writable(buffered *self, PyObject *args) -{ - CHECK_INITIALIZED(self) - return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_writable, NULL); -} - -static PyObject * -buffered_name_get(buffered *self, void *context) -{ - CHECK_INITIALIZED(self) - return _PyObject_GetAttrId(self->raw, &PyId_name); -} - -static PyObject * -buffered_mode_get(buffered *self, void *context) -{ - CHECK_INITIALIZED(self) - return _PyObject_GetAttrId(self->raw, &PyId_mode); -} - -/* Lower-level APIs */ - -static PyObject * -buffered_fileno(buffered *self, PyObject *args) -{ - CHECK_INITIALIZED(self) - return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_fileno, NULL); -} - -static PyObject * -buffered_isatty(buffered *self, PyObject *args) -{ - CHECK_INITIALIZED(self) - return PyObject_CallMethodObjArgs(self->raw, _PyIO_str_isatty, NULL); -} - -/* Serialization */ - -static PyObject * -buffered_getstate(buffered *self, PyObject *args) -{ - PyErr_Format(PyExc_TypeError, - "cannot serialize '%s' object", Py_TYPE(self)->tp_name); - return NULL; -} - -/* Forward decls */ -static PyObject * -_bufferedwriter_flush_unlocked(buffered *); -static Py_ssize_t -_bufferedreader_fill_buffer(buffered *self); -static void -_bufferedreader_reset_buf(buffered *self); -static void -_bufferedwriter_reset_buf(buffered *self); -static PyObject * -_bufferedreader_peek_unlocked(buffered *self); -static PyObject * -_bufferedreader_read_all(buffered *self); -static PyObject * -_bufferedreader_read_fast(buffered *self, Py_ssize_t); -static PyObject * -_bufferedreader_read_generic(buffered *self, Py_ssize_t); -static Py_ssize_t -_bufferedreader_raw_read(buffered *self, char *start, Py_ssize_t len); - -/* - * Helpers - */ - -/* Sets the current error to BlockingIOError */ -static void -_set_BlockingIOError(char *msg, Py_ssize_t written) -{ - PyObject *err; - PyErr_Clear(); - err = PyObject_CallFunction(PyExc_BlockingIOError, "isn", - errno, msg, written); - if (err) - PyErr_SetObject(PyExc_BlockingIOError, err); - Py_XDECREF(err); -} - -/* Returns the address of the `written` member if a BlockingIOError was - raised, NULL otherwise. The error is always re-raised. */ -static Py_ssize_t * -_buffered_check_blocking_error(void) -{ - PyObject *t, *v, *tb; - PyOSErrorObject *err; - - PyErr_Fetch(&t, &v, &tb); - if (v == NULL || !PyErr_GivenExceptionMatches(v, PyExc_BlockingIOError)) { - PyErr_Restore(t, v, tb); - return NULL; - } - err = (PyOSErrorObject *) v; - /* TODO: sanity check (err->written >= 0) */ - PyErr_Restore(t, v, tb); - return &err->written; -} - -static Py_off_t -_buffered_raw_tell(buffered *self) -{ - Py_off_t n; - PyObject *res; - res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_tell, NULL); - if (res == NULL) - return -1; - n = PyNumber_AsOff_t(res, PyExc_ValueError); - Py_DECREF(res); - if (n < 0) { - if (!PyErr_Occurred()) - PyErr_Format(PyExc_IOError, - "Raw stream returned invalid position %" PY_PRIdOFF, - (PY_OFF_T_COMPAT)n); - return -1; - } - self->abs_pos = n; - return n; -} - -static Py_off_t -_buffered_raw_seek(buffered *self, Py_off_t target, int whence) -{ - PyObject *res, *posobj, *whenceobj; - Py_off_t n; - - posobj = PyLong_FromOff_t(target); - if (posobj == NULL) - return -1; - whenceobj = PyLong_FromLong(whence); - if (whenceobj == NULL) { - Py_DECREF(posobj); - return -1; - } - res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_seek, - posobj, whenceobj, NULL); - Py_DECREF(posobj); - Py_DECREF(whenceobj); - if (res == NULL) - return -1; - n = PyNumber_AsOff_t(res, PyExc_ValueError); - Py_DECREF(res); - if (n < 0) { - if (!PyErr_Occurred()) - PyErr_Format(PyExc_IOError, - "Raw stream returned invalid position %" PY_PRIdOFF, - (PY_OFF_T_COMPAT)n); - return -1; - } - self->abs_pos = n; - return n; -} +_io_BufferedRandom___init___impl(buffered *self, PyObject *raw, + Py_ssize_t buffer_size); static int -_buffered_init(buffered *self) +_io_BufferedRandom___init__(PyObject *self, PyObject *args, PyObject *kwargs) { - Py_ssize_t n; - if (self->buffer_size <= 0) { - PyErr_SetString(PyExc_ValueError, - "buffer size must be strictly positive"); - return -1; - } - if (self->buffer) - PyMem_Free(self->buffer); - self->buffer = PyMem_Malloc(self->buffer_size); - if (self->buffer == NULL) { - PyErr_NoMemory(); - return -1; - } -#ifdef WITH_THREAD - if (self->lock) - PyThread_free_lock(self->lock); - self->lock = PyThread_allocate_lock(); - if (self->lock == NULL) { - PyErr_SetString(PyExc_RuntimeError, "can't allocate read lock"); - return -1; - } - self->owner = 0; -#endif - /* Find out whether buffer_size is a power of 2 */ - /* XXX is this optimization useful? */ - for (n = self->buffer_size - 1; n & 1; n >>= 1) - ; - if (n == 0) - self->buffer_mask = self->buffer_size - 1; - else - self->buffer_mask = 0; - if (_buffered_raw_tell(self) == -1) - PyErr_Clear(); - return 0; -} - -/* Return 1 if an EnvironmentError with errno == EINTR is set (and then - clears the error indicator), 0 otherwise. - Should only be called when PyErr_Occurred() is true. -*/ -int -_PyIO_trap_eintr(void) -{ - static PyObject *eintr_int = NULL; - PyObject *typ, *val, *tb; - PyEnvironmentErrorObject *env_err; - - if (eintr_int == NULL) { - eintr_int = PyLong_FromLong(EINTR); - assert(eintr_int != NULL); - } - if (!PyErr_ExceptionMatches(PyExc_EnvironmentError)) - return 0; - PyErr_Fetch(&typ, &val, &tb); - PyErr_NormalizeException(&typ, &val, &tb); - env_err = (PyEnvironmentErrorObject *) val; - assert(env_err != NULL); - if (env_err->myerrno != NULL && - PyObject_RichCompareBool(env_err->myerrno, eintr_int, Py_EQ) > 0) { - Py_DECREF(typ); - Py_DECREF(val); - Py_XDECREF(tb); - return 1; - } - /* This silences any error set by PyObject_RichCompareBool() */ - PyErr_Restore(typ, val, tb); - return 0; -} - -/* - * Shared methods and wrappers - */ - -static PyObject * -buffered_flush_and_rewind_unlocked(buffered *self) -{ - PyObject *res; - - res = _bufferedwriter_flush_unlocked(self); - if (res == NULL) - return NULL; - Py_DECREF(res); - - if (self->readable) { - /* Rewind the raw stream so that its position corresponds to - the current logical position. */ - Py_off_t n; - n = _buffered_raw_seek(self, -RAW_OFFSET(self), 1); - _bufferedreader_reset_buf(self); - if (n == -1) - return NULL; - } - Py_RETURN_NONE; -} - -static PyObject * -buffered_flush(buffered *self, PyObject *args) -{ - PyObject *res; - - CHECK_INITIALIZED(self) - CHECK_CLOSED(self, "flush of closed file") - - if (!ENTER_BUFFERED(self)) - return NULL; - res = buffered_flush_and_rewind_unlocked(self); - LEAVE_BUFFERED(self) - - return res; -} - -static PyObject * -buffered_peek(buffered *self, PyObject *args) -{ - Py_ssize_t n = 0; - PyObject *res = NULL; - - CHECK_INITIALIZED(self) - if (!PyArg_ParseTuple(args, "|n:peek", &n)) { - return NULL; - } - - if (!ENTER_BUFFERED(self)) - return NULL; - - if (self->writable) { - res = buffered_flush_and_rewind_unlocked(self); - if (res == NULL) - goto end; - Py_CLEAR(res); - } - res = _bufferedreader_peek_unlocked(self); - -end: - LEAVE_BUFFERED(self) - return res; -} - -static PyObject * -buffered_read(buffered *self, PyObject *args) -{ - Py_ssize_t n = -1; - PyObject *res; - - CHECK_INITIALIZED(self) - if (!PyArg_ParseTuple(args, "|O&:read", &_PyIO_ConvertSsize_t, &n)) { - return NULL; - } - if (n < -1) { - PyErr_SetString(PyExc_ValueError, - "read length must be positive or -1"); - return NULL; - } - - CHECK_CLOSED(self, "read of closed file") - - if (n == -1) { - /* The number of bytes is unspecified, read until the end of stream */ - if (!ENTER_BUFFERED(self)) - return NULL; - res = _bufferedreader_read_all(self); - } - else { - res = _bufferedreader_read_fast(self, n); - if (res != Py_None) - return res; - Py_DECREF(res); - if (!ENTER_BUFFERED(self)) - return NULL; - res = _bufferedreader_read_generic(self, n); - } - - LEAVE_BUFFERED(self) - return res; -} - -static PyObject * -buffered_read1(buffered *self, PyObject *args) -{ - Py_ssize_t n, have, r; - PyObject *res = NULL; - - CHECK_INITIALIZED(self) - if (!PyArg_ParseTuple(args, "n:read1", &n)) { - return NULL; - } - - if (n < 0) { - PyErr_SetString(PyExc_ValueError, - "read length must be positive"); - return NULL; - } - if (n == 0) - return PyBytes_FromStringAndSize(NULL, 0); - - /* Return up to n bytes. If at least one byte is buffered, we - only return buffered bytes. Otherwise, we do one raw read. */ - - have = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t); - if (have > 0) { - n = Py_MIN(have, n); - res = _bufferedreader_read_fast(self, n); - assert(res != Py_None); - return res; - } - res = PyBytes_FromStringAndSize(NULL, n); - if (res == NULL) - return NULL; - if (!ENTER_BUFFERED(self)) { - Py_DECREF(res); - return NULL; - } - _bufferedreader_reset_buf(self); - r = _bufferedreader_raw_read(self, PyBytes_AS_STRING(res), n); - LEAVE_BUFFERED(self) - if (r == -1) { - Py_DECREF(res); - return NULL; - } - if (r == -2) - r = 0; - if (n > r) - _PyBytes_Resize(&res, r); - return res; -} - -static PyObject * -_buffered_readinto_generic(buffered *self, PyObject *args, char readinto1) -{ - Py_buffer buf; - Py_ssize_t n, written = 0, remaining; - PyObject *res = NULL; - - CHECK_INITIALIZED(self) - - if (!PyArg_ParseTuple(args, - readinto1 ? "w*:readinto1" : "w*:readinto", - &buf)) - return NULL; - - n = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t); - if (n > 0) { - if (n >= buf.len) { - memcpy(buf.buf, self->buffer + self->pos, buf.len); - self->pos += buf.len; - res = PyLong_FromSsize_t(buf.len); - goto end_unlocked; - } - memcpy(buf.buf, self->buffer + self->pos, n); - self->pos += n; - written = n; - } - - if (!ENTER_BUFFERED(self)) - goto end_unlocked; - - if (self->writable) { - res = buffered_flush_and_rewind_unlocked(self); - if (res == NULL) - goto end; - Py_CLEAR(res); - } - - _bufferedreader_reset_buf(self); - self->pos = 0; - - for (remaining = buf.len - written; - remaining > 0; - written += n, remaining -= n) { - /* If remaining bytes is larger than internal buffer size, copy - * directly into caller's buffer. */ - if (remaining > self->buffer_size) { - n = _bufferedreader_raw_read(self, (char *) buf.buf + written, - remaining); - } - - /* In readinto1 mode, we do not want to fill the internal - buffer if we already have some data to return */ - else if (!(readinto1 && written)) { - n = _bufferedreader_fill_buffer(self); - if (n > 0) { - if (n > remaining) - n = remaining; - memcpy((char *) buf.buf + written, - self->buffer + self->pos, n); - self->pos += n; - continue; /* short circuit */ - } - } - else - n = 0; - - if (n == 0 || (n == -2 && written > 0)) - break; - if (n < 0) { - if (n == -2) { - Py_INCREF(Py_None); - res = Py_None; - } - goto end; - } - - /* At most one read in readinto1 mode */ - if (readinto1) { - written += n; - break; - } - } - res = PyLong_FromSsize_t(written); - -end: - LEAVE_BUFFERED(self); -end_unlocked: - PyBuffer_Release(&buf); - return res; -} - -static PyObject * -buffered_readinto(buffered *self, PyObject *args) -{ - return _buffered_readinto_generic(self, args, 0); -} - -static PyObject * -buffered_readinto1(buffered *self, PyObject *args) -{ - return _buffered_readinto_generic(self, args, 1); -} - - -static PyObject * -_buffered_readline(buffered *self, Py_ssize_t limit) -{ - PyObject *res = NULL; - PyObject *chunks = NULL; - Py_ssize_t n, written = 0; - const char *start, *s, *end; - - CHECK_CLOSED(self, "readline of closed file") - - /* First, try to find a line in the buffer. This can run unlocked because - the calls to the C API are simple enough that they can't trigger - any thread switch. */ - n = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t); - if (limit >= 0 && n > limit) - n = limit; - start = self->buffer + self->pos; - s = memchr(start, '\n', n); - if (s != NULL) { - res = PyBytes_FromStringAndSize(start, s - start + 1); - if (res != NULL) - self->pos += s - start + 1; - goto end_unlocked; - } - if (n == limit) { - res = PyBytes_FromStringAndSize(start, n); - if (res != NULL) - self->pos += n; - goto end_unlocked; - } - - if (!ENTER_BUFFERED(self)) - goto end_unlocked; - - /* Now we try to get some more from the raw stream */ - chunks = PyList_New(0); - if (chunks == NULL) - goto end; - if (n > 0) { - res = PyBytes_FromStringAndSize(start, n); - if (res == NULL) - goto end; - if (PyList_Append(chunks, res) < 0) { - Py_CLEAR(res); - goto end; - } - Py_CLEAR(res); - written += n; - self->pos += n; - if (limit >= 0) - limit -= n; - } - if (self->writable) { - PyObject *r = buffered_flush_and_rewind_unlocked(self); - if (r == NULL) - goto end; - Py_DECREF(r); - } - - for (;;) { - _bufferedreader_reset_buf(self); - n = _bufferedreader_fill_buffer(self); - if (n == -1) - goto end; - if (n <= 0) - break; - if (limit >= 0 && n > limit) - n = limit; - start = self->buffer; - end = start + n; - s = start; - while (s < end) { - if (*s++ == '\n') { - res = PyBytes_FromStringAndSize(start, s - start); - if (res == NULL) - goto end; - self->pos = s - start; - goto found; - } - } - res = PyBytes_FromStringAndSize(start, n); - if (res == NULL) - goto end; - if (n == limit) { - self->pos = n; - break; - } - if (PyList_Append(chunks, res) < 0) { - Py_CLEAR(res); - goto end; - } - Py_CLEAR(res); - written += n; - if (limit >= 0) - limit -= n; - } -found: - if (res != NULL && PyList_Append(chunks, res) < 0) { - Py_CLEAR(res); - goto end; - } - Py_CLEAR(res); - res = _PyBytes_Join(_PyIO_empty_bytes, chunks); - -end: - LEAVE_BUFFERED(self) -end_unlocked: - Py_XDECREF(chunks); - return res; -} - -static PyObject * -buffered_readline(buffered *self, PyObject *args) -{ - Py_ssize_t limit = -1; - - CHECK_INITIALIZED(self) - if (!PyArg_ParseTuple(args, "|O&:readline", &_PyIO_ConvertSsize_t, &limit)) - return NULL; - return _buffered_readline(self, limit); -} - - -static PyObject * -buffered_tell(buffered *self, PyObject *args) -{ - Py_off_t pos; - - CHECK_INITIALIZED(self) - pos = _buffered_raw_tell(self); - if (pos == -1) - return NULL; - pos -= RAW_OFFSET(self); - /* TODO: sanity check (pos >= 0) */ - return PyLong_FromOff_t(pos); -} - -static PyObject * -buffered_seek(buffered *self, PyObject *args) -{ - Py_off_t target, n; - int whence = 0; - PyObject *targetobj, *res = NULL; - - CHECK_INITIALIZED(self) - 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 - ) { - PyErr_Format(PyExc_ValueError, - "whence value %d unsupported", whence); - return NULL; - } - - CHECK_CLOSED(self, "seek of closed file") - - if (_PyIOBase_check_seekable(self->raw, Py_True) == NULL) - return NULL; - - target = PyNumber_AsOff_t(targetobj, PyExc_ValueError); - 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) { - 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 - lock in this fast path. - Don't know how to do that when whence == 2, though. */ - /* NOTE: RAW_TELL() can release the GIL but the object is in a stable - state at this point. */ - current = RAW_TELL(self); - avail = READAHEAD(self); - if (avail > 0) { - Py_off_t offset; - if (whence == 0) - offset = target - (current - RAW_OFFSET(self)); - else - offset = target; - if (offset >= -self->pos && offset <= avail) { - self->pos += offset; - return PyLong_FromOff_t(current - avail + offset); - } - } - } - - if (!ENTER_BUFFERED(self)) - return NULL; - - /* Fallback: invoke raw seek() method and clear buffer */ - if (self->writable) { - res = _bufferedwriter_flush_unlocked(self); - if (res == NULL) - goto end; - Py_CLEAR(res); - _bufferedwriter_reset_buf(self); - } - - /* TODO: align on block boundary and read buffer if needed? */ - if (whence == 1) - target -= RAW_OFFSET(self); - n = _buffered_raw_seek(self, target, whence); - if (n == -1) - goto end; - self->raw_pos = -1; - res = PyLong_FromOff_t(n); - if (res != NULL && self->readable) - _bufferedreader_reset_buf(self); - -end: - LEAVE_BUFFERED(self) - return res; -} - -static PyObject * -buffered_truncate(buffered *self, PyObject *args) -{ - PyObject *pos = Py_None; - PyObject *res = NULL; - - CHECK_INITIALIZED(self) - if (!PyArg_ParseTuple(args, "|O:truncate", &pos)) { - return NULL; - } - - if (!ENTER_BUFFERED(self)) - return NULL; - - if (self->writable) { - res = buffered_flush_and_rewind_unlocked(self); - if (res == NULL) - goto end; - Py_CLEAR(res); - } - res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_truncate, pos, NULL); - if (res == NULL) - goto end; - /* Reset cached position */ - if (_buffered_raw_tell(self) == -1) - PyErr_Clear(); - -end: - LEAVE_BUFFERED(self) - return res; -} - -static PyObject * -buffered_iternext(buffered *self) -{ - PyObject *line; - PyTypeObject *tp; - - CHECK_INITIALIZED(self); - - tp = Py_TYPE(self); - if (tp == &PyBufferedReader_Type || - tp == &PyBufferedRandom_Type) { - /* Skip method call overhead for speed */ - line = _buffered_readline(self, -1); - } - else { - line = PyObject_CallMethodObjArgs((PyObject *)self, - _PyIO_str_readline, NULL); - if (line && !PyBytes_Check(line)) { - PyErr_Format(PyExc_IOError, - "readline() should have returned a bytes object, " - "not '%.200s'", Py_TYPE(line)->tp_name); - Py_DECREF(line); - return NULL; - } - } - - if (line == NULL) - return NULL; - - if (PyBytes_GET_SIZE(line) == 0) { - /* Reached EOF or would have blocked */ - Py_DECREF(line); - return NULL; - } - - return line; -} - -static PyObject * -buffered_repr(buffered *self) -{ - PyObject *nameobj, *res; - - nameobj = _PyObject_GetAttrId((PyObject *) self, &PyId_name); - if (nameobj == NULL) { - if (PyErr_ExceptionMatches(PyExc_Exception)) - PyErr_Clear(); - else - return NULL; - res = PyUnicode_FromFormat("<%s>", Py_TYPE(self)->tp_name); - } - else { - res = PyUnicode_FromFormat("<%s name=%R>", - Py_TYPE(self)->tp_name, nameobj); - Py_DECREF(nameobj); - } - return res; -} - -/* - * class BufferedReader - */ - -PyDoc_STRVAR(bufferedreader_doc, - "Create a new buffered reader using the given readable raw IO object."); - -static void _bufferedreader_reset_buf(buffered *self) -{ - self->read_end = -1; -} - -static int -bufferedreader_init(buffered *self, PyObject *args, PyObject *kwds) -{ - char *kwlist[] = {"raw", "buffer_size", NULL}; - Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE; + int return_value = -1; + static char *_keywords[] = {"raw", "buffer_size", NULL}; PyObject *raw; - - self->ok = 0; - self->detached = 0; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|n:BufferedReader", kwlist, - &raw, &buffer_size)) { - return -1; - } - - if (_PyIOBase_check_readable(raw, Py_True) == NULL) - return -1; - - Py_CLEAR(self->raw); - Py_INCREF(raw); - self->raw = raw; - self->buffer_size = buffer_size; - self->readable = 1; - self->writable = 0; - - if (_buffered_init(self) < 0) - return -1; - _bufferedreader_reset_buf(self); - - self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedReader_Type && - Py_TYPE(raw) == &PyFileIO_Type); - - self->ok = 1; - return 0; -} - -static Py_ssize_t -_bufferedreader_raw_read(buffered *self, char *start, Py_ssize_t len) -{ - Py_buffer buf; - PyObject *memobj, *res; - Py_ssize_t n; - /* NOTE: the buffer needn't be released as its object is NULL. */ - if (PyBuffer_FillInfo(&buf, NULL, start, len, 0, PyBUF_CONTIG) == -1) - return -1; - memobj = PyMemoryView_FromBuffer(&buf); - if (memobj == NULL) - return -1; - /* NOTE: PyErr_SetFromErrno() calls PyErr_CheckSignals() when EINTR - occurs so we needn't do it ourselves. - We then retry reading, ignoring the signal if no handler has - raised (see issue #10956). - */ - do { - res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_readinto, memobj, NULL); - } while (res == NULL && _PyIO_trap_eintr()); - Py_DECREF(memobj); - if (res == NULL) - return -1; - if (res == Py_None) { - /* Non-blocking stream would have blocked. Special return code! */ - Py_DECREF(res); - return -2; - } - n = PyNumber_AsSsize_t(res, PyExc_ValueError); - Py_DECREF(res); - if (n < 0 || n > len) { - PyErr_Format(PyExc_IOError, - "raw readinto() returned invalid length %zd " - "(should have been between 0 and %zd)", n, len); - return -1; - } - if (n > 0 && self->abs_pos != -1) - self->abs_pos += n; - return n; -} - -static Py_ssize_t -_bufferedreader_fill_buffer(buffered *self) -{ - Py_ssize_t start, len, n; - if (VALID_READ_BUFFER(self)) - start = Py_SAFE_DOWNCAST(self->read_end, Py_off_t, Py_ssize_t); - else - start = 0; - len = self->buffer_size - start; - n = _bufferedreader_raw_read(self, self->buffer + start, len); - if (n <= 0) - return n; - self->read_end = start + n; - self->raw_pos = start + n; - return n; -} - -static PyObject * -_bufferedreader_read_all(buffered *self) -{ - Py_ssize_t current_size; - PyObject *res = NULL, *data = NULL, *tmp = NULL, *chunks = NULL; - - /* First copy what we have in the current buffer. */ - current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t); - if (current_size) { - data = PyBytes_FromStringAndSize( - self->buffer + self->pos, current_size); - if (data == NULL) - return NULL; - self->pos += current_size; - } - /* We're going past the buffer's bounds, flush it */ - if (self->writable) { - tmp = buffered_flush_and_rewind_unlocked(self); - if (tmp == NULL) - goto cleanup; - Py_CLEAR(tmp); - } - _bufferedreader_reset_buf(self); - - if (PyObject_HasAttr(self->raw, _PyIO_str_readall)) { - tmp = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_readall, NULL); - if (tmp == NULL) - goto cleanup; - if (tmp != Py_None && !PyBytes_Check(tmp)) { - PyErr_SetString(PyExc_TypeError, "readall() should return bytes"); - goto cleanup; - } - if (tmp == Py_None) { - if (current_size == 0) { - res = Py_None; - goto cleanup; - } else { - res = data; - goto cleanup; - } - } - else if (current_size) { - PyBytes_Concat(&data, tmp); - res = data; - goto cleanup; - } - else { - res = tmp; - goto cleanup; - } - } - - chunks = PyList_New(0); - if (chunks == NULL) - goto cleanup; - - while (1) { - if (data) { - if (PyList_Append(chunks, data) < 0) - goto cleanup; - Py_CLEAR(data); - } - - /* Read until EOF or until read() would block. */ - data = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_read, NULL); - if (data == NULL) - goto cleanup; - if (data != Py_None && !PyBytes_Check(data)) { - PyErr_SetString(PyExc_TypeError, "read() should return bytes"); - goto cleanup; - } - if (data == Py_None || PyBytes_GET_SIZE(data) == 0) { - if (current_size == 0) { - res = data; - goto cleanup; - } - else { - tmp = _PyBytes_Join(_PyIO_empty_bytes, chunks); - res = tmp; - goto cleanup; - } - } - current_size += PyBytes_GET_SIZE(data); - if (self->abs_pos != -1) - self->abs_pos += PyBytes_GET_SIZE(data); - } -cleanup: - /* res is either NULL or a borrowed ref */ - Py_XINCREF(res); - Py_XDECREF(data); - Py_XDECREF(tmp); - Py_XDECREF(chunks); - return res; -} - -/* Read n bytes from the buffer if it can, otherwise return None. - This function is simple enough that it can run unlocked. */ -static PyObject * -_bufferedreader_read_fast(buffered *self, Py_ssize_t n) -{ - Py_ssize_t current_size; - - current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t); - if (n <= current_size) { - /* Fast path: the data to read is fully buffered. */ - PyObject *res = PyBytes_FromStringAndSize(self->buffer + self->pos, n); - if (res != NULL) - self->pos += n; - return res; - } - Py_RETURN_NONE; -} - -/* Generic read function: read from the stream until enough bytes are read, - * or until an EOF occurs or until read() would block. - */ -static PyObject * -_bufferedreader_read_generic(buffered *self, Py_ssize_t n) -{ - PyObject *res = NULL; - Py_ssize_t current_size, remaining, written; - char *out; - - current_size = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t); - if (n <= current_size) - return _bufferedreader_read_fast(self, n); - - res = PyBytes_FromStringAndSize(NULL, n); - if (res == NULL) - goto error; - out = PyBytes_AS_STRING(res); - remaining = n; - written = 0; - if (current_size > 0) { - memcpy(out, self->buffer + self->pos, current_size); - remaining -= current_size; - written += current_size; - self->pos += current_size; - } - /* Flush the write buffer if necessary */ - if (self->writable) { - PyObject *r = buffered_flush_and_rewind_unlocked(self); - if (r == NULL) - goto error; - Py_DECREF(r); - } - _bufferedreader_reset_buf(self); - while (remaining > 0) { - /* We want to read a whole block at the end into buffer. - If we had readv() we could do this in one pass. */ - Py_ssize_t r = MINUS_LAST_BLOCK(self, remaining); - if (r == 0) - break; - r = _bufferedreader_raw_read(self, out + written, r); - if (r == -1) - goto error; - if (r == 0 || r == -2) { - /* EOF occurred or read() would block. */ - if (r == 0 || written > 0) { - if (_PyBytes_Resize(&res, written)) - goto error; - return res; - } - Py_DECREF(res); - Py_INCREF(Py_None); - return Py_None; - } - remaining -= r; - written += r; - } - assert(remaining <= self->buffer_size); - self->pos = 0; - self->raw_pos = 0; - self->read_end = 0; - /* NOTE: when the read is satisfied, we avoid issuing any additional - reads, which could block indefinitely (e.g. on a socket). - See issue #9550. */ - while (remaining > 0 && self->read_end < self->buffer_size) { - Py_ssize_t r = _bufferedreader_fill_buffer(self); - if (r == -1) - goto error; - if (r == 0 || r == -2) { - /* EOF occurred or read() would block. */ - if (r == 0 || written > 0) { - if (_PyBytes_Resize(&res, written)) - goto error; - return res; - } - Py_DECREF(res); - Py_INCREF(Py_None); - return Py_None; - } - if (remaining > r) { - memcpy(out + written, self->buffer + self->pos, r); - written += r; - self->pos += r; - remaining -= r; - } - else if (remaining > 0) { - memcpy(out + written, self->buffer + self->pos, remaining); - written += remaining; - self->pos += remaining; - remaining = 0; - } - if (remaining == 0) - break; - } - - return res; - -error: - Py_XDECREF(res); - return NULL; -} - -static PyObject * -_bufferedreader_peek_unlocked(buffered *self) -{ - Py_ssize_t have, r; - - have = Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t); - /* Constraints: - 1. we don't want to advance the file position. - 2. we don't want to lose block alignment, so we can't shift the buffer - to make some place. - Therefore, we either return `have` bytes (if > 0), or a full buffer. - */ - if (have > 0) { - return PyBytes_FromStringAndSize(self->buffer + self->pos, have); - } - - /* Fill the buffer from the raw stream, and copy it to the result. */ - _bufferedreader_reset_buf(self); - r = _bufferedreader_fill_buffer(self); - if (r == -1) - return NULL; - if (r == -2) - r = 0; - self->pos = 0; - return PyBytes_FromStringAndSize(self->buffer, r); -} - -static PyMethodDef bufferedreader_methods[] = { - /* BufferedIOMixin methods */ - {"detach", (PyCFunction)buffered_detach, METH_NOARGS}, - {"flush", (PyCFunction)buffered_simple_flush, METH_NOARGS}, - {"close", (PyCFunction)buffered_close, METH_NOARGS}, - {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS}, - {"readable", (PyCFunction)buffered_readable, METH_NOARGS}, - {"writable", (PyCFunction)buffered_writable, METH_NOARGS}, - {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS}, - {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS}, - {"_dealloc_warn", (PyCFunction)buffered_dealloc_warn, METH_O}, - {"__getstate__", (PyCFunction)buffered_getstate, METH_NOARGS}, - - {"read", (PyCFunction)buffered_read, METH_VARARGS}, - {"peek", (PyCFunction)buffered_peek, METH_VARARGS}, - {"read1", (PyCFunction)buffered_read1, METH_VARARGS}, - {"readinto", (PyCFunction)buffered_readinto, METH_VARARGS}, - {"readinto1", (PyCFunction)buffered_readinto1, METH_VARARGS}, - {"readline", (PyCFunction)buffered_readline, METH_VARARGS}, - {"seek", (PyCFunction)buffered_seek, METH_VARARGS}, - {"tell", (PyCFunction)buffered_tell, METH_NOARGS}, - {"truncate", (PyCFunction)buffered_truncate, METH_VARARGS}, - {"__sizeof__", (PyCFunction)buffered_sizeof, METH_NOARGS}, - {NULL, NULL} -}; - -static PyMemberDef bufferedreader_members[] = { - {"raw", T_OBJECT, offsetof(buffered, raw), READONLY}, - {"_finalizing", T_BOOL, offsetof(buffered, finalizing), 0}, - {NULL} -}; - -static PyGetSetDef bufferedreader_getset[] = { - {"closed", (getter)buffered_closed_get, NULL, NULL}, - {"name", (getter)buffered_name_get, NULL, NULL}, - {"mode", (getter)buffered_mode_get, NULL, NULL}, - {NULL} -}; - - -PyTypeObject PyBufferedReader_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "_io.BufferedReader", /*tp_name*/ - sizeof(buffered), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - (destructor)buffered_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare */ - (reprfunc)buffered_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 | Py_TPFLAGS_BASETYPE - | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_FINALIZE, /*tp_flags*/ - bufferedreader_doc, /* tp_doc */ - (traverseproc)buffered_traverse, /* tp_traverse */ - (inquiry)buffered_clear, /* tp_clear */ - 0, /* tp_richcompare */ - offsetof(buffered, weakreflist), /*tp_weaklistoffset*/ - 0, /* tp_iter */ - (iternextfunc)buffered_iternext, /* tp_iternext */ - bufferedreader_methods, /* tp_methods */ - bufferedreader_members, /* tp_members */ - bufferedreader_getset, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - offsetof(buffered, dict), /* tp_dictoffset */ - (initproc)bufferedreader_init, /* tp_init */ - 0, /* tp_alloc */ - PyType_GenericNew, /* tp_new */ - 0, /* tp_free */ - 0, /* tp_is_gc */ - 0, /* tp_bases */ - 0, /* tp_mro */ - 0, /* tp_cache */ - 0, /* tp_subclasses */ - 0, /* tp_weaklist */ - 0, /* tp_del */ - 0, /* tp_version_tag */ - 0, /* tp_finalize */ -}; - - - -/* - * class BufferedWriter - */ -PyDoc_STRVAR(bufferedwriter_doc, - "A buffer for a writeable sequential RawIO object.\n" - "\n" - "The constructor creates a BufferedWriter for the given writeable raw\n" - "stream. If the buffer_size is not given, it defaults to\n" - "DEFAULT_BUFFER_SIZE.\n" - ); - -static void -_bufferedwriter_reset_buf(buffered *self) -{ - self->write_pos = 0; - self->write_end = -1; -} - -static int -bufferedwriter_init(buffered *self, PyObject *args, PyObject *kwds) -{ - char *kwlist[] = {"raw", "buffer_size", NULL}; - Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE; - PyObject *raw; - - self->ok = 0; - self->detached = 0; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|n:BufferedWriter", kwlist, - &raw, &buffer_size)) { - return -1; - } - - if (_PyIOBase_check_writable(raw, Py_True) == NULL) - return -1; - - Py_CLEAR(self->raw); - Py_INCREF(raw); - self->raw = raw; - self->readable = 0; - self->writable = 1; - - self->buffer_size = buffer_size; - if (_buffered_init(self) < 0) - return -1; - _bufferedwriter_reset_buf(self); - self->pos = 0; - - self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedWriter_Type && - Py_TYPE(raw) == &PyFileIO_Type); - - self->ok = 1; - return 0; -} - -static Py_ssize_t -_bufferedwriter_raw_write(buffered *self, char *start, Py_ssize_t len) -{ - Py_buffer buf; - PyObject *memobj, *res; - Py_ssize_t n; - int errnum; - /* NOTE: the buffer needn't be released as its object is NULL. */ - if (PyBuffer_FillInfo(&buf, NULL, start, len, 1, PyBUF_CONTIG_RO) == -1) - return -1; - memobj = PyMemoryView_FromBuffer(&buf); - if (memobj == NULL) - return -1; - /* NOTE: PyErr_SetFromErrno() calls PyErr_CheckSignals() when EINTR - occurs so we needn't do it ourselves. - We then retry writing, ignoring the signal if no handler has - raised (see issue #10956). - */ - do { - errno = 0; - res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_write, memobj, NULL); - errnum = errno; - } while (res == NULL && _PyIO_trap_eintr()); - Py_DECREF(memobj); - if (res == NULL) - return -1; - if (res == Py_None) { - /* Non-blocking stream would have blocked. Special return code! - Being paranoid we reset errno in case it is changed by code - triggered by a decref. errno is used by _set_BlockingIOError(). */ - Py_DECREF(res); - errno = errnum; - return -2; - } - n = PyNumber_AsSsize_t(res, PyExc_ValueError); - Py_DECREF(res); - if (n < 0 || n > len) { - PyErr_Format(PyExc_IOError, - "raw write() returned invalid length %zd " - "(should have been between 0 and %zd)", n, len); - return -1; - } - if (n > 0 && self->abs_pos != -1) - self->abs_pos += n; - return n; -} - -/* `restore_pos` is 1 if we need to restore the raw stream position at - the end, 0 otherwise. */ -static PyObject * -_bufferedwriter_flush_unlocked(buffered *self) -{ - Py_ssize_t written = 0; - Py_off_t n, rewind; - - if (!VALID_WRITE_BUFFER(self) || self->write_pos == self->write_end) - goto end; - /* First, rewind */ - rewind = RAW_OFFSET(self) + (self->pos - self->write_pos); - if (rewind != 0) { - n = _buffered_raw_seek(self, -rewind, 1); - if (n < 0) { - goto error; - } - self->raw_pos -= rewind; - } - while (self->write_pos < self->write_end) { - n = _bufferedwriter_raw_write(self, - self->buffer + self->write_pos, - Py_SAFE_DOWNCAST(self->write_end - self->write_pos, - Py_off_t, Py_ssize_t)); - if (n == -1) { - goto error; - } - else if (n == -2) { - _set_BlockingIOError("write could not complete without blocking", - 0); - goto error; - } - self->write_pos += n; - self->raw_pos = self->write_pos; - written += Py_SAFE_DOWNCAST(n, Py_off_t, Py_ssize_t); - /* Partial writes can return successfully when interrupted by a - signal (see write(2)). We must run signal handlers before - blocking another time, possibly indefinitely. */ - if (PyErr_CheckSignals() < 0) - goto error; - } - - _bufferedwriter_reset_buf(self); - -end: - Py_RETURN_NONE; - -error: - return NULL; -} - -static PyObject * -bufferedwriter_write(buffered *self, PyObject *args) -{ - PyObject *res = NULL; - Py_buffer buf; - Py_ssize_t written, avail, remaining; - Py_off_t offset; - - CHECK_INITIALIZED(self) - if (!PyArg_ParseTuple(args, "y*:write", &buf)) { - return NULL; - } - - if (IS_CLOSED(self)) { - PyErr_SetString(PyExc_ValueError, "write to closed file"); - PyBuffer_Release(&buf); - return NULL; - } - - if (!ENTER_BUFFERED(self)) { - PyBuffer_Release(&buf); - return NULL; - } - - /* Fast path: the data to write can be fully buffered. */ - if (!VALID_READ_BUFFER(self) && !VALID_WRITE_BUFFER(self)) { - self->pos = 0; - self->raw_pos = 0; - } - avail = Py_SAFE_DOWNCAST(self->buffer_size - self->pos, Py_off_t, Py_ssize_t); - if (buf.len <= avail) { - memcpy(self->buffer + self->pos, buf.buf, buf.len); - if (!VALID_WRITE_BUFFER(self) || self->write_pos > self->pos) { - self->write_pos = self->pos; - } - ADJUST_POSITION(self, self->pos + buf.len); - if (self->pos > self->write_end) - self->write_end = self->pos; - written = buf.len; - goto end; - } - - /* First write the current buffer */ - res = _bufferedwriter_flush_unlocked(self); - if (res == NULL) { - Py_ssize_t *w = _buffered_check_blocking_error(); - if (w == NULL) - goto error; - if (self->readable) - _bufferedreader_reset_buf(self); - /* Make some place by shifting the buffer. */ - assert(VALID_WRITE_BUFFER(self)); - memmove(self->buffer, self->buffer + self->write_pos, - Py_SAFE_DOWNCAST(self->write_end - self->write_pos, - Py_off_t, Py_ssize_t)); - self->write_end -= self->write_pos; - self->raw_pos -= self->write_pos; - self->pos -= self->write_pos; - self->write_pos = 0; - avail = Py_SAFE_DOWNCAST(self->buffer_size - self->write_end, - Py_off_t, Py_ssize_t); - if (buf.len <= avail) { - /* Everything can be buffered */ - PyErr_Clear(); - memcpy(self->buffer + self->write_end, buf.buf, buf.len); - self->write_end += buf.len; - self->pos += buf.len; - written = buf.len; - goto end; - } - /* Buffer as much as possible. */ - memcpy(self->buffer + self->write_end, buf.buf, avail); - self->write_end += avail; - self->pos += avail; - /* XXX Modifying the existing exception e using the pointer w - will change e.characters_written but not e.args[2]. - Therefore we just replace with a new error. */ - _set_BlockingIOError("write could not complete without blocking", - avail); - goto error; - } - Py_CLEAR(res); - - /* Adjust the raw stream position if it is away from the logical stream - position. This happens if the read buffer has been filled but not - modified (and therefore _bufferedwriter_flush_unlocked() didn't rewind - the raw stream by itself). - Fixes issue #6629. - */ - offset = RAW_OFFSET(self); - if (offset != 0) { - if (_buffered_raw_seek(self, -offset, 1) < 0) - goto error; - self->raw_pos -= offset; - } - - /* Then write buf itself. At this point the buffer has been emptied. */ - remaining = buf.len; - written = 0; - while (remaining > self->buffer_size) { - Py_ssize_t n = _bufferedwriter_raw_write( - self, (char *) buf.buf + written, buf.len - written); - if (n == -1) { - goto error; - } else if (n == -2) { - /* Write failed because raw file is non-blocking */ - if (remaining > self->buffer_size) { - /* Can't buffer everything, still buffer as much as possible */ - memcpy(self->buffer, - (char *) buf.buf + written, self->buffer_size); - self->raw_pos = 0; - ADJUST_POSITION(self, self->buffer_size); - self->write_end = self->buffer_size; - written += self->buffer_size; - _set_BlockingIOError("write could not complete without " - "blocking", written); - goto error; - } - PyErr_Clear(); - break; - } - written += n; - remaining -= n; - /* Partial writes can return successfully when interrupted by a - signal (see write(2)). We must run signal handlers before - blocking another time, possibly indefinitely. */ - if (PyErr_CheckSignals() < 0) - goto error; - } - if (self->readable) - _bufferedreader_reset_buf(self); - if (remaining > 0) { - memcpy(self->buffer, (char *) buf.buf + written, remaining); - written += remaining; - } - self->write_pos = 0; - /* TODO: sanity check (remaining >= 0) */ - self->write_end = remaining; - ADJUST_POSITION(self, remaining); - self->raw_pos = 0; - -end: - res = PyLong_FromSsize_t(written); - -error: - LEAVE_BUFFERED(self) - PyBuffer_Release(&buf); - return res; -} - -static PyMethodDef bufferedwriter_methods[] = { - /* BufferedIOMixin methods */ - {"close", (PyCFunction)buffered_close, METH_NOARGS}, - {"detach", (PyCFunction)buffered_detach, METH_NOARGS}, - {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS}, - {"readable", (PyCFunction)buffered_readable, METH_NOARGS}, - {"writable", (PyCFunction)buffered_writable, METH_NOARGS}, - {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS}, - {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS}, - {"_dealloc_warn", (PyCFunction)buffered_dealloc_warn, METH_O}, - {"__getstate__", (PyCFunction)buffered_getstate, METH_NOARGS}, - - {"write", (PyCFunction)bufferedwriter_write, METH_VARARGS}, - {"truncate", (PyCFunction)buffered_truncate, METH_VARARGS}, - {"flush", (PyCFunction)buffered_flush, METH_NOARGS}, - {"seek", (PyCFunction)buffered_seek, METH_VARARGS}, - {"tell", (PyCFunction)buffered_tell, METH_NOARGS}, - {"__sizeof__", (PyCFunction)buffered_sizeof, METH_NOARGS}, - {NULL, NULL} -}; - -static PyMemberDef bufferedwriter_members[] = { - {"raw", T_OBJECT, offsetof(buffered, raw), READONLY}, - {"_finalizing", T_BOOL, offsetof(buffered, finalizing), 0}, - {NULL} -}; - -static PyGetSetDef bufferedwriter_getset[] = { - {"closed", (getter)buffered_closed_get, NULL, NULL}, - {"name", (getter)buffered_name_get, NULL, NULL}, - {"mode", (getter)buffered_mode_get, NULL, NULL}, - {NULL} -}; - - -PyTypeObject PyBufferedWriter_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "_io.BufferedWriter", /*tp_name*/ - sizeof(buffered), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - (destructor)buffered_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare */ - (reprfunc)buffered_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 | Py_TPFLAGS_BASETYPE - | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_FINALIZE, /*tp_flags*/ - bufferedwriter_doc, /* tp_doc */ - (traverseproc)buffered_traverse, /* tp_traverse */ - (inquiry)buffered_clear, /* tp_clear */ - 0, /* tp_richcompare */ - offsetof(buffered, weakreflist), /*tp_weaklistoffset*/ - 0, /* tp_iter */ - 0, /* tp_iternext */ - bufferedwriter_methods, /* tp_methods */ - bufferedwriter_members, /* tp_members */ - bufferedwriter_getset, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - offsetof(buffered, dict), /* tp_dictoffset */ - (initproc)bufferedwriter_init, /* tp_init */ - 0, /* tp_alloc */ - PyType_GenericNew, /* tp_new */ - 0, /* tp_free */ - 0, /* tp_is_gc */ - 0, /* tp_bases */ - 0, /* tp_mro */ - 0, /* tp_cache */ - 0, /* tp_subclasses */ - 0, /* tp_weaklist */ - 0, /* tp_del */ - 0, /* tp_version_tag */ - 0, /* tp_finalize */ -}; - - - -/* - * BufferedRWPair - */ - -PyDoc_STRVAR(bufferedrwpair_doc, - "A buffered reader and writer object together.\n" - "\n" - "A buffered reader object and buffered writer object put together to\n" - "form a sequential IO object that can read and write. This is typically\n" - "used with a socket or two-way pipe.\n" - "\n" - "reader and writer are RawIOBase objects that are readable and\n" - "writeable respectively. If the buffer_size is omitted it defaults to\n" - "DEFAULT_BUFFER_SIZE.\n" - ); - -/* XXX The usefulness of this (compared to having two separate IO objects) is - * questionable. - */ - -typedef struct { - PyObject_HEAD - buffered *reader; - buffered *writer; - PyObject *dict; - PyObject *weakreflist; -} rwpair; - -static int -bufferedrwpair_init(rwpair *self, PyObject *args, PyObject *kwds) -{ - PyObject *reader, *writer; Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE; - if (!PyArg_ParseTuple(args, "OO|n:BufferedRWPair", &reader, &writer, - &buffer_size)) { - return -1; - } + if (!PyArg_ParseTupleAndKeywords(args, kwargs, + "O|n:BufferedRandom", _keywords, + &raw, &buffer_size)) + goto exit; + return_value = _io_BufferedRandom___init___impl((buffered *)self, raw, buffer_size); - if (_PyIOBase_check_readable(reader, Py_True) == NULL) - return -1; - if (_PyIOBase_check_writable(writer, Py_True) == NULL) - return -1; - - self->reader = (buffered *) PyObject_CallFunction( - (PyObject *) &PyBufferedReader_Type, "On", reader, buffer_size); - if (self->reader == NULL) - return -1; - - self->writer = (buffered *) PyObject_CallFunction( - (PyObject *) &PyBufferedWriter_Type, "On", writer, buffer_size); - if (self->writer == NULL) { - Py_CLEAR(self->reader); - return -1; - } - - return 0; +exit: + return return_value; } - -static int -bufferedrwpair_traverse(rwpair *self, visitproc visit, void *arg) -{ - Py_VISIT(self->dict); - return 0; -} - -static int -bufferedrwpair_clear(rwpair *self) -{ - Py_CLEAR(self->reader); - Py_CLEAR(self->writer); - Py_CLEAR(self->dict); - return 0; -} - -static void -bufferedrwpair_dealloc(rwpair *self) -{ - _PyObject_GC_UNTRACK(self); - if (self->weakreflist != NULL) - PyObject_ClearWeakRefs((PyObject *)self); - Py_CLEAR(self->reader); - Py_CLEAR(self->writer); - Py_CLEAR(self->dict); - Py_TYPE(self)->tp_free((PyObject *) self); -} - -static PyObject * -_forward_call(buffered *self, _Py_Identifier *name, PyObject *args) -{ - PyObject *func, *ret; - if (self == NULL) { - PyErr_SetString(PyExc_ValueError, - "I/O operation on uninitialized object"); - return NULL; - } - - func = _PyObject_GetAttrId((PyObject *)self, name); - if (func == NULL) { - PyErr_SetString(PyExc_AttributeError, name->string); - return NULL; - } - - ret = PyObject_CallObject(func, args); - Py_DECREF(func); - return ret; -} - -static PyObject * -bufferedrwpair_read(rwpair *self, PyObject *args) -{ - return _forward_call(self->reader, &PyId_read, args); -} - -static PyObject * -bufferedrwpair_peek(rwpair *self, PyObject *args) -{ - return _forward_call(self->reader, &PyId_peek, args); -} - -static PyObject * -bufferedrwpair_read1(rwpair *self, PyObject *args) -{ - return _forward_call(self->reader, &PyId_read1, args); -} - -static PyObject * -bufferedrwpair_readinto(rwpair *self, PyObject *args) -{ - return _forward_call(self->reader, &PyId_readinto, args); -} - -static PyObject * -bufferedrwpair_readinto1(rwpair *self, PyObject *args) -{ - return _forward_call(self->reader, &PyId_readinto1, args); -} - -static PyObject * -bufferedrwpair_write(rwpair *self, PyObject *args) -{ - return _forward_call(self->writer, &PyId_write, args); -} - -static PyObject * -bufferedrwpair_flush(rwpair *self, PyObject *args) -{ - return _forward_call(self->writer, &PyId_flush, args); -} - -static PyObject * -bufferedrwpair_readable(rwpair *self, PyObject *args) -{ - return _forward_call(self->reader, &PyId_readable, args); -} - -static PyObject * -bufferedrwpair_writable(rwpair *self, PyObject *args) -{ - return _forward_call(self->writer, &PyId_writable, args); -} - -static PyObject * -bufferedrwpair_close(rwpair *self, PyObject *args) -{ - PyObject *exc = NULL, *val, *tb; - PyObject *ret = _forward_call(self->writer, &PyId_close, args); - if (ret == NULL) - PyErr_Fetch(&exc, &val, &tb); - else - Py_DECREF(ret); - ret = _forward_call(self->reader, &PyId_close, args); - if (exc != NULL) { - _PyErr_ChainExceptions(exc, val, tb); - Py_CLEAR(ret); - } - return ret; -} - -static PyObject * -bufferedrwpair_isatty(rwpair *self, PyObject *args) -{ - PyObject *ret = _forward_call(self->writer, &PyId_isatty, args); - - if (ret != Py_False) { - /* either True or exception */ - return ret; - } - Py_DECREF(ret); - - return _forward_call(self->reader, &PyId_isatty, args); -} - -static PyObject * -bufferedrwpair_closed_get(rwpair *self, void *context) -{ - if (self->writer == NULL) { - PyErr_SetString(PyExc_RuntimeError, - "the BufferedRWPair object is being garbage-collected"); - return NULL; - } - return PyObject_GetAttr((PyObject *) self->writer, _PyIO_str_closed); -} - -static PyMethodDef bufferedrwpair_methods[] = { - {"read", (PyCFunction)bufferedrwpair_read, METH_VARARGS}, - {"peek", (PyCFunction)bufferedrwpair_peek, METH_VARARGS}, - {"read1", (PyCFunction)bufferedrwpair_read1, METH_VARARGS}, - {"readinto", (PyCFunction)bufferedrwpair_readinto, METH_VARARGS}, - {"readinto1", (PyCFunction)bufferedrwpair_readinto1, METH_VARARGS}, - - {"write", (PyCFunction)bufferedrwpair_write, METH_VARARGS}, - {"flush", (PyCFunction)bufferedrwpair_flush, METH_NOARGS}, - - {"readable", (PyCFunction)bufferedrwpair_readable, METH_NOARGS}, - {"writable", (PyCFunction)bufferedrwpair_writable, METH_NOARGS}, - - {"close", (PyCFunction)bufferedrwpair_close, METH_NOARGS}, - {"isatty", (PyCFunction)bufferedrwpair_isatty, METH_NOARGS}, - - {"__getstate__", (PyCFunction)buffered_getstate, METH_NOARGS}, - - {NULL, NULL} -}; - -static PyGetSetDef bufferedrwpair_getset[] = { - {"closed", (getter)bufferedrwpair_closed_get, NULL, NULL}, - {NULL} -}; - -PyTypeObject PyBufferedRWPair_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "_io.BufferedRWPair", /*tp_name*/ - sizeof(rwpair), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - (destructor)bufferedrwpair_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare */ - 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 | Py_TPFLAGS_BASETYPE - | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_FINALIZE, /* tp_flags */ - bufferedrwpair_doc, /* tp_doc */ - (traverseproc)bufferedrwpair_traverse, /* tp_traverse */ - (inquiry)bufferedrwpair_clear, /* tp_clear */ - 0, /* tp_richcompare */ - offsetof(rwpair, weakreflist), /*tp_weaklistoffset*/ - 0, /* tp_iter */ - 0, /* tp_iternext */ - bufferedrwpair_methods, /* tp_methods */ - 0, /* tp_members */ - bufferedrwpair_getset, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - offsetof(rwpair, dict), /* tp_dictoffset */ - (initproc)bufferedrwpair_init, /* tp_init */ - 0, /* tp_alloc */ - PyType_GenericNew, /* tp_new */ - 0, /* tp_free */ - 0, /* tp_is_gc */ - 0, /* tp_bases */ - 0, /* tp_mro */ - 0, /* tp_cache */ - 0, /* tp_subclasses */ - 0, /* tp_weaklist */ - 0, /* tp_del */ - 0, /* tp_version_tag */ - 0, /* tp_finalize */ -}; - - - -/* - * BufferedRandom - */ - -PyDoc_STRVAR(bufferedrandom_doc, - "A buffered interface to random access streams.\n" - "\n" - "The constructor creates a reader and writer for a seekable stream,\n" - "raw, given in the first argument. If the buffer_size is omitted it\n" - "defaults to DEFAULT_BUFFER_SIZE.\n" - ); - -static int -bufferedrandom_init(buffered *self, PyObject *args, PyObject *kwds) -{ - char *kwlist[] = {"raw", "buffer_size", NULL}; - Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE; - PyObject *raw; - - self->ok = 0; - self->detached = 0; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|n:BufferedRandom", kwlist, - &raw, &buffer_size)) { - return -1; - } - - if (_PyIOBase_check_seekable(raw, Py_True) == NULL) - return -1; - if (_PyIOBase_check_readable(raw, Py_True) == NULL) - return -1; - if (_PyIOBase_check_writable(raw, Py_True) == NULL) - return -1; - - Py_CLEAR(self->raw); - Py_INCREF(raw); - self->raw = raw; - self->buffer_size = buffer_size; - self->readable = 1; - self->writable = 1; - - if (_buffered_init(self) < 0) - return -1; - _bufferedreader_reset_buf(self); - _bufferedwriter_reset_buf(self); - self->pos = 0; - - self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedRandom_Type && - Py_TYPE(raw) == &PyFileIO_Type); - - self->ok = 1; - return 0; -} - -static PyMethodDef bufferedrandom_methods[] = { - /* BufferedIOMixin methods */ - {"close", (PyCFunction)buffered_close, METH_NOARGS}, - {"detach", (PyCFunction)buffered_detach, METH_NOARGS}, - {"seekable", (PyCFunction)buffered_seekable, METH_NOARGS}, - {"readable", (PyCFunction)buffered_readable, METH_NOARGS}, - {"writable", (PyCFunction)buffered_writable, METH_NOARGS}, - {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS}, - {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS}, - {"_dealloc_warn", (PyCFunction)buffered_dealloc_warn, METH_O}, - {"__getstate__", (PyCFunction)buffered_getstate, METH_NOARGS}, - - {"flush", (PyCFunction)buffered_flush, METH_NOARGS}, - - {"seek", (PyCFunction)buffered_seek, METH_VARARGS}, - {"tell", (PyCFunction)buffered_tell, METH_NOARGS}, - {"truncate", (PyCFunction)buffered_truncate, METH_VARARGS}, - {"read", (PyCFunction)buffered_read, METH_VARARGS}, - {"read1", (PyCFunction)buffered_read1, METH_VARARGS}, - {"readinto", (PyCFunction)buffered_readinto, METH_VARARGS}, - {"readinto1", (PyCFunction)buffered_readinto1, METH_VARARGS}, - {"readline", (PyCFunction)buffered_readline, METH_VARARGS}, - {"peek", (PyCFunction)buffered_peek, METH_VARARGS}, - {"write", (PyCFunction)bufferedwriter_write, METH_VARARGS}, - {"__sizeof__", (PyCFunction)buffered_sizeof, METH_NOARGS}, - {NULL, NULL} -}; - -static PyMemberDef bufferedrandom_members[] = { - {"raw", T_OBJECT, offsetof(buffered, raw), READONLY}, - {"_finalizing", T_BOOL, offsetof(buffered, finalizing), 0}, - {NULL} -}; - -static PyGetSetDef bufferedrandom_getset[] = { - {"closed", (getter)buffered_closed_get, NULL, NULL}, - {"name", (getter)buffered_name_get, NULL, NULL}, - {"mode", (getter)buffered_mode_get, NULL, NULL}, - {NULL} -}; - - -PyTypeObject PyBufferedRandom_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "_io.BufferedRandom", /*tp_name*/ - sizeof(buffered), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - (destructor)buffered_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare */ - (reprfunc)buffered_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 | Py_TPFLAGS_BASETYPE - | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_FINALIZE, /*tp_flags*/ - bufferedrandom_doc, /* tp_doc */ - (traverseproc)buffered_traverse, /* tp_traverse */ - (inquiry)buffered_clear, /* tp_clear */ - 0, /* tp_richcompare */ - offsetof(buffered, weakreflist), /*tp_weaklistoffset*/ - 0, /* tp_iter */ - (iternextfunc)buffered_iternext, /* tp_iternext */ - bufferedrandom_methods, /* tp_methods */ - bufferedrandom_members, /* tp_members */ - bufferedrandom_getset, /* tp_getset */ - 0, /* tp_base */ - 0, /*tp_dict*/ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - offsetof(buffered, dict), /*tp_dictoffset*/ - (initproc)bufferedrandom_init, /* tp_init */ - 0, /* tp_alloc */ - PyType_GenericNew, /* tp_new */ - 0, /* tp_free */ - 0, /* tp_is_gc */ - 0, /* tp_bases */ - 0, /* tp_mro */ - 0, /* tp_cache */ - 0, /* tp_subclasses */ - 0, /* tp_weaklist */ - 0, /* tp_del */ - 0, /* tp_version_tag */ - 0, /* tp_finalize */ -}; +/*[clinic end generated code: output=78808e39f36e3fa9 input=a9049054013a1b77]*/ diff --git a/Modules/_io/bytesio.c b/Modules/_io/clinic/bytesio.c.h copy from Modules/_io/bytesio.c copy to Modules/_io/clinic/bytesio.c.h --- a/Modules/_io/bytesio.c +++ b/Modules/_io/clinic/bytesio.c.h @@ -1,593 +1,331 @@ -#include "Python.h" -#include "structmember.h" /* for offsetof() */ -#include "_iomodule.h" +/*[clinic input] +preserve +[clinic start generated code]*/ -typedef struct { - PyObject_HEAD - PyObject *buf; - Py_ssize_t pos; - Py_ssize_t string_size; - PyObject *dict; - PyObject *weakreflist; - Py_ssize_t exports; -} bytesio; +PyDoc_STRVAR(_io_BytesIO_readable__doc__, +"readable($self, /)\n" +"--\n" +"\n" +"Returns True if the IO object can be read."); -typedef struct { - PyObject_HEAD - bytesio *source; -} bytesiobuf; +#define _IO_BYTESIO_READABLE_METHODDEF \ + {"readable", (PyCFunction)_io_BytesIO_readable, METH_NOARGS, _io_BytesIO_readable__doc__}, -/* The bytesio object can be in three states: - * Py_REFCNT(buf) == 1, exports == 0. - * Py_REFCNT(buf) > 1. exports == 0, - first modification or export causes the internal buffer copying. - * exports > 0. Py_REFCNT(buf) == 1, any modifications are forbidden. -*/ +static PyObject * +_io_BytesIO_readable_impl(bytesio *self); -#define CHECK_CLOSED(self) \ - if ((self)->buf == NULL) { \ - PyErr_SetString(PyExc_ValueError, \ - "I/O operation on closed file."); \ - return NULL; \ - } - -#define CHECK_EXPORTS(self) \ - if ((self)->exports > 0) { \ - PyErr_SetString(PyExc_BufferError, \ - "Existing exports of data: object cannot be re-sized"); \ - return NULL; \ - } - -#define SHARED_BUF(self) (Py_REFCNT((self)->buf) > 1) - - -/* Internal routine to get a line from the buffer of a BytesIO - object. Returns the length between the current position to the - next newline character. */ -static Py_ssize_t -scan_eol(bytesio *self, Py_ssize_t len) +static PyObject * +_io_BytesIO_readable(bytesio *self, PyObject *Py_UNUSED(ignored)) { - const char *start, *n; - Py_ssize_t maxlen; - - assert(self->buf != NULL); - - /* Move to the end of the line, up to the end of the string, s. */ - start = PyBytes_AS_STRING(self->buf) + self->pos; - maxlen = self->string_size - self->pos; - if (len < 0 || len > maxlen) - len = maxlen; - - if (len) { - n = memchr(start, '\n', len); - if (n) - /* Get the length from the current position to the end of - the line. */ - len = n - start + 1; - } - assert(len >= 0); - assert(self->pos < PY_SSIZE_T_MAX - len); - - return len; + return _io_BytesIO_readable_impl(self); } -/* Internal routine for detaching the shared buffer of BytesIO objects. - The caller should ensure that the 'size' argument is non-negative and - not lesser than self->string_size. Returns 0 on success, -1 otherwise. */ -static int -unshare_buffer(bytesio *self, size_t size) +PyDoc_STRVAR(_io_BytesIO_writable__doc__, +"writable($self, /)\n" +"--\n" +"\n" +"Returns True if the IO object can be written."); + +#define _IO_BYTESIO_WRITABLE_METHODDEF \ + {"writable", (PyCFunction)_io_BytesIO_writable, METH_NOARGS, _io_BytesIO_writable__doc__}, + +static PyObject * +_io_BytesIO_writable_impl(bytesio *self); + +static PyObject * +_io_BytesIO_writable(bytesio *self, PyObject *Py_UNUSED(ignored)) { - PyObject *new_buf, *old_buf; - assert(SHARED_BUF(self)); - assert(self->exports == 0); - assert(size >= (size_t)self->string_size); - new_buf = PyBytes_FromStringAndSize(NULL, size); - if (new_buf == NULL) - return -1; - memcpy(PyBytes_AS_STRING(new_buf), PyBytes_AS_STRING(self->buf), - self->string_size); - old_buf = self->buf; - self->buf = new_buf; - Py_DECREF(old_buf); - return 0; + return _io_BytesIO_writable_impl(self); } -/* Internal routine for changing the size of the buffer of BytesIO objects. - The caller should ensure that the 'size' argument is non-negative. Returns - 0 on success, -1 otherwise. */ -static int -resize_buffer(bytesio *self, size_t size) +PyDoc_STRVAR(_io_BytesIO_seekable__doc__, +"seekable($self, /)\n" +"--\n" +"\n" +"Returns True if the IO object can be seeked."); + +#define _IO_BYTESIO_SEEKABLE_METHODDEF \ + {"seekable", (PyCFunction)_io_BytesIO_seekable, METH_NOARGS, _io_BytesIO_seekable__doc__}, + +static PyObject * +_io_BytesIO_seekable_impl(bytesio *self); + +static PyObject * +_io_BytesIO_seekable(bytesio *self, PyObject *Py_UNUSED(ignored)) { - /* Here, unsigned types are used to avoid dealing with signed integer - overflow, which is undefined in C. */ - size_t alloc = PyBytes_GET_SIZE(self->buf); - - assert(self->buf != NULL); - - /* For simplicity, stay in the range of the signed type. Anyway, Python - doesn't allow strings to be longer than this. */ - if (size > PY_SSIZE_T_MAX) - goto overflow; - - if (size < alloc / 2) { - /* Major downsize; resize down to exact size. */ - alloc = size + 1; - } - else if (size < alloc) { - /* Within allocated size; quick exit */ - return 0; - } - else if (size <= alloc * 1.125) { - /* Moderate upsize; overallocate similar to list_resize() */ - alloc = size + (size >> 3) + (size < 9 ? 3 : 6); - } - else { - /* Major upsize; resize up to exact size */ - alloc = size + 1; - } - - if (alloc > ((size_t)-1) / sizeof(char)) - goto overflow; - - if (SHARED_BUF(self)) { - if (unshare_buffer(self, alloc) < 0) - return -1; - } - else { - if (_PyBytes_Resize(&self->buf, alloc) < 0) - return -1; - } - - return 0; - - overflow: - PyErr_SetString(PyExc_OverflowError, - "new buffer size too large"); - return -1; + return _io_BytesIO_seekable_impl(self); } -/* Internal routine for writing a string of bytes to the buffer of a BytesIO - object. Returns the number of bytes written, or -1 on error. */ -static Py_ssize_t -write_bytes(bytesio *self, const char *bytes, Py_ssize_t len) +PyDoc_STRVAR(_io_BytesIO_flush__doc__, +"flush($self, /)\n" +"--\n" +"\n" +"Does nothing."); + +#define _IO_BYTESIO_FLUSH_METHODDEF \ + {"flush", (PyCFunction)_io_BytesIO_flush, METH_NOARGS, _io_BytesIO_flush__doc__}, + +static PyObject * +_io_BytesIO_flush_impl(bytesio *self); + +static PyObject * +_io_BytesIO_flush(bytesio *self, PyObject *Py_UNUSED(ignored)) { - size_t endpos; - assert(self->buf != NULL); - assert(self->pos >= 0); - assert(len >= 0); - - endpos = (size_t)self->pos + len; - if (endpos > (size_t)PyBytes_GET_SIZE(self->buf)) { - if (resize_buffer(self, endpos) < 0) - return -1; - } - else if (SHARED_BUF(self)) { - if (unshare_buffer(self, Py_MAX(endpos, (size_t)self->string_size)) < 0) - return -1; - } - - if (self->pos > self->string_size) { - /* In case of overseek, pad with null bytes the buffer region between - the end of stream and the current position. - - 0 lo string_size hi - | |<---used--->|<----------available----------->| - | | <--to pad-->|<---to write---> | - 0 buf position - */ - memset(PyBytes_AS_STRING(self->buf) + self->string_size, '\0', - (self->pos - self->string_size) * sizeof(char)); - } - - /* Copy the data to the internal buffer, overwriting some of the existing - data if self->pos < self->string_size. */ - memcpy(PyBytes_AS_STRING(self->buf) + self->pos, bytes, len); - self->pos = endpos; - - /* Set the new length of the internal string if it has changed. */ - if ((size_t)self->string_size < endpos) { - self->string_size = endpos; - } - - return len; + return _io_BytesIO_flush_impl(self); } -static PyObject * -bytesio_get_closed(bytesio *self) -{ - if (self->buf == NULL) { - Py_RETURN_TRUE; - } - else { - Py_RETURN_FALSE; - } -} - -PyDoc_STRVAR(readable_doc, -"readable() -> bool. Returns True if the IO object can be read."); - -PyDoc_STRVAR(writable_doc, -"writable() -> bool. Returns True if the IO object can be written."); - -PyDoc_STRVAR(seekable_doc, -"seekable() -> bool. Returns True if the IO object can be seeked."); - -/* Generic getter for the writable, readable and seekable properties */ -static PyObject * -return_not_closed(bytesio *self) -{ - CHECK_CLOSED(self); - Py_RETURN_TRUE; -} - -PyDoc_STRVAR(flush_doc, -"flush() -> None. Does nothing."); - -static PyObject * -bytesio_flush(bytesio *self) -{ - CHECK_CLOSED(self); - Py_RETURN_NONE; -} - -PyDoc_STRVAR(getbuffer_doc, -"getbuffer() -> bytes.\n" +PyDoc_STRVAR(_io_BytesIO_getbuffer__doc__, +"getbuffer($self, /)\n" +"--\n" "\n" "Get a read-write view over the contents of the BytesIO object."); +#define _IO_BYTESIO_GETBUFFER_METHODDEF \ + {"getbuffer", (PyCFunction)_io_BytesIO_getbuffer, METH_NOARGS, _io_BytesIO_getbuffer__doc__}, + static PyObject * -bytesio_getbuffer(bytesio *self) +_io_BytesIO_getbuffer_impl(bytesio *self); + +static PyObject * +_io_BytesIO_getbuffer(bytesio *self, PyObject *Py_UNUSED(ignored)) { - PyTypeObject *type = &_PyBytesIOBuffer_Type; - bytesiobuf *buf; - PyObject *view; - - CHECK_CLOSED(self); - - buf = (bytesiobuf *) type->tp_alloc(type, 0); - if (buf == NULL) - return NULL; - Py_INCREF(self); - buf->source = self; - view = PyMemoryView_FromObject((PyObject *) buf); - Py_DECREF(buf); - return view; + return _io_BytesIO_getbuffer_impl(self); } -PyDoc_STRVAR(getval_doc, -"getvalue() -> bytes.\n" +PyDoc_STRVAR(_io_BytesIO_getvalue__doc__, +"getvalue($self, /)\n" +"--\n" "\n" "Retrieve the entire contents of the BytesIO object."); +#define _IO_BYTESIO_GETVALUE_METHODDEF \ + {"getvalue", (PyCFunction)_io_BytesIO_getvalue, METH_NOARGS, _io_BytesIO_getvalue__doc__}, + static PyObject * -bytesio_getvalue(bytesio *self) +_io_BytesIO_getvalue_impl(bytesio *self); + +static PyObject * +_io_BytesIO_getvalue(bytesio *self, PyObject *Py_UNUSED(ignored)) { - CHECK_CLOSED(self); - if (self->string_size <= 1 || self->exports > 0) - return PyBytes_FromStringAndSize(PyBytes_AS_STRING(self->buf), - self->string_size); - - if (self->string_size != PyBytes_GET_SIZE(self->buf)) { - if (SHARED_BUF(self)) { - if (unshare_buffer(self, self->string_size) < 0) - return NULL; - } - else { - if (_PyBytes_Resize(&self->buf, self->string_size) < 0) - return NULL; - } - } - Py_INCREF(self->buf); - return self->buf; + return _io_BytesIO_getvalue_impl(self); } -PyDoc_STRVAR(isatty_doc, -"isatty() -> False.\n" +PyDoc_STRVAR(_io_BytesIO_isatty__doc__, +"isatty($self, /)\n" +"--\n" "\n" -"Always returns False since BytesIO objects are not connected\n" -"to a tty-like device."); +"Always returns False.\n" +"\n" +"BytesIO objects are not connected to a TTY-like device."); + +#define _IO_BYTESIO_ISATTY_METHODDEF \ + {"isatty", (PyCFunction)_io_BytesIO_isatty, METH_NOARGS, _io_BytesIO_isatty__doc__}, static PyObject * -bytesio_isatty(bytesio *self) +_io_BytesIO_isatty_impl(bytesio *self); + +static PyObject * +_io_BytesIO_isatty(bytesio *self, PyObject *Py_UNUSED(ignored)) { - CHECK_CLOSED(self); - Py_RETURN_FALSE; + return _io_BytesIO_isatty_impl(self); } -PyDoc_STRVAR(tell_doc, -"tell() -> current file position, an integer\n"); +PyDoc_STRVAR(_io_BytesIO_tell__doc__, +"tell($self, /)\n" +"--\n" +"\n" +"Current file position, an integer."); + +#define _IO_BYTESIO_TELL_METHODDEF \ + {"tell", (PyCFunction)_io_BytesIO_tell, METH_NOARGS, _io_BytesIO_tell__doc__}, static PyObject * -bytesio_tell(bytesio *self) +_io_BytesIO_tell_impl(bytesio *self); + +static PyObject * +_io_BytesIO_tell(bytesio *self, PyObject *Py_UNUSED(ignored)) { - CHECK_CLOSED(self); - return PyLong_FromSsize_t(self->pos); + return _io_BytesIO_tell_impl(self); } -static PyObject * -read_bytes(bytesio *self, Py_ssize_t size) -{ - char *output; - - assert(self->buf != NULL); - assert(size <= self->string_size); - if (size > 1 && - self->pos == 0 && size == PyBytes_GET_SIZE(self->buf) && - self->exports == 0) { - self->pos += size; - Py_INCREF(self->buf); - return self->buf; - } - - output = PyBytes_AS_STRING(self->buf) + self->pos; - self->pos += size; - return PyBytes_FromStringAndSize(output, size); -} - -PyDoc_STRVAR(read_doc, -"read([size]) -> read at most size bytes, returned as a bytes object.\n" +PyDoc_STRVAR(_io_BytesIO_read__doc__, +"read($self, size=None, /)\n" +"--\n" +"\n" +"Read at most size bytes, returned as a bytes object.\n" "\n" "If the size argument is negative, read until EOF is reached.\n" "Return an empty bytes object at EOF."); +#define _IO_BYTESIO_READ_METHODDEF \ + {"read", (PyCFunction)_io_BytesIO_read, METH_VARARGS, _io_BytesIO_read__doc__}, + static PyObject * -bytesio_read(bytesio *self, PyObject *args) +_io_BytesIO_read_impl(bytesio *self, PyObject *arg); + +static PyObject * +_io_BytesIO_read(bytesio *self, PyObject *args) { - Py_ssize_t size, n; + PyObject *return_value = NULL; PyObject *arg = Py_None; - CHECK_CLOSED(self); + if (!PyArg_UnpackTuple(args, "read", + 0, 1, + &arg)) + goto exit; + return_value = _io_BytesIO_read_impl(self, arg); - if (!PyArg_ParseTuple(args, "|O:read", &arg)) - return NULL; - - if (PyLong_Check(arg)) { - size = PyLong_AsSsize_t(arg); - if (size == -1 && PyErr_Occurred()) - return NULL; - } - else if (arg == Py_None) { - /* Read until EOF is reached, by default. */ - size = -1; - } - else { - PyErr_Format(PyExc_TypeError, "integer argument expected, got '%s'", - Py_TYPE(arg)->tp_name); - return NULL; - } - - /* adjust invalid sizes */ - n = self->string_size - self->pos; - if (size < 0 || size > n) { - size = n; - if (size < 0) - size = 0; - } - - return read_bytes(self, size); +exit: + return return_value; } - -PyDoc_STRVAR(read1_doc, -"read1(size) -> read at most size bytes, returned as a bytes object.\n" +PyDoc_STRVAR(_io_BytesIO_read1__doc__, +"read1($self, size, /)\n" +"--\n" +"\n" +"Read at most size bytes, returned as a bytes object.\n" "\n" "If the size argument is negative or omitted, read until EOF is reached.\n" "Return an empty bytes object at EOF."); -static PyObject * -bytesio_read1(bytesio *self, PyObject *n) -{ - PyObject *arg, *res; +#define _IO_BYTESIO_READ1_METHODDEF \ + {"read1", (PyCFunction)_io_BytesIO_read1, METH_O, _io_BytesIO_read1__doc__}, - arg = PyTuple_Pack(1, n); - if (arg == NULL) - return NULL; - res = bytesio_read(self, arg); - Py_DECREF(arg); - return res; -} - -PyDoc_STRVAR(readline_doc, -"readline([size]) -> next line from the file, as a bytes object.\n" +PyDoc_STRVAR(_io_BytesIO_readline__doc__, +"readline($self, size=None, /)\n" +"--\n" +"\n" +"Next line from the file, as a bytes object.\n" "\n" "Retain newline. A non-negative size argument limits the maximum\n" "number of bytes to return (an incomplete line may be returned then).\n" -"Return an empty bytes object at EOF.\n"); +"Return an empty bytes object at EOF."); + +#define _IO_BYTESIO_READLINE_METHODDEF \ + {"readline", (PyCFunction)_io_BytesIO_readline, METH_VARARGS, _io_BytesIO_readline__doc__}, static PyObject * -bytesio_readline(bytesio *self, PyObject *args) +_io_BytesIO_readline_impl(bytesio *self, PyObject *arg); + +static PyObject * +_io_BytesIO_readline(bytesio *self, PyObject *args) { - Py_ssize_t size, n; + PyObject *return_value = NULL; PyObject *arg = Py_None; - CHECK_CLOSED(self); + if (!PyArg_UnpackTuple(args, "readline", + 0, 1, + &arg)) + goto exit; + return_value = _io_BytesIO_readline_impl(self, arg); - if (!PyArg_ParseTuple(args, "|O:readline", &arg)) - return NULL; - - if (PyLong_Check(arg)) { - size = PyLong_AsSsize_t(arg); - if (size == -1 && PyErr_Occurred()) - return NULL; - } - else if (arg == Py_None) { - /* No size limit, by default. */ - size = -1; - } - else { - PyErr_Format(PyExc_TypeError, "integer argument expected, got '%s'", - Py_TYPE(arg)->tp_name); - return NULL; - } - - n = scan_eol(self, size); - - return read_bytes(self, n); +exit: + return return_value; } -PyDoc_STRVAR(readlines_doc, -"readlines([size]) -> list of strings, each a line from the file.\n" +PyDoc_STRVAR(_io_BytesIO_readlines__doc__, +"readlines($self, size=None, /)\n" +"--\n" +"\n" +"List of bytes objects, each a line from the file.\n" "\n" "Call readline() repeatedly and return a list of the lines so read.\n" "The optional size argument, if given, is an approximate bound on the\n" -"total number of bytes in the lines returned.\n"); +"total number of bytes in the lines returned."); + +#define _IO_BYTESIO_READLINES_METHODDEF \ + {"readlines", (PyCFunction)_io_BytesIO_readlines, METH_VARARGS, _io_BytesIO_readlines__doc__}, static PyObject * -bytesio_readlines(bytesio *self, PyObject *args) +_io_BytesIO_readlines_impl(bytesio *self, PyObject *arg); + +static PyObject * +_io_BytesIO_readlines(bytesio *self, PyObject *args) { - Py_ssize_t maxsize, size, n; - PyObject *result, *line; - char *output; + PyObject *return_value = NULL; PyObject *arg = Py_None; - CHECK_CLOSED(self); + if (!PyArg_UnpackTuple(args, "readlines", + 0, 1, + &arg)) + goto exit; + return_value = _io_BytesIO_readlines_impl(self, arg); - if (!PyArg_ParseTuple(args, "|O:readlines", &arg)) - return NULL; - - if (PyLong_Check(arg)) { - maxsize = PyLong_AsSsize_t(arg); - if (maxsize == -1 && PyErr_Occurred()) - return NULL; - } - else if (arg == Py_None) { - /* No size limit, by default. */ - maxsize = -1; - } - else { - PyErr_Format(PyExc_TypeError, "integer argument expected, got '%s'", - Py_TYPE(arg)->tp_name); - return NULL; - } - - size = 0; - result = PyList_New(0); - if (!result) - return NULL; - - output = PyBytes_AS_STRING(self->buf) + self->pos; - while ((n = scan_eol(self, -1)) != 0) { - self->pos += n; - line = PyBytes_FromStringAndSize(output, n); - if (!line) - goto on_error; - if (PyList_Append(result, line) == -1) { - Py_DECREF(line); - goto on_error; - } - Py_DECREF(line); - size += n; - if (maxsize > 0 && size >= maxsize) - break; - output += n; - } - return result; - - on_error: - Py_DECREF(result); - return NULL; +exit: + return return_value; } -PyDoc_STRVAR(readinto_doc, -"readinto(bytearray) -> int. Read up to len(b) bytes into b.\n" +PyDoc_STRVAR(_io_BytesIO_readinto__doc__, +"readinto($self, buffer, /)\n" +"--\n" +"\n" +"Read up to len(buffer) bytes into buffer.\n" "\n" "Returns number of bytes read (0 for EOF), or None if the object\n" "is set not to block as has no data to read."); +#define _IO_BYTESIO_READINTO_METHODDEF \ + {"readinto", (PyCFunction)_io_BytesIO_readinto, METH_O, _io_BytesIO_readinto__doc__}, + static PyObject * -bytesio_readinto(bytesio *self, PyObject *arg) +_io_BytesIO_readinto_impl(bytesio *self, Py_buffer *buffer); + +static PyObject * +_io_BytesIO_readinto(bytesio *self, PyObject *arg) { - Py_buffer buffer; - Py_ssize_t len, n; + PyObject *return_value = NULL; + Py_buffer buffer = {NULL, NULL}; - CHECK_CLOSED(self); + if (!PyArg_Parse(arg, + "w*:readinto", + &buffer)) + goto exit; + return_value = _io_BytesIO_readinto_impl(self, &buffer); - if (!PyArg_Parse(arg, "w*", &buffer)) - return NULL; +exit: + /* Cleanup for buffer */ + if (buffer.obj) + PyBuffer_Release(&buffer); - /* adjust invalid sizes */ - len = buffer.len; - n = self->string_size - self->pos; - if (len > n) { - len = n; - if (len < 0) - len = 0; - } - - memcpy(buffer.buf, PyBytes_AS_STRING(self->buf) + self->pos, len); - assert(self->pos + len < PY_SSIZE_T_MAX); - assert(len >= 0); - self->pos += len; - PyBuffer_Release(&buffer); - - return PyLong_FromSsize_t(len); + return return_value; } -PyDoc_STRVAR(truncate_doc, -"truncate([size]) -> int. Truncate the file to at most size bytes.\n" +PyDoc_STRVAR(_io_BytesIO_truncate__doc__, +"truncate($self, size=None, /)\n" +"--\n" +"\n" +"Truncate the file to at most size bytes.\n" "\n" "Size defaults to the current file position, as returned by tell().\n" -"The current file position is unchanged. Returns the new size.\n"); +"The current file position is unchanged. Returns the new size."); + +#define _IO_BYTESIO_TRUNCATE_METHODDEF \ + {"truncate", (PyCFunction)_io_BytesIO_truncate, METH_VARARGS, _io_BytesIO_truncate__doc__}, static PyObject * -bytesio_truncate(bytesio *self, PyObject *args) +_io_BytesIO_truncate_impl(bytesio *self, PyObject *arg); + +static PyObject * +_io_BytesIO_truncate(bytesio *self, PyObject *args) { - Py_ssize_t size; + PyObject *return_value = NULL; PyObject *arg = Py_None; - CHECK_CLOSED(self); - CHECK_EXPORTS(self); + if (!PyArg_UnpackTuple(args, "truncate", + 0, 1, + &arg)) + goto exit; + return_value = _io_BytesIO_truncate_impl(self, arg); - if (!PyArg_ParseTuple(args, "|O:truncate", &arg)) - return NULL; - - if (PyLong_Check(arg)) { - size = PyLong_AsSsize_t(arg); - if (size == -1 && PyErr_Occurred()) - return NULL; - } - else if (arg == Py_None) { - /* Truncate to current position if no argument is passed. */ - size = self->pos; - } - else { - PyErr_Format(PyExc_TypeError, "integer argument expected, got '%s'", - Py_TYPE(arg)->tp_name); - return NULL; - } - - if (size < 0) { - PyErr_Format(PyExc_ValueError, - "negative size value %zd", size); - return NULL; - } - - if (size < self->string_size) { - self->string_size = size; - if (resize_buffer(self, size) < 0) - return NULL; - } - - return PyLong_FromSsize_t(size); +exit: + return return_value; } -static PyObject * -bytesio_iternext(bytesio *self) -{ - Py_ssize_t n; - - CHECK_CLOSED(self); - - n = scan_eol(self, -1); - - if (n == 0) - return NULL; - - return read_bytes(self, n); -} - -PyDoc_STRVAR(seek_doc, -"seek(pos, whence=0) -> int. Change stream position.\n" +PyDoc_STRVAR(_io_BytesIO_seek__doc__, +"seek($self, pos, whence=0, /)\n" +"--\n" +"\n" +"Change stream position.\n" "\n" "Seek to byte offset pos relative to position indicated by whence:\n" " 0 Start of stream (the default). pos should be >= 0;\n" @@ -595,522 +333,94 @@ " 2 End of stream - pos usually negative.\n" "Returns the new absolute position."); +#define _IO_BYTESIO_SEEK_METHODDEF \ + {"seek", (PyCFunction)_io_BytesIO_seek, METH_VARARGS, _io_BytesIO_seek__doc__}, + static PyObject * -bytesio_seek(bytesio *self, PyObject *args) +_io_BytesIO_seek_impl(bytesio *self, Py_ssize_t pos, int whence); + +static PyObject * +_io_BytesIO_seek(bytesio *self, PyObject *args) { + PyObject *return_value = NULL; Py_ssize_t pos; - int mode = 0; + int whence = 0; - CHECK_CLOSED(self); + if (!PyArg_ParseTuple(args, + "n|i:seek", + &pos, &whence)) + goto exit; + return_value = _io_BytesIO_seek_impl(self, pos, whence); - if (!PyArg_ParseTuple(args, "n|i:seek", &pos, &mode)) - return NULL; - - if (pos < 0 && mode == 0) { - PyErr_Format(PyExc_ValueError, - "negative seek value %zd", pos); - return NULL; - } - - /* mode 0: offset relative to beginning of the string. - mode 1: offset relative to current position. - mode 2: offset relative the end of the string. */ - if (mode == 1) { - if (pos > PY_SSIZE_T_MAX - self->pos) { - PyErr_SetString(PyExc_OverflowError, - "new position too large"); - return NULL; - } - pos += self->pos; - } - else if (mode == 2) { - if (pos > PY_SSIZE_T_MAX - self->string_size) { - PyErr_SetString(PyExc_OverflowError, - "new position too large"); - return NULL; - } - pos += self->string_size; - } - else if (mode != 0) { - PyErr_Format(PyExc_ValueError, - "invalid whence (%i, should be 0, 1 or 2)", mode); - return NULL; - } - - if (pos < 0) - pos = 0; - self->pos = pos; - - return PyLong_FromSsize_t(self->pos); +exit: + return return_value; } -PyDoc_STRVAR(write_doc, -"write(bytes) -> int. Write bytes to file.\n" +PyDoc_STRVAR(_io_BytesIO_write__doc__, +"write($self, b, /)\n" +"--\n" +"\n" +"Write bytes to file.\n" "\n" "Return the number of bytes written."); +#define _IO_BYTESIO_WRITE_METHODDEF \ + {"write", (PyCFunction)_io_BytesIO_write, METH_O, _io_BytesIO_write__doc__}, + +PyDoc_STRVAR(_io_BytesIO_writelines__doc__, +"writelines($self, lines, /)\n" +"--\n" +"\n" +"Write lines to the file.\n" +"\n" +"Note that newlines are not added. lines can be any iterable object\n" +"producing bytes-like objects. This is equivalent to calling write() for\n" +"each element."); + +#define _IO_BYTESIO_WRITELINES_METHODDEF \ + {"writelines", (PyCFunction)_io_BytesIO_writelines, METH_O, _io_BytesIO_writelines__doc__}, + +PyDoc_STRVAR(_io_BytesIO_close__doc__, +"close($self, /)\n" +"--\n" +"\n" +"Disable all I/O operations."); + +#define _IO_BYTESIO_CLOSE_METHODDEF \ + {"close", (PyCFunction)_io_BytesIO_close, METH_NOARGS, _io_BytesIO_close__doc__}, + static PyObject * -bytesio_write(bytesio *self, PyObject *obj) +_io_BytesIO_close_impl(bytesio *self); + +static PyObject * +_io_BytesIO_close(bytesio *self, PyObject *Py_UNUSED(ignored)) { - Py_ssize_t n = 0; - Py_buffer buf; - PyObject *result = NULL; - - CHECK_CLOSED(self); - CHECK_EXPORTS(self); - - if (PyObject_GetBuffer(obj, &buf, PyBUF_CONTIG_RO) < 0) - return NULL; - - if (buf.len != 0) - n = write_bytes(self, buf.buf, buf.len); - if (n >= 0) - result = PyLong_FromSsize_t(n); - - PyBuffer_Release(&buf); - return result; + return _io_BytesIO_close_impl(self); } -PyDoc_STRVAR(writelines_doc, -"writelines(lines) -> None. Write bytes objects to the file.\n" +PyDoc_STRVAR(_io_BytesIO___init____doc__, +"BytesIO(initial_bytes=b\'\')\n" +"--\n" "\n" -"Note that newlines are not added. The argument can be any iterable\n" -"object producing bytes objects. This is equivalent to calling write() for\n" -"each bytes object."); - -static PyObject * -bytesio_writelines(bytesio *self, PyObject *v) -{ - PyObject *it, *item; - PyObject *ret; - - CHECK_CLOSED(self); - - it = PyObject_GetIter(v); - if (it == NULL) - return NULL; - - while ((item = PyIter_Next(it)) != NULL) { - ret = bytesio_write(self, item); - Py_DECREF(item); - if (ret == NULL) { - Py_DECREF(it); - return NULL; - } - Py_DECREF(ret); - } - Py_DECREF(it); - - /* See if PyIter_Next failed */ - if (PyErr_Occurred()) - return NULL; - - Py_RETURN_NONE; -} - -PyDoc_STRVAR(close_doc, -"close() -> None. Disable all I/O operations."); - -static PyObject * -bytesio_close(bytesio *self) -{ - CHECK_EXPORTS(self); - Py_CLEAR(self->buf); - Py_RETURN_NONE; -} - -/* Pickling support. - - Note that only pickle protocol 2 and onward are supported since we use - extended __reduce__ API of PEP 307 to make BytesIO instances picklable. - - Providing support for protocol < 2 would require the __reduce_ex__ method - which is notably long-winded when defined properly. - - For BytesIO, the implementation would similar to one coded for - object.__reduce_ex__, but slightly less general. To be more specific, we - could call bytesio_getstate directly and avoid checking for the presence of - a fallback __reduce__ method. However, we would still need a __newobj__ - function to use the efficient instance representation of PEP 307. - */ - -static PyObject * -bytesio_getstate(bytesio *self) -{ - PyObject *initvalue = bytesio_getvalue(self); - PyObject *dict; - PyObject *state; - - if (initvalue == NULL) - return NULL; - if (self->dict == NULL) { - Py_INCREF(Py_None); - dict = Py_None; - } - else { - dict = PyDict_Copy(self->dict); - if (dict == NULL) { - Py_DECREF(initvalue); - return NULL; - } - } - - state = Py_BuildValue("(OnN)", initvalue, self->pos, dict); - Py_DECREF(initvalue); - return state; -} - -static PyObject * -bytesio_setstate(bytesio *self, PyObject *state) -{ - PyObject *result; - PyObject *position_obj; - PyObject *dict; - Py_ssize_t pos; - - assert(state != NULL); - - /* We allow the state tuple to be longer than 3, because we may need - someday to extend the object's state without breaking - backward-compatibility. */ - if (!PyTuple_Check(state) || Py_SIZE(state) < 3) { - PyErr_Format(PyExc_TypeError, - "%.200s.__setstate__ argument should be 3-tuple, got %.200s", - Py_TYPE(self)->tp_name, Py_TYPE(state)->tp_name); - return NULL; - } - CHECK_EXPORTS(self); - /* Reset the object to its default state. This is only needed to handle - the case of repeated calls to __setstate__. */ - self->string_size = 0; - self->pos = 0; - - /* Set the value of the internal buffer. If state[0] does not support the - buffer protocol, bytesio_write will raise the appropriate TypeError. */ - result = bytesio_write(self, PyTuple_GET_ITEM(state, 0)); - if (result == NULL) - return NULL; - Py_DECREF(result); - - /* Set carefully the position value. Alternatively, we could use the seek - method instead of modifying self->pos directly to better protect the - object internal state against errneous (or malicious) inputs. */ - position_obj = PyTuple_GET_ITEM(state, 1); - if (!PyLong_Check(position_obj)) { - PyErr_Format(PyExc_TypeError, - "second item of state must be an integer, not %.200s", - Py_TYPE(position_obj)->tp_name); - return NULL; - } - pos = PyLong_AsSsize_t(position_obj); - if (pos == -1 && PyErr_Occurred()) - return NULL; - if (pos < 0) { - PyErr_SetString(PyExc_ValueError, - "position value cannot be negative"); - return NULL; - } - self->pos = pos; - - /* Set the dictionary of the instance variables. */ - dict = PyTuple_GET_ITEM(state, 2); - if (dict != Py_None) { - if (!PyDict_Check(dict)) { - PyErr_Format(PyExc_TypeError, - "third item of state should be a dict, got a %.200s", - Py_TYPE(dict)->tp_name); - return NULL; - } - if (self->dict) { - /* Alternatively, we could replace the internal dictionary - completely. However, it seems more practical to just update it. */ - if (PyDict_Update(self->dict, dict) < 0) - return NULL; - } - else { - Py_INCREF(dict); - self->dict = dict; - } - } - - Py_RETURN_NONE; -} - -static void -bytesio_dealloc(bytesio *self) -{ - _PyObject_GC_UNTRACK(self); - if (self->exports > 0) { - PyErr_SetString(PyExc_SystemError, - "deallocated BytesIO object has exported buffers"); - PyErr_Print(); - } - Py_CLEAR(self->buf); - Py_CLEAR(self->dict); - if (self->weakreflist != NULL) - PyObject_ClearWeakRefs((PyObject *) self); - Py_TYPE(self)->tp_free(self); -} - -static PyObject * -bytesio_new(PyTypeObject *type, PyObject *args, PyObject *kwds) -{ - bytesio *self; - - assert(type != NULL && type->tp_alloc != NULL); - self = (bytesio *)type->tp_alloc(type, 0); - if (self == NULL) - return NULL; - - /* tp_alloc initializes all the fields to zero. So we don't have to - initialize them here. */ - - self->buf = PyBytes_FromStringAndSize(NULL, 0); - if (self->buf == NULL) { - Py_DECREF(self); - return PyErr_NoMemory(); - } - - return (PyObject *)self; -} +"Buffered I/O implementation using an in-memory bytes buffer."); static int -bytesio_init(bytesio *self, PyObject *args, PyObject *kwds) +_io_BytesIO___init___impl(bytesio *self, PyObject *initvalue); + +static int +_io_BytesIO___init__(PyObject *self, PyObject *args, PyObject *kwargs) { - char *kwlist[] = {"initial_bytes", NULL}; + int return_value = -1; + static char *_keywords[] = {"initial_bytes", NULL}; PyObject *initvalue = NULL; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O:BytesIO", kwlist, - &initvalue)) - return -1; + if (!PyArg_ParseTupleAndKeywords(args, kwargs, + "|O:BytesIO", _keywords, + &initvalue)) + goto exit; + return_value = _io_BytesIO___init___impl((bytesio *)self, initvalue); - /* In case, __init__ is called multiple times. */ - self->string_size = 0; - self->pos = 0; - - if (self->exports > 0) { - PyErr_SetString(PyExc_BufferError, - "Existing exports of data: object cannot be re-sized"); - return -1; - } - if (initvalue && initvalue != Py_None) { - if (PyBytes_CheckExact(initvalue)) { - Py_INCREF(initvalue); - Py_XDECREF(self->buf); - self->buf = initvalue; - self->string_size = PyBytes_GET_SIZE(initvalue); - } - else { - PyObject *res; - res = bytesio_write(self, initvalue); - if (res == NULL) - return -1; - Py_DECREF(res); - self->pos = 0; - } - } - - return 0; +exit: + return return_value; } - -static PyObject * -bytesio_sizeof(bytesio *self, void *unused) -{ - Py_ssize_t res; - - res = sizeof(bytesio); - if (self->buf && !SHARED_BUF(self)) - res += _PySys_GetSizeOf(self->buf); - return PyLong_FromSsize_t(res); -} - -static int -bytesio_traverse(bytesio *self, visitproc visit, void *arg) -{ - Py_VISIT(self->dict); - return 0; -} - -static int -bytesio_clear(bytesio *self) -{ - Py_CLEAR(self->dict); - return 0; -} - - -static PyGetSetDef bytesio_getsetlist[] = { - {"closed", (getter)bytesio_get_closed, NULL, - "True if the file is closed."}, - {NULL}, /* sentinel */ -}; - -static struct PyMethodDef bytesio_methods[] = { - {"readable", (PyCFunction)return_not_closed, METH_NOARGS, readable_doc}, - {"seekable", (PyCFunction)return_not_closed, METH_NOARGS, seekable_doc}, - {"writable", (PyCFunction)return_not_closed, METH_NOARGS, writable_doc}, - {"close", (PyCFunction)bytesio_close, METH_NOARGS, close_doc}, - {"flush", (PyCFunction)bytesio_flush, METH_NOARGS, flush_doc}, - {"isatty", (PyCFunction)bytesio_isatty, METH_NOARGS, isatty_doc}, - {"tell", (PyCFunction)bytesio_tell, METH_NOARGS, tell_doc}, - {"write", (PyCFunction)bytesio_write, METH_O, write_doc}, - {"writelines", (PyCFunction)bytesio_writelines, METH_O, writelines_doc}, - {"read1", (PyCFunction)bytesio_read1, METH_O, read1_doc}, - {"readinto", (PyCFunction)bytesio_readinto, METH_O, readinto_doc}, - {"readline", (PyCFunction)bytesio_readline, METH_VARARGS, readline_doc}, - {"readlines", (PyCFunction)bytesio_readlines, METH_VARARGS, readlines_doc}, - {"read", (PyCFunction)bytesio_read, METH_VARARGS, read_doc}, - {"getbuffer", (PyCFunction)bytesio_getbuffer, METH_NOARGS, getbuffer_doc}, - {"getvalue", (PyCFunction)bytesio_getvalue, METH_NOARGS, getval_doc}, - {"seek", (PyCFunction)bytesio_seek, METH_VARARGS, seek_doc}, - {"truncate", (PyCFunction)bytesio_truncate, METH_VARARGS, truncate_doc}, - {"__getstate__", (PyCFunction)bytesio_getstate, METH_NOARGS, NULL}, - {"__setstate__", (PyCFunction)bytesio_setstate, METH_O, NULL}, - {"__sizeof__", (PyCFunction)bytesio_sizeof, METH_NOARGS, NULL}, - {NULL, NULL} /* sentinel */ -}; - -PyDoc_STRVAR(bytesio_doc, -"BytesIO([buffer]) -> object\n" -"\n" -"Create a buffered I/O implementation using an in-memory bytes\n" -"buffer, ready for reading and writing."); - -PyTypeObject PyBytesIO_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "_io.BytesIO", /*tp_name*/ - sizeof(bytesio), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - (destructor)bytesio_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_reserved*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash*/ - 0, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | - Py_TPFLAGS_HAVE_GC, /*tp_flags*/ - bytesio_doc, /*tp_doc*/ - (traverseproc)bytesio_traverse, /*tp_traverse*/ - (inquiry)bytesio_clear, /*tp_clear*/ - 0, /*tp_richcompare*/ - offsetof(bytesio, weakreflist), /*tp_weaklistoffset*/ - PyObject_SelfIter, /*tp_iter*/ - (iternextfunc)bytesio_iternext, /*tp_iternext*/ - bytesio_methods, /*tp_methods*/ - 0, /*tp_members*/ - bytesio_getsetlist, /*tp_getset*/ - 0, /*tp_base*/ - 0, /*tp_dict*/ - 0, /*tp_descr_get*/ - 0, /*tp_descr_set*/ - offsetof(bytesio, dict), /*tp_dictoffset*/ - (initproc)bytesio_init, /*tp_init*/ - 0, /*tp_alloc*/ - bytesio_new, /*tp_new*/ -}; - - -/* - * Implementation of the small intermediate object used by getbuffer(). - * getbuffer() returns a memoryview over this object, which should make it - * invisible from Python code. - */ - -static int -bytesiobuf_getbuffer(bytesiobuf *obj, Py_buffer *view, int flags) -{ - bytesio *b = (bytesio *) obj->source; - - if (view == NULL) { - PyErr_SetString(PyExc_BufferError, - "bytesiobuf_getbuffer: view==NULL argument is obsolete"); - return -1; - } - if (SHARED_BUF(b)) { - if (unshare_buffer(b, b->string_size) < 0) - return -1; - } - - /* cannot fail if view != NULL and readonly == 0 */ - (void)PyBuffer_FillInfo(view, (PyObject*)obj, - PyBytes_AS_STRING(b->buf), b->string_size, - 0, flags); - b->exports++; - return 0; -} - -static void -bytesiobuf_releasebuffer(bytesiobuf *obj, Py_buffer *view) -{ - bytesio *b = (bytesio *) obj->source; - b->exports--; -} - -static int -bytesiobuf_traverse(bytesiobuf *self, visitproc visit, void *arg) -{ - Py_VISIT(self->source); - return 0; -} - -static void -bytesiobuf_dealloc(bytesiobuf *self) -{ - Py_CLEAR(self->source); - Py_TYPE(self)->tp_free(self); -} - -static PyBufferProcs bytesiobuf_as_buffer = { - (getbufferproc) bytesiobuf_getbuffer, - (releasebufferproc) bytesiobuf_releasebuffer, -}; - -PyTypeObject _PyBytesIOBuffer_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "_io._BytesIOBuffer", /*tp_name*/ - sizeof(bytesiobuf), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - (destructor)bytesiobuf_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_reserved*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash*/ - 0, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - &bytesiobuf_as_buffer, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /*tp_flags*/ - 0, /*tp_doc*/ - (traverseproc)bytesiobuf_traverse, /*tp_traverse*/ - 0, /*tp_clear*/ - 0, /*tp_richcompare*/ - 0, /*tp_weaklistoffset*/ - 0, /*tp_iter*/ - 0, /*tp_iternext*/ - 0, /*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*/ - 0, /*tp_new*/ -}; +/*[clinic end generated code: output=e22697ada514f4eb input=a9049054013a1b77]*/ diff --git a/Modules/_io/fileio.c b/Modules/_io/clinic/fileio.c.h copy from Modules/_io/fileio.c copy to Modules/_io/clinic/fileio.c.h --- a/Modules/_io/fileio.c +++ b/Modules/_io/clinic/fileio.c.h @@ -1,1026 +1,268 @@ -/* Author: Daniel Stutzbach */ +/*[clinic input] +preserve +[clinic start generated code]*/ -#define PY_SSIZE_T_CLEAN -#include "Python.h" -#include "structmember.h" -#ifdef HAVE_SYS_TYPES_H -#include -#endif -#ifdef HAVE_SYS_STAT_H -#include -#endif -#ifdef HAVE_FCNTL_H -#include -#endif -#include /* For offsetof */ -#include "_iomodule.h" +PyDoc_STRVAR(_io_FileIO_close__doc__, +"close($self, /)\n" +"--\n" +"\n" +"Close the file.\n" +"\n" +"A closed file cannot be used for further I/O operations. close() may be\n" +"called more than once without error."); -/* - * Known likely problems: - * - * - Files larger then 2**32-1 - * - Files with unicode filenames - * - Passing numbers greater than 2**32-1 when an integer is expected - * - Making it work on Windows and other oddball platforms - * - * To Do: - * - * - autoconfify header file inclusion - */ +#define _IO_FILEIO_CLOSE_METHODDEF \ + {"close", (PyCFunction)_io_FileIO_close, METH_NOARGS, _io_FileIO_close__doc__}, -#ifdef MS_WINDOWS -/* can simulate truncate with Win32 API functions; see file_truncate */ -#define HAVE_FTRUNCATE -#define WIN32_LEAN_AND_MEAN -#include -#endif +static PyObject * +_io_FileIO_close_impl(fileio *self); -#if BUFSIZ < (8*1024) -#define SMALLCHUNK (8*1024) -#elif (BUFSIZ >= (2 << 25)) -#error "unreasonable BUFSIZ > 64MB defined" -#else -#define SMALLCHUNK BUFSIZ -#endif - -typedef struct { - PyObject_HEAD - int fd; - unsigned int created : 1; - unsigned int readable : 1; - unsigned int writable : 1; - unsigned int appending : 1; - signed int seekable : 2; /* -1 means unknown */ - unsigned int closefd : 1; - char finalizing; - unsigned int blksize; - PyObject *weakreflist; - PyObject *dict; -} fileio; - -PyTypeObject PyFileIO_Type; - -_Py_IDENTIFIER(name); - -#define PyFileIO_Check(op) (PyObject_TypeCheck((op), &PyFileIO_Type)) - -int -_PyFileIO_closed(PyObject *self) +static PyObject * +_io_FileIO_close(fileio *self, PyObject *Py_UNUSED(ignored)) { - return ((fileio *)self)->fd < 0; + return _io_FileIO_close_impl(self); } -/* Because this can call arbitrary code, it shouldn't be called when - the refcount is 0 (that is, not directly from tp_dealloc unless - the refcount has been temporarily re-incremented). */ -static PyObject * -fileio_dealloc_warn(fileio *self, PyObject *source) -{ - if (self->fd >= 0 && self->closefd) { - PyObject *exc, *val, *tb; - PyErr_Fetch(&exc, &val, &tb); - if (PyErr_WarnFormat(PyExc_ResourceWarning, 1, - "unclosed file %R", source)) { - /* Spurious errors can appear at shutdown */ - if (PyErr_ExceptionMatches(PyExc_Warning)) - PyErr_WriteUnraisable((PyObject *) self); - } - PyErr_Restore(exc, val, tb); - } - Py_RETURN_NONE; -} - -static PyObject * -portable_lseek(int fd, PyObject *posobj, int whence); - -static PyObject *portable_lseek(int fd, PyObject *posobj, int whence); - -/* Returns 0 on success, -1 with exception set on failure. */ -static int -internal_close(fileio *self) -{ - int err = 0; - int save_errno = 0; - if (self->fd >= 0) { - int fd = self->fd; - self->fd = -1; - /* fd is accessible and someone else may have closed it */ - if (_PyVerify_fd(fd)) { - Py_BEGIN_ALLOW_THREADS - _Py_BEGIN_SUPPRESS_IPH - err = close(fd); - if (err < 0) - save_errno = errno; - _Py_END_SUPPRESS_IPH - Py_END_ALLOW_THREADS - } else { - save_errno = errno; - err = -1; - } - } - if (err < 0) { - errno = save_errno; - PyErr_SetFromErrno(PyExc_IOError); - return -1; - } - return 0; -} - -static PyObject * -fileio_close(fileio *self) -{ - PyObject *res; - PyObject *exc, *val, *tb; - int rc; - _Py_IDENTIFIER(close); - res = _PyObject_CallMethodId((PyObject*)&PyRawIOBase_Type, - &PyId_close, "O", self); - if (!self->closefd) { - self->fd = -1; - return res; - } - if (res == NULL) - PyErr_Fetch(&exc, &val, &tb); - if (self->finalizing) { - PyObject *r = fileio_dealloc_warn(self, (PyObject *) self); - if (r) - Py_DECREF(r); - else - PyErr_Clear(); - } - rc = internal_close(self); - if (res == NULL) - _PyErr_ChainExceptions(exc, val, tb); - if (rc < 0) - Py_CLEAR(res); - return res; -} - -static PyObject * -fileio_new(PyTypeObject *type, PyObject *args, PyObject *kwds) -{ - fileio *self; - - assert(type != NULL && type->tp_alloc != NULL); - - self = (fileio *) type->tp_alloc(type, 0); - if (self != NULL) { - self->fd = -1; - self->created = 0; - self->readable = 0; - self->writable = 0; - self->appending = 0; - self->seekable = -1; - self->blksize = 0; - self->closefd = 1; - self->weakreflist = NULL; - } - - return (PyObject *) self; -} - -#ifdef O_CLOEXEC -extern int _Py_open_cloexec_works; -#endif - -static int -fileio_init(PyObject *oself, PyObject *args, PyObject *kwds) -{ - fileio *self = (fileio *) oself; - static char *kwlist[] = {"file", "mode", "closefd", "opener", NULL}; - const char *name = NULL; - PyObject *nameobj, *stringobj = NULL, *opener = Py_None; - char *mode = "r"; - char *s; -#ifdef MS_WINDOWS - Py_UNICODE *widename = NULL; -#endif - int ret = 0; - int rwa = 0, plus = 0; - int flags = 0; - int fd = -1; - int closefd = 1; - int fd_is_own = 0; -#ifdef O_CLOEXEC - int *atomic_flag_works = &_Py_open_cloexec_works; -#elif !defined(MS_WINDOWS) - int *atomic_flag_works = NULL; -#endif - struct _Py_stat_struct fdfstat; - int async_err = 0; - - assert(PyFileIO_Check(oself)); - if (self->fd >= 0) { - if (self->closefd) { - /* Have to close the existing file first. */ - if (internal_close(self) < 0) - return -1; - } - else - self->fd = -1; - } - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|siO:fileio", - kwlist, &nameobj, &mode, &closefd, - &opener)) - return -1; - - if (PyFloat_Check(nameobj)) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float"); - return -1; - } - - fd = _PyLong_AsInt(nameobj); - if (fd < 0) { - if (!PyErr_Occurred()) { - PyErr_SetString(PyExc_ValueError, - "negative file descriptor"); - return -1; - } - PyErr_Clear(); - } - -#ifdef MS_WINDOWS - if (PyUnicode_Check(nameobj)) { - int rv = _PyUnicode_HasNULChars(nameobj); - if (rv) { - if (rv != -1) - PyErr_SetString(PyExc_ValueError, "embedded null character"); - return -1; - } - widename = PyUnicode_AsUnicode(nameobj); - if (widename == NULL) - return -1; - } else -#endif - if (fd < 0) - { - if (!PyUnicode_FSConverter(nameobj, &stringobj)) { - return -1; - } - name = PyBytes_AS_STRING(stringobj); - } - - s = mode; - while (*s) { - switch (*s++) { - case 'x': - if (rwa) { - bad_mode: - PyErr_SetString(PyExc_ValueError, - "Must have exactly one of create/read/write/append " - "mode and at most one plus"); - goto error; - } - rwa = 1; - self->created = 1; - self->writable = 1; - flags |= O_EXCL | O_CREAT; - break; - case 'r': - if (rwa) - goto bad_mode; - rwa = 1; - self->readable = 1; - break; - case 'w': - if (rwa) - goto bad_mode; - rwa = 1; - self->writable = 1; - flags |= O_CREAT | O_TRUNC; - break; - case 'a': - if (rwa) - goto bad_mode; - rwa = 1; - self->writable = 1; - self->appending = 1; - flags |= O_APPEND | O_CREAT; - break; - case 'b': - break; - case '+': - if (plus) - goto bad_mode; - self->readable = self->writable = 1; - plus = 1; - break; - default: - PyErr_Format(PyExc_ValueError, - "invalid mode: %.200s", mode); - goto error; - } - } - - if (!rwa) - goto bad_mode; - - if (self->readable && self->writable) - flags |= O_RDWR; - else if (self->readable) - flags |= O_RDONLY; - else - flags |= O_WRONLY; - -#ifdef O_BINARY - flags |= O_BINARY; -#endif - -#ifdef MS_WINDOWS - flags |= O_NOINHERIT; -#elif defined(O_CLOEXEC) - flags |= O_CLOEXEC; -#endif - - if (fd >= 0) { - self->fd = fd; - self->closefd = closefd; - } - else { - self->closefd = 1; - if (!closefd) { - PyErr_SetString(PyExc_ValueError, - "Cannot use closefd=False with file name"); - goto error; - } - - errno = 0; - if (opener == Py_None) { - do { - Py_BEGIN_ALLOW_THREADS -#ifdef MS_WINDOWS - if (widename != NULL) - self->fd = _wopen(widename, flags, 0666); - else -#endif - self->fd = open(name, flags, 0666); - Py_END_ALLOW_THREADS - } while (self->fd < 0 && errno == EINTR && - !(async_err = PyErr_CheckSignals())); - - if (async_err) - goto error; - } - else { - PyObject *fdobj; - -#ifndef MS_WINDOWS - /* the opener may clear the atomic flag */ - atomic_flag_works = NULL; -#endif - - fdobj = PyObject_CallFunction(opener, "Oi", nameobj, flags); - if (fdobj == NULL) - goto error; - if (!PyLong_Check(fdobj)) { - Py_DECREF(fdobj); - PyErr_SetString(PyExc_TypeError, - "expected integer from opener"); - goto error; - } - - self->fd = _PyLong_AsInt(fdobj); - Py_DECREF(fdobj); - if (self->fd == -1) { - goto error; - } - } - - fd_is_own = 1; - if (self->fd < 0) { - PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, nameobj); - goto error; - } - -#ifndef MS_WINDOWS - if (_Py_set_inheritable(self->fd, 0, atomic_flag_works) < 0) - goto error; -#endif - } - - self->blksize = DEFAULT_BUFFER_SIZE; - if (_Py_fstat(self->fd, &fdfstat) < 0) - goto error; -#if defined(S_ISDIR) && defined(EISDIR) - /* On Unix, open will succeed for directories. - In Python, there should be no file objects referring to - directories, so we need a check. */ - if (S_ISDIR(fdfstat.st_mode)) { - errno = EISDIR; - PyErr_SetFromErrnoWithFilenameObject(PyExc_IOError, nameobj); - goto error; - } -#endif /* defined(S_ISDIR) */ -#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE - if (fdfstat.st_blksize > 1) - self->blksize = fdfstat.st_blksize; -#endif /* HAVE_STRUCT_STAT_ST_BLKSIZE */ - -#if defined(MS_WINDOWS) || defined(__CYGWIN__) - /* don't translate newlines (\r\n <=> \n) */ - _setmode(self->fd, O_BINARY); -#endif - - if (_PyObject_SetAttrId((PyObject *)self, &PyId_name, nameobj) < 0) - goto error; - - if (self->appending) { - /* For consistent behaviour, we explicitly seek to the - end of file (otherwise, it might be done only on the - first write()). */ - PyObject *pos = portable_lseek(self->fd, NULL, 2); - if (pos == NULL) - goto error; - Py_DECREF(pos); - } - - goto done; - - error: - ret = -1; - if (!fd_is_own) - self->fd = -1; - if (self->fd >= 0) - internal_close(self); - - done: - Py_CLEAR(stringobj); - return ret; -} - -static int -fileio_traverse(fileio *self, visitproc visit, void *arg) -{ - Py_VISIT(self->dict); - return 0; -} - -static int -fileio_clear(fileio *self) -{ - Py_CLEAR(self->dict); - return 0; -} - -static void -fileio_dealloc(fileio *self) -{ - self->finalizing = 1; - if (_PyIOBase_finalize((PyObject *) self) < 0) - return; - _PyObject_GC_UNTRACK(self); - if (self->weakreflist != NULL) - PyObject_ClearWeakRefs((PyObject *) self); - Py_CLEAR(self->dict); - Py_TYPE(self)->tp_free((PyObject *)self); -} - -static PyObject * -err_closed(void) -{ - PyErr_SetString(PyExc_ValueError, "I/O operation on closed file"); - return NULL; -} - -static PyObject * -err_mode(char *action) -{ - _PyIO_State *state = IO_STATE(); - if (state != NULL) - PyErr_Format(state->unsupported_operation, - "File not open for %s", action); - return NULL; -} - -static PyObject * -fileio_fileno(fileio *self) -{ - if (self->fd < 0) - return err_closed(); - return PyLong_FromLong((long) self->fd); -} - -static PyObject * -fileio_readable(fileio *self) -{ - if (self->fd < 0) - return err_closed(); - return PyBool_FromLong((long) self->readable); -} - -static PyObject * -fileio_writable(fileio *self) -{ - if (self->fd < 0) - return err_closed(); - return PyBool_FromLong((long) self->writable); -} - -static PyObject * -fileio_seekable(fileio *self) -{ - if (self->fd < 0) - return err_closed(); - if (self->seekable < 0) { - PyObject *pos = portable_lseek(self->fd, NULL, SEEK_CUR); - if (pos == NULL) { - PyErr_Clear(); - self->seekable = 0; - } else { - Py_DECREF(pos); - self->seekable = 1; - } - } - return PyBool_FromLong((long) self->seekable); -} - -static PyObject * -fileio_readinto(fileio *self, PyObject *args) -{ - Py_buffer pbuf; - Py_ssize_t n; - int err; - - if (self->fd < 0) - return err_closed(); - if (!self->readable) - return err_mode("reading"); - - if (!PyArg_ParseTuple(args, "w*", &pbuf)) - return NULL; - - n = _Py_read(self->fd, pbuf.buf, pbuf.len); - /* copy errno because PyBuffer_Release() can indirectly modify it */ - err = errno; - PyBuffer_Release(&pbuf); - - if (n == -1) { - if (err == EAGAIN) { - PyErr_Clear(); - Py_RETURN_NONE; - } - return NULL; - } - - return PyLong_FromSsize_t(n); -} - -static size_t -new_buffersize(fileio *self, size_t currentsize) -{ - size_t addend; - - /* Expand the buffer by an amount proportional to the current size, - giving us amortized linear-time behavior. For bigger sizes, use a - less-than-double growth factor to avoid excessive allocation. */ - assert(currentsize <= PY_SSIZE_T_MAX); - if (currentsize > 65536) - addend = currentsize >> 3; - else - addend = 256 + currentsize; - if (addend < SMALLCHUNK) - /* Avoid tiny read() calls. */ - addend = SMALLCHUNK; - return addend + currentsize; -} - -static PyObject * -fileio_readall(fileio *self) -{ - struct _Py_stat_struct status; - Py_off_t pos, end; - PyObject *result; - Py_ssize_t bytes_read = 0; - Py_ssize_t n; - size_t bufsize; - - if (self->fd < 0) - return err_closed(); - if (!_PyVerify_fd(self->fd)) - return PyErr_SetFromErrno(PyExc_IOError); - - _Py_BEGIN_SUPPRESS_IPH -#ifdef MS_WINDOWS - pos = _lseeki64(self->fd, 0L, SEEK_CUR); -#else - pos = lseek(self->fd, 0L, SEEK_CUR); -#endif - _Py_END_SUPPRESS_IPH - - if (_Py_fstat_noraise(self->fd, &status) == 0) - end = status.st_size; - else - end = (Py_off_t)-1; - - if (end > 0 && end >= pos && pos >= 0 && end - pos < PY_SSIZE_T_MAX) { - /* This is probably a real file, so we try to allocate a - buffer one byte larger than the rest of the file. If the - calculation is right then we should get EOF without having - to enlarge the buffer. */ - bufsize = (size_t)(end - pos + 1); - } else { - bufsize = SMALLCHUNK; - } - - result = PyBytes_FromStringAndSize(NULL, bufsize); - if (result == NULL) - return NULL; - - while (1) { - if (bytes_read >= (Py_ssize_t)bufsize) { - bufsize = new_buffersize(self, bytes_read); - if (bufsize > PY_SSIZE_T_MAX || bufsize <= 0) { - PyErr_SetString(PyExc_OverflowError, - "unbounded read returned more bytes " - "than a Python bytes object can hold"); - Py_DECREF(result); - return NULL; - } - - if (PyBytes_GET_SIZE(result) < (Py_ssize_t)bufsize) { - if (_PyBytes_Resize(&result, bufsize) < 0) - return NULL; - } - } - - n = _Py_read(self->fd, - PyBytes_AS_STRING(result) + bytes_read, - bufsize - bytes_read); - - if (n == 0) - break; - if (n == -1) { - if (errno == EAGAIN) { - PyErr_Clear(); - if (bytes_read > 0) - break; - Py_DECREF(result); - Py_RETURN_NONE; - } - Py_DECREF(result); - return NULL; - } - bytes_read += n; - pos += n; - } - - if (PyBytes_GET_SIZE(result) > bytes_read) { - if (_PyBytes_Resize(&result, bytes_read) < 0) - return NULL; - } - return result; -} - -static PyObject * -fileio_read(fileio *self, PyObject *args) -{ - char *ptr; - Py_ssize_t n; - Py_ssize_t size = -1; - PyObject *bytes; - - if (self->fd < 0) - return err_closed(); - if (!self->readable) - return err_mode("reading"); - - if (!PyArg_ParseTuple(args, "|O&", &_PyIO_ConvertSsize_t, &size)) - return NULL; - - if (size < 0) - return fileio_readall(self); - -#ifdef MS_WINDOWS - /* On Windows, the count parameter of read() is an int */ - if (size > INT_MAX) - size = INT_MAX; -#endif - - bytes = PyBytes_FromStringAndSize(NULL, size); - if (bytes == NULL) - return NULL; - ptr = PyBytes_AS_STRING(bytes); - - n = _Py_read(self->fd, ptr, size); - if (n == -1) { - /* copy errno because Py_DECREF() can indirectly modify it */ - int err = errno; - Py_DECREF(bytes); - if (err == EAGAIN) { - PyErr_Clear(); - Py_RETURN_NONE; - } - return NULL; - } - - if (n != size) { - if (_PyBytes_Resize(&bytes, n) < 0) { - Py_CLEAR(bytes); - return NULL; - } - } - - return (PyObject *) bytes; -} - -static PyObject * -fileio_write(fileio *self, PyObject *args) -{ - Py_buffer pbuf; - Py_ssize_t n; - int err; - - if (self->fd < 0) - return err_closed(); - if (!self->writable) - return err_mode("writing"); - - if (!PyArg_ParseTuple(args, "y*", &pbuf)) - return NULL; - - n = _Py_write(self->fd, pbuf.buf, pbuf.len); - /* copy errno because PyBuffer_Release() can indirectly modify it */ - err = errno; - PyBuffer_Release(&pbuf); - - if (n < 0) { - if (err == EAGAIN) { - PyErr_Clear(); - Py_RETURN_NONE; - } - return NULL; - } - - return PyLong_FromSsize_t(n); -} - -/* XXX Windows support below is likely incomplete */ - -/* Cribbed from posix_lseek() */ -static PyObject * -portable_lseek(int fd, PyObject *posobj, int whence) -{ - Py_off_t pos, res; - -#ifdef SEEK_SET - /* Turn 0, 1, 2 into SEEK_{SET,CUR,END} */ - switch (whence) { -#if SEEK_SET != 0 - case 0: whence = SEEK_SET; break; -#endif -#if SEEK_CUR != 1 - case 1: whence = SEEK_CUR; break; -#endif -#if SEEK_END != 2 - case 2: whence = SEEK_END; break; -#endif - } -#endif /* SEEK_SET */ - - if (posobj == NULL) - pos = 0; - else { - if(PyFloat_Check(posobj)) { - PyErr_SetString(PyExc_TypeError, "an integer is required"); - return NULL; - } -#if defined(HAVE_LARGEFILE_SUPPORT) - pos = PyLong_AsLongLong(posobj); -#else - pos = PyLong_AsLong(posobj); -#endif - if (PyErr_Occurred()) - return NULL; - } - - if (_PyVerify_fd(fd)) { - Py_BEGIN_ALLOW_THREADS - _Py_BEGIN_SUPPRESS_IPH -#ifdef MS_WINDOWS - res = _lseeki64(fd, pos, whence); -#else - res = lseek(fd, pos, whence); -#endif - _Py_END_SUPPRESS_IPH - Py_END_ALLOW_THREADS - } else - res = -1; - if (res < 0) - return PyErr_SetFromErrno(PyExc_IOError); - -#if defined(HAVE_LARGEFILE_SUPPORT) - return PyLong_FromLongLong(res); -#else - return PyLong_FromLong(res); -#endif -} - -static PyObject * -fileio_seek(fileio *self, PyObject *args) -{ - PyObject *posobj; - int whence = 0; - - if (self->fd < 0) - return err_closed(); - - if (!PyArg_ParseTuple(args, "O|i", &posobj, &whence)) - return NULL; - - return portable_lseek(self->fd, posobj, whence); -} - -static PyObject * -fileio_tell(fileio *self, PyObject *args) -{ - if (self->fd < 0) - return err_closed(); - - return portable_lseek(self->fd, NULL, 1); -} - -#ifdef HAVE_FTRUNCATE -static PyObject * -fileio_truncate(fileio *self, PyObject *args) -{ - PyObject *posobj = NULL; /* the new size wanted by the user */ - Py_off_t pos; - int ret; - int fd; - - fd = self->fd; - if (fd < 0) - return err_closed(); - if (!self->writable) - return err_mode("writing"); - - if (!PyArg_ParseTuple(args, "|O", &posobj)) - return NULL; - - if (posobj == Py_None || posobj == NULL) { - /* Get the current position. */ - posobj = portable_lseek(fd, NULL, 1); - if (posobj == NULL) - return NULL; - } - else { - Py_INCREF(posobj); - } - -#if defined(HAVE_LARGEFILE_SUPPORT) - pos = PyLong_AsLongLong(posobj); -#else - pos = PyLong_AsLong(posobj); -#endif - if (PyErr_Occurred()){ - Py_DECREF(posobj); - return NULL; - } - - Py_BEGIN_ALLOW_THREADS - _Py_BEGIN_SUPPRESS_IPH - errno = 0; -#ifdef MS_WINDOWS - ret = _chsize_s(fd, pos); -#else - ret = ftruncate(fd, pos); -#endif - _Py_END_SUPPRESS_IPH - Py_END_ALLOW_THREADS - - if (ret != 0) { - Py_DECREF(posobj); - PyErr_SetFromErrno(PyExc_IOError); - return NULL; - } - - return posobj; -} -#endif /* HAVE_FTRUNCATE */ - -static char * -mode_string(fileio *self) -{ - if (self->created) { - if (self->readable) - return "xb+"; - else - return "xb"; - } - if (self->appending) { - if (self->readable) - return "ab+"; - else - return "ab"; - } - else if (self->readable) { - if (self->writable) - return "rb+"; - else - return "rb"; - } - else - return "wb"; -} - -static PyObject * -fileio_repr(fileio *self) -{ - PyObject *nameobj, *res; - - if (self->fd < 0) - return PyUnicode_FromFormat("<_io.FileIO [closed]>"); - - nameobj = _PyObject_GetAttrId((PyObject *) self, &PyId_name); - if (nameobj == NULL) { - if (PyErr_ExceptionMatches(PyExc_AttributeError)) - PyErr_Clear(); - else - return NULL; - res = PyUnicode_FromFormat( - "<_io.FileIO fd=%d mode='%s' closefd=%s>", - self->fd, mode_string(self), self->closefd ? "True" : "False"); - } - else { - res = PyUnicode_FromFormat( - "<_io.FileIO name=%R mode='%s' closefd=%s>", - nameobj, mode_string(self), self->closefd ? "True" : "False"); - Py_DECREF(nameobj); - } - return res; -} - -static PyObject * -fileio_isatty(fileio *self) -{ - long res; - - if (self->fd < 0) - return err_closed(); - Py_BEGIN_ALLOW_THREADS - _Py_BEGIN_SUPPRESS_IPH - if (_PyVerify_fd(self->fd)) - res = isatty(self->fd); - else - res = 0; - _Py_END_SUPPRESS_IPH - Py_END_ALLOW_THREADS - return PyBool_FromLong(res); -} - -static PyObject * -fileio_getstate(fileio *self) -{ - PyErr_Format(PyExc_TypeError, - "cannot serialize '%s' object", Py_TYPE(self)->tp_name); - return NULL; -} - - -PyDoc_STRVAR(fileio_doc, -"file(name: str[, mode: str][, opener: None]) -> file IO object\n" +PyDoc_STRVAR(_io_FileIO___init____doc__, +"FileIO(file, mode=\'r\', closefd=True, opener=None)\n" +"--\n" "\n" -"Open a file. The mode can be 'r' (default), 'w', 'x' or 'a' for reading,\n" +"Open a file.\n" +"\n" +"The mode can be \'r\' (default), \'w\', \'x\' or \'a\' for reading,\n" "writing, exclusive creation or appending. The file will be created if it\n" -"doesn't exist when opened for writing or appending; it will be truncated\n" +"doesn\'t exist when opened for writing or appending; it will be truncated\n" "when opened for writing. A FileExistsError will be raised if it already\n" "exists when opened for creating. Opening a file for creating implies\n" -"writing so this mode behaves in a similar way to 'w'.Add a '+' to the mode\n" +"writing so this mode behaves in a similar way to \'w\'.Add a \'+\' to the mode\n" "to allow simultaneous reading and writing. A custom opener can be used by\n" "passing a callable as *opener*. The underlying file descriptor for the file\n" "object is then obtained by calling opener with (*name*, *flags*).\n" "*opener* must return an open file descriptor (passing os.open as *opener*\n" "results in functionality similar to passing None)."); -PyDoc_STRVAR(read_doc, -"read(size: int) -> bytes. read at most size bytes, returned as bytes.\n" +static int +_io_FileIO___init___impl(fileio *self, PyObject *nameobj, const char *mode, + int closefd, PyObject *opener); + +static int +_io_FileIO___init__(PyObject *self, PyObject *args, PyObject *kwargs) +{ + int return_value = -1; + static char *_keywords[] = {"file", "mode", "closefd", "opener", NULL}; + PyObject *nameobj; + const char *mode = "r"; + int closefd = 1; + PyObject *opener = Py_None; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, + "O|siO:FileIO", _keywords, + &nameobj, &mode, &closefd, &opener)) + goto exit; + return_value = _io_FileIO___init___impl((fileio *)self, nameobj, mode, closefd, opener); + +exit: + return return_value; +} + +PyDoc_STRVAR(_io_FileIO_fileno__doc__, +"fileno($self, /)\n" +"--\n" "\n" -"Only makes one system call, so less data may be returned than requested\n" -"In non-blocking mode, returns None if no data is available.\n" -"Return an empty bytes object at EOF."); +"Return the underlying file descriptor (an integer)."); -PyDoc_STRVAR(readall_doc, -"readall() -> bytes. read all data from the file, returned as bytes.\n" +#define _IO_FILEIO_FILENO_METHODDEF \ + {"fileno", (PyCFunction)_io_FileIO_fileno, METH_NOARGS, _io_FileIO_fileno__doc__}, + +static PyObject * +_io_FileIO_fileno_impl(fileio *self); + +static PyObject * +_io_FileIO_fileno(fileio *self, PyObject *Py_UNUSED(ignored)) +{ + return _io_FileIO_fileno_impl(self); +} + +PyDoc_STRVAR(_io_FileIO_readable__doc__, +"readable($self, /)\n" +"--\n" +"\n" +"True if file was opened in a read mode."); + +#define _IO_FILEIO_READABLE_METHODDEF \ + {"readable", (PyCFunction)_io_FileIO_readable, METH_NOARGS, _io_FileIO_readable__doc__}, + +static PyObject * +_io_FileIO_readable_impl(fileio *self); + +static PyObject * +_io_FileIO_readable(fileio *self, PyObject *Py_UNUSED(ignored)) +{ + return _io_FileIO_readable_impl(self); +} + +PyDoc_STRVAR(_io_FileIO_writable__doc__, +"writable($self, /)\n" +"--\n" +"\n" +"True if file was opened in a write mode."); + +#define _IO_FILEIO_WRITABLE_METHODDEF \ + {"writable", (PyCFunction)_io_FileIO_writable, METH_NOARGS, _io_FileIO_writable__doc__}, + +static PyObject * +_io_FileIO_writable_impl(fileio *self); + +static PyObject * +_io_FileIO_writable(fileio *self, PyObject *Py_UNUSED(ignored)) +{ + return _io_FileIO_writable_impl(self); +} + +PyDoc_STRVAR(_io_FileIO_seekable__doc__, +"seekable($self, /)\n" +"--\n" +"\n" +"True if file supports random-access."); + +#define _IO_FILEIO_SEEKABLE_METHODDEF \ + {"seekable", (PyCFunction)_io_FileIO_seekable, METH_NOARGS, _io_FileIO_seekable__doc__}, + +static PyObject * +_io_FileIO_seekable_impl(fileio *self); + +static PyObject * +_io_FileIO_seekable(fileio *self, PyObject *Py_UNUSED(ignored)) +{ + return _io_FileIO_seekable_impl(self); +} + +PyDoc_STRVAR(_io_FileIO_readinto__doc__, +"readinto($self, buffer, /)\n" +"--\n" +"\n" +"Same as RawIOBase.readinto()."); + +#define _IO_FILEIO_READINTO_METHODDEF \ + {"readinto", (PyCFunction)_io_FileIO_readinto, METH_O, _io_FileIO_readinto__doc__}, + +static PyObject * +_io_FileIO_readinto_impl(fileio *self, Py_buffer *buffer); + +static PyObject * +_io_FileIO_readinto(fileio *self, PyObject *arg) +{ + PyObject *return_value = NULL; + Py_buffer buffer = {NULL, NULL}; + + if (!PyArg_Parse(arg, + "w*:readinto", + &buffer)) + goto exit; + return_value = _io_FileIO_readinto_impl(self, &buffer); + +exit: + /* Cleanup for buffer */ + if (buffer.obj) + PyBuffer_Release(&buffer); + + return return_value; +} + +PyDoc_STRVAR(_io_FileIO_readall__doc__, +"readall($self, /)\n" +"--\n" +"\n" +"Read all data from the file, returned as bytes.\n" "\n" "In non-blocking mode, returns as much as is immediately available,\n" "or None if no data is available. Return an empty bytes object at EOF."); -PyDoc_STRVAR(write_doc, -"write(b: bytes) -> int. Write bytes b to file, return number written.\n" +#define _IO_FILEIO_READALL_METHODDEF \ + {"readall", (PyCFunction)_io_FileIO_readall, METH_NOARGS, _io_FileIO_readall__doc__}, + +static PyObject * +_io_FileIO_readall_impl(fileio *self); + +static PyObject * +_io_FileIO_readall(fileio *self, PyObject *Py_UNUSED(ignored)) +{ + return _io_FileIO_readall_impl(self); +} + +PyDoc_STRVAR(_io_FileIO_read__doc__, +"read($self, size=-1, /)\n" +"--\n" +"\n" +"Read at most size bytes, returned as bytes.\n" +"\n" +"Only makes one system call, so less data may be returned than requested.\n" +"In non-blocking mode, returns None if no data is available.\n" +"Return an empty bytes object at EOF."); + +#define _IO_FILEIO_READ_METHODDEF \ + {"read", (PyCFunction)_io_FileIO_read, METH_VARARGS, _io_FileIO_read__doc__}, + +static PyObject * +_io_FileIO_read_impl(fileio *self, Py_ssize_t size); + +static PyObject * +_io_FileIO_read(fileio *self, PyObject *args) +{ + PyObject *return_value = NULL; + Py_ssize_t size = -1; + + if (!PyArg_ParseTuple(args, + "|O&:read", + _PyIO_ConvertSsize_t, &size)) + goto exit; + return_value = _io_FileIO_read_impl(self, size); + +exit: + return return_value; +} + +PyDoc_STRVAR(_io_FileIO_write__doc__, +"write($self, b, /)\n" +"--\n" +"\n" +"Write bytes b to file, return number written.\n" "\n" "Only makes one system call, so not all of the data may be written.\n" "The number of bytes actually written is returned. In non-blocking mode,\n" -"returns None if the write would block." -); +"returns None if the write would block."); -PyDoc_STRVAR(fileno_doc, -"fileno() -> int. Return the underlying file descriptor (an integer)."); +#define _IO_FILEIO_WRITE_METHODDEF \ + {"write", (PyCFunction)_io_FileIO_write, METH_O, _io_FileIO_write__doc__}, -PyDoc_STRVAR(seek_doc, -"seek(offset: int[, whence: int]) -> int. Move to new file position and\n" -"return the file position.\n" +static PyObject * +_io_FileIO_write_impl(fileio *self, Py_buffer *b); + +static PyObject * +_io_FileIO_write(fileio *self, PyObject *arg) +{ + PyObject *return_value = NULL; + Py_buffer b = {NULL, NULL}; + + if (!PyArg_Parse(arg, + "y*:write", + &b)) + goto exit; + return_value = _io_FileIO_write_impl(self, &b); + +exit: + /* Cleanup for b */ + if (b.obj) + PyBuffer_Release(&b); + + return return_value; +} + +PyDoc_STRVAR(_io_FileIO_seek__doc__, +"seek($self, pos, whence=0, /)\n" +"--\n" +"\n" +"Move to new file position and return the file position.\n" "\n" "Argument offset is a byte count. Optional argument whence defaults to\n" "SEEK_SET or 0 (offset from start of file, offset should be >= 0); other values\n" @@ -1030,145 +272,103 @@ "\n" "Note that not all file objects are seekable."); -#ifdef HAVE_FTRUNCATE -PyDoc_STRVAR(truncate_doc, -"truncate([size: int]) -> int. Truncate the file to at most size bytes\n" -"and return the truncated size.\n" +#define _IO_FILEIO_SEEK_METHODDEF \ + {"seek", (PyCFunction)_io_FileIO_seek, METH_VARARGS, _io_FileIO_seek__doc__}, + +static PyObject * +_io_FileIO_seek_impl(fileio *self, PyObject *pos, int whence); + +static PyObject * +_io_FileIO_seek(fileio *self, PyObject *args) +{ + PyObject *return_value = NULL; + PyObject *pos; + int whence = 0; + + if (!PyArg_ParseTuple(args, + "O|i:seek", + &pos, &whence)) + goto exit; + return_value = _io_FileIO_seek_impl(self, pos, whence); + +exit: + return return_value; +} + +PyDoc_STRVAR(_io_FileIO_tell__doc__, +"tell($self, /)\n" +"--\n" +"\n" +"Current file position.\n" +"\n" +"Can raise OSError for non seekable files."); + +#define _IO_FILEIO_TELL_METHODDEF \ + {"tell", (PyCFunction)_io_FileIO_tell, METH_NOARGS, _io_FileIO_tell__doc__}, + +static PyObject * +_io_FileIO_tell_impl(fileio *self); + +static PyObject * +_io_FileIO_tell(fileio *self, PyObject *Py_UNUSED(ignored)) +{ + return _io_FileIO_tell_impl(self); +} + +#if defined(HAVE_FTRUNCATE) + +PyDoc_STRVAR(_io_FileIO_truncate__doc__, +"truncate($self, size=None, /)\n" +"--\n" +"\n" +"Truncate the file to at most size bytes and return the truncated size.\n" "\n" "Size defaults to the current file position, as returned by tell().\n" "The current file position is changed to the value of size."); -#endif -PyDoc_STRVAR(tell_doc, -"tell() -> int. Current file position.\n" -"\n" -"Can raise OSError for non seekable files." -); - -PyDoc_STRVAR(readinto_doc, -"readinto() -> Same as RawIOBase.readinto()."); - -PyDoc_STRVAR(close_doc, -"close() -> None. Close the file.\n" -"\n" -"A closed file cannot be used for further I/O operations. close() may be\n" -"called more than once without error."); - -PyDoc_STRVAR(isatty_doc, -"isatty() -> bool. True if the file is connected to a TTY device."); - -PyDoc_STRVAR(seekable_doc, -"seekable() -> bool. True if file supports random-access."); - -PyDoc_STRVAR(readable_doc, -"readable() -> bool. True if file was opened in a read mode."); - -PyDoc_STRVAR(writable_doc, -"writable() -> bool. True if file was opened in a write mode."); - -static PyMethodDef fileio_methods[] = { - {"read", (PyCFunction)fileio_read, METH_VARARGS, read_doc}, - {"readall", (PyCFunction)fileio_readall, METH_NOARGS, readall_doc}, - {"readinto", (PyCFunction)fileio_readinto, METH_VARARGS, readinto_doc}, - {"write", (PyCFunction)fileio_write, METH_VARARGS, write_doc}, - {"seek", (PyCFunction)fileio_seek, METH_VARARGS, seek_doc}, - {"tell", (PyCFunction)fileio_tell, METH_VARARGS, tell_doc}, -#ifdef HAVE_FTRUNCATE - {"truncate", (PyCFunction)fileio_truncate, METH_VARARGS, truncate_doc}, -#endif - {"close", (PyCFunction)fileio_close, METH_NOARGS, close_doc}, - {"seekable", (PyCFunction)fileio_seekable, METH_NOARGS, seekable_doc}, - {"readable", (PyCFunction)fileio_readable, METH_NOARGS, readable_doc}, - {"writable", (PyCFunction)fileio_writable, METH_NOARGS, writable_doc}, - {"fileno", (PyCFunction)fileio_fileno, METH_NOARGS, fileno_doc}, - {"isatty", (PyCFunction)fileio_isatty, METH_NOARGS, isatty_doc}, - {"_dealloc_warn", (PyCFunction)fileio_dealloc_warn, METH_O, NULL}, - {"__getstate__", (PyCFunction)fileio_getstate, METH_NOARGS, NULL}, - {NULL, NULL} /* sentinel */ -}; - -/* 'closed' and 'mode' are attributes for backwards compatibility reasons. */ +#define _IO_FILEIO_TRUNCATE_METHODDEF \ + {"truncate", (PyCFunction)_io_FileIO_truncate, METH_VARARGS, _io_FileIO_truncate__doc__}, static PyObject * -get_closed(fileio *self, void *closure) +_io_FileIO_truncate_impl(fileio *self, PyObject *posobj); + +static PyObject * +_io_FileIO_truncate(fileio *self, PyObject *args) { - return PyBool_FromLong((long)(self->fd < 0)); + PyObject *return_value = NULL; + PyObject *posobj = NULL; + + if (!PyArg_UnpackTuple(args, "truncate", + 0, 1, + &posobj)) + goto exit; + return_value = _io_FileIO_truncate_impl(self, posobj); + +exit: + return return_value; } +#endif /* defined(HAVE_FTRUNCATE) */ + +PyDoc_STRVAR(_io_FileIO_isatty__doc__, +"isatty($self, /)\n" +"--\n" +"\n" +"True if the file is connected to a TTY device."); + +#define _IO_FILEIO_ISATTY_METHODDEF \ + {"isatty", (PyCFunction)_io_FileIO_isatty, METH_NOARGS, _io_FileIO_isatty__doc__}, + static PyObject * -get_closefd(fileio *self, void *closure) +_io_FileIO_isatty_impl(fileio *self); + +static PyObject * +_io_FileIO_isatty(fileio *self, PyObject *Py_UNUSED(ignored)) { - return PyBool_FromLong((long)(self->closefd)); + return _io_FileIO_isatty_impl(self); } -static PyObject * -get_mode(fileio *self, void *closure) -{ - return PyUnicode_FromString(mode_string(self)); -} - -static PyGetSetDef fileio_getsetlist[] = { - {"closed", (getter)get_closed, NULL, "True if the file is closed"}, - {"closefd", (getter)get_closefd, NULL, - "True if the file descriptor will be closed by close()."}, - {"mode", (getter)get_mode, NULL, "String giving the file mode"}, - {NULL}, -}; - -static PyMemberDef fileio_members[] = { - {"_blksize", T_UINT, offsetof(fileio, blksize), 0}, - {"_finalizing", T_BOOL, offsetof(fileio, finalizing), 0}, - {NULL} -}; - -PyTypeObject PyFileIO_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "_io.FileIO", - sizeof(fileio), - 0, - (destructor)fileio_dealloc, /* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_reserved */ - (reprfunc)fileio_repr, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - PyObject_GenericGetAttr, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE - | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_FINALIZE, /* tp_flags */ - fileio_doc, /* tp_doc */ - (traverseproc)fileio_traverse, /* tp_traverse */ - (inquiry)fileio_clear, /* tp_clear */ - 0, /* tp_richcompare */ - offsetof(fileio, weakreflist), /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - fileio_methods, /* tp_methods */ - fileio_members, /* tp_members */ - fileio_getsetlist, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - offsetof(fileio, dict), /* tp_dictoffset */ - fileio_init, /* tp_init */ - PyType_GenericAlloc, /* tp_alloc */ - fileio_new, /* tp_new */ - PyObject_GC_Del, /* tp_free */ - 0, /* tp_is_gc */ - 0, /* tp_bases */ - 0, /* tp_mro */ - 0, /* tp_cache */ - 0, /* tp_subclasses */ - 0, /* tp_weaklist */ - 0, /* tp_del */ - 0, /* tp_version_tag */ - 0, /* tp_finalize */ -}; +#ifndef _IO_FILEIO_TRUNCATE_METHODDEF + #define _IO_FILEIO_TRUNCATE_METHODDEF +#endif /* !defined(_IO_FILEIO_TRUNCATE_METHODDEF) */ +/*[clinic end generated code: output=c6708e1980f6e02d input=a9049054013a1b77]*/ diff --git a/Modules/_io/iobase.c b/Modules/_io/clinic/iobase.c.h copy from Modules/_io/iobase.c copy to Modules/_io/clinic/iobase.c.h --- a/Modules/_io/iobase.c +++ b/Modules/_io/clinic/iobase.c.h @@ -1,950 +1,282 @@ -/* - An implementation of the I/O abstract base classes hierarchy - as defined by PEP 3116 - "New I/O" +/*[clinic input] +preserve +[clinic start generated code]*/ - Classes defined here: IOBase, RawIOBase. +PyDoc_STRVAR(_io__IOBase_tell__doc__, +"tell($self, /)\n" +"--\n" +"\n" +"Return current stream position."); - Written by Amaury Forgeot d'Arc and Antoine Pitrou -*/ +#define _IO__IOBASE_TELL_METHODDEF \ + {"tell", (PyCFunction)_io__IOBase_tell, METH_NOARGS, _io__IOBase_tell__doc__}, +static PyObject * +_io__IOBase_tell_impl(PyObject *self); -#define PY_SSIZE_T_CLEAN -#include "Python.h" -#include "structmember.h" -#include "_iomodule.h" - -/* - * IOBase class, an abstract class - */ - -typedef struct { - PyObject_HEAD - - PyObject *dict; - PyObject *weakreflist; -} iobase; - -PyDoc_STRVAR(iobase_doc, - "The abstract base class for all I/O classes, acting on streams of\n" - "bytes. There is no public constructor.\n" - "\n" - "This class provides dummy implementations for many methods that\n" - "derived classes can override selectively; the default implementations\n" - "represent a file that cannot be read, written or seeked.\n" - "\n" - "Even though IOBase does not declare read, readinto, or write because\n" - "their signatures will vary, implementations and clients should\n" - "consider those methods part of the interface. Also, implementations\n" - "may raise UnsupportedOperation when operations they do not support are\n" - "called.\n" - "\n" - "The basic type used for binary data read from or written to a file is\n" - "bytes. bytearrays are accepted too, and in some cases (such as\n" - "readinto) needed. Text I/O classes work with str data.\n" - "\n" - "Note that calling any method (except additional calls to close(),\n" - "which are ignored) on a closed stream should raise a ValueError.\n" - "\n" - "IOBase (and its subclasses) support the iterator protocol, meaning\n" - "that an IOBase object can be iterated over yielding the lines in a\n" - "stream.\n" - "\n" - "IOBase also supports the :keyword:`with` statement. In this example,\n" - "fp is closed after the suite of the with statement is complete:\n" - "\n" - "with open('spam.txt', 'r') as fp:\n" - " fp.write('Spam and eggs!')\n"); - -/* Use this macro whenever you want to check the internal `closed` status - of the IOBase object rather than the virtual `closed` attribute as returned - by whatever subclass. */ - -_Py_IDENTIFIER(__IOBase_closed); -#define IS_CLOSED(self) \ - _PyObject_HasAttrId(self, &PyId___IOBase_closed) - -_Py_IDENTIFIER(read); - -/* Internal methods */ static PyObject * -iobase_unsupported(const char *message) +_io__IOBase_tell(PyObject *self, PyObject *Py_UNUSED(ignored)) { - _PyIO_State *state = IO_STATE(); - if (state != NULL) - PyErr_SetString(state->unsupported_operation, message); - return NULL; + return _io__IOBase_tell_impl(self); } -/* Positionning */ +PyDoc_STRVAR(_io__IOBase_flush__doc__, +"flush($self, /)\n" +"--\n" +"\n" +"Flush write buffers, if applicable.\n" +"\n" +"This is not implemented for read-only and non-blocking streams."); -PyDoc_STRVAR(iobase_seek_doc, - "Change stream position.\n" - "\n" - "Change the stream position to the given byte offset. The offset is\n" - "interpreted relative to the position indicated by whence. Values\n" - "for whence are:\n" - "\n" - "* 0 -- start of stream (the default); offset should be zero or positive\n" - "* 1 -- current stream position; offset may be negative\n" - "* 2 -- end of stream; offset is usually negative\n" - "\n" - "Return the new absolute position."); +#define _IO__IOBASE_FLUSH_METHODDEF \ + {"flush", (PyCFunction)_io__IOBase_flush, METH_NOARGS, _io__IOBase_flush__doc__}, static PyObject * -iobase_seek(PyObject *self, PyObject *args) +_io__IOBase_flush_impl(PyObject *self); + +static PyObject * +_io__IOBase_flush(PyObject *self, PyObject *Py_UNUSED(ignored)) { - return iobase_unsupported("seek"); + return _io__IOBase_flush_impl(self); } -PyDoc_STRVAR(iobase_tell_doc, - "Return current stream position."); +PyDoc_STRVAR(_io__IOBase_close__doc__, +"close($self, /)\n" +"--\n" +"\n" +"Flush and close the IO object.\n" +"\n" +"This method has no effect if the file is already closed."); + +#define _IO__IOBASE_CLOSE_METHODDEF \ + {"close", (PyCFunction)_io__IOBase_close, METH_NOARGS, _io__IOBase_close__doc__}, static PyObject * -iobase_tell(PyObject *self, PyObject *args) +_io__IOBase_close_impl(PyObject *self); + +static PyObject * +_io__IOBase_close(PyObject *self, PyObject *Py_UNUSED(ignored)) { - _Py_IDENTIFIER(seek); - - return _PyObject_CallMethodId(self, &PyId_seek, "ii", 0, 1); + return _io__IOBase_close_impl(self); } -PyDoc_STRVAR(iobase_truncate_doc, - "Truncate file to size bytes.\n" - "\n" - "File pointer is left unchanged. Size defaults to the current IO\n" - "position as reported by tell(). Returns the new size."); +PyDoc_STRVAR(_io__IOBase_seekable__doc__, +"seekable($self, /)\n" +"--\n" +"\n" +"Return whether object supports random access.\n" +"\n" +"If False, seek(), tell() and truncate() will raise UnsupportedOperation.\n" +"This method may need to do a test seek()."); + +#define _IO__IOBASE_SEEKABLE_METHODDEF \ + {"seekable", (PyCFunction)_io__IOBase_seekable, METH_NOARGS, _io__IOBase_seekable__doc__}, static PyObject * -iobase_truncate(PyObject *self, PyObject *args) +_io__IOBase_seekable_impl(PyObject *self); + +static PyObject * +_io__IOBase_seekable(PyObject *self, PyObject *Py_UNUSED(ignored)) { - return iobase_unsupported("truncate"); + return _io__IOBase_seekable_impl(self); } -/* Flush and close methods */ +PyDoc_STRVAR(_io__IOBase_readable__doc__, +"readable($self, /)\n" +"--\n" +"\n" +"Return whether object was opened for reading.\n" +"\n" +"If False, read() will raise UnsupportedOperation."); -PyDoc_STRVAR(iobase_flush_doc, - "Flush write buffers, if applicable.\n" - "\n" - "This is not implemented for read-only and non-blocking streams.\n"); +#define _IO__IOBASE_READABLE_METHODDEF \ + {"readable", (PyCFunction)_io__IOBase_readable, METH_NOARGS, _io__IOBase_readable__doc__}, static PyObject * -iobase_flush(PyObject *self, PyObject *args) +_io__IOBase_readable_impl(PyObject *self); + +static PyObject * +_io__IOBase_readable(PyObject *self, PyObject *Py_UNUSED(ignored)) { - /* XXX Should this return the number of bytes written??? */ - if (IS_CLOSED(self)) { - PyErr_SetString(PyExc_ValueError, "I/O operation on closed file."); - return NULL; - } - Py_RETURN_NONE; + return _io__IOBase_readable_impl(self); } -PyDoc_STRVAR(iobase_close_doc, - "Flush and close the IO object.\n" - "\n" - "This method has no effect if the file is already closed.\n"); +PyDoc_STRVAR(_io__IOBase_writable__doc__, +"writable($self, /)\n" +"--\n" +"\n" +"Return whether object was opened for writing.\n" +"\n" +"If False, write() will raise UnsupportedOperation."); -static int -iobase_closed(PyObject *self) +#define _IO__IOBASE_WRITABLE_METHODDEF \ + {"writable", (PyCFunction)_io__IOBase_writable, METH_NOARGS, _io__IOBase_writable__doc__}, + +static PyObject * +_io__IOBase_writable_impl(PyObject *self); + +static PyObject * +_io__IOBase_writable(PyObject *self, PyObject *Py_UNUSED(ignored)) { - PyObject *res; - int closed; - /* This gets the derived attribute, which is *not* __IOBase_closed - in most cases! */ - res = PyObject_GetAttr(self, _PyIO_str_closed); - if (res == NULL) - return 0; - closed = PyObject_IsTrue(res); - Py_DECREF(res); - return closed; + return _io__IOBase_writable_impl(self); } +PyDoc_STRVAR(_io__IOBase_fileno__doc__, +"fileno($self, /)\n" +"--\n" +"\n" +"Returns underlying file descriptor if one exists.\n" +"\n" +"An IOError is raised if the IO object does not use a file descriptor."); + +#define _IO__IOBASE_FILENO_METHODDEF \ + {"fileno", (PyCFunction)_io__IOBase_fileno, METH_NOARGS, _io__IOBase_fileno__doc__}, + static PyObject * -iobase_closed_get(PyObject *self, void *context) +_io__IOBase_fileno_impl(PyObject *self); + +static PyObject * +_io__IOBase_fileno(PyObject *self, PyObject *Py_UNUSED(ignored)) { - return PyBool_FromLong(IS_CLOSED(self)); + return _io__IOBase_fileno_impl(self); } -PyObject * -_PyIOBase_check_closed(PyObject *self, PyObject *args) +PyDoc_STRVAR(_io__IOBase_isatty__doc__, +"isatty($self, /)\n" +"--\n" +"\n" +"Return whether this is an \'interactive\' stream.\n" +"\n" +"Return False if it can\'t be determined."); + +#define _IO__IOBASE_ISATTY_METHODDEF \ + {"isatty", (PyCFunction)_io__IOBase_isatty, METH_NOARGS, _io__IOBase_isatty__doc__}, + +static PyObject * +_io__IOBase_isatty_impl(PyObject *self); + +static PyObject * +_io__IOBase_isatty(PyObject *self, PyObject *Py_UNUSED(ignored)) { - if (iobase_closed(self)) { - PyErr_SetString(PyExc_ValueError, "I/O operation on closed file."); - return NULL; - } - if (args == Py_True) - return Py_None; - else - Py_RETURN_NONE; + return _io__IOBase_isatty_impl(self); } -/* XXX: IOBase thinks it has to maintain its own internal state in - `__IOBase_closed` and call flush() by itself, but it is redundant with - whatever behaviour a non-trivial derived class will implement. */ +PyDoc_STRVAR(_io__IOBase_readline__doc__, +"readline($self, size=-1, /)\n" +"--\n" +"\n" +"Read and return a line from the stream.\n" +"\n" +"If size is specified, at most size bytes will be read.\n" +"\n" +"The line terminator is always b\'\\n\' for binary files; for text\n" +"files, the newlines argument to open can be used to select the line\n" +"terminator(s) recognized."); + +#define _IO__IOBASE_READLINE_METHODDEF \ + {"readline", (PyCFunction)_io__IOBase_readline, METH_VARARGS, _io__IOBase_readline__doc__}, static PyObject * -iobase_close(PyObject *self, PyObject *args) +_io__IOBase_readline_impl(PyObject *self, Py_ssize_t limit); + +static PyObject * +_io__IOBase_readline(PyObject *self, PyObject *args) { - PyObject *res; + PyObject *return_value = NULL; + Py_ssize_t limit = -1; - if (IS_CLOSED(self)) - Py_RETURN_NONE; + if (!PyArg_ParseTuple(args, + "|O&:readline", + _PyIO_ConvertSsize_t, &limit)) + goto exit; + return_value = _io__IOBase_readline_impl(self, limit); - res = PyObject_CallMethodObjArgs(self, _PyIO_str_flush, NULL); - - if (_PyObject_SetAttrId(self, &PyId___IOBase_closed, Py_True) < 0) { - Py_XDECREF(res); - return NULL; - } - - if (res == NULL) - return NULL; - - Py_DECREF(res); - Py_RETURN_NONE; +exit: + return return_value; } -/* Finalization and garbage collection support */ +PyDoc_STRVAR(_io__IOBase_readlines__doc__, +"readlines($self, hint=-1, /)\n" +"--\n" +"\n" +"Return a list of lines from the stream.\n" +"\n" +"hint can be specified to control the number of lines read: no more\n" +"lines will be read if the total size (in bytes/characters) of all\n" +"lines so far exceeds hint."); -static void -iobase_finalize(PyObject *self) +#define _IO__IOBASE_READLINES_METHODDEF \ + {"readlines", (PyCFunction)_io__IOBase_readlines, METH_VARARGS, _io__IOBase_readlines__doc__}, + +static PyObject * +_io__IOBase_readlines_impl(PyObject *self, Py_ssize_t hint); + +static PyObject * +_io__IOBase_readlines(PyObject *self, PyObject *args) { - PyObject *res; - PyObject *error_type, *error_value, *error_traceback; - int closed; - _Py_IDENTIFIER(_finalizing); + PyObject *return_value = NULL; + Py_ssize_t hint = -1; - /* Save the current exception, if any. */ - PyErr_Fetch(&error_type, &error_value, &error_traceback); + if (!PyArg_ParseTuple(args, + "|O&:readlines", + _PyIO_ConvertSsize_t, &hint)) + goto exit; + return_value = _io__IOBase_readlines_impl(self, hint); - /* If `closed` doesn't exist or can't be evaluated as bool, then the - object is probably in an unusable state, so ignore. */ - res = PyObject_GetAttr(self, _PyIO_str_closed); - if (res == NULL) { - PyErr_Clear(); - closed = -1; - } - else { - closed = PyObject_IsTrue(res); - Py_DECREF(res); - if (closed == -1) - PyErr_Clear(); - } - if (closed == 0) { - /* Signal close() that it was called as part of the object - finalization process. */ - if (_PyObject_SetAttrId(self, &PyId__finalizing, Py_True)) - PyErr_Clear(); - res = PyObject_CallMethodObjArgs((PyObject *) self, _PyIO_str_close, - NULL); - /* Silencing I/O errors is bad, but printing spurious tracebacks is - equally as bad, and potentially more frequent (because of - shutdown issues). */ - if (res == NULL) - PyErr_Clear(); - else - Py_DECREF(res); - } - - /* Restore the saved exception. */ - PyErr_Restore(error_type, error_value, error_traceback); +exit: + return return_value; } -int -_PyIOBase_finalize(PyObject *self) +PyDoc_STRVAR(_io__IOBase_writelines__doc__, +"writelines($self, lines, /)\n" +"--\n" +"\n"); + +#define _IO__IOBASE_WRITELINES_METHODDEF \ + {"writelines", (PyCFunction)_io__IOBase_writelines, METH_O, _io__IOBase_writelines__doc__}, + +PyDoc_STRVAR(_io__RawIOBase_read__doc__, +"read($self, size=-1, /)\n" +"--\n" +"\n"); + +#define _IO__RAWIOBASE_READ_METHODDEF \ + {"read", (PyCFunction)_io__RawIOBase_read, METH_VARARGS, _io__RawIOBase_read__doc__}, + +static PyObject * +_io__RawIOBase_read_impl(PyObject *self, Py_ssize_t n); + +static PyObject * +_io__RawIOBase_read(PyObject *self, PyObject *args) { - int is_zombie; + PyObject *return_value = NULL; + Py_ssize_t n = -1; - /* If _PyIOBase_finalize() is called from a destructor, we need to - resurrect the object as calling close() can invoke arbitrary code. */ - is_zombie = (Py_REFCNT(self) == 0); - if (is_zombie) - return PyObject_CallFinalizerFromDealloc(self); - else { - PyObject_CallFinalizer(self); - return 0; - } + if (!PyArg_ParseTuple(args, + "|n:read", + &n)) + goto exit; + return_value = _io__RawIOBase_read_impl(self, n); + +exit: + return return_value; } -static int -iobase_traverse(iobase *self, visitproc visit, void *arg) -{ - Py_VISIT(self->dict); - return 0; -} +PyDoc_STRVAR(_io__RawIOBase_readall__doc__, +"readall($self, /)\n" +"--\n" +"\n" +"Read until EOF, using multiple read() call."); -static int -iobase_clear(iobase *self) -{ - Py_CLEAR(self->dict); - return 0; -} - -/* Destructor */ - -static void -iobase_dealloc(iobase *self) -{ - /* NOTE: since IOBaseObject has its own dict, Python-defined attributes - are still available here for close() to use. - However, if the derived class declares a __slots__, those slots are - already gone. - */ - if (_PyIOBase_finalize((PyObject *) self) < 0) { - /* When called from a heap type's dealloc, the type will be - decref'ed on return (see e.g. subtype_dealloc in typeobject.c). */ - if (PyType_HasFeature(Py_TYPE(self), Py_TPFLAGS_HEAPTYPE)) - Py_INCREF(Py_TYPE(self)); - return; - } - _PyObject_GC_UNTRACK(self); - if (self->weakreflist != NULL) - PyObject_ClearWeakRefs((PyObject *) self); - Py_CLEAR(self->dict); - Py_TYPE(self)->tp_free((PyObject *) self); -} - -/* Inquiry methods */ - -PyDoc_STRVAR(iobase_seekable_doc, - "Return whether object supports random access.\n" - "\n" - "If False, seek(), tell() and truncate() will raise UnsupportedOperation.\n" - "This method may need to do a test seek()."); +#define _IO__RAWIOBASE_READALL_METHODDEF \ + {"readall", (PyCFunction)_io__RawIOBase_readall, METH_NOARGS, _io__RawIOBase_readall__doc__}, static PyObject * -iobase_seekable(PyObject *self, PyObject *args) -{ - Py_RETURN_FALSE; -} - -PyObject * -_PyIOBase_check_seekable(PyObject *self, PyObject *args) -{ - PyObject *res = PyObject_CallMethodObjArgs(self, _PyIO_str_seekable, NULL); - if (res == NULL) - return NULL; - if (res != Py_True) { - Py_CLEAR(res); - iobase_unsupported("File or stream is not seekable."); - return NULL; - } - if (args == Py_True) { - Py_DECREF(res); - } - return res; -} - -PyDoc_STRVAR(iobase_readable_doc, - "Return whether object was opened for reading.\n" - "\n" - "If False, read() will raise UnsupportedOperation."); +_io__RawIOBase_readall_impl(PyObject *self); static PyObject * -iobase_readable(PyObject *self, PyObject *args) +_io__RawIOBase_readall(PyObject *self, PyObject *Py_UNUSED(ignored)) { - Py_RETURN_FALSE; + return _io__RawIOBase_readall_impl(self); } - -/* May be called with any object */ -PyObject * -_PyIOBase_check_readable(PyObject *self, PyObject *args) -{ - PyObject *res = PyObject_CallMethodObjArgs(self, _PyIO_str_readable, NULL); - if (res == NULL) - return NULL; - if (res != Py_True) { - Py_CLEAR(res); - iobase_unsupported("File or stream is not readable."); - return NULL; - } - if (args == Py_True) { - Py_DECREF(res); - } - return res; -} - -PyDoc_STRVAR(iobase_writable_doc, - "Return whether object was opened for writing.\n" - "\n" - "If False, write() will raise UnsupportedOperation."); - -static PyObject * -iobase_writable(PyObject *self, PyObject *args) -{ - Py_RETURN_FALSE; -} - -/* May be called with any object */ -PyObject * -_PyIOBase_check_writable(PyObject *self, PyObject *args) -{ - PyObject *res = PyObject_CallMethodObjArgs(self, _PyIO_str_writable, NULL); - if (res == NULL) - return NULL; - if (res != Py_True) { - Py_CLEAR(res); - iobase_unsupported("File or stream is not writable."); - return NULL; - } - if (args == Py_True) { - Py_DECREF(res); - } - return res; -} - -/* Context manager */ - -static PyObject * -iobase_enter(PyObject *self, PyObject *args) -{ - if (_PyIOBase_check_closed(self, Py_True) == NULL) - return NULL; - - Py_INCREF(self); - return self; -} - -static PyObject * -iobase_exit(PyObject *self, PyObject *args) -{ - return PyObject_CallMethodObjArgs(self, _PyIO_str_close, NULL); -} - -/* Lower-level APIs */ - -/* XXX Should these be present even if unimplemented? */ - -PyDoc_STRVAR(iobase_fileno_doc, - "Returns underlying file descriptor if one exists.\n" - "\n" - "An IOError is raised if the IO object does not use a file descriptor.\n"); - -static PyObject * -iobase_fileno(PyObject *self, PyObject *args) -{ - return iobase_unsupported("fileno"); -} - -PyDoc_STRVAR(iobase_isatty_doc, - "Return whether this is an 'interactive' stream.\n" - "\n" - "Return False if it can't be determined.\n"); - -static PyObject * -iobase_isatty(PyObject *self, PyObject *args) -{ - if (_PyIOBase_check_closed(self, Py_True) == NULL) - return NULL; - Py_RETURN_FALSE; -} - -/* Readline(s) and writelines */ - -PyDoc_STRVAR(iobase_readline_doc, - "Read and return a line from the stream.\n" - "\n" - "If limit is specified, at most limit bytes will be read.\n" - "\n" - "The line terminator is always b'\\n' for binary files; for text\n" - "files, the newlines argument to open can be used to select the line\n" - "terminator(s) recognized.\n"); - -static PyObject * -iobase_readline(PyObject *self, PyObject *args) -{ - /* For backwards compatibility, a (slowish) readline(). */ - - Py_ssize_t limit = -1; - int has_peek = 0; - PyObject *buffer, *result; - Py_ssize_t old_size = -1; - _Py_IDENTIFIER(peek); - - if (!PyArg_ParseTuple(args, "|O&:readline", &_PyIO_ConvertSsize_t, &limit)) { - return NULL; - } - - if (_PyObject_HasAttrId(self, &PyId_peek)) - has_peek = 1; - - buffer = PyByteArray_FromStringAndSize(NULL, 0); - if (buffer == NULL) - return NULL; - - while (limit < 0 || Py_SIZE(buffer) < limit) { - Py_ssize_t nreadahead = 1; - PyObject *b; - - if (has_peek) { - PyObject *readahead = _PyObject_CallMethodId(self, &PyId_peek, "i", 1); - if (readahead == NULL) { - /* NOTE: PyErr_SetFromErrno() calls PyErr_CheckSignals() - when EINTR occurs so we needn't do it ourselves. */ - if (_PyIO_trap_eintr()) { - continue; - } - goto fail; - } - if (!PyBytes_Check(readahead)) { - PyErr_Format(PyExc_IOError, - "peek() should have returned a bytes object, " - "not '%.200s'", Py_TYPE(readahead)->tp_name); - Py_DECREF(readahead); - goto fail; - } - if (PyBytes_GET_SIZE(readahead) > 0) { - Py_ssize_t n = 0; - const char *buf = PyBytes_AS_STRING(readahead); - if (limit >= 0) { - do { - if (n >= PyBytes_GET_SIZE(readahead) || n >= limit) - break; - if (buf[n++] == '\n') - break; - } while (1); - } - else { - do { - if (n >= PyBytes_GET_SIZE(readahead)) - break; - if (buf[n++] == '\n') - break; - } while (1); - } - nreadahead = n; - } - Py_DECREF(readahead); - } - - b = _PyObject_CallMethodId(self, &PyId_read, "n", nreadahead); - if (b == NULL) { - /* NOTE: PyErr_SetFromErrno() calls PyErr_CheckSignals() - when EINTR occurs so we needn't do it ourselves. */ - if (_PyIO_trap_eintr()) { - continue; - } - goto fail; - } - if (!PyBytes_Check(b)) { - PyErr_Format(PyExc_IOError, - "read() should have returned a bytes object, " - "not '%.200s'", Py_TYPE(b)->tp_name); - Py_DECREF(b); - goto fail; - } - if (PyBytes_GET_SIZE(b) == 0) { - Py_DECREF(b); - break; - } - - old_size = PyByteArray_GET_SIZE(buffer); - if (PyByteArray_Resize(buffer, old_size + PyBytes_GET_SIZE(b)) < 0) { - Py_DECREF(b); - goto fail; - } - memcpy(PyByteArray_AS_STRING(buffer) + old_size, - PyBytes_AS_STRING(b), PyBytes_GET_SIZE(b)); - - Py_DECREF(b); - - if (PyByteArray_AS_STRING(buffer)[PyByteArray_GET_SIZE(buffer) - 1] == '\n') - break; - } - - result = PyBytes_FromStringAndSize(PyByteArray_AS_STRING(buffer), - PyByteArray_GET_SIZE(buffer)); - Py_DECREF(buffer); - return result; - fail: - Py_DECREF(buffer); - return NULL; -} - -static PyObject * -iobase_iter(PyObject *self) -{ - if (_PyIOBase_check_closed(self, Py_True) == NULL) - return NULL; - - Py_INCREF(self); - return self; -} - -static PyObject * -iobase_iternext(PyObject *self) -{ - PyObject *line = PyObject_CallMethodObjArgs(self, _PyIO_str_readline, NULL); - - if (line == NULL) - return NULL; - - if (PyObject_Size(line) == 0) { - Py_DECREF(line); - return NULL; - } - - return line; -} - -PyDoc_STRVAR(iobase_readlines_doc, - "Return a list of lines from the stream.\n" - "\n" - "hint can be specified to control the number of lines read: no more\n" - "lines will be read if the total size (in bytes/characters) of all\n" - "lines so far exceeds hint."); - -static PyObject * -iobase_readlines(PyObject *self, PyObject *args) -{ - Py_ssize_t hint = -1, length = 0; - PyObject *result; - - if (!PyArg_ParseTuple(args, "|O&:readlines", &_PyIO_ConvertSsize_t, &hint)) { - return NULL; - } - - result = PyList_New(0); - if (result == NULL) - return NULL; - - if (hint <= 0) { - /* XXX special-casing this made sense in the Python version in order - to remove the bytecode interpretation overhead, but it could - probably be removed here. */ - _Py_IDENTIFIER(extend); - PyObject *ret = _PyObject_CallMethodId(result, &PyId_extend, "O", self); - - if (ret == NULL) { - Py_DECREF(result); - return NULL; - } - Py_DECREF(ret); - return result; - } - - while (1) { - PyObject *line = PyIter_Next(self); - if (line == NULL) { - if (PyErr_Occurred()) { - Py_DECREF(result); - return NULL; - } - else - break; /* StopIteration raised */ - } - - if (PyList_Append(result, line) < 0) { - Py_DECREF(line); - Py_DECREF(result); - return NULL; - } - length += PyObject_Size(line); - Py_DECREF(line); - - if (length > hint) - break; - } - return result; -} - -static PyObject * -iobase_writelines(PyObject *self, PyObject *args) -{ - PyObject *lines, *iter, *res; - - if (!PyArg_ParseTuple(args, "O:writelines", &lines)) { - return NULL; - } - - if (_PyIOBase_check_closed(self, Py_True) == NULL) - return NULL; - - iter = PyObject_GetIter(lines); - if (iter == NULL) - return NULL; - - while (1) { - PyObject *line = PyIter_Next(iter); - if (line == NULL) { - if (PyErr_Occurred()) { - Py_DECREF(iter); - return NULL; - } - else - break; /* Stop Iteration */ - } - - res = NULL; - do { - res = PyObject_CallMethodObjArgs(self, _PyIO_str_write, line, NULL); - } while (res == NULL && _PyIO_trap_eintr()); - Py_DECREF(line); - if (res == NULL) { - Py_DECREF(iter); - return NULL; - } - Py_DECREF(res); - } - Py_DECREF(iter); - Py_RETURN_NONE; -} - -static PyMethodDef iobase_methods[] = { - {"seek", iobase_seek, METH_VARARGS, iobase_seek_doc}, - {"tell", iobase_tell, METH_NOARGS, iobase_tell_doc}, - {"truncate", iobase_truncate, METH_VARARGS, iobase_truncate_doc}, - {"flush", iobase_flush, METH_NOARGS, iobase_flush_doc}, - {"close", iobase_close, METH_NOARGS, iobase_close_doc}, - - {"seekable", iobase_seekable, METH_NOARGS, iobase_seekable_doc}, - {"readable", iobase_readable, METH_NOARGS, iobase_readable_doc}, - {"writable", iobase_writable, METH_NOARGS, iobase_writable_doc}, - - {"_checkClosed", _PyIOBase_check_closed, METH_NOARGS}, - {"_checkSeekable", _PyIOBase_check_seekable, METH_NOARGS}, - {"_checkReadable", _PyIOBase_check_readable, METH_NOARGS}, - {"_checkWritable", _PyIOBase_check_writable, METH_NOARGS}, - - {"fileno", iobase_fileno, METH_NOARGS, iobase_fileno_doc}, - {"isatty", iobase_isatty, METH_NOARGS, iobase_isatty_doc}, - - {"__enter__", iobase_enter, METH_NOARGS}, - {"__exit__", iobase_exit, METH_VARARGS}, - - {"readline", iobase_readline, METH_VARARGS, iobase_readline_doc}, - {"readlines", iobase_readlines, METH_VARARGS, iobase_readlines_doc}, - {"writelines", iobase_writelines, METH_VARARGS}, - - {NULL, NULL} -}; - -static PyGetSetDef iobase_getset[] = { - {"__dict__", PyObject_GenericGetDict, NULL, NULL}, - {"closed", (getter)iobase_closed_get, NULL, NULL}, - {NULL} -}; - - -PyTypeObject PyIOBase_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "_io._IOBase", /*tp_name*/ - sizeof(iobase), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - (destructor)iobase_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare */ - 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 | Py_TPFLAGS_BASETYPE - | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_FINALIZE, /*tp_flags*/ - iobase_doc, /* tp_doc */ - (traverseproc)iobase_traverse, /* tp_traverse */ - (inquiry)iobase_clear, /* tp_clear */ - 0, /* tp_richcompare */ - offsetof(iobase, weakreflist), /* tp_weaklistoffset */ - iobase_iter, /* tp_iter */ - iobase_iternext, /* tp_iternext */ - iobase_methods, /* tp_methods */ - 0, /* tp_members */ - iobase_getset, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - offsetof(iobase, dict), /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - PyType_GenericNew, /* tp_new */ - 0, /* tp_free */ - 0, /* tp_is_gc */ - 0, /* tp_bases */ - 0, /* tp_mro */ - 0, /* tp_cache */ - 0, /* tp_subclasses */ - 0, /* tp_weaklist */ - 0, /* tp_del */ - 0, /* tp_version_tag */ - (destructor)iobase_finalize, /* tp_finalize */ -}; - - -/* - * RawIOBase class, Inherits from IOBase. - */ -PyDoc_STRVAR(rawiobase_doc, - "Base class for raw binary I/O."); - -/* - * The read() method is implemented by calling readinto(); derived classes - * that want to support read() only need to implement readinto() as a - * primitive operation. In general, readinto() can be more efficient than - * read(). - * - * (It would be tempting to also provide an implementation of readinto() in - * terms of read(), in case the latter is a more suitable primitive operation, - * but that would lead to nasty recursion in case a subclass doesn't implement - * either.) -*/ - -static PyObject * -rawiobase_read(PyObject *self, PyObject *args) -{ - Py_ssize_t n = -1; - PyObject *b, *res; - - if (!PyArg_ParseTuple(args, "|n:read", &n)) { - return NULL; - } - - if (n < 0) { - _Py_IDENTIFIER(readall); - - return _PyObject_CallMethodId(self, &PyId_readall, NULL); - } - - /* TODO: allocate a bytes object directly instead and manually construct - a writable memoryview pointing to it. */ - b = PyByteArray_FromStringAndSize(NULL, n); - if (b == NULL) - return NULL; - - res = PyObject_CallMethodObjArgs(self, _PyIO_str_readinto, b, NULL); - if (res == NULL || res == Py_None) { - Py_DECREF(b); - return res; - } - - n = PyNumber_AsSsize_t(res, PyExc_ValueError); - Py_DECREF(res); - if (n == -1 && PyErr_Occurred()) { - Py_DECREF(b); - return NULL; - } - - res = PyBytes_FromStringAndSize(PyByteArray_AsString(b), n); - Py_DECREF(b); - return res; -} - - -PyDoc_STRVAR(rawiobase_readall_doc, - "Read until EOF, using multiple read() call."); - -static PyObject * -rawiobase_readall(PyObject *self, PyObject *args) -{ - int r; - PyObject *chunks = PyList_New(0); - PyObject *result; - - if (chunks == NULL) - return NULL; - - while (1) { - PyObject *data = _PyObject_CallMethodId(self, &PyId_read, - "i", DEFAULT_BUFFER_SIZE); - if (!data) { - /* NOTE: PyErr_SetFromErrno() calls PyErr_CheckSignals() - when EINTR occurs so we needn't do it ourselves. */ - if (_PyIO_trap_eintr()) { - continue; - } - Py_DECREF(chunks); - return NULL; - } - if (data == Py_None) { - if (PyList_GET_SIZE(chunks) == 0) { - Py_DECREF(chunks); - return data; - } - Py_DECREF(data); - break; - } - if (!PyBytes_Check(data)) { - Py_DECREF(chunks); - Py_DECREF(data); - PyErr_SetString(PyExc_TypeError, "read() should return bytes"); - return NULL; - } - if (PyBytes_GET_SIZE(data) == 0) { - /* EOF */ - Py_DECREF(data); - break; - } - r = PyList_Append(chunks, data); - Py_DECREF(data); - if (r < 0) { - Py_DECREF(chunks); - return NULL; - } - } - result = _PyBytes_Join(_PyIO_empty_bytes, chunks); - Py_DECREF(chunks); - return result; -} - -static PyMethodDef rawiobase_methods[] = { - {"read", rawiobase_read, METH_VARARGS}, - {"readall", rawiobase_readall, METH_NOARGS, rawiobase_readall_doc}, - {NULL, NULL} -}; - -PyTypeObject PyRawIOBase_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "_io._RawIOBase", /*tp_name*/ - 0, /*tp_basicsize*/ - 0, /*tp_itemsize*/ - 0, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare */ - 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 | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_FINALIZE, /*tp_flags*/ - rawiobase_doc, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - rawiobase_methods, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - &PyIOBase_Type, /* 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, /* tp_free */ - 0, /* tp_is_gc */ - 0, /* tp_bases */ - 0, /* tp_mro */ - 0, /* tp_cache */ - 0, /* tp_subclasses */ - 0, /* tp_weaklist */ - 0, /* tp_del */ - 0, /* tp_version_tag */ - 0, /* tp_finalize */ -}; +/*[clinic end generated code: output=84eef4b7541f54b7 input=a9049054013a1b77]*/ diff --git a/Modules/_io/stringio.c b/Modules/_io/clinic/stringio.c.h copy from Modules/_io/stringio.c copy to Modules/_io/clinic/stringio.c.h --- a/Modules/_io/stringio.c +++ b/Modules/_io/clinic/stringio.c.h @@ -1,1034 +1,288 @@ -#define PY_SSIZE_T_CLEAN -#include "Python.h" -#include "structmember.h" -#include "accu.h" -#include "_iomodule.h" +/*[clinic input] +preserve +[clinic start generated code]*/ -/* Implementation note: the buffer is always at least one character longer - than the enclosed string, for proper functioning of _PyIO_find_line_ending. -*/ +PyDoc_STRVAR(_io_StringIO_getvalue__doc__, +"getvalue($self, /)\n" +"--\n" +"\n" +"Retrieve the entire contents of the object."); -#define STATE_REALIZED 1 -#define STATE_ACCUMULATING 2 +#define _IO_STRINGIO_GETVALUE_METHODDEF \ + {"getvalue", (PyCFunction)_io_StringIO_getvalue, METH_NOARGS, _io_StringIO_getvalue__doc__}, -typedef struct { - PyObject_HEAD - Py_UCS4 *buf; - Py_ssize_t pos; - Py_ssize_t string_size; - size_t buf_size; +static PyObject * +_io_StringIO_getvalue_impl(stringio *self); - /* The stringio object can be in two states: accumulating or realized. - In accumulating state, the internal buffer contains nothing and - the contents are given by the embedded _PyAccu structure. - In realized state, the internal buffer is meaningful and the - _PyAccu is destroyed. - */ - int state; - _PyAccu accu; - - char ok; /* initialized? */ - char closed; - char readuniversal; - char readtranslate; - PyObject *decoder; - PyObject *readnl; - PyObject *writenl; - - PyObject *dict; - PyObject *weakreflist; -} stringio; - -#define CHECK_INITIALIZED(self) \ - if (self->ok <= 0) { \ - PyErr_SetString(PyExc_ValueError, \ - "I/O operation on uninitialized object"); \ - return NULL; \ - } - -#define CHECK_CLOSED(self) \ - if (self->closed) { \ - PyErr_SetString(PyExc_ValueError, \ - "I/O operation on closed file"); \ - return NULL; \ - } - -#define ENSURE_REALIZED(self) \ - if (realize(self) < 0) { \ - return NULL; \ - } - -PyDoc_STRVAR(stringio_doc, - "Text I/O implementation using an in-memory buffer.\n" - "\n" - "The initial_value argument sets the value of object. The newline\n" - "argument is like the one of TextIOWrapper's constructor."); - - -/* Internal routine for changing the size, in terms of characters, of the - buffer of StringIO objects. The caller should ensure that the 'size' - argument is non-negative. Returns 0 on success, -1 otherwise. */ -static int -resize_buffer(stringio *self, size_t size) +static PyObject * +_io_StringIO_getvalue(stringio *self, PyObject *Py_UNUSED(ignored)) { - /* Here, unsigned types are used to avoid dealing with signed integer - overflow, which is undefined in C. */ - size_t alloc = self->buf_size; - Py_UCS4 *new_buf = NULL; - - assert(self->buf != NULL); - - /* Reserve one more char for line ending detection. */ - size = size + 1; - /* For simplicity, stay in the range of the signed type. Anyway, Python - doesn't allow strings to be longer than this. */ - if (size > PY_SSIZE_T_MAX) - goto overflow; - - if (size < alloc / 2) { - /* Major downsize; resize down to exact size. */ - alloc = size + 1; - } - else if (size < alloc) { - /* Within allocated size; quick exit */ - return 0; - } - else if (size <= alloc * 1.125) { - /* Moderate upsize; overallocate similar to list_resize() */ - alloc = size + (size >> 3) + (size < 9 ? 3 : 6); - } - else { - /* Major upsize; resize up to exact size */ - alloc = size + 1; - } - - if (alloc > PY_SIZE_MAX / sizeof(Py_UCS4)) - goto overflow; - new_buf = (Py_UCS4 *)PyMem_Realloc(self->buf, alloc * sizeof(Py_UCS4)); - if (new_buf == NULL) { - PyErr_NoMemory(); - return -1; - } - self->buf_size = alloc; - self->buf = new_buf; - - return 0; - - overflow: - PyErr_SetString(PyExc_OverflowError, - "new buffer size too large"); - return -1; + return _io_StringIO_getvalue_impl(self); } +PyDoc_STRVAR(_io_StringIO_tell__doc__, +"tell($self, /)\n" +"--\n" +"\n" +"Tell the current file position."); + +#define _IO_STRINGIO_TELL_METHODDEF \ + {"tell", (PyCFunction)_io_StringIO_tell, METH_NOARGS, _io_StringIO_tell__doc__}, + static PyObject * -make_intermediate(stringio *self) +_io_StringIO_tell_impl(stringio *self); + +static PyObject * +_io_StringIO_tell(stringio *self, PyObject *Py_UNUSED(ignored)) { - PyObject *intermediate = _PyAccu_Finish(&self->accu); - self->state = STATE_REALIZED; - if (intermediate == NULL) - return NULL; - if (_PyAccu_Init(&self->accu) || - _PyAccu_Accumulate(&self->accu, intermediate)) { - Py_DECREF(intermediate); - return NULL; - } - self->state = STATE_ACCUMULATING; - return intermediate; + return _io_StringIO_tell_impl(self); } -static int -realize(stringio *self) +PyDoc_STRVAR(_io_StringIO_read__doc__, +"read($self, size=None, /)\n" +"--\n" +"\n" +"Read at most size characters, returned as a string.\n" +"\n" +"If the argument is negative or omitted, read until EOF\n" +"is reached. Return an empty string at EOF."); + +#define _IO_STRINGIO_READ_METHODDEF \ + {"read", (PyCFunction)_io_StringIO_read, METH_VARARGS, _io_StringIO_read__doc__}, + +static PyObject * +_io_StringIO_read_impl(stringio *self, PyObject *arg); + +static PyObject * +_io_StringIO_read(stringio *self, PyObject *args) { - Py_ssize_t len; - PyObject *intermediate; + PyObject *return_value = NULL; + PyObject *arg = Py_None; - if (self->state == STATE_REALIZED) - return 0; - assert(self->state == STATE_ACCUMULATING); - self->state = STATE_REALIZED; + if (!PyArg_UnpackTuple(args, "read", + 0, 1, + &arg)) + goto exit; + return_value = _io_StringIO_read_impl(self, arg); - intermediate = _PyAccu_Finish(&self->accu); - if (intermediate == NULL) - return -1; - - /* Append the intermediate string to the internal buffer. - The length should be equal to the current cursor position. - */ - len = PyUnicode_GET_LENGTH(intermediate); - if (resize_buffer(self, len) < 0) { - Py_DECREF(intermediate); - return -1; - } - if (!PyUnicode_AsUCS4(intermediate, self->buf, len, 0)) { - Py_DECREF(intermediate); - return -1; - } - - Py_DECREF(intermediate); - return 0; +exit: + return return_value; } -/* Internal routine for writing a whole PyUnicode object to the buffer of a - StringIO object. Returns 0 on success, or -1 on error. */ -static Py_ssize_t -write_str(stringio *self, PyObject *obj) +PyDoc_STRVAR(_io_StringIO_readline__doc__, +"readline($self, size=None, /)\n" +"--\n" +"\n" +"Read until newline or EOF.\n" +"\n" +"Returns an empty string if EOF is hit immediately."); + +#define _IO_STRINGIO_READLINE_METHODDEF \ + {"readline", (PyCFunction)_io_StringIO_readline, METH_VARARGS, _io_StringIO_readline__doc__}, + +static PyObject * +_io_StringIO_readline_impl(stringio *self, PyObject *arg); + +static PyObject * +_io_StringIO_readline(stringio *self, PyObject *args) { - Py_ssize_t len; - PyObject *decoded = NULL; + PyObject *return_value = NULL; + PyObject *arg = Py_None; - assert(self->buf != NULL); - assert(self->pos >= 0); + if (!PyArg_UnpackTuple(args, "readline", + 0, 1, + &arg)) + goto exit; + return_value = _io_StringIO_readline_impl(self, arg); - if (self->decoder != NULL) { - decoded = _PyIncrementalNewlineDecoder_decode( - self->decoder, obj, 1 /* always final */); - } - else { - decoded = obj; - Py_INCREF(decoded); - } - if (self->writenl) { - PyObject *translated = PyUnicode_Replace( - decoded, _PyIO_str_nl, self->writenl, -1); - Py_DECREF(decoded); - decoded = translated; - } - if (decoded == NULL) - return -1; - - assert(PyUnicode_Check(decoded)); - if (PyUnicode_READY(decoded)) { - Py_DECREF(decoded); - return -1; - } - len = PyUnicode_GET_LENGTH(decoded); - assert(len >= 0); - - /* This overflow check is not strictly necessary. However, it avoids us to - deal with funky things like comparing an unsigned and a signed - integer. */ - if (self->pos > PY_SSIZE_T_MAX - len) { - PyErr_SetString(PyExc_OverflowError, - "new position too large"); - goto fail; - } - - if (self->state == STATE_ACCUMULATING) { - if (self->string_size == self->pos) { - if (_PyAccu_Accumulate(&self->accu, decoded)) - goto fail; - goto success; - } - if (realize(self)) - goto fail; - } - - if (self->pos + len > self->string_size) { - if (resize_buffer(self, self->pos + len) < 0) - goto fail; - } - - if (self->pos > self->string_size) { - /* In case of overseek, pad with null bytes the buffer region between - the end of stream and the current position. - - 0 lo string_size hi - | |<---used--->|<----------available----------->| - | | <--to pad-->|<---to write---> | - 0 buf position - - */ - memset(self->buf + self->string_size, '\0', - (self->pos - self->string_size) * sizeof(Py_UCS4)); - } - - /* Copy the data to the internal buffer, overwriting some of the - existing data if self->pos < self->string_size. */ - if (!PyUnicode_AsUCS4(decoded, - self->buf + self->pos, - self->buf_size - self->pos, - 0)) - goto fail; - -success: - /* Set the new length of the internal string if it has changed. */ - self->pos += len; - if (self->string_size < self->pos) - self->string_size = self->pos; - - Py_DECREF(decoded); - return 0; - -fail: - Py_XDECREF(decoded); - return -1; +exit: + return return_value; } -PyDoc_STRVAR(stringio_getvalue_doc, - "Retrieve the entire contents of the object."); +PyDoc_STRVAR(_io_StringIO_truncate__doc__, +"truncate($self, pos=None, /)\n" +"--\n" +"\n" +"Truncate size to pos.\n" +"\n" +"The pos argument defaults to the current file position, as\n" +"returned by tell(). The current file position is unchanged.\n" +"Returns the new absolute position."); + +#define _IO_STRINGIO_TRUNCATE_METHODDEF \ + {"truncate", (PyCFunction)_io_StringIO_truncate, METH_VARARGS, _io_StringIO_truncate__doc__}, static PyObject * -stringio_getvalue(stringio *self) +_io_StringIO_truncate_impl(stringio *self, PyObject *arg); + +static PyObject * +_io_StringIO_truncate(stringio *self, PyObject *args) { - CHECK_INITIALIZED(self); - CHECK_CLOSED(self); - if (self->state == STATE_ACCUMULATING) - return make_intermediate(self); - return PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND, self->buf, - self->string_size); + PyObject *return_value = NULL; + PyObject *arg = Py_None; + + if (!PyArg_UnpackTuple(args, "truncate", + 0, 1, + &arg)) + goto exit; + return_value = _io_StringIO_truncate_impl(self, arg); + +exit: + return return_value; } -PyDoc_STRVAR(stringio_tell_doc, - "Tell the current file position."); +PyDoc_STRVAR(_io_StringIO_seek__doc__, +"seek($self, pos, whence=0, /)\n" +"--\n" +"\n" +"Change stream position.\n" +"\n" +"Seek to character offset pos relative to position indicated by whence:\n" +" 0 Start of stream (the default). pos should be >= 0;\n" +" 1 Current position - pos must be 0;\n" +" 2 End of stream - pos must be 0.\n" +"Returns the new absolute position."); + +#define _IO_STRINGIO_SEEK_METHODDEF \ + {"seek", (PyCFunction)_io_StringIO_seek, METH_VARARGS, _io_StringIO_seek__doc__}, static PyObject * -stringio_tell(stringio *self) +_io_StringIO_seek_impl(stringio *self, Py_ssize_t pos, int whence); + +static PyObject * +_io_StringIO_seek(stringio *self, PyObject *args) { - CHECK_INITIALIZED(self); - CHECK_CLOSED(self); - return PyLong_FromSsize_t(self->pos); + PyObject *return_value = NULL; + Py_ssize_t pos; + int whence = 0; + + if (!PyArg_ParseTuple(args, + "n|i:seek", + &pos, &whence)) + goto exit; + return_value = _io_StringIO_seek_impl(self, pos, whence); + +exit: + return return_value; } -PyDoc_STRVAR(stringio_read_doc, - "Read at most n characters, returned as a string.\n" - "\n" - "If the argument is negative or omitted, read until EOF\n" - "is reached. Return an empty string at EOF.\n"); +PyDoc_STRVAR(_io_StringIO_write__doc__, +"write($self, s, /)\n" +"--\n" +"\n" +"Write string to file.\n" +"\n" +"Returns the number of characters written, which is always equal to\n" +"the length of the string."); + +#define _IO_STRINGIO_WRITE_METHODDEF \ + {"write", (PyCFunction)_io_StringIO_write, METH_O, _io_StringIO_write__doc__}, + +PyDoc_STRVAR(_io_StringIO_close__doc__, +"close($self, /)\n" +"--\n" +"\n" +"Close the IO object.\n" +"\n" +"Attempting any further operation after the object is closed\n" +"will raise a ValueError.\n" +"\n" +"This method has no effect if the file is already closed."); + +#define _IO_STRINGIO_CLOSE_METHODDEF \ + {"close", (PyCFunction)_io_StringIO_close, METH_NOARGS, _io_StringIO_close__doc__}, static PyObject * -stringio_read(stringio *self, PyObject *args) +_io_StringIO_close_impl(stringio *self); + +static PyObject * +_io_StringIO_close(stringio *self, PyObject *Py_UNUSED(ignored)) { - Py_ssize_t size, n; - Py_UCS4 *output; - PyObject *arg = Py_None; - - CHECK_INITIALIZED(self); - if (!PyArg_ParseTuple(args, "|O:read", &arg)) - return NULL; - CHECK_CLOSED(self); - - if (PyNumber_Check(arg)) { - size = PyNumber_AsSsize_t(arg, PyExc_OverflowError); - if (size == -1 && PyErr_Occurred()) - return NULL; - } - else if (arg == Py_None) { - /* Read until EOF is reached, by default. */ - size = -1; - } - else { - PyErr_Format(PyExc_TypeError, "integer argument expected, got '%s'", - Py_TYPE(arg)->tp_name); - return NULL; - } - - /* adjust invalid sizes */ - n = self->string_size - self->pos; - if (size < 0 || size > n) { - size = n; - if (size < 0) - size = 0; - } - - /* Optimization for seek(0); read() */ - if (self->state == STATE_ACCUMULATING && self->pos == 0 && size == n) { - PyObject *result = make_intermediate(self); - self->pos = self->string_size; - return result; - } - - ENSURE_REALIZED(self); - output = self->buf + self->pos; - self->pos += size; - return PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND, output, size); + return _io_StringIO_close_impl(self); } -/* Internal helper, used by stringio_readline and stringio_iternext */ -static PyObject * -_stringio_readline(stringio *self, Py_ssize_t limit) +PyDoc_STRVAR(_io_StringIO___init____doc__, +"StringIO(initial_value=\'\', newline=\'\\n\')\n" +"--\n" +"\n" +"Text I/O implementation using an in-memory buffer.\n" +"\n" +"The initial_value argument sets the value of object. The newline\n" +"argument is like the one of TextIOWrapper\'s constructor."); + +static int +_io_StringIO___init___impl(stringio *self, PyObject *value, + PyObject *newline_obj); + +static int +_io_StringIO___init__(PyObject *self, PyObject *args, PyObject *kwargs) { - Py_UCS4 *start, *end, old_char; - Py_ssize_t len, consumed; + int return_value = -1; + static char *_keywords[] = {"initial_value", "newline", NULL}; + PyObject *value = NULL; + PyObject *newline_obj = NULL; - /* In case of overseek, return the empty string */ - if (self->pos >= self->string_size) - return PyUnicode_New(0, 0); + if (!PyArg_ParseTupleAndKeywords(args, kwargs, + "|OO:StringIO", _keywords, + &value, &newline_obj)) + goto exit; + return_value = _io_StringIO___init___impl((stringio *)self, value, newline_obj); - start = self->buf + self->pos; - if (limit < 0 || limit > self->string_size - self->pos) - limit = self->string_size - self->pos; - - end = start + limit; - old_char = *end; - *end = '\0'; - len = _PyIO_find_line_ending( - self->readtranslate, self->readuniversal, self->readnl, - PyUnicode_4BYTE_KIND, (char*)start, (char*)end, &consumed); - *end = old_char; - /* If we haven't found any line ending, we just return everything - (`consumed` is ignored). */ - if (len < 0) - len = limit; - self->pos += len; - return PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND, start, len); +exit: + return return_value; } -PyDoc_STRVAR(stringio_readline_doc, - "Read until newline or EOF.\n" - "\n" - "Returns an empty string if EOF is hit immediately.\n"); +PyDoc_STRVAR(_io_StringIO_readable__doc__, +"readable($self, /)\n" +"--\n" +"\n" +"Returns True if the IO object can be read."); + +#define _IO_STRINGIO_READABLE_METHODDEF \ + {"readable", (PyCFunction)_io_StringIO_readable, METH_NOARGS, _io_StringIO_readable__doc__}, static PyObject * -stringio_readline(stringio *self, PyObject *args) +_io_StringIO_readable_impl(stringio *self); + +static PyObject * +_io_StringIO_readable(stringio *self, PyObject *Py_UNUSED(ignored)) { - PyObject *arg = Py_None; - Py_ssize_t limit = -1; - - CHECK_INITIALIZED(self); - if (!PyArg_ParseTuple(args, "|O:readline", &arg)) - return NULL; - CHECK_CLOSED(self); - ENSURE_REALIZED(self); - - if (PyNumber_Check(arg)) { - limit = PyNumber_AsSsize_t(arg, PyExc_OverflowError); - if (limit == -1 && PyErr_Occurred()) - return NULL; - } - else if (arg != Py_None) { - PyErr_Format(PyExc_TypeError, "integer argument expected, got '%s'", - Py_TYPE(arg)->tp_name); - return NULL; - } - return _stringio_readline(self, limit); + return _io_StringIO_readable_impl(self); } +PyDoc_STRVAR(_io_StringIO_writable__doc__, +"writable($self, /)\n" +"--\n" +"\n" +"Returns True if the IO object can be written."); + +#define _IO_STRINGIO_WRITABLE_METHODDEF \ + {"writable", (PyCFunction)_io_StringIO_writable, METH_NOARGS, _io_StringIO_writable__doc__}, + static PyObject * -stringio_iternext(stringio *self) +_io_StringIO_writable_impl(stringio *self); + +static PyObject * +_io_StringIO_writable(stringio *self, PyObject *Py_UNUSED(ignored)) { - PyObject *line; - - CHECK_INITIALIZED(self); - CHECK_CLOSED(self); - ENSURE_REALIZED(self); - - if (Py_TYPE(self) == &PyStringIO_Type) { - /* Skip method call overhead for speed */ - line = _stringio_readline(self, -1); - } - else { - /* XXX is subclassing StringIO really supported? */ - line = PyObject_CallMethodObjArgs((PyObject *)self, - _PyIO_str_readline, NULL); - if (line && !PyUnicode_Check(line)) { - PyErr_Format(PyExc_IOError, - "readline() should have returned an str object, " - "not '%.200s'", Py_TYPE(line)->tp_name); - Py_DECREF(line); - return NULL; - } - } - - if (line == NULL) - return NULL; - - if (PyUnicode_GET_LENGTH(line) == 0) { - /* Reached EOF */ - Py_DECREF(line); - return NULL; - } - - return line; + return _io_StringIO_writable_impl(self); } -PyDoc_STRVAR(stringio_truncate_doc, - "Truncate size to pos.\n" - "\n" - "The pos argument defaults to the current file position, as\n" - "returned by tell(). The current file position is unchanged.\n" - "Returns the new absolute position.\n"); +PyDoc_STRVAR(_io_StringIO_seekable__doc__, +"seekable($self, /)\n" +"--\n" +"\n" +"Returns True if the IO object can be seeked."); + +#define _IO_STRINGIO_SEEKABLE_METHODDEF \ + {"seekable", (PyCFunction)_io_StringIO_seekable, METH_NOARGS, _io_StringIO_seekable__doc__}, static PyObject * -stringio_truncate(stringio *self, PyObject *args) -{ - Py_ssize_t size; - PyObject *arg = Py_None; - - CHECK_INITIALIZED(self); - if (!PyArg_ParseTuple(args, "|O:truncate", &arg)) - return NULL; - CHECK_CLOSED(self); - - if (PyNumber_Check(arg)) { - size = PyNumber_AsSsize_t(arg, PyExc_OverflowError); - if (size == -1 && PyErr_Occurred()) - return NULL; - } - else if (arg == Py_None) { - /* Truncate to current position if no argument is passed. */ - size = self->pos; - } - else { - PyErr_Format(PyExc_TypeError, "integer argument expected, got '%s'", - Py_TYPE(arg)->tp_name); - return NULL; - } - - if (size < 0) { - PyErr_Format(PyExc_ValueError, - "Negative size value %zd", size); - return NULL; - } - - if (size < self->string_size) { - ENSURE_REALIZED(self); - if (resize_buffer(self, size) < 0) - return NULL; - self->string_size = size; - } - - return PyLong_FromSsize_t(size); -} - -PyDoc_STRVAR(stringio_seek_doc, - "Change stream position.\n" - "\n" - "Seek to character offset pos relative to position indicated by whence:\n" - " 0 Start of stream (the default). pos should be >= 0;\n" - " 1 Current position - pos must be 0;\n" - " 2 End of stream - pos must be 0.\n" - "Returns the new absolute position.\n"); +_io_StringIO_seekable_impl(stringio *self); static PyObject * -stringio_seek(stringio *self, PyObject *args) +_io_StringIO_seekable(stringio *self, PyObject *Py_UNUSED(ignored)) { - Py_ssize_t pos; - int mode = 0; - - CHECK_INITIALIZED(self); - if (!PyArg_ParseTuple(args, "n|i:seek", &pos, &mode)) - return NULL; - CHECK_CLOSED(self); - - if (mode != 0 && mode != 1 && mode != 2) { - PyErr_Format(PyExc_ValueError, - "Invalid whence (%i, should be 0, 1 or 2)", mode); - return NULL; - } - else if (pos < 0 && mode == 0) { - PyErr_Format(PyExc_ValueError, - "Negative seek position %zd", pos); - return NULL; - } - else if (mode != 0 && pos != 0) { - PyErr_SetString(PyExc_IOError, - "Can't do nonzero cur-relative seeks"); - return NULL; - } - - /* mode 0: offset relative to beginning of the string. - mode 1: no change to current position. - mode 2: change position to end of file. */ - if (mode == 1) { - pos = self->pos; - } - else if (mode == 2) { - pos = self->string_size; - } - - self->pos = pos; - - return PyLong_FromSsize_t(self->pos); + return _io_StringIO_seekable_impl(self); } - -PyDoc_STRVAR(stringio_write_doc, - "Write string to file.\n" - "\n" - "Returns the number of characters written, which is always equal to\n" - "the length of the string.\n"); - -static PyObject * -stringio_write(stringio *self, PyObject *obj) -{ - Py_ssize_t size; - - CHECK_INITIALIZED(self); - if (!PyUnicode_Check(obj)) { - PyErr_Format(PyExc_TypeError, "string argument expected, got '%s'", - Py_TYPE(obj)->tp_name); - return NULL; - } - if (PyUnicode_READY(obj)) - return NULL; - CHECK_CLOSED(self); - size = PyUnicode_GET_LENGTH(obj); - - if (size > 0 && write_str(self, obj) < 0) - return NULL; - - return PyLong_FromSsize_t(size); -} - -PyDoc_STRVAR(stringio_close_doc, - "Close the IO object. Attempting any further operation after the\n" - "object is closed will raise a ValueError.\n" - "\n" - "This method has no effect if the file is already closed.\n"); - -static PyObject * -stringio_close(stringio *self) -{ - self->closed = 1; - /* Free up some memory */ - if (resize_buffer(self, 0) < 0) - return NULL; - _PyAccu_Destroy(&self->accu); - Py_CLEAR(self->readnl); - Py_CLEAR(self->writenl); - Py_CLEAR(self->decoder); - Py_RETURN_NONE; -} - -static int -stringio_traverse(stringio *self, visitproc visit, void *arg) -{ - Py_VISIT(self->dict); - return 0; -} - -static int -stringio_clear(stringio *self) -{ - Py_CLEAR(self->dict); - return 0; -} - -static void -stringio_dealloc(stringio *self) -{ - _PyObject_GC_UNTRACK(self); - self->ok = 0; - if (self->buf) { - PyMem_Free(self->buf); - self->buf = NULL; - } - _PyAccu_Destroy(&self->accu); - Py_CLEAR(self->readnl); - Py_CLEAR(self->writenl); - Py_CLEAR(self->decoder); - Py_CLEAR(self->dict); - if (self->weakreflist != NULL) - PyObject_ClearWeakRefs((PyObject *) self); - Py_TYPE(self)->tp_free(self); -} - -static PyObject * -stringio_new(PyTypeObject *type, PyObject *args, PyObject *kwds) -{ - stringio *self; - - assert(type != NULL && type->tp_alloc != NULL); - self = (stringio *)type->tp_alloc(type, 0); - if (self == NULL) - return NULL; - - /* tp_alloc initializes all the fields to zero. So we don't have to - initialize them here. */ - - self->buf = (Py_UCS4 *)PyMem_Malloc(0); - if (self->buf == NULL) { - Py_DECREF(self); - return PyErr_NoMemory(); - } - - return (PyObject *)self; -} - -static int -stringio_init(stringio *self, PyObject *args, PyObject *kwds) -{ - char *kwlist[] = {"initial_value", "newline", NULL}; - PyObject *value = NULL; - PyObject *newline_obj = NULL; - char *newline = "\n"; - Py_ssize_t value_len; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OO:__init__", kwlist, - &value, &newline_obj)) - return -1; - - /* Parse the newline argument. This used to be done with the 'z' - specifier, however this allowed any object with the buffer interface to - be converted. Thus we have to parse it manually since we only want to - allow unicode objects or None. */ - if (newline_obj == Py_None) { - newline = NULL; - } - else if (newline_obj) { - if (!PyUnicode_Check(newline_obj)) { - PyErr_Format(PyExc_TypeError, - "newline must be str or None, not %.200s", - Py_TYPE(newline_obj)->tp_name); - return -1; - } - newline = _PyUnicode_AsString(newline_obj); - if (newline == NULL) - return -1; - } - - if (newline && newline[0] != '\0' - && !(newline[0] == '\n' && newline[1] == '\0') - && !(newline[0] == '\r' && newline[1] == '\0') - && !(newline[0] == '\r' && newline[1] == '\n' && newline[2] == '\0')) { - PyErr_Format(PyExc_ValueError, - "illegal newline value: %R", newline_obj); - return -1; - } - if (value && value != Py_None && !PyUnicode_Check(value)) { - PyErr_Format(PyExc_TypeError, - "initial_value must be str or None, not %.200s", - Py_TYPE(value)->tp_name); - return -1; - } - - self->ok = 0; - - _PyAccu_Destroy(&self->accu); - Py_CLEAR(self->readnl); - Py_CLEAR(self->writenl); - Py_CLEAR(self->decoder); - - assert((newline != NULL && newline_obj != Py_None) || - (newline == NULL && newline_obj == Py_None)); - - if (newline) { - self->readnl = PyUnicode_FromString(newline); - if (self->readnl == NULL) - return -1; - } - self->readuniversal = (newline == NULL || newline[0] == '\0'); - self->readtranslate = (newline == NULL); - /* If newline == "", we don't translate anything. - If newline == "\n" or newline == None, we translate to "\n", which is - a no-op. - (for newline == None, TextIOWrapper translates to os.sepline, but it - is pointless for StringIO) - */ - if (newline != NULL && newline[0] == '\r') { - self->writenl = self->readnl; - Py_INCREF(self->writenl); - } - - if (self->readuniversal) { - self->decoder = PyObject_CallFunction( - (PyObject *)&PyIncrementalNewlineDecoder_Type, - "Oi", Py_None, (int) self->readtranslate); - if (self->decoder == NULL) - return -1; - } - - /* Now everything is set up, resize buffer to size of initial value, - and copy it */ - self->string_size = 0; - if (value && value != Py_None) - value_len = PyUnicode_GetLength(value); - else - value_len = 0; - if (value_len > 0) { - /* This is a heuristic, for newline translation might change - the string length. */ - if (resize_buffer(self, 0) < 0) - return -1; - self->state = STATE_REALIZED; - self->pos = 0; - if (write_str(self, value) < 0) - return -1; - } - else { - /* Empty stringio object, we can start by accumulating */ - if (resize_buffer(self, 0) < 0) - return -1; - if (_PyAccu_Init(&self->accu)) - return -1; - self->state = STATE_ACCUMULATING; - } - self->pos = 0; - - self->closed = 0; - self->ok = 1; - return 0; -} - -/* Properties and pseudo-properties */ - -PyDoc_STRVAR(stringio_readable_doc, -"readable() -> bool. Returns True if the IO object can be read."); - -PyDoc_STRVAR(stringio_writable_doc, -"writable() -> bool. Returns True if the IO object can be written."); - -PyDoc_STRVAR(stringio_seekable_doc, -"seekable() -> bool. Returns True if the IO object can be seeked."); - -static PyObject * -stringio_seekable(stringio *self, PyObject *args) -{ - CHECK_INITIALIZED(self); - CHECK_CLOSED(self); - Py_RETURN_TRUE; -} - -static PyObject * -stringio_readable(stringio *self, PyObject *args) -{ - CHECK_INITIALIZED(self); - CHECK_CLOSED(self); - Py_RETURN_TRUE; -} - -static PyObject * -stringio_writable(stringio *self, PyObject *args) -{ - CHECK_INITIALIZED(self); - CHECK_CLOSED(self); - Py_RETURN_TRUE; -} - -/* Pickling support. - - The implementation of __getstate__ is similar to the one for BytesIO, - except that we also save the newline parameter. For __setstate__ and unlike - BytesIO, we call __init__ to restore the object's state. Doing so allows us - to avoid decoding the complex newline state while keeping the object - representation compact. - - See comment in bytesio.c regarding why only pickle protocols and onward are - supported. -*/ - -static PyObject * -stringio_getstate(stringio *self) -{ - PyObject *initvalue = stringio_getvalue(self); - PyObject *dict; - PyObject *state; - - if (initvalue == NULL) - return NULL; - if (self->dict == NULL) { - Py_INCREF(Py_None); - dict = Py_None; - } - else { - dict = PyDict_Copy(self->dict); - if (dict == NULL) - return NULL; - } - - state = Py_BuildValue("(OOnN)", initvalue, - self->readnl ? self->readnl : Py_None, - self->pos, dict); - Py_DECREF(initvalue); - return state; -} - -static PyObject * -stringio_setstate(stringio *self, PyObject *state) -{ - PyObject *initarg; - PyObject *position_obj; - PyObject *dict; - Py_ssize_t pos; - - assert(state != NULL); - CHECK_CLOSED(self); - - /* We allow the state tuple to be longer than 4, because we may need - someday to extend the object's state without breaking - backward-compatibility. */ - if (!PyTuple_Check(state) || Py_SIZE(state) < 4) { - PyErr_Format(PyExc_TypeError, - "%.200s.__setstate__ argument should be 4-tuple, got %.200s", - Py_TYPE(self)->tp_name, Py_TYPE(state)->tp_name); - return NULL; - } - - /* Initialize the object's state. */ - initarg = PyTuple_GetSlice(state, 0, 2); - if (initarg == NULL) - return NULL; - if (stringio_init(self, initarg, NULL) < 0) { - Py_DECREF(initarg); - return NULL; - } - Py_DECREF(initarg); - - /* Restore the buffer state. Even if __init__ did initialize the buffer, - we have to initialize it again since __init__ may translates the - newlines in the inital_value string. We clearly do not want that - because the string value in the state tuple has already been translated - once by __init__. So we do not take any chance and replace object's - buffer completely. */ - { - PyObject *item; - Py_UCS4 *buf; - Py_ssize_t bufsize; - - item = PyTuple_GET_ITEM(state, 0); - buf = PyUnicode_AsUCS4Copy(item); - if (buf == NULL) - return NULL; - bufsize = PyUnicode_GET_LENGTH(item); - - if (resize_buffer(self, bufsize) < 0) { - PyMem_Free(buf); - return NULL; - } - memcpy(self->buf, buf, bufsize * sizeof(Py_UCS4)); - PyMem_Free(buf); - self->string_size = bufsize; - } - - /* Set carefully the position value. Alternatively, we could use the seek - method instead of modifying self->pos directly to better protect the - object internal state against errneous (or malicious) inputs. */ - position_obj = PyTuple_GET_ITEM(state, 2); - if (!PyLong_Check(position_obj)) { - PyErr_Format(PyExc_TypeError, - "third item of state must be an integer, got %.200s", - Py_TYPE(position_obj)->tp_name); - return NULL; - } - pos = PyLong_AsSsize_t(position_obj); - if (pos == -1 && PyErr_Occurred()) - return NULL; - if (pos < 0) { - PyErr_SetString(PyExc_ValueError, - "position value cannot be negative"); - return NULL; - } - self->pos = pos; - - /* Set the dictionary of the instance variables. */ - dict = PyTuple_GET_ITEM(state, 3); - if (dict != Py_None) { - if (!PyDict_Check(dict)) { - PyErr_Format(PyExc_TypeError, - "fourth item of state should be a dict, got a %.200s", - Py_TYPE(dict)->tp_name); - return NULL; - } - if (self->dict) { - /* Alternatively, we could replace the internal dictionary - completely. However, it seems more practical to just update it. */ - if (PyDict_Update(self->dict, dict) < 0) - return NULL; - } - else { - Py_INCREF(dict); - self->dict = dict; - } - } - - Py_RETURN_NONE; -} - - -static PyObject * -stringio_closed(stringio *self, void *context) -{ - CHECK_INITIALIZED(self); - return PyBool_FromLong(self->closed); -} - -static PyObject * -stringio_line_buffering(stringio *self, void *context) -{ - CHECK_INITIALIZED(self); - CHECK_CLOSED(self); - Py_RETURN_FALSE; -} - -static PyObject * -stringio_newlines(stringio *self, void *context) -{ - CHECK_INITIALIZED(self); - CHECK_CLOSED(self); - if (self->decoder == NULL) - Py_RETURN_NONE; - return PyObject_GetAttr(self->decoder, _PyIO_str_newlines); -} - -static struct PyMethodDef stringio_methods[] = { - {"close", (PyCFunction)stringio_close, METH_NOARGS, stringio_close_doc}, - {"getvalue", (PyCFunction)stringio_getvalue, METH_NOARGS, stringio_getvalue_doc}, - {"read", (PyCFunction)stringio_read, METH_VARARGS, stringio_read_doc}, - {"readline", (PyCFunction)stringio_readline, METH_VARARGS, stringio_readline_doc}, - {"tell", (PyCFunction)stringio_tell, METH_NOARGS, stringio_tell_doc}, - {"truncate", (PyCFunction)stringio_truncate, METH_VARARGS, stringio_truncate_doc}, - {"seek", (PyCFunction)stringio_seek, METH_VARARGS, stringio_seek_doc}, - {"write", (PyCFunction)stringio_write, METH_O, stringio_write_doc}, - - {"seekable", (PyCFunction)stringio_seekable, METH_NOARGS, stringio_seekable_doc}, - {"readable", (PyCFunction)stringio_readable, METH_NOARGS, stringio_readable_doc}, - {"writable", (PyCFunction)stringio_writable, METH_NOARGS, stringio_writable_doc}, - - {"__getstate__", (PyCFunction)stringio_getstate, METH_NOARGS}, - {"__setstate__", (PyCFunction)stringio_setstate, METH_O}, - {NULL, NULL} /* sentinel */ -}; - -static PyGetSetDef stringio_getset[] = { - {"closed", (getter)stringio_closed, NULL, NULL}, - {"newlines", (getter)stringio_newlines, NULL, NULL}, - /* (following comments straight off of the original Python wrapper:) - XXX Cruft to support the TextIOWrapper API. This would only - be meaningful if StringIO supported the buffer attribute. - Hopefully, a better solution, than adding these pseudo-attributes, - will be found. - */ - {"line_buffering", (getter)stringio_line_buffering, NULL, NULL}, - {NULL} -}; - -PyTypeObject PyStringIO_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "_io.StringIO", /*tp_name*/ - sizeof(stringio), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - (destructor)stringio_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_reserved*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash*/ - 0, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE - | Py_TPFLAGS_HAVE_GC, /*tp_flags*/ - stringio_doc, /*tp_doc*/ - (traverseproc)stringio_traverse, /*tp_traverse*/ - (inquiry)stringio_clear, /*tp_clear*/ - 0, /*tp_richcompare*/ - offsetof(stringio, weakreflist), /*tp_weaklistoffset*/ - 0, /*tp_iter*/ - (iternextfunc)stringio_iternext, /*tp_iternext*/ - stringio_methods, /*tp_methods*/ - 0, /*tp_members*/ - stringio_getset, /*tp_getset*/ - 0, /*tp_base*/ - 0, /*tp_dict*/ - 0, /*tp_descr_get*/ - 0, /*tp_descr_set*/ - offsetof(stringio, dict), /*tp_dictoffset*/ - (initproc)stringio_init, /*tp_init*/ - 0, /*tp_alloc*/ - stringio_new, /*tp_new*/ -}; +/*[clinic end generated code: output=f3062096d357c652 input=a9049054013a1b77]*/ diff --git a/Modules/_io/textio.c b/Modules/_io/clinic/textio.c.h copy from Modules/_io/textio.c copy to Modules/_io/clinic/textio.c.h --- a/Modules/_io/textio.c +++ b/Modules/_io/clinic/textio.c.h @@ -1,2833 +1,464 @@ -/* - An implementation of Text I/O as defined by PEP 3116 - "New I/O" +/*[clinic input] +preserve +[clinic start generated code]*/ - Classes defined here: TextIOBase, IncrementalNewlineDecoder, TextIOWrapper. - - Written by Amaury Forgeot d'Arc and Antoine Pitrou -*/ - -#define PY_SSIZE_T_CLEAN -#include "Python.h" -#include "structmember.h" -#include "_iomodule.h" - -_Py_IDENTIFIER(close); -_Py_IDENTIFIER(_dealloc_warn); -_Py_IDENTIFIER(decode); -_Py_IDENTIFIER(fileno); -_Py_IDENTIFIER(flush); -_Py_IDENTIFIER(getpreferredencoding); -_Py_IDENTIFIER(isatty); -_Py_IDENTIFIER(mode); -_Py_IDENTIFIER(name); -_Py_IDENTIFIER(raw); -_Py_IDENTIFIER(read); -_Py_IDENTIFIER(read1); -_Py_IDENTIFIER(readable); -_Py_IDENTIFIER(replace); -_Py_IDENTIFIER(reset); -_Py_IDENTIFIER(seek); -_Py_IDENTIFIER(seekable); -_Py_IDENTIFIER(setstate); -_Py_IDENTIFIER(tell); -_Py_IDENTIFIER(writable); - -/* TextIOBase */ - -PyDoc_STRVAR(textiobase_doc, - "Base class for text I/O.\n" - "\n" - "This class provides a character and line based interface to stream\n" - "I/O. There is no readinto method because Python's character strings\n" - "are immutable. There is no public constructor.\n" - ); - -static PyObject * -_unsupported(const char *message) -{ - _PyIO_State *state = IO_STATE(); - if (state != NULL) - PyErr_SetString(state->unsupported_operation, message); - return NULL; -} - -PyDoc_STRVAR(textiobase_detach_doc, - "Separate the underlying buffer from the TextIOBase and return it.\n" - "\n" - "After the underlying buffer has been detached, the TextIO is in an\n" - "unusable state.\n" - ); - -static PyObject * -textiobase_detach(PyObject *self) -{ - return _unsupported("detach"); -} - -PyDoc_STRVAR(textiobase_read_doc, - "Read at most n characters from stream.\n" - "\n" - "Read from underlying buffer until we have n characters or we hit EOF.\n" - "If n is negative or omitted, read until EOF.\n" - ); - -static PyObject * -textiobase_read(PyObject *self, PyObject *args) -{ - return _unsupported("read"); -} - -PyDoc_STRVAR(textiobase_readline_doc, - "Read until newline or EOF.\n" - "\n" - "Returns an empty string if EOF is hit immediately.\n" - ); - -static PyObject * -textiobase_readline(PyObject *self, PyObject *args) -{ - return _unsupported("readline"); -} - -PyDoc_STRVAR(textiobase_write_doc, - "Write string to stream.\n" - "Returns the number of characters written (which is always equal to\n" - "the length of the string).\n" - ); - -static PyObject * -textiobase_write(PyObject *self, PyObject *args) -{ - return _unsupported("write"); -} - -PyDoc_STRVAR(textiobase_encoding_doc, - "Encoding of the text stream.\n" - "\n" - "Subclasses should override.\n" - ); - -static PyObject * -textiobase_encoding_get(PyObject *self, void *context) -{ - Py_RETURN_NONE; -} - -PyDoc_STRVAR(textiobase_newlines_doc, - "Line endings translated so far.\n" - "\n" - "Only line endings translated during reading are considered.\n" - "\n" - "Subclasses should override.\n" - ); - -static PyObject * -textiobase_newlines_get(PyObject *self, void *context) -{ - Py_RETURN_NONE; -} - -PyDoc_STRVAR(textiobase_errors_doc, - "The error setting of the decoder or encoder.\n" - "\n" - "Subclasses should override.\n" - ); - -static PyObject * -textiobase_errors_get(PyObject *self, void *context) -{ - Py_RETURN_NONE; -} - - -static PyMethodDef textiobase_methods[] = { - {"detach", (PyCFunction)textiobase_detach, METH_NOARGS, textiobase_detach_doc}, - {"read", textiobase_read, METH_VARARGS, textiobase_read_doc}, - {"readline", textiobase_readline, METH_VARARGS, textiobase_readline_doc}, - {"write", textiobase_write, METH_VARARGS, textiobase_write_doc}, - {NULL, NULL} -}; - -static PyGetSetDef textiobase_getset[] = { - {"encoding", (getter)textiobase_encoding_get, NULL, textiobase_encoding_doc}, - {"newlines", (getter)textiobase_newlines_get, NULL, textiobase_newlines_doc}, - {"errors", (getter)textiobase_errors_get, NULL, textiobase_errors_doc}, - {NULL} -}; - -PyTypeObject PyTextIOBase_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "_io._TextIOBase", /*tp_name*/ - 0, /*tp_basicsize*/ - 0, /*tp_itemsize*/ - 0, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare */ - 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 | Py_TPFLAGS_BASETYPE - | Py_TPFLAGS_HAVE_FINALIZE, /*tp_flags*/ - textiobase_doc, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - textiobase_methods, /* tp_methods */ - 0, /* tp_members */ - textiobase_getset, /* tp_getset */ - &PyIOBase_Type, /* 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, /* tp_free */ - 0, /* tp_is_gc */ - 0, /* tp_bases */ - 0, /* tp_mro */ - 0, /* tp_cache */ - 0, /* tp_subclasses */ - 0, /* tp_weaklist */ - 0, /* tp_del */ - 0, /* tp_version_tag */ - 0, /* tp_finalize */ -}; - - -/* IncrementalNewlineDecoder */ - -PyDoc_STRVAR(incrementalnewlinedecoder_doc, - "Codec used when reading a file in universal newlines mode. It wraps\n" - "another incremental decoder, translating \\r\\n and \\r into \\n. It also\n" - "records the types of newlines encountered. When used with\n" - "translate=False, it ensures that the newline sequence is returned in\n" - "one piece. When used with decoder=None, it expects unicode strings as\n" - "decode input and translates newlines without first invoking an external\n" - "decoder.\n" - ); - -typedef struct { - PyObject_HEAD - PyObject *decoder; - PyObject *errors; - unsigned int pendingcr: 1; - unsigned int translate: 1; - unsigned int seennl: 3; -} nldecoder_object; +PyDoc_STRVAR(_io_IncrementalNewlineDecoder___init____doc__, +"IncrementalNewlineDecoder(decoder, translate, errors=\'strict\')\n" +"--\n" +"\n" +"Codec used when reading a file in universal newlines mode.\n" +"\n" +"It wraps another incremental decoder, translating \\r\\n and \\r into \\n.\n" +"It also records the types of newlines encountered. When used with\n" +"translate=False, it ensures that the newline sequence is returned in\n" +"one piece. When used with decoder=None, it expects unicode strings as\n" +"decode input and translates newlines without first invoking an external\n" +"decoder."); static int -incrementalnewlinedecoder_init(nldecoder_object *self, - PyObject *args, PyObject *kwds) +_io_IncrementalNewlineDecoder___init___impl(nldecoder_object *self, + PyObject *decoder, int translate, + PyObject *errors); + +static int +_io_IncrementalNewlineDecoder___init__(PyObject *self, PyObject *args, PyObject *kwargs) { + int return_value = -1; + static char *_keywords[] = {"decoder", "translate", "errors", NULL}; PyObject *decoder; int translate; PyObject *errors = NULL; - char *kwlist[] = {"decoder", "translate", "errors", NULL}; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "Oi|O:IncrementalNewlineDecoder", - kwlist, &decoder, &translate, &errors)) - return -1; + if (!PyArg_ParseTupleAndKeywords(args, kwargs, + "Oi|O:IncrementalNewlineDecoder", _keywords, + &decoder, &translate, &errors)) + goto exit; + return_value = _io_IncrementalNewlineDecoder___init___impl((nldecoder_object *)self, decoder, translate, errors); - self->decoder = decoder; - Py_INCREF(decoder); - - if (errors == NULL) { - self->errors = PyUnicode_FromString("strict"); - if (self->errors == NULL) - return -1; - } - else { - Py_INCREF(errors); - self->errors = errors; - } - - self->translate = translate; - self->seennl = 0; - self->pendingcr = 0; - - return 0; +exit: + return return_value; } -static void -incrementalnewlinedecoder_dealloc(nldecoder_object *self) -{ - Py_CLEAR(self->decoder); - Py_CLEAR(self->errors); - Py_TYPE(self)->tp_free((PyObject *)self); -} +PyDoc_STRVAR(_io_IncrementalNewlineDecoder_decode__doc__, +"decode($self, /, input, final=False)\n" +"--\n" +"\n"); -static int -check_decoded(PyObject *decoded) -{ - if (decoded == NULL) - return -1; - if (!PyUnicode_Check(decoded)) { - PyErr_Format(PyExc_TypeError, - "decoder should return a string result, not '%.200s'", - Py_TYPE(decoded)->tp_name); - Py_DECREF(decoded); - return -1; - } - if (PyUnicode_READY(decoded) < 0) { - Py_DECREF(decoded); - return -1; - } - return 0; -} - -#define SEEN_CR 1 -#define SEEN_LF 2 -#define SEEN_CRLF 4 -#define SEEN_ALL (SEEN_CR | SEEN_LF | SEEN_CRLF) - -PyObject * -_PyIncrementalNewlineDecoder_decode(PyObject *myself, - PyObject *input, int final) -{ - PyObject *output; - Py_ssize_t output_len; - nldecoder_object *self = (nldecoder_object *) myself; - - if (self->decoder == NULL) { - PyErr_SetString(PyExc_ValueError, - "IncrementalNewlineDecoder.__init__ not called"); - return NULL; - } - - /* decode input (with the eventual \r from a previous pass) */ - if (self->decoder != Py_None) { - output = PyObject_CallMethodObjArgs(self->decoder, - _PyIO_str_decode, input, final ? Py_True : Py_False, NULL); - } - else { - output = input; - Py_INCREF(output); - } - - if (check_decoded(output) < 0) - return NULL; - - output_len = PyUnicode_GET_LENGTH(output); - if (self->pendingcr && (final || output_len > 0)) { - /* Prefix output with CR */ - int kind; - PyObject *modified; - char *out; - - modified = PyUnicode_New(output_len + 1, - PyUnicode_MAX_CHAR_VALUE(output)); - if (modified == NULL) - goto error; - kind = PyUnicode_KIND(modified); - out = PyUnicode_DATA(modified); - PyUnicode_WRITE(kind, PyUnicode_DATA(modified), 0, '\r'); - memcpy(out + kind, PyUnicode_DATA(output), kind * output_len); - Py_DECREF(output); - output = modified; /* output remains ready */ - self->pendingcr = 0; - output_len++; - } - - /* retain last \r even when not translating data: - * then readline() is sure to get \r\n in one pass - */ - if (!final) { - if (output_len > 0 - && PyUnicode_READ_CHAR(output, output_len - 1) == '\r') - { - PyObject *modified = PyUnicode_Substring(output, 0, output_len -1); - if (modified == NULL) - goto error; - Py_DECREF(output); - output = modified; - self->pendingcr = 1; - } - } - - /* Record which newlines are read and do newline translation if desired, - all in one pass. */ - { - void *in_str; - Py_ssize_t len; - int seennl = self->seennl; - int only_lf = 0; - int kind; - - in_str = PyUnicode_DATA(output); - len = PyUnicode_GET_LENGTH(output); - kind = PyUnicode_KIND(output); - - if (len == 0) - return output; - - /* If, up to now, newlines are consistently \n, do a quick check - for the \r *byte* with the libc's optimized memchr. - */ - if (seennl == SEEN_LF || seennl == 0) { - only_lf = (memchr(in_str, '\r', kind * len) == NULL); - } - - if (only_lf) { - /* If not already seen, quick scan for a possible "\n" character. - (there's nothing else to be done, even when in translation mode) - */ - if (seennl == 0 && - memchr(in_str, '\n', kind * len) != NULL) { - if (kind == PyUnicode_1BYTE_KIND) - seennl |= SEEN_LF; - else { - Py_ssize_t i = 0; - for (;;) { - Py_UCS4 c; - /* Fast loop for non-control characters */ - while (PyUnicode_READ(kind, in_str, i) > '\n') - i++; - c = PyUnicode_READ(kind, in_str, i++); - if (c == '\n') { - seennl |= SEEN_LF; - break; - } - if (i >= len) - break; - } - } - } - /* Finished: we have scanned for newlines, and none of them - need translating */ - } - else if (!self->translate) { - Py_ssize_t i = 0; - /* We have already seen all newline types, no need to scan again */ - if (seennl == SEEN_ALL) - goto endscan; - for (;;) { - Py_UCS4 c; - /* Fast loop for non-control characters */ - while (PyUnicode_READ(kind, in_str, i) > '\r') - i++; - c = PyUnicode_READ(kind, in_str, i++); - if (c == '\n') - seennl |= SEEN_LF; - else if (c == '\r') { - if (PyUnicode_READ(kind, in_str, i) == '\n') { - seennl |= SEEN_CRLF; - i++; - } - else - seennl |= SEEN_CR; - } - if (i >= len) - break; - if (seennl == SEEN_ALL) - break; - } - endscan: - ; - } - else { - void *translated; - int kind = PyUnicode_KIND(output); - void *in_str = PyUnicode_DATA(output); - Py_ssize_t in, out; - /* XXX: Previous in-place translation here is disabled as - resizing is not possible anymore */ - /* We could try to optimize this so that we only do a copy - when there is something to translate. On the other hand, - we already know there is a \r byte, so chances are high - that something needs to be done. */ - translated = PyMem_Malloc(kind * len); - if (translated == NULL) { - PyErr_NoMemory(); - goto error; - } - in = out = 0; - for (;;) { - Py_UCS4 c; - /* Fast loop for non-control characters */ - while ((c = PyUnicode_READ(kind, in_str, in++)) > '\r') - PyUnicode_WRITE(kind, translated, out++, c); - if (c == '\n') { - PyUnicode_WRITE(kind, translated, out++, c); - seennl |= SEEN_LF; - continue; - } - if (c == '\r') { - if (PyUnicode_READ(kind, in_str, in) == '\n') { - in++; - seennl |= SEEN_CRLF; - } - else - seennl |= SEEN_CR; - PyUnicode_WRITE(kind, translated, out++, '\n'); - continue; - } - if (in > len) - break; - PyUnicode_WRITE(kind, translated, out++, c); - } - Py_DECREF(output); - output = PyUnicode_FromKindAndData(kind, translated, out); - PyMem_Free(translated); - if (!output) - return NULL; - } - self->seennl |= seennl; - } - - return output; - - error: - Py_DECREF(output); - return NULL; -} +#define _IO_INCREMENTALNEWLINEDECODER_DECODE_METHODDEF \ + {"decode", (PyCFunction)_io_IncrementalNewlineDecoder_decode, METH_VARARGS|METH_KEYWORDS, _io_IncrementalNewlineDecoder_decode__doc__}, static PyObject * -incrementalnewlinedecoder_decode(nldecoder_object *self, - PyObject *args, PyObject *kwds) +_io_IncrementalNewlineDecoder_decode_impl(nldecoder_object *self, + PyObject *input, int final); + +static PyObject * +_io_IncrementalNewlineDecoder_decode(nldecoder_object *self, PyObject *args, PyObject *kwargs) { - char *kwlist[] = {"input", "final", NULL}; + PyObject *return_value = NULL; + static char *_keywords[] = {"input", "final", NULL}; PyObject *input; int final = 0; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|i:IncrementalNewlineDecoder", - kwlist, &input, &final)) - return NULL; - return _PyIncrementalNewlineDecoder_decode((PyObject *) self, input, final); + if (!PyArg_ParseTupleAndKeywords(args, kwargs, + "O|i:decode", _keywords, + &input, &final)) + goto exit; + return_value = _io_IncrementalNewlineDecoder_decode_impl(self, input, final); + +exit: + return return_value; } +PyDoc_STRVAR(_io_IncrementalNewlineDecoder_getstate__doc__, +"getstate($self, /)\n" +"--\n" +"\n"); + +#define _IO_INCREMENTALNEWLINEDECODER_GETSTATE_METHODDEF \ + {"getstate", (PyCFunction)_io_IncrementalNewlineDecoder_getstate, METH_NOARGS, _io_IncrementalNewlineDecoder_getstate__doc__}, + static PyObject * -incrementalnewlinedecoder_getstate(nldecoder_object *self, PyObject *args) +_io_IncrementalNewlineDecoder_getstate_impl(nldecoder_object *self); + +static PyObject * +_io_IncrementalNewlineDecoder_getstate(nldecoder_object *self, PyObject *Py_UNUSED(ignored)) { - PyObject *buffer; - unsigned PY_LONG_LONG flag; - - if (self->decoder != Py_None) { - PyObject *state = PyObject_CallMethodObjArgs(self->decoder, - _PyIO_str_getstate, NULL); - if (state == NULL) - return NULL; - if (!PyArg_Parse(state, "(OK)", &buffer, &flag)) { - Py_DECREF(state); - return NULL; - } - Py_INCREF(buffer); - Py_DECREF(state); - } - else { - buffer = PyBytes_FromString(""); - flag = 0; - } - flag <<= 1; - if (self->pendingcr) - flag |= 1; - return Py_BuildValue("NK", buffer, flag); + return _io_IncrementalNewlineDecoder_getstate_impl(self); } +PyDoc_STRVAR(_io_IncrementalNewlineDecoder_setstate__doc__, +"setstate($self, state, /)\n" +"--\n" +"\n"); + +#define _IO_INCREMENTALNEWLINEDECODER_SETSTATE_METHODDEF \ + {"setstate", (PyCFunction)_io_IncrementalNewlineDecoder_setstate, METH_O, _io_IncrementalNewlineDecoder_setstate__doc__}, + +PyDoc_STRVAR(_io_IncrementalNewlineDecoder_reset__doc__, +"reset($self, /)\n" +"--\n" +"\n"); + +#define _IO_INCREMENTALNEWLINEDECODER_RESET_METHODDEF \ + {"reset", (PyCFunction)_io_IncrementalNewlineDecoder_reset, METH_NOARGS, _io_IncrementalNewlineDecoder_reset__doc__}, + static PyObject * -incrementalnewlinedecoder_setstate(nldecoder_object *self, PyObject *state) +_io_IncrementalNewlineDecoder_reset_impl(nldecoder_object *self); + +static PyObject * +_io_IncrementalNewlineDecoder_reset(nldecoder_object *self, PyObject *Py_UNUSED(ignored)) { - PyObject *buffer; - unsigned PY_LONG_LONG flag; - - if (!PyArg_Parse(state, "(OK)", &buffer, &flag)) - return NULL; - - self->pendingcr = (int) (flag & 1); - flag >>= 1; - - if (self->decoder != Py_None) - return _PyObject_CallMethodId(self->decoder, - &PyId_setstate, "((OK))", buffer, flag); - else - Py_RETURN_NONE; + return _io_IncrementalNewlineDecoder_reset_impl(self); } -static PyObject * -incrementalnewlinedecoder_reset(nldecoder_object *self, PyObject *args) +PyDoc_STRVAR(_io_TextIOWrapper___init____doc__, +"TextIOWrapper(buffer, encoding=None, errors=None, newline=None,\n" +" line_buffering=False, write_through=False)\n" +"--\n" +"\n" +"Character and line based layer over a BufferedIOBase object, buffer.\n" +"\n" +"encoding gives the name of the encoding that the stream will be\n" +"decoded or encoded with. It defaults to locale.getpreferredencoding(False).\n" +"\n" +"errors determines the strictness of encoding and decoding (see\n" +"help(codecs.Codec) or the documentation for codecs.register) and\n" +"defaults to \"strict\".\n" +"\n" +"newline controls how line endings are handled. It can be None, \'\',\n" +"\'\\n\', \'\\r\', and \'\\r\\n\'. It works as follows:\n" +"\n" +"* On input, if newline is None, universal newlines mode is\n" +" enabled. Lines in the input can end in \'\\n\', \'\\r\', or \'\\r\\n\', and\n" +" these are translated into \'\\n\' before being returned to the\n" +" caller. If it is \'\', universal newline mode is enabled, but line\n" +" endings are returned to the caller untranslated. If it has any of\n" +" the other legal values, input lines are only terminated by the given\n" +" string, and the line ending is returned to the caller untranslated.\n" +"\n" +"* On output, if newline is None, any \'\\n\' characters written are\n" +" translated to the system default line separator, os.linesep. If\n" +" newline is \'\' or \'\\n\', no translation takes place. If newline is any\n" +" of the other legal values, any \'\\n\' characters written are translated\n" +" to the given string.\n" +"\n" +"If line_buffering is True, a call to flush is implied when a call to\n" +"write contains a newline character."); + +static int +_io_TextIOWrapper___init___impl(textio *self, PyObject *buffer, + const char *encoding, const char *errors, + const char *newline, int line_buffering, + int write_through); + +static int +_io_TextIOWrapper___init__(PyObject *self, PyObject *args, PyObject *kwargs) { - self->seennl = 0; - self->pendingcr = 0; - if (self->decoder != Py_None) - return PyObject_CallMethodObjArgs(self->decoder, _PyIO_str_reset, NULL); - else - Py_RETURN_NONE; + int return_value = -1; + static char *_keywords[] = {"buffer", "encoding", "errors", "newline", "line_buffering", "write_through", NULL}; + PyObject *buffer; + const char *encoding = NULL; + const char *errors = NULL; + const char *newline = NULL; + int line_buffering = 0; + int write_through = 0; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, + "O|zzzii:TextIOWrapper", _keywords, + &buffer, &encoding, &errors, &newline, &line_buffering, &write_through)) + goto exit; + return_value = _io_TextIOWrapper___init___impl((textio *)self, buffer, encoding, errors, newline, line_buffering, write_through); + +exit: + return return_value; } +PyDoc_STRVAR(_io_TextIOWrapper_detach__doc__, +"detach($self, /)\n" +"--\n" +"\n"); + +#define _IO_TEXTIOWRAPPER_DETACH_METHODDEF \ + {"detach", (PyCFunction)_io_TextIOWrapper_detach, METH_NOARGS, _io_TextIOWrapper_detach__doc__}, + static PyObject * -incrementalnewlinedecoder_newlines_get(nldecoder_object *self, void *context) +_io_TextIOWrapper_detach_impl(textio *self); + +static PyObject * +_io_TextIOWrapper_detach(textio *self, PyObject *Py_UNUSED(ignored)) { - switch (self->seennl) { - case SEEN_CR: - return PyUnicode_FromString("\r"); - case SEEN_LF: - return PyUnicode_FromString("\n"); - case SEEN_CRLF: - return PyUnicode_FromString("\r\n"); - case SEEN_CR | SEEN_LF: - return Py_BuildValue("ss", "\r", "\n"); - case SEEN_CR | SEEN_CRLF: - return Py_BuildValue("ss", "\r", "\r\n"); - case SEEN_LF | SEEN_CRLF: - return Py_BuildValue("ss", "\n", "\r\n"); - case SEEN_CR | SEEN_LF | SEEN_CRLF: - return Py_BuildValue("sss", "\r", "\n", "\r\n"); - default: - Py_RETURN_NONE; - } - + return _io_TextIOWrapper_detach_impl(self); } +PyDoc_STRVAR(_io_TextIOWrapper_write__doc__, +"write($self, text, /)\n" +"--\n" +"\n"); -static PyMethodDef incrementalnewlinedecoder_methods[] = { - {"decode", (PyCFunction)incrementalnewlinedecoder_decode, METH_VARARGS|METH_KEYWORDS}, - {"getstate", (PyCFunction)incrementalnewlinedecoder_getstate, METH_NOARGS}, - {"setstate", (PyCFunction)incrementalnewlinedecoder_setstate, METH_O}, - {"reset", (PyCFunction)incrementalnewlinedecoder_reset, METH_NOARGS}, - {NULL} -}; - -static PyGetSetDef incrementalnewlinedecoder_getset[] = { - {"newlines", (getter)incrementalnewlinedecoder_newlines_get, NULL, NULL}, - {NULL} -}; - -PyTypeObject PyIncrementalNewlineDecoder_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "_io.IncrementalNewlineDecoder", /*tp_name*/ - sizeof(nldecoder_object), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - (destructor)incrementalnewlinedecoder_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare */ - 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 | Py_TPFLAGS_BASETYPE, /*tp_flags*/ - incrementalnewlinedecoder_doc, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /*tp_weaklistoffset*/ - 0, /* tp_iter */ - 0, /* tp_iternext */ - incrementalnewlinedecoder_methods, /* tp_methods */ - 0, /* tp_members */ - incrementalnewlinedecoder_getset, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - (initproc)incrementalnewlinedecoder_init, /* tp_init */ - 0, /* tp_alloc */ - PyType_GenericNew, /* tp_new */ -}; - - -/* TextIOWrapper */ - -PyDoc_STRVAR(textiowrapper_doc, - "Character and line based layer over a BufferedIOBase object, buffer.\n" - "\n" - "encoding gives the name of the encoding that the stream will be\n" - "decoded or encoded with. It defaults to locale.getpreferredencoding(False).\n" - "\n" - "errors determines the strictness of encoding and decoding (see\n" - "help(codecs.Codec) or the documentation for codecs.register) and\n" - "defaults to \"strict\".\n" - "\n" - "newline controls how line endings are handled. It can be None, '',\n" - "'\\n', '\\r', and '\\r\\n'. It works as follows:\n" - "\n" - "* On input, if newline is None, universal newlines mode is\n" - " enabled. Lines in the input can end in '\\n', '\\r', or '\\r\\n', and\n" - " these are translated into '\\n' before being returned to the\n" - " caller. If it is '', universal newline mode is enabled, but line\n" - " endings are returned to the caller untranslated. If it has any of\n" - " the other legal values, input lines are only terminated by the given\n" - " string, and the line ending is returned to the caller untranslated.\n" - "\n" - "* On output, if newline is None, any '\\n' characters written are\n" - " translated to the system default line separator, os.linesep. If\n" - " newline is '' or '\\n', no translation takes place. If newline is any\n" - " of the other legal values, any '\\n' characters written are translated\n" - " to the given string.\n" - "\n" - "If line_buffering is True, a call to flush is implied when a call to\n" - "write contains a newline character." - ); - -typedef PyObject * - (*encodefunc_t)(PyObject *, PyObject *); - -typedef struct -{ - PyObject_HEAD - int ok; /* initialized? */ - int detached; - Py_ssize_t chunk_size; - PyObject *buffer; - PyObject *encoding; - PyObject *encoder; - PyObject *decoder; - PyObject *readnl; - PyObject *errors; - const char *writenl; /* utf-8 encoded, NULL stands for \n */ - char line_buffering; - char write_through; - char readuniversal; - char readtranslate; - char writetranslate; - char seekable; - char has_read1; - char telling; - char finalizing; - /* Specialized encoding func (see below) */ - encodefunc_t encodefunc; - /* Whether or not it's the start of the stream */ - char encoding_start_of_stream; - - /* Reads and writes are internally buffered in order to speed things up. - However, any read will first flush the write buffer if itsn't empty. - - Please also note that text to be written is first encoded before being - buffered. This is necessary so that encoding errors are immediately - reported to the caller, but it unfortunately means that the - IncrementalEncoder (whose encode() method is always written in Python) - becomes a bottleneck for small writes. - */ - PyObject *decoded_chars; /* buffer for text returned from decoder */ - Py_ssize_t decoded_chars_used; /* offset into _decoded_chars for read() */ - PyObject *pending_bytes; /* list of bytes objects waiting to be - written, or NULL */ - Py_ssize_t pending_bytes_count; - - /* snapshot is either None, or a tuple (dec_flags, next_input) where - * dec_flags is the second (integer) item of the decoder state and - * next_input is the chunk of input bytes that comes next after the - * snapshot point. We use this to reconstruct decoder states in tell(). - */ - PyObject *snapshot; - /* Bytes-to-characters ratio for the current chunk. Serves as input for - the heuristic in tell(). */ - double b2cratio; - - /* Cache raw object if it's a FileIO object */ - PyObject *raw; - - PyObject *weakreflist; - PyObject *dict; -} textio; - - -/* A couple of specialized cases in order to bypass the slow incremental - encoding methods for the most popular encodings. */ +#define _IO_TEXTIOWRAPPER_WRITE_METHODDEF \ + {"write", (PyCFunction)_io_TextIOWrapper_write, METH_O, _io_TextIOWrapper_write__doc__}, static PyObject * -ascii_encode(textio *self, PyObject *text) +_io_TextIOWrapper_write_impl(textio *self, PyObject *text); + +static PyObject * +_io_TextIOWrapper_write(textio *self, PyObject *arg) { - return _PyUnicode_AsASCIIString(text, PyBytes_AS_STRING(self->errors)); + PyObject *return_value = NULL; + PyObject *text; + + if (!PyArg_Parse(arg, + "U:write", + &text)) + goto exit; + return_value = _io_TextIOWrapper_write_impl(self, text); + +exit: + return return_value; } +PyDoc_STRVAR(_io_TextIOWrapper_read__doc__, +"read($self, size=-1, /)\n" +"--\n" +"\n"); + +#define _IO_TEXTIOWRAPPER_READ_METHODDEF \ + {"read", (PyCFunction)_io_TextIOWrapper_read, METH_VARARGS, _io_TextIOWrapper_read__doc__}, + static PyObject * -utf16be_encode(textio *self, PyObject *text) +_io_TextIOWrapper_read_impl(textio *self, Py_ssize_t n); + +static PyObject * +_io_TextIOWrapper_read(textio *self, PyObject *args) { - return _PyUnicode_EncodeUTF16(text, - PyBytes_AS_STRING(self->errors), 1); + PyObject *return_value = NULL; + Py_ssize_t n = -1; + + if (!PyArg_ParseTuple(args, + "|O&:read", + _PyIO_ConvertSsize_t, &n)) + goto exit; + return_value = _io_TextIOWrapper_read_impl(self, n); + +exit: + return return_value; } +PyDoc_STRVAR(_io_TextIOWrapper_readline__doc__, +"readline($self, size=-1, /)\n" +"--\n" +"\n"); + +#define _IO_TEXTIOWRAPPER_READLINE_METHODDEF \ + {"readline", (PyCFunction)_io_TextIOWrapper_readline, METH_VARARGS, _io_TextIOWrapper_readline__doc__}, + static PyObject * -utf16le_encode(textio *self, PyObject *text) +_io_TextIOWrapper_readline_impl(textio *self, Py_ssize_t size); + +static PyObject * +_io_TextIOWrapper_readline(textio *self, PyObject *args) { - return _PyUnicode_EncodeUTF16(text, - PyBytes_AS_STRING(self->errors), -1); + PyObject *return_value = NULL; + Py_ssize_t size = -1; + + if (!PyArg_ParseTuple(args, + "|n:readline", + &size)) + goto exit; + return_value = _io_TextIOWrapper_readline_impl(self, size); + +exit: + return return_value; } +PyDoc_STRVAR(_io_TextIOWrapper_seek__doc__, +"seek($self, cookie, whence=0, /)\n" +"--\n" +"\n"); + +#define _IO_TEXTIOWRAPPER_SEEK_METHODDEF \ + {"seek", (PyCFunction)_io_TextIOWrapper_seek, METH_VARARGS, _io_TextIOWrapper_seek__doc__}, + static PyObject * -utf16_encode(textio *self, PyObject *text) +_io_TextIOWrapper_seek_impl(textio *self, PyObject *cookieObj, int whence); + +static PyObject * +_io_TextIOWrapper_seek(textio *self, PyObject *args) { - if (!self->encoding_start_of_stream) { - /* Skip the BOM and use native byte ordering */ -#if PY_BIG_ENDIAN - return utf16be_encode(self, text); -#else - return utf16le_encode(self, text); -#endif - } - return _PyUnicode_EncodeUTF16(text, - PyBytes_AS_STRING(self->errors), 0); + PyObject *return_value = NULL; + PyObject *cookieObj; + int whence = 0; + + if (!PyArg_ParseTuple(args, + "O|i:seek", + &cookieObj, &whence)) + goto exit; + return_value = _io_TextIOWrapper_seek_impl(self, cookieObj, whence); + +exit: + return return_value; } +PyDoc_STRVAR(_io_TextIOWrapper_tell__doc__, +"tell($self, /)\n" +"--\n" +"\n"); + +#define _IO_TEXTIOWRAPPER_TELL_METHODDEF \ + {"tell", (PyCFunction)_io_TextIOWrapper_tell, METH_NOARGS, _io_TextIOWrapper_tell__doc__}, + static PyObject * -utf32be_encode(textio *self, PyObject *text) +_io_TextIOWrapper_tell_impl(textio *self); + +static PyObject * +_io_TextIOWrapper_tell(textio *self, PyObject *Py_UNUSED(ignored)) { - return _PyUnicode_EncodeUTF32(text, - PyBytes_AS_STRING(self->errors), 1); + return _io_TextIOWrapper_tell_impl(self); } +PyDoc_STRVAR(_io_TextIOWrapper_truncate__doc__, +"truncate($self, pos=None, /)\n" +"--\n" +"\n"); + +#define _IO_TEXTIOWRAPPER_TRUNCATE_METHODDEF \ + {"truncate", (PyCFunction)_io_TextIOWrapper_truncate, METH_VARARGS, _io_TextIOWrapper_truncate__doc__}, + static PyObject * -utf32le_encode(textio *self, PyObject *text) +_io_TextIOWrapper_truncate_impl(textio *self, PyObject *pos); + +static PyObject * +_io_TextIOWrapper_truncate(textio *self, PyObject *args) { - return _PyUnicode_EncodeUTF32(text, - PyBytes_AS_STRING(self->errors), -1); + PyObject *return_value = NULL; + PyObject *pos = Py_None; + + if (!PyArg_UnpackTuple(args, "truncate", + 0, 1, + &pos)) + goto exit; + return_value = _io_TextIOWrapper_truncate_impl(self, pos); + +exit: + return return_value; } +PyDoc_STRVAR(_io_TextIOWrapper_fileno__doc__, +"fileno($self, /)\n" +"--\n" +"\n"); + +#define _IO_TEXTIOWRAPPER_FILENO_METHODDEF \ + {"fileno", (PyCFunction)_io_TextIOWrapper_fileno, METH_NOARGS, _io_TextIOWrapper_fileno__doc__}, + static PyObject * -utf32_encode(textio *self, PyObject *text) +_io_TextIOWrapper_fileno_impl(textio *self); + +static PyObject * +_io_TextIOWrapper_fileno(textio *self, PyObject *Py_UNUSED(ignored)) { - if (!self->encoding_start_of_stream) { - /* Skip the BOM and use native byte ordering */ -#if PY_BIG_ENDIAN - return utf32be_encode(self, text); -#else - return utf32le_encode(self, text); -#endif - } - return _PyUnicode_EncodeUTF32(text, - PyBytes_AS_STRING(self->errors), 0); + return _io_TextIOWrapper_fileno_impl(self); } +PyDoc_STRVAR(_io_TextIOWrapper_seekable__doc__, +"seekable($self, /)\n" +"--\n" +"\n"); + +#define _IO_TEXTIOWRAPPER_SEEKABLE_METHODDEF \ + {"seekable", (PyCFunction)_io_TextIOWrapper_seekable, METH_NOARGS, _io_TextIOWrapper_seekable__doc__}, + static PyObject * -utf8_encode(textio *self, PyObject *text) +_io_TextIOWrapper_seekable_impl(textio *self); + +static PyObject * +_io_TextIOWrapper_seekable(textio *self, PyObject *Py_UNUSED(ignored)) { - return _PyUnicode_AsUTF8String(text, PyBytes_AS_STRING(self->errors)); + return _io_TextIOWrapper_seekable_impl(self); } +PyDoc_STRVAR(_io_TextIOWrapper_readable__doc__, +"readable($self, /)\n" +"--\n" +"\n"); + +#define _IO_TEXTIOWRAPPER_READABLE_METHODDEF \ + {"readable", (PyCFunction)_io_TextIOWrapper_readable, METH_NOARGS, _io_TextIOWrapper_readable__doc__}, + static PyObject * -latin1_encode(textio *self, PyObject *text) +_io_TextIOWrapper_readable_impl(textio *self); + +static PyObject * +_io_TextIOWrapper_readable(textio *self, PyObject *Py_UNUSED(ignored)) { - return _PyUnicode_AsLatin1String(text, PyBytes_AS_STRING(self->errors)); + return _io_TextIOWrapper_readable_impl(self); } -/* Map normalized encoding names onto the specialized encoding funcs */ +PyDoc_STRVAR(_io_TextIOWrapper_writable__doc__, +"writable($self, /)\n" +"--\n" +"\n"); -typedef struct { - const char *name; - encodefunc_t encodefunc; -} encodefuncentry; +#define _IO_TEXTIOWRAPPER_WRITABLE_METHODDEF \ + {"writable", (PyCFunction)_io_TextIOWrapper_writable, METH_NOARGS, _io_TextIOWrapper_writable__doc__}, -static encodefuncentry encodefuncs[] = { - {"ascii", (encodefunc_t) ascii_encode}, - {"iso8859-1", (encodefunc_t) latin1_encode}, - {"utf-8", (encodefunc_t) utf8_encode}, - {"utf-16-be", (encodefunc_t) utf16be_encode}, - {"utf-16-le", (encodefunc_t) utf16le_encode}, - {"utf-16", (encodefunc_t) utf16_encode}, - {"utf-32-be", (encodefunc_t) utf32be_encode}, - {"utf-32-le", (encodefunc_t) utf32le_encode}, - {"utf-32", (encodefunc_t) utf32_encode}, - {NULL, NULL} -}; +static PyObject * +_io_TextIOWrapper_writable_impl(textio *self); - -static int -textiowrapper_init(textio *self, PyObject *args, PyObject *kwds) +static PyObject * +_io_TextIOWrapper_writable(textio *self, PyObject *Py_UNUSED(ignored)) { - char *kwlist[] = {"buffer", "encoding", "errors", - "newline", "line_buffering", "write_through", - NULL}; - PyObject *buffer, *raw, *codec_info = NULL; - char *encoding = NULL; - char *errors = NULL; - char *newline = NULL; - int line_buffering = 0, write_through = 0; - _PyIO_State *state = NULL; - - PyObject *res; - int r; - - self->ok = 0; - self->detached = 0; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|zzzii:fileio", - kwlist, &buffer, &encoding, &errors, - &newline, &line_buffering, &write_through)) - return -1; - - if (newline && newline[0] != '\0' - && !(newline[0] == '\n' && newline[1] == '\0') - && !(newline[0] == '\r' && newline[1] == '\0') - && !(newline[0] == '\r' && newline[1] == '\n' && newline[2] == '\0')) { - PyErr_Format(PyExc_ValueError, - "illegal newline value: %s", newline); - return -1; - } - - Py_CLEAR(self->buffer); - Py_CLEAR(self->encoding); - Py_CLEAR(self->encoder); - Py_CLEAR(self->decoder); - Py_CLEAR(self->readnl); - Py_CLEAR(self->decoded_chars); - Py_CLEAR(self->pending_bytes); - Py_CLEAR(self->snapshot); - Py_CLEAR(self->errors); - Py_CLEAR(self->raw); - self->decoded_chars_used = 0; - self->pending_bytes_count = 0; - self->encodefunc = NULL; - self->b2cratio = 0.0; - - if (encoding == NULL) { - /* Try os.device_encoding(fileno) */ - PyObject *fileno; - state = IO_STATE(); - if (state == NULL) - goto error; - fileno = _PyObject_CallMethodId(buffer, &PyId_fileno, NULL); - /* Ignore only AttributeError and UnsupportedOperation */ - if (fileno == NULL) { - if (PyErr_ExceptionMatches(PyExc_AttributeError) || - PyErr_ExceptionMatches(state->unsupported_operation)) { - PyErr_Clear(); - } - else { - goto error; - } - } - else { - int fd = _PyLong_AsInt(fileno); - Py_DECREF(fileno); - if (fd == -1 && PyErr_Occurred()) { - goto error; - } - - self->encoding = _Py_device_encoding(fd); - if (self->encoding == NULL) - goto error; - else if (!PyUnicode_Check(self->encoding)) - Py_CLEAR(self->encoding); - } - } - if (encoding == NULL && self->encoding == NULL) { - PyObject *locale_module = _PyIO_get_locale_module(state); - if (locale_module == NULL) - goto catch_ImportError; - self->encoding = _PyObject_CallMethodId( - locale_module, &PyId_getpreferredencoding, "O", Py_False); - Py_DECREF(locale_module); - if (self->encoding == NULL) { - catch_ImportError: - /* - Importing locale can raise a ImportError because of - _functools, and locale.getpreferredencoding can raise a - ImportError if _locale is not available. These will happen - during module building. - */ - if (PyErr_ExceptionMatches(PyExc_ImportError)) { - PyErr_Clear(); - self->encoding = PyUnicode_FromString("ascii"); - } - else - goto error; - } - else if (!PyUnicode_Check(self->encoding)) - Py_CLEAR(self->encoding); - } - if (self->encoding != NULL) { - encoding = _PyUnicode_AsString(self->encoding); - if (encoding == NULL) - goto error; - } - else if (encoding != NULL) { - self->encoding = PyUnicode_FromString(encoding); - if (self->encoding == NULL) - goto error; - } - else { - PyErr_SetString(PyExc_IOError, - "could not determine default encoding"); - } - - /* Check we have been asked for a real text encoding */ - codec_info = _PyCodec_LookupTextEncoding(encoding, "codecs.open()"); - if (codec_info == NULL) { - Py_CLEAR(self->encoding); - goto error; - } - - /* XXX: Failures beyond this point have the potential to leak elements - * of the partially constructed object (like self->encoding) - */ - - if (errors == NULL) - errors = "strict"; - self->errors = PyBytes_FromString(errors); - if (self->errors == NULL) - goto error; - - self->chunk_size = 8192; - self->readuniversal = (newline == NULL || newline[0] == '\0'); - self->line_buffering = line_buffering; - self->write_through = write_through; - self->readtranslate = (newline == NULL); - if (newline) { - self->readnl = PyUnicode_FromString(newline); - if (self->readnl == NULL) - goto error; - } - self->writetranslate = (newline == NULL || newline[0] != '\0'); - if (!self->readuniversal && self->readnl) { - self->writenl = _PyUnicode_AsString(self->readnl); - if (self->writenl == NULL) - goto error; - if (!strcmp(self->writenl, "\n")) - self->writenl = NULL; - } -#ifdef MS_WINDOWS - else - self->writenl = "\r\n"; -#endif - - /* Build the decoder object */ - res = _PyObject_CallMethodId(buffer, &PyId_readable, NULL); - if (res == NULL) - goto error; - r = PyObject_IsTrue(res); - Py_DECREF(res); - if (r == -1) - goto error; - if (r == 1) { - self->decoder = _PyCodecInfo_GetIncrementalDecoder(codec_info, - errors); - if (self->decoder == NULL) - goto error; - - if (self->readuniversal) { - PyObject *incrementalDecoder = PyObject_CallFunction( - (PyObject *)&PyIncrementalNewlineDecoder_Type, - "Oi", self->decoder, (int)self->readtranslate); - if (incrementalDecoder == NULL) - goto error; - Py_CLEAR(self->decoder); - self->decoder = incrementalDecoder; - } - } - - /* Build the encoder object */ - res = _PyObject_CallMethodId(buffer, &PyId_writable, NULL); - if (res == NULL) - goto error; - r = PyObject_IsTrue(res); - Py_DECREF(res); - if (r == -1) - goto error; - if (r == 1) { - self->encoder = _PyCodecInfo_GetIncrementalEncoder(codec_info, - errors); - if (self->encoder == NULL) - goto error; - /* Get the normalized named of the codec */ - res = _PyObject_GetAttrId(codec_info, &PyId_name); - if (res == NULL) { - if (PyErr_ExceptionMatches(PyExc_AttributeError)) - PyErr_Clear(); - else - goto error; - } - else if (PyUnicode_Check(res)) { - encodefuncentry *e = encodefuncs; - while (e->name != NULL) { - if (!PyUnicode_CompareWithASCIIString(res, e->name)) { - self->encodefunc = e->encodefunc; - break; - } - e++; - } - } - Py_XDECREF(res); - } - - /* Finished sorting out the codec details */ - Py_CLEAR(codec_info); - - self->buffer = buffer; - Py_INCREF(buffer); - - if (Py_TYPE(buffer) == &PyBufferedReader_Type || - Py_TYPE(buffer) == &PyBufferedWriter_Type || - Py_TYPE(buffer) == &PyBufferedRandom_Type) { - raw = _PyObject_GetAttrId(buffer, &PyId_raw); - /* Cache the raw FileIO object to speed up 'closed' checks */ - if (raw == NULL) { - if (PyErr_ExceptionMatches(PyExc_AttributeError)) - PyErr_Clear(); - else - goto error; - } - else if (Py_TYPE(raw) == &PyFileIO_Type) - self->raw = raw; - else - Py_DECREF(raw); - } - - res = _PyObject_CallMethodId(buffer, &PyId_seekable, NULL); - if (res == NULL) - goto error; - r = PyObject_IsTrue(res); - Py_DECREF(res); - if (r < 0) - goto error; - self->seekable = self->telling = r; - - self->has_read1 = _PyObject_HasAttrId(buffer, &PyId_read1); - - self->encoding_start_of_stream = 0; - if (self->seekable && self->encoder) { - PyObject *cookieObj; - int cmp; - - self->encoding_start_of_stream = 1; - - cookieObj = PyObject_CallMethodObjArgs(buffer, _PyIO_str_tell, NULL); - if (cookieObj == NULL) - goto error; - - cmp = PyObject_RichCompareBool(cookieObj, _PyIO_zero, Py_EQ); - Py_DECREF(cookieObj); - if (cmp < 0) { - goto error; - } - - if (cmp == 0) { - self->encoding_start_of_stream = 0; - res = PyObject_CallMethodObjArgs(self->encoder, _PyIO_str_setstate, - _PyIO_zero, NULL); - if (res == NULL) - goto error; - Py_DECREF(res); - } - } - - self->ok = 1; - return 0; - - error: - Py_XDECREF(codec_info); - return -1; + return _io_TextIOWrapper_writable_impl(self); } -static int -_textiowrapper_clear(textio *self) +PyDoc_STRVAR(_io_TextIOWrapper_isatty__doc__, +"isatty($self, /)\n" +"--\n" +"\n"); + +#define _IO_TEXTIOWRAPPER_ISATTY_METHODDEF \ + {"isatty", (PyCFunction)_io_TextIOWrapper_isatty, METH_NOARGS, _io_TextIOWrapper_isatty__doc__}, + +static PyObject * +_io_TextIOWrapper_isatty_impl(textio *self); + +static PyObject * +_io_TextIOWrapper_isatty(textio *self, PyObject *Py_UNUSED(ignored)) { - self->ok = 0; - Py_CLEAR(self->buffer); - Py_CLEAR(self->encoding); - Py_CLEAR(self->encoder); - Py_CLEAR(self->decoder); - Py_CLEAR(self->readnl); - Py_CLEAR(self->decoded_chars); - Py_CLEAR(self->pending_bytes); - Py_CLEAR(self->snapshot); - Py_CLEAR(self->errors); - Py_CLEAR(self->raw); - return 0; + return _io_TextIOWrapper_isatty_impl(self); } -static void -textiowrapper_dealloc(textio *self) +PyDoc_STRVAR(_io_TextIOWrapper_flush__doc__, +"flush($self, /)\n" +"--\n" +"\n"); + +#define _IO_TEXTIOWRAPPER_FLUSH_METHODDEF \ + {"flush", (PyCFunction)_io_TextIOWrapper_flush, METH_NOARGS, _io_TextIOWrapper_flush__doc__}, + +static PyObject * +_io_TextIOWrapper_flush_impl(textio *self); + +static PyObject * +_io_TextIOWrapper_flush(textio *self, PyObject *Py_UNUSED(ignored)) { - self->finalizing = 1; - if (_PyIOBase_finalize((PyObject *) self) < 0) - return; - _textiowrapper_clear(self); - _PyObject_GC_UNTRACK(self); - if (self->weakreflist != NULL) - PyObject_ClearWeakRefs((PyObject *)self); - Py_CLEAR(self->dict); - Py_TYPE(self)->tp_free((PyObject *)self); + return _io_TextIOWrapper_flush_impl(self); } -static int -textiowrapper_traverse(textio *self, visitproc visit, void *arg) -{ - Py_VISIT(self->buffer); - Py_VISIT(self->encoding); - Py_VISIT(self->encoder); - Py_VISIT(self->decoder); - Py_VISIT(self->readnl); - Py_VISIT(self->decoded_chars); - Py_VISIT(self->pending_bytes); - Py_VISIT(self->snapshot); - Py_VISIT(self->errors); - Py_VISIT(self->raw); +PyDoc_STRVAR(_io_TextIOWrapper_close__doc__, +"close($self, /)\n" +"--\n" +"\n"); - Py_VISIT(self->dict); - return 0; -} - -static int -textiowrapper_clear(textio *self) -{ - if (_textiowrapper_clear(self) < 0) - return -1; - Py_CLEAR(self->dict); - return 0; -} +#define _IO_TEXTIOWRAPPER_CLOSE_METHODDEF \ + {"close", (PyCFunction)_io_TextIOWrapper_close, METH_NOARGS, _io_TextIOWrapper_close__doc__}, static PyObject * -textiowrapper_closed_get(textio *self, void *context); - -/* This macro takes some shortcuts to make the common case faster. */ -#define CHECK_CLOSED(self) \ - do { \ - int r; \ - PyObject *_res; \ - if (Py_TYPE(self) == &PyTextIOWrapper_Type) { \ - if (self->raw != NULL) \ - r = _PyFileIO_closed(self->raw); \ - else { \ - _res = textiowrapper_closed_get(self, NULL); \ - if (_res == NULL) \ - return NULL; \ - r = PyObject_IsTrue(_res); \ - Py_DECREF(_res); \ - if (r < 0) \ - return NULL; \ - } \ - if (r > 0) { \ - PyErr_SetString(PyExc_ValueError, \ - "I/O operation on closed file."); \ - return NULL; \ - } \ - } \ - else if (_PyIOBase_check_closed((PyObject *)self, Py_True) == NULL) \ - return NULL; \ - } while (0) - -#define CHECK_INITIALIZED(self) \ - if (self->ok <= 0) { \ - PyErr_SetString(PyExc_ValueError, \ - "I/O operation on uninitialized object"); \ - return NULL; \ - } - -#define CHECK_ATTACHED(self) \ - CHECK_INITIALIZED(self); \ - if (self->detached) { \ - PyErr_SetString(PyExc_ValueError, \ - "underlying buffer has been detached"); \ - return NULL; \ - } - -#define CHECK_ATTACHED_INT(self) \ - if (self->ok <= 0) { \ - PyErr_SetString(PyExc_ValueError, \ - "I/O operation on uninitialized object"); \ - return -1; \ - } else if (self->detached) { \ - PyErr_SetString(PyExc_ValueError, \ - "underlying buffer has been detached"); \ - return -1; \ - } - +_io_TextIOWrapper_close_impl(textio *self); static PyObject * -textiowrapper_detach(textio *self) +_io_TextIOWrapper_close(textio *self, PyObject *Py_UNUSED(ignored)) { - PyObject *buffer, *res; - CHECK_ATTACHED(self); - res = PyObject_CallMethodObjArgs((PyObject *)self, _PyIO_str_flush, NULL); - if (res == NULL) - return NULL; - Py_DECREF(res); - buffer = self->buffer; - self->buffer = NULL; - self->detached = 1; - return buffer; + return _io_TextIOWrapper_close_impl(self); } - -/* Flush the internal write buffer. This doesn't explicitly flush the - underlying buffered object, though. */ -static int -_textiowrapper_writeflush(textio *self) -{ - PyObject *pending, *b, *ret; - - if (self->pending_bytes == NULL) - return 0; - - pending = self->pending_bytes; - Py_INCREF(pending); - self->pending_bytes_count = 0; - Py_CLEAR(self->pending_bytes); - - b = _PyBytes_Join(_PyIO_empty_bytes, pending); - Py_DECREF(pending); - if (b == NULL) - return -1; - ret = NULL; - do { - ret = PyObject_CallMethodObjArgs(self->buffer, - _PyIO_str_write, b, NULL); - } while (ret == NULL && _PyIO_trap_eintr()); - Py_DECREF(b); - if (ret == NULL) - return -1; - Py_DECREF(ret); - return 0; -} - -static PyObject * -textiowrapper_write(textio *self, PyObject *args) -{ - PyObject *ret; - PyObject *text; /* owned reference */ - PyObject *b; - Py_ssize_t textlen; - int haslf = 0; - int needflush = 0, text_needflush = 0; - - CHECK_ATTACHED(self); - - if (!PyArg_ParseTuple(args, "U:write", &text)) { - return NULL; - } - - if (PyUnicode_READY(text) == -1) - return NULL; - - CHECK_CLOSED(self); - - if (self->encoder == NULL) - return _unsupported("not writable"); - - Py_INCREF(text); - - textlen = PyUnicode_GET_LENGTH(text); - - if ((self->writetranslate && self->writenl != NULL) || self->line_buffering) - if (PyUnicode_FindChar(text, '\n', 0, PyUnicode_GET_LENGTH(text), 1) != -1) - haslf = 1; - - if (haslf && self->writetranslate && self->writenl != NULL) { - PyObject *newtext = _PyObject_CallMethodId( - text, &PyId_replace, "ss", "\n", self->writenl); - Py_DECREF(text); - if (newtext == NULL) - return NULL; - text = newtext; - } - - if (self->write_through) - text_needflush = 1; - if (self->line_buffering && - (haslf || - PyUnicode_FindChar(text, '\r', 0, PyUnicode_GET_LENGTH(text), 1) != -1)) - needflush = 1; - - /* XXX What if we were just reading? */ - if (self->encodefunc != NULL) { - b = (*self->encodefunc)((PyObject *) self, text); - self->encoding_start_of_stream = 0; - } - else - b = PyObject_CallMethodObjArgs(self->encoder, - _PyIO_str_encode, text, NULL); - Py_DECREF(text); - if (b == NULL) - return NULL; - - if (self->pending_bytes == NULL) { - self->pending_bytes = PyList_New(0); - if (self->pending_bytes == NULL) { - Py_DECREF(b); - return NULL; - } - self->pending_bytes_count = 0; - } - if (PyList_Append(self->pending_bytes, b) < 0) { - Py_DECREF(b); - return NULL; - } - self->pending_bytes_count += PyBytes_GET_SIZE(b); - Py_DECREF(b); - if (self->pending_bytes_count > self->chunk_size || needflush || - text_needflush) { - if (_textiowrapper_writeflush(self) < 0) - return NULL; - } - - if (needflush) { - ret = PyObject_CallMethodObjArgs(self->buffer, _PyIO_str_flush, NULL); - if (ret == NULL) - return NULL; - Py_DECREF(ret); - } - - Py_CLEAR(self->snapshot); - - if (self->decoder) { - ret = _PyObject_CallMethodId(self->decoder, &PyId_reset, NULL); - if (ret == NULL) - return NULL; - Py_DECREF(ret); - } - - return PyLong_FromSsize_t(textlen); -} - -/* Steal a reference to chars and store it in the decoded_char buffer; - */ -static void -textiowrapper_set_decoded_chars(textio *self, PyObject *chars) -{ - Py_CLEAR(self->decoded_chars); - self->decoded_chars = chars; - self->decoded_chars_used = 0; -} - -static PyObject * -textiowrapper_get_decoded_chars(textio *self, Py_ssize_t n) -{ - PyObject *chars; - Py_ssize_t avail; - - if (self->decoded_chars == NULL) - return PyUnicode_FromStringAndSize(NULL, 0); - - /* decoded_chars is guaranteed to be "ready". */ - avail = (PyUnicode_GET_LENGTH(self->decoded_chars) - - self->decoded_chars_used); - - assert(avail >= 0); - - if (n < 0 || n > avail) - n = avail; - - if (self->decoded_chars_used > 0 || n < avail) { - chars = PyUnicode_Substring(self->decoded_chars, - self->decoded_chars_used, - self->decoded_chars_used + n); - if (chars == NULL) - return NULL; - } - else { - chars = self->decoded_chars; - Py_INCREF(chars); - } - - self->decoded_chars_used += n; - return chars; -} - -/* Read and decode the next chunk of data from the BufferedReader. - */ -static int -textiowrapper_read_chunk(textio *self, Py_ssize_t size_hint) -{ - PyObject *dec_buffer = NULL; - PyObject *dec_flags = NULL; - PyObject *input_chunk = NULL; - Py_buffer input_chunk_buf; - PyObject *decoded_chars, *chunk_size; - Py_ssize_t nbytes, nchars; - int eof; - - /* The return value is True unless EOF was reached. The decoded string is - * placed in self._decoded_chars (replacing its previous value). The - * entire input chunk is sent to the decoder, though some of it may remain - * buffered in the decoder, yet to be converted. - */ - - if (self->decoder == NULL) { - _unsupported("not readable"); - return -1; - } - - if (self->telling) { - /* To prepare for tell(), we need to snapshot a point in the file - * where the decoder's input buffer is empty. - */ - - PyObject *state = PyObject_CallMethodObjArgs(self->decoder, - _PyIO_str_getstate, NULL); - if (state == NULL) - return -1; - /* Given this, we know there was a valid snapshot point - * len(dec_buffer) bytes ago with decoder state (b'', dec_flags). - */ - if (PyArg_Parse(state, "(OO)", &dec_buffer, &dec_flags) < 0) { - Py_DECREF(state); - return -1; - } - - if (!PyBytes_Check(dec_buffer)) { - PyErr_Format(PyExc_TypeError, - "decoder getstate() should have returned a bytes " - "object, not '%.200s'", - Py_TYPE(dec_buffer)->tp_name); - Py_DECREF(state); - return -1; - } - Py_INCREF(dec_buffer); - Py_INCREF(dec_flags); - Py_DECREF(state); - } - - /* Read a chunk, decode it, and put the result in self._decoded_chars. */ - if (size_hint > 0) { - size_hint = (Py_ssize_t)(Py_MAX(self->b2cratio, 1.0) * size_hint); - } - chunk_size = PyLong_FromSsize_t(Py_MAX(self->chunk_size, size_hint)); - if (chunk_size == NULL) - goto fail; - - input_chunk = PyObject_CallMethodObjArgs(self->buffer, - (self->has_read1 ? _PyIO_str_read1: _PyIO_str_read), - chunk_size, NULL); - Py_DECREF(chunk_size); - if (input_chunk == NULL) - goto fail; - - if (PyObject_GetBuffer(input_chunk, &input_chunk_buf, 0) != 0) { - PyErr_Format(PyExc_TypeError, - "underlying %s() should have returned a bytes-like object, " - "not '%.200s'", (self->has_read1 ? "read1": "read"), - Py_TYPE(input_chunk)->tp_name); - goto fail; - } - - nbytes = input_chunk_buf.len; - eof = (nbytes == 0); - if (Py_TYPE(self->decoder) == &PyIncrementalNewlineDecoder_Type) { - decoded_chars = _PyIncrementalNewlineDecoder_decode( - self->decoder, input_chunk, eof); - } - else { - decoded_chars = PyObject_CallMethodObjArgs(self->decoder, - _PyIO_str_decode, input_chunk, eof ? Py_True : Py_False, NULL); - } - PyBuffer_Release(&input_chunk_buf); - - if (check_decoded(decoded_chars) < 0) - goto fail; - textiowrapper_set_decoded_chars(self, decoded_chars); - nchars = PyUnicode_GET_LENGTH(decoded_chars); - if (nchars > 0) - self->b2cratio = (double) nbytes / nchars; - else - self->b2cratio = 0.0; - if (nchars > 0) - eof = 0; - - if (self->telling) { - /* At the snapshot point, len(dec_buffer) bytes before the read, the - * next input to be decoded is dec_buffer + input_chunk. - */ - PyObject *next_input = dec_buffer; - PyBytes_Concat(&next_input, input_chunk); - if (next_input == NULL) { - dec_buffer = NULL; /* Reference lost to PyBytes_Concat */ - goto fail; - } - Py_CLEAR(self->snapshot); - self->snapshot = Py_BuildValue("NN", dec_flags, next_input); - } - Py_DECREF(input_chunk); - - return (eof == 0); - - fail: - Py_XDECREF(dec_buffer); - Py_XDECREF(dec_flags); - Py_XDECREF(input_chunk); - return -1; -} - -static PyObject * -textiowrapper_read(textio *self, PyObject *args) -{ - Py_ssize_t n = -1; - PyObject *result = NULL, *chunks = NULL; - - CHECK_ATTACHED(self); - - if (!PyArg_ParseTuple(args, "|O&:read", &_PyIO_ConvertSsize_t, &n)) - return NULL; - - CHECK_CLOSED(self); - - if (self->decoder == NULL) - return _unsupported("not readable"); - - if (_textiowrapper_writeflush(self) < 0) - return NULL; - - if (n < 0) { - /* Read everything */ - PyObject *bytes = _PyObject_CallMethodId(self->buffer, &PyId_read, NULL); - PyObject *decoded; - if (bytes == NULL) - goto fail; - - if (Py_TYPE(self->decoder) == &PyIncrementalNewlineDecoder_Type) - decoded = _PyIncrementalNewlineDecoder_decode(self->decoder, - bytes, 1); - else - decoded = PyObject_CallMethodObjArgs( - self->decoder, _PyIO_str_decode, bytes, Py_True, NULL); - Py_DECREF(bytes); - if (check_decoded(decoded) < 0) - goto fail; - - result = textiowrapper_get_decoded_chars(self, -1); - - if (result == NULL) { - Py_DECREF(decoded); - return NULL; - } - - PyUnicode_AppendAndDel(&result, decoded); - if (result == NULL) - goto fail; - - Py_CLEAR(self->snapshot); - return result; - } - else { - int res = 1; - Py_ssize_t remaining = n; - - result = textiowrapper_get_decoded_chars(self, n); - if (result == NULL) - goto fail; - if (PyUnicode_READY(result) == -1) - goto fail; - remaining -= PyUnicode_GET_LENGTH(result); - - /* Keep reading chunks until we have n characters to return */ - while (remaining > 0) { - res = textiowrapper_read_chunk(self, remaining); - if (res < 0) { - /* NOTE: PyErr_SetFromErrno() calls PyErr_CheckSignals() - when EINTR occurs so we needn't do it ourselves. */ - if (_PyIO_trap_eintr()) { - continue; - } - goto fail; - } - if (res == 0) /* EOF */ - break; - if (chunks == NULL) { - chunks = PyList_New(0); - if (chunks == NULL) - goto fail; - } - if (PyUnicode_GET_LENGTH(result) > 0 && - PyList_Append(chunks, result) < 0) - goto fail; - Py_DECREF(result); - result = textiowrapper_get_decoded_chars(self, remaining); - if (result == NULL) - goto fail; - remaining -= PyUnicode_GET_LENGTH(result); - } - if (chunks != NULL) { - if (result != NULL && PyList_Append(chunks, result) < 0) - goto fail; - Py_CLEAR(result); - result = PyUnicode_Join(_PyIO_empty_str, chunks); - if (result == NULL) - goto fail; - Py_CLEAR(chunks); - } - return result; - } - fail: - Py_XDECREF(result); - Py_XDECREF(chunks); - return NULL; -} - - -/* NOTE: `end` must point to the real end of the Py_UCS4 storage, - that is to the NUL character. Otherwise the function will produce - incorrect results. */ -static char * -find_control_char(int kind, char *s, char *end, Py_UCS4 ch) -{ - if (kind == PyUnicode_1BYTE_KIND) { - assert(ch < 256); - return (char *) memchr((void *) s, (char) ch, end - s); - } - for (;;) { - while (PyUnicode_READ(kind, s, 0) > ch) - s += kind; - if (PyUnicode_READ(kind, s, 0) == ch) - return s; - if (s == end) - return NULL; - s += kind; - } -} - -Py_ssize_t -_PyIO_find_line_ending( - int translated, int universal, PyObject *readnl, - int kind, char *start, char *end, Py_ssize_t *consumed) -{ - Py_ssize_t len = ((char*)end - (char*)start)/kind; - - if (translated) { - /* Newlines are already translated, only search for \n */ - char *pos = find_control_char(kind, start, end, '\n'); - if (pos != NULL) - return (pos - start)/kind + 1; - else { - *consumed = len; - return -1; - } - } - else if (universal) { - /* Universal newline search. Find any of \r, \r\n, \n - * The decoder ensures that \r\n are not split in two pieces - */ - char *s = start; - for (;;) { - Py_UCS4 ch; - /* Fast path for non-control chars. The loop always ends - since the Unicode string is NUL-terminated. */ - while (PyUnicode_READ(kind, s, 0) > '\r') - s += kind; - if (s >= end) { - *consumed = len; - return -1; - } - ch = PyUnicode_READ(kind, s, 0); - s += kind; - if (ch == '\n') - return (s - start)/kind; - if (ch == '\r') { - if (PyUnicode_READ(kind, s, 0) == '\n') - return (s - start)/kind + 1; - else - return (s - start)/kind; - } - } - } - else { - /* Non-universal mode. */ - Py_ssize_t readnl_len = PyUnicode_GET_LENGTH(readnl); - Py_UCS1 *nl = PyUnicode_1BYTE_DATA(readnl); - /* Assume that readnl is an ASCII character. */ - assert(PyUnicode_KIND(readnl) == PyUnicode_1BYTE_KIND); - if (readnl_len == 1) { - char *pos = find_control_char(kind, start, end, nl[0]); - if (pos != NULL) - return (pos - start)/kind + 1; - *consumed = len; - return -1; - } - else { - char *s = start; - char *e = end - (readnl_len - 1)*kind; - char *pos; - if (e < s) - e = s; - while (s < e) { - Py_ssize_t i; - char *pos = find_control_char(kind, s, end, nl[0]); - if (pos == NULL || pos >= e) - break; - for (i = 1; i < readnl_len; i++) { - if (PyUnicode_READ(kind, pos, i) != nl[i]) - break; - } - if (i == readnl_len) - return (pos - start)/kind + readnl_len; - s = pos + kind; - } - pos = find_control_char(kind, e, end, nl[0]); - if (pos == NULL) - *consumed = len; - else - *consumed = (pos - start)/kind; - return -1; - } - } -} - -static PyObject * -_textiowrapper_readline(textio *self, Py_ssize_t limit) -{ - PyObject *line = NULL, *chunks = NULL, *remaining = NULL; - Py_ssize_t start, endpos, chunked, offset_to_buffer; - int res; - - CHECK_CLOSED(self); - - if (_textiowrapper_writeflush(self) < 0) - return NULL; - - chunked = 0; - - while (1) { - char *ptr; - Py_ssize_t line_len; - int kind; - Py_ssize_t consumed = 0; - - /* First, get some data if necessary */ - res = 1; - while (!self->decoded_chars || - !PyUnicode_GET_LENGTH(self->decoded_chars)) { - res = textiowrapper_read_chunk(self, 0); - if (res < 0) { - /* NOTE: PyErr_SetFromErrno() calls PyErr_CheckSignals() - when EINTR occurs so we needn't do it ourselves. */ - if (_PyIO_trap_eintr()) { - continue; - } - goto error; - } - if (res == 0) - break; - } - if (res == 0) { - /* end of file */ - textiowrapper_set_decoded_chars(self, NULL); - Py_CLEAR(self->snapshot); - start = endpos = offset_to_buffer = 0; - break; - } - - if (remaining == NULL) { - line = self->decoded_chars; - start = self->decoded_chars_used; - offset_to_buffer = 0; - Py_INCREF(line); - } - else { - assert(self->decoded_chars_used == 0); - line = PyUnicode_Concat(remaining, self->decoded_chars); - start = 0; - offset_to_buffer = PyUnicode_GET_LENGTH(remaining); - Py_CLEAR(remaining); - if (line == NULL) - goto error; - if (PyUnicode_READY(line) == -1) - goto error; - } - - ptr = PyUnicode_DATA(line); - line_len = PyUnicode_GET_LENGTH(line); - kind = PyUnicode_KIND(line); - - endpos = _PyIO_find_line_ending( - self->readtranslate, self->readuniversal, self->readnl, - kind, - ptr + kind * start, - ptr + kind * line_len, - &consumed); - if (endpos >= 0) { - endpos += start; - if (limit >= 0 && (endpos - start) + chunked >= limit) - endpos = start + limit - chunked; - break; - } - - /* We can put aside up to `endpos` */ - endpos = consumed + start; - if (limit >= 0 && (endpos - start) + chunked >= limit) { - /* Didn't find line ending, but reached length limit */ - endpos = start + limit - chunked; - break; - } - - if (endpos > start) { - /* No line ending seen yet - put aside current data */ - PyObject *s; - if (chunks == NULL) { - chunks = PyList_New(0); - if (chunks == NULL) - goto error; - } - s = PyUnicode_Substring(line, start, endpos); - if (s == NULL) - goto error; - if (PyList_Append(chunks, s) < 0) { - Py_DECREF(s); - goto error; - } - chunked += PyUnicode_GET_LENGTH(s); - Py_DECREF(s); - } - /* There may be some remaining bytes we'll have to prepend to the - next chunk of data */ - if (endpos < line_len) { - remaining = PyUnicode_Substring(line, endpos, line_len); - if (remaining == NULL) - goto error; - } - Py_CLEAR(line); - /* We have consumed the buffer */ - textiowrapper_set_decoded_chars(self, NULL); - } - - if (line != NULL) { - /* Our line ends in the current buffer */ - self->decoded_chars_used = endpos - offset_to_buffer; - if (start > 0 || endpos < PyUnicode_GET_LENGTH(line)) { - PyObject *s = PyUnicode_Substring(line, start, endpos); - Py_CLEAR(line); - if (s == NULL) - goto error; - line = s; - } - } - if (remaining != NULL) { - if (chunks == NULL) { - chunks = PyList_New(0); - if (chunks == NULL) - goto error; - } - if (PyList_Append(chunks, remaining) < 0) - goto error; - Py_CLEAR(remaining); - } - if (chunks != NULL) { - if (line != NULL) { - if (PyList_Append(chunks, line) < 0) - goto error; - Py_DECREF(line); - } - line = PyUnicode_Join(_PyIO_empty_str, chunks); - if (line == NULL) - goto error; - Py_CLEAR(chunks); - } - if (line == NULL) { - Py_INCREF(_PyIO_empty_str); - line = _PyIO_empty_str; - } - - return line; - - error: - Py_XDECREF(chunks); - Py_XDECREF(remaining); - Py_XDECREF(line); - return NULL; -} - -static PyObject * -textiowrapper_readline(textio *self, PyObject *args) -{ - Py_ssize_t limit = -1; - - CHECK_ATTACHED(self); - if (!PyArg_ParseTuple(args, "|n:readline", &limit)) { - return NULL; - } - return _textiowrapper_readline(self, limit); -} - -/* Seek and Tell */ - -typedef struct { - Py_off_t start_pos; - int dec_flags; - int bytes_to_feed; - int chars_to_skip; - char need_eof; -} cookie_type; - -/* - To speed up cookie packing/unpacking, we store the fields in a temporary - string and call _PyLong_FromByteArray() or _PyLong_AsByteArray (resp.). - The following macros define at which offsets in the intermediary byte - string the various CookieStruct fields will be stored. - */ - -#define COOKIE_BUF_LEN (sizeof(Py_off_t) + 3 * sizeof(int) + sizeof(char)) - -#if PY_BIG_ENDIAN -/* We want the least significant byte of start_pos to also be the least - significant byte of the cookie, which means that in big-endian mode we - must copy the fields in reverse order. */ - -# define OFF_START_POS (sizeof(char) + 3 * sizeof(int)) -# define OFF_DEC_FLAGS (sizeof(char) + 2 * sizeof(int)) -# define OFF_BYTES_TO_FEED (sizeof(char) + sizeof(int)) -# define OFF_CHARS_TO_SKIP (sizeof(char)) -# define OFF_NEED_EOF 0 - -#else -/* Little-endian mode: the least significant byte of start_pos will - naturally end up the least significant byte of the cookie. */ - -# define OFF_START_POS 0 -# define OFF_DEC_FLAGS (sizeof(Py_off_t)) -# define OFF_BYTES_TO_FEED (sizeof(Py_off_t) + sizeof(int)) -# define OFF_CHARS_TO_SKIP (sizeof(Py_off_t) + 2 * sizeof(int)) -# define OFF_NEED_EOF (sizeof(Py_off_t) + 3 * sizeof(int)) - -#endif - -static int -textiowrapper_parse_cookie(cookie_type *cookie, PyObject *cookieObj) -{ - unsigned char buffer[COOKIE_BUF_LEN]; - PyLongObject *cookieLong = (PyLongObject *)PyNumber_Long(cookieObj); - if (cookieLong == NULL) - return -1; - - if (_PyLong_AsByteArray(cookieLong, buffer, sizeof(buffer), - PY_LITTLE_ENDIAN, 0) < 0) { - Py_DECREF(cookieLong); - return -1; - } - Py_DECREF(cookieLong); - - memcpy(&cookie->start_pos, buffer + OFF_START_POS, sizeof(cookie->start_pos)); - memcpy(&cookie->dec_flags, buffer + OFF_DEC_FLAGS, sizeof(cookie->dec_flags)); - memcpy(&cookie->bytes_to_feed, buffer + OFF_BYTES_TO_FEED, sizeof(cookie->bytes_to_feed)); - memcpy(&cookie->chars_to_skip, buffer + OFF_CHARS_TO_SKIP, sizeof(cookie->chars_to_skip)); - memcpy(&cookie->need_eof, buffer + OFF_NEED_EOF, sizeof(cookie->need_eof)); - - return 0; -} - -static PyObject * -textiowrapper_build_cookie(cookie_type *cookie) -{ - unsigned char buffer[COOKIE_BUF_LEN]; - - memcpy(buffer + OFF_START_POS, &cookie->start_pos, sizeof(cookie->start_pos)); - memcpy(buffer + OFF_DEC_FLAGS, &cookie->dec_flags, sizeof(cookie->dec_flags)); - memcpy(buffer + OFF_BYTES_TO_FEED, &cookie->bytes_to_feed, sizeof(cookie->bytes_to_feed)); - memcpy(buffer + OFF_CHARS_TO_SKIP, &cookie->chars_to_skip, sizeof(cookie->chars_to_skip)); - memcpy(buffer + OFF_NEED_EOF, &cookie->need_eof, sizeof(cookie->need_eof)); - - return _PyLong_FromByteArray(buffer, sizeof(buffer), - PY_LITTLE_ENDIAN, 0); -} - -static int -_textiowrapper_decoder_setstate(textio *self, cookie_type *cookie) -{ - PyObject *res; - /* When seeking to the start of the stream, we call decoder.reset() - rather than decoder.getstate(). - This is for a few decoders such as utf-16 for which the state value - at start is not (b"", 0) but e.g. (b"", 2) (meaning, in the case of - utf-16, that we are expecting a BOM). - */ - if (cookie->start_pos == 0 && cookie->dec_flags == 0) - res = PyObject_CallMethodObjArgs(self->decoder, _PyIO_str_reset, NULL); - else - res = _PyObject_CallMethodId(self->decoder, &PyId_setstate, - "((yi))", "", cookie->dec_flags); - if (res == NULL) - return -1; - Py_DECREF(res); - return 0; -} - -static int -_textiowrapper_encoder_reset(textio *self, int start_of_stream) -{ - PyObject *res; - if (start_of_stream) { - res = PyObject_CallMethodObjArgs(self->encoder, _PyIO_str_reset, NULL); - self->encoding_start_of_stream = 1; - } - else { - res = PyObject_CallMethodObjArgs(self->encoder, _PyIO_str_setstate, - _PyIO_zero, NULL); - self->encoding_start_of_stream = 0; - } - if (res == NULL) - return -1; - Py_DECREF(res); - return 0; -} - -static int -_textiowrapper_encoder_setstate(textio *self, cookie_type *cookie) -{ - /* Same as _textiowrapper_decoder_setstate() above. */ - return _textiowrapper_encoder_reset( - self, cookie->start_pos == 0 && cookie->dec_flags == 0); -} - -static PyObject * -textiowrapper_seek(textio *self, PyObject *args) -{ - PyObject *cookieObj, *posobj; - cookie_type cookie; - int whence = 0; - PyObject *res; - int cmp; - - CHECK_ATTACHED(self); - - if (!PyArg_ParseTuple(args, "O|i:seek", &cookieObj, &whence)) - return NULL; - CHECK_CLOSED(self); - - Py_INCREF(cookieObj); - - if (!self->seekable) { - _unsupported("underlying stream is not seekable"); - goto fail; - } - - if (whence == 1) { - /* seek relative to current position */ - cmp = PyObject_RichCompareBool(cookieObj, _PyIO_zero, Py_EQ); - if (cmp < 0) - goto fail; - - if (cmp == 0) { - _unsupported("can't do nonzero cur-relative seeks"); - goto fail; - } - - /* Seeking to the current position should attempt to - * sync the underlying buffer with the current position. - */ - Py_DECREF(cookieObj); - cookieObj = _PyObject_CallMethodId((PyObject *)self, &PyId_tell, NULL); - if (cookieObj == NULL) - goto fail; - } - else if (whence == 2) { - /* seek relative to end of file */ - cmp = PyObject_RichCompareBool(cookieObj, _PyIO_zero, Py_EQ); - if (cmp < 0) - goto fail; - - if (cmp == 0) { - _unsupported("can't do nonzero end-relative seeks"); - goto fail; - } - - res = _PyObject_CallMethodId((PyObject *)self, &PyId_flush, NULL); - if (res == NULL) - goto fail; - Py_DECREF(res); - - textiowrapper_set_decoded_chars(self, NULL); - Py_CLEAR(self->snapshot); - if (self->decoder) { - res = _PyObject_CallMethodId(self->decoder, &PyId_reset, NULL); - if (res == NULL) - goto fail; - Py_DECREF(res); - } - - res = _PyObject_CallMethodId(self->buffer, &PyId_seek, "ii", 0, 2); - Py_CLEAR(cookieObj); - if (res == NULL) - goto fail; - if (self->encoder) { - /* If seek() == 0, we are at the start of stream, otherwise not */ - cmp = PyObject_RichCompareBool(res, _PyIO_zero, Py_EQ); - if (cmp < 0 || _textiowrapper_encoder_reset(self, cmp)) { - Py_DECREF(res); - goto fail; - } - } - return res; - } - else if (whence != 0) { - PyErr_Format(PyExc_ValueError, - "invalid whence (%d, should be 0, 1 or 2)", whence); - goto fail; - } - - cmp = PyObject_RichCompareBool(cookieObj, _PyIO_zero, Py_LT); - if (cmp < 0) - goto fail; - - if (cmp == 1) { - PyErr_Format(PyExc_ValueError, - "negative seek position %R", cookieObj); - goto fail; - } - - res = PyObject_CallMethodObjArgs((PyObject *)self, _PyIO_str_flush, NULL); - if (res == NULL) - goto fail; - Py_DECREF(res); - - /* The strategy of seek() is to go back to the safe start point - * and replay the effect of read(chars_to_skip) from there. - */ - if (textiowrapper_parse_cookie(&cookie, cookieObj) < 0) - goto fail; - - /* Seek back to the safe start point. */ - posobj = PyLong_FromOff_t(cookie.start_pos); - if (posobj == NULL) - goto fail; - res = PyObject_CallMethodObjArgs(self->buffer, - _PyIO_str_seek, posobj, NULL); - Py_DECREF(posobj); - if (res == NULL) - goto fail; - Py_DECREF(res); - - textiowrapper_set_decoded_chars(self, NULL); - Py_CLEAR(self->snapshot); - - /* Restore the decoder to its state from the safe start point. */ - if (self->decoder) { - if (_textiowrapper_decoder_setstate(self, &cookie) < 0) - goto fail; - } - - if (cookie.chars_to_skip) { - /* Just like _read_chunk, feed the decoder and save a snapshot. */ - PyObject *input_chunk = _PyObject_CallMethodId( - self->buffer, &PyId_read, "i", cookie.bytes_to_feed); - PyObject *decoded; - - if (input_chunk == NULL) - goto fail; - - if (!PyBytes_Check(input_chunk)) { - PyErr_Format(PyExc_TypeError, - "underlying read() should have returned a bytes " - "object, not '%.200s'", - Py_TYPE(input_chunk)->tp_name); - Py_DECREF(input_chunk); - goto fail; - } - - self->snapshot = Py_BuildValue("iN", cookie.dec_flags, input_chunk); - if (self->snapshot == NULL) { - Py_DECREF(input_chunk); - goto fail; - } - - decoded = _PyObject_CallMethodId(self->decoder, &PyId_decode, - "Oi", input_chunk, (int)cookie.need_eof); - - if (check_decoded(decoded) < 0) - goto fail; - - textiowrapper_set_decoded_chars(self, decoded); - - /* Skip chars_to_skip of the decoded characters. */ - if (PyUnicode_GetLength(self->decoded_chars) < cookie.chars_to_skip) { - PyErr_SetString(PyExc_IOError, "can't restore logical file position"); - goto fail; - } - self->decoded_chars_used = cookie.chars_to_skip; - } - else { - self->snapshot = Py_BuildValue("iy", cookie.dec_flags, ""); - if (self->snapshot == NULL) - goto fail; - } - - /* Finally, reset the encoder (merely useful for proper BOM handling) */ - if (self->encoder) { - if (_textiowrapper_encoder_setstate(self, &cookie) < 0) - goto fail; - } - return cookieObj; - fail: - Py_XDECREF(cookieObj); - return NULL; - -} - -static PyObject * -textiowrapper_tell(textio *self, PyObject *args) -{ - PyObject *res; - PyObject *posobj = NULL; - cookie_type cookie = {0,0,0,0,0}; - PyObject *next_input; - Py_ssize_t chars_to_skip, chars_decoded; - Py_ssize_t skip_bytes, skip_back; - PyObject *saved_state = NULL; - char *input, *input_end; - char *dec_buffer; - Py_ssize_t dec_buffer_len; - int dec_flags; - - CHECK_ATTACHED(self); - CHECK_CLOSED(self); - - if (!self->seekable) { - _unsupported("underlying stream is not seekable"); - goto fail; - } - if (!self->telling) { - PyErr_SetString(PyExc_IOError, - "telling position disabled by next() call"); - goto fail; - } - - if (_textiowrapper_writeflush(self) < 0) - return NULL; - res = _PyObject_CallMethodId((PyObject *)self, &PyId_flush, NULL); - if (res == NULL) - goto fail; - Py_DECREF(res); - - posobj = _PyObject_CallMethodId(self->buffer, &PyId_tell, NULL); - if (posobj == NULL) - goto fail; - - if (self->decoder == NULL || self->snapshot == NULL) { - assert (self->decoded_chars == NULL || PyUnicode_GetLength(self->decoded_chars) == 0); - return posobj; - } - -#if defined(HAVE_LARGEFILE_SUPPORT) - cookie.start_pos = PyLong_AsLongLong(posobj); -#else - cookie.start_pos = PyLong_AsLong(posobj); -#endif - Py_DECREF(posobj); - if (PyErr_Occurred()) - goto fail; - - /* Skip backward to the snapshot point (see _read_chunk). */ - if (!PyArg_Parse(self->snapshot, "(iO)", &cookie.dec_flags, &next_input)) - goto fail; - - assert (PyBytes_Check(next_input)); - - cookie.start_pos -= PyBytes_GET_SIZE(next_input); - - /* How many decoded characters have been used up since the snapshot? */ - if (self->decoded_chars_used == 0) { - /* We haven't moved from the snapshot point. */ - return textiowrapper_build_cookie(&cookie); - } - - chars_to_skip = self->decoded_chars_used; - - /* Decoder state will be restored at the end */ - saved_state = PyObject_CallMethodObjArgs(self->decoder, - _PyIO_str_getstate, NULL); - if (saved_state == NULL) - goto fail; - -#define DECODER_GETSTATE() do { \ - PyObject *_state = PyObject_CallMethodObjArgs(self->decoder, \ - _PyIO_str_getstate, NULL); \ - if (_state == NULL) \ - goto fail; \ - if (!PyArg_Parse(_state, "(y#i)", &dec_buffer, &dec_buffer_len, &dec_flags)) { \ - Py_DECREF(_state); \ - goto fail; \ - } \ - Py_DECREF(_state); \ - } while (0) - -#define DECODER_DECODE(start, len, res) do { \ - PyObject *_decoded = _PyObject_CallMethodId( \ - self->decoder, &PyId_decode, "y#", start, len); \ - if (check_decoded(_decoded) < 0) \ - goto fail; \ - res = PyUnicode_GET_LENGTH(_decoded); \ - Py_DECREF(_decoded); \ - } while (0) - - /* Fast search for an acceptable start point, close to our - current pos */ - skip_bytes = (Py_ssize_t) (self->b2cratio * chars_to_skip); - skip_back = 1; - assert(skip_back <= PyBytes_GET_SIZE(next_input)); - input = PyBytes_AS_STRING(next_input); - while (skip_bytes > 0) { - /* Decode up to temptative start point */ - if (_textiowrapper_decoder_setstate(self, &cookie) < 0) - goto fail; - DECODER_DECODE(input, skip_bytes, chars_decoded); - if (chars_decoded <= chars_to_skip) { - DECODER_GETSTATE(); - if (dec_buffer_len == 0) { - /* Before pos and no bytes buffered in decoder => OK */ - cookie.dec_flags = dec_flags; - chars_to_skip -= chars_decoded; - break; - } - /* Skip back by buffered amount and reset heuristic */ - skip_bytes -= dec_buffer_len; - skip_back = 1; - } - else { - /* We're too far ahead, skip back a bit */ - skip_bytes -= skip_back; - skip_back *= 2; - } - } - if (skip_bytes <= 0) { - skip_bytes = 0; - if (_textiowrapper_decoder_setstate(self, &cookie) < 0) - goto fail; - } - - /* Note our initial start point. */ - cookie.start_pos += skip_bytes; - cookie.chars_to_skip = Py_SAFE_DOWNCAST(chars_to_skip, Py_ssize_t, int); - if (chars_to_skip == 0) - goto finally; - - /* We should be close to the desired position. Now feed the decoder one - * byte at a time until we reach the `chars_to_skip` target. - * As we go, note the nearest "safe start point" before the current - * location (a point where the decoder has nothing buffered, so seek() - * can safely start from there and advance to this location). - */ - chars_decoded = 0; - input = PyBytes_AS_STRING(next_input); - input_end = input + PyBytes_GET_SIZE(next_input); - input += skip_bytes; - while (input < input_end) { - Py_ssize_t n; - - DECODER_DECODE(input, (Py_ssize_t)1, n); - /* We got n chars for 1 byte */ - chars_decoded += n; - cookie.bytes_to_feed += 1; - DECODER_GETSTATE(); - - if (dec_buffer_len == 0 && chars_decoded <= chars_to_skip) { - /* Decoder buffer is empty, so this is a safe start point. */ - cookie.start_pos += cookie.bytes_to_feed; - chars_to_skip -= chars_decoded; - cookie.dec_flags = dec_flags; - cookie.bytes_to_feed = 0; - chars_decoded = 0; - } - if (chars_decoded >= chars_to_skip) - break; - input++; - } - if (input == input_end) { - /* We didn't get enough decoded data; signal EOF to get more. */ - PyObject *decoded = _PyObject_CallMethodId( - self->decoder, &PyId_decode, "yi", "", /* final = */ 1); - if (check_decoded(decoded) < 0) - goto fail; - chars_decoded += PyUnicode_GET_LENGTH(decoded); - Py_DECREF(decoded); - cookie.need_eof = 1; - - if (chars_decoded < chars_to_skip) { - PyErr_SetString(PyExc_IOError, - "can't reconstruct logical file position"); - goto fail; - } - } - -finally: - res = _PyObject_CallMethodId(self->decoder, &PyId_setstate, "(O)", saved_state); - Py_DECREF(saved_state); - if (res == NULL) - return NULL; - Py_DECREF(res); - - /* The returned cookie corresponds to the last safe start point. */ - cookie.chars_to_skip = Py_SAFE_DOWNCAST(chars_to_skip, Py_ssize_t, int); - return textiowrapper_build_cookie(&cookie); - -fail: - if (saved_state) { - PyObject *type, *value, *traceback; - PyErr_Fetch(&type, &value, &traceback); - res = _PyObject_CallMethodId(self->decoder, &PyId_setstate, "(O)", saved_state); - _PyErr_ChainExceptions(type, value, traceback); - Py_DECREF(saved_state); - Py_XDECREF(res); - } - return NULL; -} - -static PyObject * -textiowrapper_truncate(textio *self, PyObject *args) -{ - PyObject *pos = Py_None; - PyObject *res; - - CHECK_ATTACHED(self) - if (!PyArg_ParseTuple(args, "|O:truncate", &pos)) { - return NULL; - } - - res = PyObject_CallMethodObjArgs((PyObject *) self, _PyIO_str_flush, NULL); - if (res == NULL) - return NULL; - Py_DECREF(res); - - return PyObject_CallMethodObjArgs(self->buffer, _PyIO_str_truncate, pos, NULL); -} - -static PyObject * -textiowrapper_repr(textio *self) -{ - PyObject *nameobj, *modeobj, *res, *s; - - CHECK_INITIALIZED(self); - - res = PyUnicode_FromString("<_io.TextIOWrapper"); - if (res == NULL) - return NULL; - - nameobj = _PyObject_GetAttrId((PyObject *) self, &PyId_name); - if (nameobj == NULL) { - if (PyErr_ExceptionMatches(PyExc_Exception)) - PyErr_Clear(); - else - goto error; - } - else { - s = PyUnicode_FromFormat(" name=%R", nameobj); - Py_DECREF(nameobj); - if (s == NULL) - goto error; - PyUnicode_AppendAndDel(&res, s); - if (res == NULL) - return NULL; - } - modeobj = _PyObject_GetAttrId((PyObject *) self, &PyId_mode); - if (modeobj == NULL) { - if (PyErr_ExceptionMatches(PyExc_Exception)) - PyErr_Clear(); - else - goto error; - } - else { - s = PyUnicode_FromFormat(" mode=%R", modeobj); - Py_DECREF(modeobj); - if (s == NULL) - goto error; - PyUnicode_AppendAndDel(&res, s); - if (res == NULL) - return NULL; - } - s = PyUnicode_FromFormat("%U encoding=%R>", - res, self->encoding); - Py_DECREF(res); - return s; -error: - Py_XDECREF(res); - return NULL; -} - - -/* Inquiries */ - -static PyObject * -textiowrapper_fileno(textio *self, PyObject *args) -{ - CHECK_ATTACHED(self); - return _PyObject_CallMethodId(self->buffer, &PyId_fileno, NULL); -} - -static PyObject * -textiowrapper_seekable(textio *self, PyObject *args) -{ - CHECK_ATTACHED(self); - return _PyObject_CallMethodId(self->buffer, &PyId_seekable, NULL); -} - -static PyObject * -textiowrapper_readable(textio *self, PyObject *args) -{ - CHECK_ATTACHED(self); - return _PyObject_CallMethodId(self->buffer, &PyId_readable, NULL); -} - -static PyObject * -textiowrapper_writable(textio *self, PyObject *args) -{ - CHECK_ATTACHED(self); - return _PyObject_CallMethodId(self->buffer, &PyId_writable, NULL); -} - -static PyObject * -textiowrapper_isatty(textio *self, PyObject *args) -{ - CHECK_ATTACHED(self); - return _PyObject_CallMethodId(self->buffer, &PyId_isatty, NULL); -} - -static PyObject * -textiowrapper_getstate(textio *self, PyObject *args) -{ - PyErr_Format(PyExc_TypeError, - "cannot serialize '%s' object", Py_TYPE(self)->tp_name); - return NULL; -} - -static PyObject * -textiowrapper_flush(textio *self, PyObject *args) -{ - CHECK_ATTACHED(self); - CHECK_CLOSED(self); - self->telling = self->seekable; - if (_textiowrapper_writeflush(self) < 0) - return NULL; - return _PyObject_CallMethodId(self->buffer, &PyId_flush, NULL); -} - -static PyObject * -textiowrapper_close(textio *self, PyObject *args) -{ - PyObject *res; - int r; - CHECK_ATTACHED(self); - - res = textiowrapper_closed_get(self, NULL); - if (res == NULL) - return NULL; - r = PyObject_IsTrue(res); - Py_DECREF(res); - if (r < 0) - return NULL; - - if (r > 0) { - Py_RETURN_NONE; /* stream already closed */ - } - else { - PyObject *exc = NULL, *val, *tb; - if (self->finalizing) { - res = _PyObject_CallMethodId(self->buffer, &PyId__dealloc_warn, "O", self); - if (res) - Py_DECREF(res); - else - PyErr_Clear(); - } - res = _PyObject_CallMethodId((PyObject *)self, &PyId_flush, NULL); - if (res == NULL) - PyErr_Fetch(&exc, &val, &tb); - else - Py_DECREF(res); - - res = _PyObject_CallMethodId(self->buffer, &PyId_close, NULL); - if (exc != NULL) { - _PyErr_ChainExceptions(exc, val, tb); - Py_CLEAR(res); - } - return res; - } -} - -static PyObject * -textiowrapper_iternext(textio *self) -{ - PyObject *line; - - CHECK_ATTACHED(self); - - self->telling = 0; - if (Py_TYPE(self) == &PyTextIOWrapper_Type) { - /* Skip method call overhead for speed */ - line = _textiowrapper_readline(self, -1); - } - else { - line = PyObject_CallMethodObjArgs((PyObject *)self, - _PyIO_str_readline, NULL); - if (line && !PyUnicode_Check(line)) { - PyErr_Format(PyExc_IOError, - "readline() should have returned an str object, " - "not '%.200s'", Py_TYPE(line)->tp_name); - Py_DECREF(line); - return NULL; - } - } - - if (line == NULL || PyUnicode_READY(line) == -1) - return NULL; - - if (PyUnicode_GET_LENGTH(line) == 0) { - /* Reached EOF or would have blocked */ - Py_DECREF(line); - Py_CLEAR(self->snapshot); - self->telling = self->seekable; - return NULL; - } - - return line; -} - -static PyObject * -textiowrapper_name_get(textio *self, void *context) -{ - CHECK_ATTACHED(self); - return _PyObject_GetAttrId(self->buffer, &PyId_name); -} - -static PyObject * -textiowrapper_closed_get(textio *self, void *context) -{ - CHECK_ATTACHED(self); - return PyObject_GetAttr(self->buffer, _PyIO_str_closed); -} - -static PyObject * -textiowrapper_newlines_get(textio *self, void *context) -{ - PyObject *res; - CHECK_ATTACHED(self); - if (self->decoder == NULL) - Py_RETURN_NONE; - res = PyObject_GetAttr(self->decoder, _PyIO_str_newlines); - if (res == NULL) { - if (PyErr_ExceptionMatches(PyExc_AttributeError)) { - PyErr_Clear(); - Py_RETURN_NONE; - } - else { - return NULL; - } - } - return res; -} - -static PyObject * -textiowrapper_errors_get(textio *self, void *context) -{ - CHECK_INITIALIZED(self); - return PyUnicode_FromString(PyBytes_AS_STRING(self->errors)); -} - -static PyObject * -textiowrapper_chunk_size_get(textio *self, void *context) -{ - CHECK_ATTACHED(self); - return PyLong_FromSsize_t(self->chunk_size); -} - -static int -textiowrapper_chunk_size_set(textio *self, PyObject *arg, void *context) -{ - Py_ssize_t n; - CHECK_ATTACHED_INT(self); - n = PyNumber_AsSsize_t(arg, PyExc_ValueError); - if (n == -1 && PyErr_Occurred()) - return -1; - if (n <= 0) { - PyErr_SetString(PyExc_ValueError, - "a strictly positive integer is required"); - return -1; - } - self->chunk_size = n; - return 0; -} - -static PyMethodDef textiowrapper_methods[] = { - {"detach", (PyCFunction)textiowrapper_detach, METH_NOARGS}, - {"write", (PyCFunction)textiowrapper_write, METH_VARARGS}, - {"read", (PyCFunction)textiowrapper_read, METH_VARARGS}, - {"readline", (PyCFunction)textiowrapper_readline, METH_VARARGS}, - {"flush", (PyCFunction)textiowrapper_flush, METH_NOARGS}, - {"close", (PyCFunction)textiowrapper_close, METH_NOARGS}, - - {"fileno", (PyCFunction)textiowrapper_fileno, METH_NOARGS}, - {"seekable", (PyCFunction)textiowrapper_seekable, METH_NOARGS}, - {"readable", (PyCFunction)textiowrapper_readable, METH_NOARGS}, - {"writable", (PyCFunction)textiowrapper_writable, METH_NOARGS}, - {"isatty", (PyCFunction)textiowrapper_isatty, METH_NOARGS}, - {"__getstate__", (PyCFunction)textiowrapper_getstate, METH_NOARGS}, - - {"seek", (PyCFunction)textiowrapper_seek, METH_VARARGS}, - {"tell", (PyCFunction)textiowrapper_tell, METH_NOARGS}, - {"truncate", (PyCFunction)textiowrapper_truncate, METH_VARARGS}, - {NULL, NULL} -}; - -static PyMemberDef textiowrapper_members[] = { - {"encoding", T_OBJECT, offsetof(textio, encoding), READONLY}, - {"buffer", T_OBJECT, offsetof(textio, buffer), READONLY}, - {"line_buffering", T_BOOL, offsetof(textio, line_buffering), READONLY}, - {"_finalizing", T_BOOL, offsetof(textio, finalizing), 0}, - {NULL} -}; - -static PyGetSetDef textiowrapper_getset[] = { - {"name", (getter)textiowrapper_name_get, NULL, NULL}, - {"closed", (getter)textiowrapper_closed_get, NULL, NULL}, -/* {"mode", (getter)TextIOWrapper_mode_get, NULL, NULL}, -*/ - {"newlines", (getter)textiowrapper_newlines_get, NULL, NULL}, - {"errors", (getter)textiowrapper_errors_get, NULL, NULL}, - {"_CHUNK_SIZE", (getter)textiowrapper_chunk_size_get, - (setter)textiowrapper_chunk_size_set, NULL}, - {NULL} -}; - -PyTypeObject PyTextIOWrapper_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "_io.TextIOWrapper", /*tp_name*/ - sizeof(textio), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - (destructor)textiowrapper_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tps_etattr*/ - 0, /*tp_compare */ - (reprfunc)textiowrapper_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 | Py_TPFLAGS_BASETYPE - | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_FINALIZE, /*tp_flags*/ - textiowrapper_doc, /* tp_doc */ - (traverseproc)textiowrapper_traverse, /* tp_traverse */ - (inquiry)textiowrapper_clear, /* tp_clear */ - 0, /* tp_richcompare */ - offsetof(textio, weakreflist), /*tp_weaklistoffset*/ - 0, /* tp_iter */ - (iternextfunc)textiowrapper_iternext, /* tp_iternext */ - textiowrapper_methods, /* tp_methods */ - textiowrapper_members, /* tp_members */ - textiowrapper_getset, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - offsetof(textio, dict), /*tp_dictoffset*/ - (initproc)textiowrapper_init, /* tp_init */ - 0, /* tp_alloc */ - PyType_GenericNew, /* tp_new */ - 0, /* tp_free */ - 0, /* tp_is_gc */ - 0, /* tp_bases */ - 0, /* tp_mro */ - 0, /* tp_cache */ - 0, /* tp_subclasses */ - 0, /* tp_weaklist */ - 0, /* tp_del */ - 0, /* tp_version_tag */ - 0, /* tp_finalize */ -}; +/*[clinic end generated code: output=a610bd3b694886c3 input=a9049054013a1b77]*/ diff --git a/Modules/_io/fileio.c b/Modules/_io/fileio.c --- a/Modules/_io/fileio.c +++ b/Modules/_io/fileio.c @@ -43,6 +43,19 @@ #define SMALLCHUNK BUFSIZ #endif +/*[clinic input] +module _io +class _io.FileIO "fileio *" "&PyFileIO_Type" +[clinic start generated code]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=1c77708b41fda70c]*/ + +/*[python input] +class io_ssize_t_converter(CConverter): + type = 'Py_ssize_t' + converter = '_PyIO_ConvertSsize_t' +[python start generated code]*/ +/*[python end generated code: output=da39a3ee5e6b4b0d input=d0a811d3cbfd1b33]*/ + typedef struct { PyObject_HEAD int fd; @@ -126,8 +139,18 @@ return 0; } +/*[clinic input] +_io.FileIO.close + +Close the file. + +A closed file cannot be used for further I/O operations. close() may be +called more than once without error. +[clinic start generated code]*/ + static PyObject * -fileio_close(fileio *self) +_io_FileIO_close_impl(fileio *self) +/*[clinic end generated code: output=7737a319ef3bad0b input=f35231760d54a522]*/ { PyObject *res; PyObject *exc, *val, *tb; @@ -183,15 +206,36 @@ extern int _Py_open_cloexec_works; #endif +/*[clinic input] +_io.FileIO.__init__ + file as nameobj: object + mode: str = "r" + closefd: int(c_default="1") = True + opener: object = None + +Open a file. + +The mode can be 'r' (default), 'w', 'x' or 'a' for reading, +writing, exclusive creation or appending. The file will be created if it +doesn't exist when opened for writing or appending; it will be truncated +when opened for writing. A FileExistsError will be raised if it already +exists when opened for creating. Opening a file for creating implies +writing so this mode behaves in a similar way to 'w'.Add a '+' to the mode +to allow simultaneous reading and writing. A custom opener can be used by +passing a callable as *opener*. The underlying file descriptor for the file +object is then obtained by calling opener with (*name*, *flags*). +*opener* must return an open file descriptor (passing os.open as *opener* +results in functionality similar to passing None). +[clinic start generated code]*/ + static int -fileio_init(PyObject *oself, PyObject *args, PyObject *kwds) +_io_FileIO___init___impl(fileio *self, PyObject *nameobj, const char *mode, + int closefd, PyObject *opener) +/*[clinic end generated code: output=23413f68e6484bbd input=193164e293d6c097]*/ { - fileio *self = (fileio *) oself; - static char *kwlist[] = {"file", "mode", "closefd", "opener", NULL}; const char *name = NULL; - PyObject *nameobj, *stringobj = NULL, *opener = Py_None; - char *mode = "r"; - char *s; + PyObject *stringobj = NULL; + const char *s; #ifdef MS_WINDOWS Py_UNICODE *widename = NULL; #endif @@ -199,7 +243,6 @@ int rwa = 0, plus = 0; int flags = 0; int fd = -1; - int closefd = 1; int fd_is_own = 0; #ifdef O_CLOEXEC int *atomic_flag_works = &_Py_open_cloexec_works; @@ -220,11 +263,6 @@ self->fd = -1; } - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|siO:fileio", - kwlist, &nameobj, &mode, &closefd, - &opener)) - return -1; - if (PyFloat_Check(nameobj)) { PyErr_SetString(PyExc_TypeError, "integer argument expected, got float"); @@ -494,32 +532,60 @@ return NULL; } +/*[clinic input] +_io.FileIO.fileno + +Return the underlying file descriptor (an integer). +[clinic start generated code]*/ + static PyObject * -fileio_fileno(fileio *self) +_io_FileIO_fileno_impl(fileio *self) +/*[clinic end generated code: output=a9626ce5398ece90 input=0b9b2de67335ada3]*/ { if (self->fd < 0) return err_closed(); return PyLong_FromLong((long) self->fd); } +/*[clinic input] +_io.FileIO.readable + +True if file was opened in a read mode. +[clinic start generated code]*/ + static PyObject * -fileio_readable(fileio *self) +_io_FileIO_readable_impl(fileio *self) +/*[clinic end generated code: output=640744a6150fe9ba input=a3fdfed6eea721c5]*/ { if (self->fd < 0) return err_closed(); return PyBool_FromLong((long) self->readable); } +/*[clinic input] +_io.FileIO.writable + +True if file was opened in a write mode. +[clinic start generated code]*/ + static PyObject * -fileio_writable(fileio *self) +_io_FileIO_writable_impl(fileio *self) +/*[clinic end generated code: output=96cefc5446e89977 input=c204a808ca2e1748]*/ { if (self->fd < 0) return err_closed(); return PyBool_FromLong((long) self->writable); } +/*[clinic input] +_io.FileIO.seekable + +True if file supports random-access. +[clinic start generated code]*/ + static PyObject * -fileio_seekable(fileio *self) +_io_FileIO_seekable_impl(fileio *self) +/*[clinic end generated code: output=47909ca0a42e9287 input=c8e5554d2fd63c7f]*/ { if (self->fd < 0) return err_closed(); @@ -536,10 +602,18 @@ return PyBool_FromLong((long) self->seekable); } +/*[clinic input] +_io.FileIO.readinto + buffer: Py_buffer(types={'rwbuffer'}) + / + +Same as RawIOBase.readinto(). +[clinic start generated code]*/ + static PyObject * -fileio_readinto(fileio *self, PyObject *args) +_io_FileIO_readinto_impl(fileio *self, Py_buffer *buffer) +/*[clinic end generated code: output=b01a5a22c8415cb4 input=5edd8327498d468c]*/ { - Py_buffer pbuf; Py_ssize_t n; int err; @@ -548,13 +622,9 @@ if (!self->readable) return err_mode("reading"); - if (!PyArg_ParseTuple(args, "w*", &pbuf)) - return NULL; - - n = _Py_read(self->fd, pbuf.buf, pbuf.len); + n = _Py_read(self->fd, buffer->buf, buffer->len); /* copy errno because PyBuffer_Release() can indirectly modify it */ err = errno; - PyBuffer_Release(&pbuf); if (n == -1) { if (err == EAGAIN) { @@ -586,8 +656,18 @@ return addend + currentsize; } +/*[clinic input] +_io.FileIO.readall + +Read all data from the file, returned as bytes. + +In non-blocking mode, returns as much as is immediately available, +or None if no data is available. Return an empty bytes object at EOF. +[clinic start generated code]*/ + static PyObject * -fileio_readall(fileio *self) +_io_FileIO_readall_impl(fileio *self) +/*[clinic end generated code: output=faa0292b213b4022 input=dbdc137f55602834]*/ { struct _Py_stat_struct status; Py_off_t pos, end; @@ -673,12 +753,24 @@ return result; } +/*[clinic input] +_io.FileIO.read + size: io_ssize_t = -1 + / + +Read at most size bytes, returned as bytes. + +Only makes one system call, so less data may be returned than requested. +In non-blocking mode, returns None if no data is available. +Return an empty bytes object at EOF. +[clinic start generated code]*/ + static PyObject * -fileio_read(fileio *self, PyObject *args) +_io_FileIO_read_impl(fileio *self, Py_ssize_t size) +/*[clinic end generated code: output=42528d39dd0ca641 input=5c6caa5490c13a9b]*/ { char *ptr; Py_ssize_t n; - Py_ssize_t size = -1; PyObject *bytes; if (self->fd < 0) @@ -686,11 +778,8 @@ if (!self->readable) return err_mode("reading"); - if (!PyArg_ParseTuple(args, "|O&", &_PyIO_ConvertSsize_t, &size)) - return NULL; - if (size < 0) - return fileio_readall(self); + return _io_FileIO_readall_impl(self); #ifdef MS_WINDOWS /* On Windows, the count parameter of read() is an int */ @@ -725,10 +814,22 @@ return (PyObject *) bytes; } +/*[clinic input] +_io.FileIO.write + b: Py_buffer + / + +Write bytes b to file, return number written. + +Only makes one system call, so not all of the data may be written. +The number of bytes actually written is returned. In non-blocking mode, +returns None if the write would block. +[clinic start generated code]*/ + static PyObject * -fileio_write(fileio *self, PyObject *args) +_io_FileIO_write_impl(fileio *self, Py_buffer *b) +/*[clinic end generated code: output=b4059db3d363a2f7 input=ffbd8834f447ac31]*/ { - Py_buffer pbuf; Py_ssize_t n; int err; @@ -737,13 +838,9 @@ if (!self->writable) return err_mode("writing"); - if (!PyArg_ParseTuple(args, "y*", &pbuf)) - return NULL; - - n = _Py_write(self->fd, pbuf.buf, pbuf.len); + n = _Py_write(self->fd, b->buf, b->len); /* copy errno because PyBuffer_Release() can indirectly modify it */ err = errno; - PyBuffer_Release(&pbuf); if (n < 0) { if (err == EAGAIN) { @@ -817,23 +914,44 @@ #endif } +/*[clinic input] +_io.FileIO.seek + pos: object + whence: int = 0 + / + +Move to new file position and return the file position. + +Argument offset is a byte count. Optional argument whence defaults to +SEEK_SET or 0 (offset from start of file, offset should be >= 0); other values +are SEEK_CUR or 1 (move relative to current position, positive or negative), +and SEEK_END or 2 (move relative to end of file, usually negative, although +many platforms allow seeking beyond the end of a file). + +Note that not all file objects are seekable. +[clinic start generated code]*/ + static PyObject * -fileio_seek(fileio *self, PyObject *args) +_io_FileIO_seek_impl(fileio *self, PyObject *pos, int whence) +/*[clinic end generated code: output=c976acdf054e6655 input=0439194b0774d454]*/ { - PyObject *posobj; - int whence = 0; - if (self->fd < 0) return err_closed(); - if (!PyArg_ParseTuple(args, "O|i", &posobj, &whence)) - return NULL; - - return portable_lseek(self->fd, posobj, whence); + return portable_lseek(self->fd, pos, whence); } +/*[clinic input] +_io.FileIO.tell + +Current file position. + +Can raise OSError for non seekable files. +[clinic start generated code]*/ + static PyObject * -fileio_tell(fileio *self, PyObject *args) +_io_FileIO_tell_impl(fileio *self) +/*[clinic end generated code: output=ffe2147058809d0b input=807e24ead4cec2f9]*/ { if (self->fd < 0) return err_closed(); @@ -842,10 +960,21 @@ } #ifdef HAVE_FTRUNCATE +/*[clinic input] +_io.FileIO.truncate + size as posobj: object = NULL + / + +Truncate the file to at most size bytes and return the truncated size. + +Size defaults to the current file position, as returned by tell(). +The current file position is changed to the value of size. +[clinic start generated code]*/ + static PyObject * -fileio_truncate(fileio *self, PyObject *args) +_io_FileIO_truncate_impl(fileio *self, PyObject *posobj) +/*[clinic end generated code: output=e49ca7a916c176fa input=9026af44686b7318]*/ { - PyObject *posobj = NULL; /* the new size wanted by the user */ Py_off_t pos; int ret; int fd; @@ -856,9 +985,6 @@ if (!self->writable) return err_mode("writing"); - if (!PyArg_ParseTuple(args, "|O", &posobj)) - return NULL; - if (posobj == Py_None || posobj == NULL) { /* Get the current position. */ posobj = portable_lseek(fd, NULL, 1); @@ -952,8 +1078,15 @@ return res; } +/*[clinic input] +_io.FileIO.isatty + +True if the file is connected to a TTY device. +[clinic start generated code]*/ + static PyObject * -fileio_isatty(fileio *self) +_io_FileIO_isatty_impl(fileio *self) +/*[clinic end generated code: output=932c39924e9a8070 input=cd94ca1f5e95e843]*/ { long res; @@ -978,110 +1111,22 @@ return NULL; } - -PyDoc_STRVAR(fileio_doc, -"file(name: str[, mode: str][, opener: None]) -> file IO object\n" -"\n" -"Open a file. The mode can be 'r' (default), 'w', 'x' or 'a' for reading,\n" -"writing, exclusive creation or appending. The file will be created if it\n" -"doesn't exist when opened for writing or appending; it will be truncated\n" -"when opened for writing. A FileExistsError will be raised if it already\n" -"exists when opened for creating. Opening a file for creating implies\n" -"writing so this mode behaves in a similar way to 'w'.Add a '+' to the mode\n" -"to allow simultaneous reading and writing. A custom opener can be used by\n" -"passing a callable as *opener*. The underlying file descriptor for the file\n" -"object is then obtained by calling opener with (*name*, *flags*).\n" -"*opener* must return an open file descriptor (passing os.open as *opener*\n" -"results in functionality similar to passing None)."); - -PyDoc_STRVAR(read_doc, -"read(size: int) -> bytes. read at most size bytes, returned as bytes.\n" -"\n" -"Only makes one system call, so less data may be returned than requested\n" -"In non-blocking mode, returns None if no data is available.\n" -"Return an empty bytes object at EOF."); - -PyDoc_STRVAR(readall_doc, -"readall() -> bytes. read all data from the file, returned as bytes.\n" -"\n" -"In non-blocking mode, returns as much as is immediately available,\n" -"or None if no data is available. Return an empty bytes object at EOF."); - -PyDoc_STRVAR(write_doc, -"write(b: bytes) -> int. Write bytes b to file, return number written.\n" -"\n" -"Only makes one system call, so not all of the data may be written.\n" -"The number of bytes actually written is returned. In non-blocking mode,\n" -"returns None if the write would block." -); - -PyDoc_STRVAR(fileno_doc, -"fileno() -> int. Return the underlying file descriptor (an integer)."); - -PyDoc_STRVAR(seek_doc, -"seek(offset: int[, whence: int]) -> int. Move to new file position and\n" -"return the file position.\n" -"\n" -"Argument offset is a byte count. Optional argument whence defaults to\n" -"SEEK_SET or 0 (offset from start of file, offset should be >= 0); other values\n" -"are SEEK_CUR or 1 (move relative to current position, positive or negative),\n" -"and SEEK_END or 2 (move relative to end of file, usually negative, although\n" -"many platforms allow seeking beyond the end of a file).\n" -"\n" -"Note that not all file objects are seekable."); - -#ifdef HAVE_FTRUNCATE -PyDoc_STRVAR(truncate_doc, -"truncate([size: int]) -> int. Truncate the file to at most size bytes\n" -"and return the truncated size.\n" -"\n" -"Size defaults to the current file position, as returned by tell().\n" -"The current file position is changed to the value of size."); -#endif - -PyDoc_STRVAR(tell_doc, -"tell() -> int. Current file position.\n" -"\n" -"Can raise OSError for non seekable files." -); - -PyDoc_STRVAR(readinto_doc, -"readinto() -> Same as RawIOBase.readinto()."); - -PyDoc_STRVAR(close_doc, -"close() -> None. Close the file.\n" -"\n" -"A closed file cannot be used for further I/O operations. close() may be\n" -"called more than once without error."); - -PyDoc_STRVAR(isatty_doc, -"isatty() -> bool. True if the file is connected to a TTY device."); - -PyDoc_STRVAR(seekable_doc, -"seekable() -> bool. True if file supports random-access."); - -PyDoc_STRVAR(readable_doc, -"readable() -> bool. True if file was opened in a read mode."); - -PyDoc_STRVAR(writable_doc, -"writable() -> bool. True if file was opened in a write mode."); +#include "clinic/fileio.c.h" static PyMethodDef fileio_methods[] = { - {"read", (PyCFunction)fileio_read, METH_VARARGS, read_doc}, - {"readall", (PyCFunction)fileio_readall, METH_NOARGS, readall_doc}, - {"readinto", (PyCFunction)fileio_readinto, METH_VARARGS, readinto_doc}, - {"write", (PyCFunction)fileio_write, METH_VARARGS, write_doc}, - {"seek", (PyCFunction)fileio_seek, METH_VARARGS, seek_doc}, - {"tell", (PyCFunction)fileio_tell, METH_VARARGS, tell_doc}, -#ifdef HAVE_FTRUNCATE - {"truncate", (PyCFunction)fileio_truncate, METH_VARARGS, truncate_doc}, -#endif - {"close", (PyCFunction)fileio_close, METH_NOARGS, close_doc}, - {"seekable", (PyCFunction)fileio_seekable, METH_NOARGS, seekable_doc}, - {"readable", (PyCFunction)fileio_readable, METH_NOARGS, readable_doc}, - {"writable", (PyCFunction)fileio_writable, METH_NOARGS, writable_doc}, - {"fileno", (PyCFunction)fileio_fileno, METH_NOARGS, fileno_doc}, - {"isatty", (PyCFunction)fileio_isatty, METH_NOARGS, isatty_doc}, + _IO_FILEIO_READ_METHODDEF + _IO_FILEIO_READALL_METHODDEF + _IO_FILEIO_READINTO_METHODDEF + _IO_FILEIO_WRITE_METHODDEF + _IO_FILEIO_SEEK_METHODDEF + _IO_FILEIO_TELL_METHODDEF + _IO_FILEIO_TRUNCATE_METHODDEF + _IO_FILEIO_CLOSE_METHODDEF + _IO_FILEIO_SEEKABLE_METHODDEF + _IO_FILEIO_READABLE_METHODDEF + _IO_FILEIO_WRITABLE_METHODDEF + _IO_FILEIO_FILENO_METHODDEF + _IO_FILEIO_ISATTY_METHODDEF {"_dealloc_warn", (PyCFunction)fileio_dealloc_warn, METH_O, NULL}, {"__getstate__", (PyCFunction)fileio_getstate, METH_NOARGS, NULL}, {NULL, NULL} /* sentinel */ @@ -1143,7 +1188,7 @@ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_FINALIZE, /* tp_flags */ - fileio_doc, /* tp_doc */ + _io_FileIO___init____doc__, /* tp_doc */ (traverseproc)fileio_traverse, /* tp_traverse */ (inquiry)fileio_clear, /* tp_clear */ 0, /* tp_richcompare */ @@ -1158,7 +1203,7 @@ 0, /* tp_descr_get */ 0, /* tp_descr_set */ offsetof(fileio, dict), /* tp_dictoffset */ - fileio_init, /* tp_init */ + _io_FileIO___init__, /* tp_init */ PyType_GenericAlloc, /* tp_alloc */ fileio_new, /* tp_new */ PyObject_GC_Del, /* tp_free */ diff --git a/Modules/_io/iobase.c b/Modules/_io/iobase.c --- a/Modules/_io/iobase.c +++ b/Modules/_io/iobase.c @@ -13,6 +13,20 @@ #include "structmember.h" #include "_iomodule.h" +/*[clinic input] +module _io +class _io._IOBase "PyObject *" "&PyIOBase_Type" +class _io._RawIOBase "PyObject *" "&PyRawIOBase_Type" +[clinic start generated code]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=d29a4d076c2b211c]*/ + +/*[python input] +class io_ssize_t_converter(CConverter): + type = 'Py_ssize_t' + converter = '_PyIO_ConvertSsize_t' +[python start generated code]*/ +/*[python end generated code: output=da39a3ee5e6b4b0d input=d0a811d3cbfd1b33]*/ + /* * IOBase class, an abstract class */ @@ -96,11 +110,15 @@ return iobase_unsupported("seek"); } -PyDoc_STRVAR(iobase_tell_doc, - "Return current stream position."); +/*[clinic input] +_io._IOBase.tell + +Return current stream position. +[clinic start generated code]*/ static PyObject * -iobase_tell(PyObject *self, PyObject *args) +_io__IOBase_tell_impl(PyObject *self) +/*[clinic end generated code: output=89a1c0807935abe2 input=04e615fec128801f]*/ { _Py_IDENTIFIER(seek); @@ -121,13 +139,17 @@ /* Flush and close methods */ -PyDoc_STRVAR(iobase_flush_doc, - "Flush write buffers, if applicable.\n" - "\n" - "This is not implemented for read-only and non-blocking streams.\n"); +/*[clinic input] +_io._IOBase.flush + +Flush write buffers, if applicable. + +This is not implemented for read-only and non-blocking streams. +[clinic start generated code]*/ static PyObject * -iobase_flush(PyObject *self, PyObject *args) +_io__IOBase_flush_impl(PyObject *self) +/*[clinic end generated code: output=7cef4b4d54656a3b input=773be121abe270aa]*/ { /* XXX Should this return the number of bytes written??? */ if (IS_CLOSED(self)) { @@ -137,11 +159,6 @@ Py_RETURN_NONE; } -PyDoc_STRVAR(iobase_close_doc, - "Flush and close the IO object.\n" - "\n" - "This method has no effect if the file is already closed.\n"); - static int iobase_closed(PyObject *self) { @@ -180,8 +197,17 @@ `__IOBase_closed` and call flush() by itself, but it is redundant with whatever behaviour a non-trivial derived class will implement. */ +/*[clinic input] +_io._IOBase.close + +Flush and close the IO object. + +This method has no effect if the file is already closed. +[clinic start generated code]*/ + static PyObject * -iobase_close(PyObject *self, PyObject *args) +_io__IOBase_close_impl(PyObject *self) +/*[clinic end generated code: output=63c6a6f57d783d6d input=f4494d5c31dbc6b7]*/ { PyObject *res; @@ -304,14 +330,18 @@ /* Inquiry methods */ -PyDoc_STRVAR(iobase_seekable_doc, - "Return whether object supports random access.\n" - "\n" - "If False, seek(), tell() and truncate() will raise UnsupportedOperation.\n" - "This method may need to do a test seek()."); +/*[clinic input] +_io._IOBase.seekable + +Return whether object supports random access. + +If False, seek(), tell() and truncate() will raise UnsupportedOperation. +This method may need to do a test seek(). +[clinic start generated code]*/ static PyObject * -iobase_seekable(PyObject *self, PyObject *args) +_io__IOBase_seekable_impl(PyObject *self) +/*[clinic end generated code: output=4c24c67f5f32a43d input=22676eebb81dcf1e]*/ { Py_RETURN_FALSE; } @@ -333,13 +363,17 @@ return res; } -PyDoc_STRVAR(iobase_readable_doc, - "Return whether object was opened for reading.\n" - "\n" - "If False, read() will raise UnsupportedOperation."); +/*[clinic input] +_io._IOBase.readable + +Return whether object was opened for reading. + +If False, read() will raise UnsupportedOperation. +[clinic start generated code]*/ static PyObject * -iobase_readable(PyObject *self, PyObject *args) +_io__IOBase_readable_impl(PyObject *self) +/*[clinic end generated code: output=e48089250686388b input=12fc3d8f6be46434]*/ { Py_RETURN_FALSE; } @@ -362,13 +396,17 @@ return res; } -PyDoc_STRVAR(iobase_writable_doc, - "Return whether object was opened for writing.\n" - "\n" - "If False, write() will raise UnsupportedOperation."); +/*[clinic input] +_io._IOBase.writable + +Return whether object was opened for writing. + +If False, write() will raise UnsupportedOperation. +[clinic start generated code]*/ static PyObject * -iobase_writable(PyObject *self, PyObject *args) +_io__IOBase_writable_impl(PyObject *self) +/*[clinic end generated code: output=406001d0985be14f input=c17a0bb6a8dfc590]*/ { Py_RETURN_FALSE; } @@ -413,24 +451,32 @@ /* XXX Should these be present even if unimplemented? */ -PyDoc_STRVAR(iobase_fileno_doc, - "Returns underlying file descriptor if one exists.\n" - "\n" - "An IOError is raised if the IO object does not use a file descriptor.\n"); +/*[clinic input] +_io._IOBase.fileno + +Returns underlying file descriptor if one exists. + +An IOError is raised if the IO object does not use a file descriptor. +[clinic start generated code]*/ static PyObject * -iobase_fileno(PyObject *self, PyObject *args) +_io__IOBase_fileno_impl(PyObject *self) +/*[clinic end generated code: output=7cc0973f0f5f3b73 input=32773c5df4b7eede]*/ { return iobase_unsupported("fileno"); } -PyDoc_STRVAR(iobase_isatty_doc, - "Return whether this is an 'interactive' stream.\n" - "\n" - "Return False if it can't be determined.\n"); +/*[clinic input] +_io._IOBase.isatty + +Return whether this is an 'interactive' stream. + +Return False if it can't be determined. +[clinic start generated code]*/ static PyObject * -iobase_isatty(PyObject *self, PyObject *args) +_io__IOBase_isatty_impl(PyObject *self) +/*[clinic end generated code: output=60cab77cede41cdd input=9ef76530d368458b]*/ { if (_PyIOBase_check_closed(self, Py_True) == NULL) return NULL; @@ -439,30 +485,31 @@ /* Readline(s) and writelines */ -PyDoc_STRVAR(iobase_readline_doc, - "Read and return a line from the stream.\n" - "\n" - "If limit is specified, at most limit bytes will be read.\n" - "\n" - "The line terminator is always b'\\n' for binary files; for text\n" - "files, the newlines argument to open can be used to select the line\n" - "terminator(s) recognized.\n"); +/*[clinic input] +_io._IOBase.readline + size as limit: io_ssize_t = -1 + / + +Read and return a line from the stream. + +If size is specified, at most size bytes will be read. + +The line terminator is always b'\n' for binary files; for text +files, the newlines argument to open can be used to select the line +terminator(s) recognized. +[clinic start generated code]*/ static PyObject * -iobase_readline(PyObject *self, PyObject *args) +_io__IOBase_readline_impl(PyObject *self, Py_ssize_t limit) +/*[clinic end generated code: output=4479f79b58187840 input=df4cc8884f553cab]*/ { /* For backwards compatibility, a (slowish) readline(). */ - Py_ssize_t limit = -1; int has_peek = 0; PyObject *buffer, *result; Py_ssize_t old_size = -1; _Py_IDENTIFIER(peek); - if (!PyArg_ParseTuple(args, "|O&:readline", &_PyIO_ConvertSsize_t, &limit)) { - return NULL; - } - if (_PyObject_HasAttrId(self, &PyId_peek)) has_peek = 1; @@ -585,23 +632,25 @@ return line; } -PyDoc_STRVAR(iobase_readlines_doc, - "Return a list of lines from the stream.\n" - "\n" - "hint can be specified to control the number of lines read: no more\n" - "lines will be read if the total size (in bytes/characters) of all\n" - "lines so far exceeds hint."); +/*[clinic input] +_io._IOBase.readlines + hint: io_ssize_t = -1 + / + +Return a list of lines from the stream. + +hint can be specified to control the number of lines read: no more +lines will be read if the total size (in bytes/characters) of all +lines so far exceeds hint. +[clinic start generated code]*/ static PyObject * -iobase_readlines(PyObject *self, PyObject *args) +_io__IOBase_readlines_impl(PyObject *self, Py_ssize_t hint) +/*[clinic end generated code: output=2f50421677fa3dea input=1961c4a95e96e661]*/ { - Py_ssize_t hint = -1, length = 0; + Py_ssize_t length = 0; PyObject *result; - if (!PyArg_ParseTuple(args, "|O&:readlines", &_PyIO_ConvertSsize_t, &hint)) { - return NULL; - } - result = PyList_New(0); if (result == NULL) return NULL; @@ -646,14 +695,17 @@ return result; } +/*[clinic input] +_io._IOBase.writelines + lines: object + / +[clinic start generated code]*/ + static PyObject * -iobase_writelines(PyObject *self, PyObject *args) +_io__IOBase_writelines(PyObject *self, PyObject *lines) +/*[clinic end generated code: output=976eb0a9b60a6628 input=432e729a8450b3cb]*/ { - PyObject *lines, *iter, *res; - - if (!PyArg_ParseTuple(args, "O:writelines", &lines)) { - return NULL; - } + PyObject *iter, *res; if (_PyIOBase_check_closed(self, Py_True) == NULL) return NULL; @@ -688,31 +740,33 @@ Py_RETURN_NONE; } +#include "clinic/iobase.c.h" + static PyMethodDef iobase_methods[] = { {"seek", iobase_seek, METH_VARARGS, iobase_seek_doc}, - {"tell", iobase_tell, METH_NOARGS, iobase_tell_doc}, + _IO__IOBASE_TELL_METHODDEF {"truncate", iobase_truncate, METH_VARARGS, iobase_truncate_doc}, - {"flush", iobase_flush, METH_NOARGS, iobase_flush_doc}, - {"close", iobase_close, METH_NOARGS, iobase_close_doc}, + _IO__IOBASE_FLUSH_METHODDEF + _IO__IOBASE_CLOSE_METHODDEF - {"seekable", iobase_seekable, METH_NOARGS, iobase_seekable_doc}, - {"readable", iobase_readable, METH_NOARGS, iobase_readable_doc}, - {"writable", iobase_writable, METH_NOARGS, iobase_writable_doc}, + _IO__IOBASE_SEEKABLE_METHODDEF + _IO__IOBASE_READABLE_METHODDEF + _IO__IOBASE_WRITABLE_METHODDEF {"_checkClosed", _PyIOBase_check_closed, METH_NOARGS}, {"_checkSeekable", _PyIOBase_check_seekable, METH_NOARGS}, {"_checkReadable", _PyIOBase_check_readable, METH_NOARGS}, {"_checkWritable", _PyIOBase_check_writable, METH_NOARGS}, - {"fileno", iobase_fileno, METH_NOARGS, iobase_fileno_doc}, - {"isatty", iobase_isatty, METH_NOARGS, iobase_isatty_doc}, + _IO__IOBASE_FILENO_METHODDEF + _IO__IOBASE_ISATTY_METHODDEF {"__enter__", iobase_enter, METH_NOARGS}, {"__exit__", iobase_exit, METH_VARARGS}, - {"readline", iobase_readline, METH_VARARGS, iobase_readline_doc}, - {"readlines", iobase_readlines, METH_VARARGS, iobase_readlines_doc}, - {"writelines", iobase_writelines, METH_VARARGS}, + _IO__IOBASE_READLINE_METHODDEF + _IO__IOBASE_READLINES_METHODDEF + _IO__IOBASE_WRITELINES_METHODDEF {NULL, NULL} }; @@ -795,16 +849,18 @@ * either.) */ +/*[clinic input] +_io._RawIOBase.read + size as n: Py_ssize_t = -1 + / +[clinic start generated code]*/ + static PyObject * -rawiobase_read(PyObject *self, PyObject *args) +_io__RawIOBase_read_impl(PyObject *self, Py_ssize_t n) +/*[clinic end generated code: output=6cdeb731e3c9f13c input=b6d0dcf6417d1374]*/ { - Py_ssize_t n = -1; PyObject *b, *res; - if (!PyArg_ParseTuple(args, "|n:read", &n)) { - return NULL; - } - if (n < 0) { _Py_IDENTIFIER(readall); @@ -836,11 +892,15 @@ } -PyDoc_STRVAR(rawiobase_readall_doc, - "Read until EOF, using multiple read() call."); +/*[clinic input] +_io._RawIOBase.readall + +Read until EOF, using multiple read() call. +[clinic start generated code]*/ static PyObject * -rawiobase_readall(PyObject *self, PyObject *args) +_io__RawIOBase_readall_impl(PyObject *self) +/*[clinic end generated code: output=1987b9ce929425a0 input=688874141213622a]*/ { int r; PyObject *chunks = PyList_New(0); @@ -893,8 +953,8 @@ } static PyMethodDef rawiobase_methods[] = { - {"read", rawiobase_read, METH_VARARGS}, - {"readall", rawiobase_readall, METH_NOARGS, rawiobase_readall_doc}, + _IO__RAWIOBASE_READ_METHODDEF + _IO__RAWIOBASE_READALL_METHODDEF {NULL, NULL} }; diff --git a/Modules/_io/stringio.c b/Modules/_io/stringio.c --- a/Modules/_io/stringio.c +++ b/Modules/_io/stringio.c @@ -11,6 +11,12 @@ #define STATE_REALIZED 1 #define STATE_ACCUMULATING 2 +/*[clinic input] +module _io +class _io.StringIO "stringio *" "&PyStringIO_Type" +[clinic start generated code]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=c17bc0f42165cd7d]*/ + typedef struct { PyObject_HEAD Py_UCS4 *buf; @@ -39,6 +45,8 @@ PyObject *weakreflist; } stringio; +static int _io_StringIO___init__(PyObject *self, PyObject *args, PyObject *kwargs); + #define CHECK_INITIALIZED(self) \ if (self->ok <= 0) { \ PyErr_SetString(PyExc_ValueError, \ @@ -58,12 +66,6 @@ return NULL; \ } -PyDoc_STRVAR(stringio_doc, - "Text I/O implementation using an in-memory buffer.\n" - "\n" - "The initial_value argument sets the value of object. The newline\n" - "argument is like the one of TextIOWrapper's constructor."); - /* Internal routine for changing the size, in terms of characters, of the buffer of StringIO objects. The caller should ensure that the 'size' @@ -264,11 +266,15 @@ return -1; } -PyDoc_STRVAR(stringio_getvalue_doc, - "Retrieve the entire contents of the object."); +/*[clinic input] +_io.StringIO.getvalue + +Retrieve the entire contents of the object. +[clinic start generated code]*/ static PyObject * -stringio_getvalue(stringio *self) +_io_StringIO_getvalue_impl(stringio *self) +/*[clinic end generated code: output=27b6a7bfeaebce01 input=d23cb81d6791cf88]*/ { CHECK_INITIALIZED(self); CHECK_CLOSED(self); @@ -278,33 +284,40 @@ self->string_size); } -PyDoc_STRVAR(stringio_tell_doc, - "Tell the current file position."); +/*[clinic input] +_io.StringIO.tell + +Tell the current file position. +[clinic start generated code]*/ static PyObject * -stringio_tell(stringio *self) +_io_StringIO_tell_impl(stringio *self) +/*[clinic end generated code: output=2e87ac67b116c77b input=ec866ebaff02f405]*/ { CHECK_INITIALIZED(self); CHECK_CLOSED(self); return PyLong_FromSsize_t(self->pos); } -PyDoc_STRVAR(stringio_read_doc, - "Read at most n characters, returned as a string.\n" - "\n" - "If the argument is negative or omitted, read until EOF\n" - "is reached. Return an empty string at EOF.\n"); +/*[clinic input] +_io.StringIO.read + size as arg: object = None + / + +Read at most size characters, returned as a string. + +If the argument is negative or omitted, read until EOF +is reached. Return an empty string at EOF. +[clinic start generated code]*/ static PyObject * -stringio_read(stringio *self, PyObject *args) +_io_StringIO_read_impl(stringio *self, PyObject *arg) +/*[clinic end generated code: output=3676864773746f68 input=9a319015f6f3965c]*/ { Py_ssize_t size, n; Py_UCS4 *output; - PyObject *arg = Py_None; CHECK_INITIALIZED(self); - if (!PyArg_ParseTuple(args, "|O:read", &arg)) - return NULL; CHECK_CLOSED(self); if (PyNumber_Check(arg)) { @@ -373,20 +386,23 @@ return PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND, start, len); } -PyDoc_STRVAR(stringio_readline_doc, - "Read until newline or EOF.\n" - "\n" - "Returns an empty string if EOF is hit immediately.\n"); +/*[clinic input] +_io.StringIO.readline + size as arg: object = None + / + +Read until newline or EOF. + +Returns an empty string if EOF is hit immediately. +[clinic start generated code]*/ static PyObject * -stringio_readline(stringio *self, PyObject *args) +_io_StringIO_readline_impl(stringio *self, PyObject *arg) +/*[clinic end generated code: output=99fdcac03a3dee81 input=e0e0ed4042040176]*/ { - PyObject *arg = Py_None; Py_ssize_t limit = -1; CHECK_INITIALIZED(self); - if (!PyArg_ParseTuple(args, "|O:readline", &arg)) - return NULL; CHECK_CLOSED(self); ENSURE_REALIZED(self); @@ -441,22 +457,25 @@ return line; } -PyDoc_STRVAR(stringio_truncate_doc, - "Truncate size to pos.\n" - "\n" - "The pos argument defaults to the current file position, as\n" - "returned by tell(). The current file position is unchanged.\n" - "Returns the new absolute position.\n"); +/*[clinic input] +_io.StringIO.truncate + pos as arg: object = None + / + +Truncate size to pos. + +The pos argument defaults to the current file position, as +returned by tell(). The current file position is unchanged. +Returns the new absolute position. +[clinic start generated code]*/ static PyObject * -stringio_truncate(stringio *self, PyObject *args) +_io_StringIO_truncate_impl(stringio *self, PyObject *arg) +/*[clinic end generated code: output=6072439c2b01d306 input=748619a494ba53ad]*/ { Py_ssize_t size; - PyObject *arg = Py_None; CHECK_INITIALIZED(self); - if (!PyArg_ParseTuple(args, "|O:truncate", &arg)) - return NULL; CHECK_CLOSED(self); if (PyNumber_Check(arg)) { @@ -490,49 +509,51 @@ return PyLong_FromSsize_t(size); } -PyDoc_STRVAR(stringio_seek_doc, - "Change stream position.\n" - "\n" - "Seek to character offset pos relative to position indicated by whence:\n" - " 0 Start of stream (the default). pos should be >= 0;\n" - " 1 Current position - pos must be 0;\n" - " 2 End of stream - pos must be 0.\n" - "Returns the new absolute position.\n"); +/*[clinic input] +_io.StringIO.seek + pos: Py_ssize_t + whence: int = 0 + / + +Change stream position. + +Seek to character offset pos relative to position indicated by whence: + 0 Start of stream (the default). pos should be >= 0; + 1 Current position - pos must be 0; + 2 End of stream - pos must be 0. +Returns the new absolute position. +[clinic start generated code]*/ static PyObject * -stringio_seek(stringio *self, PyObject *args) +_io_StringIO_seek_impl(stringio *self, Py_ssize_t pos, int whence) +/*[clinic end generated code: output=e9e0ac9a8ae71c25 input=e3855b24e7cae06a]*/ { - Py_ssize_t pos; - int mode = 0; - CHECK_INITIALIZED(self); - if (!PyArg_ParseTuple(args, "n|i:seek", &pos, &mode)) - return NULL; CHECK_CLOSED(self); - if (mode != 0 && mode != 1 && mode != 2) { + if (whence != 0 && whence != 1 && whence != 2) { PyErr_Format(PyExc_ValueError, - "Invalid whence (%i, should be 0, 1 or 2)", mode); + "Invalid whence (%i, should be 0, 1 or 2)", whence); return NULL; } - else if (pos < 0 && mode == 0) { + else if (pos < 0 && whence == 0) { PyErr_Format(PyExc_ValueError, "Negative seek position %zd", pos); return NULL; } - else if (mode != 0 && pos != 0) { + else if (whence != 0 && pos != 0) { PyErr_SetString(PyExc_IOError, "Can't do nonzero cur-relative seeks"); return NULL; } - /* mode 0: offset relative to beginning of the string. - mode 1: no change to current position. - mode 2: change position to end of file. */ - if (mode == 1) { + /* whence = 0: offset relative to beginning of the string. + whence = 1: no change to current position. + whence = 2: change position to end of file. */ + if (whence == 1) { pos = self->pos; } - else if (mode == 2) { + else if (whence == 2) { pos = self->string_size; } @@ -541,14 +562,20 @@ return PyLong_FromSsize_t(self->pos); } -PyDoc_STRVAR(stringio_write_doc, - "Write string to file.\n" - "\n" - "Returns the number of characters written, which is always equal to\n" - "the length of the string.\n"); +/*[clinic input] +_io.StringIO.write + s as obj: object + / + +Write string to file. + +Returns the number of characters written, which is always equal to +the length of the string. +[clinic start generated code]*/ static PyObject * -stringio_write(stringio *self, PyObject *obj) +_io_StringIO_write(stringio *self, PyObject *obj) +/*[clinic end generated code: output=0deaba91a15b94da input=cf96f3b16586e669]*/ { Py_ssize_t size; @@ -569,14 +596,20 @@ return PyLong_FromSsize_t(size); } -PyDoc_STRVAR(stringio_close_doc, - "Close the IO object. Attempting any further operation after the\n" - "object is closed will raise a ValueError.\n" - "\n" - "This method has no effect if the file is already closed.\n"); +/*[clinic input] +_io.StringIO.close + +Close the IO object. + +Attempting any further operation after the object is closed +will raise a ValueError. + +This method has no effect if the file is already closed. +[clinic start generated code]*/ static PyObject * -stringio_close(stringio *self) +_io_StringIO_close_impl(stringio *self) +/*[clinic end generated code: output=04399355cbe518f1 input=cbc10b45f35d6d46]*/ { self->closed = 1; /* Free up some memory */ @@ -644,19 +677,25 @@ return (PyObject *)self; } +/*[clinic input] +_io.StringIO.__init__ + initial_value as value: object(c_default="NULL") = '' + newline as newline_obj: object(c_default="NULL") = '\n' + +Text I/O implementation using an in-memory buffer. + +The initial_value argument sets the value of object. The newline +argument is like the one of TextIOWrapper's constructor. +[clinic start generated code]*/ + static int -stringio_init(stringio *self, PyObject *args, PyObject *kwds) +_io_StringIO___init___impl(stringio *self, PyObject *value, + PyObject *newline_obj) +/*[clinic end generated code: output=a421ea023b22ef4e input=cee2d9181b2577a3]*/ { - char *kwlist[] = {"initial_value", "newline", NULL}; - PyObject *value = NULL; - PyObject *newline_obj = NULL; char *newline = "\n"; Py_ssize_t value_len; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OO:__init__", kwlist, - &value, &newline_obj)) - return -1; - /* Parse the newline argument. This used to be done with the 'z' specifier, however this allowed any object with the buffer interface to be converted. Thus we have to parse it manually since we only want to @@ -761,33 +800,45 @@ /* Properties and pseudo-properties */ -PyDoc_STRVAR(stringio_readable_doc, -"readable() -> bool. Returns True if the IO object can be read."); +/*[clinic input] +_io.StringIO.readable -PyDoc_STRVAR(stringio_writable_doc, -"writable() -> bool. Returns True if the IO object can be written."); - -PyDoc_STRVAR(stringio_seekable_doc, -"seekable() -> bool. Returns True if the IO object can be seeked."); +Returns True if the IO object can be read. +[clinic start generated code]*/ static PyObject * -stringio_seekable(stringio *self, PyObject *args) +_io_StringIO_readable_impl(stringio *self) +/*[clinic end generated code: output=b19d44dd8b1ceb99 input=39ce068b224c21ad]*/ { CHECK_INITIALIZED(self); CHECK_CLOSED(self); Py_RETURN_TRUE; } +/*[clinic input] +_io.StringIO.writable + +Returns True if the IO object can be written. +[clinic start generated code]*/ + static PyObject * -stringio_readable(stringio *self, PyObject *args) +_io_StringIO_writable_impl(stringio *self) +/*[clinic end generated code: output=13e4dd77187074ca input=7a691353aac38835]*/ { CHECK_INITIALIZED(self); CHECK_CLOSED(self); Py_RETURN_TRUE; } +/*[clinic input] +_io.StringIO.seekable + +Returns True if the IO object can be seeked. +[clinic start generated code]*/ + static PyObject * -stringio_writable(stringio *self, PyObject *args) +_io_StringIO_seekable_impl(stringio *self) +/*[clinic end generated code: output=4d20b4641c756879 input=4c606d05b32952e6]*/ { CHECK_INITIALIZED(self); CHECK_CLOSED(self); @@ -809,7 +860,7 @@ static PyObject * stringio_getstate(stringio *self) { - PyObject *initvalue = stringio_getvalue(self); + PyObject *initvalue = _io_StringIO_getvalue_impl(self); PyObject *dict; PyObject *state; @@ -857,7 +908,7 @@ initarg = PyTuple_GetSlice(state, 0, 2); if (initarg == NULL) return NULL; - if (stringio_init(self, initarg, NULL) < 0) { + if (_io_StringIO___init__((PyObject *)self, initarg, NULL) < 0) { Py_DECREF(initarg); return NULL; } @@ -959,19 +1010,21 @@ return PyObject_GetAttr(self->decoder, _PyIO_str_newlines); } +#include "clinic/stringio.c.h" + static struct PyMethodDef stringio_methods[] = { - {"close", (PyCFunction)stringio_close, METH_NOARGS, stringio_close_doc}, - {"getvalue", (PyCFunction)stringio_getvalue, METH_NOARGS, stringio_getvalue_doc}, - {"read", (PyCFunction)stringio_read, METH_VARARGS, stringio_read_doc}, - {"readline", (PyCFunction)stringio_readline, METH_VARARGS, stringio_readline_doc}, - {"tell", (PyCFunction)stringio_tell, METH_NOARGS, stringio_tell_doc}, - {"truncate", (PyCFunction)stringio_truncate, METH_VARARGS, stringio_truncate_doc}, - {"seek", (PyCFunction)stringio_seek, METH_VARARGS, stringio_seek_doc}, - {"write", (PyCFunction)stringio_write, METH_O, stringio_write_doc}, + _IO_STRINGIO_CLOSE_METHODDEF + _IO_STRINGIO_GETVALUE_METHODDEF + _IO_STRINGIO_READ_METHODDEF + _IO_STRINGIO_READLINE_METHODDEF + _IO_STRINGIO_TELL_METHODDEF + _IO_STRINGIO_TRUNCATE_METHODDEF + _IO_STRINGIO_SEEK_METHODDEF + _IO_STRINGIO_WRITE_METHODDEF - {"seekable", (PyCFunction)stringio_seekable, METH_NOARGS, stringio_seekable_doc}, - {"readable", (PyCFunction)stringio_readable, METH_NOARGS, stringio_readable_doc}, - {"writable", (PyCFunction)stringio_writable, METH_NOARGS, stringio_writable_doc}, + _IO_STRINGIO_SEEKABLE_METHODDEF + _IO_STRINGIO_READABLE_METHODDEF + _IO_STRINGIO_WRITABLE_METHODDEF {"__getstate__", (PyCFunction)stringio_getstate, METH_NOARGS}, {"__setstate__", (PyCFunction)stringio_setstate, METH_O}, @@ -1013,7 +1066,7 @@ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /*tp_flags*/ - stringio_doc, /*tp_doc*/ + _io_StringIO___init____doc__, /*tp_doc*/ (traverseproc)stringio_traverse, /*tp_traverse*/ (inquiry)stringio_clear, /*tp_clear*/ 0, /*tp_richcompare*/ @@ -1028,7 +1081,7 @@ 0, /*tp_descr_get*/ 0, /*tp_descr_set*/ offsetof(stringio, dict), /*tp_dictoffset*/ - (initproc)stringio_init, /*tp_init*/ + _io_StringIO___init__, /*tp_init*/ 0, /*tp_alloc*/ stringio_new, /*tp_new*/ }; diff --git a/Modules/_io/textio.c b/Modules/_io/textio.c --- a/Modules/_io/textio.c +++ b/Modules/_io/textio.c @@ -11,6 +11,20 @@ #include "structmember.h" #include "_iomodule.h" +/*[clinic input] +module _io +class _io.IncrementalNewlineDecoder "nldecoder_object *" "&PyIncrementalNewlineDecoder_Type" +class _io.TextIOWrapper "textio *" "&TextIOWrapper_TYpe" +[clinic start generated code]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=2097a4fc85670c26]*/ + +/*[python input] +class io_ssize_t_converter(CConverter): + type = 'Py_ssize_t' + converter = '_PyIO_ConvertSsize_t' +[python start generated code]*/ +/*[python end generated code: output=da39a3ee5e6b4b0d input=d0a811d3cbfd1b33]*/ + _Py_IDENTIFIER(close); _Py_IDENTIFIER(_dealloc_warn); _Py_IDENTIFIER(decode); @@ -210,16 +224,6 @@ /* IncrementalNewlineDecoder */ -PyDoc_STRVAR(incrementalnewlinedecoder_doc, - "Codec used when reading a file in universal newlines mode. It wraps\n" - "another incremental decoder, translating \\r\\n and \\r into \\n. It also\n" - "records the types of newlines encountered. When used with\n" - "translate=False, it ensures that the newline sequence is returned in\n" - "one piece. When used with decoder=None, it expects unicode strings as\n" - "decode input and translates newlines without first invoking an external\n" - "decoder.\n" - ); - typedef struct { PyObject_HEAD PyObject *decoder; @@ -229,19 +233,28 @@ unsigned int seennl: 3; } nldecoder_object; +/*[clinic input] +_io.IncrementalNewlineDecoder.__init__ + decoder: object + translate: int + errors: object(c_default="NULL") = "strict" + +Codec used when reading a file in universal newlines mode. + +It wraps another incremental decoder, translating \r\n and \r into \n. +It also records the types of newlines encountered. When used with +translate=False, it ensures that the newline sequence is returned in +one piece. When used with decoder=None, it expects unicode strings as +decode input and translates newlines without first invoking an external +decoder. +[clinic start generated code]*/ + static int -incrementalnewlinedecoder_init(nldecoder_object *self, - PyObject *args, PyObject *kwds) +_io_IncrementalNewlineDecoder___init___impl(nldecoder_object *self, + PyObject *decoder, int translate, + PyObject *errors) +/*[clinic end generated code: output=fbd04d443e764ec2 input=89db6b19c6b126bf]*/ { - PyObject *decoder; - int translate; - PyObject *errors = NULL; - char *kwlist[] = {"decoder", "translate", "errors", NULL}; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "Oi|O:IncrementalNewlineDecoder", - kwlist, &decoder, &translate, &errors)) - return -1; - self->decoder = decoder; Py_INCREF(decoder); @@ -495,22 +508,27 @@ return NULL; } +/*[clinic input] +_io.IncrementalNewlineDecoder.decode + input: object + final: int(c_default="0") = False +[clinic start generated code]*/ + static PyObject * -incrementalnewlinedecoder_decode(nldecoder_object *self, - PyObject *args, PyObject *kwds) +_io_IncrementalNewlineDecoder_decode_impl(nldecoder_object *self, + PyObject *input, int final) +/*[clinic end generated code: output=0d486755bb37a66e input=d65677385bfd6827]*/ { - char *kwlist[] = {"input", "final", NULL}; - PyObject *input; - int final = 0; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|i:IncrementalNewlineDecoder", - kwlist, &input, &final)) - return NULL; return _PyIncrementalNewlineDecoder_decode((PyObject *) self, input, final); } +/*[clinic input] +_io.IncrementalNewlineDecoder.getstate +[clinic start generated code]*/ + static PyObject * -incrementalnewlinedecoder_getstate(nldecoder_object *self, PyObject *args) +_io_IncrementalNewlineDecoder_getstate_impl(nldecoder_object *self) +/*[clinic end generated code: output=f0d2c9c136f4e0d0 input=f8ff101825e32e7f]*/ { PyObject *buffer; unsigned PY_LONG_LONG flag; @@ -537,8 +555,16 @@ return Py_BuildValue("NK", buffer, flag); } +/*[clinic input] +_io.IncrementalNewlineDecoder.setstate + state: object + / +[clinic start generated code]*/ + static PyObject * -incrementalnewlinedecoder_setstate(nldecoder_object *self, PyObject *state) +_io_IncrementalNewlineDecoder_setstate(nldecoder_object *self, + PyObject *state) +/*[clinic end generated code: output=c10c622508b576cb input=c53fb505a76dbbe2]*/ { PyObject *buffer; unsigned PY_LONG_LONG flag; @@ -556,8 +582,13 @@ Py_RETURN_NONE; } +/*[clinic input] +_io.IncrementalNewlineDecoder.reset +[clinic start generated code]*/ + static PyObject * -incrementalnewlinedecoder_reset(nldecoder_object *self, PyObject *args) +_io_IncrementalNewlineDecoder_reset_impl(nldecoder_object *self) +/*[clinic end generated code: output=32fa40c7462aa8ff input=728678ddaea776df]*/ { self->seennl = 0; self->pendingcr = 0; @@ -591,95 +622,8 @@ } - -static PyMethodDef incrementalnewlinedecoder_methods[] = { - {"decode", (PyCFunction)incrementalnewlinedecoder_decode, METH_VARARGS|METH_KEYWORDS}, - {"getstate", (PyCFunction)incrementalnewlinedecoder_getstate, METH_NOARGS}, - {"setstate", (PyCFunction)incrementalnewlinedecoder_setstate, METH_O}, - {"reset", (PyCFunction)incrementalnewlinedecoder_reset, METH_NOARGS}, - {NULL} -}; - -static PyGetSetDef incrementalnewlinedecoder_getset[] = { - {"newlines", (getter)incrementalnewlinedecoder_newlines_get, NULL, NULL}, - {NULL} -}; - -PyTypeObject PyIncrementalNewlineDecoder_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "_io.IncrementalNewlineDecoder", /*tp_name*/ - sizeof(nldecoder_object), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - (destructor)incrementalnewlinedecoder_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare */ - 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 | Py_TPFLAGS_BASETYPE, /*tp_flags*/ - incrementalnewlinedecoder_doc, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /*tp_weaklistoffset*/ - 0, /* tp_iter */ - 0, /* tp_iternext */ - incrementalnewlinedecoder_methods, /* tp_methods */ - 0, /* tp_members */ - incrementalnewlinedecoder_getset, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - (initproc)incrementalnewlinedecoder_init, /* tp_init */ - 0, /* tp_alloc */ - PyType_GenericNew, /* tp_new */ -}; - - /* TextIOWrapper */ -PyDoc_STRVAR(textiowrapper_doc, - "Character and line based layer over a BufferedIOBase object, buffer.\n" - "\n" - "encoding gives the name of the encoding that the stream will be\n" - "decoded or encoded with. It defaults to locale.getpreferredencoding(False).\n" - "\n" - "errors determines the strictness of encoding and decoding (see\n" - "help(codecs.Codec) or the documentation for codecs.register) and\n" - "defaults to \"strict\".\n" - "\n" - "newline controls how line endings are handled. It can be None, '',\n" - "'\\n', '\\r', and '\\r\\n'. It works as follows:\n" - "\n" - "* On input, if newline is None, universal newlines mode is\n" - " enabled. Lines in the input can end in '\\n', '\\r', or '\\r\\n', and\n" - " these are translated into '\\n' before being returned to the\n" - " caller. If it is '', universal newline mode is enabled, but line\n" - " endings are returned to the caller untranslated. If it has any of\n" - " the other legal values, input lines are only terminated by the given\n" - " string, and the line ending is returned to the caller untranslated.\n" - "\n" - "* On output, if newline is None, any '\\n' characters written are\n" - " translated to the system default line separator, os.linesep. If\n" - " newline is '' or '\\n', no translation takes place. If newline is any\n" - " of the other legal values, any '\\n' characters written are translated\n" - " to the given string.\n" - "\n" - "If line_buffering is True, a call to flush is implied when a call to\n" - "write contains a newline character." - ); - typedef PyObject * (*encodefunc_t)(PyObject *, PyObject *); @@ -742,7 +686,6 @@ PyObject *dict; } textio; - /* A couple of specialized cases in order to bypass the slow incremental encoding methods for the most popular encodings. */ @@ -843,28 +786,59 @@ }; +/*[clinic input] +_io.TextIOWrapper.__init__ + buffer: object + encoding: str(nullable=True) = NULL + errors: str(nullable=True) = NULL + newline: str(nullable=True) = NULL + line_buffering: int(c_default="0") = False + write_through: int(c_default="0") = False + +Character and line based layer over a BufferedIOBase object, buffer. + +encoding gives the name of the encoding that the stream will be +decoded or encoded with. It defaults to locale.getpreferredencoding(False). + +errors determines the strictness of encoding and decoding (see +help(codecs.Codec) or the documentation for codecs.register) and +defaults to "strict". + +newline controls how line endings are handled. It can be None, '', +'\n', '\r', and '\r\n'. It works as follows: + +* On input, if newline is None, universal newlines mode is + enabled. Lines in the input can end in '\n', '\r', or '\r\n', and + these are translated into '\n' before being returned to the + caller. If it is '', universal newline mode is enabled, but line + endings are returned to the caller untranslated. If it has any of + the other legal values, input lines are only terminated by the given + string, and the line ending is returned to the caller untranslated. + +* On output, if newline is None, any '\n' characters written are + translated to the system default line separator, os.linesep. If + newline is '' or '\n', no translation takes place. If newline is any + of the other legal values, any '\n' characters written are translated + to the given string. + +If line_buffering is True, a call to flush is implied when a call to +write contains a newline character. +[clinic start generated code]*/ + static int -textiowrapper_init(textio *self, PyObject *args, PyObject *kwds) +_io_TextIOWrapper___init___impl(textio *self, PyObject *buffer, + const char *encoding, const char *errors, + const char *newline, int line_buffering, + int write_through) +/*[clinic end generated code: output=56a83402ce2a8381 input=1f20decb8d54a4ec]*/ { - char *kwlist[] = {"buffer", "encoding", "errors", - "newline", "line_buffering", "write_through", - NULL}; - PyObject *buffer, *raw, *codec_info = NULL; - char *encoding = NULL; - char *errors = NULL; - char *newline = NULL; - int line_buffering = 0, write_through = 0; + PyObject *raw, *codec_info = NULL; _PyIO_State *state = NULL; - PyObject *res; int r; self->ok = 0; self->detached = 0; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|zzzii:fileio", - kwlist, &buffer, &encoding, &errors, - &newline, &line_buffering, &write_through)) - return -1; if (newline && newline[0] != '\0' && !(newline[0] == '\n' && newline[1] == '\0') @@ -1244,8 +1218,13 @@ } +/*[clinic input] +_io.TextIOWrapper.detach +[clinic start generated code]*/ + static PyObject * -textiowrapper_detach(textio *self) +_io_TextIOWrapper_detach_impl(textio *self) +/*[clinic end generated code: output=7ba3715cd032d5f2 input=e5a71fbda9e1d9f9]*/ { PyObject *buffer, *res; CHECK_ATTACHED(self); @@ -1290,25 +1269,26 @@ return 0; } +/*[clinic input] +_io.TextIOWrapper.write + text: unicode + / +[clinic start generated code]*/ + static PyObject * -textiowrapper_write(textio *self, PyObject *args) +_io_TextIOWrapper_write_impl(textio *self, PyObject *text) +/*[clinic end generated code: output=d2deb0d50771fcec input=fdf19153584a0e44]*/ { PyObject *ret; - PyObject *text; /* owned reference */ PyObject *b; Py_ssize_t textlen; int haslf = 0; int needflush = 0, text_needflush = 0; - CHECK_ATTACHED(self); - - if (!PyArg_ParseTuple(args, "U:write", &text)) { - return NULL; - } - if (PyUnicode_READY(text) == -1) return NULL; + CHECK_ATTACHED(self); CHECK_CLOSED(self); if (self->encoder == NULL) @@ -1557,17 +1537,19 @@ return -1; } +/*[clinic input] +_io.TextIOWrapper.read + size as n: io_ssize_t = -1 + / +[clinic start generated code]*/ + static PyObject * -textiowrapper_read(textio *self, PyObject *args) +_io_TextIOWrapper_read_impl(textio *self, Py_ssize_t n) +/*[clinic end generated code: output=7e651ce6cc6a25a6 input=8c09398424085cca]*/ { - Py_ssize_t n = -1; PyObject *result = NULL, *chunks = NULL; CHECK_ATTACHED(self); - - if (!PyArg_ParseTuple(args, "|O&:read", &_PyIO_ConvertSsize_t, &n)) - return NULL; - CHECK_CLOSED(self); if (self->decoder == NULL) @@ -1933,16 +1915,18 @@ return NULL; } +/*[clinic input] +_io.TextIOWrapper.readline + size: Py_ssize_t = -1 + / +[clinic start generated code]*/ + static PyObject * -textiowrapper_readline(textio *self, PyObject *args) +_io_TextIOWrapper_readline_impl(textio *self, Py_ssize_t size) +/*[clinic end generated code: output=344afa98804e8b25 input=56c7172483b36db6]*/ { - Py_ssize_t limit = -1; - CHECK_ATTACHED(self); - if (!PyArg_ParseTuple(args, "|n:readline", &limit)) { - return NULL; - } - return _textiowrapper_readline(self, limit); + return _textiowrapper_readline(self, size); } /* Seek and Tell */ @@ -2074,19 +2058,23 @@ self, cookie->start_pos == 0 && cookie->dec_flags == 0); } +/*[clinic input] +_io.TextIOWrapper.seek + cookie as cookieObj: object + whence: int = 0 + / +[clinic start generated code]*/ + static PyObject * -textiowrapper_seek(textio *self, PyObject *args) +_io_TextIOWrapper_seek_impl(textio *self, PyObject *cookieObj, int whence) +/*[clinic end generated code: output=0a15679764e2d04d input=0458abeb3d7842be]*/ { - PyObject *cookieObj, *posobj; + PyObject *posobj; cookie_type cookie; - int whence = 0; PyObject *res; int cmp; CHECK_ATTACHED(self); - - if (!PyArg_ParseTuple(args, "O|i:seek", &cookieObj, &whence)) - return NULL; CHECK_CLOSED(self); Py_INCREF(cookieObj); @@ -2258,8 +2246,13 @@ } +/*[clinic input] +_io.TextIOWrapper.tell +[clinic start generated code]*/ + static PyObject * -textiowrapper_tell(textio *self, PyObject *args) +_io_TextIOWrapper_tell_impl(textio *self) +/*[clinic end generated code: output=4f168c08bf34ad5f input=9a2caf88c24f9ddf]*/ { PyObject *res; PyObject *posobj = NULL; @@ -2466,16 +2459,19 @@ return NULL; } +/*[clinic input] +_io.TextIOWrapper.truncate + pos: object = None + / +[clinic start generated code]*/ + static PyObject * -textiowrapper_truncate(textio *self, PyObject *args) +_io_TextIOWrapper_truncate_impl(textio *self, PyObject *pos) +/*[clinic end generated code: output=90ec2afb9bb7745f input=56ec8baa65aea377]*/ { - PyObject *pos = Py_None; PyObject *res; CHECK_ATTACHED(self) - if (!PyArg_ParseTuple(args, "|O:truncate", &pos)) { - return NULL; - } res = PyObject_CallMethodObjArgs((PyObject *) self, _PyIO_str_flush, NULL); if (res == NULL) @@ -2540,36 +2536,61 @@ /* Inquiries */ +/*[clinic input] +_io.TextIOWrapper.fileno +[clinic start generated code]*/ + static PyObject * -textiowrapper_fileno(textio *self, PyObject *args) +_io_TextIOWrapper_fileno_impl(textio *self) +/*[clinic end generated code: output=21490a4c3da13e6c input=c488ca83d0069f9b]*/ { CHECK_ATTACHED(self); return _PyObject_CallMethodId(self->buffer, &PyId_fileno, NULL); } +/*[clinic input] +_io.TextIOWrapper.seekable +[clinic start generated code]*/ + static PyObject * -textiowrapper_seekable(textio *self, PyObject *args) +_io_TextIOWrapper_seekable_impl(textio *self) +/*[clinic end generated code: output=ab223dbbcffc0f00 input=8b005ca06e1fca13]*/ { CHECK_ATTACHED(self); return _PyObject_CallMethodId(self->buffer, &PyId_seekable, NULL); } +/*[clinic input] +_io.TextIOWrapper.readable +[clinic start generated code]*/ + static PyObject * -textiowrapper_readable(textio *self, PyObject *args) +_io_TextIOWrapper_readable_impl(textio *self) +/*[clinic end generated code: output=72ff7ba289a8a91b input=0704ea7e01b0d3eb]*/ { CHECK_ATTACHED(self); return _PyObject_CallMethodId(self->buffer, &PyId_readable, NULL); } +/*[clinic input] +_io.TextIOWrapper.writable +[clinic start generated code]*/ + static PyObject * -textiowrapper_writable(textio *self, PyObject *args) +_io_TextIOWrapper_writable_impl(textio *self) +/*[clinic end generated code: output=a728c71790d03200 input=c41740bc9d8636e8]*/ { CHECK_ATTACHED(self); return _PyObject_CallMethodId(self->buffer, &PyId_writable, NULL); } +/*[clinic input] +_io.TextIOWrapper.isatty +[clinic start generated code]*/ + static PyObject * -textiowrapper_isatty(textio *self, PyObject *args) +_io_TextIOWrapper_isatty_impl(textio *self) +/*[clinic end generated code: output=12be1a35bace882e input=fb68d9f2c99bbfff]*/ { CHECK_ATTACHED(self); return _PyObject_CallMethodId(self->buffer, &PyId_isatty, NULL); @@ -2583,8 +2604,13 @@ return NULL; } +/*[clinic input] +_io.TextIOWrapper.flush +[clinic start generated code]*/ + static PyObject * -textiowrapper_flush(textio *self, PyObject *args) +_io_TextIOWrapper_flush_impl(textio *self) +/*[clinic end generated code: output=59de9165f9c2e4d2 input=928c60590694ab85]*/ { CHECK_ATTACHED(self); CHECK_CLOSED(self); @@ -2594,8 +2620,13 @@ return _PyObject_CallMethodId(self->buffer, &PyId_flush, NULL); } +/*[clinic input] +_io.TextIOWrapper.close +[clinic start generated code]*/ + static PyObject * -textiowrapper_close(textio *self, PyObject *args) +_io_TextIOWrapper_close_impl(textio *self) +/*[clinic end generated code: output=056ccf8b4876e4f4 input=9c2114315eae1948]*/ { PyObject *res; int r; @@ -2739,24 +2770,81 @@ return 0; } +#include "clinic/textio.c.h" + +static PyMethodDef incrementalnewlinedecoder_methods[] = { + _IO_INCREMENTALNEWLINEDECODER_DECODE_METHODDEF + _IO_INCREMENTALNEWLINEDECODER_GETSTATE_METHODDEF + _IO_INCREMENTALNEWLINEDECODER_SETSTATE_METHODDEF + _IO_INCREMENTALNEWLINEDECODER_RESET_METHODDEF + {NULL} +}; + +static PyGetSetDef incrementalnewlinedecoder_getset[] = { + {"newlines", (getter)incrementalnewlinedecoder_newlines_get, NULL, NULL}, + {NULL} +}; + +PyTypeObject PyIncrementalNewlineDecoder_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "_io.IncrementalNewlineDecoder", /*tp_name*/ + sizeof(nldecoder_object), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + (destructor)incrementalnewlinedecoder_dealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare */ + 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 | Py_TPFLAGS_BASETYPE, /*tp_flags*/ + _io_IncrementalNewlineDecoder___init____doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /*tp_weaklistoffset*/ + 0, /* tp_iter */ + 0, /* tp_iternext */ + incrementalnewlinedecoder_methods, /* tp_methods */ + 0, /* tp_members */ + incrementalnewlinedecoder_getset, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + _io_IncrementalNewlineDecoder___init__, /* tp_init */ + 0, /* tp_alloc */ + PyType_GenericNew, /* tp_new */ +}; + + static PyMethodDef textiowrapper_methods[] = { - {"detach", (PyCFunction)textiowrapper_detach, METH_NOARGS}, - {"write", (PyCFunction)textiowrapper_write, METH_VARARGS}, - {"read", (PyCFunction)textiowrapper_read, METH_VARARGS}, - {"readline", (PyCFunction)textiowrapper_readline, METH_VARARGS}, - {"flush", (PyCFunction)textiowrapper_flush, METH_NOARGS}, - {"close", (PyCFunction)textiowrapper_close, METH_NOARGS}, + _IO_TEXTIOWRAPPER_DETACH_METHODDEF + _IO_TEXTIOWRAPPER_WRITE_METHODDEF + _IO_TEXTIOWRAPPER_READ_METHODDEF + _IO_TEXTIOWRAPPER_READLINE_METHODDEF + _IO_TEXTIOWRAPPER_FLUSH_METHODDEF + _IO_TEXTIOWRAPPER_CLOSE_METHODDEF - {"fileno", (PyCFunction)textiowrapper_fileno, METH_NOARGS}, - {"seekable", (PyCFunction)textiowrapper_seekable, METH_NOARGS}, - {"readable", (PyCFunction)textiowrapper_readable, METH_NOARGS}, - {"writable", (PyCFunction)textiowrapper_writable, METH_NOARGS}, - {"isatty", (PyCFunction)textiowrapper_isatty, METH_NOARGS}, + _IO_TEXTIOWRAPPER_FILENO_METHODDEF + _IO_TEXTIOWRAPPER_SEEKABLE_METHODDEF + _IO_TEXTIOWRAPPER_READABLE_METHODDEF + _IO_TEXTIOWRAPPER_WRITABLE_METHODDEF + _IO_TEXTIOWRAPPER_ISATTY_METHODDEF {"__getstate__", (PyCFunction)textiowrapper_getstate, METH_NOARGS}, - {"seek", (PyCFunction)textiowrapper_seek, METH_VARARGS}, - {"tell", (PyCFunction)textiowrapper_tell, METH_NOARGS}, - {"truncate", (PyCFunction)textiowrapper_truncate, METH_VARARGS}, + _IO_TEXTIOWRAPPER_SEEK_METHODDEF + _IO_TEXTIOWRAPPER_TELL_METHODDEF + _IO_TEXTIOWRAPPER_TRUNCATE_METHODDEF {NULL, NULL} }; @@ -2802,7 +2890,7 @@ 0, /*tp_as_buffer*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_FINALIZE, /*tp_flags*/ - textiowrapper_doc, /* tp_doc */ + _io_TextIOWrapper___init____doc__, /* tp_doc */ (traverseproc)textiowrapper_traverse, /* tp_traverse */ (inquiry)textiowrapper_clear, /* tp_clear */ 0, /* tp_richcompare */ @@ -2817,7 +2905,7 @@ 0, /* tp_descr_get */ 0, /* tp_descr_set */ offsetof(textio, dict), /*tp_dictoffset*/ - (initproc)textiowrapper_init, /* tp_init */ + _io_TextIOWrapper___init__, /* tp_init */ 0, /* tp_alloc */ PyType_GenericNew, /* tp_new */ 0, /* tp_free */ -- Repository URL: https://hg.python.org/cpython From solipsis at pitrou.net Thu Apr 16 10:46:43 2015 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Thu, 16 Apr 2015 08:46:43 +0000 Subject: [Python-checkins] Daily reference leaks (4f74452a11e5): sum=9 Message-ID: <20150416084642.43333.98588@psf.io> results for 4f74452a11e5 on branch "default" -------------------------------------------- test_collections leaked [0, 0, 4] references, sum=4 test_collections leaked [0, 0, 2] memory blocks, sum=2 test_functools leaked [0, 0, 3] memory blocks, sum=3 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflog6667o4', '--timeout', '7200'] From python-checkins at python.org Thu Apr 16 10:58:57 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Thu, 16 Apr 2015 08:58:57 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Null_merge?= Message-ID: <20150416085857.31107.82687@psf.io> https://hg.python.org/cpython/rev/4e81b20e7a57 changeset: 95689:4e81b20e7a57 parent: 95686:49007ed1a1a5 parent: 95687:2d8e4047c270 user: Serhiy Storchaka date: Thu Apr 16 11:58:11 2015 +0300 summary: Null merge files: -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Apr 16 10:58:57 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Thu, 16 Apr 2015 08:58:57 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E4=29=3A_Backported_tes?= =?utf-8?q?ts_from_issue_=2320175=2E?= Message-ID: <20150416085857.31119.2826@psf.io> https://hg.python.org/cpython/rev/2d8e4047c270 changeset: 95687:2d8e4047c270 branch: 3.4 parent: 95663:d0819a8fda1b user: Serhiy Storchaka date: Thu Apr 16 11:54:14 2015 +0300 summary: Backported tests from issue #20175. files: Lib/test/test_fileio.py | 15 ++++++++++++--- Lib/test/test_io.py | 11 +++++++++++ 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/Lib/test/test_fileio.py b/Lib/test/test_fileio.py --- a/Lib/test/test_fileio.py +++ b/Lib/test/test_fileio.py @@ -126,9 +126,9 @@ self.assertTrue(f.closed) def testMethods(self): - methods = ['fileno', 'isatty', 'read', 'readinto', - 'seek', 'tell', 'truncate', 'write', 'seekable', - 'readable', 'writable'] + methods = ['fileno', 'isatty', 'seekable', 'readable', 'writable', + 'read', 'readall', 'readline', 'readlines', + 'tell', 'truncate', 'flush'] self.f.close() self.assertTrue(self.f.closed) @@ -138,6 +138,15 @@ # should raise on closed file self.assertRaises(ValueError, method) + self.assertRaises(ValueError, self.f.readinto) # XXX should be TypeError? + self.assertRaises(ValueError, self.f.readinto, bytearray(1)) + self.assertRaises(ValueError, self.f.seek) + self.assertRaises(ValueError, self.f.seek, 0) + self.assertRaises(ValueError, self.f.write) + self.assertRaises(ValueError, self.f.write, b'') + self.assertRaises(TypeError, self.f.writelines) + self.assertRaises(ValueError, self.f.writelines, b'') + def testOpendir(self): # Issue 3703: opening a directory should fill the errno # Windows always returns "[Errno 13]: Permission denied diff --git a/Lib/test/test_io.py b/Lib/test/test_io.py --- a/Lib/test/test_io.py +++ b/Lib/test/test_io.py @@ -2087,6 +2087,17 @@ self.assertRaises(TypeError, t.__init__, b, newline=42) self.assertRaises(ValueError, t.__init__, b, newline='xyzzy') + def test_uninitialized(self): + t = self.TextIOWrapper.__new__(self.TextIOWrapper) + del t + t = self.TextIOWrapper.__new__(self.TextIOWrapper) + self.assertRaises(Exception, repr, t) + self.assertRaisesRegex((ValueError, AttributeError), + 'uninitialized|has no attribute', + t.read, 0) + t.__init__(self.MockRawIO()) + self.assertEqual(t.read(0), '') + def test_non_text_encoding_codecs_are_rejected(self): # Ensure the constructor complains if passed a codec that isn't # marked as a text encoding -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Apr 16 10:58:57 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Thu, 16 Apr 2015 08:58:57 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_Backported_tes?= =?utf-8?q?ts_from_issue_=2320175=2E?= Message-ID: <20150416085857.74162.17569@psf.io> https://hg.python.org/cpython/rev/867c509c8c5e changeset: 95688:867c509c8c5e branch: 2.7 parent: 95675:5576c8240963 user: Serhiy Storchaka date: Thu Apr 16 11:56:35 2015 +0300 summary: Backported tests from issue #20175. files: Lib/test/test_fileio.py | 15 ++++++++++++--- Lib/test/test_io.py | 11 +++++++++++ 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/Lib/test/test_fileio.py b/Lib/test/test_fileio.py --- a/Lib/test/test_fileio.py +++ b/Lib/test/test_fileio.py @@ -125,9 +125,9 @@ self.assertTrue(f.closed) def testMethods(self): - methods = ['fileno', 'isatty', 'read', 'readinto', - 'seek', 'tell', 'truncate', 'write', 'seekable', - 'readable', 'writable'] + methods = ['fileno', 'isatty', 'seekable', 'readable', 'writable', + 'read', 'readall', 'readline', 'readlines', + 'tell', 'truncate', 'flush'] if sys.platform.startswith('atheos'): methods.remove('truncate') @@ -139,6 +139,15 @@ # should raise on closed file self.assertRaises(ValueError, method) + self.assertRaises(ValueError, self.f.readinto) # XXX should be TypeError? + self.assertRaises(ValueError, self.f.readinto, bytearray(1)) + self.assertRaises(ValueError, self.f.seek) + self.assertRaises(ValueError, self.f.seek, 0) + self.assertRaises(ValueError, self.f.write) + self.assertRaises(ValueError, self.f.write, b'') + self.assertRaises(TypeError, self.f.writelines) + self.assertRaises(ValueError, self.f.writelines, b'') + def testOpendir(self): # Issue 3703: opening a directory should fill the errno # Windows always returns "[Errno 13]: Permission denied diff --git a/Lib/test/test_io.py b/Lib/test/test_io.py --- a/Lib/test/test_io.py +++ b/Lib/test/test_io.py @@ -1990,6 +1990,17 @@ self.assertRaises(TypeError, t.__init__, b, newline=42) self.assertRaises(ValueError, t.__init__, b, newline='xyzzy') + def test_uninitialized(self): + t = self.TextIOWrapper.__new__(self.TextIOWrapper) + del t + t = self.TextIOWrapper.__new__(self.TextIOWrapper) + self.assertRaises(Exception, repr, t) + self.assertRaisesRegexp((ValueError, AttributeError), + 'uninitialized|has no attribute', + t.read, 0) + t.__init__(self.MockRawIO()) + self.assertEqual(t.read(0), u'') + def test_detach(self): r = self.BytesIO() b = self.BufferedWriter(r) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Apr 16 17:22:03 2015 From: python-checkins at python.org (christian.heimes) Date: Thu, 16 Apr 2015 15:22:03 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Fix_typo_in_assert_stateme?= =?utf-8?q?nt?= Message-ID: <20150416152203.101218.8888@psf.io> https://hg.python.org/cpython/rev/743c54a2830f changeset: 95690:743c54a2830f user: Christian Heimes date: Thu Apr 16 17:21:54 2015 +0200 summary: Fix typo in assert statement files: Modules/_io/fileio.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Modules/_io/fileio.c b/Modules/_io/fileio.c --- a/Modules/_io/fileio.c +++ b/Modules/_io/fileio.c @@ -252,7 +252,7 @@ struct _Py_stat_struct fdfstat; int async_err = 0; - assert(PyFileIO_Check(oself)); + assert(PyFileIO_Check(self)); if (self->fd >= 0) { if (self->closefd) { /* Have to close the existing file first. */ -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Apr 16 17:26:38 2015 From: python-checkins at python.org (christian.heimes) Date: Thu, 16 Apr 2015 15:26:38 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Remove_redundant_check_for?= =?utf-8?q?_tb_!=3D_NULL_to_shut_up_Coverity_=2E_It_has_been_set_to?= Message-ID: <20150416152637.6603.39336@psf.io> https://hg.python.org/cpython/rev/075f8aab52b3 changeset: 95691:075f8aab52b3 user: Christian Heimes date: Thu Apr 16 17:25:45 2015 +0200 summary: Remove redundant check for tb != NULL to shut up Coverity . It has been set to Py_None a couple of lines earlier. CID 1291697 (#1 of 1): Dereference before null check (REVERSE_INULL) check_after_deref: Null-checking tb suggests that it may be null, but it has already been dereferenced on all paths leading to the check. files: Python/pylifecycle.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -1283,7 +1283,7 @@ goto display_stack; } - has_tb = (tb != NULL && tb != Py_None); + has_tb = (tb != Py_None); PyErr_Display(exception, v, tb); Py_XDECREF(exception); Py_XDECREF(v); -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Apr 16 17:29:26 2015 From: python-checkins at python.org (christian.heimes) Date: Thu, 16 Apr 2015 15:29:26 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Remove_redundant_check_fro?= =?utf-8?q?_md5module=2E?= Message-ID: <20150416152926.6589.15124@psf.io> https://hg.python.org/cpython/rev/5612dc5e6af9 changeset: 95692:5612dc5e6af9 user: Christian Heimes date: Thu Apr 16 17:29:11 2015 +0200 summary: Remove redundant check fro md5module. CID 1294331 (#1 of 1): Identical code for different branches (IDENTICAL_BRANCHES) files: Modules/md5module.c | 9 ++------- 1 files changed, 2 insertions(+), 7 deletions(-) diff --git a/Modules/md5module.c b/Modules/md5module.c --- a/Modules/md5module.c +++ b/Modules/md5module.c @@ -350,13 +350,8 @@ { MD5object *newobj; - if (Py_TYPE(self) == &MD5type) { - if ( (newobj = newMD5object())==NULL) - return NULL; - } else { - if ( (newobj = newMD5object())==NULL) - return NULL; - } + if ((newobj = newMD5object())==NULL) + return NULL; newobj->hash_state = self->hash_state; return (PyObject *)newobj; -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Apr 16 17:49:42 2015 From: python-checkins at python.org (berker.peksag) Date: Thu, 16 Apr 2015 15:49:42 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_PEP_489=3A_Updates_from_Petr_?= =?utf-8?q?Viktorin=2E?= Message-ID: <20150416154939.21329.88270@psf.io> https://hg.python.org/peps/rev/923f53842cc5 changeset: 5758:923f53842cc5 user: Berker Peksag date: Thu Apr 16 18:49:43 2015 +0300 summary: PEP 489: Updates from Petr Viktorin. files: pep-0489.txt | 650 +++++++++++++++++++++++++------------- 1 files changed, 424 insertions(+), 226 deletions(-) diff --git a/pep-0489.txt b/pep-0489.txt --- a/pep-0489.txt +++ b/pep-0489.txt @@ -11,7 +11,7 @@ Content-Type: text/x-rst Created: 11-Aug-2013 Python-Version: 3.5 -Post-History: 23-Aug-2013, 20-Feb-2015 +Post-History: 23-Aug-2013, 20-Feb-2015, 16-Apr-2015 Resolution: @@ -25,19 +25,20 @@ specifically to hook into the ModuleSpec-based loading mechanism introduced in PEP 451. -Extensions that do not require custom memory layout for their module objects -may be executed in arbitrary pre-defined namespaces, paving the way for -extension modules being runnable with Python's ``-m`` switch. -Other extensions can use custom types for their module implementation. -Module types are no longer restricted to types.ModuleType. +This proposal draws inspiration from PyType_Spec of PEP 384 to allow extension +authors to only define features they need, and to allow future additions +to extension module declarations. -This proposal makes it easy to support properties at the module -level and to safely store arbitrary global state in the module that is -covered by normal garbage collection and supports reloading and -sub-interpreters. +Extensions modules are created in a two-step process, fitting better into +the ModuleSpec architecture, with parallels to __new__ and __init__ of classes. + +Extension modules can safely store arbitrary C-level per-module state in +the module that is covered by normal garbage collection and supports +reloading and sub-interpreters. Extension authors are encouraged to take these issues into account when using the new API. +The proposal also allows extension modules with non-ASCII names. Motivation @@ -48,55 +49,47 @@ code is being executed (PEP 302). A ModuleSpec object (PEP 451) is used to hold information about the module, and passed to the relevant hooks. + For extensions, i.e. shared libraries, the module init function is executed straight away and does both the creation and -initialisation. The initialisation function is not passed ModuleSpec -information about the loaded module, such as the __file__ or fully-qualified +initialization. The initialization function is not passed the ModuleSpec, +or any information it contains, such as the __file__ or fully-qualified name. This hinders relative imports and resource loading. +In Py3, modules are also not being added to sys.modules, which means that a +(potentially transitive) re-import of the module will really try to re-import +it and thus run into an infinite loop when it executes the module init function +again. Without the FQMN, it is not trivial to correctly add the module to +sys.modules either. This is specifically a problem for Cython generated modules, for which it's not uncommon that the module init code has the same level of complexity as that of any 'regular' Python module. Also, the lack of __file__ and __name__ -information hinders the compilation of __init__.py modules, i.e. packages, +information hinders the compilation of "__init__.py" modules, i.e. packages, especially when relative imports are being used at module init time. -The other disadvantage of the discrepancy is that existing Python programmers -learning C cannot effectively map concepts between the two domains. -As long as extension modules are fundamentally different from pure Python ones -in the way they're initialised, they are harder for people to pick up without -relying on something like cffi, SWIG or Cython to handle the actual extension -module creation. - -Currently, extension modules are also not added to sys.modules until they are -fully initialized, which means that a (potentially transitive) -re-import of the module will really try to reimport it and thus run into an -infinite loop when it executes the module init function again. -Without the fully qualified module name, it is not trivial to correctly add -the module to sys.modules either. - Furthermore, the majority of currently existing extension modules has -problems with sub-interpreter support and/or reloading, and, while it is -possible with the current infrastructure to support these +problems with sub-interpreter support and/or interpreter reloading, and, while +it is possible with the current infrastructure to support these features, it is neither easy nor efficient. Addressing these issues was the goal of PEP 3121, but many extensions, including some in the standard library, took the least-effort approach to porting to Python 3, leaving these issues unresolved. -This PEP keeps the backwards-compatible behavior, which should reduce pressure -and give extension authors adequate time to consider these issues when porting. +This PEP keeps backwards compatibility, which should reduce pressure and give +extension authors adequate time to consider these issues when porting. The current process =================== -Currently, extension modules export an initialisation function named +Currently, extension modules export an initialization function named "PyInit_modulename", named after the file name of the shared library. This function is executed by the import machinery and must return either NULL in -the case of an exception, or a fully initialised module object. The +the case of an exception, or a fully initialized module object. The function receives no arguments, so it has no way of knowing about its import context. During its execution, the module init function creates a module object -based on a PyModuleDef struct. It then continues to initialise it by adding +based on a PyModuleDef struct. It then continues to initialize it by adding attributes to the module dict, creating types, etc. In the back, the shared library loader keeps a note of the fully qualified @@ -110,192 +103,241 @@ The proposal ============ -The current extension module initialisation will be deprecated in favour of -a new initialisation scheme. Since the current scheme will continue to be +The current extension module initialization will be deprecated in favor of +a new initialization scheme. Since the current scheme will continue to be available, existing code will continue to work unchanged, including binary compatibility. -Extension modules that support the new initialisation scheme must export -the public symbol "PyModuleExec_modulename", and optionally -"PyModuleCreate_modulename", where "modulename" is the -name of the module. This mimics the previous naming convention for -the "PyInit_modulename" function. +Extension modules that support the new initialization scheme must export +the public symbol "PyModuleExport_", where "modulename" +is the name of the module. (For modules with non-ASCII names the symbol name +is slightly different, see "Export Hook Name" below.) -If defined, these symbols must resolve to C functions with the following -signatures, respectively:: +If defined, this symbol must resolve to a C function with the following +signature:: + + PyModuleExport* (*PyModuleExportFunction)(void) + +The function must return a pointer to a PyModuleExport structure. +This structure must be available for the lifetime of the module created from +it ? usually, it will be declared statically. + +The PyModuleExport structure describes the new module, similarly to +PEP 384's PyType_Spec for types. The structure is defined as:: + + typedef struct { + int slot; + void *value; + } PyModuleDesc_Slot; + + typedef struct { + const char* doc; + int flags; + PyModuleDesc_Slot *slots; + } PyModuleDesc; + +The *doc* member specifies the module's docstring. + +The *flags* may currently be either 0 or ``PyModule_EXPORT_SINGLETON``, described +in "Singleton Modules" below. +Other flag values may be added in the future. + +The *slots* points to an array of PyModuleDesc_Slot structures, terminated +by a slot with id set to 0 (i.e. ``{0, NULL}``). + +To specify a slot, a unique slot ID must be provided. +New Python versions may introduce new slot IDs, but slot IDs will never be +recycled. Slots may get deprecated, but will continue to be supported +throughout Python 3.x. + +A slot's value pointer may not be NULL, unless specified otherwise in the +slot's documentation. + +The following slots are available, and described later: + +* Py_mod_create +* Py_mod_statedef +* Py_mod_methods +* Py_mod_exec + +Unknown slot IDs will cause the import to fail with ImportError. + +.. note:: + + An alternate proposal is to use PyModuleDef instead of PyModuleDesc, + re-purposing the m_reload pointer to hold the slots:: + + typedef struct PyModuleDef { + PyModuleDef_Base m_base; + const char* m_name; + const char* m_doc; + Py_ssize_t m_size; + PyMethodDef *m_methods; + PyModuleDesc_Slot* m_slots; /* changed from `inquiry m_reload;` */ + traverseproc m_traverse; + inquiry m_clear; + freefunc m_free; + } PyModuleDef; + + This would simplify both the implementation and the API, at the expense + of renaming a member of PyModuleDef, and re-purposing a function pointer as + a data pointer. + + +Creation Slots +-------------- + +The following slots affect module creation phase, i.e. they are hooks for +ExecutionLoader.create_module. +They serve to describe creation of the module object itself. + +Py_mod_create +............. + +The Py_mod_create slot is used to support custom module subclasses. +The value pointer must point to a function with the following signature:: + + PyObject* (*PyModuleCreateFunction)(PyObject *spec, PyModuleDesc *desc) + +The function receives a ModuleSpec instance, as defined in PEP 451, +and the PyModuleDesc structure. +It should return a new module object, or set an error +and return NULL. + +This function is not responsible for setting import-related attributes +specified in PEP 451 [#pep-0451-attributes]_ (such as ``__name__`` or +``__loader__``) on the new module. + +There is no requirement for the returned object to be an instance of +types.ModuleType. Any type can be used, as long as it supports setting and +getting attributes, including at least the import-related attributes. + +If a module instance is returned from Py_mod_create, the import machinery will +store a pointer to PyModuleDesc in the module object so that it may be +retrieved by PyModule_GetDesc (described later). + +.. note:: + + If PyModuleDef is used instead of PyModuleDesc, the def is stored + instead, to be retrieved by PyModule_GetDef. + +Note that when this function is called, the module's entry in sys.modules +is not populated yet. Attempting to import the same module again +(possibly transitively), may lead to an infinite loop. +Extension authors are advised to keep Py_mod_create minimal, an in particular +to not call user code from it. + +Multiple Py_mod_create slots may not be specified. If they are, import +will fail with ImportError. + + +Py_mod_statedef +............... + +The Py_mod_statedef slot is used to allocate per-module storage for C-level +state. +The value pointer must point to the following structure:: + + typedef struct PyModule_StateDef { + int size; + traverseproc traverse; + inquiry clear; + freefunc free; + } PyModule_StateDef; + +The meaning of the members is the same as for the corresponding members in +PyModuleDef. + +Specifying multiple Py_mod_statedef slots, or specifying Py_mod_statedef +together with Py_mod_create, will cause the import to fail with ImportError. + +.. note:: + + If PyModuleDef is reused, this information is taken from PyModuleDef, + so the slot is not necessary. + + +Execution slots +--------------- + +The following slots affect module "execution" phase, i.e. they are processed in +ExecutionLoader.exec_module. +They serve to describe how the module is initialized ? e.g. how it is populated +with functions, types, or constants, and what import-time side effects +take place. + +These slots may be specified multiple times, and are processed in the order +they appear in the slots array. + +When using the default import machinery, these slots are processed after +import-related attributes specified in PEP 451 [#pep-0451-attributes]_ +(such as ``__name__`` or ``__loader__``) are set and the module is added +to sys.modules. + + +Py_mod_methods +.............. + +This slot's value pointer must point to an array of PyMethodDef structures. +The specified methods are added to the module, like with PyModuleDef.m_methods. + +.. note:: + + If PyModuleDef is reused this slot is unnecessary, since methods are + already included in PyModuleDef. + + +Py_mod_exec +........... + +The function in this slot must have the signature:: int (*PyModuleExecFunction)(PyObject* module) - PyObject* (*PyModuleCreateFunction)(PyObject* module_spec) +It will be called to initialize a module. Usually, this amounts to +setting the module's initial attributes. -The PyModuleExec function -------------------------- +The "module" argument receives the module object to initialize. This will +always be the module object created from the corresponding PyModuleDesc. +When this function is called, import-related attributes (such as ``__spec__``) +will have been set, and the module has already been added to sys.modules. -The PyModuleExec function is used to implement "loader.exec_module" -defined in PEP 451. - -It function will be called to initialize a module. (Usually, this amounts to -setting the module's initial attributes.) -This happens in two situations: when the module is first initialized for -a given (sub-)interpreter, and possibly later when the module is reloaded. - -When PyModuleExec is called, the module has already been added to -sys.modules, and import-related attributes specified in -PEP 451 [#pep-0451-attributes]_) have been set on the module. - -The "module" argument receives the module object to initialize. - -If PyModuleCreate is defined, "module" will generally be the the object -returned by it. -It is possible for a custom loader to pass any object to -PyModuleExec, so this function should check and fail with TypeError -if the module's type is unsupported. -Any other assumptions should also be checked. - -If PyModuleCreate is not defined, PyModuleExec is expected to operate -on any Python object for which attributes can be added by PyObject_GetAttr* -and retrieved by PyObject_SetAttr*. -This allows loading an extension into a pre-created module, making it possible -to run it as __main__ in the future, participate in certain lazy-loading -schemes [#lazy_import_concerns]_, or enable other creative uses. If PyModuleExec replaces the module's entry in sys.modules, the new object will be used and returned by importlib machinery. (This mirrors the behavior of Python modules. Note that for extensions, -implementing PyModuleCreate is usually a better solution for the use cases +implementing Py_mod_create is usually a better solution for the use cases this serves.) The function must return ``0`` on success, or, on error, set an exception and return ``-1``. -The PyModuleCreate function ---------------------------- - -The optional PyModuleCreate function is used to implement -"loader.create_module" defined in PEP 451. -By exporting it, an extension module indicates that it uses a custom -module object. -This prevents loading the extension in a pre-created module, -but gives greater flexibility in allowing a custom C-level layout -of the module object. -Most extensions will not need to implement this function. - -The "module_spec" argument receives a "ModuleSpec" instance, as defined in -PEP 451. - -When called, this function must create and return a module object, -or set an exception and return NULL. -There is no requirement for the returned object to be an instance of -types.ModuleType. Any type can be used, as long as it supports setting and -getting attributes, including at least the import-related attributes -specified in PEP 451 [#pep-0451-attributes]_. -This follows the current support for allowing arbitrary objects in sys.modules -and makes it easier for extension modules to define a type that exactly matches -their needs for holding module state. - -Note that when this function is called, the module's entry in sys.modules -is not populated yet. Attempting to import the same module again -(possibly transitively), may lead to an infinite loop. -Extension authors are advised to keep PyModuleCreate minimal, an in particular -to not call user code from it. - -If PyModuleCreate is not defined, the default loader will construct -a module object as if with PyModule_New. - - -Initialization helper functions -------------------------------- - -For two initialization tasks previously done by PyModule_Create, -two functions are introduced:: - - int PyModule_SetDocString(PyObject *m, const char *doc) - int PyModule_AddFunctions(PyObject *m, PyMethodDef *functions) - -These set the module docstring, and add the module functions, respectively. -Both will work on any Python object that supports setting attributes. -They return ``0`` on success, and on failure, they set the exception -and return ``-1``. - - -PyCapsule convenience functions -------------------------------- - -Instead of custom module objects, PyCapsule will become the preferred -mechanism for storing per-module C data. -Two new convenience functions will be added to help with this. - -* - :: - - PyObject *PyModule_AddCapsule( - PyObject *module, - const char *module_name, - const char *attribute_name, - void *pointer, - PyCapsule_Destructor destructor) - - Add a new PyCapsule to *module* as *attribute_name*. - The capsule name is formed by joining *module_name* and *attribute_name* - by a dot. - - This convenience function can be used from a module initialization function - instead of separate calls to PyCapsule_New and PyModule_AddObject. - - Returns a borrowed reference to the new capsule, - or NULL (with exception set) on failure. - -* - :: - - void *PyModule_GetCapsulePointer( - PyObject *module, - const char *module_name, - const char *attribute_name) - - Returns the pointer stored in *module* as *attribute_name*, or NULL - (with an exception set) on failure. The capsule name is formed by joining - *module_name* and *attribute_name* by a dot. - - This convenience function can be used instead of separate calls to - PyObject_GetAttr and PyCapsule_GetPointer. - -Extension authors are encouraged to define a macro to -call PyModule_GetCapsulePointer and cast the result to an appropriate type. - - -Generalizing PyModule_* functions ---------------------------------- - -The following functions and macros will be modified to work on any object -that supports attribute access: - - * PyModule_GetNameObject - * PyModule_GetName - * PyModule_GetFilenameObject - * PyModule_GetFilename - * PyModule_AddIntConstant - * PyModule_AddStringConstant - * PyModule_AddIntMacro - * PyModule_AddStringMacro - * PyModule_AddObject - -The PyModule_GetDict function will continue to only work on true module -objects. This means that it should not be used on extension modules that only -define PyModuleExec. - - Legacy Init ----------- -If PyModuleExec is not defined, the import machinery will try to initialize -the module using the PyModuleInit hook, as described in PEP 3121. +If the PyModuleExport function is not defined, the import machinery will try to +initialize the module using the PyInit hook, as described in PEP 3121. -If PyModuleExec is defined, PyModuleInit will be ignored. +If PyModuleExport is defined, PyModuleInit will be ignored. Modules requiring compatibility with previous versions of CPython may implement PyModuleInit in addition to the new hook. +Modules using the legacy init API will be initialized entirely in the +Loader.create_module step; Loader.exec_module will be a no-op. + +.. XXX: Give example code for a backwards-compatible Init based on slots + +.. note:: + + If PyModuleDef is reused, implementing the PyInit hook becomes easy: + + * call PyModule_Create with the PyModuleDef (m_reload was ignored in + previous Python versions, so the slots array will be ignored). + Alternatively, call the Py_mod_create function (keeping in mind that + the spec is not available with PyInit). + * call the Py_mod_exec function(s). + Subinterpreters and Interpreter Reloading ----------------------------------------- @@ -307,59 +349,200 @@ No user-defined functions, methods, or instances may leak to different interpreters. To achieve this, all module-level state should be kept in either the module -dict, or in the module object. +dict, or in the module object's storage reachable by PyModule_GetState. A simple rule of thumb is: Do not define any static data, except built-in types with no mutable or user-settable class attributes. +PyModule_GetDesc +---------------- + +To retrieve the PyModuleDesc structure used to create a module, +a new function will be added:: + + PyModuleDesc* PyModule_GetDesc(PyObject *module) + +The function returns NULL if the parameter is not a module object, or was not +created using PyModuleDesc. + +.. note:: + + This is unnecessary if PyModuleDef is reused: the existing + PyModule_GetDef can be used instead. + + +Singleton Modules +----------------- + +Modules defined by PyModuleDef may be registered with PyState_AddModule, +and later retrieved with PyState_FindModule. + +Under the new API, there is no one-to-one mapping between PyModuleSpec +and the module created from it. +In particular, multiple modules may be loaded from the same description. + +This means that there is no "global" instance of a module object. +Any C-level callbacks that need access to the module state need to be passed +a reference to the module object, either directly or indirectly. + + +However, there are some modules that really need to be only loaded once: +typically ones that wrap a C library with global state. +These modules should set the PyModule_EXPORT_SINGLETON flag +in PyModuleDesc.flags. When this flag is set, loading an additional +copy of the module after it has been loaded once will return the previously +loaded object. +This will be done on a low level, using _PyImport_FixupExtensionObject. +Additionally, the module will be automatically registered using +PyState_AddSingletonModule (see below) after execution slots are processed. + +Singleton modules can be retrieved, registered or unregistered with +the interpreter state using three new functions, which parallel their +PyModuleDef counterparts, PyState_FindModule, PyState_AddModule, +and PyState_RemoveModule:: + + PyObject* PyState_FindSingletonModule(PyModuleDesc *desc) + int PyState_AddSingletonModule(PyObject *module, PyModuleDesc *desc) + int PyState_RemoveSingletonModule(PyModuleDesc *desc) + + +.. note:: + + If PyModuleDef is used instead of PyModuleDesc, the flag would be specified + as a slot with NULL value, i.e. ``{Py_mod_flag_singleton, NULL}``. + In this case, PyState_FindModule, PyState_AddModule and + PyState_RemoveModule can be used instead of the new functions. + +.. note:: + + Another possibility is to use PyModuleDef_Base in PyModuleDesc, and + have PyState_FindModule and friends work with either of the two structures. + + +Export Hook Name +---------------- + +As portable C identifiers are limited to ASCII, module names +must be encoded to form the PyModuleExport hook name. + +For ASCII module names, the import hook is named +PyModuleExport_, where is the name of the module. + +For module names containing non-ASCII characters, the import hook is named +PyModuleExportU_, where the name is encoded using CPython's +"punycode" encoding (Punycode [#rfc-3492]_ with a lowercase suffix), +with hyphens ("-") replaced by underscores ("_"). + + +In Python:: + + def export_hook_name(name): + try: + encoded = b'_' + name.encode('ascii') + except UnicodeDecodeError: + encoded = b'U_' + name.encode('punycode').replace(b'-', b'_') + return b'PyModuleExport' + encoded + +Examples: + +============= =========================== +Module name Export hook name +============= =========================== +spam PyModuleExport_spam +lan?m?t PyModuleExportU_lanmt_2sa6t +??? PyModuleExportU_zck5b2b +============= =========================== + + Module Reloading ---------------- -Reloading an extension module will re-execute its PyModuleInit function. -Similar caveats apply to reloading an extension module as to reloading -a Python module. Notably, attributes or any other state of the module -are not reset before reloading. +Reloading an extension module using importlib.reload() will continue to +have no effect, except re-setting import-related attributes. -Additionally, due to limitations in shared library loading (both dlopen on -POSIX and LoadModuleEx on Windows), it is not generally possible to load +Due to limitations in shared library loading (both dlopen on POSIX and +LoadModuleEx on Windows), it is not generally possible to load a modified library after it has changed on disk. -Therefore, reloading extension modules is of limited use. + +Use cases for reloading other than trying out a new version of the module +are too rare to require all module authors to keep reloading in mind. +If reload-like functionality is needed, authors can export a dedicated +function for it. Multiple modules in one library ------------------------------- -To support multiple Python modules in one shared library, the library -must export appropriate PyModuleExec_ or PyModuleCreate_ hooks -for each exported module. -The modules are loaded using a ModuleSpec with origin set to the name of the -library file, and name set to the module name. +To support multiple Python modules in one shared library, the library can +export additional PyModuleExport* symbols besides the one that corresponds +to the library's filename. -Note that this mechanism can currently only be used to *load* such modules, +Note that this mechanism can currently only be used to *load* extra modules, not to *find* them. -XXX: This is an existing issue; either fix it/wait for a fix or provide -an example of how to load such modules. +Given the filesystem location of a shared library and a module name, +a module may be loaded with:: + + import importlib.machinery + import importlib.util + loader = importlib.machinery.ExtensionFileLoader(name, path) + spec = importlib.util.spec_from_loader(name, loader) + return importlib.util.module_from_spec(spec) + +On platforms that support symbolic links, these may be used to install one +library under multiple names, exposing all exported modules to normal +import machinery. + + +Testing and initial implementations +----------------------------------- + +For testing, a new built-in module ``_testimportmodexport`` will be created. +The library will export several additional modules using the mechanism +described in "Multiple modules in one library". + +The ``_testcapi`` module will be unchanged, and will use the old API +indefinitely (or until the old API is removed). + +The ``_csv`` and ``readline`` modules will be converted to the new API as +part of the initial implementation. + + +Possible Future Extensions +========================== + +The slots mechanism, inspired by PyType_Slot from PEP 384, +allows later extensions. + +Some extension modules exports many constants; for example _ssl has +a long list of calls in the form:: + + PyModule_AddIntConstant(m, "SSL_ERROR_ZERO_RETURN", + PY_SSL_ERROR_ZERO_RETURN); + +Converting this to a declarative list, similar to PyMethodDef, +would reduce boilerplate, and provide free error-checking which +is often missing. + +String constants and types can be handled similarly. +(Note that non-default bases for types cannot be portably specified +statically; this case would need a Py_mod_exec function that runs +before the slots are added. The free error-checking would still be +beneficial, though.) + +Another possibility is providing a "main" function that would be run +when the module is given to Python's -m switch. +For this to work, the runpy module will need to be modified to take +advantage of ModuleSpec-based loading introduced in PEP 451. +Also, it will be necessary to add a mechanism for setting up a module +according to slots it wasn't originally defined with. Implementation ============== -XXX - not started - - -Open issues -=========== - -We should expose some kind of API in importlib.util (or a better place?) that -can be used to check that a module works with reloading and subinterpreters. - - -Related issues -============== - -The runpy module will need to be modified to take advantage of PEP 451 -and this PEP. This is out of scope for this PEP. +Work-in-progress implementation is available in a Github repository [#gh-repo]_; +a patchset is at [#gh-patch]_. Previous Approaches @@ -372,11 +555,17 @@ where module creation and initialization is broken into distinct steps. It also did not support loading an extension into pre-existing module objects. -Nick Coghlan proposed the Create annd Exec hooks, and wrote a prototype +Nick Coghlan proposed "Create" and "Exec" hooks, and wrote a prototype implementation [#nicks-prototype]_. At this time PEP 451 was still not implemented, so the prototype does not use ModuleSpec. +The original version of this PEP used Create and Exec hooks, and allowed +loading into arbitrary pre-constructed objects with Exec hook. +The proposal made extension module initialization closer to how Python modules +are initialized, but it was later recognized that this isn't an important goal. +The current PEP describes a simpler solution. + References ========== @@ -393,6 +582,15 @@ .. [#nicks-prototype] https://mail.python.org/pipermail/python-dev/2013-August/128101.html +.. [#rfc-3492] + http://tools.ietf.org/html/rfc3492 + +.. [#gh-repo] + https://github.com/encukou/cpython/commits/pep489 + +.. [#gh-patch] + https://github.com/encukou/cpython/compare/master...encukou:pep489.patch + Copyright ========= -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Thu Apr 16 18:20:19 2015 From: python-checkins at python.org (r.david.murray) Date: Thu, 16 Apr 2015 16:20:19 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_=2318128=3A_use_standard_+?= =?utf-8?q?NNNN_timezone_format_in_POT-Creation-Date_header=2E?= Message-ID: <20150416162019.31125.69728@psf.io> https://hg.python.org/cpython/rev/c969413584cf changeset: 95693:c969413584cf user: R David Murray date: Thu Apr 16 12:15:09 2015 -0400 summary: #18128: use standard +NNNN timezone format in POT-Creation-Date header. Patch by Michael McFadden, with a few small style tweaks. files: Doc/whatsnew/3.5.rst | 4 + Lib/test/test_tools/test_i18n.py | 68 ++++++++++++++++++++ Misc/ACKS | 1 + Misc/NEWS | 3 + Tools/i18n/pygettext.py | 4 +- 5 files changed, 77 insertions(+), 3 deletions(-) diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -814,6 +814,10 @@ * The :mod:`socket` module now exports the CAN_RAW_FD_FRAMES constant on linux 3.6 and greater. +* The `pygettext.py` Tool now uses the standard +NNNN format for timezones in + the POT-Creation-Date header. + + Changes in the C API -------------------- diff --git a/Lib/test/test_tools/test_i18n.py b/Lib/test/test_tools/test_i18n.py new file mode 100644 --- /dev/null +++ b/Lib/test/test_tools/test_i18n.py @@ -0,0 +1,68 @@ +"""Tests to cover the Tools/i18n package""" + +import os +import unittest + +from test.script_helper import assert_python_ok +from test.test_tools import toolsdir +from test.support import temp_cwd + +class Test_pygettext(unittest.TestCase): + """Tests for the pygettext.py tool""" + + script = os.path.join(toolsdir,'i18n', 'pygettext.py') + + def get_header(self, data): + """ utility: return the header of a .po file as a dictionary """ + headers = {} + for line in data.split('\n'): + if not line or line.startswith(('#', 'msgid','msgstr')): + continue + line = line.strip('"') + key, val = line.split(':',1) + headers[key] = val.strip() + return headers + + def test_header(self): + """Make sure the required fields are in the header, according to: + http://www.gnu.org/software/gettext/manual/gettext.html#Header-Entry + """ + with temp_cwd(None) as cwd: + assert_python_ok(self.script) + with open('messages.pot') as fp: + data = fp.read() + header = self.get_header(data) + + self.assertIn("Project-Id-Version", header) + self.assertIn("POT-Creation-Date", header) + self.assertIn("PO-Revision-Date", header) + self.assertIn("Last-Translator", header) + self.assertIn("Language-Team", header) + self.assertIn("MIME-Version", header) + self.assertIn("Content-Type", header) + self.assertIn("Content-Transfer-Encoding", header) + self.assertIn("Generated-By", header) + + # not clear if these should be required in POT (template) files + #self.assertIn("Report-Msgid-Bugs-To", header) + #self.assertIn("Language", header) + + #"Plural-Forms" is optional + + + def test_POT_Creation_Date(self): + """ Match the date format from xgettext for POT-Creation-Date """ + from datetime import datetime + with temp_cwd(None) as cwd: + assert_python_ok(self.script) + with open('messages.pot') as fp: + data = fp.read() + header = self.get_header(data) + creationDate = header['POT-Creation-Date'] + + # peel off the escaped newline at the end of string + if creationDate.endswith('\\n'): + creationDate = creationDate[:-len('\\n')] + + # This will raise if the date format does not exactly match. + datetime.strptime(creationDate, '%Y-%m-%d %H:%M%z') diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -911,6 +911,7 @@ Rebecca McCreary Kirk McDonald Chris McDonough +Michael McFadden Greg McFarlane Alan McIntyre Jessica McKellar diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -187,6 +187,9 @@ Tools/Demos ----------- +- Issue #18128: pygettext now uses standard +NNNN format in the + POT-Creation-Date header. + - Issue #23935: Argument Clinic's understanding of format units accepting bytes, bytearrays, and buffers is now consistent with both the documentation and the implementation. diff --git a/Tools/i18n/pygettext.py b/Tools/i18n/pygettext.py --- a/Tools/i18n/pygettext.py +++ b/Tools/i18n/pygettext.py @@ -441,9 +441,7 @@ def write(self, fp): options = self.__options - timestamp = time.strftime('%Y-%m-%d %H:%M+%Z') - # The time stamp in the header doesn't have the same format as that - # generated by xgettext... + timestamp = time.strftime('%Y-%m-%d %H:%M%z') encoding = fp.encoding if fp.encoding else 'UTF-8' print(pot_header % {'time': timestamp, 'version': __version__, 'charset': encoding, -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Apr 16 20:26:28 2015 From: python-checkins at python.org (christian.heimes) Date: Thu, 16 Apr 2015 18:26:28 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Update_coverity_modeling_f?= =?utf-8?q?ile_to_silence_datetime_warnings?= Message-ID: <20150416182627.7190.49024@psf.io> https://hg.python.org/cpython/rev/caf9f2df05d4 changeset: 95694:caf9f2df05d4 parent: 95692:5612dc5e6af9 user: Christian Heimes date: Thu Apr 16 20:25:03 2015 +0200 summary: Update coverity modeling file to silence datetime warnings files: Misc/coverity_model.c | 58 ++++++++++++++++++++++++++++++- 1 files changed, 57 insertions(+), 1 deletions(-) diff --git a/Misc/coverity_model.c b/Misc/coverity_model.c --- a/Misc/coverity_model.c +++ b/Misc/coverity_model.c @@ -122,7 +122,8 @@ /* Coverity doesn't understand that fdopendir() may take ownership of fd. */ -DIR *fdopendir(int fd) { +DIR *fdopendir(int fd) +{ DIR *d; if (d) { __coverity_close__(fd); @@ -130,3 +131,58 @@ return d; } +/* Modules/_datetime.c + * + * Coverity thinks that the input values for these function come from a + * tainted source PyDateTime_DATE_GET_* macros use bit shifting. + */ +static PyObject * +build_struct_time(int y, int m, int d, int hh, int mm, int ss, int dstflag) +{ + PyObject *result; + + __coverity_tainted_data_sanitize__(y); + __coverity_tainted_data_sanitize__(m); + __coverity_tainted_data_sanitize__(d); + __coverity_tainted_data_sanitize__(hh); + __coverity_tainted_data_sanitize__(mm); + __coverity_tainted_data_sanitize__(ss); + __coverity_tainted_data_sanitize__(dstflag); + + return result; +} + +static int +ymd_to_ord(int year, int month, int day) +{ + int ord = 0; + + __coverity_tainted_data_sanitize__(year); + __coverity_tainted_data_sanitize__(month); + __coverity_tainted_data_sanitize__(day); + + return ord; +} + +static int +normalize_date(int *year, int *month, int *day) +{ + __coverity_tainted_data_sanitize__(*year); + __coverity_tainted_data_sanitize__(*month); + __coverity_tainted_data_sanitize__(*day); + + return 0; +} + +static int +weekday(int year, int month, int day) +{ + int w = 0; + + __coverity_tainted_data_sanitize__(year); + __coverity_tainted_data_sanitize__(month); + __coverity_tainted_data_sanitize__(day); + + return w; +} + -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Apr 16 20:26:28 2015 From: python-checkins at python.org (christian.heimes) Date: Thu, 16 Apr 2015 18:26:28 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_default_-=3E_default?= =?utf-8?q?=29=3A_Merge?= Message-ID: <20150416182628.59431.93038@psf.io> https://hg.python.org/cpython/rev/dc4f96f3d329 changeset: 95695:dc4f96f3d329 parent: 95693:c969413584cf parent: 95694:caf9f2df05d4 user: Christian Heimes date: Thu Apr 16 20:26:19 2015 +0200 summary: Merge files: Misc/coverity_model.c | 58 ++++++++++++++++++++++++++++++- 1 files changed, 57 insertions(+), 1 deletions(-) diff --git a/Misc/coverity_model.c b/Misc/coverity_model.c --- a/Misc/coverity_model.c +++ b/Misc/coverity_model.c @@ -122,7 +122,8 @@ /* Coverity doesn't understand that fdopendir() may take ownership of fd. */ -DIR *fdopendir(int fd) { +DIR *fdopendir(int fd) +{ DIR *d; if (d) { __coverity_close__(fd); @@ -130,3 +131,58 @@ return d; } +/* Modules/_datetime.c + * + * Coverity thinks that the input values for these function come from a + * tainted source PyDateTime_DATE_GET_* macros use bit shifting. + */ +static PyObject * +build_struct_time(int y, int m, int d, int hh, int mm, int ss, int dstflag) +{ + PyObject *result; + + __coverity_tainted_data_sanitize__(y); + __coverity_tainted_data_sanitize__(m); + __coverity_tainted_data_sanitize__(d); + __coverity_tainted_data_sanitize__(hh); + __coverity_tainted_data_sanitize__(mm); + __coverity_tainted_data_sanitize__(ss); + __coverity_tainted_data_sanitize__(dstflag); + + return result; +} + +static int +ymd_to_ord(int year, int month, int day) +{ + int ord = 0; + + __coverity_tainted_data_sanitize__(year); + __coverity_tainted_data_sanitize__(month); + __coverity_tainted_data_sanitize__(day); + + return ord; +} + +static int +normalize_date(int *year, int *month, int *day) +{ + __coverity_tainted_data_sanitize__(*year); + __coverity_tainted_data_sanitize__(*month); + __coverity_tainted_data_sanitize__(*day); + + return 0; +} + +static int +weekday(int year, int month, int day) +{ + int w = 0; + + __coverity_tainted_data_sanitize__(year); + __coverity_tainted_data_sanitize__(month); + __coverity_tainted_data_sanitize__(day); + + return w; +} + -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Apr 16 22:36:32 2015 From: python-checkins at python.org (r.david.murray) Date: Thu, 16 Apr 2015 20:36:32 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_=237159=3A_generalize_urll?= =?utf-8?q?ib_prior_auth_support=2E?= Message-ID: <20150416203631.59431.30699@psf.io> https://hg.python.org/cpython/rev/1b9e81cb83bc changeset: 95696:1b9e81cb83bc user: R David Murray date: Thu Apr 16 16:36:18 2015 -0400 summary: #7159: generalize urllib prior auth support. This fix is a superset of the functionality introduced by the issue #19494 enhancement, and supersedes that fix. Instead of a new handler, we have a new password manager that tracks whether we should send the auth for a given uri. This allows us to say "always send", satisfying #19494, or track that we've succeeded in auth and send the creds right away on every *subsequent* request. The support for using the password manager is added to AbstractBasicAuth, which means the proxy handler also now can handle prior auth if passed the new password manager. Patch by Akshit Khurana, docs mostly by me. files: Doc/library/urllib.request.rst | 72 ++++++++++++-- Doc/whatsnew/3.5.rst | 12 +- Lib/test/test_urllib2.py | 104 +++++++++++++++++--- Lib/urllib/request.py | 78 ++++++++++++--- Misc/ACKS | 1 + Misc/NEWS | 4 + 6 files changed, 220 insertions(+), 51 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 @@ -283,13 +283,36 @@ fits. +.. class:: HTTPPasswordMgrWithPriorAuth() + + A variant of :class:`HTTPPasswordMgrWithDefaultRealm` that also has a + database of ``uri -> is_authenticated`` mappings. Can be used by a + BasicAuth handler to determine when to send authentication credentials + immediately instead of waiting for a ``401`` response first. + + .. versionadded:: 3.5 + + .. class:: AbstractBasicAuthHandler(password_mgr=None) This is a mixin class that helps with HTTP authentication, both to the remote host and to a proxy. *password_mgr*, if given, should be something that is compatible with :class:`HTTPPasswordMgr`; refer to section :ref:`http-password-mgr` for information on the interface that must be - supported. + supported. If *passwd_mgr* also provides ``is_authenticated`` and + ``update_authenticated`` methods (see + :ref:`http-password-mgr-with-prior-auth`), then the handler will use the + ``is_authenticated`` result for a given URI to determine whether or not to + send authentication credentials with the request. If ``is_authenticated`` + returns ``True`` for the URI, credentials are sent. If ``is_authenticated + is ``False``, credentials are not sent, and then if a ``401`` response is + received the request is re-sent with the authentication credentials. If + authentication succeeds, ``update_authenticated`` is called to set + ``is_authenticated`` ``True`` for the URI, so that subsequent requests to + the URI or any of its super-URIs will automatically include the + authentication credentials. + + .. versionadded:: 3.5: added ``is_authenticated`` support. .. class:: HTTPBasicAuthHandler(password_mgr=None) @@ -301,17 +324,6 @@ presented with a wrong Authentication scheme. -.. class:: HTTPBasicPriorAuthHandler(password_mgr=None) - - A variant of :class:`HTTPBasicAuthHandler` which automatically sends - authorization credentials with the first request, rather than waiting to - first receive a HTTP 401 "Unauthorised" error response. This allows - authentication to sites that don't provide a 401 response when receiving - a request without an Authorization header. Aside from this difference, - this behaves exactly as :class:`HTTPBasicAuthHandler`. - - .. versionadded:: 3.5 - .. class:: ProxyBasicAuthHandler(password_mgr=None) Handle authentication with the proxy. *password_mgr*, if given, should be @@ -852,6 +864,42 @@ searched if the given *realm* has no matching user/password. +.. _http-password-mgr-with-prior-auth: + +HTTPPasswordMgrWithPriorAuth Objects +------------------------------------ + +This password manager extends :class:`HTTPPasswordMgrWithDefaultRealm` to support +tracking URIs for which authentication credentials should always be sent. + + +.. method:: HTTPPasswordMgrWithPriorAuth.add_password(realm, uri, user, \ + passwd, is_authenticated=False) + + *realm*, *uri*, *user*, *passwd* are as for + :meth:`HTTPPasswordMgr.add_password`. *is_authenticated* sets the initial + value of the ``is_authenticated`` flag for the given URI or list of URIs. + If *is_authenticated* is specified as ``True``, *realm* is ignored. + + +.. method:: HTTPPasswordMgr.find_user_password(realm, authuri) + + Same as for :class:`HTTPPasswordMgrWithDefaultRealm` objects + + +.. method:: HTTPPasswordMgrWithPriorAuth.update_authenticated(self, uri, \ + is_authenticated=False) + + Update the ``is_authenticated`` flag for the given *uri* or list + of URIs. + + +.. method:: HTTPPasswordMgrWithPriorAuth.is_authenticated(self, authuri) + + Returns the current state of the ``is_authenticated`` flag for + the given URI. + + .. _abstract-basic-auth-handler: AbstractBasicAuthHandler Objects diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -520,11 +520,13 @@ urllib ------ -* A new :class:`urllib.request.HTTPBasicPriorAuthHandler` allows HTTP Basic - Authentication credentials to be sent unconditionally with the first HTTP - request, rather than waiting for a HTTP 401 Unauthorized response from the - server. - (Contributed by Matej Cepl in :issue:`19494`.) +* A new :class:`~urllib.request.HTTPPasswordMgrWithPriorAuth` allows HTTP Basic + Authentication credentials to be managed so as to eliminate unnecessary + ``401`` response handling, or to unconditionally send credentials + on the first request in order to communicate with servers that return a + ``404`` response instead of a ``401`` if the ``Authorization`` header is not + sent. (Contributed by Matej Cepl in :issue:`19494` and Akshit Khurana in + :issue:`7159`.) wsgiref ------- 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 @@ -11,7 +11,9 @@ import urllib.request # The proxy bypass method imported below has logic specific to the OSX # proxy config data structure but is testable on all platforms. -from urllib.request import Request, OpenerDirector, _parse_proxy, _proxy_bypass_macosx_sysconf +from urllib.request import (Request, OpenerDirector, HTTPBasicAuthHandler, + HTTPPasswordMgrWithPriorAuth, _parse_proxy, + _proxy_bypass_macosx_sysconf) from urllib.parse import urlparse import urllib.error import http.client @@ -447,6 +449,25 @@ def https_open(self, req): return self.do_open(self.httpconn, req) + +class MockHTTPHandlerCheckAuth(urllib.request.BaseHandler): + # useful for testing auth + # sends supplied code response + # checks if auth header is specified in request + def __init__(self, code): + self.code = code + self.has_auth_header = False + + def reset(self): + self.has_auth_header = False + + def http_open(self, req): + if req.has_header('Authorization'): + self.has_auth_header = True + name = http.client.responses[self.code] + return MockResponse(self.code, name, MockFile(), "", req.get_full_url()) + + class MockPasswordManager: def add_password(self, realm, uri, user, password): self.realm = realm @@ -1395,6 +1416,72 @@ self.assertEqual(len(http_handler.requests), 1) self.assertFalse(http_handler.requests[0].has_header(auth_header)) + def test_basic_prior_auth_auto_send(self): + # Assume already authenticated if is_authenticated=True + # for APIs like Github that don't return 401 + + user, password = "wile", "coyote" + request_url = "http://acme.example.com/protected" + + http_handler = MockHTTPHandlerCheckAuth(200) + + pwd_manager = HTTPPasswordMgrWithPriorAuth() + auth_prior_handler = HTTPBasicAuthHandler(pwd_manager) + auth_prior_handler.add_password( + None, request_url, user, password, is_authenticated=True) + + is_auth = pwd_manager.is_authenticated(request_url) + self.assertTrue(is_auth) + + opener = OpenerDirector() + opener.add_handler(auth_prior_handler) + opener.add_handler(http_handler) + + opener.open(request_url) + + # expect request to be sent with auth header + self.assertTrue(http_handler.has_auth_header) + + def test_basic_prior_auth_send_after_first_success(self): + # Auto send auth header after authentication is successful once + + user, password = 'wile', 'coyote' + request_url = 'http://acme.example.com/protected' + realm = 'ACME' + + pwd_manager = HTTPPasswordMgrWithPriorAuth() + auth_prior_handler = HTTPBasicAuthHandler(pwd_manager) + auth_prior_handler.add_password(realm, request_url, user, password) + + is_auth = pwd_manager.is_authenticated(request_url) + self.assertFalse(is_auth) + + opener = OpenerDirector() + opener.add_handler(auth_prior_handler) + + http_handler = MockHTTPHandler( + 401, 'WWW-Authenticate: Basic realm="%s"\r\n\r\n' % None) + opener.add_handler(http_handler) + + opener.open(request_url) + + is_auth = pwd_manager.is_authenticated(request_url) + self.assertTrue(is_auth) + + http_handler = MockHTTPHandlerCheckAuth(200) + self.assertFalse(http_handler.has_auth_header) + + opener = OpenerDirector() + opener.add_handler(auth_prior_handler) + opener.add_handler(http_handler) + + # After getting 200 from MockHTTPHandler + # Next request sends header in the first request + opener.open(request_url) + + # expect request to be sent with auth header + self.assertTrue(http_handler.has_auth_header) + def test_http_closed(self): """Test the connection is cleaned up when the response is closed""" for (transfer, data) in ( @@ -1422,21 +1509,6 @@ handler.do_open(conn, req) self.assertTrue(conn.fakesock.closed, "Connection not closed") - def test_auth_prior_handler(self): - pwd_manager = MockPasswordManager() - pwd_manager.add_password(None, 'https://example.com', - 'somebody', 'verysecret') - auth_prior_handler = urllib.request.HTTPBasicPriorAuthHandler( - pwd_manager) - http_hand = MockHTTPSHandler() - - opener = OpenerDirector() - opener.add_handler(http_hand) - opener.add_handler(auth_prior_handler) - - req = Request("https://example.com") - opener.open(req) - self.assertNotIn('Authorization', http_hand.httpconn.req_headers) class MiscTests(unittest.TestCase): diff --git a/Lib/urllib/request.py b/Lib/urllib/request.py --- a/Lib/urllib/request.py +++ b/Lib/urllib/request.py @@ -120,9 +120,10 @@ 'Request', 'OpenerDirector', 'BaseHandler', 'HTTPDefaultErrorHandler', 'HTTPRedirectHandler', 'HTTPCookieProcessor', 'ProxyHandler', 'HTTPPasswordMgr', 'HTTPPasswordMgrWithDefaultRealm', - 'AbstractBasicAuthHandler', 'HTTPBasicAuthHandler', 'ProxyBasicAuthHandler', - 'AbstractDigestAuthHandler', 'HTTPDigestAuthHandler', 'ProxyDigestAuthHandler', - 'HTTPHandler', 'FileHandler', 'FTPHandler', 'CacheFTPHandler', 'DataHandler', + 'HTTPPasswordMgrWithPriorAuth', 'AbstractBasicAuthHandler', + 'HTTPBasicAuthHandler', 'ProxyBasicAuthHandler', 'AbstractDigestAuthHandler', + 'HTTPDigestAuthHandler', 'ProxyDigestAuthHandler', 'HTTPHandler', + 'FileHandler', 'FTPHandler', 'CacheFTPHandler', 'DataHandler', 'UnknownHandler', 'HTTPErrorProcessor', # Functions 'urlopen', 'install_opener', 'build_opener', @@ -835,6 +836,37 @@ return HTTPPasswordMgr.find_user_password(self, None, authuri) +class HTTPPasswordMgrWithPriorAuth(HTTPPasswordMgrWithDefaultRealm): + + def __init__(self, *args, **kwargs): + self.authenticated = {} + super().__init__(*args, **kwargs) + + def add_password(self, realm, uri, user, passwd, is_authenticated=False): + self.update_authenticated(uri, is_authenticated) + # Add a default for prior auth requests + if realm is not None: + super().add_password(None, uri, user, passwd) + super().add_password(realm, uri, user, passwd) + + def update_authenticated(self, uri, is_authenticated=False): + # uri could be a single URI or a sequence + if isinstance(uri, str): + uri = [uri] + + for default_port in True, False: + for u in uri: + reduced_uri = self.reduce_uri(u, default_port) + self.authenticated[reduced_uri] = is_authenticated + + def is_authenticated(self, authuri): + for default_port in True, False: + reduced_authuri = self.reduce_uri(authuri, default_port) + for uri in self.authenticated: + if self.is_suburi(uri, reduced_authuri): + return self.authenticated[uri] + + class AbstractBasicAuthHandler: # XXX this allows for multiple auth-schemes, but will stupidly pick @@ -889,6 +921,31 @@ else: return None + def http_request(self, req): + if (not hasattr(self.passwd, 'is_authenticated') or + not self.passwd.is_authenticated(req.full_url)): + return req + + if not req.has_header('Authorization'): + user, passwd = self.passwd.find_user_password(None, req.full_url) + credentials = '{0}:{1}'.format(user, passwd).encode() + auth_str = base64.standard_b64encode(credentials).decode() + req.add_unredirected_header('Authorization', + 'Basic {}'.format(auth_str.strip())) + return req + + def http_response(self, req, response): + if hasattr(self.passwd, 'is_authenticated'): + if 200 <= response.code < 300: + self.passwd.update_authenticated(req.full_url, True) + else: + self.passwd.update_authenticated(req.full_url, False) + return response + + https_request = http_request + https_response = http_response + + class HTTPBasicAuthHandler(AbstractBasicAuthHandler, BaseHandler): @@ -916,21 +973,6 @@ return response -class HTTPBasicPriorAuthHandler(HTTPBasicAuthHandler): - handler_order = 400 - - def http_request(self, req): - if not req.has_header('Authorization'): - user, passwd = self.passwd.find_user_password(None, req.host) - credentials = '{0}:{1}'.format(user, passwd).encode() - auth_str = base64.standard_b64encode(credentials).decode() - req.add_unredirected_header('Authorization', - 'Basic {}'.format(auth_str.strip())) - return req - - https_request = http_request - - # Return n random bytes. _randombytes = os.urandom diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -722,6 +722,7 @@ Lawrence Kesteloot Vivek Khera Dhiru Kholia +Akshit Khurana Mads Kiilerich Jason Killen Jan Kim diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -37,6 +37,10 @@ Library ------- +- Issue #7159: urllib.request now supports sending auth credentials + automatically after the first 401. This enhancement is a superset of the + enhancement from issue #19494 and supersedes that change. + - Issue #23703: Fix a regression in urljoin() introduced in 901e4e52b20a. Patch by Demian Brecht. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Apr 16 23:15:12 2015 From: python-checkins at python.org (r.david.murray) Date: Thu, 16 Apr 2015 21:15:12 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_=2316914=3A_add_timestamps?= =?utf-8?q?_to_smtplib_debugging_output_via_new_debuglevel_2=2E?= Message-ID: <20150416211512.6593.54119@psf.io> https://hg.python.org/cpython/rev/65037930edb0 changeset: 95697:65037930edb0 user: R David Murray date: Thu Apr 16 17:14:42 2015 -0400 summary: #16914: add timestamps to smtplib debugging output via new debuglevel 2. Patch by Gavin Chappell and Maciej Szulik. files: Doc/library/smtplib.rst | 5 ++- Doc/whatsnew/3.5.rst | 9 +++++++ Lib/smtplib.py | 33 ++++++++++++++++----------- Lib/test/test_smtplib.py | 21 +++++++++++++++++ Misc/ACKS | 2 + 5 files changed, 54 insertions(+), 16 deletions(-) diff --git a/Doc/library/smtplib.rst b/Doc/library/smtplib.rst --- a/Doc/library/smtplib.rst +++ b/Doc/library/smtplib.rst @@ -189,8 +189,9 @@ .. method:: SMTP.set_debuglevel(level) - Set the debug output level. A true value for *level* results in debug messages - for connection and for all messages sent to and received from the server. + Set the debug output level. A value of 1 or ``True`` for *level* results in debug + messages for connection and for all messages sent to and received from the server. + A value of 2 for *level* results in these messages being timestamped. .. method:: SMTP.docmd(cmd, args='') diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -468,6 +468,10 @@ implement custom authentication mechanisms. (Contributed by Milan Oberkirch in :issue:`15014`.) +* Additional debuglevel (2) shows timestamps for debug messages in + :class:`smtplib.SMTP`. (Contributed by Gavin Chappell and Maciej Szulik in + :issue:`16914`.) + sndhdr ------ @@ -819,6 +823,11 @@ * The `pygettext.py` Tool now uses the standard +NNNN format for timezones in the POT-Creation-Date header. +* The :mod:`smtplib` module now uses :data:`sys.stderr` instead of previous + module level :data:`stderr` variable for debug output. If your (test) + program depends on patching the module level variable to capture the debug + output, you will need to update it to capture sys.stderr instead. + Changes in the C API -------------------- diff --git a/Lib/smtplib.py b/Lib/smtplib.py --- a/Lib/smtplib.py +++ b/Lib/smtplib.py @@ -50,8 +50,9 @@ import base64 import hmac import copy +import datetime +import sys from email.base64mime import body_encode as encode_base64 -from sys import stderr __all__ = ["SMTPException", "SMTPServerDisconnected", "SMTPResponseException", "SMTPSenderRefused", "SMTPRecipientsRefused", "SMTPDataError", @@ -282,12 +283,17 @@ """ self.debuglevel = debuglevel + def _print_debug(self, *args): + if self.debuglevel > 1: + print(datetime.datetime.now().time(), *args, file=sys.stderr) + else: + print(*args, file=sys.stderr) + def _get_socket(self, host, port, timeout): # This makes it simpler for SMTP_SSL to use the SMTP connect code # and just alter the socket connection bit. if self.debuglevel > 0: - print('connect: to', (host, port), self.source_address, - file=stderr) + self._print_debug('connect: to', (host, port), self.source_address) return socket.create_connection((host, port), timeout, self.source_address) @@ -317,18 +323,18 @@ if not port: port = self.default_port if self.debuglevel > 0: - print('connect:', (host, port), file=stderr) + self._print_debug('connect:', (host, port)) self.sock = self._get_socket(host, port, self.timeout) self.file = None (code, msg) = self.getreply() if self.debuglevel > 0: - print("connect:", msg, file=stderr) + self._print_debug('connect:', msg) return (code, msg) def send(self, s): """Send `s' to the server.""" if self.debuglevel > 0: - print('send:', repr(s), file=stderr) + self._print_debug('send:', repr(s)) if hasattr(self, 'sock') and self.sock: if isinstance(s, str): s = s.encode("ascii") @@ -375,7 +381,7 @@ self.close() raise SMTPServerDisconnected("Connection unexpectedly closed") if self.debuglevel > 0: - print('reply:', repr(line), file=stderr) + self._print_debug('reply:', repr(line)) if len(line) > _MAXLINE: self.close() raise SMTPResponseException(500, "Line too long.") @@ -394,8 +400,7 @@ errmsg = b"\n".join(resp) if self.debuglevel > 0: - print('reply: retcode (%s); Msg: %s' % (errcode, errmsg), - file=stderr) + self._print_debug('reply: retcode (%s); Msg: %s' % (errcode, errmsg)) return errcode, errmsg def docmd(self, cmd, args=""): @@ -524,7 +529,7 @@ self.putcmd("data") (code, repl) = self.getreply() if self.debuglevel > 0: - print("data:", (code, repl), file=stderr) + self._print_debug('data:', (code, repl)) if code != 354: raise SMTPDataError(code, repl) else: @@ -537,7 +542,7 @@ self.send(q) (code, msg) = self.getreply() if self.debuglevel > 0: - print("data:", (code, msg), file=stderr) + self._print_debug('data:', (code, msg)) return (code, msg) def verify(self, address): @@ -940,7 +945,7 @@ def _get_socket(self, host, port, timeout): if self.debuglevel > 0: - print('connect:', (host, port), file=stderr) + self._print_debug('connect:', (host, port)) new_socket = socket.create_connection((host, port), timeout, self.source_address) new_socket = self.context.wrap_socket(new_socket, @@ -988,14 +993,14 @@ self.sock.connect(host) except OSError: if self.debuglevel > 0: - print('connect fail:', host, file=stderr) + self._print_debug('connect fail:', host) if self.sock: self.sock.close() self.sock = None raise (code, msg) = self.getreply() if self.debuglevel > 0: - print('connect:', msg, file=stderr) + self._print_debug('connect:', msg) return (code, msg) diff --git a/Lib/test/test_smtplib.py b/Lib/test/test_smtplib.py --- a/Lib/test/test_smtplib.py +++ b/Lib/test/test_smtplib.py @@ -124,6 +124,27 @@ self.assertEqual(smtp.sock.gettimeout(), 30) smtp.close() + def test_debuglevel(self): + mock_socket.reply_with(b"220 Hello world") + smtp = smtplib.SMTP() + smtp.set_debuglevel(1) + with support.captured_stderr() as stderr: + smtp.connect(HOST, self.port) + smtp.close() + expected = re.compile(r"^connect:", re.MULTILINE) + self.assertRegex(stderr.getvalue(), expected) + + def test_debuglevel_2(self): + mock_socket.reply_with(b"220 Hello world") + smtp = smtplib.SMTP() + smtp.set_debuglevel(2) + with support.captured_stderr() as stderr: + smtp.connect(HOST, self.port) + smtp.close() + expected = re.compile(r"^\d{2}:\d{2}:\d{2}\.\d{6} connect: ", + re.MULTILINE) + self.assertRegex(stderr.getvalue(), expected) + # Test server thread using the specified SMTP server class def debugging_server(serv, serv_evt, client_evt): diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -235,6 +235,7 @@ John Chandler Hye-Shik Chang Jeffrey Chang +Gavin Chappell Godefroid Chapelle Brad Chapman Greg Chapman @@ -1368,6 +1369,7 @@ P?ter Szab? John Szakmeister Amir Szekely +Maciej Szulik Arfrever Frehtes Taifersar Arahesis Hideaki Takahashi Indra Talip -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Apr 16 23:16:23 2015 From: python-checkins at python.org (r.david.murray) Date: Thu, 16 Apr 2015 21:16:23 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_News_item_for_=2316914=2E?= Message-ID: <20150416211622.15811.83488@psf.io> https://hg.python.org/cpython/rev/de19c0ffe8d5 changeset: 95698:de19c0ffe8d5 user: R David Murray date: Thu Apr 16 17:16:15 2015 -0400 summary: News item for #16914. 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 @@ -37,6 +37,8 @@ Library ------- +- Issue #16914: new debuglevel 2 in smtplib adds timestamps to debug output. + - Issue #7159: urllib.request now supports sending auth credentials automatically after the first 401. This enhancement is a superset of the enhancement from issue #19494 and supersedes that change. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Apr 16 23:25:06 2015 From: python-checkins at python.org (r.david.murray) Date: Thu, 16 Apr 2015 21:25:06 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_=2316914=3A_reflow_paragra?= =?utf-8?q?ph_and_add_missing_versionchanged=2E?= Message-ID: <20150416212506.31115.21440@psf.io> https://hg.python.org/cpython/rev/724473a18ada changeset: 95699:724473a18ada user: R David Murray date: Thu Apr 16 17:24:52 2015 -0400 summary: #16914: reflow paragraph and add missing versionchanged. files: Doc/library/smtplib.rst | 9 ++++++--- 1 files changed, 6 insertions(+), 3 deletions(-) diff --git a/Doc/library/smtplib.rst b/Doc/library/smtplib.rst --- a/Doc/library/smtplib.rst +++ b/Doc/library/smtplib.rst @@ -189,9 +189,12 @@ .. method:: SMTP.set_debuglevel(level) - Set the debug output level. A value of 1 or ``True`` for *level* results in debug - messages for connection and for all messages sent to and received from the server. - A value of 2 for *level* results in these messages being timestamped. + Set the debug output level. A value of 1 or ``True`` for *level* results in + debug messages for connection and for all messages sent to and received from + the server. A value of 2 for *level* results in these messages being + timestamped. + + .. versionchanged:: 3.5 Added debuglevel 2. .. method:: SMTP.docmd(cmd, args='') -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Apr 17 00:55:10 2015 From: python-checkins at python.org (r.david.murray) Date: Thu, 16 Apr 2015 22:55:10 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_=2316914=3A_fix_test_error?= =?utf-8?q?s_under_-W_error=3A=3ABytesWarning=2E?= Message-ID: <20150416225510.6583.48944@psf.io> https://hg.python.org/cpython/rev/e532937914fc changeset: 95700:e532937914fc user: R David Murray date: Thu Apr 16 18:54:56 2015 -0400 summary: #16914: fix test errors under -W error::BytesWarning. There are doubtless other debug messages in smtplib that would trigger an error if they were tested, but this fixes the things we do now test, which is good enough for now. files: Lib/smtplib.py | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/smtplib.py b/Lib/smtplib.py --- a/Lib/smtplib.py +++ b/Lib/smtplib.py @@ -328,7 +328,7 @@ self.file = None (code, msg) = self.getreply() if self.debuglevel > 0: - self._print_debug('connect:', msg) + self._print_debug('connect:', repr(msg)) return (code, msg) def send(self, s): @@ -400,7 +400,7 @@ errmsg = b"\n".join(resp) if self.debuglevel > 0: - self._print_debug('reply: retcode (%s); Msg: %s' % (errcode, errmsg)) + self._print_debug('reply: retcode (%s); Msg: %a' % (errcode, errmsg)) return errcode, errmsg def docmd(self, cmd, args=""): -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Apr 17 03:58:40 2015 From: python-checkins at python.org (berker.peksag) Date: Fri, 17 Apr 2015 01:58:40 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Fix_two_typos_in_AbstractB?= =?utf-8?q?asicAuthHandler_documentation=2E?= Message-ID: <20150417015840.40536.6421@psf.io> https://hg.python.org/cpython/rev/35a9d60145cd changeset: 95701:35a9d60145cd user: Berker Peksag date: Fri Apr 17 04:58:45 2015 +0300 summary: Fix two typos in AbstractBasicAuthHandler documentation. files: Doc/library/urllib.request.rst | 5 +++-- 1 files changed, 3 insertions(+), 2 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 @@ -304,7 +304,7 @@ :ref:`http-password-mgr-with-prior-auth`), then the handler will use the ``is_authenticated`` result for a given URI to determine whether or not to send authentication credentials with the request. If ``is_authenticated`` - returns ``True`` for the URI, credentials are sent. If ``is_authenticated + returns ``True`` for the URI, credentials are sent. If ``is_authenticated`` is ``False``, credentials are not sent, and then if a ``401`` response is received the request is re-sent with the authentication credentials. If authentication succeeds, ``update_authenticated`` is called to set @@ -312,7 +312,8 @@ the URI or any of its super-URIs will automatically include the authentication credentials. - .. versionadded:: 3.5: added ``is_authenticated`` support. + .. versionadded:: 3.5 + Added ``is_authenticated`` support. .. class:: HTTPBasicAuthHandler(password_mgr=None) -- Repository URL: https://hg.python.org/cpython From solipsis at pitrou.net Fri Apr 17 10:49:39 2015 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Fri, 17 Apr 2015 08:49:39 +0000 Subject: [Python-checkins] Daily reference leaks (35a9d60145cd): sum=0 Message-ID: <20150417084930.129835.88129@psf.io> results for 35a9d60145cd on branch "default" -------------------------------------------- test_asyncio leaked [3, 0, 0] memory blocks, sum=3 test_collections leaked [-2, -4, 2] references, sum=-4 test_collections leaked [-1, -2, 1] memory blocks, sum=-2 test_functools leaked [0, 0, 3] memory blocks, sum=3 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogeimg_a', '--timeout', '7200'] From python-checkins at python.org Fri Apr 17 16:21:33 2015 From: python-checkins at python.org (daniel.holth) Date: Fri, 17 Apr 2015 14:21:33 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_Add_PEP_491?= Message-ID: <20150417142131.40536.70625@psf.io> https://hg.python.org/peps/rev/97d14432cdbc changeset: 5759:97d14432cdbc user: Daniel Holth date: Fri Apr 17 10:21:24 2015 -0400 summary: Add PEP 491 files: pep-0491.txt | 546 +++++++++++++++++++++++++++++++++++++++ 1 files changed, 546 insertions(+), 0 deletions(-) diff --git a/pep-0491.txt b/pep-0491.txt new file mode 100644 --- /dev/null +++ b/pep-0491.txt @@ -0,0 +1,546 @@ +PEP: 491 +Title: The Wheel Binary Package Format 1.9 +Version: $Revision$ +Last-Modified: $Date$ +Author: Daniel Holth +Discussions-To: +Status: Draft +Type: Standards Track +Content-Type: text/x-rst +Created: 16 April 2015 + +Abstract +======== + +This PEP describes the second version of a built-package format for Python +called "wheel". Wheel provides a Python-specific, relocatable package format +that allows people to install software more quickly and predictably than +re-building from source each time. + +A wheel is a ZIP-format archive with a specially formatted file name and +the ``.whl`` extension. It contains a single distribution nearly as it +would be installed according to PEP 376 with a particular installation +scheme. Simple wheels can be unpacked onto ``sys.path`` and used directly +but wheels are usually installed with a specialized installer. + +This version of the wheel specification adds support for installing +distributions into many different directories, and adds a way to find +those files after they have been installed. + +Rationale +========= + +Wheel 1.0 is best at installing files into ``site-packages`` and a few +other locations specified by distutils, but users would like to install +files from single distribution into many directories -- perhaps separate +locations for docs, data, and code. Unfortunately not everyone agrees +on where these install locations should be relative to the root directory. +This version of the format adds many more categories, each of which can be +installed to a different destination based on policy. Since it might +also be important to locate the installed files at runtime, this version +of the format also adds a way to record the installed paths in a way that +can be read by the installed software. + +Details +======= + +Installing a wheel 'distribution-1.0-py32-none-any.whl' +------------------------------------------------------- + +Wheel installation notionally consists of two phases: + +- Unpack. + + a. Parse ``distribution-1.0.dist-info/WHEEL``. + b. Check that installer is compatible with Wheel-Version. Warn if + minor version is greater, abort if major version is greater. + c. If Root-Is-Purelib == 'true', unpack archive into purelib + (site-packages). + d. Else unpack archive into platlib (site-packages). + +- Spread. + + a. Unpacked archive includes ``distribution-1.0.dist-info/`` and (if + there is data) ``distribution-1.0.data/``. + b. Move each subtree of ``distribution-1.0.data/`` onto its + destination path. Each subdirectory of ``distribution-1.0.data/`` + is a key into a dict of destination directories, such as + ``distribution-1.0.data/(purelib|platlib|headers|scripts|data)``. + c. Update scripts starting with ``#!python`` to point to the correct + interpreter. (Note: Python scripts are usually handled by package + metadata, and not included verbatim in wheel.) + d. Update ``distribution-1.0.dist.info/RECORD`` with the installed + paths. + e. If empty, remove the ``distribution-1.0.data`` directory. + f. Compile any installed .py to .pyc. (Uninstallers should be smart + enough to remove .pyc even if it is not mentioned in RECORD.) + +In practice, installers will usually extract files directly from the archive +to their destinations without writing a temporary ``distribution-1.0.data/`` +directory. + +Recommended installer features +'''''''''''''''''''''''''''''' + +Rewrite ``#!python``. + In wheel, verbatim scripts are packaged in + ``{distribution}-{version}.data/scripts/``. If the first line of + a file in ``scripts/`` starts with exactly ``b'#!python'``, rewrite to + point to the correct interpreter. Unix installers may need to add + the +x bit to these files if the archive was created on Windows. + + The ``b'#!pythonw'`` convention is allowed. ``b'#!pythonw'`` indicates + a GUI script instead of a console script. + +Generate script wrappers. + Python scripts are more commonly represented as a ``module:callable`` + string in package metadata, and are not included verbatim in the wheel + archive's ``scripts`` directory. This kind of script gives the installer + an opportunity to generate platform specific wrappers. + +Recommended archiver features +''''''''''''''''''''''''''''' + +Place ``.dist-info`` at the end of the archive. + Archivers are encouraged to place the ``.dist-info`` files physically + at the end of the archive. This enables some potentially interesting + ZIP tricks including the ability to amend the metadata without + rewriting the entire archive. + + +File Format +----------- + +File name convention +'''''''''''''''''''' + +The wheel filename is ``{distribution}-{version}(-{build +tag})?-{python tag}-{abi tag}-{platform tag}.whl``. + +distribution + Distribution name, e.g. 'django', 'pyramid'. + +version + Distribution version, e.g. 1.0. + +build tag + Optional build number. Must start with a digit. A tie breaker + if two wheels have the same version. Sort as the empty string + if unspecified, else sort the initial digits as a number, and the + remainder lexicographically. + +language implementation and version tag + E.g. 'py27', 'py2', 'py3'. + +abi tag + E.g. 'cp33m', 'abi3', 'none'. + +platform tag + E.g. 'linux_x86_64', 'any'. + +For example, ``distribution-1.0-1-py27-none-any.whl`` is the first +build of a package called 'distribution', and is compatible with +Python 2.7 (any Python 2.7 implementation), with no ABI (pure Python), +on any CPU architecture. + +The last three components of the filename before the extension are +called "compatibility tags." The compatibility tags express the +package's basic interpreter requirements and are detailed in PEP 425. + +Escaping and Unicode +'''''''''''''''''''' + +Each component of the filename is escaped by replacing runs of +non-alphanumeric characters with an underscore ``_``:: + + re.sub("[^\w\d.]+", "_", distribution, re.UNICODE) + +The archive filename is Unicode. The packaging tools may only support +ASCII package names, but Unicode filenames are supported in this +specification. + +The filenames *inside* the archive are encoded as UTF-8. Although some +ZIP clients in common use do not properly display UTF-8 filenames, +the encoding is supported by both the ZIP specification and Python's +``zipfile``. + +File contents +''''''''''''' + +The contents of a wheel file, where {distribution} is replaced with the +name of the package, e.g. ``beaglevote`` and {version} is replaced with +its version, e.g. ``1.0.0``, consist of: + +#. ``/``, the root of the archive, contains all files to be installed in + ``purelib`` or ``platlib`` as specified in ``WHEEL``. ``purelib`` and + ``platlib`` are usually both ``site-packages``. +#. ``{distribution}-{version}.dist-info/`` contains metadata. +#. ``{distribution}-{version}.data/`` contains one subdirectory + for each non-empty install scheme key not already covered, where + the subdirectory name is an index into a dictionary of install paths + (e.g. ``data``, ``scripts``, ``include``, ``purelib``, ``platlib``). +#. Python scripts must appear in ``scripts`` and begin with exactly + ``b'#!python'`` in order to enjoy script wrapper generation and + ``#!python`` rewriting at install time. They may have any or no + extension. +#. ``{distribution}-{version}.dist-info/METADATA`` is Metadata version 1.1 + or greater format metadata. +#. ``{distribution}-{version}.dist-info/WHEEL`` is metadata about the archive + itself in the same basic key: value format:: + + Wheel-Version: 1.9 + Generator: bdist_wheel 1.9 + Root-Is-Purelib: true + Tag: py2-none-any + Tag: py3-none-any + Build: 1 + Install-Paths-To: wheel/_paths.py + Install-Paths-To: wheel/_paths.json + +#. ``Wheel-Version`` is the version number of the Wheel specification. +#. ``Generator`` is the name and optionally the version of the software + that produced the archive. +#. ``Root-Is-Purelib`` is true if the top level directory of the archive + should be installed into purelib; otherwise the root should be installed + into platlib. +#. ``Tag`` is the wheel's expanded compatibility tags; in the example the + filename would contain ``py2.py3-none-any``. +#. ``Build`` is the build number and is omitted if there is no build number. +#. ``Install-Paths-To`` is a location *relative to the archive* that will be + overwritten with the install-time paths of each category in the install + scheme. See the install paths section. May appear 0 or more times. +#. A wheel installer should warn if Wheel-Version is greater than the + version it supports, and must fail if Wheel-Version has a greater + major version than the version it supports. +#. Wheel, being an installation format that is intended to work across + multiple versions of Python, does not generally include .pyc files. +#. Wheel does not contain setup.py or setup.cfg. + +The .dist-info directory +^^^^^^^^^^^^^^^^^^^^^^^^ + +#. Wheel .dist-info directories include at a minimum METADATA, WHEEL, + and RECORD. +#. METADATA is the package metadata, the same format as PKG-INFO as + found at the root of sdists. +#. WHEEL is the wheel metadata specific to a build of the package. +#. RECORD is a list of (almost) all the files in the wheel and their + secure hashes. Unlike PEP 376, every file except RECORD, which + cannot contain a hash of itself, must include its hash. The hash + algorithm must be sha256 or better; specifically, md5 and sha1 are + not permitted, as signed wheel files rely on the strong hashes in + RECORD to validate the integrity of the archive. +#. PEP 376's INSTALLER and REQUESTED are not included in the archive. +#. RECORD.jws is used for digital signatures. It is not mentioned in + RECORD. +#. RECORD.p7s is allowed as a courtesy to anyone who would prefer to + use S/MIME signatures to secure their wheel files. It is not + mentioned in RECORD. +#. During extraction, wheel installers verify all the hashes in RECORD + against the file contents. Apart from RECORD and its signatures, + installation will fail if any file in the archive is not both + mentioned and correctly hashed in RECORD. + +The .data directory +^^^^^^^^^^^^^^^^^^^ + +Any file that is not normally installed inside site-packages goes into +the .data directory, named as the .dist-info directory but with the +.data/ extension:: + + distribution-1.0.dist-info/ + + distribution-1.0.data/ + +The .data directory contains subdirectories with the scripts, headers, +documentation and so forth from the distribution. During installation the +contents of these subdirectories are moved onto their destination paths. + +If a subdirectory is not found in the install scheme, the installer should +emit a warning, and it should be installed at ``distribution-1.0.data/...`` +as if the package was unpacked by a standard unzip tool. + +Install paths +^^^^^^^^^^^^^ + +In addition to the distutils install paths, wheel now includes the listed +categories based on GNU autotools. This expanded scheme should help installers +to implement system policy, but installers may root each category at any +location. + +A UNIX install scheme might map the categories to their installation patnhs +like this:: + + { + 'bindir': '$eprefix/bin', + 'sbindir': '$eprefix/sbin', + 'libexecdir': '$eprefix/libexec', + 'sysconfdir': '$prefix/etc', + 'sharedstatedir': '$prefix/com', + 'localstatedir': '$prefix/var', + 'libdir': '$eprefix/lib', + 'static_libdir': r'$prefix/lib', + 'includedir': '$prefix/include', + 'datarootdir': '$prefix/share', + 'datadir': '$datarootdir', + 'mandir': '$datarootdir/man', + 'infodir': '$datarootdir/info', + 'localedir': '$datarootdir/locale', + 'docdir': '$datarootdir/doc/$dist_name', + 'htmldir': '$docdir', + 'dvidir': '$docdir', + 'psdir': '$docdir', + 'pdfdir': '$docdir', + 'pkgdatadir': '$datadir/$dist_name' + } + +If a package needs to find its files at runtime, it can request +they be written to a specified file or files by the installer *and* +included in those same files inside the archive itself, relative +to their location within the archive (so a wheel is still installed +correctly if unpacked with a standard unzip tool, or perhaps not +unpacked at all). + +If the ``WHEEL`` metadata contains these files: + + Install-Paths-To: wheel/_paths.py + Install-Paths-To: wheel/_paths.json + +Then the wheel installer, when it is about to unpack ``wheel/_paths.py`` from +the archive, replaces it with the actual paths used at install time. The +paths may be absolute or relative to the generated file. + +If the filename ends with ``.py`` then a Python script is written. The +script MUST be executed to get the paths, but it will probably look like +this:: + + data='../wheel-0.26.0.dev1.data/data' + headers='../wheel-0.26.0.dev1.data/headers' + platlib='../wheel-0.26.0.dev1.data/platlib' + purelib='../wheel-0.26.0.dev1.data/purelib' + scripts='../wheel-0.26.0.dev1.data/scripts' + # ... + +If the filename ends with ``.json`` then a JSON document is written:: + + { "data": "../wheel-0.26.0.dev1.data/data", ... } + +Only the categories actually used by a particular wheel must be written to +this file. + +These files are designed to be written to a location that can be found by the +installed package without introducing any dependency on a packaging library. + + +Signed wheel files +------------------ + +Wheel files include an extended RECORD that enables digital +signatures. PEP 376's RECORD is altered to include a secure hash +``digestname=urlsafe_b64encode_nopad(digest)`` (urlsafe base64 +encoding with no trailing = characters) as the second column instead +of an md5sum. All possible entries are hashed, including any +generated files such as .pyc files, but not RECORD which cannot contain its +own hash. For example:: + + file.py,sha256=AVTFPZpEKzuHr7OvQZmhaU3LvwKz06AJw8mT\_pNh2yI,3144 + distribution-1.0.dist-info/RECORD,, + +The signature file(s) RECORD.jws and RECORD.p7s are not mentioned in +RECORD at all since they can only be added after RECORD is generated. +Every other file in the archive must have a correct hash in RECORD +or the installation will fail. + +If JSON web signatures are used, one or more JSON Web Signature JSON +Serialization (JWS-JS) signatures is stored in a file RECORD.jws adjacent +to RECORD. JWS is used to sign RECORD by including the SHA-256 hash of +RECORD as the signature's JSON payload:: + + { "hash": "sha256=ADD-r2urObZHcxBW3Cr-vDCu5RJwT4CaRTHiFmbcIYY" } + +(The hash value is the same format used in RECORD.) + +If RECORD.p7s is used, it must contain a detached S/MIME format signature +of RECORD. + +A wheel installer is not required to understand digital signatures but +MUST verify the hashes in RECORD against the extracted file contents. +When the installer checks file hashes against RECORD, a separate signature +checker only needs to establish that RECORD matches the signature. + +See + +- http://self-issued.info/docs/draft-ietf-jose-json-web-signature.html +- http://self-issued.info/docs/draft-jones-jose-jws-json-serialization.html +- http://self-issued.info/docs/draft-ietf-jose-json-web-key.html +- http://self-issued.info/docs/draft-jones-jose-json-private-key.html + + +Comparison to .egg +------------------ + +#. Wheel is an installation format; egg is importable. Wheel archives + do not need to include .pyc and are less tied to a specific Python + version or implementation. Wheel can install (pure Python) packages + built with previous versions of Python so you don't always have to + wait for the packager to catch up. +#. Wheel uses .dist-info directories; egg uses .egg-info. Wheel is + compatible with the new world of Python packaging and the new + concepts it brings. +#. Wheel has a richer file naming convention for today's + multi-implementation world. A single wheel archive can indicate + its compatibility with a number of Python language versions and + implementations, ABIs, and system architectures. Historically the + ABI has been specific to a CPython release, wheel is ready for the + stable ABI. +#. Wheel is lossless. The first wheel implementation bdist_wheel + always generates egg-info, and then converts it to a .whl. It is + also possible to convert existing eggs and bdist_wininst + distributions. +#. Wheel is versioned. Every wheel file contains the version of the + wheel specification and the implementation that packaged it. + Hopefully the next migration can simply be to Wheel 2.0. +#. Wheel is a reference to the other Python. + + +FAQ +=== + + +Wheel defines a .data directory. Should I put all my data there? +----------------------------------------------------------------- + + This specification does not have an opinion on how you should organize + your code. The .data directory is just a place for any files that are + not normally installed inside ``site-packages`` or on the PYTHONPATH. + In other words, you may continue to use ``pkgutil.get_data(package, + resource)`` even though *those* files will usually not be distributed + in *wheel's* ``.data`` directory. + + +Why does wheel include attached signatures? +------------------------------------------- + + Attached signatures are more convenient than detached signatures + because they travel with the archive. Since only the individual files + are signed, the archive can be recompressed without invalidating + the signature or individual files can be verified without having + to download the whole archive. + + +Why does wheel allow JWS signatures? +------------------------------------ + + The JOSE specifications of which JWS is a part are designed to be easy + to implement, a feature that is also one of wheel's primary design + goals. JWS yields a useful, concise pure-Python implementation. + + +Why does wheel also allow S/MIME signatures? +-------------------------------------------- + + S/MIME signatures are allowed for users who need or want to use + existing public key infrastructure with wheel. + + Signed packages are only a basic building block in a secure package + update system. Wheel only provides the building block. + + +What's the deal with "purelib" vs. "platlib"? +--------------------------------------------- + + Wheel preserves the "purelib" vs. "platlib" distinction, which is + significant on some platforms. For example, Fedora installs pure + Python packages to '/usr/lib/pythonX.Y/site-packages' and platform + dependent packages to '/usr/lib64/pythonX.Y/site-packages'. + + A wheel with "Root-Is-Purelib: false" with all its files + in ``{name}-{version}.data/purelib`` is equivalent to a wheel with + "Root-Is-Purelib: true" with those same files in the root, and it + is legal to have files in both the "purelib" and "platlib" categories. + + In practice a wheel should have only one of "purelib" or "platlib" + depending on whether it is pure Python or not and those files should + be at the root with the appropriate setting given for "Root-is-purelib". + + +Is it possible to import Python code directly from a wheel file? +---------------------------------------------------------------- + + Technically, due to the combination of supporting installation via + simple extraction and using an archive format that is compatible with + ``zipimport``, a subset of wheel files *do* support being placed directly + on ``sys.path``. However, while this behaviour is a natural consequence + of the format design, actually relying on it is generally discouraged. + + Firstly, wheel *is* designed primarily as a distribution format, so + skipping the installation step also means deliberately avoiding any + reliance on features that assume full installation (such as being able + to use standard tools like ``pip`` and ``virtualenv`` to capture and + manage dependencies in a way that can be properly tracked for auditing + and security update purposes, or integrating fully with the standard + build machinery for C extensions by publishing header files in the + appropriate place). + + Secondly, while some Python software is written to support running + directly from a zip archive, it is still common for code to be written + assuming it has been fully installed. When that assumption is broken + by trying to run the software from a zip archive, the failures can often + be obscure and hard to diagnose (especially when they occur in third + party libraries). The two most common sources of problems with this + are the fact that importing C extensions from a zip archive is *not* + supported by CPython (since doing so is not supported directly by the + dynamic loading machinery on any platform) and that when running from + a zip archive the ``__file__`` attribute no longer refers to an + ordinary filesystem path, but to a combination path that includes + both the location of the zip archive on the filesystem and the + relative path to the module inside the archive. Even when software + correctly uses the abstract resource APIs internally, interfacing with + external components may still require the availability of an actual + on-disk file. + + Like metaclasses, monkeypatching and metapath importers, if you're not + already sure you need to take advantage of this feature, you almost + certainly don't need it. If you *do* decide to use it anyway, be + aware that many projects will require a failure to be reproduced with + a fully installed package before accepting it as a genuine bug. + + +References +========== + +.. [1] PEP acceptance + (http://mail.python.org/pipermail/python-dev/2013-February/124103.html) + + +Appendix +======== + +Example urlsafe-base64-nopad implementation:: + + # urlsafe-base64-nopad for Python 3 + import base64 + + def urlsafe_b64encode_nopad(data): + return base64.urlsafe_b64encode(data).rstrip(b'=') + + def urlsafe_b64decode_nopad(data): + pad = b'=' * (4 - (len(data) & 3)) + return base64.urlsafe_b64decode(data + pad) + + +Copyright +========= + +This document has been placed into the public domain. + + + +.. + Local Variables: + mode: indented-text + indent-tabs-mode: nil + sentence-end-double-space: t + fill-column: 70 + coding: utf-8 + End: -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Fri Apr 17 20:05:51 2015 From: python-checkins at python.org (berker.peksag) Date: Fri, 17 Apr 2015 18:05:51 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_PEP_489=3A_Update_from_Petr?= =?utf-8?q?=2E?= Message-ID: <20150417180551.27928.61535@psf.io> https://hg.python.org/peps/rev/3c57b668084d changeset: 5760:3c57b668084d user: Berker Peksag date: Fri Apr 17 21:05:59 2015 +0300 summary: PEP 489: Update from Petr. files: pep-0489.txt | 62 +++++++++++++++++++++------------------ 1 files changed, 33 insertions(+), 29 deletions(-) diff --git a/pep-0489.txt b/pep-0489.txt --- a/pep-0489.txt +++ b/pep-0489.txt @@ -128,13 +128,13 @@ typedef struct { int slot; void *value; - } PyModuleDesc_Slot; + } PyModuleExport_Slot; typedef struct { const char* doc; int flags; - PyModuleDesc_Slot *slots; - } PyModuleDesc; + PyModuleExport_Slot *slots; + } PyModuleExport; The *doc* member specifies the module's docstring. @@ -142,7 +142,7 @@ in "Singleton Modules" below. Other flag values may be added in the future. -The *slots* points to an array of PyModuleDesc_Slot structures, terminated +The *slots* points to an array of PyModuleExport_Slot structures, terminated by a slot with id set to 0 (i.e. ``{0, NULL}``). To specify a slot, a unique slot ID must be provided. @@ -164,7 +164,7 @@ .. note:: - An alternate proposal is to use PyModuleDef instead of PyModuleDesc, + An alternate proposal is to use PyModuleDef instead of PyModuleExport, re-purposing the m_reload pointer to hold the slots:: typedef struct PyModuleDef { @@ -173,7 +173,7 @@ const char* m_doc; Py_ssize_t m_size; PyMethodDef *m_methods; - PyModuleDesc_Slot* m_slots; /* changed from `inquiry m_reload;` */ + PyModuleExport_Slot* m_slots; /* changed from `inquiry m_reload;` */ traverseproc m_traverse; inquiry m_clear; freefunc m_free; @@ -197,10 +197,10 @@ The Py_mod_create slot is used to support custom module subclasses. The value pointer must point to a function with the following signature:: - PyObject* (*PyModuleCreateFunction)(PyObject *spec, PyModuleDesc *desc) + PyObject* (*PyModuleCreateFunction)(PyObject *spec, PyModuleExport *exp) The function receives a ModuleSpec instance, as defined in PEP 451, -and the PyModuleDesc structure. +and the PyModuleExport structure. It should return a new module object, or set an error and return NULL. @@ -213,12 +213,12 @@ getting attributes, including at least the import-related attributes. If a module instance is returned from Py_mod_create, the import machinery will -store a pointer to PyModuleDesc in the module object so that it may be -retrieved by PyModule_GetDesc (described later). +store a pointer to PyModuleExport in the module object so that it may be +retrieved by PyModule_GetExport (described later). .. note:: - If PyModuleDef is used instead of PyModuleDesc, the def is stored + If PyModuleDef is used instead of PyModuleExport, the def is stored instead, to be retrieved by PyModule_GetDef. Note that when this function is called, the module's entry in sys.modules @@ -230,6 +230,9 @@ Multiple Py_mod_create slots may not be specified. If they are, import will fail with ImportError. +If Py_mod_create is not specified, the import machinery will create a normal +module object, as if by calling PyModule_Create. + Py_mod_statedef ............... @@ -290,7 +293,7 @@ Py_mod_exec ........... -The function in this slot must have the signature:: +The entry in this slot must point to a function with the following signature:: int (*PyModuleExecFunction)(PyObject* module) @@ -298,7 +301,7 @@ setting the module's initial attributes. The "module" argument receives the module object to initialize. This will -always be the module object created from the corresponding PyModuleDesc. +always be the module object created from the corresponding PyModuleExport. When this function is called, import-related attributes (such as ``__spec__``) will have been set, and the module has already been added to sys.modules. @@ -317,20 +320,21 @@ ----------- If the PyModuleExport function is not defined, the import machinery will try to -initialize the module using the PyInit hook, as described in PEP 3121. +initialize the module using the "PyInit_" hook, +as described in PEP 3121. -If PyModuleExport is defined, PyModuleInit will be ignored. +If the PyModuleExport function is defined, the PyInit function will be ignored. Modules requiring compatibility with previous versions of CPython may implement -PyModuleInit in addition to the new hook. +the PyInit function in addition to the new hook. Modules using the legacy init API will be initialized entirely in the Loader.create_module step; Loader.exec_module will be a no-op. -.. XXX: Give example code for a backwards-compatible Init based on slots +.. XXX: Give example code for a backwards-compatible PyInit based on slots .. note:: - If PyModuleDef is reused, implementing the PyInit hook becomes easy: + If PyModuleDef is reused, implementing the PyInit function becomes easy: * call PyModule_Create with the PyModuleDef (m_reload was ignored in previous Python versions, so the slots array will be ignored). @@ -354,16 +358,16 @@ with no mutable or user-settable class attributes. -PyModule_GetDesc ----------------- +PyModule_GetExport +------------------ -To retrieve the PyModuleDesc structure used to create a module, +To retrieve the PyModuleExport structure used to create a module, a new function will be added:: - PyModuleDesc* PyModule_GetDesc(PyObject *module) + PyModuleExport* PyModule_GetExport(PyObject *module) The function returns NULL if the parameter is not a module object, or was not -created using PyModuleDesc. +created using PyModuleExport. .. note:: @@ -389,7 +393,7 @@ However, there are some modules that really need to be only loaded once: typically ones that wrap a C library with global state. These modules should set the PyModule_EXPORT_SINGLETON flag -in PyModuleDesc.flags. When this flag is set, loading an additional +in PyModuleExport.flags. When this flag is set, loading an additional copy of the module after it has been loaded once will return the previously loaded object. This will be done on a low level, using _PyImport_FixupExtensionObject. @@ -401,21 +405,21 @@ PyModuleDef counterparts, PyState_FindModule, PyState_AddModule, and PyState_RemoveModule:: - PyObject* PyState_FindSingletonModule(PyModuleDesc *desc) - int PyState_AddSingletonModule(PyObject *module, PyModuleDesc *desc) - int PyState_RemoveSingletonModule(PyModuleDesc *desc) + PyObject* PyState_FindSingletonModule(PyModuleExport *exp) + int PyState_AddSingletonModule(PyObject *module, PyModuleExport *exp) + int PyState_RemoveSingletonModule(PyModuleExport *exp) .. note:: - If PyModuleDef is used instead of PyModuleDesc, the flag would be specified + If PyModuleDef is used instead of PyModuleExport, the flag would be specified as a slot with NULL value, i.e. ``{Py_mod_flag_singleton, NULL}``. In this case, PyState_FindModule, PyState_AddModule and PyState_RemoveModule can be used instead of the new functions. .. note:: - Another possibility is to use PyModuleDef_Base in PyModuleDesc, and + Another possibility is to use PyModuleDef_Base in PyModuleExport, and have PyState_FindModule and friends work with either of the two structures. -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Fri Apr 17 20:06:44 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Fri, 17 Apr 2015 18:06:44 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2320184=3A_Converte?= =?utf-8?q?d_=5Fdbm_and_=5Fgdbm_modules_to_Argument_Clinic=2E?= Message-ID: <20150417180644.21331.79082@psf.io> https://hg.python.org/cpython/rev/49910ff21ba5 changeset: 95702:49910ff21ba5 user: Serhiy Storchaka date: Fri Apr 17 21:05:18 2015 +0300 summary: Issue #20184: Converted _dbm and _gdbm modules to Argument Clinic. files: Modules/_dbmmodule.c | 128 +- Modules/_gdbmmodule.c | 306 ++++--- Modules/clinic/_dbmmodule.c.h | 90 ++- Modules/_gdbmmodule.c | 782 +++++---------------- 4 files changed, 534 insertions(+), 772 deletions(-) diff --git a/Modules/_dbmmodule.c b/Modules/_dbmmodule.c --- a/Modules/_dbmmodule.c +++ b/Modules/_dbmmodule.c @@ -29,10 +29,10 @@ #endif /*[clinic input] -module dbm -class dbm.dbm "dbmobject *" "&Dbmtype" +module _dbm +class _dbm.dbm "dbmobject *" "&Dbmtype" [clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=92450564684a69a3]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=9b1aa8756d16150e]*/ typedef struct { PyObject_HEAD @@ -51,15 +51,6 @@ static PyObject *DbmError; -/*[python input] -class dbmobject_converter(self_converter): - type = "dbmobject *" - def pre_render(self): - super().pre_render() - self.name = 'dp' -[python start generated code]*/ -/*[python end generated code: output=da39a3ee5e6b4b0d input=6ad536357913879a]*/ - static PyObject * newdbmobject(const char *file, int flags, int mode) { @@ -183,29 +174,43 @@ (objobjargproc)dbm_ass_sub, /*mp_ass_subscript*/ }; +/*[clinic input] +_dbm.dbm.close + +Close the database. +[clinic start generated code]*/ + static PyObject * -dbm__close(dbmobject *dp, PyObject *unused) +_dbm_dbm_close_impl(dbmobject *self) +/*[clinic end generated code: output=c8dc5b6709600b86 input=046db72377d51be8]*/ { - if (dp->di_dbm) - dbm_close(dp->di_dbm); - dp->di_dbm = NULL; + if (self->di_dbm) + dbm_close(self->di_dbm); + self->di_dbm = NULL; Py_INCREF(Py_None); return Py_None; } +/*[clinic input] +_dbm.dbm.keys + +Return a list of all keys in the database. +[clinic start generated code]*/ + static PyObject * -dbm_keys(dbmobject *dp, PyObject *unused) +_dbm_dbm_keys_impl(dbmobject *self) +/*[clinic end generated code: output=434549f7c121b33c input=d210ba778cd9c68a]*/ { PyObject *v, *item; datum key; int err; - check_dbmobject_open(dp); + check_dbmobject_open(self); v = PyList_New(0); if (v == NULL) return NULL; - for (key = dbm_firstkey(dp->di_dbm); key.dptr; - key = dbm_nextkey(dp->di_dbm)) { + for (key = dbm_firstkey(self->di_dbm); key.dptr; + key = dbm_nextkey(self->di_dbm)) { item = PyBytes_FromStringAndSize(key.dptr, key.dsize); if (item == NULL) { Py_DECREF(v); @@ -267,29 +272,26 @@ }; /*[clinic input] - -dbm.dbm.get - - self: dbmobject +_dbm.dbm.get key: str(types={'str', 'robuffer'}, length=True) - default: object = None + default: object(c_default="NULL") = b'' / Return the value for key if present, otherwise default. [clinic start generated code]*/ static PyObject * -dbm_dbm_get_impl(dbmobject *dp, const char *key, Py_ssize_clean_t key_length, - PyObject *default_value) -/*[clinic end generated code: output=4f5c0e523eaf1251 input=f81478bc211895ef]*/ +_dbm_dbm_get_impl(dbmobject *self, const char *key, + Py_ssize_clean_t key_length, PyObject *default_value) +/*[clinic end generated code: output=b44f95eba8203d93 input=fee97bbe85e84822]*/ { datum dbm_key, val; dbm_key.dptr = (char *)key; dbm_key.dsize = key_length; - check_dbmobject_open(dp); - val = dbm_fetch(dp->di_dbm, dbm_key); + check_dbmobject_open(self); + val = dbm_fetch(self->di_dbm, dbm_key); if (val.dptr != NULL) return PyBytes_FromStringAndSize(val.dptr, val.dsize); @@ -297,46 +299,55 @@ return default_value; } +/*[clinic input] +_dbm.dbm.setdefault + key: str(types={'str', 'robuffer'}, length=True) + default: object(c_default="NULL") = b'' + / + +Return the value for key if present, otherwise default. + +If key is not in the database, it is inserted with default as the value. +[clinic start generated code]*/ + static PyObject * -dbm_setdefault(dbmobject *dp, PyObject *args) +_dbm_dbm_setdefault_impl(dbmobject *self, const char *key, + Py_ssize_clean_t key_length, + PyObject *default_value) +/*[clinic end generated code: output=52545886cf272161 input=6a3b99ae91f20203]*/ { - datum key, val; - PyObject *defvalue = NULL; - char *tmp_ptr; + datum dbm_key, val; Py_ssize_t tmp_size; - if (!PyArg_ParseTuple(args, "s#|O:setdefault", - &tmp_ptr, &tmp_size, &defvalue)) - return NULL; - key.dptr = tmp_ptr; - key.dsize = tmp_size; - check_dbmobject_open(dp); - val = dbm_fetch(dp->di_dbm, key); + dbm_key.dptr = (char *)key; + dbm_key.dsize = key_length; + check_dbmobject_open(self); + val = dbm_fetch(self->di_dbm, dbm_key); if (val.dptr != NULL) return PyBytes_FromStringAndSize(val.dptr, val.dsize); - if (defvalue == NULL) { - defvalue = PyBytes_FromStringAndSize(NULL, 0); - if (defvalue == NULL) + if (default_value == NULL) { + default_value = PyBytes_FromStringAndSize(NULL, 0); + if (default_value == NULL) return NULL; val.dptr = NULL; val.dsize = 0; } else { - if ( !PyArg_Parse(defvalue, "s#", &val.dptr, &tmp_size) ) { + if ( !PyArg_Parse(default_value, "s#", &val.dptr, &tmp_size) ) { PyErr_SetString(PyExc_TypeError, "dbm mappings have byte string elements only"); return NULL; } val.dsize = tmp_size; - Py_INCREF(defvalue); + Py_INCREF(default_value); } - if (dbm_store(dp->di_dbm, key, val, DBM_INSERT) < 0) { - dbm_clearerr(dp->di_dbm); + if (dbm_store(self->di_dbm, dbm_key, val, DBM_INSERT) < 0) { + dbm_clearerr(self->di_dbm); PyErr_SetString(DbmError, "cannot add item to database"); - Py_DECREF(defvalue); + Py_DECREF(default_value); return NULL; } - return defvalue; + return default_value; } static PyObject * @@ -355,15 +366,10 @@ static PyMethodDef dbm_methods[] = { - {"close", (PyCFunction)dbm__close, METH_NOARGS, - "close()\nClose the database."}, - {"keys", (PyCFunction)dbm_keys, METH_NOARGS, - "keys() -> list\nReturn a list of all keys in the database."}, - DBM_DBM_GET_METHODDEF - {"setdefault", (PyCFunction)dbm_setdefault, METH_VARARGS, - "setdefault(key[, default]) -> value\n" - "Return the value for key if present, otherwise default. If key\n" - "is not in the database, it is inserted with default as the value."}, + _DBM_DBM_CLOSE_METHODDEF + _DBM_DBM_KEYS_METHODDEF + _DBM_DBM_GET_METHODDEF + _DBM_DBM_SETDEFAULT_METHODDEF {"__enter__", dbm__enter__, METH_NOARGS, NULL}, {"__exit__", dbm__exit__, METH_VARARGS, NULL}, {NULL, NULL} /* sentinel */ @@ -404,7 +410,7 @@ /*[clinic input] -dbm.open as dbmopen +_dbm.open as dbmopen filename: str The filename to open. @@ -425,7 +431,7 @@ static PyObject * dbmopen_impl(PyModuleDef *module, const char *filename, const char *flags, int mode) -/*[clinic end generated code: output=e8d4b36f25c733fd input=6499ab0fab1333ac]*/ +/*[clinic end generated code: output=e8d4b36f25c733fd input=226334bade5764e6]*/ { int iflags; diff --git a/Modules/_gdbmmodule.c b/Modules/_gdbmmodule.c --- a/Modules/_gdbmmodule.c +++ b/Modules/_gdbmmodule.c @@ -16,17 +16,23 @@ extern const char * gdbm_strerror(gdbm_error); #endif +/*[clinic input] +module _gdbm +class _gdbm.gdbm "dbmobject *" "&Dbmtype" +[clinic start generated code]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=113927c6170729b2]*/ + PyDoc_STRVAR(gdbmmodule__doc__, "This module provides an interface to the GNU DBM (GDBM) library.\n\ \n\ This module is quite similar to the dbm module, but uses GDBM instead to\n\ -provide some additional functionality. Please note that the file formats\n\ -created by GDBM and dbm are incompatible. \n\ +provide some additional functionality. Please note that the file formats\n\ +created by GDBM and dbm are incompatible.\n\ \n\ GDBM objects behave like mappings (dictionaries), except that keys and\n\ -values are always strings. Printing a GDBM object doesn't print the\n\ -keys and values, and the items() and values() methods are not\n\ -supported."); +values are always immutable bytes-like objects or strings. Printing\n\ +a GDBM object doesn't print the keys and values, and the items() and\n\ +values() methods are not supported."); typedef struct { PyObject_HEAD @@ -36,6 +42,8 @@ static PyTypeObject Dbmtype; +#include "clinic/_gdbmmodule.c.h" + #define is_dbmobject(v) (Py_TYPE(v) == &Dbmtype) #define check_dbmobject_open(v) if ((v)->di_dbm == NULL) \ { PyErr_SetString(DbmError, "GDBM object has already been closed"); \ @@ -48,15 +56,15 @@ PyDoc_STRVAR(gdbm_object__doc__, "This object represents a GDBM database.\n\ GDBM objects behave like mappings (dictionaries), except that keys and\n\ -values are always strings. Printing a GDBM object doesn't print the\n\ -keys and values, and the items() and values() methods are not\n\ -supported.\n\ +values are always immutable bytes-like objects or strings. Printing\n\ +a GDBM object doesn't print the keys and values, and the items() and\n\ +values() methods are not supported.\n\ \n\ GDBM objects also support additional operations such as firstkey,\n\ nextkey, reorganize, and sync."); static PyObject * -newdbmobject(char *file, int flags, int mode) +newdbmobject(const char *file, int flags, int mode) { dbmobject *dp; @@ -65,7 +73,7 @@ return NULL; dp->di_size = -1; errno = 0; - if ((dp->di_dbm = gdbm_open(file, 0, flags, mode, NULL)) == 0) { + if ((dp->di_dbm = gdbm_open((char *)file, 0, flags, mode, NULL)) == 0) { if (errno != 0) PyErr_SetFromErrno(DbmError); else @@ -135,24 +143,27 @@ return v; } -PyDoc_STRVAR(dbm_get__doc__, -"get(key[, default]) -> value\n\ -Get the value for key, or default if not present; if not given,\n\ -default is None."); +/*[clinic input] +_gdbm.gdbm.get + + key: object + default: object = None + / + +Get the value for key, or default if not present. +[clinic start generated code]*/ static PyObject * -dbm_get(dbmobject *dp, PyObject *args) +_gdbm_gdbm_get_impl(dbmobject *self, PyObject *key, PyObject *default_value) +/*[clinic end generated code: output=19b7c585ad4f554a input=a9c20423f34c17b6]*/ { - PyObject *v, *res; - PyObject *def = Py_None; + PyObject *res; - if (!PyArg_UnpackTuple(args, "get", 1, 2, &v, &def)) - return NULL; - res = dbm_subscript(dp, v); + res = dbm_subscript(self, key); if (res == NULL && PyErr_ExceptionMatches(PyExc_KeyError)) { PyErr_Clear(); - Py_INCREF(def); - return def; + Py_INCREF(default_value); + return default_value; } return res; } @@ -198,25 +209,29 @@ return 0; } -PyDoc_STRVAR(dbm_setdefault__doc__, -"setdefault(key[, default]) -> value\n\ -Get value for key, or set it to default and return default if not present;\n\ -if not given, default is None."); +/*[clinic input] +_gdbm.gdbm.setdefault + + key: object + default: object = None + / + +Get value for key, or set it to default and return default if not present. +[clinic start generated code]*/ static PyObject * -dbm_setdefault(dbmobject *dp, PyObject *args) +_gdbm_gdbm_setdefault_impl(dbmobject *self, PyObject *key, + PyObject *default_value) +/*[clinic end generated code: output=88760ee520329012 input=0db46b69e9680171]*/ { - PyObject *v, *res; - PyObject *def = Py_None; + PyObject *res; - if (!PyArg_UnpackTuple(args, "setdefault", 1, 2, &v, &def)) - return NULL; - res = dbm_subscript(dp, v); + res = dbm_subscript(self, key); if (res == NULL && PyErr_ExceptionMatches(PyExc_KeyError)) { PyErr_Clear(); - if (dbm_ass_sub(dp, v, def) < 0) + if (dbm_ass_sub(self, key, default_value) < 0) return NULL; - return dbm_subscript(dp, v); + return dbm_subscript(self, key); } return res; } @@ -227,43 +242,49 @@ (objobjargproc)dbm_ass_sub, /*mp_ass_subscript*/ }; -PyDoc_STRVAR(dbm_close__doc__, -"close() -> None\n\ -Closes the database."); +/*[clinic input] +_gdbm.gdbm.close + +Close the database. +[clinic start generated code]*/ static PyObject * -dbm_close(dbmobject *dp, PyObject *unused) +_gdbm_gdbm_close_impl(dbmobject *self) +/*[clinic end generated code: output=23512a594598b563 input=0a203447379b45fd]*/ { - if (dp->di_dbm) - gdbm_close(dp->di_dbm); - dp->di_dbm = NULL; + if (self->di_dbm) + gdbm_close(self->di_dbm); + self->di_dbm = NULL; Py_INCREF(Py_None); return Py_None; } /* XXX Should return a set or a set view */ -PyDoc_STRVAR(dbm_keys__doc__, -"keys() -> list_of_keys\n\ -Get a list of all keys in the database."); +/*[clinic input] +_gdbm.gdbm.keys + +Get a list of all keys in the database. +[clinic start generated code]*/ static PyObject * -dbm_keys(dbmobject *dp, PyObject *unused) +_gdbm_gdbm_keys_impl(dbmobject *self) +/*[clinic end generated code: output=cb4b1776c3645dcc input=1832ee0a3132cfaf]*/ { PyObject *v, *item; datum key, nextkey; int err; - if (dp == NULL || !is_dbmobject(dp)) { + if (self == NULL || !is_dbmobject(self)) { PyErr_BadInternalCall(); return NULL; } - check_dbmobject_open(dp); + check_dbmobject_open(self); v = PyList_New(0); if (v == NULL) return NULL; - key = gdbm_firstkey(dp->di_dbm); + key = gdbm_firstkey(self->di_dbm); while (key.dptr) { item = PyBytes_FromStringAndSize(key.dptr, key.dsize); if (item == NULL) { @@ -278,7 +299,7 @@ Py_DECREF(v); return NULL; } - nextkey = gdbm_nextkey(dp->di_dbm, key); + nextkey = gdbm_nextkey(self->di_dbm, key); free(key.dptr); key = nextkey; } @@ -329,21 +350,25 @@ 0, /* sq_inplace_repeat */ }; -PyDoc_STRVAR(dbm_firstkey__doc__, -"firstkey() -> key\n\ -It's possible to loop over every key in the database using this method\n\ -and the nextkey() method. The traversal is ordered by GDBM's internal\n\ -hash values, and won't be sorted by the key values. This method\n\ -returns the starting key."); +/*[clinic input] +_gdbm.gdbm.firstkey + +Return the starting key for the traversal. + +It's possible to loop over every key in the database using this method +and the nextkey() method. The traversal is ordered by GDBM's internal +hash values, and won't be sorted by the key values. +[clinic start generated code]*/ static PyObject * -dbm_firstkey(dbmobject *dp, PyObject *unused) +_gdbm_gdbm_firstkey_impl(dbmobject *self) +/*[clinic end generated code: output=9ff85628d84b65d2 input=0dbd6a335d69bba0]*/ { PyObject *v; datum key; - check_dbmobject_open(dp); - key = gdbm_firstkey(dp->di_dbm); + check_dbmobject_open(self); + key = gdbm_firstkey(self->di_dbm); if (key.dptr) { v = PyBytes_FromStringAndSize(key.dptr, key.dsize); free(key.dptr); @@ -355,27 +380,35 @@ } } -PyDoc_STRVAR(dbm_nextkey__doc__, -"nextkey(key) -> next_key\n\ -Returns the key that follows key in the traversal.\n\ -The following code prints every key in the database db, without having\n\ -to create a list in memory that contains them all:\n\ -\n\ - k = db.firstkey()\n\ - while k != None:\n\ - print k\n\ - k = db.nextkey(k)"); +/*[clinic input] +_gdbm.gdbm.nextkey + + key: str(types={'str', 'robuffer'}, length=True) + / + +Returns the key that follows key in the traversal. + +The following code prints every key in the database db, without having +to create a list in memory that contains them all: + + k = db.firstkey() + while k != None: + print(k) + k = db.nextkey(k) +[clinic start generated code]*/ static PyObject * -dbm_nextkey(dbmobject *dp, PyObject *args) +_gdbm_gdbm_nextkey_impl(dbmobject *self, const char *key, + Py_ssize_clean_t key_length) +/*[clinic end generated code: output=192ab892de6eb2f6 input=df8e8828201214a6]*/ { PyObject *v; - datum key, nextkey; + datum dbm_key, nextkey; - if (!PyArg_ParseTuple(args, "s#:nextkey", &key.dptr, &key.dsize)) - return NULL; - check_dbmobject_open(dp); - nextkey = gdbm_nextkey(dp->di_dbm, key); + dbm_key.dptr = (char *)key; + dbm_key.dsize = key_length; + check_dbmobject_open(self); + nextkey = gdbm_nextkey(self->di_dbm, dbm_key); if (nextkey.dptr) { v = PyBytes_FromStringAndSize(nextkey.dptr, nextkey.dsize); free(nextkey.dptr); @@ -387,20 +420,25 @@ } } -PyDoc_STRVAR(dbm_reorganize__doc__, -"reorganize() -> None\n\ -If you have carried out a lot of deletions and would like to shrink\n\ -the space used by the GDBM file, this routine will reorganize the\n\ -database. GDBM will not shorten the length of a database file except\n\ -by using this reorganization; otherwise, deleted file space will be\n\ -kept and reused as new (key,value) pairs are added."); +/*[clinic input] +_gdbm.gdbm.reorganize + +Reorganize the database. + +If you have carried out a lot of deletions and would like to shrink +the space used by the GDBM file, this routine will reorganize the +database. GDBM will not shorten the length of a database file except +by using this reorganization; otherwise, deleted file space will be +kept and reused as new (key,value) pairs are added. +[clinic start generated code]*/ static PyObject * -dbm_reorganize(dbmobject *dp, PyObject *unused) +_gdbm_gdbm_reorganize_impl(dbmobject *self) +/*[clinic end generated code: output=38d9624df92e961d input=f6bea85bcfd40dd2]*/ { - check_dbmobject_open(dp); + check_dbmobject_open(self); errno = 0; - if (gdbm_reorganize(dp->di_dbm) < 0) { + if (gdbm_reorganize(self->di_dbm) < 0) { if (errno != 0) PyErr_SetFromErrno(DbmError); else @@ -411,16 +449,21 @@ return Py_None; } -PyDoc_STRVAR(dbm_sync__doc__, -"sync() -> None\n\ -When the database has been opened in fast mode, this method forces\n\ -any unwritten data to be written to the disk."); +/*[clinic input] +_gdbm.gdbm.sync + +Flush the database to the disk file. + +When the database has been opened in fast mode, this method forces +any unwritten data to be written to the disk. +[clinic start generated code]*/ static PyObject * -dbm_sync(dbmobject *dp, PyObject *unused) +_gdbm_gdbm_sync_impl(dbmobject *self) +/*[clinic end generated code: output=488b15f47028f125 input=2a47d2c9e153ab8a]*/ { - check_dbmobject_open(dp); - gdbm_sync(dp->di_dbm); + check_dbmobject_open(self); + gdbm_sync(self->di_dbm); Py_INCREF(Py_None); return Py_None; } @@ -440,14 +483,15 @@ } static PyMethodDef dbm_methods[] = { - {"close", (PyCFunction)dbm_close, METH_NOARGS, dbm_close__doc__}, - {"keys", (PyCFunction)dbm_keys, METH_NOARGS, dbm_keys__doc__}, - {"firstkey", (PyCFunction)dbm_firstkey,METH_NOARGS, dbm_firstkey__doc__}, - {"nextkey", (PyCFunction)dbm_nextkey, METH_VARARGS, dbm_nextkey__doc__}, - {"reorganize",(PyCFunction)dbm_reorganize,METH_NOARGS, dbm_reorganize__doc__}, - {"sync", (PyCFunction)dbm_sync, METH_NOARGS, dbm_sync__doc__}, - {"get", (PyCFunction)dbm_get, METH_VARARGS, dbm_get__doc__}, - {"setdefault",(PyCFunction)dbm_setdefault,METH_VARARGS, dbm_setdefault__doc__}, + _GDBM_GDBM_CLOSE_METHODDEF + _GDBM_GDBM_KEYS_METHODDEF + _GDBM_GDBM_FIRSTKEY_METHODDEF + _GDBM_GDBM_NEXTKEY_METHODDEF + _GDBM_GDBM_REORGANIZE_METHODDEF + _GDBM_GDBM_SYNC_METHODDEF + _GDBM_GDBM_GET_METHODDEF + _GDBM_GDBM_GET_METHODDEF + _GDBM_GDBM_SETDEFAULT_METHODDEF {"__enter__", dbm__enter__, METH_NOARGS, NULL}, {"__exit__", dbm__exit__, METH_VARARGS, NULL}, {NULL, NULL} /* sentinel */ @@ -486,40 +530,44 @@ /* ----------------------------------------------------------------- */ -PyDoc_STRVAR(dbmopen__doc__, -"open(filename, [flags, [mode]]) -> dbm_object\n\ -Open a dbm database and return a dbm object. The filename argument is\n\ -the name of the database file.\n\ -\n\ -The optional flags argument can be 'r' (to open an existing database\n\ -for reading only -- default), 'w' (to open an existing database for\n\ -reading and writing), 'c' (which creates the database if it doesn't\n\ -exist), or 'n' (which always creates a new empty database).\n\ -\n\ -Some versions of gdbm support additional flags which must be\n\ -appended to one of the flags described above. The module constant\n\ -'open_flags' is a string of valid additional flags. The 'f' flag\n\ -opens the database in fast mode; altered data will not automatically\n\ -be written to the disk after every change. This results in faster\n\ -writes to the database, but may result in an inconsistent database\n\ -if the program crashes while the database is still open. Use the\n\ -sync() method to force any unwritten data to be written to the disk.\n\ -The 's' flag causes all database operations to be synchronized to\n\ -disk. The 'u' flag disables locking of the database file.\n\ -\n\ -The optional mode argument is the Unix mode of the file, used only\n\ -when the database has to be created. It defaults to octal 0666. "); +/*[clinic input] +_gdbm.open as dbmopen + filename as name: str + flags: str="r" + mode: int(py_default="0o666") = 0o666 + / + +Open a dbm database and return a dbm object. + +The filename argument is the name of the database file. + +The optional flags argument can be 'r' (to open an existing database +for reading only -- default), 'w' (to open an existing database for +reading and writing), 'c' (which creates the database if it doesn't +exist), or 'n' (which always creates a new empty database). + +Some versions of gdbm support additional flags which must be +appended to one of the flags described above. The module constant +'open_flags' is a string of valid additional flags. The 'f' flag +opens the database in fast mode; altered data will not automatically +be written to the disk after every change. This results in faster +writes to the database, but may result in an inconsistent database +if the program crashes while the database is still open. Use the +sync() method to force any unwritten data to be written to the disk. +The 's' flag causes all database operations to be synchronized to +disk. The 'u' flag disables locking of the database file. + +The optional mode argument is the Unix mode of the file, used only +when the database has to be created. It defaults to octal 0o666. +[clinic start generated code]*/ static PyObject * -dbmopen(PyObject *self, PyObject *args) +dbmopen_impl(PyModuleDef *module, const char *name, const char *flags, + int mode) +/*[clinic end generated code: output=365b31415c03ccd4 input=55563cd60e51984a]*/ { - char *name; - char *flags = "r"; int iflags; - int mode = 0666; - if (!PyArg_ParseTuple(args, "s|si:open", &name, &flags, &mode)) - return NULL; switch (flags[0]) { case 'r': iflags = GDBM_READER; @@ -580,7 +628,7 @@ ; static PyMethodDef dbmmodule_methods[] = { - { "open", (PyCFunction)dbmopen, METH_VARARGS, dbmopen__doc__}, + DBMOPEN_METHODDEF { 0, 0 }, }; diff --git a/Modules/clinic/_dbmmodule.c.h b/Modules/clinic/_dbmmodule.c.h --- a/Modules/clinic/_dbmmodule.c.h +++ b/Modules/clinic/_dbmmodule.c.h @@ -2,32 +2,102 @@ preserve [clinic start generated code]*/ -PyDoc_STRVAR(dbm_dbm_get__doc__, -"get($self, key, default=None, /)\n" +PyDoc_STRVAR(_dbm_dbm_close__doc__, +"close($self, /)\n" +"--\n" +"\n" +"Close the database."); + +#define _DBM_DBM_CLOSE_METHODDEF \ + {"close", (PyCFunction)_dbm_dbm_close, METH_NOARGS, _dbm_dbm_close__doc__}, + +static PyObject * +_dbm_dbm_close_impl(dbmobject *self); + +static PyObject * +_dbm_dbm_close(dbmobject *self, PyObject *Py_UNUSED(ignored)) +{ + return _dbm_dbm_close_impl(self); +} + +PyDoc_STRVAR(_dbm_dbm_keys__doc__, +"keys($self, /)\n" +"--\n" +"\n" +"Return a list of all keys in the database."); + +#define _DBM_DBM_KEYS_METHODDEF \ + {"keys", (PyCFunction)_dbm_dbm_keys, METH_NOARGS, _dbm_dbm_keys__doc__}, + +static PyObject * +_dbm_dbm_keys_impl(dbmobject *self); + +static PyObject * +_dbm_dbm_keys(dbmobject *self, PyObject *Py_UNUSED(ignored)) +{ + return _dbm_dbm_keys_impl(self); +} + +PyDoc_STRVAR(_dbm_dbm_get__doc__, +"get($self, key, default=b\'\', /)\n" "--\n" "\n" "Return the value for key if present, otherwise default."); -#define DBM_DBM_GET_METHODDEF \ - {"get", (PyCFunction)dbm_dbm_get, METH_VARARGS, dbm_dbm_get__doc__}, +#define _DBM_DBM_GET_METHODDEF \ + {"get", (PyCFunction)_dbm_dbm_get, METH_VARARGS, _dbm_dbm_get__doc__}, static PyObject * -dbm_dbm_get_impl(dbmobject *dp, const char *key, Py_ssize_clean_t key_length, - PyObject *default_value); +_dbm_dbm_get_impl(dbmobject *self, const char *key, + Py_ssize_clean_t key_length, PyObject *default_value); static PyObject * -dbm_dbm_get(dbmobject *dp, PyObject *args) +_dbm_dbm_get(dbmobject *self, PyObject *args) { PyObject *return_value = NULL; const char *key; Py_ssize_clean_t key_length; - PyObject *default_value = Py_None; + PyObject *default_value = NULL; if (!PyArg_ParseTuple(args, "s#|O:get", &key, &key_length, &default_value)) goto exit; - return_value = dbm_dbm_get_impl(dp, key, key_length, default_value); + return_value = _dbm_dbm_get_impl(self, key, key_length, default_value); + +exit: + return return_value; +} + +PyDoc_STRVAR(_dbm_dbm_setdefault__doc__, +"setdefault($self, key, default=b\'\', /)\n" +"--\n" +"\n" +"Return the value for key if present, otherwise default.\n" +"\n" +"If key is not in the database, it is inserted with default as the value."); + +#define _DBM_DBM_SETDEFAULT_METHODDEF \ + {"setdefault", (PyCFunction)_dbm_dbm_setdefault, METH_VARARGS, _dbm_dbm_setdefault__doc__}, + +static PyObject * +_dbm_dbm_setdefault_impl(dbmobject *self, const char *key, + Py_ssize_clean_t key_length, + PyObject *default_value); + +static PyObject * +_dbm_dbm_setdefault(dbmobject *self, PyObject *args) +{ + PyObject *return_value = NULL; + const char *key; + Py_ssize_clean_t key_length; + PyObject *default_value = NULL; + + if (!PyArg_ParseTuple(args, + "s#|O:setdefault", + &key, &key_length, &default_value)) + goto exit; + return_value = _dbm_dbm_setdefault_impl(self, key, key_length, default_value); exit: return return_value; @@ -71,4 +141,4 @@ exit: return return_value; } -/*[clinic end generated code: output=d6ec55c6c5d0b19d input=a9049054013a1b77]*/ +/*[clinic end generated code: output=951fcfdb6d667a61 input=a9049054013a1b77]*/ diff --git a/Modules/_gdbmmodule.c b/Modules/clinic/_gdbmmodule.c.h copy from Modules/_gdbmmodule.c copy to Modules/clinic/_gdbmmodule.c.h --- a/Modules/_gdbmmodule.c +++ b/Modules/clinic/_gdbmmodule.c.h @@ -1,618 +1,256 @@ +/*[clinic input] +preserve +[clinic start generated code]*/ -/* DBM module using dictionary interface */ -/* Author: Anthony Baxter, after dbmmodule.c */ -/* Doc strings: Mitch Chapman */ +PyDoc_STRVAR(_gdbm_gdbm_get__doc__, +"get($self, key, default=None, /)\n" +"--\n" +"\n" +"Get the value for key, or default if not present."); - -#include "Python.h" - -#include -#include -#include -#include "gdbm.h" - -#if defined(WIN32) && !defined(__CYGWIN__) -#include "gdbmerrno.h" -extern const char * gdbm_strerror(gdbm_error); -#endif - -PyDoc_STRVAR(gdbmmodule__doc__, -"This module provides an interface to the GNU DBM (GDBM) library.\n\ -\n\ -This module is quite similar to the dbm module, but uses GDBM instead to\n\ -provide some additional functionality. Please note that the file formats\n\ -created by GDBM and dbm are incompatible. \n\ -\n\ -GDBM objects behave like mappings (dictionaries), except that keys and\n\ -values are always strings. Printing a GDBM object doesn't print the\n\ -keys and values, and the items() and values() methods are not\n\ -supported."); - -typedef struct { - PyObject_HEAD - int di_size; /* -1 means recompute */ - GDBM_FILE di_dbm; -} dbmobject; - -static PyTypeObject Dbmtype; - -#define is_dbmobject(v) (Py_TYPE(v) == &Dbmtype) -#define check_dbmobject_open(v) if ((v)->di_dbm == NULL) \ - { PyErr_SetString(DbmError, "GDBM object has already been closed"); \ - return NULL; } - - - -static PyObject *DbmError; - -PyDoc_STRVAR(gdbm_object__doc__, -"This object represents a GDBM database.\n\ -GDBM objects behave like mappings (dictionaries), except that keys and\n\ -values are always strings. Printing a GDBM object doesn't print the\n\ -keys and values, and the items() and values() methods are not\n\ -supported.\n\ -\n\ -GDBM objects also support additional operations such as firstkey,\n\ -nextkey, reorganize, and sync."); +#define _GDBM_GDBM_GET_METHODDEF \ + {"get", (PyCFunction)_gdbm_gdbm_get, METH_VARARGS, _gdbm_gdbm_get__doc__}, static PyObject * -newdbmobject(char *file, int flags, int mode) +_gdbm_gdbm_get_impl(dbmobject *self, PyObject *key, PyObject *default_value); + +static PyObject * +_gdbm_gdbm_get(dbmobject *self, PyObject *args) { - dbmobject *dp; + PyObject *return_value = NULL; + PyObject *key; + PyObject *default_value = Py_None; - dp = PyObject_New(dbmobject, &Dbmtype); - if (dp == NULL) - return NULL; - dp->di_size = -1; - errno = 0; - if ((dp->di_dbm = gdbm_open(file, 0, flags, mode, NULL)) == 0) { - if (errno != 0) - PyErr_SetFromErrno(DbmError); - else - PyErr_SetString(DbmError, gdbm_strerror(gdbm_errno)); - Py_DECREF(dp); - return NULL; - } - return (PyObject *)dp; + if (!PyArg_UnpackTuple(args, "get", + 1, 2, + &key, &default_value)) + goto exit; + return_value = _gdbm_gdbm_get_impl(self, key, default_value); + +exit: + return return_value; } -/* Methods */ +PyDoc_STRVAR(_gdbm_gdbm_setdefault__doc__, +"setdefault($self, key, default=None, /)\n" +"--\n" +"\n" +"Get value for key, or set it to default and return default if not present."); -static void -dbm_dealloc(dbmobject *dp) +#define _GDBM_GDBM_SETDEFAULT_METHODDEF \ + {"setdefault", (PyCFunction)_gdbm_gdbm_setdefault, METH_VARARGS, _gdbm_gdbm_setdefault__doc__}, + +static PyObject * +_gdbm_gdbm_setdefault_impl(dbmobject *self, PyObject *key, + PyObject *default_value); + +static PyObject * +_gdbm_gdbm_setdefault(dbmobject *self, PyObject *args) { - if (dp->di_dbm) - gdbm_close(dp->di_dbm); - PyObject_Del(dp); + PyObject *return_value = NULL; + PyObject *key; + PyObject *default_value = Py_None; + + if (!PyArg_UnpackTuple(args, "setdefault", + 1, 2, + &key, &default_value)) + goto exit; + return_value = _gdbm_gdbm_setdefault_impl(self, key, default_value); + +exit: + return return_value; } -static Py_ssize_t -dbm_length(dbmobject *dp) +PyDoc_STRVAR(_gdbm_gdbm_close__doc__, +"close($self, /)\n" +"--\n" +"\n" +"Close the database."); + +#define _GDBM_GDBM_CLOSE_METHODDEF \ + {"close", (PyCFunction)_gdbm_gdbm_close, METH_NOARGS, _gdbm_gdbm_close__doc__}, + +static PyObject * +_gdbm_gdbm_close_impl(dbmobject *self); + +static PyObject * +_gdbm_gdbm_close(dbmobject *self, PyObject *Py_UNUSED(ignored)) { - if (dp->di_dbm == NULL) { - PyErr_SetString(DbmError, "GDBM object has already been closed"); - return -1; - } - if (dp->di_size < 0) { - datum key,okey; - int size; - okey.dsize=0; - okey.dptr=NULL; - - size = 0; - for (key=gdbm_firstkey(dp->di_dbm); key.dptr; - key = gdbm_nextkey(dp->di_dbm,okey)) { - size++; - if(okey.dsize) free(okey.dptr); - okey=key; - } - dp->di_size = size; - } - return dp->di_size; + return _gdbm_gdbm_close_impl(self); } +PyDoc_STRVAR(_gdbm_gdbm_keys__doc__, +"keys($self, /)\n" +"--\n" +"\n" +"Get a list of all keys in the database."); + +#define _GDBM_GDBM_KEYS_METHODDEF \ + {"keys", (PyCFunction)_gdbm_gdbm_keys, METH_NOARGS, _gdbm_gdbm_keys__doc__}, + static PyObject * -dbm_subscript(dbmobject *dp, PyObject *key) +_gdbm_gdbm_keys_impl(dbmobject *self); + +static PyObject * +_gdbm_gdbm_keys(dbmobject *self, PyObject *Py_UNUSED(ignored)) { - PyObject *v; - datum drec, krec; - - if (!PyArg_Parse(key, "s#", &krec.dptr, &krec.dsize) ) - return NULL; - - if (dp->di_dbm == NULL) { - PyErr_SetString(DbmError, - "GDBM object has already been closed"); - return NULL; - } - drec = gdbm_fetch(dp->di_dbm, krec); - if (drec.dptr == 0) { - PyErr_SetObject(PyExc_KeyError, key); - return NULL; - } - v = PyBytes_FromStringAndSize(drec.dptr, drec.dsize); - free(drec.dptr); - return v; + return _gdbm_gdbm_keys_impl(self); } -PyDoc_STRVAR(dbm_get__doc__, -"get(key[, default]) -> value\n\ -Get the value for key, or default if not present; if not given,\n\ -default is None."); +PyDoc_STRVAR(_gdbm_gdbm_firstkey__doc__, +"firstkey($self, /)\n" +"--\n" +"\n" +"Return the starting key for the traversal.\n" +"\n" +"It\'s possible to loop over every key in the database using this method\n" +"and the nextkey() method. The traversal is ordered by GDBM\'s internal\n" +"hash values, and won\'t be sorted by the key values."); + +#define _GDBM_GDBM_FIRSTKEY_METHODDEF \ + {"firstkey", (PyCFunction)_gdbm_gdbm_firstkey, METH_NOARGS, _gdbm_gdbm_firstkey__doc__}, static PyObject * -dbm_get(dbmobject *dp, PyObject *args) +_gdbm_gdbm_firstkey_impl(dbmobject *self); + +static PyObject * +_gdbm_gdbm_firstkey(dbmobject *self, PyObject *Py_UNUSED(ignored)) { - PyObject *v, *res; - PyObject *def = Py_None; - - if (!PyArg_UnpackTuple(args, "get", 1, 2, &v, &def)) - return NULL; - res = dbm_subscript(dp, v); - if (res == NULL && PyErr_ExceptionMatches(PyExc_KeyError)) { - PyErr_Clear(); - Py_INCREF(def); - return def; - } - return res; + return _gdbm_gdbm_firstkey_impl(self); } -static int -dbm_ass_sub(dbmobject *dp, PyObject *v, PyObject *w) +PyDoc_STRVAR(_gdbm_gdbm_nextkey__doc__, +"nextkey($self, key, /)\n" +"--\n" +"\n" +"Returns the key that follows key in the traversal.\n" +"\n" +"The following code prints every key in the database db, without having\n" +"to create a list in memory that contains them all:\n" +"\n" +" k = db.firstkey()\n" +" while k != None:\n" +" print(k)\n" +" k = db.nextkey(k)"); + +#define _GDBM_GDBM_NEXTKEY_METHODDEF \ + {"nextkey", (PyCFunction)_gdbm_gdbm_nextkey, METH_O, _gdbm_gdbm_nextkey__doc__}, + +static PyObject * +_gdbm_gdbm_nextkey_impl(dbmobject *self, const char *key, + Py_ssize_clean_t key_length); + +static PyObject * +_gdbm_gdbm_nextkey(dbmobject *self, PyObject *arg) { - datum krec, drec; + PyObject *return_value = NULL; + const char *key; + Py_ssize_clean_t key_length; - if (!PyArg_Parse(v, "s#", &krec.dptr, &krec.dsize) ) { - PyErr_SetString(PyExc_TypeError, - "gdbm mappings have bytes or string indices only"); - return -1; - } - if (dp->di_dbm == NULL) { - PyErr_SetString(DbmError, - "GDBM object has already been closed"); - return -1; - } - dp->di_size = -1; - if (w == NULL) { - if (gdbm_delete(dp->di_dbm, krec) < 0) { - PyErr_SetObject(PyExc_KeyError, v); - return -1; - } - } - else { - if (!PyArg_Parse(w, "s#", &drec.dptr, &drec.dsize)) { - PyErr_SetString(PyExc_TypeError, - "gdbm mappings have byte or string elements only"); - return -1; - } - errno = 0; - if (gdbm_store(dp->di_dbm, krec, drec, GDBM_REPLACE) < 0) { - if (errno != 0) - PyErr_SetFromErrno(DbmError); - else - PyErr_SetString(DbmError, - gdbm_strerror(gdbm_errno)); - return -1; - } - } - return 0; + if (!PyArg_Parse(arg, + "s#:nextkey", + &key, &key_length)) + goto exit; + return_value = _gdbm_gdbm_nextkey_impl(self, key, key_length); + +exit: + return return_value; } -PyDoc_STRVAR(dbm_setdefault__doc__, -"setdefault(key[, default]) -> value\n\ -Get value for key, or set it to default and return default if not present;\n\ -if not given, default is None."); +PyDoc_STRVAR(_gdbm_gdbm_reorganize__doc__, +"reorganize($self, /)\n" +"--\n" +"\n" +"Reorganize the database.\n" +"\n" +"If you have carried out a lot of deletions and would like to shrink\n" +"the space used by the GDBM file, this routine will reorganize the\n" +"database. GDBM will not shorten the length of a database file except\n" +"by using this reorganization; otherwise, deleted file space will be\n" +"kept and reused as new (key,value) pairs are added."); + +#define _GDBM_GDBM_REORGANIZE_METHODDEF \ + {"reorganize", (PyCFunction)_gdbm_gdbm_reorganize, METH_NOARGS, _gdbm_gdbm_reorganize__doc__}, static PyObject * -dbm_setdefault(dbmobject *dp, PyObject *args) +_gdbm_gdbm_reorganize_impl(dbmobject *self); + +static PyObject * +_gdbm_gdbm_reorganize(dbmobject *self, PyObject *Py_UNUSED(ignored)) { - PyObject *v, *res; - PyObject *def = Py_None; - - if (!PyArg_UnpackTuple(args, "setdefault", 1, 2, &v, &def)) - return NULL; - res = dbm_subscript(dp, v); - if (res == NULL && PyErr_ExceptionMatches(PyExc_KeyError)) { - PyErr_Clear(); - if (dbm_ass_sub(dp, v, def) < 0) - return NULL; - return dbm_subscript(dp, v); - } - return res; + return _gdbm_gdbm_reorganize_impl(self); } -static PyMappingMethods dbm_as_mapping = { - (lenfunc)dbm_length, /*mp_length*/ - (binaryfunc)dbm_subscript, /*mp_subscript*/ - (objobjargproc)dbm_ass_sub, /*mp_ass_subscript*/ -}; +PyDoc_STRVAR(_gdbm_gdbm_sync__doc__, +"sync($self, /)\n" +"--\n" +"\n" +"Flush the database to the disk file.\n" +"\n" +"When the database has been opened in fast mode, this method forces\n" +"any unwritten data to be written to the disk."); -PyDoc_STRVAR(dbm_close__doc__, -"close() -> None\n\ -Closes the database."); +#define _GDBM_GDBM_SYNC_METHODDEF \ + {"sync", (PyCFunction)_gdbm_gdbm_sync, METH_NOARGS, _gdbm_gdbm_sync__doc__}, static PyObject * -dbm_close(dbmobject *dp, PyObject *unused) +_gdbm_gdbm_sync_impl(dbmobject *self); + +static PyObject * +_gdbm_gdbm_sync(dbmobject *self, PyObject *Py_UNUSED(ignored)) { - if (dp->di_dbm) - gdbm_close(dp->di_dbm); - dp->di_dbm = NULL; - Py_INCREF(Py_None); - return Py_None; + return _gdbm_gdbm_sync_impl(self); } -/* XXX Should return a set or a set view */ -PyDoc_STRVAR(dbm_keys__doc__, -"keys() -> list_of_keys\n\ -Get a list of all keys in the database."); +PyDoc_STRVAR(dbmopen__doc__, +"open($module, filename, flags=\'r\', mode=0o666, /)\n" +"--\n" +"\n" +"Open a dbm database and return a dbm object.\n" +"\n" +"The filename argument is the name of the database file.\n" +"\n" +"The optional flags argument can be \'r\' (to open an existing database\n" +"for reading only -- default), \'w\' (to open an existing database for\n" +"reading and writing), \'c\' (which creates the database if it doesn\'t\n" +"exist), or \'n\' (which always creates a new empty database).\n" +"\n" +"Some versions of gdbm support additional flags which must be\n" +"appended to one of the flags described above. The module constant\n" +"\'open_flags\' is a string of valid additional flags. The \'f\' flag\n" +"opens the database in fast mode; altered data will not automatically\n" +"be written to the disk after every change. This results in faster\n" +"writes to the database, but may result in an inconsistent database\n" +"if the program crashes while the database is still open. Use the\n" +"sync() method to force any unwritten data to be written to the disk.\n" +"The \'s\' flag causes all database operations to be synchronized to\n" +"disk. The \'u\' flag disables locking of the database file.\n" +"\n" +"The optional mode argument is the Unix mode of the file, used only\n" +"when the database has to be created. It defaults to octal 0o666."); + +#define DBMOPEN_METHODDEF \ + {"open", (PyCFunction)dbmopen, METH_VARARGS, dbmopen__doc__}, static PyObject * -dbm_keys(dbmobject *dp, PyObject *unused) -{ - PyObject *v, *item; - datum key, nextkey; - int err; - - if (dp == NULL || !is_dbmobject(dp)) { - PyErr_BadInternalCall(); - return NULL; - } - check_dbmobject_open(dp); - - v = PyList_New(0); - if (v == NULL) - return NULL; - - key = gdbm_firstkey(dp->di_dbm); - while (key.dptr) { - item = PyBytes_FromStringAndSize(key.dptr, key.dsize); - if (item == NULL) { - free(key.dptr); - Py_DECREF(v); - return NULL; - } - err = PyList_Append(v, item); - Py_DECREF(item); - if (err != 0) { - free(key.dptr); - Py_DECREF(v); - return NULL; - } - nextkey = gdbm_nextkey(dp->di_dbm, key); - free(key.dptr); - key = nextkey; - } - return v; -} - -static int -dbm_contains(PyObject *self, PyObject *arg) -{ - dbmobject *dp = (dbmobject *)self; - datum key; - Py_ssize_t size; - - if ((dp)->di_dbm == NULL) { - PyErr_SetString(DbmError, - "GDBM object has already been closed"); - return -1; - } - if (PyUnicode_Check(arg)) { - key.dptr = PyUnicode_AsUTF8AndSize(arg, &size); - key.dsize = size; - if (key.dptr == NULL) - return -1; - } - else if (!PyBytes_Check(arg)) { - PyErr_Format(PyExc_TypeError, - "gdbm key must be bytes or string, not %.100s", - arg->ob_type->tp_name); - return -1; - } - else { - key.dptr = PyBytes_AS_STRING(arg); - key.dsize = PyBytes_GET_SIZE(arg); - } - return gdbm_exists(dp->di_dbm, key); -} - -static PySequenceMethods dbm_as_sequence = { - 0, /* sq_length */ - 0, /* sq_concat */ - 0, /* sq_repeat */ - 0, /* sq_item */ - 0, /* sq_slice */ - 0, /* sq_ass_item */ - 0, /* sq_ass_slice */ - dbm_contains, /* sq_contains */ - 0, /* sq_inplace_concat */ - 0, /* sq_inplace_repeat */ -}; - -PyDoc_STRVAR(dbm_firstkey__doc__, -"firstkey() -> key\n\ -It's possible to loop over every key in the database using this method\n\ -and the nextkey() method. The traversal is ordered by GDBM's internal\n\ -hash values, and won't be sorted by the key values. This method\n\ -returns the starting key."); +dbmopen_impl(PyModuleDef *module, const char *name, const char *flags, + int mode); static PyObject * -dbm_firstkey(dbmobject *dp, PyObject *unused) +dbmopen(PyModuleDef *module, PyObject *args) { - PyObject *v; - datum key; + PyObject *return_value = NULL; + const char *name; + const char *flags = "r"; + int mode = 438; - check_dbmobject_open(dp); - key = gdbm_firstkey(dp->di_dbm); - if (key.dptr) { - v = PyBytes_FromStringAndSize(key.dptr, key.dsize); - free(key.dptr); - return v; - } - else { - Py_INCREF(Py_None); - return Py_None; - } + if (!PyArg_ParseTuple(args, + "s|si:open", + &name, &flags, &mode)) + goto exit; + return_value = dbmopen_impl(module, name, flags, mode); + +exit: + return return_value; } - -PyDoc_STRVAR(dbm_nextkey__doc__, -"nextkey(key) -> next_key\n\ -Returns the key that follows key in the traversal.\n\ -The following code prints every key in the database db, without having\n\ -to create a list in memory that contains them all:\n\ -\n\ - k = db.firstkey()\n\ - while k != None:\n\ - print k\n\ - k = db.nextkey(k)"); - -static PyObject * -dbm_nextkey(dbmobject *dp, PyObject *args) -{ - PyObject *v; - datum key, nextkey; - - if (!PyArg_ParseTuple(args, "s#:nextkey", &key.dptr, &key.dsize)) - return NULL; - check_dbmobject_open(dp); - nextkey = gdbm_nextkey(dp->di_dbm, key); - if (nextkey.dptr) { - v = PyBytes_FromStringAndSize(nextkey.dptr, nextkey.dsize); - free(nextkey.dptr); - return v; - } - else { - Py_INCREF(Py_None); - return Py_None; - } -} - -PyDoc_STRVAR(dbm_reorganize__doc__, -"reorganize() -> None\n\ -If you have carried out a lot of deletions and would like to shrink\n\ -the space used by the GDBM file, this routine will reorganize the\n\ -database. GDBM will not shorten the length of a database file except\n\ -by using this reorganization; otherwise, deleted file space will be\n\ -kept and reused as new (key,value) pairs are added."); - -static PyObject * -dbm_reorganize(dbmobject *dp, PyObject *unused) -{ - check_dbmobject_open(dp); - errno = 0; - if (gdbm_reorganize(dp->di_dbm) < 0) { - if (errno != 0) - PyErr_SetFromErrno(DbmError); - else - PyErr_SetString(DbmError, gdbm_strerror(gdbm_errno)); - return NULL; - } - Py_INCREF(Py_None); - return Py_None; -} - -PyDoc_STRVAR(dbm_sync__doc__, -"sync() -> None\n\ -When the database has been opened in fast mode, this method forces\n\ -any unwritten data to be written to the disk."); - -static PyObject * -dbm_sync(dbmobject *dp, PyObject *unused) -{ - check_dbmobject_open(dp); - gdbm_sync(dp->di_dbm); - Py_INCREF(Py_None); - return Py_None; -} - -static PyObject * -dbm__enter__(PyObject *self, PyObject *args) -{ - Py_INCREF(self); - return self; -} - -static PyObject * -dbm__exit__(PyObject *self, PyObject *args) -{ - _Py_IDENTIFIER(close); - return _PyObject_CallMethodId(self, &PyId_close, NULL); -} - -static PyMethodDef dbm_methods[] = { - {"close", (PyCFunction)dbm_close, METH_NOARGS, dbm_close__doc__}, - {"keys", (PyCFunction)dbm_keys, METH_NOARGS, dbm_keys__doc__}, - {"firstkey", (PyCFunction)dbm_firstkey,METH_NOARGS, dbm_firstkey__doc__}, - {"nextkey", (PyCFunction)dbm_nextkey, METH_VARARGS, dbm_nextkey__doc__}, - {"reorganize",(PyCFunction)dbm_reorganize,METH_NOARGS, dbm_reorganize__doc__}, - {"sync", (PyCFunction)dbm_sync, METH_NOARGS, dbm_sync__doc__}, - {"get", (PyCFunction)dbm_get, METH_VARARGS, dbm_get__doc__}, - {"setdefault",(PyCFunction)dbm_setdefault,METH_VARARGS, dbm_setdefault__doc__}, - {"__enter__", dbm__enter__, METH_NOARGS, NULL}, - {"__exit__", dbm__exit__, METH_VARARGS, NULL}, - {NULL, NULL} /* sentinel */ -}; - -static PyTypeObject Dbmtype = { - PyVarObject_HEAD_INIT(0, 0) - "_gdbm.gdbm", - sizeof(dbmobject), - 0, - (destructor)dbm_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_reserved*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - &dbm_as_sequence, /*tp_as_sequence*/ - &dbm_as_mapping, /*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_xxx4*/ - gdbm_object__doc__, /*tp_doc*/ - 0, /*tp_traverse*/ - 0, /*tp_clear*/ - 0, /*tp_richcompare*/ - 0, /*tp_weaklistoffset*/ - 0, /*tp_iter*/ - 0, /*tp_iternext*/ - dbm_methods, /*tp_methods*/ -}; - -/* ----------------------------------------------------------------- */ - -PyDoc_STRVAR(dbmopen__doc__, -"open(filename, [flags, [mode]]) -> dbm_object\n\ -Open a dbm database and return a dbm object. The filename argument is\n\ -the name of the database file.\n\ -\n\ -The optional flags argument can be 'r' (to open an existing database\n\ -for reading only -- default), 'w' (to open an existing database for\n\ -reading and writing), 'c' (which creates the database if it doesn't\n\ -exist), or 'n' (which always creates a new empty database).\n\ -\n\ -Some versions of gdbm support additional flags which must be\n\ -appended to one of the flags described above. The module constant\n\ -'open_flags' is a string of valid additional flags. The 'f' flag\n\ -opens the database in fast mode; altered data will not automatically\n\ -be written to the disk after every change. This results in faster\n\ -writes to the database, but may result in an inconsistent database\n\ -if the program crashes while the database is still open. Use the\n\ -sync() method to force any unwritten data to be written to the disk.\n\ -The 's' flag causes all database operations to be synchronized to\n\ -disk. The 'u' flag disables locking of the database file.\n\ -\n\ -The optional mode argument is the Unix mode of the file, used only\n\ -when the database has to be created. It defaults to octal 0666. "); - -static PyObject * -dbmopen(PyObject *self, PyObject *args) -{ - char *name; - char *flags = "r"; - int iflags; - int mode = 0666; - - if (!PyArg_ParseTuple(args, "s|si:open", &name, &flags, &mode)) - return NULL; - switch (flags[0]) { - case 'r': - iflags = GDBM_READER; - break; - case 'w': - iflags = GDBM_WRITER; - break; - case 'c': - iflags = GDBM_WRCREAT; - break; - case 'n': - iflags = GDBM_NEWDB; - break; - default: - PyErr_SetString(DbmError, - "First flag must be one of 'r', 'w', 'c' or 'n'"); - return NULL; - } - for (flags++; *flags != '\0'; flags++) { - char buf[40]; - switch (*flags) { -#ifdef GDBM_FAST - case 'f': - iflags |= GDBM_FAST; - break; -#endif -#ifdef GDBM_SYNC - case 's': - iflags |= GDBM_SYNC; - break; -#endif -#ifdef GDBM_NOLOCK - case 'u': - iflags |= GDBM_NOLOCK; - break; -#endif - default: - PyOS_snprintf(buf, sizeof(buf), "Flag '%c' is not supported.", - *flags); - PyErr_SetString(DbmError, buf); - return NULL; - } - } - - return newdbmobject(name, iflags, mode); -} - -static char dbmmodule_open_flags[] = "rwcn" -#ifdef GDBM_FAST - "f" -#endif -#ifdef GDBM_SYNC - "s" -#endif -#ifdef GDBM_NOLOCK - "u" -#endif - ; - -static PyMethodDef dbmmodule_methods[] = { - { "open", (PyCFunction)dbmopen, METH_VARARGS, dbmopen__doc__}, - { 0, 0 }, -}; - - -static struct PyModuleDef _gdbmmodule = { - PyModuleDef_HEAD_INIT, - "_gdbm", - gdbmmodule__doc__, - -1, - dbmmodule_methods, - NULL, - NULL, - NULL, - NULL -}; - -PyMODINIT_FUNC -PyInit__gdbm(void) { - PyObject *m, *d, *s; - - if (PyType_Ready(&Dbmtype) < 0) - return NULL; - m = PyModule_Create(&_gdbmmodule); - if (m == NULL) - return NULL; - d = PyModule_GetDict(m); - DbmError = PyErr_NewException("_gdbm.error", PyExc_IOError, NULL); - if (DbmError != NULL) { - PyDict_SetItemString(d, "error", DbmError); - s = PyUnicode_FromString(dbmmodule_open_flags); - PyDict_SetItemString(d, "open_flags", s); - Py_DECREF(s); - } - return m; -} +/*[clinic end generated code: output=b41c68a5f30699cb input=a9049054013a1b77]*/ -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Apr 17 20:29:34 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Fri, 17 Apr 2015 18:29:34 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2320181=3A_Converte?= =?utf-8?q?d_the_unicodedata_module_to_Argument_Clinic=2E?= Message-ID: <20150417182933.120222.18831@psf.io> https://hg.python.org/cpython/rev/c6d468e0ecc6 changeset: 95703:c6d468e0ecc6 user: Serhiy Storchaka date: Fri Apr 17 21:18:49 2015 +0300 summary: Issue #20181: Converted the unicodedata module to Argument Clinic. files: Modules/clinic/unicodedata.c.h | 372 +++++++++++++++++- Modules/unicodedata.c | 425 +++++++++----------- 2 files changed, 557 insertions(+), 240 deletions(-) diff --git a/Modules/clinic/unicodedata.c.h b/Modules/clinic/unicodedata.c.h --- a/Modules/clinic/unicodedata.c.h +++ b/Modules/clinic/unicodedata.c.h @@ -3,37 +3,385 @@ [clinic start generated code]*/ PyDoc_STRVAR(unicodedata_UCD_decimal__doc__, -"decimal($self, unichr, default=None, /)\n" +"decimal($self, chr, default=None, /)\n" "--\n" "\n" "Converts a Unicode character into its equivalent decimal value.\n" "\n" -"Returns the decimal value assigned to the Unicode character unichr\n" -"as integer. If no such value is defined, default is returned, or, if\n" -"not given, ValueError is raised."); +"Returns the decimal value assigned to the character chr as integer.\n" +"If no such value is defined, default is returned, or, if not given,\n" +"ValueError is raised."); #define UNICODEDATA_UCD_DECIMAL_METHODDEF \ {"decimal", (PyCFunction)unicodedata_UCD_decimal, METH_VARARGS, unicodedata_UCD_decimal__doc__}, static PyObject * -unicodedata_UCD_decimal_impl(PreviousDBVersion *self, - PyUnicodeObject *unichr, +unicodedata_UCD_decimal_impl(PyObject *self, int chr, PyObject *default_value); static PyObject * -unicodedata_UCD_decimal(PreviousDBVersion *self, PyObject *args) +unicodedata_UCD_decimal(PyObject *self, PyObject *args) { PyObject *return_value = NULL; - PyUnicodeObject *unichr; + int chr; PyObject *default_value = NULL; if (!PyArg_ParseTuple(args, - "O!|O:decimal", - &PyUnicode_Type, &unichr, &default_value)) + "C|O:decimal", + &chr, &default_value)) goto exit; - return_value = unicodedata_UCD_decimal_impl(self, unichr, default_value); + return_value = unicodedata_UCD_decimal_impl(self, chr, default_value); exit: return return_value; } -/*[clinic end generated code: output=33b488251c4fd143 input=a9049054013a1b77]*/ + +PyDoc_STRVAR(unicodedata_UCD_digit__doc__, +"digit($self, chr, default=None, /)\n" +"--\n" +"\n" +"Converts a Unicode character into its equivalent digit value.\n" +"\n" +"Returns the digit value assigned to the character chr as integer.\n" +"If no such value is defined, default is returned, or, if not given,\n" +"ValueError is raised."); + +#define UNICODEDATA_UCD_DIGIT_METHODDEF \ + {"digit", (PyCFunction)unicodedata_UCD_digit, METH_VARARGS, unicodedata_UCD_digit__doc__}, + +static PyObject * +unicodedata_UCD_digit_impl(PyObject *self, int chr, PyObject *default_value); + +static PyObject * +unicodedata_UCD_digit(PyObject *self, PyObject *args) +{ + PyObject *return_value = NULL; + int chr; + PyObject *default_value = NULL; + + if (!PyArg_ParseTuple(args, + "C|O:digit", + &chr, &default_value)) + goto exit; + return_value = unicodedata_UCD_digit_impl(self, chr, default_value); + +exit: + return return_value; +} + +PyDoc_STRVAR(unicodedata_UCD_numeric__doc__, +"numeric($self, chr, default=None, /)\n" +"--\n" +"\n" +"Converts a Unicode character into its equivalent numeric value.\n" +"\n" +"Returns the numeric value assigned to the character chr as float.\n" +"If no such value is defined, default is returned, or, if not given,\n" +"ValueError is raised."); + +#define UNICODEDATA_UCD_NUMERIC_METHODDEF \ + {"numeric", (PyCFunction)unicodedata_UCD_numeric, METH_VARARGS, unicodedata_UCD_numeric__doc__}, + +static PyObject * +unicodedata_UCD_numeric_impl(PyObject *self, int chr, + PyObject *default_value); + +static PyObject * +unicodedata_UCD_numeric(PyObject *self, PyObject *args) +{ + PyObject *return_value = NULL; + int chr; + PyObject *default_value = NULL; + + if (!PyArg_ParseTuple(args, + "C|O:numeric", + &chr, &default_value)) + goto exit; + return_value = unicodedata_UCD_numeric_impl(self, chr, default_value); + +exit: + return return_value; +} + +PyDoc_STRVAR(unicodedata_UCD_category__doc__, +"category($self, chr, /)\n" +"--\n" +"\n" +"Returns the general category assigned to the character chr as string."); + +#define UNICODEDATA_UCD_CATEGORY_METHODDEF \ + {"category", (PyCFunction)unicodedata_UCD_category, METH_O, unicodedata_UCD_category__doc__}, + +static PyObject * +unicodedata_UCD_category_impl(PyObject *self, int chr); + +static PyObject * +unicodedata_UCD_category(PyObject *self, PyObject *arg) +{ + PyObject *return_value = NULL; + int chr; + + if (!PyArg_Parse(arg, + "C:category", + &chr)) + goto exit; + return_value = unicodedata_UCD_category_impl(self, chr); + +exit: + return return_value; +} + +PyDoc_STRVAR(unicodedata_UCD_bidirectional__doc__, +"bidirectional($self, chr, /)\n" +"--\n" +"\n" +"Returns the bidirectional class assigned to the character chr as string.\n" +"\n" +"If no such value is defined, an empty string is returned."); + +#define UNICODEDATA_UCD_BIDIRECTIONAL_METHODDEF \ + {"bidirectional", (PyCFunction)unicodedata_UCD_bidirectional, METH_O, unicodedata_UCD_bidirectional__doc__}, + +static PyObject * +unicodedata_UCD_bidirectional_impl(PyObject *self, int chr); + +static PyObject * +unicodedata_UCD_bidirectional(PyObject *self, PyObject *arg) +{ + PyObject *return_value = NULL; + int chr; + + if (!PyArg_Parse(arg, + "C:bidirectional", + &chr)) + goto exit; + return_value = unicodedata_UCD_bidirectional_impl(self, chr); + +exit: + return return_value; +} + +PyDoc_STRVAR(unicodedata_UCD_combining__doc__, +"combining($self, chr, /)\n" +"--\n" +"\n" +"Returns the canonical combining class assigned to the character chr as integer.\n" +"\n" +"Returns 0 if no combining class is defined."); + +#define UNICODEDATA_UCD_COMBINING_METHODDEF \ + {"combining", (PyCFunction)unicodedata_UCD_combining, METH_O, unicodedata_UCD_combining__doc__}, + +static int +unicodedata_UCD_combining_impl(PyObject *self, int chr); + +static PyObject * +unicodedata_UCD_combining(PyObject *self, PyObject *arg) +{ + PyObject *return_value = NULL; + int chr; + int _return_value; + + if (!PyArg_Parse(arg, + "C:combining", + &chr)) + goto exit; + _return_value = unicodedata_UCD_combining_impl(self, chr); + if ((_return_value == -1) && PyErr_Occurred()) + goto exit; + return_value = PyLong_FromLong((long)_return_value); + +exit: + return return_value; +} + +PyDoc_STRVAR(unicodedata_UCD_mirrored__doc__, +"mirrored($self, chr, /)\n" +"--\n" +"\n" +"Returns the mirrored property assigned to the character chr as integer.\n" +"\n" +"Returns 1 if the character has been identified as a \"mirrored\"\n" +"character in bidirectional text, 0 otherwise."); + +#define UNICODEDATA_UCD_MIRRORED_METHODDEF \ + {"mirrored", (PyCFunction)unicodedata_UCD_mirrored, METH_O, unicodedata_UCD_mirrored__doc__}, + +static int +unicodedata_UCD_mirrored_impl(PyObject *self, int chr); + +static PyObject * +unicodedata_UCD_mirrored(PyObject *self, PyObject *arg) +{ + PyObject *return_value = NULL; + int chr; + int _return_value; + + if (!PyArg_Parse(arg, + "C:mirrored", + &chr)) + goto exit; + _return_value = unicodedata_UCD_mirrored_impl(self, chr); + if ((_return_value == -1) && PyErr_Occurred()) + goto exit; + return_value = PyLong_FromLong((long)_return_value); + +exit: + return return_value; +} + +PyDoc_STRVAR(unicodedata_UCD_east_asian_width__doc__, +"east_asian_width($self, chr, /)\n" +"--\n" +"\n" +"Returns the east asian width assigned to the character chr as string."); + +#define UNICODEDATA_UCD_EAST_ASIAN_WIDTH_METHODDEF \ + {"east_asian_width", (PyCFunction)unicodedata_UCD_east_asian_width, METH_O, unicodedata_UCD_east_asian_width__doc__}, + +static PyObject * +unicodedata_UCD_east_asian_width_impl(PyObject *self, int chr); + +static PyObject * +unicodedata_UCD_east_asian_width(PyObject *self, PyObject *arg) +{ + PyObject *return_value = NULL; + int chr; + + if (!PyArg_Parse(arg, + "C:east_asian_width", + &chr)) + goto exit; + return_value = unicodedata_UCD_east_asian_width_impl(self, chr); + +exit: + return return_value; +} + +PyDoc_STRVAR(unicodedata_UCD_decomposition__doc__, +"decomposition($self, chr, /)\n" +"--\n" +"\n" +"Returns the character decomposition mapping assigned to the character chr as string.\n" +"\n" +"An empty string is returned in case no such mapping is defined."); + +#define UNICODEDATA_UCD_DECOMPOSITION_METHODDEF \ + {"decomposition", (PyCFunction)unicodedata_UCD_decomposition, METH_O, unicodedata_UCD_decomposition__doc__}, + +static PyObject * +unicodedata_UCD_decomposition_impl(PyObject *self, int chr); + +static PyObject * +unicodedata_UCD_decomposition(PyObject *self, PyObject *arg) +{ + PyObject *return_value = NULL; + int chr; + + if (!PyArg_Parse(arg, + "C:decomposition", + &chr)) + goto exit; + return_value = unicodedata_UCD_decomposition_impl(self, chr); + +exit: + return return_value; +} + +PyDoc_STRVAR(unicodedata_UCD_normalize__doc__, +"normalize($self, form, unistr, /)\n" +"--\n" +"\n" +"Return the normal form \'form\' for the Unicode string unistr.\n" +"\n" +"Valid values for form are \'NFC\', \'NFKC\', \'NFD\', and \'NFKD\'."); + +#define UNICODEDATA_UCD_NORMALIZE_METHODDEF \ + {"normalize", (PyCFunction)unicodedata_UCD_normalize, METH_VARARGS, unicodedata_UCD_normalize__doc__}, + +static PyObject * +unicodedata_UCD_normalize_impl(PyObject *self, const char *form, + PyObject *input); + +static PyObject * +unicodedata_UCD_normalize(PyObject *self, PyObject *args) +{ + PyObject *return_value = NULL; + const char *form; + PyObject *input; + + if (!PyArg_ParseTuple(args, + "sO!:normalize", + &form, &PyUnicode_Type, &input)) + goto exit; + return_value = unicodedata_UCD_normalize_impl(self, form, input); + +exit: + return return_value; +} + +PyDoc_STRVAR(unicodedata_UCD_name__doc__, +"name($self, chr, default=None, /)\n" +"--\n" +"\n" +"Returns the name assigned to the character chr as a string.\n" +"\n" +"If no name is defined, default is returned, or, if not given,\n" +"ValueError is raised."); + +#define UNICODEDATA_UCD_NAME_METHODDEF \ + {"name", (PyCFunction)unicodedata_UCD_name, METH_VARARGS, unicodedata_UCD_name__doc__}, + +static PyObject * +unicodedata_UCD_name_impl(PyObject *self, int chr, PyObject *default_value); + +static PyObject * +unicodedata_UCD_name(PyObject *self, PyObject *args) +{ + PyObject *return_value = NULL; + int chr; + PyObject *default_value = NULL; + + if (!PyArg_ParseTuple(args, + "C|O:name", + &chr, &default_value)) + goto exit; + return_value = unicodedata_UCD_name_impl(self, chr, default_value); + +exit: + return return_value; +} + +PyDoc_STRVAR(unicodedata_UCD_lookup__doc__, +"lookup($self, name, /)\n" +"--\n" +"\n" +"Look up character by name.\n" +"\n" +"If a character with the given name is found, return the\n" +"corresponding character. If not found, KeyError is raised."); + +#define UNICODEDATA_UCD_LOOKUP_METHODDEF \ + {"lookup", (PyCFunction)unicodedata_UCD_lookup, METH_O, unicodedata_UCD_lookup__doc__}, + +static PyObject * +unicodedata_UCD_lookup_impl(PyObject *self, const char *name, + Py_ssize_clean_t name_length); + +static PyObject * +unicodedata_UCD_lookup(PyObject *self, PyObject *arg) +{ + PyObject *return_value = NULL; + const char *name; + Py_ssize_clean_t name_length; + + if (!PyArg_Parse(arg, + "s#:lookup", + &name, &name_length)) + goto exit; + return_value = unicodedata_UCD_lookup_impl(self, name, name_length); + +exit: + return return_value; +} +/*[clinic end generated code: output=1f04e31ae703ffed input=a9049054013a1b77]*/ diff --git a/Modules/unicodedata.c b/Modules/unicodedata.c --- a/Modules/unicodedata.c +++ b/Modules/unicodedata.c @@ -101,50 +101,31 @@ } -static Py_UCS4 getuchar(PyUnicodeObject *obj) -{ - if (PyUnicode_READY(obj)) - return (Py_UCS4)-1; - if (PyUnicode_GET_LENGTH(obj) == 1) { - if (PyUnicode_READY(obj)) - return (Py_UCS4)-1; - return PyUnicode_READ_CHAR(obj, 0); - } - PyErr_SetString(PyExc_TypeError, - "need a single Unicode character as parameter"); - return (Py_UCS4)-1; -} - /* --- Module API --------------------------------------------------------- */ /*[clinic input] - unicodedata.UCD.decimal - unichr: object(type='PyUnicodeObject *', subclass_of='&PyUnicode_Type') + self: self + chr: int(types={'str'}) default: object=NULL / Converts a Unicode character into its equivalent decimal value. -Returns the decimal value assigned to the Unicode character unichr -as integer. If no such value is defined, default is returned, or, if -not given, ValueError is raised. +Returns the decimal value assigned to the character chr as integer. +If no such value is defined, default is returned, or, if not given, +ValueError is raised. [clinic start generated code]*/ static PyObject * -unicodedata_UCD_decimal_impl(PreviousDBVersion *self, - PyUnicodeObject *unichr, +unicodedata_UCD_decimal_impl(PyObject *self, int chr, PyObject *default_value) -/*[clinic end generated code: output=bf853108f246ba19 input=c25c9d2b4de076b1]*/ +/*[clinic end generated code: output=be23376e1a185231 input=3acf7f2238874a49]*/ { int have_old = 0; long rc; - Py_UCS4 c; - - c = getuchar(unichr); - if (c == (Py_UCS4)-1) - return NULL; + Py_UCS4 c = (Py_UCS4)chr; if (self && UCD_Check(self)) { const change_record *old = get_old_record(self, c); @@ -175,61 +156,64 @@ return PyLong_FromLong(rc); } -PyDoc_STRVAR(unicodedata_digit__doc__, -"digit(unichr[, default])\n\ -\n\ -Returns the digit value assigned to the Unicode character unichr as\n\ -integer. If no such value is defined, default is returned, or, if\n\ -not given, ValueError is raised."); +/*[clinic input] +unicodedata.UCD.digit + + self: self + chr: int(types={'str'}) + default: object=NULL + / + +Converts a Unicode character into its equivalent digit value. + +Returns the digit value assigned to the character chr as integer. +If no such value is defined, default is returned, or, if not given, +ValueError is raised. +[clinic start generated code]*/ static PyObject * -unicodedata_digit(PyObject *self, PyObject *args) +unicodedata_UCD_digit_impl(PyObject *self, int chr, PyObject *default_value) +/*[clinic end generated code: output=96e18c950171fd2f input=733f093b399f5ab6]*/ { - PyUnicodeObject *v; - PyObject *defobj = NULL; long rc; - Py_UCS4 c; - - if (!PyArg_ParseTuple(args, "O!|O:digit", &PyUnicode_Type, &v, &defobj)) - return NULL; - c = getuchar(v); - if (c == (Py_UCS4)-1) - return NULL; + Py_UCS4 c = (Py_UCS4)chr; rc = Py_UNICODE_TODIGIT(c); if (rc < 0) { - if (defobj == NULL) { + if (default_value == NULL) { PyErr_SetString(PyExc_ValueError, "not a digit"); return NULL; } else { - Py_INCREF(defobj); - return defobj; + Py_INCREF(default_value); + return default_value; } } return PyLong_FromLong(rc); } -PyDoc_STRVAR(unicodedata_numeric__doc__, -"numeric(unichr[, default])\n\ -\n\ -Returns the numeric value assigned to the Unicode character unichr\n\ -as float. If no such value is defined, default is returned, or, if\n\ -not given, ValueError is raised."); +/*[clinic input] +unicodedata.UCD.numeric + + self: self + chr: int(types={'str'}) + default: object=NULL + / + +Converts a Unicode character into its equivalent numeric value. + +Returns the numeric value assigned to the character chr as float. +If no such value is defined, default is returned, or, if not given, +ValueError is raised. +[clinic start generated code]*/ static PyObject * -unicodedata_numeric(PyObject *self, PyObject *args) +unicodedata_UCD_numeric_impl(PyObject *self, int chr, + PyObject *default_value) +/*[clinic end generated code: output=53ce281fe85b10c4 input=c5875fa7cc768fb2]*/ { - PyUnicodeObject *v; - PyObject *defobj = NULL; int have_old = 0; double rc; - Py_UCS4 c; - - if (!PyArg_ParseTuple(args, "O!|O:numeric", &PyUnicode_Type, &v, &defobj)) - return NULL; - c = getuchar(v); - if (c == (Py_UCS4)-1) - return NULL; + Py_UCS4 c = (Py_UCS4)chr; if (self && UCD_Check(self)) { const change_record *old = get_old_record(self, c); @@ -247,37 +231,34 @@ if (!have_old) rc = Py_UNICODE_TONUMERIC(c); if (rc == -1.0) { - if (defobj == NULL) { + if (default_value == NULL) { PyErr_SetString(PyExc_ValueError, "not a numeric character"); return NULL; } else { - Py_INCREF(defobj); - return defobj; + Py_INCREF(default_value); + return default_value; } } return PyFloat_FromDouble(rc); } -PyDoc_STRVAR(unicodedata_category__doc__, -"category(unichr)\n\ -\n\ -Returns the general category assigned to the Unicode character\n\ -unichr as string."); +/*[clinic input] +unicodedata.UCD.category + + self: self + chr: int(types={'str'}) + / + +Returns the general category assigned to the character chr as string. +[clinic start generated code]*/ static PyObject * -unicodedata_category(PyObject *self, PyObject *args) +unicodedata_UCD_category_impl(PyObject *self, int chr) +/*[clinic end generated code: output=8571539ee2e6783a input=f5edd6fd04bd455d]*/ { - PyUnicodeObject *v; int index; - Py_UCS4 c; - - if (!PyArg_ParseTuple(args, "O!:category", - &PyUnicode_Type, &v)) - return NULL; - c = getuchar(v); - if (c == (Py_UCS4)-1) - return NULL; + Py_UCS4 c = (Py_UCS4)chr; index = (int) _getrecord_ex(c)->category; if (self && UCD_Check(self)) { const change_record *old = get_old_record(self, c); @@ -287,26 +268,24 @@ return PyUnicode_FromString(_PyUnicode_CategoryNames[index]); } -PyDoc_STRVAR(unicodedata_bidirectional__doc__, -"bidirectional(unichr)\n\ -\n\ -Returns the bidirectional class assigned to the Unicode character\n\ -unichr as string. If no such value is defined, an empty string is\n\ -returned."); +/*[clinic input] +unicodedata.UCD.bidirectional + + self: self + chr: int(types={'str'}) + / + +Returns the bidirectional class assigned to the character chr as string. + +If no such value is defined, an empty string is returned. +[clinic start generated code]*/ static PyObject * -unicodedata_bidirectional(PyObject *self, PyObject *args) +unicodedata_UCD_bidirectional_impl(PyObject *self, int chr) +/*[clinic end generated code: output=d36310ce2039bb92 input=5ce2f877b35305b5]*/ { - PyUnicodeObject *v; int index; - Py_UCS4 c; - - if (!PyArg_ParseTuple(args, "O!:bidirectional", - &PyUnicode_Type, &v)) - return NULL; - c = getuchar(v); - if (c == (Py_UCS4)-1) - return NULL; + Py_UCS4 c = (Py_UCS4)chr; index = (int) _getrecord_ex(c)->bidirectional; if (self && UCD_Check(self)) { const change_record *old = get_old_record(self, c); @@ -318,55 +297,52 @@ return PyUnicode_FromString(_PyUnicode_BidirectionalNames[index]); } -PyDoc_STRVAR(unicodedata_combining__doc__, -"combining(unichr)\n\ -\n\ -Returns the canonical combining class assigned to the Unicode\n\ -character unichr as integer. Returns 0 if no combining class is\n\ -defined."); +/*[clinic input] +unicodedata.UCD.combining -> int -static PyObject * -unicodedata_combining(PyObject *self, PyObject *args) + self: self + chr: int(types={'str'}) + / + +Returns the canonical combining class assigned to the character chr as integer. + +Returns 0 if no combining class is defined. +[clinic start generated code]*/ + +static int +unicodedata_UCD_combining_impl(PyObject *self, int chr) +/*[clinic end generated code: output=cad056d0cb6a5920 input=9125ea7d50b319e7]*/ { - PyUnicodeObject *v; int index; - Py_UCS4 c; - - if (!PyArg_ParseTuple(args, "O!:combining", - &PyUnicode_Type, &v)) - return NULL; - c = getuchar(v); - if (c == (Py_UCS4)-1) - return NULL; + Py_UCS4 c = (Py_UCS4)chr; index = (int) _getrecord_ex(c)->combining; if (self && UCD_Check(self)) { const change_record *old = get_old_record(self, c); if (old->category_changed == 0) index = 0; /* unassigned */ } - return PyLong_FromLong(index); + return index; } -PyDoc_STRVAR(unicodedata_mirrored__doc__, -"mirrored(unichr)\n\ -\n\ -Returns the mirrored property assigned to the Unicode character\n\ -unichr as integer. Returns 1 if the character has been identified as\n\ -a \"mirrored\" character in bidirectional text, 0 otherwise."); +/*[clinic input] +unicodedata.UCD.mirrored -> int -static PyObject * -unicodedata_mirrored(PyObject *self, PyObject *args) + self: self + chr: int(types={'str'}) + / + +Returns the mirrored property assigned to the character chr as integer. + +Returns 1 if the character has been identified as a "mirrored" +character in bidirectional text, 0 otherwise. +[clinic start generated code]*/ + +static int +unicodedata_UCD_mirrored_impl(PyObject *self, int chr) +/*[clinic end generated code: output=2532dbf8121b50e6 input=4e51e8aaf8d7e23e]*/ { - PyUnicodeObject *v; int index; - Py_UCS4 c; - - if (!PyArg_ParseTuple(args, "O!:mirrored", - &PyUnicode_Type, &v)) - return NULL; - c = getuchar(v); - if (c == (Py_UCS4)-1) - return NULL; + Py_UCS4 c = (Py_UCS4)chr; index = (int) _getrecord_ex(c)->mirrored; if (self && UCD_Check(self)) { const change_record *old = get_old_record(self, c); @@ -375,28 +351,25 @@ else if (old->mirrored_changed != 0xFF) index = old->mirrored_changed; } - return PyLong_FromLong(index); + return index; } -PyDoc_STRVAR(unicodedata_east_asian_width__doc__, -"east_asian_width(unichr)\n\ -\n\ -Returns the east asian width assigned to the Unicode character\n\ -unichr as string."); +/*[clinic input] +unicodedata.UCD.east_asian_width + + self: self + chr: int(types={'str'}) + / + +Returns the east asian width assigned to the character chr as string. +[clinic start generated code]*/ static PyObject * -unicodedata_east_asian_width(PyObject *self, PyObject *args) +unicodedata_UCD_east_asian_width_impl(PyObject *self, int chr) +/*[clinic end generated code: output=484e8537d9ee8197 input=f93c61f37276c8f0]*/ { - PyUnicodeObject *v; int index; - Py_UCS4 c; - - if (!PyArg_ParseTuple(args, "O!:east_asian_width", - &PyUnicode_Type, &v)) - return NULL; - c = getuchar(v); - if (c == (Py_UCS4)-1) - return NULL; + Py_UCS4 c = (Py_UCS4)chr; index = (int) _getrecord_ex(c)->east_asian_width; if (self && UCD_Check(self)) { const change_record *old = get_old_record(self, c); @@ -406,29 +379,27 @@ return PyUnicode_FromString(_PyUnicode_EastAsianWidthNames[index]); } -PyDoc_STRVAR(unicodedata_decomposition__doc__, -"decomposition(unichr)\n\ -\n\ -Returns the character decomposition mapping assigned to the Unicode\n\ -character unichr as string. An empty string is returned in case no\n\ -such mapping is defined."); +/*[clinic input] +unicodedata.UCD.decomposition + + self: self + chr: int(types={'str'}) + / + +Returns the character decomposition mapping assigned to the character chr as string. + +An empty string is returned in case no such mapping is defined. +[clinic start generated code]*/ static PyObject * -unicodedata_decomposition(PyObject *self, PyObject *args) +unicodedata_UCD_decomposition_impl(PyObject *self, int chr) +/*[clinic end generated code: output=7d699f3ec7565d27 input=7f2c0ee66d75468f]*/ { - PyUnicodeObject *v; char decomp[256]; int code, index, count; size_t i; unsigned int prefix_index; - Py_UCS4 c; - - if (!PyArg_ParseTuple(args, "O!:decomposition", - &PyUnicode_Type, &v)) - return NULL; - c = getuchar(v); - if (c == (Py_UCS4)-1) - return NULL; + Py_UCS4 c = (Py_UCS4)chr; code = (int)c; @@ -829,22 +800,24 @@ return 1; /* certainly normalized */ } -PyDoc_STRVAR(unicodedata_normalize__doc__, -"normalize(form, unistr)\n\ -\n\ -Return the normal form 'form' for the Unicode string unistr. Valid\n\ -values for form are 'NFC', 'NFKC', 'NFD', and 'NFKD'."); +/*[clinic input] +unicodedata.UCD.normalize -static PyObject* -unicodedata_normalize(PyObject *self, PyObject *args) + self: self + form: str + unistr as input: object(subclass_of='&PyUnicode_Type') + / + +Return the normal form 'form' for the Unicode string unistr. + +Valid values for form are 'NFC', 'NFKC', 'NFD', and 'NFKD'. +[clinic start generated code]*/ + +static PyObject * +unicodedata_UCD_normalize_impl(PyObject *self, const char *form, + PyObject *input) +/*[clinic end generated code: output=62d1f8870027efdc input=cd092e631cf11883]*/ { - char *form; - PyObject *input; - - if(!PyArg_ParseTuple(args, "sO!:normalize", - &form, &PyUnicode_Type, &input)) - return NULL; - if (PyUnicode_READY(input) == -1) return NULL; @@ -1203,64 +1176,67 @@ /* -------------------------------------------------------------------- */ /* Python bindings */ -PyDoc_STRVAR(unicodedata_name__doc__, -"name(unichr[, default])\n\ -Returns the name assigned to the Unicode character unichr as a\n\ -string. If no name is defined, default is returned, or, if not\n\ -given, ValueError is raised."); +/*[clinic input] +unicodedata.UCD.name + + self: self + chr: int(types={'str'}) + default: object=NULL + / + +Returns the name assigned to the character chr as a string. + +If no name is defined, default is returned, or, if not given, +ValueError is raised. +[clinic start generated code]*/ static PyObject * -unicodedata_name(PyObject* self, PyObject* args) +unicodedata_UCD_name_impl(PyObject *self, int chr, PyObject *default_value) +/*[clinic end generated code: output=6bbb37a326407707 input=51ee2f971c918113]*/ { char name[NAME_MAXLEN]; - Py_UCS4 c; - - PyUnicodeObject* v; - PyObject* defobj = NULL; - if (!PyArg_ParseTuple(args, "O!|O:name", &PyUnicode_Type, &v, &defobj)) - return NULL; - - c = getuchar(v); - if (c == (Py_UCS4)-1) - return NULL; + Py_UCS4 c = (Py_UCS4)chr; if (!_getucname(self, c, name, sizeof(name), 0)) { - if (defobj == NULL) { + if (default_value == NULL) { PyErr_SetString(PyExc_ValueError, "no such name"); return NULL; } else { - Py_INCREF(defobj); - return defobj; + Py_INCREF(default_value); + return default_value; } } return PyUnicode_FromString(name); } -PyDoc_STRVAR(unicodedata_lookup__doc__, -"lookup(name)\n\ -\n\ -Look up character by name. If a character with the\n\ -given name is found, return the corresponding Unicode\n\ -character. If not found, KeyError is raised."); +/*[clinic input] +unicodedata.UCD.lookup + + self: self + name: str(types={'str', 'robuffer'}, length=True) + / + +Look up character by name. + +If a character with the given name is found, return the +corresponding character. If not found, KeyError is raised. +[clinic start generated code]*/ static PyObject * -unicodedata_lookup(PyObject* self, PyObject* args) +unicodedata_UCD_lookup_impl(PyObject *self, const char *name, + Py_ssize_clean_t name_length) +/*[clinic end generated code: output=765cb8186788e6be input=f2bf29706135a590]*/ { Py_UCS4 code; - - char* name; - Py_ssize_t namelen; unsigned int index; - if (!PyArg_ParseTuple(args, "s#:lookup", &name, &namelen)) - return NULL; - if (namelen > INT_MAX) { + if (name_length > INT_MAX) { PyErr_SetString(PyExc_KeyError, "name too long"); return NULL; } - if (!_getcode(self, name, (int)namelen, &code, 1)) { + if (!_getcode(self, name, (int)name_length, &code, 1)) { PyErr_Format(PyExc_KeyError, "undefined character name '%s'", name); return NULL; } @@ -1279,24 +1255,17 @@ static PyMethodDef unicodedata_functions[] = { UNICODEDATA_UCD_DECIMAL_METHODDEF - {"digit", unicodedata_digit, METH_VARARGS, unicodedata_digit__doc__}, - {"numeric", unicodedata_numeric, METH_VARARGS, unicodedata_numeric__doc__}, - {"category", unicodedata_category, METH_VARARGS, - unicodedata_category__doc__}, - {"bidirectional", unicodedata_bidirectional, METH_VARARGS, - unicodedata_bidirectional__doc__}, - {"combining", unicodedata_combining, METH_VARARGS, - unicodedata_combining__doc__}, - {"mirrored", unicodedata_mirrored, METH_VARARGS, - unicodedata_mirrored__doc__}, - {"east_asian_width", unicodedata_east_asian_width, METH_VARARGS, - unicodedata_east_asian_width__doc__}, - {"decomposition", unicodedata_decomposition, METH_VARARGS, - unicodedata_decomposition__doc__}, - {"name", unicodedata_name, METH_VARARGS, unicodedata_name__doc__}, - {"lookup", unicodedata_lookup, METH_VARARGS, unicodedata_lookup__doc__}, - {"normalize", unicodedata_normalize, METH_VARARGS, - unicodedata_normalize__doc__}, + UNICODEDATA_UCD_DIGIT_METHODDEF + UNICODEDATA_UCD_NUMERIC_METHODDEF + UNICODEDATA_UCD_CATEGORY_METHODDEF + UNICODEDATA_UCD_BIDIRECTIONAL_METHODDEF + UNICODEDATA_UCD_COMBINING_METHODDEF + UNICODEDATA_UCD_MIRRORED_METHODDEF + UNICODEDATA_UCD_EAST_ASIAN_WIDTH_METHODDEF + UNICODEDATA_UCD_DECOMPOSITION_METHODDEF + UNICODEDATA_UCD_NAME_METHODDEF + UNICODEDATA_UCD_LOOKUP_METHODDEF + UNICODEDATA_UCD_NORMALIZE_METHODDEF {NULL, NULL} /* sentinel */ }; -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Apr 17 22:43:46 2015 From: python-checkins at python.org (berker.peksag) Date: Fri, 17 Apr 2015 20:43:46 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_Add_PEP_492_by_Yury_Selivanov?= =?utf-8?q?=2E?= Message-ID: <20150417204346.27928.33024@psf.io> https://hg.python.org/peps/rev/e532f0629fc3 changeset: 5761:e532f0629fc3 user: Berker Peksag date: Fri Apr 17 23:43:55 2015 +0300 summary: Add PEP 492 by Yury Selivanov. files: pep-0492.txt | 1014 ++++++++++++++++++++++++++++++++++++++ 1 files changed, 1014 insertions(+), 0 deletions(-) diff --git a/pep-0492.txt b/pep-0492.txt new file mode 100644 --- /dev/null +++ b/pep-0492.txt @@ -0,0 +1,1014 @@ +PEP: 492 +Title: Coroutines with async and await syntax +Version: $Revision$ +Last-Modified: $Date$ +Author: Yury Selivanov +Status: Draft +Type: Standards Track +Content-Type: text/x-rst +Created: 09-Apr-2015 +Python-Version: 3.5 + + +Abstract +======== + +This PEP introduces new syntax for coroutines, asynchronous ``with`` +statements and ``for`` loops. The main motivation behind this proposal is to +streamline writing and maintaining asynchronous code, as well as to simplify +previously hard to implement code patterns. + + +Rationale and Goals +=================== + +Current Python supports implementing coroutines via generators (PEP 342), +further enhanced by the ``yield from`` syntax introduced in PEP 380. +This approach has a number of shortcomings: + +* it is easy to confuse coroutines with regular generators, since they share + the same syntax; async libraries often attempt to alleviate this by using + decorators (e.g. ``@asyncio.coroutine`` [1]_); + +* it is not possible to natively define a coroutine which has no ``yield`` + or ``yield from`` statements, again requiring the use of decorators to + fix potential refactoring issues; + +* support for asynchronous calls is limited to expressions where ``yield`` is + allowed syntactically, limiting the usefulness of syntactic features, such + as ``with`` and ``for`` statements. + +This proposal makes coroutines a native Python language feature, and clearly +separates them from generators. This removes generator/coroutine ambiguity, +and makes it possible to reliably define coroutines without reliance on a +specific library. This also enables linters and IDEs to improve static code +analysis and refactoring. + +Native coroutines and the associated new syntax features make it possible +to define context manager and iteration protocols in asynchronous terms. +As shown later in this proposal, the new ``async with`` statement lets Python +programs perform asynchronous calls when entering and exiting a runtime +context, and the new ``async for`` statement makes it possible to perform +asynchronous calls in iterators. + + +Specification +============= + +This proposal introduces new syntax and semantics to enhance coroutine support +in Python, it does not change the internal implementation of coroutines, which +are still based on generators. + +It is strongly suggested that the reader understands how coroutines are +implemented in Python (PEP 342 and PEP 380). It is also recommended to read +PEP 3156 (asyncio framework). + +From this point in this document we use the word *coroutine* to refer to +functions declared using the new syntax. *generator-based coroutine* is used +where necessary to refer to coroutines that are based on generator syntax. + + +New Coroutine Declaration Syntax +-------------------------------- + +The following new syntax is used to declare a coroutine:: + + async def read_data(db): + pass + +Key properties of coroutines: + +* Coroutines are always generators, even if they do not contain ``await`` + expressions. + +* It is a ``SyntaxError`` to have ``yield`` or ``yield from`` expressions in + an ``async`` function. + +* Internally, a new code object flag - ``CO_ASYNC`` - is introduced to enable + runtime detection of coroutines (and migrating existing code). + All coroutines have both ``CO_ASYNC`` and ``CO_GENERATOR`` flags set. + +* Regular generators, when called, return a *generator object*; similarly, + coroutines return a *coroutine object*. + +* ``StopIteration`` exceptions are not propagated out of coroutines, and are + replaced with a ``RuntimeError``. For regular generators such behavior + requires a future import (see PEP 479). + + +types.async_def() +----------------- + +A new function ``async_def(gen)`` is added to the ``types`` module. It +applies ``CO_ASYNC`` flag to the passed generator's code object, so that it +returns a *coroutine object* when called. + +This feature enables an easy upgrade path for existing libraries. + + +Await Expression +---------------- + +The following new ``await`` expression is used to obtain a result of coroutine +execution:: + + async def read_data(db): + data = await db.fetch('SELECT ...') + ... + +``await``, similarly to ``yield from``, suspends execution of ``read_data`` +coroutine until ``db.fetch`` *awaitable* completes and returns the result +data. + +It uses the ``yield from`` implementation with an extra step of validating its +argument. ``await`` only accepts an *awaitable*, which can be one of: + +* A *coroutine object* returned from a coroutine or a generator decorated with + ``types.async_def()``. + +* An object with an ``__await__`` method returning an iterator. + + Any ``yield from`` chain of calls ends with a ``yield``. This is a + fundamental mechanism of how *Futures* are implemented. Since, internally, + coroutines are a special kind of generators, every ``await`` is suspended by + a ``yield`` somewhere down the chain of ``await`` calls (please refer to PEP + 3156 for a detailed explanation.) + + To enable this behavior for coroutines, a new magic method called + ``__await__`` is added. In asyncio, for instance, to enable Future objects + in ``await`` statements, the only change is to add ``__await__ = __iter__`` + line to ``asyncio.Future`` class. + + Objects with ``__await__`` method are called *Future-like* objects in the + rest of this PEP. + + Also, please note that ``__aiter__`` method (see its definition below) cannot + be used for this purpose. It is a different protocol, and would be like + using ``__iter__`` instead of ``__call__`` for regular callables. + +It is a ``SyntaxError`` to use ``await`` outside of a coroutine. + + +Asynchronous Context Managers and "async with" +---------------------------------------------- + +An *asynchronous context manager* is a context manager that is able to suspend +execution in its *enter* and *exit* methods. + +To make this possible, a new protocol for asynchronous context managers is +proposed. Two new magic methods are added: ``__aenter__`` and ``__aexit__``. +Both must return an *awaitable*. + +An example of an asynchronous context manager:: + + class AsyncContextManager: + async def __aenter__(self): + await log('entering context') + + async def __aexit__(self, exc_type, exc, tb): + await log('exiting context') + + +New Syntax +'''''''''' + +A new statement for asynchronous context managers is proposed:: + + async with EXPR as VAR: + BLOCK + + +which is semantically equivalent to:: + + mgr = (EXPR) + aexit = type(mgr).__aexit__ + aenter = type(mgr).__aenter__(mgr) + exc = True + + try: + try: + VAR = await aenter + BLOCK + except: + exc = False + exit_res = await aexit(mgr, *sys.exc_info()) + if not exit_res: + raise + + finally: + if exc: + await aexit(mgr, None, None, None) + + +As with regular ``with`` statements, it is possible to specify multiple context +managers in a single ``async with`` statement. + +It is an error to pass a regular context manager without ``__aenter__`` and +``__aexit__`` methods to ``async with``. It is a ``SyntaxError`` to use +``async with`` outside of a coroutine. + + +Example +''''''' + +With asynchronous context managers it is easy to implement proper database +transaction managers for coroutines:: + + async def commit(session, data): + ... + + async with session.transaction(): + ... + await session.update(data) + ... + +Code that needs locking also looks lighter:: + + async with lock: + ... + +instead of:: + + with (yield from lock): + ... + + +Asynchronous Iterators and "async for" +-------------------------------------- + +An *asynchronous iterable* is able to call asynchronous code in its *iter* +implementation, and *asynchronous iterator* can call asynchronous code in its +*next* method. To support asynchronous iteration: + +1. An object must implement an ``__aiter__`` method returning an *awaitable* + resulting in an *asynchronous iterator object*. + +2. An *asynchronous iterator object* must implement an ``__anext__`` method + returning an *awaitable*. + +3. To stop iteration```__anext__`` must raise a ``StopAsyncIteration`` + exception. + +An example of asynchronous iterable:: + + class AsyncIterable: + async def __aiter__(self): + return self + + async def __anext__(self): + data = await self.fetch_data() + if data: + return data + else: + raise StopAsyncIteration + + async def fetch_data(self): + ... + + +New Syntax +'''''''''' + +A new statement for iterating through asynchronous iterators is proposed:: + + async for TARGET in ITER: + BLOCK + else: + BLOCK2 + +which is semantically equivalent to:: + + iter = (ITER) + iter = await type(iter).__aiter__(iter) + running = True + while running: + try: + TARGET = await type(iter).__anext__(iter) + except StopAsyncIteration: + running = False + else: + BLOCK + else: + BLOCK2 + + +It is an error to pass a regular iterable without ``__aiter__`` method to +``async for``. It is a ``SyntaxError`` to use ``async for`` outside of a +coroutine. + +As for with regular ``for`` statement, ``async for`` has an optional ``else`` +clause. + + +Example 1 +''''''''' + +With asynchronous iteration protocol it is possible to asynchronously buffer +data during iteration:: + + async for data in cursor: + ... + +Where ``cursor`` is an asynchronous iterator that prefetches ``N`` rows +of data from a database after every ``N`` iterations. + +The following code illustrates new asynchronous iteration protocol:: + + class Cursor: + def __init__(self): + self.buffer = collections.deque() + + def _prefetch(self): + ... + + async def __aiter__(self): + return self + + async def __anext__(self): + if not self.buffer: + self.buffer = await self._prefetch() + if not self.buffer: + raise StopAsyncIteration + return self.buffer.popleft() + +then the ``Cursor`` class can be used as follows:: + + async for row in Cursor(): + print(row) + +which would be equivalent to the following code:: + + i = await Cursor().__aiter__() + while True: + try: + row = await i.__anext__() + except StopAsyncIteration: + break + else: + print(row) + + +Example 2 +''''''''' + +The following is a utility class that transforms a regular iterable to an +asynchronous one. While this is not a very useful thing to do, the code +illustrates the relationship between regular and asynchronous iterators. + +:: + + class AsyncIteratorWrapper: + def __init__(self, obj): + self._it = iter(obj) + + async def __aiter__(self): + return self + + async def __anext__(self): + try: + value = next(self._it) + except StopIteration: + raise StopAsyncIteration + return value + + data = "abc" + it = AsyncIteratorWrapper("abc") + async for item in it: + print(it) + + +Why StopAsyncIteration? +''''''''''''''''''''''' + +Coroutines are still based on generators internally. So, before PEP 479, there +was no fundamental difference between + +:: + + def g1(): + yield from fut + return 'spam' + +and + +:: + + def g2(): + yield from fut + raise StopIteration('spam') + +And since PEP 479 is accepted and enabled by default for coroutines, the +following example will have its ``StopIteration`` wrapped into a +``RuntimeError`` + +:: + + async def a1(): + await fut + raise StopIteration('spam') + +The only way to tell the outside code that the iteration has ended is to raise +something other than ``StopIteration``. Therefore, a new built-in exception +class ``StopAsyncIteration`` was added. + +Moreover, with semantics from PEP 479, all ``StopIteration`` exceptions raised +in coroutines are wrapped in ``RuntimeError``. + + +Debugging Features +------------------ + +One of the most frequent mistakes that people make when using generators as +coroutines is forgetting to use ``yield from``:: + + @asyncio.coroutine + def useful(): + asyncio.sleep(1) # this will do noting without 'yield from' + +For debugging this kind of mistakes there is a special debug mode in asyncio, +in which ``@coroutine`` decorator wraps all functions with a special object +with a destructor logging a warning. Whenever a wrapped generator gets garbage +collected, a detailed logging message is generated with information about where +exactly the decorator function was defined, stack trace of where it was +collected, etc. Wrapper object also provides a convenient ``__repr__`` +function with detailed information about the generator. + +The only problem is how to enable these debug capabilities. Since debug +facilities should be a no-op in production mode, ``@coroutine`` decorator makes +the decision of whether to wrap or not to wrap based on an OS environment +variable ``PYTHONASYNCIODEBUG``. This way it is possible to run asyncio +programs with asyncio's own functions instrumented. ``EventLoop.set_debug``, a +different debug facility, has no impact on ``@coroutine`` decorator's behavior. + +With this proposal, coroutines is a native, distinct from generators, +concept. A new method ``set_async_wrapper`` is added to the ``sys`` module, +with which frameworks can provide advanced debugging facilities. + +It is also important to make coroutines as fast and efficient as possible, +therefore there are no debug features enabled by default. + +Example:: + + async def debug_me(): + await asyncio.sleep(1) + + def async_debug_wrap(generator): + return asyncio.AsyncDebugWrapper(generator) + + sys.set_async_wrapper(async_debug_wrap) + + debug_me() # <- this line will likely GC the coroutine object and + # trigger AsyncDebugWrapper's code. + + assert isinstance(debug_me(), AsyncDebugWrapper) + + sys.set_async_wrapper(None) # <- this unsets any previously set wrapper + assert not isinstance(debug_me(), AsyncDebugWrapper) + +If ``sys.set_async_wrapper()`` is called twice, the new wrapper replaces the +previous wrapper. ``sys.set_async_wrapper(None)`` unsets the wrapper. + + +Glossary +======== + +:Coroutine: + A coroutine function, or just "coroutine", is declared with ``async def``. + It uses ``await`` and ``return value``; see `New Coroutine Declaration + Syntax`_ for details. + +:Coroutine object: + Returned from a coroutine function. See `Await Expression`_ for details. + +:Future-like object: + An object with an ``__await__`` method. It is consumed by ``await`` in a + coroutine. A coroutine waiting for a Future-like object is suspended until + the Future-like object's ``__await__`` completes. ``await`` returns the + result of the Future-like object. See `Await Expression`_ for details. + +:Awaitable: + A *future-like* object or a *coroutine object*. See `Await Expression`_ + for details. + +:Generator-based coroutine: + Coroutines based in generator syntax. Most common example is + ``@asyncio.coroutine``. + +:Asynchronous context manager: + An asynchronous context manager has ``__aenter__`` and ``__aexit__`` methods + and can be used with ``async with``. See + `Asynchronous Context Managers and "async with"`_ for details. + +:Asynchronous iterable: + An object with an ``__aiter__`` method, which must return an *asynchronous + iterator* object. Can be used with ``async for``. See + `Asynchronous Iterators and "async for"`_ for details. + +:Asynchronous iterator: + An asynchronous iterator has an ``__anext__`` method.See + `Asynchronous Iterators and "async for"`_ for details. + + +List of functions and methods +============================= + +================= ======================================= ================= +Method Can contain Can't contain +================= ======================================= ================= +async def func await, return value yield, yield from +async def __a*__ await, return value yield, yield from +def __a*__ return Future-like await +def __await__ yield, yield from, return iterable await +generator yield, yield from, return value await +================= ======================================= ================= + +Where: + +* "async def func": coroutine; + +* "async def __a*__": ``__aiter__``, ``__anext__``, ``__aenter__``, + ``__aexit__`` defined with the ``async`` keyword; + +* "def __a*__": ``__aiter__``, ``__anext__``, ``__aenter__``, ``__aexit__`` + defined without the ``async`` keyword, must return an *awaitable*; + +* "def __await__": ``__await__`` method to implement *Future-like* objects; + +* generator: a "regular" generator, function defined with ``def`` and which + contains a least one ``yield`` or ``yield from`` expression. + +*Future-like* is an object with an ``__await__`` method, see +`Await Expression`_ section for details. + + +Transition Plan +=============== + +To avoid backwards compatibility issues with ``async`` and ``await`` keywords, +it was decided to modify ``tokenizer.c`` in such a way, that it: + +* recognizes ``async def`` name tokens combination (start of a coroutine); + +* keeps track of regular functions and coroutines; + +* replaces ``'async'`` token with ``ASYNC`` and ``'await'`` token with + ``AWAIT`` when in the process of yielding tokens for coroutines. + +This approach allows for seamless combination of new syntax features (all of +them available only in ``async`` functions) with any existing code. + +An example of having "async def" and "async" attribute in one piece of code:: + + class Spam: + async = 42 + + async def ham(): + print(getattr(Spam, 'async')) + + # The coroutine can be executed and will print '42' + + +Backwards Compatibility +----------------------- + +The only backwards incompatible change is an extra argument ``is_async`` to +``FunctionDef`` AST node. But since it is a documented fact that the structure +of AST nodes is an implementation detail and subject to change, this should not +be considered a serious issue. + + +Grammar Updates +--------------- + +Grammar changes are also fairly minimal:: + + await_expr: AWAIT test + await_stmt: await_expr + + decorated: decorators (classdef | funcdef | async_funcdef) + async_funcdef: ASYNC funcdef + + async_stmt: ASYNC (funcdef | with_stmt) # will add for_stmt later + + compound_stmt: (if_stmt | while_stmt | for_stmt | try_stmt | with_stmt + | funcdef | classdef | decorated | async_stmt) + + atom: ('(' [yield_expr|await_expr|testlist_comp] ')' | + '[' [testlist_comp] ']' | + '{' [dictorsetmaker] '}' | + NAME | NUMBER | STRING+ | '...' | 'None' | 'True' | 'False?) + + expr_stmt: testlist_star_expr (augassign (yield_expr|await_expr|testlist) | + ('=' (yield_expr|await_expr|testlist_star_expr))*) + + +Transition Period Shortcomings +------------------------------ + +There is just one. + +Until ``async`` and ``await`` are not proper keywords, it is not possible (or +at least very hard) to fix ``tokenizer.c`` to recognize them on the **same +line** with ``def`` keyword:: + + # async and await will always be parsed as variables + + async def outer(): # 1 + def nested(a=(await fut)): + pass + + async def foo(): return (await fut) # 2 + +Since ``await`` and ``async`` in such cases are parsed as ``NAME`` tokens, a +``SyntaxError`` will be raised. + +To workaround these issues, the above examples can be easily rewritten to a +more readable form:: + + async def outer(): # 1 + a_default = await fut + def nested(a=a_default): + pass + + async def foo(): # 2 + return (await fut) + +This limitation will go away as soon as ``async`` and ``await`` ate proper +keywords. Or if it's decided to use a future import for this PEP. + + +Deprecation Plans +----------------- + +``async`` and ``await`` names will be softly deprecated in CPython 3.5 and 3.6. +In 3.7 we will transform them to proper keywords. Making ``async`` and +``await`` proper keywords before 3.7 might make it harder for people to port +their code to Python 3. + + +asyncio +------- + +``asyncio`` module was adapted and tested to work with coroutines and new +statements. Backwards compatibility is 100% preserved. + +The required changes are mainly: + +1. Modify ``@asyncio.coroutine`` decorator to use new ``types.async_def()`` + function. + +2. Add ``__await__ = __iter__`` line to ``asyncio.Future`` class. + +3. Add ``ensure_task()`` as an alias for ``async()`` function. Deprecate + ``async()`` function. + + +Design Considerations +===================== + +No implicit wrapping in Futures +------------------------------- + +There is a proposal to add similar mechanism to ECMAScript 7 [2]_. A key +difference is that JavaScript "async functions" always return a Promise. While +this approach has some advantages, it also implies that a new Promise object is +created on each "async function" invocation. + +We could implement a similar functionality in Python, by wrapping all +coroutines in a Future object, but this has the following disadvantages: + +1. Performance. A new Future object would be instantiated on each coroutine + call. Moreover, this makes implementation of ``await`` expressions slower + (disabling optimizations of ``yield from``). + +2. A new built-in ``Future`` object would need to be added. + +3. Coming up with a generic ``Future`` interface that is usable for any use + case in any framework is a very hard to solve problem. + +4. It is not a feature that is used frequently, when most of the code is + coroutines. + + +Why "async" and "await" keywords +-------------------------------- + +async/await is not a new concept in programming languages: + +* C# has it since long time ago [5]_; + +* proposal to add async/await in ECMAScript 7 [2]_; + see also Traceur project [9]_; + +* Facebook's Hack/HHVM [6]_; + +* Google's Dart language [7]_; + +* Scala [8]_; + +* proposal to add async/await to C++ [10]_; + +* and many other less popular languages. + +This is a huge benefit, as some users already have experience with async/await, +and because it makes working with many languages in one project easier (Python +with ECMAScript 7 for instance). + + +Why "__aiter__" is a coroutine +------------------------------ + +In principle, ``__aiter__`` could be a regular function. There are several +good reasons to make it a coroutine: + +* as most of the ``__anext__``, ``__aenter__``, and ``__aexit__`` methods are + coroutines, users would often make a mistake defining it as ``async`` + anyways; + +* there might be a need to run some asynchronous operations in ``__aiter__``, + for instance to prepare DB queries or do some file operation. + + +Importance of "async" keyword +----------------------------- + +While it is possible to just implement ``await`` expression and treat all +functions with at least one ``await`` as coroutines, this approach makes +APIs design, code refactoring and its long time support harder. + +Let's pretend that Python only has ``await`` keyword:: + + def useful(): + ... + await log(...) + ... + + def important(): + await useful() + +If ``useful()`` function is refactored and someone removes all ``await`` +expressions from it, it would become a regular python function, and all code +that depends on it, including ``important()`` would be broken. To mitigate this +issue a decorator similar to ``@asyncio.coroutine`` has to be introduced. + + +Why "async def" +--------------- + +For some people bare ``async name(): pass`` syntax might look more appealing +than ``async def name(): pass``. It is certainly easier to type. But on the +other hand, it breaks the symmetry between ``async def``, ``async with`` and +``async for``, where ``async`` is a modifier, stating that the statement is +asynchronous. It is also more consistent with the existing grammar. + + +Why not a __future__ import +--------------------------- + +``__future__`` imports are inconvenient and easy to forget to add. Also, they +are enabled for the whole source file. Consider that there is a big project +with a popular module named "async.py". With future imports it is required to +either import it using ``__import__()`` or ``importlib.import_module()`` calls, +or to rename the module. The proposed approach makes it possible to continue +using old code and modules without a hassle, while coming up with a migration +plan for future python versions. + + +Why magic methods start with "a" +-------------------------------- + +New asynchronous magic methods ``__aiter__``, ``__anext__``, ``__aenter__``, +and ``__aexit__`` all start with the same prefix "a". An alternative proposal +is to use "async" prefix, so that ``__aiter__`` becomes ``__async_iter__``. +However, to align new magic methods with the existing ones, such as +``__radd__`` and ``__iadd__`` it was decided to use a shorter version. + + +Why not reuse existing magic names +---------------------------------- + +An alternative idea about new asynchronous iterators and context managers was +to reuse existing magic methods, by adding an ``async`` keyword to their +declarations:: + + class CM: + async def __enter__(self): # instead of __aenter__ + ... + +This approach has the following downsides: + +* it would not be possible to create an object that works in both ``with`` and + ``async with`` statements; + +* it would look confusing and would require some implicit magic behind the + scenes in the interpreter; + +* one of the main points of this proposal is to make coroutines as simple + and foolproof as possible. + + +Comprehensions +-------------- + +For the sake of restricting the broadness of this PEP there is no new syntax +for asynchronous comprehensions. This should be considered in a separate PEP, +if there is a strong demand for this feature. + + +Performance +=========== + +Overall Impact +-------------- + +This proposal introduces no observable performance impact. Here is an output +of python's official set of benchmarks [4]_: + +:: + + python perf.py -r -b default ../cpython/python.exe ../cpython-aw/python.exe + + [skipped] + + Report on Darwin ysmac 14.3.0 Darwin Kernel Version 14.3.0: + Mon Mar 23 11:59:05 PDT 2015; root:xnu-2782.20.48~5/RELEASE_X86_64 + x86_64 i386 + + Total CPU cores: 8 + + ### etree_iterparse ### + Min: 0.365359 -> 0.349168: 1.05x faster + Avg: 0.396924 -> 0.379735: 1.05x faster + Significant (t=9.71) + Stddev: 0.01225 -> 0.01277: 1.0423x larger + + The following not significant results are hidden, use -v to show them: + django_v2, 2to3, etree_generate, etree_parse, etree_process, fastpickle, + fastunpickle, json_dump_v2, json_load, nbody, regex_v8, tornado_http. + + +Tokenizer modifications +----------------------- + +There is no observable slowdown of parsing python files with the modified +tokenizer: parsing of one 12Mb file (``Lib/test/test_binop.py`` repeated 1000 +times) takes the same amount of time. + + +async/await +----------- + +The following micro-benchmark was used to determine performance difference +between "async" functions and generators:: + + import sys + import time + + def binary(n): + if n <= 0: + return 1 + l = yield from binary(n - 1) + r = yield from binary(n - 1) + return l + 1 + r + + async def abinary(n): + if n <= 0: + return 1 + l = await abinary(n - 1) + r = await abinary(n - 1) + return l + 1 + r + + def timeit(gen, depth, repeat): + t0 = time.time() + for _ in range(repeat): + list(gen(depth)) + t1 = time.time() + print('{}({}) * {}: total {:.3f}s'.format( + gen.__name__, depth, repeat, t1-t0)) + +The result is that there is no observable performance difference. Minimum +timing of 3 runs + +:: + + abinary(19) * 30: total 12.985s + binary(19) * 30: total 12.953s + +Note that depth of 19 means 1,048,575 calls. + + +Reference Implementation +======================== + +The reference implementation can be found here: [3]_. + +List of high-level changes and new protocols +-------------------------------------------- + +1. New syntax for defining coroutines: ``async def`` and new ``await`` + keyword. + +2. New ``__await__`` method for Future-like objects. + +3. New syntax for asynchronous context managers: ``async with``. And + associated protocol with ``__aenter__`` and ``__aexit__`` methods. + +4. New syntax for asynchronous iteration: ``async for``. And associated + protocol with ``__aiter__``, ``__aexit__`` and new built-in exception + ``StopAsyncIteration``. + +5. New AST nodes: ``AsyncFor``, ``AsyncWith``, ``Await``; ``FunctionDef`` AST + node got a new argument ``is_async``. + +6. New functions: ``sys.set_async_wrapper(callback)`` and + ``types.async_def(gen)``. + +7. New ``CO_ASYNC`` bit flag for code objects. + +While the list of changes and new things is not short, it is important to +understand, that most users will not use these features directly. It is +intended to be used in frameworks and libraries to provide users with +convenient to use and unambiguous APIs with ``async def``, ``await``, ``async +for`` and ``async with`` syntax. + + +Working example +--------------- + +All concepts proposed in this PEP are implemented [3]_ and can be tested. + +:: + + import asyncio + + + async def echo_server(): + print('Serving on localhost:8000') + await asyncio.start_server(handle_connection, 'localhost', 8000) + + + async def handle_connection(reader, writer): + print('New connection...') + + while True: + data = await reader.read(8192) + + if not data: + break + + print('Sending {:.10}... back'.format(repr(data))) + writer.write(data) + + + loop = asyncio.get_event_loop() + loop.run_until_complete(echo_server()) + try: + loop.run_forever() + finally: + loop.close() + + +References +========== + +.. [1] https://docs.python.org/3/library/asyncio-task.html#asyncio.coroutine + +.. [2] http://wiki.ecmascript.org/doku.php?id=strawman:async_functions + +.. [3] https://github.com/1st1/cpython/tree/await + +.. [4] https://hg.python.org/benchmarks + +.. [5] https://msdn.microsoft.com/en-us/library/hh191443.aspx + +.. [6] http://docs.hhvm.com/manual/en/hack.async.php + +.. [7] https://www.dartlang.org/articles/await-async/ + +.. [8] http://docs.scala-lang.org/sips/pending/async.html + +.. [9] https://github.com/google/traceur-compiler/wiki/LanguageFeatures#async-functions-experimental + +.. [10] http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3722.pdf (PDF) + + +Acknowledgments +=============== + +I thank Guido van Rossum, Victor Stinner, Elvis Pranskevichus, Andrew Svetlov, +and ?ukasz Langa for their initial feedback. + + +Copyright +========= + +This document has been placed in the public domain. + +.. + Local Variables: + mode: indented-text + indent-tabs-mode: nil + sentence-end-double-space: t + fill-column: 70 + coding: utf-8 + End: -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Fri Apr 17 22:57:11 2015 From: python-checkins at python.org (yury.selivanov) Date: Fri, 17 Apr 2015 20:57:11 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_pep_492=3A_Fix_typos?= Message-ID: <20150417205711.31111.31420@psf.io> https://hg.python.org/peps/rev/35406e447668 changeset: 5762:35406e447668 user: Yury Selivanov date: Fri Apr 17 16:57:08 2015 -0400 summary: pep 492: Fix typos files: pep-0492.txt | 13 ++++--------- 1 files changed, 4 insertions(+), 9 deletions(-) diff --git a/pep-0492.txt b/pep-0492.txt --- a/pep-0492.txt +++ b/pep-0492.txt @@ -371,10 +371,8 @@ raise StopAsyncIteration return value - data = "abc" - it = AsyncIteratorWrapper("abc") - async for item in it: - print(it) + async for item in AsyncIteratorWrapper("abc"): + print(item) Why StopAsyncIteration? @@ -501,11 +499,11 @@ :Asynchronous iterable: An object with an ``__aiter__`` method, which must return an *asynchronous - iterator* object. Can be used with ``async for``. See + iterator* object. Can be used with ``async for``. See `Asynchronous Iterators and "async for"`_ for details. :Asynchronous iterator: - An asynchronous iterator has an ``__anext__`` method.See + An asynchronous iterator has an ``__anext__`` method. See `Asynchronous Iterators and "async for"`_ for details. @@ -537,9 +535,6 @@ * generator: a "regular" generator, function defined with ``def`` and which contains a least one ``yield`` or ``yield from`` expression. -*Future-like* is an object with an ``__await__`` method, see -`Await Expression`_ section for details. - Transition Plan =============== -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Fri Apr 17 23:14:51 2015 From: python-checkins at python.org (yury.selivanov) Date: Fri, 17 Apr 2015 21:14:51 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_pep-0492=3A_rename_set=5Fasyn?= =?utf-8?q?c=5Fwrapper_-=3E_set=5Fcoroutine=5Fwrapper?= Message-ID: <20150417211450.15803.89852@psf.io> https://hg.python.org/peps/rev/699ef9a26ef9 changeset: 5763:699ef9a26ef9 user: Yury Selivanov date: Fri Apr 17 17:14:47 2015 -0400 summary: pep-0492: rename set_async_wrapper -> set_coroutine_wrapper files: pep-0492.txt | 16 +++++++--------- 1 files changed, 7 insertions(+), 9 deletions(-) diff --git a/pep-0492.txt b/pep-0492.txt --- a/pep-0492.txt +++ b/pep-0492.txt @@ -439,7 +439,7 @@ different debug facility, has no impact on ``@coroutine`` decorator's behavior. With this proposal, coroutines is a native, distinct from generators, -concept. A new method ``set_async_wrapper`` is added to the ``sys`` module, +concept. A new method ``set_coroutine_wrapper`` is added to the ``sys`` module, with which frameworks can provide advanced debugging facilities. It is also important to make coroutines as fast and efficient as possible, @@ -453,18 +453,19 @@ def async_debug_wrap(generator): return asyncio.AsyncDebugWrapper(generator) - sys.set_async_wrapper(async_debug_wrap) + sys.set_coroutine_wrapper(async_debug_wrap) debug_me() # <- this line will likely GC the coroutine object and # trigger AsyncDebugWrapper's code. assert isinstance(debug_me(), AsyncDebugWrapper) - sys.set_async_wrapper(None) # <- this unsets any previously set wrapper + sys.set_coroutine_wrapper(None) # <- this unsets any + # previously set wrapper assert not isinstance(debug_me(), AsyncDebugWrapper) -If ``sys.set_async_wrapper()`` is called twice, the new wrapper replaces the -previous wrapper. ``sys.set_async_wrapper(None)`` unsets the wrapper. +If ``sys.set_coroutine_wrapper()`` is called twice, the new wrapper replaces the +previous wrapper. ``sys.set_coroutine_wrapper(None)`` unsets the wrapper. Glossary @@ -915,7 +916,7 @@ 5. New AST nodes: ``AsyncFor``, ``AsyncWith``, ``Await``; ``FunctionDef`` AST node got a new argument ``is_async``. -6. New functions: ``sys.set_async_wrapper(callback)`` and +6. New functions: ``sys.set_coroutine_wrapper(callback)`` and ``types.async_def(gen)``. 7. New ``CO_ASYNC`` bit flag for code objects. @@ -936,12 +937,10 @@ import asyncio - async def echo_server(): print('Serving on localhost:8000') await asyncio.start_server(handle_connection, 'localhost', 8000) - async def handle_connection(reader, writer): print('New connection...') @@ -954,7 +953,6 @@ print('Sending {:.10}... back'.format(repr(data))) writer.write(data) - loop = asyncio.get_event_loop() loop.run_until_complete(echo_server()) try: -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Fri Apr 17 23:37:44 2015 From: python-checkins at python.org (yury.selivanov) Date: Fri, 17 Apr 2015 21:37:44 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_pep-0492=3A_Fix_snippet_with_?= =?utf-8?q?Grammar?= Message-ID: <20150417213744.21337.65415@psf.io> https://hg.python.org/peps/rev/6a3cf99aace6 changeset: 5764:6a3cf99aace6 user: Yury Selivanov date: Fri Apr 17 17:37:41 2015 -0400 summary: pep-0492: Fix snippet with Grammar files: pep-0492.txt | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/pep-0492.txt b/pep-0492.txt --- a/pep-0492.txt +++ b/pep-0492.txt @@ -584,7 +584,7 @@ decorated: decorators (classdef | funcdef | async_funcdef) async_funcdef: ASYNC funcdef - async_stmt: ASYNC (funcdef | with_stmt) # will add for_stmt later + async_stmt: ASYNC (funcdef | with_stmt | for_stmt) compound_stmt: (if_stmt | while_stmt | for_stmt | try_stmt | with_stmt | funcdef | classdef | decorated | async_stmt) -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Fri Apr 17 23:44:15 2015 From: python-checkins at python.org (guido.van.rossum) Date: Fri, 17 Apr 2015 21:44:15 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_New_version_of_PEP_484_for_re?= =?utf-8?q?view_by_python-dev=2E?= Message-ID: <20150417214415.40534.76576@psf.io> https://hg.python.org/peps/rev/9c4dca560aa9 changeset: 5765:9c4dca560aa9 user: Guido van Rossum date: Fri Apr 17 14:44:03 2015 -0700 summary: New version of PEP 484 for review by python-dev. files: pep-0484.txt | 684 ++++++++++++++++++++++++++++---------- 1 files changed, 507 insertions(+), 177 deletions(-) diff --git a/pep-0484.txt b/pep-0484.txt --- a/pep-0484.txt +++ b/pep-0484.txt @@ -3,12 +3,13 @@ Version: $Revision$ Last-Modified: $Date$ Author: Guido van Rossum , Jukka Lehtosalo , ?ukasz Langa +BDFL-delegate: Mark Shannon Discussions-To: Python-Dev Status: Draft Type: Standards Track Content-Type: text/x-rst Created: 29-Sep-2014 -Post-History: 16-Jan-2015,20-Mar-2015 +Post-History: 16-Jan-2015,20-Mar-2015,17-Apr-2015 Resolution: @@ -33,7 +34,7 @@ type "sequence of integers" can be written as ``Sequence[int]``. The square brackets mean that no new syntax needs to be added to the language. The example here uses a custom class ``Sequence``, imported -from a pure-Python module ``typing.py``. The ``Sequence[int]`` +from a pure-Python module ``typing``. The ``Sequence[int]`` notation works by implementing ``__getitem__()`` in the metaclass. The type system supports unions, generic types, and a special type @@ -78,47 +79,134 @@ mandatory, even by convention. +What is checked? +================ + +Any function (or method -- for brevity we won't be repeating this) +with at least one argument or return annotation is checked, unless +type checking is disabled by the ``@no_type_check`` decorator or a +``# type: ignore`` comment (see below). + +A checked function should have annotations for all its arguments and +its return type, with the exception that the ``self`` argument of a +method should not be annotated; it is assumed to have the type of the +containing class. Notably, the return type of ``__init__`` should be +annotated with ``-> None``. + +The body of a checked function is checked for consistency with the +given annotations. The annotations are also used to check correctness +of calls appearing in other checked functions. + +Functions without any annotations (or whose checking is disabled) are +assumed to have type ``Any`` when they are referenced in checked +functions, and this should completely silence complaints from the +checker regarding those references (although a checker may still +request that a type be specified using a cast or a ``# type:`` comment +if a more specific type than ``Any`` is needed for analysis of +subsequent code). + +A type checker should understand decorators; this may require +annotations on decorator definitions. In particular, a type checker +should understand the built-in decorators ``@property``, +``@staticmethod`` and ``@classmethod``. The first argument of a class +method should not be annotated; it is assumed to be a subclass of the +defining class. + + Type Definition Syntax ====================== The syntax leverages PEP 3107-style annotations with a number of -extensions described in sections below. In its basic form, type hinting -is used by filling function annotations with classes:: +extensions described in sections below. In its basic form, type +hinting is used by filling function annotation slots with classes:: def greeting(name: str) -> str: return 'Hello ' + name -This denotes that the expected type of the ``name`` argument is ``str``. -Analogically, the expected return type is ``str``. Subclasses of -a specified argument type are also accepted as valid types for that -argument. +This states that the expected type of the ``name`` argument is +``str``. Analogically, the expected return type is ``str``. -Abstract base classes, types available in the ``types`` module, and -user-defined classes may be used as type hints as well. Annotations -must be valid expressions that evaluate without raising exceptions at -the time the function is defined. In addition, the needs of static -analysis require that annotations must be simple enough to be -interpreted by static analysis tools. (This is an intentionally -somewhat vague requirement.) +Expressions whose type is a subtype of a specific argument type are +also accepted for that argument. -.. FIXME: Define rigorously what is/isn't supported. -When used as an annotation, the expression ``None`` is considered -equivalent to ``NoneType`` (i.e., ``type(None)`` for type hinting -purposes. +Acceptable type hints +--------------------- -Type aliases are also valid type hints:: +Type hints may be built-in classes (including those defined in +standard library or third-party extension modules), abstract base +classes, types available in the ``types`` module, and user-defined +classes (including those defined in the standard library or +third-party modules). Annotations for built-in classes (and other +classes at the discretion of the developer) may be placed in stub +files (see below). - integer = int +Annotations must be valid expressions that evaluate without raising +exceptions at the time the function is defined (but see below for +forward references). - def retry(url: str, retry_count: integer) -> None: ... +The needs of static analysis require that annotations must be simple +enough to be interpreted by static analysis tools. In particular, +dynamically computed types are not acceptable. (This is an +intentionally somewhat vague requirement, specific inclusions and +exclusions may be added to future versions of this PEP as warranted by +the discussion.) -New names that are added to support features described in following -sections are available in the ``typing`` package. +In addition to the above, the following special constructs defined +below may be used: ``None``, ``Any``, ``Union``, ``Tuple``, +``Callable``, all ABCs and stand-ins for concrete classes exported +from ``typing`` (e.g. ``Sequence`` and ``Dict``), type variables, and +type aliases. +All newly introducedw names used to support features described in +following sections (such as ``Any`` and ``Union``) are available in +the ``typing`` module. -Callbacks ---------- + +Using None +---------- + +When used in a type hint, the expression ``None`` is considered +equivalent to ``type(None)``. + + +Type aliases +------------ + +Type aliases are defined by simple variable assignments:: + + Url = str + + def retry(url: Url, retry_count: int) -> None: ... + +Note that we recommend capitalizing alias names, since they represent +user-defined types, which (like user-defined classes) are typically +spelled that way. + +Type aliases may be as complex as type hints in annotations -- +anything that is acceptable as a type hint is acceptable in a type +alias:: + + from typing import TypeVar, Iterable, Tuple + + T = TypeVar('T', int, float, complex) + Vector = Iterable[Tuple[T, T]] + + def inproduct(v: Vector) -> T: + return sum(x*y for x, y in v) + +This is equivalent to:: + + from typing import TypeVar, Iterable, Tuple + + T = TypeVar('T', int, float, complex) + + def inproduct(v: Iterable[Tuple[T, T]]) -> T: + return sum(x*y for x, y in v) + + +Callable +-------- Frameworks expecting callback functions of specific signatures might be type hinted using ``Callable[[Arg1Type, Arg2Type], ReturnType]``. @@ -173,44 +261,217 @@ def first(l: Sequence[T]) -> T: # Generic function return l[0] -In this case the contract is that the returning value is consistent with +In this case the contract is that the returned value is consistent with the elements held by the collection. -``TypeVar`` supports constraining parametric types to classes with any of -the specified bases. Example:: +``TypeVar`` supports constraining parametric types to a fixed set of +possible types. For example, we can define a type variable that ranges +over just ``str`` and ``bytes``. By default, a type variable ranges +over all possible types. Example of constraining a type variable:: + + from typing import TypeVar + + AnyStr = TypeVar('AnyStr', str, bytes) + + def concat(x: AnyStr, y: AnyStr) -> AnyStr: + return x + y + +The function ``concat`` can be called with either two ``str`` arguments +or two ``bytes`` arguments, but not with a mix of ``str`` and ``bytes`` +arguments. + +Note that subtypes of types constrained by a type variable are treated +as their respective explicitly listed base types in the context of the +type variable. Consider this example:: + + class MyStr(str): ... + + x = concat(MyStr('apple'), MyStr('pie')) + +The call is valid but the type variable ``AnyStr`` will be set to +``str`` and not ``MyStr``. In effect, the inferred type of the return +value assigned to ``x`` will also be ``str``. + +Additionally, ``Any`` is a valid value for every type variable. +Consider the following:: + + def count_truthy(elements: List[Any]) -> int: + return sum(1 for elem in elements if element) + +This is equivalent to omitting the generic notation and just saying +``elements: List``. + + +User-defined generic types +-------------------------- + +You can include a ``Generic`` base class to define a user-defined class +as generic. Example:: + + from typing import TypeVar, Generic + + T = TypeVar('T') + + class LoggedVar(Generic[T]): + def __init__(self, value: T, name: str, logger: Logger) -> None: + self.name = name + self.logger = logger + self.value = value + + def set(self, new: T) -> None: + self.log('Set ' + repr(self.value)) + self.value = new + + def get(self) -> T: + self.log('Get ' + repr(self.value)) + return self.value + + def log(self, message: str) -> None: + self.logger.info('{}: {}'.format(self.name message)) + +``Generic[T]`` as a base class defines that the class ``LoggedVar`` +takes a single type parameter ``T``. This also makes ``T`` valid as +a type within the class body. + +The ``Generic`` base class uses a metaclass that defines ``__getitem__`` +so that ``LoggedVar[t]`` is valid as a type:: from typing import Iterable - X = TypeVar('X') - Y = TypeVar('Y', Iterable[X]) + def zero_all_vars(vars: Iterable[LoggedVar[int]]) -> None: + for var in vars: + var.set(0) - def filter(rule: Callable[[X], bool], input: Y) -> Y: +A generic type can have any number of type variables, and type variables +may be constrained. This is valid:: + + from typing import TypeVar, Generic + ... + + T = TypeVar('T') + S = TypeVar('S') + + class Pair(Generic[T, S]): ... -.. FIXME: Add an example with multiple bases defined. +Each type variable argument to ``Generic`` must be distinct. This is +thus invalid:: -In the example above we specify that ``Y`` can be any subclass of -Iterable with elements of type ``X``, as long as the return type of -``filter()`` will be the same as the type of the ``input`` -argument. + from typing import TypeVar, Generic + ... -.. FIXME: Explain more about how this works. + T = TypeVar('T') + + class Pair(Generic[T, T]): # INVALID + ... + +You can use multiple inheritance with ``Generic``:: + + from typing import TypeVar, Generic, Sized + + T = TypeVar('T') + + class LinkedList(Sized, Generic[T]): + ... + + +Arbitrary generic types as base classes +--------------------------------------- + +``Generic[T]`` is only valid as a base class -- it's not a proper type. +However, user-defined generic types such as ``LinkedList[T]`` from the +above example and built-in generic types and ABCs such as ``List[T]`` +and ``Iterable[T]`` are valid both as types and as base classes. For +example, we can define a subclass of ``Dict`` that specializes type +arguments:: + + from typing import Dict, List, Optional + + class Node: + ... + + class SymbolTable(Dict[str, List[Node]]): + def push(self, name: str, node: Node) -> None: + self.setdefault(name, []).append(node) + + def pop(self, name: str) -> Node: + return self[name].pop() + + def lookup(self, name: str) -> Optional[Node]: + nodes = self.get(name) + if nodes: + return nodes[-1] + return None + +``SymbolTable`` is a subclass of ``dict`` and a subtype of ``Dict[str, +List[Node]]``. + +If a generic base class has a type variable as a type argument, this +makes the defined class generic. For example, we can define a generic +``LinkedList`` class that is iterable and a container:: + + from typing import TypeVar, Iterable, Container + + T = TypeVar('T') + + class LinkedList(Iterable[T], Container[T]): + ... + +Now ``LinkedList[int]`` is a valid type. Note that we can use ``T`` +multiple times in the base class list, as long as we don't use the +same type variable ``T`` multiple times within ``Generic[...]``. + + +Abstract generic types +---------------------- + +The metaclass used by ``Generic`` is a subclass of ``abc.ABCMeta``. +A generic class can be an ABC by including abstract methods +or properties, and generic classes can also have ABCs as base +classes without a metaclass conflict. Forward references ------------------ When a type hint contains names that have not been defined yet, that -definition may be expressed as a string, to be resolved later. For -example, instead of writing:: +definition may be expressed as a string literal, to be resolved later. - def notify_by_email(employees: Set[Employee]) -> None: ... +A situation where this occurs commonly is the definition of a +container class, where the class being defined occurs in the signature +of some of the methods. For example, the following code (the start of +a simple binary tree implementation) does not work:: -one might write:: + class Tree: + def __init__(self, left: Tree, right: Tree): + self.left = left + self.right = right - def notify_by_email(employees: 'Set[Employee]') -> None: ... +To address this, we write:: -.. FIXME: Rigorously define this, and give a motivational example. + class Tree: + def __init__(self, left: 'Tree', right: 'Tree'): + self.left = left + self.right = right + +The string literal should contain a valid Python expression (i.e., +``compile(lit, '', 'expr')`` should be a valid code object) and it +should evaluate without errors once the module has been fully loaded. +The local and global namespace in which it is evaluated should be the +same namespaces in which default arguments to the same function would +be evaluated. + +Moreover, the expression should be parseable as a valid type hint, i.e., +it is constrained by the rules from the section `Acceptable type hints`_ +above. + +It is allowable to use string literals as *part* of a type hint, for +example:: + + class Tree: + ... + def leaves(self) -> List['Tree']: + ... Union types @@ -264,18 +525,17 @@ almost all operations on it, and assigning it to a variable (or using it as a return value) of a more specialized type is a type error. On the other hand, when a value has type ``Any``, the type checker will -allow all operations on it, and a value of type `Any`` can be assigned +allow all operations on it, and a value of type ``Any`` can be assigned to a variable (or used as a return value) of a more constrained type. -Platform-specific type checking -------------------------------- +Predefined constants +-------------------- -In some cases the typing information will depend on the platform that -the program is being executed on. To enable specifying those -differences, simple conditionals can be used:: +Some predefined Boolean constants are defined in the ``typing`` +module to enable platform-specific type definitions and such:: - from typing import PY2, WINDOWS + from typing import PY2, PY3, WINDOWS, POSIX if PY2: text = unicode @@ -289,66 +549,82 @@ else: loop = UnixSelectorEventLoop -.. FIXME: Also define PY3 and POSIX? - -Arbitrary literals defined in the form of ``NAME = True`` will also be -accepted by the type checker to differentiate type resolution:: - - DEBUG = False - ... - if DEBUG: - class Tracer: - - else: - class Tracer: - - -For the purposes of type hinting, the type checker assumes ``__debug__`` -is set to ``True``, in other words the ``-O`` command-line option is not -used while type checking. +It is up to the type checker implementation to define their values, as +long as ``PY2 == not PY3`` and ``WINDOWS == not POSIX``. When the +program is being executed these always reflect the current platform, +and this is also the suggested default when the program is being +type-checked. Compatibility with other uses of function annotations ------------------------------------------------------ +===================================================== A number of existing or potential use cases for function annotations -exist, which are incompatible with type hinting. These may confuse a -static type checker. However, since type hinting annotations have no -runtime behavior (other than evaluation of the annotation expression -and storing annotations in the ``__annotations__`` attribute of the -function object), this does not make the program incorrect -- it just -makes it issue warnings when a static analyzer is used. +exist, which are incompatible with type hinting. These may confuse +a static type checker. However, since type hinting annotations have no +runtime behavior (other than evaluation of the annotation expression and +storing annotations in the ``__annotations__`` attribute of the function +object), this does not make the program incorrect -- it just may cause +a type checker to emit spurious warnings or errors. To mark portions of the program that should not be covered by type -hinting, use the following: +hinting, you can use one or more of the following: -* a ``@no_type_check`` decorator on classes and functions +* a ``# type: ignore`` comment; -* a ``# type: ignore`` comment on arbitrary lines +* a ``@no_type_check`` decorator on a class or function; -.. FIXME: should we have a module-wide comment as well? +* a custom class or function decorator marked with + ``@no_type_check_decorator``. -.. FIXME: suggest that other uses of annotations be replaced with decorators +For more details see later sections. -.. FIXME: add reference to "rejected alternatives" +In order for maximal compatibility with offline type checking it may +eventually be a good idea to change interfaces that rely on annotations +to switch to a different mechanism, for example a decorator. In Python +3.5 there is no pressure to do this, however. See also the longer +discussion under `Rejected alternatives`_ below. -Type Hints on Local and Global Variables -======================================== +Type comments +============= No first-class syntax support for explicitly marking variables as being of a specific type is added by this PEP. To help with type inference in complex cases, a comment of the following format may be used:: x = [] # type: List[Employee] + x, y, z = [], [], [] # type: List[int], List[int], List[str] + x, y, z = [], [], [] # type: (List[int], List[int], List[str]) + x = [ + 1, + 2, + ] # type: List[int] -In the case where type information for a local variable is needed before -it is declared, an ``Undefined`` placeholder might be used:: +Type comments should be put on the last line of the statement that +contains the variable definition. They can also be placed on +``with`` statements and ``for`` statements, right after the colon. - from typing import Undefined +Examples of type comments on ``with`` and ``for`` statements:: - x = Undefined # type: List[Employee] - y = Undefined(int) + with frobnicate() as foo: # type: int + # Here foo is an int + ... + + for x, y in points: # type: float, float + # Here x and y are floats + ... + +The ``# type: ignore`` comment should be put on the line that the +error refers to:: + + import http.client + errors = { + 'not_found': http.client.NOT_FOUND # type: ignore + } + +A ``# type: ignore`` comment on a line by itself disables all type +checking for the rest of the file. If type hinting proves useful in general, a syntax for typing variables may be provided in a future Python version. @@ -360,7 +636,7 @@ programmer may know that an expression is of a more constrained type than the type checker infers. For example:: - from typing import List + from typing import List, cast def find_first_str(a: List[object]) -> str: index = next(i for i, x in enumerate(a) if isinstance(x, str)) @@ -374,11 +650,11 @@ expression unchanged -- it does not check the type, and it does not convert or coerce the value. -Casts differ from type comments (see the previous section). When -using a type comment, the type checker should still verify that the -inferred type is consistent with the stated type. When using a cast, -the type checker trusts the programmer. Also, casts can be used in -expressions, while type comments only apply to assignments. +Casts differ from type comments (see the previous section). When using +a type comment, the type checker should still verify that the inferred +type is consistent with the stated type. When using a cast, the type +checker should blindly believe the programmer. Also, casts can be used +in expressions, while type comments only apply to assignments. Stub Files @@ -390,28 +666,31 @@ * Extension modules -* 3rd party modules whose authors have not yet added type hints +* Third-party modules whose authors have not yet added type hints -* Standard library modules for which type hints have not yet been written +* Standard library modules for which type hints have not yet been + written * Modules that must be compatible with Python 2 and 3 * Modules that use annotations for other purposes -Stub files have the same syntax as regular Python modules. There is -one feature of the ``typing`` module that may only be used in stub -files: the ``@overload`` decorator described below. +Stub files have the same syntax as regular Python modules. There is one +feature of the ``typing`` module that may only be used in stub files: +the ``@overload`` decorator described below. The type checker should only check function signatures in stub files; -function bodies in stub files should just be a single ``pass`` statement. +function bodies in stub files should just be a single ``pass`` +statement. -The type checker should have a configurable search path for stub -files. If a stub file is found the type checker should not read the +The type checker should have a configurable search path for stub files. +If a stub file is found the type checker should not read the corresponding "real" module. -Stub files may use the ``.py`` extension or alternatively may use the -``.pyi`` extension. The latter makes it possible to maintain stub -files in the same directory as the corresponding real module. +While stub files are syntactically valid Python modules, they use the +``.pyi`` extension to make it possible to maintain stub files in the +same directory as the corresponding real module. This also reinforces +the notion that no runtime behavior should be expected of stub files. Function overloading -------------------- @@ -478,6 +757,54 @@ to be constrained by the overloading syntax defined for type hints in stub files. +Storing and distributing stub files +----------------------------------- + +The easiest form of stub file storage and distribution is to put them +alongside Python modules in the same directory. This makes them easy to +find by both programmers and the tools. However, since package +maintainers are free not to add type hinting to their packages, +third-party stubs installable by ``pip`` from PyPI are also supported. +In this case we have to consider three issues: naming, versioning, +installation path. + +This PEP does not provide a recommendation on a naming scheme that +should be used for third-party stub file packages. Discoverability will +hopefully be based on package popularity, like with Django packages for +example. + +Third-party stubs have to be versioned using the lowest version of the +source package that is compatible. Example: FooPackage has versions +1.0, 1.1, 1.2, 1.3, 2.0, 2.1, 2.2. There are API changes in versions +1.1, 2.0 and 2.2. The stub file package maintainer is free to release +stubs for all versions but at least 1.0, 1.1, 2.0 and 2.2 are needed +to enable the end user type check all versions. This is because the +user knows that the closest *lower or equal* version of stubs is +compatible. In the provided example, for FooPackage 1.3 the user would +choose stubs version 1.1. + +Note that if the user decides to use the "latest" available source +package, using the "latest" stub files should generally also work if +they're updated often. + +Third-party stub packages can use any location for stub storage. The +type checker will search for them using PYTHONPATH. A default fallback +directory that is always checked is ``shared/typehints/python3.5/`` (or +3.6, etc.). Since there can only be one package installed for a given +Python version per environment, no additional versioning is performed +under that directory (just like bare directory installs by ``pip`` in +site-packages). Stub file package authors might use the following +snippet in ``setup.py``:: + + ... + data_files=[ + ( + 'shared/typehints/python{}.{}'.format(*sys.version_info[:2]), + pathlib.Path(SRC_PATH).glob('**/*.pyi'), + ), + ], + ... + Exceptions ========== @@ -488,12 +815,12 @@ docstring. -The ``typing`` Package -====================== +The ``typing`` Module +===================== To open the usage of static type checking to Python 3.5 as well as older versions, a uniform namespace is required. For this purpose, a new -package in the standard library is introduced called ``typing``. It +module in the standard library is introduced called ``typing``. It holds a set of classes representing builtin types with generics, namely: * Dict, used as ``Dict[key_type, value_type]`` @@ -511,12 +838,24 @@ using one type and ellipsis, for example ``Tuple[int, ...]``. (The ``...`` here are part of the syntax.) +* NamedTuple, used as + ``NamedTuple(type_name, [(field_name, field_type), ...])`` + and equivalent to + ``collections.namedtuple(type_name, [field_name, ...])``. + The generic versions of concrete collection types (``Dict``, ``List``, ``Set``, ``FrozenSet``, and homogeneous arbitrary-length ``Tuple``) are mainly useful for annotating return values. For arguments, prefer the abstract collection types defined below, e.g. ``Mapping``, ``Sequence`` or ``AbstractSet``. +The ``typing`` module defines the ``Generator`` type for return values +of generator functions. It is a subtype of ``Iterable`` and it has +additional type variables for the type accepted by the ``send()`` +method and the return type of the generator: + +* Generator, used as ``Generator[yield_type, send_type, return_type]`` + It also introduces factories and helper members needed to express generics and union types: @@ -527,24 +866,20 @@ * TypeVar, used as ``X = TypeVar('X', Type1, Type2, Type3)`` or simply ``Y = TypeVar('Y')`` -* Undefined, used as ``local_variable = Undefined # type: List[int]`` or - ``local_variable = Undefined(List[int])`` (the latter being slower - during runtime) - * Callable, used as ``Callable[[Arg1Type, Arg2Type], ReturnType]`` -* AnyStr, equivalent to ``TypeVar('AnyStr', str, bytes)`` +* AnyStr, defined as ``TypeVar('AnyStr', str, bytes)`` All abstract base classes available in ``collections.abc`` are -importable from the ``typing`` package, with added generics support: +importable from the ``typing`` module, with added generics support: * ByteString -* Callable +* Callable (see above) * Container -* Hashable +* Hashable (not generic, but present for completeness) * ItemsView @@ -566,14 +901,26 @@ * Sequence -* Set as ``AbstractSet``. This name change was required because ``Set`` - in the ``typing`` module means ``set()`` with generics. +* Set, renamed to ``AbstractSet``. This name change was required + because ``Set`` in the ``typing`` module means ``set()`` with + generics. -* Sized +* Sized (not generic, but present for completeness) * ValuesView -* Mapping +A few one-off types are defined that test for single special methods +(similar to ``Hashable`` or ``Sized``): + +* Reversible, to test for ``__reversed__`` + +* SupportsAbs, to test for ``__abs__`` + +* SupportsFloat, to test for ``__float__`` + +* SupportsInt, to test for ``__int__`` + +* SupportsRound, to test for ``__round__`` The library includes literals for platform-specific type hinting: @@ -585,55 +932,42 @@ * POSIX, equivalent to ``not WINDOWS`` +The following conveniece functions and decorators are exported: + +* cast, described earlier + +* no_type_check, a decorator to disable type checking per class or + function (see below) + +* no_type_check_decorator, a decorator to create your own decorators + with the same meaning as ``@no_type_check`` (see below) + +* overload, described earlier + +* get_type_hints, a utility function to retrieve the type hints from a + function or method. Given a function or method object, it returns + a dict with the same format as ``__annotations__``, but evaluating + forward references (which are given as string literals) as expressions + in the context of the original function or method definition. + The following types are available in the ``typing.io`` module: -* IO +* IO (generic over ``AnyStr``) -* BinaryIO +* BinaryIO (a simple subclass of ``IO[bytes]``) -* TextIO +* TextIO (a simple subclass of ``IO[str]``) The following types are provided by the ``typing.re`` module: * Match and Pattern, types of ``re.match()`` and ``re.compile()`` - results + results (generic over ``AnyStr``) As a convenience measure, types from ``typing.io`` and ``typing.re`` are also available in ``typing`` (quoting Guido, "There's a reason those modules have two-letter names."). -The place of the ``typing`` module in the standard library ----------------------------------------------------------- - -.. FIXME: complete this section (or discard?) - - -Usage Patterns -============== - -The main use case of type hinting is static analysis using an external -tool without executing the analyzed program. Existing tools used for -that purpose like ``pyflakes`` [pyflakes]_ or ``pylint`` [pylint]_ -might be extended to support type checking. New tools, like mypy [mypy]_, -can be adopted specifically for this purpose. - -Type checking based on type hints is understood as a best-effort -mechanism. In other words, whenever types are not annotated and cannot -be inferred, the type checker considers such code valid. Type errors -are only reported in case of explicit or inferred conflict. Moreover, -as a mechanism that is not tied to execution of the code, it does not -affect runtime behaviour. In other words, even in the case of a typing -error, the program will continue running. - -The implementation of a type checker, whether linting source files or -enforcing type information during runtime, is out of scope for this PEP. - -.. FIXME: This is somewhat redundant with the updated initial sections. - -.. FIXME: Describe run-time behavior of generic types. - - Rejected Alternatives ===================== @@ -771,7 +1105,7 @@ that class names become defined once the entire body of the class has been executed. Our solution, which isn't particularly elegant, but gets the job done, is to allow using string literals in annotations. -Most of the time you won't have to use this though -- most _uses_ of +Most of the time you won't have to use this though -- most *uses* of type hints are expected to reference builtin types or types defined in other modules. @@ -782,6 +1116,21 @@ since the Python interpreter doesn't actually know whether a particular annotation is meant to be a type hint or something else. +A compromise is possible where a ``__future__`` import could enable +turning *all* annotations in a given module into string literals, as +follows:: + + from __future__ import annotations + + class ImSet: + def add(self, a: ImSet) -> List[ImSet]: ... + + assert ImSet.add.__annotations__ == {'a': 'ImSet', 'return': 'List[ImSet]'} + +Such a ``__future__`` import statement will be proposed in a separate +PEP. + + The double colon ---------------- @@ -864,26 +1213,6 @@ problem would that solve? It would just be procrastination. -Is Type Hinting Pythonic? -========================= - -.. FIXME: Do we really need this section? - -Type annotations provide important documentation for how a unit of code -should be used. Programmers should therefore provide type hints on -public APIs, namely argument and return types on functions and methods -considered public. However, because types of local and global variables -can be often inferred, they are rarely necessary. - -The kind of information that type hints hold has always been possible to -achieve by means of docstrings. In fact, a number of formalized -mini-languages for describing accepted arguments have evolved. Moving -this information to the function declaration makes it more visible and -easier to access both at runtime and by static analysis. Adding to that -the notion that ?explicit is better than implicit?, type hints are -indeed *Pythonic*. - - PEP Development Process ======================= @@ -901,7 +1230,8 @@ This document could not be completed without valuable input, encouragement and advice from Jim Baker, Jeremy Siek, Michael Matson -Vitousek, Andrey Vlasovskikh, and Radomir Dopieralski. +Vitousek, Andrey Vlasovskikh, Radomir Dopieralski, Peter Ludemann, +and the BDFL-Delegate, Mark Shannon. Influences include existing languages, libraries and frameworks mentioned in PEP 482. Many thanks to their creators, in alphabetical -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Sat Apr 18 00:07:02 2015 From: python-checkins at python.org (yury.selivanov) Date: Fri, 17 Apr 2015 22:07:02 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_pep-0492=3A_Fix_explanation_t?= =?utf-8?q?hat_async_def_are_always_coroutines?= Message-ID: <20150417220702.27902.29556@psf.io> https://hg.python.org/peps/rev/130e8d350a1b changeset: 5766:130e8d350a1b user: Yury Selivanov date: Fri Apr 17 18:06:30 2015 -0400 summary: pep-0492: Fix explanation that async def are always coroutines files: pep-0492.txt | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pep-0492.txt b/pep-0492.txt --- a/pep-0492.txt +++ b/pep-0492.txt @@ -78,8 +78,8 @@ Key properties of coroutines: -* Coroutines are always generators, even if they do not contain ``await`` - expressions. +* ``async def`` functions are always coroutines, even if they do not contain + ``await`` expressions. * It is a ``SyntaxError`` to have ``yield`` or ``yield from`` expressions in an ``async`` function. -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Sat Apr 18 01:34:18 2015 From: python-checkins at python.org (yury.selivanov) Date: Fri, 17 Apr 2015 23:34:18 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_pep-0492=3A_Add_a_sub-section?= =?utf-8?q?_about_Async_Lambdas?= Message-ID: <20150417233418.40540.47954@psf.io> https://hg.python.org/peps/rev/f3196e8f9bb6 changeset: 5767:f3196e8f9bb6 user: Yury Selivanov date: Fri Apr 17 19:34:15 2015 -0400 summary: pep-0492: Add a sub-section about Async Lambdas files: pep-0492.txt | 9 +++++++++ 1 files changed, 9 insertions(+), 0 deletions(-) diff --git a/pep-0492.txt b/pep-0492.txt --- a/pep-0492.txt +++ b/pep-0492.txt @@ -811,6 +811,15 @@ if there is a strong demand for this feature. +Async lambdas +------------- + +Lambda coroutines are not part of this proposal. In this proposal they would +look like ``async lambda(parameters): expression``. Unless there is a strong +demand to have them as part of this proposal, it is recommended to consider +them later in a separate PEP. + + Performance =========== -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Sat Apr 18 02:09:21 2015 From: python-checkins at python.org (berker.peksag) Date: Sat, 18 Apr 2015 00:09:21 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_Fix_markup=2E?= Message-ID: <20150418000921.40524.80928@psf.io> https://hg.python.org/peps/rev/22f696a84d15 changeset: 5768:22f696a84d15 user: Berker Peksag date: Sat Apr 18 03:09:31 2015 +0300 summary: Fix markup. files: pep-0492.txt | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/pep-0492.txt b/pep-0492.txt --- a/pep-0492.txt +++ b/pep-0492.txt @@ -246,7 +246,7 @@ 2. An *asynchronous iterator object* must implement an ``__anext__`` method returning an *awaitable*. -3. To stop iteration```__anext__`` must raise a ``StopAsyncIteration`` +3. To stop iteration ``__anext__`` must raise a ``StopAsyncIteration`` exception. An example of asynchronous iterable:: -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Sat Apr 18 06:07:44 2015 From: python-checkins at python.org (christian.heimes) Date: Sat, 18 Apr 2015 04:07:44 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Remove_local_dead_code=2E_?= =?utf-8?q?In_both_blocks_dir_is_always_greater_0=2E?= Message-ID: <20150418035743.21341.12294@psf.io> https://hg.python.org/cpython/rev/bc1a178b3bc8 changeset: 95704:bc1a178b3bc8 user: Christian Heimes date: Sat Apr 18 05:54:02 2015 +0200 summary: Remove local dead code. In both blocks dir is always greater 0. files: Objects/bytearrayobject.c | 3 +-- Objects/bytesobject.c | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/Objects/bytearrayobject.c b/Objects/bytearrayobject.c --- a/Objects/bytearrayobject.c +++ b/Objects/bytearrayobject.c @@ -1171,10 +1171,9 @@ /* Issue #23573: FIXME, windows has no memrchr() */ else if (sub_len == 1 && dir > 0) { unsigned char needle = *sub; - int mode = (dir > 0) ? FAST_SEARCH : FAST_RSEARCH; res = stringlib_fastsearch_memchr_1char( PyByteArray_AS_STRING(self) + start, end - start, - needle, needle, mode); + needle, needle, FAST_SEARCH); if (res >= 0) res += start; } diff --git a/Objects/bytesobject.c b/Objects/bytesobject.c --- a/Objects/bytesobject.c +++ b/Objects/bytesobject.c @@ -1806,10 +1806,9 @@ /* Issue #23573: FIXME, windows has no memrchr() */ else if (sub_len == 1 && dir > 0) { unsigned char needle = *sub; - int mode = (dir > 0) ? FAST_SEARCH : FAST_RSEARCH; res = stringlib_fastsearch_memchr_1char( PyBytes_AS_STRING(self) + start, end - start, - needle, needle, mode); + needle, needle, FAST_SEARCH); if (res >= 0) res += start; } -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Apr 18 08:44:08 2015 From: python-checkins at python.org (berker.peksag) Date: Sat, 18 Apr 2015 06:44:08 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_Fix_PEP_generation_error=2E?= Message-ID: <20150418064408.6579.38095@psf.io> https://hg.python.org/peps/rev/f113c9a86b96 changeset: 5769:f113c9a86b96 user: Berker Peksag date: Sat Apr 18 09:44:19 2015 +0300 summary: Fix PEP generation error. files: pep-0484.txt | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/pep-0484.txt b/pep-0484.txt --- a/pep-0484.txt +++ b/pep-0484.txt @@ -3,7 +3,7 @@ Version: $Revision$ Last-Modified: $Date$ Author: Guido van Rossum , Jukka Lehtosalo , ?ukasz Langa -BDFL-delegate: Mark Shannon +BDFL-Delegate: Mark Shannon Discussions-To: Python-Dev Status: Draft Type: Standards Track -- Repository URL: https://hg.python.org/peps From solipsis at pitrou.net Sat Apr 18 10:37:32 2015 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Sat, 18 Apr 2015 08:37:32 +0000 Subject: [Python-checkins] Daily reference leaks (bc1a178b3bc8): sum=3 Message-ID: <20150418083732.31119.3336@psf.io> results for bc1a178b3bc8 on branch "default" -------------------------------------------- test_functools leaked [0, 0, 3] memory blocks, sum=3 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogXodq18', '--timeout', '7200'] From python-checkins at python.org Sat Apr 18 14:16:21 2015 From: python-checkins at python.org (vinay.sajip) Date: Sat, 18 Apr 2015 12:16:21 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzIzNTM2?= =?utf-8?q?=3A_Clarified_scope_of_fileConfig=28=29=27s_API=2E?= Message-ID: <20150418121532.27916.52966@psf.io> https://hg.python.org/cpython/rev/968c086bf6cc changeset: 95706:968c086bf6cc branch: 3.4 parent: 95687:2d8e4047c270 user: Vinay Sajip date: Sat Apr 18 13:14:10 2015 +0100 summary: Issue #23536: Clarified scope of fileConfig()'s API. files: Doc/library/logging.config.rst | 12 ++++++++++++ 1 files changed, 12 insertions(+), 0 deletions(-) diff --git a/Doc/library/logging.config.rst b/Doc/library/logging.config.rst --- a/Doc/library/logging.config.rst +++ b/Doc/library/logging.config.rst @@ -615,6 +615,18 @@ specified in a section called ``[formatter_form01]``. The root logger configuration must be specified in a section called ``[logger_root]``. +.. note:: + + The :func:`fileConfig` API is older than the :func:`dictConfig` API and does + not provide functionality to cover certain aspects of logging. For example, + you cannot configure :class:`~logging.Filter` objects, which provide for + filtering of messages beyond simple integer levels, using :func:`fileConfig`. + If you need to have instances of :class:`~logging.Filter` in your logging + configuration, you will need to use :func:`dictConfig`. Note that future + enhancements to configuration functionality will be added to + :func:`dictConfig`, so it's worth considering transitioning to this newer + API when it's convenient to do so. + Examples of these sections in the file are given below. :: [loggers] -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Apr 18 14:16:21 2015 From: python-checkins at python.org (vinay.sajip) Date: Sat, 18 Apr 2015 12:16:21 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Closes_=2323536=3A_Clarified_scope_of_fileConfig=28=29?= =?utf-8?q?=27s_API=2E?= Message-ID: <20150418121532.30343.51080@psf.io> https://hg.python.org/cpython/rev/439517000aa2 changeset: 95707:439517000aa2 parent: 95704:bc1a178b3bc8 parent: 95706:968c086bf6cc user: Vinay Sajip date: Sat Apr 18 13:15:10 2015 +0100 summary: Closes #23536: Clarified scope of fileConfig()'s API. files: Doc/library/logging.config.rst | 12 ++++++++++++ 1 files changed, 12 insertions(+), 0 deletions(-) diff --git a/Doc/library/logging.config.rst b/Doc/library/logging.config.rst --- a/Doc/library/logging.config.rst +++ b/Doc/library/logging.config.rst @@ -615,6 +615,18 @@ specified in a section called ``[formatter_form01]``. The root logger configuration must be specified in a section called ``[logger_root]``. +.. note:: + + The :func:`fileConfig` API is older than the :func:`dictConfig` API and does + not provide functionality to cover certain aspects of logging. For example, + you cannot configure :class:`~logging.Filter` objects, which provide for + filtering of messages beyond simple integer levels, using :func:`fileConfig`. + If you need to have instances of :class:`~logging.Filter` in your logging + configuration, you will need to use :func:`dictConfig`. Note that future + enhancements to configuration functionality will be added to + :func:`dictConfig`, so it's worth considering transitioning to this newer + API when it's convenient to do so. + Examples of these sections in the file are given below. :: [loggers] -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Apr 18 14:16:21 2015 From: python-checkins at python.org (vinay.sajip) Date: Sat, 18 Apr 2015 12:16:21 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzIzNTM2?= =?utf-8?q?=3A_Clarified_scope_of_fileConfig=28=29=27s_API=2E?= Message-ID: <20150418121532.27924.40822@psf.io> https://hg.python.org/cpython/rev/df28044b7e14 changeset: 95705:df28044b7e14 branch: 2.7 parent: 95688:867c509c8c5e user: Vinay Sajip date: Sat Apr 18 13:05:19 2015 +0100 summary: Issue #23536: Clarified scope of fileConfig()'s API. files: Doc/library/logging.config.rst | 12 ++++++++++++ 1 files changed, 12 insertions(+), 0 deletions(-) diff --git a/Doc/library/logging.config.rst b/Doc/library/logging.config.rst --- a/Doc/library/logging.config.rst +++ b/Doc/library/logging.config.rst @@ -580,6 +580,18 @@ specified in a section called ``[formatter_form01]``. The root logger configuration must be specified in a section called ``[logger_root]``. +.. note:: + + The :func:`fileConfig` API is older than the :func:`dictConfig` API and does + not provide functionality to cover certain aspects of logging. For example, + you cannot configure :class:`~logging.Filter` objects, which provide for + filtering of messages beyond simple integer levels, using :func:`fileConfig`. + If you need to have instances of :class:`~logging.Filter` in your logging + configuration, you will need to use :func:`dictConfig`. Note that future + enhancements to configuration functionality will be added to + :func:`dictConfig`, so it's worth considering transitioning to this newer + API when it's convenient to do so. + Examples of these sections in the file are given below. :: [loggers] -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Apr 18 16:40:41 2015 From: python-checkins at python.org (yury.selivanov) Date: Sat, 18 Apr 2015 14:40:41 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_pep-0492=3A_Fixes=2C_edits=2E?= Message-ID: <20150418144041.6601.88354@psf.io> https://hg.python.org/peps/rev/7dce8391c235 changeset: 5770:7dce8391c235 user: Yury Selivanov date: Sat Apr 18 10:40:37 2015 -0400 summary: pep-0492: Fixes, edits. files: pep-0492.txt | 12 ++++++------ 1 files changed, 6 insertions(+), 6 deletions(-) diff --git a/pep-0492.txt b/pep-0492.txt --- a/pep-0492.txt +++ b/pep-0492.txt @@ -480,13 +480,13 @@ Returned from a coroutine function. See `Await Expression`_ for details. :Future-like object: - An object with an ``__await__`` method. It is consumed by ``await`` in a - coroutine. A coroutine waiting for a Future-like object is suspended until - the Future-like object's ``__await__`` completes. ``await`` returns the - result of the Future-like object. See `Await Expression`_ for details. + An object with an ``__await__`` method. Can be consumed by an ``await`` + expression in a coroutine. A coroutine waiting for a Future-like object is + suspended until the Future-like object's ``__await__`` completes, and + returns the result. See `Await Expression`_ for details. :Awaitable: - A *future-like* object or a *coroutine object*. See `Await Expression`_ + A *Future-like* object or a *coroutine object*. See `Await Expression`_ for details. :Generator-based coroutine: @@ -516,7 +516,7 @@ ================= ======================================= ================= async def func await, return value yield, yield from async def __a*__ await, return value yield, yield from -def __a*__ return Future-like await +def __a*__ return awaitable await def __await__ yield, yield from, return iterable await generator yield, yield from, return value await ================= ======================================= ================= -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Sat Apr 18 19:32:18 2015 From: python-checkins at python.org (yury.selivanov) Date: Sat, 18 Apr 2015 17:32:18 +0000 Subject: [Python-checkins] =?utf-8?b?cGVwczogcGVwLTA0OTI6IGFzeW5jX2RlZigp?= =?utf-8?q?_works_on_generator-functions=2E?= Message-ID: <20150418173218.6583.54795@psf.io> https://hg.python.org/peps/rev/48106b854247 changeset: 5771:48106b854247 user: Yury Selivanov date: Sat Apr 18 13:31:56 2015 -0400 summary: pep-0492: async_def() works on generator-functions. files: pep-0492.txt | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pep-0492.txt b/pep-0492.txt --- a/pep-0492.txt +++ b/pep-0492.txt @@ -99,8 +99,8 @@ types.async_def() ----------------- -A new function ``async_def(gen)`` is added to the ``types`` module. It -applies ``CO_ASYNC`` flag to the passed generator's code object, so that it +A new function ``async_def(gen)`` is added to the ``types`` module. It applies +``CO_ASYNC`` flag to the passed generator-function's code object, so that it returns a *coroutine object* when called. This feature enables an easy upgrade path for existing libraries. -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Sun Apr 19 03:32:39 2015 From: python-checkins at python.org (berker.peksag) Date: Sun, 19 Apr 2015 01:32:39 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2315566=3A_Document_encoding_and_errors_parameter?= =?utf-8?q?s_of_TarInfo=2Efrombuf=28=29=2E?= Message-ID: <20150419013238.31099.60950@psf.io> https://hg.python.org/cpython/rev/85cba64e24dc changeset: 95709:85cba64e24dc parent: 95707:439517000aa2 parent: 95708:d737ab3ea1ae user: Berker Peksag date: Sun Apr 19 04:32:52 2015 +0300 summary: Issue #15566: Document encoding and errors parameters of TarInfo.frombuf(). Patch by Andy Holst. files: Doc/library/tarfile.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/library/tarfile.rst b/Doc/library/tarfile.rst --- a/Doc/library/tarfile.rst +++ b/Doc/library/tarfile.rst @@ -504,7 +504,7 @@ Create a :class:`TarInfo` object. -.. method:: TarInfo.frombuf(buf) +.. method:: TarInfo.frombuf(buf, encoding, errors) Create and return a :class:`TarInfo` object from string buffer *buf*. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Apr 19 03:32:38 2015 From: python-checkins at python.org (berker.peksag) Date: Sun, 19 Apr 2015 01:32:38 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzE1NTY2?= =?utf-8?q?=3A_Document_encoding_and_errors_parameters_of_TarInfo=2Efrombu?= =?utf-8?b?ZigpLg==?= Message-ID: <20150419013238.6607.89919@psf.io> https://hg.python.org/cpython/rev/d737ab3ea1ae changeset: 95708:d737ab3ea1ae branch: 3.4 parent: 95706:968c086bf6cc user: Berker Peksag date: Sun Apr 19 04:32:23 2015 +0300 summary: Issue #15566: Document encoding and errors parameters of TarInfo.frombuf(). Patch by Andy Holst. files: Doc/library/tarfile.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/library/tarfile.rst b/Doc/library/tarfile.rst --- a/Doc/library/tarfile.rst +++ b/Doc/library/tarfile.rst @@ -465,7 +465,7 @@ Create a :class:`TarInfo` object. -.. method:: TarInfo.frombuf(buf) +.. method:: TarInfo.frombuf(buf, encoding, errors) Create and return a :class:`TarInfo` object from string buffer *buf*. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Apr 19 03:37:47 2015 From: python-checkins at python.org (berker.peksag) Date: Sun, 19 Apr 2015 01:37:47 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Mark_TarInfo=2Efrombuf=28=29_and_TarInfo=2Efromtarfile?= =?utf-8?q?=28=29_as_classmethods=2E?= Message-ID: <20150419013747.31123.55498@psf.io> https://hg.python.org/cpython/rev/e4802f19eee4 changeset: 95711:e4802f19eee4 parent: 95709:85cba64e24dc parent: 95710:36a2c5eea3d7 user: Berker Peksag date: Sun Apr 19 04:38:01 2015 +0300 summary: Mark TarInfo.frombuf() and TarInfo.fromtarfile() as classmethods. files: Doc/library/tarfile.rst | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Doc/library/tarfile.rst b/Doc/library/tarfile.rst --- a/Doc/library/tarfile.rst +++ b/Doc/library/tarfile.rst @@ -504,14 +504,14 @@ Create a :class:`TarInfo` object. -.. method:: TarInfo.frombuf(buf, encoding, errors) +.. classmethod:: TarInfo.frombuf(buf, encoding, errors) Create and return a :class:`TarInfo` object from string buffer *buf*. - Raises :exc:`HeaderError` if the buffer is invalid.. + Raises :exc:`HeaderError` if the buffer is invalid. -.. method:: TarInfo.fromtarfile(tarfile) +.. classmethod:: TarInfo.fromtarfile(tarfile) Read the next member from the :class:`TarFile` object *tarfile* and return it as a :class:`TarInfo` object. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Apr 19 03:37:47 2015 From: python-checkins at python.org (berker.peksag) Date: Sun, 19 Apr 2015 01:37:47 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E4=29=3A_Mark_TarInfo?= =?utf-8?q?=2Efrombuf=28=29_and_TarInfo=2Efromtarfile=28=29_as_classmethod?= =?utf-8?q?s=2E?= Message-ID: <20150419013747.21357.48290@psf.io> https://hg.python.org/cpython/rev/36a2c5eea3d7 changeset: 95710:36a2c5eea3d7 branch: 3.4 parent: 95708:d737ab3ea1ae user: Berker Peksag date: Sun Apr 19 04:37:35 2015 +0300 summary: Mark TarInfo.frombuf() and TarInfo.fromtarfile() as classmethods. files: Doc/library/tarfile.rst | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Doc/library/tarfile.rst b/Doc/library/tarfile.rst --- a/Doc/library/tarfile.rst +++ b/Doc/library/tarfile.rst @@ -465,14 +465,14 @@ Create a :class:`TarInfo` object. -.. method:: TarInfo.frombuf(buf, encoding, errors) +.. classmethod:: TarInfo.frombuf(buf, encoding, errors) Create and return a :class:`TarInfo` object from string buffer *buf*. - Raises :exc:`HeaderError` if the buffer is invalid.. + Raises :exc:`HeaderError` if the buffer is invalid. -.. method:: TarInfo.fromtarfile(tarfile) +.. classmethod:: TarInfo.fromtarfile(tarfile) Read the next member from the :class:`TarFile` object *tarfile* and return it as a :class:`TarInfo` object. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Apr 19 09:52:42 2015 From: python-checkins at python.org (chris.angelico) Date: Sun, 19 Apr 2015 07:52:42 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_Undefer_PEP_3152_at_PEP_autho?= =?utf-8?q?r=27s_request?= Message-ID: <20150419075242.30329.77789@psf.io> https://hg.python.org/peps/rev/f9527b279a30 changeset: 5772:f9527b279a30 user: Chris Angelico date: Sun Apr 19 17:52:35 2015 +1000 summary: Undefer PEP 3152 at PEP author's request files: pep-3152.txt | 9 +-------- 1 files changed, 1 insertions(+), 8 deletions(-) diff --git a/pep-3152.txt b/pep-3152.txt --- a/pep-3152.txt +++ b/pep-3152.txt @@ -3,7 +3,7 @@ Version: $Revision$ Last-Modified: $Date$ Author: Gregory Ewing -Status: Deferred +Status: Draft Type: Standards Track Content-Type: text/x-rst Created: 13-Feb-2009 @@ -27,13 +27,6 @@ independently of PEP 380 if so desired. -PEP Deferral -============ - -Further exploration of the concepts covered in this PEP has been deferred -at least until after PEP 3156 has been resolved. - - Specification ============= -- Repository URL: https://hg.python.org/peps From solipsis at pitrou.net Sun Apr 19 10:47:04 2015 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Sun, 19 Apr 2015 08:47:04 +0000 Subject: [Python-checkins] Daily reference leaks (e4802f19eee4): sum=3 Message-ID: <20150419084704.30343.1978@psf.io> results for e4802f19eee4 on branch "default" -------------------------------------------- test_functools leaked [0, 0, 3] memory blocks, sum=3 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogpWwLfY', '--timeout', '7200'] From python-checkins at python.org Sun Apr 19 10:59:14 2015 From: python-checkins at python.org (victor.stinner) Date: Sun, 19 Apr 2015 08:59:14 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_PEP_475=3A_update_the_list_of?= =?utf-8?q?_modified_functions_according_to_the_implementation?= Message-ID: <20150419085914.30331.970@psf.io> https://hg.python.org/peps/rev/6f686f08d88c changeset: 5773:6f686f08d88c user: Victor Stinner date: Sun Apr 19 10:59:06 2015 +0200 summary: PEP 475: update the list of modified functions according to the implementation Mention also the special case of socket.socket.connect(). files: pep-0475.txt | 79 +++++++++++++++++++++++++++++---------- 1 files changed, 58 insertions(+), 21 deletions(-) diff --git a/pep-0475.txt b/pep-0475.txt --- a/pep-0475.txt +++ b/pep-0475.txt @@ -168,37 +168,74 @@ Example of standard library functions that need to be modified to comply with this PEP: -* ``open()``, ``os.open()`` -* ``os.read()``, ``io.FileIO.read()``, ``io.FileIO.readinto()`` -* ``os.write()``, ``io.FileIO.write()`` -* ``os.waitpid()`` -* ``socket.accept()`` -* ``socket.connect()`` -* ``socket.recv()``, ``socket.recv_into()`` -* ``socket.recv_from()`` -* ``socket.send()`` -* ``socket.sendto()`` +* ``open()``, ``os.open()``, ``io.open()`` +* functions of the ``faulthandler`` module +* ``os`` functions: + + - ``os.fchdir()`` + - ``os.fchmod()`` + - ``os.fchown()`` + - ``os.fdatasync()`` + - ``os.fstat()`` + - ``os.fstatvfs()`` + - ``os.fsync()`` + - ``os.ftruncate()`` + - ``os.mkfifo()`` + - ``os.mknod()`` + - ``os.posix_fadvise()`` + - ``os.posix_fallocate()`` + - ``os.pread()`` + - ``os.pwrite()`` + - ``os.read()`` + - ``os.readv()`` + - ``os.sendfile()`` + - ``os.wait3()`` + - ``os.wait4()`` + - ``os.wait()`` + - ``os.waitid()`` + - ``os.waitpid()`` + - ``os.write()`` + - ``os.writev()`` + - special cases: ``os.close()`` and ``os.dup2()`` now ignore ``EINTR`` error, + the syscall is not retried + +* ``select.select()``, ``select.poll.poll()``, ``select.epoll.poll()``, + ``select.kqueue.control()``, ``select.devpoll.poll()`` +* ``socket.socket()`` methods: + + - ``accept()`` + - ``connect()`` (except for non-blocking sockets) + - ``recv()`` + - ``recvfrom()`` + - ``recvmsg()`` + - ``send()`` + - ``sendall()`` + - ``sendmsg()`` + - ``sendto()`` + +* ``signal.sigtimedwait()``, ``signal.sigwaitinfo()`` * ``time.sleep()`` -* ``select.select()`` -* ``select.poll()`` -* ``select.epoll.poll()`` -* ``select.devpoll.poll()`` -* ``select.kqueue.control()`` -* ``selectors.SelectSelector.select()`` and other selector classes -(note: the ``selector`` module already retries on ``InterruptedError``, but it +(Note: the ``selector`` module already retries on ``InterruptedError``, but it doesn't recompute the timeout yet) -``os.close`` and ``close()`` methods are a special case: they will ignore -EINTR instead of retrying. The reason is complex but involves behaviour -under Linux and the fact that the file descriptor may really be closed -even if EINTR is returned. See articles: +``os.close``, ``close()`` methods and ``os.dup2()`` are a special case: they +will ignore ``EINTR`` instead of retrying. The reason is complex but involves +behaviour under Linux and the fact that the file descriptor may really be +closed even if EINTR is returned. See articles: * `Returning EINTR from close() `_ * `(LKML) Re: [patch 7/7] uml: retry host close() on EINTR `_ * `close() and EINTR `_ +The ``socket.socket.connect()`` method does not retry ``connect()`` for +non-blocking sockets if it is interrupted by a signal (fails with ``EINTR``). +The connection runs asynchronously in background. The caller is responsible +to wait until the socket becomes writable (ex: using ``select.select()``) +and then call ``socket.socket.getsockopt(socket.SOL_SOCKET, socket.SO_ERROR)`` +to check if the connection succeeded (``getsockopt()`` returns ``0``) or failed. + InterruptedError handling ------------------------- -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Sun Apr 19 14:44:11 2015 From: python-checkins at python.org (matthias.klose) Date: Sun, 19 Apr 2015 12:44:11 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A__-_=2322980=3A_fix_triplet?= =?utf-8?q?_configure_test_for_more_targets?= Message-ID: <20150419124411.27900.25008@psf.io> https://hg.python.org/cpython/rev/558335559383 changeset: 95712:558335559383 user: doko at ubuntu.com date: Sun Apr 19 14:44:05 2015 +0200 summary: - #22980: fix triplet configure test for more targets files: configure | 7 +++++++ configure.ac | 7 +++++++ 2 files changed, 14 insertions(+), 0 deletions(-) diff --git a/configure b/configure --- a/configure +++ b/configure @@ -5069,9 +5069,16 @@ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for the platform triplet based on compiler characteristics" >&5 $as_echo_n "checking for the platform triplet based on compiler characteristics... " >&6; } cat >> conftest.c <> conftest.c < https://hg.python.org/cpython/rev/cb619f1c616b changeset: 95713:cb619f1c616b user: Serhiy Storchaka date: Sun Apr 19 20:38:19 2015 +0300 summary: Use PyArg_ParseTuple (new API) instead of PyArg_Parse (old API) for parsing tuples. files: Modules/_io/textio.c | 10 +++++----- 1 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Modules/_io/textio.c b/Modules/_io/textio.c --- a/Modules/_io/textio.c +++ b/Modules/_io/textio.c @@ -538,7 +538,7 @@ _PyIO_str_getstate, NULL); if (state == NULL) return NULL; - if (!PyArg_Parse(state, "(OK)", &buffer, &flag)) { + if (!PyArg_ParseTuple(state, "OK", &buffer, &flag)) { Py_DECREF(state); return NULL; } @@ -569,7 +569,7 @@ PyObject *buffer; unsigned PY_LONG_LONG flag; - if (!PyArg_Parse(state, "(OK)", &buffer, &flag)) + if (!PyArg_ParseTuple(state, "OK", &buffer, &flag)) return NULL; self->pendingcr = (int) (flag & 1); @@ -1449,7 +1449,7 @@ /* Given this, we know there was a valid snapshot point * len(dec_buffer) bytes ago with decoder state (b'', dec_flags). */ - if (PyArg_Parse(state, "(OO)", &dec_buffer, &dec_flags) < 0) { + if (PyArg_ParseTuple(state, "OO", &dec_buffer, &dec_flags) < 0) { Py_DECREF(state); return -1; } @@ -2305,7 +2305,7 @@ goto fail; /* Skip backward to the snapshot point (see _read_chunk). */ - if (!PyArg_Parse(self->snapshot, "(iO)", &cookie.dec_flags, &next_input)) + if (!PyArg_ParseTuple(self->snapshot, "iO", &cookie.dec_flags, &next_input)) goto fail; assert (PyBytes_Check(next_input)); @@ -2331,7 +2331,7 @@ _PyIO_str_getstate, NULL); \ if (_state == NULL) \ goto fail; \ - if (!PyArg_Parse(_state, "(y#i)", &dec_buffer, &dec_buffer_len, &dec_flags)) { \ + if (!PyArg_ParseTuple(_state, "y#i", &dec_buffer, &dec_buffer_len, &dec_flags)) { \ Py_DECREF(_state); \ goto fail; \ } \ -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Apr 19 20:13:27 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Sun, 19 Apr 2015 18:13:27 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Fixed_error_message_for_the_=22u=23=22_format_code=2E?= Message-ID: <20150419181327.31125.62226@psf.io> https://hg.python.org/cpython/rev/4aab4e0cd759 changeset: 95715:4aab4e0cd759 parent: 95713:cb619f1c616b parent: 95714:d2edac11d57c user: Serhiy Storchaka date: Sun Apr 19 21:13:00 2015 +0300 summary: Fixed error message for the "u#" format code. files: Python/getargs.c | 7 ++++--- 1 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Python/getargs.c b/Python/getargs.c --- a/Python/getargs.c +++ b/Python/getargs.c @@ -967,7 +967,7 @@ Py_UNICODE **p = va_arg(*p_va, Py_UNICODE **); if (*format == '#') { - /* "s#" or "Z#" */ + /* "u#" or "Z#" */ FETCH_SIZE; if (c == 'Z' && arg == Py_None) { @@ -982,10 +982,11 @@ STORE_SIZE(len); } else - return converterr("str or None", arg, msgbuf, bufsize); + return converterr(c == 'Z' ? "str or None" : "str", + arg, msgbuf, bufsize); format++; } else { - /* "s" or "Z" */ + /* "u" or "Z" */ if (c == 'Z' && arg == Py_None) *p = NULL; else if (PyUnicode_Check(arg)) { -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Apr 19 20:13:27 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Sun, 19 Apr 2015 18:13:27 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E4=29=3A_Fixed_error_me?= =?utf-8?q?ssage_for_the_=22u=23=22_format_code=2E?= Message-ID: <20150419181327.27906.17687@psf.io> https://hg.python.org/cpython/rev/d2edac11d57c changeset: 95714:d2edac11d57c branch: 3.4 parent: 95710:36a2c5eea3d7 user: Serhiy Storchaka date: Sun Apr 19 21:11:30 2015 +0300 summary: Fixed error message for the "u#" format code. files: Python/getargs.c | 7 ++++--- 1 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Python/getargs.c b/Python/getargs.c --- a/Python/getargs.c +++ b/Python/getargs.c @@ -968,7 +968,7 @@ Py_UNICODE **p = va_arg(*p_va, Py_UNICODE **); if (*format == '#') { - /* "s#" or "Z#" */ + /* "u#" or "Z#" */ FETCH_SIZE; if (c == 'Z' && arg == Py_None) { @@ -983,10 +983,11 @@ STORE_SIZE(len); } else - return converterr("str or None", arg, msgbuf, bufsize); + return converterr(c == 'Z' ? "str or None" : "str", + arg, msgbuf, bufsize); format++; } else { - /* "s" or "Z" */ + /* "u" or "Z" */ if (c == 'Z' && arg == Py_None) *p = NULL; else if (PyUnicode_Check(arg)) { -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Apr 19 20:15:52 2015 From: python-checkins at python.org (yury.selivanov) Date: Sun, 19 Apr 2015 18:15:52 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_pep-0492=3A_AsyncFuntionDef_a?= =?utf-8?q?st_node=3B_100=25_backwards_compatible?= Message-ID: <20150419181551.30335.52570@psf.io> https://hg.python.org/peps/rev/d6718ddbc92b changeset: 5774:d6718ddbc92b user: Yury Selivanov date: Sun Apr 19 14:15:49 2015 -0400 summary: pep-0492: AsyncFuntionDef ast node; 100% backwards compatible files: pep-0492.txt | 8 ++------ 1 files changed, 2 insertions(+), 6 deletions(-) diff --git a/pep-0492.txt b/pep-0492.txt --- a/pep-0492.txt +++ b/pep-0492.txt @@ -567,10 +567,7 @@ Backwards Compatibility ----------------------- -The only backwards incompatible change is an extra argument ``is_async`` to -``FunctionDef`` AST node. But since it is a documented fact that the structure -of AST nodes is an implementation detail and subject to change, this should not -be considered a serious issue. +This proposal preserves 100% backwards compatibility. Grammar Updates @@ -922,8 +919,7 @@ protocol with ``__aiter__``, ``__aexit__`` and new built-in exception ``StopAsyncIteration``. -5. New AST nodes: ``AsyncFor``, ``AsyncWith``, ``Await``; ``FunctionDef`` AST - node got a new argument ``is_async``. +5. New AST nodes: ``AsyncFunctionDef``, ``AsyncFor``, ``AsyncWith``, ``Await``. 6. New functions: ``sys.set_coroutine_wrapper(callback)`` and ``types.async_def(gen)``. -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Sun Apr 19 21:15:49 2015 From: python-checkins at python.org (christian.heimes) Date: Sun, 19 Apr 2015 19:15:49 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogSXNzdWUgIzIzOTk4?= =?utf-8?q?=3A_PyImport=5FReInitLock=28=29_now_checks_for_lock_allocation_?= =?utf-8?q?error?= Message-ID: <20150419191549.27912.59239@psf.io> https://hg.python.org/cpython/rev/7d7bf5c34d7e changeset: 95717:7d7bf5c34d7e branch: 3.3 parent: 94832:21cd7f83e0aa user: Christian Heimes date: Sun Apr 19 21:08:42 2015 +0200 summary: Issue #23998: PyImport_ReInitLock() now checks for lock allocation error files: Misc/NEWS | 5 +++++ Python/import.c | 6 +++++- 2 files changed, 10 insertions(+), 1 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -32,6 +32,11 @@ - Issue #23365: Fixed possible integer overflow in itertools.combinations_with_replacement. +C API +----- + +- Issue #23998: PyImport_ReInitLock() now checks for lock allocation error + What's New in Python 3.3.6? =========================== diff --git a/Python/import.c b/Python/import.c --- a/Python/import.c +++ b/Python/import.c @@ -199,8 +199,12 @@ void _PyImport_ReInitLock(void) { - if (import_lock != NULL) + if (import_lock != NULL) { import_lock = PyThread_allocate_lock(); + if (import_lock == NULL) { + Py_FatalError("PyImport_ReInitLock failed to create a new lock"); + } + } if (import_lock_level > 1) { /* Forked as a side effect of import */ long me = PyThread_get_thread_ident(); -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Apr 19 21:15:49 2015 From: python-checkins at python.org (christian.heimes) Date: Sun, 19 Apr 2015 19:15:49 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy4zIC0+IDMuNCk6?= =?utf-8?q?_Issue_=2323998=3A_PyImport=5FReInitLock=28=29_now_checks_for_l?= =?utf-8?q?ock_allocation_error?= Message-ID: <20150419191549.31125.15106@psf.io> https://hg.python.org/cpython/rev/e0bd083fc9c1 changeset: 95718:e0bd083fc9c1 branch: 3.4 parent: 95714:d2edac11d57c parent: 95717:7d7bf5c34d7e user: Christian Heimes date: Sun Apr 19 21:12:14 2015 +0200 summary: Issue #23998: PyImport_ReInitLock() now checks for lock allocation error files: Misc/NEWS | 5 +++++ Python/import.c | 6 +++++- 2 files changed, 10 insertions(+), 1 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -201,6 +201,11 @@ - Issue #23686: Update OS X 10.5 installer and Windows builds to use OpenSSL 1.0.2a. +C API +----- + +- Issue #23998: PyImport_ReInitLock() now checks for lock allocation error + What's New in Python 3.4.3? =========================== diff --git a/Python/import.c b/Python/import.c --- a/Python/import.c +++ b/Python/import.c @@ -207,8 +207,12 @@ void _PyImport_ReInitLock(void) { - if (import_lock != NULL) + if (import_lock != NULL) { import_lock = PyThread_allocate_lock(); + if (import_lock == NULL) { + Py_FatalError("PyImport_ReInitLock failed to create a new lock"); + } + } if (import_lock_level > 1) { /* Forked as a side effect of import */ long me = PyThread_get_thread_ident(); -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Apr 19 21:15:49 2015 From: python-checkins at python.org (christian.heimes) Date: Sun, 19 Apr 2015 19:15:49 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzIzOTk4?= =?utf-8?q?=3A_PyImport=5FReInitLock=28=29_now_checks_for_lock_allocation_?= =?utf-8?q?error?= Message-ID: <20150419191549.30317.92293@psf.io> https://hg.python.org/cpython/rev/d70995cf44b3 changeset: 95716:d70995cf44b3 branch: 2.7 parent: 95705:df28044b7e14 user: Christian Heimes date: Sun Apr 19 21:08:28 2015 +0200 summary: Issue #23998: PyImport_ReInitLock() now checks for lock allocation error files: Misc/NEWS | 2 ++ Python/import.c | 6 +++++- 2 files changed, 7 insertions(+), 1 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -263,6 +263,8 @@ C API ----- +- Issue #23998: PyImport_ReInitLock() now checks for lock allocation error + - Issue #22079: PyType_Ready() now checks that statically allocated type has no dynamically allocated bases. diff --git a/Python/import.c b/Python/import.c --- a/Python/import.c +++ b/Python/import.c @@ -337,8 +337,12 @@ void _PyImport_ReInitLock(void) { - if (import_lock != NULL) + if (import_lock != NULL) { import_lock = PyThread_allocate_lock(); + if (import_lock == NULL) { + Py_FatalError("PyImport_ReInitLock failed to create a new lock"); + } + } import_lock_thread = -1; import_lock_level = 0; } -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Apr 19 21:15:54 2015 From: python-checkins at python.org (christian.heimes) Date: Sun, 19 Apr 2015 19:15:54 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2323998=3A_PyImport=5FReInitLock=28=29_now_checks?= =?utf-8?q?_for_lock_allocation_error?= Message-ID: <20150419191554.21343.38679@psf.io> https://hg.python.org/cpython/rev/7ae8fd62d743 changeset: 95719:7ae8fd62d743 parent: 95715:4aab4e0cd759 parent: 95718:e0bd083fc9c1 user: Christian Heimes date: Sun Apr 19 21:15:02 2015 +0200 summary: Issue #23998: PyImport_ReInitLock() now checks for lock allocation error files: Misc/NEWS | 5 +++++ Python/import.c | 6 +++++- 2 files changed, 10 insertions(+), 1 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -213,6 +213,11 @@ if Argument Clinic processes the same symbol multiple times, and it's emitted at the end of all processing rather than immediately after the first use. +C API +----- + +- Issue #23998: PyImport_ReInitLock() now checks for lock allocation error + What's New in Python 3.5.0 alpha 3? =================================== diff --git a/Python/import.c b/Python/import.c --- a/Python/import.c +++ b/Python/import.c @@ -209,8 +209,12 @@ void _PyImport_ReInitLock(void) { - if (import_lock != NULL) + if (import_lock != NULL) { import_lock = PyThread_allocate_lock(); + if (import_lock == NULL) { + Py_FatalError("PyImport_ReInitLock failed to create a new lock"); + } + } if (import_lock_level > 1) { /* Forked as a side effect of import */ long me = PyThread_get_thread_ident(); -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Apr 20 02:59:52 2015 From: python-checkins at python.org (guido.van.rossum) Date: Mon, 20 Apr 2015 00:59:52 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Remove_spurious_text_from_?= =?utf-8?q?build_instructions_README=2E?= Message-ID: <20150420005952.30345.92997@psf.io> https://hg.python.org/cpython/rev/25eae6db2cc1 changeset: 95720:25eae6db2cc1 user: Guido van Rossum date: Wed Apr 15 17:40:07 2015 -0700 summary: Remove spurious text from build instructions README. It said "New text", an apparent test edit by MvL ages ago. files: README | 2 -- 1 files changed, 0 insertions(+), 2 deletions(-) diff --git a/README b/README --- a/README +++ b/README @@ -15,8 +15,6 @@ On Unix, Linux, BSD, OSX, and Cygwin: -New text - ./configure make make test -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Apr 20 04:40:22 2015 From: python-checkins at python.org (steve.dower) Date: Mon, 20 Apr 2015 02:40:22 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Force_the_buildbots_to_cle?= =?utf-8?q?an_up_all_externals=2E?= Message-ID: <20150420024022.31129.68037@psf.io> https://hg.python.org/cpython/rev/a1dc6693e576 changeset: 95721:a1dc6693e576 user: Steve Dower date: Sun Apr 19 19:40:09 2015 -0700 summary: Force the buildbots to clean up all externals. files: Tools/buildbot/build.bat | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Tools/buildbot/build.bat b/Tools/buildbot/build.bat --- a/Tools/buildbot/build.bat +++ b/Tools/buildbot/build.bat @@ -10,7 +10,7 @@ @rem a new version of an external library, especially Tcl/Tk): @rem 1) uncomment the following line: - at rem call "%~dp0..\..\PCbuild\get_externals.bat" --clean-only +call "%~dp0..\..\PCbuild\get_externals.bat" --clean-only @rem 2) commit and push @rem 3) wait for all Windows bots to start a build with that changeset -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Apr 20 04:46:53 2015 From: python-checkins at python.org (steve.dower) Date: Mon, 20 Apr 2015 02:46:53 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Backed_out_buildbot_clean?= Message-ID: <20150420024653.31129.13676@psf.io> https://hg.python.org/cpython/rev/8e045e9fbe90 changeset: 95722:8e045e9fbe90 user: Steve Dower date: Sun Apr 19 19:45:51 2015 -0700 summary: Backed out buildbot clean files: Tools/buildbot/build.bat | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Tools/buildbot/build.bat b/Tools/buildbot/build.bat --- a/Tools/buildbot/build.bat +++ b/Tools/buildbot/build.bat @@ -10,7 +10,7 @@ @rem a new version of an external library, especially Tcl/Tk): @rem 1) uncomment the following line: -call "%~dp0..\..\PCbuild\get_externals.bat" --clean-only + at rem call "%~dp0..\..\PCbuild\get_externals.bat" --clean-only @rem 2) commit and push @rem 3) wait for all Windows bots to start a build with that changeset -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Apr 20 04:50:55 2015 From: python-checkins at python.org (steve.dower) Date: Mon, 20 Apr 2015 02:50:55 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Minor_fixes_to_Windows_bui?= =?utf-8?q?ld_scripts?= Message-ID: <20150420025055.31107.98012@psf.io> https://hg.python.org/cpython/rev/cf0324e424b0 changeset: 95723:cf0324e424b0 user: Steve Dower date: Sun Apr 19 19:50:35 2015 -0700 summary: Minor fixes to Windows build scripts files: Tools/msi/make_zip.py | 13 ++++++++++--- Tools/msi/testrelease.bat | 5 ++++- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/Tools/msi/make_zip.py b/Tools/msi/make_zip.py --- a/Tools/msi/make_zip.py +++ b/Tools/msi/make_zip.py @@ -30,9 +30,16 @@ return False return True - if name in {'_ctypes_test.pyd', '_testbuffer.pyd', '_testcapi.pyd', '_testimportmultiple.pyd', 'xxlimited.pyd'}: - return False - return p.suffix.lower() not in {'.pyc', '.pyo'} + suffix = p.suffix.lower() + if suffix == '.pyd': + return name not in { + '_ctypes_test.pyd', + '_testbuffer.pyd', + '_testcapi.pyd', + '_testimportmultiple.pyd', + 'xxlimited.pyd', + } + return suffix not in {'.pyc', '.pyo'} def include_in_tools(p): if p.is_dir() and p.name.lower() in {'scripts', 'i18n', 'pynche', 'demo', 'parser'}: diff --git a/Tools/msi/testrelease.bat b/Tools/msi/testrelease.bat --- a/Tools/msi/testrelease.bat +++ b/Tools/msi/testrelease.bat @@ -1,4 +1,4 @@ - at setlocal + at setlocal enableextensions @echo off set D=%~dp0 @@ -51,6 +51,9 @@ @if not exist "%~1" exit /B 1 + at set EXE=%~1 + at if not "%EXE:embed=%"=="%EXE%" exit /B 0 + @set EXITCODE=0 @echo Installing %1 into %2 "%~1" /passive /log "%~2\install\log.txt" TargetDir="%~2\Python" Include_debug=1 Include_symbols=1 %~3 -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Apr 20 05:07:34 2015 From: python-checkins at python.org (yury.selivanov) Date: Mon, 20 Apr 2015 03:07:34 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_pep-0492=3A_Mention_PEP_3152?= =?utf-8?q?=2E?= Message-ID: <20150420030734.31123.82107@psf.io> https://hg.python.org/peps/rev/428c7c753500 changeset: 5775:428c7c753500 user: Yury Selivanov date: Sun Apr 19 23:07:15 2015 -0400 summary: pep-0492: Mention PEP 3152. files: pep-0492.txt | 52 +++++++++++++++++++++++++++++++++++++++- 1 files changed, 51 insertions(+), 1 deletions(-) diff --git a/pep-0492.txt b/pep-0492.txt --- a/pep-0492.txt +++ b/pep-0492.txt @@ -61,7 +61,7 @@ It is strongly suggested that the reader understands how coroutines are implemented in Python (PEP 342 and PEP 380). It is also recommended to read -PEP 3156 (asyncio framework). +PEP 3156 (asyncio framework) and PEP 3152 (Cofunctions). From this point in this document we use the word *coroutine* to refer to functions declared using the new syntax. *generator-based coroutine* is used @@ -659,6 +659,56 @@ Design Considerations ===================== +PEP 3152 +-------- + +PEP 3152 by Gregory Ewing proposes a different mechanism for coroutines +(called "cofunctions"). Some key points: + +1. A new keyword ``codef`` to declare a *cofunction*. *Cofunction* is always a + generator, even if there is no ``cocall`` expressions inside it. Maps to + ``async def`` in this proposal. + +2. A new keyword ``cocall`` to call a *cofunction*. Can only be used inside a + *cofunction*. Maps to ``await`` in this proposal (with some differences, + see below.) + +3. It is not possible to call a *cofunction* without a ``cocall`` keyword. + +4. ``cocall`` grammatically requires parentheses after it:: + + atom: cocall | + cocall: 'cocall' atom cotrailer* '(' [arglist] ')' + cotrailer: '[' subscriptlist ']' | '.' NAME + +5. ``cocall f(*args, **kwds)`` is semantically equivalent to + ``yield from f.__cocall__(*args, **kwds)``. + +Differences from this proposal: + +1. There is no equivalent of ``__cocall__`` in this PEP, which is called and + its result is passed to ``yield from`` in the ``cocall`` expression. + ``await`` keyword expects an *awaitable* object, validates the type, and + executes ``yield from`` on it. Although, ``__await__`` method is similar to + ``__cocall__``, but is only used to define *Future-like* objects. + +2. ``await`` is defined in the same way as ``yield`` in the grammar (it is + later enforced that ``await`` can only be inside ``async def``). + +3. To make asyncio work with PEP 3152 it would be required to modify + ``@asyncio.coroutine`` decorator to wrap all functions in an object with a + ``__cocall__`` method. To call *cofunctions* from existing generator-based + coroutines it would be required to use ``costart`` built-in. In this + proposal ``@asyncio.coroutine`` simply sets ``CO_ASYNC`` on the wrapped + function's code object and everything works automatically. + +4. Since it is impossible to call a *cofunction* without a ``cocall`` keyword, + it automatically prevents the common mistake of forgetting to use + ``yield from`` on generator-based coroutines. + +5. There are no equivalents of ``async for`` and ``async with`` in PEP 3152. + + No implicit wrapping in Futures ------------------------------- -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Mon Apr 20 05:15:01 2015 From: python-checkins at python.org (benjamin.peterson) Date: Mon, 20 Apr 2015 03:15:01 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E4=29=3A_fix_grammar?= Message-ID: <20150420031501.21337.32486@psf.io> https://hg.python.org/cpython/rev/512a2408181f changeset: 95724:512a2408181f branch: 3.4 parent: 95718:e0bd083fc9c1 user: Benjamin Peterson date: Sun Apr 19 23:14:37 2015 -0400 summary: fix grammar files: Doc/library/urllib.request.rst | 2 +- 1 files changed, 1 insertions(+), 1 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 @@ -1067,7 +1067,7 @@ the various ways in which a (X)HTML or a XML document could have specified its encoding information. -As the python.org website uses *utf-8* encoding as specified in it's meta tag, we +As the python.org website uses *utf-8* encoding as specified in its meta tag, we will use the same for decoding the bytes object. :: >>> with urllib.request.urlopen('http://www.python.org/') as f: -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Apr 20 05:15:01 2015 From: python-checkins at python.org (benjamin.peterson) Date: Mon, 20 Apr 2015 03:15:01 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?b?KTogbWVyZ2UgMy40?= Message-ID: <20150420031501.31115.88706@psf.io> https://hg.python.org/cpython/rev/8d9bf18defd7 changeset: 95725:8d9bf18defd7 parent: 95723:cf0324e424b0 parent: 95724:512a2408181f user: Benjamin Peterson date: Sun Apr 19 23:14:57 2015 -0400 summary: merge 3.4 files: -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Apr 20 05:19:56 2015 From: python-checkins at python.org (yury.selivanov) Date: Mon, 20 Apr 2015 03:19:56 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_pep-0492=3A_Edits_re_PEP_3152?= =?utf-8?q?=2E?= Message-ID: <20150420031956.31107.47154@psf.io> https://hg.python.org/peps/rev/fac089ecab12 changeset: 5776:fac089ecab12 user: Yury Selivanov date: Sun Apr 19 23:19:52 2015 -0400 summary: pep-0492: Edits re PEP 3152. files: pep-0492.txt | 6 ++++-- 1 files changed, 4 insertions(+), 2 deletions(-) diff --git a/pep-0492.txt b/pep-0492.txt --- a/pep-0492.txt +++ b/pep-0492.txt @@ -692,8 +692,10 @@ executes ``yield from`` on it. Although, ``__await__`` method is similar to ``__cocall__``, but is only used to define *Future-like* objects. -2. ``await`` is defined in the same way as ``yield`` in the grammar (it is - later enforced that ``await`` can only be inside ``async def``). +2. ``await`` is defined in almost the same way as ``yield from`` in the grammar + (it is later enforced that ``await`` can only be inside ``async def``). It + is possible to simply write ``await future``, whereas ``cocall`` always + requires parentheses. 3. To make asyncio work with PEP 3152 it would be required to modify ``@asyncio.coroutine`` decorator to wrap all functions in an object with a -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Mon Apr 20 05:23:16 2015 From: python-checkins at python.org (yury.selivanov) Date: Mon, 20 Apr 2015 03:23:16 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_pep-0492=3A_More_edits_re_PEP?= =?utf-8?q?_3152=2E?= Message-ID: <20150420032316.31099.34784@psf.io> https://hg.python.org/peps/rev/a4dc346653ad changeset: 5777:a4dc346653ad user: Yury Selivanov date: Sun Apr 19 23:23:12 2015 -0400 summary: pep-0492: More edits re PEP 3152. files: pep-0492.txt | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) diff --git a/pep-0492.txt b/pep-0492.txt --- a/pep-0492.txt +++ b/pep-0492.txt @@ -706,7 +706,8 @@ 4. Since it is impossible to call a *cofunction* without a ``cocall`` keyword, it automatically prevents the common mistake of forgetting to use - ``yield from`` on generator-based coroutines. + ``yield from`` on generator-based coroutines. This proposal addresses + this problem with a different approach, see `Debugging Features`_. 5. There are no equivalents of ``async for`` and ``async with`` in PEP 3152. -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Mon Apr 20 08:33:18 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Mon, 20 Apr 2015 06:33:18 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzIzODQy?= =?utf-8?q?=3A_Added_tests_for_os=2Emajor=28=29=2C_os=2Eminor=28=29_and_os?= =?utf-8?b?Lm1ha2VkZXYoKS4=?= Message-ID: <20150420063318.31123.47817@psf.io> https://hg.python.org/cpython/rev/998d967b8a57 changeset: 95727:998d967b8a57 branch: 3.4 parent: 95724:512a2408181f user: Serhiy Storchaka date: Mon Apr 20 09:22:13 2015 +0300 summary: Issue #23842: Added tests for os.major(), os.minor() and os.makedev(). files: Lib/test/test_posix.py | 30 ++++++++++++++++++++++++++++++ 1 files changed, 30 insertions(+), 0 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 @@ -443,6 +443,36 @@ else: self.assertTrue(stat.S_ISFIFO(posix.stat(support.TESTFN).st_mode)) + @unittest.skipUnless(hasattr(posix, 'stat'), 'test needs posix.stat()') + @unittest.skipUnless(hasattr(posix, 'makedev'), 'test needs posix.makedev()') + def test_makedev(self): + st = posix.stat(support.TESTFN) + dev = st.st_dev + self.assertIsInstance(dev, int) + self.assertGreaterEqual(dev, 0) + + major = posix.major(dev) + self.assertIsInstance(major, int) + self.assertGreaterEqual(major, 0) + self.assertEqual(posix.major(dev), major) + self.assertRaises(TypeError, posix.major, float(dev)) + self.assertRaises(TypeError, posix.major) + self.assertRaises((ValueError, OverflowError), posix.major, -1) + + minor = posix.minor(dev) + self.assertIsInstance(minor, int) + self.assertGreaterEqual(minor, 0) + self.assertEqual(posix.minor(dev), minor) + self.assertRaises(TypeError, posix.minor, float(dev)) + self.assertRaises(TypeError, posix.minor) + self.assertRaises((ValueError, OverflowError), posix.minor, -1) + + self.assertEqual(posix.makedev(major, minor), dev) + self.assertRaises(TypeError, posix.makedev, float(major), minor) + self.assertRaises(TypeError, posix.makedev, major, float(minor)) + self.assertRaises(TypeError, posix.makedev, major) + self.assertRaises(TypeError, posix.makedev) + def _test_all_chown_common(self, chown_func, first_param, stat_func): """Common code for chown, fchown and lchown tests.""" def check_stat(uid, gid): -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Apr 20 08:33:18 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Mon, 20 Apr 2015 06:33:18 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2323842=3A_Added_tests_for_os=2Emajor=28=29=2C_os?= =?utf-8?b?Lm1pbm9yKCkgYW5kIG9zLm1ha2VkZXYoKS4=?= Message-ID: <20150420063318.31125.31623@psf.io> https://hg.python.org/cpython/rev/d477da6f287f changeset: 95728:d477da6f287f parent: 95725:8d9bf18defd7 parent: 95727:998d967b8a57 user: Serhiy Storchaka date: Mon Apr 20 09:23:21 2015 +0300 summary: Issue #23842: Added tests for os.major(), os.minor() and os.makedev(). files: Lib/test/test_posix.py | 30 ++++++++++++++++++++++++++++++ 1 files changed, 30 insertions(+), 0 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 @@ -442,6 +442,36 @@ else: self.assertTrue(stat.S_ISFIFO(posix.stat(support.TESTFN).st_mode)) + @unittest.skipUnless(hasattr(posix, 'stat'), 'test needs posix.stat()') + @unittest.skipUnless(hasattr(posix, 'makedev'), 'test needs posix.makedev()') + def test_makedev(self): + st = posix.stat(support.TESTFN) + dev = st.st_dev + self.assertIsInstance(dev, int) + self.assertGreaterEqual(dev, 0) + + major = posix.major(dev) + self.assertIsInstance(major, int) + self.assertGreaterEqual(major, 0) + self.assertEqual(posix.major(dev), major) + self.assertRaises(TypeError, posix.major, float(dev)) + self.assertRaises(TypeError, posix.major) + self.assertRaises((ValueError, OverflowError), posix.major, -1) + + minor = posix.minor(dev) + self.assertIsInstance(minor, int) + self.assertGreaterEqual(minor, 0) + self.assertEqual(posix.minor(dev), minor) + self.assertRaises(TypeError, posix.minor, float(dev)) + self.assertRaises(TypeError, posix.minor) + self.assertRaises((ValueError, OverflowError), posix.minor, -1) + + self.assertEqual(posix.makedev(major, minor), dev) + self.assertRaises(TypeError, posix.makedev, float(major), minor) + self.assertRaises(TypeError, posix.makedev, major, float(minor)) + self.assertRaises(TypeError, posix.makedev, major) + self.assertRaises(TypeError, posix.makedev) + def _test_all_chown_common(self, chown_func, first_param, stat_func): """Common code for chown, fchown and lchown tests.""" def check_stat(uid, gid): -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Apr 20 08:33:18 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Mon, 20 Apr 2015 06:33:18 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzIzNzI4?= =?utf-8?q?=3A_binascii=2Ecrc=5Fhqx=28=29_could_return_an_integer_outside_?= =?utf-8?q?of_the_range?= Message-ID: <20150420063318.27926.85089@psf.io> https://hg.python.org/cpython/rev/0ead02929df2 changeset: 95729:0ead02929df2 branch: 3.4 parent: 95727:998d967b8a57 user: Serhiy Storchaka date: Mon Apr 20 09:26:49 2015 +0300 summary: Issue #23728: binascii.crc_hqx() could return an integer outside of the range 0-0xffff for empty data. files: Lib/test/test_binascii.py | 12 ++++++++++++ Misc/NEWS | 3 +++ Modules/binascii.c | 16 ++++++++-------- Modules/clinic/binascii.c.h | 14 +++++++------- 4 files changed, 30 insertions(+), 15 deletions(-) diff --git a/Lib/test/test_binascii.py b/Lib/test/test_binascii.py --- a/Lib/test/test_binascii.py +++ b/Lib/test/test_binascii.py @@ -136,6 +136,18 @@ # Issue #7701 (crash on a pydebug build) self.assertEqual(binascii.b2a_uu(b'x'), b'!> \n') + def test_crc_hqx(self): + crc = binascii.crc_hqx(self.type2test(b"Test the CRC-32 of"), 0) + crc = binascii.crc_hqx(self.type2test(b" this string."), crc) + self.assertEqual(crc, 14290) + + self.assertRaises(TypeError, binascii.crc_hqx) + self.assertRaises(TypeError, binascii.crc_hqx, self.type2test(b'')) + + for crc in 0, 1, 0x1234, 0x12345, 0x12345678, -1: + self.assertEqual(binascii.crc_hqx(self.type2test(b''), crc), + crc & 0xffff) + def test_crc32(self): crc = binascii.crc32(self.type2test(b"Test the CRC-32 of")) crc = binascii.crc32(self.type2test(b" this string."), crc) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -29,6 +29,9 @@ Library ------- +- Issue #23728: binascii.crc_hqx() could return an integer outside of the range + 0-0xffff for empty data. + - Issue #23811: Add missing newline to the PyCompileError error message. Patch by Alex Shkop. diff --git a/Modules/binascii.c b/Modules/binascii.c --- a/Modules/binascii.c +++ b/Modules/binascii.c @@ -909,31 +909,31 @@ /*[clinic input] -binascii.crc_hqx -> int +binascii.crc_hqx -> unsigned_int data: Py_buffer - crc: int + crc: unsigned_int(bitwise=True) / Compute hqx CRC incrementally. [clinic start generated code]*/ -static int -binascii_crc_hqx_impl(PyModuleDef *module, Py_buffer *data, int crc) -/*[clinic end generated code: output=634dac18dfa863d7 input=68060931b2f51c8a]*/ +static unsigned int +binascii_crc_hqx_impl(PyModuleDef *module, Py_buffer *data, unsigned int crc) +/*[clinic end generated code: output=167c2dac62625717 input=add8c53712ccceda]*/ { unsigned char *bin_data; - unsigned int ucrc = (unsigned int)crc; Py_ssize_t len; + crc &= 0xffff; bin_data = data->buf; len = data->len; while(len-- > 0) { - ucrc=((ucrc<<8)&0xff00)^crctab_hqx[((ucrc>>8)&0xff)^*bin_data++]; + crc = ((crc<<8)&0xff00) ^ crctab_hqx[(crc>>8)^*bin_data++]; } - return (int)ucrc; + return crc; } #ifndef USE_ZLIB_CRC32 diff --git a/Modules/clinic/binascii.c.h b/Modules/clinic/binascii.c.h --- a/Modules/clinic/binascii.c.h +++ b/Modules/clinic/binascii.c.h @@ -267,25 +267,25 @@ #define BINASCII_CRC_HQX_METHODDEF \ {"crc_hqx", (PyCFunction)binascii_crc_hqx, METH_VARARGS, binascii_crc_hqx__doc__}, -static int -binascii_crc_hqx_impl(PyModuleDef *module, Py_buffer *data, int crc); +static unsigned int +binascii_crc_hqx_impl(PyModuleDef *module, Py_buffer *data, unsigned int crc); static PyObject * binascii_crc_hqx(PyModuleDef *module, PyObject *args) { PyObject *return_value = NULL; Py_buffer data = {NULL, NULL}; - int crc; - int _return_value; + unsigned int crc; + unsigned int _return_value; if (!PyArg_ParseTuple(args, - "y*i:crc_hqx", + "y*I:crc_hqx", &data, &crc)) goto exit; _return_value = binascii_crc_hqx_impl(module, &data, crc); if ((_return_value == -1) && PyErr_Occurred()) goto exit; - return_value = PyLong_FromLong((long)_return_value); + return_value = PyLong_FromUnsignedLong((unsigned long)_return_value); exit: /* Cleanup for data */ @@ -543,4 +543,4 @@ return return_value; } -/*[clinic end generated code: output=e46d29f8c9adae7e input=a9049054013a1b77]*/ +/*[clinic end generated code: output=22761b36f4f9e5bb input=a9049054013a1b77]*/ -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Apr 20 08:33:18 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Mon, 20 Apr 2015 06:33:18 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzIzODQy?= =?utf-8?b?OiBvcy5tYWpvcigpLCBvcy5taW5vcigpIGFuZCBvcy5tYWtlZGV2KCkgbm93?= =?utf-8?q?_support_ints_again=2E?= Message-ID: <20150420063318.31123.37672@psf.io> https://hg.python.org/cpython/rev/cd7d51b5c951 changeset: 95726:cd7d51b5c951 branch: 2.7 parent: 95716:d70995cf44b3 user: Serhiy Storchaka date: Mon Apr 20 09:21:23 2015 +0300 summary: Issue #23842: os.major(), os.minor() and os.makedev() now support ints again. files: Lib/test/test_posix.py | 34 ++++++++++++++++++++++++++++++ Misc/NEWS | 2 + Modules/posixmodule.c | 33 +++++++++++++++++++++++++--- 3 files changed, 65 insertions(+), 4 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 @@ -261,6 +261,40 @@ def test_stat(self): self.assertTrue(posix.stat(test_support.TESTFN)) + @unittest.skipUnless(hasattr(posix, 'stat'), 'test needs posix.stat()') + @unittest.skipUnless(hasattr(posix, 'makedev'), 'test needs posix.makedev()') + def test_makedev(self): + st = posix.stat(test_support.TESTFN) + dev = st.st_dev + self.assertIsInstance(dev, (int, long)) + self.assertGreaterEqual(dev, 0) + + major = posix.major(dev) + self.assertIsInstance(major, (int, long)) + self.assertGreaterEqual(major, 0) + self.assertEqual(posix.major(int(dev)), major) + self.assertEqual(posix.major(long(dev)), major) + self.assertRaises(TypeError, posix.major, float(dev)) + self.assertRaises(TypeError, posix.major) + self.assertRaises((ValueError, OverflowError), posix.major, -1) + + minor = posix.minor(dev) + self.assertIsInstance(minor, (int, long)) + self.assertGreaterEqual(minor, 0) + self.assertEqual(posix.minor(int(dev)), minor) + self.assertEqual(posix.minor(long(dev)), minor) + self.assertRaises(TypeError, posix.minor, float(dev)) + self.assertRaises(TypeError, posix.minor) + self.assertRaises((ValueError, OverflowError), posix.minor, -1) + + self.assertEqual(posix.makedev(major, minor), dev) + self.assertEqual(posix.makedev(int(major), int(minor)), dev) + self.assertEqual(posix.makedev(long(major), long(minor)), dev) + self.assertRaises(TypeError, posix.makedev, float(major), minor) + self.assertRaises(TypeError, posix.makedev, major, float(minor)) + self.assertRaises(TypeError, posix.makedev, major) + self.assertRaises(TypeError, posix.makedev) + def _test_all_chown_common(self, chown_func, first_param, stat_func): """Common code for chown, fchown and lchown tests.""" def check_stat(uid, gid): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -21,6 +21,8 @@ Library ------- +- Issue #23842: os.major(), os.minor() and os.makedev() now support ints again. + - Issue #23811: Add missing newline to the PyCompileError error message. Patch by Alex Shkop. diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -478,13 +478,38 @@ static int _Py_Dev_Converter(PyObject *obj, void *p) { + PyObject *index = PyNumber_Index(obj); + if (index == NULL) + return 0; + if (PyInt_Check(index)) { + long x = PyInt_AS_LONG(index); + Py_DECREF(index); + if (x == -1 && PyErr_Occurred()) + return 0; + if (x < 0) { + PyErr_SetString(PyExc_OverflowError, + "can't convert negative number to unsigned long"); + return 0; + } + *((dev_t *)p) = (unsigned long)x; + } + else if (PyLong_Check(index)) { #ifdef HAVE_LONG_LONG - *((dev_t *)p) = PyLong_AsUnsignedLongLong(obj); + *((dev_t *)p) = PyLong_AsUnsignedLongLong(index); #else - *((dev_t *)p) = PyLong_AsUnsignedLong(obj); -#endif - if (PyErr_Occurred()) + *((dev_t *)p) = PyLong_AsUnsignedLong(index); +#endif + Py_DECREF(index); + if (PyErr_Occurred()) + return 0; + } + else { + Py_DECREF(index); + PyErr_Format(PyExc_TypeError, + "expected int/long, %s found", + Py_TYPE(obj)->tp_name); return 0; + } return 1; } -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Apr 20 08:33:19 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Mon, 20 Apr 2015 06:33:19 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzIzNzI4?= =?utf-8?q?=3A_Added_a_test_for_binascii=2Ecrc=5Fhqx=28=29=2E?= Message-ID: <20150420063318.30329.78309@psf.io> https://hg.python.org/cpython/rev/17702fd8ac0d changeset: 95731:17702fd8ac0d branch: 2.7 parent: 95726:cd7d51b5c951 user: Serhiy Storchaka date: Mon Apr 20 09:32:29 2015 +0300 summary: Issue #23728: Added a test for binascii.crc_hqx(). files: Lib/test/test_binascii.py | 8 ++++++++ 1 files changed, 8 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_binascii.py b/Lib/test/test_binascii.py --- a/Lib/test/test_binascii.py +++ b/Lib/test/test_binascii.py @@ -137,6 +137,14 @@ # Issue #7701 (crash on a pydebug build) self.assertEqual(binascii.b2a_uu('x'), '!> \n') + def test_crc_hqx(self): + crc = binascii.crc_hqx(self.type2test(b"Test the CRC-32 of"), 0) + crc = binascii.crc_hqx(self.type2test(b" this string."), crc) + self.assertEqual(crc, 14290) + + self.assertRaises(TypeError, binascii.crc_hqx) + self.assertRaises(TypeError, binascii.crc_hqx, self.type2test(b'')) + def test_crc32(self): crc = binascii.crc32(self.type2test("Test the CRC-32 of")) crc = binascii.crc32(self.type2test(" this string."), crc) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Apr 20 08:33:19 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Mon, 20 Apr 2015 06:33:19 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2323728=3A_binascii=2Ecrc=5Fhqx=28=29_could_retur?= =?utf-8?q?n_an_integer_outside_of_the_range?= Message-ID: <20150420063318.6585.1090@psf.io> https://hg.python.org/cpython/rev/abb86c6b11b2 changeset: 95730:abb86c6b11b2 parent: 95728:d477da6f287f parent: 95729:0ead02929df2 user: Serhiy Storchaka date: Mon Apr 20 09:31:51 2015 +0300 summary: Issue #23728: binascii.crc_hqx() could return an integer outside of the range 0-0xffff for empty data. files: Lib/test/test_binascii.py | 12 ++++++++++++ Misc/NEWS | 3 +++ Modules/binascii.c | 16 ++++++++-------- Modules/clinic/binascii.c.h | 16 ++++++++-------- 4 files changed, 31 insertions(+), 16 deletions(-) diff --git a/Lib/test/test_binascii.py b/Lib/test/test_binascii.py --- a/Lib/test/test_binascii.py +++ b/Lib/test/test_binascii.py @@ -135,6 +135,18 @@ # Issue #7701 (crash on a pydebug build) self.assertEqual(binascii.b2a_uu(b'x'), b'!> \n') + def test_crc_hqx(self): + crc = binascii.crc_hqx(self.type2test(b"Test the CRC-32 of"), 0) + crc = binascii.crc_hqx(self.type2test(b" this string."), crc) + self.assertEqual(crc, 14290) + + self.assertRaises(TypeError, binascii.crc_hqx) + self.assertRaises(TypeError, binascii.crc_hqx, self.type2test(b'')) + + for crc in 0, 1, 0x1234, 0x12345, 0x12345678, -1: + self.assertEqual(binascii.crc_hqx(self.type2test(b''), crc), + crc & 0xffff) + def test_crc32(self): crc = binascii.crc32(self.type2test(b"Test the CRC-32 of")) crc = binascii.crc32(self.type2test(b" this string."), crc) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -37,6 +37,9 @@ Library ------- +- Issue #23728: binascii.crc_hqx() could return an integer outside of the range + 0-0xffff for empty data. + - Issue #16914: new debuglevel 2 in smtplib adds timestamps to debug output. - Issue #7159: urllib.request now supports sending auth credentials diff --git a/Modules/binascii.c b/Modules/binascii.c --- a/Modules/binascii.c +++ b/Modules/binascii.c @@ -908,31 +908,31 @@ /*[clinic input] -binascii.crc_hqx -> int +binascii.crc_hqx -> unsigned_int data: Py_buffer - crc: int + crc: unsigned_int(bitwise=True) / Compute hqx CRC incrementally. [clinic start generated code]*/ -static int -binascii_crc_hqx_impl(PyModuleDef *module, Py_buffer *data, int crc) -/*[clinic end generated code: output=634dac18dfa863d7 input=68060931b2f51c8a]*/ +static unsigned int +binascii_crc_hqx_impl(PyModuleDef *module, Py_buffer *data, unsigned int crc) +/*[clinic end generated code: output=167c2dac62625717 input=add8c53712ccceda]*/ { unsigned char *bin_data; - unsigned int ucrc = (unsigned int)crc; Py_ssize_t len; + crc &= 0xffff; bin_data = data->buf; len = data->len; while(len-- > 0) { - ucrc=((ucrc<<8)&0xff00)^crctab_hqx[((ucrc>>8)&0xff)^*bin_data++]; + crc = ((crc<<8)&0xff00) ^ crctab_hqx[(crc>>8)^*bin_data++]; } - return (int)ucrc; + return crc; } #ifndef USE_ZLIB_CRC32 diff --git a/Modules/clinic/binascii.c.h b/Modules/clinic/binascii.c.h --- a/Modules/clinic/binascii.c.h +++ b/Modules/clinic/binascii.c.h @@ -267,25 +267,25 @@ #define BINASCII_CRC_HQX_METHODDEF \ {"crc_hqx", (PyCFunction)binascii_crc_hqx, METH_VARARGS, binascii_crc_hqx__doc__}, -static int -binascii_crc_hqx_impl(PyModuleDef *module, Py_buffer *data, int crc); +static unsigned int +binascii_crc_hqx_impl(PyModuleDef *module, Py_buffer *data, unsigned int crc); static PyObject * binascii_crc_hqx(PyModuleDef *module, PyObject *args) { PyObject *return_value = NULL; Py_buffer data = {NULL, NULL}; - int crc; - int _return_value; + unsigned int crc; + unsigned int _return_value; if (!PyArg_ParseTuple(args, - "y*i:crc_hqx", + "y*I:crc_hqx", &data, &crc)) goto exit; _return_value = binascii_crc_hqx_impl(module, &data, crc); - if ((_return_value == -1) && PyErr_Occurred()) + if ((_return_value == (unsigned int)-1) && PyErr_Occurred()) goto exit; - return_value = PyLong_FromLong((long)_return_value); + return_value = PyLong_FromUnsignedLong((unsigned long)_return_value); exit: /* Cleanup for data */ @@ -544,4 +544,4 @@ return return_value; } -/*[clinic end generated code: output=175025a8a94fbdd1 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=5f8d3578618b3432 input=a9049054013a1b77]*/ -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Apr 20 09:14:31 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Mon, 20 Apr 2015 07:14:31 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2323908=3A_os_functions_now_reject_paths_with_emb?= =?utf-8?q?edded_null_character?= Message-ID: <20150420071431.30341.65655@psf.io> https://hg.python.org/cpython/rev/bdf13c7dcf7f changeset: 95733:bdf13c7dcf7f parent: 95730:abb86c6b11b2 parent: 95732:cdadde8396a4 user: Serhiy Storchaka date: Mon Apr 20 10:12:28 2015 +0300 summary: Issue #23908: os functions now reject paths with embedded null character on Windows instead of silently truncate them. Removed no longer used _PyUnicode_HasNULChars(). files: Include/unicodeobject.h | 6 ---- Lib/test/test_posix.py | 36 +++++++++++++++++++++++++++++ Misc/NEWS | 3 ++ Modules/_io/fileio.c | 13 ++++----- Modules/posixmodule.c | 5 ++++ Objects/unicodeobject.c | 15 ------------ 6 files changed, 50 insertions(+), 28 deletions(-) diff --git a/Include/unicodeobject.h b/Include/unicodeobject.h --- a/Include/unicodeobject.h +++ b/Include/unicodeobject.h @@ -2060,12 +2060,6 @@ PyObject *element /* Element string */ ); -/* Checks whether the string contains any NUL characters. */ - -#ifndef Py_LIMITED_API -PyAPI_FUNC(int) _PyUnicode_HasNULChars(PyObject *); -#endif - /* Checks whether argument is a valid identifier. */ PyAPI_FUNC(int) PyUnicode_IsIdentifier(PyObject *s); 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 @@ -1168,6 +1168,42 @@ else: self.fail("No valid path_error2() test for os." + name) + def test_path_with_null_character(self): + fn = support.TESTFN + fn_with_NUL = fn + '\0' + self.addCleanup(support.unlink, fn) + support.unlink(fn) + fd = None + try: + with self.assertRaises(ValueError): + fd = os.open(fn_with_NUL, os.O_WRONLY | os.O_CREAT) # raises + finally: + if fd is not None: + os.close(fd) + self.assertFalse(os.path.exists(fn)) + self.assertRaises(ValueError, os.mkdir, fn_with_NUL) + self.assertFalse(os.path.exists(fn)) + open(fn, 'wb').close() + self.assertRaises(ValueError, os.stat, fn_with_NUL) + + def test_path_with_null_byte(self): + fn = os.fsencode(support.TESTFN) + fn_with_NUL = fn + b'\0' + self.addCleanup(support.unlink, fn) + support.unlink(fn) + fd = None + try: + with self.assertRaises(ValueError): + fd = os.open(fn_with_NUL, os.O_WRONLY | os.O_CREAT) # raises + finally: + if fd is not None: + os.close(fd) + self.assertFalse(os.path.exists(fn)) + self.assertRaises(ValueError, os.mkdir, fn_with_NUL) + self.assertFalse(os.path.exists(fn)) + open(fn, 'wb').close() + self.assertRaises(ValueError, os.stat, fn_with_NUL) + class PosixGroupsTester(unittest.TestCase): def setUp(self): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -37,6 +37,9 @@ Library ------- +- Issue #23908: os functions now reject paths with embedded null character + on Windows instead of silently truncate them. + - Issue #23728: binascii.crc_hqx() could return an integer outside of the range 0-0xffff for empty data. diff --git a/Modules/_io/fileio.c b/Modules/_io/fileio.c --- a/Modules/_io/fileio.c +++ b/Modules/_io/fileio.c @@ -281,15 +281,14 @@ #ifdef MS_WINDOWS if (PyUnicode_Check(nameobj)) { - int rv = _PyUnicode_HasNULChars(nameobj); - if (rv) { - if (rv != -1) - PyErr_SetString(PyExc_ValueError, "embedded null character"); + Py_ssize_t length; + widename = PyUnicode_AsUnicodeAndSize(nameobj, &length); + if (widename == NULL) + return -1; + if (wcslen(widename) != length) { + PyErr_SetString(PyExc_ValueError, "embedded null character"); return -1; } - widename = PyUnicode_AsUnicode(nameobj); - if (widename == NULL) - return -1; } else #endif if (fd < 0) diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -866,6 +866,11 @@ Py_DECREF(unicode); return 0; } + if (wcslen(wide) != length) { + FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character"); + Py_DECREF(unicode); + return 0; + } path->wide = wide; path->narrow = NULL; diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -3607,21 +3607,6 @@ int -_PyUnicode_HasNULChars(PyObject* str) -{ - Py_ssize_t pos; - - if (PyUnicode_READY(str) == -1) - return -1; - pos = findchar(PyUnicode_DATA(str), PyUnicode_KIND(str), - PyUnicode_GET_LENGTH(str), '\0', 1); - if (pos == -1) - return 0; - else - return 1; -} - -int PyUnicode_FSConverter(PyObject* arg, void* addr) { PyObject *output = NULL; -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Apr 20 09:14:31 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Mon, 20 Apr 2015 07:14:31 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzIzOTA4?= =?utf-8?q?=3A_os_functions_now_reject_paths_with_embedded_null_character?= Message-ID: <20150420071431.30317.44333@psf.io> https://hg.python.org/cpython/rev/cdadde8396a4 changeset: 95732:cdadde8396a4 branch: 3.4 parent: 95729:0ead02929df2 user: Serhiy Storchaka date: Mon Apr 20 09:53:58 2015 +0300 summary: Issue #23908: os functions now reject paths with embedded null character on Windows instead of silently truncate them. files: Lib/test/test_posix.py | 36 ++++++++++++++++++++++++++++++ Misc/NEWS | 3 ++ Modules/_io/fileio.c | 13 +++++----- Modules/posixmodule.c | 5 ++++ 4 files changed, 50 insertions(+), 7 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 @@ -1169,6 +1169,42 @@ else: self.fail("No valid path_error2() test for os." + name) + def test_path_with_null_character(self): + fn = support.TESTFN + fn_with_NUL = fn + '\0' + self.addCleanup(support.unlink, fn) + support.unlink(fn) + fd = None + try: + with self.assertRaises(TypeError): + fd = os.open(fn_with_NUL, os.O_WRONLY | os.O_CREAT) # raises + finally: + if fd is not None: + os.close(fd) + self.assertFalse(os.path.exists(fn)) + self.assertRaises(TypeError, os.mkdir, fn_with_NUL) + self.assertFalse(os.path.exists(fn)) + open(fn, 'wb').close() + self.assertRaises(TypeError, os.stat, fn_with_NUL) + + def test_path_with_null_byte(self): + fn = os.fsencode(support.TESTFN) + fn_with_NUL = fn + b'\0' + self.addCleanup(support.unlink, fn) + support.unlink(fn) + fd = None + try: + with self.assertRaises(ValueError): + fd = os.open(fn_with_NUL, os.O_WRONLY | os.O_CREAT) # raises + finally: + if fd is not None: + os.close(fd) + self.assertFalse(os.path.exists(fn)) + self.assertRaises(ValueError, os.mkdir, fn_with_NUL) + self.assertFalse(os.path.exists(fn)) + open(fn, 'wb').close() + self.assertRaises(ValueError, os.stat, fn_with_NUL) + class PosixGroupsTester(unittest.TestCase): def setUp(self): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -29,6 +29,9 @@ Library ------- +- Issue #23908: os functions now reject paths with embedded null character + on Windows instead of silently truncate them. + - Issue #23728: binascii.crc_hqx() could return an integer outside of the range 0-0xffff for empty data. diff --git a/Modules/_io/fileio.c b/Modules/_io/fileio.c --- a/Modules/_io/fileio.c +++ b/Modules/_io/fileio.c @@ -275,15 +275,14 @@ #ifdef MS_WINDOWS if (PyUnicode_Check(nameobj)) { - int rv = _PyUnicode_HasNULChars(nameobj); - if (rv) { - if (rv != -1) - PyErr_SetString(PyExc_TypeError, "embedded NUL character"); + Py_ssize_t length; + widename = PyUnicode_AsUnicodeAndSize(nameobj, &length); + if (widename == NULL) + return -1; + if (wcslen(widename) != length) { + PyErr_SetString(PyExc_TypeError, "embedded NUL character"); return -1; } - widename = PyUnicode_AsUnicode(nameobj); - if (widename == NULL) - return -1; } else #endif if (fd < 0) diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -858,6 +858,11 @@ Py_DECREF(unicode); return 0; } + if (wcslen(wide) != length) { + FORMAT_EXCEPTION(PyExc_TypeError, "embedded null character"); + Py_DECREF(unicode); + return 0; + } path->wide = wide; path->narrow = NULL; -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Apr 20 10:20:25 2015 From: python-checkins at python.org (larry.hastings) Date: Mon, 20 Apr 2015 08:20:25 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Added_tag_v3=2E5=2E0a4_for?= =?utf-8?q?_changeset_413e0e0004f4?= Message-ID: <20150420082012.31123.23445@psf.io> https://hg.python.org/cpython/rev/5b845fec4daf changeset: 95736:5b845fec4daf user: Larry Hastings date: Sun Apr 19 13:56:54 2015 -0700 summary: Added tag v3.5.0a4 for changeset 413e0e0004f4 files: .hgtags | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/.hgtags b/.hgtags --- a/.hgtags +++ b/.hgtags @@ -147,3 +147,4 @@ 5d4b6a57d5fd7564bf73f3db0e46fe5eeb00bcd8 v3.5.0a1 0337bd7ebcb6559d69679bc7025059ad1ce4f432 v3.5.0a2 82656e28b5e5c4ae48d8dd8b5f0d7968908a82b6 v3.5.0a3 +413e0e0004f4f954331cb8122aa55fe208984955 v3.5.0a4 -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Apr 20 10:20:25 2015 From: python-checkins at python.org (larry.hastings) Date: Mon, 20 Apr 2015 08:20:25 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Post-release_updates_for_P?= =?utf-8?q?ython_3=2E5=2E0a4=2E?= Message-ID: <20150420082012.6605.55520@psf.io> https://hg.python.org/cpython/rev/4f65d3423635 changeset: 95737:4f65d3423635 user: Larry Hastings date: Mon Apr 20 01:18:10 2015 -0700 summary: Post-release updates for Python 3.5.0a4. 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 4 /* Version as a string */ -#define PY_VERSION "3.5.0a4" +#define PY_VERSION "3.5.0a4+" /*--end constants--*/ /* Version as a single 4-byte hex number, e.g. 0x010502B2 == 1.5.2b2. diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -2,6 +2,18 @@ Python News +++++++++++ +What's New in Python 3.5.0 beta 1? +================================== + +Release date: 2015-04-24 + +Core and Builtins +----------------- + +Library +------- + + What's New in Python 3.5.0 alpha 4? =================================== -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Apr 20 10:20:25 2015 From: python-checkins at python.org (larry.hastings) Date: Mon, 20 Apr 2015 08:20:25 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Version_number_bump_for_Py?= =?utf-8?q?thon_3=2E5=2E0a4=2E?= Message-ID: <20150420082012.27912.61280@psf.io> https://hg.python.org/cpython/rev/413e0e0004f4 changeset: 95735:413e0e0004f4 tag: v3.5.0a4 user: Larry Hastings date: Sun Apr 19 13:51:40 2015 -0700 summary: Version number bump for Python 3.5.0a4. files: Include/patchlevel.h | 4 ++-- Lib/distutils/__init__.py | 2 +- Lib/idlelib/idlever.py | 2 +- Misc/NEWS | 2 +- README | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Include/patchlevel.h b/Include/patchlevel.h --- a/Include/patchlevel.h +++ b/Include/patchlevel.h @@ -20,10 +20,10 @@ #define PY_MINOR_VERSION 5 #define PY_MICRO_VERSION 0 #define PY_RELEASE_LEVEL PY_RELEASE_LEVEL_ALPHA -#define PY_RELEASE_SERIAL 3 +#define PY_RELEASE_SERIAL 4 /* Version as a string */ -#define PY_VERSION "3.5.0a3+" +#define PY_VERSION "3.5.0a4" /*--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.5.0a3" +__version__ = "3.5.0a4" #--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.5.0a3" +IDLE_VERSION = "3.5.0a4" diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -5,7 +5,7 @@ What's New in Python 3.5.0 alpha 4? =================================== -Release date: XXX +Release date: 2015-04-19 Core and Builtins ----------------- diff --git a/README b/README --- a/README +++ b/README @@ -1,4 +1,4 @@ -This is Python version 3.5.0 alpha 3 +This is Python version 3.5.0 alpha 4 ==================================== Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Apr 20 10:20:25 2015 From: python-checkins at python.org (larry.hastings) Date: Mon, 20 Apr 2015 08:20:25 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_default_-=3E_default?= =?utf-8?q?=29=3A_Merge_Python_3=2E5=2E0a4_release_engineering_commits=2E?= Message-ID: <20150420082017.31119.36244@psf.io> https://hg.python.org/cpython/rev/09fa20da2872 changeset: 95738:09fa20da2872 parent: 95737:4f65d3423635 parent: 95733:bdf13c7dcf7f user: Larry Hastings date: Mon Apr 20 01:19:55 2015 -0700 summary: Merge Python 3.5.0a4 release engineering commits. files: Include/unicodeobject.h | 6 -- Lib/test/test_binascii.py | 12 ++++ Lib/test/test_posix.py | 66 +++++++++++++++++++++++++ Misc/NEWS | 6 ++ Modules/_io/fileio.c | 13 ++-- Modules/binascii.c | 16 +++--- Modules/clinic/binascii.c.h | 16 +++--- Modules/posixmodule.c | 5 + Objects/unicodeobject.c | 15 ----- README | 2 - Tools/msi/make_zip.py | 13 +++- Tools/msi/testrelease.bat | 5 +- 12 files changed, 125 insertions(+), 50 deletions(-) diff --git a/Include/unicodeobject.h b/Include/unicodeobject.h --- a/Include/unicodeobject.h +++ b/Include/unicodeobject.h @@ -2060,12 +2060,6 @@ PyObject *element /* Element string */ ); -/* Checks whether the string contains any NUL characters. */ - -#ifndef Py_LIMITED_API -PyAPI_FUNC(int) _PyUnicode_HasNULChars(PyObject *); -#endif - /* Checks whether argument is a valid identifier. */ PyAPI_FUNC(int) PyUnicode_IsIdentifier(PyObject *s); diff --git a/Lib/test/test_binascii.py b/Lib/test/test_binascii.py --- a/Lib/test/test_binascii.py +++ b/Lib/test/test_binascii.py @@ -135,6 +135,18 @@ # Issue #7701 (crash on a pydebug build) self.assertEqual(binascii.b2a_uu(b'x'), b'!> \n') + def test_crc_hqx(self): + crc = binascii.crc_hqx(self.type2test(b"Test the CRC-32 of"), 0) + crc = binascii.crc_hqx(self.type2test(b" this string."), crc) + self.assertEqual(crc, 14290) + + self.assertRaises(TypeError, binascii.crc_hqx) + self.assertRaises(TypeError, binascii.crc_hqx, self.type2test(b'')) + + for crc in 0, 1, 0x1234, 0x12345, 0x12345678, -1: + self.assertEqual(binascii.crc_hqx(self.type2test(b''), crc), + crc & 0xffff) + def test_crc32(self): crc = binascii.crc32(self.type2test(b"Test the CRC-32 of")) crc = binascii.crc32(self.type2test(b" this string."), crc) 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 @@ -442,6 +442,36 @@ else: self.assertTrue(stat.S_ISFIFO(posix.stat(support.TESTFN).st_mode)) + @unittest.skipUnless(hasattr(posix, 'stat'), 'test needs posix.stat()') + @unittest.skipUnless(hasattr(posix, 'makedev'), 'test needs posix.makedev()') + def test_makedev(self): + st = posix.stat(support.TESTFN) + dev = st.st_dev + self.assertIsInstance(dev, int) + self.assertGreaterEqual(dev, 0) + + major = posix.major(dev) + self.assertIsInstance(major, int) + self.assertGreaterEqual(major, 0) + self.assertEqual(posix.major(dev), major) + self.assertRaises(TypeError, posix.major, float(dev)) + self.assertRaises(TypeError, posix.major) + self.assertRaises((ValueError, OverflowError), posix.major, -1) + + minor = posix.minor(dev) + self.assertIsInstance(minor, int) + self.assertGreaterEqual(minor, 0) + self.assertEqual(posix.minor(dev), minor) + self.assertRaises(TypeError, posix.minor, float(dev)) + self.assertRaises(TypeError, posix.minor) + self.assertRaises((ValueError, OverflowError), posix.minor, -1) + + self.assertEqual(posix.makedev(major, minor), dev) + self.assertRaises(TypeError, posix.makedev, float(major), minor) + self.assertRaises(TypeError, posix.makedev, major, float(minor)) + self.assertRaises(TypeError, posix.makedev, major) + self.assertRaises(TypeError, posix.makedev) + def _test_all_chown_common(self, chown_func, first_param, stat_func): """Common code for chown, fchown and lchown tests.""" def check_stat(uid, gid): @@ -1138,6 +1168,42 @@ else: self.fail("No valid path_error2() test for os." + name) + def test_path_with_null_character(self): + fn = support.TESTFN + fn_with_NUL = fn + '\0' + self.addCleanup(support.unlink, fn) + support.unlink(fn) + fd = None + try: + with self.assertRaises(ValueError): + fd = os.open(fn_with_NUL, os.O_WRONLY | os.O_CREAT) # raises + finally: + if fd is not None: + os.close(fd) + self.assertFalse(os.path.exists(fn)) + self.assertRaises(ValueError, os.mkdir, fn_with_NUL) + self.assertFalse(os.path.exists(fn)) + open(fn, 'wb').close() + self.assertRaises(ValueError, os.stat, fn_with_NUL) + + def test_path_with_null_byte(self): + fn = os.fsencode(support.TESTFN) + fn_with_NUL = fn + b'\0' + self.addCleanup(support.unlink, fn) + support.unlink(fn) + fd = None + try: + with self.assertRaises(ValueError): + fd = os.open(fn_with_NUL, os.O_WRONLY | os.O_CREAT) # raises + finally: + if fd is not None: + os.close(fd) + self.assertFalse(os.path.exists(fn)) + self.assertRaises(ValueError, os.mkdir, fn_with_NUL) + self.assertFalse(os.path.exists(fn)) + open(fn, 'wb').close() + self.assertRaises(ValueError, os.stat, fn_with_NUL) + class PosixGroupsTester(unittest.TestCase): def setUp(self): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -49,6 +49,12 @@ Library ------- +- Issue #23908: os functions now reject paths with embedded null character + on Windows instead of silently truncate them. + +- Issue #23728: binascii.crc_hqx() could return an integer outside of the range + 0-0xffff for empty data. + - Issue #16914: new debuglevel 2 in smtplib adds timestamps to debug output. - Issue #7159: urllib.request now supports sending auth credentials diff --git a/Modules/_io/fileio.c b/Modules/_io/fileio.c --- a/Modules/_io/fileio.c +++ b/Modules/_io/fileio.c @@ -281,15 +281,14 @@ #ifdef MS_WINDOWS if (PyUnicode_Check(nameobj)) { - int rv = _PyUnicode_HasNULChars(nameobj); - if (rv) { - if (rv != -1) - PyErr_SetString(PyExc_ValueError, "embedded null character"); + Py_ssize_t length; + widename = PyUnicode_AsUnicodeAndSize(nameobj, &length); + if (widename == NULL) + return -1; + if (wcslen(widename) != length) { + PyErr_SetString(PyExc_ValueError, "embedded null character"); return -1; } - widename = PyUnicode_AsUnicode(nameobj); - if (widename == NULL) - return -1; } else #endif if (fd < 0) diff --git a/Modules/binascii.c b/Modules/binascii.c --- a/Modules/binascii.c +++ b/Modules/binascii.c @@ -908,31 +908,31 @@ /*[clinic input] -binascii.crc_hqx -> int +binascii.crc_hqx -> unsigned_int data: Py_buffer - crc: int + crc: unsigned_int(bitwise=True) / Compute hqx CRC incrementally. [clinic start generated code]*/ -static int -binascii_crc_hqx_impl(PyModuleDef *module, Py_buffer *data, int crc) -/*[clinic end generated code: output=634dac18dfa863d7 input=68060931b2f51c8a]*/ +static unsigned int +binascii_crc_hqx_impl(PyModuleDef *module, Py_buffer *data, unsigned int crc) +/*[clinic end generated code: output=167c2dac62625717 input=add8c53712ccceda]*/ { unsigned char *bin_data; - unsigned int ucrc = (unsigned int)crc; Py_ssize_t len; + crc &= 0xffff; bin_data = data->buf; len = data->len; while(len-- > 0) { - ucrc=((ucrc<<8)&0xff00)^crctab_hqx[((ucrc>>8)&0xff)^*bin_data++]; + crc = ((crc<<8)&0xff00) ^ crctab_hqx[(crc>>8)^*bin_data++]; } - return (int)ucrc; + return crc; } #ifndef USE_ZLIB_CRC32 diff --git a/Modules/clinic/binascii.c.h b/Modules/clinic/binascii.c.h --- a/Modules/clinic/binascii.c.h +++ b/Modules/clinic/binascii.c.h @@ -267,25 +267,25 @@ #define BINASCII_CRC_HQX_METHODDEF \ {"crc_hqx", (PyCFunction)binascii_crc_hqx, METH_VARARGS, binascii_crc_hqx__doc__}, -static int -binascii_crc_hqx_impl(PyModuleDef *module, Py_buffer *data, int crc); +static unsigned int +binascii_crc_hqx_impl(PyModuleDef *module, Py_buffer *data, unsigned int crc); static PyObject * binascii_crc_hqx(PyModuleDef *module, PyObject *args) { PyObject *return_value = NULL; Py_buffer data = {NULL, NULL}; - int crc; - int _return_value; + unsigned int crc; + unsigned int _return_value; if (!PyArg_ParseTuple(args, - "y*i:crc_hqx", + "y*I:crc_hqx", &data, &crc)) goto exit; _return_value = binascii_crc_hqx_impl(module, &data, crc); - if ((_return_value == -1) && PyErr_Occurred()) + if ((_return_value == (unsigned int)-1) && PyErr_Occurred()) goto exit; - return_value = PyLong_FromLong((long)_return_value); + return_value = PyLong_FromUnsignedLong((unsigned long)_return_value); exit: /* Cleanup for data */ @@ -544,4 +544,4 @@ return return_value; } -/*[clinic end generated code: output=175025a8a94fbdd1 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=5f8d3578618b3432 input=a9049054013a1b77]*/ diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -866,6 +866,11 @@ Py_DECREF(unicode); return 0; } + if (wcslen(wide) != length) { + FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character"); + Py_DECREF(unicode); + return 0; + } path->wide = wide; path->narrow = NULL; diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -3607,21 +3607,6 @@ int -_PyUnicode_HasNULChars(PyObject* str) -{ - Py_ssize_t pos; - - if (PyUnicode_READY(str) == -1) - return -1; - pos = findchar(PyUnicode_DATA(str), PyUnicode_KIND(str), - PyUnicode_GET_LENGTH(str), '\0', 1); - if (pos == -1) - return 0; - else - return 1; -} - -int PyUnicode_FSConverter(PyObject* arg, void* addr) { PyObject *output = NULL; diff --git a/README b/README --- a/README +++ b/README @@ -15,8 +15,6 @@ On Unix, Linux, BSD, OSX, and Cygwin: -New text - ./configure make make test diff --git a/Tools/msi/make_zip.py b/Tools/msi/make_zip.py --- a/Tools/msi/make_zip.py +++ b/Tools/msi/make_zip.py @@ -30,9 +30,16 @@ return False return True - if name in {'_ctypes_test.pyd', '_testbuffer.pyd', '_testcapi.pyd', '_testimportmultiple.pyd', 'xxlimited.pyd'}: - return False - return p.suffix.lower() not in {'.pyc', '.pyo'} + suffix = p.suffix.lower() + if suffix == '.pyd': + return name not in { + '_ctypes_test.pyd', + '_testbuffer.pyd', + '_testcapi.pyd', + '_testimportmultiple.pyd', + 'xxlimited.pyd', + } + return suffix not in {'.pyc', '.pyo'} def include_in_tools(p): if p.is_dir() and p.name.lower() in {'scripts', 'i18n', 'pynche', 'demo', 'parser'}: diff --git a/Tools/msi/testrelease.bat b/Tools/msi/testrelease.bat --- a/Tools/msi/testrelease.bat +++ b/Tools/msi/testrelease.bat @@ -1,4 +1,4 @@ - at setlocal + at setlocal enableextensions @echo off set D=%~dp0 @@ -51,6 +51,9 @@ @if not exist "%~1" exit /B 1 + at set EXE=%~1 + at if not "%EXE:embed=%"=="%EXE%" exit /B 0 + @set EXITCODE=0 @echo Installing %1 into %2 "%~1" /passive /log "%~2\install\log.txt" TargetDir="%~2\Python" Include_debug=1 Include_symbols=1 %~3 -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Apr 20 10:20:25 2015 From: python-checkins at python.org (larry.hastings) Date: Mon, 20 Apr 2015 08:20:25 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Regenerated_pydoc-topics_a?= =?utf-8?q?nd_fixed_bad/suspicious_doc_markup_for_Python_3=2E5=2E0a4=2E?= Message-ID: <20150420082012.27914.32680@psf.io> https://hg.python.org/cpython/rev/8a426f51351a changeset: 95734:8a426f51351a parent: 95719:7ae8fd62d743 user: Larry Hastings date: Sun Apr 19 13:50:12 2015 -0700 summary: Regenerated pydoc-topics and fixed bad/suspicious doc markup for Python 3.5.0a4. files: Doc/c-api/structures.rst | 2 +- Doc/library/importlib.rst | 2 +- Doc/library/py_compile.rst | 2 +- Doc/tools/susp-ignored.csv | 2 +- Doc/using/cmdline.rst | 2 +- Lib/pydoc_data/topics.py | 6 +++--- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Doc/c-api/structures.rst b/Doc/c-api/structures.rst --- a/Doc/c-api/structures.rst +++ b/Doc/c-api/structures.rst @@ -44,7 +44,7 @@ PyObject ob_base; - See documentation of :c:type::`PyObject` above. + See documentation of :c:type:`PyObject` above. .. c:macro:: PyObject_VAR_HEAD diff --git a/Doc/library/importlib.rst b/Doc/library/importlib.rst --- a/Doc/library/importlib.rst +++ b/Doc/library/importlib.rst @@ -1120,7 +1120,7 @@ file path. For example, if *path* is ``/foo/bar/__pycache__/baz.cpython-32.pyc`` the returned path would be ``/foo/bar/baz.py``. *path* need not exist, however if it does not conform - to :pep:`3147` or :pep`488` format, a ``ValueError`` is raised. If + to :pep:`3147` or :pep:`488` format, a ``ValueError`` is raised. If :attr:`sys.implementation.cache_tag` is not defined, :exc:`NotImplementedError` is raised. diff --git a/Doc/library/py_compile.rst b/Doc/library/py_compile.rst --- a/Doc/library/py_compile.rst +++ b/Doc/library/py_compile.rst @@ -30,7 +30,7 @@ Compile a source file to byte-code and write out the byte-code cache file. The source code is loaded from the file name *file*. The byte-code is - written to *cfile*, which defaults to the :pep:`3147`/:pep`488` path, ending + written to *cfile*, which defaults to the :pep:`3147`/:pep:`488` path, ending in ``.pyc``. For example, if *file* is ``/foo/bar/baz.py`` *cfile* will default to ``/foo/bar/__pycache__/baz.cpython-32.pyc`` for Python 3.2. If *dfile* is diff --git a/Doc/tools/susp-ignored.csv b/Doc/tools/susp-ignored.csv --- a/Doc/tools/susp-ignored.csv +++ b/Doc/tools/susp-ignored.csv @@ -275,7 +275,6 @@ whatsnew/3.2,,:prefix,zope-conf = ${custom:prefix}/etc/zope.conf whatsnew/changelog,,:gz,": TarFile opened with external fileobj and ""w:gz"" mode didn't" whatsnew/changelog,,::,": Use ""127.0.0.1"" or ""::1"" instead of ""localhost"" as much as" -library/stdtypes,3688,::,>>> m[::2].tolist() library/tarfile,149,:xz,'x:xz' library/xml.etree.elementtree,290,:sometag,prefix:sometag library/xml.etree.elementtree,301,:fictional,">> m[::2].tolist() diff --git a/Doc/using/cmdline.rst b/Doc/using/cmdline.rst --- a/Doc/using/cmdline.rst +++ b/Doc/using/cmdline.rst @@ -199,7 +199,7 @@ .. cmdoption:: -B - If given, Python won't try to write ``.pyc``` files on the + If given, Python won't try to write ``.pyc`` files on the import of source modules. See also :envvar:`PYTHONDONTWRITEBYTECODE`. 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 29 15:14:32 2015 +# Autogenerated by Sphinx on Sun Apr 19 13:44:03 2015 topics = {'assert': u'\nThe "assert" statement\n**********************\n\nAssert statements are a convenient way to insert debugging assertions\ninto a program:\n\n assert_stmt ::= "assert" expression ["," expression]\n\nThe simple form, "assert expression", is equivalent to\n\n if __debug__:\n if not expression: raise AssertionError\n\nThe extended form, "assert expression1, expression2", is equivalent to\n\n if __debug__:\n if not expression1: raise AssertionError(expression2)\n\nThese equivalences assume that "__debug__" and "AssertionError" refer\nto the built-in variables with those names. In the current\nimplementation, the built-in variable "__debug__" is "True" under\nnormal circumstances, "False" when optimization is requested (command\nline option -O). The current code generator emits no code for an\nassert statement when optimization is requested at compile time. Note\nthat it is unnecessary to include the source code for the expression\nthat failed in the error message; it will be displayed as part of the\nstack trace.\n\nAssignments to "__debug__" are illegal. The value for the built-in\nvariable is determined when the interpreter starts.\n', 'assignment': u'\nAssignment statements\n*********************\n\nAssignment statements are used to (re)bind names to values and to\nmodify attributes or items of mutable objects:\n\n assignment_stmt ::= (target_list "=")+ (expression_list | yield_expression)\n target_list ::= target ("," target)* [","]\n target ::= identifier\n | "(" target_list ")"\n | "[" target_list "]"\n | attributeref\n | subscription\n | slicing\n | "*" target\n\n(See section *Primaries* for the syntax definitions for\n*attributeref*, *subscription*, and *slicing*.)\n\nAn assignment statement evaluates the expression list (remember that\nthis can be a single expression or a comma-separated list, the latter\nyielding a tuple) and assigns the single resulting object to each of\nthe target lists, from left to right.\n\nAssignment is defined recursively depending on the form of the target\n(list). When a target is part of a mutable object (an attribute\nreference, subscription or slicing), the mutable object must\nultimately perform the assignment and decide about its validity, and\nmay raise an exception if the assignment is unacceptable. The rules\nobserved by various types and the exceptions raised are given with the\ndefinition of the object types (see section *The standard type\nhierarchy*).\n\nAssignment of an object to a target list, optionally enclosed in\nparentheses or square brackets, is recursively defined as follows.\n\n* If the target list is a single target: The object is assigned to\n that target.\n\n* If the target list is a comma-separated list of targets: The\n object must be an iterable with the same number of items as there\n are targets in the target list, and the items are assigned, from\n left to right, to the corresponding targets.\n\n * If the target list contains one target prefixed with an\n asterisk, called a "starred" target: The object must be a sequence\n with at least as many items as there are targets in the target\n list, minus one. The first items of the sequence are assigned,\n from left to right, to the targets before the starred target. The\n final items of the sequence are assigned to the targets after the\n starred target. A list of the remaining items in the sequence is\n then assigned to the starred target (the list can be empty).\n\n * Else: The object must be a sequence with the same number of\n items as there are targets in the target list, and the items are\n assigned, from left to right, to the corresponding targets.\n\nAssignment of an object to a single target is recursively defined as\nfollows.\n\n* If the target is an identifier (name):\n\n * If the name does not occur in a "global" or "nonlocal" statement\n in the current code block: the name is bound to the object in the\n current local namespace.\n\n * Otherwise: the name is bound to the object in the global\n namespace or the outer namespace determined by "nonlocal",\n respectively.\n\n The name is rebound if it was already bound. This may cause the\n reference count for the object previously bound to the name to reach\n zero, causing the object to be deallocated and its destructor (if it\n has one) to be called.\n\n* If the target is a target list enclosed in parentheses or in\n square brackets: The object must be an iterable with the same number\n of items as there are targets in the target list, and its items are\n assigned, from left to right, to the corresponding targets.\n\n* If the target is an attribute reference: The primary expression in\n the reference is evaluated. It should yield an object with\n assignable attributes; if this is not the case, "TypeError" is\n raised. That object is then asked to assign the assigned object to\n the given attribute; if it cannot perform the assignment, it raises\n an exception (usually but not necessarily "AttributeError").\n\n Note: If the object is a class instance and the attribute reference\n occurs on both sides of the assignment operator, the RHS expression,\n "a.x" can access either an instance attribute or (if no instance\n attribute exists) a class attribute. The LHS target "a.x" is always\n set as an instance attribute, creating it if necessary. Thus, the\n two occurrences of "a.x" do not necessarily refer to the same\n attribute: if the RHS expression refers to a class attribute, the\n LHS creates a new instance attribute as the target of the\n assignment:\n\n class Cls:\n x = 3 # class variable\n inst = Cls()\n inst.x = inst.x + 1 # writes inst.x as 4 leaving Cls.x as 3\n\n This description does not necessarily apply to descriptor\n attributes, such as properties created with "property()".\n\n* If the target is a subscription: The primary expression in the\n reference is evaluated. It should yield either a mutable sequence\n object (such as a list) or a mapping object (such as a dictionary).\n Next, the subscript expression is evaluated.\n\n If the primary is a mutable sequence object (such as a list), the\n subscript must yield an integer. If it is negative, the sequence\'s\n length is added to it. The resulting value must be a nonnegative\n integer less than the sequence\'s length, and the sequence is asked\n to assign the assigned object to its item with that index. If the\n index is out of range, "IndexError" is raised (assignment to a\n subscripted sequence cannot add new items to a list).\n\n If the primary is a mapping object (such as a dictionary), the\n subscript must have a type compatible with the mapping\'s key type,\n and the mapping is then asked to create a key/datum pair which maps\n the subscript to the assigned object. This can either replace an\n existing key/value pair with the same key value, or insert a new\n key/value pair (if no key with the same value existed).\n\n For user-defined objects, the "__setitem__()" method is called with\n appropriate arguments.\n\n* If the target is a slicing: The primary expression in the\n reference is evaluated. It should yield a mutable sequence object\n (such as a list). The assigned object should be a sequence object\n of the same type. Next, the lower and upper bound expressions are\n evaluated, insofar they are present; defaults are zero and the\n sequence\'s length. The bounds should evaluate to integers. If\n either bound is negative, the sequence\'s length is added to it. The\n resulting bounds are clipped to lie between zero and the sequence\'s\n length, inclusive. Finally, the sequence object is asked to replace\n the slice with the items of the assigned sequence. The length of\n the slice may be different from the length of the assigned sequence,\n thus changing the length of the target sequence, if the target\n sequence allows it.\n\n**CPython implementation detail:** In the current implementation, the\nsyntax for targets is taken to be the same as for expressions, and\ninvalid syntax is rejected during the code generation phase, causing\nless detailed error messages.\n\nAlthough the definition of assignment implies that overlaps between\nthe left-hand side and the right-hand side are \'simultanenous\' (for\nexample "a, b = b, a" swaps two variables), overlaps *within* the\ncollection of assigned-to variables occur left-to-right, sometimes\nresulting in confusion. For instance, the following program prints\n"[0, 2]":\n\n x = [0, 1]\n i = 0\n i, x[i] = 1, 2 # i is updated, then x[i] is updated\n print(x)\n\nSee also: **PEP 3132** - Extended Iterable Unpacking\n\n The specification for the "*target" feature.\n\n\nAugmented assignment statements\n===============================\n\nAugmented assignment is the combination, in a single statement, of a\nbinary operation and an assignment statement:\n\n augmented_assignment_stmt ::= augtarget augop (expression_list | yield_expression)\n augtarget ::= identifier | attributeref | subscription | slicing\n augop ::= "+=" | "-=" | "*=" | "@=" | "/=" | "//=" | "%=" | "**="\n | ">>=" | "<<=" | "&=" | "^=" | "|="\n\n(See section *Primaries* for the syntax definitions of the last three\nsymbols.)\n\nAn augmented assignment evaluates the target (which, unlike normal\nassignment statements, cannot be an unpacking) and the expression\nlist, performs the binary operation specific to the type of assignment\non the two operands, and assigns the result to the original target.\nThe target is only evaluated once.\n\nAn augmented assignment expression like "x += 1" can be rewritten as\n"x = x + 1" to achieve a similar, but not exactly equal effect. In the\naugmented version, "x" is only evaluated once. Also, when possible,\nthe actual operation is performed *in-place*, meaning that rather than\ncreating a new object and assigning that to the target, the old object\nis modified instead.\n\nUnlike normal assignments, augmented assignments evaluate the left-\nhand side *before* evaluating the right-hand side. For example, "a[i]\n+= f(x)" first looks-up "a[i]", then it evaluates "f(x)" and performs\nthe addition, and lastly, it writes the result back to "a[i]".\n\nWith the exception of assigning to tuples and multiple targets in a\nsingle statement, the assignment done by augmented assignment\nstatements is handled the same way as normal assignments. Similarly,\nwith the exception of the possible *in-place* behavior, the binary\noperation performed by augmented assignment is the same as the normal\nbinary operations.\n\nFor targets which are attribute references, the same *caveat about\nclass and instance attributes* applies as for regular assignments.\n', 'atom-identifiers': u'\nIdentifiers (Names)\n*******************\n\nAn identifier occurring as an atom is a name. See section\n*Identifiers and keywords* for lexical definition and section *Naming\nand binding* for documentation of naming and binding.\n\nWhen the name is bound to an object, evaluation of the atom yields\nthat object. When a name is not bound, an attempt to evaluate it\nraises a "NameError" exception.\n\n**Private name mangling:** When an identifier that textually occurs in\na class definition begins with two or more underscore characters and\ndoes not end in two or more underscores, it is considered a *private\nname* of that class. Private names are transformed to a longer form\nbefore code is generated for them. The transformation inserts the\nclass name, with leading underscores removed and a single underscore\ninserted, in front of the name. For example, the identifier "__spam"\noccurring in a class named "Ham" will be transformed to "_Ham__spam".\nThis transformation is independent of the syntactical context in which\nthe identifier is used. If the transformed name is extremely long\n(longer than 255 characters), implementation defined truncation may\nhappen. If the class name consists only of underscores, no\ntransformation is done.\n', @@ -60,8 +60,8 @@ 'shifting': u'\nShifting operations\n*******************\n\nThe shifting operations have lower priority than the arithmetic\noperations:\n\n shift_expr ::= a_expr | shift_expr ( "<<" | ">>" ) a_expr\n\nThese operators accept integers as arguments. They shift the first\nargument to the left or right by the number of bits given by the\nsecond argument.\n\nA right shift by *n* bits is defined as floor division by "pow(2,n)".\nA left shift by *n* bits is defined as multiplication with "pow(2,n)".\n\nNote: In the current implementation, the right-hand operand is\n required to be at most "sys.maxsize". If the right-hand operand is\n larger than "sys.maxsize" an "OverflowError" exception is raised.\n', 'slicings': u'\nSlicings\n********\n\nA slicing selects a range of items in a sequence object (e.g., a\nstring, tuple or list). Slicings may be used as expressions or as\ntargets in assignment or "del" statements. The syntax for a slicing:\n\n slicing ::= primary "[" slice_list "]"\n slice_list ::= slice_item ("," slice_item)* [","]\n slice_item ::= expression | proper_slice\n proper_slice ::= [lower_bound] ":" [upper_bound] [ ":" [stride] ]\n lower_bound ::= expression\n upper_bound ::= expression\n stride ::= expression\n\nThere is ambiguity in the formal syntax here: anything that looks like\nan expression list also looks like a slice list, so any subscription\ncan be interpreted as a slicing. Rather than further complicating the\nsyntax, this is disambiguated by defining that in this case the\ninterpretation as a subscription takes priority over the\ninterpretation as a slicing (this is the case if the slice list\ncontains no proper slice).\n\nThe semantics for a slicing are as follows. The primary is indexed\n(using the same "__getitem__()" method as normal subscription) with a\nkey that is constructed from the slice list, as follows. If the slice\nlist contains at least one comma, the key is a tuple containing the\nconversion of the slice items; otherwise, the conversion of the lone\nslice item is the key. The conversion of a slice item that is an\nexpression is that expression. The conversion of a proper slice is a\nslice object (see section *The standard type hierarchy*) whose\n"start", "stop" and "step" attributes are the values of the\nexpressions given as lower bound, upper bound and stride,\nrespectively, substituting "None" for missing expressions.\n', 'specialattrs': u'\nSpecial Attributes\n******************\n\nThe implementation adds a few special read-only attributes to several\nobject types, where they are relevant. Some of these are not reported\nby the "dir()" built-in function.\n\nobject.__dict__\n\n A dictionary or other mapping object used to store an object\'s\n (writable) attributes.\n\ninstance.__class__\n\n The class to which a class instance belongs.\n\nclass.__bases__\n\n The tuple of base classes of a class object.\n\nclass.__name__\n\n The name of the class or type.\n\nclass.__qualname__\n\n The *qualified name* of the class or type.\n\n New in version 3.3.\n\nclass.__mro__\n\n This attribute is a tuple of classes that are considered when\n looking for base classes during method resolution.\n\nclass.mro()\n\n This method can be overridden by a metaclass to customize the\n method resolution order for its instances. It is called at class\n instantiation, and its result is stored in "__mro__".\n\nclass.__subclasses__()\n\n Each class keeps a list of weak references to its immediate\n subclasses. This method returns a list of all those references\n still alive. Example:\n\n >>> int.__subclasses__()\n []\n\n-[ Footnotes ]-\n\n[1] Additional information on these special methods may be found\n in the Python Reference Manual (*Basic customization*).\n\n[2] As a consequence, the list "[1, 2]" is considered equal to\n "[1.0, 2.0]", and similarly for tuples.\n\n[3] They must have since the parser can\'t tell the type of the\n operands.\n\n[4] Cased characters are those with general category property\n being one of "Lu" (Letter, uppercase), "Ll" (Letter, lowercase),\n or "Lt" (Letter, titlecase).\n\n[5] To format only a tuple you should therefore provide a\n singleton tuple whose only element is the tuple to be formatted.\n', - 'specialnames': u'\nSpecial method names\n********************\n\nA class can implement certain operations that are invoked by special\nsyntax (such as arithmetic operations or subscripting and slicing) by\ndefining methods with special names. This is Python\'s approach to\n*operator overloading*, allowing classes to define their own behavior\nwith respect to language operators. For instance, if a class defines\na method named "__getitem__()", and "x" is an instance of this class,\nthen "x[i]" is roughly equivalent to "type(x).__getitem__(x, i)".\nExcept where mentioned, attempts to execute an operation raise an\nexception when no appropriate method is defined (typically\n"AttributeError" or "TypeError").\n\nWhen implementing a class that emulates any built-in type, it is\nimportant that the emulation only be implemented to the degree that it\nmakes sense for the object being modelled. For example, some\nsequences may work well with retrieval of individual elements, but\nextracting a slice may not make sense. (One example of this is the\n"NodeList" interface in the W3C\'s Document Object Model.)\n\n\nBasic customization\n===================\n\nobject.__new__(cls[, ...])\n\n Called to create a new instance of class *cls*. "__new__()" is a\n static method (special-cased so you need not declare it as such)\n that takes the class of which an instance was requested as its\n first argument. The remaining arguments are those passed to the\n object constructor expression (the call to the class). The return\n value of "__new__()" should be the new object instance (usually an\n instance of *cls*).\n\n Typical implementations create a new instance of the class by\n invoking the superclass\'s "__new__()" method using\n "super(currentclass, cls).__new__(cls[, ...])" with appropriate\n arguments and then modifying the newly-created instance as\n necessary before returning it.\n\n If "__new__()" returns an instance of *cls*, then the new\n instance\'s "__init__()" method will be invoked like\n "__init__(self[, ...])", where *self* is the new instance and the\n remaining arguments are the same as were passed to "__new__()".\n\n If "__new__()" does not return an instance of *cls*, then the new\n instance\'s "__init__()" method will not be invoked.\n\n "__new__()" is intended mainly to allow subclasses of immutable\n types (like int, str, or tuple) to customize instance creation. It\n is also commonly overridden in custom metaclasses in order to\n customize class creation.\n\nobject.__init__(self[, ...])\n\n Called after the instance has been created (by "__new__()"), but\n before it is returned to the caller. The arguments are those\n passed to the class constructor expression. If a base class has an\n "__init__()" method, the derived class\'s "__init__()" method, if\n any, must explicitly call it to ensure proper initialization of the\n base class part of the instance; for example:\n "BaseClass.__init__(self, [args...])".\n\n Because "__new__()" and "__init__()" work together in constructing\n objects ("__new__()" to create it, and "__init__()" to customise\n it), no non-"None" value may be returned by "__init__()"; doing so\n will cause a "TypeError" to be raised at runtime.\n\nobject.__del__(self)\n\n Called when the instance is about to be destroyed. This is also\n called a destructor. If a base class has a "__del__()" method, the\n derived class\'s "__del__()" method, if any, must explicitly call it\n to ensure proper deletion of the base class part of the instance.\n Note that it is possible (though not recommended!) for the\n "__del__()" method to postpone destruction of the instance by\n creating a new reference to it. It may then be called at a later\n time when this new reference is deleted. It is not guaranteed that\n "__del__()" methods are called for objects that still exist when\n the interpreter exits.\n\n Note: "del x" doesn\'t directly call "x.__del__()" --- the former\n decrements the reference count for "x" by one, and the latter is\n only called when "x"\'s reference count reaches zero. Some common\n situations that may prevent the reference count of an object from\n going to zero include: circular references between objects (e.g.,\n a doubly-linked list or a tree data structure with parent and\n child pointers); a reference to the object on the stack frame of\n a function that caught an exception (the traceback stored in\n "sys.exc_info()[2]" keeps the stack frame alive); or a reference\n to the object on the stack frame that raised an unhandled\n exception in interactive mode (the traceback stored in\n "sys.last_traceback" keeps the stack frame alive). The first\n situation can only be remedied by explicitly breaking the cycles;\n the second can be resolved by freeing the reference to the\n traceback object when it is no longer useful, and the third can\n be resolved by storing "None" in "sys.last_traceback". Circular\n references which are garbage are detected and cleaned up when the\n cyclic garbage collector is enabled (it\'s on by default). Refer\n to the documentation for the "gc" module for more information\n about this topic.\n\n Warning: Due to the precarious circumstances under which\n "__del__()" methods are invoked, exceptions that occur during\n their execution are ignored, and a warning is printed to\n "sys.stderr" instead. Also, when "__del__()" is invoked in\n response to a module being deleted (e.g., when execution of the\n program is done), other globals referenced by the "__del__()"\n method may already have been deleted or in the process of being\n torn down (e.g. the import machinery shutting down). For this\n reason, "__del__()" methods should do the absolute minimum needed\n to maintain external invariants. Starting with version 1.5,\n Python guarantees that globals whose name begins with a single\n underscore are deleted from their module before other globals are\n deleted; if no other references to such globals exist, this may\n help in assuring that imported modules are still available at the\n time when the "__del__()" method is called.\n\nobject.__repr__(self)\n\n Called by the "repr()" built-in function to compute the "official"\n string representation of an object. If at all possible, this\n should look like a valid Python expression that could be used to\n recreate an object with the same value (given an appropriate\n environment). If this is not possible, a string of the form\n "<...some useful description...>" should be returned. The return\n value must be a string object. If a class defines "__repr__()" but\n not "__str__()", then "__repr__()" is also used when an "informal"\n string representation of instances of that class is required.\n\n This is typically used for debugging, so it is important that the\n representation is information-rich and unambiguous.\n\nobject.__str__(self)\n\n Called by "str(object)" and the built-in functions "format()" and\n "print()" to compute the "informal" or nicely printable string\n representation of an object. The return value must be a *string*\n object.\n\n This method differs from "object.__repr__()" in that there is no\n expectation that "__str__()" return a valid Python expression: a\n more convenient or concise representation can be used.\n\n The default implementation defined by the built-in type "object"\n calls "object.__repr__()".\n\nobject.__bytes__(self)\n\n Called by "bytes()" to compute a byte-string representation of an\n object. This should return a "bytes" object.\n\nobject.__format__(self, format_spec)\n\n Called by the "format()" built-in function (and by extension, the\n "str.format()" method of class "str") to produce a "formatted"\n string representation of an object. The "format_spec" argument is a\n string that contains a description of the formatting options\n desired. The interpretation of the "format_spec" argument is up to\n the type implementing "__format__()", however most classes will\n either delegate formatting to one of the built-in types, or use a\n similar formatting option syntax.\n\n See *Format Specification Mini-Language* for a description of the\n standard formatting syntax.\n\n The return value must be a string object.\n\n Changed in version 3.4: The __format__ method of "object" itself\n raises a "TypeError" if passed any non-empty string.\n\nobject.__lt__(self, other)\nobject.__le__(self, other)\nobject.__eq__(self, other)\nobject.__ne__(self, other)\nobject.__gt__(self, other)\nobject.__ge__(self, other)\n\n These are the so-called "rich comparison" methods. The\n correspondence between operator symbols and method names is as\n follows: "xy" calls\n "x.__gt__(y)", and "x>=y" calls "x.__ge__(y)".\n\n A rich comparison method may return the singleton "NotImplemented"\n if it does not implement the operation for a given pair of\n arguments. By convention, "False" and "True" are returned for a\n successful comparison. However, these methods can return any value,\n so if the comparison operator is used in a Boolean context (e.g.,\n in the condition of an "if" statement), Python will call "bool()"\n on the value to determine if the result is true or false.\n\n There are no implied relationships among the comparison operators.\n The truth of "x==y" does not imply that "x!=y" is false.\n Accordingly, when defining "__eq__()", one should also define\n "__ne__()" so that the operators will behave as expected. See the\n paragraph on "__hash__()" for some important notes on creating\n *hashable* objects which support custom comparison operations and\n are usable as dictionary keys.\n\n There are no swapped-argument versions of these methods (to be used\n when the left argument does not support the operation but the right\n argument does); rather, "__lt__()" and "__gt__()" are each other\'s\n reflection, "__le__()" and "__ge__()" are each other\'s reflection,\n and "__eq__()" and "__ne__()" are their own reflection.\n\n Arguments to rich comparison methods are never coerced.\n\n To automatically generate ordering operations from a single root\n operation, see "functools.total_ordering()".\n\nobject.__hash__(self)\n\n Called by built-in function "hash()" and for operations on members\n of hashed collections including "set", "frozenset", and "dict".\n "__hash__()" should return an integer. The only required property\n is that objects which compare equal have the same hash value; it is\n advised to somehow mix together (e.g. using exclusive or) the hash\n values for the components of the object that also play a part in\n comparison of objects.\n\n Note: "hash()" truncates the value returned from an object\'s\n custom "__hash__()" method to the size of a "Py_ssize_t". This\n is typically 8 bytes on 64-bit builds and 4 bytes on 32-bit\n builds. If an object\'s "__hash__()" must interoperate on builds\n of different bit sizes, be sure to check the width on all\n supported builds. An easy way to do this is with "python -c\n "import sys; print(sys.hash_info.width)""\n\n If a class does not define an "__eq__()" method it should not\n define a "__hash__()" operation either; if it defines "__eq__()"\n but not "__hash__()", its instances will not be usable as items in\n hashable collections. If a class defines mutable objects and\n implements an "__eq__()" method, it should not implement\n "__hash__()", since the implementation of hashable collections\n requires that a key\'s hash value is immutable (if the object\'s hash\n value changes, it will be in the wrong hash bucket).\n\n User-defined classes have "__eq__()" and "__hash__()" methods by\n default; with them, all objects compare unequal (except with\n themselves) and "x.__hash__()" returns an appropriate value such\n that "x == y" implies both that "x is y" and "hash(x) == hash(y)".\n\n A class that overrides "__eq__()" and does not define "__hash__()"\n will have its "__hash__()" implicitly set to "None". When the\n "__hash__()" method of a class is "None", instances of the class\n will raise an appropriate "TypeError" when a program attempts to\n retrieve their hash value, and will also be correctly identified as\n unhashable when checking "isinstance(obj, collections.Hashable").\n\n If a class that overrides "__eq__()" needs to retain the\n implementation of "__hash__()" from a parent class, the interpreter\n must be told this explicitly by setting "__hash__ =\n .__hash__".\n\n If a class that does not override "__eq__()" wishes to suppress\n hash support, it should include "__hash__ = None" in the class\n definition. A class which defines its own "__hash__()" that\n explicitly raises a "TypeError" would be incorrectly identified as\n hashable by an "isinstance(obj, collections.Hashable)" call.\n\n Note: By default, the "__hash__()" values of str, bytes and\n datetime objects are "salted" with an unpredictable random value.\n Although they remain constant within an individual Python\n process, they are not predictable between repeated invocations of\n Python.This is intended to provide protection against a denial-\n of-service caused by carefully-chosen inputs that exploit the\n worst case performance of a dict insertion, O(n^2) complexity.\n See http://www.ocert.org/advisories/ocert-2011-003.html for\n details.Changing hash values affects the iteration order of\n dicts, sets and other mappings. Python has never made guarantees\n about this ordering (and it typically varies between 32-bit and\n 64-bit builds).See also "PYTHONHASHSEED".\n\n Changed in version 3.3: Hash randomization is enabled by default.\n\nobject.__bool__(self)\n\n Called to implement truth value testing and the built-in operation\n "bool()"; should return "False" or "True". When this method is not\n defined, "__len__()" is called, if it is defined, and the object is\n considered true if its result is nonzero. If a class defines\n neither "__len__()" nor "__bool__()", all its instances are\n considered true.\n\n\nCustomizing attribute access\n============================\n\nThe following methods can be defined to customize the meaning of\nattribute access (use of, assignment to, or deletion of "x.name") for\nclass instances.\n\nobject.__getattr__(self, name)\n\n Called when an attribute lookup has not found the attribute in the\n usual places (i.e. it is not an instance attribute nor is it found\n in the class tree for "self"). "name" is the attribute name. This\n method should return the (computed) attribute value or raise an\n "AttributeError" exception.\n\n Note that if the attribute is found through the normal mechanism,\n "__getattr__()" is not called. (This is an intentional asymmetry\n between "__getattr__()" and "__setattr__()".) This is done both for\n efficiency reasons and because otherwise "__getattr__()" would have\n no way to access other attributes of the instance. Note that at\n least for instance variables, you can fake total control by not\n inserting any values in the instance attribute dictionary (but\n instead inserting them in another object). See the\n "__getattribute__()" method below for a way to actually get total\n control over attribute access.\n\nobject.__getattribute__(self, name)\n\n Called unconditionally to implement attribute accesses for\n instances of the class. If the class also defines "__getattr__()",\n the latter will not be called unless "__getattribute__()" either\n calls it explicitly or raises an "AttributeError". This method\n should return the (computed) attribute value or raise an\n "AttributeError" exception. In order to avoid infinite recursion in\n this method, its implementation should always call the base class\n method with the same name to access any attributes it needs, for\n example, "object.__getattribute__(self, name)".\n\n Note: This method may still be bypassed when looking up special\n methods as the result of implicit invocation via language syntax\n or built-in functions. See *Special method lookup*.\n\nobject.__setattr__(self, name, value)\n\n Called when an attribute assignment is attempted. This is called\n instead of the normal mechanism (i.e. store the value in the\n instance dictionary). *name* is the attribute name, *value* is the\n value to be assigned to it.\n\n If "__setattr__()" wants to assign to an instance attribute, it\n should call the base class method with the same name, for example,\n "object.__setattr__(self, name, value)".\n\nobject.__delattr__(self, name)\n\n Like "__setattr__()" but for attribute deletion instead of\n assignment. This should only be implemented if "del obj.name" is\n meaningful for the object.\n\nobject.__dir__(self)\n\n Called when "dir()" is called on the object. A sequence must be\n returned. "dir()" converts the returned sequence to a list and\n sorts it.\n\n\nImplementing Descriptors\n------------------------\n\nThe following methods only apply when an instance of the class\ncontaining the method (a so-called *descriptor* class) appears in an\n*owner* class (the descriptor must be in either the owner\'s class\ndictionary or in the class dictionary for one of its parents). In the\nexamples below, "the attribute" refers to the attribute whose name is\nthe key of the property in the owner class\' "__dict__".\n\nobject.__get__(self, instance, owner)\n\n Called to get the attribute of the owner class (class attribute\n access) or of an instance of that class (instance attribute\n access). *owner* is always the owner class, while *instance* is the\n instance that the attribute was accessed through, or "None" when\n the attribute is accessed through the *owner*. This method should\n return the (computed) attribute value or raise an "AttributeError"\n exception.\n\nobject.__set__(self, instance, value)\n\n Called to set the attribute on an instance *instance* of the owner\n class to a new value, *value*.\n\nobject.__delete__(self, instance)\n\n Called to delete the attribute on an instance *instance* of the\n owner class.\n\nThe attribute "__objclass__" is interpreted by the "inspect" module as\nspecifying the class where this object was defined (setting this\nappropriately can assist in runtime introspection of dynamic class\nattributes). For callables, it may indicate that an instance of the\ngiven type (or a subclass) is expected or required as the first\npositional argument (for example, CPython sets this attribute for\nunbound methods that are implemented in C).\n\n\nInvoking Descriptors\n--------------------\n\nIn general, a descriptor is an object attribute with "binding\nbehavior", one whose attribute access has been overridden by methods\nin the descriptor protocol: "__get__()", "__set__()", and\n"__delete__()". If any of those methods are defined for an object, it\nis said to be a descriptor.\n\nThe default behavior for attribute access is to get, set, or delete\nthe attribute from an object\'s dictionary. For instance, "a.x" has a\nlookup chain starting with "a.__dict__[\'x\']", then\n"type(a).__dict__[\'x\']", and continuing through the base classes of\n"type(a)" excluding metaclasses.\n\nHowever, if the looked-up value is an object defining one of the\ndescriptor methods, then Python may override the default behavior and\ninvoke the descriptor method instead. Where this occurs in the\nprecedence chain depends on which descriptor methods were defined and\nhow they were called.\n\nThe starting point for descriptor invocation is a binding, "a.x". How\nthe arguments are assembled depends on "a":\n\nDirect Call\n The simplest and least common call is when user code directly\n invokes a descriptor method: "x.__get__(a)".\n\nInstance Binding\n If binding to an object instance, "a.x" is transformed into the\n call: "type(a).__dict__[\'x\'].__get__(a, type(a))".\n\nClass Binding\n If binding to a class, "A.x" is transformed into the call:\n "A.__dict__[\'x\'].__get__(None, A)".\n\nSuper Binding\n If "a" is an instance of "super", then the binding "super(B,\n obj).m()" searches "obj.__class__.__mro__" for the base class "A"\n immediately preceding "B" and then invokes the descriptor with the\n call: "A.__dict__[\'m\'].__get__(obj, obj.__class__)".\n\nFor instance bindings, the precedence of descriptor invocation depends\non the which descriptor methods are defined. A descriptor can define\nany combination of "__get__()", "__set__()" and "__delete__()". If it\ndoes not define "__get__()", then accessing the attribute will return\nthe descriptor object itself unless there is a value in the object\'s\ninstance dictionary. If the descriptor defines "__set__()" and/or\n"__delete__()", it is a data descriptor; if it defines neither, it is\na non-data descriptor. Normally, data descriptors define both\n"__get__()" and "__set__()", while non-data descriptors have just the\n"__get__()" method. Data descriptors with "__set__()" and "__get__()"\ndefined always override a redefinition in an instance dictionary. In\ncontrast, non-data descriptors can be overridden by instances.\n\nPython methods (including "staticmethod()" and "classmethod()") are\nimplemented as non-data descriptors. Accordingly, instances can\nredefine and override methods. This allows individual instances to\nacquire behaviors that differ from other instances of the same class.\n\nThe "property()" function is implemented as a data descriptor.\nAccordingly, instances cannot override the behavior of a property.\n\n\n__slots__\n---------\n\nBy default, instances of classes have a dictionary for attribute\nstorage. This wastes space for objects having very few instance\nvariables. The space consumption can become acute when creating large\nnumbers of instances.\n\nThe default can be overridden by defining *__slots__* in a class\ndefinition. The *__slots__* declaration takes a sequence of instance\nvariables and reserves just enough space in each instance to hold a\nvalue for each variable. Space is saved because *__dict__* is not\ncreated for each instance.\n\nobject.__slots__\n\n This class variable can be assigned a string, iterable, or sequence\n of strings with variable names used by instances. *__slots__*\n reserves space for the declared variables and prevents the\n automatic creation of *__dict__* and *__weakref__* for each\n instance.\n\n\nNotes on using *__slots__*\n~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n* When inheriting from a class without *__slots__*, the *__dict__*\n attribute of that class will always be accessible, so a *__slots__*\n definition in the subclass is meaningless.\n\n* Without a *__dict__* variable, instances cannot be assigned new\n variables not listed in the *__slots__* definition. Attempts to\n assign to an unlisted variable name raises "AttributeError". If\n dynamic assignment of new variables is desired, then add\n "\'__dict__\'" to the sequence of strings in the *__slots__*\n declaration.\n\n* Without a *__weakref__* variable for each instance, classes\n defining *__slots__* do not support weak references to its\n instances. If weak reference support is needed, then add\n "\'__weakref__\'" to the sequence of strings in the *__slots__*\n declaration.\n\n* *__slots__* are implemented at the class level by creating\n descriptors (*Implementing Descriptors*) for each variable name. As\n a result, class attributes cannot be used to set default values for\n instance variables defined by *__slots__*; otherwise, the class\n attribute would overwrite the descriptor assignment.\n\n* The action of a *__slots__* declaration is limited to the class\n where it is defined. As a result, subclasses will have a *__dict__*\n unless they also define *__slots__* (which must only contain names\n of any *additional* slots).\n\n* If a class defines a slot also defined in a base class, the\n instance variable defined by the base class slot is inaccessible\n (except by retrieving its descriptor directly from the base class).\n This renders the meaning of the program undefined. In the future, a\n check may be added to prevent this.\n\n* Nonempty *__slots__* does not work for classes derived from\n "variable-length" built-in types such as "int", "bytes" and "tuple".\n\n* Any non-string iterable may be assigned to *__slots__*. Mappings\n may also be used; however, in the future, special meaning may be\n assigned to the values corresponding to each key.\n\n* *__class__* assignment works only if both classes have the same\n *__slots__*.\n\n\nCustomizing class creation\n==========================\n\nBy default, classes are constructed using "type()". The class body is\nexecuted in a new namespace and the class name is bound locally to the\nresult of "type(name, bases, namespace)".\n\nThe class creation process can be customised by passing the\n"metaclass" keyword argument in the class definition line, or by\ninheriting from an existing class that included such an argument. In\nthe following example, both "MyClass" and "MySubclass" are instances\nof "Meta":\n\n class Meta(type):\n pass\n\n class MyClass(metaclass=Meta):\n pass\n\n class MySubclass(MyClass):\n pass\n\nAny other keyword arguments that are specified in the class definition\nare passed through to all metaclass operations described below.\n\nWhen a class definition is executed, the following steps occur:\n\n* the appropriate metaclass is determined\n\n* the class namespace is prepared\n\n* the class body is executed\n\n* the class object is created\n\n\nDetermining the appropriate metaclass\n-------------------------------------\n\nThe appropriate metaclass for a class definition is determined as\nfollows:\n\n* if no bases and no explicit metaclass are given, then "type()" is\n used\n\n* if an explicit metaclass is given and it is *not* an instance of\n "type()", then it is used directly as the metaclass\n\n* if an instance of "type()" is given as the explicit metaclass, or\n bases are defined, then the most derived metaclass is used\n\nThe most derived metaclass is selected from the explicitly specified\nmetaclass (if any) and the metaclasses (i.e. "type(cls)") of all\nspecified base classes. The most derived metaclass is one which is a\nsubtype of *all* of these candidate metaclasses. If none of the\ncandidate metaclasses meets that criterion, then the class definition\nwill fail with "TypeError".\n\n\nPreparing the class namespace\n-----------------------------\n\nOnce the appropriate metaclass has been identified, then the class\nnamespace is prepared. If the metaclass has a "__prepare__" attribute,\nit is called as "namespace = metaclass.__prepare__(name, bases,\n**kwds)" (where the additional keyword arguments, if any, come from\nthe class definition).\n\nIf the metaclass has no "__prepare__" attribute, then the class\nnamespace is initialised as an empty "dict()" instance.\n\nSee also: **PEP 3115** - Metaclasses in Python 3000\n\n Introduced the "__prepare__" namespace hook\n\n\nExecuting the class body\n------------------------\n\nThe class body is executed (approximately) as "exec(body, globals(),\nnamespace)". The key difference from a normal call to "exec()" is that\nlexical scoping allows the class body (including any methods) to\nreference names from the current and outer scopes when the class\ndefinition occurs inside a function.\n\nHowever, even when the class definition occurs inside the function,\nmethods defined inside the class still cannot see names defined at the\nclass scope. Class variables must be accessed through the first\nparameter of instance or class methods, and cannot be accessed at all\nfrom static methods.\n\n\nCreating the class object\n-------------------------\n\nOnce the class namespace has been populated by executing the class\nbody, the class object is created by calling "metaclass(name, bases,\nnamespace, **kwds)" (the additional keywords passed here are the same\nas those passed to "__prepare__").\n\nThis class object is the one that will be referenced by the zero-\nargument form of "super()". "__class__" is an implicit closure\nreference created by the compiler if any methods in a class body refer\nto either "__class__" or "super". This allows the zero argument form\nof "super()" to correctly identify the class being defined based on\nlexical scoping, while the class or instance that was used to make the\ncurrent call is identified based on the first argument passed to the\nmethod.\n\nAfter the class object is created, it is passed to the class\ndecorators included in the class definition (if any) and the resulting\nobject is bound in the local namespace as the defined class.\n\nSee also: **PEP 3135** - New super\n\n Describes the implicit "__class__" closure reference\n\n\nMetaclass example\n-----------------\n\nThe potential uses for metaclasses are boundless. Some ideas that have\nbeen explored include logging, interface checking, automatic\ndelegation, automatic property creation, proxies, frameworks, and\nautomatic resource locking/synchronization.\n\nHere is an example of a metaclass that uses an\n"collections.OrderedDict" to remember the order that class variables\nare defined:\n\n class OrderedClass(type):\n\n @classmethod\n def __prepare__(metacls, name, bases, **kwds):\n return collections.OrderedDict()\n\n def __new__(cls, name, bases, namespace, **kwds):\n result = type.__new__(cls, name, bases, dict(namespace))\n result.members = tuple(namespace)\n return result\n\n class A(metaclass=OrderedClass):\n def one(self): pass\n def two(self): pass\n def three(self): pass\n def four(self): pass\n\n >>> A.members\n (\'__module__\', \'one\', \'two\', \'three\', \'four\')\n\nWhen the class definition for *A* gets executed, the process begins\nwith calling the metaclass\'s "__prepare__()" method which returns an\nempty "collections.OrderedDict". That mapping records the methods and\nattributes of *A* as they are defined within the body of the class\nstatement. Once those definitions are executed, the ordered dictionary\nis fully populated and the metaclass\'s "__new__()" method gets\ninvoked. That method builds the new type and it saves the ordered\ndictionary keys in an attribute called "members".\n\n\nCustomizing instance and subclass checks\n========================================\n\nThe following methods are used to override the default behavior of the\n"isinstance()" and "issubclass()" built-in functions.\n\nIn particular, the metaclass "abc.ABCMeta" implements these methods in\norder to allow the addition of Abstract Base Classes (ABCs) as\n"virtual base classes" to any class or type (including built-in\ntypes), including other ABCs.\n\nclass.__instancecheck__(self, instance)\n\n Return true if *instance* should be considered a (direct or\n indirect) instance of *class*. If defined, called to implement\n "isinstance(instance, class)".\n\nclass.__subclasscheck__(self, subclass)\n\n Return true if *subclass* should be considered a (direct or\n indirect) subclass of *class*. If defined, called to implement\n "issubclass(subclass, class)".\n\nNote that these methods are looked up on the type (metaclass) of a\nclass. They cannot be defined as class methods in the actual class.\nThis is consistent with the lookup of special methods that are called\non instances, only in this case the instance is itself a class.\n\nSee also: **PEP 3119** - Introducing Abstract Base Classes\n\n Includes the specification for customizing "isinstance()" and\n "issubclass()" behavior through "__instancecheck__()" and\n "__subclasscheck__()", with motivation for this functionality in\n the context of adding Abstract Base Classes (see the "abc"\n module) to the language.\n\n\nEmulating callable objects\n==========================\n\nobject.__call__(self[, args...])\n\n Called when the instance is "called" as a function; if this method\n is defined, "x(arg1, arg2, ...)" is a shorthand for\n "x.__call__(arg1, arg2, ...)".\n\n\nEmulating container types\n=========================\n\nThe following methods can be defined to implement container objects.\nContainers usually are sequences (such as lists or tuples) or mappings\n(like dictionaries), but can represent other containers as well. The\nfirst set of methods is used either to emulate a sequence or to\nemulate a mapping; the difference is that for a sequence, the\nallowable keys should be the integers *k* for which "0 <= k < N" where\n*N* is the length of the sequence, or slice objects, which define a\nrange of items. It is also recommended that mappings provide the\nmethods "keys()", "values()", "items()", "get()", "clear()",\n"setdefault()", "pop()", "popitem()", "copy()", and "update()"\nbehaving similar to those for Python\'s standard dictionary objects.\nThe "collections" module provides a "MutableMapping" abstract base\nclass to help create those methods from a base set of "__getitem__()",\n"__setitem__()", "__delitem__()", and "keys()". Mutable sequences\nshould provide methods "append()", "count()", "index()", "extend()",\n"insert()", "pop()", "remove()", "reverse()" and "sort()", like Python\nstandard list objects. Finally, sequence types should implement\naddition (meaning concatenation) and multiplication (meaning\nrepetition) by defining the methods "__add__()", "__radd__()",\n"__iadd__()", "__mul__()", "__rmul__()" and "__imul__()" described\nbelow; they should not define other numerical operators. It is\nrecommended that both mappings and sequences implement the\n"__contains__()" method to allow efficient use of the "in" operator;\nfor mappings, "in" should search the mapping\'s keys; for sequences, it\nshould search through the values. It is further recommended that both\nmappings and sequences implement the "__iter__()" method to allow\nefficient iteration through the container; for mappings, "__iter__()"\nshould be the same as "keys()"; for sequences, it should iterate\nthrough the values.\n\nobject.__len__(self)\n\n Called to implement the built-in function "len()". Should return\n the length of the object, an integer ">=" 0. Also, an object that\n doesn\'t define a "__bool__()" method and whose "__len__()" method\n returns zero is considered to be false in a Boolean context.\n\nobject.__length_hint__(self)\n\n Called to implement "operator.length_hint()". Should return an\n estimated length for the object (which may be greater or less than\n the actual length). The length must be an integer ">=" 0. This\n method is purely an optimization and is never required for\n correctness.\n\n New in version 3.4.\n\nNote: Slicing is done exclusively with the following three methods.\n A call like\n\n a[1:2] = b\n\n is translated to\n\n a[slice(1, 2, None)] = b\n\n and so forth. Missing slice items are always filled in with "None".\n\nobject.__getitem__(self, key)\n\n Called to implement evaluation of "self[key]". For sequence types,\n the accepted keys should be integers and slice objects. Note that\n the special interpretation of negative indexes (if the class wishes\n to emulate a sequence type) is up to the "__getitem__()" method. If\n *key* is of an inappropriate type, "TypeError" may be raised; if of\n a value outside the set of indexes for the sequence (after any\n special interpretation of negative values), "IndexError" should be\n raised. For mapping types, if *key* is missing (not in the\n container), "KeyError" should be raised.\n\n Note: "for" loops expect that an "IndexError" will be raised for\n illegal indexes to allow proper detection of the end of the\n sequence.\n\nobject.__missing__(self, key)\n\n Called by "dict"."__getitem__()" to implement "self[key]" for dict\n subclasses when key is not in the dictionary.\n\nobject.__setitem__(self, key, value)\n\n Called to implement assignment to "self[key]". Same note as for\n "__getitem__()". This should only be implemented for mappings if\n the objects support changes to the values for keys, or if new keys\n can be added, or for sequences if elements can be replaced. The\n same exceptions should be raised for improper *key* values as for\n the "__getitem__()" method.\n\nobject.__delitem__(self, key)\n\n Called to implement deletion of "self[key]". Same note as for\n "__getitem__()". This should only be implemented for mappings if\n the objects support removal of keys, or for sequences if elements\n can be removed from the sequence. The same exceptions should be\n raised for improper *key* values as for the "__getitem__()" method.\n\nobject.__iter__(self)\n\n This method is called when an iterator is required for a container.\n This method should return a new iterator object that can iterate\n over all the objects in the container. For mappings, it should\n iterate over the keys of the container.\n\n Iterator objects also need to implement this method; they are\n required to return themselves. For more information on iterator\n objects, see *Iterator Types*.\n\nobject.__reversed__(self)\n\n Called (if present) by the "reversed()" built-in to implement\n reverse iteration. It should return a new iterator object that\n iterates over all the objects in the container in reverse order.\n\n If the "__reversed__()" method is not provided, the "reversed()"\n built-in will fall back to using the sequence protocol ("__len__()"\n and "__getitem__()"). Objects that support the sequence protocol\n should only provide "__reversed__()" if they can provide an\n implementation that is more efficient than the one provided by\n "reversed()".\n\nThe membership test operators ("in" and "not in") are normally\nimplemented as an iteration through a sequence. However, container\nobjects can supply the following special method with a more efficient\nimplementation, which also does not require the object be a sequence.\n\nobject.__contains__(self, item)\n\n Called to implement membership test operators. Should return true\n if *item* is in *self*, false otherwise. For mapping objects, this\n should consider the keys of the mapping rather than the values or\n the key-item pairs.\n\n For objects that don\'t define "__contains__()", the membership test\n first tries iteration via "__iter__()", then the old sequence\n iteration protocol via "__getitem__()", see *this section in the\n language reference*.\n\n\nEmulating numeric types\n=======================\n\nThe following methods can be defined to emulate numeric objects.\nMethods corresponding to operations that are not supported by the\nparticular kind of number implemented (e.g., bitwise operations for\nnon-integral numbers) should be left undefined.\n\nobject.__add__(self, other)\nobject.__sub__(self, other)\nobject.__mul__(self, other)\nobject.__matmul__(self, other)\nobject.__truediv__(self, other)\nobject.__floordiv__(self, other)\nobject.__mod__(self, other)\nobject.__divmod__(self, other)\nobject.__pow__(self, other[, modulo])\nobject.__lshift__(self, other)\nobject.__rshift__(self, other)\nobject.__and__(self, other)\nobject.__xor__(self, other)\nobject.__or__(self, other)\n\n These methods are called to implement the binary arithmetic\n operations ("+", "-", "*", "@", "/", "//", "%", "divmod()",\n "pow()", "**", "<<", ">>", "&", "^", "|"). For instance, to\n evaluate the expression "x + y", where *x* is an instance of a\n class that has an "__add__()" method, "x.__add__(y)" is called.\n The "__divmod__()" method should be the equivalent to using\n "__floordiv__()" and "__mod__()"; it should not be related to\n "__truediv__()". Note that "__pow__()" should be defined to accept\n an optional third argument if the ternary version of the built-in\n "pow()" function is to be supported.\n\n If one of those methods does not support the operation with the\n supplied arguments, it should return "NotImplemented".\n\nobject.__radd__(self, other)\nobject.__rsub__(self, other)\nobject.__rmul__(self, other)\nobject.__rmatmul__(self, other)\nobject.__rtruediv__(self, other)\nobject.__rfloordiv__(self, other)\nobject.__rmod__(self, other)\nobject.__rdivmod__(self, other)\nobject.__rpow__(self, other)\nobject.__rlshift__(self, other)\nobject.__rrshift__(self, other)\nobject.__rand__(self, other)\nobject.__rxor__(self, other)\nobject.__ror__(self, other)\n\n These methods are called to implement the binary arithmetic\n operations ("+", "-", "*", "@", "/", "//", "%", "divmod()",\n "pow()", "**", "<<", ">>", "&", "^", "|") with reflected (swapped)\n operands. These functions are only called if the left operand does\n not support the corresponding operation and the operands are of\n different types. [2] For instance, to evaluate the expression "x -\n y", where *y* is an instance of a class that has an "__rsub__()"\n method, "y.__rsub__(x)" is called if "x.__sub__(y)" returns\n *NotImplemented*.\n\n Note that ternary "pow()" will not try calling "__rpow__()" (the\n coercion rules would become too complicated).\n\n Note: If the right operand\'s type is a subclass of the left\n operand\'s type and that subclass provides the reflected method\n for the operation, this method will be called before the left\n operand\'s non-reflected method. This behavior allows subclasses\n to override their ancestors\' operations.\n\nobject.__iadd__(self, other)\nobject.__isub__(self, other)\nobject.__imul__(self, other)\nobject.__imatmul__(self, other)\nobject.__itruediv__(self, other)\nobject.__ifloordiv__(self, other)\nobject.__imod__(self, other)\nobject.__ipow__(self, other[, modulo])\nobject.__ilshift__(self, other)\nobject.__irshift__(self, other)\nobject.__iand__(self, other)\nobject.__ixor__(self, other)\nobject.__ior__(self, other)\n\n These methods are called to implement the augmented arithmetic\n assignments ("+=", "-=", "*=", "@=", "/=", "//=", "%=", "**=",\n "<<=", ">>=", "&=", "^=", "|="). These methods should attempt to\n do the operation in-place (modifying *self*) and return the result\n (which could be, but does not have to be, *self*). If a specific\n method is not defined, the augmented assignment falls back to the\n normal methods. For instance, if *x* is an instance of a class\n with an "__iadd__()" method, "x += y" is equivalent to "x =\n x.__iadd__(y)" . Otherwise, "x.__add__(y)" and "y.__radd__(x)" are\n considered, as with the evaluation of "x + y". In certain\n situations, augmented assignment can result in unexpected errors\n (see *Why does a_tuple[i] += [\'item\'] raise an exception when the\n addition works?*), but this behavior is in fact part of the data\n model.\n\nobject.__neg__(self)\nobject.__pos__(self)\nobject.__abs__(self)\nobject.__invert__(self)\n\n Called to implement the unary arithmetic operations ("-", "+",\n "abs()" and "~").\n\nobject.__complex__(self)\nobject.__int__(self)\nobject.__float__(self)\nobject.__round__(self[, n])\n\n Called to implement the built-in functions "complex()", "int()",\n "float()" and "round()". Should return a value of the appropriate\n type.\n\nobject.__index__(self)\n\n Called to implement "operator.index()", and whenever Python needs\n to losslessly convert the numeric object to an integer object (such\n as in slicing, or in the built-in "bin()", "hex()" and "oct()"\n functions). Presence of this method indicates that the numeric\n object is an integer type. Must return an integer.\n\n Note: In order to have a coherent integer type class, when\n "__index__()" is defined "__int__()" should also be defined, and\n both should return the same value.\n\n\nWith Statement Context Managers\n===============================\n\nA *context manager* is an object that defines the runtime context to\nbe established when executing a "with" statement. The context manager\nhandles the entry into, and the exit from, the desired runtime context\nfor the execution of the block of code. Context managers are normally\ninvoked using the "with" statement (described in section *The with\nstatement*), but can also be used by directly invoking their methods.\n\nTypical uses of context managers include saving and restoring various\nkinds of global state, locking and unlocking resources, closing opened\nfiles, etc.\n\nFor more information on context managers, see *Context Manager Types*.\n\nobject.__enter__(self)\n\n Enter the runtime context related to this object. The "with"\n statement will bind this method\'s return value to the target(s)\n specified in the "as" clause of the statement, if any.\n\nobject.__exit__(self, exc_type, exc_value, traceback)\n\n Exit the runtime context related to this object. The parameters\n describe the exception that caused the context to be exited. If the\n context was exited without an exception, all three arguments will\n be "None".\n\n If an exception is supplied, and the method wishes to suppress the\n exception (i.e., prevent it from being propagated), it should\n return a true value. Otherwise, the exception will be processed\n normally upon exit from this method.\n\n Note that "__exit__()" methods should not reraise the passed-in\n exception; this is the caller\'s responsibility.\n\nSee also: **PEP 0343** - The "with" statement\n\n The specification, background, and examples for the Python "with"\n statement.\n\n\nSpecial method lookup\n=====================\n\nFor custom classes, implicit invocations of special methods are only\nguaranteed to work correctly if defined on an object\'s type, not in\nthe object\'s instance dictionary. That behaviour is the reason why\nthe following code raises an exception:\n\n >>> class C:\n ... pass\n ...\n >>> c = C()\n >>> c.__len__ = lambda: 5\n >>> len(c)\n Traceback (most recent call last):\n File "", line 1, in \n TypeError: object of type \'C\' has no len()\n\nThe rationale behind this behaviour lies with a number of special\nmethods such as "__hash__()" and "__repr__()" that are implemented by\nall objects, including type objects. If the implicit lookup of these\nmethods used the conventional lookup process, they would fail when\ninvoked on the type object itself:\n\n >>> 1 .__hash__() == hash(1)\n True\n >>> int.__hash__() == hash(int)\n Traceback (most recent call last):\n File "", line 1, in \n TypeError: descriptor \'__hash__\' of \'int\' object needs an argument\n\nIncorrectly attempting to invoke an unbound method of a class in this\nway is sometimes referred to as \'metaclass confusion\', and is avoided\nby bypassing the instance when looking up special methods:\n\n >>> type(1).__hash__(1) == hash(1)\n True\n >>> type(int).__hash__(int) == hash(int)\n True\n\nIn addition to bypassing any instance attributes in the interest of\ncorrectness, implicit special method lookup generally also bypasses\nthe "__getattribute__()" method even of the object\'s metaclass:\n\n >>> class Meta(type):\n ... def __getattribute__(*args):\n ... print("Metaclass getattribute invoked")\n ... return type.__getattribute__(*args)\n ...\n >>> class C(object, metaclass=Meta):\n ... def __len__(self):\n ... return 10\n ... def __getattribute__(*args):\n ... print("Class getattribute invoked")\n ... return object.__getattribute__(*args)\n ...\n >>> c = C()\n >>> c.__len__() # Explicit lookup via instance\n Class getattribute invoked\n 10\n >>> type(c).__len__(c) # Explicit lookup via type\n Metaclass getattribute invoked\n 10\n >>> len(c) # Implicit lookup\n 10\n\nBypassing the "__getattribute__()" machinery in this fashion provides\nsignificant scope for speed optimisations within the interpreter, at\nthe cost of some flexibility in the handling of special methods (the\nspecial method *must* be set on the class object itself in order to be\nconsistently invoked by the interpreter).\n\n-[ Footnotes ]-\n\n[1] It *is* possible in some cases to change an object\'s type,\n under certain controlled conditions. It generally isn\'t a good\n idea though, since it can lead to some very strange behaviour if\n it is handled incorrectly.\n\n[2] For operands of the same type, it is assumed that if the non-\n reflected method (such as "__add__()") fails the operation is not\n supported, which is why the reflected method is not called.\n', - 'string-methods': u'\nString Methods\n**************\n\nStrings implement all of the *common* sequence operations, along with\nthe additional methods described below.\n\nStrings also support two styles of string formatting, one providing a\nlarge degree of flexibility and customization (see "str.format()",\n*Format String Syntax* and *String Formatting*) and the other based on\nC "printf" style formatting that handles a narrower range of types and\nis slightly harder to use correctly, but is often faster for the cases\nit can handle (*printf-style String Formatting*).\n\nThe *Text Processing Services* section of the standard library covers\na number of other modules that provide various text related utilities\n(including regular expression support in the "re" module).\n\nstr.capitalize()\n\n Return a copy of the string with its first character capitalized\n and the rest lowercased.\n\nstr.casefold()\n\n Return a casefolded copy of the string. Casefolded strings may be\n used for caseless matching.\n\n Casefolding is similar to lowercasing but more aggressive because\n it is intended to remove all case distinctions in a string. For\n example, the German lowercase letter "\'\xdf\'" is equivalent to ""ss"".\n Since it is already lowercase, "lower()" would do nothing to "\'\xdf\'";\n "casefold()" converts it to ""ss"".\n\n The casefolding algorithm is described in section 3.13 of the\n Unicode Standard.\n\n New in version 3.3.\n\nstr.center(width[, fillchar])\n\n Return centered in a string of length *width*. Padding is done\n using the specified *fillchar* (default is an ASCII space). The\n original string is returned if *width* is less than or equal to\n "len(s)".\n\nstr.count(sub[, start[, end]])\n\n Return the number of non-overlapping occurrences of substring *sub*\n in the range [*start*, *end*]. Optional arguments *start* and\n *end* are interpreted as in slice notation.\n\nstr.encode(encoding="utf-8", errors="strict")\n\n Return an encoded version of the string as a bytes object. Default\n encoding is "\'utf-8\'". *errors* may be given to set a different\n error handling scheme. The default for *errors* is "\'strict\'",\n meaning that encoding errors raise a "UnicodeError". Other possible\n values are "\'ignore\'", "\'replace\'", "\'xmlcharrefreplace\'",\n "\'backslashreplace\'" and any other name registered via\n "codecs.register_error()", see section *Error Handlers*. For a list\n of possible encodings, see section *Standard Encodings*.\n\n Changed in version 3.1: Support for keyword arguments added.\n\nstr.endswith(suffix[, start[, end]])\n\n Return "True" if the string ends with the specified *suffix*,\n otherwise return "False". *suffix* can also be a tuple of suffixes\n to look for. With optional *start*, test beginning at that\n position. With optional *end*, stop comparing at that position.\n\nstr.expandtabs(tabsize=8)\n\n Return a copy of the string where all tab characters are replaced\n by one or more spaces, depending on the current column and the\n given tab size. Tab positions occur every *tabsize* characters\n (default is 8, giving tab positions at columns 0, 8, 16 and so on).\n To expand the string, the current column is set to zero and the\n string is examined character by character. If the character is a\n tab ("\\t"), one or more space characters are inserted in the result\n until the current column is equal to the next tab position. (The\n tab character itself is not copied.) If the character is a newline\n ("\\n") or return ("\\r"), it is copied and the current column is\n reset to zero. Any other character is copied unchanged and the\n current column is incremented by one regardless of how the\n character is represented when printed.\n\n >>> \'01\\t012\\t0123\\t01234\'.expandtabs()\n \'01 012 0123 01234\'\n >>> \'01\\t012\\t0123\\t01234\'.expandtabs(4)\n \'01 012 0123 01234\'\n\nstr.find(sub[, start[, end]])\n\n Return the lowest index in the string where substring *sub* is\n found, such that *sub* is contained in the slice "s[start:end]".\n Optional arguments *start* and *end* are interpreted as in slice\n notation. Return "-1" if *sub* is not found.\n\n Note: The "find()" method should be used only if you need to know\n the position of *sub*. To check if *sub* is a substring or not,\n use the "in" operator:\n\n >>> \'Py\' in \'Python\'\n True\n\nstr.format(*args, **kwargs)\n\n Perform a string formatting operation. The string on which this\n method is called can contain literal text or replacement fields\n delimited by braces "{}". Each replacement field contains either\n the numeric index of a positional argument, or the name of a\n keyword argument. Returns a copy of the string where each\n replacement field is replaced with the string value of the\n corresponding argument.\n\n >>> "The sum of 1 + 2 is {0}".format(1+2)\n \'The sum of 1 + 2 is 3\'\n\n See *Format String Syntax* for a description of the various\n formatting options that can be specified in format strings.\n\nstr.format_map(mapping)\n\n Similar to "str.format(**mapping)", except that "mapping" is used\n directly and not copied to a "dict". This is useful if for example\n "mapping" is a dict subclass:\n\n >>> class Default(dict):\n ... def __missing__(self, key):\n ... return key\n ...\n >>> \'{name} was born in {country}\'.format_map(Default(name=\'Guido\'))\n \'Guido was born in country\'\n\n New in version 3.2.\n\nstr.index(sub[, start[, end]])\n\n Like "find()", but raise "ValueError" when the substring is not\n found.\n\nstr.isalnum()\n\n Return true if all characters in the string are alphanumeric and\n there is at least one character, false otherwise. A character "c"\n is alphanumeric if one of the following returns "True":\n "c.isalpha()", "c.isdecimal()", "c.isdigit()", or "c.isnumeric()".\n\nstr.isalpha()\n\n Return true if all characters in the string are alphabetic and\n there is at least one character, false otherwise. Alphabetic\n characters are those characters defined in the Unicode character\n database as "Letter", i.e., those with general category property\n being one of "Lm", "Lt", "Lu", "Ll", or "Lo". Note that this is\n different from the "Alphabetic" property defined in the Unicode\n Standard.\n\nstr.isdecimal()\n\n Return true if all characters in the string are decimal characters\n and there is at least one character, false otherwise. Decimal\n characters are those from general category "Nd". This category\n includes digit characters, and all characters that can be used to\n form decimal-radix numbers, e.g. U+0660, ARABIC-INDIC DIGIT ZERO.\n\nstr.isdigit()\n\n Return true if all characters in the string are digits and there is\n at least one character, false otherwise. Digits include decimal\n characters and digits that need special handling, such as the\n compatibility superscript digits. Formally, a digit is a character\n that has the property value Numeric_Type=Digit or\n Numeric_Type=Decimal.\n\nstr.isidentifier()\n\n Return true if the string is a valid identifier according to the\n language definition, section *Identifiers and keywords*.\n\n Use "keyword.iskeyword()" to test for reserved identifiers such as\n "def" and "class".\n\nstr.islower()\n\n Return true if all cased characters [4] in the string are lowercase\n and there is at least one cased character, false otherwise.\n\nstr.isnumeric()\n\n Return true if all characters in the string are numeric characters,\n and there is at least one character, false otherwise. Numeric\n characters include digit characters, and all characters that have\n the Unicode numeric value property, e.g. U+2155, VULGAR FRACTION\n ONE FIFTH. Formally, numeric characters are those with the\n property value Numeric_Type=Digit, Numeric_Type=Decimal or\n Numeric_Type=Numeric.\n\nstr.isprintable()\n\n Return true if all characters in the string are printable or the\n string is empty, false otherwise. Nonprintable characters are\n those characters defined in the Unicode character database as\n "Other" or "Separator", excepting the ASCII space (0x20) which is\n considered printable. (Note that printable characters in this\n context are those which should not be escaped when "repr()" is\n invoked on a string. It has no bearing on the handling of strings\n written to "sys.stdout" or "sys.stderr".)\n\nstr.isspace()\n\n Return true if there are only whitespace characters in the string\n and there is at least one character, false otherwise. Whitespace\n characters are those characters defined in the Unicode character\n database as "Other" or "Separator" and those with bidirectional\n property being one of "WS", "B", or "S".\n\nstr.istitle()\n\n Return true if the string is a titlecased string and there is at\n least one character, for example uppercase characters may only\n follow uncased characters and lowercase characters only cased ones.\n Return false otherwise.\n\nstr.isupper()\n\n Return true if all cased characters [4] in the string are uppercase\n and there is at least one cased character, false otherwise.\n\nstr.join(iterable)\n\n Return a string which is the concatenation of the strings in the\n *iterable* *iterable*. A "TypeError" will be raised if there are\n any non-string values in *iterable*, including "bytes" objects.\n The separator between elements is the string providing this method.\n\nstr.ljust(width[, fillchar])\n\n Return the string left justified in a string of length *width*.\n Padding is done using the specified *fillchar* (default is an ASCII\n space). The original string is returned if *width* is less than or\n equal to "len(s)".\n\nstr.lower()\n\n Return a copy of the string with all the cased characters [4]\n converted to lowercase.\n\n The lowercasing algorithm used is described in section 3.13 of the\n Unicode Standard.\n\nstr.lstrip([chars])\n\n Return a copy of the string with leading characters removed. The\n *chars* argument is a string specifying the set of characters to be\n removed. If omitted or "None", the *chars* argument defaults to\n removing whitespace. The *chars* argument is not a prefix; rather,\n all combinations of its values are stripped:\n\n >>> \' spacious \'.lstrip()\n \'spacious \'\n >>> \'www.example.com\'.lstrip(\'cmowz.\')\n \'example.com\'\n\nstatic str.maketrans(x[, y[, z]])\n\n This static method returns a translation table usable for\n "str.translate()".\n\n If there is only one argument, it must be a dictionary mapping\n Unicode ordinals (integers) or characters (strings of length 1) to\n Unicode ordinals, strings (of arbitrary lengths) or None.\n Character keys will then be converted to ordinals.\n\n If there are two arguments, they must be strings of equal length,\n and in the resulting dictionary, each character in x will be mapped\n to the character at the same position in y. If there is a third\n argument, it must be a string, whose characters will be mapped to\n None in the result.\n\nstr.partition(sep)\n\n Split the string at the first occurrence of *sep*, and return a\n 3-tuple containing the part before the separator, the separator\n itself, and the part after the separator. If the separator is not\n found, return a 3-tuple containing the string itself, followed by\n two empty strings.\n\nstr.replace(old, new[, count])\n\n Return a copy of the string with all occurrences of substring *old*\n replaced by *new*. If the optional argument *count* is given, only\n the first *count* occurrences are replaced.\n\nstr.rfind(sub[, start[, end]])\n\n Return the highest index in the string where substring *sub* is\n found, such that *sub* is contained within "s[start:end]".\n Optional arguments *start* and *end* are interpreted as in slice\n notation. Return "-1" on failure.\n\nstr.rindex(sub[, start[, end]])\n\n Like "rfind()" but raises "ValueError" when the substring *sub* is\n not found.\n\nstr.rjust(width[, fillchar])\n\n Return the string right justified in a string of length *width*.\n Padding is done using the specified *fillchar* (default is an ASCII\n space). The original string is returned if *width* is less than or\n equal to "len(s)".\n\nstr.rpartition(sep)\n\n Split the string at the last occurrence of *sep*, and return a\n 3-tuple containing the part before the separator, the separator\n itself, and the part after the separator. If the separator is not\n found, return a 3-tuple containing two empty strings, followed by\n the string itself.\n\nstr.rsplit(sep=None, maxsplit=-1)\n\n Return a list of the words in the string, using *sep* as the\n delimiter string. If *maxsplit* is given, at most *maxsplit* splits\n are done, the *rightmost* ones. If *sep* is not specified or\n "None", any whitespace string is a separator. Except for splitting\n from the right, "rsplit()" behaves like "split()" which is\n described in detail below.\n\nstr.rstrip([chars])\n\n Return a copy of the string with trailing characters removed. The\n *chars* argument is a string specifying the set of characters to be\n removed. If omitted or "None", the *chars* argument defaults to\n removing whitespace. The *chars* argument is not a suffix; rather,\n all combinations of its values are stripped:\n\n >>> \' spacious \'.rstrip()\n \' spacious\'\n >>> \'mississippi\'.rstrip(\'ipz\')\n \'mississ\'\n\nstr.split(sep=None, maxsplit=-1)\n\n Return a list of the words in the string, using *sep* as the\n delimiter string. If *maxsplit* is given, at most *maxsplit*\n splits are done (thus, the list will have at most "maxsplit+1"\n elements). If *maxsplit* is not specified or "-1", then there is\n no limit on the number of splits (all possible splits are made).\n\n If *sep* is given, consecutive delimiters are not grouped together\n and are deemed to delimit empty strings (for example,\n "\'1,,2\'.split(\',\')" returns "[\'1\', \'\', \'2\']"). The *sep* argument\n may consist of multiple characters (for example,\n "\'1<>2<>3\'.split(\'<>\')" returns "[\'1\', \'2\', \'3\']"). Splitting an\n empty string with a specified separator returns "[\'\']".\n\n For example:\n\n >>> \'1,2,3\'.split(\',\')\n [\'1\', \'2\', \'3\']\n >>> \'1,2,3\'.split(\',\', maxsplit=1)\n [\'1\', \'2,3\']\n >>> \'1,2,,3,\'.split(\',\')\n [\'1\', \'2\', \'\', \'3\', \'\']\n\n If *sep* is not specified or is "None", a different splitting\n algorithm is applied: runs of consecutive whitespace are regarded\n as a single separator, and the result will contain no empty strings\n at the start or end if the string has leading or trailing\n whitespace. Consequently, splitting an empty string or a string\n consisting of just whitespace with a "None" separator returns "[]".\n\n For example:\n\n >>> \'1 2 3\'.split()\n [\'1\', \'2\', \'3\']\n >>> \'1 2 3\'.split(maxsplit=1)\n [\'1\', \'2 3\']\n >>> \' 1 2 3 \'.split()\n [\'1\', \'2\', \'3\']\n\nstr.splitlines([keepends])\n\n Return a list of the lines in the string, breaking at line\n boundaries. This method uses the *universal newlines* approach to\n splitting lines. Line breaks are not included in the resulting list\n unless *keepends* is given and true.\n\n For example:\n\n >>> \'ab c\\n\\nde fg\\rkl\\r\\n\'.splitlines()\n [\'ab c\', \'\', \'de fg\', \'kl\']\n >>> \'ab c\\n\\nde fg\\rkl\\r\\n\'.splitlines(keepends=True)\n [\'ab c\\n\', \'\\n\', \'de fg\\r\', \'kl\\r\\n\']\n\n Unlike "split()" when a delimiter string *sep* is given, this\n method returns an empty list for the empty string, and a terminal\n line break does not result in an extra line:\n\n >>> "".splitlines()\n []\n >>> "One line\\n".splitlines()\n [\'One line\']\n\n For comparison, "split(\'\\n\')" gives:\n\n >>> \'\'.split(\'\\n\')\n [\'\']\n >>> \'Two lines\\n\'.split(\'\\n\')\n [\'Two lines\', \'\']\n\nstr.startswith(prefix[, start[, end]])\n\n Return "True" if string starts with the *prefix*, otherwise return\n "False". *prefix* can also be a tuple of prefixes to look for.\n With optional *start*, test string beginning at that position.\n With optional *end*, stop comparing string at that position.\n\nstr.strip([chars])\n\n Return a copy of the string with the leading and trailing\n characters removed. The *chars* argument is a string specifying the\n set of characters to be removed. If omitted or "None", the *chars*\n argument defaults to removing whitespace. The *chars* argument is\n not a prefix or suffix; rather, all combinations of its values are\n stripped:\n\n >>> \' spacious \'.strip()\n \'spacious\'\n >>> \'www.example.com\'.strip(\'cmowz.\')\n \'example\'\n\nstr.swapcase()\n\n Return a copy of the string with uppercase characters converted to\n lowercase and vice versa. Note that it is not necessarily true that\n "s.swapcase().swapcase() == s".\n\nstr.title()\n\n Return a titlecased version of the string where words start with an\n uppercase character and the remaining characters are lowercase.\n\n For example:\n\n >>> \'Hello world\'.title()\n \'Hello World\'\n\n The algorithm uses a simple language-independent definition of a\n word as groups of consecutive letters. The definition works in\n many contexts but it means that apostrophes in contractions and\n possessives form word boundaries, which may not be the desired\n result:\n\n >>> "they\'re bill\'s friends from the UK".title()\n "They\'Re Bill\'S Friends From The Uk"\n\n A workaround for apostrophes can be constructed using regular\n expressions:\n\n >>> import re\n >>> def titlecase(s):\n ... return re.sub(r"[A-Za-z]+(\'[A-Za-z]+)?",\n ... lambda mo: mo.group(0)[0].upper() +\n ... mo.group(0)[1:].lower(),\n ... s)\n ...\n >>> titlecase("they\'re bill\'s friends.")\n "They\'re Bill\'s Friends."\n\nstr.translate(map)\n\n Return a copy of the *s* where all characters have been mapped\n through the *map* which must be a dictionary of Unicode ordinals\n (integers) to Unicode ordinals, strings or "None". Unmapped\n characters are left untouched. Characters mapped to "None" are\n deleted.\n\n You can use "str.maketrans()" to create a translation map from\n character-to-character mappings in different formats.\n\n Note: An even more flexible approach is to create a custom\n character mapping codec using the "codecs" module (see\n "encodings.cp1251" for an example).\n\nstr.upper()\n\n Return a copy of the string with all the cased characters [4]\n converted to uppercase. Note that "str.upper().isupper()" might be\n "False" if "s" contains uncased characters or if the Unicode\n category of the resulting character(s) is not "Lu" (Letter,\n uppercase), but e.g. "Lt" (Letter, titlecase).\n\n The uppercasing algorithm used is described in section 3.13 of the\n Unicode Standard.\n\nstr.zfill(width)\n\n Return a copy of the string left filled with ASCII "\'0\'" digits to\n make a string of length *width*. A leading sign prefix ("\'+\'"/"\'-\'"\n is handled by inserting the padding *after* the sign character\n rather than before. The original string is returned if *width* is\n less than or equal to "len(s)".\n\n For example:\n\n >>> "42".zfill(5)\n \'00042\'\n >>> "-42".zfill(5)\n \'-0042\'\n', + 'specialnames': u'\nSpecial method names\n********************\n\nA class can implement certain operations that are invoked by special\nsyntax (such as arithmetic operations or subscripting and slicing) by\ndefining methods with special names. This is Python\'s approach to\n*operator overloading*, allowing classes to define their own behavior\nwith respect to language operators. For instance, if a class defines\na method named "__getitem__()", and "x" is an instance of this class,\nthen "x[i]" is roughly equivalent to "type(x).__getitem__(x, i)".\nExcept where mentioned, attempts to execute an operation raise an\nexception when no appropriate method is defined (typically\n"AttributeError" or "TypeError").\n\nWhen implementing a class that emulates any built-in type, it is\nimportant that the emulation only be implemented to the degree that it\nmakes sense for the object being modelled. For example, some\nsequences may work well with retrieval of individual elements, but\nextracting a slice may not make sense. (One example of this is the\n"NodeList" interface in the W3C\'s Document Object Model.)\n\n\nBasic customization\n===================\n\nobject.__new__(cls[, ...])\n\n Called to create a new instance of class *cls*. "__new__()" is a\n static method (special-cased so you need not declare it as such)\n that takes the class of which an instance was requested as its\n first argument. The remaining arguments are those passed to the\n object constructor expression (the call to the class). The return\n value of "__new__()" should be the new object instance (usually an\n instance of *cls*).\n\n Typical implementations create a new instance of the class by\n invoking the superclass\'s "__new__()" method using\n "super(currentclass, cls).__new__(cls[, ...])" with appropriate\n arguments and then modifying the newly-created instance as\n necessary before returning it.\n\n If "__new__()" returns an instance of *cls*, then the new\n instance\'s "__init__()" method will be invoked like\n "__init__(self[, ...])", where *self* is the new instance and the\n remaining arguments are the same as were passed to "__new__()".\n\n If "__new__()" does not return an instance of *cls*, then the new\n instance\'s "__init__()" method will not be invoked.\n\n "__new__()" is intended mainly to allow subclasses of immutable\n types (like int, str, or tuple) to customize instance creation. It\n is also commonly overridden in custom metaclasses in order to\n customize class creation.\n\nobject.__init__(self[, ...])\n\n Called after the instance has been created (by "__new__()"), but\n before it is returned to the caller. The arguments are those\n passed to the class constructor expression. If a base class has an\n "__init__()" method, the derived class\'s "__init__()" method, if\n any, must explicitly call it to ensure proper initialization of the\n base class part of the instance; for example:\n "BaseClass.__init__(self, [args...])".\n\n Because "__new__()" and "__init__()" work together in constructing\n objects ("__new__()" to create it, and "__init__()" to customise\n it), no non-"None" value may be returned by "__init__()"; doing so\n will cause a "TypeError" to be raised at runtime.\n\nobject.__del__(self)\n\n Called when the instance is about to be destroyed. This is also\n called a destructor. If a base class has a "__del__()" method, the\n derived class\'s "__del__()" method, if any, must explicitly call it\n to ensure proper deletion of the base class part of the instance.\n Note that it is possible (though not recommended!) for the\n "__del__()" method to postpone destruction of the instance by\n creating a new reference to it. It may then be called at a later\n time when this new reference is deleted. It is not guaranteed that\n "__del__()" methods are called for objects that still exist when\n the interpreter exits.\n\n Note: "del x" doesn\'t directly call "x.__del__()" --- the former\n decrements the reference count for "x" by one, and the latter is\n only called when "x"\'s reference count reaches zero. Some common\n situations that may prevent the reference count of an object from\n going to zero include: circular references between objects (e.g.,\n a doubly-linked list or a tree data structure with parent and\n child pointers); a reference to the object on the stack frame of\n a function that caught an exception (the traceback stored in\n "sys.exc_info()[2]" keeps the stack frame alive); or a reference\n to the object on the stack frame that raised an unhandled\n exception in interactive mode (the traceback stored in\n "sys.last_traceback" keeps the stack frame alive). The first\n situation can only be remedied by explicitly breaking the cycles;\n the second can be resolved by freeing the reference to the\n traceback object when it is no longer useful, and the third can\n be resolved by storing "None" in "sys.last_traceback". Circular\n references which are garbage are detected and cleaned up when the\n cyclic garbage collector is enabled (it\'s on by default). Refer\n to the documentation for the "gc" module for more information\n about this topic.\n\n Warning: Due to the precarious circumstances under which\n "__del__()" methods are invoked, exceptions that occur during\n their execution are ignored, and a warning is printed to\n "sys.stderr" instead. Also, when "__del__()" is invoked in\n response to a module being deleted (e.g., when execution of the\n program is done), other globals referenced by the "__del__()"\n method may already have been deleted or in the process of being\n torn down (e.g. the import machinery shutting down). For this\n reason, "__del__()" methods should do the absolute minimum needed\n to maintain external invariants. Starting with version 1.5,\n Python guarantees that globals whose name begins with a single\n underscore are deleted from their module before other globals are\n deleted; if no other references to such globals exist, this may\n help in assuring that imported modules are still available at the\n time when the "__del__()" method is called.\n\nobject.__repr__(self)\n\n Called by the "repr()" built-in function to compute the "official"\n string representation of an object. If at all possible, this\n should look like a valid Python expression that could be used to\n recreate an object with the same value (given an appropriate\n environment). If this is not possible, a string of the form\n "<...some useful description...>" should be returned. The return\n value must be a string object. If a class defines "__repr__()" but\n not "__str__()", then "__repr__()" is also used when an "informal"\n string representation of instances of that class is required.\n\n This is typically used for debugging, so it is important that the\n representation is information-rich and unambiguous.\n\nobject.__str__(self)\n\n Called by "str(object)" and the built-in functions "format()" and\n "print()" to compute the "informal" or nicely printable string\n representation of an object. The return value must be a *string*\n object.\n\n This method differs from "object.__repr__()" in that there is no\n expectation that "__str__()" return a valid Python expression: a\n more convenient or concise representation can be used.\n\n The default implementation defined by the built-in type "object"\n calls "object.__repr__()".\n\nobject.__bytes__(self)\n\n Called by "bytes()" to compute a byte-string representation of an\n object. This should return a "bytes" object.\n\nobject.__format__(self, format_spec)\n\n Called by the "format()" built-in function (and by extension, the\n "str.format()" method of class "str") to produce a "formatted"\n string representation of an object. The "format_spec" argument is a\n string that contains a description of the formatting options\n desired. The interpretation of the "format_spec" argument is up to\n the type implementing "__format__()", however most classes will\n either delegate formatting to one of the built-in types, or use a\n similar formatting option syntax.\n\n See *Format Specification Mini-Language* for a description of the\n standard formatting syntax.\n\n The return value must be a string object.\n\n Changed in version 3.4: The __format__ method of "object" itself\n raises a "TypeError" if passed any non-empty string.\n\nobject.__lt__(self, other)\nobject.__le__(self, other)\nobject.__eq__(self, other)\nobject.__ne__(self, other)\nobject.__gt__(self, other)\nobject.__ge__(self, other)\n\n These are the so-called "rich comparison" methods. The\n correspondence between operator symbols and method names is as\n follows: "xy" calls\n "x.__gt__(y)", and "x>=y" calls "x.__ge__(y)".\n\n A rich comparison method may return the singleton "NotImplemented"\n if it does not implement the operation for a given pair of\n arguments. By convention, "False" and "True" are returned for a\n successful comparison. However, these methods can return any value,\n so if the comparison operator is used in a Boolean context (e.g.,\n in the condition of an "if" statement), Python will call "bool()"\n on the value to determine if the result is true or false.\n\n There are no implied relationships among the comparison operators.\n The truth of "x==y" does not imply that "x!=y" is false.\n Accordingly, when defining "__eq__()", one should also define\n "__ne__()" so that the operators will behave as expected. See the\n paragraph on "__hash__()" for some important notes on creating\n *hashable* objects which support custom comparison operations and\n are usable as dictionary keys.\n\n There are no swapped-argument versions of these methods (to be used\n when the left argument does not support the operation but the right\n argument does); rather, "__lt__()" and "__gt__()" are each other\'s\n reflection, "__le__()" and "__ge__()" are each other\'s reflection,\n and "__eq__()" and "__ne__()" are their own reflection.\n\n Arguments to rich comparison methods are never coerced.\n\n To automatically generate ordering operations from a single root\n operation, see "functools.total_ordering()".\n\nobject.__hash__(self)\n\n Called by built-in function "hash()" and for operations on members\n of hashed collections including "set", "frozenset", and "dict".\n "__hash__()" should return an integer. The only required property\n is that objects which compare equal have the same hash value; it is\n advised to somehow mix together (e.g. using exclusive or) the hash\n values for the components of the object that also play a part in\n comparison of objects.\n\n Note: "hash()" truncates the value returned from an object\'s\n custom "__hash__()" method to the size of a "Py_ssize_t". This\n is typically 8 bytes on 64-bit builds and 4 bytes on 32-bit\n builds. If an object\'s "__hash__()" must interoperate on builds\n of different bit sizes, be sure to check the width on all\n supported builds. An easy way to do this is with "python -c\n "import sys; print(sys.hash_info.width)""\n\n If a class does not define an "__eq__()" method it should not\n define a "__hash__()" operation either; if it defines "__eq__()"\n but not "__hash__()", its instances will not be usable as items in\n hashable collections. If a class defines mutable objects and\n implements an "__eq__()" method, it should not implement\n "__hash__()", since the implementation of hashable collections\n requires that a key\'s hash value is immutable (if the object\'s hash\n value changes, it will be in the wrong hash bucket).\n\n User-defined classes have "__eq__()" and "__hash__()" methods by\n default; with them, all objects compare unequal (except with\n themselves) and "x.__hash__()" returns an appropriate value such\n that "x == y" implies both that "x is y" and "hash(x) == hash(y)".\n\n A class that overrides "__eq__()" and does not define "__hash__()"\n will have its "__hash__()" implicitly set to "None". When the\n "__hash__()" method of a class is "None", instances of the class\n will raise an appropriate "TypeError" when a program attempts to\n retrieve their hash value, and will also be correctly identified as\n unhashable when checking "isinstance(obj, collections.Hashable").\n\n If a class that overrides "__eq__()" needs to retain the\n implementation of "__hash__()" from a parent class, the interpreter\n must be told this explicitly by setting "__hash__ =\n .__hash__".\n\n If a class that does not override "__eq__()" wishes to suppress\n hash support, it should include "__hash__ = None" in the class\n definition. A class which defines its own "__hash__()" that\n explicitly raises a "TypeError" would be incorrectly identified as\n hashable by an "isinstance(obj, collections.Hashable)" call.\n\n Note: By default, the "__hash__()" values of str, bytes and\n datetime objects are "salted" with an unpredictable random value.\n Although they remain constant within an individual Python\n process, they are not predictable between repeated invocations of\n Python.This is intended to provide protection against a denial-\n of-service caused by carefully-chosen inputs that exploit the\n worst case performance of a dict insertion, O(n^2) complexity.\n See http://www.ocert.org/advisories/ocert-2011-003.html for\n details.Changing hash values affects the iteration order of\n dicts, sets and other mappings. Python has never made guarantees\n about this ordering (and it typically varies between 32-bit and\n 64-bit builds).See also "PYTHONHASHSEED".\n\n Changed in version 3.3: Hash randomization is enabled by default.\n\nobject.__bool__(self)\n\n Called to implement truth value testing and the built-in operation\n "bool()"; should return "False" or "True". When this method is not\n defined, "__len__()" is called, if it is defined, and the object is\n considered true if its result is nonzero. If a class defines\n neither "__len__()" nor "__bool__()", all its instances are\n considered true.\n\n\nCustomizing attribute access\n============================\n\nThe following methods can be defined to customize the meaning of\nattribute access (use of, assignment to, or deletion of "x.name") for\nclass instances.\n\nobject.__getattr__(self, name)\n\n Called when an attribute lookup has not found the attribute in the\n usual places (i.e. it is not an instance attribute nor is it found\n in the class tree for "self"). "name" is the attribute name. This\n method should return the (computed) attribute value or raise an\n "AttributeError" exception.\n\n Note that if the attribute is found through the normal mechanism,\n "__getattr__()" is not called. (This is an intentional asymmetry\n between "__getattr__()" and "__setattr__()".) This is done both for\n efficiency reasons and because otherwise "__getattr__()" would have\n no way to access other attributes of the instance. Note that at\n least for instance variables, you can fake total control by not\n inserting any values in the instance attribute dictionary (but\n instead inserting them in another object). See the\n "__getattribute__()" method below for a way to actually get total\n control over attribute access.\n\nobject.__getattribute__(self, name)\n\n Called unconditionally to implement attribute accesses for\n instances of the class. If the class also defines "__getattr__()",\n the latter will not be called unless "__getattribute__()" either\n calls it explicitly or raises an "AttributeError". This method\n should return the (computed) attribute value or raise an\n "AttributeError" exception. In order to avoid infinite recursion in\n this method, its implementation should always call the base class\n method with the same name to access any attributes it needs, for\n example, "object.__getattribute__(self, name)".\n\n Note: This method may still be bypassed when looking up special\n methods as the result of implicit invocation via language syntax\n or built-in functions. See *Special method lookup*.\n\nobject.__setattr__(self, name, value)\n\n Called when an attribute assignment is attempted. This is called\n instead of the normal mechanism (i.e. store the value in the\n instance dictionary). *name* is the attribute name, *value* is the\n value to be assigned to it.\n\n If "__setattr__()" wants to assign to an instance attribute, it\n should call the base class method with the same name, for example,\n "object.__setattr__(self, name, value)".\n\nobject.__delattr__(self, name)\n\n Like "__setattr__()" but for attribute deletion instead of\n assignment. This should only be implemented if "del obj.name" is\n meaningful for the object.\n\nobject.__dir__(self)\n\n Called when "dir()" is called on the object. A sequence must be\n returned. "dir()" converts the returned sequence to a list and\n sorts it.\n\n\nImplementing Descriptors\n------------------------\n\nThe following methods only apply when an instance of the class\ncontaining the method (a so-called *descriptor* class) appears in an\n*owner* class (the descriptor must be in either the owner\'s class\ndictionary or in the class dictionary for one of its parents). In the\nexamples below, "the attribute" refers to the attribute whose name is\nthe key of the property in the owner class\' "__dict__".\n\nobject.__get__(self, instance, owner)\n\n Called to get the attribute of the owner class (class attribute\n access) or of an instance of that class (instance attribute\n access). *owner* is always the owner class, while *instance* is the\n instance that the attribute was accessed through, or "None" when\n the attribute is accessed through the *owner*. This method should\n return the (computed) attribute value or raise an "AttributeError"\n exception.\n\nobject.__set__(self, instance, value)\n\n Called to set the attribute on an instance *instance* of the owner\n class to a new value, *value*.\n\nobject.__delete__(self, instance)\n\n Called to delete the attribute on an instance *instance* of the\n owner class.\n\nThe attribute "__objclass__" is interpreted by the "inspect" module as\nspecifying the class where this object was defined (setting this\nappropriately can assist in runtime introspection of dynamic class\nattributes). For callables, it may indicate that an instance of the\ngiven type (or a subclass) is expected or required as the first\npositional argument (for example, CPython sets this attribute for\nunbound methods that are implemented in C).\n\n\nInvoking Descriptors\n--------------------\n\nIn general, a descriptor is an object attribute with "binding\nbehavior", one whose attribute access has been overridden by methods\nin the descriptor protocol: "__get__()", "__set__()", and\n"__delete__()". If any of those methods are defined for an object, it\nis said to be a descriptor.\n\nThe default behavior for attribute access is to get, set, or delete\nthe attribute from an object\'s dictionary. For instance, "a.x" has a\nlookup chain starting with "a.__dict__[\'x\']", then\n"type(a).__dict__[\'x\']", and continuing through the base classes of\n"type(a)" excluding metaclasses.\n\nHowever, if the looked-up value is an object defining one of the\ndescriptor methods, then Python may override the default behavior and\ninvoke the descriptor method instead. Where this occurs in the\nprecedence chain depends on which descriptor methods were defined and\nhow they were called.\n\nThe starting point for descriptor invocation is a binding, "a.x". How\nthe arguments are assembled depends on "a":\n\nDirect Call\n The simplest and least common call is when user code directly\n invokes a descriptor method: "x.__get__(a)".\n\nInstance Binding\n If binding to an object instance, "a.x" is transformed into the\n call: "type(a).__dict__[\'x\'].__get__(a, type(a))".\n\nClass Binding\n If binding to a class, "A.x" is transformed into the call:\n "A.__dict__[\'x\'].__get__(None, A)".\n\nSuper Binding\n If "a" is an instance of "super", then the binding "super(B,\n obj).m()" searches "obj.__class__.__mro__" for the base class "A"\n immediately preceding "B" and then invokes the descriptor with the\n call: "A.__dict__[\'m\'].__get__(obj, obj.__class__)".\n\nFor instance bindings, the precedence of descriptor invocation depends\non the which descriptor methods are defined. A descriptor can define\nany combination of "__get__()", "__set__()" and "__delete__()". If it\ndoes not define "__get__()", then accessing the attribute will return\nthe descriptor object itself unless there is a value in the object\'s\ninstance dictionary. If the descriptor defines "__set__()" and/or\n"__delete__()", it is a data descriptor; if it defines neither, it is\na non-data descriptor. Normally, data descriptors define both\n"__get__()" and "__set__()", while non-data descriptors have just the\n"__get__()" method. Data descriptors with "__set__()" and "__get__()"\ndefined always override a redefinition in an instance dictionary. In\ncontrast, non-data descriptors can be overridden by instances.\n\nPython methods (including "staticmethod()" and "classmethod()") are\nimplemented as non-data descriptors. Accordingly, instances can\nredefine and override methods. This allows individual instances to\nacquire behaviors that differ from other instances of the same class.\n\nThe "property()" function is implemented as a data descriptor.\nAccordingly, instances cannot override the behavior of a property.\n\n\n__slots__\n---------\n\nBy default, instances of classes have a dictionary for attribute\nstorage. This wastes space for objects having very few instance\nvariables. The space consumption can become acute when creating large\nnumbers of instances.\n\nThe default can be overridden by defining *__slots__* in a class\ndefinition. The *__slots__* declaration takes a sequence of instance\nvariables and reserves just enough space in each instance to hold a\nvalue for each variable. Space is saved because *__dict__* is not\ncreated for each instance.\n\nobject.__slots__\n\n This class variable can be assigned a string, iterable, or sequence\n of strings with variable names used by instances. *__slots__*\n reserves space for the declared variables and prevents the\n automatic creation of *__dict__* and *__weakref__* for each\n instance.\n\n\nNotes on using *__slots__*\n~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n* When inheriting from a class without *__slots__*, the *__dict__*\n attribute of that class will always be accessible, so a *__slots__*\n definition in the subclass is meaningless.\n\n* Without a *__dict__* variable, instances cannot be assigned new\n variables not listed in the *__slots__* definition. Attempts to\n assign to an unlisted variable name raises "AttributeError". If\n dynamic assignment of new variables is desired, then add\n "\'__dict__\'" to the sequence of strings in the *__slots__*\n declaration.\n\n* Without a *__weakref__* variable for each instance, classes\n defining *__slots__* do not support weak references to its\n instances. If weak reference support is needed, then add\n "\'__weakref__\'" to the sequence of strings in the *__slots__*\n declaration.\n\n* *__slots__* are implemented at the class level by creating\n descriptors (*Implementing Descriptors*) for each variable name. As\n a result, class attributes cannot be used to set default values for\n instance variables defined by *__slots__*; otherwise, the class\n attribute would overwrite the descriptor assignment.\n\n* The action of a *__slots__* declaration is limited to the class\n where it is defined. As a result, subclasses will have a *__dict__*\n unless they also define *__slots__* (which must only contain names\n of any *additional* slots).\n\n* If a class defines a slot also defined in a base class, the\n instance variable defined by the base class slot is inaccessible\n (except by retrieving its descriptor directly from the base class).\n This renders the meaning of the program undefined. In the future, a\n check may be added to prevent this.\n\n* Nonempty *__slots__* does not work for classes derived from\n "variable-length" built-in types such as "int", "bytes" and "tuple".\n\n* Any non-string iterable may be assigned to *__slots__*. Mappings\n may also be used; however, in the future, special meaning may be\n assigned to the values corresponding to each key.\n\n* *__class__* assignment works only if both classes have the same\n *__slots__*.\n\n\nCustomizing class creation\n==========================\n\nBy default, classes are constructed using "type()". The class body is\nexecuted in a new namespace and the class name is bound locally to the\nresult of "type(name, bases, namespace)".\n\nThe class creation process can be customised by passing the\n"metaclass" keyword argument in the class definition line, or by\ninheriting from an existing class that included such an argument. In\nthe following example, both "MyClass" and "MySubclass" are instances\nof "Meta":\n\n class Meta(type):\n pass\n\n class MyClass(metaclass=Meta):\n pass\n\n class MySubclass(MyClass):\n pass\n\nAny other keyword arguments that are specified in the class definition\nare passed through to all metaclass operations described below.\n\nWhen a class definition is executed, the following steps occur:\n\n* the appropriate metaclass is determined\n\n* the class namespace is prepared\n\n* the class body is executed\n\n* the class object is created\n\n\nDetermining the appropriate metaclass\n-------------------------------------\n\nThe appropriate metaclass for a class definition is determined as\nfollows:\n\n* if no bases and no explicit metaclass are given, then "type()" is\n used\n\n* if an explicit metaclass is given and it is *not* an instance of\n "type()", then it is used directly as the metaclass\n\n* if an instance of "type()" is given as the explicit metaclass, or\n bases are defined, then the most derived metaclass is used\n\nThe most derived metaclass is selected from the explicitly specified\nmetaclass (if any) and the metaclasses (i.e. "type(cls)") of all\nspecified base classes. The most derived metaclass is one which is a\nsubtype of *all* of these candidate metaclasses. If none of the\ncandidate metaclasses meets that criterion, then the class definition\nwill fail with "TypeError".\n\n\nPreparing the class namespace\n-----------------------------\n\nOnce the appropriate metaclass has been identified, then the class\nnamespace is prepared. If the metaclass has a "__prepare__" attribute,\nit is called as "namespace = metaclass.__prepare__(name, bases,\n**kwds)" (where the additional keyword arguments, if any, come from\nthe class definition).\n\nIf the metaclass has no "__prepare__" attribute, then the class\nnamespace is initialised as an empty "dict()" instance.\n\nSee also: **PEP 3115** - Metaclasses in Python 3000\n\n Introduced the "__prepare__" namespace hook\n\n\nExecuting the class body\n------------------------\n\nThe class body is executed (approximately) as "exec(body, globals(),\nnamespace)". The key difference from a normal call to "exec()" is that\nlexical scoping allows the class body (including any methods) to\nreference names from the current and outer scopes when the class\ndefinition occurs inside a function.\n\nHowever, even when the class definition occurs inside the function,\nmethods defined inside the class still cannot see names defined at the\nclass scope. Class variables must be accessed through the first\nparameter of instance or class methods, and cannot be accessed at all\nfrom static methods.\n\n\nCreating the class object\n-------------------------\n\nOnce the class namespace has been populated by executing the class\nbody, the class object is created by calling "metaclass(name, bases,\nnamespace, **kwds)" (the additional keywords passed here are the same\nas those passed to "__prepare__").\n\nThis class object is the one that will be referenced by the zero-\nargument form of "super()". "__class__" is an implicit closure\nreference created by the compiler if any methods in a class body refer\nto either "__class__" or "super". This allows the zero argument form\nof "super()" to correctly identify the class being defined based on\nlexical scoping, while the class or instance that was used to make the\ncurrent call is identified based on the first argument passed to the\nmethod.\n\nAfter the class object is created, it is passed to the class\ndecorators included in the class definition (if any) and the resulting\nobject is bound in the local namespace as the defined class.\n\nSee also: **PEP 3135** - New super\n\n Describes the implicit "__class__" closure reference\n\n\nMetaclass example\n-----------------\n\nThe potential uses for metaclasses are boundless. Some ideas that have\nbeen explored include logging, interface checking, automatic\ndelegation, automatic property creation, proxies, frameworks, and\nautomatic resource locking/synchronization.\n\nHere is an example of a metaclass that uses an\n"collections.OrderedDict" to remember the order that class variables\nare defined:\n\n class OrderedClass(type):\n\n @classmethod\n def __prepare__(metacls, name, bases, **kwds):\n return collections.OrderedDict()\n\n def __new__(cls, name, bases, namespace, **kwds):\n result = type.__new__(cls, name, bases, dict(namespace))\n result.members = tuple(namespace)\n return result\n\n class A(metaclass=OrderedClass):\n def one(self): pass\n def two(self): pass\n def three(self): pass\n def four(self): pass\n\n >>> A.members\n (\'__module__\', \'one\', \'two\', \'three\', \'four\')\n\nWhen the class definition for *A* gets executed, the process begins\nwith calling the metaclass\'s "__prepare__()" method which returns an\nempty "collections.OrderedDict". That mapping records the methods and\nattributes of *A* as they are defined within the body of the class\nstatement. Once those definitions are executed, the ordered dictionary\nis fully populated and the metaclass\'s "__new__()" method gets\ninvoked. That method builds the new type and it saves the ordered\ndictionary keys in an attribute called "members".\n\n\nCustomizing instance and subclass checks\n========================================\n\nThe following methods are used to override the default behavior of the\n"isinstance()" and "issubclass()" built-in functions.\n\nIn particular, the metaclass "abc.ABCMeta" implements these methods in\norder to allow the addition of Abstract Base Classes (ABCs) as\n"virtual base classes" to any class or type (including built-in\ntypes), including other ABCs.\n\nclass.__instancecheck__(self, instance)\n\n Return true if *instance* should be considered a (direct or\n indirect) instance of *class*. If defined, called to implement\n "isinstance(instance, class)".\n\nclass.__subclasscheck__(self, subclass)\n\n Return true if *subclass* should be considered a (direct or\n indirect) subclass of *class*. If defined, called to implement\n "issubclass(subclass, class)".\n\nNote that these methods are looked up on the type (metaclass) of a\nclass. They cannot be defined as class methods in the actual class.\nThis is consistent with the lookup of special methods that are called\non instances, only in this case the instance is itself a class.\n\nSee also: **PEP 3119** - Introducing Abstract Base Classes\n\n Includes the specification for customizing "isinstance()" and\n "issubclass()" behavior through "__instancecheck__()" and\n "__subclasscheck__()", with motivation for this functionality in\n the context of adding Abstract Base Classes (see the "abc"\n module) to the language.\n\n\nEmulating callable objects\n==========================\n\nobject.__call__(self[, args...])\n\n Called when the instance is "called" as a function; if this method\n is defined, "x(arg1, arg2, ...)" is a shorthand for\n "x.__call__(arg1, arg2, ...)".\n\n\nEmulating container types\n=========================\n\nThe following methods can be defined to implement container objects.\nContainers usually are sequences (such as lists or tuples) or mappings\n(like dictionaries), but can represent other containers as well. The\nfirst set of methods is used either to emulate a sequence or to\nemulate a mapping; the difference is that for a sequence, the\nallowable keys should be the integers *k* for which "0 <= k < N" where\n*N* is the length of the sequence, or slice objects, which define a\nrange of items. It is also recommended that mappings provide the\nmethods "keys()", "values()", "items()", "get()", "clear()",\n"setdefault()", "pop()", "popitem()", "copy()", and "update()"\nbehaving similar to those for Python\'s standard dictionary objects.\nThe "collections" module provides a "MutableMapping" abstract base\nclass to help create those methods from a base set of "__getitem__()",\n"__setitem__()", "__delitem__()", and "keys()". Mutable sequences\nshould provide methods "append()", "count()", "index()", "extend()",\n"insert()", "pop()", "remove()", "reverse()" and "sort()", like Python\nstandard list objects. Finally, sequence types should implement\naddition (meaning concatenation) and multiplication (meaning\nrepetition) by defining the methods "__add__()", "__radd__()",\n"__iadd__()", "__mul__()", "__rmul__()" and "__imul__()" described\nbelow; they should not define other numerical operators. It is\nrecommended that both mappings and sequences implement the\n"__contains__()" method to allow efficient use of the "in" operator;\nfor mappings, "in" should search the mapping\'s keys; for sequences, it\nshould search through the values. It is further recommended that both\nmappings and sequences implement the "__iter__()" method to allow\nefficient iteration through the container; for mappings, "__iter__()"\nshould be the same as "keys()"; for sequences, it should iterate\nthrough the values.\n\nobject.__len__(self)\n\n Called to implement the built-in function "len()". Should return\n the length of the object, an integer ">=" 0. Also, an object that\n doesn\'t define a "__bool__()" method and whose "__len__()" method\n returns zero is considered to be false in a Boolean context.\n\nobject.__length_hint__(self)\n\n Called to implement "operator.length_hint()". Should return an\n estimated length for the object (which may be greater or less than\n the actual length). The length must be an integer ">=" 0. This\n method is purely an optimization and is never required for\n correctness.\n\n New in version 3.4.\n\nNote: Slicing is done exclusively with the following three methods.\n A call like\n\n a[1:2] = b\n\n is translated to\n\n a[slice(1, 2, None)] = b\n\n and so forth. Missing slice items are always filled in with "None".\n\nobject.__getitem__(self, key)\n\n Called to implement evaluation of "self[key]". For sequence types,\n the accepted keys should be integers and slice objects. Note that\n the special interpretation of negative indexes (if the class wishes\n to emulate a sequence type) is up to the "__getitem__()" method. If\n *key* is of an inappropriate type, "TypeError" may be raised; if of\n a value outside the set of indexes for the sequence (after any\n special interpretation of negative values), "IndexError" should be\n raised. For mapping types, if *key* is missing (not in the\n container), "KeyError" should be raised.\n\n Note: "for" loops expect that an "IndexError" will be raised for\n illegal indexes to allow proper detection of the end of the\n sequence.\n\nobject.__missing__(self, key)\n\n Called by "dict"."__getitem__()" to implement "self[key]" for dict\n subclasses when key is not in the dictionary.\n\nobject.__setitem__(self, key, value)\n\n Called to implement assignment to "self[key]". Same note as for\n "__getitem__()". This should only be implemented for mappings if\n the objects support changes to the values for keys, or if new keys\n can be added, or for sequences if elements can be replaced. The\n same exceptions should be raised for improper *key* values as for\n the "__getitem__()" method.\n\nobject.__delitem__(self, key)\n\n Called to implement deletion of "self[key]". Same note as for\n "__getitem__()". This should only be implemented for mappings if\n the objects support removal of keys, or for sequences if elements\n can be removed from the sequence. The same exceptions should be\n raised for improper *key* values as for the "__getitem__()" method.\n\nobject.__iter__(self)\n\n This method is called when an iterator is required for a container.\n This method should return a new iterator object that can iterate\n over all the objects in the container. For mappings, it should\n iterate over the keys of the container.\n\n Iterator objects also need to implement this method; they are\n required to return themselves. For more information on iterator\n objects, see *Iterator Types*.\n\nobject.__reversed__(self)\n\n Called (if present) by the "reversed()" built-in to implement\n reverse iteration. It should return a new iterator object that\n iterates over all the objects in the container in reverse order.\n\n If the "__reversed__()" method is not provided, the "reversed()"\n built-in will fall back to using the sequence protocol ("__len__()"\n and "__getitem__()"). Objects that support the sequence protocol\n should only provide "__reversed__()" if they can provide an\n implementation that is more efficient than the one provided by\n "reversed()".\n\nThe membership test operators ("in" and "not in") are normally\nimplemented as an iteration through a sequence. However, container\nobjects can supply the following special method with a more efficient\nimplementation, which also does not require the object be a sequence.\n\nobject.__contains__(self, item)\n\n Called to implement membership test operators. Should return true\n if *item* is in *self*, false otherwise. For mapping objects, this\n should consider the keys of the mapping rather than the values or\n the key-item pairs.\n\n For objects that don\'t define "__contains__()", the membership test\n first tries iteration via "__iter__()", then the old sequence\n iteration protocol via "__getitem__()", see *this section in the\n language reference*.\n\n\nEmulating numeric types\n=======================\n\nThe following methods can be defined to emulate numeric objects.\nMethods corresponding to operations that are not supported by the\nparticular kind of number implemented (e.g., bitwise operations for\nnon-integral numbers) should be left undefined.\n\nobject.__add__(self, other)\nobject.__sub__(self, other)\nobject.__mul__(self, other)\nobject.__matmul__(self, other)\nobject.__truediv__(self, other)\nobject.__floordiv__(self, other)\nobject.__mod__(self, other)\nobject.__divmod__(self, other)\nobject.__pow__(self, other[, modulo])\nobject.__lshift__(self, other)\nobject.__rshift__(self, other)\nobject.__and__(self, other)\nobject.__xor__(self, other)\nobject.__or__(self, other)\n\n These methods are called to implement the binary arithmetic\n operations ("+", "-", "*", "@", "/", "//", "%", "divmod()",\n "pow()", "**", "<<", ">>", "&", "^", "|"). For instance, to\n evaluate the expression "x + y", where *x* is an instance of a\n class that has an "__add__()" method, "x.__add__(y)" is called.\n The "__divmod__()" method should be the equivalent to using\n "__floordiv__()" and "__mod__()"; it should not be related to\n "__truediv__()". Note that "__pow__()" should be defined to accept\n an optional third argument if the ternary version of the built-in\n "pow()" function is to be supported.\n\n If one of those methods does not support the operation with the\n supplied arguments, it should return "NotImplemented".\n\nobject.__radd__(self, other)\nobject.__rsub__(self, other)\nobject.__rmul__(self, other)\nobject.__rmatmul__(self, other)\nobject.__rtruediv__(self, other)\nobject.__rfloordiv__(self, other)\nobject.__rmod__(self, other)\nobject.__rdivmod__(self, other)\nobject.__rpow__(self, other)\nobject.__rlshift__(self, other)\nobject.__rrshift__(self, other)\nobject.__rand__(self, other)\nobject.__rxor__(self, other)\nobject.__ror__(self, other)\n\n These methods are called to implement the binary arithmetic\n operations ("+", "-", "*", "@", "/", "//", "%", "divmod()",\n "pow()", "**", "<<", ">>", "&", "^", "|") with reflected (swapped)\n operands. These functions are only called if the left operand does\n not support the corresponding operation and the operands are of\n different types. [2] For instance, to evaluate the expression "x -\n y", where *y* is an instance of a class that has an "__rsub__()"\n method, "y.__rsub__(x)" is called if "x.__sub__(y)" returns\n *NotImplemented*.\n\n Note that ternary "pow()" will not try calling "__rpow__()" (the\n coercion rules would become too complicated).\n\n Note: If the right operand\'s type is a subclass of the left\n operand\'s type and that subclass provides the reflected method\n for the operation, this method will be called before the left\n operand\'s non-reflected method. This behavior allows subclasses\n to override their ancestors\' operations.\n\nobject.__iadd__(self, other)\nobject.__isub__(self, other)\nobject.__imul__(self, other)\nobject.__imatmul__(self, other)\nobject.__itruediv__(self, other)\nobject.__ifloordiv__(self, other)\nobject.__imod__(self, other)\nobject.__ipow__(self, other[, modulo])\nobject.__ilshift__(self, other)\nobject.__irshift__(self, other)\nobject.__iand__(self, other)\nobject.__ixor__(self, other)\nobject.__ior__(self, other)\n\n These methods are called to implement the augmented arithmetic\n assignments ("+=", "-=", "*=", "@=", "/=", "//=", "%=", "**=",\n "<<=", ">>=", "&=", "^=", "|="). These methods should attempt to\n do the operation in-place (modifying *self*) and return the result\n (which could be, but does not have to be, *self*). If a specific\n method is not defined, the augmented assignment falls back to the\n normal methods. For instance, if *x* is an instance of a class\n with an "__iadd__()" method, "x += y" is equivalent to "x =\n x.__iadd__(y)" . Otherwise, "x.__add__(y)" and "y.__radd__(x)" are\n considered, as with the evaluation of "x + y". In certain\n situations, augmented assignment can result in unexpected errors\n (see *Why does a_tuple[i] += [\'item\'] raise an exception when the\n addition works?*), but this behavior is in fact part of the data\n model.\n\nobject.__neg__(self)\nobject.__pos__(self)\nobject.__abs__(self)\nobject.__invert__(self)\n\n Called to implement the unary arithmetic operations ("-", "+",\n "abs()" and "~").\n\nobject.__complex__(self)\nobject.__int__(self)\nobject.__float__(self)\nobject.__round__(self[, n])\n\n Called to implement the built-in functions "complex()", "int()",\n "float()" and "round()". Should return a value of the appropriate\n type.\n\nobject.__index__(self)\n\n Called to implement "operator.index()", and whenever Python needs\n to losslessly convert the numeric object to an integer object (such\n as in slicing, or in the built-in "bin()", "hex()" and "oct()"\n functions). Presence of this method indicates that the numeric\n object is an integer type. Must return an integer.\n\n Note: In order to have a coherent integer type class, when\n "__index__()" is defined "__int__()" should also be defined, and\n both should return the same value.\n\n\nWith Statement Context Managers\n===============================\n\nA *context manager* is an object that defines the runtime context to\nbe established when executing a "with" statement. The context manager\nhandles the entry into, and the exit from, the desired runtime context\nfor the execution of the block of code. Context managers are normally\ninvoked using the "with" statement (described in section *The with\nstatement*), but can also be used by directly invoking their methods.\n\nTypical uses of context managers include saving and restoring various\nkinds of global state, locking and unlocking resources, closing opened\nfiles, etc.\n\nFor more information on context managers, see *Context Manager Types*.\n\nobject.__enter__(self)\n\n Enter the runtime context related to this object. The "with"\n statement will bind this method\'s return value to the target(s)\n specified in the "as" clause of the statement, if any.\n\nobject.__exit__(self, exc_type, exc_value, traceback)\n\n Exit the runtime context related to this object. The parameters\n describe the exception that caused the context to be exited. If the\n context was exited without an exception, all three arguments will\n be "None".\n\n If an exception is supplied, and the method wishes to suppress the\n exception (i.e., prevent it from being propagated), it should\n return a true value. Otherwise, the exception will be processed\n normally upon exit from this method.\n\n Note that "__exit__()" methods should not reraise the passed-in\n exception; this is the caller\'s responsibility.\n\nSee also: **PEP 0343** - The "with" statement\n\n The specification, background, and examples for the Python "with"\n statement.\n\n\nSpecial method lookup\n=====================\n\nFor custom classes, implicit invocations of special methods are only\nguaranteed to work correctly if defined on an object\'s type, not in\nthe object\'s instance dictionary. That behaviour is the reason why\nthe following code raises an exception:\n\n >>> class C:\n ... pass\n ...\n >>> c = C()\n >>> c.__len__ = lambda: 5\n >>> len(c)\n Traceback (most recent call last):\n File "", line 1, in \n TypeError: object of type \'C\' has no len()\n\nThe rationale behind this behaviour lies with a number of special\nmethods such as "__hash__()" and "__repr__()" that are implemented by\nall objects, including type objects. If the implicit lookup of these\nmethods used the conventional lookup process, they would fail when\ninvoked on the type object itself:\n\n >>> 1 .__hash__() == hash(1)\n True\n >>> int.__hash__() == hash(int)\n Traceback (most recent call last):\n File "", line 1, in \n TypeError: descriptor \'__hash__\' of \'int\' object needs an argument\n\nIncorrectly attempting to invoke an unbound method of a class in this\nway is sometimes referred to as \'metaclass confusion\', and is avoided\nby bypassing the instance when looking up special methods:\n\n >>> type(1).__hash__(1) == hash(1)\n True\n >>> type(int).__hash__(int) == hash(int)\n True\n\nIn addition to bypassing any instance attributes in the interest of\ncorrectness, implicit special method lookup generally also bypasses\nthe "__getattribute__()" method even of the object\'s metaclass:\n\n >>> class Meta(type):\n ... def __getattribute__(*args):\n ... print("Metaclass getattribute invoked")\n ... return type.__getattribute__(*args)\n ...\n >>> class C(object, metaclass=Meta):\n ... def __len__(self):\n ... return 10\n ... def __getattribute__(*args):\n ... print("Class getattribute invoked")\n ... return object.__getattribute__(*args)\n ...\n >>> c = C()\n >>> c.__len__() # Explicit lookup via instance\n Class getattribute invoked\n 10\n >>> type(c).__len__(c) # Explicit lookup via type\n Metaclass getattribute invoked\n 10\n >>> len(c) # Implicit lookup\n 10\n\nBypassing the "__getattribute__()" machinery in this fashion provides\nsignificant scope for speed optimisations within the interpreter, at\nthe cost of some flexibility in the handling of special methods (the\nspecial method *must* be set on the class object itself in order to be\nconsistently invoked by the interpreter).\n\n-[ Footnotes ]-\n\n[1] It *is* possible in some cases to change an object\'s type,\n under certain controlled conditions. It generally isn\'t a good\n idea though, since it can lead to some very strange behaviour if\n it is handled incorrectly.\n\n[2] For operands of the same type, it is assumed that if the non-\n reflected method (such as "__add__()") fails the operation is not\n supported, which is why the reflected method is not called.\n', + 'string-methods': u'\nString Methods\n**************\n\nStrings implement all of the *common* sequence operations, along with\nthe additional methods described below.\n\nStrings also support two styles of string formatting, one providing a\nlarge degree of flexibility and customization (see "str.format()",\n*Format String Syntax* and *String Formatting*) and the other based on\nC "printf" style formatting that handles a narrower range of types and\nis slightly harder to use correctly, but is often faster for the cases\nit can handle (*printf-style String Formatting*).\n\nThe *Text Processing Services* section of the standard library covers\na number of other modules that provide various text related utilities\n(including regular expression support in the "re" module).\n\nstr.capitalize()\n\n Return a copy of the string with its first character capitalized\n and the rest lowercased.\n\nstr.casefold()\n\n Return a casefolded copy of the string. Casefolded strings may be\n used for caseless matching.\n\n Casefolding is similar to lowercasing but more aggressive because\n it is intended to remove all case distinctions in a string. For\n example, the German lowercase letter "\'\xdf\'" is equivalent to ""ss"".\n Since it is already lowercase, "lower()" would do nothing to "\'\xdf\'";\n "casefold()" converts it to ""ss"".\n\n The casefolding algorithm is described in section 3.13 of the\n Unicode Standard.\n\n New in version 3.3.\n\nstr.center(width[, fillchar])\n\n Return centered in a string of length *width*. Padding is done\n using the specified *fillchar* (default is an ASCII space). The\n original string is returned if *width* is less than or equal to\n "len(s)".\n\nstr.count(sub[, start[, end]])\n\n Return the number of non-overlapping occurrences of substring *sub*\n in the range [*start*, *end*]. Optional arguments *start* and\n *end* are interpreted as in slice notation.\n\nstr.encode(encoding="utf-8", errors="strict")\n\n Return an encoded version of the string as a bytes object. Default\n encoding is "\'utf-8\'". *errors* may be given to set a different\n error handling scheme. The default for *errors* is "\'strict\'",\n meaning that encoding errors raise a "UnicodeError". Other possible\n values are "\'ignore\'", "\'replace\'", "\'xmlcharrefreplace\'",\n "\'backslashreplace\'" and any other name registered via\n "codecs.register_error()", see section *Error Handlers*. For a list\n of possible encodings, see section *Standard Encodings*.\n\n Changed in version 3.1: Support for keyword arguments added.\n\nstr.endswith(suffix[, start[, end]])\n\n Return "True" if the string ends with the specified *suffix*,\n otherwise return "False". *suffix* can also be a tuple of suffixes\n to look for. With optional *start*, test beginning at that\n position. With optional *end*, stop comparing at that position.\n\nstr.expandtabs(tabsize=8)\n\n Return a copy of the string where all tab characters are replaced\n by one or more spaces, depending on the current column and the\n given tab size. Tab positions occur every *tabsize* characters\n (default is 8, giving tab positions at columns 0, 8, 16 and so on).\n To expand the string, the current column is set to zero and the\n string is examined character by character. If the character is a\n tab ("\\t"), one or more space characters are inserted in the result\n until the current column is equal to the next tab position. (The\n tab character itself is not copied.) If the character is a newline\n ("\\n") or return ("\\r"), it is copied and the current column is\n reset to zero. Any other character is copied unchanged and the\n current column is incremented by one regardless of how the\n character is represented when printed.\n\n >>> \'01\\t012\\t0123\\t01234\'.expandtabs()\n \'01 012 0123 01234\'\n >>> \'01\\t012\\t0123\\t01234\'.expandtabs(4)\n \'01 012 0123 01234\'\n\nstr.find(sub[, start[, end]])\n\n Return the lowest index in the string where substring *sub* is\n found, such that *sub* is contained in the slice "s[start:end]".\n Optional arguments *start* and *end* are interpreted as in slice\n notation. Return "-1" if *sub* is not found.\n\n Note: The "find()" method should be used only if you need to know\n the position of *sub*. To check if *sub* is a substring or not,\n use the "in" operator:\n\n >>> \'Py\' in \'Python\'\n True\n\nstr.format(*args, **kwargs)\n\n Perform a string formatting operation. The string on which this\n method is called can contain literal text or replacement fields\n delimited by braces "{}". Each replacement field contains either\n the numeric index of a positional argument, or the name of a\n keyword argument. Returns a copy of the string where each\n replacement field is replaced with the string value of the\n corresponding argument.\n\n >>> "The sum of 1 + 2 is {0}".format(1+2)\n \'The sum of 1 + 2 is 3\'\n\n See *Format String Syntax* for a description of the various\n formatting options that can be specified in format strings.\n\nstr.format_map(mapping)\n\n Similar to "str.format(**mapping)", except that "mapping" is used\n directly and not copied to a "dict". This is useful if for example\n "mapping" is a dict subclass:\n\n >>> class Default(dict):\n ... def __missing__(self, key):\n ... return key\n ...\n >>> \'{name} was born in {country}\'.format_map(Default(name=\'Guido\'))\n \'Guido was born in country\'\n\n New in version 3.2.\n\nstr.index(sub[, start[, end]])\n\n Like "find()", but raise "ValueError" when the substring is not\n found.\n\nstr.isalnum()\n\n Return true if all characters in the string are alphanumeric and\n there is at least one character, false otherwise. A character "c"\n is alphanumeric if one of the following returns "True":\n "c.isalpha()", "c.isdecimal()", "c.isdigit()", or "c.isnumeric()".\n\nstr.isalpha()\n\n Return true if all characters in the string are alphabetic and\n there is at least one character, false otherwise. Alphabetic\n characters are those characters defined in the Unicode character\n database as "Letter", i.e., those with general category property\n being one of "Lm", "Lt", "Lu", "Ll", or "Lo". Note that this is\n different from the "Alphabetic" property defined in the Unicode\n Standard.\n\nstr.isdecimal()\n\n Return true if all characters in the string are decimal characters\n and there is at least one character, false otherwise. Decimal\n characters are those from general category "Nd". This category\n includes digit characters, and all characters that can be used to\n form decimal-radix numbers, e.g. U+0660, ARABIC-INDIC DIGIT ZERO.\n\nstr.isdigit()\n\n Return true if all characters in the string are digits and there is\n at least one character, false otherwise. Digits include decimal\n characters and digits that need special handling, such as the\n compatibility superscript digits. Formally, a digit is a character\n that has the property value Numeric_Type=Digit or\n Numeric_Type=Decimal.\n\nstr.isidentifier()\n\n Return true if the string is a valid identifier according to the\n language definition, section *Identifiers and keywords*.\n\n Use "keyword.iskeyword()" to test for reserved identifiers such as\n "def" and "class".\n\nstr.islower()\n\n Return true if all cased characters [4] in the string are lowercase\n and there is at least one cased character, false otherwise.\n\nstr.isnumeric()\n\n Return true if all characters in the string are numeric characters,\n and there is at least one character, false otherwise. Numeric\n characters include digit characters, and all characters that have\n the Unicode numeric value property, e.g. U+2155, VULGAR FRACTION\n ONE FIFTH. Formally, numeric characters are those with the\n property value Numeric_Type=Digit, Numeric_Type=Decimal or\n Numeric_Type=Numeric.\n\nstr.isprintable()\n\n Return true if all characters in the string are printable or the\n string is empty, false otherwise. Nonprintable characters are\n those characters defined in the Unicode character database as\n "Other" or "Separator", excepting the ASCII space (0x20) which is\n considered printable. (Note that printable characters in this\n context are those which should not be escaped when "repr()" is\n invoked on a string. It has no bearing on the handling of strings\n written to "sys.stdout" or "sys.stderr".)\n\nstr.isspace()\n\n Return true if there are only whitespace characters in the string\n and there is at least one character, false otherwise. Whitespace\n characters are those characters defined in the Unicode character\n database as "Other" or "Separator" and those with bidirectional\n property being one of "WS", "B", or "S".\n\nstr.istitle()\n\n Return true if the string is a titlecased string and there is at\n least one character, for example uppercase characters may only\n follow uncased characters and lowercase characters only cased ones.\n Return false otherwise.\n\nstr.isupper()\n\n Return true if all cased characters [4] in the string are uppercase\n and there is at least one cased character, false otherwise.\n\nstr.join(iterable)\n\n Return a string which is the concatenation of the strings in the\n *iterable* *iterable*. A "TypeError" will be raised if there are\n any non-string values in *iterable*, including "bytes" objects.\n The separator between elements is the string providing this method.\n\nstr.ljust(width[, fillchar])\n\n Return the string left justified in a string of length *width*.\n Padding is done using the specified *fillchar* (default is an ASCII\n space). The original string is returned if *width* is less than or\n equal to "len(s)".\n\nstr.lower()\n\n Return a copy of the string with all the cased characters [4]\n converted to lowercase.\n\n The lowercasing algorithm used is described in section 3.13 of the\n Unicode Standard.\n\nstr.lstrip([chars])\n\n Return a copy of the string with leading characters removed. The\n *chars* argument is a string specifying the set of characters to be\n removed. If omitted or "None", the *chars* argument defaults to\n removing whitespace. The *chars* argument is not a prefix; rather,\n all combinations of its values are stripped:\n\n >>> \' spacious \'.lstrip()\n \'spacious \'\n >>> \'www.example.com\'.lstrip(\'cmowz.\')\n \'example.com\'\n\nstatic str.maketrans(x[, y[, z]])\n\n This static method returns a translation table usable for\n "str.translate()".\n\n If there is only one argument, it must be a dictionary mapping\n Unicode ordinals (integers) or characters (strings of length 1) to\n Unicode ordinals, strings (of arbitrary lengths) or None.\n Character keys will then be converted to ordinals.\n\n If there are two arguments, they must be strings of equal length,\n and in the resulting dictionary, each character in x will be mapped\n to the character at the same position in y. If there is a third\n argument, it must be a string, whose characters will be mapped to\n None in the result.\n\nstr.partition(sep)\n\n Split the string at the first occurrence of *sep*, and return a\n 3-tuple containing the part before the separator, the separator\n itself, and the part after the separator. If the separator is not\n found, return a 3-tuple containing the string itself, followed by\n two empty strings.\n\nstr.replace(old, new[, count])\n\n Return a copy of the string with all occurrences of substring *old*\n replaced by *new*. If the optional argument *count* is given, only\n the first *count* occurrences are replaced.\n\nstr.rfind(sub[, start[, end]])\n\n Return the highest index in the string where substring *sub* is\n found, such that *sub* is contained within "s[start:end]".\n Optional arguments *start* and *end* are interpreted as in slice\n notation. Return "-1" on failure.\n\nstr.rindex(sub[, start[, end]])\n\n Like "rfind()" but raises "ValueError" when the substring *sub* is\n not found.\n\nstr.rjust(width[, fillchar])\n\n Return the string right justified in a string of length *width*.\n Padding is done using the specified *fillchar* (default is an ASCII\n space). The original string is returned if *width* is less than or\n equal to "len(s)".\n\nstr.rpartition(sep)\n\n Split the string at the last occurrence of *sep*, and return a\n 3-tuple containing the part before the separator, the separator\n itself, and the part after the separator. If the separator is not\n found, return a 3-tuple containing two empty strings, followed by\n the string itself.\n\nstr.rsplit(sep=None, maxsplit=-1)\n\n Return a list of the words in the string, using *sep* as the\n delimiter string. If *maxsplit* is given, at most *maxsplit* splits\n are done, the *rightmost* ones. If *sep* is not specified or\n "None", any whitespace string is a separator. Except for splitting\n from the right, "rsplit()" behaves like "split()" which is\n described in detail below.\n\nstr.rstrip([chars])\n\n Return a copy of the string with trailing characters removed. The\n *chars* argument is a string specifying the set of characters to be\n removed. If omitted or "None", the *chars* argument defaults to\n removing whitespace. The *chars* argument is not a suffix; rather,\n all combinations of its values are stripped:\n\n >>> \' spacious \'.rstrip()\n \' spacious\'\n >>> \'mississippi\'.rstrip(\'ipz\')\n \'mississ\'\n\nstr.split(sep=None, maxsplit=-1)\n\n Return a list of the words in the string, using *sep* as the\n delimiter string. If *maxsplit* is given, at most *maxsplit*\n splits are done (thus, the list will have at most "maxsplit+1"\n elements). If *maxsplit* is not specified or "-1", then there is\n no limit on the number of splits (all possible splits are made).\n\n If *sep* is given, consecutive delimiters are not grouped together\n and are deemed to delimit empty strings (for example,\n "\'1,,2\'.split(\',\')" returns "[\'1\', \'\', \'2\']"). The *sep* argument\n may consist of multiple characters (for example,\n "\'1<>2<>3\'.split(\'<>\')" returns "[\'1\', \'2\', \'3\']"). Splitting an\n empty string with a specified separator returns "[\'\']".\n\n For example:\n\n >>> \'1,2,3\'.split(\',\')\n [\'1\', \'2\', \'3\']\n >>> \'1,2,3\'.split(\',\', maxsplit=1)\n [\'1\', \'2,3\']\n >>> \'1,2,,3,\'.split(\',\')\n [\'1\', \'2\', \'\', \'3\', \'\']\n\n If *sep* is not specified or is "None", a different splitting\n algorithm is applied: runs of consecutive whitespace are regarded\n as a single separator, and the result will contain no empty strings\n at the start or end if the string has leading or trailing\n whitespace. Consequently, splitting an empty string or a string\n consisting of just whitespace with a "None" separator returns "[]".\n\n For example:\n\n >>> \'1 2 3\'.split()\n [\'1\', \'2\', \'3\']\n >>> \'1 2 3\'.split(maxsplit=1)\n [\'1\', \'2 3\']\n >>> \' 1 2 3 \'.split()\n [\'1\', \'2\', \'3\']\n\nstr.splitlines([keepends])\n\n Return a list of the lines in the string, breaking at line\n boundaries. Line breaks are not included in the resulting list\n unless *keepends* is given and true.\n\n This method splits on the following line boundaries. In\n particular, the boundaries are a superset of *universal newlines*.\n\n +-------------------------+-------------------------------+\n | Representation | Description |\n +=========================+===============================+\n | "\\n" | Line Feed |\n +-------------------------+-------------------------------+\n | "\\r" | Carriage Return |\n +-------------------------+-------------------------------+\n | "\\r\\n" | Carriage Return + Line Feed |\n +-------------------------+-------------------------------+\n | "\\v" or "\\x0b" | Line Tabulation |\n +-------------------------+-------------------------------+\n | "\\f" or "\\x0c" | Form Feed |\n +-------------------------+-------------------------------+\n | "\\x1c" | File Separator |\n +-------------------------+-------------------------------+\n | "\\x1d" | Group Separator |\n +-------------------------+-------------------------------+\n | "\\x1e" | Record Separator |\n +-------------------------+-------------------------------+\n | "\\x85" | Next Line (C1 Control Code) |\n +-------------------------+-------------------------------+\n | "\\u2028" | Line Separator |\n +-------------------------+-------------------------------+\n | "\\u2029" | Paragraph Separator |\n +-------------------------+-------------------------------+\n\n Changed in version 3.2: "\\v" and "\\f" added to list of line\n boundaries.\n\n For example:\n\n >>> \'ab c\\n\\nde fg\\rkl\\r\\n\'.splitlines()\n [\'ab c\', \'\', \'de fg\', \'kl\']\n >>> \'ab c\\n\\nde fg\\rkl\\r\\n\'.splitlines(keepends=True)\n [\'ab c\\n\', \'\\n\', \'de fg\\r\', \'kl\\r\\n\']\n\n Unlike "split()" when a delimiter string *sep* is given, this\n method returns an empty list for the empty string, and a terminal\n line break does not result in an extra line:\n\n >>> "".splitlines()\n []\n >>> "One line\\n".splitlines()\n [\'One line\']\n\n For comparison, "split(\'\\n\')" gives:\n\n >>> \'\'.split(\'\\n\')\n [\'\']\n >>> \'Two lines\\n\'.split(\'\\n\')\n [\'Two lines\', \'\']\n\nstr.startswith(prefix[, start[, end]])\n\n Return "True" if string starts with the *prefix*, otherwise return\n "False". *prefix* can also be a tuple of prefixes to look for.\n With optional *start*, test string beginning at that position.\n With optional *end*, stop comparing string at that position.\n\nstr.strip([chars])\n\n Return a copy of the string with the leading and trailing\n characters removed. The *chars* argument is a string specifying the\n set of characters to be removed. If omitted or "None", the *chars*\n argument defaults to removing whitespace. The *chars* argument is\n not a prefix or suffix; rather, all combinations of its values are\n stripped:\n\n >>> \' spacious \'.strip()\n \'spacious\'\n >>> \'www.example.com\'.strip(\'cmowz.\')\n \'example\'\n\nstr.swapcase()\n\n Return a copy of the string with uppercase characters converted to\n lowercase and vice versa. Note that it is not necessarily true that\n "s.swapcase().swapcase() == s".\n\nstr.title()\n\n Return a titlecased version of the string where words start with an\n uppercase character and the remaining characters are lowercase.\n\n For example:\n\n >>> \'Hello world\'.title()\n \'Hello World\'\n\n The algorithm uses a simple language-independent definition of a\n word as groups of consecutive letters. The definition works in\n many contexts but it means that apostrophes in contractions and\n possessives form word boundaries, which may not be the desired\n result:\n\n >>> "they\'re bill\'s friends from the UK".title()\n "They\'Re Bill\'S Friends From The Uk"\n\n A workaround for apostrophes can be constructed using regular\n expressions:\n\n >>> import re\n >>> def titlecase(s):\n ... return re.sub(r"[A-Za-z]+(\'[A-Za-z]+)?",\n ... lambda mo: mo.group(0)[0].upper() +\n ... mo.group(0)[1:].lower(),\n ... s)\n ...\n >>> titlecase("they\'re bill\'s friends.")\n "They\'re Bill\'s Friends."\n\nstr.translate(map)\n\n Return a copy of the *s* where all characters have been mapped\n through the *map* which must be a dictionary of Unicode ordinals\n (integers) to Unicode ordinals, strings or "None". Unmapped\n characters are left untouched. Characters mapped to "None" are\n deleted.\n\n You can use "str.maketrans()" to create a translation map from\n character-to-character mappings in different formats.\n\n Note: An even more flexible approach is to create a custom\n character mapping codec using the "codecs" module (see\n "encodings.cp1251" for an example).\n\nstr.upper()\n\n Return a copy of the string with all the cased characters [4]\n converted to uppercase. Note that "str.upper().isupper()" might be\n "False" if "s" contains uncased characters or if the Unicode\n category of the resulting character(s) is not "Lu" (Letter,\n uppercase), but e.g. "Lt" (Letter, titlecase).\n\n The uppercasing algorithm used is described in section 3.13 of the\n Unicode Standard.\n\nstr.zfill(width)\n\n Return a copy of the string left filled with ASCII "\'0\'" digits to\n make a string of length *width*. A leading sign prefix\n ("\'+\'"/"\'-\'") is handled by inserting the padding *after* the sign\n character rather than before. The original string is returned if\n *width* is less than or equal to "len(s)".\n\n For example:\n\n >>> "42".zfill(5)\n \'00042\'\n >>> "-42".zfill(5)\n \'-0042\'\n', 'strings': u'\nString and Bytes literals\n*************************\n\nString literals are described by the following lexical definitions:\n\n stringliteral ::= [stringprefix](shortstring | longstring)\n stringprefix ::= "r" | "u" | "R" | "U"\n shortstring ::= "\'" shortstringitem* "\'" | \'"\' shortstringitem* \'"\'\n longstring ::= "\'\'\'" longstringitem* "\'\'\'" | \'"""\' longstringitem* \'"""\'\n shortstringitem ::= shortstringchar | stringescapeseq\n longstringitem ::= longstringchar | stringescapeseq\n shortstringchar ::= \n longstringchar ::= \n stringescapeseq ::= "\\" \n\n bytesliteral ::= bytesprefix(shortbytes | longbytes)\n bytesprefix ::= "b" | "B" | "br" | "Br" | "bR" | "BR" | "rb" | "rB" | "Rb" | "RB"\n shortbytes ::= "\'" shortbytesitem* "\'" | \'"\' shortbytesitem* \'"\'\n longbytes ::= "\'\'\'" longbytesitem* "\'\'\'" | \'"""\' longbytesitem* \'"""\'\n shortbytesitem ::= shortbyteschar | bytesescapeseq\n longbytesitem ::= longbyteschar | bytesescapeseq\n shortbyteschar ::= \n longbyteschar ::= \n bytesescapeseq ::= "\\" \n\nOne syntactic restriction not indicated by these productions is that\nwhitespace is not allowed between the "stringprefix" or "bytesprefix"\nand the rest of the literal. The source character set is defined by\nthe encoding declaration; it is UTF-8 if no encoding declaration is\ngiven in the source file; see section *Encoding declarations*.\n\nIn plain English: Both types of literals can be enclosed in matching\nsingle quotes ("\'") or double quotes ("""). They can also be enclosed\nin matching groups of three single or double quotes (these are\ngenerally referred to as *triple-quoted strings*). The backslash\n("\\") character is used to escape characters that otherwise have a\nspecial meaning, such as newline, backslash itself, or the quote\ncharacter.\n\nBytes literals are always prefixed with "\'b\'" or "\'B\'"; they produce\nan instance of the "bytes" type instead of the "str" type. They may\nonly contain ASCII characters; bytes with a numeric value of 128 or\ngreater must be expressed with escapes.\n\nAs of Python 3.3 it is possible again to prefix string literals with a\n"u" prefix to simplify maintenance of dual 2.x and 3.x codebases.\n\nBoth string and bytes literals may optionally be prefixed with a\nletter "\'r\'" or "\'R\'"; such strings are called *raw strings* and treat\nbackslashes as literal characters. As a result, in string literals,\n"\'\\U\'" and "\'\\u\'" escapes in raw strings are not treated specially.\nGiven that Python 2.x\'s raw unicode literals behave differently than\nPython 3.x\'s the "\'ur\'" syntax is not supported.\n\nNew in version 3.3: The "\'rb\'" prefix of raw bytes literals has been\nadded as a synonym of "\'br\'".\n\nNew in version 3.3: Support for the unicode legacy literal\n("u\'value\'") was reintroduced to simplify the maintenance of dual\nPython 2.x and 3.x codebases. See **PEP 414** for more information.\n\nIn triple-quoted literals, unescaped newlines and quotes are allowed\n(and are retained), except that three unescaped quotes in a row\nterminate the literal. (A "quote" is the character used to open the\nliteral, i.e. either "\'" or """.)\n\nUnless an "\'r\'" or "\'R\'" prefix is present, escape sequences in string\nand bytes literals are interpreted according to rules similar to those\nused by Standard C. The recognized escape sequences are:\n\n+-------------------+-----------------------------------+---------+\n| Escape Sequence | Meaning | Notes |\n+===================+===================================+=========+\n| "\\newline" | Backslash and newline ignored | |\n+-------------------+-----------------------------------+---------+\n| "\\\\" | Backslash ("\\") | |\n+-------------------+-----------------------------------+---------+\n| "\\\'" | Single quote ("\'") | |\n+-------------------+-----------------------------------+---------+\n| "\\"" | Double quote (""") | |\n+-------------------+-----------------------------------+---------+\n| "\\a" | ASCII Bell (BEL) | |\n+-------------------+-----------------------------------+---------+\n| "\\b" | ASCII Backspace (BS) | |\n+-------------------+-----------------------------------+---------+\n| "\\f" | ASCII Formfeed (FF) | |\n+-------------------+-----------------------------------+---------+\n| "\\n" | ASCII Linefeed (LF) | |\n+-------------------+-----------------------------------+---------+\n| "\\r" | ASCII Carriage Return (CR) | |\n+-------------------+-----------------------------------+---------+\n| "\\t" | ASCII Horizontal Tab (TAB) | |\n+-------------------+-----------------------------------+---------+\n| "\\v" | ASCII Vertical Tab (VT) | |\n+-------------------+-----------------------------------+---------+\n| "\\ooo" | Character with octal value *ooo* | (1,3) |\n+-------------------+-----------------------------------+---------+\n| "\\xhh" | Character with hex value *hh* | (2,3) |\n+-------------------+-----------------------------------+---------+\n\nEscape sequences only recognized in string literals are:\n\n+-------------------+-----------------------------------+---------+\n| Escape Sequence | Meaning | Notes |\n+===================+===================================+=========+\n| "\\N{name}" | Character named *name* in the | (4) |\n| | Unicode database | |\n+-------------------+-----------------------------------+---------+\n| "\\uxxxx" | Character with 16-bit hex value | (5) |\n| | *xxxx* | |\n+-------------------+-----------------------------------+---------+\n| "\\Uxxxxxxxx" | Character with 32-bit hex value | (6) |\n| | *xxxxxxxx* | |\n+-------------------+-----------------------------------+---------+\n\nNotes:\n\n1. As in Standard C, up to three octal digits are accepted.\n\n2. Unlike in Standard C, exactly two hex digits are required.\n\n3. In a bytes literal, hexadecimal and octal escapes denote the\n byte with the given value. In a string literal, these escapes\n denote a Unicode character with the given value.\n\n4. Changed in version 3.3: Support for name aliases [1] has been\n added.\n\n5. Individual code units which form parts of a surrogate pair can\n be encoded using this escape sequence. Exactly four hex digits are\n required.\n\n6. Any Unicode character can be encoded this way. Exactly eight\n hex digits are required.\n\nUnlike Standard C, all unrecognized escape sequences are left in the\nstring unchanged, i.e., *the backslash is left in the result*. (This\nbehavior is useful when debugging: if an escape sequence is mistyped,\nthe resulting output is more easily recognized as broken.) It is also\nimportant to note that the escape sequences only recognized in string\nliterals fall into the category of unrecognized escapes for bytes\nliterals.\n\nEven in a raw literal, quotes can be escaped with a backslash, but the\nbackslash remains in the result; for example, "r"\\""" is a valid\nstring literal consisting of two characters: a backslash and a double\nquote; "r"\\"" is not a valid string literal (even a raw string cannot\nend in an odd number of backslashes). Specifically, *a raw literal\ncannot end in a single backslash* (since the backslash would escape\nthe following quote character). Note also that a single backslash\nfollowed by a newline is interpreted as those two characters as part\nof the literal, *not* as a line continuation.\n', 'subscriptions': u'\nSubscriptions\n*************\n\nA subscription selects an item of a sequence (string, tuple or list)\nor mapping (dictionary) object:\n\n subscription ::= primary "[" expression_list "]"\n\nThe primary must evaluate to an object that supports subscription\n(lists or dictionaries for example). User-defined objects can support\nsubscription by defining a "__getitem__()" method.\n\nFor built-in objects, there are two types of objects that support\nsubscription:\n\nIf the primary is a mapping, the expression list must evaluate to an\nobject whose value is one of the keys of the mapping, and the\nsubscription selects the value in the mapping that corresponds to that\nkey. (The expression list is a tuple except if it has exactly one\nitem.)\n\nIf the primary is a sequence, the expression (list) must evaluate to\nan integer or a slice (as discussed in the following section).\n\nThe formal syntax makes no special provision for negative indices in\nsequences; however, built-in sequences all provide a "__getitem__()"\nmethod that interprets negative indices by adding the length of the\nsequence to the index (so that "x[-1]" selects the last item of "x").\nThe resulting value must be a nonnegative integer less than the number\nof items in the sequence, and the subscription selects the item whose\nindex is that value (counting from zero). Since the support for\nnegative indices and slicing occurs in the object\'s "__getitem__()"\nmethod, subclasses overriding this method will need to explicitly add\nthat support.\n\nA string\'s items are characters. A character is not a separate data\ntype but a string of exactly one character.\n', 'truth': u'\nTruth Value Testing\n*******************\n\nAny object can be tested for truth value, for use in an "if" or\n"while" condition or as operand of the Boolean operations below. The\nfollowing values are considered false:\n\n* "None"\n\n* "False"\n\n* zero of any numeric type, for example, "0", "0.0", "0j".\n\n* any empty sequence, for example, "\'\'", "()", "[]".\n\n* any empty mapping, for example, "{}".\n\n* instances of user-defined classes, if the class defines a\n "__bool__()" or "__len__()" method, when that method returns the\n integer zero or "bool" value "False". [1]\n\nAll other values are considered true --- so objects of many types are\nalways true.\n\nOperations and built-in functions that have a Boolean result always\nreturn "0" or "False" for false and "1" or "True" for true, unless\notherwise stated. (Important exception: the Boolean operations "or"\nand "and" always return one of their operands.)\n', -- Repository URL: https://hg.python.org/cpython From solipsis at pitrou.net Mon Apr 20 10:43:10 2015 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Mon, 20 Apr 2015 08:43:10 +0000 Subject: [Python-checkins] Daily reference leaks (8d9bf18defd7): sum=6 Message-ID: <20150420084306.31125.58541@psf.io> results for 8d9bf18defd7 on branch "default" -------------------------------------------- test_asyncio leaked [0, 3, 0] memory blocks, sum=3 test_functools leaked [0, 0, 3] memory blocks, sum=3 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogpZ3kkn', '--timeout', '7200'] From python-checkins at python.org Mon Apr 20 13:08:22 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Mon, 20 Apr 2015 11:08:22 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzE2ODQw?= =?utf-8?q?=3A_Turn_on_support_of_bignums_only_in_final_release_of_Tcl_8?= =?utf-8?b?LjUu?= Message-ID: <20150420110809.21339.14105@psf.io> https://hg.python.org/cpython/rev/7f1622478d17 changeset: 95740:7f1622478d17 branch: 3.4 parent: 95732:cdadde8396a4 user: Serhiy Storchaka date: Mon Apr 20 14:05:37 2015 +0300 summary: Issue #16840: Turn on support of bignums only in final release of Tcl 8.5. files: Modules/_tkinter.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Modules/_tkinter.c b/Modules/_tkinter.c --- a/Modules/_tkinter.c +++ b/Modules/_tkinter.c @@ -69,7 +69,7 @@ #error "Tk older than 8.3.1 not supported" #endif -#if TK_VERSION_HEX >= 0x08050000 +#if TK_VERSION_HEX >= 0x08050002 #define HAVE_LIBTOMMAMTH #include #endif -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Apr 20 13:08:22 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Mon, 20 Apr 2015 11:08:22 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzE2ODQw?= =?utf-8?q?=3A_Turn_on_support_of_bignums_only_in_final_release_of_Tcl_8?= =?utf-8?b?LjUu?= Message-ID: <20150420110809.6585.56642@psf.io> https://hg.python.org/cpython/rev/8ab077c22fbf changeset: 95739:8ab077c22fbf branch: 2.7 parent: 95731:17702fd8ac0d user: Serhiy Storchaka date: Mon Apr 20 14:05:37 2015 +0300 summary: Issue #16840: Turn on support of bignums only in final release of Tcl 8.5. files: Modules/_tkinter.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Modules/_tkinter.c b/Modules/_tkinter.c --- a/Modules/_tkinter.c +++ b/Modules/_tkinter.c @@ -96,7 +96,7 @@ #error "unsupported Tcl configuration" #endif -#if TK_VERSION_HEX >= 0x08050000 +#if TK_VERSION_HEX >= 0x08050002 #define HAVE_LIBTOMMAMTH #include #endif -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Apr 20 13:08:22 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Mon, 20 Apr 2015 11:08:22 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2316840=3A_Turn_on_support_of_bignums_only_in_fin?= =?utf-8?q?al_release_of_Tcl_8=2E5=2E?= Message-ID: <20150420110809.6591.39000@psf.io> https://hg.python.org/cpython/rev/7a7f09528866 changeset: 95741:7a7f09528866 parent: 95738:09fa20da2872 parent: 95740:7f1622478d17 user: Serhiy Storchaka date: Mon Apr 20 14:07:41 2015 +0300 summary: Issue #16840: Turn on support of bignums only in final release of Tcl 8.5. files: Modules/_tkinter.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Modules/_tkinter.c b/Modules/_tkinter.c --- a/Modules/_tkinter.c +++ b/Modules/_tkinter.c @@ -56,7 +56,7 @@ #error "Tk older than 8.4 not supported" #endif -#if TK_VERSION_HEX >= 0x08050000 +#if TK_VERSION_HEX >= 0x08050002 #define HAVE_LIBTOMMAMTH #include #endif -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Apr 20 18:25:41 2015 From: python-checkins at python.org (guido.van.rossum) Date: Mon, 20 Apr 2015 16:25:41 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E4=29=3A_Fix_asyncio_is?= =?utf-8?q?sue_235=3A_Queue_subclass_bug_caused_by_JoinableQueue_merge=2E?= Message-ID: <20150420162539.27930.87664@psf.io> https://hg.python.org/cpython/rev/8e0dc4d3b49c changeset: 95742:8e0dc4d3b49c branch: 3.4 parent: 95740:7f1622478d17 user: Guido van Rossum date: Mon Apr 20 09:24:24 2015 -0700 summary: Fix asyncio issue 235: Queue subclass bug caused by JoinableQueue merge. files: Lib/asyncio/queues.py | 19 ++++++++---- Lib/test/test_asyncio/test_queues.py | 24 ++++++++++++--- Misc/NEWS | 4 ++ 3 files changed, 36 insertions(+), 11 deletions(-) diff --git a/Lib/asyncio/queues.py b/Lib/asyncio/queues.py --- a/Lib/asyncio/queues.py +++ b/Lib/asyncio/queues.py @@ -54,6 +54,8 @@ self._finished.set() self._init(maxsize) + # These three are overridable in subclasses. + def _init(self, maxsize): self._queue = collections.deque() @@ -62,6 +64,11 @@ def _put(self, item): self._queue.append(item) + + # End of the overridable methods. + + def __put_internal(self, item): + self._put(item) self._unfinished_tasks += 1 self._finished.clear() @@ -133,7 +140,7 @@ 'queue non-empty, why are getters waiting?') getter = self._getters.popleft() - self._put(item) + self.__put_internal(item) # getter cannot be cancelled, we just removed done getters getter.set_result(self._get()) @@ -145,7 +152,7 @@ yield from waiter else: - self._put(item) + self.__put_internal(item) def put_nowait(self, item): """Put an item into the queue without blocking. @@ -158,7 +165,7 @@ 'queue non-empty, why are getters waiting?') getter = self._getters.popleft() - self._put(item) + self.__put_internal(item) # getter cannot be cancelled, we just removed done getters getter.set_result(self._get()) @@ -166,7 +173,7 @@ elif self._maxsize > 0 and self._maxsize <= self.qsize(): raise QueueFull else: - self._put(item) + self.__put_internal(item) @coroutine def get(self): @@ -180,7 +187,7 @@ if self._putters: assert self.full(), 'queue not full, why are putters waiting?' item, putter = self._putters.popleft() - self._put(item) + self.__put_internal(item) # When a getter runs and frees up a slot so this putter can # run, we need to defer the put for a tick to ensure that @@ -207,7 +214,7 @@ if self._putters: assert self.full(), 'queue not full, why are putters waiting?' item, putter = self._putters.popleft() - self._put(item) + self.__put_internal(item) # Wake putter on next tick. # getter cannot be cancelled, we just removed done putters diff --git a/Lib/test/test_asyncio/test_queues.py b/Lib/test/test_asyncio/test_queues.py --- a/Lib/test/test_asyncio/test_queues.py +++ b/Lib/test/test_asyncio/test_queues.py @@ -408,14 +408,16 @@ self.assertEqual([1, 2, 3], items) -class QueueJoinTests(_QueueTestBase): +class _QueueJoinTestMixin: + + q_class = None def test_task_done_underflow(self): - q = asyncio.Queue(loop=self.loop) + q = self.q_class(loop=self.loop) self.assertRaises(ValueError, q.task_done) def test_task_done(self): - q = asyncio.Queue(loop=self.loop) + q = self.q_class(loop=self.loop) for i in range(100): q.put_nowait(i) @@ -452,7 +454,7 @@ self.loop.run_until_complete(asyncio.wait(tasks, loop=self.loop)) def test_join_empty_queue(self): - q = asyncio.Queue(loop=self.loop) + q = self.q_class(loop=self.loop) # Test that a queue join()s successfully, and before anything else # (done twice for insurance). @@ -465,12 +467,24 @@ self.loop.run_until_complete(join()) def test_format(self): - q = asyncio.Queue(loop=self.loop) + q = self.q_class(loop=self.loop) self.assertEqual(q._format(), 'maxsize=0') q._unfinished_tasks = 2 self.assertEqual(q._format(), 'maxsize=0 tasks=2') +class QueueJoinTests(_QueueJoinTestMixin, _QueueTestBase): + q_class = asyncio.Queue + + +class LifoQueueJoinTests(_QueueJoinTestMixin, _QueueTestBase): + q_class = asyncio.LifoQueue + + +class PriorityQueueJoinTests(_QueueJoinTestMixin, _QueueTestBase): + q_class = asyncio.PriorityQueue + + if __name__ == '__main__': unittest.main() diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -29,6 +29,10 @@ Library ------- +- Fix asyncio issue 235: LifoQueue and PriorityQueue's put didn't + increment unfinished tasks (this bug was introduced in 3.4.3 when + JoinableQueue was merged with Queue). + - Issue #23908: os functions now reject paths with embedded null character on Windows instead of silently truncate them. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Apr 20 18:30:15 2015 From: python-checkins at python.org (guido.van.rossum) Date: Mon, 20 Apr 2015 16:30:15 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Fix_asyncio_issue_235_=28merge_from_3=2E4=29=2E?= Message-ID: <20150420163011.27928.68702@psf.io> https://hg.python.org/cpython/rev/c3cd486cb6b9 changeset: 95743:c3cd486cb6b9 parent: 95741:7a7f09528866 parent: 95742:8e0dc4d3b49c user: Guido van Rossum date: Mon Apr 20 09:29:57 2015 -0700 summary: Fix asyncio issue 235 (merge from 3.4). files: Lib/asyncio/queues.py | 19 ++++++++---- Lib/test/test_asyncio/test_queues.py | 24 ++++++++++++--- Misc/NEWS | 4 ++ 3 files changed, 36 insertions(+), 11 deletions(-) diff --git a/Lib/asyncio/queues.py b/Lib/asyncio/queues.py --- a/Lib/asyncio/queues.py +++ b/Lib/asyncio/queues.py @@ -53,6 +53,8 @@ self._finished.set() self._init(maxsize) + # These three are overridable in subclasses. + def _init(self, maxsize): self._queue = collections.deque() @@ -61,6 +63,11 @@ def _put(self, item): self._queue.append(item) + + # End of the overridable methods. + + def __put_internal(self, item): + self._put(item) self._unfinished_tasks += 1 self._finished.clear() @@ -132,7 +139,7 @@ 'queue non-empty, why are getters waiting?') getter = self._getters.popleft() - self._put(item) + self.__put_internal(item) # getter cannot be cancelled, we just removed done getters getter.set_result(self._get()) @@ -144,7 +151,7 @@ yield from waiter else: - self._put(item) + self.__put_internal(item) def put_nowait(self, item): """Put an item into the queue without blocking. @@ -157,7 +164,7 @@ 'queue non-empty, why are getters waiting?') getter = self._getters.popleft() - self._put(item) + self.__put_internal(item) # getter cannot be cancelled, we just removed done getters getter.set_result(self._get()) @@ -165,7 +172,7 @@ elif self._maxsize > 0 and self._maxsize <= self.qsize(): raise QueueFull else: - self._put(item) + self.__put_internal(item) @coroutine def get(self): @@ -179,7 +186,7 @@ if self._putters: assert self.full(), 'queue not full, why are putters waiting?' item, putter = self._putters.popleft() - self._put(item) + self.__put_internal(item) # When a getter runs and frees up a slot so this putter can # run, we need to defer the put for a tick to ensure that @@ -206,7 +213,7 @@ if self._putters: assert self.full(), 'queue not full, why are putters waiting?' item, putter = self._putters.popleft() - self._put(item) + self.__put_internal(item) # Wake putter on next tick. # getter cannot be cancelled, we just removed done putters diff --git a/Lib/test/test_asyncio/test_queues.py b/Lib/test/test_asyncio/test_queues.py --- a/Lib/test/test_asyncio/test_queues.py +++ b/Lib/test/test_asyncio/test_queues.py @@ -408,14 +408,16 @@ self.assertEqual([1, 2, 3], items) -class QueueJoinTests(_QueueTestBase): +class _QueueJoinTestMixin: + + q_class = None def test_task_done_underflow(self): - q = asyncio.Queue(loop=self.loop) + q = self.q_class(loop=self.loop) self.assertRaises(ValueError, q.task_done) def test_task_done(self): - q = asyncio.Queue(loop=self.loop) + q = self.q_class(loop=self.loop) for i in range(100): q.put_nowait(i) @@ -452,7 +454,7 @@ self.loop.run_until_complete(asyncio.wait(tasks, loop=self.loop)) def test_join_empty_queue(self): - q = asyncio.Queue(loop=self.loop) + q = self.q_class(loop=self.loop) # Test that a queue join()s successfully, and before anything else # (done twice for insurance). @@ -465,12 +467,24 @@ self.loop.run_until_complete(join()) def test_format(self): - q = asyncio.Queue(loop=self.loop) + q = self.q_class(loop=self.loop) self.assertEqual(q._format(), 'maxsize=0') q._unfinished_tasks = 2 self.assertEqual(q._format(), 'maxsize=0 tasks=2') +class QueueJoinTests(_QueueJoinTestMixin, _QueueTestBase): + q_class = asyncio.Queue + + +class LifoQueueJoinTests(_QueueJoinTestMixin, _QueueTestBase): + q_class = asyncio.LifoQueue + + +class PriorityQueueJoinTests(_QueueJoinTestMixin, _QueueTestBase): + q_class = asyncio.PriorityQueue + + if __name__ == '__main__': unittest.main() diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -49,6 +49,10 @@ Library ------- +- Fix asyncio issue 235: LifoQueue and PriorityQueue's put didn't + increment unfinished tasks (this bug was introduced when + JoinableQueue was merged with Queue). + - Issue #23908: os functions now reject paths with embedded null character on Windows instead of silently truncate them. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Apr 20 21:05:31 2015 From: python-checkins at python.org (matthias.klose) Date: Mon, 20 Apr 2015 19:05:31 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A__-_move_some_NEWS_items_to?= =?utf-8?q?_3=2E5=2E0_beta_1?= Message-ID: <20150420190531.31113.77802@psf.io> https://hg.python.org/cpython/rev/ccac513ee610 changeset: 95744:ccac513ee610 user: doko at ubuntu.com date: Mon Apr 20 21:05:23 2015 +0200 summary: - move some NEWS items to 3.5.0 beta 1 files: Misc/NEWS | 20 ++++++++++---------- 1 files changed, 10 insertions(+), 10 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -13,6 +13,16 @@ Library ------- +- Fix asyncio issue 235: LifoQueue and PriorityQueue's put didn't + increment unfinished tasks (this bug was introduced when + JoinableQueue was merged with Queue). + +- Issue #23908: os functions now reject paths with embedded null character + on Windows instead of silently truncate them. + +- Issue #23728: binascii.crc_hqx() could return an integer outside of the range + 0-0xffff for empty data. + What's New in Python 3.5.0 alpha 4? =================================== @@ -49,16 +59,6 @@ Library ------- -- Fix asyncio issue 235: LifoQueue and PriorityQueue's put didn't - increment unfinished tasks (this bug was introduced when - JoinableQueue was merged with Queue). - -- Issue #23908: os functions now reject paths with embedded null character - on Windows instead of silently truncate them. - -- Issue #23728: binascii.crc_hqx() could return an integer outside of the range - 0-0xffff for empty data. - - Issue #16914: new debuglevel 2 in smtplib adds timestamps to debug output. - Issue #7159: urllib.request now supports sending auth credentials -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Apr 21 00:22:41 2015 From: python-checkins at python.org (benjamin.peterson) Date: Mon, 20 Apr 2015 22:22:41 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E4=29=3A_recommend_requ?= =?utf-8?q?ests_library_=28closes_=2323989=29?= Message-ID: <20150420222241.6607.77786@psf.io> https://hg.python.org/cpython/rev/c9239543235e changeset: 95745:c9239543235e branch: 3.4 parent: 95742:8e0dc4d3b49c user: Benjamin Peterson date: Mon Apr 20 18:18:14 2015 -0400 summary: recommend requests library (closes #23989) Patch from Van Lindberg files: Doc/library/http.client.rst | 5 +++++ Doc/library/urllib.request.rst | 5 +++++ 2 files changed, 10 insertions(+), 0 deletions(-) diff --git a/Doc/library/http.client.rst b/Doc/library/http.client.rst --- a/Doc/library/http.client.rst +++ b/Doc/library/http.client.rst @@ -19,6 +19,11 @@ HTTPS protocols. It is normally not used directly --- the module :mod:`urllib.request` uses it to handle URLs that use HTTP and HTTPS. +.. seealso:: + + The `Requests package `_ + is recommended for a higher-level http client interface. + .. note:: HTTPS support is only available if Python was compiled with SSL support 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 @@ -12,6 +12,11 @@ opening URLs (mostly HTTP) in a complex world --- basic and digest authentication, redirections, cookies and more. +.. seealso:: + + The `Requests package `_ + is recommended for a higher-level http client interface. + The :mod:`urllib.request` module defines the following functions: -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Apr 21 00:22:46 2015 From: python-checkins at python.org (benjamin.peterson) Date: Mon, 20 Apr 2015 22:22:46 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?b?KTogbWVyZ2UgMy40ICgjMjM5ODkp?= Message-ID: <20150420222246.21357.37662@psf.io> https://hg.python.org/cpython/rev/65ce1d9eee30 changeset: 95747:65ce1d9eee30 parent: 95744:ccac513ee610 parent: 95745:c9239543235e user: Benjamin Peterson date: Mon Apr 20 18:22:21 2015 -0400 summary: merge 3.4 (#23989) files: Doc/library/http.client.rst | 5 +++++ Doc/library/urllib.request.rst | 5 +++++ 2 files changed, 10 insertions(+), 0 deletions(-) diff --git a/Doc/library/http.client.rst b/Doc/library/http.client.rst --- a/Doc/library/http.client.rst +++ b/Doc/library/http.client.rst @@ -19,6 +19,11 @@ HTTPS protocols. It is normally not used directly --- the module :mod:`urllib.request` uses it to handle URLs that use HTTP and HTTPS. +.. seealso:: + + The `Requests package `_ + is recommended for a higher-level http client interface. + .. note:: HTTPS support is only available if Python was compiled with SSL support 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 @@ -12,6 +12,11 @@ opening URLs (mostly HTTP) in a complex world --- basic and digest authentication, redirections, cookies and more. +.. seealso:: + + The `Requests package `_ + is recommended for a higher-level http client interface. + The :mod:`urllib.request` module defines the following functions: -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Apr 21 00:23:00 2015 From: python-checkins at python.org (benjamin.peterson) Date: Mon, 20 Apr 2015 22:23:00 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_recommend_requ?= =?utf-8?q?ests_library_=28closes_=2323989=29?= Message-ID: <20150420222241.120224.22138@psf.io> https://hg.python.org/cpython/rev/3cf2990d19ab changeset: 95746:3cf2990d19ab branch: 2.7 parent: 95739:8ab077c22fbf user: Benjamin Peterson date: Mon Apr 20 18:20:27 2015 -0400 summary: recommend requests library (closes #23989) Patch by Van Lindberg. files: Doc/library/httplib.rst | 5 +++++ Doc/library/urllib.rst | 5 +++++ Doc/library/urllib2.rst | 5 +++++ 3 files changed, 15 insertions(+), 0 deletions(-) diff --git a/Doc/library/httplib.rst b/Doc/library/httplib.rst --- a/Doc/library/httplib.rst +++ b/Doc/library/httplib.rst @@ -24,6 +24,11 @@ HTTPS protocols. It is normally not used directly --- the module :mod:`urllib` uses it to handle URLs that use HTTP and HTTPS. +.. seealso:: + + The `Requests package `_ + is recommended for a higher-level http client interface. + .. note:: HTTPS support is only available if the :mod:`socket` module was compiled with diff --git a/Doc/library/urllib.rst b/Doc/library/urllib.rst --- a/Doc/library/urllib.rst +++ b/Doc/library/urllib.rst @@ -24,6 +24,11 @@ instead of filenames. Some restrictions apply --- it can only open URLs for reading, and no seek operations are available. +.. seealso:: + + The `Requests package `_ + is recommended for a higher-level http client interface. + .. warning:: When opening HTTPS URLs, it does not attempt to validate the server certificate. Use at your own risk! diff --git a/Doc/library/urllib2.rst b/Doc/library/urllib2.rst --- a/Doc/library/urllib2.rst +++ b/Doc/library/urllib2.rst @@ -18,6 +18,11 @@ URLs (mostly HTTP) in a complex world --- basic and digest authentication, redirections, cookies and more. +.. seealso:: + + The `Requests package `_ + is recommended for a higher-level http client interface. + The :mod:`urllib2` module defines the following functions: -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Apr 21 01:25:12 2015 From: python-checkins at python.org (yury.selivanov) Date: Mon, 20 Apr 2015 23:25:12 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_pep-0492=3A_Renames=3B_add_sy?= =?utf-8?q?s=2Eget=5Fcoroutine=5Fwrapper=28=29?= Message-ID: <20150420232512.21353.2000@psf.io> https://hg.python.org/peps/rev/4bd8ab31109c changeset: 5778:4bd8ab31109c user: Yury Selivanov date: Mon Apr 20 19:25:08 2015 -0400 summary: pep-0492: Renames; add sys.get_coroutine_wrapper() Renames: * types.async_def() -> types.coroutine() * CO_ASYNC -> CO_COROUTINE Add `sys.get_coroutine_wrapper()` files: pep-0492.txt | 43 ++++++++++++++++++++------------------- 1 files changed, 22 insertions(+), 21 deletions(-) diff --git a/pep-0492.txt b/pep-0492.txt --- a/pep-0492.txt +++ b/pep-0492.txt @@ -84,9 +84,9 @@ * It is a ``SyntaxError`` to have ``yield`` or ``yield from`` expressions in an ``async`` function. -* Internally, a new code object flag - ``CO_ASYNC`` - is introduced to enable - runtime detection of coroutines (and migrating existing code). - All coroutines have both ``CO_ASYNC`` and ``CO_GENERATOR`` flags set. +* Internally, a new code object flag - ``CO_COROUTINE`` - is introduced to + enable runtime detection of coroutines (and migrating existing code). All + coroutines have both ``CO_COROUTINE`` and ``CO_GENERATOR`` flags set. * Regular generators, when called, return a *generator object*; similarly, coroutines return a *coroutine object*. @@ -96,12 +96,12 @@ requires a future import (see PEP 479). -types.async_def() +types.coroutine() ----------------- -A new function ``async_def(gen)`` is added to the ``types`` module. It applies -``CO_ASYNC`` flag to the passed generator-function's code object, so that it -returns a *coroutine object* when called. +A new function ``coroutine(gen)`` is added to the ``types`` module. It applies +``CO_COROUTINE`` flag to the passed generator-function's code object, +making it to return a *coroutine object* when called. This feature enables an easy upgrade path for existing libraries. @@ -123,8 +123,8 @@ It uses the ``yield from`` implementation with an extra step of validating its argument. ``await`` only accepts an *awaitable*, which can be one of: -* A *coroutine object* returned from a coroutine or a generator decorated with - ``types.async_def()``. +* A *coroutine object* returned from a *coroutine* or a generator decorated + with ``types.coroutine()``. * An object with an ``__await__`` method returning an iterator. @@ -438,9 +438,10 @@ programs with asyncio's own functions instrumented. ``EventLoop.set_debug``, a different debug facility, has no impact on ``@coroutine`` decorator's behavior. -With this proposal, coroutines is a native, distinct from generators, -concept. A new method ``set_coroutine_wrapper`` is added to the ``sys`` module, -with which frameworks can provide advanced debugging facilities. +With this proposal, coroutines is a native, distinct from generators, concept. +New methods ``set_coroutine_wrapper`` and ``get_coroutine_wrapper`` are added +to the ``sys`` module, with which frameworks can provide advanced debugging +facilities. It is also important to make coroutines as fast and efficient as possible, therefore there are no debug features enabled by default. @@ -464,8 +465,8 @@ # previously set wrapper assert not isinstance(debug_me(), AsyncDebugWrapper) -If ``sys.set_coroutine_wrapper()`` is called twice, the new wrapper replaces the -previous wrapper. ``sys.set_coroutine_wrapper(None)`` unsets the wrapper. +If ``sys.set_coroutine_wrapper()`` is called twice, the new wrapper replaces +the previous wrapper. ``sys.set_coroutine_wrapper(None)`` unsets the wrapper. Glossary @@ -647,7 +648,7 @@ The required changes are mainly: -1. Modify ``@asyncio.coroutine`` decorator to use new ``types.async_def()`` +1. Modify ``@asyncio.coroutine`` decorator to use new ``types.coroutine()`` function. 2. Add ``__await__ = __iter__`` line to ``asyncio.Future`` class. @@ -701,7 +702,7 @@ ``@asyncio.coroutine`` decorator to wrap all functions in an object with a ``__cocall__`` method. To call *cofunctions* from existing generator-based coroutines it would be required to use ``costart`` built-in. In this - proposal ``@asyncio.coroutine`` simply sets ``CO_ASYNC`` on the wrapped + proposal ``@asyncio.coroutine`` simply sets ``CO_COROUTINE`` on the wrapped function's code object and everything works automatically. 4. Since it is impossible to call a *cofunction* without a ``cocall`` keyword, @@ -794,8 +795,8 @@ If ``useful()`` function is refactored and someone removes all ``await`` expressions from it, it would become a regular python function, and all code -that depends on it, including ``important()`` would be broken. To mitigate this -issue a decorator similar to ``@asyncio.coroutine`` has to be introduced. +that depends on it, including ``important()`` would be broken. To mitigate +this issue a decorator similar to ``@asyncio.coroutine`` has to be introduced. Why "async def" @@ -974,10 +975,10 @@ 5. New AST nodes: ``AsyncFunctionDef``, ``AsyncFor``, ``AsyncWith``, ``Await``. -6. New functions: ``sys.set_coroutine_wrapper(callback)`` and - ``types.async_def(gen)``. +6. New functions: ``sys.set_coroutine_wrapper(callback)``, + ``sys.get_coroutine_wrapper()``, and ``types.coroutine(gen)``. -7. New ``CO_ASYNC`` bit flag for code objects. +7. New ``CO_COROUTINE`` bit flag for code objects. While the list of changes and new things is not short, it is important to understand, that most users will not use these features directly. It is -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Tue Apr 21 02:23:50 2015 From: python-checkins at python.org (yury.selivanov) Date: Tue, 21 Apr 2015 00:23:50 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_pep-0492=3A_Trim_lines_at_72?= Message-ID: <20150421002350.6577.620@psf.io> https://hg.python.org/peps/rev/646dc160b8fe changeset: 5779:646dc160b8fe user: Yury Selivanov date: Mon Apr 20 20:23:45 2015 -0400 summary: pep-0492: Trim lines at 72 files: pep-0492.txt | 639 ++++++++++++++++++++------------------ 1 files changed, 338 insertions(+), 301 deletions(-) diff --git a/pep-0492.txt b/pep-0492.txt --- a/pep-0492.txt +++ b/pep-0492.txt @@ -14,58 +14,59 @@ ======== This PEP introduces new syntax for coroutines, asynchronous ``with`` -statements and ``for`` loops. The main motivation behind this proposal is to -streamline writing and maintaining asynchronous code, as well as to simplify -previously hard to implement code patterns. +statements and ``for`` loops. The main motivation behind this proposal +is to streamline writing and maintaining asynchronous code, as well as +to simplify previously hard to implement code patterns. Rationale and Goals =================== -Current Python supports implementing coroutines via generators (PEP 342), -further enhanced by the ``yield from`` syntax introduced in PEP 380. -This approach has a number of shortcomings: +Current Python supports implementing coroutines via generators (PEP +342), further enhanced by the ``yield from`` syntax introduced in PEP +380. This approach has a number of shortcomings: -* it is easy to confuse coroutines with regular generators, since they share - the same syntax; async libraries often attempt to alleviate this by using - decorators (e.g. ``@asyncio.coroutine`` [1]_); +* it is easy to confuse coroutines with regular generators, since they + share the same syntax; async libraries often attempt to alleviate + this by using decorators (e.g. ``@asyncio.coroutine`` [1]_); -* it is not possible to natively define a coroutine which has no ``yield`` - or ``yield from`` statements, again requiring the use of decorators to - fix potential refactoring issues; +* it is not possible to natively define a coroutine which has no + ``yield`` or ``yield from`` statements, again requiring the use of + decorators to fix potential refactoring issues; -* support for asynchronous calls is limited to expressions where ``yield`` is - allowed syntactically, limiting the usefulness of syntactic features, such - as ``with`` and ``for`` statements. +* support for asynchronous calls is limited to expressions where + ``yield`` is allowed syntactically, limiting the usefulness of + syntactic features, such as ``with`` and ``for`` statements. -This proposal makes coroutines a native Python language feature, and clearly -separates them from generators. This removes generator/coroutine ambiguity, -and makes it possible to reliably define coroutines without reliance on a -specific library. This also enables linters and IDEs to improve static code -analysis and refactoring. +This proposal makes coroutines a native Python language feature, and +clearly separates them from generators. This removes +generator/coroutine ambiguity, and makes it possible to reliably define +coroutines without reliance on a specific library. This also enables +linters and IDEs to improve static code analysis and refactoring. -Native coroutines and the associated new syntax features make it possible -to define context manager and iteration protocols in asynchronous terms. -As shown later in this proposal, the new ``async with`` statement lets Python -programs perform asynchronous calls when entering and exiting a runtime -context, and the new ``async for`` statement makes it possible to perform -asynchronous calls in iterators. +Native coroutines and the associated new syntax features make it +possible to define context manager and iteration protocols in +asynchronous terms. As shown later in this proposal, the new ``async +with`` statement lets Python programs perform asynchronous calls when +entering and exiting a runtime context, and the new ``async for`` +statement makes it possible to perform asynchronous calls in iterators. Specification ============= -This proposal introduces new syntax and semantics to enhance coroutine support -in Python, it does not change the internal implementation of coroutines, which -are still based on generators. +This proposal introduces new syntax and semantics to enhance coroutine +support in Python, it does not change the internal implementation of +coroutines, which are still based on generators. It is strongly suggested that the reader understands how coroutines are -implemented in Python (PEP 342 and PEP 380). It is also recommended to read -PEP 3156 (asyncio framework) and PEP 3152 (Cofunctions). +implemented in Python (PEP 342 and PEP 380). It is also recommended to +read PEP 3156 (asyncio framework) and PEP 3152 (Cofunctions). -From this point in this document we use the word *coroutine* to refer to -functions declared using the new syntax. *generator-based coroutine* is used -where necessary to refer to coroutines that are based on generator syntax. +From this point in this document we use the word *coroutine* to refer +to functions declared using the new syntax. *generator-based +coroutine* is used where necessary to refer to coroutines that are +based on generator syntax. New Coroutine Declaration Syntax @@ -78,30 +79,31 @@ Key properties of coroutines: -* ``async def`` functions are always coroutines, even if they do not contain - ``await`` expressions. +* ``async def`` functions are always coroutines, even if they do not + contain ``await`` expressions. -* It is a ``SyntaxError`` to have ``yield`` or ``yield from`` expressions in - an ``async`` function. +* It is a ``SyntaxError`` to have ``yield`` or ``yield from`` + expressions in an ``async`` function. -* Internally, a new code object flag - ``CO_COROUTINE`` - is introduced to - enable runtime detection of coroutines (and migrating existing code). All - coroutines have both ``CO_COROUTINE`` and ``CO_GENERATOR`` flags set. +* Internally, a new code object flag - ``CO_COROUTINE`` - is introduced + to enable runtime detection of coroutines (and migrating existing + code). All coroutines have both ``CO_COROUTINE`` and ``CO_GENERATOR`` + flags set. -* Regular generators, when called, return a *generator object*; similarly, - coroutines return a *coroutine object*. +* Regular generators, when called, return a *generator object*; + similarly, coroutines return a *coroutine object*. -* ``StopIteration`` exceptions are not propagated out of coroutines, and are - replaced with a ``RuntimeError``. For regular generators such behavior - requires a future import (see PEP 479). +* ``StopIteration`` exceptions are not propagated out of coroutines, + and are replaced with a ``RuntimeError``. For regular generators + such behavior requires a future import (see PEP 479). types.coroutine() ----------------- -A new function ``coroutine(gen)`` is added to the ``types`` module. It applies -``CO_COROUTINE`` flag to the passed generator-function's code object, -making it to return a *coroutine object* when called. +A new function ``coroutine(gen)`` is added to the ``types`` module. It +applies ``CO_COROUTINE`` flag to the passed generator-function's code +object, making it to return a *coroutine object* when called. This feature enables an easy upgrade path for existing libraries. @@ -109,42 +111,45 @@ Await Expression ---------------- -The following new ``await`` expression is used to obtain a result of coroutine -execution:: +The following new ``await`` expression is used to obtain a result of +coroutine execution:: async def read_data(db): data = await db.fetch('SELECT ...') ... -``await``, similarly to ``yield from``, suspends execution of ``read_data`` -coroutine until ``db.fetch`` *awaitable* completes and returns the result -data. +``await``, similarly to ``yield from``, suspends execution of +``read_data`` coroutine until ``db.fetch`` *awaitable* completes and +returns the result data. -It uses the ``yield from`` implementation with an extra step of validating its -argument. ``await`` only accepts an *awaitable*, which can be one of: +It uses the ``yield from`` implementation with an extra step of +validating its argument. ``await`` only accepts an *awaitable*, which +can be one of: -* A *coroutine object* returned from a *coroutine* or a generator decorated - with ``types.coroutine()``. +* A *coroutine object* returned from a *coroutine* or a generator + decorated with ``types.coroutine()``. * An object with an ``__await__`` method returning an iterator. Any ``yield from`` chain of calls ends with a ``yield``. This is a - fundamental mechanism of how *Futures* are implemented. Since, internally, - coroutines are a special kind of generators, every ``await`` is suspended by - a ``yield`` somewhere down the chain of ``await`` calls (please refer to PEP - 3156 for a detailed explanation.) + fundamental mechanism of how *Futures* are implemented. Since, + internally, coroutines are a special kind of generators, every + ``await`` is suspended by a ``yield`` somewhere down the chain of + ``await`` calls (please refer to PEP 3156 for a detailed + explanation.) To enable this behavior for coroutines, a new magic method called - ``__await__`` is added. In asyncio, for instance, to enable Future objects - in ``await`` statements, the only change is to add ``__await__ = __iter__`` - line to ``asyncio.Future`` class. + ``__await__`` is added. In asyncio, for instance, to enable Future + objects in ``await`` statements, the only change is to add + ``__await__ = __iter__`` line to ``asyncio.Future`` class. - Objects with ``__await__`` method are called *Future-like* objects in the - rest of this PEP. + Objects with ``__await__`` method are called *Future-like* objects in + the rest of this PEP. - Also, please note that ``__aiter__`` method (see its definition below) cannot - be used for this purpose. It is a different protocol, and would be like - using ``__iter__`` instead of ``__call__`` for regular callables. + Also, please note that ``__aiter__`` method (see its definition + below) cannot be used for this purpose. It is a different protocol, + and would be like using ``__iter__`` instead of ``__call__`` for + regular callables. It is a ``SyntaxError`` to use ``await`` outside of a coroutine. @@ -152,12 +157,12 @@ Asynchronous Context Managers and "async with" ---------------------------------------------- -An *asynchronous context manager* is a context manager that is able to suspend -execution in its *enter* and *exit* methods. +An *asynchronous context manager* is a context manager that is able to +suspend execution in its *enter* and *exit* methods. -To make this possible, a new protocol for asynchronous context managers is -proposed. Two new magic methods are added: ``__aenter__`` and ``__aexit__``. -Both must return an *awaitable*. +To make this possible, a new protocol for asynchronous context managers +is proposed. Two new magic methods are added: ``__aenter__`` and +``__aexit__``. Both must return an *awaitable*. An example of an asynchronous context manager:: @@ -200,19 +205,19 @@ await aexit(mgr, None, None, None) -As with regular ``with`` statements, it is possible to specify multiple context -managers in a single ``async with`` statement. +As with regular ``with`` statements, it is possible to specify multiple +context managers in a single ``async with`` statement. -It is an error to pass a regular context manager without ``__aenter__`` and -``__aexit__`` methods to ``async with``. It is a ``SyntaxError`` to use -``async with`` outside of a coroutine. +It is an error to pass a regular context manager without ``__aenter__`` +and ``__aexit__`` methods to ``async with``. It is a ``SyntaxError`` +to use ``async with`` outside of a coroutine. Example ''''''' -With asynchronous context managers it is easy to implement proper database -transaction managers for coroutines:: +With asynchronous context managers it is easy to implement proper +database transaction managers for coroutines:: async def commit(session, data): ... @@ -236,15 +241,16 @@ Asynchronous Iterators and "async for" -------------------------------------- -An *asynchronous iterable* is able to call asynchronous code in its *iter* -implementation, and *asynchronous iterator* can call asynchronous code in its -*next* method. To support asynchronous iteration: +An *asynchronous iterable* is able to call asynchronous code in its +*iter* implementation, and *asynchronous iterator* can call +asynchronous code in its *next* method. To support asynchronous +iteration: -1. An object must implement an ``__aiter__`` method returning an *awaitable* - resulting in an *asynchronous iterator object*. +1. An object must implement an ``__aiter__`` method returning an + *awaitable* resulting in an *asynchronous iterator object*. -2. An *asynchronous iterator object* must implement an ``__anext__`` method - returning an *awaitable*. +2. An *asynchronous iterator object* must implement an ``__anext__`` + method returning an *awaitable*. 3. To stop iteration ``__anext__`` must raise a ``StopAsyncIteration`` exception. @@ -269,7 +275,8 @@ New Syntax '''''''''' -A new statement for iterating through asynchronous iterators is proposed:: +A new statement for iterating through asynchronous iterators is +proposed:: async for TARGET in ITER: BLOCK @@ -292,19 +299,19 @@ BLOCK2 -It is an error to pass a regular iterable without ``__aiter__`` method to -``async for``. It is a ``SyntaxError`` to use ``async for`` outside of a -coroutine. +It is an error to pass a regular iterable without ``__aiter__`` method +to ``async for``. It is a ``SyntaxError`` to use ``async for`` outside +of a coroutine. -As for with regular ``for`` statement, ``async for`` has an optional ``else`` -clause. +As for with regular ``for`` statement, ``async for`` has an optional +``else`` clause. Example 1 ''''''''' -With asynchronous iteration protocol it is possible to asynchronously buffer -data during iteration:: +With asynchronous iteration protocol it is possible to asynchronously +buffer data during iteration:: async for data in cursor: ... @@ -351,9 +358,10 @@ Example 2 ''''''''' -The following is a utility class that transforms a regular iterable to an -asynchronous one. While this is not a very useful thing to do, the code -illustrates the relationship between regular and asynchronous iterators. +The following is a utility class that transforms a regular iterable to +an asynchronous one. While this is not a very useful thing to do, the +code illustrates the relationship between regular and asynchronous +iterators. :: @@ -378,8 +386,8 @@ Why StopAsyncIteration? ''''''''''''''''''''''' -Coroutines are still based on generators internally. So, before PEP 479, there -was no fundamental difference between +Coroutines are still based on generators internally. So, before PEP +479, there was no fundamental difference between :: @@ -395,8 +403,8 @@ yield from fut raise StopIteration('spam') -And since PEP 479 is accepted and enabled by default for coroutines, the -following example will have its ``StopIteration`` wrapped into a +And since PEP 479 is accepted and enabled by default for coroutines, +the following example will have its ``StopIteration`` wrapped into a ``RuntimeError`` :: @@ -405,46 +413,48 @@ await fut raise StopIteration('spam') -The only way to tell the outside code that the iteration has ended is to raise -something other than ``StopIteration``. Therefore, a new built-in exception -class ``StopAsyncIteration`` was added. +The only way to tell the outside code that the iteration has ended is +to raise something other than ``StopIteration``. Therefore, a new +built-in exception class ``StopAsyncIteration`` was added. -Moreover, with semantics from PEP 479, all ``StopIteration`` exceptions raised -in coroutines are wrapped in ``RuntimeError``. +Moreover, with semantics from PEP 479, all ``StopIteration`` exceptions +raised in coroutines are wrapped in ``RuntimeError``. Debugging Features ------------------ -One of the most frequent mistakes that people make when using generators as -coroutines is forgetting to use ``yield from``:: +One of the most frequent mistakes that people make when using +generators as coroutines is forgetting to use ``yield from``:: @asyncio.coroutine def useful(): asyncio.sleep(1) # this will do noting without 'yield from' -For debugging this kind of mistakes there is a special debug mode in asyncio, -in which ``@coroutine`` decorator wraps all functions with a special object -with a destructor logging a warning. Whenever a wrapped generator gets garbage -collected, a detailed logging message is generated with information about where -exactly the decorator function was defined, stack trace of where it was -collected, etc. Wrapper object also provides a convenient ``__repr__`` -function with detailed information about the generator. +For debugging this kind of mistakes there is a special debug mode in +asyncio, in which ``@coroutine`` decorator wraps all functions with a +special object with a destructor logging a warning. Whenever a wrapped +generator gets garbage collected, a detailed logging message is +generated with information about where exactly the decorator function +was defined, stack trace of where it was collected, etc. Wrapper +object also provides a convenient ``__repr__`` function with detailed +information about the generator. -The only problem is how to enable these debug capabilities. Since debug -facilities should be a no-op in production mode, ``@coroutine`` decorator makes -the decision of whether to wrap or not to wrap based on an OS environment -variable ``PYTHONASYNCIODEBUG``. This way it is possible to run asyncio -programs with asyncio's own functions instrumented. ``EventLoop.set_debug``, a -different debug facility, has no impact on ``@coroutine`` decorator's behavior. +The only problem is how to enable these debug capabilities. Since +debug facilities should be a no-op in production mode, ``@coroutine`` +decorator makes the decision of whether to wrap or not to wrap based on +an OS environment variable ``PYTHONASYNCIODEBUG``. This way it is +possible to run asyncio programs with asyncio's own functions +instrumented. ``EventLoop.set_debug``, a different debug facility, has +no impact on ``@coroutine`` decorator's behavior. -With this proposal, coroutines is a native, distinct from generators, concept. -New methods ``set_coroutine_wrapper`` and ``get_coroutine_wrapper`` are added -to the ``sys`` module, with which frameworks can provide advanced debugging -facilities. +With this proposal, coroutines is a native, distinct from generators, +concept. New methods ``set_coroutine_wrapper`` and +``get_coroutine_wrapper`` are added to the ``sys`` module, with which +frameworks can provide advanced debugging facilities. -It is also important to make coroutines as fast and efficient as possible, -therefore there are no debug features enabled by default. +It is also important to make coroutines as fast and efficient as +possible, therefore there are no debug features enabled by default. Example:: @@ -465,44 +475,47 @@ # previously set wrapper assert not isinstance(debug_me(), AsyncDebugWrapper) -If ``sys.set_coroutine_wrapper()`` is called twice, the new wrapper replaces -the previous wrapper. ``sys.set_coroutine_wrapper(None)`` unsets the wrapper. +If ``sys.set_coroutine_wrapper()`` is called twice, the new wrapper +replaces the previous wrapper. ``sys.set_coroutine_wrapper(None)`` +unsets the wrapper. Glossary ======== :Coroutine: - A coroutine function, or just "coroutine", is declared with ``async def``. - It uses ``await`` and ``return value``; see `New Coroutine Declaration - Syntax`_ for details. + A coroutine function, or just "coroutine", is declared with ``async + def``. It uses ``await`` and ``return value``; see `New Coroutine + Declaration Syntax`_ for details. :Coroutine object: - Returned from a coroutine function. See `Await Expression`_ for details. + Returned from a coroutine function. See `Await Expression`_ for + details. :Future-like object: - An object with an ``__await__`` method. Can be consumed by an ``await`` - expression in a coroutine. A coroutine waiting for a Future-like object is - suspended until the Future-like object's ``__await__`` completes, and - returns the result. See `Await Expression`_ for details. + An object with an ``__await__`` method. Can be consumed by an + ``await`` expression in a coroutine. A coroutine waiting for a + Future-like object is suspended until the Future-like object's + ``__await__`` completes, and returns the result. See `Await + Expression`_ for details. :Awaitable: - A *Future-like* object or a *coroutine object*. See `Await Expression`_ - for details. + A *Future-like* object or a *coroutine object*. See `Await + Expression`_ for details. :Generator-based coroutine: Coroutines based in generator syntax. Most common example is ``@asyncio.coroutine``. :Asynchronous context manager: - An asynchronous context manager has ``__aenter__`` and ``__aexit__`` methods - and can be used with ``async with``. See - `Asynchronous Context Managers and "async with"`_ for details. + An asynchronous context manager has ``__aenter__`` and ``__aexit__`` + methods and can be used with ``async with``. See `Asynchronous + Context Managers and "async with"`_ for details. :Asynchronous iterable: - An object with an ``__aiter__`` method, which must return an *asynchronous - iterator* object. Can be used with ``async for``. See - `Asynchronous Iterators and "async for"`_ for details. + An object with an ``__aiter__`` method, which must return an + *asynchronous iterator* object. Can be used with ``async for``. + See `Asynchronous Iterators and "async for"`_ for details. :Asynchronous iterator: An asynchronous iterator has an ``__anext__`` method. See @@ -512,15 +525,15 @@ List of functions and methods ============================= -================= ======================================= ================= -Method Can contain Can't contain -================= ======================================= ================= -async def func await, return value yield, yield from -async def __a*__ await, return value yield, yield from -def __a*__ return awaitable await -def __await__ yield, yield from, return iterable await -generator yield, yield from, return value await -================= ======================================= ================= +================= =================================== ================= +Method Can contain Can't contain +================= =================================== ================= +async def func await, return value yield, yield from +async def __a*__ await, return value yield, yield from +def __a*__ return awaitable await +def __await__ yield, yield from, return iterable await +generator yield, yield from, return value await +================= =================================== ================= Where: @@ -529,32 +542,38 @@ * "async def __a*__": ``__aiter__``, ``__anext__``, ``__aenter__``, ``__aexit__`` defined with the ``async`` keyword; -* "def __a*__": ``__aiter__``, ``__anext__``, ``__aenter__``, ``__aexit__`` - defined without the ``async`` keyword, must return an *awaitable*; +* "def __a*__": ``__aiter__``, ``__anext__``, ``__aenter__``, + ``__aexit__`` defined without the ``async`` keyword, must return an + *awaitable*; -* "def __await__": ``__await__`` method to implement *Future-like* objects; +* "def __await__": ``__await__`` method to implement *Future-like* + objects; -* generator: a "regular" generator, function defined with ``def`` and which - contains a least one ``yield`` or ``yield from`` expression. +* generator: a "regular" generator, function defined with ``def`` and + which contains a least one ``yield`` or ``yield from`` expression. Transition Plan =============== -To avoid backwards compatibility issues with ``async`` and ``await`` keywords, -it was decided to modify ``tokenizer.c`` in such a way, that it: +To avoid backwards compatibility issues with ``async`` and ``await`` +keywords, it was decided to modify ``tokenizer.c`` in such a way, that +it: -* recognizes ``async def`` name tokens combination (start of a coroutine); +* recognizes ``async def`` name tokens combination (start of a + coroutine); * keeps track of regular functions and coroutines; * replaces ``'async'`` token with ``ASYNC`` and ``'await'`` token with ``AWAIT`` when in the process of yielding tokens for coroutines. -This approach allows for seamless combination of new syntax features (all of -them available only in ``async`` functions) with any existing code. +This approach allows for seamless combination of new syntax features +(all of them available only in ``async`` functions) with any existing +code. -An example of having "async def" and "async" attribute in one piece of code:: +An example of having "async def" and "async" attribute in one piece of +code:: class Spam: async = 42 @@ -584,16 +603,18 @@ async_stmt: ASYNC (funcdef | with_stmt | for_stmt) - compound_stmt: (if_stmt | while_stmt | for_stmt | try_stmt | with_stmt - | funcdef | classdef | decorated | async_stmt) + compound_stmt: (if_stmt | while_stmt | for_stmt | try_stmt | + with_stmt | funcdef | classdef | decorated | + async_stmt) atom: ('(' [yield_expr|await_expr|testlist_comp] ')' | '[' [testlist_comp] ']' | '{' [dictorsetmaker] '}' | NAME | NUMBER | STRING+ | '...' | 'None' | 'True' | 'False?) - expr_stmt: testlist_star_expr (augassign (yield_expr|await_expr|testlist) | - ('=' (yield_expr|await_expr|testlist_star_expr))*) + expr_stmt: testlist_star_expr + (augassign (yield_expr|await_expr|testlist) | + ('=' (yield_expr|await_expr|testlist_star_expr))*) Transition Period Shortcomings @@ -601,9 +622,9 @@ There is just one. -Until ``async`` and ``await`` are not proper keywords, it is not possible (or -at least very hard) to fix ``tokenizer.c`` to recognize them on the **same -line** with ``def`` keyword:: +Until ``async`` and ``await`` are not proper keywords, it is not +possible (or at least very hard) to fix ``tokenizer.c`` to recognize +them on the **same line** with ``def`` keyword:: # async and await will always be parsed as variables @@ -613,11 +634,11 @@ async def foo(): return (await fut) # 2 -Since ``await`` and ``async`` in such cases are parsed as ``NAME`` tokens, a -``SyntaxError`` will be raised. +Since ``await`` and ``async`` in such cases are parsed as ``NAME`` +tokens, a ``SyntaxError`` will be raised. -To workaround these issues, the above examples can be easily rewritten to a -more readable form:: +To workaround these issues, the above examples can be easily rewritten +to a more readable form:: async def outer(): # 1 a_default = await fut @@ -627,34 +648,35 @@ async def foo(): # 2 return (await fut) -This limitation will go away as soon as ``async`` and ``await`` ate proper -keywords. Or if it's decided to use a future import for this PEP. +This limitation will go away as soon as ``async`` and ``await`` ate +proper keywords. Or if it's decided to use a future import for this +PEP. Deprecation Plans ----------------- -``async`` and ``await`` names will be softly deprecated in CPython 3.5 and 3.6. -In 3.7 we will transform them to proper keywords. Making ``async`` and -``await`` proper keywords before 3.7 might make it harder for people to port -their code to Python 3. +``async`` and ``await`` names will be softly deprecated in CPython 3.5 +and 3.6. In 3.7 we will transform them to proper keywords. Making +``async`` and ``await`` proper keywords before 3.7 might make it harder +for people to port their code to Python 3. asyncio ------- -``asyncio`` module was adapted and tested to work with coroutines and new -statements. Backwards compatibility is 100% preserved. +``asyncio`` module was adapted and tested to work with coroutines and +new statements. Backwards compatibility is 100% preserved. The required changes are mainly: -1. Modify ``@asyncio.coroutine`` decorator to use new ``types.coroutine()`` - function. +1. Modify ``@asyncio.coroutine`` decorator to use new + ``types.coroutine()`` function. 2. Add ``__await__ = __iter__`` line to ``asyncio.Future`` class. -3. Add ``ensure_task()`` as an alias for ``async()`` function. Deprecate - ``async()`` function. +3. Add ``ensure_task()`` as an alias for ``async()`` function. + Deprecate ``async()`` function. Design Considerations @@ -666,15 +688,16 @@ PEP 3152 by Gregory Ewing proposes a different mechanism for coroutines (called "cofunctions"). Some key points: -1. A new keyword ``codef`` to declare a *cofunction*. *Cofunction* is always a - generator, even if there is no ``cocall`` expressions inside it. Maps to - ``async def`` in this proposal. +1. A new keyword ``codef`` to declare a *cofunction*. *Cofunction* is + always a generator, even if there is no ``cocall`` expressions + inside it. Maps to ``async def`` in this proposal. -2. A new keyword ``cocall`` to call a *cofunction*. Can only be used inside a - *cofunction*. Maps to ``await`` in this proposal (with some differences, - see below.) +2. A new keyword ``cocall`` to call a *cofunction*. Can only be used + inside a *cofunction*. Maps to ``await`` in this proposal (with + some differences, see below.) -3. It is not possible to call a *cofunction* without a ``cocall`` keyword. +3. It is not possible to call a *cofunction* without a ``cocall`` + keyword. 4. ``cocall`` grammatically requires parentheses after it:: @@ -687,54 +710,59 @@ Differences from this proposal: -1. There is no equivalent of ``__cocall__`` in this PEP, which is called and - its result is passed to ``yield from`` in the ``cocall`` expression. - ``await`` keyword expects an *awaitable* object, validates the type, and - executes ``yield from`` on it. Although, ``__await__`` method is similar to - ``__cocall__``, but is only used to define *Future-like* objects. +1. There is no equivalent of ``__cocall__`` in this PEP, which is + called and its result is passed to ``yield from`` in the ``cocall`` + expression. ``await`` keyword expects an *awaitable* object, + validates the type, and executes ``yield from`` on it. Although, + ``__await__`` method is similar to ``__cocall__``, but is only used + to define *Future-like* objects. -2. ``await`` is defined in almost the same way as ``yield from`` in the grammar - (it is later enforced that ``await`` can only be inside ``async def``). It - is possible to simply write ``await future``, whereas ``cocall`` always - requires parentheses. +2. ``await`` is defined in almost the same way as ``yield from`` in the + grammar (it is later enforced that ``await`` can only be inside + ``async def``). It is possible to simply write ``await future``, + whereas ``cocall`` always requires parentheses. 3. To make asyncio work with PEP 3152 it would be required to modify - ``@asyncio.coroutine`` decorator to wrap all functions in an object with a - ``__cocall__`` method. To call *cofunctions* from existing generator-based - coroutines it would be required to use ``costart`` built-in. In this - proposal ``@asyncio.coroutine`` simply sets ``CO_COROUTINE`` on the wrapped - function's code object and everything works automatically. + ``@asyncio.coroutine`` decorator to wrap all functions in an object + with a ``__cocall__`` method. To call *cofunctions* from existing + generator-based coroutines it would be required to use ``costart`` + built-in. In this proposal ``@asyncio.coroutine`` simply sets + ``CO_COROUTINE`` on the wrapped function's code object and + everything works automatically. -4. Since it is impossible to call a *cofunction* without a ``cocall`` keyword, - it automatically prevents the common mistake of forgetting to use - ``yield from`` on generator-based coroutines. This proposal addresses - this problem with a different approach, see `Debugging Features`_. +4. Since it is impossible to call a *cofunction* without a ``cocall`` + keyword, it automatically prevents the common mistake of forgetting + to use ``yield from`` on generator-based coroutines. This proposal + addresses this problem with a different approach, see `Debugging + Features`_. -5. There are no equivalents of ``async for`` and ``async with`` in PEP 3152. +5. There are no equivalents of ``async for`` and ``async with`` in PEP + 3152. No implicit wrapping in Futures ------------------------------- -There is a proposal to add similar mechanism to ECMAScript 7 [2]_. A key -difference is that JavaScript "async functions" always return a Promise. While -this approach has some advantages, it also implies that a new Promise object is -created on each "async function" invocation. +There is a proposal to add similar mechanism to ECMAScript 7 [2]_. A +key difference is that JavaScript "async functions" always return a +Promise. While this approach has some advantages, it also implies that +a new Promise object is created on each "async function" invocation. We could implement a similar functionality in Python, by wrapping all -coroutines in a Future object, but this has the following disadvantages: +coroutines in a Future object, but this has the following +disadvantages: -1. Performance. A new Future object would be instantiated on each coroutine - call. Moreover, this makes implementation of ``await`` expressions slower - (disabling optimizations of ``yield from``). +1. Performance. A new Future object would be instantiated on each + coroutine call. Moreover, this makes implementation of ``await`` + expressions slower (disabling optimizations of ``yield from``). 2. A new built-in ``Future`` object would need to be added. -3. Coming up with a generic ``Future`` interface that is usable for any use - case in any framework is a very hard to solve problem. +3. Coming up with a generic ``Future`` interface that is usable for any + use case in any framework is a very hard to solve problem. -4. It is not a feature that is used frequently, when most of the code is - coroutines. +4. It is not a feature that is used frequently, when most of the code + is coroutines. Why "async" and "await" keywords @@ -757,31 +785,32 @@ * and many other less popular languages. -This is a huge benefit, as some users already have experience with async/await, -and because it makes working with many languages in one project easier (Python -with ECMAScript 7 for instance). +This is a huge benefit, as some users already have experience with +async/await, and because it makes working with many languages in one +project easier (Python with ECMAScript 7 for instance). Why "__aiter__" is a coroutine ------------------------------ -In principle, ``__aiter__`` could be a regular function. There are several -good reasons to make it a coroutine: +In principle, ``__aiter__`` could be a regular function. There are +several good reasons to make it a coroutine: -* as most of the ``__anext__``, ``__aenter__``, and ``__aexit__`` methods are - coroutines, users would often make a mistake defining it as ``async`` - anyways; +* as most of the ``__anext__``, ``__aenter__``, and ``__aexit__`` + methods are coroutines, users would often make a mistake defining it + as ``async`` anyways; -* there might be a need to run some asynchronous operations in ``__aiter__``, - for instance to prepare DB queries or do some file operation. +* there might be a need to run some asynchronous operations in + ``__aiter__``, for instance to prepare DB queries or do some file + operation. Importance of "async" keyword ----------------------------- -While it is possible to just implement ``await`` expression and treat all -functions with at least one ``await`` as coroutines, this approach makes -APIs design, code refactoring and its long time support harder. +While it is possible to just implement ``await`` expression and treat +all functions with at least one ``await`` as coroutines, this approach +makes APIs design, code refactoring and its long time support harder. Let's pretend that Python only has ``await`` keyword:: @@ -793,50 +822,54 @@ def important(): await useful() -If ``useful()`` function is refactored and someone removes all ``await`` -expressions from it, it would become a regular python function, and all code -that depends on it, including ``important()`` would be broken. To mitigate -this issue a decorator similar to ``@asyncio.coroutine`` has to be introduced. +If ``useful()`` function is refactored and someone removes all +``await`` expressions from it, it would become a regular python +function, and all code that depends on it, including ``important()`` +would be broken. To mitigate this issue a decorator similar to +``@asyncio.coroutine`` has to be introduced. Why "async def" --------------- -For some people bare ``async name(): pass`` syntax might look more appealing -than ``async def name(): pass``. It is certainly easier to type. But on the -other hand, it breaks the symmetry between ``async def``, ``async with`` and -``async for``, where ``async`` is a modifier, stating that the statement is -asynchronous. It is also more consistent with the existing grammar. +For some people bare ``async name(): pass`` syntax might look more +appealing than ``async def name(): pass``. It is certainly easier to +type. But on the other hand, it breaks the symmetry between ``async +def``, ``async with`` and ``async for``, where ``async`` is a modifier, +stating that the statement is asynchronous. It is also more consistent +with the existing grammar. Why not a __future__ import --------------------------- -``__future__`` imports are inconvenient and easy to forget to add. Also, they -are enabled for the whole source file. Consider that there is a big project -with a popular module named "async.py". With future imports it is required to -either import it using ``__import__()`` or ``importlib.import_module()`` calls, -or to rename the module. The proposed approach makes it possible to continue -using old code and modules without a hassle, while coming up with a migration -plan for future python versions. +``__future__`` imports are inconvenient and easy to forget to add. +Also, they are enabled for the whole source file. Consider that there +is a big project with a popular module named "async.py". With future +imports it is required to either import it using ``__import__()`` or +``importlib.import_module()`` calls, or to rename the module. The +proposed approach makes it possible to continue using old code and +modules without a hassle, while coming up with a migration plan for +future python versions. Why magic methods start with "a" -------------------------------- -New asynchronous magic methods ``__aiter__``, ``__anext__``, ``__aenter__``, -and ``__aexit__`` all start with the same prefix "a". An alternative proposal -is to use "async" prefix, so that ``__aiter__`` becomes ``__async_iter__``. -However, to align new magic methods with the existing ones, such as -``__radd__`` and ``__iadd__`` it was decided to use a shorter version. +New asynchronous magic methods ``__aiter__``, ``__anext__``, +``__aenter__``, and ``__aexit__`` all start with the same prefix "a". +An alternative proposal is to use "async" prefix, so that ``__aiter__`` +becomes ``__async_iter__``. However, to align new magic methods with +the existing ones, such as ``__radd__`` and ``__iadd__`` it was decided +to use a shorter version. Why not reuse existing magic names ---------------------------------- -An alternative idea about new asynchronous iterators and context managers was -to reuse existing magic methods, by adding an ``async`` keyword to their -declarations:: +An alternative idea about new asynchronous iterators and context +managers was to reuse existing magic methods, by adding an ``async`` +keyword to their declarations:: class CM: async def __enter__(self): # instead of __aenter__ @@ -844,31 +877,31 @@ This approach has the following downsides: -* it would not be possible to create an object that works in both ``with`` and - ``async with`` statements; +* it would not be possible to create an object that works in both + ``with`` and ``async with`` statements; -* it would look confusing and would require some implicit magic behind the - scenes in the interpreter; +* it would look confusing and would require some implicit magic behind + the scenes in the interpreter; -* one of the main points of this proposal is to make coroutines as simple - and foolproof as possible. +* one of the main points of this proposal is to make coroutines as + simple and foolproof as possible. Comprehensions -------------- -For the sake of restricting the broadness of this PEP there is no new syntax -for asynchronous comprehensions. This should be considered in a separate PEP, -if there is a strong demand for this feature. +For the sake of restricting the broadness of this PEP there is no new +syntax for asynchronous comprehensions. This should be considered in a +separate PEP, if there is a strong demand for this feature. Async lambdas ------------- -Lambda coroutines are not part of this proposal. In this proposal they would -look like ``async lambda(parameters): expression``. Unless there is a strong -demand to have them as part of this proposal, it is recommended to consider -them later in a separate PEP. +Lambda coroutines are not part of this proposal. In this proposal they +would look like ``async lambda(parameters): expression``. Unless there +is a strong demand to have them as part of this proposal, it is +recommended to consider them later in a separate PEP. Performance @@ -877,8 +910,8 @@ Overall Impact -------------- -This proposal introduces no observable performance impact. Here is an output -of python's official set of benchmarks [4]_: +This proposal introduces no observable performance impact. Here is an +output of python's official set of benchmarks [4]_: :: @@ -906,16 +939,17 @@ Tokenizer modifications ----------------------- -There is no observable slowdown of parsing python files with the modified -tokenizer: parsing of one 12Mb file (``Lib/test/test_binop.py`` repeated 1000 -times) takes the same amount of time. +There is no observable slowdown of parsing python files with the +modified tokenizer: parsing of one 12Mb file +(``Lib/test/test_binop.py`` repeated 1000 times) takes the same amount +of time. async/await ----------- -The following micro-benchmark was used to determine performance difference -between "async" functions and generators:: +The following micro-benchmark was used to determine performance +difference between "async" functions and generators:: import sys import time @@ -942,8 +976,8 @@ print('{}({}) * {}: total {:.3f}s'.format( gen.__name__, depth, repeat, t1-t0)) -The result is that there is no observable performance difference. Minimum -timing of 3 runs +The result is that there is no observable performance difference. +Minimum timing of 3 runs :: @@ -969,28 +1003,30 @@ 3. New syntax for asynchronous context managers: ``async with``. And associated protocol with ``__aenter__`` and ``__aexit__`` methods. -4. New syntax for asynchronous iteration: ``async for``. And associated - protocol with ``__aiter__``, ``__aexit__`` and new built-in exception - ``StopAsyncIteration``. +4. New syntax for asynchronous iteration: ``async for``. And + associated protocol with ``__aiter__``, ``__aexit__`` and new built- + in exception ``StopAsyncIteration``. -5. New AST nodes: ``AsyncFunctionDef``, ``AsyncFor``, ``AsyncWith``, ``Await``. +5. New AST nodes: ``AsyncFunctionDef``, ``AsyncFor``, ``AsyncWith``, + ``Await``. 6. New functions: ``sys.set_coroutine_wrapper(callback)``, ``sys.get_coroutine_wrapper()``, and ``types.coroutine(gen)``. 7. New ``CO_COROUTINE`` bit flag for code objects. -While the list of changes and new things is not short, it is important to -understand, that most users will not use these features directly. It is -intended to be used in frameworks and libraries to provide users with -convenient to use and unambiguous APIs with ``async def``, ``await``, ``async -for`` and ``async with`` syntax. +While the list of changes and new things is not short, it is important +to understand, that most users will not use these features directly. +It is intended to be used in frameworks and libraries to provide users +with convenient to use and unambiguous APIs with ``async def``, +``await``, ``async for`` and ``async with`` syntax. Working example --------------- -All concepts proposed in this PEP are implemented [3]_ and can be tested. +All concepts proposed in this PEP are implemented [3]_ and can be +tested. :: @@ -998,7 +1034,8 @@ async def echo_server(): print('Serving on localhost:8000') - await asyncio.start_server(handle_connection, 'localhost', 8000) + await asyncio.start_server(handle_connection, + 'localhost', 8000) async def handle_connection(reader, writer): print('New connection...') @@ -1047,8 +1084,8 @@ Acknowledgments =============== -I thank Guido van Rossum, Victor Stinner, Elvis Pranskevichus, Andrew Svetlov, -and ?ukasz Langa for their initial feedback. +I thank Guido van Rossum, Victor Stinner, Elvis Pranskevichus, Andrew +Svetlov, and ?ukasz Langa for their initial feedback. Copyright -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Tue Apr 21 02:27:37 2015 From: python-checkins at python.org (yury.selivanov) Date: Tue, 21 Apr 2015 00:27:37 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_pep-0492=3A_Add_a_Post-Histor?= =?utf-8?q?y_header=2E?= Message-ID: <20150421002737.30317.28481@psf.io> https://hg.python.org/peps/rev/5d90d861c9b6 changeset: 5780:5d90d861c9b6 user: Yury Selivanov date: Mon Apr 20 20:27:34 2015 -0400 summary: pep-0492: Add a Post-History header. files: pep-0492.txt | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/pep-0492.txt b/pep-0492.txt --- a/pep-0492.txt +++ b/pep-0492.txt @@ -8,6 +8,7 @@ Content-Type: text/x-rst Created: 09-Apr-2015 Python-Version: 3.5 +Post-History: 17-Apr-2015 Abstract -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Tue Apr 21 03:20:15 2015 From: python-checkins at python.org (greg.ward) Date: Tue, 21 Apr 2015 01:20:15 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_=2317445=3A_difflib=3A_add?= =?utf-8?q?_diff=5Fbytes=28=29=2C_to_compare_bytes_rather_than_str?= Message-ID: <20150421012015.98632.92788@psf.io> https://hg.python.org/cpython/rev/1764d42b340d changeset: 95748:1764d42b340d user: Greg Ward date: Mon Apr 20 20:21:21 2015 -0400 summary: #17445: difflib: add diff_bytes(), to compare bytes rather than str Some applications (e.g. traditional Unix diff, version control systems) neither know nor care about the encodings of the files they are comparing. They are textual, but to the diff utility they are just bytes. This worked fine under Python 2, because all of the hardcoded strings in difflib.py are ASCII, so could safely be combined with old-style u'' strings. But it stopped working in 3.x. The solution is to use surrogate escapes for a lossless bytes->str->bytes roundtrip. That means {unified,context}_diff() can continue to just handle strings without worrying about bytes. Callers who have to deal with bytes will need to change to using diff_bytes(). Use case: Mercurial's test runner uses difflib to compare current hg output with known good output. But Mercurial's output is just bytes, since it can contain: * file contents (arbitrary unknown encoding) * filenames (arbitrary unknown encoding) * usernames and commit messages (usually UTF-8, but not guaranteed because old versions of Mercurial did not enforce it) * user messages (locale encoding) Since the output of any given hg command can include text in multiple encodings, it is hopeless to try to treat it as decodable Unicode text. It's just bytes, all the way down. This is an elaboration of a patch by Terry Reedy. files: Doc/library/difflib.rst | 15 ++ Doc/whatsnew/3.5.rst | 3 + Lib/difflib.py | 51 +++++++++- Lib/test/test_difflib.py | 147 ++++++++++++++++++++++++++- Misc/NEWS | 4 + 5 files changed, 218 insertions(+), 2 deletions(-) diff --git a/Doc/library/difflib.rst b/Doc/library/difflib.rst --- a/Doc/library/difflib.rst +++ b/Doc/library/difflib.rst @@ -315,6 +315,21 @@ See :ref:`difflib-interface` for a more detailed example. +.. function:: diff_bytes(dfunc, a, b, fromfile=b'', tofile=b'', fromfiledate=b'', tofiledate=b'', n=3, lineterm=b'\\n') + + Compare *a* and *b* (lists of bytes objects) using *dfunc*; yield a + sequence of delta lines (also bytes) in the format returned by *dfunc*. + *dfunc* must be a callable, typically either :func:`unified_diff` or + :func:`context_diff`. + + Allows you to compare data with unknown or inconsistent encoding. All + inputs except *n* must be bytes objects, not str. Works by losslessly + converting all inputs (except *n*) to str, and calling ``dfunc(a, b, + fromfile, tofile, fromfiledate, tofiledate, n, lineterm)``. The output of + *dfunc* is then converted back to bytes, so the delta lines that you + receive have the same unknown/inconsistent encodings as *a* and *b*. + + .. versionadded:: 3.5 .. function:: IS_LINE_JUNK(line) diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -302,6 +302,9 @@ charset of HTML document changed from ``'ISO-8859-1'`` to ``'utf-8'``. (Contributed by Berker Peksag in :issue:`2052`.) +* It's now possible to compare lists of byte strings with + :func:`difflib.diff_bytes` (fixes a regression from Python 2). + distutils --------- diff --git a/Lib/difflib.py b/Lib/difflib.py --- a/Lib/difflib.py +++ b/Lib/difflib.py @@ -28,7 +28,7 @@ __all__ = ['get_close_matches', 'ndiff', 'restore', 'SequenceMatcher', 'Differ','IS_CHARACTER_JUNK', 'IS_LINE_JUNK', 'context_diff', - 'unified_diff', 'HtmlDiff', 'Match'] + 'unified_diff', 'diff_bytes', 'HtmlDiff', 'Match'] from heapq import nlargest as _nlargest from collections import namedtuple as _namedtuple @@ -1174,6 +1174,7 @@ four """ + _check_types(a, b, fromfile, tofile, fromfiledate, tofiledate, lineterm) started = False for group in SequenceMatcher(None,a,b).get_grouped_opcodes(n): if not started: @@ -1261,6 +1262,7 @@ four """ + _check_types(a, b, fromfile, tofile, fromfiledate, tofiledate, lineterm) prefix = dict(insert='+ ', delete='- ', replace='! ', equal=' ') started = False for group in SequenceMatcher(None,a,b).get_grouped_opcodes(n): @@ -1292,6 +1294,53 @@ for line in b[j1:j2]: yield prefix[tag] + line +def _check_types(a, b, *args): + # Checking types is weird, but the alternative is garbled output when + # someone passes mixed bytes and str to {unified,context}_diff(). E.g. + # without this check, passing filenames as bytes results in output like + # --- b'oldfile.txt' + # +++ b'newfile.txt' + # because of how str.format() incorporates bytes objects. + if a and not isinstance(a[0], str): + raise TypeError('lines to compare must be str, not %s (%r)' % + (type(a[0]).__name__, a[0])) + if b and not isinstance(b[0], str): + raise TypeError('lines to compare must be str, not %s (%r)' % + (type(b[0]).__name__, b[0])) + for arg in args: + if not isinstance(arg, str): + raise TypeError('all arguments must be str, not: %r' % (arg,)) + +def diff_bytes(dfunc, a, b, fromfile=b'', tofile=b'', + fromfiledate=b'', tofiledate=b'', n=3, lineterm=b'\n'): + r""" + Compare `a` and `b`, two sequences of lines represented as bytes rather + than str. This is a wrapper for `dfunc`, which is typically either + unified_diff() or context_diff(). Inputs are losslessly converted to + strings so that `dfunc` only has to worry about strings, and encoded + back to bytes on return. This is necessary to compare files with + unknown or inconsistent encoding. All other inputs (except `n`) must be + bytes rather than str. + """ + def decode(s): + try: + return s.decode('ascii', 'surrogateescape') + except AttributeError as err: + msg = ('all arguments must be bytes, not %s (%r)' % + (type(s).__name__, s)) + raise TypeError(msg) from err + a = list(map(decode, a)) + b = list(map(decode, b)) + fromfile = decode(fromfile) + tofile = decode(tofile) + fromfiledate = decode(fromfiledate) + tofiledate = decode(tofiledate) + lineterm = decode(lineterm) + + lines = dfunc(a, b, fromfile, tofile, fromfiledate, tofiledate, n, lineterm) + for line in lines: + yield line.encode('ascii', 'surrogateescape') + def ndiff(a, b, linejunk=None, charjunk=IS_CHARACTER_JUNK): r""" Compare `a` and `b` (lists of strings); return a `Differ`-style delta. diff --git a/Lib/test/test_difflib.py b/Lib/test/test_difflib.py --- a/Lib/test/test_difflib.py +++ b/Lib/test/test_difflib.py @@ -322,12 +322,157 @@ self.assertEqual(fmt(0,0), '0') +class TestBytes(unittest.TestCase): + # don't really care about the content of the output, just the fact + # that it's bytes and we don't crash + def check(self, diff): + diff = list(diff) # trigger exceptions first + for line in diff: + self.assertIsInstance( + line, bytes, + "all lines of diff should be bytes, but got: %r" % line) + + def test_byte_content(self): + # if we receive byte strings, we return byte strings + a = [b'hello', b'andr\xe9'] # iso-8859-1 bytes + b = [b'hello', b'andr\xc3\xa9'] # utf-8 bytes + + unified = difflib.unified_diff + context = difflib.context_diff + + check = self.check + check(difflib.diff_bytes(unified, a, a)) + check(difflib.diff_bytes(unified, a, b)) + + # now with filenames (content and filenames are all bytes!) + check(difflib.diff_bytes(unified, a, a, b'a', b'a')) + check(difflib.diff_bytes(unified, a, b, b'a', b'b')) + + # and with filenames and dates + check(difflib.diff_bytes(unified, a, a, b'a', b'a', b'2005', b'2013')) + check(difflib.diff_bytes(unified, a, b, b'a', b'b', b'2005', b'2013')) + + # same all over again, with context diff + check(difflib.diff_bytes(context, a, a)) + check(difflib.diff_bytes(context, a, b)) + check(difflib.diff_bytes(context, a, a, b'a', b'a')) + check(difflib.diff_bytes(context, a, b, b'a', b'b')) + check(difflib.diff_bytes(context, a, a, b'a', b'a', b'2005', b'2013')) + check(difflib.diff_bytes(context, a, b, b'a', b'b', b'2005', b'2013')) + + def test_byte_filenames(self): + # somebody renamed a file from ISO-8859-2 to UTF-8 + fna = b'\xb3odz.txt' # "?odz.txt" + fnb = b'\xc5\x82odz.txt' + + # they transcoded the content at the same time + a = [b'\xa3odz is a city in Poland.'] + b = [b'\xc5\x81odz is a city in Poland.'] + + check = self.check + unified = difflib.unified_diff + context = difflib.context_diff + check(difflib.diff_bytes(unified, a, b, fna, fnb)) + check(difflib.diff_bytes(context, a, b, fna, fnb)) + + def assertDiff(expect, actual): + # do not compare expect and equal as lists, because unittest + # uses difflib to report difference between lists + actual = list(actual) + self.assertEqual(len(expect), len(actual)) + for e, a in zip(expect, actual): + self.assertEqual(e, a) + + expect = [ + b'--- \xb3odz.txt', + b'+++ \xc5\x82odz.txt', + b'@@ -1 +1 @@', + b'-\xa3odz is a city in Poland.', + b'+\xc5\x81odz is a city in Poland.', + ] + actual = difflib.diff_bytes(unified, a, b, fna, fnb, lineterm=b'') + assertDiff(expect, actual) + + # with dates (plain ASCII) + datea = b'2005-03-18' + dateb = b'2005-03-19' + check(difflib.diff_bytes(unified, a, b, fna, fnb, datea, dateb)) + check(difflib.diff_bytes(context, a, b, fna, fnb, datea, dateb)) + + expect = [ + # note the mixed encodings here: this is deeply wrong by every + # tenet of Unicode, but it doesn't crash, it's parseable by + # patch, and it's how UNIX(tm) diff behaves + b'--- \xb3odz.txt\t2005-03-18', + b'+++ \xc5\x82odz.txt\t2005-03-19', + b'@@ -1 +1 @@', + b'-\xa3odz is a city in Poland.', + b'+\xc5\x81odz is a city in Poland.', + ] + actual = difflib.diff_bytes(unified, a, b, fna, fnb, datea, dateb, + lineterm=b'') + assertDiff(expect, actual) + + def test_mixed_types_content(self): + # type of input content must be consistent: all str or all bytes + a = [b'hello'] + b = ['hello'] + + unified = difflib.unified_diff + context = difflib.context_diff + + expect = "lines to compare must be str, not bytes (b'hello')" + self._assert_type_error(expect, unified, a, b) + self._assert_type_error(expect, unified, b, a) + self._assert_type_error(expect, context, a, b) + self._assert_type_error(expect, context, b, a) + + expect = "all arguments must be bytes, not str ('hello')" + self._assert_type_error(expect, difflib.diff_bytes, unified, a, b) + self._assert_type_error(expect, difflib.diff_bytes, unified, b, a) + self._assert_type_error(expect, difflib.diff_bytes, context, a, b) + self._assert_type_error(expect, difflib.diff_bytes, context, b, a) + + def test_mixed_types_filenames(self): + # cannot pass filenames as bytes if content is str (this may not be + # the right behaviour, but at least the test demonstrates how + # things work) + a = ['hello\n'] + b = ['ohell\n'] + fna = b'ol\xe9.txt' # filename transcoded from ISO-8859-1 + fnb = b'ol\xc3a9.txt' # to UTF-8 + self._assert_type_error( + "all arguments must be str, not: b'ol\\xe9.txt'", + difflib.unified_diff, a, b, fna, fnb) + + def test_mixed_types_dates(self): + # type of dates must be consistent with type of contents + a = [b'foo\n'] + b = [b'bar\n'] + datea = '1 f?v' + dateb = '3 f?v' + self._assert_type_error( + "all arguments must be bytes, not str ('1 f?v')", + difflib.diff_bytes, difflib.unified_diff, + a, b, b'a', b'b', datea, dateb) + + # if input is str, non-ASCII dates are fine + a = ['foo\n'] + b = ['bar\n'] + list(difflib.unified_diff(a, b, 'a', 'b', datea, dateb)) + + def _assert_type_error(self, msg, generator, *args): + with self.assertRaises(TypeError) as ctx: + list(generator(*args)) + self.assertEqual(msg, str(ctx.exception)) + + def test_main(): difflib.HtmlDiff._default_prefix = 0 Doctests = doctest.DocTestSuite(difflib) run_unittest( TestWithAscii, TestAutojunk, TestSFpatches, TestSFbugs, - TestOutputFormat, Doctests) + TestOutputFormat, TestBytes, Doctests) if __name__ == '__main__': test_main() diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -195,6 +195,10 @@ - Issue #23310: Fix MagicMock's initializer to work with __methods__, just like configure_mock(). Patch by Kasia Jachim. +- Issue #17445: add difflib.diff_bytes() to support comparison of + byte strings (fixes a regression from Python 2). + + Build ----- -- Repository URL: https://hg.python.org/cpython From solipsis at pitrou.net Tue Apr 21 10:35:46 2015 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Tue, 21 Apr 2015 08:35:46 +0000 Subject: [Python-checkins] Daily reference leaks (1764d42b340d): sum=3 Message-ID: <20150421083546.30343.29739@psf.io> results for 1764d42b340d on branch "default" -------------------------------------------- test_functools leaked [0, 0, 3] memory blocks, sum=3 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogofRnAE', '--timeout', '7200'] From python-checkins at python.org Tue Apr 21 10:57:48 2015 From: python-checkins at python.org (christian.heimes) Date: Tue, 21 Apr 2015 08:57:48 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Get_rid_of_unused-but-set-?= =?utf-8?q?variable_warning=2E_len_and_len2_should_be_equal_and?= Message-ID: <20150421085748.6581.1451@psf.io> https://hg.python.org/cpython/rev/475c6a4dfab3 changeset: 95749:475c6a4dfab3 user: Christian Heimes date: Tue Apr 21 10:57:41 2015 +0200 summary: Get rid of unused-but-set-variable warning. len and len2 should be equal and len2 is technically more correct, too. files: Modules/posixmodule.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -9891,7 +9891,7 @@ return PyErr_NoMemory(); len2 = confstr(name, buf, len); assert(len == len2); - result = PyUnicode_DecodeFSDefaultAndSize(buf, len-1); + result = PyUnicode_DecodeFSDefaultAndSize(buf, len2-1); PyMem_Free(buf); } else -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Apr 21 18:07:11 2015 From: python-checkins at python.org (benjamin.peterson) Date: Tue, 21 Apr 2015 16:07:11 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?b?KTogbWVyZ2UgMy40ICgjMjQwMjIp?= Message-ID: <20150421160711.6581.4241@psf.io> https://hg.python.org/cpython/rev/03b2259c6cd3 changeset: 95751:03b2259c6cd3 parent: 95749:475c6a4dfab3 parent: 95750:414e08c478f4 user: Benjamin Peterson date: Tue Apr 21 12:07:06 2015 -0400 summary: merge 3.4 (#24022) files: Lib/test/test_compile.py | 14 +++++++++++++- Misc/NEWS | 2 ++ Parser/tokenizer.c | 7 +++---- 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/Lib/test/test_compile.py b/Lib/test/test_compile.py --- a/Lib/test/test_compile.py +++ b/Lib/test/test_compile.py @@ -1,9 +1,11 @@ import math +import os import unittest import sys import _ast +import tempfile import types -from test import support +from test import support, script_helper class TestSpecifics(unittest.TestCase): @@ -492,6 +494,16 @@ self.assertInvalidSingle('f()\nxy # blah\nblah()') self.assertInvalidSingle('x = 5 # comment\nx = 6\n') + def test_particularly_evil_undecodable(self): + # Issue 24022 + src = b'0000\x00\n00000000000\n\x00\n\x9e\n' + with tempfile.TemporaryDirectory() as tmpd: + fn = os.path.join(tmpd, "bad.py") + with open(fn, "wb") as fp: + fp.write(src) + res = script_helper.run_python_until_end(fn)[0] + self.assertIn(b"Non-UTF-8", res.err) + @support.cpython_only def test_compiler_recursion_limit(self): # Expected limit is sys.getrecursionlimit() * the scaling factor diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,8 @@ Core and Builtins ----------------- +- Issue #24022: Fix tokenizer crash when processing undecodable source code. + Library ------- diff --git a/Parser/tokenizer.c b/Parser/tokenizer.c --- a/Parser/tokenizer.c +++ b/Parser/tokenizer.c @@ -1307,6 +1307,8 @@ { PyObject *s; int result; + if (tok->decoding_erred) + return 0; s = PyUnicode_DecodeUTF8(tok->start, tok->cur - tok->start, NULL); if (s == NULL || PyUnicode_READY(s) == -1) { if (PyErr_ExceptionMatches(PyExc_UnicodeDecodeError)) { @@ -1475,11 +1477,8 @@ c = tok_nextc(tok); } tok_backup(tok, c); - if (nonascii && - !verify_identifier(tok)) { - tok->done = E_IDENTIFIER; + if (nonascii && !verify_identifier(tok)) return ERRORTOKEN; - } *p_start = tok->start; *p_end = tok->cur; return NAME; -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Apr 21 18:07:11 2015 From: python-checkins at python.org (benjamin.peterson) Date: Tue, 21 Apr 2015 16:07:11 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E4=29=3A_do_not_call_in?= =?utf-8?q?to_python_api_if_an_exception_is_set_=28=2324022=29?= Message-ID: <20150421160710.27900.79267@psf.io> https://hg.python.org/cpython/rev/414e08c478f4 changeset: 95750:414e08c478f4 branch: 3.4 parent: 95745:c9239543235e user: Benjamin Peterson date: Tue Apr 21 12:05:19 2015 -0400 summary: do not call into python api if an exception is set (#24022) files: Lib/test/test_compile.py | 14 +++++++++++++- Misc/NEWS | 2 ++ Parser/tokenizer.c | 7 +++---- 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/Lib/test/test_compile.py b/Lib/test/test_compile.py --- a/Lib/test/test_compile.py +++ b/Lib/test/test_compile.py @@ -1,9 +1,11 @@ import math +import os import unittest import sys import _ast +import tempfile import types -from test import support +from test import support, script_helper class TestSpecifics(unittest.TestCase): @@ -492,6 +494,16 @@ self.assertInvalidSingle('f()\nxy # blah\nblah()') self.assertInvalidSingle('x = 5 # comment\nx = 6\n') + def test_particularly_evil_undecodable(self): + # Issue 24022 + src = b'0000\x00\n00000000000\n\x00\n\x9e\n' + with tempfile.TemporaryDirectory() as tmpd: + fn = os.path.join(tmpd, "bad.py") + with open(fn, "wb") as fp: + fp.write(src) + res = script_helper.run_python_until_end(fn)[0] + self.assertIn(b"Non-UTF-8", res.err) + @support.cpython_only def test_compiler_recursion_limit(self): # Expected limit is sys.getrecursionlimit() * the scaling factor diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,8 @@ Core and Builtins ----------------- +- Issue #24022: Fix tokenizer crash when processing undecodable source code. + - Issue #23309: Avoid a deadlock at shutdown if a daemon thread is aborted while it is holding a lock to a buffered I/O object, and the main thread tries to use the same I/O object (typically stdout or stderr). A fatal diff --git a/Parser/tokenizer.c b/Parser/tokenizer.c --- a/Parser/tokenizer.c +++ b/Parser/tokenizer.c @@ -1301,6 +1301,8 @@ { PyObject *s; int result; + if (tok->decoding_erred) + return 0; s = PyUnicode_DecodeUTF8(tok->start, tok->cur - tok->start, NULL); if (s == NULL || PyUnicode_READY(s) == -1) { if (PyErr_ExceptionMatches(PyExc_UnicodeDecodeError)) { @@ -1469,11 +1471,8 @@ c = tok_nextc(tok); } tok_backup(tok, c); - if (nonascii && - !verify_identifier(tok)) { - tok->done = E_IDENTIFIER; + if (nonascii && !verify_identifier(tok)) return ERRORTOKEN; - } *p_start = tok->start; *p_end = tok->cur; return NAME; -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Apr 21 19:07:06 2015 From: python-checkins at python.org (yury.selivanov) Date: Tue, 21 Apr 2015 17:07:06 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_pep-0492=3A_More_info_on_=5F?= =?utf-8?q?=5Fcocall=5F=5F=3B_Add_a_section_about_coroutine-generators?= Message-ID: <20150421170706.31113.82304@psf.io> https://hg.python.org/peps/rev/08de7f65f280 changeset: 5781:08de7f65f280 user: Yury Selivanov date: Tue Apr 21 13:07:02 2015 -0400 summary: pep-0492: More info on __cocall__; Add a section about coroutine-generators files: pep-0492.txt | 26 +++++++++++++++++++++++++- 1 files changed, 25 insertions(+), 1 deletions(-) diff --git a/pep-0492.txt b/pep-0492.txt --- a/pep-0492.txt +++ b/pep-0492.txt @@ -737,10 +737,34 @@ addresses this problem with a different approach, see `Debugging Features`_. -5. There are no equivalents of ``async for`` and ``async with`` in PEP +5. A shortcoming of requiring a ``cocall`` keyword to call a coroutine + is that if is decided to implement coroutine-generators -- + coroutines with ``yield`` or ``async yield`` expressions -- we + wouldn't need a ``cocall`` keyword to call them. So we'll end up + having ``__cocall__`` and no ``__call__`` for regular coroutines, + and having ``__call__`` and no ``__cocall__`` for coroutine- + generators. + +6. There are no equivalents of ``async for`` and ``async with`` in PEP 3152. +Coroutine-generators +-------------------- + +With ``async for`` keyword it is desirable to have a concept of a +*coroutine-generator* -- a coroutine with ``yield`` and ``yield from`` +expressions. To avoid any ambiguity with regular generators, we would +likely require to have an ``async`` keyword before ``yield``, and +``async yield from`` would raise a ``StopAsyncIteration`` exception. + +While it is possible to implement coroutine-generators, we believe that +they are out of scope of this proposal. It is an advanced concept that +should be carefully considered and balanced, with a non-trivial changes +in the implementation of current generator objects. This is a matter +for a separate PEP. + + No implicit wrapping in Futures ------------------------------- -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Tue Apr 21 19:10:26 2015 From: python-checkins at python.org (yury.selivanov) Date: Tue, 21 Apr 2015 17:10:26 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_pep-0492=3A_Bump_post-history?= Message-ID: <20150421171026.6595.77171@psf.io> https://hg.python.org/peps/rev/56af525ebd7f changeset: 5782:56af525ebd7f user: Yury Selivanov date: Tue Apr 21 13:10:22 2015 -0400 summary: pep-0492: Bump post-history files: pep-0492.txt | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/pep-0492.txt b/pep-0492.txt --- a/pep-0492.txt +++ b/pep-0492.txt @@ -8,7 +8,7 @@ Content-Type: text/x-rst Created: 09-Apr-2015 Python-Version: 3.5 -Post-History: 17-Apr-2015 +Post-History: 17-Apr-2015, 21-Apr-2015 Abstract -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Tue Apr 21 20:11:46 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Tue, 21 Apr 2015 18:11:46 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzIzMDA4?= =?utf-8?q?=3A_Fixed_resolving_attributes_with_boolean_value_is_False_in_p?= =?utf-8?q?ydoc=2E?= Message-ID: <20150421181145.30760.41692@psf.io> https://hg.python.org/cpython/rev/d1b9eb9de8af changeset: 95752:d1b9eb9de8af branch: 2.7 parent: 95746:3cf2990d19ab user: Serhiy Storchaka date: Tue Apr 21 21:09:23 2015 +0300 summary: Issue #23008: Fixed resolving attributes with boolean value is False in pydoc. files: Lib/pydoc.py | 2 +- Misc/NEWS | 2 ++ 2 files changed, 3 insertions(+), 1 deletions(-) diff --git a/Lib/pydoc.py b/Lib/pydoc.py --- a/Lib/pydoc.py +++ b/Lib/pydoc.py @@ -1540,7 +1540,7 @@ """Given an object or a path to an object, get the object and its name.""" if isinstance(thing, str): object = locate(thing, forceload) - if not object: + if object is None: raise ImportError, 'no Python documentation found for %r' % thing return object, thing else: diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -21,6 +21,8 @@ Library ------- +- Issue #23008: Fixed resolving attributes with boolean value is False in pydoc. + - Issue #23842: os.major(), os.minor() and os.makedev() now support ints again. - Issue #23811: Add missing newline to the PyCompileError error message. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Apr 21 20:11:46 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Tue, 21 Apr 2015 18:11:46 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2323008=3A_Fixed_resolving_attributes_with_boolea?= =?utf-8?q?n_value_is_False_in_pydoc=2E?= Message-ID: <20150421181146.30345.54925@psf.io> https://hg.python.org/cpython/rev/03330e5edb37 changeset: 95754:03330e5edb37 parent: 95751:03b2259c6cd3 parent: 95753:a480f470c469 user: Serhiy Storchaka date: Tue Apr 21 21:11:13 2015 +0300 summary: Issue #23008: Fixed resolving attributes with boolean value is False in pydoc. files: Lib/pydoc.py | 2 +- Lib/test/test_pydoc.py | 8 ++++++++ Misc/NEWS | 2 ++ 3 files changed, 11 insertions(+), 1 deletions(-) diff --git a/Lib/pydoc.py b/Lib/pydoc.py --- a/Lib/pydoc.py +++ b/Lib/pydoc.py @@ -1588,7 +1588,7 @@ """Given an object or a path to an object, get the object and its name.""" if isinstance(thing, str): object = locate(thing, forceload) - if not object: + if object is None: raise ImportError('''\ No Python documentation found for %r. Use help() to get the interactive help utility. 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 @@ -1006,6 +1006,14 @@ result = output.getvalue().strip() self.assertEqual(expected_text, result) + def test_resolve_false(self): + # Issue #23008: pydoc enum.{,Int}Enum failed + # because bool(enum.Enum) is False. + with captured_stdout() as help_io: + pydoc.help('enum.Enum') + helptext = help_io.getvalue() + self.assertIn('class Enum', helptext) + @reap_threads def test_main(): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -15,6 +15,8 @@ Library ------- +- Issue #23008: Fixed resolving attributes with boolean value is False in pydoc. + - Fix asyncio issue 235: LifoQueue and PriorityQueue's put didn't increment unfinished tasks (this bug was introduced when JoinableQueue was merged with Queue). -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Apr 21 20:11:47 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Tue, 21 Apr 2015 18:11:47 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzIzMDA4?= =?utf-8?q?=3A_Fixed_resolving_attributes_with_boolean_value_is_False_in_p?= =?utf-8?q?ydoc=2E?= Message-ID: <20150421181146.98632.18513@psf.io> https://hg.python.org/cpython/rev/a480f470c469 changeset: 95753:a480f470c469 branch: 3.4 parent: 95750:414e08c478f4 user: Serhiy Storchaka date: Tue Apr 21 21:09:48 2015 +0300 summary: Issue #23008: Fixed resolving attributes with boolean value is False in pydoc. files: Lib/pydoc.py | 2 +- Lib/test/test_pydoc.py | 8 ++++++++ Misc/NEWS | 2 ++ 3 files changed, 11 insertions(+), 1 deletions(-) diff --git a/Lib/pydoc.py b/Lib/pydoc.py --- a/Lib/pydoc.py +++ b/Lib/pydoc.py @@ -1590,7 +1590,7 @@ """Given an object or a path to an object, get the object and its name.""" if isinstance(thing, str): object = locate(thing, forceload) - if not object: + if object is None: raise ImportError('no Python documentation found for %r' % thing) return object, thing else: 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 @@ -1029,6 +1029,14 @@ print_diffs(expected_text, result) self.fail("outputs are not equal, see diff above") + def test_resolve_false(self): + # Issue #23008: pydoc enum.{,Int}Enum failed + # because bool(enum.Enum) is False. + with captured_stdout() as help_io: + pydoc.help('enum.Enum') + helptext = help_io.getvalue() + self.assertIn('class Enum', helptext) + @reap_threads def test_main(): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -31,6 +31,8 @@ Library ------- +- Issue #23008: Fixed resolving attributes with boolean value is False in pydoc. + - Fix asyncio issue 235: LifoQueue and PriorityQueue's put didn't increment unfinished tasks (this bug was introduced in 3.4.3 when JoinableQueue was merged with Queue). -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Apr 21 20:18:03 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Tue, 21 Apr 2015 18:18:03 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzE2ODQw?= =?utf-8?q?=2E_Turn_off_bignum_support_in_tkinter_with_with_Tcl_earlier_th?= =?utf-8?q?an?= Message-ID: <20150421181801.82000.43039@psf.io> https://hg.python.org/cpython/rev/5116916e4f7f changeset: 95755:5116916e4f7f branch: 2.7 parent: 95752:d1b9eb9de8af user: Serhiy Storchaka date: Tue Apr 21 21:17:33 2015 +0300 summary: Issue #16840. Turn off bignum support in tkinter with with Tcl earlier than 8.5.8 (tclTomMath.h was broken) and non-final Tcl 8.6. files: Modules/_tkinter.c | 7 ++++--- Modules/tkinter.h | 22 +++++++++++++++------- 2 files changed, 19 insertions(+), 10 deletions(-) diff --git a/Modules/_tkinter.c b/Modules/_tkinter.c --- a/Modules/_tkinter.c +++ b/Modules/_tkinter.c @@ -80,7 +80,7 @@ #define CONST #endif -#if TK_VERSION_HEX < 0x08030102 +#if TK_HEX_VERSION < 0x08030201 #error "Tk older than 8.3.1 not supported" #endif @@ -96,7 +96,8 @@ #error "unsupported Tcl configuration" #endif -#if TK_VERSION_HEX >= 0x08050002 +#if TK_HEX_VERSION >= 0x08050208 && TK_HEX_VERSION < 0x08060000 || \ + TK_HEX_VERSION >= 0x08060200 #define HAVE_LIBTOMMAMTH #include #endif @@ -1405,7 +1406,7 @@ #endif } -#if TK_VERSION_HEX >= 0x08050000 +#if TK_HEX_VERSION >= 0x08050000 if (app->BooleanType == NULL && strcmp(value->typePtr->name, "booleanString") == 0) { /* booleanString type is not registered in Tcl */ diff --git a/Modules/tkinter.h b/Modules/tkinter.h --- a/Modules/tkinter.h +++ b/Modules/tkinter.h @@ -4,24 +4,32 @@ /* This header is used to share some macros between _tkinter.c and * tkappinit.c. * Be sure to include tk.h before including this header so - * TK_VERSION_HEX is properly defined. */ + * TK_HEX_VERSION is properly defined. */ /* TK_RELEASE_LEVEL is always one of the following: - * TCL_ALPHA_RELEASE 0 + * TCL_ALPHA_RELEASE 0 * TCL_BETA_RELEASE 1 * TCL_FINAL_RELEASE 2 */ +#define TK_HEX_VERSION ((TK_MAJOR_VERSION << 24) | \ + (TK_MINOR_VERSION << 16) | \ + (TK_RELEASE_LEVEL << 8) | \ + (TK_RELEASE_SERIAL << 0)) + +/* TK_VERSION_HEX packs fields in wrong order, not suitable for comparing of + * non-final releases. Left for backward compatibility. + */ #define TK_VERSION_HEX ((TK_MAJOR_VERSION << 24) | \ - (TK_MINOR_VERSION << 16) | \ - (TK_RELEASE_SERIAL << 8) | \ - (TK_RELEASE_LEVEL << 0)) + (TK_MINOR_VERSION << 16) | \ + (TK_RELEASE_SERIAL << 8) | \ + (TK_RELEASE_LEVEL << 0)) /* Protect Tk 8.4.13 and older from a deadlock that happens when trying * to load tk after a failed attempt. */ -#if TK_VERSION_HEX < 0x08040e02 +#if TK_HEX_VERSION < 0x0804020e #define TKINTER_PROTECT_LOADTK #define TKINTER_LOADTK_ERRMSG \ - "Calling Tk_Init again after a previous call failed might deadlock" + "Calling Tk_Init again after a previous call failed might deadlock" #endif #endif /* !TKINTER_H */ -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Apr 21 22:19:33 2015 From: python-checkins at python.org (benjamin.peterson) Date: Tue, 21 Apr 2015 20:19:33 +0000 Subject: [Python-checkins] =?utf-8?q?devguide=3A_note_removal_of_Skip?= Message-ID: <20150421201928.98646.98940@psf.io> https://hg.python.org/devguide/rev/326e0a588978 changeset: 742:326e0a588978 user: Benjamin Peterson date: Tue Apr 21 16:19:23 2015 -0400 summary: note removal of Skip files: developers.rst | 3 +++ 1 files changed, 3 insertions(+), 0 deletions(-) diff --git a/developers.rst b/developers.rst --- a/developers.rst +++ b/developers.rst @@ -407,6 +407,9 @@ Permissions Dropped on Request ------------------------------ +- Skip Montanaro's permissions were removed on 21 April 2015 by BCP per `his + request `_. + - Roy Smith, Matt Fleming and Richard Emslie sent drop requests. 4 Aug 2008 GFB -- Repository URL: https://hg.python.org/devguide From python-checkins at python.org Wed Apr 22 01:46:59 2015 From: python-checkins at python.org (andrew.kuchling) Date: Tue, 21 Apr 2015 23:46:59 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogIzE1MTgzOiBjbGFy?= =?utf-8?q?ify_timeit_documentation_to_say_that_setup_statement_isn=27t_ti?= =?utf-8?q?med?= Message-ID: <20150421234659.98634.9276@psf.io> https://hg.python.org/cpython/rev/e0e3d2ec56b6 changeset: 95756:e0e3d2ec56b6 branch: 3.4 parent: 95753:a480f470c469 user: Andrew Kuchling date: Tue Apr 21 19:43:33 2015 -0400 summary: #15183: clarify timeit documentation to say that setup statement isn't timed files: Doc/library/timeit.rst | 2 ++ Lib/timeit.py | 3 ++- 2 files changed, 4 insertions(+), 1 deletions(-) diff --git a/Doc/library/timeit.rst b/Doc/library/timeit.rst --- a/Doc/library/timeit.rst +++ b/Doc/library/timeit.rst @@ -94,6 +94,8 @@ method. The :meth:`.repeat` method is a convenience to call :meth:`.timeit` multiple times and return a list of results. + The execution time of *setup* is excluded from the overall timed execution run. + The *stmt* and *setup* parameters can also take objects that are callable without arguments. This will embed calls to them in a timer function that will then be executed by :meth:`.timeit`. Note that the timing overhead is a diff --git a/Lib/timeit.py b/Lib/timeit.py --- a/Lib/timeit.py +++ b/Lib/timeit.py @@ -14,7 +14,8 @@ Options: -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') + -s/--setup S: statement to be executed once initially (default 'pass'). + Execution time of this setup statement is NOT timed. -p/--process: use time.process_time() (default is time.perf_counter()) -t/--time: use time.time() (deprecated) -c/--clock: use time.clock() (deprecated) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Apr 22 01:47:00 2015 From: python-checkins at python.org (andrew.kuchling) Date: Tue, 21 Apr 2015 23:47:00 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Merge_from_3=2E4?= Message-ID: <20150421234659.30752.38115@psf.io> https://hg.python.org/cpython/rev/25c03271860d changeset: 95757:25c03271860d parent: 95754:03330e5edb37 parent: 95756:e0e3d2ec56b6 user: Andrew Kuchling date: Tue Apr 21 19:44:54 2015 -0400 summary: Merge from 3.4 files: Doc/library/timeit.rst | 2 ++ Lib/timeit.py | 3 ++- 2 files changed, 4 insertions(+), 1 deletions(-) diff --git a/Doc/library/timeit.rst b/Doc/library/timeit.rst --- a/Doc/library/timeit.rst +++ b/Doc/library/timeit.rst @@ -104,6 +104,8 @@ method. The :meth:`.repeat` method is a convenience to call :meth:`.timeit` multiple times and return a list of results. + The execution time of *setup* is excluded from the overall timed execution run. + The *stmt* and *setup* parameters can also take objects that are callable without arguments. This will embed calls to them in a timer function that will then be executed by :meth:`.timeit`. Note that the timing overhead is a diff --git a/Lib/timeit.py b/Lib/timeit.py --- a/Lib/timeit.py +++ b/Lib/timeit.py @@ -14,7 +14,8 @@ Options: -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') + -s/--setup S: statement to be executed once initially (default 'pass'). + Execution time of this setup statement is NOT timed. -p/--process: use time.process_time() (default is time.perf_counter()) -t/--time: use time.time() (deprecated) -c/--clock: use time.clock() (deprecated) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Apr 22 02:52:27 2015 From: python-checkins at python.org (yury.selivanov) Date: Wed, 22 Apr 2015 00:52:27 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_pep-0492=3A_Add_flow=5Fstmt_t?= =?utf-8?q?o_Grammar?= Message-ID: <20150422005226.22482.4418@psf.io> https://hg.python.org/peps/rev/e4e94b8fcf45 changeset: 5783:e4e94b8fcf45 user: Yury Selivanov date: Tue Apr 21 20:52:19 2015 -0400 summary: pep-0492: Add flow_stmt to Grammar files: pep-0492.txt | 3 +++ 1 files changed, 3 insertions(+), 0 deletions(-) diff --git a/pep-0492.txt b/pep-0492.txt --- a/pep-0492.txt +++ b/pep-0492.txt @@ -608,6 +608,9 @@ with_stmt | funcdef | classdef | decorated | async_stmt) + flow_stmt: (break_stmt | continue_stmt | return_stmt | + raise_stmt | yield_stmt | await_stmt) + atom: ('(' [yield_expr|await_expr|testlist_comp] ')' | '[' [testlist_comp] ']' | '{' [dictorsetmaker] '}' | -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Wed Apr 22 06:53:02 2015 From: python-checkins at python.org (berker.peksag) Date: Wed, 22 Apr 2015 04:53:02 +0000 Subject: [Python-checkins] =?utf-8?q?devguide=3A_Issue_=2316574=3A_Clarify?= =?utf-8?q?_that_once_a_PEP_has_implemented=2C_it_needs_be?= Message-ID: <20150422045302.82010.58838@psf.io> https://hg.python.org/devguide/rev/0c4006b7c7ff changeset: 743:0c4006b7c7ff user: Berker Peksag date: Wed Apr 22 07:53:34 2015 +0300 summary: Issue #16574: Clarify that once a PEP has implemented, it needs be documented in Python docs. Patch by Carol Willing. Wording suggested by Terry J. Reedy. files: documenting.rst | 4 +++- 1 files changed, 3 insertions(+), 1 deletions(-) diff --git a/documenting.rst b/documenting.rst --- a/documenting.rst +++ b/documenting.rst @@ -1125,7 +1125,9 @@ A reference to a Python Enhancement Proposal. This generates appropriate index entries. The text "PEP *number*\ " is generated; in the HTML output, - this text is a hyperlink to an online copy of the specified PEP. + this text is a hyperlink to an online copy of the specified PEP. Such + hyperlinks should not be a substitute for properly documenting the + language in the manuals. .. describe:: rfc -- Repository URL: https://hg.python.org/devguide From python-checkins at python.org Wed Apr 22 08:38:49 2015 From: python-checkins at python.org (berker.peksag) Date: Wed, 22 Apr 2015 06:38:49 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2323917=3A_Fall_bac?= =?utf-8?q?k_to_sequential_compilation_when_ProcessPoolExecutor?= Message-ID: <20150422063849.6589.81457@psf.io> https://hg.python.org/cpython/rev/572dc6bdc0a3 changeset: 95758:572dc6bdc0a3 user: Berker Peksag date: Wed Apr 22 09:39:19 2015 +0300 summary: Issue #23917: Fall back to sequential compilation when ProcessPoolExecutor doesn't exist. Patch by Claudiu Popa. files: Doc/library/compileall.rst | 4 ++-- Lib/compileall.py | 4 +--- Lib/test/test_compileall.py | 8 ++++---- Misc/NEWS | 3 +++ 4 files changed, 10 insertions(+), 9 deletions(-) diff --git a/Doc/library/compileall.rst b/Doc/library/compileall.rst --- a/Doc/library/compileall.rst +++ b/Doc/library/compileall.rst @@ -142,8 +142,8 @@ The argument *workers* specifies how many workers are used to compile files in parallel. The default is to not use multiple workers. If the platform can't use multiple workers and *workers* argument is given, - then a :exc:`NotImplementedError` will be raised. - If *workers* is lower than ``0``, a :exc:`ValueError` will be raised. + then sequential compilation will be used as a fallback. If *workers* is + lower than ``0``, a :exc:`ValueError` will be raised. .. versionchanged:: 3.2 Added the *legacy* and *optimize* parameter. diff --git a/Lib/compileall.py b/Lib/compileall.py --- a/Lib/compileall.py +++ b/Lib/compileall.py @@ -69,11 +69,9 @@ files = _walk_dir(dir, quiet=quiet, maxlevels=maxlevels, ddir=ddir) success = 1 - if workers is not None and workers != 1: + if workers is not None and workers != 1 and ProcessPoolExecutor is not None: if workers < 0: raise ValueError('workers must be greater or equal to 0') - if ProcessPoolExecutor is None: - raise NotImplementedError('multiprocessing support not available') workers = workers or None with ProcessPoolExecutor(max_workers=workers) as executor: diff --git a/Lib/test/test_compileall.py b/Lib/test/test_compileall.py --- a/Lib/test/test_compileall.py +++ b/Lib/test/test_compileall.py @@ -136,10 +136,10 @@ self.assertTrue(compile_file_mock.called) @mock.patch('compileall.ProcessPoolExecutor', new=None) - def test_compile_missing_multiprocessing(self): - with self.assertRaisesRegex(NotImplementedError, - "multiprocessing support not available"): - compileall.compile_dir(self.directory, quiet=True, workers=5) + @mock.patch('compileall.compile_file') + def test_compile_missing_multiprocessing(self, compile_file_mock): + compileall.compile_dir(self.directory, quiet=True, workers=5) + self.assertTrue(compile_file_mock.called) class EncodingTest(unittest.TestCase): """Issue 6716: compileall should escape source code when printing errors diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -15,6 +15,9 @@ Library ------- +- Issue #23917: Fall back to sequential compilation when ProcessPoolExecutor + doesn't exist. Patch by Claudiu Popa. + - Issue #23008: Fixed resolving attributes with boolean value is False in pydoc. - Fix asyncio issue 235: LifoQueue and PriorityQueue's put didn't -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Apr 22 10:02:32 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Wed, 22 Apr 2015 08:02:32 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzE2ODQw?= =?utf-8?q?=3A_Skip_bignum_tests_on_minor_releases_where_they_are_not_supp?= =?utf-8?q?orted=2E?= Message-ID: <20150422080232.21347.24618@psf.io> https://hg.python.org/cpython/rev/4bf210f59ac6 changeset: 95762:4bf210f59ac6 branch: 2.7 parent: 95759:cebe15821a0c user: Serhiy Storchaka date: Wed Apr 22 10:51:49 2015 +0300 summary: Issue #16840: Skip bignum tests on minor releases where they are not supported. files: Lib/test/test_tcl.py | 4 +++- 1 files changed, 3 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_tcl.py b/Lib/test/test_tcl.py --- a/Lib/test/test_tcl.py +++ b/Lib/test/test_tcl.py @@ -130,7 +130,9 @@ integers = (0, 1, -1, 2**31-1, -2**31) if tcl_version >= (8, 4): # wideInt was added in Tcl 8.4 integers += (2**31, -2**31-1, 2**63-1, -2**63) - if tcl_version >= (8, 5): # bignum was added in Tcl 8.5 + # bignum was added in Tcl 8.5, but its support is able only since 8.5.8 + if (get_tk_patchlevel() >= (8, 6, 0, 'final') or + (8, 5, 8) <= get_tk_patchlevel() < (8, 6)): integers += (2**63, -2**63-1, 2**1000, -2**1000) return integers -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Apr 22 10:02:32 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Wed, 22 Apr 2015 08:02:32 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzE2ODQw?= =?utf-8?q?=2E_Turn_off_bignum_support_in_tkinter_with_with_Tcl_earlier_th?= =?utf-8?q?an?= Message-ID: <20150422080232.27918.48271@psf.io> https://hg.python.org/cpython/rev/97519d85b5c8 changeset: 95763:97519d85b5c8 branch: 3.4 parent: 95760:5bf0d9086cfc user: Serhiy Storchaka date: Wed Apr 22 10:53:08 2015 +0300 summary: Issue #16840. Turn off bignum support in tkinter with with Tcl earlier than 8.5.8 (tclTomMath.h was broken) and non-final Tcl 8.6. files: Lib/test/test_tcl.py | 4 +++- Modules/_tkinter.c | 7 ++++--- Modules/tkinter.h | 22 +++++++++++++++------- 3 files changed, 22 insertions(+), 11 deletions(-) diff --git a/Lib/test/test_tcl.py b/Lib/test/test_tcl.py --- a/Lib/test/test_tcl.py +++ b/Lib/test/test_tcl.py @@ -133,7 +133,9 @@ integers = (0, 1, -1, 2**31-1, -2**31) if tcl_version >= (8, 4): # wideInt was added in Tcl 8.4 integers += (2**31, -2**31-1, 2**63-1, -2**63) - if tcl_version >= (8, 5): # bignum was added in Tcl 8.5 + # bignum was added in Tcl 8.5, but its support is able only since 8.5.8 + if (get_tk_patchlevel() >= (8, 6, 0, 'final') or + (8, 5, 8) <= get_tk_patchlevel() < (8, 6)): integers += (2**63, -2**63-1, 2**1000, -2**1000) return integers diff --git a/Modules/_tkinter.c b/Modules/_tkinter.c --- a/Modules/_tkinter.c +++ b/Modules/_tkinter.c @@ -65,11 +65,12 @@ #define CONST #endif -#if TK_VERSION_HEX < 0x08030102 +#if TK_HEX_VERSION < 0x08030201 #error "Tk older than 8.3.1 not supported" #endif -#if TK_VERSION_HEX >= 0x08050002 +#if TK_HEX_VERSION >= 0x08050208 && TK_HEX_VERSION < 0x08060000 || \ + TK_HEX_VERSION >= 0x08060200 #define HAVE_LIBTOMMAMTH #include #endif @@ -1214,7 +1215,7 @@ Tcl_GetCharLength(value)); } -#if TK_VERSION_HEX >= 0x08050000 +#if TK_HEX_VERSION >= 0x08050000 if (app->BooleanType == NULL && strcmp(value->typePtr->name, "booleanString") == 0) { /* booleanString type is not registered in Tcl */ diff --git a/Modules/tkinter.h b/Modules/tkinter.h --- a/Modules/tkinter.h +++ b/Modules/tkinter.h @@ -4,24 +4,32 @@ /* This header is used to share some macros between _tkinter.c and * tkappinit.c. * Be sure to include tk.h before including this header so - * TK_VERSION_HEX is properly defined. */ + * TK_HEX_VERSION is properly defined. */ /* TK_RELEASE_LEVEL is always one of the following: - * TCL_ALPHA_RELEASE 0 + * TCL_ALPHA_RELEASE 0 * TCL_BETA_RELEASE 1 * TCL_FINAL_RELEASE 2 */ +#define TK_HEX_VERSION ((TK_MAJOR_VERSION << 24) | \ + (TK_MINOR_VERSION << 16) | \ + (TK_RELEASE_LEVEL << 8) | \ + (TK_RELEASE_SERIAL << 0)) + +/* TK_VERSION_HEX packs fields in wrong order, not suitable for comparing of + * non-final releases. Left for backward compatibility. + */ #define TK_VERSION_HEX ((TK_MAJOR_VERSION << 24) | \ - (TK_MINOR_VERSION << 16) | \ - (TK_RELEASE_SERIAL << 8) | \ - (TK_RELEASE_LEVEL << 0)) + (TK_MINOR_VERSION << 16) | \ + (TK_RELEASE_SERIAL << 8) | \ + (TK_RELEASE_LEVEL << 0)) /* Protect Tk 8.4.13 and older from a deadlock that happens when trying * to load tk after a failed attempt. */ -#if TK_VERSION_HEX < 0x08040e02 +#if TK_HEX_VERSION < 0x0804020e #define TKINTER_PROTECT_LOADTK #define TKINTER_LOADTK_ERRMSG \ - "Calling Tk_Init again after a previous call failed might deadlock" + "Calling Tk_Init again after a previous call failed might deadlock" #endif #endif /* !TKINTER_H */ -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Apr 22 10:02:31 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Wed, 22 Apr 2015 08:02:31 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_Fixed_full_Tcl?= =?utf-8?q?_version_parsing_in_tests_for_pre-final_versions=2E?= Message-ID: <20150422080231.31113.29103@psf.io> https://hg.python.org/cpython/rev/cebe15821a0c changeset: 95759:cebe15821a0c branch: 2.7 parent: 95755:5116916e4f7f user: Serhiy Storchaka date: Wed Apr 22 08:35:53 2015 +0300 summary: Fixed full Tcl version parsing in tests for pre-final versions. files: Lib/lib-tk/test/test_ttk/support.py | 18 ++++--- Lib/lib-tk/test/test_ttk/test_widgets.py | 4 +- Lib/test/test_tcl.py | 26 +++++------ 3 files changed, 23 insertions(+), 25 deletions(-) diff --git a/Lib/lib-tk/test/test_ttk/support.py b/Lib/lib-tk/test/test_ttk/support.py --- a/Lib/lib-tk/test/test_ttk/support.py +++ b/Lib/lib-tk/test/test_ttk/support.py @@ -1,3 +1,4 @@ +import re import unittest import Tkinter as tkinter @@ -61,14 +62,15 @@ global _tk_patchlevel if _tk_patchlevel is None: tcl = tkinter.Tcl() - patchlevel = [] - for x in tcl.call('info', 'patchlevel').split('.'): - try: - x = int(x, 10) - except ValueError: - x = -1 - patchlevel.append(x) - _tk_patchlevel = tuple(patchlevel) + patchlevel = tcl.call('info', 'patchlevel') + m = re.match(r'(\d+)\.(\d+)([ab.])(\d+)$', patchlevel) + major, minor, releaselevel, serial = m.groups() + major, minor, serial = int(major), int(minor), int(serial) + releaselevel = {'a': 'alpha', 'b': 'beta', '.': 'final'}[releaselevel] + if releaselevel == 'final': + _tk_patchlevel = major, minor, serial, releaselevel, 0 + else: + _tk_patchlevel = major, minor, 0, releaselevel, serial return _tk_patchlevel units = { diff --git a/Lib/lib-tk/test/test_ttk/test_widgets.py b/Lib/lib-tk/test/test_ttk/test_widgets.py --- a/Lib/lib-tk/test/test_ttk/test_widgets.py +++ b/Lib/lib-tk/test/test_ttk/test_widgets.py @@ -22,7 +22,7 @@ widget = self.create() self.assertEqual(widget['class'], '') errmsg='attempt to change read-only option' - if get_tk_patchlevel() < (8, 6, 0): # actually this was changed in 8.6b3 + if get_tk_patchlevel() < (8, 6, 0, 'beta', 3): errmsg='Attempt to change read-only option' self.checkInvalidParam(widget, 'class', 'Foo', errmsg=errmsg) widget2 = self.create(class_='Foo') @@ -553,7 +553,7 @@ widget = self.create() self.assertEqual(str(widget['orient']), 'vertical') errmsg='attempt to change read-only option' - if get_tk_patchlevel() < (8, 6, 0): # actually this was changed in 8.6b3 + if get_tk_patchlevel() < (8, 6, 0, 'beta', 3): errmsg='Attempt to change read-only option' self.checkInvalidParam(widget, 'orient', 'horizontal', errmsg=errmsg) diff --git a/Lib/test/test_tcl.py b/Lib/test/test_tcl.py --- a/Lib/test/test_tcl.py +++ b/Lib/test/test_tcl.py @@ -1,4 +1,5 @@ import unittest +import re import sys import os from test import test_support @@ -18,27 +19,22 @@ except ImportError: INT_MAX = PY_SSIZE_T_MAX = sys.maxsize -tcl_version = _tkinter.TCL_VERSION.split('.') -try: - for i in range(len(tcl_version)): - tcl_version[i] = int(tcl_version[i]) -except ValueError: - pass -tcl_version = tuple(tcl_version) +tcl_version = tuple(map(int, _tkinter.TCL_VERSION.split('.'))) _tk_patchlevel = None def get_tk_patchlevel(): global _tk_patchlevel if _tk_patchlevel is None: tcl = Tcl() - patchlevel = [] - for x in tcl.call('info', 'patchlevel').split('.'): - try: - x = int(x, 10) - except ValueError: - x = -1 - patchlevel.append(x) - _tk_patchlevel = tuple(patchlevel) + patchlevel = tcl.call('info', 'patchlevel') + m = re.match(r'(\d+)\.(\d+)([ab.])(\d+)$', patchlevel) + major, minor, releaselevel, serial = m.groups() + major, minor, serial = int(major), int(minor), int(serial) + releaselevel = {'a': 'alpha', 'b': 'beta', '.': 'final'}[releaselevel] + if releaselevel == 'final': + _tk_patchlevel = major, minor, serial, releaselevel, 0 + else: + _tk_patchlevel = major, minor, 0, releaselevel, serial return _tk_patchlevel -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Apr 22 10:02:31 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Wed, 22 Apr 2015 08:02:31 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E4=29=3A_Fixed_full_Tcl?= =?utf-8?q?_version_parsing_in_tests_for_pre-final_versions=2E?= Message-ID: <20150422080231.31111.70520@psf.io> https://hg.python.org/cpython/rev/5bf0d9086cfc changeset: 95760:5bf0d9086cfc branch: 3.4 parent: 95756:e0e3d2ec56b6 user: Serhiy Storchaka date: Wed Apr 22 08:36:03 2015 +0300 summary: Fixed full Tcl version parsing in tests for pre-final versions. files: Lib/test/test_tcl.py | 26 ++++------ Lib/tkinter/test/support.py | 20 ++++---- Lib/tkinter/test/test_ttk/test_widgets.py | 4 +- 3 files changed, 23 insertions(+), 27 deletions(-) diff --git a/Lib/test/test_tcl.py b/Lib/test/test_tcl.py --- a/Lib/test/test_tcl.py +++ b/Lib/test/test_tcl.py @@ -1,4 +1,5 @@ import unittest +import re import sys import os from test import support @@ -17,27 +18,22 @@ except ImportError: INT_MAX = PY_SSIZE_T_MAX = sys.maxsize -tcl_version = _tkinter.TCL_VERSION.split('.') -try: - for i in range(len(tcl_version)): - tcl_version[i] = int(tcl_version[i]) -except ValueError: - pass -tcl_version = tuple(tcl_version) +tcl_version = tuple(map(int, _tkinter.TCL_VERSION.split('.'))) _tk_patchlevel = None def get_tk_patchlevel(): global _tk_patchlevel if _tk_patchlevel is None: tcl = Tcl() - patchlevel = [] - for x in tcl.call('info', 'patchlevel').split('.'): - try: - x = int(x, 10) - except ValueError: - x = -1 - patchlevel.append(x) - _tk_patchlevel = tuple(patchlevel) + patchlevel = tcl.call('info', 'patchlevel') + m = re.fullmatch(r'(\d+)\.(\d+)([ab.])(\d+)', patchlevel) + major, minor, releaselevel, serial = m.groups() + major, minor, serial = int(major), int(minor), int(serial) + releaselevel = {'a': 'alpha', 'b': 'beta', '.': 'final'}[releaselevel] + if releaselevel == 'final': + _tk_patchlevel = major, minor, serial, releaselevel, 0 + else: + _tk_patchlevel = major, minor, 0, releaselevel, serial return _tk_patchlevel diff --git a/Lib/tkinter/test/support.py b/Lib/tkinter/test/support.py --- a/Lib/tkinter/test/support.py +++ b/Lib/tkinter/test/support.py @@ -1,7 +1,6 @@ -import sys +import re import tkinter import unittest -from test.support import requires class AbstractTkTest: @@ -63,14 +62,15 @@ global _tk_patchlevel if _tk_patchlevel is None: tcl = tkinter.Tcl() - patchlevel = [] - for x in tcl.call('info', 'patchlevel').split('.'): - try: - x = int(x, 10) - except ValueError: - x = -1 - patchlevel.append(x) - _tk_patchlevel = tuple(patchlevel) + patchlevel = tcl.call('info', 'patchlevel') + m = re.fullmatch(r'(\d+)\.(\d+)([ab.])(\d+)', patchlevel) + major, minor, releaselevel, serial = m.groups() + major, minor, serial = int(major), int(minor), int(serial) + releaselevel = {'a': 'alpha', 'b': 'beta', '.': 'final'}[releaselevel] + if releaselevel == 'final': + _tk_patchlevel = major, minor, serial, releaselevel, 0 + else: + _tk_patchlevel = major, minor, 0, releaselevel, serial return _tk_patchlevel units = { diff --git a/Lib/tkinter/test/test_ttk/test_widgets.py b/Lib/tkinter/test/test_ttk/test_widgets.py --- a/Lib/tkinter/test/test_ttk/test_widgets.py +++ b/Lib/tkinter/test/test_ttk/test_widgets.py @@ -20,7 +20,7 @@ widget = self.create() self.assertEqual(widget['class'], '') errmsg='attempt to change read-only option' - if get_tk_patchlevel() < (8, 6, 0): # actually this was changed in 8.6b3 + if get_tk_patchlevel() < (8, 6, 0, 'beta', 3): errmsg='Attempt to change read-only option' self.checkInvalidParam(widget, 'class', 'Foo', errmsg=errmsg) widget2 = self.create(class_='Foo') @@ -551,7 +551,7 @@ widget = self.create() self.assertEqual(str(widget['orient']), 'vertical') errmsg='attempt to change read-only option' - if get_tk_patchlevel() < (8, 6, 0): # actually this was changed in 8.6b3 + if get_tk_patchlevel() < (8, 6, 0, 'beta', 3): errmsg='Attempt to change read-only option' self.checkInvalidParam(widget, 'orient', 'horizontal', errmsg=errmsg) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Apr 22 10:02:44 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Wed, 22 Apr 2015 08:02:44 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_default_-=3E_default?= =?utf-8?q?=29=3A_Merge_heads?= Message-ID: <20150422080232.30754.83862@psf.io> https://hg.python.org/cpython/rev/fc36120477ae changeset: 95765:fc36120477ae parent: 95764:701b830abbf0 parent: 95758:572dc6bdc0a3 user: Serhiy Storchaka date: Wed Apr 22 11:01:38 2015 +0300 summary: Merge heads files: Doc/library/compileall.rst | 4 ++-- Lib/compileall.py | 4 +--- Lib/test/test_compileall.py | 8 ++++---- Misc/NEWS | 3 +++ 4 files changed, 10 insertions(+), 9 deletions(-) diff --git a/Doc/library/compileall.rst b/Doc/library/compileall.rst --- a/Doc/library/compileall.rst +++ b/Doc/library/compileall.rst @@ -142,8 +142,8 @@ The argument *workers* specifies how many workers are used to compile files in parallel. The default is to not use multiple workers. If the platform can't use multiple workers and *workers* argument is given, - then a :exc:`NotImplementedError` will be raised. - If *workers* is lower than ``0``, a :exc:`ValueError` will be raised. + then sequential compilation will be used as a fallback. If *workers* is + lower than ``0``, a :exc:`ValueError` will be raised. .. versionchanged:: 3.2 Added the *legacy* and *optimize* parameter. diff --git a/Lib/compileall.py b/Lib/compileall.py --- a/Lib/compileall.py +++ b/Lib/compileall.py @@ -69,11 +69,9 @@ files = _walk_dir(dir, quiet=quiet, maxlevels=maxlevels, ddir=ddir) success = 1 - if workers is not None and workers != 1: + if workers is not None and workers != 1 and ProcessPoolExecutor is not None: if workers < 0: raise ValueError('workers must be greater or equal to 0') - if ProcessPoolExecutor is None: - raise NotImplementedError('multiprocessing support not available') workers = workers or None with ProcessPoolExecutor(max_workers=workers) as executor: diff --git a/Lib/test/test_compileall.py b/Lib/test/test_compileall.py --- a/Lib/test/test_compileall.py +++ b/Lib/test/test_compileall.py @@ -136,10 +136,10 @@ self.assertTrue(compile_file_mock.called) @mock.patch('compileall.ProcessPoolExecutor', new=None) - def test_compile_missing_multiprocessing(self): - with self.assertRaisesRegex(NotImplementedError, - "multiprocessing support not available"): - compileall.compile_dir(self.directory, quiet=True, workers=5) + @mock.patch('compileall.compile_file') + def test_compile_missing_multiprocessing(self, compile_file_mock): + compileall.compile_dir(self.directory, quiet=True, workers=5) + self.assertTrue(compile_file_mock.called) class EncodingTest(unittest.TestCase): """Issue 6716: compileall should escape source code when printing errors diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -15,6 +15,9 @@ Library ------- +- Issue #23917: Fall back to sequential compilation when ProcessPoolExecutor + doesn't exist. Patch by Claudiu Popa. + - Issue #23008: Fixed resolving attributes with boolean value is False in pydoc. - Fix asyncio issue 235: LifoQueue and PriorityQueue's put didn't -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Apr 22 10:02:45 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Wed, 22 Apr 2015 08:02:45 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2316840=2E_Turn_off_bignum_support_in_tkinter_wit?= =?utf-8?q?h_with_Tcl_earlier_than?= Message-ID: <20150422080232.98626.87411@psf.io> https://hg.python.org/cpython/rev/701b830abbf0 changeset: 95764:701b830abbf0 parent: 95761:9f13e9385186 parent: 95763:97519d85b5c8 user: Serhiy Storchaka date: Wed Apr 22 10:59:32 2015 +0300 summary: Issue #16840. Turn off bignum support in tkinter with with Tcl earlier than 8.5.8 (tclTomMath.h was broken) and non-final Tcl 8.6. Removed TK_VERSION_HEX. files: Lib/test/test_tcl.py | 4 +++- Modules/_tkinter.c | 7 ++++--- Modules/tkinter.h | 16 ++++++++-------- 3 files changed, 15 insertions(+), 12 deletions(-) diff --git a/Lib/test/test_tcl.py b/Lib/test/test_tcl.py --- a/Lib/test/test_tcl.py +++ b/Lib/test/test_tcl.py @@ -131,7 +131,9 @@ def get_integers(self): integers = (0, 1, -1, 2**31-1, -2**31, 2**31, -2**31-1, 2**63-1, -2**63) - if tcl_version >= (8, 5): # bignum was added in Tcl 8.5 + # bignum was added in Tcl 8.5, but its support is able only since 8.5.8 + if (get_tk_patchlevel() >= (8, 6, 0, 'final') or + (8, 5, 8) <= get_tk_patchlevel() < (8, 6)): integers += (2**63, -2**63-1, 2**1000, -2**1000) return integers diff --git a/Modules/_tkinter.c b/Modules/_tkinter.c --- a/Modules/_tkinter.c +++ b/Modules/_tkinter.c @@ -52,11 +52,12 @@ #include "tkinter.h" -#if TK_VERSION_HEX < 0x08040002 +#if TK_HEX_VERSION < 0x08040200 #error "Tk older than 8.4 not supported" #endif -#if TK_VERSION_HEX >= 0x08050002 +#if TK_HEX_VERSION >= 0x08050208 && TK_HEX_VERSION < 0x08060000 || \ + TK_HEX_VERSION >= 0x08060200 #define HAVE_LIBTOMMAMTH #include #endif @@ -1227,7 +1228,7 @@ Tcl_GetCharLength(value)); } -#if TK_VERSION_HEX >= 0x08050000 +#if TK_HEX_VERSION >= 0x08050000 if (app->BooleanType == NULL && strcmp(value->typePtr->name, "booleanString") == 0) { /* booleanString type is not registered in Tcl */ diff --git a/Modules/tkinter.h b/Modules/tkinter.h --- a/Modules/tkinter.h +++ b/Modules/tkinter.h @@ -4,24 +4,24 @@ /* This header is used to share some macros between _tkinter.c and * tkappinit.c. * Be sure to include tk.h before including this header so - * TK_VERSION_HEX is properly defined. */ + * TK_HEX_VERSION is properly defined. */ /* TK_RELEASE_LEVEL is always one of the following: - * TCL_ALPHA_RELEASE 0 + * TCL_ALPHA_RELEASE 0 * TCL_BETA_RELEASE 1 * TCL_FINAL_RELEASE 2 */ -#define TK_VERSION_HEX ((TK_MAJOR_VERSION << 24) | \ - (TK_MINOR_VERSION << 16) | \ - (TK_RELEASE_SERIAL << 8) | \ - (TK_RELEASE_LEVEL << 0)) +#define TK_HEX_VERSION ((TK_MAJOR_VERSION << 24) | \ + (TK_MINOR_VERSION << 16) | \ + (TK_RELEASE_LEVEL << 8) | \ + (TK_RELEASE_SERIAL << 0)) /* Protect Tk 8.4.13 and older from a deadlock that happens when trying * to load tk after a failed attempt. */ -#if TK_VERSION_HEX < 0x08040e02 +#if TK_HEX_VERSION < 0x0804020e #define TKINTER_PROTECT_LOADTK #define TKINTER_LOADTK_ERRMSG \ - "Calling Tk_Init again after a previous call failed might deadlock" + "Calling Tk_Init again after a previous call failed might deadlock" #endif #endif /* !TKINTER_H */ -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Apr 22 10:02:45 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Wed, 22 Apr 2015 08:02:45 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Fixed_full_Tcl_version_parsing_in_tests_for_pre-final_ve?= =?utf-8?q?rsions=2E?= Message-ID: <20150422080231.22456.95923@psf.io> https://hg.python.org/cpython/rev/9f13e9385186 changeset: 95761:9f13e9385186 parent: 95757:25c03271860d parent: 95760:5bf0d9086cfc user: Serhiy Storchaka date: Wed Apr 22 08:36:41 2015 +0300 summary: Fixed full Tcl version parsing in tests for pre-final versions. files: Lib/test/test_tcl.py | 26 ++++------ Lib/tkinter/test/support.py | 20 ++++---- Lib/tkinter/test/test_ttk/test_widgets.py | 4 +- 3 files changed, 23 insertions(+), 27 deletions(-) diff --git a/Lib/test/test_tcl.py b/Lib/test/test_tcl.py --- a/Lib/test/test_tcl.py +++ b/Lib/test/test_tcl.py @@ -1,4 +1,5 @@ import unittest +import re import sys import os from test import support @@ -17,27 +18,22 @@ except ImportError: INT_MAX = PY_SSIZE_T_MAX = sys.maxsize -tcl_version = _tkinter.TCL_VERSION.split('.') -try: - for i in range(len(tcl_version)): - tcl_version[i] = int(tcl_version[i]) -except ValueError: - pass -tcl_version = tuple(tcl_version) +tcl_version = tuple(map(int, _tkinter.TCL_VERSION.split('.'))) _tk_patchlevel = None def get_tk_patchlevel(): global _tk_patchlevel if _tk_patchlevel is None: tcl = Tcl() - patchlevel = [] - for x in tcl.call('info', 'patchlevel').split('.'): - try: - x = int(x, 10) - except ValueError: - x = -1 - patchlevel.append(x) - _tk_patchlevel = tuple(patchlevel) + patchlevel = tcl.call('info', 'patchlevel') + m = re.fullmatch(r'(\d+)\.(\d+)([ab.])(\d+)', patchlevel) + major, minor, releaselevel, serial = m.groups() + major, minor, serial = int(major), int(minor), int(serial) + releaselevel = {'a': 'alpha', 'b': 'beta', '.': 'final'}[releaselevel] + if releaselevel == 'final': + _tk_patchlevel = major, minor, serial, releaselevel, 0 + else: + _tk_patchlevel = major, minor, 0, releaselevel, serial return _tk_patchlevel diff --git a/Lib/tkinter/test/support.py b/Lib/tkinter/test/support.py --- a/Lib/tkinter/test/support.py +++ b/Lib/tkinter/test/support.py @@ -1,7 +1,6 @@ -import sys +import re import tkinter import unittest -from test.support import requires class AbstractTkTest: @@ -63,14 +62,15 @@ global _tk_patchlevel if _tk_patchlevel is None: tcl = tkinter.Tcl() - patchlevel = [] - for x in tcl.call('info', 'patchlevel').split('.'): - try: - x = int(x, 10) - except ValueError: - x = -1 - patchlevel.append(x) - _tk_patchlevel = tuple(patchlevel) + patchlevel = tcl.call('info', 'patchlevel') + m = re.fullmatch(r'(\d+)\.(\d+)([ab.])(\d+)', patchlevel) + major, minor, releaselevel, serial = m.groups() + major, minor, serial = int(major), int(minor), int(serial) + releaselevel = {'a': 'alpha', 'b': 'beta', '.': 'final'}[releaselevel] + if releaselevel == 'final': + _tk_patchlevel = major, minor, serial, releaselevel, 0 + else: + _tk_patchlevel = major, minor, 0, releaselevel, serial return _tk_patchlevel units = { diff --git a/Lib/tkinter/test/test_ttk/test_widgets.py b/Lib/tkinter/test/test_ttk/test_widgets.py --- a/Lib/tkinter/test/test_ttk/test_widgets.py +++ b/Lib/tkinter/test/test_ttk/test_widgets.py @@ -20,7 +20,7 @@ widget = self.create() self.assertEqual(widget['class'], '') errmsg='attempt to change read-only option' - if get_tk_patchlevel() < (8, 6, 0): # actually this was changed in 8.6b3 + if get_tk_patchlevel() < (8, 6, 0, 'beta', 3): errmsg='Attempt to change read-only option' self.checkInvalidParam(widget, 'class', 'Foo', errmsg=errmsg) widget2 = self.create(class_='Foo') @@ -551,7 +551,7 @@ widget = self.create() self.assertEqual(str(widget['orient']), 'vertical') errmsg='attempt to change read-only option' - if get_tk_patchlevel() < (8, 6, 0): # actually this was changed in 8.6b3 + if get_tk_patchlevel() < (8, 6, 0, 'beta', 3): errmsg='Attempt to change read-only option' self.checkInvalidParam(widget, 'orient', 'horizontal', errmsg=errmsg) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Apr 22 10:31:47 2015 From: python-checkins at python.org (berker.peksag) Date: Wed, 22 Apr 2015 08:31:47 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2321483=3A_Skip_tes?= =?utf-8?q?t=5Ftimestamp=5Foverflow_on_NFS=2E?= Message-ID: <20150422083147.21329.99500@psf.io> https://hg.python.org/cpython/rev/aa60f4d1a569 changeset: 95766:aa60f4d1a569 user: Berker Peksag date: Wed Apr 22 11:32:19 2015 +0300 summary: Issue #21483: Skip test_timestamp_overflow on NFS. Patch by Isaac Schwabacher. files: Lib/test/test_import/__init__.py | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_import/__init__.py b/Lib/test/test_import/__init__.py --- a/Lib/test/test_import/__init__.py +++ b/Lib/test/test_import/__init__.py @@ -291,7 +291,8 @@ except OverflowError: self.skipTest("cannot set modification time to large integer") except OSError as e: - if e.errno != getattr(errno, 'EOVERFLOW', None): + if e.errno not in (getattr(errno, 'EOVERFLOW', None), + getattr(errno, 'EINVAL', None)): raise self.skipTest("cannot set modification time to large integer ({})".format(e)) __import__(TESTFN) -- Repository URL: https://hg.python.org/cpython From solipsis at pitrou.net Wed Apr 22 10:38:52 2015 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Wed, 22 Apr 2015 08:38:52 +0000 Subject: [Python-checkins] Daily reference leaks (25c03271860d): sum=3 Message-ID: <20150422083852.98626.74912@psf.io> results for 25c03271860d on branch "default" -------------------------------------------- test_functools leaked [0, 0, 3] memory blocks, sum=3 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogIq8Rnd', '--timeout', '7200'] From python-checkins at python.org Wed Apr 22 14:49:44 2015 From: python-checkins at python.org (matthias.klose) Date: Wed, 22 Apr 2015 12:49:44 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A__-_move_NEWS_item_to_3=2E5?= Message-ID: <20150422124936.98638.99082@psf.io> https://hg.python.org/cpython/rev/6047f6506af5 changeset: 95767:6047f6506af5 user: doko at ubuntu.com date: Wed Apr 22 14:49:27 2015 +0200 summary: - move NEWS item to 3.5 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 @@ -15,6 +15,9 @@ Library ------- +- Issue #17445: add difflib.diff_bytes() to support comparison of + byte strings (fixes a regression from Python 2). + - Issue #23917: Fall back to sequential compilation when ProcessPoolExecutor doesn't exist. Patch by Claudiu Popa. @@ -202,9 +205,6 @@ - Issue #23310: Fix MagicMock's initializer to work with __methods__, just like configure_mock(). Patch by Kasia Jachim. -- Issue #17445: add difflib.diff_bytes() to support comparison of - byte strings (fixes a regression from Python 2). - Build ----- -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Apr 22 15:16:34 2015 From: python-checkins at python.org (benjamin.peterson) Date: Wed, 22 Apr 2015 13:16:34 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?b?KTogbWVyZ2UgMy40ICgjMjI3ODUp?= Message-ID: <20150422131634.21333.8475@psf.io> https://hg.python.org/cpython/rev/c031fa8e6884 changeset: 95769:c031fa8e6884 parent: 95767:6047f6506af5 parent: 95768:aa6b73823685 user: Benjamin Peterson date: Wed Apr 22 09:16:27 2015 -0400 summary: merge 3.4 (#22785) files: Objects/rangeobject.c | 6 +++++- 1 files changed, 5 insertions(+), 1 deletions(-) diff --git a/Objects/rangeobject.c b/Objects/rangeobject.c --- a/Objects/rangeobject.c +++ b/Objects/rangeobject.c @@ -139,7 +139,11 @@ "range(stop) -> range object\n\ range(start, stop[, step]) -> range object\n\ \n\ -Return a sequence of numbers from start to stop by step."); +Return an object that produces a sequence of integers from start (inclusive)\n\ +to stop (exclusive) by step. range(i, j) produces i, i+1, i+2, ..., j-1.\n\ +start defaults to 0, and stop is omitted! range(4) produces 0, 1, 2, 3.\n\ +These are exactly the valid indices for a list of 4 elements.\n\ +When step is given, it specifies the increment (or decrement)."); static void range_dealloc(rangeobject *r) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Apr 22 15:16:34 2015 From: python-checkins at python.org (benjamin.peterson) Date: Wed, 22 Apr 2015 13:16:34 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E4=29=3A_improved_range?= =?utf-8?q?_docstring_=28closes_=2322785=29?= Message-ID: <20150422131634.31105.35240@psf.io> https://hg.python.org/cpython/rev/aa6b73823685 changeset: 95768:aa6b73823685 branch: 3.4 parent: 95763:97519d85b5c8 user: Benjamin Peterson date: Wed Apr 22 09:16:07 2015 -0400 summary: improved range docstring (closes #22785) Patch by Ned Batchelder. files: Objects/rangeobject.c | 6 +++++- 1 files changed, 5 insertions(+), 1 deletions(-) diff --git a/Objects/rangeobject.c b/Objects/rangeobject.c --- a/Objects/rangeobject.c +++ b/Objects/rangeobject.c @@ -139,7 +139,11 @@ "range(stop) -> range object\n\ range(start, stop[, step]) -> range object\n\ \n\ -Return a sequence of numbers from start to stop by step."); +Return an object that produces a sequence of integers from start (inclusive)\n\ +to stop (exclusive) by step. range(i, j) produces i, i+1, i+2, ..., j-1.\n\ +start defaults to 0, and stop is omitted! range(4) produces 0, 1, 2, 3.\n\ +These are exactly the valid indices for a list of 4 elements.\n\ +When step is given, it specifies the increment (or decrement)."); static void range_dealloc(rangeobject *r) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Apr 22 22:16:18 2015 From: python-checkins at python.org (christian.heimes) Date: Wed, 22 Apr 2015 20:16:18 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Fix_=2Egitignore_for_=27python=27_binary=2E?= Message-ID: <20150422201618.27916.99608@psf.io> https://hg.python.org/cpython/rev/6da0afdefd8a changeset: 95771:6da0afdefd8a parent: 95769:c031fa8e6884 parent: 95770:efcccb70a84c user: Christian Heimes date: Wed Apr 22 22:16:01 2015 +0200 summary: Fix .gitignore for 'python' binary. files: .gitignore | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/.gitignore b/.gitignore --- a/.gitignore +++ b/.gitignore @@ -67,7 +67,7 @@ platform pybuilddir.txt pyconfig.h -python$ +python python-config python-config.py python.bat -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Apr 22 22:16:18 2015 From: python-checkins at python.org (christian.heimes) Date: Wed, 22 Apr 2015 20:16:18 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogRml4IC5naXRpZ25v?= =?utf-8?q?re_for_=27python=27_binary=2E?= Message-ID: <20150422201618.6587.48375@psf.io> https://hg.python.org/cpython/rev/efcccb70a84c changeset: 95770:efcccb70a84c branch: 3.4 parent: 95768:aa6b73823685 user: Christian Heimes date: Wed Apr 22 22:15:44 2015 +0200 summary: Fix .gitignore for 'python' binary. files: .gitignore | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/.gitignore b/.gitignore --- a/.gitignore +++ b/.gitignore @@ -58,7 +58,7 @@ platform pybuilddir.txt pyconfig.h -python$ +python python-config python-config.py python.exe -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Apr 22 23:09:51 2015 From: python-checkins at python.org (guido.van.rossum) Date: Wed, 22 Apr 2015 21:09:51 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_Separate_-=3E_surround=2E?= Message-ID: <20150422210945.18913.42217@psf.io> https://hg.python.org/peps/rev/6c208fbae66c changeset: 5784:6c208fbae66c user: Guido van Rossum date: Wed Apr 22 14:09:41 2015 -0700 summary: Separate -> surround. files: pep-0008.txt | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pep-0008.txt b/pep-0008.txt --- a/pep-0008.txt +++ b/pep-0008.txt @@ -266,10 +266,10 @@ Blank Lines ----------- -Separate top-level function and class definitions with two blank +Surround top-level function and class definitions with two blank lines. -Method definitions inside a class are separated by a single blank +Method definitions inside a class are surrounded by a single blank line. Extra blank lines may be used (sparingly) to separate groups of -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Wed Apr 22 23:36:29 2015 From: python-checkins at python.org (facundo.batista) Date: Wed, 22 Apr 2015 21:36:29 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2323887=3A_urllib?= =?utf-8?q?=2Eerror=2EHTTPError_now_has_a_proper_repr=28=29_representation?= =?utf-8?q?=2E?= Message-ID: <20150422213629.21351.20650@psf.io> https://hg.python.org/cpython/rev/e9ea679a92fa changeset: 95772:e9ea679a92fa user: Facundo Batista date: Wed Apr 22 18:35:54 2015 -0300 summary: Issue #23887: urllib.error.HTTPError now has a proper repr() representation. files: Lib/test/test_urllib2.py | 145 ++++++++++++++++++-------- Lib/urllib/error.py | 7 +- Misc/NEWS | 3 + 3 files changed, 111 insertions(+), 44 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 @@ -23,6 +23,7 @@ # CacheFTPHandler (hard to write) # parse_keqv_list, parse_http_list, HTTPDigestAuthHandler + class TrivialTests(unittest.TestCase): def test___all__(self): @@ -73,6 +74,7 @@ err = urllib.error.URLError('reason') self.assertIn(err.reason, str(err)) + class RequestHdrsTests(unittest.TestCase): def test_request_headers_dict(self): @@ -132,7 +134,6 @@ req.remove_header("Unredirected-spam") self.assertFalse(req.has_header("Unredirected-spam")) - def test_password_manager(self): mgr = urllib.request.HTTPPasswordMgr() add = mgr.add_password @@ -236,43 +237,60 @@ class MockOpener: addheaders = [] + def open(self, req, data=None, timeout=socket._GLOBAL_DEFAULT_TIMEOUT): self.req, self.data, self.timeout = req, data, timeout + def error(self, proto, *args): self.proto, self.args = proto, args + class MockFile: - def read(self, count=None): pass - def readline(self, count=None): pass - def close(self): pass + def read(self, count=None): + pass + + def readline(self, count=None): + pass + + def close(self): + pass + class MockHeaders(dict): def getheaders(self, name): return list(self.values()) + class MockResponse(io.StringIO): def __init__(self, code, msg, headers, data, url=None): io.StringIO.__init__(self, data) self.code, self.msg, self.headers, self.url = code, msg, headers, url + def info(self): return self.headers + def geturl(self): return self.url + class MockCookieJar: def add_cookie_header(self, request): self.ach_req = request + def extract_cookies(self, response, request): self.ec_req, self.ec_r = request, response + class FakeMethod: def __init__(self, meth_name, action, handle): self.meth_name = meth_name self.handle = handle self.action = action + def __call__(self, *args): return self.handle(self.meth_name, self.action, *args) + class MockHTTPResponse(io.IOBase): def __init__(self, fp, msg, status, reason): self.fp = fp @@ -326,24 +344,31 @@ self.data = body if self.raise_on_endheaders: raise OSError() + def getresponse(self): return MockHTTPResponse(MockFile(), {}, 200, "OK") def close(self): pass + class MockHandler: # useful for testing handler machinery # see add_ordered_mock_handlers() docstring handler_order = 500 + def __init__(self, methods): self._define_methods(methods) + def _define_methods(self, methods): for spec in methods: - if len(spec) == 2: name, action = spec - else: name, action = spec, None + if len(spec) == 2: + name, action = spec + else: + name, action = spec, None meth = FakeMethod(name, action, self.handle) setattr(self.__class__, name, meth) + def handle(self, fn_name, action, *args, **kwds): self.parent.calls.append((self, fn_name, args, kwds)) if action is None: @@ -366,16 +391,21 @@ elif action == "raise": raise urllib.error.URLError("blah") assert False - def close(self): pass + + def close(self): + pass + def add_parent(self, parent): self.parent = parent self.parent.calls = [] + def __lt__(self, other): if not hasattr(other, "handler_order"): # No handler_order, leave in original order. Yuck. return True return self.handler_order < other.handler_order + def add_ordered_mock_handlers(opener, meth_spec): """Create MockHandlers and add them to an OpenerDirector. @@ -398,7 +428,9 @@ handlers = [] count = 0 for meths in meth_spec: - class MockHandlerSubclass(MockHandler): pass + class MockHandlerSubclass(MockHandler): + pass + h = MockHandlerSubclass(meths) h.handler_order += count h.add_parent(opener) @@ -407,12 +439,14 @@ opener.add_handler(h) return handlers + def build_test_opener(*handler_instances): opener = OpenerDirector() for h in handler_instances: opener.add_handler(h) return opener + class MockHTTPHandler(urllib.request.BaseHandler): # useful for testing redirections and auth # sends supplied headers and code as first response @@ -421,9 +455,11 @@ self.code = code self.headers = headers self.reset() + def reset(self): self._count = 0 self.requests = [] + def http_open(self, req): import email, http.client, copy self.requests.append(copy.deepcopy(req)) @@ -438,6 +474,7 @@ msg = email.message_from_string("\r\n\r\n") return MockResponse(200, "OK", msg, "", req.get_full_url()) + class MockHTTPSHandler(urllib.request.AbstractHTTPHandler): # Useful for testing the Proxy-Authorization request by verifying the # properties of httpcon @@ -468,12 +505,14 @@ return MockResponse(self.code, name, MockFile(), "", req.get_full_url()) + class MockPasswordManager: def add_password(self, realm, uri, user, password): self.realm = realm self.url = uri self.user = user self.password = password + def find_user_password(self, realm, authuri): self.target_realm = realm self.target_url = authuri @@ -538,11 +577,11 @@ def test_handler_order(self): o = OpenerDirector() handlers = [] - for meths, handler_order in [ - ([("http_open", "return self")], 500), - (["http_open"], 0), - ]: - class MockHandlerSubclass(MockHandler): pass + for meths, handler_order in [([("http_open", "return self")], 500), + (["http_open"], 0)]: + class MockHandlerSubclass(MockHandler): + pass + h = MockHandlerSubclass(meths) h.handler_order = handler_order handlers.append(h) @@ -580,7 +619,8 @@ handlers = add_ordered_mock_handlers(o, meth_spec) class Unknown: - def __eq__(self, other): return True + def __eq__(self, other): + return True req = Request("http://example.com/") o.open(req) @@ -593,7 +633,6 @@ self.assertEqual((handler, method_name), got[:2]) self.assertEqual(args, got[2]) - def test_processors(self): # *_request / *_response methods get called appropriately o = OpenerDirector() @@ -629,6 +668,7 @@ if args[1] is not None: self.assertIsInstance(args[1], MockResponse) + def sanepathname2url(path): try: path.encode("utf-8") @@ -640,18 +680,25 @@ # XXX don't ask me about the mac... return urlpath + class HandlerTests(unittest.TestCase): def test_ftp(self): class MockFTPWrapper: - def __init__(self, data): self.data = data + def __init__(self, data): + self.data = data + def retrfile(self, filename, filetype): self.filename, self.filetype = filename, filetype return io.StringIO(self.data), len(self.data) - def close(self): pass + + def close(self): + pass class NullFTPHandler(urllib.request.FTPHandler): - def __init__(self, data): self.data = data + def __init__(self, data): + self.data = data + def connect_ftp(self, user, passwd, host, port, dirs, timeout=socket._GLOBAL_DEFAULT_TIMEOUT): self.user, self.passwd = user, passwd @@ -889,7 +936,7 @@ self.assertRaises(ValueError, h.do_request_, req) else: newreq = h.do_request_(req) - self.assertEqual(int(newreq.get_header('Content-length')),30) + self.assertEqual(int(newreq.get_header('Content-length')), 30) file_obj.close() @@ -922,12 +969,12 @@ # Check whether host is determined correctly if there is no proxy np_ds_req = h.do_request_(ds_req) - self.assertEqual(np_ds_req.unredirected_hdrs["Host"],"example.com") + self.assertEqual(np_ds_req.unredirected_hdrs["Host"], "example.com") # Check whether host is determined correctly if there is a proxy - ds_req.set_proxy("someproxy:3128",None) + ds_req.set_proxy("someproxy:3128", None) p_ds_req = h.do_request_(ds_req) - self.assertEqual(p_ds_req.unredirected_hdrs["Host"],"example.com") + self.assertEqual(p_ds_req.unredirected_hdrs["Host"], "example.com") def test_full_url_setter(self): # Checks to ensure that components are set correctly after setting the @@ -969,15 +1016,14 @@ weird_url = 'http://www.python.org?getspam' req = Request(weird_url) newreq = h.do_request_(req) - self.assertEqual(newreq.host,'www.python.org') - self.assertEqual(newreq.selector,'/?getspam') + self.assertEqual(newreq.host, 'www.python.org') + self.assertEqual(newreq.selector, '/?getspam') url_without_path = 'http://www.python.org' req = Request(url_without_path) newreq = h.do_request_(req) - self.assertEqual(newreq.host,'www.python.org') - self.assertEqual(newreq.selector,'') - + self.assertEqual(newreq.host, 'www.python.org') + self.assertEqual(newreq.selector, '') def test_errors(self): h = urllib.request.HTTPErrorProcessor() @@ -1064,6 +1110,7 @@ # loop detection req = Request(from_url) req.timeout = socket._GLOBAL_DEFAULT_TIMEOUT + def redirect(h, req, url=to_url): h.http_error_302(req, MockFile(), 302, "Blah", MockHeaders({"location": url})) @@ -1094,7 +1141,6 @@ self.assertEqual(count, urllib.request.HTTPRedirectHandler.max_redirections) - def test_invalid_redirect(self): from_url = "http://example.com/a.html" valid_schemes = ['http','https','ftp'] @@ -1197,7 +1243,6 @@ self.assertEqual(req.host, "www.python.org") del os.environ['no_proxy'] - def test_proxy_https(self): o = OpenerDirector() ph = urllib.request.ProxyHandler(dict(https="proxy.example.com:3128")) @@ -1221,21 +1266,21 @@ https_handler = MockHTTPSHandler() o.add_handler(https_handler) req = Request("https://www.example.com/") - req.add_header("Proxy-Authorization","FooBar") - req.add_header("User-Agent","Grail") + req.add_header("Proxy-Authorization", "FooBar") + req.add_header("User-Agent", "Grail") self.assertEqual(req.host, "www.example.com") self.assertIsNone(req._tunnel_host) o.open(req) # Verify Proxy-Authorization gets tunneled to request. # httpsconn req_headers do not have the Proxy-Authorization header but # the req will have. - self.assertNotIn(("Proxy-Authorization","FooBar"), + self.assertNotIn(("Proxy-Authorization", "FooBar"), https_handler.httpconn.req_headers) - self.assertIn(("User-Agent","Grail"), + self.assertIn(("User-Agent", "Grail"), https_handler.httpconn.req_headers) self.assertIsNotNone(req._tunnel_host) self.assertEqual(req.host, "proxy.example.com:3128") - self.assertEqual(req.get_header("Proxy-authorization"),"FooBar") + self.assertEqual(req.get_header("Proxy-authorization"), "FooBar") # TODO: This should be only for OSX @unittest.skipUnless(sys.platform == 'darwin', "only relevant for OSX") @@ -1267,7 +1312,7 @@ realm = "ACME Widget Store" http_handler = MockHTTPHandler( 401, 'WWW-Authenticate: Basic realm=%s%s%s\r\n\r\n' % - (quote_char, realm, quote_char) ) + (quote_char, realm, quote_char)) opener.add_handler(auth_handler) opener.add_handler(http_handler) self._test_basic_auth(opener, auth_handler, "Authorization", @@ -1325,13 +1370,16 @@ def __init__(self): OpenerDirector.__init__(self) self.recorded = [] + def record(self, info): self.recorded.append(info) + class TestDigestAuthHandler(urllib.request.HTTPDigestAuthHandler): def http_error_401(self, *args, **kwds): self.parent.record("digest") urllib.request.HTTPDigestAuthHandler.http_error_401(self, *args, **kwds) + class TestBasicAuthHandler(urllib.request.HTTPBasicAuthHandler): def http_error_401(self, *args, **kwds): self.parent.record("basic") @@ -1367,7 +1415,7 @@ 401, 'WWW-Authenticate: Kerberos\r\n\r\n') opener.add_handler(digest_auth_handler) opener.add_handler(http_handler) - self.assertRaises(ValueError,opener.open,"http://www.example.com") + self.assertRaises(ValueError, opener.open, "http://www.example.com") def test_unsupported_auth_basic_handler(self): # While using BasicAuthHandler @@ -1377,7 +1425,7 @@ 401, 'WWW-Authenticate: NTLM\r\n\r\n') opener.add_handler(basic_auth_handler) opener.add_handler(http_handler) - self.assertRaises(ValueError,opener.open,"http://www.example.com") + self.assertRaises(ValueError, opener.open, "http://www.example.com") def _test_basic_auth(self, opener, auth_handler, auth_header, realm, http_handler, password_manager, @@ -1510,6 +1558,7 @@ self.assertTrue(conn.fakesock.closed, "Connection not closed") + class MiscTests(unittest.TestCase): def opener_has_handler(self, opener, handler_class): @@ -1517,11 +1566,16 @@ for h in opener.handlers)) def test_build_opener(self): - class MyHTTPHandler(urllib.request.HTTPHandler): pass + class MyHTTPHandler(urllib.request.HTTPHandler): + pass + class FooHandler(urllib.request.BaseHandler): - def foo_open(self): pass + def foo_open(self): + pass + class BarHandler(urllib.request.BaseHandler): - def bar_open(self): pass + def bar_open(self): + pass build_opener = urllib.request.build_opener @@ -1548,7 +1602,9 @@ self.opener_has_handler(o, urllib.request.HTTPHandler) # Issue2670: multiple handlers sharing the same base class - class MyOtherHTTPHandler(urllib.request.HTTPHandler): pass + class MyOtherHTTPHandler(urllib.request.HTTPHandler): + pass + o = build_opener(MyHTTPHandler, MyOtherHTTPHandler) self.opener_has_handler(o, MyHTTPHandler) self.opener_has_handler(o, MyOtherHTTPHandler) @@ -1584,6 +1640,8 @@ self.assertEqual(err.headers, 'Content-Length: 42') expected_errmsg = 'HTTP Error %s: %s' % (err.code, err.msg) self.assertEqual(str(err), expected_errmsg) + expected_errmsg = '' % (err.code, err.msg) + self.assertEqual(repr(err), expected_errmsg) def test_parse_proxy(self): parse_proxy_test_cases = [ @@ -1622,9 +1680,10 @@ self.assertRaises(ValueError, _parse_proxy, 'file:/ftp.example.com'), + class RequestTests(unittest.TestCase): class PutRequest(Request): - method='PUT' + method = 'PUT' def setUp(self): self.get = Request("http://www.python.org/~jeremy/") @@ -1713,7 +1772,7 @@ def test_url_fullurl_get_full_url(self): urls = ['http://docs.python.org', 'http://docs.python.org/library/urllib2.html#OK', - 'http://www.python.org/?qs=query#fragment=true' ] + 'http://www.python.org/?qs=query#fragment=true'] for url in urls: req = Request(url) self.assertEqual(req.get_full_url(), req.full_url) diff --git a/Lib/urllib/error.py b/Lib/urllib/error.py --- a/Lib/urllib/error.py +++ b/Lib/urllib/error.py @@ -35,6 +35,7 @@ def __str__(self): return '' % self.reason + class HTTPError(URLError, urllib.response.addinfourl): """Raised when HTTP error occurs, but also acts like non-error return""" __super_init = urllib.response.addinfourl.__init__ @@ -55,6 +56,9 @@ def __str__(self): return 'HTTP Error %s: %s' % (self.code, self.msg) + def __repr__(self): + return '' % (self.code, self.msg) + # since URLError specifies a .reason attribute, HTTPError should also # provide this attribute. See issue13211 for discussion. @property @@ -69,8 +73,9 @@ def headers(self, headers): self.hdrs = headers -# exception raised when downloaded size does not match content-length + class ContentTooShortError(URLError): + """Exception raised when downloaded size does not match content-length.""" def __init__(self, message, content): URLError.__init__(self, message) self.content = content diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -33,6 +33,9 @@ - Issue #23728: binascii.crc_hqx() could return an integer outside of the range 0-0xffff for empty data. +- Issue #23887: urllib.error.HTTPError now has a proper repr() representation. + Patch by Berker Peksag. + What's New in Python 3.5.0 alpha 4? =================================== -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Apr 22 23:55:38 2015 From: python-checkins at python.org (christian.heimes) Date: Wed, 22 Apr 2015 21:55:38 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Next_attempt=3A_fix_=2Egitignore_for_Unix_and_OSX=2E_Sor?= =?utf-8?q?ry_RDM!?= Message-ID: <20150422215537.31101.33970@psf.io> https://hg.python.org/cpython/rev/2e93da3d9f1e changeset: 95774:2e93da3d9f1e parent: 95772:e9ea679a92fa parent: 95773:09d5bbf0f01d user: Christian Heimes date: Wed Apr 22 23:55:29 2015 +0200 summary: Next attempt: fix .gitignore for Unix and OSX. Sorry RDM! files: .gitignore | 5 ++++- 1 files changed, 4 insertions(+), 1 deletions(-) diff --git a/.gitignore b/.gitignore --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,7 @@ +# Two-trick pony for OSX and other case insensitive file systems: +# Ignore ./python binary on Unix but still look into ./Python/ directory. +/python +!/Python/** *.cover *.o *.orig @@ -67,7 +71,6 @@ platform pybuilddir.txt pyconfig.h -python python-config python-config.py python.bat -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Apr 22 23:55:38 2015 From: python-checkins at python.org (christian.heimes) Date: Wed, 22 Apr 2015 21:55:38 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E4=29=3A_Next_attempt?= =?utf-8?q?=3A_fix_=2Egitignore_for_Unix_and_OSX=2E_Sorry_RDM!?= Message-ID: <20150422215537.98644.87743@psf.io> https://hg.python.org/cpython/rev/09d5bbf0f01d changeset: 95773:09d5bbf0f01d branch: 3.4 parent: 95770:efcccb70a84c user: Christian Heimes date: Wed Apr 22 23:54:44 2015 +0200 summary: Next attempt: fix .gitignore for Unix and OSX. Sorry RDM! files: .gitignore | 5 ++++- 1 files changed, 4 insertions(+), 1 deletions(-) diff --git a/.gitignore b/.gitignore --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,7 @@ +# Two-trick pony for OSX and other case insensitive file systems: +# Ignore ./python binary on Unix but still look into ./Python/ directory. +/python +!/Python/** *.cover *.o *.orig @@ -58,7 +62,6 @@ platform pybuilddir.txt pyconfig.h -python python-config python-config.py python.exe -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Apr 23 00:38:34 2015 From: python-checkins at python.org (barry.warsaw) Date: Wed, 22 Apr 2015 22:38:34 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzI0MDI5?= =?utf-8?q?=3A_Document_the_name_binding_behavior_for_submodule_imports=2E?= Message-ID: <20150422223834.27912.81077@psf.io> https://hg.python.org/cpython/rev/3968e7a9614c changeset: 95775:3968e7a9614c branch: 3.4 parent: 95770:efcccb70a84c user: Barry Warsaw date: Wed Apr 22 18:29:16 2015 -0400 summary: Issue #24029: Document the name binding behavior for submodule imports. files: Doc/reference/import.rst | 35 ++++++++++++++++++++++++++++ Misc/NEWS | 5 ++++ 2 files changed, 40 insertions(+), 0 deletions(-) diff --git a/Doc/reference/import.rst b/Doc/reference/import.rst --- a/Doc/reference/import.rst +++ b/Doc/reference/import.rst @@ -461,6 +461,41 @@ into :data:`sys.modules`, but it must remove **only** the failing module, and only if the loader itself has loaded it explicitly. +Submodules +---------- + +When a submodule is loaded using any mechanism (e.g. ``importlib`` APIs, the +``import`` or ``import-from`` statements, or built-in ``__import__()``) a +binding is placed in the parent module's namespace to the submodule object. +For example, if package ``spam`` has a submodule ``foo``, after importing +``spam.foo``, ``spam`` will have an attribute ``foo`` which is bound to the +submodule. Let's say you have the following directory structure:: + + spam/ + __init__.py + foo.py + bar.py + +and ``spam/__init__.py`` has the following lines in it:: + + from .foo import Foo + from .bar import Bar + +then executing the following puts a name binding to ``foo`` and ``bar`` in the +``spam`` module:: + + >>> import spam + >>> spam.foo + + >>> spam.bar + + +Given Python's familiar name binding rules this might seem surprising, but +it's actually a fundamental feature of the import system. The invariant +holding is that if you have ``sys.modules['spam']`` and +``sys.modules['spam.foo']`` (as you would after the above import), the latter +must appear as the ``foo`` attribute of the former. + Module spec ----------- diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -220,6 +220,11 @@ - Issue #23998: PyImport_ReInitLock() now checks for lock allocation error +Documentation +------------- + +- Issue #24029: Document the name binding behavior for submodule imports. + What's New in Python 3.4.3? =========================== -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Apr 23 00:38:35 2015 From: python-checkins at python.org (barry.warsaw) Date: Wed, 22 Apr 2015 22:38:35 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2324029=3A_Document_the_name_binding_behavior_for?= =?utf-8?q?_submodule_imports=2E?= Message-ID: <20150422223834.81998.98081@psf.io> https://hg.python.org/cpython/rev/6295f207dfaa changeset: 95777:6295f207dfaa parent: 95774:2e93da3d9f1e parent: 95776:351ad8c4f3a6 user: Barry Warsaw date: Wed Apr 22 18:38:26 2015 -0400 summary: Issue #24029: Document the name binding behavior for submodule imports. files: Doc/reference/import.rst | 35 ++++++++++++++++++++++++++++ Misc/NEWS | 5 ++++ 2 files changed, 40 insertions(+), 0 deletions(-) diff --git a/Doc/reference/import.rst b/Doc/reference/import.rst --- a/Doc/reference/import.rst +++ b/Doc/reference/import.rst @@ -468,6 +468,41 @@ ``create_module()`` is not. Starting in Python 3.6 it will be an error to not define ``create_module()`` on a loader attached to a ModuleSpec. +Submodules +---------- + +When a submodule is loaded using any mechanism (e.g. ``importlib`` APIs, the +``import`` or ``import-from`` statements, or built-in ``__import__()``) a +binding is placed in the parent module's namespace to the submodule object. +For example, if package ``spam`` has a submodule ``foo``, after importing +``spam.foo``, ``spam`` will have an attribute ``foo`` which is bound to the +submodule. Let's say you have the following directory structure:: + + spam/ + __init__.py + foo.py + bar.py + +and ``spam/__init__.py`` has the following lines in it:: + + from .foo import Foo + from .bar import Bar + +then executing the following puts a name binding to ``foo`` and ``bar`` in the +``spam`` module:: + + >>> import spam + >>> spam.foo + + >>> spam.bar + + +Given Python's familiar name binding rules this might seem surprising, but +it's actually a fundamental feature of the import system. The invariant +holding is that if you have ``sys.modules['spam']`` and +``sys.modules['spam.foo']`` (as you would after the above import), the latter +must appear as the ``foo`` attribute of the former. + Module spec ----------- diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -36,6 +36,11 @@ - Issue #23887: urllib.error.HTTPError now has a proper repr() representation. Patch by Berker Peksag. +Documentation +------------- + +- Issue #24029: Document the name binding behavior for submodule imports. + What's New in Python 3.5.0 alpha 4? =================================== -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Apr 23 00:38:35 2015 From: python-checkins at python.org (barry.warsaw) Date: Wed, 22 Apr 2015 22:38:35 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy40IC0+IDMuNCk6?= =?utf-8?q?_Issue_=2324029=3A_Document_the_name_binding_behavior_for_submo?= =?utf-8?q?dule_imports=2E?= Message-ID: <20150422223834.22460.16055@psf.io> https://hg.python.org/cpython/rev/351ad8c4f3a6 changeset: 95776:351ad8c4f3a6 branch: 3.4 parent: 95773:09d5bbf0f01d parent: 95775:3968e7a9614c user: Barry Warsaw date: Wed Apr 22 18:36:44 2015 -0400 summary: Issue #24029: Document the name binding behavior for submodule imports. files: Doc/reference/import.rst | 35 ++++++++++++++++++++++++++++ Misc/NEWS | 5 ++++ 2 files changed, 40 insertions(+), 0 deletions(-) diff --git a/Doc/reference/import.rst b/Doc/reference/import.rst --- a/Doc/reference/import.rst +++ b/Doc/reference/import.rst @@ -461,6 +461,41 @@ into :data:`sys.modules`, but it must remove **only** the failing module, and only if the loader itself has loaded it explicitly. +Submodules +---------- + +When a submodule is loaded using any mechanism (e.g. ``importlib`` APIs, the +``import`` or ``import-from`` statements, or built-in ``__import__()``) a +binding is placed in the parent module's namespace to the submodule object. +For example, if package ``spam`` has a submodule ``foo``, after importing +``spam.foo``, ``spam`` will have an attribute ``foo`` which is bound to the +submodule. Let's say you have the following directory structure:: + + spam/ + __init__.py + foo.py + bar.py + +and ``spam/__init__.py`` has the following lines in it:: + + from .foo import Foo + from .bar import Bar + +then executing the following puts a name binding to ``foo`` and ``bar`` in the +``spam`` module:: + + >>> import spam + >>> spam.foo + + >>> spam.bar + + +Given Python's familiar name binding rules this might seem surprising, but +it's actually a fundamental feature of the import system. The invariant +holding is that if you have ``sys.modules['spam']`` and +``sys.modules['spam.foo']`` (as you would after the above import), the latter +must appear as the ``foo`` attribute of the former. + Module spec ----------- diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -220,6 +220,11 @@ - Issue #23998: PyImport_ReInitLock() now checks for lock allocation error +Documentation +------------- + +- Issue #24029: Document the name binding behavior for submodule imports. + What's New in Python 3.4.3? =========================== -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Apr 23 09:59:18 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Thu, 23 Apr 2015 07:59:18 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_Use_more_preci?= =?utf-8?q?se_Tcl_version_checks_in_tests=2E?= Message-ID: <20150423075918.30345.53333@psf.io> https://hg.python.org/cpython/rev/9e47ed690e75 changeset: 95778:9e47ed690e75 branch: 2.7 parent: 95762:4bf210f59ac6 user: Serhiy Storchaka date: Thu Apr 23 10:57:15 2015 +0300 summary: Use more precise Tcl version checks in tests. files: Lib/lib-tk/test/test_tkinter/test_widgets.py | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/lib-tk/test/test_tkinter/test_widgets.py b/Lib/lib-tk/test/test_tkinter/test_widgets.py --- a/Lib/lib-tk/test/test_tkinter/test_widgets.py +++ b/Lib/lib-tk/test/test_tkinter/test_widgets.py @@ -1037,7 +1037,7 @@ def test_paneconfigure_height(self): p, b, c = self.create2() self.check_paneconfigure(p, b, 'height', 10, 10, - stringify=tcl_version < (8, 5)) + stringify=get_tk_patchlevel() < (8, 5, 11)) self.check_paneconfigure_bad(p, b, 'height', 'bad screen distance "badValue"') @@ -1085,7 +1085,7 @@ def test_paneconfigure_width(self): p, b, c = self.create2() self.check_paneconfigure(p, b, 'width', 10, 10, - stringify=tcl_version < (8, 5)) + stringify=get_tk_patchlevel() < (8, 5, 11)) self.check_paneconfigure_bad(p, b, 'width', 'bad screen distance "badValue"') -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Apr 23 09:59:18 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Thu, 23 Apr 2015 07:59:18 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E4=29=3A_Use_more_preci?= =?utf-8?q?se_Tcl_version_checks_in_tests=2E?= Message-ID: <20150423075918.21331.37749@psf.io> https://hg.python.org/cpython/rev/2d7e9a0418f2 changeset: 95779:2d7e9a0418f2 branch: 3.4 parent: 95776:351ad8c4f3a6 user: Serhiy Storchaka date: Thu Apr 23 10:57:40 2015 +0300 summary: Use more precise Tcl version checks in tests. files: Lib/tkinter/test/test_tkinter/test_widgets.py | 4 ++-- Lib/tkinter/test/test_ttk/test_widgets.py | 6 ++++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/Lib/tkinter/test/test_tkinter/test_widgets.py b/Lib/tkinter/test/test_tkinter/test_widgets.py --- a/Lib/tkinter/test/test_tkinter/test_widgets.py +++ b/Lib/tkinter/test/test_tkinter/test_widgets.py @@ -1040,7 +1040,7 @@ def test_paneconfigure_height(self): p, b, c = self.create2() self.check_paneconfigure(p, b, 'height', 10, 10, - stringify=tcl_version < (8, 5)) + stringify=get_tk_patchlevel() < (8, 5, 11)) self.check_paneconfigure_bad(p, b, 'height', 'bad screen distance "badValue"') @@ -1088,7 +1088,7 @@ def test_paneconfigure_width(self): p, b, c = self.create2() self.check_paneconfigure(p, b, 'width', 10, 10, - stringify=tcl_version < (8, 5)) + stringify=get_tk_patchlevel() < (8, 5, 11)) self.check_paneconfigure_bad(p, b, 'width', 'bad screen distance "badValue"') diff --git a/Lib/tkinter/test/test_ttk/test_widgets.py b/Lib/tkinter/test/test_ttk/test_widgets.py --- a/Lib/tkinter/test/test_ttk/test_widgets.py +++ b/Lib/tkinter/test/test_ttk/test_widgets.py @@ -352,7 +352,8 @@ expected=('mon', 'tue', 'wed', 'thur')) self.checkParam(self.combo, 'values', ('mon', 'tue', 'wed', 'thur')) self.checkParam(self.combo, 'values', (42, 3.14, '', 'any string')) - self.checkParam(self.combo, 'values', '', expected=()) + self.checkParam(self.combo, 'values', '', + expected='' if get_tk_patchlevel() < (8, 5, 10) else ()) self.combo['values'] = ['a', 1, 'c'] @@ -1125,7 +1126,8 @@ self.checkParam(widget, 'columns', 'a b c', expected=('a', 'b', 'c')) self.checkParam(widget, 'columns', ('a', 'b', 'c')) - self.checkParam(widget, 'columns', ()) + self.checkParam(widget, 'columns', (), + expected='' if get_tk_patchlevel() < (8, 5, 10) else ()) def test_displaycolumns(self): widget = self.create() -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Apr 23 09:59:18 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Thu, 23 Apr 2015 07:59:18 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Use_more_precise_Tcl_version_checks_in_tests=2E?= Message-ID: <20150423075918.27922.47434@psf.io> https://hg.python.org/cpython/rev/2cc5650169fb changeset: 95780:2cc5650169fb parent: 95777:6295f207dfaa parent: 95779:2d7e9a0418f2 user: Serhiy Storchaka date: Thu Apr 23 10:58:15 2015 +0300 summary: Use more precise Tcl version checks in tests. files: Lib/tkinter/test/test_tkinter/test_widgets.py | 4 ++-- Lib/tkinter/test/test_ttk/test_widgets.py | 6 ++++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/Lib/tkinter/test/test_tkinter/test_widgets.py b/Lib/tkinter/test/test_tkinter/test_widgets.py --- a/Lib/tkinter/test/test_tkinter/test_widgets.py +++ b/Lib/tkinter/test/test_tkinter/test_widgets.py @@ -1041,7 +1041,7 @@ def test_paneconfigure_height(self): p, b, c = self.create2() self.check_paneconfigure(p, b, 'height', 10, 10, - stringify=tcl_version < (8, 5)) + stringify=get_tk_patchlevel() < (8, 5, 11)) self.check_paneconfigure_bad(p, b, 'height', 'bad screen distance "badValue"') @@ -1089,7 +1089,7 @@ def test_paneconfigure_width(self): p, b, c = self.create2() self.check_paneconfigure(p, b, 'width', 10, 10, - stringify=tcl_version < (8, 5)) + stringify=get_tk_patchlevel() < (8, 5, 11)) self.check_paneconfigure_bad(p, b, 'width', 'bad screen distance "badValue"') diff --git a/Lib/tkinter/test/test_ttk/test_widgets.py b/Lib/tkinter/test/test_ttk/test_widgets.py --- a/Lib/tkinter/test/test_ttk/test_widgets.py +++ b/Lib/tkinter/test/test_ttk/test_widgets.py @@ -352,7 +352,8 @@ expected=('mon', 'tue', 'wed', 'thur')) self.checkParam(self.combo, 'values', ('mon', 'tue', 'wed', 'thur')) self.checkParam(self.combo, 'values', (42, 3.14, '', 'any string')) - self.checkParam(self.combo, 'values', '', expected=()) + self.checkParam(self.combo, 'values', '', + expected='' if get_tk_patchlevel() < (8, 5, 10) else ()) self.combo['values'] = ['a', 1, 'c'] @@ -1125,7 +1126,8 @@ self.checkParam(widget, 'columns', 'a b c', expected=('a', 'b', 'c')) self.checkParam(widget, 'columns', ('a', 'b', 'c')) - self.checkParam(widget, 'columns', ()) + self.checkParam(widget, 'columns', (), + expected='' if get_tk_patchlevel() < (8, 5, 10) else ()) def test_displaycolumns(self): widget = self.create() -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Apr 23 10:37:20 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Thu, 23 Apr 2015 08:37:20 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2323713=3A_Fixed_fragility_of_test=5Fimap=5Funord?= =?utf-8?q?ered=5Fhandle=5Fiterable=5Fexception=2E?= Message-ID: <20150423083720.21347.55909@psf.io> https://hg.python.org/cpython/rev/f60f65507d8e changeset: 95783:f60f65507d8e parent: 95780:2cc5650169fb parent: 95782:0eb5968c15ad user: Serhiy Storchaka date: Thu Apr 23 11:36:40 2015 +0300 summary: Issue #23713: Fixed fragility of test_imap_unordered_handle_iterable_exception. Patch by Davin Potts. files: Lib/test/_test_multiprocessing.py | 10 ++++++++-- 1 files changed, 8 insertions(+), 2 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 @@ -1799,17 +1799,23 @@ it = self.pool.imap_unordered(sqr, exception_throwing_generator(10, 3), 1) + expected_values = list(map(sqr, list(range(10)))) with self.assertRaises(SayWhenError): # imap_unordered makes it difficult to anticipate the SayWhenError for i in range(10): - self.assertEqual(next(it), i*i) + value = next(it) + self.assertIn(value, expected_values) + expected_values.remove(value) it = self.pool.imap_unordered(sqr, exception_throwing_generator(20, 7), 2) + expected_values = list(map(sqr, list(range(20)))) with self.assertRaises(SayWhenError): for i in range(20): - self.assertEqual(next(it), i*i) + value = next(it) + self.assertIn(value, expected_values) + expected_values.remove(value) def test_make_pool(self): self.assertRaises(ValueError, multiprocessing.Pool, -1) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Apr 23 10:37:22 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Thu, 23 Apr 2015 08:37:22 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzIzNzEz?= =?utf-8?q?=3A_Fixed_fragility_of_test=5Fimap=5Funordered=5Fhandle=5Fitera?= =?utf-8?q?ble=5Fexception=2E?= Message-ID: <20150423083719.22470.38239@psf.io> https://hg.python.org/cpython/rev/0ac30526c208 changeset: 95781:0ac30526c208 branch: 2.7 parent: 95778:9e47ed690e75 user: Serhiy Storchaka date: Thu Apr 23 11:35:43 2015 +0300 summary: Issue #23713: Fixed fragility of test_imap_unordered_handle_iterable_exception. Patch by Davin Potts. files: Lib/test/test_multiprocessing.py | 10 ++++++++-- 1 files changed, 8 insertions(+), 2 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 @@ -1219,17 +1219,23 @@ it = self.pool.imap_unordered(sqr, exception_throwing_generator(10, 3), 1) + expected_values = map(sqr, range(10)) with self.assertRaises(SayWhenError): # imap_unordered makes it difficult to anticipate the SayWhenError for i in range(10): - self.assertEqual(next(it), i*i) + value = next(it) + self.assertIn(value, expected_values) + expected_values.remove(value) it = self.pool.imap_unordered(sqr, exception_throwing_generator(20, 7), 2) + expected_values = map(sqr, range(20)) with self.assertRaises(SayWhenError): for i in range(20): - self.assertEqual(next(it), i*i) + value = next(it) + self.assertIn(value, expected_values) + expected_values.remove(value) def test_make_pool(self): self.assertRaises(ValueError, multiprocessing.Pool, -1) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Apr 23 10:37:22 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Thu, 23 Apr 2015 08:37:22 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzIzNzEz?= =?utf-8?q?=3A_Fixed_fragility_of_test=5Fimap=5Funordered=5Fhandle=5Fitera?= =?utf-8?q?ble=5Fexception=2E?= Message-ID: <20150423083719.18887.45346@psf.io> https://hg.python.org/cpython/rev/0eb5968c15ad changeset: 95782:0eb5968c15ad branch: 3.4 parent: 95779:2d7e9a0418f2 user: Serhiy Storchaka date: Thu Apr 23 11:35:59 2015 +0300 summary: Issue #23713: Fixed fragility of test_imap_unordered_handle_iterable_exception. Patch by Davin Potts. files: Lib/test/_test_multiprocessing.py | 10 ++++++++-- 1 files changed, 8 insertions(+), 2 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 @@ -1799,17 +1799,23 @@ it = self.pool.imap_unordered(sqr, exception_throwing_generator(10, 3), 1) + expected_values = list(map(sqr, list(range(10)))) with self.assertRaises(SayWhenError): # imap_unordered makes it difficult to anticipate the SayWhenError for i in range(10): - self.assertEqual(next(it), i*i) + value = next(it) + self.assertIn(value, expected_values) + expected_values.remove(value) it = self.pool.imap_unordered(sqr, exception_throwing_generator(20, 7), 2) + expected_values = list(map(sqr, list(range(20)))) with self.assertRaises(SayWhenError): for i in range(20): - self.assertEqual(next(it), i*i) + value = next(it) + self.assertIn(value, expected_values) + expected_values.remove(value) def test_make_pool(self): self.assertRaises(ValueError, multiprocessing.Pool, -1) -- Repository URL: https://hg.python.org/cpython From solipsis at pitrou.net Thu Apr 23 10:40:22 2015 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Thu, 23 Apr 2015 08:40:22 +0000 Subject: [Python-checkins] Daily reference leaks (6295f207dfaa): sum=3 Message-ID: <20150423084022.27930.32959@psf.io> results for 6295f207dfaa on branch "default" -------------------------------------------- test_collections leaked [2, -2, 0] references, sum=0 test_functools leaked [0, 0, 3] memory blocks, sum=3 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogvHIJi6', '--timeout', '7200'] From python-checkins at python.org Thu Apr 23 11:26:06 2015 From: python-checkins at python.org (christian.heimes) Date: Thu, 23 Apr 2015 09:26:06 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzI0MDMx?= =?utf-8?q?=3A_make_patchcheck_now_supports_git_checkouts=2C_too=2E?= Message-ID: <20150423092606.6599.95152@psf.io> https://hg.python.org/cpython/rev/0f9c43fb189d changeset: 95784:0f9c43fb189d branch: 3.4 parent: 95782:0eb5968c15ad user: Christian Heimes date: Thu Apr 23 11:24:14 2015 +0200 summary: Issue #24031: make patchcheck now supports git checkouts, too. files: Misc/NEWS | 4 ++ Tools/scripts/patchcheck.py | 34 ++++++++++++++++++------ 2 files changed, 29 insertions(+), 9 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -225,6 +225,10 @@ - Issue #24029: Document the name binding behavior for submodule imports. +Tools/Demos +----------- + +- Issue #24031: make patchcheck now supports git checkouts, too. What's New in Python 3.4.3? =========================== diff --git a/Tools/scripts/patchcheck.py b/Tools/scripts/patchcheck.py --- a/Tools/scripts/patchcheck.py +++ b/Tools/scripts/patchcheck.py @@ -49,15 +49,31 @@ @status("Getting the list of files that have been added/changed", info=lambda x: n_files_str(len(x))) def changed_files(): - """Get the list of changed or added files from Mercurial.""" - if not os.path.isdir(os.path.join(SRCDIR, '.hg')): - sys.exit('need a checkout to get modified files') - - cmd = 'hg status --added --modified --no-status' - if mq_patches_applied(): - cmd += ' --rev qparent' - with subprocess.Popen(cmd.split(), stdout=subprocess.PIPE) as st: - return [x.decode().rstrip() for x in st.stdout] + """Get the list of changed or added files from Mercurial or git.""" + if os.path.isdir(os.path.join(SRCDIR, '.hg')): + cmd = 'hg status --added --modified --no-status' + if mq_patches_applied(): + cmd += ' --rev qparent' + with subprocess.Popen(cmd.split(), stdout=subprocess.PIPE) as st: + return [x.decode().rstrip() for x in st.stdout] + elif os.path.isdir(os.path.join(SRCDIR, '.git')): + cmd = 'git status --porcelain' + filenames = [] + with subprocess.Popen(cmd.split(), stdout=subprocess.PIPE) as st: + for line in st.stdout: + line = line.decode().rstrip() + status = set(line[:2]) + # modified, added or unmerged files + if not status.intersection('MAU'): + continue + filename = line[3:] + if ' -> ' in filename: + # file is renamed + filename = filename.split(' -> ', 2)[1].strip() + filenames.append(filename) + return filenames + else: + sys.exit('need a Mercurial or git checkout to get modified files') def report_modified_files(file_paths): -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Apr 23 11:26:06 2015 From: python-checkins at python.org (christian.heimes) Date: Thu, 23 Apr 2015 09:26:06 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2324031=3A_make_patchcheck_now_supports_git_check?= =?utf-8?q?outs=2C_too=2E?= Message-ID: <20150423092606.27908.49152@psf.io> https://hg.python.org/cpython/rev/d1b706e57fbe changeset: 95785:d1b706e57fbe parent: 95783:f60f65507d8e parent: 95784:0f9c43fb189d user: Christian Heimes date: Thu Apr 23 11:25:41 2015 +0200 summary: Issue #24031: make patchcheck now supports git checkouts, too. files: Misc/NEWS | 4 ++ Tools/scripts/patchcheck.py | 34 ++++++++++++++++++------ 2 files changed, 29 insertions(+), 9 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -41,6 +41,10 @@ - Issue #24029: Document the name binding behavior for submodule imports. +Tools/Demos +----------- + +- Issue #24031: make patchcheck now supports git checkouts, too. What's New in Python 3.5.0 alpha 4? =================================== diff --git a/Tools/scripts/patchcheck.py b/Tools/scripts/patchcheck.py --- a/Tools/scripts/patchcheck.py +++ b/Tools/scripts/patchcheck.py @@ -49,15 +49,31 @@ @status("Getting the list of files that have been added/changed", info=lambda x: n_files_str(len(x))) def changed_files(): - """Get the list of changed or added files from Mercurial.""" - if not os.path.isdir(os.path.join(SRCDIR, '.hg')): - sys.exit('need a checkout to get modified files') - - cmd = 'hg status --added --modified --no-status' - if mq_patches_applied(): - cmd += ' --rev qparent' - with subprocess.Popen(cmd.split(), stdout=subprocess.PIPE) as st: - return [x.decode().rstrip() for x in st.stdout] + """Get the list of changed or added files from Mercurial or git.""" + if os.path.isdir(os.path.join(SRCDIR, '.hg')): + cmd = 'hg status --added --modified --no-status' + if mq_patches_applied(): + cmd += ' --rev qparent' + with subprocess.Popen(cmd.split(), stdout=subprocess.PIPE) as st: + return [x.decode().rstrip() for x in st.stdout] + elif os.path.isdir(os.path.join(SRCDIR, '.git')): + cmd = 'git status --porcelain' + filenames = [] + with subprocess.Popen(cmd.split(), stdout=subprocess.PIPE) as st: + for line in st.stdout: + line = line.decode().rstrip() + status = set(line[:2]) + # modified, added or unmerged files + if not status.intersection('MAU'): + continue + filename = line[3:] + if ' -> ' in filename: + # file is renamed + filename = filename.split(' -> ', 2)[1].strip() + filenames.append(filename) + return filenames + else: + sys.exit('need a Mercurial or git checkout to get modified files') def report_modified_files(file_paths): -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Apr 23 18:52:08 2015 From: python-checkins at python.org (yury.selivanov) Date: Thu, 23 Apr 2015 16:52:08 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_pep-0492=3A_Update_PEP_3152_s?= =?utf-8?q?ection?= Message-ID: <20150423165208.31113.7955@psf.io> https://hg.python.org/peps/rev/352d4f907266 changeset: 5785:352d4f907266 parent: 5783:e4e94b8fcf45 user: Yury Selivanov date: Thu Apr 23 12:51:13 2015 -0400 summary: pep-0492: Update PEP 3152 section files: pep-0492.txt | 18 +++++++++++++++++- 1 files changed, 17 insertions(+), 1 deletions(-) diff --git a/pep-0492.txt b/pep-0492.txt --- a/pep-0492.txt +++ b/pep-0492.txt @@ -748,7 +748,23 @@ and having ``__call__`` and no ``__cocall__`` for coroutine- generators. -6. There are no equivalents of ``async for`` and ``async with`` in PEP +6. Requiring parentheses grammatically also introduces a whole lot + of new problems. + + Code like the following:: + + await fut + await function_returning_future() + await asyncio.gather(coro1(arg1, arg2), coro2(arg1, arg2)) + + would look like:: + + cocall fut() # or cocall costart(fut) + cocall (function_returning_future())() + cocall asyncio.gather(costart(coro1, arg1, arg2), + costart(coro2, arg1, arg2)) + +7. There are no equivalents of ``async for`` and ``async with`` in PEP 3152. -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Thu Apr 23 18:52:08 2015 From: python-checkins at python.org (yury.selivanov) Date: Thu, 23 Apr 2015 16:52:08 +0000 Subject: [Python-checkins] =?utf-8?q?peps_=28merge_default_-=3E_default=29?= =?utf-8?q?=3A_null_merge?= Message-ID: <20150423165208.30752.83878@psf.io> https://hg.python.org/peps/rev/364270ff01e2 changeset: 5786:364270ff01e2 parent: 5785:352d4f907266 parent: 5784:6c208fbae66c user: Yury Selivanov date: Thu Apr 23 12:52:06 2015 -0400 summary: null merge files: pep-0008.txt | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pep-0008.txt b/pep-0008.txt --- a/pep-0008.txt +++ b/pep-0008.txt @@ -266,10 +266,10 @@ Blank Lines ----------- -Separate top-level function and class definitions with two blank +Surround top-level function and class definitions with two blank lines. -Method definitions inside a class are separated by a single blank +Method definitions inside a class are surrounded by a single blank line. Extra blank lines may be used (sparingly) to separate groups of -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Thu Apr 23 20:20:47 2015 From: python-checkins at python.org (yury.selivanov) Date: Thu, 23 Apr 2015 18:20:47 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_pep-0492=3A_Explain_why_=22as?= =?utf-8?q?ync_def=22_and_not_=22def_async=22=2E?= Message-ID: <20150423182044.98648.57369@psf.io> https://hg.python.org/peps/rev/8cb4c0ab0931 changeset: 5787:8cb4c0ab0931 user: Yury Selivanov date: Thu Apr 23 14:20:41 2015 -0400 summary: pep-0492: Explain why "async def" and not "def async". files: pep-0492.txt | 16 ++++++++++++++++ 1 files changed, 16 insertions(+), 0 deletions(-) diff --git a/pep-0492.txt b/pep-0492.txt --- a/pep-0492.txt +++ b/pep-0492.txt @@ -884,6 +884,22 @@ with the existing grammar. +Why "async def" and not "def async" +----------------------------------- + +``async`` keyword is a *statement qualifier*. A good analogy to it are +"static", "public", "unsafe" keywords from other languages. "async +for" is an asynchronous "for" statement, "async with" is an +asynchronous "with" statement, "async def" is an asynchronous function. + +Having "async" after the main statement keyword might introduce some +confusion, like "for async item in iterator" can be read as "for each +asynchronous item in iterator". + +Also, "async def" better separates coroutines from regular functions +visually. + + Why not a __future__ import --------------------------- -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Thu Apr 23 20:23:42 2015 From: python-checkins at python.org (yury.selivanov) Date: Thu, 23 Apr 2015 18:23:42 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_pep-0492=3A_Why_=22async_def?= =?utf-8?q?=22_--_add_a_note_about_grammar=2E?= Message-ID: <20150423182341.30756.76798@psf.io> https://hg.python.org/peps/rev/ec319bf4c86e changeset: 5788:ec319bf4c86e user: Yury Selivanov date: Thu Apr 23 14:23:36 2015 -0400 summary: pep-0492: Why "async def" -- add a note about grammar. files: pep-0492.txt | 5 +++-- 1 files changed, 3 insertions(+), 2 deletions(-) diff --git a/pep-0492.txt b/pep-0492.txt --- a/pep-0492.txt +++ b/pep-0492.txt @@ -896,8 +896,9 @@ confusion, like "for async item in iterator" can be read as "for each asynchronous item in iterator". -Also, "async def" better separates coroutines from regular functions -visually. +Having ``async`` keyword before ``def``, ``with`` and ``for`` also +makes the language grammar simpler. And "async def" better separates +coroutines from regular functions visually. Why not a __future__ import -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Thu Apr 23 20:42:29 2015 From: python-checkins at python.org (yury.selivanov) Date: Thu, 23 Apr 2015 18:42:29 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_pep-0492=3A_Add_that_it=27s_a?= =?utf-8?q?_TypeError_if_=5F=5Fawait=5F=5F_returns_non-iterator?= Message-ID: <20150423184226.30760.40856@psf.io> https://hg.python.org/peps/rev/a0b8dc058d06 changeset: 5789:a0b8dc058d06 user: Yury Selivanov date: Thu Apr 23 14:42:24 2015 -0400 summary: pep-0492: Add that it's a TypeError if __await__ returns non-iterator files: pep-0492.txt | 3 +++ 1 files changed, 3 insertions(+), 0 deletions(-) diff --git a/pep-0492.txt b/pep-0492.txt --- a/pep-0492.txt +++ b/pep-0492.txt @@ -152,6 +152,9 @@ and would be like using ``__iter__`` instead of ``__call__`` for regular callables. + It is a ``TypeError`` if ``__await__`` returns anything but an + iterator. + It is a ``SyntaxError`` to use ``await`` outside of a coroutine. -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Thu Apr 23 21:53:29 2015 From: python-checkins at python.org (yury.selivanov) Date: Thu, 23 Apr 2015 19:53:29 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_pep-0492=3A_=27Why_not_reuse_?= =?utf-8?b?ZXhpc3RpbmcgImZvciIgYW5kICJ3aXRoIi4uLicgc2VjdGlvbg==?= Message-ID: <20150423195328.98638.51381@psf.io> https://hg.python.org/peps/rev/6284d8e240c5 changeset: 5790:6284d8e240c5 user: Yury Selivanov date: Thu Apr 23 15:53:20 2015 -0400 summary: pep-0492: 'Why not reuse existing "for" and "with"...' section files: pep-0492.txt | 14 ++++++++++++-- 1 files changed, 12 insertions(+), 2 deletions(-) diff --git a/pep-0492.txt b/pep-0492.txt --- a/pep-0492.txt +++ b/pep-0492.txt @@ -754,13 +754,13 @@ 6. Requiring parentheses grammatically also introduces a whole lot of new problems. - Code like the following:: + The following code:: await fut await function_returning_future() await asyncio.gather(coro1(arg1, arg2), coro2(arg1, arg2)) - would look like:: + would look like:: cocall fut() # or cocall costart(fut) cocall (function_returning_future())() @@ -951,6 +951,16 @@ simple and foolproof as possible. +Why not reuse existing "for" and "with" statements +-------------------------------------------------- + +The vision behind existing generator-based coroutines and this proposal +is to make it easy for users to see where the code might be suspended. +Making existing "for" and "with" statements to recognize asynchronous +iterators and context managers will inevitable create invisible +implicit suspend points, making it harder to reason about the code. + + Comprehensions -------------- -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Thu Apr 23 21:54:23 2015 From: python-checkins at python.org (yury.selivanov) Date: Thu, 23 Apr 2015 19:54:23 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_pep-0492=3A_Fix_a_typo?= Message-ID: <20150423195423.31101.95108@psf.io> https://hg.python.org/peps/rev/5a2cce14fc58 changeset: 5791:5a2cce14fc58 user: Yury Selivanov date: Thu Apr 23 15:54:21 2015 -0400 summary: pep-0492: Fix a typo files: pep-0492.txt | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/pep-0492.txt b/pep-0492.txt --- a/pep-0492.txt +++ b/pep-0492.txt @@ -957,7 +957,7 @@ The vision behind existing generator-based coroutines and this proposal is to make it easy for users to see where the code might be suspended. Making existing "for" and "with" statements to recognize asynchronous -iterators and context managers will inevitable create invisible +iterators and context managers will inevitably create invisible implicit suspend points, making it harder to reason about the code. -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Thu Apr 23 21:55:48 2015 From: python-checkins at python.org (yury.selivanov) Date: Thu, 23 Apr 2015 19:55:48 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_pep-0492=3A_Fix_wording?= Message-ID: <20150423195548.27926.1059@psf.io> https://hg.python.org/peps/rev/725a6bf06978 changeset: 5792:725a6bf06978 user: Yury Selivanov date: Thu Apr 23 15:55:46 2015 -0400 summary: pep-0492: Fix wording files: pep-0492.txt | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pep-0492.txt b/pep-0492.txt --- a/pep-0492.txt +++ b/pep-0492.txt @@ -957,8 +957,8 @@ The vision behind existing generator-based coroutines and this proposal is to make it easy for users to see where the code might be suspended. Making existing "for" and "with" statements to recognize asynchronous -iterators and context managers will inevitably create invisible -implicit suspend points, making it harder to reason about the code. +iterators and context managers will inevitably create implicit suspend +points, making it harder to reason about the code. Comprehensions -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Thu Apr 23 22:00:16 2015 From: python-checkins at python.org (yury.selivanov) Date: Thu, 23 Apr 2015 20:00:16 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_pep-0492=3A_Glossary=3A_Futur?= =?utf-8?q?e-like=2E=5F=5Fawait=5F=5F_must_return_an_iterator?= Message-ID: <20150423200015.6591.5479@psf.io> https://hg.python.org/peps/rev/bdb807d4d4bc changeset: 5793:bdb807d4d4bc user: Yury Selivanov date: Thu Apr 23 15:59:16 2015 -0400 summary: pep-0492: Glossary: Future-like.__await__ must return an iterator files: pep-0492.txt | 10 +++++----- 1 files changed, 5 insertions(+), 5 deletions(-) diff --git a/pep-0492.txt b/pep-0492.txt --- a/pep-0492.txt +++ b/pep-0492.txt @@ -497,11 +497,11 @@ details. :Future-like object: - An object with an ``__await__`` method. Can be consumed by an - ``await`` expression in a coroutine. A coroutine waiting for a - Future-like object is suspended until the Future-like object's - ``__await__`` completes, and returns the result. See `Await - Expression`_ for details. + An object with an ``__await__`` method returning an iterator. Can + be consumed by an ``await`` expression in a coroutine. A coroutine + waiting for a Future-like object is suspended until the Future-like + object's ``__await__`` completes, and returns the result. See + `Await Expression`_ for details. :Awaitable: A *Future-like* object or a *coroutine object*. See `Await -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Thu Apr 23 22:22:59 2015 From: python-checkins at python.org (yury.selivanov) Date: Thu, 23 Apr 2015 20:22:59 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_pep-0492=3A_Edits_in_PEP_3152?= =?utf-8?q?_section?= Message-ID: <20150423202259.82026.54035@psf.io> https://hg.python.org/peps/rev/48270715bd25 changeset: 5794:48270715bd25 user: Yury Selivanov date: Thu Apr 23 16:22:57 2015 -0400 summary: pep-0492: Edits in PEP 3152 section files: pep-0492.txt | 9 ++++----- 1 files changed, 4 insertions(+), 5 deletions(-) diff --git a/pep-0492.txt b/pep-0492.txt --- a/pep-0492.txt +++ b/pep-0492.txt @@ -731,11 +731,10 @@ 3. To make asyncio work with PEP 3152 it would be required to modify ``@asyncio.coroutine`` decorator to wrap all functions in an object - with a ``__cocall__`` method. To call *cofunctions* from existing - generator-based coroutines it would be required to use ``costart`` - built-in. In this proposal ``@asyncio.coroutine`` simply sets - ``CO_COROUTINE`` on the wrapped function's code object and - everything works automatically. + with a ``__cocall__`` method, or to implement ``__cocall__`` on + generators. To call *cofunctions* from existing generator-based + coroutines it would be required to use ``costart(cofunc, *args, + **kwargs)`` built-in. 4. Since it is impossible to call a *cofunction* without a ``cocall`` keyword, it automatically prevents the common mistake of forgetting -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Thu Apr 23 22:25:33 2015 From: python-checkins at python.org (yury.selivanov) Date: Thu, 23 Apr 2015 20:25:33 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_pep-0492=3A_Fix_example_in_De?= =?utf-8?q?bugging_Features_section?= Message-ID: <20150423202532.18893.67390@psf.io> https://hg.python.org/peps/rev/73836bbcba5f changeset: 5795:73836bbcba5f user: Yury Selivanov date: Thu Apr 23 16:25:30 2015 -0400 summary: pep-0492: Fix example in Debugging Features section files: pep-0492.txt | 8 ++++---- 1 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pep-0492.txt b/pep-0492.txt --- a/pep-0492.txt +++ b/pep-0492.txt @@ -466,18 +466,18 @@ await asyncio.sleep(1) def async_debug_wrap(generator): - return asyncio.AsyncDebugWrapper(generator) + return asyncio.CoroWrapper(generator) sys.set_coroutine_wrapper(async_debug_wrap) debug_me() # <- this line will likely GC the coroutine object and - # trigger AsyncDebugWrapper's code. + # trigger asyncio.CoroWrapper's code. - assert isinstance(debug_me(), AsyncDebugWrapper) + assert isinstance(debug_me(), asyncio.CoroWrapper) sys.set_coroutine_wrapper(None) # <- this unsets any # previously set wrapper - assert not isinstance(debug_me(), AsyncDebugWrapper) + assert not isinstance(debug_me(), asyncio.CoroWrapper) If ``sys.set_coroutine_wrapper()`` is called twice, the new wrapper replaces the previous wrapper. ``sys.set_coroutine_wrapper(None)`` -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Thu Apr 23 22:27:44 2015 From: python-checkins at python.org (yury.selivanov) Date: Thu, 23 Apr 2015 20:27:44 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_pep-0492=3A_Slightly_imrpove_?= =?utf-8?q?example_2_of_=22async_for=22_section?= Message-ID: <20150423202744.82012.44756@psf.io> https://hg.python.org/peps/rev/2c85e3e7f906 changeset: 5796:2c85e3e7f906 user: Yury Selivanov date: Thu Apr 23 16:27:42 2015 -0400 summary: pep-0492: Slightly imrpove example 2 of "async for" section files: pep-0492.txt | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pep-0492.txt b/pep-0492.txt --- a/pep-0492.txt +++ b/pep-0492.txt @@ -383,8 +383,8 @@ raise StopAsyncIteration return value - async for item in AsyncIteratorWrapper("abc"): - print(item) + async for letter in AsyncIteratorWrapper("abc"): + print(letter) Why StopAsyncIteration? -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Thu Apr 23 22:45:03 2015 From: python-checkins at python.org (yury.selivanov) Date: Thu, 23 Apr 2015 20:45:03 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_pep-0492=3A_It=27s_a_TypeErro?= =?utf-8?q?r_to_pass_non-awaitable_to_=27await=27?= Message-ID: <20150423204501.22466.93975@psf.io> https://hg.python.org/peps/rev/f4c7a7617880 changeset: 5797:f4c7a7617880 user: Yury Selivanov date: Thu Apr 23 16:44:59 2015 -0400 summary: pep-0492: It's a TypeError to pass non-awaitable to 'await' files: pep-0492.txt | 3 +++ 1 files changed, 3 insertions(+), 0 deletions(-) diff --git a/pep-0492.txt b/pep-0492.txt --- a/pep-0492.txt +++ b/pep-0492.txt @@ -157,6 +157,9 @@ It is a ``SyntaxError`` to use ``await`` outside of a coroutine. +It is a ``TypeError`` to pass anything other than an *awaitable* object +to an ``await`` expression. + Asynchronous Context Managers and "async with" ---------------------------------------------- -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Thu Apr 23 22:48:08 2015 From: python-checkins at python.org (yury.selivanov) Date: Thu, 23 Apr 2015 20:48:08 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_pep-0492=3A_TypeError_if_an_o?= =?utf-8?q?bject_without_=5F=5Faiter=5F=5F_is_passed_to_async_for?= Message-ID: <20150423204808.31117.68229@psf.io> https://hg.python.org/peps/rev/c927aa2716b8 changeset: 5798:c927aa2716b8 user: Yury Selivanov date: Thu Apr 23 16:48:07 2015 -0400 summary: pep-0492: TypeError if an object without __aiter__ is passed to async for files: pep-0492.txt | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pep-0492.txt b/pep-0492.txt --- a/pep-0492.txt +++ b/pep-0492.txt @@ -306,9 +306,9 @@ BLOCK2 -It is an error to pass a regular iterable without ``__aiter__`` method -to ``async for``. It is a ``SyntaxError`` to use ``async for`` outside -of a coroutine. +It is a ``TypeError`` to pass a regular iterable without ``__aiter__`` +method to ``async for``. It is a ``SyntaxError`` to use ``async for`` +outside of a coroutine. As for with regular ``for`` statement, ``async for`` has an optional ``else`` clause. -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Thu Apr 23 23:08:06 2015 From: python-checkins at python.org (benjamin.peterson) Date: Thu, 23 Apr 2015 21:08:06 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?b?KTogbWVyZ2UgMy40ICgjMjQwNDQp?= Message-ID: <20150423210806.6603.17562@psf.io> https://hg.python.org/cpython/rev/bd656916586f changeset: 95789:bd656916586f parent: 95785:d1b706e57fbe parent: 95788:80485b8e43cd user: Benjamin Peterson date: Thu Apr 23 17:06:45 2015 -0400 summary: merge 3.4 (#24044) files: Misc/NEWS | 3 +++ Objects/listobject.c | 6 ++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -78,6 +78,9 @@ - Issue #23466: %c, %o, %x, and %X in bytes formatting now raise TypeError on non-integer input. +- Issue #24044: Fix possible null pointer dereference in list.sort in out of + memory conditions. + Library ------- diff --git a/Objects/listobject.c b/Objects/listobject.c --- a/Objects/listobject.c +++ b/Objects/listobject.c @@ -1961,8 +1961,10 @@ keys = &ms.temparray[saved_ob_size+1]; else { keys = PyMem_MALLOC(sizeof(PyObject *) * saved_ob_size); - if (keys == NULL) - return NULL; + if (keys == NULL) { + PyErr_NoMemory(); + goto keyfunc_fail; + } } for (i = 0; i < saved_ob_size ; i++) { -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Apr 23 23:08:06 2015 From: python-checkins at python.org (benjamin.peterson) Date: Thu, 23 Apr 2015 21:08:06 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E2=29=3A_properly_handl?= =?utf-8?q?e_malloc_failure_=28closes_=2324044=29?= Message-ID: <20150423210806.30754.64647@psf.io> https://hg.python.org/cpython/rev/91096d27c802 changeset: 95786:91096d27c802 branch: 3.2 parent: 94677:29316b605ae4 user: Benjamin Peterson date: Thu Apr 23 17:04:36 2015 -0400 summary: properly handle malloc failure (closes #24044) Patch by Christian Heimes. files: Misc/NEWS | 3 +++ Objects/listobject.c | 6 ++++-- 2 files changed, 7 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 #24044: Fix possible null pointer dereference in list.sort in out of + memory conditions. + - Issue #23055: Fixed a buffer overflow in PyUnicode_FromFormatV. Analysis and fix by Guido Vranken. diff --git a/Objects/listobject.c b/Objects/listobject.c --- a/Objects/listobject.c +++ b/Objects/listobject.c @@ -1924,8 +1924,10 @@ keys = &ms.temparray[saved_ob_size+1]; else { keys = PyMem_MALLOC(sizeof(PyObject *) * saved_ob_size); - if (keys == NULL) - return NULL; + if (keys == NULL) { + PyErr_NoMemory(); + goto keyfunc_fail; + } } for (i = 0; i < saved_ob_size ; i++) { -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Apr 23 23:08:06 2015 From: python-checkins at python.org (benjamin.peterson) Date: Thu, 23 Apr 2015 21:08:06 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy4zIC0+IDMuNCk6?= =?utf-8?q?_merge_3=2E3_=28=2324044=29?= Message-ID: <20150423210806.22466.32578@psf.io> https://hg.python.org/cpython/rev/80485b8e43cd changeset: 95788:80485b8e43cd branch: 3.4 parent: 95784:0f9c43fb189d parent: 95787:0d8f15053f42 user: Benjamin Peterson date: Thu Apr 23 17:06:33 2015 -0400 summary: merge 3.3 (#24044) files: Misc/NEWS | 3 +++ Objects/listobject.c | 6 ++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -28,6 +28,9 @@ - Issue #23629: Fix the default __sizeof__ implementation for variable-sized objects. +- Issue #24044: Fix possible null pointer dereference in list.sort in out of + memory conditions. + Library ------- diff --git a/Objects/listobject.c b/Objects/listobject.c --- a/Objects/listobject.c +++ b/Objects/listobject.c @@ -1961,8 +1961,10 @@ keys = &ms.temparray[saved_ob_size+1]; else { keys = PyMem_MALLOC(sizeof(PyObject *) * saved_ob_size); - if (keys == NULL) - return NULL; + if (keys == NULL) { + PyErr_NoMemory(); + goto keyfunc_fail; + } } for (i = 0; i < saved_ob_size ; i++) { -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Apr 23 23:08:06 2015 From: python-checkins at python.org (benjamin.peterson) Date: Thu, 23 Apr 2015 21:08:06 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy4yIC0+IDMuMyk6?= =?utf-8?q?_merge_3=2E2_=28=2324044=29?= Message-ID: <20150423210806.18901.17294@psf.io> https://hg.python.org/cpython/rev/0d8f15053f42 changeset: 95787:0d8f15053f42 branch: 3.3 parent: 95717:7d7bf5c34d7e parent: 95786:91096d27c802 user: Benjamin Peterson date: Thu Apr 23 17:05:07 2015 -0400 summary: merge 3.2 (#24044) files: Misc/NEWS | 3 +++ Objects/listobject.c | 6 ++++-- 2 files changed, 7 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 #24044: Fix possible null pointer dereference in list.sort in out of + memory conditions. + - Issue #23055: Fixed a buffer overflow in PyUnicode_FromFormatV. Analysis and fix by Guido Vranken. diff --git a/Objects/listobject.c b/Objects/listobject.c --- a/Objects/listobject.c +++ b/Objects/listobject.c @@ -1953,8 +1953,10 @@ keys = &ms.temparray[saved_ob_size+1]; else { keys = PyMem_MALLOC(sizeof(PyObject *) * saved_ob_size); - if (keys == NULL) - return NULL; + if (keys == NULL) { + PyErr_NoMemory(); + goto keyfunc_fail; + } } for (i = 0; i < saved_ob_size ; i++) { -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Apr 23 23:41:17 2015 From: python-checkins at python.org (serhiy.storchaka) Date: Thu, 23 Apr 2015 21:41:17 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2324007=3A_Argument?= =?utf-8?q?_Clinic_now_writes_the_format_of_PyArg=5FParse*=28=29_at_the?= Message-ID: <20150423214116.6605.61530@psf.io> https://hg.python.org/cpython/rev/151cab576cab changeset: 95790:151cab576cab user: Serhiy Storchaka date: Fri Apr 24 00:40:51 2015 +0300 summary: Issue #24007: Argument Clinic now writes the format of PyArg_Parse*() at the same line as function name. files: Modules/_io/clinic/_iomodule.c.h | 5 +- Modules/_io/clinic/bufferedio.c.h | 50 +- Modules/_io/clinic/bytesio.c.h | 12 +- Modules/_io/clinic/fileio.c.h | 19 +- Modules/_io/clinic/iobase.c.h | 11 +- Modules/_io/clinic/stringio.c.h | 8 +- Modules/_io/clinic/textio.c.h | 24 +- Modules/cjkcodecs/clinic/multibytecodec.c.h | 14 +- Modules/clinic/_bz2module.c.h | 12 +- Modules/clinic/_codecsmodule.c.h | 6 +- Modules/clinic/_cryptmodule.c.h | 5 +- Modules/clinic/_datetimemodule.c.h | 5 +- Modules/clinic/_dbmmodule.c.h | 11 +- Modules/clinic/_gdbmmodule.c.h | 9 +- Modules/clinic/_lzmamodule.c.h | 23 +- Modules/clinic/_opcode.c.h | 5 +- Modules/clinic/_pickle.c.h | 20 +- Modules/clinic/arraymodule.c.h | 26 +- Modules/clinic/audioop.c.h | 80 +- Modules/clinic/binascii.c.h | 62 +- Modules/clinic/cmathmodule.c.h | 88 +- Modules/clinic/fcntlmodule.c.h | 14 +- Modules/clinic/grpmodule.c.h | 8 +- Modules/clinic/md5module.c.h | 5 +- Modules/clinic/posixmodule.c.h | 406 +++------ Modules/clinic/pwdmodule.c.h | 6 +- Modules/clinic/pyexpat.c.h | 26 +- Modules/clinic/sha1module.c.h | 5 +- Modules/clinic/sha256module.c.h | 8 +- Modules/clinic/sha512module.c.h | 8 +- Modules/clinic/spwdmodule.c.h | 6 +- Modules/clinic/unicodedata.c.h | 45 +- Modules/clinic/zlibmodule.c.h | 33 +- Objects/clinic/bytearrayobject.c.h | 41 +- Objects/clinic/bytesobject.c.h | 32 +- Objects/clinic/unicodeobject.c.h | 5 +- Python/clinic/bltinmodule.c.h | 12 +- Python/clinic/import.c.h | 32 +- Tools/clinic/clinic.py | 13 +- 39 files changed, 377 insertions(+), 823 deletions(-) diff --git a/Modules/_io/clinic/_iomodule.c.h b/Modules/_io/clinic/_iomodule.c.h --- a/Modules/_io/clinic/_iomodule.c.h +++ b/Modules/_io/clinic/_iomodule.c.h @@ -148,8 +148,7 @@ int closefd = 1; PyObject *opener = Py_None; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "O|sizzziO:open", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|sizzziO:open", _keywords, &file, &mode, &buffering, &encoding, &errors, &newline, &closefd, &opener)) goto exit; return_value = _io_open_impl(module, file, mode, buffering, encoding, errors, newline, closefd, opener); @@ -157,4 +156,4 @@ exit: return return_value; } -/*[clinic end generated code: output=c51a5a443c11f02b input=a9049054013a1b77]*/ +/*[clinic end generated code: output=97cdc09bf68a8064 input=a9049054013a1b77]*/ diff --git a/Modules/_io/clinic/bufferedio.c.h b/Modules/_io/clinic/bufferedio.c.h --- a/Modules/_io/clinic/bufferedio.c.h +++ b/Modules/_io/clinic/bufferedio.c.h @@ -19,9 +19,7 @@ PyObject *return_value = NULL; Py_buffer buffer = {NULL, NULL}; - if (!PyArg_Parse(arg, - "w*:readinto", - &buffer)) + if (!PyArg_Parse(arg, "w*:readinto", &buffer)) goto exit; return_value = _io__BufferedIOBase_readinto_impl(self, &buffer); @@ -50,9 +48,7 @@ PyObject *return_value = NULL; Py_buffer buffer = {NULL, NULL}; - if (!PyArg_Parse(arg, - "w*:readinto1", - &buffer)) + if (!PyArg_Parse(arg, "w*:readinto1", &buffer)) goto exit; return_value = _io__BufferedIOBase_readinto1_impl(self, &buffer); @@ -102,8 +98,7 @@ PyObject *return_value = NULL; Py_ssize_t size = 0; - if (!PyArg_ParseTuple(args, - "|n:peek", + if (!PyArg_ParseTuple(args, "|n:peek", &size)) goto exit; return_value = _io__Buffered_peek_impl(self, size); @@ -129,8 +124,7 @@ PyObject *return_value = NULL; Py_ssize_t n = -1; - if (!PyArg_ParseTuple(args, - "|O&:read", + if (!PyArg_ParseTuple(args, "|O&:read", _PyIO_ConvertSsize_t, &n)) goto exit; return_value = _io__Buffered_read_impl(self, n); @@ -156,9 +150,7 @@ PyObject *return_value = NULL; Py_ssize_t n; - if (!PyArg_Parse(arg, - "n:read1", - &n)) + if (!PyArg_Parse(arg, "n:read1", &n)) goto exit; return_value = _io__Buffered_read1_impl(self, n); @@ -183,9 +175,7 @@ PyObject *return_value = NULL; Py_buffer buffer = {NULL, NULL}; - if (!PyArg_Parse(arg, - "w*:readinto", - &buffer)) + if (!PyArg_Parse(arg, "w*:readinto", &buffer)) goto exit; return_value = _io__Buffered_readinto_impl(self, &buffer); @@ -214,9 +204,7 @@ PyObject *return_value = NULL; Py_buffer buffer = {NULL, NULL}; - if (!PyArg_Parse(arg, - "w*:readinto1", - &buffer)) + if (!PyArg_Parse(arg, "w*:readinto1", &buffer)) goto exit; return_value = _io__Buffered_readinto1_impl(self, &buffer); @@ -245,8 +233,7 @@ PyObject *return_value = NULL; Py_ssize_t size = -1; - if (!PyArg_ParseTuple(args, - "|O&:readline", + if (!PyArg_ParseTuple(args, "|O&:readline", _PyIO_ConvertSsize_t, &size)) goto exit; return_value = _io__Buffered_readline_impl(self, size); @@ -273,8 +260,7 @@ PyObject *targetobj; int whence = 0; - if (!PyArg_ParseTuple(args, - "O|i:seek", + if (!PyArg_ParseTuple(args, "O|i:seek", &targetobj, &whence)) goto exit; return_value = _io__Buffered_seek_impl(self, targetobj, whence); @@ -328,8 +314,7 @@ PyObject *raw; Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "O|n:BufferedReader", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|n:BufferedReader", _keywords, &raw, &buffer_size)) goto exit; return_value = _io_BufferedReader___init___impl((buffered *)self, raw, buffer_size); @@ -360,8 +345,7 @@ PyObject *raw; Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "O|n:BufferedWriter", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|n:BufferedWriter", _keywords, &raw, &buffer_size)) goto exit; return_value = _io_BufferedWriter___init___impl((buffered *)self, raw, buffer_size); @@ -387,9 +371,7 @@ PyObject *return_value = NULL; Py_buffer buffer = {NULL, NULL}; - if (!PyArg_Parse(arg, - "y*:write", - &buffer)) + if (!PyArg_Parse(arg, "y*:write", &buffer)) goto exit; return_value = _io_BufferedWriter_write_impl(self, &buffer); @@ -430,8 +412,7 @@ if ((Py_TYPE(self) == &PyBufferedRWPair_Type) && !_PyArg_NoKeywords("BufferedRWPair", kwargs)) goto exit; - if (!PyArg_ParseTuple(args, - "OO|n:BufferedRWPair", + if (!PyArg_ParseTuple(args, "OO|n:BufferedRWPair", &reader, &writer, &buffer_size)) goto exit; return_value = _io_BufferedRWPair___init___impl((rwpair *)self, reader, writer, buffer_size); @@ -462,8 +443,7 @@ PyObject *raw; Py_ssize_t buffer_size = DEFAULT_BUFFER_SIZE; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "O|n:BufferedRandom", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|n:BufferedRandom", _keywords, &raw, &buffer_size)) goto exit; return_value = _io_BufferedRandom___init___impl((buffered *)self, raw, buffer_size); @@ -471,4 +451,4 @@ exit: return return_value; } -/*[clinic end generated code: output=78808e39f36e3fa9 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=2bbb5e239b4ffe6f input=a9049054013a1b77]*/ diff --git a/Modules/_io/clinic/bytesio.c.h b/Modules/_io/clinic/bytesio.c.h --- a/Modules/_io/clinic/bytesio.c.h +++ b/Modules/_io/clinic/bytesio.c.h @@ -276,9 +276,7 @@ PyObject *return_value = NULL; Py_buffer buffer = {NULL, NULL}; - if (!PyArg_Parse(arg, - "w*:readinto", - &buffer)) + if (!PyArg_Parse(arg, "w*:readinto", &buffer)) goto exit; return_value = _io_BytesIO_readinto_impl(self, &buffer); @@ -346,8 +344,7 @@ Py_ssize_t pos; int whence = 0; - if (!PyArg_ParseTuple(args, - "n|i:seek", + if (!PyArg_ParseTuple(args, "n|i:seek", &pos, &whence)) goto exit; return_value = _io_BytesIO_seek_impl(self, pos, whence); @@ -414,8 +411,7 @@ static char *_keywords[] = {"initial_bytes", NULL}; PyObject *initvalue = NULL; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "|O:BytesIO", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O:BytesIO", _keywords, &initvalue)) goto exit; return_value = _io_BytesIO___init___impl((bytesio *)self, initvalue); @@ -423,4 +419,4 @@ exit: return return_value; } -/*[clinic end generated code: output=e22697ada514f4eb input=a9049054013a1b77]*/ +/*[clinic end generated code: output=500ccc149587fac4 input=a9049054013a1b77]*/ diff --git a/Modules/_io/clinic/fileio.c.h b/Modules/_io/clinic/fileio.c.h --- a/Modules/_io/clinic/fileio.c.h +++ b/Modules/_io/clinic/fileio.c.h @@ -55,8 +55,7 @@ int closefd = 1; PyObject *opener = Py_None; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "O|siO:FileIO", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|siO:FileIO", _keywords, &nameobj, &mode, &closefd, &opener)) goto exit; return_value = _io_FileIO___init___impl((fileio *)self, nameobj, mode, closefd, opener); @@ -155,9 +154,7 @@ PyObject *return_value = NULL; Py_buffer buffer = {NULL, NULL}; - if (!PyArg_Parse(arg, - "w*:readinto", - &buffer)) + if (!PyArg_Parse(arg, "w*:readinto", &buffer)) goto exit; return_value = _io_FileIO_readinto_impl(self, &buffer); @@ -212,8 +209,7 @@ PyObject *return_value = NULL; Py_ssize_t size = -1; - if (!PyArg_ParseTuple(args, - "|O&:read", + if (!PyArg_ParseTuple(args, "|O&:read", _PyIO_ConvertSsize_t, &size)) goto exit; return_value = _io_FileIO_read_impl(self, size); @@ -244,9 +240,7 @@ PyObject *return_value = NULL; Py_buffer b = {NULL, NULL}; - if (!PyArg_Parse(arg, - "y*:write", - &b)) + if (!PyArg_Parse(arg, "y*:write", &b)) goto exit; return_value = _io_FileIO_write_impl(self, &b); @@ -285,8 +279,7 @@ PyObject *pos; int whence = 0; - if (!PyArg_ParseTuple(args, - "O|i:seek", + if (!PyArg_ParseTuple(args, "O|i:seek", &pos, &whence)) goto exit; return_value = _io_FileIO_seek_impl(self, pos, whence); @@ -371,4 +364,4 @@ #ifndef _IO_FILEIO_TRUNCATE_METHODDEF #define _IO_FILEIO_TRUNCATE_METHODDEF #endif /* !defined(_IO_FILEIO_TRUNCATE_METHODDEF) */ -/*[clinic end generated code: output=c6708e1980f6e02d input=a9049054013a1b77]*/ +/*[clinic end generated code: output=b1a20b10c81add64 input=a9049054013a1b77]*/ diff --git a/Modules/_io/clinic/iobase.c.h b/Modules/_io/clinic/iobase.c.h --- a/Modules/_io/clinic/iobase.c.h +++ b/Modules/_io/clinic/iobase.c.h @@ -185,8 +185,7 @@ PyObject *return_value = NULL; Py_ssize_t limit = -1; - if (!PyArg_ParseTuple(args, - "|O&:readline", + if (!PyArg_ParseTuple(args, "|O&:readline", _PyIO_ConvertSsize_t, &limit)) goto exit; return_value = _io__IOBase_readline_impl(self, limit); @@ -217,8 +216,7 @@ PyObject *return_value = NULL; Py_ssize_t hint = -1; - if (!PyArg_ParseTuple(args, - "|O&:readlines", + if (!PyArg_ParseTuple(args, "|O&:readlines", _PyIO_ConvertSsize_t, &hint)) goto exit; return_value = _io__IOBase_readlines_impl(self, hint); @@ -252,8 +250,7 @@ PyObject *return_value = NULL; Py_ssize_t n = -1; - if (!PyArg_ParseTuple(args, - "|n:read", + if (!PyArg_ParseTuple(args, "|n:read", &n)) goto exit; return_value = _io__RawIOBase_read_impl(self, n); @@ -279,4 +276,4 @@ { return _io__RawIOBase_readall_impl(self); } -/*[clinic end generated code: output=84eef4b7541f54b7 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=fe034152b6884e65 input=a9049054013a1b77]*/ diff --git a/Modules/_io/clinic/stringio.c.h b/Modules/_io/clinic/stringio.c.h --- a/Modules/_io/clinic/stringio.c.h +++ b/Modules/_io/clinic/stringio.c.h @@ -156,8 +156,7 @@ Py_ssize_t pos; int whence = 0; - if (!PyArg_ParseTuple(args, - "n|i:seek", + if (!PyArg_ParseTuple(args, "n|i:seek", &pos, &whence)) goto exit; return_value = _io_StringIO_seek_impl(self, pos, whence); @@ -222,8 +221,7 @@ PyObject *value = NULL; PyObject *newline_obj = NULL; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "|OO:StringIO", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OO:StringIO", _keywords, &value, &newline_obj)) goto exit; return_value = _io_StringIO___init___impl((stringio *)self, value, newline_obj); @@ -285,4 +283,4 @@ { return _io_StringIO_seekable_impl(self); } -/*[clinic end generated code: output=f3062096d357c652 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=f061cf3a20cd14ed input=a9049054013a1b77]*/ diff --git a/Modules/_io/clinic/textio.c.h b/Modules/_io/clinic/textio.c.h --- a/Modules/_io/clinic/textio.c.h +++ b/Modules/_io/clinic/textio.c.h @@ -29,8 +29,7 @@ int translate; PyObject *errors = NULL; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "Oi|O:IncrementalNewlineDecoder", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|O:IncrementalNewlineDecoder", _keywords, &decoder, &translate, &errors)) goto exit; return_value = _io_IncrementalNewlineDecoder___init___impl((nldecoder_object *)self, decoder, translate, errors); @@ -59,8 +58,7 @@ PyObject *input; int final = 0; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "O|i:decode", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|i:decode", _keywords, &input, &final)) goto exit; return_value = _io_IncrementalNewlineDecoder_decode_impl(self, input, final); @@ -163,8 +161,7 @@ int line_buffering = 0; int write_through = 0; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "O|zzzii:TextIOWrapper", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|zzzii:TextIOWrapper", _keywords, &buffer, &encoding, &errors, &newline, &line_buffering, &write_through)) goto exit; return_value = _io_TextIOWrapper___init___impl((textio *)self, buffer, encoding, errors, newline, line_buffering, write_through); @@ -207,9 +204,7 @@ PyObject *return_value = NULL; PyObject *text; - if (!PyArg_Parse(arg, - "U:write", - &text)) + if (!PyArg_Parse(arg, "U:write", &text)) goto exit; return_value = _io_TextIOWrapper_write_impl(self, text); @@ -234,8 +229,7 @@ PyObject *return_value = NULL; Py_ssize_t n = -1; - if (!PyArg_ParseTuple(args, - "|O&:read", + if (!PyArg_ParseTuple(args, "|O&:read", _PyIO_ConvertSsize_t, &n)) goto exit; return_value = _io_TextIOWrapper_read_impl(self, n); @@ -261,8 +255,7 @@ PyObject *return_value = NULL; Py_ssize_t size = -1; - if (!PyArg_ParseTuple(args, - "|n:readline", + if (!PyArg_ParseTuple(args, "|n:readline", &size)) goto exit; return_value = _io_TextIOWrapper_readline_impl(self, size); @@ -289,8 +282,7 @@ PyObject *cookieObj; int whence = 0; - if (!PyArg_ParseTuple(args, - "O|i:seek", + if (!PyArg_ParseTuple(args, "O|i:seek", &cookieObj, &whence)) goto exit; return_value = _io_TextIOWrapper_seek_impl(self, cookieObj, whence); @@ -461,4 +453,4 @@ { return _io_TextIOWrapper_close_impl(self); } -/*[clinic end generated code: output=a610bd3b694886c3 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=690608f85aab8ba5 input=a9049054013a1b77]*/ diff --git a/Modules/cjkcodecs/clinic/multibytecodec.c.h b/Modules/cjkcodecs/clinic/multibytecodec.c.h --- a/Modules/cjkcodecs/clinic/multibytecodec.c.h +++ b/Modules/cjkcodecs/clinic/multibytecodec.c.h @@ -29,8 +29,7 @@ PyObject *input; const char *errors = NULL; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "O|z:encode", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|z:encode", _keywords, &input, &errors)) goto exit; return_value = _multibytecodec_MultibyteCodec_encode_impl(self, input, errors); @@ -66,8 +65,7 @@ Py_buffer input = {NULL, NULL}; const char *errors = NULL; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "y*|z:decode", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "y*|z:decode", _keywords, &input, &errors)) goto exit; return_value = _multibytecodec_MultibyteCodec_decode_impl(self, &input, errors); @@ -101,8 +99,7 @@ PyObject *input; int final = 0; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "O|i:encode", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|i:encode", _keywords, &input, &final)) goto exit; return_value = _multibytecodec_MultibyteIncrementalEncoder_encode_impl(self, input, final); @@ -149,8 +146,7 @@ Py_buffer input = {NULL, NULL}; int final = 0; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "y*|i:decode", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "y*|i:decode", _keywords, &input, &final)) goto exit; return_value = _multibytecodec_MultibyteIncrementalDecoder_decode_impl(self, &input, final); @@ -321,4 +317,4 @@ #define _MULTIBYTECODEC___CREATE_CODEC_METHODDEF \ {"__create_codec", (PyCFunction)_multibytecodec___create_codec, METH_O, _multibytecodec___create_codec__doc__}, -/*[clinic end generated code: output=0fe582cb941024c1 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=c104f5fd548c1ac5 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_bz2module.c.h b/Modules/clinic/_bz2module.c.h --- a/Modules/clinic/_bz2module.c.h +++ b/Modules/clinic/_bz2module.c.h @@ -25,9 +25,7 @@ PyObject *return_value = NULL; Py_buffer data = {NULL, NULL}; - if (!PyArg_Parse(arg, - "y*:compress", - &data)) + if (!PyArg_Parse(arg, "y*:compress", &data)) goto exit; return_value = _bz2_BZ2Compressor_compress_impl(self, &data); @@ -84,8 +82,7 @@ if ((Py_TYPE(self) == &BZ2Compressor_Type) && !_PyArg_NoKeywords("BZ2Compressor", kwargs)) goto exit; - if (!PyArg_ParseTuple(args, - "|i:BZ2Compressor", + if (!PyArg_ParseTuple(args, "|i:BZ2Compressor", &compresslevel)) goto exit; return_value = _bz2_BZ2Compressor___init___impl((BZ2Compressor *)self, compresslevel); @@ -128,8 +125,7 @@ Py_buffer data = {NULL, NULL}; Py_ssize_t max_length = -1; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "y*|n:decompress", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "y*|n:decompress", _keywords, &data, &max_length)) goto exit; return_value = _bz2_BZ2Decompressor_decompress_impl(self, &data, max_length); @@ -169,4 +165,4 @@ exit: return return_value; } -/*[clinic end generated code: output=e8a48a949969c355 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=fef29b76b3314fc7 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_codecsmodule.c.h b/Modules/clinic/_codecsmodule.c.h --- a/Modules/clinic/_codecsmodule.c.h +++ b/Modules/clinic/_codecsmodule.c.h @@ -20,13 +20,11 @@ PyObject *return_value = NULL; const char *encoding; - if (!PyArg_Parse(arg, - "s:_forget_codec", - &encoding)) + if (!PyArg_Parse(arg, "s:_forget_codec", &encoding)) goto exit; return_value = _codecs__forget_codec_impl(module, encoding); exit: return return_value; } -/*[clinic end generated code: output=fc5ce4d3166f7d96 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=52cc017e06c8ef9a input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_cryptmodule.c.h b/Modules/clinic/_cryptmodule.c.h --- a/Modules/clinic/_cryptmodule.c.h +++ b/Modules/clinic/_cryptmodule.c.h @@ -26,8 +26,7 @@ const char *word; const char *salt; - if (!PyArg_ParseTuple(args, - "ss:crypt", + if (!PyArg_ParseTuple(args, "ss:crypt", &word, &salt)) goto exit; return_value = crypt_crypt_impl(module, word, salt); @@ -35,4 +34,4 @@ exit: return return_value; } -/*[clinic end generated code: output=b5b8d977189d19ea input=a9049054013a1b77]*/ +/*[clinic end generated code: output=22c295c9bce018c4 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_datetimemodule.c.h b/Modules/clinic/_datetimemodule.c.h --- a/Modules/clinic/_datetimemodule.c.h +++ b/Modules/clinic/_datetimemodule.c.h @@ -26,8 +26,7 @@ static char *_keywords[] = {"tz", NULL}; PyObject *tz = Py_None; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "|O:now", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O:now", _keywords, &tz)) goto exit; return_value = datetime_datetime_now_impl(type, tz); @@ -35,4 +34,4 @@ exit: return return_value; } -/*[clinic end generated code: output=a5c51b96f10c462c input=a9049054013a1b77]*/ +/*[clinic end generated code: output=7f45c670d6e4953a input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_dbmmodule.c.h b/Modules/clinic/_dbmmodule.c.h --- a/Modules/clinic/_dbmmodule.c.h +++ b/Modules/clinic/_dbmmodule.c.h @@ -59,8 +59,7 @@ Py_ssize_clean_t key_length; PyObject *default_value = NULL; - if (!PyArg_ParseTuple(args, - "s#|O:get", + if (!PyArg_ParseTuple(args, "s#|O:get", &key, &key_length, &default_value)) goto exit; return_value = _dbm_dbm_get_impl(self, key, key_length, default_value); @@ -93,8 +92,7 @@ Py_ssize_clean_t key_length; PyObject *default_value = NULL; - if (!PyArg_ParseTuple(args, - "s#|O:setdefault", + if (!PyArg_ParseTuple(args, "s#|O:setdefault", &key, &key_length, &default_value)) goto exit; return_value = _dbm_dbm_setdefault_impl(self, key, key_length, default_value); @@ -132,8 +130,7 @@ const char *flags = "r"; int mode = 438; - if (!PyArg_ParseTuple(args, - "s|si:open", + if (!PyArg_ParseTuple(args, "s|si:open", &filename, &flags, &mode)) goto exit; return_value = dbmopen_impl(module, filename, flags, mode); @@ -141,4 +138,4 @@ exit: return return_value; } -/*[clinic end generated code: output=951fcfdb6d667a61 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=1d92e81b28c558d0 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_gdbmmodule.c.h b/Modules/clinic/_gdbmmodule.c.h --- a/Modules/clinic/_gdbmmodule.c.h +++ b/Modules/clinic/_gdbmmodule.c.h @@ -147,9 +147,7 @@ const char *key; Py_ssize_clean_t key_length; - if (!PyArg_Parse(arg, - "s#:nextkey", - &key, &key_length)) + if (!PyArg_Parse(arg, "s#:nextkey", &key, &key_length)) goto exit; return_value = _gdbm_gdbm_nextkey_impl(self, key, key_length); @@ -244,8 +242,7 @@ const char *flags = "r"; int mode = 438; - if (!PyArg_ParseTuple(args, - "s|si:open", + if (!PyArg_ParseTuple(args, "s|si:open", &name, &flags, &mode)) goto exit; return_value = dbmopen_impl(module, name, flags, mode); @@ -253,4 +250,4 @@ exit: return return_value; } -/*[clinic end generated code: output=b41c68a5f30699cb input=a9049054013a1b77]*/ +/*[clinic end generated code: output=d3d8d871bcccb68a input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_lzmamodule.c.h b/Modules/clinic/_lzmamodule.c.h --- a/Modules/clinic/_lzmamodule.c.h +++ b/Modules/clinic/_lzmamodule.c.h @@ -25,9 +25,7 @@ PyObject *return_value = NULL; Py_buffer data = {NULL, NULL}; - if (!PyArg_Parse(arg, - "y*:compress", - &data)) + if (!PyArg_Parse(arg, "y*:compress", &data)) goto exit; return_value = _lzma_LZMACompressor_compress_impl(self, &data); @@ -95,8 +93,7 @@ Py_buffer data = {NULL, NULL}; Py_ssize_t max_length = -1; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "y*|n:decompress", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "y*|n:decompress", _keywords, &data, &max_length)) goto exit; return_value = _lzma_LZMADecompressor_decompress_impl(self, &data, max_length); @@ -145,8 +142,7 @@ PyObject *memlimit = Py_None; PyObject *filters = Py_None; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "|iOO:LZMADecompressor", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iOO:LZMADecompressor", _keywords, &format, &memlimit, &filters)) goto exit; return_value = _lzma_LZMADecompressor___init___impl((Decompressor *)self, format, memlimit, filters); @@ -175,9 +171,7 @@ PyObject *return_value = NULL; int check_id; - if (!PyArg_Parse(arg, - "i:is_check_supported", - &check_id)) + if (!PyArg_Parse(arg, "i:is_check_supported", &check_id)) goto exit; return_value = _lzma_is_check_supported_impl(module, check_id); @@ -205,9 +199,7 @@ PyObject *return_value = NULL; lzma_filter filter = {LZMA_VLI_UNKNOWN, NULL}; - if (!PyArg_Parse(arg, - "O&:_encode_filter_properties", - lzma_filter_converter, &filter)) + if (!PyArg_Parse(arg, "O&:_encode_filter_properties", lzma_filter_converter, &filter)) goto exit; return_value = _lzma__encode_filter_properties_impl(module, filter); @@ -241,8 +233,7 @@ lzma_vli filter_id; Py_buffer encoded_props = {NULL, NULL}; - if (!PyArg_ParseTuple(args, - "O&y*:_decode_filter_properties", + if (!PyArg_ParseTuple(args, "O&y*:_decode_filter_properties", lzma_vli_converter, &filter_id, &encoded_props)) goto exit; return_value = _lzma__decode_filter_properties_impl(module, filter_id, &encoded_props); @@ -254,4 +245,4 @@ return return_value; } -/*[clinic end generated code: output=8981089cde080b54 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=2d3e0842be3d3fe1 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_opcode.c.h b/Modules/clinic/_opcode.c.h --- a/Modules/clinic/_opcode.c.h +++ b/Modules/clinic/_opcode.c.h @@ -22,8 +22,7 @@ PyObject *oparg = Py_None; int _return_value; - if (!PyArg_ParseTuple(args, - "i|O:stack_effect", + if (!PyArg_ParseTuple(args, "i|O:stack_effect", &opcode, &oparg)) goto exit; _return_value = _opcode_stack_effect_impl(module, opcode, oparg); @@ -34,4 +33,4 @@ exit: return return_value; } -/*[clinic end generated code: output=dbe45148bc21ecdf input=a9049054013a1b77]*/ +/*[clinic end generated code: output=8ee7cb735705e8b3 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_pickle.c.h b/Modules/clinic/_pickle.c.h --- a/Modules/clinic/_pickle.c.h +++ b/Modules/clinic/_pickle.c.h @@ -97,8 +97,7 @@ PyObject *protocol = NULL; int fix_imports = 1; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "O|Op:Pickler", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Op:Pickler", _keywords, &file, &protocol, &fix_imports)) goto exit; return_value = _pickle_Pickler___init___impl((PicklerObject *)self, file, protocol, fix_imports); @@ -288,8 +287,7 @@ const char *encoding = "ASCII"; const char *errors = "strict"; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "O|$pss:Unpickler", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|$pss:Unpickler", _keywords, &file, &fix_imports, &encoding, &errors)) goto exit; return_value = _pickle_Unpickler___init___impl((UnpicklerObject *)self, file, fix_imports, encoding, errors); @@ -395,8 +393,7 @@ PyObject *protocol = NULL; int fix_imports = 1; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "OO|O$p:dump", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|O$p:dump", _keywords, &obj, &file, &protocol, &fix_imports)) goto exit; return_value = _pickle_dump_impl(module, obj, file, protocol, fix_imports); @@ -439,8 +436,7 @@ PyObject *protocol = NULL; int fix_imports = 1; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "O|O$p:dumps", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O$p:dumps", _keywords, &obj, &protocol, &fix_imports)) goto exit; return_value = _pickle_dumps_impl(module, obj, protocol, fix_imports); @@ -495,8 +491,7 @@ const char *encoding = "ASCII"; const char *errors = "strict"; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "O|$pss:load", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|$pss:load", _keywords, &file, &fix_imports, &encoding, &errors)) goto exit; return_value = _pickle_load_impl(module, file, fix_imports, encoding, errors); @@ -542,8 +537,7 @@ const char *encoding = "ASCII"; const char *errors = "strict"; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "O|$pss:loads", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|$pss:loads", _keywords, &data, &fix_imports, &encoding, &errors)) goto exit; return_value = _pickle_loads_impl(module, data, fix_imports, encoding, errors); @@ -551,4 +545,4 @@ exit: return return_value; } -/*[clinic end generated code: output=2c413ecc2ec74f7c input=a9049054013a1b77]*/ +/*[clinic end generated code: output=06f3a5233298448e input=a9049054013a1b77]*/ diff --git a/Modules/clinic/arraymodule.c.h b/Modules/clinic/arraymodule.c.h --- a/Modules/clinic/arraymodule.c.h +++ b/Modules/clinic/arraymodule.c.h @@ -76,8 +76,7 @@ PyObject *return_value = NULL; Py_ssize_t i = -1; - if (!PyArg_ParseTuple(args, - "|n:pop", + if (!PyArg_ParseTuple(args, "|n:pop", &i)) goto exit; return_value = array_array_pop_impl(self, i); @@ -114,8 +113,7 @@ Py_ssize_t i; PyObject *v; - if (!PyArg_ParseTuple(args, - "nO:insert", + if (!PyArg_ParseTuple(args, "nO:insert", &i, &v)) goto exit; return_value = array_array_insert_impl(self, i, v); @@ -212,8 +210,7 @@ PyObject *f; Py_ssize_t n; - if (!PyArg_ParseTuple(args, - "On:fromfile", + if (!PyArg_ParseTuple(args, "On:fromfile", &f, &n)) goto exit; return_value = array_array_fromfile_impl(self, f, n); @@ -278,9 +275,7 @@ PyObject *return_value = NULL; Py_buffer buffer = {NULL, NULL}; - if (!PyArg_Parse(arg, - "s*:fromstring", - &buffer)) + if (!PyArg_Parse(arg, "s*:fromstring", &buffer)) goto exit; return_value = array_array_fromstring_impl(self, &buffer); @@ -310,9 +305,7 @@ PyObject *return_value = NULL; Py_buffer buffer = {NULL, NULL}; - if (!PyArg_Parse(arg, - "y*:frombytes", - &buffer)) + if (!PyArg_Parse(arg, "y*:frombytes", &buffer)) goto exit; return_value = array_array_frombytes_impl(self, &buffer); @@ -386,9 +379,7 @@ Py_UNICODE *ustr; Py_ssize_clean_t ustr_length; - if (!PyArg_Parse(arg, - "u#:fromunicode", - &ustr, &ustr_length)) + if (!PyArg_Parse(arg, "u#:fromunicode", &ustr, &ustr_length)) goto exit; return_value = array_array_fromunicode_impl(self, ustr, ustr_length); @@ -461,8 +452,7 @@ enum machine_format_code mformat_code; PyObject *items; - if (!PyArg_ParseTuple(args, - "OCiO:_array_reconstructor", + if (!PyArg_ParseTuple(args, "OCiO:_array_reconstructor", &arraytype, &typecode, &mformat_code, &items)) goto exit; return_value = array__array_reconstructor_impl(module, arraytype, typecode, mformat_code, items); @@ -506,4 +496,4 @@ #define ARRAY_ARRAYITERATOR___SETSTATE___METHODDEF \ {"__setstate__", (PyCFunction)array_arrayiterator___setstate__, METH_O, array_arrayiterator___setstate____doc__}, -/*[clinic end generated code: output=48e8198c8087cd00 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=d2e82c65ea841cfc input=a9049054013a1b77]*/ diff --git a/Modules/clinic/audioop.c.h b/Modules/clinic/audioop.c.h --- a/Modules/clinic/audioop.c.h +++ b/Modules/clinic/audioop.c.h @@ -23,8 +23,7 @@ int width; Py_ssize_t index; - if (!PyArg_ParseTuple(args, - "y*in:getsample", + if (!PyArg_ParseTuple(args, "y*in:getsample", &fragment, &width, &index)) goto exit; return_value = audioop_getsample_impl(module, &fragment, width, index); @@ -56,8 +55,7 @@ Py_buffer fragment = {NULL, NULL}; int width; - if (!PyArg_ParseTuple(args, - "y*i:max", + if (!PyArg_ParseTuple(args, "y*i:max", &fragment, &width)) goto exit; return_value = audioop_max_impl(module, &fragment, width); @@ -89,8 +87,7 @@ Py_buffer fragment = {NULL, NULL}; int width; - if (!PyArg_ParseTuple(args, - "y*i:minmax", + if (!PyArg_ParseTuple(args, "y*i:minmax", &fragment, &width)) goto exit; return_value = audioop_minmax_impl(module, &fragment, width); @@ -122,8 +119,7 @@ Py_buffer fragment = {NULL, NULL}; int width; - if (!PyArg_ParseTuple(args, - "y*i:avg", + if (!PyArg_ParseTuple(args, "y*i:avg", &fragment, &width)) goto exit; return_value = audioop_avg_impl(module, &fragment, width); @@ -155,8 +151,7 @@ Py_buffer fragment = {NULL, NULL}; int width; - if (!PyArg_ParseTuple(args, - "y*i:rms", + if (!PyArg_ParseTuple(args, "y*i:rms", &fragment, &width)) goto exit; return_value = audioop_rms_impl(module, &fragment, width); @@ -189,8 +184,7 @@ Py_buffer fragment = {NULL, NULL}; Py_buffer reference = {NULL, NULL}; - if (!PyArg_ParseTuple(args, - "y*y*:findfit", + if (!PyArg_ParseTuple(args, "y*y*:findfit", &fragment, &reference)) goto exit; return_value = audioop_findfit_impl(module, &fragment, &reference); @@ -226,8 +220,7 @@ Py_buffer fragment = {NULL, NULL}; Py_buffer reference = {NULL, NULL}; - if (!PyArg_ParseTuple(args, - "y*y*:findfactor", + if (!PyArg_ParseTuple(args, "y*y*:findfactor", &fragment, &reference)) goto exit; return_value = audioop_findfactor_impl(module, &fragment, &reference); @@ -263,8 +256,7 @@ Py_buffer fragment = {NULL, NULL}; Py_ssize_t length; - if (!PyArg_ParseTuple(args, - "y*n:findmax", + if (!PyArg_ParseTuple(args, "y*n:findmax", &fragment, &length)) goto exit; return_value = audioop_findmax_impl(module, &fragment, length); @@ -296,8 +288,7 @@ Py_buffer fragment = {NULL, NULL}; int width; - if (!PyArg_ParseTuple(args, - "y*i:avgpp", + if (!PyArg_ParseTuple(args, "y*i:avgpp", &fragment, &width)) goto exit; return_value = audioop_avgpp_impl(module, &fragment, width); @@ -329,8 +320,7 @@ Py_buffer fragment = {NULL, NULL}; int width; - if (!PyArg_ParseTuple(args, - "y*i:maxpp", + if (!PyArg_ParseTuple(args, "y*i:maxpp", &fragment, &width)) goto exit; return_value = audioop_maxpp_impl(module, &fragment, width); @@ -362,8 +352,7 @@ Py_buffer fragment = {NULL, NULL}; int width; - if (!PyArg_ParseTuple(args, - "y*i:cross", + if (!PyArg_ParseTuple(args, "y*i:cross", &fragment, &width)) goto exit; return_value = audioop_cross_impl(module, &fragment, width); @@ -397,8 +386,7 @@ int width; double factor; - if (!PyArg_ParseTuple(args, - "y*id:mul", + if (!PyArg_ParseTuple(args, "y*id:mul", &fragment, &width, &factor)) goto exit; return_value = audioop_mul_impl(module, &fragment, width, factor); @@ -433,8 +421,7 @@ double lfactor; double rfactor; - if (!PyArg_ParseTuple(args, - "y*idd:tomono", + if (!PyArg_ParseTuple(args, "y*idd:tomono", &fragment, &width, &lfactor, &rfactor)) goto exit; return_value = audioop_tomono_impl(module, &fragment, width, lfactor, rfactor); @@ -469,8 +456,7 @@ double lfactor; double rfactor; - if (!PyArg_ParseTuple(args, - "y*idd:tostereo", + if (!PyArg_ParseTuple(args, "y*idd:tostereo", &fragment, &width, &lfactor, &rfactor)) goto exit; return_value = audioop_tostereo_impl(module, &fragment, width, lfactor, rfactor); @@ -504,8 +490,7 @@ Py_buffer fragment2 = {NULL, NULL}; int width; - if (!PyArg_ParseTuple(args, - "y*y*i:add", + if (!PyArg_ParseTuple(args, "y*y*i:add", &fragment1, &fragment2, &width)) goto exit; return_value = audioop_add_impl(module, &fragment1, &fragment2, width); @@ -542,8 +527,7 @@ int width; int bias; - if (!PyArg_ParseTuple(args, - "y*ii:bias", + if (!PyArg_ParseTuple(args, "y*ii:bias", &fragment, &width, &bias)) goto exit; return_value = audioop_bias_impl(module, &fragment, width, bias); @@ -575,8 +559,7 @@ Py_buffer fragment = {NULL, NULL}; int width; - if (!PyArg_ParseTuple(args, - "y*i:reverse", + if (!PyArg_ParseTuple(args, "y*i:reverse", &fragment, &width)) goto exit; return_value = audioop_reverse_impl(module, &fragment, width); @@ -608,8 +591,7 @@ Py_buffer fragment = {NULL, NULL}; int width; - if (!PyArg_ParseTuple(args, - "y*i:byteswap", + if (!PyArg_ParseTuple(args, "y*i:byteswap", &fragment, &width)) goto exit; return_value = audioop_byteswap_impl(module, &fragment, width); @@ -643,8 +625,7 @@ int width; int newwidth; - if (!PyArg_ParseTuple(args, - "y*ii:lin2lin", + if (!PyArg_ParseTuple(args, "y*ii:lin2lin", &fragment, &width, &newwidth)) goto exit; return_value = audioop_lin2lin_impl(module, &fragment, width, newwidth); @@ -685,8 +666,7 @@ int weightA = 1; int weightB = 0; - if (!PyArg_ParseTuple(args, - "y*iiiiO|ii:ratecv", + if (!PyArg_ParseTuple(args, "y*iiiiO|ii:ratecv", &fragment, &width, &nchannels, &inrate, &outrate, &state, &weightA, &weightB)) goto exit; return_value = audioop_ratecv_impl(module, &fragment, width, nchannels, inrate, outrate, state, weightA, weightB); @@ -718,8 +698,7 @@ Py_buffer fragment = {NULL, NULL}; int width; - if (!PyArg_ParseTuple(args, - "y*i:lin2ulaw", + if (!PyArg_ParseTuple(args, "y*i:lin2ulaw", &fragment, &width)) goto exit; return_value = audioop_lin2ulaw_impl(module, &fragment, width); @@ -751,8 +730,7 @@ Py_buffer fragment = {NULL, NULL}; int width; - if (!PyArg_ParseTuple(args, - "y*i:ulaw2lin", + if (!PyArg_ParseTuple(args, "y*i:ulaw2lin", &fragment, &width)) goto exit; return_value = audioop_ulaw2lin_impl(module, &fragment, width); @@ -784,8 +762,7 @@ Py_buffer fragment = {NULL, NULL}; int width; - if (!PyArg_ParseTuple(args, - "y*i:lin2alaw", + if (!PyArg_ParseTuple(args, "y*i:lin2alaw", &fragment, &width)) goto exit; return_value = audioop_lin2alaw_impl(module, &fragment, width); @@ -817,8 +794,7 @@ Py_buffer fragment = {NULL, NULL}; int width; - if (!PyArg_ParseTuple(args, - "y*i:alaw2lin", + if (!PyArg_ParseTuple(args, "y*i:alaw2lin", &fragment, &width)) goto exit; return_value = audioop_alaw2lin_impl(module, &fragment, width); @@ -852,8 +828,7 @@ int width; PyObject *state; - if (!PyArg_ParseTuple(args, - "y*iO:lin2adpcm", + if (!PyArg_ParseTuple(args, "y*iO:lin2adpcm", &fragment, &width, &state)) goto exit; return_value = audioop_lin2adpcm_impl(module, &fragment, width, state); @@ -887,8 +862,7 @@ int width; PyObject *state; - if (!PyArg_ParseTuple(args, - "y*iO:adpcm2lin", + if (!PyArg_ParseTuple(args, "y*iO:adpcm2lin", &fragment, &width, &state)) goto exit; return_value = audioop_adpcm2lin_impl(module, &fragment, width, state); @@ -900,4 +874,4 @@ return return_value; } -/*[clinic end generated code: output=9b01aafef50425ae input=a9049054013a1b77]*/ +/*[clinic end generated code: output=a076e1b213a8727b input=a9049054013a1b77]*/ diff --git a/Modules/clinic/binascii.c.h b/Modules/clinic/binascii.c.h --- a/Modules/clinic/binascii.c.h +++ b/Modules/clinic/binascii.c.h @@ -20,9 +20,7 @@ PyObject *return_value = NULL; Py_buffer data = {NULL, NULL}; - if (!PyArg_Parse(arg, - "O&:a2b_uu", - ascii_buffer_converter, &data)) + if (!PyArg_Parse(arg, "O&:a2b_uu", ascii_buffer_converter, &data)) goto exit; return_value = binascii_a2b_uu_impl(module, &data); @@ -52,9 +50,7 @@ PyObject *return_value = NULL; Py_buffer data = {NULL, NULL}; - if (!PyArg_Parse(arg, - "y*:b2a_uu", - &data)) + if (!PyArg_Parse(arg, "y*:b2a_uu", &data)) goto exit; return_value = binascii_b2a_uu_impl(module, &data); @@ -84,9 +80,7 @@ PyObject *return_value = NULL; Py_buffer data = {NULL, NULL}; - if (!PyArg_Parse(arg, - "O&:a2b_base64", - ascii_buffer_converter, &data)) + if (!PyArg_Parse(arg, "O&:a2b_base64", ascii_buffer_converter, &data)) goto exit; return_value = binascii_a2b_base64_impl(module, &data); @@ -116,9 +110,7 @@ PyObject *return_value = NULL; Py_buffer data = {NULL, NULL}; - if (!PyArg_Parse(arg, - "y*:b2a_base64", - &data)) + if (!PyArg_Parse(arg, "y*:b2a_base64", &data)) goto exit; return_value = binascii_b2a_base64_impl(module, &data); @@ -148,9 +140,7 @@ PyObject *return_value = NULL; Py_buffer data = {NULL, NULL}; - if (!PyArg_Parse(arg, - "O&:a2b_hqx", - ascii_buffer_converter, &data)) + if (!PyArg_Parse(arg, "O&:a2b_hqx", ascii_buffer_converter, &data)) goto exit; return_value = binascii_a2b_hqx_impl(module, &data); @@ -180,9 +170,7 @@ PyObject *return_value = NULL; Py_buffer data = {NULL, NULL}; - if (!PyArg_Parse(arg, - "y*:rlecode_hqx", - &data)) + if (!PyArg_Parse(arg, "y*:rlecode_hqx", &data)) goto exit; return_value = binascii_rlecode_hqx_impl(module, &data); @@ -212,9 +200,7 @@ PyObject *return_value = NULL; Py_buffer data = {NULL, NULL}; - if (!PyArg_Parse(arg, - "y*:b2a_hqx", - &data)) + if (!PyArg_Parse(arg, "y*:b2a_hqx", &data)) goto exit; return_value = binascii_b2a_hqx_impl(module, &data); @@ -244,9 +230,7 @@ PyObject *return_value = NULL; Py_buffer data = {NULL, NULL}; - if (!PyArg_Parse(arg, - "y*:rledecode_hqx", - &data)) + if (!PyArg_Parse(arg, "y*:rledecode_hqx", &data)) goto exit; return_value = binascii_rledecode_hqx_impl(module, &data); @@ -278,8 +262,7 @@ unsigned int crc; unsigned int _return_value; - if (!PyArg_ParseTuple(args, - "y*I:crc_hqx", + if (!PyArg_ParseTuple(args, "y*I:crc_hqx", &data, &crc)) goto exit; _return_value = binascii_crc_hqx_impl(module, &data, crc); @@ -315,8 +298,7 @@ unsigned int crc = 0; unsigned int _return_value; - if (!PyArg_ParseTuple(args, - "y*|I:crc32", + if (!PyArg_ParseTuple(args, "y*|I:crc32", &data, &crc)) goto exit; _return_value = binascii_crc32_impl(module, &data, crc); @@ -353,9 +335,7 @@ PyObject *return_value = NULL; Py_buffer data = {NULL, NULL}; - if (!PyArg_Parse(arg, - "y*:b2a_hex", - &data)) + if (!PyArg_Parse(arg, "y*:b2a_hex", &data)) goto exit; return_value = binascii_b2a_hex_impl(module, &data); @@ -387,9 +367,7 @@ PyObject *return_value = NULL; Py_buffer data = {NULL, NULL}; - if (!PyArg_Parse(arg, - "y*:hexlify", - &data)) + if (!PyArg_Parse(arg, "y*:hexlify", &data)) goto exit; return_value = binascii_hexlify_impl(module, &data); @@ -422,9 +400,7 @@ PyObject *return_value = NULL; Py_buffer hexstr = {NULL, NULL}; - if (!PyArg_Parse(arg, - "O&:a2b_hex", - ascii_buffer_converter, &hexstr)) + if (!PyArg_Parse(arg, "O&:a2b_hex", ascii_buffer_converter, &hexstr)) goto exit; return_value = binascii_a2b_hex_impl(module, &hexstr); @@ -456,9 +432,7 @@ PyObject *return_value = NULL; Py_buffer hexstr = {NULL, NULL}; - if (!PyArg_Parse(arg, - "O&:unhexlify", - ascii_buffer_converter, &hexstr)) + if (!PyArg_Parse(arg, "O&:unhexlify", ascii_buffer_converter, &hexstr)) goto exit; return_value = binascii_unhexlify_impl(module, &hexstr); @@ -490,8 +464,7 @@ Py_buffer data = {NULL, NULL}; int header = 0; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "O&|i:a2b_qp", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&|i:a2b_qp", _keywords, ascii_buffer_converter, &data, &header)) goto exit; return_value = binascii_a2b_qp_impl(module, &data, header); @@ -531,8 +504,7 @@ int istext = 1; int header = 0; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "y*|iii:b2a_qp", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "y*|iii:b2a_qp", _keywords, &data, "etabs, &istext, &header)) goto exit; return_value = binascii_b2a_qp_impl(module, &data, quotetabs, istext, header); @@ -544,4 +516,4 @@ return return_value; } -/*[clinic end generated code: output=5f8d3578618b3432 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=b1a3cbf7660ebaa5 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/cmathmodule.c.h b/Modules/clinic/cmathmodule.c.h --- a/Modules/clinic/cmathmodule.c.h +++ b/Modules/clinic/cmathmodule.c.h @@ -21,9 +21,7 @@ Py_complex z; Py_complex _return_value; - if (!PyArg_Parse(arg, - "D:acos", - &z)) + if (!PyArg_Parse(arg, "D:acos", &z)) goto exit; /* modifications for z */ errno = 0; PyFPE_START_PROTECT("complex function", goto exit); @@ -64,9 +62,7 @@ Py_complex z; Py_complex _return_value; - if (!PyArg_Parse(arg, - "D:acosh", - &z)) + if (!PyArg_Parse(arg, "D:acosh", &z)) goto exit; /* modifications for z */ errno = 0; PyFPE_START_PROTECT("complex function", goto exit); @@ -107,9 +103,7 @@ Py_complex z; Py_complex _return_value; - if (!PyArg_Parse(arg, - "D:asin", - &z)) + if (!PyArg_Parse(arg, "D:asin", &z)) goto exit; /* modifications for z */ errno = 0; PyFPE_START_PROTECT("complex function", goto exit); @@ -150,9 +144,7 @@ Py_complex z; Py_complex _return_value; - if (!PyArg_Parse(arg, - "D:asinh", - &z)) + if (!PyArg_Parse(arg, "D:asinh", &z)) goto exit; /* modifications for z */ errno = 0; PyFPE_START_PROTECT("complex function", goto exit); @@ -193,9 +185,7 @@ Py_complex z; Py_complex _return_value; - if (!PyArg_Parse(arg, - "D:atan", - &z)) + if (!PyArg_Parse(arg, "D:atan", &z)) goto exit; /* modifications for z */ errno = 0; PyFPE_START_PROTECT("complex function", goto exit); @@ -236,9 +226,7 @@ Py_complex z; Py_complex _return_value; - if (!PyArg_Parse(arg, - "D:atanh", - &z)) + if (!PyArg_Parse(arg, "D:atanh", &z)) goto exit; /* modifications for z */ errno = 0; PyFPE_START_PROTECT("complex function", goto exit); @@ -279,9 +267,7 @@ Py_complex z; Py_complex _return_value; - if (!PyArg_Parse(arg, - "D:cos", - &z)) + if (!PyArg_Parse(arg, "D:cos", &z)) goto exit; /* modifications for z */ errno = 0; PyFPE_START_PROTECT("complex function", goto exit); @@ -322,9 +308,7 @@ Py_complex z; Py_complex _return_value; - if (!PyArg_Parse(arg, - "D:cosh", - &z)) + if (!PyArg_Parse(arg, "D:cosh", &z)) goto exit; /* modifications for z */ errno = 0; PyFPE_START_PROTECT("complex function", goto exit); @@ -365,9 +349,7 @@ Py_complex z; Py_complex _return_value; - if (!PyArg_Parse(arg, - "D:exp", - &z)) + if (!PyArg_Parse(arg, "D:exp", &z)) goto exit; /* modifications for z */ errno = 0; PyFPE_START_PROTECT("complex function", goto exit); @@ -408,9 +390,7 @@ Py_complex z; Py_complex _return_value; - if (!PyArg_Parse(arg, - "D:log10", - &z)) + if (!PyArg_Parse(arg, "D:log10", &z)) goto exit; /* modifications for z */ errno = 0; PyFPE_START_PROTECT("complex function", goto exit); @@ -451,9 +431,7 @@ Py_complex z; Py_complex _return_value; - if (!PyArg_Parse(arg, - "D:sin", - &z)) + if (!PyArg_Parse(arg, "D:sin", &z)) goto exit; /* modifications for z */ errno = 0; PyFPE_START_PROTECT("complex function", goto exit); @@ -494,9 +472,7 @@ Py_complex z; Py_complex _return_value; - if (!PyArg_Parse(arg, - "D:sinh", - &z)) + if (!PyArg_Parse(arg, "D:sinh", &z)) goto exit; /* modifications for z */ errno = 0; PyFPE_START_PROTECT("complex function", goto exit); @@ -537,9 +513,7 @@ Py_complex z; Py_complex _return_value; - if (!PyArg_Parse(arg, - "D:sqrt", - &z)) + if (!PyArg_Parse(arg, "D:sqrt", &z)) goto exit; /* modifications for z */ errno = 0; PyFPE_START_PROTECT("complex function", goto exit); @@ -580,9 +554,7 @@ Py_complex z; Py_complex _return_value; - if (!PyArg_Parse(arg, - "D:tan", - &z)) + if (!PyArg_Parse(arg, "D:tan", &z)) goto exit; /* modifications for z */ errno = 0; PyFPE_START_PROTECT("complex function", goto exit); @@ -623,9 +595,7 @@ Py_complex z; Py_complex _return_value; - if (!PyArg_Parse(arg, - "D:tanh", - &z)) + if (!PyArg_Parse(arg, "D:tanh", &z)) goto exit; /* modifications for z */ errno = 0; PyFPE_START_PROTECT("complex function", goto exit); @@ -668,8 +638,7 @@ Py_complex x; PyObject *y_obj = NULL; - if (!PyArg_ParseTuple(args, - "D|O:log", + if (!PyArg_ParseTuple(args, "D|O:log", &x, &y_obj)) goto exit; return_value = cmath_log_impl(module, x, y_obj); @@ -696,9 +665,7 @@ PyObject *return_value = NULL; Py_complex z; - if (!PyArg_Parse(arg, - "D:phase", - &z)) + if (!PyArg_Parse(arg, "D:phase", &z)) goto exit; return_value = cmath_phase_impl(module, z); @@ -726,9 +693,7 @@ PyObject *return_value = NULL; Py_complex z; - if (!PyArg_Parse(arg, - "D:polar", - &z)) + if (!PyArg_Parse(arg, "D:polar", &z)) goto exit; return_value = cmath_polar_impl(module, z); @@ -755,8 +720,7 @@ double r; double phi; - if (!PyArg_ParseTuple(args, - "dd:rect", + if (!PyArg_ParseTuple(args, "dd:rect", &r, &phi)) goto exit; return_value = cmath_rect_impl(module, r, phi); @@ -783,9 +747,7 @@ PyObject *return_value = NULL; Py_complex z; - if (!PyArg_Parse(arg, - "D:isfinite", - &z)) + if (!PyArg_Parse(arg, "D:isfinite", &z)) goto exit; return_value = cmath_isfinite_impl(module, z); @@ -811,9 +773,7 @@ PyObject *return_value = NULL; Py_complex z; - if (!PyArg_Parse(arg, - "D:isnan", - &z)) + if (!PyArg_Parse(arg, "D:isnan", &z)) goto exit; return_value = cmath_isnan_impl(module, z); @@ -839,13 +799,11 @@ PyObject *return_value = NULL; Py_complex z; - if (!PyArg_Parse(arg, - "D:isinf", - &z)) + if (!PyArg_Parse(arg, "D:isinf", &z)) goto exit; return_value = cmath_isinf_impl(module, z); exit: return return_value; } -/*[clinic end generated code: output=9143b8dcc8069024 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=274f59792cf4f418 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/fcntlmodule.c.h b/Modules/clinic/fcntlmodule.c.h --- a/Modules/clinic/fcntlmodule.c.h +++ b/Modules/clinic/fcntlmodule.c.h @@ -32,8 +32,7 @@ int code; PyObject *arg = NULL; - if (!PyArg_ParseTuple(args, - "O&i|O:fcntl", + if (!PyArg_ParseTuple(args, "O&i|O:fcntl", conv_descriptor, &fd, &code, &arg)) goto exit; return_value = fcntl_fcntl_impl(module, fd, code, arg); @@ -91,8 +90,7 @@ PyObject *ob_arg = NULL; int mutate_arg = 1; - if (!PyArg_ParseTuple(args, - "O&I|Op:ioctl", + if (!PyArg_ParseTuple(args, "O&I|Op:ioctl", conv_descriptor, &fd, &code, &ob_arg, &mutate_arg)) goto exit; return_value = fcntl_ioctl_impl(module, fd, code, ob_arg, mutate_arg); @@ -123,8 +121,7 @@ int fd; int code; - if (!PyArg_ParseTuple(args, - "O&i:flock", + if (!PyArg_ParseTuple(args, "O&i:flock", conv_descriptor, &fd, &code)) goto exit; return_value = fcntl_flock_impl(module, fd, code); @@ -177,8 +174,7 @@ PyObject *startobj = NULL; int whence = 0; - if (!PyArg_ParseTuple(args, - "O&i|OOi:lockf", + if (!PyArg_ParseTuple(args, "O&i|OOi:lockf", conv_descriptor, &fd, &code, &lenobj, &startobj, &whence)) goto exit; return_value = fcntl_lockf_impl(module, fd, code, lenobj, startobj, whence); @@ -186,4 +182,4 @@ exit: return return_value; } -/*[clinic end generated code: output=badaa968eb04410d input=a9049054013a1b77]*/ +/*[clinic end generated code: output=92963b631d00f0fe input=a9049054013a1b77]*/ diff --git a/Modules/clinic/grpmodule.c.h b/Modules/clinic/grpmodule.c.h --- a/Modules/clinic/grpmodule.c.h +++ b/Modules/clinic/grpmodule.c.h @@ -23,8 +23,7 @@ static char *_keywords[] = {"id", NULL}; PyObject *id; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "O:getgrgid", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O:getgrgid", _keywords, &id)) goto exit; return_value = grp_getgrgid_impl(module, id); @@ -54,8 +53,7 @@ static char *_keywords[] = {"name", NULL}; PyObject *name; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "U:getgrnam", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "U:getgrnam", _keywords, &name)) goto exit; return_value = grp_getgrnam_impl(module, name); @@ -84,4 +82,4 @@ { return grp_getgrall_impl(module); } -/*[clinic end generated code: output=4709a6ba40bb8df9 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=5191c25600afb1bd input=a9049054013a1b77]*/ diff --git a/Modules/clinic/md5module.c.h b/Modules/clinic/md5module.c.h --- a/Modules/clinic/md5module.c.h +++ b/Modules/clinic/md5module.c.h @@ -84,8 +84,7 @@ static char *_keywords[] = {"string", NULL}; PyObject *string = NULL; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "|O:md5", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O:md5", _keywords, &string)) goto exit; return_value = _md5_md5_impl(module, string); @@ -93,4 +92,4 @@ exit: return return_value; } -/*[clinic end generated code: output=f72618edfd35d984 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=0f803ded701aca54 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/posixmodule.c.h b/Modules/clinic/posixmodule.c.h --- a/Modules/clinic/posixmodule.c.h +++ b/Modules/clinic/posixmodule.c.h @@ -42,8 +42,7 @@ int dir_fd = DEFAULT_DIR_FD; int follow_symlinks = 1; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "O&|$O&p:stat", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&|$O&p:stat", _keywords, path_converter, &path, FSTATAT_DIR_FD_CONVERTER, &dir_fd, &follow_symlinks)) goto exit; return_value = os_stat_impl(module, &path, dir_fd, follow_symlinks); @@ -78,8 +77,7 @@ path_t path = PATH_T_INITIALIZE("lstat", "path", 0, 0); int dir_fd = DEFAULT_DIR_FD; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "O&|$O&:lstat", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&|$O&:lstat", _keywords, path_converter, &path, FSTATAT_DIR_FD_CONVERTER, &dir_fd)) goto exit; return_value = os_lstat_impl(module, &path, dir_fd); @@ -142,8 +140,7 @@ int follow_symlinks = 1; int _return_value; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "O&i|$O&pp:access", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&i|$O&pp:access", _keywords, path_converter, &path, &mode, FACCESSAT_DIR_FD_CONVERTER, &dir_fd, &effective_ids, &follow_symlinks)) goto exit; _return_value = os_access_impl(module, &path, mode, dir_fd, effective_ids, follow_symlinks); @@ -182,9 +179,7 @@ int fd; char *_return_value; - if (!PyArg_Parse(arg, - "i:ttyname", - &fd)) + if (!PyArg_Parse(arg, "i:ttyname", &fd)) goto exit; _return_value = os_ttyname_impl(module, fd); if (_return_value == NULL) @@ -242,8 +237,7 @@ static char *_keywords[] = {"path", NULL}; path_t path = PATH_T_INITIALIZE("chdir", "path", 0, PATH_HAVE_FCHDIR); - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "O&:chdir", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&:chdir", _keywords, path_converter, &path)) goto exit; return_value = os_chdir_impl(module, &path); @@ -279,8 +273,7 @@ static char *_keywords[] = {"fd", NULL}; int fd; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "O&:fchdir", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&:fchdir", _keywords, fildes_converter, &fd)) goto exit; return_value = os_fchdir_impl(module, fd); @@ -334,8 +327,7 @@ int dir_fd = DEFAULT_DIR_FD; int follow_symlinks = 1; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "O&i|$O&p:chmod", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&i|$O&p:chmod", _keywords, path_converter, &path, &mode, FCHMODAT_DIR_FD_CONVERTER, &dir_fd, &follow_symlinks)) goto exit; return_value = os_chmod_impl(module, &path, mode, dir_fd, follow_symlinks); @@ -371,8 +363,7 @@ int fd; int mode; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "ii:fchmod", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii:fchmod", _keywords, &fd, &mode)) goto exit; return_value = os_fchmod_impl(module, fd, mode); @@ -408,8 +399,7 @@ path_t path = PATH_T_INITIALIZE("lchmod", "path", 0, 0); int mode; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "O&i:lchmod", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&i:lchmod", _keywords, path_converter, &path, &mode)) goto exit; return_value = os_lchmod_impl(module, &path, mode); @@ -453,8 +443,7 @@ unsigned long flags; int follow_symlinks = 1; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "O&k|p:chflags", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&k|p:chflags", _keywords, path_converter, &path, &flags, &follow_symlinks)) goto exit; return_value = os_chflags_impl(module, &path, flags, follow_symlinks); @@ -493,8 +482,7 @@ path_t path = PATH_T_INITIALIZE("lchflags", "path", 0, 0); unsigned long flags; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "O&k:lchflags", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&k:lchflags", _keywords, path_converter, &path, &flags)) goto exit; return_value = os_lchflags_impl(module, &path, flags); @@ -529,8 +517,7 @@ static char *_keywords[] = {"path", NULL}; path_t path = PATH_T_INITIALIZE("chroot", "path", 0, 0); - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "O&:chroot", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&:chroot", _keywords, path_converter, &path)) goto exit; return_value = os_chroot_impl(module, &path); @@ -565,8 +552,7 @@ static char *_keywords[] = {"fd", NULL}; int fd; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "O&:fsync", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&:fsync", _keywords, fildes_converter, &fd)) goto exit; return_value = os_fsync_impl(module, fd); @@ -620,8 +606,7 @@ static char *_keywords[] = {"fd", NULL}; int fd; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "O&:fdatasync", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&:fdatasync", _keywords, fildes_converter, &fd)) goto exit; return_value = os_fdatasync_impl(module, fd); @@ -682,8 +667,7 @@ int dir_fd = DEFAULT_DIR_FD; int follow_symlinks = 1; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "O&O&O&|$O&p:chown", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&O&O&|$O&p:chown", _keywords, path_converter, &path, _Py_Uid_Converter, &uid, _Py_Gid_Converter, &gid, FCHOWNAT_DIR_FD_CONVERTER, &dir_fd, &follow_symlinks)) goto exit; return_value = os_chown_impl(module, &path, uid, gid, dir_fd, follow_symlinks); @@ -722,8 +706,7 @@ uid_t uid; gid_t gid; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "iO&O&:fchown", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "iO&O&:fchown", _keywords, &fd, _Py_Uid_Converter, &uid, _Py_Gid_Converter, &gid)) goto exit; return_value = os_fchown_impl(module, fd, uid, gid); @@ -760,8 +743,7 @@ uid_t uid; gid_t gid; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "O&O&O&:lchown", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&O&O&:lchown", _keywords, path_converter, &path, _Py_Uid_Converter, &uid, _Py_Gid_Converter, &gid)) goto exit; return_value = os_lchown_impl(module, &path, uid, gid); @@ -848,8 +830,7 @@ int dst_dir_fd = DEFAULT_DIR_FD; int follow_symlinks = 1; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "O&O&|$O&O&p:link", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&O&|$O&O&p:link", _keywords, path_converter, &src, path_converter, &dst, dir_fd_converter, &src_dir_fd, dir_fd_converter, &dst_dir_fd, &follow_symlinks)) goto exit; return_value = os_link_impl(module, &src, &dst, src_dir_fd, dst_dir_fd, follow_symlinks); @@ -895,8 +876,7 @@ static char *_keywords[] = {"path", NULL}; path_t path = PATH_T_INITIALIZE("listdir", "path", 1, PATH_HAVE_FDOPENDIR); - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "|O&:listdir", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O&:listdir", _keywords, path_converter, &path)) goto exit; return_value = os_listdir_impl(module, &path); @@ -928,9 +908,7 @@ PyObject *return_value = NULL; PyObject *path; - if (!PyArg_Parse(arg, - "U:_getfinalpathname", - &path)) + if (!PyArg_Parse(arg, "U:_getfinalpathname", &path)) goto exit; return_value = os__getfinalpathname_impl(module, path); @@ -961,8 +939,7 @@ static char *_keywords[] = {"path", NULL}; PyObject *path; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "U:_getvolumepathname", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "U:_getvolumepathname", _keywords, &path)) goto exit; return_value = os__getvolumepathname_impl(module, path); @@ -1001,8 +978,7 @@ int mode = 511; int dir_fd = DEFAULT_DIR_FD; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "O&|i$O&:mkdir", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&|i$O&:mkdir", _keywords, path_converter, &path, &mode, MKDIRAT_DIR_FD_CONVERTER, &dir_fd)) goto exit; return_value = os_mkdir_impl(module, &path, mode, dir_fd); @@ -1034,9 +1010,7 @@ PyObject *return_value = NULL; int increment; - if (!PyArg_Parse(arg, - "i:nice", - &increment)) + if (!PyArg_Parse(arg, "i:nice", &increment)) goto exit; return_value = os_nice_impl(module, increment); @@ -1068,8 +1042,7 @@ int which; int who; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "ii:getpriority", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii:getpriority", _keywords, &which, &who)) goto exit; return_value = os_getpriority_impl(module, which, who); @@ -1103,8 +1076,7 @@ int who; int priority; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "iii:setpriority", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "iii:setpriority", _keywords, &which, &who, &priority)) goto exit; return_value = os_setpriority_impl(module, which, who, priority); @@ -1144,8 +1116,7 @@ int src_dir_fd = DEFAULT_DIR_FD; int dst_dir_fd = DEFAULT_DIR_FD; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "O&O&|$O&O&:rename", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&O&|$O&O&:rename", _keywords, path_converter, &src, path_converter, &dst, dir_fd_converter, &src_dir_fd, dir_fd_converter, &dst_dir_fd)) goto exit; return_value = os_rename_impl(module, &src, &dst, src_dir_fd, dst_dir_fd); @@ -1188,8 +1159,7 @@ int src_dir_fd = DEFAULT_DIR_FD; int dst_dir_fd = DEFAULT_DIR_FD; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "O&O&|$O&O&:replace", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&O&|$O&O&:replace", _keywords, path_converter, &src, path_converter, &dst, dir_fd_converter, &src_dir_fd, dir_fd_converter, &dst_dir_fd)) goto exit; return_value = os_replace_impl(module, &src, &dst, src_dir_fd, dst_dir_fd); @@ -1228,8 +1198,7 @@ path_t path = PATH_T_INITIALIZE("rmdir", "path", 0, 0); int dir_fd = DEFAULT_DIR_FD; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "O&|$O&:rmdir", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&|$O&:rmdir", _keywords, path_converter, &path, UNLINKAT_DIR_FD_CONVERTER, &dir_fd)) goto exit; return_value = os_rmdir_impl(module, &path, dir_fd); @@ -1263,8 +1232,7 @@ Py_UNICODE *command; long _return_value; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "u:system", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "u:system", _keywords, &command)) goto exit; _return_value = os_system_impl(module, command); @@ -1300,8 +1268,7 @@ PyObject *command = NULL; long _return_value; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "O&:system", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&:system", _keywords, PyUnicode_FSConverter, &command)) goto exit; _return_value = os_system_impl(module, command); @@ -1336,9 +1303,7 @@ PyObject *return_value = NULL; int mask; - if (!PyArg_Parse(arg, - "i:umask", - &mask)) + if (!PyArg_Parse(arg, "i:umask", &mask)) goto exit; return_value = os_umask_impl(module, mask); @@ -1371,8 +1336,7 @@ path_t path = PATH_T_INITIALIZE("unlink", "path", 0, 0); int dir_fd = DEFAULT_DIR_FD; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "O&|$O&:unlink", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&|$O&:unlink", _keywords, path_converter, &path, UNLINKAT_DIR_FD_CONVERTER, &dir_fd)) goto exit; return_value = os_unlink_impl(module, &path, dir_fd); @@ -1409,8 +1373,7 @@ path_t path = PATH_T_INITIALIZE("remove", "path", 0, 0); int dir_fd = DEFAULT_DIR_FD; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "O&|$O&:remove", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&|$O&:remove", _keywords, path_converter, &path, UNLINKAT_DIR_FD_CONVERTER, &dir_fd)) goto exit; return_value = os_remove_impl(module, &path, dir_fd); @@ -1494,8 +1457,7 @@ int dir_fd = DEFAULT_DIR_FD; int follow_symlinks = 1; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "O&|O$OO&p:utime", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&|O$OO&p:utime", _keywords, path_converter, &path, ×, &ns, FUTIMENSAT_DIR_FD_CONVERTER, &dir_fd, &follow_symlinks)) goto exit; return_value = os_utime_impl(module, &path, times, ns, dir_fd, follow_symlinks); @@ -1526,8 +1488,7 @@ static char *_keywords[] = {"status", NULL}; int status; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "i:_exit", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i:_exit", _keywords, &status)) goto exit; return_value = os__exit_impl(module, status); @@ -1562,8 +1523,7 @@ PyObject *path = NULL; PyObject *argv; - if (!PyArg_ParseTuple(args, - "O&O:execv", + if (!PyArg_ParseTuple(args, "O&O:execv", PyUnicode_FSConverter, &path, &argv)) goto exit; return_value = os_execv_impl(module, path, argv); @@ -1608,8 +1568,7 @@ PyObject *argv; PyObject *env; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "O&OO:execve", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&OO:execve", _keywords, path_converter, &path, &argv, &env)) goto exit; return_value = os_execve_impl(module, &path, argv, env); @@ -1652,8 +1611,7 @@ PyObject *path = NULL; PyObject *argv; - if (!PyArg_ParseTuple(args, - "iO&O:spawnv", + if (!PyArg_ParseTuple(args, "iO&O:spawnv", &mode, PyUnicode_FSConverter, &path, &argv)) goto exit; return_value = os_spawnv_impl(module, mode, path, argv); @@ -1700,8 +1658,7 @@ PyObject *argv; PyObject *env; - if (!PyArg_ParseTuple(args, - "iO&OO:spawnve", + if (!PyArg_ParseTuple(args, "iO&OO:spawnve", &mode, PyUnicode_FSConverter, &path, &argv, &env)) goto exit; return_value = os_spawnve_impl(module, mode, path, argv, env); @@ -1784,8 +1741,7 @@ static char *_keywords[] = {"policy", NULL}; int policy; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "i:sched_get_priority_max", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i:sched_get_priority_max", _keywords, &policy)) goto exit; return_value = os_sched_get_priority_max_impl(module, policy); @@ -1817,8 +1773,7 @@ static char *_keywords[] = {"policy", NULL}; int policy; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "i:sched_get_priority_min", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i:sched_get_priority_min", _keywords, &policy)) goto exit; return_value = os_sched_get_priority_min_impl(module, policy); @@ -1851,9 +1806,7 @@ PyObject *return_value = NULL; pid_t pid; - if (!PyArg_Parse(arg, - "" _Py_PARSE_PID ":sched_getscheduler", - &pid)) + if (!PyArg_Parse(arg, "" _Py_PARSE_PID ":sched_getscheduler", &pid)) goto exit; return_value = os_sched_getscheduler_impl(module, pid); @@ -1884,8 +1837,7 @@ static char *_keywords[] = {"sched_priority", NULL}; PyObject *sched_priority; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "O:sched_param", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O:sched_param", _keywords, &sched_priority)) goto exit; return_value = os_sched_param_impl(type, sched_priority); @@ -1922,8 +1874,7 @@ int policy; struct sched_param param; - if (!PyArg_ParseTuple(args, - "" _Py_PARSE_PID "iO&:sched_setscheduler", + if (!PyArg_ParseTuple(args, "" _Py_PARSE_PID "iO&:sched_setscheduler", &pid, &policy, convert_sched_param, ¶m)) goto exit; return_value = os_sched_setscheduler_impl(module, pid, policy, ¶m); @@ -1957,9 +1908,7 @@ PyObject *return_value = NULL; pid_t pid; - if (!PyArg_Parse(arg, - "" _Py_PARSE_PID ":sched_getparam", - &pid)) + if (!PyArg_Parse(arg, "" _Py_PARSE_PID ":sched_getparam", &pid)) goto exit; return_value = os_sched_getparam_impl(module, pid); @@ -1994,8 +1943,7 @@ pid_t pid; struct sched_param param; - if (!PyArg_ParseTuple(args, - "" _Py_PARSE_PID "O&:sched_setparam", + if (!PyArg_ParseTuple(args, "" _Py_PARSE_PID "O&:sched_setparam", &pid, convert_sched_param, ¶m)) goto exit; return_value = os_sched_setparam_impl(module, pid, ¶m); @@ -2029,9 +1977,7 @@ pid_t pid; double _return_value; - if (!PyArg_Parse(arg, - "" _Py_PARSE_PID ":sched_rr_get_interval", - &pid)) + if (!PyArg_Parse(arg, "" _Py_PARSE_PID ":sched_rr_get_interval", &pid)) goto exit; _return_value = os_sched_rr_get_interval_impl(module, pid); if ((_return_value == -1.0) && PyErr_Occurred()) @@ -2089,8 +2035,7 @@ pid_t pid; PyObject *mask; - if (!PyArg_ParseTuple(args, - "" _Py_PARSE_PID "O:sched_setaffinity", + if (!PyArg_ParseTuple(args, "" _Py_PARSE_PID "O:sched_setaffinity", &pid, &mask)) goto exit; return_value = os_sched_setaffinity_impl(module, pid, mask); @@ -2123,9 +2068,7 @@ PyObject *return_value = NULL; pid_t pid; - if (!PyArg_Parse(arg, - "" _Py_PARSE_PID ":sched_getaffinity", - &pid)) + if (!PyArg_Parse(arg, "" _Py_PARSE_PID ":sched_getaffinity", &pid)) goto exit; return_value = os_sched_getaffinity_impl(module, pid); @@ -2314,8 +2257,7 @@ static char *_keywords[] = {"pid", NULL}; pid_t pid; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "" _Py_PARSE_PID ":getpgid", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "" _Py_PARSE_PID ":getpgid", _keywords, &pid)) goto exit; return_value = os_getpgid_impl(module, pid); @@ -2460,8 +2402,7 @@ pid_t pid; Py_ssize_t signal; - if (!PyArg_ParseTuple(args, - "" _Py_PARSE_PID "n:kill", + if (!PyArg_ParseTuple(args, "" _Py_PARSE_PID "n:kill", &pid, &signal)) goto exit; return_value = os_kill_impl(module, pid, signal); @@ -2493,8 +2434,7 @@ pid_t pgid; int signal; - if (!PyArg_ParseTuple(args, - "" _Py_PARSE_PID "i:killpg", + if (!PyArg_ParseTuple(args, "" _Py_PARSE_PID "i:killpg", &pgid, &signal)) goto exit; return_value = os_killpg_impl(module, pgid, signal); @@ -2525,9 +2465,7 @@ PyObject *return_value = NULL; int op; - if (!PyArg_Parse(arg, - "i:plock", - &op)) + if (!PyArg_Parse(arg, "i:plock", &op)) goto exit; return_value = os_plock_impl(module, op); @@ -2557,9 +2495,7 @@ PyObject *return_value = NULL; uid_t uid; - if (!PyArg_Parse(arg, - "O&:setuid", - _Py_Uid_Converter, &uid)) + if (!PyArg_Parse(arg, "O&:setuid", _Py_Uid_Converter, &uid)) goto exit; return_value = os_setuid_impl(module, uid); @@ -2589,9 +2525,7 @@ PyObject *return_value = NULL; uid_t euid; - if (!PyArg_Parse(arg, - "O&:seteuid", - _Py_Uid_Converter, &euid)) + if (!PyArg_Parse(arg, "O&:seteuid", _Py_Uid_Converter, &euid)) goto exit; return_value = os_seteuid_impl(module, euid); @@ -2621,9 +2555,7 @@ PyObject *return_value = NULL; gid_t egid; - if (!PyArg_Parse(arg, - "O&:setegid", - _Py_Gid_Converter, &egid)) + if (!PyArg_Parse(arg, "O&:setegid", _Py_Gid_Converter, &egid)) goto exit; return_value = os_setegid_impl(module, egid); @@ -2654,8 +2586,7 @@ uid_t ruid; uid_t euid; - if (!PyArg_ParseTuple(args, - "O&O&:setreuid", + if (!PyArg_ParseTuple(args, "O&O&:setreuid", _Py_Uid_Converter, &ruid, _Py_Uid_Converter, &euid)) goto exit; return_value = os_setreuid_impl(module, ruid, euid); @@ -2687,8 +2618,7 @@ gid_t rgid; gid_t egid; - if (!PyArg_ParseTuple(args, - "O&O&:setregid", + if (!PyArg_ParseTuple(args, "O&O&:setregid", _Py_Gid_Converter, &rgid, _Py_Gid_Converter, &egid)) goto exit; return_value = os_setregid_impl(module, rgid, egid); @@ -2719,9 +2649,7 @@ PyObject *return_value = NULL; gid_t gid; - if (!PyArg_Parse(arg, - "O&:setgid", - _Py_Gid_Converter, &gid)) + if (!PyArg_Parse(arg, "O&:setgid", _Py_Gid_Converter, &gid)) goto exit; return_value = os_setgid_impl(module, gid); @@ -2768,8 +2696,7 @@ static char *_keywords[] = {"options", NULL}; int options; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "i:wait3", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i:wait3", _keywords, &options)) goto exit; return_value = os_wait3_impl(module, options); @@ -2805,8 +2732,7 @@ pid_t pid; int options; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "" _Py_PARSE_PID "i:wait4", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "" _Py_PARSE_PID "i:wait4", _keywords, &pid, &options)) goto exit; return_value = os_wait4_impl(module, pid, options); @@ -2850,8 +2776,7 @@ id_t id; int options; - if (!PyArg_ParseTuple(args, - "i" _Py_PARSE_PID "i:waitid", + if (!PyArg_ParseTuple(args, "i" _Py_PARSE_PID "i:waitid", &idtype, &id, &options)) goto exit; return_value = os_waitid_impl(module, idtype, id, options); @@ -2888,8 +2813,7 @@ pid_t pid; int options; - if (!PyArg_ParseTuple(args, - "" _Py_PARSE_PID "i:waitpid", + if (!PyArg_ParseTuple(args, "" _Py_PARSE_PID "i:waitpid", &pid, &options)) goto exit; return_value = os_waitpid_impl(module, pid, options); @@ -2926,8 +2850,7 @@ Py_intptr_t pid; int options; - if (!PyArg_ParseTuple(args, - "" _Py_PARSE_INTPTR "i:waitpid", + if (!PyArg_ParseTuple(args, "" _Py_PARSE_INTPTR "i:waitpid", &pid, &options)) goto exit; return_value = os_waitpid_impl(module, pid, options); @@ -2998,8 +2921,7 @@ int target_is_directory = 0; int dir_fd = DEFAULT_DIR_FD; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "O&O&|p$O&:symlink", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&O&|p$O&:symlink", _keywords, path_converter, &src, path_converter, &dst, &target_is_directory, SYMLINKAT_DIR_FD_CONVERTER, &dir_fd)) goto exit; return_value = os_symlink_impl(module, &src, &dst, target_is_directory, dir_fd); @@ -3061,9 +2983,7 @@ PyObject *return_value = NULL; pid_t pid; - if (!PyArg_Parse(arg, - "" _Py_PARSE_PID ":getsid", - &pid)) + if (!PyArg_Parse(arg, "" _Py_PARSE_PID ":getsid", &pid)) goto exit; return_value = os_getsid_impl(module, pid); @@ -3116,8 +3036,7 @@ pid_t pid; pid_t pgrp; - if (!PyArg_ParseTuple(args, - "" _Py_PARSE_PID "" _Py_PARSE_PID ":setpgid", + if (!PyArg_ParseTuple(args, "" _Py_PARSE_PID "" _Py_PARSE_PID ":setpgid", &pid, &pgrp)) goto exit; return_value = os_setpgid_impl(module, pid, pgrp); @@ -3148,9 +3067,7 @@ PyObject *return_value = NULL; int fd; - if (!PyArg_Parse(arg, - "i:tcgetpgrp", - &fd)) + if (!PyArg_Parse(arg, "i:tcgetpgrp", &fd)) goto exit; return_value = os_tcgetpgrp_impl(module, fd); @@ -3181,8 +3098,7 @@ int fd; pid_t pgid; - if (!PyArg_ParseTuple(args, - "i" _Py_PARSE_PID ":tcsetpgrp", + if (!PyArg_ParseTuple(args, "i" _Py_PARSE_PID ":tcsetpgrp", &fd, &pgid)) goto exit; return_value = os_tcsetpgrp_impl(module, fd, pgid); @@ -3222,8 +3138,7 @@ int dir_fd = DEFAULT_DIR_FD; int _return_value; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "O&i|i$O&:open", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&i|i$O&:open", _keywords, path_converter, &path, &flags, &mode, OPENAT_DIR_FD_CONVERTER, &dir_fd)) goto exit; _return_value = os_open_impl(module, &path, flags, mode, dir_fd); @@ -3257,8 +3172,7 @@ static char *_keywords[] = {"fd", NULL}; int fd; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "i:close", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i:close", _keywords, &fd)) goto exit; return_value = os_close_impl(module, fd); @@ -3286,8 +3200,7 @@ int fd_low; int fd_high; - if (!PyArg_ParseTuple(args, - "ii:closerange", + if (!PyArg_ParseTuple(args, "ii:closerange", &fd_low, &fd_high)) goto exit; return_value = os_closerange_impl(module, fd_low, fd_high); @@ -3315,9 +3228,7 @@ int fd; int _return_value; - if (!PyArg_Parse(arg, - "i:dup", - &fd)) + if (!PyArg_Parse(arg, "i:dup", &fd)) goto exit; _return_value = os_dup_impl(module, fd); if ((_return_value == -1) && PyErr_Occurred()) @@ -3349,8 +3260,7 @@ int fd2; int inheritable = 1; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "ii|p:dup2", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii|p:dup2", _keywords, &fd, &fd2, &inheritable)) goto exit; return_value = os_dup2_impl(module, fd, fd2, inheritable); @@ -3388,8 +3298,7 @@ int command; Py_off_t length; - if (!PyArg_ParseTuple(args, - "iiO&:lockf", + if (!PyArg_ParseTuple(args, "iiO&:lockf", &fd, &command, Py_off_t_converter, &length)) goto exit; return_value = os_lockf_impl(module, fd, command, length); @@ -3424,8 +3333,7 @@ int how; Py_off_t _return_value; - if (!PyArg_ParseTuple(args, - "iO&i:lseek", + if (!PyArg_ParseTuple(args, "iO&i:lseek", &fd, Py_off_t_converter, &position, &how)) goto exit; _return_value = os_lseek_impl(module, fd, position, how); @@ -3456,8 +3364,7 @@ int fd; Py_ssize_t length; - if (!PyArg_ParseTuple(args, - "in:read", + if (!PyArg_ParseTuple(args, "in:read", &fd, &length)) goto exit; return_value = os_read_impl(module, fd, length); @@ -3496,8 +3403,7 @@ PyObject *buffers; Py_ssize_t _return_value; - if (!PyArg_ParseTuple(args, - "iO:readv", + if (!PyArg_ParseTuple(args, "iO:readv", &fd, &buffers)) goto exit; _return_value = os_readv_impl(module, fd, buffers); @@ -3536,8 +3442,7 @@ int length; Py_off_t offset; - if (!PyArg_ParseTuple(args, - "iiO&:pread", + if (!PyArg_ParseTuple(args, "iiO&:pread", &fd, &length, Py_off_t_converter, &offset)) goto exit; return_value = os_pread_impl(module, fd, length, offset); @@ -3568,8 +3473,7 @@ Py_buffer data = {NULL, NULL}; Py_ssize_t _return_value; - if (!PyArg_ParseTuple(args, - "iy*:write", + if (!PyArg_ParseTuple(args, "iy*:write", &fd, &data)) goto exit; _return_value = os_write_impl(module, fd, &data); @@ -3607,8 +3511,7 @@ static char *_keywords[] = {"fd", NULL}; int fd; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "i:fstat", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i:fstat", _keywords, &fd)) goto exit; return_value = os_fstat_impl(module, fd); @@ -3639,9 +3542,7 @@ int fd; int _return_value; - if (!PyArg_Parse(arg, - "i:isatty", - &fd)) + if (!PyArg_Parse(arg, "i:isatty", &fd)) goto exit; _return_value = os_isatty_impl(module, fd); if ((_return_value == -1) && PyErr_Occurred()) @@ -3703,9 +3604,7 @@ PyObject *return_value = NULL; int flags; - if (!PyArg_Parse(arg, - "i:pipe2", - &flags)) + if (!PyArg_Parse(arg, "i:pipe2", &flags)) goto exit; return_value = os_pipe2_impl(module, flags); @@ -3740,8 +3639,7 @@ PyObject *buffers; Py_ssize_t _return_value; - if (!PyArg_ParseTuple(args, - "iO:writev", + if (!PyArg_ParseTuple(args, "iO:writev", &fd, &buffers)) goto exit; _return_value = os_writev_impl(module, fd, buffers); @@ -3783,8 +3681,7 @@ Py_off_t offset; Py_ssize_t _return_value; - if (!PyArg_ParseTuple(args, - "iy*O&:pwrite", + if (!PyArg_ParseTuple(args, "iy*O&:pwrite", &fd, &buffer, Py_off_t_converter, &offset)) goto exit; _return_value = os_pwrite_impl(module, fd, &buffer, offset); @@ -3830,8 +3727,7 @@ int mode = 438; int dir_fd = DEFAULT_DIR_FD; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "O&|i$O&:mkfifo", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&|i$O&:mkfifo", _keywords, path_converter, &path, &mode, MKFIFOAT_DIR_FD_CONVERTER, &dir_fd)) goto exit; return_value = os_mkfifo_impl(module, &path, mode, dir_fd); @@ -3882,8 +3778,7 @@ dev_t device = 0; int dir_fd = DEFAULT_DIR_FD; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "O&|iO&$O&:mknod", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&|iO&$O&:mknod", _keywords, path_converter, &path, &mode, _Py_Dev_Converter, &device, MKNODAT_DIR_FD_CONVERTER, &dir_fd)) goto exit; return_value = os_mknod_impl(module, &path, mode, device, dir_fd); @@ -3918,9 +3813,7 @@ dev_t device; unsigned int _return_value; - if (!PyArg_Parse(arg, - "O&:major", - _Py_Dev_Converter, &device)) + if (!PyArg_Parse(arg, "O&:major", _Py_Dev_Converter, &device)) goto exit; _return_value = os_major_impl(module, device); if ((_return_value == (unsigned int)-1) && PyErr_Occurred()) @@ -3954,9 +3847,7 @@ dev_t device; unsigned int _return_value; - if (!PyArg_Parse(arg, - "O&:minor", - _Py_Dev_Converter, &device)) + if (!PyArg_Parse(arg, "O&:minor", _Py_Dev_Converter, &device)) goto exit; _return_value = os_minor_impl(module, device); if ((_return_value == (unsigned int)-1) && PyErr_Occurred()) @@ -3991,8 +3882,7 @@ int minor; dev_t _return_value; - if (!PyArg_ParseTuple(args, - "ii:makedev", + if (!PyArg_ParseTuple(args, "ii:makedev", &major, &minor)) goto exit; _return_value = os_makedev_impl(module, major, minor); @@ -4027,8 +3917,7 @@ int fd; Py_off_t length; - if (!PyArg_ParseTuple(args, - "iO&:ftruncate", + if (!PyArg_ParseTuple(args, "iO&:ftruncate", &fd, Py_off_t_converter, &length)) goto exit; return_value = os_ftruncate_impl(module, fd, length); @@ -4064,8 +3953,7 @@ path_t path = PATH_T_INITIALIZE("truncate", "path", 0, PATH_HAVE_FTRUNCATE); Py_off_t length; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "O&O&:truncate", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&O&:truncate", _keywords, path_converter, &path, Py_off_t_converter, &length)) goto exit; return_value = os_truncate_impl(module, &path, length); @@ -4105,8 +3993,7 @@ Py_off_t offset; Py_off_t length; - if (!PyArg_ParseTuple(args, - "iO&O&:posix_fallocate", + if (!PyArg_ParseTuple(args, "iO&O&:posix_fallocate", &fd, Py_off_t_converter, &offset, Py_off_t_converter, &length)) goto exit; return_value = os_posix_fallocate_impl(module, fd, offset, length); @@ -4149,8 +4036,7 @@ Py_off_t length; int advice; - if (!PyArg_ParseTuple(args, - "iO&O&i:posix_fadvise", + if (!PyArg_ParseTuple(args, "iO&O&i:posix_fadvise", &fd, Py_off_t_converter, &offset, Py_off_t_converter, &length, &advice)) goto exit; return_value = os_posix_fadvise_impl(module, fd, offset, length, advice); @@ -4182,8 +4068,7 @@ PyObject *name; PyObject *value; - if (!PyArg_ParseTuple(args, - "UU:putenv", + if (!PyArg_ParseTuple(args, "UU:putenv", &name, &value)) goto exit; return_value = os_putenv_impl(module, name, value); @@ -4215,8 +4100,7 @@ PyObject *name = NULL; PyObject *value = NULL; - if (!PyArg_ParseTuple(args, - "O&O&:putenv", + if (!PyArg_ParseTuple(args, "O&O&:putenv", PyUnicode_FSConverter, &name, PyUnicode_FSConverter, &value)) goto exit; return_value = os_putenv_impl(module, name, value); @@ -4252,9 +4136,7 @@ PyObject *return_value = NULL; PyObject *name = NULL; - if (!PyArg_Parse(arg, - "O&:unsetenv", - PyUnicode_FSConverter, &name)) + if (!PyArg_Parse(arg, "O&:unsetenv", PyUnicode_FSConverter, &name)) goto exit; return_value = os_unsetenv_impl(module, name); @@ -4285,9 +4167,7 @@ PyObject *return_value = NULL; int code; - if (!PyArg_Parse(arg, - "i:strerror", - &code)) + if (!PyArg_Parse(arg, "i:strerror", &code)) goto exit; return_value = os_strerror_impl(module, code); @@ -4316,9 +4196,7 @@ int status; int _return_value; - if (!PyArg_Parse(arg, - "i:WCOREDUMP", - &status)) + if (!PyArg_Parse(arg, "i:WCOREDUMP", &status)) goto exit; _return_value = os_WCOREDUMP_impl(module, status); if ((_return_value == -1) && PyErr_Occurred()) @@ -4356,8 +4234,7 @@ int status; int _return_value; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "i:WIFCONTINUED", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i:WIFCONTINUED", _keywords, &status)) goto exit; _return_value = os_WIFCONTINUED_impl(module, status); @@ -4393,8 +4270,7 @@ int status; int _return_value; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "i:WIFSTOPPED", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i:WIFSTOPPED", _keywords, &status)) goto exit; _return_value = os_WIFSTOPPED_impl(module, status); @@ -4430,8 +4306,7 @@ int status; int _return_value; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "i:WIFSIGNALED", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i:WIFSIGNALED", _keywords, &status)) goto exit; _return_value = os_WIFSIGNALED_impl(module, status); @@ -4467,8 +4342,7 @@ int status; int _return_value; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "i:WIFEXITED", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i:WIFEXITED", _keywords, &status)) goto exit; _return_value = os_WIFEXITED_impl(module, status); @@ -4504,8 +4378,7 @@ int status; int _return_value; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "i:WEXITSTATUS", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i:WEXITSTATUS", _keywords, &status)) goto exit; _return_value = os_WEXITSTATUS_impl(module, status); @@ -4541,8 +4414,7 @@ int status; int _return_value; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "i:WTERMSIG", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i:WTERMSIG", _keywords, &status)) goto exit; _return_value = os_WTERMSIG_impl(module, status); @@ -4578,8 +4450,7 @@ int status; int _return_value; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "i:WSTOPSIG", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i:WSTOPSIG", _keywords, &status)) goto exit; _return_value = os_WSTOPSIG_impl(module, status); @@ -4615,9 +4486,7 @@ PyObject *return_value = NULL; int fd; - if (!PyArg_Parse(arg, - "i:fstatvfs", - &fd)) + if (!PyArg_Parse(arg, "i:fstatvfs", &fd)) goto exit; return_value = os_fstatvfs_impl(module, fd); @@ -4652,8 +4521,7 @@ static char *_keywords[] = {"path", NULL}; path_t path = PATH_T_INITIALIZE("statvfs", "path", 0, PATH_HAVE_FSTATVFS); - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "O&:statvfs", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&:statvfs", _keywords, path_converter, &path)) goto exit; return_value = os_statvfs_impl(module, &path); @@ -4688,8 +4556,7 @@ static char *_keywords[] = {"path", NULL}; Py_UNICODE *path; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "u:_getdiskusage", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "u:_getdiskusage", _keywords, &path)) goto exit; return_value = os__getdiskusage_impl(module, path); @@ -4724,8 +4591,7 @@ int name; long _return_value; - if (!PyArg_ParseTuple(args, - "iO&:fpathconf", + if (!PyArg_ParseTuple(args, "iO&:fpathconf", &fd, conv_path_confname, &name)) goto exit; _return_value = os_fpathconf_impl(module, fd, name); @@ -4766,8 +4632,7 @@ int name; long _return_value; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "O&O&:pathconf", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&O&:pathconf", _keywords, path_converter, &path, conv_path_confname, &name)) goto exit; _return_value = os_pathconf_impl(module, &path, name); @@ -4804,9 +4669,7 @@ PyObject *return_value = NULL; int name; - if (!PyArg_Parse(arg, - "O&:confstr", - conv_confstr_confname, &name)) + if (!PyArg_Parse(arg, "O&:confstr", conv_confstr_confname, &name)) goto exit; return_value = os_confstr_impl(module, name); @@ -4837,9 +4700,7 @@ int name; long _return_value; - if (!PyArg_Parse(arg, - "O&:sysconf", - conv_sysconf_confname, &name)) + if (!PyArg_Parse(arg, "O&:sysconf", conv_sysconf_confname, &name)) goto exit; _return_value = os_sysconf_impl(module, name); if ((_return_value == -1) && PyErr_Occurred()) @@ -4921,8 +4782,7 @@ static char *_keywords[] = {"fd", NULL}; int fd; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "i:device_encoding", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i:device_encoding", _keywords, &fd)) goto exit; return_value = os_device_encoding_impl(module, fd); @@ -4953,8 +4813,7 @@ uid_t euid; uid_t suid; - if (!PyArg_ParseTuple(args, - "O&O&O&:setresuid", + if (!PyArg_ParseTuple(args, "O&O&O&:setresuid", _Py_Uid_Converter, &ruid, _Py_Uid_Converter, &euid, _Py_Uid_Converter, &suid)) goto exit; return_value = os_setresuid_impl(module, ruid, euid, suid); @@ -4987,8 +4846,7 @@ gid_t egid; gid_t sgid; - if (!PyArg_ParseTuple(args, - "O&O&O&:setresgid", + if (!PyArg_ParseTuple(args, "O&O&O&:setresgid", _Py_Gid_Converter, &rgid, _Py_Gid_Converter, &egid, _Py_Gid_Converter, &sgid)) goto exit; return_value = os_setresgid_impl(module, rgid, egid, sgid); @@ -5072,8 +4930,7 @@ path_t attribute = PATH_T_INITIALIZE("getxattr", "attribute", 0, 0); int follow_symlinks = 1; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "O&O&|$p:getxattr", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&O&|$p:getxattr", _keywords, path_converter, &path, path_converter, &attribute, &follow_symlinks)) goto exit; return_value = os_getxattr_impl(module, &path, &attribute, follow_symlinks); @@ -5121,8 +4978,7 @@ int flags = 0; int follow_symlinks = 1; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "O&O&y*|i$p:setxattr", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&O&y*|i$p:setxattr", _keywords, path_converter, &path, path_converter, &attribute, &value, &flags, &follow_symlinks)) goto exit; return_value = os_setxattr_impl(module, &path, &attribute, &value, flags, follow_symlinks); @@ -5170,8 +5026,7 @@ path_t attribute = PATH_T_INITIALIZE("removexattr", "attribute", 0, 0); int follow_symlinks = 1; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "O&O&|$p:removexattr", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&O&|$p:removexattr", _keywords, path_converter, &path, path_converter, &attribute, &follow_symlinks)) goto exit; return_value = os_removexattr_impl(module, &path, &attribute, follow_symlinks); @@ -5215,8 +5070,7 @@ path_t path = PATH_T_INITIALIZE("listxattr", "path", 1, 1); int follow_symlinks = 1; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "|O&$p:listxattr", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O&$p:listxattr", _keywords, path_converter, &path, &follow_symlinks)) goto exit; return_value = os_listxattr_impl(module, &path, follow_symlinks); @@ -5248,9 +5102,7 @@ PyObject *return_value = NULL; Py_ssize_t size; - if (!PyArg_Parse(arg, - "n:urandom", - &size)) + if (!PyArg_Parse(arg, "n:urandom", &size)) goto exit; return_value = os_urandom_impl(module, size); @@ -5295,9 +5147,7 @@ int fd; int _return_value; - if (!PyArg_Parse(arg, - "i:get_inheritable", - &fd)) + if (!PyArg_Parse(arg, "i:get_inheritable", &fd)) goto exit; _return_value = os_get_inheritable_impl(module, fd); if ((_return_value == -1) && PyErr_Occurred()) @@ -5327,8 +5177,7 @@ int fd; int inheritable; - if (!PyArg_ParseTuple(args, - "ii:set_inheritable", + if (!PyArg_ParseTuple(args, "ii:set_inheritable", &fd, &inheritable)) goto exit; return_value = os_set_inheritable_impl(module, fd, inheritable); @@ -5358,9 +5207,7 @@ Py_intptr_t handle; int _return_value; - if (!PyArg_Parse(arg, - "" _Py_PARSE_INTPTR ":get_handle_inheritable", - &handle)) + if (!PyArg_Parse(arg, "" _Py_PARSE_INTPTR ":get_handle_inheritable", &handle)) goto exit; _return_value = os_get_handle_inheritable_impl(module, handle); if ((_return_value == -1) && PyErr_Occurred()) @@ -5395,8 +5242,7 @@ Py_intptr_t handle; int inheritable; - if (!PyArg_ParseTuple(args, - "" _Py_PARSE_INTPTR "p:set_handle_inheritable", + if (!PyArg_ParseTuple(args, "" _Py_PARSE_INTPTR "p:set_handle_inheritable", &handle, &inheritable)) goto exit; return_value = os_set_handle_inheritable_impl(module, handle, inheritable); @@ -5870,4 +5716,4 @@ #ifndef OS_SET_HANDLE_INHERITABLE_METHODDEF #define OS_SET_HANDLE_INHERITABLE_METHODDEF #endif /* !defined(OS_SET_HANDLE_INHERITABLE_METHODDEF) */ -/*[clinic end generated code: output=0e3fb3bb5df25fea input=a9049054013a1b77]*/ +/*[clinic end generated code: output=bba73c13a01c09a0 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/pwdmodule.c.h b/Modules/clinic/pwdmodule.c.h --- a/Modules/clinic/pwdmodule.c.h +++ b/Modules/clinic/pwdmodule.c.h @@ -33,9 +33,7 @@ PyObject *return_value = NULL; PyObject *arg; - if (!PyArg_Parse(arg_, - "U:getpwnam", - &arg)) + if (!PyArg_Parse(arg_, "U:getpwnam", &arg)) goto exit; return_value = pwd_getpwnam_impl(module, arg); @@ -70,4 +68,4 @@ #ifndef PWD_GETPWALL_METHODDEF #define PWD_GETPWALL_METHODDEF #endif /* !defined(PWD_GETPWALL_METHODDEF) */ -/*[clinic end generated code: output=e7d5ac24b20e91ae input=a9049054013a1b77]*/ +/*[clinic end generated code: output=2ed0ecf34fd3f98f input=a9049054013a1b77]*/ diff --git a/Modules/clinic/pyexpat.c.h b/Modules/clinic/pyexpat.c.h --- a/Modules/clinic/pyexpat.c.h +++ b/Modules/clinic/pyexpat.c.h @@ -24,8 +24,7 @@ PyObject *data; int isFinal = 0; - if (!PyArg_ParseTuple(args, - "O|i:Parse", + if (!PyArg_ParseTuple(args, "O|i:Parse", &data, &isFinal)) goto exit; return_value = pyexpat_xmlparser_Parse_impl(self, data, isFinal); @@ -61,9 +60,7 @@ PyObject *return_value = NULL; const char *base; - if (!PyArg_Parse(arg, - "s:SetBase", - &base)) + if (!PyArg_Parse(arg, "s:SetBase", &base)) goto exit; return_value = pyexpat_xmlparser_SetBase_impl(self, base); @@ -131,8 +128,7 @@ const char *context; const char *encoding = NULL; - if (!PyArg_ParseTuple(args, - "z|s:ExternalEntityParserCreate", + if (!PyArg_ParseTuple(args, "z|s:ExternalEntityParserCreate", &context, &encoding)) goto exit; return_value = pyexpat_xmlparser_ExternalEntityParserCreate_impl(self, context, encoding); @@ -164,9 +160,7 @@ PyObject *return_value = NULL; int flag; - if (!PyArg_Parse(arg, - "i:SetParamEntityParsing", - &flag)) + if (!PyArg_Parse(arg, "i:SetParamEntityParsing", &flag)) goto exit; return_value = pyexpat_xmlparser_SetParamEntityParsing_impl(self, flag); @@ -198,8 +192,7 @@ PyObject *return_value = NULL; int flag = 1; - if (!PyArg_ParseTuple(args, - "|p:UseForeignDTD", + if (!PyArg_ParseTuple(args, "|p:UseForeignDTD", &flag)) goto exit; return_value = pyexpat_xmlparser_UseForeignDTD_impl(self, flag); @@ -250,8 +243,7 @@ const char *namespace_separator = NULL; PyObject *intern = NULL; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "|zzO:ParserCreate", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|zzO:ParserCreate", _keywords, &encoding, &namespace_separator, &intern)) goto exit; return_value = pyexpat_ParserCreate_impl(module, encoding, namespace_separator, intern); @@ -278,9 +270,7 @@ PyObject *return_value = NULL; long code; - if (!PyArg_Parse(arg, - "l:ErrorString", - &code)) + if (!PyArg_Parse(arg, "l:ErrorString", &code)) goto exit; return_value = pyexpat_ErrorString_impl(module, code); @@ -291,4 +281,4 @@ #ifndef PYEXPAT_XMLPARSER_USEFOREIGNDTD_METHODDEF #define PYEXPAT_XMLPARSER_USEFOREIGNDTD_METHODDEF #endif /* !defined(PYEXPAT_XMLPARSER_USEFOREIGNDTD_METHODDEF) */ -/*[clinic end generated code: output=abdf05a21dae98c7 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=958c0faa1b855fc7 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/sha1module.c.h b/Modules/clinic/sha1module.c.h --- a/Modules/clinic/sha1module.c.h +++ b/Modules/clinic/sha1module.c.h @@ -84,8 +84,7 @@ static char *_keywords[] = {"string", NULL}; PyObject *string = NULL; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "|O:sha1", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O:sha1", _keywords, &string)) goto exit; return_value = _sha1_sha1_impl(module, string); @@ -93,4 +92,4 @@ exit: return return_value; } -/*[clinic end generated code: output=b2890b9ca964b217 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=be19102f3120490a input=a9049054013a1b77]*/ diff --git a/Modules/clinic/sha256module.c.h b/Modules/clinic/sha256module.c.h --- a/Modules/clinic/sha256module.c.h +++ b/Modules/clinic/sha256module.c.h @@ -84,8 +84,7 @@ static char *_keywords[] = {"string", NULL}; PyObject *string = NULL; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "|O:sha256", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O:sha256", _keywords, &string)) goto exit; return_value = _sha256_sha256_impl(module, string); @@ -113,8 +112,7 @@ static char *_keywords[] = {"string", NULL}; PyObject *string = NULL; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "|O:sha224", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O:sha224", _keywords, &string)) goto exit; return_value = _sha256_sha224_impl(module, string); @@ -122,4 +120,4 @@ exit: return return_value; } -/*[clinic end generated code: output=8a0520371b097358 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=354cedf3b632c7b2 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/sha512module.c.h b/Modules/clinic/sha512module.c.h --- a/Modules/clinic/sha512module.c.h +++ b/Modules/clinic/sha512module.c.h @@ -102,8 +102,7 @@ static char *_keywords[] = {"string", NULL}; PyObject *string = NULL; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "|O:sha512", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O:sha512", _keywords, &string)) goto exit; return_value = _sha512_sha512_impl(module, string); @@ -135,8 +134,7 @@ static char *_keywords[] = {"string", NULL}; PyObject *string = NULL; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "|O:sha384", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O:sha384", _keywords, &string)) goto exit; return_value = _sha512_sha384_impl(module, string); @@ -170,4 +168,4 @@ #ifndef _SHA512_SHA384_METHODDEF #define _SHA512_SHA384_METHODDEF #endif /* !defined(_SHA512_SHA384_METHODDEF) */ -/*[clinic end generated code: output=de7bda19fde49310 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=1c7d385731fee7c0 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/spwdmodule.c.h b/Modules/clinic/spwdmodule.c.h --- a/Modules/clinic/spwdmodule.c.h +++ b/Modules/clinic/spwdmodule.c.h @@ -24,9 +24,7 @@ PyObject *return_value = NULL; PyObject *arg; - if (!PyArg_Parse(arg_, - "U:getspnam", - &arg)) + if (!PyArg_Parse(arg_, "U:getspnam", &arg)) goto exit; return_value = spwd_getspnam_impl(module, arg); @@ -67,4 +65,4 @@ #ifndef SPWD_GETSPALL_METHODDEF #define SPWD_GETSPALL_METHODDEF #endif /* !defined(SPWD_GETSPALL_METHODDEF) */ -/*[clinic end generated code: output=67a4f8c47008f28f input=a9049054013a1b77]*/ +/*[clinic end generated code: output=6c178830413f7763 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/unicodedata.c.h b/Modules/clinic/unicodedata.c.h --- a/Modules/clinic/unicodedata.c.h +++ b/Modules/clinic/unicodedata.c.h @@ -26,8 +26,7 @@ int chr; PyObject *default_value = NULL; - if (!PyArg_ParseTuple(args, - "C|O:decimal", + if (!PyArg_ParseTuple(args, "C|O:decimal", &chr, &default_value)) goto exit; return_value = unicodedata_UCD_decimal_impl(self, chr, default_value); @@ -59,8 +58,7 @@ int chr; PyObject *default_value = NULL; - if (!PyArg_ParseTuple(args, - "C|O:digit", + if (!PyArg_ParseTuple(args, "C|O:digit", &chr, &default_value)) goto exit; return_value = unicodedata_UCD_digit_impl(self, chr, default_value); @@ -93,8 +91,7 @@ int chr; PyObject *default_value = NULL; - if (!PyArg_ParseTuple(args, - "C|O:numeric", + if (!PyArg_ParseTuple(args, "C|O:numeric", &chr, &default_value)) goto exit; return_value = unicodedata_UCD_numeric_impl(self, chr, default_value); @@ -121,9 +118,7 @@ PyObject *return_value = NULL; int chr; - if (!PyArg_Parse(arg, - "C:category", - &chr)) + if (!PyArg_Parse(arg, "C:category", &chr)) goto exit; return_value = unicodedata_UCD_category_impl(self, chr); @@ -151,9 +146,7 @@ PyObject *return_value = NULL; int chr; - if (!PyArg_Parse(arg, - "C:bidirectional", - &chr)) + if (!PyArg_Parse(arg, "C:bidirectional", &chr)) goto exit; return_value = unicodedata_UCD_bidirectional_impl(self, chr); @@ -182,9 +175,7 @@ int chr; int _return_value; - if (!PyArg_Parse(arg, - "C:combining", - &chr)) + if (!PyArg_Parse(arg, "C:combining", &chr)) goto exit; _return_value = unicodedata_UCD_combining_impl(self, chr); if ((_return_value == -1) && PyErr_Occurred()) @@ -217,9 +208,7 @@ int chr; int _return_value; - if (!PyArg_Parse(arg, - "C:mirrored", - &chr)) + if (!PyArg_Parse(arg, "C:mirrored", &chr)) goto exit; _return_value = unicodedata_UCD_mirrored_impl(self, chr); if ((_return_value == -1) && PyErr_Occurred()) @@ -248,9 +237,7 @@ PyObject *return_value = NULL; int chr; - if (!PyArg_Parse(arg, - "C:east_asian_width", - &chr)) + if (!PyArg_Parse(arg, "C:east_asian_width", &chr)) goto exit; return_value = unicodedata_UCD_east_asian_width_impl(self, chr); @@ -278,9 +265,7 @@ PyObject *return_value = NULL; int chr; - if (!PyArg_Parse(arg, - "C:decomposition", - &chr)) + if (!PyArg_Parse(arg, "C:decomposition", &chr)) goto exit; return_value = unicodedata_UCD_decomposition_impl(self, chr); @@ -310,8 +295,7 @@ const char *form; PyObject *input; - if (!PyArg_ParseTuple(args, - "sO!:normalize", + if (!PyArg_ParseTuple(args, "sO!:normalize", &form, &PyUnicode_Type, &input)) goto exit; return_value = unicodedata_UCD_normalize_impl(self, form, input); @@ -342,8 +326,7 @@ int chr; PyObject *default_value = NULL; - if (!PyArg_ParseTuple(args, - "C|O:name", + if (!PyArg_ParseTuple(args, "C|O:name", &chr, &default_value)) goto exit; return_value = unicodedata_UCD_name_impl(self, chr, default_value); @@ -375,13 +358,11 @@ const char *name; Py_ssize_clean_t name_length; - if (!PyArg_Parse(arg, - "s#:lookup", - &name, &name_length)) + if (!PyArg_Parse(arg, "s#:lookup", &name, &name_length)) goto exit; return_value = unicodedata_UCD_lookup_impl(self, name, name_length); exit: return return_value; } -/*[clinic end generated code: output=1f04e31ae703ffed input=a9049054013a1b77]*/ +/*[clinic end generated code: output=4f8da33c6bc6efc9 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/zlibmodule.c.h b/Modules/clinic/zlibmodule.c.h --- a/Modules/clinic/zlibmodule.c.h +++ b/Modules/clinic/zlibmodule.c.h @@ -26,8 +26,7 @@ Py_buffer bytes = {NULL, NULL}; int level = Z_DEFAULT_COMPRESSION; - if (!PyArg_ParseTuple(args, - "y*|i:compress", + if (!PyArg_ParseTuple(args, "y*|i:compress", &bytes, &level)) goto exit; return_value = zlib_compress_impl(module, &bytes, level); @@ -68,8 +67,7 @@ int wbits = MAX_WBITS; unsigned int bufsize = DEF_BUF_SIZE; - if (!PyArg_ParseTuple(args, - "y*|iO&:decompress", + if (!PyArg_ParseTuple(args, "y*|iO&:decompress", &data, &wbits, uint_converter, &bufsize)) goto exit; return_value = zlib_decompress_impl(module, &data, wbits, bufsize); @@ -127,8 +125,7 @@ int strategy = Z_DEFAULT_STRATEGY; Py_buffer zdict = {NULL, NULL}; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "|iiiiiy*:compressobj", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iiiiiy*:compressobj", _keywords, &level, &method, &wbits, &memLevel, &strategy, &zdict)) goto exit; return_value = zlib_compressobj_impl(module, level, method, wbits, memLevel, strategy, &zdict); @@ -167,8 +164,7 @@ int wbits = MAX_WBITS; PyObject *zdict = NULL; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "|iO:decompressobj", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iO:decompressobj", _keywords, &wbits, &zdict)) goto exit; return_value = zlib_decompressobj_impl(module, wbits, zdict); @@ -202,9 +198,7 @@ PyObject *return_value = NULL; Py_buffer data = {NULL, NULL}; - if (!PyArg_Parse(arg, - "y*:compress", - &data)) + if (!PyArg_Parse(arg, "y*:compress", &data)) goto exit; return_value = zlib_Compress_compress_impl(self, &data); @@ -247,8 +241,7 @@ Py_buffer data = {NULL, NULL}; unsigned int max_length = 0; - if (!PyArg_ParseTuple(args, - "y*|O&:decompress", + if (!PyArg_ParseTuple(args, "y*|O&:decompress", &data, uint_converter, &max_length)) goto exit; return_value = zlib_Decompress_decompress_impl(self, &data, max_length); @@ -285,8 +278,7 @@ PyObject *return_value = NULL; int mode = Z_FINISH; - if (!PyArg_ParseTuple(args, - "|i:flush", + if (!PyArg_ParseTuple(args, "|i:flush", &mode)) goto exit; return_value = zlib_Compress_flush_impl(self, mode); @@ -360,8 +352,7 @@ PyObject *return_value = NULL; unsigned int length = DEF_BUF_SIZE; - if (!PyArg_ParseTuple(args, - "|O&:flush", + if (!PyArg_ParseTuple(args, "|O&:flush", uint_converter, &length)) goto exit; return_value = zlib_Decompress_flush_impl(self, length); @@ -394,8 +385,7 @@ Py_buffer data = {NULL, NULL}; unsigned int value = 1; - if (!PyArg_ParseTuple(args, - "y*|I:adler32", + if (!PyArg_ParseTuple(args, "y*|I:adler32", &data, &value)) goto exit; return_value = zlib_adler32_impl(module, &data, value); @@ -432,8 +422,7 @@ Py_buffer data = {NULL, NULL}; unsigned int value = 0; - if (!PyArg_ParseTuple(args, - "y*|I:crc32", + if (!PyArg_ParseTuple(args, "y*|I:crc32", &data, &value)) goto exit; return_value = zlib_crc32_impl(module, &data, value); @@ -449,4 +438,4 @@ #ifndef ZLIB_COMPRESS_COPY_METHODDEF #define ZLIB_COMPRESS_COPY_METHODDEF #endif /* !defined(ZLIB_COMPRESS_COPY_METHODDEF) */ -/*[clinic end generated code: output=6cdeb624bebfe11f input=a9049054013a1b77]*/ +/*[clinic end generated code: output=56ed1147bbbb4788 input=a9049054013a1b77]*/ diff --git a/Objects/clinic/bytearrayobject.c.h b/Objects/clinic/bytearrayobject.c.h --- a/Objects/clinic/bytearrayobject.c.h +++ b/Objects/clinic/bytearrayobject.c.h @@ -107,8 +107,7 @@ Py_buffer frm = {NULL, NULL}; Py_buffer to = {NULL, NULL}; - if (!PyArg_ParseTuple(args, - "y*y*:maketrans", + if (!PyArg_ParseTuple(args, "y*y*:maketrans", &frm, &to)) goto exit; return_value = bytearray_maketrans_impl(&frm, &to); @@ -152,8 +151,7 @@ Py_buffer new = {NULL, NULL}; Py_ssize_t count = -1; - if (!PyArg_ParseTuple(args, - "y*y*|n:replace", + if (!PyArg_ParseTuple(args, "y*y*|n:replace", &old, &new, &count)) goto exit; return_value = bytearray_replace_impl(self, &old, &new, count); @@ -198,8 +196,7 @@ PyObject *sep = Py_None; Py_ssize_t maxsplit = -1; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "|On:split", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|On:split", _keywords, &sep, &maxsplit)) goto exit; return_value = bytearray_split_impl(self, sep, maxsplit); @@ -271,8 +268,7 @@ PyObject *sep = Py_None; Py_ssize_t maxsplit = -1; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "|On:rsplit", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|On:rsplit", _keywords, &sep, &maxsplit)) goto exit; return_value = bytearray_rsplit_impl(self, sep, maxsplit); @@ -323,8 +319,7 @@ Py_ssize_t index; int item; - if (!PyArg_ParseTuple(args, - "nO&:insert", + if (!PyArg_ParseTuple(args, "nO&:insert", &index, _getbytevalue, &item)) goto exit; return_value = bytearray_insert_impl(self, index, item); @@ -354,9 +349,7 @@ PyObject *return_value = NULL; int item; - if (!PyArg_Parse(arg, - "O&:append", - _getbytevalue, &item)) + if (!PyArg_Parse(arg, "O&:append", _getbytevalue, &item)) goto exit; return_value = bytearray_append_impl(self, item); @@ -400,8 +393,7 @@ PyObject *return_value = NULL; Py_ssize_t index = -1; - if (!PyArg_ParseTuple(args, - "|n:pop", + if (!PyArg_ParseTuple(args, "|n:pop", &index)) goto exit; return_value = bytearray_pop_impl(self, index); @@ -431,9 +423,7 @@ PyObject *return_value = NULL; int value; - if (!PyArg_Parse(arg, - "O&:remove", - _getbytevalue, &value)) + if (!PyArg_Parse(arg, "O&:remove", _getbytevalue, &value)) goto exit; return_value = bytearray_remove_impl(self, value); @@ -561,8 +551,7 @@ const char *encoding = NULL; const char *errors = NULL; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "|ss:decode", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|ss:decode", _keywords, &encoding, &errors)) goto exit; return_value = bytearray_decode_impl(self, encoding, errors); @@ -606,8 +595,7 @@ static char *_keywords[] = {"keepends", NULL}; int keepends = 0; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "|i:splitlines", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:splitlines", _keywords, &keepends)) goto exit; return_value = bytearray_splitlines_impl(self, keepends); @@ -637,9 +625,7 @@ PyObject *return_value = NULL; PyObject *string; - if (!PyArg_Parse(arg, - "U:fromhex", - &string)) + if (!PyArg_Parse(arg, "U:fromhex", &string)) goto exit; return_value = bytearray_fromhex_impl((PyObject*)cls, string); @@ -683,8 +669,7 @@ PyObject *return_value = NULL; int proto = 0; - if (!PyArg_ParseTuple(args, - "|i:__reduce_ex__", + if (!PyArg_ParseTuple(args, "|i:__reduce_ex__", &proto)) goto exit; return_value = bytearray_reduce_ex_impl(self, proto); @@ -710,4 +695,4 @@ { return bytearray_sizeof_impl(self); } -/*[clinic end generated code: output=2a698741a4f14047 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=966c15ff22c5e243 input=a9049054013a1b77]*/ diff --git a/Objects/clinic/bytesobject.c.h b/Objects/clinic/bytesobject.c.h --- a/Objects/clinic/bytesobject.c.h +++ b/Objects/clinic/bytesobject.c.h @@ -30,8 +30,7 @@ PyObject *sep = Py_None; Py_ssize_t maxsplit = -1; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "|On:split", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|On:split", _keywords, &sep, &maxsplit)) goto exit; return_value = bytes_split_impl(self, sep, maxsplit); @@ -65,9 +64,7 @@ PyObject *return_value = NULL; Py_buffer sep = {NULL, NULL}; - if (!PyArg_Parse(arg, - "y*:partition", - &sep)) + if (!PyArg_Parse(arg, "y*:partition", &sep)) goto exit; return_value = bytes_partition_impl(self, &sep); @@ -104,9 +101,7 @@ PyObject *return_value = NULL; Py_buffer sep = {NULL, NULL}; - if (!PyArg_Parse(arg, - "y*:rpartition", - &sep)) + if (!PyArg_Parse(arg, "y*:rpartition", &sep)) goto exit; return_value = bytes_rpartition_impl(self, &sep); @@ -148,8 +143,7 @@ PyObject *sep = Py_None; Py_ssize_t maxsplit = -1; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "|On:rsplit", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|On:rsplit", _keywords, &sep, &maxsplit)) goto exit; return_value = bytes_rsplit_impl(self, sep, maxsplit); @@ -332,8 +326,7 @@ Py_buffer frm = {NULL, NULL}; Py_buffer to = {NULL, NULL}; - if (!PyArg_ParseTuple(args, - "y*y*:maketrans", + if (!PyArg_ParseTuple(args, "y*y*:maketrans", &frm, &to)) goto exit; return_value = bytes_maketrans_impl(&frm, &to); @@ -377,8 +370,7 @@ Py_buffer new = {NULL, NULL}; Py_ssize_t count = -1; - if (!PyArg_ParseTuple(args, - "y*y*|n:replace", + if (!PyArg_ParseTuple(args, "y*y*|n:replace", &old, &new, &count)) goto exit; return_value = bytes_replace_impl(self, &old, &new, count); @@ -424,8 +416,7 @@ const char *encoding = NULL; const char *errors = NULL; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "|ss:decode", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|ss:decode", _keywords, &encoding, &errors)) goto exit; return_value = bytes_decode_impl(self, encoding, errors); @@ -456,8 +447,7 @@ static char *_keywords[] = {"keepends", NULL}; int keepends = 0; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "|i:splitlines", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:splitlines", _keywords, &keepends)) goto exit; return_value = bytes_splitlines_impl(self, keepends); @@ -487,13 +477,11 @@ PyObject *return_value = NULL; PyObject *string; - if (!PyArg_Parse(arg, - "U:fromhex", - &string)) + if (!PyArg_Parse(arg, "U:fromhex", &string)) goto exit; return_value = bytes_fromhex_impl(type, string); exit: return return_value; } -/*[clinic end generated code: output=deaf886e15270679 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=bd0ce8f25d7e18f4 input=a9049054013a1b77]*/ diff --git a/Objects/clinic/unicodeobject.c.h b/Objects/clinic/unicodeobject.c.h --- a/Objects/clinic/unicodeobject.c.h +++ b/Objects/clinic/unicodeobject.c.h @@ -30,8 +30,7 @@ PyObject *y = NULL; PyObject *z = NULL; - if (!PyArg_ParseTuple(args, - "O|UU:maketrans", + if (!PyArg_ParseTuple(args, "O|UU:maketrans", &x, &y, &z)) goto exit; return_value = unicode_maketrans_impl(x, y, z); @@ -39,4 +38,4 @@ exit: return return_value; } -/*[clinic end generated code: output=4670413843c53055 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=94affdff5b2daff5 input=a9049054013a1b77]*/ diff --git a/Python/clinic/bltinmodule.c.h b/Python/clinic/bltinmodule.c.h --- a/Python/clinic/bltinmodule.c.h +++ b/Python/clinic/bltinmodule.c.h @@ -93,8 +93,7 @@ PyObject *value; PyObject *format_spec = NULL; - if (!PyArg_ParseTuple(args, - "O|U:format", + if (!PyArg_ParseTuple(args, "O|U:format", &value, &format_spec)) goto exit; return_value = builtin_format_impl(module, value, format_spec); @@ -121,9 +120,7 @@ PyObject *return_value = NULL; int i; - if (!PyArg_Parse(arg, - "i:chr", - &i)) + if (!PyArg_Parse(arg, "i:chr", &i)) goto exit; return_value = builtin_chr_impl(module, i); @@ -169,8 +166,7 @@ int dont_inherit = 0; int optimize = -1; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "OO&s|iii:compile", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO&s|iii:compile", _keywords, &source, PyUnicode_FSDecoder, &filename, &mode, &flags, &dont_inherit, &optimize)) goto exit; return_value = builtin_compile_impl(module, source, filename, mode, flags, dont_inherit, optimize); @@ -664,4 +660,4 @@ exit: return return_value; } -/*[clinic end generated code: output=b308ab64aa4d4ff8 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=9b34d1ca57effad8 input=a9049054013a1b77]*/ diff --git a/Python/clinic/import.c.h b/Python/clinic/import.c.h --- a/Python/clinic/import.c.h +++ b/Python/clinic/import.c.h @@ -88,8 +88,7 @@ PyCodeObject *code; PyObject *path; - if (!PyArg_ParseTuple(args, - "O!U:_fix_co_filename", + if (!PyArg_ParseTuple(args, "O!U:_fix_co_filename", &PyCode_Type, &code, &path)) goto exit; return_value = _imp__fix_co_filename_impl(module, code, path); @@ -134,9 +133,7 @@ PyObject *return_value = NULL; PyObject *name; - if (!PyArg_Parse(arg, - "U:init_builtin", - &name)) + if (!PyArg_Parse(arg, "U:init_builtin", &name)) goto exit; return_value = _imp_init_builtin_impl(module, name); @@ -162,9 +159,7 @@ PyObject *return_value = NULL; PyObject *name; - if (!PyArg_Parse(arg, - "U:init_frozen", - &name)) + if (!PyArg_Parse(arg, "U:init_frozen", &name)) goto exit; return_value = _imp_init_frozen_impl(module, name); @@ -190,9 +185,7 @@ PyObject *return_value = NULL; PyObject *name; - if (!PyArg_Parse(arg, - "U:get_frozen_object", - &name)) + if (!PyArg_Parse(arg, "U:get_frozen_object", &name)) goto exit; return_value = _imp_get_frozen_object_impl(module, name); @@ -218,9 +211,7 @@ PyObject *return_value = NULL; PyObject *name; - if (!PyArg_Parse(arg, - "U:is_frozen_package", - &name)) + if (!PyArg_Parse(arg, "U:is_frozen_package", &name)) goto exit; return_value = _imp_is_frozen_package_impl(module, name); @@ -246,9 +237,7 @@ PyObject *return_value = NULL; PyObject *name; - if (!PyArg_Parse(arg, - "U:is_builtin", - &name)) + if (!PyArg_Parse(arg, "U:is_builtin", &name)) goto exit; return_value = _imp_is_builtin_impl(module, name); @@ -274,9 +263,7 @@ PyObject *return_value = NULL; PyObject *name; - if (!PyArg_Parse(arg, - "U:is_frozen", - &name)) + if (!PyArg_Parse(arg, "U:is_frozen", &name)) goto exit; return_value = _imp_is_frozen_impl(module, name); @@ -307,8 +294,7 @@ PyObject *path; PyObject *file = NULL; - if (!PyArg_ParseTuple(args, - "UO&|O:load_dynamic", + if (!PyArg_ParseTuple(args, "UO&|O:load_dynamic", &name, PyUnicode_FSDecoder, &path, &file)) goto exit; return_value = _imp_load_dynamic_impl(module, name, path, file); @@ -322,4 +308,4 @@ #ifndef _IMP_LOAD_DYNAMIC_METHODDEF #define _IMP_LOAD_DYNAMIC_METHODDEF #endif /* !defined(_IMP_LOAD_DYNAMIC_METHODDEF) */ -/*[clinic end generated code: output=b64fe33fe76591cf input=a9049054013a1b77]*/ +/*[clinic end generated code: output=6d75cece35863874 input=a9049054013a1b77]*/ diff --git a/Tools/clinic/clinic.py b/Tools/clinic/clinic.py --- a/Tools/clinic/clinic.py +++ b/Tools/clinic/clinic.py @@ -786,9 +786,7 @@ """ % argname) parser_definition = parser_body(parser_prototype, normalize_snippet(""" - if (!PyArg_Parse(%s, - "{format_units}:{name}", - {parse_arguments})) + if (!PyArg_Parse(%s, "{format_units}:{name}", {parse_arguments})) goto exit; """ % argname, indent=4)) @@ -825,8 +823,7 @@ parser_prototype = parser_prototype_varargs parser_definition = parser_body(parser_prototype, normalize_snippet(""" - if (!PyArg_ParseTuple(args, - "{format_units}:{name}", + if (!PyArg_ParseTuple(args, "{format_units}:{name}", {parse_arguments})) goto exit; """, indent=4)) @@ -838,14 +835,12 @@ parser_prototype = parser_prototype_keyword body = normalize_snippet(""" - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "{format_units}:{name}", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "{format_units}:{name}", _keywords, {parse_arguments})) goto exit; """, indent=4) parser_definition = parser_body(parser_prototype, normalize_snippet(""" - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "{format_units}:{name}", _keywords, + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "{format_units}:{name}", _keywords, {parse_arguments})) goto exit; """, indent=4)) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Apr 24 09:05:19 2015 From: python-checkins at python.org (nick.coghlan) Date: Fri, 24 Apr 2015 07:05:19 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_PEP_394=3A_fix_typo_reported_?= =?utf-8?q?by_Jan_Pokorn=C3=BD?= Message-ID: <20150424070447.18885.63814@psf.io> https://hg.python.org/peps/rev/836dfe5c8ed4 changeset: 5799:836dfe5c8ed4 user: Nick Coghlan date: Fri Apr 24 17:04:39 2015 +1000 summary: PEP 394: fix typo reported by Jan Pokorn? files: pep-0394.txt | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/pep-0394.txt b/pep-0394.txt --- a/pep-0394.txt +++ b/pep-0394.txt @@ -149,7 +149,7 @@ sysadmins to install many very similar versions of the interpreter. * When the ``pythonX.X`` binaries are provided by a distribution, the ``python2`` and ``python3`` commands should refer to one of those files - rather being provided as a separate binary file. + rather than being provided as a separate binary file. * It is suggested that even distribution-specific packages follow the ``python2``/``python3`` convention, even in code that is not intended to operate on other distributions. This will reduce problems if the -- Repository URL: https://hg.python.org/peps From solipsis at pitrou.net Fri Apr 24 10:39:34 2015 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Fri, 24 Apr 2015 08:39:34 +0000 Subject: [Python-checkins] Daily reference leaks (151cab576cab): sum=6 Message-ID: <20150424083934.6585.65288@psf.io> results for 151cab576cab on branch "default" -------------------------------------------- test_asyncio leaked [0, 0, 3] memory blocks, sum=3 test_functools leaked [0, 0, 3] memory blocks, sum=3 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogBiogZA', '--timeout', '7200'] From python-checkins at python.org Fri Apr 24 18:03:00 2015 From: python-checkins at python.org (benjamin.peterson) Date: Fri, 24 Apr 2015 16:03:00 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?b?KTogbWVyZ2UgMy40ICgjMjQwNDkp?= Message-ID: <20150424160257.6591.4757@psf.io> https://hg.python.org/cpython/rev/5c0247a6f98a changeset: 95792:5c0247a6f98a parent: 95790:151cab576cab parent: 95791:135d5a3e415b user: Benjamin Peterson date: Fri Apr 24 12:02:53 2015 -0400 summary: merge 3.4 (#24049) files: Doc/reference/executionmodel.rst | 4 -- Python/symtable.c | 31 -------------------- 2 files changed, 0 insertions(+), 35 deletions(-) diff --git a/Doc/reference/executionmodel.rst b/Doc/reference/executionmodel.rst --- a/Doc/reference/executionmodel.rst +++ b/Doc/reference/executionmodel.rst @@ -161,10 +161,6 @@ If a variable is referenced in an enclosing scope, it is illegal to delete the name. An error will be reported at compile time. -If the wild card form of import --- ``import *`` --- is used in a function and -the function contains or is a nested block with free variables, the compiler -will raise a :exc:`SyntaxError`. - .. XXX from * also invalid with relative imports (at least currently) The :func:`eval` and :func:`exec` functions do not have access to the full diff --git a/Python/symtable.c b/Python/symtable.c --- a/Python/symtable.c +++ b/Python/symtable.c @@ -583,35 +583,6 @@ return 1; } -/* Check for illegal statements in unoptimized namespaces */ -static int -check_unoptimized(const PySTEntryObject* ste) { - const char* trailer; - - if (ste->ste_type != FunctionBlock || !ste->ste_unoptimized - || !(ste->ste_free || ste->ste_child_free)) - return 1; - - trailer = (ste->ste_child_free ? - "contains a nested function with free variables" : - "is a nested function"); - - switch (ste->ste_unoptimized) { - case OPT_TOPLEVEL: /* import * at top-level is fine */ - return 1; - case OPT_IMPORT_STAR: - PyErr_Format(PyExc_SyntaxError, - "import * is not allowed in function '%U' because it %s", - ste->ste_name, trailer); - break; - } - - PyErr_SyntaxLocationObject(ste->ste_table->st_filename, - ste->ste_opt_lineno, - ste->ste_opt_col_offset); - return 0; -} - /* Enter the final scope information into the ste_symbols dict. * * All arguments are dicts. Modifies symbols, others are read-only. @@ -854,8 +825,6 @@ if (!update_symbols(ste->ste_symbols, scopes, bound, newfree, ste->ste_type == ClassBlock)) goto error; - if (!check_unoptimized(ste)) - goto error; temp = PyNumber_InPlaceOr(free, newfree); if (!temp) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Fri Apr 24 18:03:00 2015 From: python-checkins at python.org (benjamin.peterson) Date: Fri, 24 Apr 2015 16:03:00 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E4=29=3A_remove_dead_*-?= =?utf-8?q?import_checking_code_=28closes_=2324049=29?= Message-ID: <20150424160257.6585.22438@psf.io> https://hg.python.org/cpython/rev/135d5a3e415b changeset: 95791:135d5a3e415b branch: 3.4 parent: 95788:80485b8e43cd user: Benjamin Peterson date: Fri Apr 24 12:02:29 2015 -0400 summary: remove dead *-import checking code (closes #24049) files: Doc/reference/executionmodel.rst | 4 -- Python/symtable.c | 31 -------------------- 2 files changed, 0 insertions(+), 35 deletions(-) diff --git a/Doc/reference/executionmodel.rst b/Doc/reference/executionmodel.rst --- a/Doc/reference/executionmodel.rst +++ b/Doc/reference/executionmodel.rst @@ -161,10 +161,6 @@ If a variable is referenced in an enclosing scope, it is illegal to delete the name. An error will be reported at compile time. -If the wild card form of import --- ``import *`` --- is used in a function and -the function contains or is a nested block with free variables, the compiler -will raise a :exc:`SyntaxError`. - .. XXX from * also invalid with relative imports (at least currently) The :func:`eval` and :func:`exec` functions do not have access to the full diff --git a/Python/symtable.c b/Python/symtable.c --- a/Python/symtable.c +++ b/Python/symtable.c @@ -583,35 +583,6 @@ return 1; } -/* Check for illegal statements in unoptimized namespaces */ -static int -check_unoptimized(const PySTEntryObject* ste) { - const char* trailer; - - if (ste->ste_type != FunctionBlock || !ste->ste_unoptimized - || !(ste->ste_free || ste->ste_child_free)) - return 1; - - trailer = (ste->ste_child_free ? - "contains a nested function with free variables" : - "is a nested function"); - - switch (ste->ste_unoptimized) { - case OPT_TOPLEVEL: /* import * at top-level is fine */ - return 1; - case OPT_IMPORT_STAR: - PyErr_Format(PyExc_SyntaxError, - "import * is not allowed in function '%U' because it %s", - ste->ste_name, trailer); - break; - } - - PyErr_SyntaxLocationObject(ste->ste_table->st_filename, - ste->ste_opt_lineno, - ste->ste_opt_col_offset); - return 0; -} - /* Enter the final scope information into the ste_symbols dict. * * All arguments are dicts. Modifies symbols, others are read-only. @@ -854,8 +825,6 @@ if (!update_symbols(ste->ste_symbols, scopes, bound, newfree, ste->ste_type == ClassBlock)) goto error; - if (!check_unoptimized(ste)) - goto error; temp = PyNumber_InPlaceOr(free, newfree); if (!temp) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Apr 25 00:14:46 2015 From: python-checkins at python.org (guido.van.rossum) Date: Fri, 24 Apr 2015 22:14:46 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_Mark_PEP_3152_=28codef/cocall?= =?utf-8?q?=29_as_rejected=2E?= Message-ID: <20150424221446.30744.47829@psf.io> https://hg.python.org/peps/rev/ce6d0b081d10 changeset: 5800:ce6d0b081d10 user: Guido van Rossum date: Fri Apr 24 15:14:39 2015 -0700 summary: Mark PEP 3152 (codef/cocall) as rejected. files: pep-3152.txt | 7 ++++++- 1 files changed, 6 insertions(+), 1 deletions(-) diff --git a/pep-3152.txt b/pep-3152.txt --- a/pep-3152.txt +++ b/pep-3152.txt @@ -3,7 +3,7 @@ Version: $Revision$ Last-Modified: $Date$ Author: Gregory Ewing -Status: Draft +Status: Rejected Type: Standards Track Content-Type: text/x-rst Created: 13-Feb-2009 @@ -26,6 +26,11 @@ it. However, it would be possible to define and implement cofunctions independently of PEP 380 if so desired. +Rejection +--------- + +See https://mail.python.org/pipermail/python-dev/2015-April/139503.html + Specification ============= -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Sat Apr 25 00:23:54 2015 From: python-checkins at python.org (victor.stinner) Date: Fri, 24 Apr 2015 22:23:54 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzkyNDY6?= =?utf-8?q?_On_POSIX=2C_os=2Egetcwd=28=29_now_supports_paths_longer_than_1?= =?utf-8?q?025_bytes?= Message-ID: <20150424222354.98620.46143@psf.io> https://hg.python.org/cpython/rev/abf1f3ae4fa8 changeset: 95793:abf1f3ae4fa8 branch: 3.4 parent: 95791:135d5a3e415b user: Victor Stinner date: Sat Apr 25 00:16:10 2015 +0200 summary: Issue #9246: On POSIX, os.getcwd() now supports paths longer than 1025 bytes Patch written by William Orr. files: Misc/NEWS | 3 ++ Modules/posixmodule.c | 36 ++++++++++++++++++++++++------ 2 files changed, 31 insertions(+), 8 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -34,6 +34,9 @@ Library ------- +- Issue #9246: On POSIX, os.getcwd() now supports paths longer than 1025 bytes. + Patch written by William Orr. + - Issue #23008: Fixed resolving attributes with boolean value is False in pydoc. - Fix asyncio issue 235: LifoQueue and PriorityQueue's put didn't diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -3418,12 +3418,15 @@ static PyObject * posix_getcwd(int use_bytes) { - char buf[1026]; - char *res; + char *buf, *tmpbuf; + char *cwd; + const size_t chunk = 1024; + size_t buflen = 0; + PyObject *obj; #ifdef MS_WINDOWS if (!use_bytes) { - wchar_t wbuf[1026]; + wchar_t wbuf[MAXPATHLEN]; wchar_t *wbuf2 = wbuf; PyObject *resobj; DWORD len; @@ -3457,14 +3460,31 @@ return NULL; #endif + buf = cwd = NULL; Py_BEGIN_ALLOW_THREADS - res = getcwd(buf, sizeof buf); + do { + buflen += chunk; + tmpbuf = PyMem_RawRealloc(buf, buflen); + if (tmpbuf == NULL) + break; + + buf = tmpbuf; + cwd = getcwd(buf, buflen); + } while (cwd == NULL && errno == ERANGE); Py_END_ALLOW_THREADS - if (res == NULL) - return posix_error(); + + if (cwd == NULL) { + PyMem_RawFree(buf); + return posix_error(); + } + if (use_bytes) - return PyBytes_FromStringAndSize(buf, strlen(buf)); - return PyUnicode_DecodeFSDefault(buf); + obj = PyBytes_FromStringAndSize(buf, strlen(buf)); + else + obj = PyUnicode_DecodeFSDefault(buf); + PyMem_RawFree(buf); + + return obj; } PyDoc_STRVAR(posix_getcwd__doc__, -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Apr 25 00:23:54 2015 From: python-checkins at python.org (victor.stinner) Date: Fri, 24 Apr 2015 22:23:54 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?b?KTogKE1lcmdlIDMuNCkgSXNzdWUgIzkyNDY6IE9uIFBPU0lYLCBvcy5nZXRj?= =?utf-8?q?wd=28=29_now_supports_paths_longer_than?= Message-ID: <20150424222354.27916.54369@psf.io> https://hg.python.org/cpython/rev/b871ace5c58f changeset: 95794:b871ace5c58f parent: 95792:5c0247a6f98a parent: 95793:abf1f3ae4fa8 user: Victor Stinner date: Sat Apr 25 00:21:52 2015 +0200 summary: (Merge 3.4) Issue #9246: On POSIX, os.getcwd() now supports paths longer than 1025 bytes. Patch written by William Orr. files: Misc/NEWS | 5 +++- Modules/posixmodule.c | 36 ++++++++++++++++++++++++------ 2 files changed, 32 insertions(+), 9 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -15,6 +15,9 @@ Library ------- +- Issue #9246: On POSIX, os.getcwd() now supports paths longer than 1025 bytes. + Patch written by William Orr. + - Issue #17445: add difflib.diff_bytes() to support comparison of byte strings (fixes a regression from Python 2). @@ -33,7 +36,7 @@ - Issue #23728: binascii.crc_hqx() could return an integer outside of the range 0-0xffff for empty data. -- Issue #23887: urllib.error.HTTPError now has a proper repr() representation. +- Issue #23887: urllib.error.HTTPError now has a proper repr() representation. Patch by Berker Peksag. Documentation diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -3267,12 +3267,15 @@ static PyObject * posix_getcwd(int use_bytes) { - char buf[1026]; - char *res; + char *buf, *tmpbuf; + char *cwd; + const size_t chunk = 1024; + size_t buflen = 0; + PyObject *obj; #ifdef MS_WINDOWS if (!use_bytes) { - wchar_t wbuf[1026]; + wchar_t wbuf[MAXPATHLEN]; wchar_t *wbuf2 = wbuf; PyObject *resobj; DWORD len; @@ -3306,14 +3309,31 @@ return NULL; #endif + buf = cwd = NULL; Py_BEGIN_ALLOW_THREADS - res = getcwd(buf, sizeof buf); + do { + buflen += chunk; + tmpbuf = PyMem_RawRealloc(buf, buflen); + if (tmpbuf == NULL) + break; + + buf = tmpbuf; + cwd = getcwd(buf, buflen); + } while (cwd == NULL && errno == ERANGE); Py_END_ALLOW_THREADS - if (res == NULL) + + if (cwd == NULL) { + PyMem_RawFree(buf); return posix_error(); + } + if (use_bytes) - return PyBytes_FromStringAndSize(buf, strlen(buf)); - return PyUnicode_DecodeFSDefault(buf); + obj = PyBytes_FromStringAndSize(buf, strlen(buf)); + else + obj = PyUnicode_DecodeFSDefault(buf); + PyMem_RawFree(buf); + + return obj; } @@ -8873,7 +8893,7 @@ fd = _wopen(path->wide, _O_WRONLY | _O_BINARY | _O_NOINHERIT); else fd = _open(path->narrow, _O_WRONLY | _O_BINARY | _O_NOINHERIT); - if (fd < 0) + if (fd < 0) result = -1; else { result = _chsize_s(fd, length); -- Repository URL: https://hg.python.org/cpython From solipsis at pitrou.net Sat Apr 25 10:40:37 2015 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Sat, 25 Apr 2015 08:40:37 +0000 Subject: [Python-checkins] Daily reference leaks (b871ace5c58f): sum=5 Message-ID: <20150425084037.102145.54296@psf.io> results for b871ace5c58f on branch "default" -------------------------------------------- test_collections leaked [2, 0, 0] references, sum=2 test_functools leaked [0, 0, 3] memory blocks, sum=3 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogxcbYSA', '--timeout', '7200'] From python-checkins at python.org Sat Apr 25 20:16:30 2015 From: python-checkins at python.org (benjamin.peterson) Date: Sat, 25 Apr 2015 18:16:30 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_fix_relative_l?= =?utf-8?q?ink_=28closes_=2324057=29?= Message-ID: <20150425181630.6603.18088@psf.io> https://hg.python.org/cpython/rev/4e48a55cffb8 changeset: 95796:4e48a55cffb8 branch: 2.7 parent: 95781:0ac30526c208 user: Benjamin Peterson date: Sat Apr 25 14:15:16 2015 -0400 summary: fix relative link (closes #24057) files: Doc/library/datetime.rst | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/library/datetime.rst b/Doc/library/datetime.rst --- a/Doc/library/datetime.rst +++ b/Doc/library/datetime.rst @@ -619,8 +619,8 @@ .. _datetime-datetime: -:class:`datetime` Objects -------------------------- +:class:`.datetime` Objects +-------------------------- A :class:`.datetime` object is a single object containing all the information from a :class:`date` object and a :class:`.time` object. Like a :class:`date` -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Apr 25 20:16:30 2015 From: python-checkins at python.org (benjamin.peterson) Date: Sat, 25 Apr 2015 18:16:30 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E4=29=3A_fix_relative_l?= =?utf-8?q?ink_=28closes_=2324057=29?= Message-ID: <20150425181630.6599.27594@psf.io> https://hg.python.org/cpython/rev/875787fee2cc changeset: 95795:875787fee2cc branch: 3.4 parent: 95793:abf1f3ae4fa8 user: Benjamin Peterson date: Sat Apr 25 14:15:16 2015 -0400 summary: fix relative link (closes #24057) files: Doc/library/datetime.rst | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/library/datetime.rst b/Doc/library/datetime.rst --- a/Doc/library/datetime.rst +++ b/Doc/library/datetime.rst @@ -664,8 +664,8 @@ .. _datetime-datetime: -:class:`datetime` Objects -------------------------- +:class:`.datetime` Objects +-------------------------- A :class:`.datetime` object is a single object containing all the information from a :class:`date` object and a :class:`.time` object. Like a :class:`date` -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sat Apr 25 20:16:31 2015 From: python-checkins at python.org (benjamin.peterson) Date: Sat, 25 Apr 2015 18:16:31 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?b?KTogbWVyZ2UgMy40ICgjMjQwNTcp?= Message-ID: <20150425181630.102135.72853@psf.io> https://hg.python.org/cpython/rev/0351b0cb31d6 changeset: 95797:0351b0cb31d6 parent: 95794:b871ace5c58f parent: 95795:875787fee2cc user: Benjamin Peterson date: Sat Apr 25 14:16:25 2015 -0400 summary: merge 3.4 (#24057) files: Doc/library/datetime.rst | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/library/datetime.rst b/Doc/library/datetime.rst --- a/Doc/library/datetime.rst +++ b/Doc/library/datetime.rst @@ -666,8 +666,8 @@ .. _datetime-datetime: -:class:`datetime` Objects -------------------------- +:class:`.datetime` Objects +-------------------------- A :class:`.datetime` object is a single object containing all the information from a :class:`date` object and a :class:`.time` object. Like a :class:`date` -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Apr 26 01:22:36 2015 From: python-checkins at python.org (gregory.p.smith) Date: Sat, 25 Apr 2015 23:22:36 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Implements_issue_=239951?= =?utf-8?q?=3A_Adds_a_hex=28=29_method_to_bytes=2C_bytearray=2C_=26_memory?= =?utf-8?q?view=2E?= Message-ID: <20150425232235.101104.49583@psf.io> https://hg.python.org/cpython/rev/c9f1630cf2b1 changeset: 95798:c9f1630cf2b1 user: Gregory P. Smith date: Sat Apr 25 23:22:26 2015 +0000 summary: Implements issue #9951: Adds a hex() method to bytes, bytearray, & memoryview. Also updates a few internal implementations of the same thing to use the new built-in code. Contributed by Arnon Yaari. files: Doc/library/stdtypes.rst | 37 ++++++++++++++++++ Doc/whatsnew/3.5.rst | 3 + Lib/test/test_bytes.py | 8 +++ Lib/test/test_doctest.py | 2 +- Makefile.pre.in | 2 + Misc/ACKS | 1 + Misc/NEWS | 1 + Modules/sha1module.c | 23 +---------- Modules/sha256module.c | 23 +---------- Modules/sha512module.c | 23 +---------- Objects/bytearrayobject.c | 15 +++++++ Objects/bytesobject.c | 16 +++++++ Objects/memoryobject.c | 14 ++++++ PCbuild/pythoncore.vcxproj | 2 + PCbuild/pythoncore.vcxproj.filters | 6 ++ 15 files changed, 112 insertions(+), 64 deletions(-) diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst --- a/Doc/library/stdtypes.rst +++ b/Doc/library/stdtypes.rst @@ -2289,6 +2289,19 @@ >>> bytes.fromhex('2Ef0 F1f2 ') b'.\xf0\xf1\xf2' +A reverse conversion function exists to transform a bytes object into its +hexadecimal representation. + +.. method:: bytes.hex() + + Return a string object containing two hexadecimal digits for each + byte in the instance. + + >>> b'\xf0\xf1\xf2'.hex() + 'f0f1f2' + + .. versionadded:: 3.5 + Since bytes objects are sequences of integers (akin to a tuple), for a bytes object *b*, ``b[0]`` will be an integer, while ``b[0:1]`` will be a bytes object of length 1. (This contrasts with text strings, where both indexing @@ -2344,6 +2357,19 @@ >>> bytearray.fromhex('2Ef0 F1f2 ') bytearray(b'.\xf0\xf1\xf2') +A reverse conversion function exists to transform a bytearray object into its +hexadecimal representation. + +.. method:: bytearray.hex() + + Return a string object containing two hexadecimal digits for each + byte in the instance. + + >>> bytearray(b'\xf0\xf1\xf2').hex() + 'f0f1f2' + + .. versionadded:: 3.5 + Since bytearray objects are sequences of integers (akin to a list), for a bytearray object *b*, ``b[0]`` will be an integer, while ``b[0:1]`` will be a bytearray object of length 1. (This contrasts with text strings, where @@ -3458,6 +3484,17 @@ supports all format strings, including those that are not in :mod:`struct` module syntax. + .. method:: hex() + + Return a string object containing two hexadecimal digits for each + byte in the buffer. :: + + >>> m = memoryview(b"abc") + >>> m.hex() + '616263' + + .. versionadded:: 3.5 + .. method:: tolist() Return the data in the buffer as a list of elements. :: diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -80,6 +80,9 @@ * ``bytes % args``, ``bytearray % args``: :pep:`461` - Adding ``%`` formatting to bytes and bytearray +* ``b'\xf0\x9f\x90\x8d'.hex()``, ``bytearray(b'\xf0\x9f\x90\x8d').hex()``, + ``memoryview(b'\xf0\x9f\x90\x8d').hex()``: :issue:`9951` - A ``hex`` method + has been added to bytes, bytearray, and memoryview. Implementation improvements: 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 @@ -301,6 +301,14 @@ self.assertRaises(ValueError, self.type2test.fromhex, '\x00') self.assertRaises(ValueError, self.type2test.fromhex, '12 \x00 34') + def test_hex(self): + self.assertRaises(TypeError, self.type2test.hex) + self.assertRaises(TypeError, self.type2test.hex, 1) + self.assertEquals(self.type2test(b"").hex(), "") + self.assertEquals(bytearray([0x1a, 0x2b, 0x30]).hex(), '1a2b30') + self.assertEquals(self.type2test(b"\x1a\x2b\x30").hex(), '1a2b30') + self.assertEquals(memoryview(b"\x1a\x2b\x30").hex(), '1a2b30') + def test_join(self): self.assertEqual(self.type2test(b"").join([]), b"") self.assertEqual(self.type2test(b"").join([b""]), b"") diff --git a/Lib/test/test_doctest.py b/Lib/test/test_doctest.py --- a/Lib/test/test_doctest.py +++ b/Lib/test/test_doctest.py @@ -659,7 +659,7 @@ >>> import builtins >>> tests = doctest.DocTestFinder().find(builtins) - >>> 790 < len(tests) < 800 # approximate number of objects with docstrings + >>> 790 < len(tests) < 810 # approximate number of objects with docstrings True >>> real_tests = [t for t in tests if len(t.examples) > 0] >>> len(real_tests) # objects that actually have doctests diff --git a/Makefile.pre.in b/Makefile.pre.in --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -402,6 +402,7 @@ Python/getopt.o \ Python/pystrcmp.o \ Python/pystrtod.o \ + Python/pystrhex.o \ Python/dtoa.o \ Python/formatter_unicode.o \ Python/fileutils.o \ @@ -919,6 +920,7 @@ $(srcdir)/Include/pystate.h \ $(srcdir)/Include/pystrcmp.h \ $(srcdir)/Include/pystrtod.h \ + $(srcdir)/Include/pystrhex.h \ $(srcdir)/Include/pythonrun.h \ $(srcdir)/Include/pythread.h \ $(srcdir)/Include/pytime.h \ diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -1547,6 +1547,7 @@ Robert Xiao Florent Xicluna Hirokazu Yamamoto +Arnon Yaari Ka-Ping Yee Jason Yeo EungJun Yi diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -11,6 +11,7 @@ ----------------- - Issue #24022: Fix tokenizer crash when processing undecodable source code. +- Issue #9951: Added a hex() method to bytes, bytearray, and memoryview. Library ------- diff --git a/Modules/sha1module.c b/Modules/sha1module.c --- a/Modules/sha1module.c +++ b/Modules/sha1module.c @@ -18,6 +18,7 @@ #include "Python.h" #include "hashlib.h" +#include "pystrhex.h" /*[clinic input] module _sha1 @@ -364,32 +365,12 @@ { unsigned char digest[SHA1_DIGESTSIZE]; struct sha1_state temp; - PyObject *retval; - Py_UCS1 *hex_digest; - int i, j; /* Get the raw (binary) digest value */ temp = self->hash_state; sha1_done(&temp, digest); - /* Create a new string */ - retval = PyUnicode_New(SHA1_DIGESTSIZE * 2, 127); - if (!retval) - return NULL; - hex_digest = PyUnicode_1BYTE_DATA(retval); - - /* Make hex version of the digest */ - for(i=j=0; i> 4) & 0xf; - hex_digest[j++] = Py_hexdigits[c]; - c = (digest[i] & 0xf); - hex_digest[j++] = Py_hexdigits[c]; - } -#ifdef Py_DEBUG - assert(_PyUnicode_CheckConsistency(retval, 1)); -#endif - return retval; + return _Py_strhex((const char *)digest, SHA1_DIGESTSIZE); } /*[clinic input] diff --git a/Modules/sha256module.c b/Modules/sha256module.c --- a/Modules/sha256module.c +++ b/Modules/sha256module.c @@ -19,6 +19,7 @@ #include "Python.h" #include "structmember.h" #include "hashlib.h" +#include "pystrhex.h" /*[clinic input] module _sha256 @@ -454,32 +455,12 @@ { unsigned char digest[SHA_DIGESTSIZE]; SHAobject temp; - PyObject *retval; - Py_UCS1 *hex_digest; - int i, j; /* Get the raw (binary) digest value */ SHAcopy(self, &temp); sha_final(digest, &temp); - /* Create a new string */ - retval = PyUnicode_New(self->digestsize * 2, 127); - if (!retval) - return NULL; - hex_digest = PyUnicode_1BYTE_DATA(retval); - - /* Make hex version of the digest */ - for(i=j=0; idigestsize; i++) { - unsigned char c; - c = (digest[i] >> 4) & 0xf; - hex_digest[j++] = Py_hexdigits[c]; - c = (digest[i] & 0xf); - hex_digest[j++] = Py_hexdigits[c]; - } -#ifdef Py_DEBUG - assert(_PyUnicode_CheckConsistency(retval, 1)); -#endif - return retval; + return _Py_strhex((const char *)digest, self->digestsize); } /*[clinic input] diff --git a/Modules/sha512module.c b/Modules/sha512module.c --- a/Modules/sha512module.c +++ b/Modules/sha512module.c @@ -19,6 +19,7 @@ #include "Python.h" #include "structmember.h" #include "hashlib.h" +#include "pystrhex.h" /*[clinic input] module _sha512 @@ -521,32 +522,12 @@ { unsigned char digest[SHA_DIGESTSIZE]; SHAobject temp; - PyObject *retval; - Py_UCS1 *hex_digest; - int i, j; /* Get the raw (binary) digest value */ SHAcopy(self, &temp); sha512_final(digest, &temp); - /* Create a new string */ - retval = PyUnicode_New(self->digestsize * 2, 127); - if (!retval) - return NULL; - hex_digest = PyUnicode_1BYTE_DATA(retval); - - /* Make hex version of the digest */ - for (i=j=0; idigestsize; i++) { - unsigned char c; - c = (digest[i] >> 4) & 0xf; - hex_digest[j++] = Py_hexdigits[c]; - c = (digest[i] & 0xf); - hex_digest[j++] = Py_hexdigits[c]; - } -#ifdef Py_DEBUG - assert(_PyUnicode_CheckConsistency(retval, 1)); -#endif - return retval; + return _Py_strhex((const char *)digest, self->digestsize); } /*[clinic input] diff --git a/Objects/bytearrayobject.c b/Objects/bytearrayobject.c --- a/Objects/bytearrayobject.c +++ b/Objects/bytearrayobject.c @@ -5,6 +5,7 @@ #include "structmember.h" #include "bytes_methods.h" #include "bytesobject.h" +#include "pystrhex.h" /*[clinic input] class bytearray "PyByteArrayObject *" "&PyByteArray_Type" @@ -2872,6 +2873,19 @@ return NULL; } +PyDoc_STRVAR(hex__doc__, +"B.hex() -> string\n\ +\n\ +Create a string of hexadecimal numbers from a bytearray object.\n\ +Example: bytearray([0xb9, 0x01, 0xef]).hex() -> 'b901ef'."); + +static PyObject * +bytearray_hex(PyBytesObject *self) +{ + char* argbuf = PyByteArray_AS_STRING(self); + Py_ssize_t arglen = PyByteArray_GET_SIZE(self); + return _Py_strhex(argbuf, arglen); +} static PyObject * _common_reduce(PyByteArrayObject *self, int proto) @@ -3002,6 +3016,7 @@ BYTEARRAY_EXTEND_METHODDEF {"find", (PyCFunction)bytearray_find, METH_VARARGS, find__doc__}, BYTEARRAY_FROMHEX_METHODDEF + {"hex", (PyCFunction)bytearray_hex, METH_NOARGS, hex__doc__}, {"index", (PyCFunction)bytearray_index, METH_VARARGS, index__doc__}, BYTEARRAY_INSERT_METHODDEF {"isalnum", (PyCFunction)stringlib_isalnum, METH_NOARGS, diff --git a/Objects/bytesobject.c b/Objects/bytesobject.c --- a/Objects/bytesobject.c +++ b/Objects/bytesobject.c @@ -5,6 +5,7 @@ #include "Python.h" #include "bytes_methods.h" +#include "pystrhex.h" #include /*[clinic input] @@ -3036,6 +3037,20 @@ return NULL; } +PyDoc_STRVAR(hex__doc__, +"B.hex() -> string\n\ +\n\ +Create a string of hexadecimal numbers from a bytes object.\n\ +Example: b'\\xb9\\x01\\xef'.hex() -> 'b901ef'."); + +static PyObject * +bytes_hex(PyBytesObject *self) +{ + char* argbuf = PyBytes_AS_STRING(self); + Py_ssize_t arglen = PyBytes_GET_SIZE(self); + return _Py_strhex(argbuf, arglen); +} + static PyObject * bytes_getnewargs(PyBytesObject *v) { @@ -3057,6 +3072,7 @@ expandtabs__doc__}, {"find", (PyCFunction)bytes_find, METH_VARARGS, find__doc__}, BYTES_FROMHEX_METHODDEF + {"hex", (PyCFunction)bytes_hex, METH_NOARGS, hex__doc__}, {"index", (PyCFunction)bytes_index, METH_VARARGS, index__doc__}, {"isalnum", (PyCFunction)stringlib_isalnum, METH_NOARGS, _Py_isalnum__doc__}, diff --git a/Objects/memoryobject.c b/Objects/memoryobject.c --- a/Objects/memoryobject.c +++ b/Objects/memoryobject.c @@ -1,6 +1,7 @@ /* Memoryview object implementation */ #include "Python.h" +#include "pystrhex.h" #include @@ -2158,6 +2159,14 @@ } static PyObject * +memory_hex(PyMemoryViewObject *self, PyObject *dummy) +{ + Py_buffer *src = VIEW_ADDR(self); + CHECK_RELEASED(self); + return _Py_strhex(src->buf, src->len); +} + +static PyObject * memory_repr(PyMemoryViewObject *self) { if (self->flags & _Py_MEMORYVIEW_RELEASED) @@ -3061,6 +3070,10 @@ "tobytes($self, /)\n--\n\ \n\ Return the data in the buffer as a byte string."); +PyDoc_STRVAR(memory_hex_doc, +"hex($self, /)\n--\n\ +\n\ +Return the data in the buffer as a string of hexadecimal numbers."); PyDoc_STRVAR(memory_tolist_doc, "tolist($self, /)\n--\n\ \n\ @@ -3073,6 +3086,7 @@ static PyMethodDef memory_methods[] = { {"release", (PyCFunction)memory_release, METH_NOARGS, memory_release_doc}, {"tobytes", (PyCFunction)memory_tobytes, METH_NOARGS, memory_tobytes_doc}, + {"hex", (PyCFunction)memory_hex, METH_NOARGS, memory_hex_doc}, {"tolist", (PyCFunction)memory_tolist, METH_NOARGS, memory_tolist_doc}, {"cast", (PyCFunction)memory_cast, METH_VARARGS|METH_KEYWORDS, memory_cast_doc}, {"__enter__", memory_enter, METH_NOARGS, NULL}, diff --git a/PCbuild/pythoncore.vcxproj b/PCbuild/pythoncore.vcxproj --- a/PCbuild/pythoncore.vcxproj +++ b/PCbuild/pythoncore.vcxproj @@ -147,6 +147,7 @@ + @@ -376,6 +377,7 @@ + diff --git a/PCbuild/pythoncore.vcxproj.filters b/PCbuild/pythoncore.vcxproj.filters --- a/PCbuild/pythoncore.vcxproj.filters +++ b/PCbuild/pythoncore.vcxproj.filters @@ -243,6 +243,9 @@ Include + + Include + Include @@ -908,6 +911,9 @@ Python + + Python + Python -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Apr 26 01:42:50 2015 From: python-checkins at python.org (gregory.p.smith) Date: Sat, 25 Apr 2015 23:42:50 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue9951=3A_update_=5Fhas?= =?utf-8?q?hopenssl_and_md5module_to_use_=5FPy=5Fstrhex=28=29=2E?= Message-ID: <20150425234250.21331.70530@psf.io> https://hg.python.org/cpython/rev/955a479b31a8 changeset: 95799:955a479b31a8 user: Gregory P. Smith date: Sat Apr 25 23:42:38 2015 +0000 summary: Issue9951: update _hashopenssl and md5module to use _Py_strhex(). Also update _posixsubprocess to use Py_hexdigits instead of its own constant. files: Modules/_hashopenssl.c | 22 +++------------------- Modules/_posixsubprocess.c | 2 +- Modules/md5module.c | 23 ++--------------------- 3 files changed, 6 insertions(+), 41 deletions(-) diff --git a/Modules/_hashopenssl.c b/Modules/_hashopenssl.c --- a/Modules/_hashopenssl.c +++ b/Modules/_hashopenssl.c @@ -16,6 +16,7 @@ #include "Python.h" #include "structmember.h" #include "hashlib.h" +#include "pystrhex.h" /* EVP is the preferred interface to hashing in OpenSSL */ @@ -157,9 +158,7 @@ { unsigned char digest[EVP_MAX_MD_SIZE]; EVP_MD_CTX temp_ctx; - PyObject *retval; - char *hex_digest; - unsigned int i, j, digest_size; + unsigned int digest_size; /* Get the raw (binary) digest value */ locked_EVP_MD_CTX_copy(&temp_ctx, self); @@ -168,22 +167,7 @@ EVP_MD_CTX_cleanup(&temp_ctx); - /* Allocate a new buffer */ - hex_digest = PyMem_Malloc(digest_size * 2 + 1); - if (!hex_digest) - return PyErr_NoMemory(); - - /* Make hex version of the digest */ - for(i=j=0; i> 4) & 0xf; - hex_digest[j++] = Py_hexdigits[c]; - c = (digest[i] & 0xf); - hex_digest[j++] = Py_hexdigits[c]; - } - retval = PyUnicode_FromStringAndSize(hex_digest, digest_size * 2); - PyMem_Free(hex_digest); - return retval; + return _Py_strhex((const char *)digest, digest_size); } PyDoc_STRVAR(EVP_update__doc__, diff --git a/Modules/_posixsubprocess.c b/Modules/_posixsubprocess.c --- a/Modules/_posixsubprocess.c +++ b/Modules/_posixsubprocess.c @@ -504,7 +504,7 @@ _Py_write_noraise(errpipe_write, "OSError:", 8); cur = hex_errno + sizeof(hex_errno); while (saved_errno != 0 && cur > hex_errno) { - *--cur = "0123456789ABCDEF"[saved_errno % 16]; + *--cur = Py_hexdigits[saved_errno % 16]; saved_errno /= 16; } _Py_write_noraise(errpipe_write, cur, hex_errno + sizeof(hex_errno) - cur); diff --git a/Modules/md5module.c b/Modules/md5module.c --- a/Modules/md5module.c +++ b/Modules/md5module.c @@ -18,6 +18,7 @@ #include "Python.h" #include "hashlib.h" +#include "pystrhex.h" /*[clinic input] module _md5 @@ -387,32 +388,12 @@ { unsigned char digest[MD5_DIGESTSIZE]; struct md5_state temp; - PyObject *retval; - Py_UCS1 *hex_digest; - int i, j; /* Get the raw (binary) digest value */ temp = self->hash_state; md5_done(&temp, digest); - /* Create a new string */ - retval = PyUnicode_New(MD5_DIGESTSIZE * 2, 127); - if (!retval) - return NULL; - hex_digest = PyUnicode_1BYTE_DATA(retval); - - /* Make hex version of the digest */ - for(i=j=0; i> 4) & 0xf; - hex_digest[j++] = Py_hexdigits[c]; - c = (digest[i] & 0xf); - hex_digest[j++] = Py_hexdigits[c]; - } -#ifdef Py_DEBUG - assert(_PyUnicode_CheckConsistency(retval, 1)); -#endif - return retval; + return _Py_strhex((const char*)digest, MD5_DIGESTSIZE); } /*[clinic input] -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Apr 26 02:41:10 2015 From: python-checkins at python.org (gregory.p.smith) Date: Sun, 26 Apr 2015 00:41:10 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Add_the_files_missing_from?= =?utf-8?q?_c9f1630cf2b1_for_issue9951=2E?= Message-ID: <20150426004110.6599.87151@psf.io> https://hg.python.org/cpython/rev/a7737204c221 changeset: 95800:a7737204c221 user: Gregory P. Smith date: Sun Apr 26 00:41:00 2015 +0000 summary: Add the files missing from c9f1630cf2b1 for issue9951. hg status should be my friend more often... files: Include/pystrhex.h | 17 +++++++++ Python/pystrhex.c | 60 ++++++++++++++++++++++++++++++++++ 2 files changed, 77 insertions(+), 0 deletions(-) diff --git a/Include/pystrhex.h b/Include/pystrhex.h new file mode 100644 --- /dev/null +++ b/Include/pystrhex.h @@ -0,0 +1,17 @@ +#ifndef Py_STRHEX_H +#define Py_STRHEX_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Returns a str() containing the hex representation of argbuf. */ +PyAPI_FUNC(PyObject*) _Py_strhex(const char* argbuf, const Py_ssize_t arglen); +/* Returns a bytes() containing the ASCII hex representation of argbuf. */ +PyAPI_FUNC(PyObject*) _Py_strhex_bytes(const char* argbuf, const Py_ssize_t arglen); + +#ifdef __cplusplus +} +#endif + +#endif /* !Py_STRHEX_H */ diff --git a/Python/pystrhex.c b/Python/pystrhex.c new file mode 100644 --- /dev/null +++ b/Python/pystrhex.c @@ -0,0 +1,60 @@ +/* bytes to hex implementation */ + +#include "Python.h" + +static PyObject *_Py_strhex_impl(const char* argbuf, const Py_ssize_t arglen, + int return_bytes) +{ + PyObject *retval; + Py_UCS1* retbuf; + Py_ssize_t i, j; + + assert(arglen >= 0); + if (arglen > PY_SSIZE_T_MAX / 2) + return PyErr_NoMemory(); + + if (return_bytes) { + /* If _PyBytes_FromSize() were public we could avoid malloc+copy. */ + retbuf = (Py_UCS1*) PyMem_Malloc(arglen*2); + if (!retbuf) + return PyErr_NoMemory(); + } else { + retval = PyUnicode_New(arglen*2, 127); + if (!retval) + return NULL; + retbuf = PyUnicode_1BYTE_DATA(retval); + } + + /* make hex version of string, taken from shamodule.c */ + for (i=j=0; i < arglen; i++) { + unsigned char c; + c = (argbuf[i] >> 4) & 0xf; + retbuf[j++] = Py_hexdigits[c]; + c = argbuf[i] & 0xf; + retbuf[j++] = Py_hexdigits[c]; + } + + if (return_bytes) { + retval = PyBytes_FromStringAndSize((const char *)retbuf, arglen*2); + PyMem_Free(retbuf); + } +#ifdef Py_DEBUG + else { + assert(_PyUnicode_CheckConsistency(retval, 1)); + } +#endif + + return retval; +} + +PyObject *_Py_strhex(const char* argbuf, const Py_ssize_t arglen) +{ + return _Py_strhex_impl(argbuf, arglen, 0); +} + +/* Same as above but returns a bytes() instead of str() to avoid the + * need to decode the str() when bytes are needed. */ +PyObject *_Py_strhex_bytes(const char* argbuf, const Py_ssize_t arglen) +{ + return _Py_strhex_impl(argbuf, arglen, 1); +} -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Apr 26 02:42:24 2015 From: python-checkins at python.org (gregory.p.smith) Date: Sun, 26 Apr 2015 00:42:24 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Switch_binascii_over_to_us?= =?utf-8?q?ing_the_common_=5FPy=5Fstrhex_implementation_for_its_hex?= Message-ID: <20150426004224.3991.77095@psf.io> https://hg.python.org/cpython/rev/7f0811452d0f changeset: 95801:7f0811452d0f user: Gregory P. Smith date: Sun Apr 26 00:42:13 2015 +0000 summary: Switch binascii over to using the common _Py_strhex implementation for its hex and hexlify functions. issue9951. files: Modules/binascii.c | 31 +++---------------------------- 1 files changed, 3 insertions(+), 28 deletions(-) diff --git a/Modules/binascii.c b/Modules/binascii.c --- a/Modules/binascii.c +++ b/Modules/binascii.c @@ -56,6 +56,7 @@ #define PY_SSIZE_T_CLEAN #include "Python.h" +#include "pystrhex.h" #ifdef USE_ZLIB_CRC32 #include "zlib.h" #endif @@ -1117,33 +1118,7 @@ binascii_b2a_hex_impl(PyModuleDef *module, Py_buffer *data) /*[clinic end generated code: output=179318922c2f8fda input=96423cfa299ff3b1]*/ { - char* argbuf; - Py_ssize_t arglen; - PyObject *retval; - char* retbuf; - Py_ssize_t i, j; - - argbuf = data->buf; - arglen = data->len; - - assert(arglen >= 0); - if (arglen > PY_SSIZE_T_MAX / 2) - return PyErr_NoMemory(); - - retval = PyBytes_FromStringAndSize(NULL, arglen*2); - if (!retval) - return NULL; - retbuf = PyBytes_AS_STRING(retval); - - /* make hex version of string, taken from shamodule.c */ - for (i=j=0; i < arglen; i++) { - unsigned char c; - c = (argbuf[i] >> 4) & 0xf; - retbuf[j++] = Py_hexdigits[c]; - c = argbuf[i] & 0xf; - retbuf[j++] = Py_hexdigits[c]; - } - return retval; + return _Py_strhex_bytes((const char *)data->buf, data->len); } /*[clinic input] @@ -1158,7 +1133,7 @@ binascii_hexlify_impl(PyModuleDef *module, Py_buffer *data) /*[clinic end generated code: output=6098440091fb61dc input=2e3afae7f083f061]*/ { - return binascii_b2a_hex_impl(module, data); + return _Py_strhex_bytes((const char *)data->buf, data->len); } static int -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Apr 26 07:00:09 2015 From: python-checkins at python.org (gregory.p.smith) Date: Sun, 26 Apr 2015 05:00:09 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Add_missing_PyAPI=5FFUNC_m?= =?utf-8?q?acro=27s_to_the_public_functions_as_other_=2Ec_files_do?= Message-ID: <20150426050007.21345.17242@psf.io> https://hg.python.org/cpython/rev/b46308353ed9 changeset: 95802:b46308353ed9 user: Gregory P. Smith date: Sun Apr 26 04:59:52 2015 +0000 summary: Add missing PyAPI_FUNC macro's to the public functions as other .c files do in hopes that this fixes the windows extension module link error for modules trying to call _Py_strhex functions. issue9951. files: Python/pystrhex.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Python/pystrhex.c b/Python/pystrhex.c --- a/Python/pystrhex.c +++ b/Python/pystrhex.c @@ -47,14 +47,14 @@ return retval; } -PyObject *_Py_strhex(const char* argbuf, const Py_ssize_t arglen) +PyAPI_FUNC(PyObject *) _Py_strhex(const char* argbuf, const Py_ssize_t arglen) { return _Py_strhex_impl(argbuf, arglen, 0); } /* Same as above but returns a bytes() instead of str() to avoid the * need to decode the str() when bytes are needed. */ -PyObject *_Py_strhex_bytes(const char* argbuf, const Py_ssize_t arglen) +PyAPI_FUNC(PyObject *) _Py_strhex_bytes(const char* argbuf, const Py_ssize_t arglen) { return _Py_strhex_impl(argbuf, arglen, 1); } -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Apr 26 07:06:02 2015 From: python-checkins at python.org (gregory.p.smith) Date: Sun, 26 Apr 2015 05:06:02 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Use_assertEqual_rather_tha?= =?utf-8?q?n_assertEquals_to_avoid_the_deprecation_warning=2E?= Message-ID: <20150426050602.21345.78779@psf.io> https://hg.python.org/cpython/rev/8c044904cddb changeset: 95803:8c044904cddb user: Gregory P. Smith date: Sun Apr 26 05:05:53 2015 +0000 summary: Use assertEqual rather than assertEquals to avoid the deprecation warning. files: Lib/test/test_bytes.py | 8 ++++---- 1 files changed, 4 insertions(+), 4 deletions(-) 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 @@ -304,10 +304,10 @@ def test_hex(self): self.assertRaises(TypeError, self.type2test.hex) self.assertRaises(TypeError, self.type2test.hex, 1) - self.assertEquals(self.type2test(b"").hex(), "") - self.assertEquals(bytearray([0x1a, 0x2b, 0x30]).hex(), '1a2b30') - self.assertEquals(self.type2test(b"\x1a\x2b\x30").hex(), '1a2b30') - self.assertEquals(memoryview(b"\x1a\x2b\x30").hex(), '1a2b30') + self.assertEqual(self.type2test(b"").hex(), "") + self.assertEqual(bytearray([0x1a, 0x2b, 0x30]).hex(), '1a2b30') + self.assertEqual(self.type2test(b"\x1a\x2b\x30").hex(), '1a2b30') + self.assertEqual(memoryview(b"\x1a\x2b\x30").hex(), '1a2b30') def test_join(self): self.assertEqual(self.type2test(b"").join([]), b"") -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Apr 26 08:44:18 2015 From: python-checkins at python.org (gregory.p.smith) Date: Sun, 26 Apr 2015 06:44:18 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Fix_computation_of_max=5Ffd_on_OpenBSD=2E__Issue_=232385?= =?utf-8?q?2=2E?= Message-ID: <20150426064417.102161.37901@psf.io> https://hg.python.org/cpython/rev/08d0cc23fb00 changeset: 95805:08d0cc23fb00 parent: 95803:8c044904cddb parent: 95804:7df280b311d0 user: Gregory P. Smith date: Sat Apr 25 23:44:02 2015 -0700 summary: Fix computation of max_fd on OpenBSD. Issue #23852. files: Modules/_posixsubprocess.c | 10 ++++++++++ 1 files changed, 10 insertions(+), 0 deletions(-) diff --git a/Modules/_posixsubprocess.c b/Modules/_posixsubprocess.c --- a/Modules/_posixsubprocess.c +++ b/Modules/_posixsubprocess.c @@ -14,6 +14,9 @@ #ifdef HAVE_SYS_SYSCALL_H #include #endif +#if defined(HAVE_SYS_RESOURCE_H) +#include +#endif #ifdef HAVE_DIRENT_H #include #endif @@ -174,6 +177,13 @@ if (local_max_fd >= 0) return local_max_fd; #endif +#if defined(HAVE_SYS_RESOURCE_H) && defined(__OpenBSD__) + struct rlimit rl; + /* Not on the POSIX async signal safe functions list but likely + * safe. TODO - Someone should audit OpenBSD to make sure. */ + if (getrlimit(RLIMIT_NOFILE, &rl) >= 0) + return (long) rl.rlim_max; +#endif #ifdef _SC_OPEN_MAX local_max_fd = sysconf(_SC_OPEN_MAX); if (local_max_fd == -1) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Apr 26 08:44:17 2015 From: python-checkins at python.org (gregory.p.smith) Date: Sun, 26 Apr 2015 06:44:17 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E4=29=3A_Fix_computatio?= =?utf-8?q?n_of_max=5Ffd_on_OpenBSD=2E__Issue_=2323852=2E?= Message-ID: <20150426064417.101100.76474@psf.io> https://hg.python.org/cpython/rev/7df280b311d0 changeset: 95804:7df280b311d0 branch: 3.4 parent: 95795:875787fee2cc user: Gregory P. Smith date: Sat Apr 25 23:43:34 2015 -0700 summary: Fix computation of max_fd on OpenBSD. Issue #23852. files: Modules/_posixsubprocess.c | 10 ++++++++++ 1 files changed, 10 insertions(+), 0 deletions(-) diff --git a/Modules/_posixsubprocess.c b/Modules/_posixsubprocess.c --- a/Modules/_posixsubprocess.c +++ b/Modules/_posixsubprocess.c @@ -14,6 +14,9 @@ #ifdef HAVE_SYS_SYSCALL_H #include #endif +#if defined(HAVE_SYS_RESOURCE_H) +#include +#endif #ifdef HAVE_DIRENT_H #include #endif @@ -174,6 +177,13 @@ if (local_max_fd >= 0) return local_max_fd; #endif +#if defined(HAVE_SYS_RESOURCE_H) && defined(__OpenBSD__) + struct rlimit rl; + /* Not on the POSIX async signal safe functions list but likely + * safe. TODO - Someone should audit OpenBSD to make sure. */ + if (getrlimit(RLIMIT_NOFILE, &rl) >= 0) + return (long) rl.rlim_max; +#endif #ifdef _SC_OPEN_MAX local_max_fd = sysconf(_SC_OPEN_MAX); if (local_max_fd == -1) -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Apr 26 08:51:50 2015 From: python-checkins at python.org (gregory.p.smith) Date: Sun, 26 Apr 2015 06:51:50 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Silence_a_gcc_=22may_be_us?= =?utf-8?q?ed_uninitialized=22_compiler_warning=2E__Not_true=2E?= Message-ID: <20150426065150.31127.12165@psf.io> https://hg.python.org/cpython/rev/106c5ee3c024 changeset: 95806:106c5ee3c024 user: Gregory P. Smith date: Sat Apr 25 23:51:39 2015 -0700 summary: Silence a gcc "may be used uninitialized" compiler warning. Not true. Initializing retval prevents the naive warning. files: Python/pystrhex.c | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/Python/pystrhex.c b/Python/pystrhex.c --- a/Python/pystrhex.c +++ b/Python/pystrhex.c @@ -18,6 +18,7 @@ retbuf = (Py_UCS1*) PyMem_Malloc(arglen*2); if (!retbuf) return PyErr_NoMemory(); + retval = NULL; /* silence a compiler warning, assigned later. */ } else { retval = PyUnicode_New(arglen*2, 127); if (!retval) -- Repository URL: https://hg.python.org/cpython From solipsis at pitrou.net Sun Apr 26 10:34:46 2015 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Sun, 26 Apr 2015 08:34:46 +0000 Subject: [Python-checkins] Daily reference leaks (8c044904cddb): sum=3 Message-ID: <20150426083446.4017.53797@psf.io> results for 8c044904cddb on branch "default" -------------------------------------------- test_functools leaked [0, 0, 3] memory blocks, sum=3 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogK9zb4L', '--timeout', '7200'] From python-checkins at python.org Sun Apr 26 11:10:30 2015 From: python-checkins at python.org (berker.peksag) Date: Sun, 26 Apr 2015 09:10:30 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2323356=3A_Simplify_convert=5Farg=5Fline=5Fto=5Fa?= =?utf-8?q?rgs_example=2E?= Message-ID: <20150426091029.31115.91693@psf.io> https://hg.python.org/cpython/rev/2d3ed019bc9f changeset: 95808:2d3ed019bc9f parent: 95806:106c5ee3c024 parent: 95807:bd8b99034121 user: Berker Peksag date: Sun Apr 26 12:10:27 2015 +0300 summary: Issue #23356: Simplify convert_arg_line_to_args example. Patch by py.user. files: Doc/library/argparse.rst | 5 +---- 1 files changed, 1 insertions(+), 4 deletions(-) diff --git a/Doc/library/argparse.rst b/Doc/library/argparse.rst --- a/Doc/library/argparse.rst +++ b/Doc/library/argparse.rst @@ -1948,10 +1948,7 @@ as an argument:: def convert_arg_line_to_args(self, arg_line): - for arg in arg_line.split(): - if not arg.strip(): - continue - yield arg + return arg_line.split() Exiting methods -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Apr 26 11:10:29 2015 From: python-checkins at python.org (berker.peksag) Date: Sun, 26 Apr 2015 09:10:29 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzIzMzU2?= =?utf-8?q?=3A_Simplify_convert=5Farg=5Fline=5Fto=5Fargs_example=2E?= Message-ID: <20150426091029.6579.6294@psf.io> https://hg.python.org/cpython/rev/bd8b99034121 changeset: 95807:bd8b99034121 branch: 3.4 parent: 95804:7df280b311d0 user: Berker Peksag date: Sun Apr 26 12:09:54 2015 +0300 summary: Issue #23356: Simplify convert_arg_line_to_args example. Patch by py.user. files: Doc/library/argparse.rst | 5 +---- 1 files changed, 1 insertions(+), 4 deletions(-) diff --git a/Doc/library/argparse.rst b/Doc/library/argparse.rst --- a/Doc/library/argparse.rst +++ b/Doc/library/argparse.rst @@ -1921,10 +1921,7 @@ as an argument:: def convert_arg_line_to_args(self, arg_line): - for arg in arg_line.split(): - if not arg.strip(): - continue - yield arg + return arg_line.split() Exiting methods -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Apr 26 11:12:45 2015 From: python-checkins at python.org (berker.peksag) Date: Sun, 26 Apr 2015 09:12:45 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzIzMzU2?= =?utf-8?q?=3A_Simplify_convert=5Farg=5Fline=5Fto=5Fargs_example=2E?= Message-ID: <20150426091245.27900.16213@psf.io> https://hg.python.org/cpython/rev/050e0c0b3d90 changeset: 95809:050e0c0b3d90 branch: 2.7 parent: 95796:4e48a55cffb8 user: Berker Peksag date: Sun Apr 26 12:12:45 2015 +0300 summary: Issue #23356: Simplify convert_arg_line_to_args example. Patch by py.user. files: Doc/library/argparse.rst | 5 +---- 1 files changed, 1 insertions(+), 4 deletions(-) diff --git a/Doc/library/argparse.rst b/Doc/library/argparse.rst --- a/Doc/library/argparse.rst +++ b/Doc/library/argparse.rst @@ -1884,10 +1884,7 @@ as an argument:: def convert_arg_line_to_args(self, arg_line): - for arg in arg_line.split(): - if not arg.strip(): - continue - yield arg + return arg_line.split() Exiting methods -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Apr 26 18:49:47 2015 From: python-checkins at python.org (antoine.pitrou) Date: Sun, 26 Apr 2015 16:49:47 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Add_missing_newline_in_NEW?= =?utf-8?q?S?= Message-ID: <20150426164947.21333.80284@psf.io> https://hg.python.org/cpython/rev/a6140242b79f changeset: 95812:a6140242b79f user: Antoine Pitrou date: Sun Apr 26 18:48:28 2015 +0200 summary: Add missing newline in NEWS files: Misc/NEWS | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -14,6 +14,7 @@ unnormalized StopIteration exception. Patch by Stefan Behnel. - Issue #24022: Fix tokenizer crash when processing undecodable source code. + - Issue #9951: Added a hex() method to bytes, bytearray, and memoryview. Library -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Apr 26 18:49:46 2015 From: python-checkins at python.org (antoine.pitrou) Date: Sun, 26 Apr 2015 16:49:46 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzIzOTk2?= =?utf-8?q?=3A_Avoid_a_crash_when_a_delegated_generator_raises_an_unnormal?= =?utf-8?q?ized?= Message-ID: <20150426164946.129409.59430@psf.io> https://hg.python.org/cpython/rev/15c80f63ea1c changeset: 95810:15c80f63ea1c branch: 3.4 parent: 95807:bd8b99034121 user: Antoine Pitrou date: Sun Apr 26 18:46:40 2015 +0200 summary: Issue #23996: Avoid a crash when a delegated generator raises an unnormalized StopIteration exception. Patch by Stefan Behnel. files: Misc/NEWS | 3 +++ Objects/genobject.c | 27 ++++++++++++++++++++++----- 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,9 @@ Core and Builtins ----------------- +- Issue #23996: Avoid a crash when a delegated generator raises an + unnormalized StopIteration exception. Patch by Stefan Behnel. + - Issue #24022: Fix tokenizer crash when processing undecodable source code. - Issue #23309: Avoid a deadlock at shutdown if a daemon thread is aborted diff --git a/Objects/genobject.c b/Objects/genobject.c --- a/Objects/genobject.c +++ b/Objects/genobject.c @@ -396,13 +396,30 @@ if (PyErr_ExceptionMatches(PyExc_StopIteration)) { PyErr_Fetch(&et, &ev, &tb); + if (ev) { + /* exception will usually be normalised already */ + if (Py_TYPE(ev) == (PyTypeObject *) et + || PyObject_IsInstance(ev, PyExc_StopIteration)) { + value = ((PyStopIterationObject *)ev)->value; + Py_INCREF(value); + Py_DECREF(ev); + } else if (et == PyExc_StopIteration) { + /* avoid normalisation and take ev as value */ + value = ev; + } else { + /* normalisation required */ + PyErr_NormalizeException(&et, &ev, &tb); + if (!PyObject_IsInstance(ev, PyExc_StopIteration)) { + PyErr_Restore(et, ev, tb); + return -1; + } + value = ((PyStopIterationObject *)ev)->value; + Py_INCREF(value); + Py_DECREF(ev); + } + } Py_XDECREF(et); Py_XDECREF(tb); - if (ev) { - value = ((PyStopIterationObject *)ev)->value; - Py_INCREF(value); - Py_DECREF(ev); - } } else if (PyErr_Occurred()) { return -1; } -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Apr 26 18:49:47 2015 From: python-checkins at python.org (antoine.pitrou) Date: Sun, 26 Apr 2015 16:49:47 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2323996=3A_Avoid_a_crash_when_a_delegated_generat?= =?utf-8?q?or_raises_an_unnormalized?= Message-ID: <20150426164946.30327.88452@psf.io> https://hg.python.org/cpython/rev/9d0c6c66b0ac changeset: 95811:9d0c6c66b0ac parent: 95808:2d3ed019bc9f parent: 95810:15c80f63ea1c user: Antoine Pitrou date: Sun Apr 26 18:48:16 2015 +0200 summary: Issue #23996: Avoid a crash when a delegated generator raises an unnormalized StopIteration exception. Patch by Stefan Behnel. files: Misc/NEWS | 3 +++ Objects/genobject.c | 27 ++++++++++++++++++++++----- 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,9 @@ Core and Builtins ----------------- +- Issue #23996: Avoid a crash when a delegated generator raises an + unnormalized StopIteration exception. Patch by Stefan Behnel. + - Issue #24022: Fix tokenizer crash when processing undecodable source code. - Issue #9951: Added a hex() method to bytes, bytearray, and memoryview. diff --git a/Objects/genobject.c b/Objects/genobject.c --- a/Objects/genobject.c +++ b/Objects/genobject.c @@ -396,13 +396,30 @@ if (PyErr_ExceptionMatches(PyExc_StopIteration)) { PyErr_Fetch(&et, &ev, &tb); + if (ev) { + /* exception will usually be normalised already */ + if (Py_TYPE(ev) == (PyTypeObject *) et + || PyObject_IsInstance(ev, PyExc_StopIteration)) { + value = ((PyStopIterationObject *)ev)->value; + Py_INCREF(value); + Py_DECREF(ev); + } else if (et == PyExc_StopIteration) { + /* avoid normalisation and take ev as value */ + value = ev; + } else { + /* normalisation required */ + PyErr_NormalizeException(&et, &ev, &tb); + if (!PyObject_IsInstance(ev, PyExc_StopIteration)) { + PyErr_Restore(et, ev, tb); + return -1; + } + value = ((PyStopIterationObject *)ev)->value; + Py_INCREF(value); + Py_DECREF(ev); + } + } Py_XDECREF(et); Py_XDECREF(tb); - if (ev) { - value = ((PyStopIterationObject *)ev)->value; - Py_INCREF(value); - Py_DECREF(ev); - } } else if (PyErr_Occurred()) { return -1; } -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Apr 26 21:56:27 2015 From: python-checkins at python.org (benjamin.peterson) Date: Sun, 26 Apr 2015 19:56:27 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E4=29=3A_remove_extern_?= =?utf-8?q?definition=2C_since_it=27s_in_a_header_file_=28closes_=2324058?= =?utf-8?q?=29?= Message-ID: <20150426195627.4009.21776@psf.io> https://hg.python.org/cpython/rev/ec6ed10d611e changeset: 95813:ec6ed10d611e branch: 3.4 parent: 95810:15c80f63ea1c user: Benjamin Peterson date: Sun Apr 26 15:55:06 2015 -0400 summary: remove extern definition, since it's in a header file (closes #24058) files: Modules/readline.c | 2 -- 1 files changed, 0 insertions(+), 2 deletions(-) diff --git a/Modules/readline.c b/Modules/readline.c --- a/Modules/readline.c +++ b/Modules/readline.c @@ -1062,8 +1062,6 @@ rl_callback_handler_remove(); } -extern PyThreadState* _PyOS_ReadlineTState; - static char * readline_until_enter_or_signal(const char *prompt, int *signal) { -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Apr 26 21:56:28 2015 From: python-checkins at python.org (benjamin.peterson) Date: Sun, 26 Apr 2015 19:56:28 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?b?KTogbWVyZ2UgMy40ICgjMjQwNTgp?= Message-ID: <20150426195627.4021.47397@psf.io> https://hg.python.org/cpython/rev/cb4334ab8453 changeset: 95815:cb4334ab8453 parent: 95812:a6140242b79f parent: 95813:ec6ed10d611e user: Benjamin Peterson date: Sun Apr 26 15:56:23 2015 -0400 summary: merge 3.4 (#24058) files: Modules/readline.c | 2 -- 1 files changed, 0 insertions(+), 2 deletions(-) diff --git a/Modules/readline.c b/Modules/readline.c --- a/Modules/readline.c +++ b/Modules/readline.c @@ -1103,8 +1103,6 @@ rl_callback_handler_remove(); } -extern PyThreadState* _PyOS_ReadlineTState; - static char * readline_until_enter_or_signal(const char *prompt, int *signal) { -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Sun Apr 26 21:56:27 2015 From: python-checkins at python.org (benjamin.peterson) Date: Sun, 26 Apr 2015 19:56:27 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_remove_extern_?= =?utf-8?q?definition=2C_since_it=27s_in_a_header_file_=28closes_=2324058?= =?utf-8?q?=29?= Message-ID: <20150426195627.27928.31764@psf.io> https://hg.python.org/cpython/rev/192f9efe4a38 changeset: 95814:192f9efe4a38 branch: 2.7 parent: 95809:050e0c0b3d90 user: Benjamin Peterson date: Sun Apr 26 15:55:06 2015 -0400 summary: remove extern definition, since it's in a header file (closes #24058) files: Modules/readline.c | 2 -- 1 files changed, 0 insertions(+), 2 deletions(-) diff --git a/Modules/readline.c b/Modules/readline.c --- a/Modules/readline.c +++ b/Modules/readline.c @@ -975,8 +975,6 @@ rl_callback_handler_remove(); } -extern PyThreadState* _PyOS_ReadlineTState; - static char * readline_until_enter_or_signal(char *prompt, int *signal) { -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Apr 27 02:35:02 2015 From: python-checkins at python.org (benjamin.peterson) Date: Mon, 27 Apr 2015 00:35:02 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogYWxsb3cgMi43IHRv?= =?utf-8?q?_be_built_with_asan_=28closes_=2324061=29?= Message-ID: <20150427003502.129418.55222@psf.io> https://hg.python.org/cpython/rev/4234b0dd2a54 changeset: 95816:4234b0dd2a54 branch: 2.7 parent: 95814:192f9efe4a38 user: Benjamin Peterson date: Sun Apr 26 20:33:38 2015 -0400 summary: allow 2.7 to be built with asan (closes #24061) files: Objects/obmalloc.c | 20 ++++++++++++++++++++ 1 files changed, 20 insertions(+), 0 deletions(-) diff --git a/Objects/obmalloc.c b/Objects/obmalloc.c --- a/Objects/obmalloc.c +++ b/Objects/obmalloc.c @@ -1,5 +1,23 @@ #include "Python.h" +#if defined(__has_feature) /* Clang */ + #if __has_feature(address_sanitizer) /* is ASAN enabled? */ + #define ATTRIBUTE_NO_ADDRESS_SAFETY_ANALYSIS \ + __attribute__((no_address_safety_analysis)) \ + __attribute__ ((noinline)) + #else + #define ATTRIBUTE_NO_ADDRESS_SAFETY_ANALYSIS + #endif +#else + #if defined(__SANITIZE_ADDRESS__) /* GCC 4.8.x, is ASAN enabled? */ + #define ATTRIBUTE_NO_ADDRESS_SAFETY_ANALYSIS \ + __attribute__((no_address_safety_analysis)) \ + __attribute__ ((noinline)) + #else + #define ATTRIBUTE_NO_ADDRESS_SAFETY_ANALYSIS + #endif +#endif + #ifdef WITH_PYMALLOC #ifdef HAVE_MMAP @@ -971,6 +989,7 @@ /* free */ #undef PyObject_Free +ATTRIBUTE_NO_ADDRESS_SAFETY_ANALYSIS void PyObject_Free(void *p) { @@ -1201,6 +1220,7 @@ */ #undef PyObject_Realloc +ATTRIBUTE_NO_ADDRESS_SAFETY_ANALYSIS void * PyObject_Realloc(void *p, size_t nbytes) { -- Repository URL: https://hg.python.org/cpython From solipsis at pitrou.net Mon Apr 27 10:37:44 2015 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Mon, 27 Apr 2015 08:37:44 +0000 Subject: [Python-checkins] Daily reference leaks (cb4334ab8453): sum=3 Message-ID: <20150427083743.103087.21400@psf.io> results for cb4334ab8453 on branch "default" -------------------------------------------- test_functools leaked [0, 0, 3] memory blocks, sum=3 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogGZTLLb', '--timeout', '7200'] From python-checkins at python.org Mon Apr 27 12:53:57 2015 From: python-checkins at python.org (berker.peksag) Date: Mon, 27 Apr 2015 10:53:57 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzI0MDYy?= =?utf-8?q?=3A_Fix_os=2Estat_links=2E_Patch_by_July_Tikhonov=2E?= Message-ID: <20150427105357.129426.49707@psf.io> https://hg.python.org/cpython/rev/5850f0c17c34 changeset: 95817:5850f0c17c34 branch: 3.4 parent: 95813:ec6ed10d611e user: Berker Peksag date: Mon Apr 27 13:53:28 2015 +0300 summary: Issue #24062: Fix os.stat links. Patch by July Tikhonov. files: Doc/library/os.rst | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/library/os.rst b/Doc/library/os.rst --- a/Doc/library/os.rst +++ b/Doc/library/os.rst @@ -772,7 +772,7 @@ .. seealso:: - The :func:`stat` function. + The :func:`.stat` function. Availability: Unix, Windows. @@ -1601,7 +1601,7 @@ .. seealso:: - The :func:`stat` function. + The :func:`.stat` function. .. versionchanged:: 3.2 Added support for Windows 6.0 (Vista) symbolic links. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Apr 27 12:53:57 2015 From: python-checkins at python.org (berker.peksag) Date: Mon, 27 Apr 2015 10:53:57 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2324062=3A_Fix_os=2Estat_links=2E_Patch_by_July_T?= =?utf-8?q?ikhonov=2E?= Message-ID: <20150427105357.4001.49252@psf.io> https://hg.python.org/cpython/rev/18882c93f4bd changeset: 95818:18882c93f4bd parent: 95815:cb4334ab8453 parent: 95817:5850f0c17c34 user: Berker Peksag date: Mon Apr 27 13:53:54 2015 +0300 summary: Issue #24062: Fix os.stat links. Patch by July Tikhonov. files: Doc/library/os.rst | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/library/os.rst b/Doc/library/os.rst --- a/Doc/library/os.rst +++ b/Doc/library/os.rst @@ -773,7 +773,7 @@ .. seealso:: - The :func:`stat` function. + The :func:`.stat` function. Availability: Unix, Windows. @@ -1647,7 +1647,7 @@ .. seealso:: - The :func:`stat` function. + The :func:`.stat` function. .. versionchanged:: 3.2 Added support for Windows 6.0 (Vista) symbolic links. -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Apr 27 16:49:26 2015 From: python-checkins at python.org (andrew.svetlov) Date: Mon, 27 Apr 2015 14:49:26 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzIxMzU0?= =?utf-8?q?=3A_PyCFunction=5FNew_function_is_exposed_by_python_DLL_again?= =?utf-8?q?=2E?= Message-ID: <20150427144926.31123.19011@psf.io> https://hg.python.org/cpython/rev/69951573cb0e changeset: 95819:69951573cb0e branch: 3.4 parent: 95817:5850f0c17c34 user: Andrew Svetlov date: Mon Apr 27 17:48:50 2015 +0300 summary: Issue #21354: PyCFunction_New function is exposed by python DLL again. files: Misc/NEWS | 2 ++ Objects/methodobject.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 #24044: Fix possible null pointer dereference in list.sort in out of memory conditions. +- Issue #21354: PyCFunction_New function is exposed by python DLL again. + Library ------- diff --git a/Objects/methodobject.c b/Objects/methodobject.c --- a/Objects/methodobject.c +++ b/Objects/methodobject.c @@ -16,7 +16,7 @@ /* undefine macro trampoline to PyCFunction_NewEx */ #undef PyCFunction_New -PyObject * +PyAPI_FUNC(PyObject *) PyCFunction_New(PyMethodDef *ml, PyObject *self) { return PyCFunction_NewEx(ml, self, NULL); -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Mon Apr 27 16:49:26 2015 From: python-checkins at python.org (andrew.svetlov) Date: Mon, 27 Apr 2015 14:49:26 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?b?KTogTWVyZ2UgMy40?= Message-ID: <20150427144926.30339.56504@psf.io> https://hg.python.org/cpython/rev/4803a6d569f7 changeset: 95820:4803a6d569f7 parent: 95818:18882c93f4bd parent: 95819:69951573cb0e user: Andrew Svetlov date: Mon Apr 27 17:49:16 2015 +0300 summary: Merge 3.4 files: Misc/NEWS | 2 ++ Objects/methodobject.c | 2 +- 2 files changed, 3 insertions(+), 1 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -89,6 +89,8 @@ - Issue #24044: Fix possible null pointer dereference in list.sort in out of memory conditions. +- Issue #21354: PyCFunction_New function is exposed by python DLL again. + Library ------- diff --git a/Objects/methodobject.c b/Objects/methodobject.c --- a/Objects/methodobject.c +++ b/Objects/methodobject.c @@ -16,7 +16,7 @@ /* undefine macro trampoline to PyCFunction_NewEx */ #undef PyCFunction_New -PyObject * +PyAPI_FUNC(PyObject *) PyCFunction_New(PyMethodDef *ml, PyObject *self) { return PyCFunction_NewEx(ml, self, NULL); -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Apr 28 03:44:37 2015 From: python-checkins at python.org (benjamin.peterson) Date: Tue, 28 Apr 2015 01:44:37 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_remove_the_concept_of_an_u?= =?utf-8?q?noptimized_function_scope_from_the_compiler=2C_since_it?= Message-ID: <20150428014436.20334.33294@psf.io> https://hg.python.org/cpython/rev/3c143f60177c changeset: 95821:3c143f60177c user: Benjamin Peterson date: Mon Apr 27 21:44:22 2015 -0400 summary: remove the concept of an unoptimized function scope from the compiler, since it can't happen anymore files: Include/symtable.h | 5 ----- Lib/symtable.py | 9 ++------- Modules/symtablemodule.c | 3 --- Python/compile.c | 7 ++----- Python/symtable.c | 16 ---------------- 5 files changed, 4 insertions(+), 36 deletions(-) diff --git a/Include/symtable.h b/Include/symtable.h --- a/Include/symtable.h +++ b/Include/symtable.h @@ -43,7 +43,6 @@ PyObject *ste_children; /* list of child blocks */ PyObject *ste_directives;/* locations of global and nonlocal statements */ _Py_block_ty ste_type; /* module, class, or function */ - int ste_unoptimized; /* false if namespace is optimized */ int ste_nested; /* true if block is nested */ unsigned ste_free : 1; /* true if block has free variables */ unsigned ste_child_free : 1; /* true if a child block has free vars, @@ -108,10 +107,6 @@ #define FREE 4 #define CELL 5 -/* The following two names are used for the ste_unoptimized bit field */ -#define OPT_IMPORT_STAR 1 -#define OPT_TOPLEVEL 2 /* top-level names, including eval and exec */ - #define GENERATOR 1 #define GENERATOR_EXPRESSION 2 diff --git a/Lib/symtable.py b/Lib/symtable.py --- a/Lib/symtable.py +++ b/Lib/symtable.py @@ -2,7 +2,7 @@ import _symtable from _symtable import (USE, DEF_GLOBAL, DEF_LOCAL, DEF_PARAM, - DEF_IMPORT, DEF_BOUND, OPT_IMPORT_STAR, SCOPE_OFF, SCOPE_MASK, FREE, + DEF_IMPORT, DEF_BOUND, SCOPE_OFF, SCOPE_MASK, FREE, LOCAL, GLOBAL_IMPLICIT, GLOBAL_EXPLICIT, CELL) import weakref @@ -74,8 +74,7 @@ return self._table.lineno def is_optimized(self): - return bool(self._table.type == _symtable.TYPE_FUNCTION - and not self._table.optimized) + return bool(self._table.type == _symtable.TYPE_FUNCTION) def is_nested(self): return bool(self._table.nested) @@ -87,10 +86,6 @@ """Return true if the scope uses exec. Deprecated method.""" return False - def has_import_star(self): - """Return true if the scope uses import *""" - return bool(self._table.optimized & OPT_IMPORT_STAR) - def get_identifiers(self): return self._table.symbols.keys() diff --git a/Modules/symtablemodule.c b/Modules/symtablemodule.c --- a/Modules/symtablemodule.c +++ b/Modules/symtablemodule.c @@ -84,9 +84,6 @@ PyModule_AddIntConstant(m, "TYPE_CLASS", ClassBlock); PyModule_AddIntConstant(m, "TYPE_MODULE", ModuleBlock); - PyModule_AddIntMacro(m, OPT_IMPORT_STAR); - PyModule_AddIntMacro(m, OPT_TOPLEVEL); - PyModule_AddIntMacro(m, LOCAL); PyModule_AddIntMacro(m, GLOBAL_EXPLICIT); PyModule_AddIntMacro(m, GLOBAL_IMPLICIT); diff --git a/Python/compile.c b/Python/compile.c --- a/Python/compile.c +++ b/Python/compile.c @@ -2753,8 +2753,7 @@ optype = OP_FAST; break; case GLOBAL_IMPLICIT: - if (c->u->u_ste->ste_type == FunctionBlock && - !c->u->u_ste->ste_unoptimized) + if (c->u->u_ste->ste_type == FunctionBlock) optype = OP_GLOBAL; break; case GLOBAL_EXPLICIT: @@ -4185,9 +4184,7 @@ int flags = 0; Py_ssize_t n; if (ste->ste_type == FunctionBlock) { - flags |= CO_NEWLOCALS; - if (!ste->ste_unoptimized) - flags |= CO_OPTIMIZED; + flags |= CO_NEWLOCALS | CO_OPTIMIZED; if (ste->ste_nested) flags |= CO_NESTED; if (ste->ste_generator) diff --git a/Python/symtable.c b/Python/symtable.c --- a/Python/symtable.c +++ b/Python/symtable.c @@ -47,7 +47,6 @@ ste->ste_directives = NULL; ste->ste_type = block; - ste->ste_unoptimized = 0; ste->ste_nested = 0; ste->ste_free = 0; ste->ste_varargs = 0; @@ -113,7 +112,6 @@ {"symbols", T_OBJECT, OFF(ste_symbols), READONLY}, {"varnames", T_OBJECT, OFF(ste_varnames), READONLY}, {"children", T_OBJECT, OFF(ste_children), READONLY}, - {"optimized",T_INT, OFF(ste_unoptimized), READONLY}, {"nested", T_INT, OFF(ste_nested), READONLY}, {"type", T_INT, OFF(ste_type), READONLY}, {"lineno", T_INT, OFF(ste_lineno), READONLY}, @@ -271,7 +269,6 @@ } st->st_top = st->st_cur; - st->st_cur->ste_unoptimized = OPT_TOPLEVEL; switch (mod->kind) { case Module_kind: seq = mod->v.Module.body; @@ -1245,21 +1242,9 @@ break; case Import_kind: VISIT_SEQ(st, alias, s->v.Import.names); - /* XXX Don't have the lineno available inside - visit_alias */ - if (st->st_cur->ste_unoptimized && !st->st_cur->ste_opt_lineno) { - st->st_cur->ste_opt_lineno = s->lineno; - st->st_cur->ste_opt_col_offset = s->col_offset; - } break; case ImportFrom_kind: VISIT_SEQ(st, alias, s->v.ImportFrom.names); - /* XXX Don't have the lineno available inside - visit_alias */ - if (st->st_cur->ste_unoptimized && !st->st_cur->ste_opt_lineno) { - st->st_cur->ste_opt_lineno = s->lineno; - st->st_cur->ste_opt_col_offset = s->col_offset; - } break; case Global_kind: { int i; @@ -1615,7 +1600,6 @@ Py_DECREF(store_name); return 0; } - st->st_cur->ste_unoptimized |= OPT_IMPORT_STAR; Py_DECREF(store_name); return 1; } -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Tue Apr 28 04:40:41 2015 From: python-checkins at python.org (yury.selivanov) Date: Tue, 28 Apr 2015 02:40:41 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_pep-0492=3A_v3=3B_tp=5Fawait?= =?utf-8?q?=2C_noiter=2C_new_await_syntax=2C_etc?= Message-ID: <20150428024041.20324.3024@psf.io> https://hg.python.org/peps/rev/4f50594e091e changeset: 5801:4f50594e091e user: Yury Selivanov date: Mon Apr 27 22:40:36 2015 -0400 summary: pep-0492: v3; tp_await, noiter, new await syntax, etc files: pep-0492.txt | 130 ++++++++++++++++++++++++++++++-------- 1 files changed, 101 insertions(+), 29 deletions(-) diff --git a/pep-0492.txt b/pep-0492.txt --- a/pep-0492.txt +++ b/pep-0492.txt @@ -8,7 +8,7 @@ Content-Type: text/x-rst Created: 09-Apr-2015 Python-Version: 3.5 -Post-History: 17-Apr-2015, 21-Apr-2015 +Post-History: 17-Apr-2015, 21-Apr-2015, 27-Apr-2015 Abstract @@ -155,12 +155,40 @@ It is a ``TypeError`` if ``__await__`` returns anything but an iterator. +* Objects defined with CPython C API with a ``tp_await`` function, + returning an iterator (similar to ``__await__`` method). + It is a ``SyntaxError`` to use ``await`` outside of a coroutine. It is a ``TypeError`` to pass anything other than an *awaitable* object to an ``await`` expression. +Syntax of "await" expression +'''''''''''''''''''''''''''' + +``await`` keyword is defined differently from ``yield`` and ``yield +from``. The main difference is that *await expressions* do not require +parentheses around them most of the times. + +Examples:: + +================================== ================================== +Expression Will be parsed as +================================== ================================== +``if await fut: pass`` ``if (await fut): pass`` +``if await fut + 1: pass`` ``if (await fut) + 1: pass`` +``pair = await fut, 'spam'`` ``pair = (await fut), 'spam'`` +``with await fut, open(): pass`` ``with (await fut), open(): pass`` +``await foo()['spam'].baz()()`` ``await ( foo()['spam'].baz()() )`` +``return await coro()`` ``return ( await coro() )`` +``res = await coro() ** 2`` ``res = (await coro()) ** 2`` +``func(a1=await coro(), a2=0)`` ``func(a1=(await coro()), a2=0)`` +================================== ================================== + +See `Grammar Updates`_ section for details. + + Asynchronous Context Managers and "async with" ---------------------------------------------- @@ -487,6 +515,49 @@ unsets the wrapper. +inspect.iscoroutine() and inspect.iscoroutineobject() +----------------------------------------------------- + +Two new functions are added to the ``inspect`` module: + +* ``inspect.iscoroutine(obj)`` returns ``True`` if ``obj`` is a + coroutine object. + +* ``inspect.iscoroutinefunction(obj)`` returns ``True`` is ``obj`` is a + coroutine function. + + +Differences between coroutines and generators +--------------------------------------------- + +A great effort has been made to make sure that coroutines and +generators are separate concepts: + +1. Coroutine objects do not implement ``__iter__`` and ``__next__`` + methods. Therefore they cannot be iterated over or passed to + ``iter()``, ``list()``, ``tuple()`` and other built-ins. They + also cannot be used in a ``for..in`` loop. + +2. ``yield from`` does not accept coroutine objects (unless it is used + in a generator-based coroutine decorated with ``types.coroutine``.) + +3. ``yield from`` does not accept coroutine objects from plain Python + generators (*not* generator-based coroutines.) + +4. ``inspect.isgenerator()`` and ``inspect.isgeneratorfunction()`` + return ``False`` for coroutine objects and coroutine functions. + + +Coroutine objects +----------------- + +Coroutines are based on generators internally, thus they share the +implementation. Similarly to generator objects, coroutine objects have +``throw``, ``send`` and ``close`` methods. ``StopIteration`` and +``GeneratorExit`` play the same role for coroutine objects (although +PEP 479 is enabled by default for coroutines). + + Glossary ======== @@ -500,11 +571,12 @@ details. :Future-like object: - An object with an ``__await__`` method returning an iterator. Can - be consumed by an ``await`` expression in a coroutine. A coroutine - waiting for a Future-like object is suspended until the Future-like - object's ``__await__`` completes, and returns the result. See - `Await Expression`_ for details. + An object with an ``__await__`` method, or a C object with + ``tp_await`` function, returning an iterator. Can be consumed by + an ``await`` expression in a coroutine. A coroutine waiting for a + Future-like object is suspended until the Future-like object's + ``__await__`` completes, and returns the result. See `Await + Expression`_ for details. :Awaitable: A *Future-like* object or a *coroutine object*. See `Await @@ -602,29 +674,16 @@ Grammar changes are also fairly minimal:: - await_expr: AWAIT test - await_stmt: await_expr - decorated: decorators (classdef | funcdef | async_funcdef) async_funcdef: ASYNC funcdef + compound_stmt: (if_stmt | while_stmt | for_stmt | try_stmt | with_stmt + | funcdef | classdef | decorated | async_stmt) + async_stmt: ASYNC (funcdef | with_stmt | for_stmt) - compound_stmt: (if_stmt | while_stmt | for_stmt | try_stmt | - with_stmt | funcdef | classdef | decorated | - async_stmt) - - flow_stmt: (break_stmt | continue_stmt | return_stmt | - raise_stmt | yield_stmt | await_stmt) - - atom: ('(' [yield_expr|await_expr|testlist_comp] ')' | - '[' [testlist_comp] ']' | - '{' [dictorsetmaker] '}' | - NAME | NUMBER | STRING+ | '...' | 'None' | 'True' | 'False?) - - expr_stmt: testlist_star_expr - (augassign (yield_expr|await_expr|testlist) | - ('=' (yield_expr|await_expr|testlist_star_expr))*) + power: atom_expr ['**' factor] + atom_expr: [AWAIT] atom trailer* Transition Period Shortcomings @@ -889,6 +948,15 @@ with the existing grammar. +Why "async for/with" instead of "await for/with" +------------------------------------------------ + +``async`` is an adjective, and hence it is a better choice for a +*statement qualifier* keyword. ``await for/with`` would imply that +something is awaiting for a completion of a ``for`` or ``with`` +statement. + + Why "async def" and not "def async" ----------------------------------- @@ -946,11 +1014,13 @@ * it would not be possible to create an object that works in both ``with`` and ``async with`` statements; -* it would look confusing and would require some implicit magic behind - the scenes in the interpreter; +* it would break backwards compatibility, as nothing prohibits from + returning a Future-like objects from ``__enter__`` and/or + ``__exit__`` in Python <= 3.4; * one of the main points of this proposal is to make coroutines as - simple and foolproof as possible. + simple and foolproof as possible, hence the clear separation of the + protocols. Why not reuse existing "for" and "with" statements @@ -1074,7 +1144,8 @@ 1. New syntax for defining coroutines: ``async def`` and new ``await`` keyword. -2. New ``__await__`` method for Future-like objects. +2. New ``__await__`` method for Future-like objects, and new + ``tp_await`` slot in ``PyTypeObject``. 3. New syntax for asynchronous context managers: ``async with``. And associated protocol with ``__aenter__`` and ``__aexit__`` methods. @@ -1087,7 +1158,8 @@ ``Await``. 6. New functions: ``sys.set_coroutine_wrapper(callback)``, - ``sys.get_coroutine_wrapper()``, and ``types.coroutine(gen)``. + ``sys.get_coroutine_wrapper()``, ``types.coroutine(gen)``, + ``inspect.iscoroutinefunction()``, and ``inspect.iscoroutine()``. 7. New ``CO_COROUTINE`` bit flag for code objects. -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Tue Apr 28 05:02:34 2015 From: python-checkins at python.org (yury.selivanov) Date: Tue, 28 Apr 2015 03:02:34 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_pep-0492=3A_Fix_markup?= Message-ID: <20150428030234.65721.75923@psf.io> https://hg.python.org/peps/rev/5cc9ca92d9db changeset: 5802:5cc9ca92d9db user: Yury Selivanov date: Mon Apr 27 23:02:31 2015 -0400 summary: pep-0492: Fix markup files: pep-0492.txt | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/pep-0492.txt b/pep-0492.txt --- a/pep-0492.txt +++ b/pep-0492.txt @@ -171,7 +171,7 @@ from``. The main difference is that *await expressions* do not require parentheses around them most of the times. -Examples:: +Examples: ================================== ================================== Expression Will be parsed as -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Tue Apr 28 05:06:00 2015 From: python-checkins at python.org (yury.selivanov) Date: Tue, 28 Apr 2015 03:06:00 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_pep-0492=3A_Rename_section?= Message-ID: <20150428030600.22937.59384@psf.io> https://hg.python.org/peps/rev/c6cedc4620f9 changeset: 5803:c6cedc4620f9 user: Yury Selivanov date: Mon Apr 27 23:05:58 2015 -0400 summary: pep-0492: Rename section files: pep-0492.txt | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pep-0492.txt b/pep-0492.txt --- a/pep-0492.txt +++ b/pep-0492.txt @@ -948,8 +948,8 @@ with the existing grammar. -Why "async for/with" instead of "await for/with" ------------------------------------------------- +Why not "await for" and "await with" +------------------------------------ ``async`` is an adjective, and hence it is a better choice for a *statement qualifier* keyword. ``await for/with`` would imply that -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Tue Apr 28 05:24:30 2015 From: python-checkins at python.org (yury.selivanov) Date: Tue, 28 Apr 2015 03:24:30 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_pep-0492=3A_Add_one_more_=27a?= =?utf-8?q?wait=27_syntax_example?= Message-ID: <20150428032430.65697.61996@psf.io> https://hg.python.org/peps/rev/4110da8ae758 changeset: 5804:4110da8ae758 user: Yury Selivanov date: Mon Apr 27 23:24:26 2015 -0400 summary: pep-0492: Add one more 'await' syntax example files: pep-0492.txt | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/pep-0492.txt b/pep-0492.txt --- a/pep-0492.txt +++ b/pep-0492.txt @@ -184,6 +184,7 @@ ``return await coro()`` ``return ( await coro() )`` ``res = await coro() ** 2`` ``res = (await coro()) ** 2`` ``func(a1=await coro(), a2=0)`` ``func(a1=(await coro()), a2=0)`` +``await foo() + await bar()`` ``(await foo()) + (await bar())`` ================================== ================================== See `Grammar Updates`_ section for details. -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Tue Apr 28 06:04:56 2015 From: python-checkins at python.org (benjamin.peterson) Date: Tue, 28 Apr 2015 04:04:56 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_remove_deleted_method?= Message-ID: <20150428040456.20332.6502@psf.io> https://hg.python.org/cpython/rev/293d9964cf6e changeset: 95822:293d9964cf6e user: Benjamin Peterson date: Tue Apr 28 00:04:53 2015 -0400 summary: remove deleted method files: Doc/library/symtable.rst | 4 ---- 1 files changed, 0 insertions(+), 4 deletions(-) diff --git a/Doc/library/symtable.rst b/Doc/library/symtable.rst --- a/Doc/library/symtable.rst +++ b/Doc/library/symtable.rst @@ -71,10 +71,6 @@ Return ``True`` if the block uses ``exec``. - .. method:: has_import_star() - - Return ``True`` if the block uses a starred from-import. - .. method:: get_identifiers() Return a list of names of symbols in this table. -- Repository URL: https://hg.python.org/cpython From solipsis at pitrou.net Tue Apr 28 10:37:56 2015 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Tue, 28 Apr 2015 08:37:56 +0000 Subject: [Python-checkins] Daily reference leaks (293d9964cf6e): sum=3 Message-ID: <20150428083756.109696.81480@psf.io> results for 293d9964cf6e on branch "default" -------------------------------------------- test_functools leaked [0, 0, 3] memory blocks, sum=3 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogToKr6v', '--timeout', '7200'] From solipsis at pitrou.net Wed Apr 29 10:37:23 2015 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Wed, 29 Apr 2015 08:37:23 +0000 Subject: [Python-checkins] Daily reference leaks (293d9964cf6e): sum=3 Message-ID: <20150429083723.7794.99906@psf.io> results for 293d9964cf6e on branch "default" -------------------------------------------- test_functools leaked [0, 0, 3] memory blocks, sum=3 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogQQ9CxX', '--timeout', '7200'] From python-checkins at python.org Wed Apr 29 18:09:23 2015 From: python-checkins at python.org (yury.selivanov) Date: Wed, 29 Apr 2015 16:09:23 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_pep-0492=3A_Add_invalid_synta?= =?utf-8?q?x_examples=3B_fix_typo=2E?= Message-ID: <20150429160923.7800.89083@psf.io> https://hg.python.org/peps/rev/d048458307b7 changeset: 5805:d048458307b7 user: Yury Selivanov date: Wed Apr 29 12:09:19 2015 -0400 summary: pep-0492: Add invalid syntax examples; fix typo. files: pep-0492.txt | 14 ++++++++++++-- 1 files changed, 12 insertions(+), 2 deletions(-) diff --git a/pep-0492.txt b/pep-0492.txt --- a/pep-0492.txt +++ b/pep-0492.txt @@ -171,7 +171,7 @@ from``. The main difference is that *await expressions* do not require parentheses around them most of the times. -Examples: +Valid syntax examples: ================================== ================================== Expression Will be parsed as @@ -187,6 +187,16 @@ ``await foo() + await bar()`` ``(await foo()) + (await bar())`` ================================== ================================== +Invalid syntax examples: + +================================== ================================== +Expression Should be written as +================================== ================================== +``await await coro()`` ``await (await coro())`` +``await -coro()`` ``await (-coro())`` +================================== ================================== + + See `Grammar Updates`_ section for details. @@ -718,7 +728,7 @@ async def foo(): # 2 return (await fut) -This limitation will go away as soon as ``async`` and ``await`` ate +This limitation will go away as soon as ``async`` and ``await`` are proper keywords. Or if it's decided to use a future import for this PEP. -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Wed Apr 29 18:28:20 2015 From: python-checkins at python.org (yury.selivanov) Date: Wed, 29 Apr 2015 16:28:20 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_pep-0492=3A_Add_another_synta?= =?utf-8?q?x_example?= Message-ID: <20150429162820.25435.9376@psf.io> https://hg.python.org/peps/rev/3cbd6795d46a changeset: 5806:3cbd6795d46a user: Yury Selivanov date: Wed Apr 29 12:28:16 2015 -0400 summary: pep-0492: Add another syntax example files: pep-0492.txt | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/pep-0492.txt b/pep-0492.txt --- a/pep-0492.txt +++ b/pep-0492.txt @@ -185,6 +185,7 @@ ``res = await coro() ** 2`` ``res = (await coro()) ** 2`` ``func(a1=await coro(), a2=0)`` ``func(a1=(await coro()), a2=0)`` ``await foo() + await bar()`` ``(await foo()) + (await bar())`` +``-await foo()`` ``-(await foo())`` ================================== ================================== Invalid syntax examples: -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Wed Apr 29 23:53:57 2015 From: python-checkins at python.org (ned.deily) Date: Wed, 29 Apr 2015 21:53:57 +0000 Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzI0MDc3?= =?utf-8?q?=3A_Fix_typo_in_man_page_for_-I_command_option=3A_-s=2C_not_-S?= =?utf-8?q?=2E?= Message-ID: <20150429215357.25447.29573@psf.io> https://hg.python.org/cpython/rev/d774401879d8 changeset: 95823:d774401879d8 branch: 3.4 parent: 95819:69951573cb0e user: Ned Deily date: Wed Apr 29 14:51:43 2015 -0700 summary: Issue #24077: Fix typo in man page for -I command option: -s, not -S. files: Misc/NEWS | 2 ++ Misc/python.man | 2 +- 2 files changed, 3 insertions(+), 1 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -236,6 +236,8 @@ - Issue #24029: Document the name binding behavior for submodule imports. +- Issue #24077: Fix typo in man page for -I command option: -s, not -S. + Tools/Demos ----------- diff --git a/Misc/python.man b/Misc/python.man --- a/Misc/python.man +++ b/Misc/python.man @@ -143,7 +143,7 @@ raises an exception. .TP .B \-I -Run Python in isolated mode. This also implies \fB\-E\fP and \fB\-S\fP. In +Run Python in isolated mode. This also implies \fB\-E\fP and \fB\-s\fP. In isolated mode sys.path contains neither the script?s directory nor the user?s site-packages directory. All PYTHON* environment variables are ignored, too. Further restrictions may be imposed to prevent the user from injecting -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Wed Apr 29 23:53:58 2015 From: python-checkins at python.org (ned.deily) Date: Wed, 29 Apr 2015 21:53:58 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2324077=3A_merge_from_3=2E4?= Message-ID: <20150429215357.124202.89327@psf.io> https://hg.python.org/cpython/rev/493b3310d5d0 changeset: 95824:493b3310d5d0 parent: 95822:293d9964cf6e parent: 95823:d774401879d8 user: Ned Deily date: Wed Apr 29 14:53:34 2015 -0700 summary: Issue #24077: merge from 3.4 files: Misc/NEWS | 2 ++ Misc/python.man | 2 +- 2 files changed, 3 insertions(+), 1 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -49,6 +49,8 @@ - Issue #24029: Document the name binding behavior for submodule imports. +- Issue #24077: Fix typo in man page for -I command option: -s, not -S + Tools/Demos ----------- diff --git a/Misc/python.man b/Misc/python.man --- a/Misc/python.man +++ b/Misc/python.man @@ -143,7 +143,7 @@ raises an exception. .TP .B \-I -Run Python in isolated mode. This also implies \fB\-E\fP and \fB\-S\fP. In +Run Python in isolated mode. This also implies \fB\-E\fP and \fB\-s\fP. In isolated mode sys.path contains neither the script?s directory nor the user?s site-packages directory. All PYTHON* environment variables are ignored, too. Further restrictions may be imposed to prevent the user from injecting -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Apr 30 00:01:54 2015 From: python-checkins at python.org (benjamin.peterson) Date: Wed, 29 Apr 2015 22:01:54 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_improve_phrasi?= =?utf-8?q?ng?= Message-ID: <20150429220153.25435.90869@psf.io> https://hg.python.org/cpython/rev/6986ccbcf41e changeset: 95827:6986ccbcf41e branch: 2.7 parent: 95816:4234b0dd2a54 user: Benjamin Peterson date: Wed Apr 29 18:00:44 2015 -0400 summary: improve phrasing files: Misc/python.man | 3 +-- 1 files changed, 1 insertions(+), 2 deletions(-) diff --git a/Misc/python.man b/Misc/python.man --- a/Misc/python.man +++ b/Misc/python.man @@ -87,8 +87,7 @@ .SH DESCRIPTION Python is an interpreted, interactive, object-oriented programming language that combines remarkable power with very clear syntax. -For an introduction to programming in Python you are referred to the -Python Tutorial. +For an introduction to programming in Python, see the Python Tutorial. The Python Library Reference documents built-in and standard types, constants, functions and modules. Finally, the Python Reference Manual describes the syntax and -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Apr 30 00:01:54 2015 From: python-checkins at python.org (benjamin.peterson) Date: Wed, 29 Apr 2015 22:01:54 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?b?KTogbWVyZ2UgMy40?= Message-ID: <20150429220153.62663.52069@psf.io> https://hg.python.org/cpython/rev/93168607ad70 changeset: 95826:93168607ad70 parent: 95824:493b3310d5d0 parent: 95825:08c247ff8c1e user: Benjamin Peterson date: Wed Apr 29 18:00:57 2015 -0400 summary: merge 3.4 files: Misc/python.man | 3 +-- 1 files changed, 1 insertions(+), 2 deletions(-) diff --git a/Misc/python.man b/Misc/python.man --- a/Misc/python.man +++ b/Misc/python.man @@ -87,8 +87,7 @@ .SH DESCRIPTION Python is an interpreted, interactive, object-oriented programming language that combines remarkable power with very clear syntax. -For an introduction to programming in Python you are referred to the -Python Tutorial. +For an introduction to programming in Python, see the Python Tutorial. The Python Library Reference documents built-in and standard types, constants, functions and modules. Finally, the Python Reference Manual describes the syntax and -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Apr 30 00:01:53 2015 From: python-checkins at python.org (benjamin.peterson) Date: Wed, 29 Apr 2015 22:01:53 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E4=29=3A_improve_phrasi?= =?utf-8?q?ng?= Message-ID: <20150429220153.7798.92754@psf.io> https://hg.python.org/cpython/rev/08c247ff8c1e changeset: 95825:08c247ff8c1e branch: 3.4 parent: 95823:d774401879d8 user: Benjamin Peterson date: Wed Apr 29 18:00:44 2015 -0400 summary: improve phrasing files: Misc/python.man | 3 +-- 1 files changed, 1 insertions(+), 2 deletions(-) diff --git a/Misc/python.man b/Misc/python.man --- a/Misc/python.man +++ b/Misc/python.man @@ -87,8 +87,7 @@ .SH DESCRIPTION Python is an interpreted, interactive, object-oriented programming language that combines remarkable power with very clear syntax. -For an introduction to programming in Python you are referred to the -Python Tutorial. +For an introduction to programming in Python, see the Python Tutorial. The Python Library Reference documents built-in and standard types, constants, functions and modules. Finally, the Python Reference Manual describes the syntax and -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Apr 30 00:07:25 2015 From: python-checkins at python.org (yury.selivanov) Date: Wed, 29 Apr 2015 22:07:25 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_pep-0492=3A_Add_operator_prec?= =?utf-8?q?edence_table_for_await_expression=2E?= Message-ID: <20150429220725.3998.88885@psf.io> https://hg.python.org/peps/rev/d355918bc0d7 changeset: 5807:d355918bc0d7 user: Yury Selivanov date: Wed Apr 29 18:07:18 2015 -0400 summary: pep-0492: Add operator precedence table for await expression. files: pep-0492.txt | 74 +++++++++++++++++++++++++++++++++++++-- 1 files changed, 70 insertions(+), 4 deletions(-) diff --git a/pep-0492.txt b/pep-0492.txt --- a/pep-0492.txt +++ b/pep-0492.txt @@ -164,13 +164,80 @@ to an ``await`` expression. -Syntax of "await" expression -'''''''''''''''''''''''''''' +Updated operator precedence table +''''''''''''''''''''''''''''''''' ``await`` keyword is defined differently from ``yield`` and ``yield -from``. The main difference is that *await expressions* do not require +from`` in the Grammar. + +The key difference is that *await expressions* do not require parentheses around them most of the times. +Also, ``yield from`` allows any expression as its argument, including +expressions like ``yield from a() + b()``, that would be parsed as +``yield from (a() + b())``, which is almost always a bug. In general, +the result of any arithmetic operation is not an *awaitable* object. +To avoid this kind of mistakes, it was decided to make ``await`` +precedence lower than ``[]``, ``()``, and ``.``, but higher than ``**`` +operators. + ++------------------------------+-----------------------------------+ +| Operator | Description | ++==============================+===================================+ +| ``yield``, ``yield from`` | Yield expression | ++------------------------------+-----------------------------------+ +| ``lambda`` | Lambda expression | ++------------------------------+-----------------------------------+ +| ``if`` -- ``else`` | Conditional expression | ++------------------------------+-----------------------------------+ +| ``or`` | Boolean OR | ++------------------------------+-----------------------------------+ +| ``and`` | Boolean AND | ++------------------------------+-----------------------------------+ +| ``not`` ``x`` | Boolean NOT | ++------------------------------+-----------------------------------+ +| ``in``, ``not in``, | Comparisons, including membership | +| ``is``, ``is not``, ``<``, | tests and identity tests | +| ``<=``, ``>``, ``>=``, | | +| ``!=``, ``==`` | | ++------------------------------+-----------------------------------+ +| ``|`` | Bitwise OR | ++------------------------------+-----------------------------------+ +| ``^`` | Bitwise XOR | ++------------------------------+-----------------------------------+ +| ``&`` | Bitwise AND | ++------------------------------+-----------------------------------+ +| ``<<``, ``>>`` | Shifts | ++------------------------------+-----------------------------------+ +| ``+``, ``-`` | Addition and subtraction | ++------------------------------+-----------------------------------+ +| ``*``, ``@``, ``/``, ``//``, | Multiplication, matrix | +| ``%`` | multiplication, division, | +| | remainder | ++------------------------------+-----------------------------------+ +| ``+x``, ``-x``, ``~x`` | Positive, negative, bitwise NOT | ++------------------------------+-----------------------------------+ +| ``**`` | Exponentiation | ++------------------------------+-----------------------------------+ +| ``await`` | Await expression | ++------------------------------+-----------------------------------+ +| ``x[index]``, | Subscription, slicing, | +| ``x[index:index]``, | call, attribute reference | +| ``x(arguments...)``, | | +| ``x.attribute`` | | ++------------------------------+-----------------------------------+ +| ``(expressions...)``, | Binding or tuple display, | +| ``[expressions...]``, | list display, | +| ``{key: value...}``, | dictionary display, | +| ``{expressions...}`` | set display | ++------------------------------+-----------------------------------+ + +See `Grammar Updates`_ section for details. + + +Examples of "await" expressions +''''''''''''''''''''''''''''''' + Valid syntax examples: ================================== ================================== @@ -197,7 +264,6 @@ ``await -coro()`` ``await (-coro())`` ================================== ================================== - See `Grammar Updates`_ section for details. -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Thu Apr 30 00:18:15 2015 From: python-checkins at python.org (yury.selivanov) Date: Wed, 29 Apr 2015 22:18:15 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_pep-0492=3A_Incorporate_some_?= =?utf-8?q?feedback_from_Stephen_J=2E_Turnbull=2E?= Message-ID: <20150429221815.124182.99377@psf.io> https://hg.python.org/peps/rev/8472dc165730 changeset: 5808:8472dc165730 user: Yury Selivanov date: Wed Apr 29 18:18:11 2015 -0400 summary: pep-0492: Incorporate some feedback from Stephen J. Turnbull. files: pep-0492.txt | 19 +++++++++---------- 1 files changed, 9 insertions(+), 10 deletions(-) diff --git a/pep-0492.txt b/pep-0492.txt --- a/pep-0492.txt +++ b/pep-0492.txt @@ -60,9 +60,11 @@ support in Python, it does not change the internal implementation of coroutines, which are still based on generators. -It is strongly suggested that the reader understands how coroutines are -implemented in Python (PEP 342 and PEP 380). It is also recommended to -read PEP 3156 (asyncio framework) and PEP 3152 (Cofunctions). +This specification presumes knowledge of the implementation of +coroutines in Python (PEP 342 and PEP 380). Motivation for the syntax +changes proposed here comes from the asyncio framework (PEP 3156) and +the "Cofunctions" proposal (PEP 3152, now rejected in favor of this +specification). From this point in this document we use the word *coroutine* to refer to functions declared using the new syntax. *generator-based @@ -1114,18 +1116,15 @@ Comprehensions -------------- -For the sake of restricting the broadness of this PEP there is no new -syntax for asynchronous comprehensions. This should be considered in a -separate PEP, if there is a strong demand for this feature. +Syntax for asynchronous comprehensions could be provided, but this +construct is outside of the scope of this PEP. Async lambdas ------------- -Lambda coroutines are not part of this proposal. In this proposal they -would look like ``async lambda(parameters): expression``. Unless there -is a strong demand to have them as part of this proposal, it is -recommended to consider them later in a separate PEP. +Syntax for asynchronous lambda functions could be provided, but this +construct is outside of the scope of this PEP. Performance -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Thu Apr 30 02:17:52 2015 From: python-checkins at python.org (nick.coghlan) Date: Thu, 30 Apr 2015 00:17:52 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_PEP_476=3A_improve_guidance_o?= =?utf-8?q?n_opting_out?= Message-ID: <20150430001751.7802.27782@psf.io> https://hg.python.org/peps/rev/dfd96ee9d6a8 changeset: 5809:dfd96ee9d6a8 user: Nick Coghlan date: Thu Apr 30 10:17:44 2015 +1000 summary: PEP 476: improve guidance on opting out files: pep-0476.txt | 32 +++++++++++++++++++++++++++----- 1 files changed, 27 insertions(+), 5 deletions(-) diff --git a/pep-0476.txt b/pep-0476.txt --- a/pep-0476.txt +++ b/pep-0476.txt @@ -121,8 +121,9 @@ Opting out ---------- -For users who wish to opt out of certificate verification, they can achieve -this by providing the ``context`` argument to ``urllib.urlopen``:: +For users who wish to opt out of certificate verification on a single +connection, they can achieve this by providing the ``context`` argument to +``urllib.urlopen``:: import ssl @@ -130,12 +131,33 @@ context = ssl._create_unverified_context() urllib.urlopen("https://no-valid-cert", context=context) -It is also possible **though highly discouraged** to globally disable -verification by monkeypatching the ``ssl`` module:: +It is also possible, **though highly discouraged**, to globally disable +verification by monkeypatching the ``ssl`` module in versions of Python that +implement this PEP:: import ssl - ssl._create_default_https_context = ssl._create_unverified_context + try: + _create_unverified_https_context = ssl._create_unverified_context + except AttributeError: + # Legacy Python that doesn't verify HTTPS certificates by default + pass + else: + # Handle target environment that doesn't support HTTPS verification + ssl._create_default_https_context = _create_unverified_https_context + +This guidance is aimed primarily at system administrators that wish to adopt +newer versions of Python that implement this PEP in legacy environments that +do not yet support certificate verification on HTTPS connections. For +example, an administrator may opt out by adding the monkeypatch above to +``sitecustomize.py`` in their Standard Operating Environment for Python. +Applications and libraries SHOULD NOT be making this change process wide +(except perhaps in response to a system administrator controlled configuration +setting). + +Particularly security sensitive applications should always provide an explicit +application defined SSL context rather than relying on the default behaviour +of the underlying Python implementation. Other protocols =============== -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Thu Apr 30 03:30:29 2015 From: python-checkins at python.org (yury.selivanov) Date: Thu, 30 Apr 2015 01:30:29 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_pep-0492=3A_v4=2E?= Message-ID: <20150430013029.7810.58432@psf.io> https://hg.python.org/peps/rev/f37b0c1fb126 changeset: 5810:f37b0c1fb126 user: Yury Selivanov date: Wed Apr 29 21:11:53 2015 -0400 summary: pep-0492: v4. files: pep-0492.txt | 348 ++++++++++++++++++++++---------------- 1 files changed, 201 insertions(+), 147 deletions(-) diff --git a/pep-0492.txt b/pep-0492.txt --- a/pep-0492.txt +++ b/pep-0492.txt @@ -8,7 +8,7 @@ Content-Type: text/x-rst Created: 09-Apr-2015 Python-Version: 3.5 -Post-History: 17-Apr-2015, 21-Apr-2015, 27-Apr-2015 +Post-History: 17-Apr-2015, 21-Apr-2015, 27-Apr-2015, 29-Apr-2015 Abstract @@ -57,8 +57,7 @@ ============= This proposal introduces new syntax and semantics to enhance coroutine -support in Python, it does not change the internal implementation of -coroutines, which are still based on generators. +support in Python. This specification presumes knowledge of the implementation of coroutines in Python (PEP 342 and PEP 380). Motivation for the syntax @@ -66,21 +65,22 @@ the "Cofunctions" proposal (PEP 3152, now rejected in favor of this specification). -From this point in this document we use the word *coroutine* to refer -to functions declared using the new syntax. *generator-based +From this point in this document we use the word *native coroutine* to +refer to functions declared using the new syntax. *generator-based coroutine* is used where necessary to refer to coroutines that are -based on generator syntax. +based on generator syntax. *coroutine* is used in contexts where both +definitions are applicable. New Coroutine Declaration Syntax -------------------------------- -The following new syntax is used to declare a coroutine:: +The following new syntax is used to declare a *native coroutine*:: async def read_data(db): pass -Key properties of coroutines: +Key properties of *native coroutines*: * ``async def`` functions are always coroutines, even if they do not contain ``await`` expressions. @@ -88,10 +88,16 @@ * It is a ``SyntaxError`` to have ``yield`` or ``yield from`` expressions in an ``async`` function. -* Internally, a new code object flag - ``CO_COROUTINE`` - is introduced - to enable runtime detection of coroutines (and migrating existing - code). All coroutines have both ``CO_COROUTINE`` and ``CO_GENERATOR`` - flags set. +* Internally, two new code object flags were introduced: + + - ``CO_COROUTINE`` is used to enable runtime detection of + *coroutines* (and migrating existing code). + + - ``CO_NATIVE_COROUTINE`` is used to mark *native coroutines* + (defined with new syntax.) + + All coroutines have ``CO_COROUTINE``, ``CO_NATIVE_COROUTINE``, and + ``CO_GENERATOR`` flags set. * Regular generators, when called, return a *generator object*; similarly, coroutines return a *coroutine object*. @@ -100,15 +106,25 @@ and are replaced with a ``RuntimeError``. For regular generators such behavior requires a future import (see PEP 479). +* See also `Coroutine objects`_ section. + types.coroutine() ----------------- A new function ``coroutine(gen)`` is added to the ``types`` module. It -applies ``CO_COROUTINE`` flag to the passed generator-function's code -object, making it to return a *coroutine object* when called. +allows interoperability between existing *generator-based coroutines* +in asyncio and *native coroutines* introduced by this PEP. -This feature enables an easy upgrade path for existing libraries. +The function applies ``CO_COROUTINE`` flag to generator-function's code +object, making it return a *coroutine object*. + +The function can be used as a decorator, since it modifies generator- +functions in-place and returns them. + +Note, that the ``CO_NATIVE_COROUTINE`` flag is not applied by +``types.coroutine()`` to make it possible to separate *native +coroutines* defined with new syntax, from *generator-based coroutines*. Await Expression @@ -129,7 +145,9 @@ validating its argument. ``await`` only accepts an *awaitable*, which can be one of: -* A *coroutine object* returned from a *coroutine* or a generator +* A *native coroutine object* returned from a *native coroutine*. + +* A *generator-based coroutine object* returned from a generator decorated with ``types.coroutine()``. * An object with an ``__await__`` method returning an iterator. @@ -142,7 +160,7 @@ explanation.) To enable this behavior for coroutines, a new magic method called - ``__await__`` is added. In asyncio, for instance, to enable Future + ``__await__`` is added. In asyncio, for instance, to enable *Future* objects in ``await`` statements, the only change is to add ``__await__ = __iter__`` line to ``asyncio.Future`` class. @@ -160,7 +178,9 @@ * Objects defined with CPython C API with a ``tp_await`` function, returning an iterator (similar to ``__await__`` method). -It is a ``SyntaxError`` to use ``await`` outside of a coroutine. +It is a ``SyntaxError`` to use ``await`` outside of an ``async def`` +function (like it is a ``SyntaxError`` to use ``yield`` outside of +``def`` function.) It is a ``TypeError`` to pass anything other than an *awaitable* object to an ``await`` expression. @@ -169,11 +189,22 @@ Updated operator precedence table ''''''''''''''''''''''''''''''''' -``await`` keyword is defined differently from ``yield`` and ``yield -from`` in the Grammar. +``await`` keyword is defined as follows:: -The key difference is that *await expressions* do not require -parentheses around them most of the times. + power ::= await ["**" u_expr] + await ::= ["await"] primary + +where "primary" represents the most tightly bound operations of the +language. Its syntax is:: + + primary ::= atom | attributeref | subscription | slicing | call + +See Python Documentation [12]_ and `Grammar Updates`_ section of this +proposal for details. + +The key ``await`` difference from ``yield`` and ``yield from`` +operators is that *await expressions* do not require parentheses around +them most of the times. Also, ``yield from`` allows any expression as its argument, including expressions like ``yield from a() + b()``, that would be parsed as @@ -186,7 +217,8 @@ +------------------------------+-----------------------------------+ | Operator | Description | +==============================+===================================+ -| ``yield``, ``yield from`` | Yield expression | +| ``yield`` ``x``, | Yield expression | +| ``yield from`` ``x`` | | +------------------------------+-----------------------------------+ | ``lambda`` | Lambda expression | +------------------------------+-----------------------------------+ @@ -221,7 +253,7 @@ +------------------------------+-----------------------------------+ | ``**`` | Exponentiation | +------------------------------+-----------------------------------+ -| ``await`` | Await expression | +| ``await`` ``x`` | Await expression | +------------------------------+-----------------------------------+ | ``x[index]``, | Subscription, slicing, | | ``x[index:index]``, | call, attribute reference | @@ -234,8 +266,6 @@ | ``{expressions...}`` | set display | +------------------------------+-----------------------------------+ -See `Grammar Updates`_ section for details. - Examples of "await" expressions ''''''''''''''''''''''''''''''' @@ -266,8 +296,6 @@ ``await -coro()`` ``await (-coro())`` ================================== ================================== -See `Grammar Updates`_ section for details. - Asynchronous Context Managers and "async with" ---------------------------------------------- @@ -306,18 +334,13 @@ exc = True try: - try: - VAR = await aenter - BLOCK - except: - exc = False - exit_res = await aexit(mgr, *sys.exc_info()) - if not exit_res: - raise - - finally: - if exc: - await aexit(mgr, None, None, None) + VAR = await aenter + BLOCK + except: + if not await aexit(mgr, *sys.exc_info()): + raise + else: + await aexit(mgr, None, None, None) As with regular ``with`` statements, it is possible to specify multiple @@ -325,13 +348,13 @@ It is an error to pass a regular context manager without ``__aenter__`` and ``__aexit__`` methods to ``async with``. It is a ``SyntaxError`` -to use ``async with`` outside of a coroutine. +to use ``async with`` outside of an ``async def`` function. Example ''''''' -With asynchronous context managers it is easy to implement proper +With *asynchronous context managers* it is easy to implement proper database transaction managers for coroutines:: async def commit(session, data): @@ -416,7 +439,7 @@ It is a ``TypeError`` to pass a regular iterable without ``__aiter__`` method to ``async for``. It is a ``SyntaxError`` to use ``async for`` -outside of a coroutine. +outside of an ``async def`` function. As for with regular ``for`` statement, ``async for`` has an optional ``else`` clause. @@ -536,11 +559,61 @@ raised in coroutines are wrapped in ``RuntimeError``. +Coroutine objects +----------------- + +Differences from generators +''''''''''''''''''''''''''' + +This section applies only to *native coroutines* with +``CO_NATIVE_COROUTINE`` flag, i.e. defined with the new ``async def`` +syntax. + +**The behavior of existing *generator-based coroutines* in asyncio +remains unchanged.** + +Great effort has been made to make sure that coroutines and +generators are treated as distinct concepts: + +1. *Native coroutine objects* do not implement ``__iter__`` and + ``__next__`` methods. Therefore, they cannot be iterated over or + passed to ``iter()``, ``list()``, ``tuple()`` and other built-ins. + They also cannot be used in a ``for..in`` loop. + + An attempt to use ``__iter__`` or ``__next__`` on a *native + coroutine object* will result in a ``TypeError``. + +2. *Plain generators* cannot ``yield from`` *native coroutine objects*: + doing so will result in a ``TypeError``. + +3. *generator-based coroutines* (for asyncio code must be decorated + with ``@asyncio.coroutine``) can ``yield from`` *native coroutine + objects*. + +4. ``inspect.isgenerator()`` and ``inspect.isgeneratorfunction()`` + return ``False`` for *native coroutine objects* and *native + coroutine functions*. + + +Coroutine object methods +'''''''''''''''''''''''' + +Coroutines are based on generators internally, thus they share the +implementation. Similarly to generator objects, coroutine objects have +``throw()``, ``send()`` and ``close()`` methods. ``StopIteration`` and +``GeneratorExit`` play the same role for coroutine objects (although +PEP 479 is enabled by default for coroutines). See PEP 342, PEP 380, +and Python Documentation [11]_ for details. + +``throw()``, ``send()`` methods for coroutine objects are used to push +values and raise errors into *Future-like* objects. + + Debugging Features ------------------ -One of the most frequent mistakes that people make when using -generators as coroutines is forgetting to use ``yield from``:: +A common beginner mistake is forgetting to use ``yield from`` on +coroutines:: @asyncio.coroutine def useful(): @@ -590,65 +663,58 @@ # previously set wrapper assert not isinstance(debug_me(), asyncio.CoroWrapper) -If ``sys.set_coroutine_wrapper()`` is called twice, the new wrapper -replaces the previous wrapper. ``sys.set_coroutine_wrapper(None)`` -unsets the wrapper. +New Standard Library Functions +------------------------------ -inspect.iscoroutine() and inspect.iscoroutineobject() ------------------------------------------------------ - -Two new functions are added to the ``inspect`` module: +* ``types.coroutine(gen)``. See `types.coroutine()`_ section for + details. * ``inspect.iscoroutine(obj)`` returns ``True`` if ``obj`` is a - coroutine object. + *coroutine object*. -* ``inspect.iscoroutinefunction(obj)`` returns ``True`` is ``obj`` is a - coroutine function. +* ``inspect.iscoroutinefunction(obj)`` returns ``True`` if ``obj`` is a + *coroutine function*. +* ``inspect.isawaitable(obj)`` returns ``True`` if ``obj`` can be used + in ``await`` expression. See `Await Expression`_ for details. -Differences between coroutines and generators ---------------------------------------------- +* ``sys.set_coroutine_wrapper(wraper)`` allows to intercept creation of + *coroutine objects*. ``wraper`` must be a callable that accepts one + argument: a *coroutine object* or ``None``. ``None`` resets the + wrapper. If called twice, the new wrapper replaces the previous one. + See `Debugging Features`_ for more details. -A great effort has been made to make sure that coroutines and -generators are separate concepts: - -1. Coroutine objects do not implement ``__iter__`` and ``__next__`` - methods. Therefore they cannot be iterated over or passed to - ``iter()``, ``list()``, ``tuple()`` and other built-ins. They - also cannot be used in a ``for..in`` loop. - -2. ``yield from`` does not accept coroutine objects (unless it is used - in a generator-based coroutine decorated with ``types.coroutine``.) - -3. ``yield from`` does not accept coroutine objects from plain Python - generators (*not* generator-based coroutines.) - -4. ``inspect.isgenerator()`` and ``inspect.isgeneratorfunction()`` - return ``False`` for coroutine objects and coroutine functions. - - -Coroutine objects ------------------ - -Coroutines are based on generators internally, thus they share the -implementation. Similarly to generator objects, coroutine objects have -``throw``, ``send`` and ``close`` methods. ``StopIteration`` and -``GeneratorExit`` play the same role for coroutine objects (although -PEP 479 is enabled by default for coroutines). +* ``sys.get_coroutine_wrapper()`` returns the current wrapper object. + Returns ``None`` if no wrapper was set. See `Debugging Features`_ + for more details. Glossary ======== +:Native coroutine: + A coroutine function is declared with ``async def``. It uses + ``await`` and ``return value``; see `New Coroutine Declaration + Syntax`_ for details. + +:Native coroutine object: + Returned from a native coroutine function. See `Await Expression`_ + for details. + +:Generator-based coroutine: + Coroutines based on generator syntax. Most common example are + functions decorated with ``@asyncio.coroutine``. + +:Generator-based coroutine object: + Returned from a generator-based coroutine function. + :Coroutine: - A coroutine function, or just "coroutine", is declared with ``async - def``. It uses ``await`` and ``return value``; see `New Coroutine - Declaration Syntax`_ for details. + Either *native coroutine* or *generator-based coroutine*. :Coroutine object: - Returned from a coroutine function. See `Await Expression`_ for - details. + Either *native coroutine object* or *generator-based coroutine + object*. :Future-like object: An object with an ``__await__`` method, or a C object with @@ -662,10 +728,6 @@ A *Future-like* object or a *coroutine object*. See `Await Expression`_ for details. -:Generator-based coroutine: - Coroutines based in generator syntax. Most common example is - ``@asyncio.coroutine``. - :Asynchronous context manager: An asynchronous context manager has ``__aenter__`` and ``__aexit__`` methods and can be used with ``async with``. See `Asynchronous @@ -696,7 +758,7 @@ Where: -* "async def func": coroutine; +* "async def func": native coroutine; * "async def __a*__": ``__aiter__``, ``__anext__``, ``__aenter__``, ``__aexit__`` defined with the ``async`` keyword; @@ -720,12 +782,13 @@ it: * recognizes ``async def`` name tokens combination (start of a - coroutine); + native coroutine); -* keeps track of regular functions and coroutines; +* keeps track of regular functions and native coroutines; * replaces ``'async'`` token with ``ASYNC`` and ``'await'`` token with - ``AWAIT`` when in the process of yielding tokens for coroutines. + ``AWAIT`` when in the process of yielding tokens for native + coroutines. This approach allows for seamless combination of new syntax features (all of them available only in ``async`` functions) with any existing @@ -749,6 +812,34 @@ This proposal preserves 100% backwards compatibility. +asyncio +------- + +``asyncio`` module was adapted and tested to work with coroutines and +new statements. Backwards compatibility is 100% preserved, i.e. all +existing code will work as-is. + +The required changes are mainly: + +1. Modify ``@asyncio.coroutine`` decorator to use new + ``types.coroutine()`` function. + +2. Add ``__await__ = __iter__`` line to ``asyncio.Future`` class. + +3. Add ``ensure_task()`` as an alias for ``async()`` function. + Deprecate ``async()`` function. + + +Migration strategy +'''''''''''''''''' + +Because *plain generators* cannot ``yield from`` *native coroutine +objects* (see `Differences from generators`_ section for more details), +it is advised to make sure that all generator-based coroutines are +decorated with ``@asyncio.coroutine`` *before* starting to use the new +syntax. + + Grammar Updates --------------- @@ -811,23 +902,6 @@ for people to port their code to Python 3. -asyncio -------- - -``asyncio`` module was adapted and tested to work with coroutines and -new statements. Backwards compatibility is 100% preserved. - -The required changes are mainly: - -1. Modify ``@asyncio.coroutine`` decorator to use new - ``types.coroutine()`` function. - -2. Add ``__await__ = __iter__`` line to ``asyncio.Future`` class. - -3. Add ``ensure_task()`` as an alias for ``async()`` function. - Deprecate ``async()`` function. - - Design Considerations ===================== @@ -928,31 +1002,6 @@ for a separate PEP. -No implicit wrapping in Futures -------------------------------- - -There is a proposal to add similar mechanism to ECMAScript 7 [2]_. A -key difference is that JavaScript "async functions" always return a -Promise. While this approach has some advantages, it also implies that -a new Promise object is created on each "async function" invocation. - -We could implement a similar functionality in Python, by wrapping all -coroutines in a Future object, but this has the following -disadvantages: - -1. Performance. A new Future object would be instantiated on each - coroutine call. Moreover, this makes implementation of ``await`` - expressions slower (disabling optimizations of ``yield from``). - -2. A new built-in ``Future`` object would need to be added. - -3. Coming up with a generic ``Future`` interface that is usable for any - use case in any framework is a very hard to solve problem. - -4. It is not a feature that is used frequently, when most of the code - is coroutines. - - Why "async" and "await" keywords -------------------------------- @@ -978,8 +1027,8 @@ project easier (Python with ECMAScript 7 for instance). -Why "__aiter__" is a coroutine ------------------------------- +Why "__aiter__" returns awaitable +--------------------------------- In principle, ``__aiter__`` could be a regular function. There are several good reasons to make it a coroutine: @@ -1098,9 +1147,9 @@ returning a Future-like objects from ``__enter__`` and/or ``__exit__`` in Python <= 3.4; -* one of the main points of this proposal is to make coroutines as - simple and foolproof as possible, hence the clear separation of the - protocols. +* one of the main points of this proposal is to make native coroutines + as simple and foolproof as possible, hence the clear separation of + the protocols. Why not reuse existing "for" and "with" statements @@ -1120,8 +1169,8 @@ construct is outside of the scope of this PEP. -Async lambdas -------------- +Async lambda functions +---------------------- Syntax for asynchronous lambda functions could be provided, but this construct is outside of the scope of this PEP. @@ -1236,9 +1285,11 @@ 6. New functions: ``sys.set_coroutine_wrapper(callback)``, ``sys.get_coroutine_wrapper()``, ``types.coroutine(gen)``, - ``inspect.iscoroutinefunction()``, and ``inspect.iscoroutine()``. + ``inspect.iscoroutinefunction()``, ``inspect.iscoroutine()``, + and ``inspect.isawaitable()``. -7. New ``CO_COROUTINE`` bit flag for code objects. +7. New ``CO_COROUTINE`` and ``CO_NATIVE_COROUTINE`` bit flags for code + objects. While the list of changes and new things is not short, it is important to understand, that most users will not use these features directly. @@ -1305,6 +1356,9 @@ .. [10] http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3722.pdf (PDF) +.. [11] https://docs.python.org/3/reference/expressions.html#generator-iterator-methods + +.. [12] https://docs.python.org/3/reference/expressions.html#primaries Acknowledgments =============== -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Thu Apr 30 05:10:27 2015 From: python-checkins at python.org (yury.selivanov) Date: Thu, 30 Apr 2015 03:10:27 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_pep-0492=3A_Reword_tokenizati?= =?utf-8?q?on_algorithm_description=2E?= Message-ID: <20150430031027.7818.78751@psf.io> https://hg.python.org/peps/rev/552773d7e085 changeset: 5811:552773d7e085 user: Yury Selivanov date: Wed Apr 29 23:10:23 2015 -0400 summary: pep-0492: Reword tokenization algorithm description. files: pep-0492.txt | 16 +++++++++------- 1 files changed, 9 insertions(+), 7 deletions(-) diff --git a/pep-0492.txt b/pep-0492.txt --- a/pep-0492.txt +++ b/pep-0492.txt @@ -781,14 +781,16 @@ keywords, it was decided to modify ``tokenizer.c`` in such a way, that it: -* recognizes ``async def`` name tokens combination (start of a - native coroutine); +* recognizes ``async def`` ``NAME`` tokens combination; -* keeps track of regular functions and native coroutines; +* keeps track of regular ``def`` and ``async def`` indented blocks; -* replaces ``'async'`` token with ``ASYNC`` and ``'await'`` token with - ``AWAIT`` when in the process of yielding tokens for native - coroutines. +* while tokenizing ``async def`` block, it replaces ``'async'`` + ``NAME`` token with ``ASYNC``, and ``'await'`` ``NAME`` token with + ``AWAIT``; + +* while tokenizing ``def`` block, it yields ``'async'`` and ``'await'`` + ``NAME`` tokens as is. This approach allows for seamless combination of new syntax features (all of them available only in ``async`` functions) with any existing @@ -843,7 +845,7 @@ Grammar Updates --------------- -Grammar changes are also fairly minimal:: +Grammar changes are fairly minimal:: decorated: decorators (classdef | funcdef | async_funcdef) async_funcdef: ASYNC funcdef -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Thu Apr 30 05:18:06 2015 From: python-checkins at python.org (yury.selivanov) Date: Thu, 30 Apr 2015 03:18:06 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_pep-0492=3A_Rewrite_=22Why_no?= =?utf-8?q?t_a_=5F=5Ffuture=5F=5F_import=22_section=3B_tx_to_Nick_Coghlan?= =?utf-8?q?=2E?= Message-ID: <20150430031806.3501.18733@psf.io> https://hg.python.org/peps/rev/5db3ad3d540b changeset: 5812:5db3ad3d540b user: Yury Selivanov date: Wed Apr 29 23:18:03 2015 -0400 summary: pep-0492: Rewrite "Why not a __future__ import" section; tx to Nick Coghlan. files: pep-0492.txt | 13 +++++-------- 1 files changed, 5 insertions(+), 8 deletions(-) diff --git a/pep-0492.txt b/pep-0492.txt --- a/pep-0492.txt +++ b/pep-0492.txt @@ -1108,14 +1108,11 @@ Why not a __future__ import --------------------------- -``__future__`` imports are inconvenient and easy to forget to add. -Also, they are enabled for the whole source file. Consider that there -is a big project with a popular module named "async.py". With future -imports it is required to either import it using ``__import__()`` or -``importlib.import_module()`` calls, or to rename the module. The -proposed approach makes it possible to continue using old code and -modules without a hassle, while coming up with a migration plan for -future python versions. +`Transition Plan`_ section explains how tokenizer is modified to treat +``async`` and ``await`` as keywords *only* in ``async def`` blocks. +Hence ``async def`` fills the role that a module level compiler +declaration like ``from __future__ import async_await`` would otherwise +fill. Why magic methods start with "a" -- Repository URL: https://hg.python.org/peps From python-checkins at python.org Thu Apr 30 05:25:49 2015 From: python-checkins at python.org (yury.selivanov) Date: Thu, 30 Apr 2015 03:25:49 +0000 Subject: [Python-checkins] =?utf-8?q?peps=3A_pep-0492=3A_Drop_=5F=5Ffuture?= =?utf-8?q?=5F=5F_from_=22Transition_Period_Shortcomings=22?= Message-ID: <20150430032549.85191.69082@psf.io> https://hg.python.org/peps/rev/ffe5f363fd88 changeset: 5813:ffe5f363fd88 user: Yury Selivanov date: Wed Apr 29 23:25:46 2015 -0400 summary: pep-0492: Drop __future__ from "Transition Period Shortcomings" files: pep-0492.txt | 3 +-- 1 files changed, 1 insertions(+), 2 deletions(-) diff --git a/pep-0492.txt b/pep-0492.txt --- a/pep-0492.txt +++ b/pep-0492.txt @@ -891,8 +891,7 @@ return (await fut) This limitation will go away as soon as ``async`` and ``await`` are -proper keywords. Or if it's decided to use a future import for this -PEP. +proper keywords. Deprecation Plans -- Repository URL: https://hg.python.org/peps From solipsis at pitrou.net Thu Apr 30 10:37:22 2015 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Thu, 30 Apr 2015 08:37:22 +0000 Subject: [Python-checkins] Daily reference leaks (93168607ad70): sum=3 Message-ID: <20150430083721.3970.3419@psf.io> results for 93168607ad70 on branch "default" -------------------------------------------- test_functools leaked [0, 0, 3] memory blocks, sum=3 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflog0E2TER', '--timeout', '7200'] From python-checkins at python.org Thu Apr 30 13:44:56 2015 From: python-checkins at python.org (matthias.klose) Date: Thu, 30 Apr 2015 11:44:56 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?b?KTogIC0gbWVyZ2UgMy40?= Message-ID: <20150430114456.1919.6122@psf.io> https://hg.python.org/cpython/rev/5d065807a05f changeset: 95829:5d065807a05f parent: 95826:93168607ad70 parent: 95828:eb09f737120b user: doko at ubuntu.com date: Thu Apr 30 13:44:43 2015 +0200 summary: - merge 3.4 files: Makefile.pre.in | 3 +-- 1 files changed, 1 insertions(+), 2 deletions(-) diff --git a/Makefile.pre.in b/Makefile.pre.in --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -1137,8 +1137,7 @@ # Install the library PLATDIR= @PLATDIR@ -EXTRAPLATDIR= @EXTRAPLATDIR@ -MACHDEPS= $(PLATDIR) $(EXTRAPLATDIR) +MACHDEPS= $(PLATDIR) XMLLIBSUBDIRS= xml xml/dom xml/etree xml/parsers xml/sax LIBSUBDIRS= tkinter tkinter/test tkinter/test/test_tkinter \ tkinter/test/test_ttk site-packages test \ -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Apr 30 13:44:58 2015 From: python-checkins at python.org (matthias.klose) Date: Thu, 30 Apr 2015 11:44:58 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E4=29=3A__-_remove_unus?= =?utf-8?q?ed_EXTRAPLATDIR_macro_in_Makefile=2Epre=2Ein?= Message-ID: <20150430114456.85181.59379@psf.io> https://hg.python.org/cpython/rev/eb09f737120b changeset: 95828:eb09f737120b branch: 3.4 parent: 95825:08c247ff8c1e user: doko at ubuntu.com date: Thu Apr 30 13:44:18 2015 +0200 summary: - remove unused EXTRAPLATDIR macro in Makefile.pre.in files: Makefile.pre.in | 3 +-- 1 files changed, 1 insertions(+), 2 deletions(-) diff --git a/Makefile.pre.in b/Makefile.pre.in --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -1124,8 +1124,7 @@ # Install the library PLATDIR= @PLATDIR@ -EXTRAPLATDIR= @EXTRAPLATDIR@ -MACHDEPS= $(PLATDIR) $(EXTRAPLATDIR) +MACHDEPS= $(PLATDIR) XMLLIBSUBDIRS= xml xml/dom xml/etree xml/parsers xml/sax LIBSUBDIRS= tkinter tkinter/test tkinter/test/test_tkinter \ tkinter/test/test_ttk site-packages test \ -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Apr 30 17:08:19 2015 From: python-checkins at python.org (raymond.hettinger) Date: Thu, 30 Apr 2015 15:08:19 +0000 Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2323910=3A_Optimize?= =?utf-8?q?_property=28=29_getter_calls=2E__Patch_by_Joe_Jevnik?= Message-ID: <20150430150819.11926.42862@psf.io> https://hg.python.org/cpython/rev/661cdbd617b8 changeset: 95830:661cdbd617b8 user: Raymond Hettinger date: Thu Apr 30 08:08:13 2015 -0700 summary: Issue #23910: Optimize property() getter calls. Patch by Joe Jevnik files: Misc/NEWS | 2 ++ Objects/descrobject.c | 10 +++++++++- 2 files changed, 11 insertions(+), 1 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -13,6 +13,8 @@ - Issue #23996: Avoid a crash when a delegated generator raises an unnormalized StopIteration exception. Patch by Stefan Behnel. +- Issue #23910: Optimize property() getter calls. Patch by Joe Jevnik. + - Issue #24022: Fix tokenizer crash when processing undecodable source code. - Issue #9951: Added a hex() method to bytes, bytearray, and memoryview. diff --git a/Objects/descrobject.c b/Objects/descrobject.c --- a/Objects/descrobject.c +++ b/Objects/descrobject.c @@ -1372,6 +1372,8 @@ static PyObject * property_descr_get(PyObject *self, PyObject *obj, PyObject *type) { + static PyObject *args = NULL; + PyObject *ret; propertyobject *gs = (propertyobject *)self; if (obj == NULL || obj == Py_None) { @@ -1382,7 +1384,13 @@ PyErr_SetString(PyExc_AttributeError, "unreadable attribute"); return NULL; } - return PyObject_CallFunctionObjArgs(gs->prop_get, obj, NULL); + if (!args && !(args = PyTuple_New(1))) { + return NULL; + } + PyTuple_SET_ITEM(args, 0, obj); + ret = PyObject_Call(gs->prop_get, args, NULL); + PyTuple_SET_ITEM(args, 0, NULL); + return ret; } static int -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Apr 30 23:38:19 2015 From: python-checkins at python.org (benjamin.peterson) Date: Thu, 30 Apr 2015 21:38:19 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?b?KTogbWVyZ2UgMy40?= Message-ID: <20150430213819.7814.89101@psf.io> https://hg.python.org/cpython/rev/6f6e78931875 changeset: 95833:6f6e78931875 parent: 95830:661cdbd617b8 parent: 95831:96e2c0101672 user: Benjamin Peterson date: Thu Apr 30 17:38:14 2015 -0400 summary: merge 3.4 files: Misc/python.man | 12 ++++++------ 1 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Misc/python.man b/Misc/python.man --- a/Misc/python.man +++ b/Misc/python.man @@ -431,17 +431,17 @@ The integer must be a decimal number in the range [0,4294967295]. Specifying the value 0 will disable hash randomization. .SH AUTHOR -The Python Software Foundation: http://www.python.org/psf +The Python Software Foundation: https://www.python.org/psf .SH INTERNET RESOURCES -Main website: http://www.python.org/ +Main website: https://www.python.org/ .br -Documentation: http://docs.python.org/py3k/ +Documentation: https://docs.python.org/ .br -Developer resources: http://docs.python.org/devguide/ +Developer resources: https://docs.python.org/devguide/ .br -Downloads: http://python.org/download/ +Downloads: https://www.python.org/downloads/ .br -Module repository: http://pypi.python.org/ +Module repository: https://pypi.python.org/ .br Newsgroups: comp.lang.python, comp.lang.python.announce .SH LICENSING -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Apr 30 23:38:19 2015 From: python-checkins at python.org (benjamin.peterson) Date: Thu, 30 Apr 2015 21:38:19 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_update_links?= Message-ID: <20150430213819.124208.3237@psf.io> https://hg.python.org/cpython/rev/c17e29454447 changeset: 95832:c17e29454447 branch: 2.7 parent: 95827:6986ccbcf41e user: Benjamin Peterson date: Thu Apr 30 17:37:11 2015 -0400 summary: update links files: Misc/python.man | 12 ++++++------ 1 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Misc/python.man b/Misc/python.man --- a/Misc/python.man +++ b/Misc/python.man @@ -452,17 +452,17 @@ the value 0 will lead to the same hash values as when hash randomization is disabled. .SH AUTHOR -The Python Software Foundation: http://www.python.org/psf +The Python Software Foundation: https://www.python.org/psf .SH INTERNET RESOURCES -Main website: http://www.python.org/ +Main website: https://www.python.org/ .br -Documentation: http://docs.python.org/ +Documentation: https://docs.python.org/2/ .br -Developer resources: http://docs.python.org/devguide/ +Developer resources: https://docs.python.org/devguide/ .br -Downloads: http://python.org/download/ +Downloads: https://www.python.org/downloads/ .br -Module repository: http://pypi.python.org/ +Module repository: https://pypi.python.org/ .br Newsgroups: comp.lang.python, comp.lang.python.announce .SH LICENSING -- Repository URL: https://hg.python.org/cpython From python-checkins at python.org Thu Apr 30 23:38:18 2015 From: python-checkins at python.org (benjamin.peterson) Date: Thu, 30 Apr 2015 21:38:18 +0000 Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E4=29=3A_update_links?= Message-ID: <20150430213818.1941.82101@psf.io> https://hg.python.org/cpython/rev/96e2c0101672 changeset: 95831:96e2c0101672 branch: 3.4 parent: 95828:eb09f737120b user: Benjamin Peterson date: Thu Apr 30 17:37:11 2015 -0400 summary: update links files: Misc/python.man | 12 ++++++------ 1 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Misc/python.man b/Misc/python.man --- a/Misc/python.man +++ b/Misc/python.man @@ -434,17 +434,17 @@ The integer must be a decimal number in the range [0,4294967295]. Specifying the value 0 will disable hash randomization. .SH AUTHOR -The Python Software Foundation: http://www.python.org/psf +The Python Software Foundation: https://www.python.org/psf .SH INTERNET RESOURCES -Main website: http://www.python.org/ +Main website: https://www.python.org/ .br -Documentation: http://docs.python.org/py3k/ +Documentation: https://docs.python.org/ .br -Developer resources: http://docs.python.org/devguide/ +Developer resources: https://docs.python.org/devguide/ .br -Downloads: http://python.org/download/ +Downloads: https://www.python.org/downloads/ .br -Module repository: http://pypi.python.org/ +Module repository: https://pypi.python.org/ .br Newsgroups: comp.lang.python, comp.lang.python.announce .SH LICENSING -- Repository URL: https://hg.python.org/cpython