From python-checkins at python.org Fri Aug 1 00:35:54 2014 From: python-checkins at python.org (antoine.pitrou) Date: Fri, 1 Aug 2014 00:35:54 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2322111=3A_Assorted?= =?utf-8?q?_cleanups_in_test=5Fimaplib=2E__Patch_by_Milan_Oberkirch=2E?= Message-ID: <3hPRKk0320z7Lk3@mail.python.org> http://hg.python.org/cpython/rev/6b2cafab7a9f changeset: 91949:6b2cafab7a9f user: Antoine Pitrou date: Thu Jul 31 18:35:45 2014 -0400 summary: Issue #22111: Assorted cleanups in test_imaplib. Patch by Milan Oberkirch. files: Lib/test/test_imaplib.py | 116 +++++++++++--------------- Misc/NEWS | 2 + 2 files changed, 53 insertions(+), 65 deletions(-) diff --git a/Lib/test/test_imaplib.py b/Lib/test/test_imaplib.py --- a/Lib/test/test_imaplib.py +++ b/Lib/test/test_imaplib.py @@ -11,7 +11,8 @@ import time import calendar -from test.support import reap_threads, verbose, transient_internet, run_with_tz, run_with_locale +from test.support import (reap_threads, verbose, transient_internet, + run_with_tz, run_with_locale) import unittest from datetime import datetime, timezone, timedelta try: @@ -22,8 +23,8 @@ else: from ssl import HAS_SNI -CERTFILE = None -CAFILE = None +CERTFILE = os.path.join(os.path.dirname(__file__) or os.curdir, "keycert3.pem") +CAFILE = os.path.join(os.path.dirname(__file__) or os.curdir, "pycacert.pem") class TestImaplib(unittest.TestCase): @@ -44,17 +45,15 @@ def test_Internaldate2tuple_issue10941(self): self.assertNotEqual(imaplib.Internaldate2tuple( b'25 (INTERNALDATE "02-Apr-2000 02:30:00 +0000")'), - imaplib.Internaldate2tuple( - b'25 (INTERNALDATE "02-Apr-2000 03:30:00 +0000")')) - - + imaplib.Internaldate2tuple( + b'25 (INTERNALDATE "02-Apr-2000 03:30:00 +0000")')) def timevalues(self): return [2000000000, 2000000000.0, time.localtime(2000000000), (2033, 5, 18, 5, 33, 20, -1, -1, -1), (2033, 5, 18, 5, 33, 20, -1, -1, 1), datetime.fromtimestamp(2000000000, - timezone(timedelta(0, 2*60*60))), + timezone(timedelta(0, 2 * 60 * 60))), '"18-May-2033 05:33:20 +0200"'] @run_with_locale('LC_ALL', 'de_DE', 'fr_FR') @@ -75,7 +74,6 @@ if ssl: - class SecureTCPServer(socketserver.TCPServer): def get_request(self): @@ -96,13 +94,13 @@ class SimpleIMAPHandler(socketserver.StreamRequestHandler): - timeout = 1 continuation = None capabilities = '' def _send(self, message): - if verbose: print("SENT: %r" % message.strip()) + if verbose: + print("SENT: %r" % message.strip()) self.wfile.write(message) def _send_line(self, message): @@ -135,7 +133,8 @@ if line.endswith(b'\r\n'): break - if verbose: print('GOT: %r' % line.strip()) + if verbose: + print('GOT: %r' % line.strip()) if self.continuation: try: self.continuation.send(line) @@ -147,8 +146,8 @@ cmd = splitline[1] args = splitline[2:] - if hasattr(self, 'cmd_'+cmd): - continuation = getattr(self, 'cmd_'+cmd)(tag, args) + if hasattr(self, 'cmd_' + cmd): + continuation = getattr(self, 'cmd_' + cmd)(tag, args) if continuation: self.continuation = continuation next(continuation) @@ -156,7 +155,9 @@ self._send_tagged(tag, 'BAD', cmd + ' unknown') def cmd_CAPABILITY(self, tag, args): - caps = 'IMAP4rev1 ' + self.capabilities if self.capabilities else 'IMAP4rev1' + caps = ('IMAP4rev1 ' + self.capabilities + if self.capabilities + else 'IMAP4rev1') self._send_textline('* CAPABILITY ' + caps) self._send_tagged(tag, 'OK', 'CAPABILITY completed') @@ -165,7 +166,9 @@ self._send_tagged(tag, 'OK', 'LOGOUT completed') -class BaseThreadedNetworkedTests(unittest.TestCase): +class ThreadedNetworkedTests(unittest.TestCase): + server_class = socketserver.TCPServer + imap_class = imaplib.IMAP4 def make_server(self, addr, hdlr): @@ -175,7 +178,8 @@ self.server_close() raise - if verbose: print("creating server") + if verbose: + print("creating server") server = MyServer(addr, hdlr) self.assertEqual(server.server_address, server.socket.getsockname()) @@ -191,18 +195,21 @@ # Short poll interval to make the test finish quickly. # Time between requests is short enough that we won't wake # up spuriously too many times. - kwargs={'poll_interval':0.01}) + kwargs={'poll_interval': 0.01}) t.daemon = True # In case this function raises. t.start() - if verbose: print("server running") + if verbose: + print("server running") return server, t def reap_server(self, server, thread): - if verbose: print("waiting for server") + if verbose: + print("waiting for server") server.shutdown() server.server_close() thread.join() - if verbose: print("done") + if verbose: + print("done") @contextmanager def reaped_server(self, hdlr): @@ -259,7 +266,7 @@ def cmd_AUTHENTICATE(self, tag, args): self._send_tagged(tag, 'NO', 'unrecognized authentication ' - 'type {}'.format(args[0])) + 'type {}'.format(args[0])) with self.reaped_pair(MyServer) as (server, client): with self.assertRaises(imaplib.IMAP4.error): @@ -293,13 +300,13 @@ code, data = client.authenticate('MYAUTH', lambda x: b'fake') self.assertEqual(code, 'OK') self.assertEqual(server.response, - b'ZmFrZQ==\r\n') #b64 encoded 'fake' + b'ZmFrZQ==\r\n') # b64 encoded 'fake' with self.reaped_pair(MyServer) as (server, client): code, data = client.authenticate('MYAUTH', lambda x: 'fake') self.assertEqual(code, 'OK') self.assertEqual(server.response, - b'ZmFrZQ==\r\n') #b64 encoded 'fake' + b'ZmFrZQ==\r\n') # b64 encoded 'fake' @reap_threads def test_login_cram_md5(self): @@ -310,9 +317,10 @@ def cmd_AUTHENTICATE(self, tag, args): self._send_textline('+ PDE4OTYuNjk3MTcwOTUyQHBvc3RvZmZpY2Uucm' - 'VzdG9uLm1jaS5uZXQ=') + 'VzdG9uLm1jaS5uZXQ=') r = yield - if r == b'dGltIGYxY2E2YmU0NjRiOWVmYTFjY2E2ZmZkNmNmMmQ5ZjMy\r\n': + if (r == b'dGltIGYxY2E2YmU0NjRiOWVmYT' + b'FjY2E2ZmZkNmNmMmQ5ZjMy\r\n'): self._send_tagged(tag, 'OK', 'CRAM-MD5 successful') else: self._send_tagged(tag, 'NO', 'No access') @@ -327,27 +335,19 @@ ret, data = client.login_cram_md5("tim", b"tanstaaftanstaaf") self.assertEqual(ret, "OK") - def test_linetoolong(self): class TooLongHandler(SimpleIMAPHandler): def handle(self): # Send a very long response line - self.wfile.write(b'* OK ' + imaplib._MAXLINE*b'x' + b'\r\n') + self.wfile.write(b'* OK ' + imaplib._MAXLINE * b'x' + b'\r\n') with self.reaped_server(TooLongHandler) as server: self.assertRaises(imaplib.IMAP4.error, self.imap_class, *server.server_address) -class ThreadedNetworkedTests(BaseThreadedNetworkedTests): - - server_class = socketserver.TCPServer - imap_class = imaplib.IMAP4 - - @unittest.skipUnless(ssl, "SSL not available") -class ThreadedNetworkedTestsSSL(BaseThreadedNetworkedTests): - +class ThreadedNetworkedTestsSSL(ThreadedNetworkedTests): server_class = SecureTCPServer imap_class = IMAP4_SSL @@ -359,8 +359,9 @@ ssl_context.check_hostname = True ssl_context.load_verify_locations(CAFILE) - with self.assertRaisesRegex(ssl.CertificateError, - "hostname '127.0.0.1' doesn't match 'localhost'"): + with self.assertRaisesRegex( + ssl.CertificateError, + "hostname '127.0.0.1' doesn't match 'localhost'"): with self.reaped_server(SimpleIMAPHandler) as server: client = self.imap_class(*server.server_address, ssl_context=ssl_context) @@ -372,6 +373,8 @@ client.shutdown() + at unittest.skipUnless( + support.is_resource_enabled('network'), 'network resource disabled') class RemoteIMAPTest(unittest.TestCase): host = 'cyrus.andrew.cmu.edu' port = 143 @@ -405,6 +408,8 @@ @unittest.skipUnless(ssl, "SSL not available") + at unittest.skipUnless( + support.is_resource_enabled('network'), 'network resource disabled') class RemoteIMAP_STARTTLSTest(RemoteIMAPTest): def setUp(self): @@ -458,7 +463,8 @@ def test_logincapa_with_client_ssl_context(self): with transient_internet(self.host): - _server = self.imap_class(self.host, self.port, ssl_context=self.create_ssl_context()) + _server = self.imap_class( + self.host, self.port, ssl_context=self.create_ssl_context()) self.check_logincapa(_server) def test_logout(self): @@ -469,35 +475,15 @@ def test_ssl_context_certfile_exclusive(self): with transient_internet(self.host): - self.assertRaises(ValueError, self.imap_class, self.host, self.port, - certfile=CERTFILE, ssl_context=self.create_ssl_context()) + self.assertRaises( + ValueError, self.imap_class, self.host, self.port, + certfile=CERTFILE, ssl_context=self.create_ssl_context()) def test_ssl_context_keyfile_exclusive(self): with transient_internet(self.host): - self.assertRaises(ValueError, self.imap_class, self.host, self.port, - keyfile=CERTFILE, ssl_context=self.create_ssl_context()) - - -def load_tests(*args): - tests = [TestImaplib] - - if support.is_resource_enabled('network'): - if ssl: - global CERTFILE, CAFILE - CERTFILE = os.path.join(os.path.dirname(__file__) or os.curdir, - "keycert3.pem") - if not os.path.exists(CERTFILE): - raise support.TestFailed("Can't read certificate files!") - CAFILE = os.path.join(os.path.dirname(__file__) or os.curdir, - "pycacert.pem") - if not os.path.exists(CAFILE): - raise support.TestFailed("Can't read CA file!") - tests.extend([ - ThreadedNetworkedTests, ThreadedNetworkedTestsSSL, - RemoteIMAPTest, RemoteIMAP_SSLTest, RemoteIMAP_STARTTLSTest, - ]) - - return unittest.TestSuite([unittest.makeSuite(test) for test in tests]) + self.assertRaises( + ValueError, self.imap_class, self.host, self.port, + keyfile=CERTFILE, ssl_context=self.create_ssl_context()) if __name__ == "__main__": diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -786,6 +786,8 @@ Tests ----- +- Issue #22111: Assorted cleanups in test_imaplib. Patch by Milan Oberkirch. + - Issue #22002: Added ``load_package_tests`` function to test.support and used it to implement/augment test discovery in test_asyncio, test_email, test_importlib, test_json, and test_tools. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Aug 1 00:47:12 2014 From: python-checkins at python.org (antoine.pitrou) Date: Fri, 1 Aug 2014 00:47:12 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Simplify_code_in_multiproc?= =?utf-8?q?essing=2EConnection=2Esend=5Fbytes=28=29=2E?= Message-ID: <3hPRZm3t0pz7LjQ@mail.python.org> http://hg.python.org/cpython/rev/20fd13242a45 changeset: 91950:20fd13242a45 user: Antoine Pitrou date: Thu Jul 31 18:41:57 2014 -0400 summary: Simplify code in multiprocessing.Connection.send_bytes(). Followup to issue #20540; patch by Serhiy. files: Lib/multiprocessing/connection.py | 15 ++++++--------- 1 files changed, 6 insertions(+), 9 deletions(-) diff --git a/Lib/multiprocessing/connection.py b/Lib/multiprocessing/connection.py --- a/Lib/multiprocessing/connection.py +++ b/Lib/multiprocessing/connection.py @@ -400,17 +400,14 @@ if n > 16384: # The payload is large so Nagle's algorithm won't be triggered # and we'd better avoid the cost of concatenation. - chunks = [header, buf] - elif n > 0: + self._send(header) + self._send(buf) + else: # Issue #?20540: concatenate before sending, to avoid delays due # to Nagle's algorithm on a TCP socket. - chunks = [header + buf] - else: - # This code path is necessary to avoid "broken pipe" errors - # when sending a 0-length buffer if the other end closed the pipe. - chunks = [header] - for chunk in chunks: - self._send(chunk) + # Also note we want to avoid sending a 0-length buffer separately, + # to avoid "broken pipe" errors if the other end closed the pipe. + self._send(header + buf) def _recv_bytes(self, maxsize=None): buf = self._recv(4) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Aug 1 06:49:03 2014 From: python-checkins at python.org (zach.ware) Date: Fri, 1 Aug 2014 06:49:03 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2321907=3A_Further_?= =?utf-8?q?improvments_to_build=5Fpgo=2Ebat=2E__Patch_by_Ingolf_Becker=2E?= Message-ID: <3hPbcH5y6Gz7LjW@mail.python.org> http://hg.python.org/cpython/rev/60c61ea64021 changeset: 91951:60c61ea64021 user: Zachary Ware date: Thu Jul 31 23:48:45 2014 -0500 summary: Issue #21907: Further improvments to build_pgo.bat. Patch by Ingolf Becker. files: Misc/ACKS | 1 + PCbuild/build_pgo.bat | 35 +++++++++++++++---------- PCbuild/pginstrument.props | 2 +- 3 files changed, 23 insertions(+), 15 deletions(-) diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -98,6 +98,7 @@ Samuel L. Bayer Donald Beaudry David Beazley +Ingolf Becker Neal Becker Robin Becker Torsten Becker diff --git a/PCbuild/build_pgo.bat b/PCbuild/build_pgo.bat --- a/PCbuild/build_pgo.bat +++ b/PCbuild/build_pgo.bat @@ -7,14 +7,15 @@ setlocal set platf=Win32 +set dir=%~dp0 rem use the performance testsuite. This is quick and simple -set job1=%~dp0..\tools\pybench\pybench.py -n 1 -C 1 --with-gc -set path1=%~dp0..\tools\pybench +set job1="%dir%..\tools\pybench\pybench.py" -n 1 -C 1 --with-gc +set path1="%dir%..\tools\pybench" rem or the whole testsuite for more thorough testing -set job2=%~dp0..\lib\test\regrtest.py -set path2=%~dp0..\lib +set job2="%dir%..\lib\test\regrtest.py" +set path2="%dir%..\lib" set job=%job1% set clrpath=%path1% @@ -23,19 +24,25 @@ if "%1"=="-p" (set platf=%2) & shift & shift & goto CheckOpts if "%1"=="-2" (set job=%job2%) & (set clrpath=%path2%) & shift & goto CheckOpts -set PGI=%platf%-pgi -set PGO=%platf%-pgo +set PGI=%dir%%platf%-pgi +set PGO=%dir%%platf%-pgo - at echo on +rem We cannot cross compile PGO builds, as the optimization needs to be run natively +set vs_platf=x86 +if "%platf%"=="x64" (set vs_platf=amd64) +rem Setup the environment +call "%VS100COMNTOOLS%..\..\VC\vcvarsall.bat" %vs_platf% + rem build the instrumented version -call build -p %platf% -c PGInstrument +msbuild "%dir%pcbuild.sln" /t:Build /p:Configuration=PGInstrument /p:Platform=%platf% %1 %2 %3 %4 %5 %6 %7 %8 %9 rem remove .pyc files, .pgc files and execute the job -%PGI%\python.exe rmpyc.py "%clrpath%" -del %PGI%\*.pgc -%PGI%\python.exe "%job%" +"%PGI%\python.exe" "%dir%rmpyc.py" %clrpath% +del "%PGI%\*.pgc" +"%PGI%\python.exe" %job% -rem finally build the optimized version -if exist %PGO% del /s /q %PGO% -call build -p %platf% -c PGUpdate +rem clean +if exist "%PGO%" del /s /q "%PGO%" +rem build optimized version +msbuild "%dir%pcbuild.sln" /t:Build /p:Configuration=PGUpdate /p:Platform=%platf% %1 %2 %3 %4 %5 %6 %7 %8 %9 diff --git a/PCbuild/pginstrument.props b/PCbuild/pginstrument.props --- a/PCbuild/pginstrument.props +++ b/PCbuild/pginstrument.props @@ -1,7 +1,7 @@ ? - $(SolutionDir)$(Platform)-pgi\ + $(SolutionDir)$(Platform)-pgi <_ProjectFileVersion>10.0.30319.1 -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Aug 1 06:59:55 2014 From: python-checkins at python.org (zach.ware) Date: Fri, 1 Aug 2014 06:59:55 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2321907=3A_Avoid_us?= =?utf-8?q?ing_double_quotes_to_check_argument_values=2E?= Message-ID: <3hPbrq06d5z7Ljd@mail.python.org> http://hg.python.org/cpython/rev/4c1d543135ef changeset: 91952:4c1d543135ef user: Zachary Ware date: Thu Jul 31 23:58:27 2014 -0500 summary: Issue #21907: Avoid using double quotes to check argument values. Double quotes in expanded variables can match literal double quotes, which makes for a big mess when passing in a quoted argument (like "/p:externalsDir=..\externals", for example). files: PCbuild/build.bat | 12 ++++++------ 1 files changed, 6 insertions(+), 6 deletions(-) diff --git a/PCbuild/build.bat b/PCbuild/build.bat --- a/PCbuild/build.bat +++ b/PCbuild/build.bat @@ -16,13 +16,13 @@ set dir=%~dp0 :CheckOpts -if "%1"=="-c" (set conf=%2) & shift & shift & goto CheckOpts -if "%1"=="-p" (set platf=%2) & shift & shift & goto CheckOpts -if "%1"=="-r" (set target=Rebuild) & shift & goto CheckOpts -if "%1"=="-d" (set conf=Debug) & shift & goto CheckOpts -if "%1"=="-e" call "%dir%get_externals.bat" & shift & goto CheckOpts +if '%1'=='-c' (set conf=%2) & shift & shift & goto CheckOpts +if '%1'=='-p' (set platf=%2) & shift & shift & goto CheckOpts +if '%1'=='-r' (set target=Rebuild) & shift & goto CheckOpts +if '%1'=='-d' (set conf=Debug) & shift & goto CheckOpts +if '%1'=='-e' call "%dir%get_externals.bat" & shift & goto CheckOpts -if "%platf%"=="x64" (set vs_platf=x86_amd64) +if '%platf%'=='x64' (set vs_platf=x86_amd64) rem Setup the environment call "%VS100COMNTOOLS%..\..\VC\vcvarsall.bat" %vs_platf% -- Repository URL: http://hg.python.org/cpython From solipsis at pitrou.net Fri Aug 1 10:04:24 2014 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Fri, 01 Aug 2014 10:04:24 +0200 Subject: [Python-checkins] Daily reference leaks (20fd13242a45): sum=-482 Message-ID: results for 20fd13242a45 on branch "default" -------------------------------------------- test_asyncio leaked [-159, -106, -106] references, sum=-371 test_asyncio leaked [-46, -27, -28] memory blocks, sum=-101 test_collections leaked [-2, -4, 0] references, sum=-6 test_collections leaked [-1, -2, 0] memory blocks, sum=-3 test_functools leaked [0, 0, 3] memory blocks, sum=3 test_site leaked [-2, 2, -2] references, sum=-2 test_site leaked [-2, 2, -2] memory blocks, sum=-2 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/cpython/refleaks/reflog5doC0C', '-x'] From python-checkins at python.org Fri Aug 1 12:34:48 2014 From: python-checkins at python.org (victor.stinner) Date: Fri, 1 Aug 2014 12:34:48 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2318395=3A_Rename_?= =?utf-8?b?YGBfUHlfY2hhcjJ3Y2hhcigpYGAgdG8gOmM6ZnVuYzpgUHlfRGVjb2RlTG9j?= =?utf-8?q?ale=60=2C_rename?= Message-ID: <3hPlHD4mScz7LjQ@mail.python.org> http://hg.python.org/cpython/rev/93a798c7f270 changeset: 91953:93a798c7f270 user: Victor Stinner date: Fri Aug 01 12:28:48 2014 +0200 summary: Issue #18395: Rename ``_Py_char2wchar()`` to :c:func:`Py_DecodeLocale`, rename ``_Py_wchar2char()`` to :c:func:`Py_EncodeLocale`, and document these functions. files: Doc/c-api/sys.rst | 54 +++++++++++++++++++++++ Doc/c-api/unicode.rst | 35 +++++++++------ Doc/library/codecs.rst | 1 + Doc/library/os.rst | 7 +- Include/fileutils.h | 4 +- Misc/NEWS | 4 + Misc/coverity_model.c | 2 +- Modules/getpath.c | 16 +++--- Modules/main.c | 4 +- Objects/unicodeobject.c | 8 +- Programs/python.c | 2 +- Python/fileutils.c | 67 +++++++++++++++------------- Python/frozenmain.c | 2 +- 13 files changed, 138 insertions(+), 68 deletions(-) diff --git a/Doc/c-api/sys.rst b/Doc/c-api/sys.rst --- a/Doc/c-api/sys.rst +++ b/Doc/c-api/sys.rst @@ -47,6 +47,60 @@ not call those functions directly! :c:type:`PyOS_sighandler_t` is a typedef alias for :c:type:`void (\*)(int)`. +.. c:function:: wchar_t* Py_DecodeLocale(const char* arg, size_t *size) + + Decode a byte string from the locale encoding with the :ref:`surrogateescape + error handler `: undecodable bytes are decoded as + characters in range U+DC80..U+DCFF. If a byte sequence can be decoded as a + surrogate character, escape the bytes using the surrogateescape error + handler instead of decoding them. + + Return a pointer to a newly allocated wide character string, use + :c:func:`PyMem_RawFree` to free the memory. If size is not ``NULL``, write + the number of wide characters excluding the null character into ``*size`` + + Return ``NULL`` on decoding error or memory allocation error. If *size* is + not ``NULL``, ``*size`` is set to ``(size_t)-1`` on memory error or set to + ``(size_t)-2`` on decoding error. + + Decoding errors should never happen, unless there is a bug in the C + library. + + Use the :c:func:`Py_EncodeLocale` function to encode the character string + back to a byte string. + + .. seealso:: + + The :c:func:`PyUnicode_DecodeFSDefaultAndSize` and + :c:func:`PyUnicode_DecodeLocaleAndSize` functions. + + .. versionadded:: 3.5 + + +.. c:function:: char* Py_EncodeLocale(const wchar_t *text, size_t *error_pos) + + Encode a wide character string to the locale encoding with the + :ref:`surrogateescape error handler `: surrogate characters + in the range U+DC80..U+DCFF are converted to bytes 0x80..0xFF. + + Return a pointer to a newly allocated byte string, use :c:func:`PyMem_Free` + to free the memory. Return ``NULL`` on encoding error or memory allocation + error + + If error_pos is not ``NULL``, ``*error_pos`` is set to the index of the + invalid character on encoding error, or set to ``(size_t)-1`` otherwise. + + Use the :c:func:`Py_DecodeLocale` function to decode the bytes string back + to a wide character string. + + .. seealso:: + + The :c:func:`PyUnicode_EncodeFSDefault` and + :c:func:`PyUnicode_EncodeLocale` functions. + + .. versionadded:: 3.5 + + .. _systemfunctions: System Functions diff --git a/Doc/c-api/unicode.rst b/Doc/c-api/unicode.rst --- a/Doc/c-api/unicode.rst +++ b/Doc/c-api/unicode.rst @@ -758,11 +758,13 @@ *errors* is ``NULL``. *str* must end with a null character but cannot contain embedded null characters. + Use :c:func:`PyUnicode_DecodeFSDefaultAndSize` to decode a string from + :c:data:`Py_FileSystemDefaultEncoding` (the locale encoding read at + Python startup). + .. seealso:: - Use :c:func:`PyUnicode_DecodeFSDefaultAndSize` to decode a string from - :c:data:`Py_FileSystemDefaultEncoding` (the locale encoding read at - Python startup). + The :c:func:`Py_DecodeLocale` function. .. versionadded:: 3.3 @@ -783,11 +785,13 @@ *errors* is ``NULL``. Return a :class:`bytes` object. *str* cannot contain embedded null characters. + Use :c:func:`PyUnicode_EncodeFSDefault` to encode a string to + :c:data:`Py_FileSystemDefaultEncoding` (the locale encoding read at + Python startup). + .. seealso:: - Use :c:func:`PyUnicode_EncodeFSDefault` to encode a string to - :c:data:`Py_FileSystemDefaultEncoding` (the locale encoding read at - Python startup). + The :c:func:`Py_EncodeLocale` function. .. versionadded:: 3.3 @@ -832,12 +836,14 @@ If :c:data:`Py_FileSystemDefaultEncoding` is not set, fall back to the locale encoding. + :c:data:`Py_FileSystemDefaultEncoding` is initialized at startup from the + locale encoding and cannot be modified later. If you need to decode a string + from the current locale encoding, use + :c:func:`PyUnicode_DecodeLocaleAndSize`. + .. seealso:: - :c:data:`Py_FileSystemDefaultEncoding` is initialized at startup from the - locale encoding and cannot be modified later. If you need to decode a - string from the current locale encoding, use - :c:func:`PyUnicode_DecodeLocaleAndSize`. + The :c:func:`Py_DecodeLocale` function. .. versionchanged:: 3.2 Use ``"strict"`` error handler on Windows. @@ -867,12 +873,13 @@ If :c:data:`Py_FileSystemDefaultEncoding` is not set, fall back to the locale encoding. + :c:data:`Py_FileSystemDefaultEncoding` is initialized at startup from the + locale encoding and cannot be modified later. If you need to encode a string + to the current locale encoding, use :c:func:`PyUnicode_EncodeLocale`. + .. seealso:: - :c:data:`Py_FileSystemDefaultEncoding` is initialized at startup from the - locale encoding and cannot be modified later. If you need to encode a - string to the current locale encoding, use - :c:func:`PyUnicode_EncodeLocale`. + The :c:func:`Py_EncodeLocale` function. .. versionadded:: 3.2 diff --git a/Doc/library/codecs.rst b/Doc/library/codecs.rst --- a/Doc/library/codecs.rst +++ b/Doc/library/codecs.rst @@ -318,6 +318,7 @@ encodings. +.. _surrogateescape: .. _codec-base-classes: Codec Base Classes diff --git a/Doc/library/os.rst b/Doc/library/os.rst --- a/Doc/library/os.rst +++ b/Doc/library/os.rst @@ -78,9 +78,10 @@ .. versionchanged:: 3.1 On some systems, conversion using the file system encoding may fail. In this - case, Python uses the ``surrogateescape`` encoding error handler, which means - that undecodable bytes are replaced by a Unicode character U+DCxx on - decoding, and these are again translated to the original byte on encoding. + case, Python uses the :ref:`surrogateescape encoding error handler + `, which means that undecodable bytes are replaced by a + Unicode character U+DCxx on decoding, and these are again translated to the + original byte on encoding. The file system encoding must guarantee to successfully decode all bytes diff --git a/Include/fileutils.h b/Include/fileutils.h --- a/Include/fileutils.h +++ b/Include/fileutils.h @@ -7,11 +7,11 @@ PyAPI_FUNC(PyObject *) _Py_device_encoding(int); -PyAPI_FUNC(wchar_t *) _Py_char2wchar( +PyAPI_FUNC(wchar_t *) Py_DecodeLocale( const char *arg, size_t *size); -PyAPI_FUNC(char*) _Py_wchar2char( +PyAPI_FUNC(char*) Py_EncodeLocale( const wchar_t *text, size_t *error_pos); diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,10 @@ Core and Builtins ----------------- +- Issue #18395: Rename ``_Py_char2wchar()`` to :c:func:`Py_DecodeLocale`, + rename ``_Py_wchar2char()`` to :c:func:`Py_EncodeLocale`, and document + these functions. + - Issue #20179: Apply Argument Clinic to bytes and bytearray. Patch by Tal Einat. diff --git a/Misc/coverity_model.c b/Misc/coverity_model.c --- a/Misc/coverity_model.c +++ b/Misc/coverity_model.c @@ -85,7 +85,7 @@ } /* Python/fileutils.c */ -wchar_t *_Py_char2wchar(const char* arg, size_t *size) +wchar_t *Py_DecodeLocale(const char* arg, size_t *size) { wchar_t *w; __coverity_tainted_data_sink__(arg); diff --git a/Modules/getpath.c b/Modules/getpath.c --- a/Modules/getpath.c +++ b/Modules/getpath.c @@ -336,7 +336,7 @@ joinpath(prefix, L"Modules/Setup"); if (isfile(prefix)) { /* Check VPATH to see if argv0_path is in the build directory. */ - vpath = _Py_char2wchar(VPATH, NULL); + vpath = Py_DecodeLocale(VPATH, NULL); if (vpath != NULL) { wcsncpy(prefix, argv0_path, MAXPATHLEN); prefix[MAXPATHLEN] = L'\0'; @@ -491,10 +491,10 @@ wchar_t *_pythonpath, *_prefix, *_exec_prefix; wchar_t *lib_python; - _pythonpath = _Py_char2wchar(PYTHONPATH, NULL); - _prefix = _Py_char2wchar(PREFIX, NULL); - _exec_prefix = _Py_char2wchar(EXEC_PREFIX, NULL); - lib_python = _Py_char2wchar("lib/python" VERSION, NULL); + _pythonpath = Py_DecodeLocale(PYTHONPATH, NULL); + _prefix = Py_DecodeLocale(PREFIX, NULL); + _exec_prefix = Py_DecodeLocale(EXEC_PREFIX, NULL); + lib_python = Py_DecodeLocale("lib/python" VERSION, NULL); if (!_pythonpath || !_prefix || !_exec_prefix || !lib_python) { Py_FatalError( @@ -503,7 +503,7 @@ } if (_path) { - path_buffer = _Py_char2wchar(_path, NULL); + path_buffer = Py_DecodeLocale(_path, NULL); path = path_buffer; } @@ -584,7 +584,7 @@ ** be running the interpreter in the build directory, so we use the ** build-directory-specific logic to find Lib and such. */ - wchar_t* wbuf = _Py_char2wchar(modPath, NULL); + wchar_t* wbuf = Py_DecodeLocale(modPath, NULL); if (wbuf == NULL) { Py_FatalError("Cannot decode framework location"); } @@ -709,7 +709,7 @@ if (_rtpypath && _rtpypath[0] != '\0') { size_t rtpypath_len; - rtpypath = _Py_char2wchar(_rtpypath, &rtpypath_len); + rtpypath = Py_DecodeLocale(_rtpypath, &rtpypath_len); if (rtpypath != NULL) bufsz += rtpypath_len + 1; } diff --git a/Modules/main.c b/Modules/main.c --- a/Modules/main.c +++ b/Modules/main.c @@ -647,7 +647,7 @@ /* Used by Mac/Tools/pythonw.c to forward * the argv0 of the stub executable */ - wchar_t* wbuf = _Py_char2wchar(pyvenv_launcher, NULL); + wchar_t* wbuf = Py_DecodeLocale(pyvenv_launcher, NULL); if (wbuf == NULL) { Py_FatalError("Cannot decode __PYVENV_LAUNCHER__"); @@ -730,7 +730,7 @@ char *cfilename_buffer; const char *cfilename; int err = errno; - cfilename_buffer = _Py_wchar2char(filename, NULL); + cfilename_buffer = Py_EncodeLocale(filename, NULL); if (cfilename_buffer != NULL) cfilename = cfilename_buffer; else diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -3255,7 +3255,7 @@ /* "surrogateescape" error handler */ char *str; - str = _Py_wchar2char(wstr, &error_pos); + str = Py_EncodeLocale(wstr, &error_pos); if (str == NULL) { if (error_pos == (size_t)-1) { PyErr_NoMemory(); @@ -3308,7 +3308,7 @@ if (errmsg != NULL) { size_t errlen; - wstr = _Py_char2wchar(errmsg, &errlen); + wstr = Py_DecodeLocale(errmsg, &errlen); if (wstr != NULL) { reason = PyUnicode_FromWideChar(wstr, errlen); PyMem_RawFree(wstr); @@ -3526,7 +3526,7 @@ if (surrogateescape) { /* "surrogateescape" error handler */ - wstr = _Py_char2wchar(str, &wlen); + wstr = Py_DecodeLocale(str, &wlen); if (wstr == NULL) { if (wlen == (size_t)-1) PyErr_NoMemory(); @@ -3581,7 +3581,7 @@ error_pos = mbstowcs_errorpos(str, len); if (errmsg != NULL) { size_t errlen; - wstr = _Py_char2wchar(errmsg, &errlen); + wstr = Py_DecodeLocale(errmsg, &errlen); if (wstr != NULL) { reason = PyUnicode_FromWideChar(wstr, errlen); PyMem_RawFree(wstr); diff --git a/Programs/python.c b/Programs/python.c --- a/Programs/python.c +++ b/Programs/python.c @@ -52,7 +52,7 @@ setlocale(LC_ALL, ""); for (i = 0; i < argc; i++) { - argv_copy[i] = _Py_char2wchar(argv[i], NULL); + argv_copy[i] = Py_DecodeLocale(argv[i], NULL); if (!argv_copy[i]) { PyMem_RawFree(oldloc); fprintf(stderr, "Fatal Python error: " diff --git a/Python/fileutils.c b/Python/fileutils.c --- a/Python/fileutils.c +++ b/Python/fileutils.c @@ -82,11 +82,11 @@ Values of force_ascii: - 1: the workaround is used: _Py_wchar2char() uses - encode_ascii_surrogateescape() and _Py_char2wchar() uses + 1: the workaround is used: Py_EncodeLocale() uses + encode_ascii_surrogateescape() and Py_DecodeLocale() uses decode_ascii_surrogateescape() - 0: the workaround is not used: _Py_wchar2char() uses wcstombs() and - _Py_char2wchar() uses mbstowcs() + 0: the workaround is not used: Py_EncodeLocale() uses wcstombs() and + Py_DecodeLocale() uses mbstowcs() -1: unknown, need to call check_force_ascii() to get the value */ static int force_ascii = -1; @@ -241,24 +241,26 @@ /* Decode a byte string from the locale encoding with the - surrogateescape error handler (undecodable bytes are decoded as characters - in range U+DC80..U+DCFF). If a byte sequence can be decoded as a surrogate + surrogateescape error handler: undecodable bytes are decoded as characters + in range U+DC80..U+DCFF. If a byte sequence can be decoded as a surrogate character, escape the bytes using the surrogateescape error handler instead of decoding them. - Use _Py_wchar2char() to encode the character string back to a byte string. + Return a pointer to a newly allocated wide character string, use + PyMem_RawFree() to free the memory. If size is not NULL, write the number of + wide characters excluding the null character into *size - Return a pointer to a newly allocated wide character string (use - PyMem_RawFree() to free the memory) and write the number of written wide - characters excluding the null character into *size if size is not NULL, or - NULL on error (decoding or memory allocation error). If size is not NULL, - *size is set to (size_t)-1 on memory error and (size_t)-2 on decoding - error. + Return NULL on decoding error or memory allocation error. If *size* is not + NULL, *size is set to (size_t)-1 on memory error or set to (size_t)-2 on + decoding error. - Conversion errors should never happen, unless there is a bug in the C - library. */ + Decoding errors should never happen, unless there is a bug in the C + library. + + Use the Py_EncodeLocale() function to encode the character string back to a + byte string. */ wchar_t* -_Py_char2wchar(const char* arg, size_t *size) +Py_DecodeLocale(const char* arg, size_t *size) { #ifdef __APPLE__ wchar_t *wstr; @@ -389,19 +391,20 @@ #endif /* __APPLE__ */ } -/* Encode a (wide) character string to the locale encoding with the - surrogateescape error handler (characters in range U+DC80..U+DCFF are - converted to bytes 0x80..0xFF). +/* Encode a wide character string to the locale encoding with the + surrogateescape error handler: surrogate characters in the range + U+DC80..U+DCFF are converted to bytes 0x80..0xFF. - This function is the reverse of _Py_char2wchar(). + Return a pointer to a newly allocated byte string, use PyMem_Free() to free + the memory. Return NULL on encoding or memory allocation error. - Return a pointer to a newly allocated byte string (use PyMem_Free() to free - the memory), or NULL on encoding or memory allocation error. + If error_pos is not NULL, *error_pos is set to the index of the invalid + character on encoding error, or set to (size_t)-1 otherwise. - If error_pos is not NULL: *error_pos is the index of the invalid character - on encoding error, or (size_t)-1 otherwise. */ + Use the Py_DecodeLocale() function to decode the bytes string back to a wide + character string. */ char* -_Py_wchar2char(const wchar_t *text, size_t *error_pos) +Py_EncodeLocale(const wchar_t *text, size_t *error_pos) { #ifdef __APPLE__ Py_ssize_t len; @@ -520,7 +523,7 @@ { int err; char *fname; - fname = _Py_wchar2char(path, NULL); + fname = Py_EncodeLocale(path, NULL); if (fname == NULL) { errno = EINVAL; return -1; @@ -784,7 +787,7 @@ errno = EINVAL; return NULL; } - cpath = _Py_wchar2char(path, NULL); + cpath = Py_EncodeLocale(path, NULL); if (cpath == NULL) return NULL; f = fopen(cpath, cmode); @@ -875,7 +878,7 @@ int res; size_t r1; - cpath = _Py_wchar2char(path, NULL); + cpath = Py_EncodeLocale(path, NULL); if (cpath == NULL) { errno = EINVAL; return -1; @@ -889,7 +892,7 @@ return -1; } cbuf[res] = '\0'; /* buf will be null terminated */ - wbuf = _Py_char2wchar(cbuf, &r1); + wbuf = Py_DecodeLocale(cbuf, &r1); if (wbuf == NULL) { errno = EINVAL; return -1; @@ -920,7 +923,7 @@ wchar_t *wresolved_path; char *res; size_t r; - cpath = _Py_wchar2char(path, NULL); + cpath = Py_EncodeLocale(path, NULL); if (cpath == NULL) { errno = EINVAL; return NULL; @@ -930,7 +933,7 @@ if (res == NULL) return NULL; - wresolved_path = _Py_char2wchar(cresolved_path, &r); + wresolved_path = Py_DecodeLocale(cresolved_path, &r); if (wresolved_path == NULL) { errno = EINVAL; return NULL; @@ -963,7 +966,7 @@ if (getcwd(fname, Py_ARRAY_LENGTH(fname)) == NULL) return NULL; - wname = _Py_char2wchar(fname, &len); + wname = Py_DecodeLocale(fname, &len); if (wname == NULL) return NULL; if (size <= len) { diff --git a/Python/frozenmain.c b/Python/frozenmain.c --- a/Python/frozenmain.c +++ b/Python/frozenmain.c @@ -52,7 +52,7 @@ setlocale(LC_ALL, ""); for (i = 0; i < argc; i++) { - argv_copy[i] = _Py_char2wchar(argv[i], NULL); + argv_copy[i] = Py_DecodeLocale(argv[i], NULL); argv_copy2[i] = argv_copy[i]; if (!argv_copy[i]) { fprintf(stderr, "Unable to decode the command line argument #%i\n", -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Aug 1 12:34:50 2014 From: python-checkins at python.org (victor.stinner) Date: Fri, 1 Aug 2014 12:34:50 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2318395=2C_=2322108?= =?utf-8?q?=3A_Update_embedded_Python_examples_to_decode_correctly?= Message-ID: <3hPlHG0SJdz7Lk8@mail.python.org> http://hg.python.org/cpython/rev/94d0e842b9ea changeset: 91954:94d0e842b9ea user: Victor Stinner date: Fri Aug 01 12:28:49 2014 +0200 summary: Issue #18395, #22108: Update embedded Python examples to decode correctly command line parameters: use Py_DecodeLocale() and PyUnicode_DecodeFSDefault(). files: Doc/c-api/init.rst | 15 +++++++++++++++ Doc/extending/embedding.rst | 20 +++++++++++++------- Doc/extending/extending.rst | 12 +++++++++++- Doc/includes/run-func.c | 2 +- 4 files changed, 40 insertions(+), 9 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 @@ -134,6 +134,9 @@ change for the duration of the program's execution. No code in the Python interpreter will change the contents of this storage. + Use :c:func:`Py_DecodeLocale` to decode a bytes string to get a + :c:type:`wchar_*` string. + .. c:function:: wchar* Py_GetProgramName() @@ -243,6 +246,9 @@ :data:`sys.exec_prefix` to be empty. It is up to the caller to modify these if required after calling :c:func:`Py_Initialize`. + Use :c:func:`Py_DecodeLocale` to decode a bytes string to get a + :c:type:`wchar_*` string. + .. c:function:: const char* Py_GetVersion() @@ -339,6 +345,9 @@ :data:`sys.path`, which is the same as prepending the current working directory (``"."``). + Use :c:func:`Py_DecodeLocale` to decode a bytes string to get a + :c:type:`wchar_*` string. + .. note:: It is recommended that applications embedding the Python interpreter for purposes other than executing a single script pass 0 as *updatepath*, @@ -363,6 +372,9 @@ to 1 unless the :program:`python` interpreter was started with the :option:`-I`. + Use :c:func:`Py_DecodeLocale` to decode a bytes string to get a + :c:type:`wchar_*` string. + .. versionchanged:: 3.4 The *updatepath* value depends on :option:`-I`. @@ -377,6 +389,9 @@ execution. No code in the Python interpreter will change the contents of this storage. + Use :c:func:`Py_DecodeLocale` to decode a bytes string to get a + :c:type:`wchar_*` string. + .. c:function:: w_char* Py_GetPythonHome() diff --git a/Doc/extending/embedding.rst b/Doc/extending/embedding.rst --- a/Doc/extending/embedding.rst +++ b/Doc/extending/embedding.rst @@ -58,12 +58,18 @@ int main(int argc, char *argv[]) { - Py_SetProgramName(argv[0]); /* optional but recommended */ - Py_Initialize(); - PyRun_SimpleString("from time import time,ctime\n" - "print('Today is', ctime(time()))\n"); - Py_Finalize(); - return 0; + wchar_t *program = Py_DecodeLocale(argv[0], NULL); + if (program == NULL) { + fprintf(stderr, "Fatal error: cannot decode argv[0]\n"); + exit(1); + } + Py_SetProgramName(program); /* optional but recommended */ + Py_Initialize(); + PyRun_SimpleString("from time import time,ctime\n" + "print('Today is', ctime(time()))\n"); + Py_Finalize(); + PyMem_RawFree(program); + return 0; } The :c:func:`Py_SetProgramName` function should be called before @@ -160,7 +166,7 @@ interesting part with respect to embedding Python starts with :: Py_Initialize(); - pName = PyUnicode_FromString(argv[1]); + pName = PyUnicode_DecodeFSDefault(argv[1]); /* Error checking of pName left out */ pModule = PyImport_Import(pName); diff --git a/Doc/extending/extending.rst b/Doc/extending/extending.rst --- a/Doc/extending/extending.rst +++ b/Doc/extending/extending.rst @@ -370,11 +370,17 @@ int main(int argc, char *argv[]) { + wchar_t *program = Py_DecodeLocale(argv[0], NULL); + if (program == NULL) { + fprintf(stderr, "Fatal error: cannot decode argv[0]\n"); + exit(1); + } + /* Add a built-in module, before Py_Initialize */ PyImport_AppendInittab("spam", PyInit_spam); /* Pass argv[0] to the Python interpreter */ - Py_SetProgramName(argv[0]); + Py_SetProgramName(program); /* Initialize the Python interpreter. Required. */ Py_Initialize(); @@ -386,6 +392,10 @@ ... + PyMem_RawFree(program); + return 0; + } + .. note:: Removing entries from ``sys.modules`` or importing compiled modules into diff --git a/Doc/includes/run-func.c b/Doc/includes/run-func.c --- a/Doc/includes/run-func.c +++ b/Doc/includes/run-func.c @@ -13,7 +13,7 @@ } Py_Initialize(); - pName = PyUnicode_FromString(argv[1]); + pName = PyUnicode_DecodeFSDefault(argv[1]); /* Error checking of pName left out */ pModule = PyImport_Import(pName); -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Aug 1 17:49:43 2014 From: python-checkins at python.org (matthias.klose) Date: Fri, 1 Aug 2014 17:49:43 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A__-_update_conf?= =?utf-8?q?ig=2Eguess_and_config=2Esub_to_support_openrisc=2E?= Message-ID: <3hPtGb5rlXz7LjM@mail.python.org> http://hg.python.org/cpython/rev/99718bc17109 changeset: 91955:99718bc17109 branch: 2.7 parent: 91947:818989a48e96 user: doko at ubuntu.com date: Fri Aug 01 17:48:17 2014 +0200 summary: - update config.guess and config.sub to support openrisc. files: config.guess | 192 +++++--------------------------------- config.sub | 23 ++-- 2 files changed, 40 insertions(+), 175 deletions(-) diff --git a/config.guess b/config.guess --- a/config.guess +++ b/config.guess @@ -1,8 +1,8 @@ #! /bin/sh # Attempt to guess a canonical system name. -# Copyright 1992-2013 Free Software Foundation, Inc. +# Copyright 1992-2014 Free Software Foundation, Inc. -timestamp='2013-06-10' +timestamp='2014-03-23' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by @@ -50,7 +50,7 @@ GNU config.guess ($timestamp) Originally written by Per Bothner. -Copyright 1992-2013 Free Software Foundation, Inc. +Copyright 1992-2014 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." @@ -149,7 +149,7 @@ LIBC=gnu #endif EOF - eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'` + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC' | sed 's, ,,g'` ;; esac @@ -826,7 +826,7 @@ *:MINGW*:*) echo ${UNAME_MACHINE}-pc-mingw32 exit ;; - i*:MSYS*:*) + *:MSYS*:*) echo ${UNAME_MACHINE}-pc-msys exit ;; i*:windows32*:*) @@ -969,10 +969,10 @@ eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; } ;; - or1k:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + openrisc*:Linux:*:*) + echo or1k-unknown-linux-${LIBC} exit ;; - or32:Linux:*:*) + or32:Linux:*:* | or1k*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; padre:Linux:*:*) @@ -1260,16 +1260,26 @@ if test "$UNAME_PROCESSOR" = unknown ; then UNAME_PROCESSOR=powerpc fi - if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then - if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ - (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ - grep IS_64BIT_ARCH >/dev/null - then - case $UNAME_PROCESSOR in - i386) UNAME_PROCESSOR=x86_64 ;; - powerpc) UNAME_PROCESSOR=powerpc64 ;; - esac + if test `echo "$UNAME_RELEASE" | sed -e 's/\..*//'` -le 10 ; then + if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + case $UNAME_PROCESSOR in + i386) UNAME_PROCESSOR=x86_64 ;; + powerpc) UNAME_PROCESSOR=powerpc64 ;; + esac + fi fi + elif test "$UNAME_PROCESSOR" = i386 ; then + # Avoid executing cc on OS X 10.9, as it ships with a stub + # that puts up a graphical alert prompting to install + # developer tools. Any system running Mac OS X 10.7 or + # later (Darwin 11 and later) is required to have a 64-bit + # processor. This is not true of the ARM version of Darwin + # that Apple uses in portable devices. + UNAME_PROCESSOR=x86_64 fi echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} exit ;; @@ -1361,154 +1371,6 @@ exit ;; esac -eval $set_cc_for_build -cat >$dummy.c < -# include -#endif -main () -{ -#if defined (sony) -#if defined (MIPSEB) - /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, - I don't know.... */ - printf ("mips-sony-bsd\n"); exit (0); -#else -#include - printf ("m68k-sony-newsos%s\n", -#ifdef NEWSOS4 - "4" -#else - "" -#endif - ); exit (0); -#endif -#endif - -#if defined (__arm) && defined (__acorn) && defined (__unix) - printf ("arm-acorn-riscix\n"); exit (0); -#endif - -#if defined (hp300) && !defined (hpux) - printf ("m68k-hp-bsd\n"); exit (0); -#endif - -#if defined (NeXT) -#if !defined (__ARCHITECTURE__) -#define __ARCHITECTURE__ "m68k" -#endif - int version; - version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; - if (version < 4) - printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); - else - printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); - exit (0); -#endif - -#if defined (MULTIMAX) || defined (n16) -#if defined (UMAXV) - printf ("ns32k-encore-sysv\n"); exit (0); -#else -#if defined (CMU) - printf ("ns32k-encore-mach\n"); exit (0); -#else - printf ("ns32k-encore-bsd\n"); exit (0); -#endif -#endif -#endif - -#if defined (__386BSD__) - printf ("i386-pc-bsd\n"); exit (0); -#endif - -#if defined (sequent) -#if defined (i386) - printf ("i386-sequent-dynix\n"); exit (0); -#endif -#if defined (ns32000) - printf ("ns32k-sequent-dynix\n"); exit (0); -#endif -#endif - -#if defined (_SEQUENT_) - struct utsname un; - - uname(&un); - - if (strncmp(un.version, "V2", 2) == 0) { - printf ("i386-sequent-ptx2\n"); exit (0); - } - if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ - printf ("i386-sequent-ptx1\n"); exit (0); - } - printf ("i386-sequent-ptx\n"); exit (0); - -#endif - -#if defined (vax) -# if !defined (ultrix) -# include -# if defined (BSD) -# if BSD == 43 - printf ("vax-dec-bsd4.3\n"); exit (0); -# else -# if BSD == 199006 - printf ("vax-dec-bsd4.3reno\n"); exit (0); -# else - printf ("vax-dec-bsd\n"); exit (0); -# endif -# endif -# else - printf ("vax-dec-bsd\n"); exit (0); -# endif -# else - printf ("vax-dec-ultrix\n"); exit (0); -# endif -#endif - -#if defined (alliant) && defined (i860) - printf ("i860-alliant-bsd\n"); exit (0); -#endif - - exit (1); -} -EOF - -$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` && - { echo "$SYSTEM_NAME"; exit; } - -# Apollos put the system type in the environment. - -test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; } - -# Convex versions that predate uname can use getsysinfo(1) - -if [ -x /usr/convex/getsysinfo ] -then - case `getsysinfo -f cpu_type` in - c1*) - echo c1-convex-bsd - exit ;; - c2*) - if getsysinfo -f scalar_acc - then echo c32-convex-bsd - else echo c2-convex-bsd - fi - exit ;; - c34*) - echo c34-convex-bsd - exit ;; - c38*) - echo c38-convex-bsd - exit ;; - c4*) - echo c4-convex-bsd - exit ;; - esac -fi - cat >&2 < http://hg.python.org/cpython/rev/77f36cdb71b0 changeset: 91956:77f36cdb71b0 branch: 3.4 parent: 91944:1927f47a1838 user: doko at ubuntu.com date: Fri Aug 01 17:48:34 2014 +0200 summary: - update config.guess and config.sub to support openrisc. files: config.guess | 192 +++++--------------------------------- config.sub | 23 ++-- 2 files changed, 40 insertions(+), 175 deletions(-) diff --git a/config.guess b/config.guess --- a/config.guess +++ b/config.guess @@ -1,8 +1,8 @@ #! /bin/sh # Attempt to guess a canonical system name. -# Copyright 1992-2013 Free Software Foundation, Inc. +# Copyright 1992-2014 Free Software Foundation, Inc. -timestamp='2013-06-10' +timestamp='2014-03-23' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by @@ -50,7 +50,7 @@ GNU config.guess ($timestamp) Originally written by Per Bothner. -Copyright 1992-2013 Free Software Foundation, Inc. +Copyright 1992-2014 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." @@ -149,7 +149,7 @@ LIBC=gnu #endif EOF - eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'` + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC' | sed 's, ,,g'` ;; esac @@ -826,7 +826,7 @@ *:MINGW*:*) echo ${UNAME_MACHINE}-pc-mingw32 exit ;; - i*:MSYS*:*) + *:MSYS*:*) echo ${UNAME_MACHINE}-pc-msys exit ;; i*:windows32*:*) @@ -969,10 +969,10 @@ eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; } ;; - or1k:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + openrisc*:Linux:*:*) + echo or1k-unknown-linux-${LIBC} exit ;; - or32:Linux:*:*) + or32:Linux:*:* | or1k*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; padre:Linux:*:*) @@ -1260,16 +1260,26 @@ if test "$UNAME_PROCESSOR" = unknown ; then UNAME_PROCESSOR=powerpc fi - if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then - if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ - (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ - grep IS_64BIT_ARCH >/dev/null - then - case $UNAME_PROCESSOR in - i386) UNAME_PROCESSOR=x86_64 ;; - powerpc) UNAME_PROCESSOR=powerpc64 ;; - esac + if test `echo "$UNAME_RELEASE" | sed -e 's/\..*//'` -le 10 ; then + if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + case $UNAME_PROCESSOR in + i386) UNAME_PROCESSOR=x86_64 ;; + powerpc) UNAME_PROCESSOR=powerpc64 ;; + esac + fi fi + elif test "$UNAME_PROCESSOR" = i386 ; then + # Avoid executing cc on OS X 10.9, as it ships with a stub + # that puts up a graphical alert prompting to install + # developer tools. Any system running Mac OS X 10.7 or + # later (Darwin 11 and later) is required to have a 64-bit + # processor. This is not true of the ARM version of Darwin + # that Apple uses in portable devices. + UNAME_PROCESSOR=x86_64 fi echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} exit ;; @@ -1361,154 +1371,6 @@ exit ;; esac -eval $set_cc_for_build -cat >$dummy.c < -# include -#endif -main () -{ -#if defined (sony) -#if defined (MIPSEB) - /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, - I don't know.... */ - printf ("mips-sony-bsd\n"); exit (0); -#else -#include - printf ("m68k-sony-newsos%s\n", -#ifdef NEWSOS4 - "4" -#else - "" -#endif - ); exit (0); -#endif -#endif - -#if defined (__arm) && defined (__acorn) && defined (__unix) - printf ("arm-acorn-riscix\n"); exit (0); -#endif - -#if defined (hp300) && !defined (hpux) - printf ("m68k-hp-bsd\n"); exit (0); -#endif - -#if defined (NeXT) -#if !defined (__ARCHITECTURE__) -#define __ARCHITECTURE__ "m68k" -#endif - int version; - version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; - if (version < 4) - printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); - else - printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); - exit (0); -#endif - -#if defined (MULTIMAX) || defined (n16) -#if defined (UMAXV) - printf ("ns32k-encore-sysv\n"); exit (0); -#else -#if defined (CMU) - printf ("ns32k-encore-mach\n"); exit (0); -#else - printf ("ns32k-encore-bsd\n"); exit (0); -#endif -#endif -#endif - -#if defined (__386BSD__) - printf ("i386-pc-bsd\n"); exit (0); -#endif - -#if defined (sequent) -#if defined (i386) - printf ("i386-sequent-dynix\n"); exit (0); -#endif -#if defined (ns32000) - printf ("ns32k-sequent-dynix\n"); exit (0); -#endif -#endif - -#if defined (_SEQUENT_) - struct utsname un; - - uname(&un); - - if (strncmp(un.version, "V2", 2) == 0) { - printf ("i386-sequent-ptx2\n"); exit (0); - } - if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ - printf ("i386-sequent-ptx1\n"); exit (0); - } - printf ("i386-sequent-ptx\n"); exit (0); - -#endif - -#if defined (vax) -# if !defined (ultrix) -# include -# if defined (BSD) -# if BSD == 43 - printf ("vax-dec-bsd4.3\n"); exit (0); -# else -# if BSD == 199006 - printf ("vax-dec-bsd4.3reno\n"); exit (0); -# else - printf ("vax-dec-bsd\n"); exit (0); -# endif -# endif -# else - printf ("vax-dec-bsd\n"); exit (0); -# endif -# else - printf ("vax-dec-ultrix\n"); exit (0); -# endif -#endif - -#if defined (alliant) && defined (i860) - printf ("i860-alliant-bsd\n"); exit (0); -#endif - - exit (1); -} -EOF - -$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` && - { echo "$SYSTEM_NAME"; exit; } - -# Apollos put the system type in the environment. - -test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; } - -# Convex versions that predate uname can use getsysinfo(1) - -if [ -x /usr/convex/getsysinfo ] -then - case `getsysinfo -f cpu_type` in - c1*) - echo c1-convex-bsd - exit ;; - c2*) - if getsysinfo -f scalar_acc - then echo c32-convex-bsd - else echo c2-convex-bsd - fi - exit ;; - c34*) - echo c34-convex-bsd - exit ;; - c38*) - echo c38-convex-bsd - exit ;; - c4*) - echo c4-convex-bsd - exit ;; - esac -fi - cat >&2 < http://hg.python.org/cpython/rev/118d6f49d6d6 changeset: 91957:118d6f49d6d6 parent: 91954:94d0e842b9ea parent: 91956:77f36cdb71b0 user: doko at ubuntu.com date: Fri Aug 01 17:49:24 2014 +0200 summary: - update config.guess and config.sub to support openrisc. files: config.guess | 192 +++++--------------------------------- config.sub | 23 ++-- 2 files changed, 40 insertions(+), 175 deletions(-) diff --git a/config.guess b/config.guess --- a/config.guess +++ b/config.guess @@ -1,8 +1,8 @@ #! /bin/sh # Attempt to guess a canonical system name. -# Copyright 1992-2013 Free Software Foundation, Inc. +# Copyright 1992-2014 Free Software Foundation, Inc. -timestamp='2013-06-10' +timestamp='2014-03-23' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by @@ -50,7 +50,7 @@ GNU config.guess ($timestamp) Originally written by Per Bothner. -Copyright 1992-2013 Free Software Foundation, Inc. +Copyright 1992-2014 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." @@ -149,7 +149,7 @@ LIBC=gnu #endif EOF - eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'` + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC' | sed 's, ,,g'` ;; esac @@ -826,7 +826,7 @@ *:MINGW*:*) echo ${UNAME_MACHINE}-pc-mingw32 exit ;; - i*:MSYS*:*) + *:MSYS*:*) echo ${UNAME_MACHINE}-pc-msys exit ;; i*:windows32*:*) @@ -969,10 +969,10 @@ eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; } ;; - or1k:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + openrisc*:Linux:*:*) + echo or1k-unknown-linux-${LIBC} exit ;; - or32:Linux:*:*) + or32:Linux:*:* | or1k*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; padre:Linux:*:*) @@ -1260,16 +1260,26 @@ if test "$UNAME_PROCESSOR" = unknown ; then UNAME_PROCESSOR=powerpc fi - if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then - if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ - (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ - grep IS_64BIT_ARCH >/dev/null - then - case $UNAME_PROCESSOR in - i386) UNAME_PROCESSOR=x86_64 ;; - powerpc) UNAME_PROCESSOR=powerpc64 ;; - esac + if test `echo "$UNAME_RELEASE" | sed -e 's/\..*//'` -le 10 ; then + if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + case $UNAME_PROCESSOR in + i386) UNAME_PROCESSOR=x86_64 ;; + powerpc) UNAME_PROCESSOR=powerpc64 ;; + esac + fi fi + elif test "$UNAME_PROCESSOR" = i386 ; then + # Avoid executing cc on OS X 10.9, as it ships with a stub + # that puts up a graphical alert prompting to install + # developer tools. Any system running Mac OS X 10.7 or + # later (Darwin 11 and later) is required to have a 64-bit + # processor. This is not true of the ARM version of Darwin + # that Apple uses in portable devices. + UNAME_PROCESSOR=x86_64 fi echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} exit ;; @@ -1361,154 +1371,6 @@ exit ;; esac -eval $set_cc_for_build -cat >$dummy.c < -# include -#endif -main () -{ -#if defined (sony) -#if defined (MIPSEB) - /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, - I don't know.... */ - printf ("mips-sony-bsd\n"); exit (0); -#else -#include - printf ("m68k-sony-newsos%s\n", -#ifdef NEWSOS4 - "4" -#else - "" -#endif - ); exit (0); -#endif -#endif - -#if defined (__arm) && defined (__acorn) && defined (__unix) - printf ("arm-acorn-riscix\n"); exit (0); -#endif - -#if defined (hp300) && !defined (hpux) - printf ("m68k-hp-bsd\n"); exit (0); -#endif - -#if defined (NeXT) -#if !defined (__ARCHITECTURE__) -#define __ARCHITECTURE__ "m68k" -#endif - int version; - version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; - if (version < 4) - printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); - else - printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); - exit (0); -#endif - -#if defined (MULTIMAX) || defined (n16) -#if defined (UMAXV) - printf ("ns32k-encore-sysv\n"); exit (0); -#else -#if defined (CMU) - printf ("ns32k-encore-mach\n"); exit (0); -#else - printf ("ns32k-encore-bsd\n"); exit (0); -#endif -#endif -#endif - -#if defined (__386BSD__) - printf ("i386-pc-bsd\n"); exit (0); -#endif - -#if defined (sequent) -#if defined (i386) - printf ("i386-sequent-dynix\n"); exit (0); -#endif -#if defined (ns32000) - printf ("ns32k-sequent-dynix\n"); exit (0); -#endif -#endif - -#if defined (_SEQUENT_) - struct utsname un; - - uname(&un); - - if (strncmp(un.version, "V2", 2) == 0) { - printf ("i386-sequent-ptx2\n"); exit (0); - } - if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ - printf ("i386-sequent-ptx1\n"); exit (0); - } - printf ("i386-sequent-ptx\n"); exit (0); - -#endif - -#if defined (vax) -# if !defined (ultrix) -# include -# if defined (BSD) -# if BSD == 43 - printf ("vax-dec-bsd4.3\n"); exit (0); -# else -# if BSD == 199006 - printf ("vax-dec-bsd4.3reno\n"); exit (0); -# else - printf ("vax-dec-bsd\n"); exit (0); -# endif -# endif -# else - printf ("vax-dec-bsd\n"); exit (0); -# endif -# else - printf ("vax-dec-ultrix\n"); exit (0); -# endif -#endif - -#if defined (alliant) && defined (i860) - printf ("i860-alliant-bsd\n"); exit (0); -#endif - - exit (1); -} -EOF - -$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` && - { echo "$SYSTEM_NAME"; exit; } - -# Apollos put the system type in the environment. - -test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; } - -# Convex versions that predate uname can use getsysinfo(1) - -if [ -x /usr/convex/getsysinfo ] -then - case `getsysinfo -f cpu_type` in - c1*) - echo c1-convex-bsd - exit ;; - c2*) - if getsysinfo -f scalar_acc - then echo c32-convex-bsd - else echo c2-convex-bsd - fi - exit ;; - c34*) - echo c34-convex-bsd - exit ;; - c38*) - echo c38-convex-bsd - exit ;; - c4*) - echo c4-convex-bsd - exit ;; - esac -fi - cat >&2 < http://hg.python.org/peps/rev/5b21e2a85e78 changeset: 5513:5b21e2a85e78 user: Andrew Kuchling date: Fri Aug 01 16:39:37 2014 -0400 summary: Mention blog.python.org files: pep-0101.txt | 6 ++++++ 1 files changed, 6 insertions(+), 0 deletions(-) diff --git a/pep-0101.txt b/pep-0101.txt --- a/pep-0101.txt +++ b/pep-0101.txt @@ -53,6 +53,10 @@ task of any release manager is to draft the release schedule. But in case you just signed up... sucker! I mean, uh, congratulations! + * Posting access to http://blog.python.org, a Blogger-hosted weblog. + The RSS feed from this blog is used for the 'Python News' section + on www.python.org. + How to Make A Release Here are the steps taken to make a Python release. Some steps are more @@ -542,6 +546,8 @@ python-announce at python.org python-dev at python.org + ___ Also post the announcement to . + Now it's time to do some cleaning up. These steps are very important! ___ Do the guided post-release steps with the release script. -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Fri Aug 1 22:58:25 2014 From: python-checkins at python.org (charles-francois.natali) Date: Fri, 1 Aug 2014 22:58:25 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2322110=3A_Enable_e?= =?utf-8?q?xtra_compilation_warnings=2E?= Message-ID: <3hQ16n3SYSz7LjM@mail.python.org> http://hg.python.org/cpython/rev/2c70897e5f98 changeset: 91958:2c70897e5f98 user: Charles-Fran?ois Natali date: Fri Aug 01 21:57:49 2014 +0100 summary: Issue #22110: Enable extra compilation warnings. files: configure | 88 ++++++++++++++++++++++++++++++++++++++++ configure.ac | 46 ++++++++++++++++++++ 2 files changed, 134 insertions(+), 0 deletions(-) diff --git a/configure b/configure --- a/configure +++ b/configure @@ -6510,6 +6510,94 @@ BASECFLAGS="$BASECFLAGS -Werror=declaration-after-statement" fi + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can turn on $CC mixed sign comparison warning" >&5 +$as_echo_n "checking if we can turn on $CC mixed sign comparison warning... " >&6; } + ac_save_cc="$CC" + CC="$CC -Wsign-compare" + save_CFLAGS="$CFLAGS" + if ${ac_cv_enable_sign_compare_warning+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + +int +main () +{ + + ; + return 0; +} + +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + + ac_cv_enable_sign_compare_warning=yes + +else + + ac_cv_enable_sign_compare_warning=no + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi + + CFLAGS="$save_CFLAGS" + CC="$ac_save_cc" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_enable_sign_compare_warning" >&5 +$as_echo "$ac_cv_enable_sign_compare_warning" >&6; } + + if test $ac_cv_enable_sign_compare_warning = yes + then + BASECFLAGS="$BASECFLAGS -Wsign-compare" + fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can turn on $CC unreachable code warning" >&5 +$as_echo_n "checking if we can turn on $CC unreachable code warning... " >&6; } + ac_save_cc="$CC" + CC="$CC -Wunreachable-code" + save_CFLAGS="$CFLAGS" + if ${ac_cv_enable_unreachable_code_warning+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + +int +main () +{ + + ; + return 0; +} + +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + + ac_cv_enable_unreachable_code_warning=yes + +else + + ac_cv_enable_unreachable_code_warning=no + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi + + CFLAGS="$save_CFLAGS" + CC="$ac_save_cc" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_enable_unreachable_code_warning" >&5 +$as_echo "$ac_cv_enable_unreachable_code_warning" >&6; } + + # Don't enable unreachable code warning in debug mode, since it usually + # results in non-standard code paths. + if test $ac_cv_enable_unreachable_code_warning = yes && test "$Py_DEBUG" != "true" + then + BASECFLAGS="$BASECFLAGS -Wunreachable-code" + fi + # if using gcc on alpha, use -mieee to get (near) full IEEE 754 # support. Without this, treatment of subnormals doesn't follow # the standard. diff --git a/configure.ac b/configure.ac --- a/configure.ac +++ b/configure.ac @@ -1234,6 +1234,52 @@ BASECFLAGS="$BASECFLAGS -Werror=declaration-after-statement" fi + AC_MSG_CHECKING(if we can turn on $CC mixed sign comparison warning) + ac_save_cc="$CC" + CC="$CC -Wsign-compare" + save_CFLAGS="$CFLAGS" + AC_CACHE_VAL(ac_cv_enable_sign_compare_warning, + AC_COMPILE_IFELSE( + [ + AC_LANG_PROGRAM([[]], [[]]) + ],[ + ac_cv_enable_sign_compare_warning=yes + ],[ + ac_cv_enable_sign_compare_warning=no + ])) + CFLAGS="$save_CFLAGS" + CC="$ac_save_cc" + AC_MSG_RESULT($ac_cv_enable_sign_compare_warning) + + if test $ac_cv_enable_sign_compare_warning = yes + then + BASECFLAGS="$BASECFLAGS -Wsign-compare" + fi + + AC_MSG_CHECKING(if we can turn on $CC unreachable code warning) + ac_save_cc="$CC" + CC="$CC -Wunreachable-code" + save_CFLAGS="$CFLAGS" + AC_CACHE_VAL(ac_cv_enable_unreachable_code_warning, + AC_COMPILE_IFELSE( + [ + AC_LANG_PROGRAM([[]], [[]]) + ],[ + ac_cv_enable_unreachable_code_warning=yes + ],[ + ac_cv_enable_unreachable_code_warning=no + ])) + CFLAGS="$save_CFLAGS" + CC="$ac_save_cc" + AC_MSG_RESULT($ac_cv_enable_unreachable_code_warning) + + # Don't enable unreachable code warning in debug mode, since it usually + # results in non-standard code paths. + if test $ac_cv_enable_unreachable_code_warning = yes && test "$Py_DEBUG" != "true" + then + BASECFLAGS="$BASECFLAGS -Wunreachable-code" + fi + # if using gcc on alpha, use -mieee to get (near) full IEEE 754 # support. Without this, treatment of subnormals doesn't follow # the standard. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Aug 2 07:31:04 2014 From: python-checkins at python.org (terry.reedy) Date: Sat, 2 Aug 2014 07:31:04 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2322077=3A_Improve_?= =?utf-8?q?index_error_messages_for_bytearrays=2C_bytes=2C_lists=2C_and?= Message-ID: <3hQDVJ4qkNz7Ljh@mail.python.org> http://hg.python.org/cpython/rev/02d6d3a7a181 changeset: 91959:02d6d3a7a181 user: Terry Jan Reedy date: Sat Aug 02 01:30:37 2014 -0400 summary: Issue #22077: Improve index error messages for bytearrays, bytes, lists, and tuples by adding 'or slices'. Added ', not tp_name); return NULL; } } @@ -650,7 +652,9 @@ } } else { - PyErr_SetString(PyExc_TypeError, "bytearray indices must be integer"); + PyErr_Format(PyExc_TypeError, + "bytearray indices must be integers or slices, not %.200s", + Py_TYPE(index)->tp_name); return -1; } diff --git a/Objects/bytesobject.c b/Objects/bytesobject.c --- a/Objects/bytesobject.c +++ b/Objects/bytesobject.c @@ -999,7 +999,7 @@ } else { PyErr_Format(PyExc_TypeError, - "byte indices must be integers, not %.200s", + "byte indices must be integers or slices, not %.200s", Py_TYPE(item)->tp_name); return NULL; } diff --git a/Objects/listobject.c b/Objects/listobject.c --- a/Objects/listobject.c +++ b/Objects/listobject.c @@ -2444,7 +2444,7 @@ } else { PyErr_Format(PyExc_TypeError, - "list indices must be integers, not %.200s", + "list indices must be integers or slices, not %.200s", item->ob_type->tp_name); return NULL; } @@ -2608,7 +2608,7 @@ } else { PyErr_Format(PyExc_TypeError, - "list indices must be integers, not %.200s", + "list indices must be integers or slices, not %.200s", item->ob_type->tp_name); return -1; } diff --git a/Objects/tupleobject.c b/Objects/tupleobject.c --- a/Objects/tupleobject.c +++ b/Objects/tupleobject.c @@ -746,7 +746,7 @@ } else { PyErr_Format(PyExc_TypeError, - "tuple indices must be integers, not %.200s", + "tuple indices must be integers or slices, not %.200s", Py_TYPE(item)->tp_name); return NULL; } -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Aug 2 08:51:57 2014 From: python-checkins at python.org (raymond.hettinger) Date: Sat, 2 Aug 2014 08:51:57 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_Fix_typo_in_co?= =?utf-8?q?mment=2E?= Message-ID: <3hQGHd1BFhz7Ljq@mail.python.org> http://hg.python.org/cpython/rev/133ee2b48e52 changeset: 91960:133ee2b48e52 branch: 2.7 parent: 91955:99718bc17109 user: Raymond Hettinger date: Fri Aug 01 23:51:51 2014 -0700 summary: Fix typo in comment. files: Objects/classobject.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Objects/classobject.c b/Objects/classobject.c --- a/Objects/classobject.c +++ b/Objects/classobject.c @@ -4,7 +4,7 @@ #include "Python.h" #include "structmember.h" -/* Free list for method objects to safe malloc/free overhead +/* Free list for method objects to save malloc/free overhead * The im_self element is used to chain the elements. */ static PyMethodObject *free_list; -- Repository URL: http://hg.python.org/cpython From solipsis at pitrou.net Sat Aug 2 10:11:42 2014 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Sat, 02 Aug 2014 10:11:42 +0200 Subject: [Python-checkins] Daily reference leaks (2c70897e5f98): sum=-734 Message-ID: results for 2c70897e5f98 on branch "default" -------------------------------------------- test_asyncio leaked [-212, 106, -477] references, sum=-583 test_asyncio leaked [-61, 33, -135] memory blocks, sum=-163 test_collections leaked [2, 4, 0] references, sum=6 test_collections leaked [1, 2, 0] memory blocks, sum=3 test_functools leaked [0, 0, 3] memory blocks, sum=3 test_site leaked [0, 2, -2] references, sum=0 test_site leaked [0, 2, -2] memory blocks, sum=0 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/cpython/refleaks/refloglzuFKu', '-x'] From python-checkins at python.org Sat Aug 2 13:10:50 2014 From: python-checkins at python.org (ezio.melotti) Date: Sat, 2 Aug 2014 13:10:50 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython=3A_=2315114=3A_the_strict_mod?= =?utf-8?q?e_and_argument_of_HTMLParser=2C_HTMLParser=2Eerror=2C_and_the?= Message-ID: <3hQN2L355Dz7LjR@mail.python.org> http://hg.python.org/cpython/rev/0e2e47c1f205 changeset: 91961:0e2e47c1f205 parent: 91959:02d6d3a7a181 user: Ezio Melotti date: Sat Aug 02 14:10:30 2014 +0300 summary: #15114: the strict mode and argument of HTMLParser, HTMLParser.error, and the HTMLParserError exception have been removed. files: Doc/library/html.parser.rst | 42 +-------- Lib/html/parser.py | 106 ++--------------------- Lib/test/test_htmlparser.py | 69 +-------------- Misc/NEWS | 3 + 4 files changed, 23 insertions(+), 197 deletions(-) diff --git a/Doc/library/html.parser.rst b/Doc/library/html.parser.rst --- a/Doc/library/html.parser.rst +++ b/Doc/library/html.parser.rst @@ -16,9 +16,9 @@ This module defines a class :class:`HTMLParser` which serves as the basis for parsing text files formatted in HTML (HyperText Mark-up Language) and XHTML. -.. class:: HTMLParser(strict=False, *, convert_charrefs=False) +.. class:: HTMLParser(*, convert_charrefs=False) - Create a parser instance. + Create a parser instance able to parse invalid markup. If *convert_charrefs* is ``True`` (default: ``False``), all character references (except the ones in ``script``/``style`` elements) are @@ -26,12 +26,6 @@ The use of ``convert_charrefs=True`` is encouraged and will become the default in Python 3.5. - If *strict* is ``False`` (the default), the parser will accept and parse - invalid markup. If *strict* is ``True`` the parser will raise an - :exc:`~html.parser.HTMLParseError` exception instead [#]_ when it's not - able to parse the markup. The use of ``strict=True`` is discouraged and - the *strict* argument is deprecated. - An :class:`.HTMLParser` instance is fed HTML data and calls handler methods when start tags, end tags, text, comments, and other markup elements are encountered. The user should subclass :class:`.HTMLParser` and override its @@ -40,32 +34,9 @@ This parser does not check that end tags match start tags or call the end-tag handler for elements which are closed implicitly by closing an outer element. - .. versionchanged:: 3.2 - *strict* argument added. - - .. deprecated-removed:: 3.3 3.5 - The *strict* argument and the strict mode have been deprecated. - The parser is now able to accept and parse invalid markup too. - .. versionchanged:: 3.4 *convert_charrefs* keyword argument added. -An exception is defined as well: - - -.. exception:: HTMLParseError - - Exception raised by the :class:`HTMLParser` class when it encounters an error - while parsing and *strict* is ``True``. This exception provides three - attributes: :attr:`msg` is a brief message explaining the error, - :attr:`lineno` is the number of the line on which the broken construct was - detected, and :attr:`offset` is the number of characters into the line at - which the construct starts. - - .. deprecated-removed:: 3.3 3.5 - This exception has been deprecated because it's never raised by the parser - (when the default non-strict mode is used). - Example HTML Parser Application ------------------------------- @@ -246,8 +217,7 @@ The *data* parameter will be the entire contents of the declaration inside the ```` markup. It is sometimes useful to be overridden by a - derived class. The base class implementation raises an :exc:`HTMLParseError` - when *strict* is ``True``. + derived class. The base class implementation does nothing. .. _htmlparser-examples: @@ -358,9 +328,3 @@ Data : tag soup End tag : p End tag : a - -.. rubric:: Footnotes - -.. [#] For backward compatibility reasons *strict* mode does not raise - exceptions for all non-compliant HTML. That is, some invalid HTML - is tolerated even in *strict* mode. diff --git a/Lib/html/parser.py b/Lib/html/parser.py --- a/Lib/html/parser.py +++ b/Lib/html/parser.py @@ -29,35 +29,15 @@ piclose = re.compile('>') commentclose = re.compile(r'--\s*>') # Note: -# 1) the strict attrfind isn't really strict, but we can't make it -# correctly strict without breaking backward compatibility; -# 2) if you change tagfind/attrfind remember to update locatestarttagend too; -# 3) if you change tagfind/attrfind and/or locatestarttagend the parser will +# 1) if you change tagfind/attrfind remember to update locatestarttagend too; +# 2) if you change tagfind/attrfind and/or locatestarttagend the parser will # explode, so don't do it. -tagfind = re.compile('([a-zA-Z][-.a-zA-Z0-9:_]*)(?:\s|/(?!>))*') # see http://www.w3.org/TR/html5/tokenization.html#tag-open-state # and http://www.w3.org/TR/html5/tokenization.html#tag-name-state tagfind_tolerant = re.compile('([a-zA-Z][^\t\n\r\f />\x00]*)(?:\s|/(?!>))*') -attrfind = re.compile( - r'\s*([a-zA-Z_][-.:a-zA-Z_0-9]*)(\s*=\s*' - r'(\'[^\']*\'|"[^"]*"|[^\s"\'=<>`]*))?') attrfind_tolerant = re.compile( r'((?<=[\'"\s/])[^\s/>][^\s/=>]*)(\s*=+\s*' r'(\'[^\']*\'|"[^"]*"|(?![\'"])[^>\s]*))?(?:\s|/(?!>))*') -locatestarttagend = re.compile(r""" - <[a-zA-Z][-.a-zA-Z0-9:_]* # tag name - (?:\s+ # whitespace before attribute name - (?:[a-zA-Z_][-.:a-zA-Z0-9_]* # attribute name - (?:\s*=\s* # value indicator - (?:'[^']*' # LITA-enclosed value - |\"[^\"]*\" # LIT-enclosed value - |[^'\">\s]+ # bare value - ) - )? - ) - )* - \s* # trailing whitespace -""", re.VERBOSE) locatestarttagend_tolerant = re.compile(r""" <[a-zA-Z][^\t\n\r\f />\x00]* # tag name (?:[\s/]* # optional whitespace before attribute name @@ -79,24 +59,6 @@ endtagfind = re.compile('') -class HTMLParseError(Exception): - """Exception raised for all parse errors.""" - - def __init__(self, msg, position=(None, None)): - assert msg - self.msg = msg - self.lineno = position[0] - self.offset = position[1] - - def __str__(self): - result = self.msg - if self.lineno is not None: - result = result + ", at line %d" % self.lineno - if self.offset is not None: - result = result + ", column %d" % (self.offset + 1) - return result - - _default_sentinel = object() class HTMLParser(_markupbase.ParserBase): @@ -123,22 +85,12 @@ CDATA_CONTENT_ELEMENTS = ("script", "style") - def __init__(self, strict=_default_sentinel, *, - convert_charrefs=_default_sentinel): + def __init__(self, *, convert_charrefs=_default_sentinel): """Initialize and reset this instance. If convert_charrefs is True (default: False), all character references are automatically converted to the corresponding Unicode characters. - If strict is set to False (the default) the parser will parse invalid - markup, otherwise it will raise an error. Note that the strict mode - and argument are deprecated. """ - if strict is not _default_sentinel: - warnings.warn("The strict argument and mode are deprecated.", - DeprecationWarning, stacklevel=2) - else: - strict = False # default - self.strict = strict if convert_charrefs is _default_sentinel: convert_charrefs = False # default warnings.warn("The value of convert_charrefs will become True in " @@ -168,11 +120,6 @@ """Handle any buffered data.""" self.goahead(1) - def error(self, message): - warnings.warn("The 'error' method is deprecated.", - DeprecationWarning, stacklevel=2) - raise HTMLParseError(message, self.getpos()) - __starttag_text = None def get_starttag_text(self): @@ -227,10 +174,7 @@ elif startswith("', i + 1) if k < 0: k = rawdata.find('<', i + 1) @@ -282,13 +224,10 @@ if match: # match.group() will contain at least 2 chars if end and match.group() == rawdata[i:]: - if self.strict: - self.error("EOF in middle of entity or char ref") - else: - k = match.end() - if k <= i: - k = n - i = self.updatepos(i, i + 1) + k = match.end() + if k <= i: + k = n + i = self.updatepos(i, i + 1) # incomplete break elif (i + 1) < n: @@ -367,18 +306,12 @@ # Now parse the data between i+1 and j into a tag and attrs attrs = [] - if self.strict: - match = tagfind.match(rawdata, i+1) - else: - match = tagfind_tolerant.match(rawdata, i+1) + match = tagfind_tolerant.match(rawdata, i+1) assert match, 'unexpected call to parse_starttag()' k = match.end() self.lasttag = tag = match.group(1).lower() while k < endpos: - if self.strict: - m = attrfind.match(rawdata, k) - else: - m = attrfind_tolerant.match(rawdata, k) + m = attrfind_tolerant.match(rawdata, k) if not m: break attrname, rest, attrvalue = m.group(1, 2, 3) @@ -401,9 +334,6 @@ - self.__starttag_text.rfind("\n") else: offset = offset + len(self.__starttag_text) - if self.strict: - self.error("junk characters in start tag: %r" - % (rawdata[k:endpos][:20],)) self.handle_data(rawdata[i:endpos]) return endpos if end.endswith('/>'): @@ -419,10 +349,7 @@ # or -1 if incomplete. def check_for_whole_start_tag(self, i): rawdata = self.rawdata - if self.strict: - m = locatestarttagend.match(rawdata, i) - else: - m = locatestarttagend_tolerant.match(rawdata, i) + m = locatestarttagend_tolerant.match(rawdata, i) if m: j = m.end() next = rawdata[j:j+1] @@ -435,9 +362,6 @@ # buffer boundary return -1 # else bogus input - if self.strict: - self.updatepos(i, j + 1) - self.error("malformed empty start tag") if j > i: return j else: @@ -450,9 +374,6 @@ # end of input in or before attribute value, or we have the # '/' from a '/>' ending return -1 - if self.strict: - self.updatepos(i, j) - self.error("malformed start tag") if j > i: return j else: @@ -472,8 +393,6 @@ if self.cdata_elem is not None: self.handle_data(rawdata[i:gtpos]) return gtpos - if self.strict: - self.error("bad end tag: %r" % (rawdata[i:gtpos],)) # find the name: w3.org/TR/html5/tokenization.html#tag-name-state namematch = tagfind_tolerant.match(rawdata, i+2) if not namematch: @@ -539,8 +458,7 @@ pass def unknown_decl(self, data): - if self.strict: - self.error("unknown declaration: %r" % (data,)) + pass # Internal -- helper to remove special character quoting def unescape(self, s): diff --git a/Lib/test/test_htmlparser.py b/Lib/test/test_htmlparser.py --- a/Lib/test/test_htmlparser.py +++ b/Lib/test/test_htmlparser.py @@ -85,7 +85,7 @@ class TestCaseBase(unittest.TestCase): def get_collector(self): - raise NotImplementedError + return EventCollector(convert_charrefs=False) def _run_check(self, source, expected_events, collector=None): if collector is None: @@ -105,21 +105,8 @@ self._run_check(source, events, EventCollectorExtra(convert_charrefs=False)) - def _parse_error(self, source): - def parse(source=source): - parser = self.get_collector() - parser.feed(source) - parser.close() - with self.assertRaises(html.parser.HTMLParseError): - with self.assertWarns(DeprecationWarning): - parse() - -class HTMLParserStrictTestCase(TestCaseBase): - - def get_collector(self): - with support.check_warnings(("", DeprecationWarning), quite=False): - return EventCollector(strict=True, convert_charrefs=False) +class HTMLParserTestCase(TestCaseBase): def test_processing_instruction_only(self): self._run_check("", [ @@ -201,9 +188,6 @@ ("data", "this < text > contains < bare>pointy< brackets"), ]) - def test_illegal_declarations(self): - self._parse_error('') - def test_starttag_end_boundary(self): self._run_check("""""", [("starttag", "a", [("b", "<")])]) self._run_check("""""", [("starttag", "a", [("b", ">")])]) @@ -238,25 +222,6 @@ self._run_check(["", ""], output) - def test_starttag_junk_chars(self): - self._parse_error("") - self._parse_error("") - self._parse_error("") - self._parse_error("") - self._parse_error("'") - self._parse_error("" % dtd, [('decl', 'DOCTYPE ' + dtd)]) - def test_declaration_junk_chars(self): - self._parse_error("") - def test_startendtag(self): self._run_check("

", [ ("startendtag", "p", []), @@ -421,23 +383,12 @@ self._run_check('no charrefs here', [('data', 'no charrefs here')], collector=collector()) - -class HTMLParserTolerantTestCase(HTMLParserStrictTestCase): - - def get_collector(self): - return EventCollector(convert_charrefs=False) - def test_deprecation_warnings(self): with self.assertWarns(DeprecationWarning): EventCollector() # convert_charrefs not passed explicitly - with self.assertWarns(DeprecationWarning): - EventCollector(strict=True) - with self.assertWarns(DeprecationWarning): - EventCollector(strict=False) - with self.assertRaises(html.parser.HTMLParseError): - with self.assertWarns(DeprecationWarning): - EventCollector().error('test') + # the remaining tests were for the "tolerant" parser (which is now + # the default), and check various kind of broken markup def test_tolerant_parsing(self): self._run_check('te>>xt&a<\n' '", diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -121,6 +121,9 @@ Library ------- +- Issue #15114: the strict mode and argument of HTMLParser, HTMLParser.error, + and the HTMLParserError exception have been removed. + - Issue #22085: Dropped support of Tk 8.3 in Tkinter. - Issue #21580: Now Tkinter correctly handles bytes arguments passed to Tk. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Aug 2 14:15:15 2014 From: python-checkins at python.org (ezio.melotti) Date: Sat, 2 Aug 2014 14:15:15 +0200 (CEST) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbjogQWRkIGFuIF9fYWxsX18gdG8g?= =?utf-8?q?html=2Eentities=2E?= Message-ID: <3hQPSg63mBz7LlD@mail.python.org> http://hg.python.org/cpython/rev/5abe28a9c8fe changeset: 91962:5abe28a9c8fe user: Ezio Melotti date: Sat Aug 02 15:15:02 2014 +0300 summary: Add an __all__ to html.entities. files: Lib/html/entities.py | 3 +++ Misc/NEWS | 2 ++ 2 files changed, 5 insertions(+), 0 deletions(-) diff --git a/Lib/html/entities.py b/Lib/html/entities.py --- a/Lib/html/entities.py +++ b/Lib/html/entities.py @@ -1,5 +1,8 @@ """HTML character entity references.""" +__all__ = ['html5', 'name2codepoint', 'codepoint2name', 'entitydefs'] + + # maps the HTML entity name to the Unicode codepoint name2codepoint = { 'AElig': 0x00c6, # latin capital letter AE = latin capital ligature AE, U+00C6 ISOlat1 diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -121,6 +121,8 @@ Library ------- +- Add an __all__ to html.entities. + - Issue #15114: the strict mode and argument of HTMLParser, HTMLParser.error, and the HTMLParserError exception have been removed. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Aug 2 17:36:35 2014 From: python-checkins at python.org (ezio.melotti) Date: Sat, 2 Aug 2014 17:36:35 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython=3A_=2321047=3A_set_the_defaul?= =?utf-8?q?t_value_for_the_*convert=5Fcharrefs*_argument_of_HTMLParser?= Message-ID: <3hQTwz4bDcz7Lkt@mail.python.org> http://hg.python.org/cpython/rev/4425024f2e01 changeset: 91963:4425024f2e01 user: Ezio Melotti date: Sat Aug 02 18:36:12 2014 +0300 summary: #21047: set the default value for the *convert_charrefs* argument of HTMLParser to True. Patch by Berker Peksag. files: Doc/library/html.parser.rst | 9 +++++---- Lib/html/parser.py | 10 ++-------- Lib/test/test_htmlparser.py | 7 ++----- Misc/NEWS | 3 +++ 4 files changed, 12 insertions(+), 17 deletions(-) diff --git a/Doc/library/html.parser.rst b/Doc/library/html.parser.rst --- a/Doc/library/html.parser.rst +++ b/Doc/library/html.parser.rst @@ -16,15 +16,13 @@ This module defines a class :class:`HTMLParser` which serves as the basis for parsing text files formatted in HTML (HyperText Mark-up Language) and XHTML. -.. class:: HTMLParser(*, convert_charrefs=False) +.. class:: HTMLParser(*, convert_charrefs=True) Create a parser instance able to parse invalid markup. - If *convert_charrefs* is ``True`` (default: ``False``), all character + If *convert_charrefs* is ``True`` (the default), all character references (except the ones in ``script``/``style`` elements) are automatically converted to the corresponding Unicode characters. - The use of ``convert_charrefs=True`` is encouraged and will become - the default in Python 3.5. An :class:`.HTMLParser` instance is fed HTML data and calls handler methods when start tags, end tags, text, comments, and other markup elements are @@ -37,6 +35,9 @@ .. versionchanged:: 3.4 *convert_charrefs* keyword argument added. + .. versionchanged:: 3.5 + The default value for argument *convert_charrefs* is now ``True``. + Example HTML Parser Application ------------------------------- diff --git a/Lib/html/parser.py b/Lib/html/parser.py --- a/Lib/html/parser.py +++ b/Lib/html/parser.py @@ -59,7 +59,6 @@ endtagfind = re.compile('') -_default_sentinel = object() class HTMLParser(_markupbase.ParserBase): """Find tags and other markup and call handler functions. @@ -85,17 +84,12 @@ CDATA_CONTENT_ELEMENTS = ("script", "style") - def __init__(self, *, convert_charrefs=_default_sentinel): + def __init__(self, *, convert_charrefs=True): """Initialize and reset this instance. - If convert_charrefs is True (default: False), all character references + If convert_charrefs is True (the default), all character references are automatically converted to the corresponding Unicode characters. """ - if convert_charrefs is _default_sentinel: - convert_charrefs = False # default - warnings.warn("The value of convert_charrefs will become True in " - "3.5. You are encouraged to set the value explicitly.", - DeprecationWarning, stacklevel=2) self.convert_charrefs = convert_charrefs self.reset() diff --git a/Lib/test/test_htmlparser.py b/Lib/test/test_htmlparser.py --- a/Lib/test/test_htmlparser.py +++ b/Lib/test/test_htmlparser.py @@ -346,7 +346,8 @@ self._run_check(html, expected) def test_convert_charrefs(self): - collector = lambda: EventCollectorCharrefs(convert_charrefs=True) + # default value for convert_charrefs is now True + collector = lambda: EventCollectorCharrefs() self.assertTrue(collector().convert_charrefs) charrefs = ['"', '"', '"', '"', '"', '"'] # check charrefs in the middle of the text/attributes @@ -383,10 +384,6 @@ self._run_check('no charrefs here', [('data', 'no charrefs here')], collector=collector()) - def test_deprecation_warnings(self): - with self.assertWarns(DeprecationWarning): - EventCollector() # convert_charrefs not passed explicitly - # the remaining tests were for the "tolerant" parser (which is now # the default), and check various kind of broken markup def test_tolerant_parsing(self): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -121,6 +121,9 @@ Library ------- +- Issue #21047: set the default value for the *convert_charrefs* argument + of HTMLParser to True. Patch by Berker Peksag. + - Add an __all__ to html.entities. - Issue #15114: the strict mode and argument of HTMLParser, HTMLParser.error, -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Aug 2 17:54:55 2014 From: python-checkins at python.org (ezio.melotti) Date: Sat, 2 Aug 2014 17:54:55 +0200 (CEST) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbjogIzE1MTE0LCAjMjEwNDc6IHVw?= =?utf-8?q?date_whatsnew_in_Python_3=2E5=2E?= Message-ID: <3hQVL712G7z7Ll6@mail.python.org> http://hg.python.org/cpython/rev/5b95f3fdcc0b changeset: 91964:5b95f3fdcc0b user: Ezio Melotti date: Sat Aug 02 18:54:30 2014 +0300 summary: #15114, #21047: update whatsnew in Python 3.5. files: Doc/whatsnew/3.5.rst | 6 ++++++ 1 files changed, 6 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 @@ -335,6 +335,12 @@ attribute, the qualified name, which is now used for the representation of a generator (``repr(gen)``). See :issue:`21205`. +* The deprecated "strict" mode and argument of :class:`~html.parser.HTMLParser`, + :meth:`HTMLParser.error`, and the :exc:`HTMLParserError` exception have been + removed (contributed by Ezio Melotti in :issue:`15114`). + The *convert_charrefs* argument of :class:`~html.parser.HTMLParser` is + now ``True`` by default (contributed by Berker Peksag in :issue:`21047`). + Changes in the C API -------------------- -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Aug 3 07:30:33 2014 From: python-checkins at python.org (raymond.hettinger) Date: Sun, 3 Aug 2014 07:30:33 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Fix_whitespace_in_example?= =?utf-8?q?=2E?= Message-ID: <3hQrRF5sZ4z7LjS@mail.python.org> http://hg.python.org/cpython/rev/b1cbcbf5d4e6 changeset: 91965:b1cbcbf5d4e6 user: Raymond Hettinger date: Sat Aug 02 22:30:26 2014 -0700 summary: Fix whitespace in example. files: Doc/library/reprlib.rst | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/library/reprlib.rst b/Doc/library/reprlib.rst --- a/Doc/library/reprlib.rst +++ b/Doc/library/reprlib.rst @@ -49,8 +49,8 @@ >>> class MyList(list): ... @recursive_repr() - ... def __repr__(self): - ... return '<' + '|'.join(map(repr, self)) + '>' + ... def __repr__(self): + ... return '<' + '|'.join(map(repr, self)) + '>' ... >>> m = MyList('abc') >>> m.append(m) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Aug 3 07:32:41 2014 From: python-checkins at python.org (raymond.hettinger) Date: Sun, 3 Aug 2014 07:32:41 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E4=29=3A_Fix_whitespace?= =?utf-8?q?_in_example=2E?= Message-ID: <3hQrTj30yHz7LlN@mail.python.org> http://hg.python.org/cpython/rev/6d6da976553e changeset: 91966:6d6da976553e branch: 3.4 parent: 91956:77f36cdb71b0 user: Raymond Hettinger date: Sat Aug 02 22:32:10 2014 -0700 summary: Fix whitespace in example. files: Doc/library/reprlib.rst | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/library/reprlib.rst b/Doc/library/reprlib.rst --- a/Doc/library/reprlib.rst +++ b/Doc/library/reprlib.rst @@ -49,8 +49,8 @@ >>> class MyList(list): ... @recursive_repr() - ... def __repr__(self): - ... return '<' + '|'.join(map(repr, self)) + '>' + ... def __repr__(self): + ... return '<' + '|'.join(map(repr, self)) + '>' ... >>> m = MyList('abc') >>> m.append(m) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Aug 3 07:32:42 2014 From: python-checkins at python.org (raymond.hettinger) Date: Sun, 3 Aug 2014 07:32:42 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_merge?= Message-ID: <3hQrTk4cSFz7Lkv@mail.python.org> http://hg.python.org/cpython/rev/751328f413a8 changeset: 91967:751328f413a8 parent: 91965:b1cbcbf5d4e6 parent: 91966:6d6da976553e user: Raymond Hettinger date: Sat Aug 02 22:32:33 2014 -0700 summary: merge files: -- Repository URL: http://hg.python.org/cpython From solipsis at pitrou.net Sun Aug 3 10:30:23 2014 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Sun, 03 Aug 2014 10:30:23 +0200 Subject: [Python-checkins] Daily reference leaks (5b95f3fdcc0b): sum=-328 Message-ID: results for 5b95f3fdcc0b on branch "default" -------------------------------------------- test_asyncio leaked [-265, 106, -106] references, sum=-265 test_asyncio leaked [-75, 31, -28] memory blocks, sum=-72 test_collections leaked [2, 0, 0] references, sum=2 test_functools leaked [0, 0, 3] memory blocks, sum=3 test_site leaked [0, 0, 2] references, sum=2 test_site leaked [0, 0, 2] memory blocks, sum=2 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/cpython/refleaks/reflogLjPSqu', '-x'] From python-checkins at python.org Sun Aug 3 21:30:55 2014 From: python-checkins at python.org (jason.coombs) Date: Sun, 3 Aug 2014 21:30:55 +0200 (CEST) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzEzNTQw?= =?utf-8?q?=3A_Expanded_argparse_documents_to_clarify_the_action_API?= Message-ID: <3hRC4v6NQwz7LjS@mail.python.org> http://hg.python.org/cpython/rev/956c6d33a57d changeset: 91968:956c6d33a57d branch: 2.7 parent: 73954:d60856651139 user: Jason R. Coombs date: Tue Dec 13 23:36:45 2011 -0500 summary: Issue #13540: Expanded argparse documents to clarify the action API files: Doc/library/argparse.rst | 95 ++++++++++++++++++++++----- 1 files changed, 76 insertions(+), 19 deletions(-) diff --git a/Doc/library/argparse.rst b/Doc/library/argparse.rst --- a/Doc/library/argparse.rst +++ b/Doc/library/argparse.rst @@ -650,7 +650,7 @@ actions can do just about anything with the command-line arguments associated with them, though most actions simply add an attribute to the object returned by :meth:`~ArgumentParser.parse_args`. The ``action`` keyword argument specifies -how the command-line arguments should be handled. The supported actions are: +how the command-line arguments should be handled. The supplied actions are: * ``'store'`` - This just stores the argument's value. This is the default action. For example:: @@ -713,24 +713,9 @@ >>> parser.parse_args(['--version']) PROG 2.0 -You can also specify an arbitrary action by passing an object that implements -the Action API. The easiest way to do this is to extend -:class:`argparse.Action`, supplying an appropriate ``__call__`` method. The -``__call__`` method should accept four parameters: - -* ``parser`` - The ArgumentParser object which contains this action. - -* ``namespace`` - The :class:`Namespace` object that will be returned by - :meth:`~ArgumentParser.parse_args`. Most actions add an attribute to this - object. - -* ``values`` - The associated command-line arguments, with any type conversions - applied. (Type conversions are specified with the type_ keyword argument to - :meth:`~ArgumentParser.add_argument`. - -* ``option_string`` - The option string that was used to invoke this action. - The ``option_string`` argument is optional, and will be absent if the action - is associated with a positional argument. +You may also specify an arbitrary action by passing an Action class or other +class that implements the same interface. The recommended way to do this is +to extend :class:`argparse.Action`, overriding the ``__call__`` method. An example of a custom action:: @@ -748,6 +733,9 @@ >>> args Namespace(bar='1', foo='2') +Many actions also override the ``__init__`` method, validating the parameters +to the argument definition and raising a ValueError or other Exception on +failure. nargs ^^^^^ @@ -1153,6 +1141,75 @@ >>> parser.parse_args('--foo XXX'.split()) Namespace(bar='XXX') +Action classes +^^^^^^^^^^^^^^ + +.. class:: Action(option_strings, dest, nargs=None, const=None, default=None, + type=None, choices=None, required=False, help=None, + metavar=None) + +Action objects are used by an ArgumentParser to represent the information +needed to parse a single argument from one or more strings from the +command line. The keyword arguments to the Action constructor are made +available as attributes of Action instances. + +* ``option_strings`` - A list of command-line option strings which + should be associated with this action. + +* ``dest`` - The name of the attribute to hold the created object(s) + +* ``nargs`` - The number of command-line arguments that should be + consumed. By default, one argument will be consumed and a single + value will be produced. Other values include: + - N (an integer) consumes N arguments (and produces a list) + - '?' consumes zero or one arguments + - '*' consumes zero or more arguments (and produces a list) + - '+' consumes one or more arguments (and produces a list) + Note that the difference between the default and nargs=1 is that + with the default, a single value will be produced, while with + nargs=1, a list containing a single value will be produced. + +* ``const`` - The value to be produced if the option is specified and the + option uses an action that takes no values. + +* ``default`` - The value to be produced if the option is not specified. + +* ``type`` - The type which the command-line arguments should be converted + to, should be one of 'string', 'int', 'float', 'complex' or a + callable object that accepts a single string argument. If None, + 'string' is assumed. + +* ``choices`` - A container of values that should be allowed. If not None, + after a command-line argument has been converted to the appropriate + type, an exception will be raised if it is not a member of this + collection. + +* ``required`` - True if the action must always be specified at the + command line. This is only meaningful for optional command-line + arguments. + +* ``help`` - The help string describing the argument. + +* ``metavar`` - The name to be used for the option's argument with the + help string. If None, the 'dest' value will be used as the name. + +Action classes must also override the ``__call__`` method, which should accept +four parameters: + +* ``parser`` - The ArgumentParser object which contains this action. + +* ``namespace`` - The :class:`Namespace` object that will be returned by + :meth:`~ArgumentParser.parse_args`. Most actions add an attribute to this + object using :func:`setattr`. + +* ``values`` - The associated command-line arguments, with any type conversions + applied. Type conversions are specified with the type_ keyword argument to + :meth:`~ArgumentParser.add_argument`. + +* ``option_string`` - The option string that was used to invoke this action. + The ``option_string`` argument is optional, and will be absent if the action + is associated with a positional argument. + The parse_args() method ----------------------- -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Aug 3 21:30:57 2014 From: python-checkins at python.org (jason.coombs) Date: Sun, 3 Aug 2014 21:30:57 +0200 (CEST) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzEzNTQw?= =?utf-8?q?=3A_Removed_redundant_documentation_about_Action_instance_attri?= =?utf-8?q?butes=2E?= Message-ID: <3hRC4x29hmz7Lmq@mail.python.org> http://hg.python.org/cpython/rev/008a5473f300 changeset: 91969:008a5473f300 branch: 2.7 user: Jason R. Coombs date: Sun Jul 20 10:52:46 2014 -0400 summary: Issue #13540: Removed redundant documentation about Action instance attributes. Updated example and documentation per recommendations by Steven Bethard in msg149524. files: Doc/library/argparse.rst | 75 +++++++++------------------ 1 files changed, 26 insertions(+), 49 deletions(-) diff --git a/Doc/library/argparse.rst b/Doc/library/argparse.rst --- a/Doc/library/argparse.rst +++ b/Doc/library/argparse.rst @@ -713,13 +713,18 @@ >>> parser.parse_args(['--version']) PROG 2.0 -You may also specify an arbitrary action by passing an Action class or other -class that implements the same interface. The recommended way to do this is -to extend :class:`argparse.Action`, overriding the ``__call__`` method. +You may also specify an arbitrary action by passing an Action subclass or +other object that implements the same interface. The recommended way to do +this is to extend :class:`argparse.Action`, overriding the ``__call__`` method +and optionally the ``__init__`` method. An example of a custom action:: >>> class FooAction(argparse.Action): + ... def __init__(self, option_strings, dest, nargs=None, **kwargs): + ... if nargs is not None: + ... raise ValueError("nargs not allowed") + ... super(FooAction, self).__init__(option_strings, dest, **kwargs) ... def __call__(self, parser, namespace, values, option_string=None): ... print '%r %r %r' % (namespace, values, option_string) ... setattr(namespace, self.dest, values) @@ -733,9 +738,7 @@ >>> args Namespace(bar='1', foo='2') -Many actions also override the ``__init__`` method, validating the parameters -to the argument definition and raising a ValueError or other Exception on -failure. +For more details, see :class:`argparse.Action`. nargs ^^^^^ @@ -1144,57 +1147,28 @@ Action classes ^^^^^^^^^^^^^^ +Action classes implement the Action API, a callable which returns a callable +which processes arguments from the command-line. Any object which follows +this API may be passed as the ``action`` parameter to +:method:`add_argument`. + .. class:: Action(option_strings, dest, nargs=None, const=None, default=None, type=None, choices=None, required=False, help=None, metavar=None) Action objects are used by an ArgumentParser to represent the information needed to parse a single argument from one or more strings from the -command line. The keyword arguments to the Action constructor are made -available as attributes of Action instances. +command line. The Action class must accept the two positional arguments +plus any keyword arguments passed to :method:`ArgumentParser.add_argument` +except for the ``action`` itself. -* ``option_strings`` - A list of command-line option strings which - should be associated with this action. +Instances of Action (or return value of any callable to the ``action`` +parameter) should have attributes "dest", "option_strings", "default", "type", +"required", "help", etc. defined. The easiest way to ensure these attributes +are defined is to call ``Action.__init__``. -* ``dest`` - The name of the attribute to hold the created object(s) - -* ``nargs`` - The number of command-line arguments that should be - consumed. By default, one argument will be consumed and a single - value will be produced. Other values include: - - N (an integer) consumes N arguments (and produces a list) - - '?' consumes zero or one arguments - - '*' consumes zero or more arguments (and produces a list) - - '+' consumes one or more arguments (and produces a list) - Note that the difference between the default and nargs=1 is that - with the default, a single value will be produced, while with - nargs=1, a list containing a single value will be produced. - -* ``const`` - The value to be produced if the option is specified and the - option uses an action that takes no values. - -* ``default`` - The value to be produced if the option is not specified. - -* ``type`` - The type which the command-line arguments should be converted - to, should be one of 'string', 'int', 'float', 'complex' or a - callable object that accepts a single string argument. If None, - 'string' is assumed. - -* ``choices`` - A container of values that should be allowed. If not None, - after a command-line argument has been converted to the appropriate - type, an exception will be raised if it is not a member of this - collection. - -* ``required`` - True if the action must always be specified at the - command line. This is only meaningful for optional command-line - arguments. - -* ``help`` - The help string describing the argument. - -* ``metavar`` - The name to be used for the option's argument with the - help string. If None, the 'dest' value will be used as the name. - -Action classes must also override the ``__call__`` method, which should accept -four parameters: +Action instances should be callable, so subclasses must override the +``__call__`` method, which should accept four parameters: * ``parser`` - The ArgumentParser object which contains this action. @@ -1210,6 +1184,9 @@ The ``option_string`` argument is optional, and will be absent if the action is associated with a positional argument. +The ``__call__`` method may perform arbitrary actions, but will typically set +attributes on the ``namespace`` based on ``dest`` and ``values``. + The parse_args() method ----------------------- -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Aug 3 21:30:58 2014 From: python-checkins at python.org (jason.coombs) Date: Sun, 3 Aug 2014 21:30:58 +0200 (CEST) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzEzNTQw?= =?utf-8?q?=3A_Update_references_to_Action_class_to_match_syntax_used_for_?= =?utf-8?q?other?= Message-ID: <3hRC4y3rz1z7Ln8@mail.python.org> http://hg.python.org/cpython/rev/7a627bc9d40e changeset: 91970:7a627bc9d40e branch: 2.7 user: Jason R. Coombs date: Sun Aug 03 14:54:11 2014 -0400 summary: Issue #13540: Update references to Action class to match syntax used for other classes in this file. files: Doc/library/argparse.rst | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/library/argparse.rst b/Doc/library/argparse.rst --- a/Doc/library/argparse.rst +++ b/Doc/library/argparse.rst @@ -715,7 +715,7 @@ You may also specify an arbitrary action by passing an Action subclass or other object that implements the same interface. The recommended way to do -this is to extend :class:`argparse.Action`, overriding the ``__call__`` method +this is to extend :class:`Action`, overriding the ``__call__`` method and optionally the ``__init__`` method. An example of a custom action:: @@ -738,7 +738,7 @@ >>> args Namespace(bar='1', foo='2') -For more details, see :class:`argparse.Action`. +For more details, see :class:`Action`. nargs ^^^^^ -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Aug 3 21:30:59 2014 From: python-checkins at python.org (jason.coombs) Date: Sun, 3 Aug 2014 21:30:59 +0200 (CEST) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMi43IC0+IDIuNyk6?= =?utf-8?q?_Issue_=2313540=3A_Merge_commits?= Message-ID: <3hRC4z71gLz7Ln8@mail.python.org> http://hg.python.org/cpython/rev/b232e937e668 changeset: 91971:b232e937e668 branch: 2.7 parent: 91960:133ee2b48e52 parent: 91970:7a627bc9d40e user: Jason R. Coombs date: Sun Aug 03 14:57:20 2014 -0400 summary: Issue #13540: Merge commits files: Doc/library/argparse.rst | 72 ++++++++++++++++++++------- 1 files changed, 53 insertions(+), 19 deletions(-) diff --git a/Doc/library/argparse.rst b/Doc/library/argparse.rst --- a/Doc/library/argparse.rst +++ b/Doc/library/argparse.rst @@ -664,7 +664,7 @@ actions can do just about anything with the command-line arguments associated with them, though most actions simply add an attribute to the object returned by :meth:`~ArgumentParser.parse_args`. The ``action`` keyword argument specifies -how the command-line arguments should be handled. The supported actions are: +how the command-line arguments should be handled. The supplied actions are: * ``'store'`` - This just stores the argument's value. This is the default action. For example:: @@ -740,28 +740,18 @@ >>> parser.parse_args(['--version']) PROG 2.0 -You can also specify an arbitrary action by passing an object that implements -the Action API. The easiest way to do this is to extend -:class:`argparse.Action`, supplying an appropriate ``__call__`` method. The -``__call__`` method should accept four parameters: - -* ``parser`` - The ArgumentParser object which contains this action. - -* ``namespace`` - The :class:`Namespace` object that will be returned by - :meth:`~ArgumentParser.parse_args`. Most actions add an attribute to this - object. - -* ``values`` - The associated command-line arguments, with any type conversions - applied. (Type conversions are specified with the type_ keyword argument to - :meth:`~ArgumentParser.add_argument`.) - -* ``option_string`` - The option string that was used to invoke this action. - The ``option_string`` argument is optional, and will be absent if the action - is associated with a positional argument. +You may also specify an arbitrary action by passing an Action subclass or +other object that implements the same interface. The recommended way to do +this is to extend :class:`Action`, overriding the ``__call__`` method +and optionally the ``__init__`` method. An example of a custom action:: >>> class FooAction(argparse.Action): + ... def __init__(self, option_strings, dest, nargs=None, **kwargs): + ... if nargs is not None: + ... raise ValueError("nargs not allowed") + ... super(FooAction, self).__init__(option_strings, dest, **kwargs) ... def __call__(self, parser, namespace, values, option_string=None): ... print '%r %r %r' % (namespace, values, option_string) ... setattr(namespace, self.dest, values) @@ -775,6 +765,7 @@ >>> args Namespace(bar='1', foo='2') +For more details, see :class:`Action`. nargs ^^^^^ @@ -1218,6 +1209,49 @@ >>> parser.parse_args('--foo XXX'.split()) Namespace(bar='XXX') +Action classes +^^^^^^^^^^^^^^ + +Action classes implement the Action API, a callable which returns a callable +which processes arguments from the command-line. Any object which follows +this API may be passed as the ``action`` parameter to +:method:`add_argument`. + +.. class:: Action(option_strings, dest, nargs=None, const=None, default=None, + type=None, choices=None, required=False, help=None, + metavar=None) + +Action objects are used by an ArgumentParser to represent the information +needed to parse a single argument from one or more strings from the +command line. The Action class must accept the two positional arguments +plus any keyword arguments passed to :method:`ArgumentParser.add_argument` +except for the ``action`` itself. + +Instances of Action (or return value of any callable to the ``action`` +parameter) should have attributes "dest", "option_strings", "default", "type", +"required", "help", etc. defined. The easiest way to ensure these attributes +are defined is to call ``Action.__init__``. + +Action instances should be callable, so subclasses must override the +``__call__`` method, which should accept four parameters: + +* ``parser`` - The ArgumentParser object which contains this action. + +* ``namespace`` - The :class:`Namespace` object that will be returned by + :meth:`~ArgumentParser.parse_args`. Most actions add an attribute to this + object using :func:`setattr`. + +* ``values`` - The associated command-line arguments, with any type conversions + applied. Type conversions are specified with the type_ keyword argument to + :meth:`~ArgumentParser.add_argument`. + +* ``option_string`` - The option string that was used to invoke this action. + The ``option_string`` argument is optional, and will be absent if the action + is associated with a positional argument. + +The ``__call__`` method may perform arbitrary actions, but will typically set +attributes on the ``namespace`` based on ``dest`` and ``values``. + The parse_args() method ----------------------- -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Aug 3 21:31:48 2014 From: python-checkins at python.org (jason.coombs) Date: Sun, 3 Aug 2014 21:31:48 +0200 (CEST) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4yKTogSXNzdWUgIzEzNTQw?= =?utf-8?q?=3A_Expanded_argparse_documents_to_clarify_the_action_API?= Message-ID: <3hRC5w6kknz7LjS@mail.python.org> http://hg.python.org/cpython/rev/e2c9e0a3ef02 changeset: 91972:e2c9e0a3ef02 branch: 3.2 parent: 91664:4de94641ba3e user: Jason R. Coombs date: Tue Dec 13 23:36:45 2011 -0500 summary: Issue #13540: Expanded argparse documents to clarify the action API files: Doc/library/argparse.rst | 95 ++++++++++++++++++++++----- 1 files changed, 76 insertions(+), 19 deletions(-) diff --git a/Doc/library/argparse.rst b/Doc/library/argparse.rst --- a/Doc/library/argparse.rst +++ b/Doc/library/argparse.rst @@ -663,7 +663,7 @@ actions can do just about anything with the command-line arguments associated with them, though most actions simply add an attribute to the object returned by :meth:`~ArgumentParser.parse_args`. The ``action`` keyword argument specifies -how the command-line arguments should be handled. The supported actions are: +how the command-line arguments should be handled. The supplied actions are: * ``'store'`` - This just stores the argument's value. This is the default action. For example:: @@ -737,24 +737,9 @@ >>> parser.parse_args(['--version']) PROG 2.0 -You can also specify an arbitrary action by passing an object that implements -the Action API. The easiest way to do this is to extend -:class:`argparse.Action`, supplying an appropriate ``__call__`` method. The -``__call__`` method should accept four parameters: - -* ``parser`` - The ArgumentParser object which contains this action. - -* ``namespace`` - The :class:`Namespace` object that will be returned by - :meth:`~ArgumentParser.parse_args`. Most actions add an attribute to this - object. - -* ``values`` - The associated command-line arguments, with any type conversions - applied. (Type conversions are specified with the type_ keyword argument to - :meth:`~ArgumentParser.add_argument`.) - -* ``option_string`` - The option string that was used to invoke this action. - The ``option_string`` argument is optional, and will be absent if the action - is associated with a positional argument. +You may also specify an arbitrary action by passing an Action class or other +class that implements the same interface. The recommended way to do this is +to extend :class:`argparse.Action`, overriding the ``__call__`` method. An example of a custom action:: @@ -772,6 +757,9 @@ >>> args Namespace(bar='1', foo='2') +Many actions also override the ``__init__`` method, validating the parameters +to the argument definition and raising a ValueError or other Exception on +failure. nargs ^^^^^ @@ -1218,6 +1206,75 @@ >>> parser.parse_args('--foo XXX'.split()) Namespace(bar='XXX') +Action classes +^^^^^^^^^^^^^^ + +.. class:: Action(option_strings, dest, nargs=None, const=None, default=None, + type=None, choices=None, required=False, help=None, + metavar=None) + +Action objects are used by an ArgumentParser to represent the information +needed to parse a single argument from one or more strings from the +command line. The keyword arguments to the Action constructor are made +available as attributes of Action instances. + +* ``option_strings`` - A list of command-line option strings which + should be associated with this action. + +* ``dest`` - The name of the attribute to hold the created object(s) + +* ``nargs`` - The number of command-line arguments that should be + consumed. By default, one argument will be consumed and a single + value will be produced. Other values include: + - N (an integer) consumes N arguments (and produces a list) + - '?' consumes zero or one arguments + - '*' consumes zero or more arguments (and produces a list) + - '+' consumes one or more arguments (and produces a list) + Note that the difference between the default and nargs=1 is that + with the default, a single value will be produced, while with + nargs=1, a list containing a single value will be produced. + +* ``const`` - The value to be produced if the option is specified and the + option uses an action that takes no values. + +* ``default`` - The value to be produced if the option is not specified. + +* ``type`` - The type which the command-line arguments should be converted + to, should be one of 'string', 'int', 'float', 'complex' or a + callable object that accepts a single string argument. If None, + 'string' is assumed. + +* ``choices`` - A container of values that should be allowed. If not None, + after a command-line argument has been converted to the appropriate + type, an exception will be raised if it is not a member of this + collection. + +* ``required`` - True if the action must always be specified at the + command line. This is only meaningful for optional command-line + arguments. + +* ``help`` - The help string describing the argument. + +* ``metavar`` - The name to be used for the option's argument with the + help string. If None, the 'dest' value will be used as the name. + +Action classes must also override the ``__call__`` method, which should accept +four parameters: + +* ``parser`` - The ArgumentParser object which contains this action. + +* ``namespace`` - The :class:`Namespace` object that will be returned by + :meth:`~ArgumentParser.parse_args`. Most actions add an attribute to this + object using :func:`setattr`. + +* ``values`` - The associated command-line arguments, with any type conversions + applied. Type conversions are specified with the type_ keyword argument to + :meth:`~ArgumentParser.add_argument`. + +* ``option_string`` - The option string that was used to invoke this action. + The ``option_string`` argument is optional, and will be absent if the action + is associated with a positional argument. + The parse_args() method ----------------------- -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Aug 3 21:31:50 2014 From: python-checkins at python.org (jason.coombs) Date: Sun, 3 Aug 2014 21:31:50 +0200 (CEST) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4yKTogSXNzdWUgIzEzNTQw?= =?utf-8?q?=3A_Removed_redundant_documentation_about_Action_instance_attri?= =?utf-8?q?butes=2E?= Message-ID: <3hRC5y2RlGz7Lmx@mail.python.org> http://hg.python.org/cpython/rev/c10a6ca9cb32 changeset: 91973:c10a6ca9cb32 branch: 3.2 user: Jason R. Coombs date: Sun Jul 20 10:52:46 2014 -0400 summary: Issue #13540: Removed redundant documentation about Action instance attributes. Updated example and documentation per recommendations by Steven Bethard in msg149524. files: Doc/library/argparse.rst | 75 +++++++++------------------ 1 files changed, 26 insertions(+), 49 deletions(-) diff --git a/Doc/library/argparse.rst b/Doc/library/argparse.rst --- a/Doc/library/argparse.rst +++ b/Doc/library/argparse.rst @@ -737,13 +737,18 @@ >>> parser.parse_args(['--version']) PROG 2.0 -You may also specify an arbitrary action by passing an Action class or other -class that implements the same interface. The recommended way to do this is -to extend :class:`argparse.Action`, overriding the ``__call__`` method. +You may also specify an arbitrary action by passing an Action subclass or +other object that implements the same interface. The recommended way to do +this is to extend :class:`argparse.Action`, overriding the ``__call__`` method +and optionally the ``__init__`` method. An example of a custom action:: >>> class FooAction(argparse.Action): + ... def __init__(self, option_strings, dest, nargs=None, **kwargs): + ... if nargs is not None: + ... raise ValueError("nargs not allowed") + ... super(FooAction, self).__init__(option_strings, dest, **kwargs) ... def __call__(self, parser, namespace, values, option_string=None): ... print('%r %r %r' % (namespace, values, option_string)) ... setattr(namespace, self.dest, values) @@ -757,9 +762,7 @@ >>> args Namespace(bar='1', foo='2') -Many actions also override the ``__init__`` method, validating the parameters -to the argument definition and raising a ValueError or other Exception on -failure. +For more details, see :class:`argparse.Action`. nargs ^^^^^ @@ -1209,57 +1212,28 @@ Action classes ^^^^^^^^^^^^^^ +Action classes implement the Action API, a callable which returns a callable +which processes arguments from the command-line. Any object which follows +this API may be passed as the ``action`` parameter to +:method:`add_argument`. + .. class:: Action(option_strings, dest, nargs=None, const=None, default=None, type=None, choices=None, required=False, help=None, metavar=None) Action objects are used by an ArgumentParser to represent the information needed to parse a single argument from one or more strings from the -command line. The keyword arguments to the Action constructor are made -available as attributes of Action instances. +command line. The Action class must accept the two positional arguments +plus any keyword arguments passed to :method:`ArgumentParser.add_argument` +except for the ``action`` itself. -* ``option_strings`` - A list of command-line option strings which - should be associated with this action. +Instances of Action (or return value of any callable to the ``action`` +parameter) should have attributes "dest", "option_strings", "default", "type", +"required", "help", etc. defined. The easiest way to ensure these attributes +are defined is to call ``Action.__init__``. -* ``dest`` - The name of the attribute to hold the created object(s) - -* ``nargs`` - The number of command-line arguments that should be - consumed. By default, one argument will be consumed and a single - value will be produced. Other values include: - - N (an integer) consumes N arguments (and produces a list) - - '?' consumes zero or one arguments - - '*' consumes zero or more arguments (and produces a list) - - '+' consumes one or more arguments (and produces a list) - Note that the difference between the default and nargs=1 is that - with the default, a single value will be produced, while with - nargs=1, a list containing a single value will be produced. - -* ``const`` - The value to be produced if the option is specified and the - option uses an action that takes no values. - -* ``default`` - The value to be produced if the option is not specified. - -* ``type`` - The type which the command-line arguments should be converted - to, should be one of 'string', 'int', 'float', 'complex' or a - callable object that accepts a single string argument. If None, - 'string' is assumed. - -* ``choices`` - A container of values that should be allowed. If not None, - after a command-line argument has been converted to the appropriate - type, an exception will be raised if it is not a member of this - collection. - -* ``required`` - True if the action must always be specified at the - command line. This is only meaningful for optional command-line - arguments. - -* ``help`` - The help string describing the argument. - -* ``metavar`` - The name to be used for the option's argument with the - help string. If None, the 'dest' value will be used as the name. - -Action classes must also override the ``__call__`` method, which should accept -four parameters: +Action instances should be callable, so subclasses must override the +``__call__`` method, which should accept four parameters: * ``parser`` - The ArgumentParser object which contains this action. @@ -1275,6 +1249,9 @@ The ``option_string`` argument is optional, and will be absent if the action is associated with a positional argument. +The ``__call__`` method may perform arbitrary actions, but will typically set +attributes on the ``namespace`` based on ``dest`` and ``values``. + The parse_args() method ----------------------- -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Aug 3 21:31:51 2014 From: python-checkins at python.org (jason.coombs) Date: Sun, 3 Aug 2014 21:31:51 +0200 (CEST) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4yKTogSXNzdWUgIzEzNTQw?= =?utf-8?q?=3A_Update_references_to_Action_class_to_match_syntax_used_for_?= =?utf-8?q?other?= Message-ID: <3hRC5z49HYz7LnD@mail.python.org> http://hg.python.org/cpython/rev/634f3fe8cbde changeset: 91974:634f3fe8cbde branch: 3.2 user: Jason R. Coombs date: Sun Aug 03 14:54:11 2014 -0400 summary: Issue #13540: Update references to Action class to match syntax used for other classes in this file. files: Doc/library/argparse.rst | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/library/argparse.rst b/Doc/library/argparse.rst --- a/Doc/library/argparse.rst +++ b/Doc/library/argparse.rst @@ -739,7 +739,7 @@ You may also specify an arbitrary action by passing an Action subclass or other object that implements the same interface. The recommended way to do -this is to extend :class:`argparse.Action`, overriding the ``__call__`` method +this is to extend :class:`Action`, overriding the ``__call__`` method and optionally the ``__init__`` method. An example of a custom action:: @@ -762,7 +762,7 @@ >>> args Namespace(bar='1', foo='2') -For more details, see :class:`argparse.Action`. +For more details, see :class:`Action`. nargs ^^^^^ -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Aug 3 21:31:52 2014 From: python-checkins at python.org (jason.coombs) Date: Sun, 3 Aug 2014 21:31:52 +0200 (CEST) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy4yIC0+IDMuMyk6?= =?utf-8?q?_Issue_=2313540=3A_Merge_changes_from_3=2E2?= Message-ID: <3hRC606bN7z7Ln7@mail.python.org> http://hg.python.org/cpython/rev/a36d469f31c1 changeset: 91975:a36d469f31c1 branch: 3.3 parent: 91665:b957f475e41e parent: 91974:634f3fe8cbde user: Jason R. Coombs date: Sun Aug 03 15:26:32 2014 -0400 summary: Issue #13540: Merge changes from 3.2 files: Doc/library/argparse.rst | 72 ++++++++++++++++++++------- 1 files changed, 53 insertions(+), 19 deletions(-) diff --git a/Doc/library/argparse.rst b/Doc/library/argparse.rst --- a/Doc/library/argparse.rst +++ b/Doc/library/argparse.rst @@ -683,7 +683,7 @@ actions can do just about anything with the command-line arguments associated with them, though most actions simply add an attribute to the object returned by :meth:`~ArgumentParser.parse_args`. The ``action`` keyword argument specifies -how the command-line arguments should be handled. The supported actions are: +how the command-line arguments should be handled. The supplied actions are: * ``'store'`` - This just stores the argument's value. This is the default action. For example:: @@ -757,28 +757,18 @@ >>> parser.parse_args(['--version']) PROG 2.0 -You can also specify an arbitrary action by passing an object that implements -the Action API. The easiest way to do this is to extend -:class:`argparse.Action`, supplying an appropriate ``__call__`` method. The -``__call__`` method should accept four parameters: - -* ``parser`` - The ArgumentParser object which contains this action. - -* ``namespace`` - The :class:`Namespace` object that will be returned by - :meth:`~ArgumentParser.parse_args`. Most actions add an attribute to this - object. - -* ``values`` - The associated command-line arguments, with any type conversions - applied. (Type conversions are specified with the type_ keyword argument to - :meth:`~ArgumentParser.add_argument`.) - -* ``option_string`` - The option string that was used to invoke this action. - The ``option_string`` argument is optional, and will be absent if the action - is associated with a positional argument. +You may also specify an arbitrary action by passing an Action subclass or +other object that implements the same interface. The recommended way to do +this is to extend :class:`Action`, overriding the ``__call__`` method +and optionally the ``__init__`` method. An example of a custom action:: >>> class FooAction(argparse.Action): + ... def __init__(self, option_strings, dest, nargs=None, **kwargs): + ... if nargs is not None: + ... raise ValueError("nargs not allowed") + ... super(FooAction, self).__init__(option_strings, dest, **kwargs) ... def __call__(self, parser, namespace, values, option_string=None): ... print('%r %r %r' % (namespace, values, option_string)) ... setattr(namespace, self.dest, values) @@ -792,6 +782,7 @@ >>> args Namespace(bar='1', foo='2') +For more details, see :class:`Action`. nargs ^^^^^ @@ -1238,6 +1229,49 @@ >>> parser.parse_args('--foo XXX'.split()) Namespace(bar='XXX') +Action classes +^^^^^^^^^^^^^^ + +Action classes implement the Action API, a callable which returns a callable +which processes arguments from the command-line. Any object which follows +this API may be passed as the ``action`` parameter to +:method:`add_argument`. + +.. class:: Action(option_strings, dest, nargs=None, const=None, default=None, + type=None, choices=None, required=False, help=None, + metavar=None) + +Action objects are used by an ArgumentParser to represent the information +needed to parse a single argument from one or more strings from the +command line. The Action class must accept the two positional arguments +plus any keyword arguments passed to :method:`ArgumentParser.add_argument` +except for the ``action`` itself. + +Instances of Action (or return value of any callable to the ``action`` +parameter) should have attributes "dest", "option_strings", "default", "type", +"required", "help", etc. defined. The easiest way to ensure these attributes +are defined is to call ``Action.__init__``. + +Action instances should be callable, so subclasses must override the +``__call__`` method, which should accept four parameters: + +* ``parser`` - The ArgumentParser object which contains this action. + +* ``namespace`` - The :class:`Namespace` object that will be returned by + :meth:`~ArgumentParser.parse_args`. Most actions add an attribute to this + object using :func:`setattr`. + +* ``values`` - The associated command-line arguments, with any type conversions + applied. Type conversions are specified with the type_ keyword argument to + :meth:`~ArgumentParser.add_argument`. + +* ``option_string`` - The option string that was used to invoke this action. + The ``option_string`` argument is optional, and will be absent if the action + is associated with a positional argument. + +The ``__call__`` method may perform arbitrary actions, but will typically set +attributes on the ``namespace`` based on ``dest`` and ``values``. + The parse_args() method ----------------------- -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Aug 3 21:31:54 2014 From: python-checkins at python.org (jason.coombs) Date: Sun, 3 Aug 2014 21:31:54 +0200 (CEST) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy4zIC0+IDMuNCk6?= =?utf-8?q?_Issue_=2313540=3A_Merge_changes_from_3=2E3?= Message-ID: <3hRC622RNSz7LnC@mail.python.org> http://hg.python.org/cpython/rev/c689156580ca changeset: 91976:c689156580ca branch: 3.4 parent: 91966:6d6da976553e parent: 91975:a36d469f31c1 user: Jason R. Coombs date: Sun Aug 03 15:26:58 2014 -0400 summary: Issue #13540: Merge changes from 3.3 files: Doc/library/argparse.rst | 72 ++++++++++++++++++++------- 1 files changed, 53 insertions(+), 19 deletions(-) diff --git a/Doc/library/argparse.rst b/Doc/library/argparse.rst --- a/Doc/library/argparse.rst +++ b/Doc/library/argparse.rst @@ -683,7 +683,7 @@ actions can do just about anything with the command-line arguments associated with them, though most actions simply add an attribute to the object returned by :meth:`~ArgumentParser.parse_args`. The ``action`` keyword argument specifies -how the command-line arguments should be handled. The supported actions are: +how the command-line arguments should be handled. The supplied actions are: * ``'store'`` - This just stores the argument's value. This is the default action. For example:: @@ -757,28 +757,18 @@ >>> parser.parse_args(['--version']) PROG 2.0 -You can also specify an arbitrary action by passing an object that implements -the Action API. The easiest way to do this is to extend -:class:`argparse.Action`, supplying an appropriate ``__call__`` method. The -``__call__`` method should accept four parameters: - -* ``parser`` - The ArgumentParser object which contains this action. - -* ``namespace`` - The :class:`Namespace` object that will be returned by - :meth:`~ArgumentParser.parse_args`. Most actions add an attribute to this - object. - -* ``values`` - The associated command-line arguments, with any type conversions - applied. (Type conversions are specified with the type_ keyword argument to - :meth:`~ArgumentParser.add_argument`.) - -* ``option_string`` - The option string that was used to invoke this action. - The ``option_string`` argument is optional, and will be absent if the action - is associated with a positional argument. +You may also specify an arbitrary action by passing an Action subclass or +other object that implements the same interface. The recommended way to do +this is to extend :class:`Action`, overriding the ``__call__`` method +and optionally the ``__init__`` method. An example of a custom action:: >>> class FooAction(argparse.Action): + ... def __init__(self, option_strings, dest, nargs=None, **kwargs): + ... if nargs is not None: + ... raise ValueError("nargs not allowed") + ... super(FooAction, self).__init__(option_strings, dest, **kwargs) ... def __call__(self, parser, namespace, values, option_string=None): ... print('%r %r %r' % (namespace, values, option_string)) ... setattr(namespace, self.dest, values) @@ -792,6 +782,7 @@ >>> args Namespace(bar='1', foo='2') +For more details, see :class:`Action`. nargs ^^^^^ @@ -1238,6 +1229,49 @@ >>> parser.parse_args('--foo XXX'.split()) Namespace(bar='XXX') +Action classes +^^^^^^^^^^^^^^ + +Action classes implement the Action API, a callable which returns a callable +which processes arguments from the command-line. Any object which follows +this API may be passed as the ``action`` parameter to +:method:`add_argument`. + +.. class:: Action(option_strings, dest, nargs=None, const=None, default=None, + type=None, choices=None, required=False, help=None, + metavar=None) + +Action objects are used by an ArgumentParser to represent the information +needed to parse a single argument from one or more strings from the +command line. The Action class must accept the two positional arguments +plus any keyword arguments passed to :method:`ArgumentParser.add_argument` +except for the ``action`` itself. + +Instances of Action (or return value of any callable to the ``action`` +parameter) should have attributes "dest", "option_strings", "default", "type", +"required", "help", etc. defined. The easiest way to ensure these attributes +are defined is to call ``Action.__init__``. + +Action instances should be callable, so subclasses must override the +``__call__`` method, which should accept four parameters: + +* ``parser`` - The ArgumentParser object which contains this action. + +* ``namespace`` - The :class:`Namespace` object that will be returned by + :meth:`~ArgumentParser.parse_args`. Most actions add an attribute to this + object using :func:`setattr`. + +* ``values`` - The associated command-line arguments, with any type conversions + applied. Type conversions are specified with the type_ keyword argument to + :meth:`~ArgumentParser.add_argument`. + +* ``option_string`` - The option string that was used to invoke this action. + The ``option_string`` argument is optional, and will be absent if the action + is associated with a positional argument. + +The ``__call__`` method may perform arbitrary actions, but will typically set +attributes on the ``namespace`` based on ``dest`` and ``values``. + The parse_args() method ----------------------- -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Aug 3 21:31:55 2014 From: python-checkins at python.org (jason.coombs) Date: Sun, 3 Aug 2014 21:31:55 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2313540=3A_Merge_changes_from_3=2E4?= Message-ID: <3hRC6350Lvz7LnF@mail.python.org> http://hg.python.org/cpython/rev/a2d01ed713cb changeset: 91977:a2d01ed713cb parent: 91967:751328f413a8 parent: 91976:c689156580ca user: Jason R. Coombs date: Sun Aug 03 15:27:18 2014 -0400 summary: Issue #13540: Merge changes from 3.4 files: Doc/library/argparse.rst | 72 ++++++++++++++++++++------- 1 files changed, 53 insertions(+), 19 deletions(-) diff --git a/Doc/library/argparse.rst b/Doc/library/argparse.rst --- a/Doc/library/argparse.rst +++ b/Doc/library/argparse.rst @@ -683,7 +683,7 @@ actions can do just about anything with the command-line arguments associated with them, though most actions simply add an attribute to the object returned by :meth:`~ArgumentParser.parse_args`. The ``action`` keyword argument specifies -how the command-line arguments should be handled. The supported actions are: +how the command-line arguments should be handled. The supplied actions are: * ``'store'`` - This just stores the argument's value. This is the default action. For example:: @@ -757,28 +757,18 @@ >>> parser.parse_args(['--version']) PROG 2.0 -You can also specify an arbitrary action by passing an object that implements -the Action API. The easiest way to do this is to extend -:class:`argparse.Action`, supplying an appropriate ``__call__`` method. The -``__call__`` method should accept four parameters: - -* ``parser`` - The ArgumentParser object which contains this action. - -* ``namespace`` - The :class:`Namespace` object that will be returned by - :meth:`~ArgumentParser.parse_args`. Most actions add an attribute to this - object. - -* ``values`` - The associated command-line arguments, with any type conversions - applied. (Type conversions are specified with the type_ keyword argument to - :meth:`~ArgumentParser.add_argument`.) - -* ``option_string`` - The option string that was used to invoke this action. - The ``option_string`` argument is optional, and will be absent if the action - is associated with a positional argument. +You may also specify an arbitrary action by passing an Action subclass or +other object that implements the same interface. The recommended way to do +this is to extend :class:`Action`, overriding the ``__call__`` method +and optionally the ``__init__`` method. An example of a custom action:: >>> class FooAction(argparse.Action): + ... def __init__(self, option_strings, dest, nargs=None, **kwargs): + ... if nargs is not None: + ... raise ValueError("nargs not allowed") + ... super(FooAction, self).__init__(option_strings, dest, **kwargs) ... def __call__(self, parser, namespace, values, option_string=None): ... print('%r %r %r' % (namespace, values, option_string)) ... setattr(namespace, self.dest, values) @@ -792,6 +782,7 @@ >>> args Namespace(bar='1', foo='2') +For more details, see :class:`Action`. nargs ^^^^^ @@ -1238,6 +1229,49 @@ >>> parser.parse_args('--foo XXX'.split()) Namespace(bar='XXX') +Action classes +^^^^^^^^^^^^^^ + +Action classes implement the Action API, a callable which returns a callable +which processes arguments from the command-line. Any object which follows +this API may be passed as the ``action`` parameter to +:method:`add_argument`. + +.. class:: Action(option_strings, dest, nargs=None, const=None, default=None, + type=None, choices=None, required=False, help=None, + metavar=None) + +Action objects are used by an ArgumentParser to represent the information +needed to parse a single argument from one or more strings from the +command line. The Action class must accept the two positional arguments +plus any keyword arguments passed to :method:`ArgumentParser.add_argument` +except for the ``action`` itself. + +Instances of Action (or return value of any callable to the ``action`` +parameter) should have attributes "dest", "option_strings", "default", "type", +"required", "help", etc. defined. The easiest way to ensure these attributes +are defined is to call ``Action.__init__``. + +Action instances should be callable, so subclasses must override the +``__call__`` method, which should accept four parameters: + +* ``parser`` - The ArgumentParser object which contains this action. + +* ``namespace`` - The :class:`Namespace` object that will be returned by + :meth:`~ArgumentParser.parse_args`. Most actions add an attribute to this + object using :func:`setattr`. + +* ``values`` - The associated command-line arguments, with any type conversions + applied. Type conversions are specified with the type_ keyword argument to + :meth:`~ArgumentParser.add_argument`. + +* ``option_string`` - The option string that was used to invoke this action. + The ``option_string`` argument is optional, and will be absent if the action + is associated with a positional argument. + +The ``__call__`` method may perform arbitrary actions, but will typically set +attributes on the ``namespace`` based on ``dest`` and ``values``. + The parse_args() method ----------------------- -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Aug 4 05:03:46 2014 From: python-checkins at python.org (terry.reedy) Date: Mon, 4 Aug 2014 05:03:46 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_PEP_8_spacing_?= =?utf-8?q?in_idlelib=2EconfigDialog=3A_mostly_a_=3D_b_in_assignments=2C?= Message-ID: <3hRP7Q5cB4z7Lpk@mail.python.org> http://hg.python.org/cpython/rev/50722d2f08c7 changeset: 91978:50722d2f08c7 branch: 2.7 parent: 91971:b232e937e668 user: Terry Jan Reedy date: Sun Aug 03 23:02:53 2014 -0400 summary: PEP 8 spacing in idlelib.configDialog: mostly a = b in assignments, a, b in arg lists, and hanging indents for long arg lists. files: Lib/idlelib/configDialog.py | 1156 +++++++++++----------- 1 files changed, 597 insertions(+), 559 deletions(-) diff --git a/Lib/idlelib/configDialog.py b/Lib/idlelib/configDialog.py --- a/Lib/idlelib/configDialog.py +++ b/Lib/idlelib/configDialog.py @@ -29,42 +29,44 @@ """ Toplevel.__init__(self, parent) self.parent = parent + if _htest: + parent.instance_dict = {} self.wm_withdraw() self.configure(borderwidth=5) self.title('IDLE Preferences') - if _htest: - parent.instance_dict = {} - self.geometry("+%d+%d" % (parent.winfo_rootx()+20, - parent.winfo_rooty()+(30 if not _htest else 150))) + self.geometry( + "+%d+%d" % (parent.winfo_rootx() + 20, + parent.winfo_rooty() + (30 if not _htest else 150))) #Theme Elements. Each theme element key is its display name. #The first value of the tuple is the sample area tag name. #The second value is the display name list sort index. - self.themeElements={'Normal Text':('normal','00'), - 'Python Keywords':('keyword','01'), - 'Python Definitions':('definition','02'), + self.themeElements={ + 'Normal Text':('normal', '00'), + 'Python Keywords':('keyword', '01'), + 'Python Definitions':('definition', '02'), 'Python Builtins':('builtin', '03'), - 'Python Comments':('comment','04'), - 'Python Strings':('string','05'), - 'Selected Text':('hilite','06'), - 'Found Text':('hit','07'), - 'Cursor':('cursor','08'), - 'Error Text':('error','09'), - 'Shell Normal Text':('console','10'), - 'Shell Stdout Text':('stdout','11'), - 'Shell Stderr Text':('stderr','12'), + 'Python Comments':('comment', '04'), + 'Python Strings':('string', '05'), + 'Selected Text':('hilite', '06'), + 'Found Text':('hit', '07'), + 'Cursor':('cursor', '08'), + 'Error Text':('error', '09'), + 'Shell Normal Text':('console', '10'), + 'Shell Stdout Text':('stdout', '11'), + 'Shell Stderr Text':('stderr', '12'), } self.ResetChangedItems() #load initial values in changed items dict self.CreateWidgets() - self.resizable(height=FALSE,width=FALSE) + self.resizable(height=FALSE, width=FALSE) self.transient(parent) self.grab_set() self.protocol("WM_DELETE_WINDOW", self.Cancel) self.tabPages.focus_set() #key bindings for this dialog - #self.bind('',self.Cancel) #dismiss dialog, no save - #self.bind('',self.Apply) #apply changes, save - #self.bind('',self.Help) #context help + #self.bind('', self.Cancel) #dismiss dialog, no save + #self.bind('', self.Apply) #apply changes, save + #self.bind('', self.Help) #context help self.LoadConfigs() self.AttachVarCallbacks() #avoid callbacks during LoadConfigs @@ -74,40 +76,40 @@ def CreateWidgets(self): self.tabPages = TabbedPageSet(self, - page_names=['Fonts/Tabs','Highlighting','Keys','General']) - frameActionButtons = Frame(self,pady=2) + page_names=['Fonts/Tabs', 'Highlighting', 'Keys', 'General']) + frameActionButtons = Frame(self, pady=2) #action buttons if macosxSupport.isAquaTk(): # Changing the default padding on OSX results in unreadable # text in the buttons - paddingArgs={} + paddingArgs = {} else: - paddingArgs={'padx':6, 'pady':3} + paddingArgs = {'padx':6, 'pady':3} # Comment out button creation and packing until implement self.Help -## self.buttonHelp = Button(frameActionButtons,text='Help', -## command=self.Help,takefocus=FALSE, +## self.buttonHelp = Button(frameActionButtons, text='Help', +## command=self.Help, takefocus=FALSE, ## **paddingArgs) - self.buttonOk = Button(frameActionButtons,text='Ok', - command=self.Ok,takefocus=FALSE, - **paddingArgs) - self.buttonApply = Button(frameActionButtons,text='Apply', - command=self.Apply,takefocus=FALSE, - **paddingArgs) - self.buttonCancel = Button(frameActionButtons,text='Cancel', - command=self.Cancel,takefocus=FALSE, - **paddingArgs) + self.buttonOk = Button( + frameActionButtons, text='Ok', + command=self.Ok, takefocus=FALSE, **paddingArgs) + self.buttonApply = Button( + frameActionButtons, text='Apply', + command=self.Apply, takefocus=FALSE, **paddingArgs) + self.buttonCancel = Button( + frameActionButtons, text='Cancel', + command=self.Cancel, takefocus=FALSE, **paddingArgs) self.CreatePageFontTab() self.CreatePageHighlight() self.CreatePageKeys() self.CreatePageGeneral() -## self.buttonHelp.pack(side=RIGHT,padx=5) - self.buttonOk.pack(side=LEFT,padx=5) - self.buttonApply.pack(side=LEFT,padx=5) - self.buttonCancel.pack(side=LEFT,padx=5) +## self.buttonHelp.pack(side=RIGHT, padx=5) + self.buttonOk.pack(side=LEFT, padx=5) + self.buttonApply.pack(side=LEFT, padx=5) + self.buttonCancel.pack(side=LEFT, padx=5) frameActionButtons.pack(side=BOTTOM) Frame(self, height=2, borderwidth=0).pack(side=BOTTOM) - self.tabPages.pack(side=TOP,expand=TRUE,fill=BOTH) + self.tabPages.pack(side=TOP, expand=TRUE, fill=BOTH) def CreatePageFontTab(self): parent = self.parent @@ -115,63 +117,66 @@ self.fontBold = BooleanVar(parent) self.fontName = StringVar(parent) self.spaceNum = IntVar(parent) - self.editFont = tkFont.Font(parent,('courier',10,'normal')) + self.editFont = tkFont.Font(parent, ('courier', 10, 'normal')) ##widget creation #body frame - frame=self.tabPages.pages['Fonts/Tabs'].frame + frame = self.tabPages.pages['Fonts/Tabs'].frame #body section frames - frameFont=LabelFrame(frame,borderwidth=2,relief=GROOVE, - text=' Base Editor Font ') - frameIndent=LabelFrame(frame,borderwidth=2,relief=GROOVE, - text=' Indentation Width ') + frameFont = LabelFrame( + frame, borderwidth=2, relief=GROOVE, text=' Base Editor Font ') + frameIndent = LabelFrame( + frame, borderwidth=2, relief=GROOVE, text=' Indentation Width ') #frameFont - frameFontName=Frame(frameFont) - frameFontParam=Frame(frameFont) - labelFontNameTitle=Label(frameFontName,justify=LEFT, - text='Font Face :') - self.listFontName=Listbox(frameFontName,height=5,takefocus=FALSE, - exportselection=FALSE) - self.listFontName.bind('',self.OnListFontButtonRelease) - scrollFont=Scrollbar(frameFontName) + frameFontName = Frame(frameFont) + frameFontParam = Frame(frameFont) + labelFontNameTitle = Label( + frameFontName, justify=LEFT, text='Font Face :') + self.listFontName = Listbox( + frameFontName, height=5, takefocus=FALSE, exportselection=FALSE) + self.listFontName.bind( + '', self.OnListFontButtonRelease) + scrollFont = Scrollbar(frameFontName) scrollFont.config(command=self.listFontName.yview) self.listFontName.config(yscrollcommand=scrollFont.set) - labelFontSizeTitle=Label(frameFontParam,text='Size :') - self.optMenuFontSize=DynOptionMenu(frameFontParam,self.fontSize,None, - command=self.SetFontSample) - checkFontBold=Checkbutton(frameFontParam,variable=self.fontBold, - onvalue=1,offvalue=0,text='Bold',command=self.SetFontSample) - frameFontSample=Frame(frameFont,relief=SOLID,borderwidth=1) - self.labelFontSample=Label(frameFontSample, - text='AaBbCcDdEe\nFfGgHhIiJjK\n1234567890\n#:+=(){}[]', - justify=LEFT,font=self.editFont) + labelFontSizeTitle = Label(frameFontParam, text='Size :') + self.optMenuFontSize = DynOptionMenu( + frameFontParam, self.fontSize, None, command=self.SetFontSample) + checkFontBold = Checkbutton( + frameFontParam, variable=self.fontBold, onvalue=1, + offvalue=0, text='Bold', command=self.SetFontSample) + frameFontSample = Frame(frameFont, relief=SOLID, borderwidth=1) + self.labelFontSample = Label( + frameFontSample, justify=LEFT, font=self.editFont, + text='AaBbCcDdEe\nFfGgHhIiJjK\n1234567890\n#:+=(){}[]') #frameIndent - frameIndentSize=Frame(frameIndent) - labelSpaceNumTitle=Label(frameIndentSize, justify=LEFT, - text='Python Standard: 4 Spaces!') - self.scaleSpaceNum=Scale(frameIndentSize, variable=self.spaceNum, - orient='horizontal', - tickinterval=2, from_=2, to=16) + frameIndentSize = Frame(frameIndent) + labelSpaceNumTitle = Label( + frameIndentSize, justify=LEFT, + text='Python Standard: 4 Spaces!') + self.scaleSpaceNum = Scale( + frameIndentSize, variable=self.spaceNum, + orient='horizontal', tickinterval=2, from_=2, to=16) #widget packing #body - frameFont.pack(side=LEFT,padx=5,pady=5,expand=TRUE,fill=BOTH) - frameIndent.pack(side=LEFT,padx=5,pady=5,fill=Y) + frameFont.pack(side=LEFT, padx=5, pady=5, expand=TRUE, fill=BOTH) + frameIndent.pack(side=LEFT, padx=5, pady=5, fill=Y) #frameFont - frameFontName.pack(side=TOP,padx=5,pady=5,fill=X) - frameFontParam.pack(side=TOP,padx=5,pady=5,fill=X) - labelFontNameTitle.pack(side=TOP,anchor=W) - self.listFontName.pack(side=LEFT,expand=TRUE,fill=X) - scrollFont.pack(side=LEFT,fill=Y) - labelFontSizeTitle.pack(side=LEFT,anchor=W) - self.optMenuFontSize.pack(side=LEFT,anchor=W) - checkFontBold.pack(side=LEFT,anchor=W,padx=20) - frameFontSample.pack(side=TOP,padx=5,pady=5,expand=TRUE,fill=BOTH) - self.labelFontSample.pack(expand=TRUE,fill=BOTH) + frameFontName.pack(side=TOP, padx=5, pady=5, fill=X) + frameFontParam.pack(side=TOP, padx=5, pady=5, fill=X) + labelFontNameTitle.pack(side=TOP, anchor=W) + self.listFontName.pack(side=LEFT, expand=TRUE, fill=X) + scrollFont.pack(side=LEFT, fill=Y) + labelFontSizeTitle.pack(side=LEFT, anchor=W) + self.optMenuFontSize.pack(side=LEFT, anchor=W) + checkFontBold.pack(side=LEFT, anchor=W, padx=20) + frameFontSample.pack(side=TOP, padx=5, pady=5, expand=TRUE, fill=BOTH) + self.labelFontSample.pack(expand=TRUE, fill=BOTH) #frameIndent - frameIndentSize.pack(side=TOP,fill=X) - labelSpaceNumTitle.pack(side=TOP,anchor=W,padx=5) - self.scaleSpaceNum.pack(side=TOP,padx=5,fill=X) + frameIndentSize.pack(side=TOP, fill=X) + labelSpaceNumTitle.pack(side=TOP, anchor=W, padx=5) + self.scaleSpaceNum.pack(side=TOP, padx=5, fill=X) return frame def CreatePageHighlight(self): @@ -186,84 +191,100 @@ ##widget creation #body frame - frame=self.tabPages.pages['Highlighting'].frame + frame = self.tabPages.pages['Highlighting'].frame #body section frames - frameCustom=LabelFrame(frame,borderwidth=2,relief=GROOVE, - text=' Custom Highlighting ') - frameTheme=LabelFrame(frame,borderwidth=2,relief=GROOVE, - text=' Highlighting Theme ') + frameCustom = LabelFrame(frame, borderwidth=2, relief=GROOVE, + text=' Custom Highlighting ') + frameTheme = LabelFrame(frame, borderwidth=2, relief=GROOVE, + text=' Highlighting Theme ') #frameCustom - self.textHighlightSample=Text(frameCustom,relief=SOLID,borderwidth=1, - font=('courier',12,''),cursor='hand2',width=21,height=11, - takefocus=FALSE,highlightthickness=0,wrap=NONE) + self.textHighlightSample=Text( + frameCustom, relief=SOLID, borderwidth=1, + font=('courier', 12, ''), cursor='hand2', width=21, height=11, + takefocus=FALSE, highlightthickness=0, wrap=NONE) text=self.textHighlightSample - text.bind('',lambda e: 'break') - text.bind('',lambda e: 'break') - textAndTags=(('#you can click here','comment'),('\n','normal'), - ('#to choose items','comment'),('\n','normal'),('def','keyword'), - (' ','normal'),('func','definition'),('(param):','normal'), - ('\n ','normal'),('"""string"""','string'),('\n var0 = ','normal'), - ("'string'",'string'),('\n var1 = ','normal'),("'selected'",'hilite'), - ('\n var2 = ','normal'),("'found'",'hit'), - ('\n var3 = ','normal'),('list', 'builtin'), ('(','normal'), - ('None', 'builtin'),(')\n\n','normal'), - (' error ','error'),(' ','normal'),('cursor |','cursor'), - ('\n ','normal'),('shell','console'),(' ','normal'),('stdout','stdout'), - (' ','normal'),('stderr','stderr'),('\n','normal')) + text.bind('', lambda e: 'break') + text.bind('', lambda e: 'break') + textAndTags=( + ('#you can click here', 'comment'), ('\n', 'normal'), + ('#to choose items', 'comment'), ('\n', 'normal'), + ('def', 'keyword'), (' ', 'normal'), + ('func', 'definition'), ('(param):\n ', 'normal'), + ('"""string"""', 'string'), ('\n var0 = ', 'normal'), + ("'string'", 'string'), ('\n var1 = ', 'normal'), + ("'selected'", 'hilite'), ('\n var2 = ', 'normal'), + ("'found'", 'hit'), ('\n var3 = ', 'normal'), + ('list', 'builtin'), ('(', 'normal'), + ('None', 'builtin'), (')\n\n', 'normal'), + (' error ', 'error'), (' ', 'normal'), + ('cursor |', 'cursor'), ('\n ', 'normal'), + ('shell', 'console'), (' ', 'normal'), + ('stdout', 'stdout'), (' ', 'normal'), + ('stderr', 'stderr'), ('\n', 'normal')) for txTa in textAndTags: - text.insert(END,txTa[0],txTa[1]) + text.insert(END, txTa[0], txTa[1]) for element in self.themeElements: - text.tag_bind(self.themeElements[element][0],'', - lambda event,elem=element: event.widget.winfo_toplevel() - .highlightTarget.set(elem)) + def tem(event, elem=element): + event.widget.winfo_toplevel().highlightTarget.set(elem) + text.tag_bind( + self.themeElements[element][0], '', tem) text.config(state=DISABLED) - self.frameColourSet=Frame(frameCustom,relief=SOLID,borderwidth=1) - frameFgBg=Frame(frameCustom) - buttonSetColour=Button(self.frameColourSet,text='Choose Colour for :', - command=self.GetColour,highlightthickness=0) - self.optMenuHighlightTarget=DynOptionMenu(self.frameColourSet, - self.highlightTarget,None,highlightthickness=0)#,command=self.SetHighlightTargetBinding - self.radioFg=Radiobutton(frameFgBg,variable=self.fgHilite, - value=1,text='Foreground',command=self.SetColourSampleBinding) - self.radioBg=Radiobutton(frameFgBg,variable=self.fgHilite, - value=0,text='Background',command=self.SetColourSampleBinding) + self.frameColourSet = Frame(frameCustom, relief=SOLID, borderwidth=1) + frameFgBg = Frame(frameCustom) + buttonSetColour = Button( + self.frameColourSet, text='Choose Colour for :', + command=self.GetColour, highlightthickness=0) + self.optMenuHighlightTarget = DynOptionMenu( + self.frameColourSet, self.highlightTarget, None, + highlightthickness=0) #, command=self.SetHighlightTargetBinding + self.radioFg = Radiobutton( + frameFgBg, variable=self.fgHilite, value=1, + text='Foreground', command=self.SetColourSampleBinding) + self.radioBg=Radiobutton( + frameFgBg, variable=self.fgHilite, value=0, + text='Background', command=self.SetColourSampleBinding) self.fgHilite.set(1) - buttonSaveCustomTheme=Button(frameCustom, - text='Save as New Custom Theme',command=self.SaveAsNewTheme) + buttonSaveCustomTheme = Button( + frameCustom, text='Save as New Custom Theme', + command=self.SaveAsNewTheme) #frameTheme - labelTypeTitle=Label(frameTheme,text='Select : ') - self.radioThemeBuiltin=Radiobutton(frameTheme,variable=self.themeIsBuiltin, - value=1,command=self.SetThemeType,text='a Built-in Theme') - self.radioThemeCustom=Radiobutton(frameTheme,variable=self.themeIsBuiltin, - value=0,command=self.SetThemeType,text='a Custom Theme') - self.optMenuThemeBuiltin=DynOptionMenu(frameTheme, - self.builtinTheme,None,command=None) - self.optMenuThemeCustom=DynOptionMenu(frameTheme, - self.customTheme,None,command=None) - self.buttonDeleteCustomTheme=Button(frameTheme,text='Delete Custom Theme', + labelTypeTitle = Label(frameTheme, text='Select : ') + self.radioThemeBuiltin = Radiobutton( + frameTheme, variable=self.themeIsBuiltin, value=1, + command=self.SetThemeType, text='a Built-in Theme') + self.radioThemeCustom = Radiobutton( + frameTheme, variable=self.themeIsBuiltin, value=0, + command=self.SetThemeType, text='a Custom Theme') + self.optMenuThemeBuiltin = DynOptionMenu( + frameTheme, self.builtinTheme, None, command=None) + self.optMenuThemeCustom=DynOptionMenu( + frameTheme, self.customTheme, None, command=None) + self.buttonDeleteCustomTheme=Button( + frameTheme, text='Delete Custom Theme', command=self.DeleteCustomTheme) ##widget packing #body - frameCustom.pack(side=LEFT,padx=5,pady=5,expand=TRUE,fill=BOTH) - frameTheme.pack(side=LEFT,padx=5,pady=5,fill=Y) + frameCustom.pack(side=LEFT, padx=5, pady=5, expand=TRUE, fill=BOTH) + frameTheme.pack(side=LEFT, padx=5, pady=5, fill=Y) #frameCustom - self.frameColourSet.pack(side=TOP,padx=5,pady=5,expand=TRUE,fill=X) - frameFgBg.pack(side=TOP,padx=5,pady=0) - self.textHighlightSample.pack(side=TOP,padx=5,pady=5,expand=TRUE, - fill=BOTH) - buttonSetColour.pack(side=TOP,expand=TRUE,fill=X,padx=8,pady=4) - self.optMenuHighlightTarget.pack(side=TOP,expand=TRUE,fill=X,padx=8,pady=3) - self.radioFg.pack(side=LEFT,anchor=E) - self.radioBg.pack(side=RIGHT,anchor=W) - buttonSaveCustomTheme.pack(side=BOTTOM,fill=X,padx=5,pady=5) + self.frameColourSet.pack(side=TOP, padx=5, pady=5, expand=TRUE, fill=X) + frameFgBg.pack(side=TOP, padx=5, pady=0) + self.textHighlightSample.pack( + side=TOP, padx=5, pady=5, expand=TRUE, fill=BOTH) + buttonSetColour.pack(side=TOP, expand=TRUE, fill=X, padx=8, pady=4) + self.optMenuHighlightTarget.pack( + side=TOP, expand=TRUE, fill=X, padx=8, pady=3) + self.radioFg.pack(side=LEFT, anchor=E) + self.radioBg.pack(side=RIGHT, anchor=W) + buttonSaveCustomTheme.pack(side=BOTTOM, fill=X, padx=5, pady=5) #frameTheme - labelTypeTitle.pack(side=TOP,anchor=W,padx=5,pady=5) - self.radioThemeBuiltin.pack(side=TOP,anchor=W,padx=5) - self.radioThemeCustom.pack(side=TOP,anchor=W,padx=5,pady=2) - self.optMenuThemeBuiltin.pack(side=TOP,fill=X,padx=5,pady=5) - self.optMenuThemeCustom.pack(side=TOP,fill=X,anchor=W,padx=5,pady=5) - self.buttonDeleteCustomTheme.pack(side=TOP,fill=X,padx=5,pady=5) + labelTypeTitle.pack(side=TOP, anchor=W, padx=5, pady=5) + self.radioThemeBuiltin.pack(side=TOP, anchor=W, padx=5) + self.radioThemeCustom.pack(side=TOP, anchor=W, padx=5, pady=2) + self.optMenuThemeBuiltin.pack(side=TOP, fill=X, padx=5, pady=5) + self.optMenuThemeCustom.pack(side=TOP, fill=X, anchor=W, padx=5, pady=5) + self.buttonDeleteCustomTheme.pack(side=TOP, fill=X, padx=5, pady=5) return frame def CreatePageKeys(self): @@ -276,63 +297,69 @@ ##widget creation #body frame - frame=self.tabPages.pages['Keys'].frame + frame = self.tabPages.pages['Keys'].frame #body section frames - frameCustom=LabelFrame(frame,borderwidth=2,relief=GROOVE, - text=' Custom Key Bindings ') - frameKeySets=LabelFrame(frame,borderwidth=2,relief=GROOVE, - text=' Key Set ') + frameCustom = LabelFrame( + frame, borderwidth=2, relief=GROOVE, + text=' Custom Key Bindings ') + frameKeySets = LabelFrame( + frame, borderwidth=2, relief=GROOVE, text=' Key Set ') #frameCustom - frameTarget=Frame(frameCustom) - labelTargetTitle=Label(frameTarget,text='Action - Key(s)') - scrollTargetY=Scrollbar(frameTarget) - scrollTargetX=Scrollbar(frameTarget,orient=HORIZONTAL) - self.listBindings=Listbox(frameTarget,takefocus=FALSE, - exportselection=FALSE) - self.listBindings.bind('',self.KeyBindingSelected) + frameTarget = Frame(frameCustom) + labelTargetTitle = Label(frameTarget, text='Action - Key(s)') + scrollTargetY = Scrollbar(frameTarget) + scrollTargetX = Scrollbar(frameTarget, orient=HORIZONTAL) + self.listBindings = Listbox( + frameTarget, takefocus=FALSE, exportselection=FALSE) + self.listBindings.bind('', self.KeyBindingSelected) scrollTargetY.config(command=self.listBindings.yview) scrollTargetX.config(command=self.listBindings.xview) self.listBindings.config(yscrollcommand=scrollTargetY.set) self.listBindings.config(xscrollcommand=scrollTargetX.set) - self.buttonNewKeys=Button(frameCustom,text='Get New Keys for Selection', - command=self.GetNewKeys,state=DISABLED) + self.buttonNewKeys = Button( + frameCustom, text='Get New Keys for Selection', + command=self.GetNewKeys, state=DISABLED) #frameKeySets frames = [Frame(frameKeySets, padx=2, pady=2, borderwidth=0) for i in range(2)] - self.radioKeysBuiltin=Radiobutton(frames[0],variable=self.keysAreBuiltin, - value=1,command=self.SetKeysType,text='Use a Built-in Key Set') - self.radioKeysCustom=Radiobutton(frames[0],variable=self.keysAreBuiltin, - value=0,command=self.SetKeysType,text='Use a Custom Key Set') - self.optMenuKeysBuiltin=DynOptionMenu(frames[0], - self.builtinKeys,None,command=None) - self.optMenuKeysCustom=DynOptionMenu(frames[0], - self.customKeys,None,command=None) - self.buttonDeleteCustomKeys=Button(frames[1],text='Delete Custom Key Set', + self.radioKeysBuiltin = Radiobutton( + frames[0], variable=self.keysAreBuiltin, value=1, + command=self.SetKeysType, text='Use a Built-in Key Set') + self.radioKeysCustom = Radiobutton( + frames[0], variable=self.keysAreBuiltin, value=0, + command=self.SetKeysType, text='Use a Custom Key Set') + self.optMenuKeysBuiltin = DynOptionMenu( + frames[0], self.builtinKeys, None, command=None) + self.optMenuKeysCustom = DynOptionMenu( + frames[0], self.customKeys, None, command=None) + self.buttonDeleteCustomKeys = Button( + frames[1], text='Delete Custom Key Set', command=self.DeleteCustomKeys) - buttonSaveCustomKeys=Button(frames[1], - text='Save as New Custom Key Set',command=self.SaveAsNewKeySet) + buttonSaveCustomKeys = Button( + frames[1], text='Save as New Custom Key Set', + command=self.SaveAsNewKeySet) ##widget packing #body - frameCustom.pack(side=BOTTOM,padx=5,pady=5,expand=TRUE,fill=BOTH) - frameKeySets.pack(side=BOTTOM,padx=5,pady=5,fill=BOTH) + frameCustom.pack(side=BOTTOM, padx=5, pady=5, expand=TRUE, fill=BOTH) + frameKeySets.pack(side=BOTTOM, padx=5, pady=5, fill=BOTH) #frameCustom - self.buttonNewKeys.pack(side=BOTTOM,fill=X,padx=5,pady=5) - frameTarget.pack(side=LEFT,padx=5,pady=5,expand=TRUE,fill=BOTH) + self.buttonNewKeys.pack(side=BOTTOM, fill=X, padx=5, pady=5) + frameTarget.pack(side=LEFT, padx=5, pady=5, expand=TRUE, fill=BOTH) #frame target - frameTarget.columnconfigure(0,weight=1) - frameTarget.rowconfigure(1,weight=1) - labelTargetTitle.grid(row=0,column=0,columnspan=2,sticky=W) - self.listBindings.grid(row=1,column=0,sticky=NSEW) - scrollTargetY.grid(row=1,column=1,sticky=NS) - scrollTargetX.grid(row=2,column=0,sticky=EW) + frameTarget.columnconfigure(0, weight=1) + frameTarget.rowconfigure(1, weight=1) + labelTargetTitle.grid(row=0, column=0, columnspan=2, sticky=W) + self.listBindings.grid(row=1, column=0, sticky=NSEW) + scrollTargetY.grid(row=1, column=1, sticky=NS) + scrollTargetX.grid(row=2, column=0, sticky=EW) #frameKeySets self.radioKeysBuiltin.grid(row=0, column=0, sticky=W+NS) self.radioKeysCustom.grid(row=1, column=0, sticky=W+NS) self.optMenuKeysBuiltin.grid(row=0, column=1, sticky=NSEW) self.optMenuKeysCustom.grid(row=1, column=1, sticky=NSEW) - self.buttonDeleteCustomKeys.pack(side=LEFT,fill=X,expand=True,padx=2) - buttonSaveCustomKeys.pack(side=LEFT,fill=X,expand=True,padx=2) + self.buttonDeleteCustomKeys.pack(side=LEFT, fill=X, expand=True, padx=2) + buttonSaveCustomKeys.pack(side=LEFT, fill=X, expand=True, padx=2) frames[0].pack(side=TOP, fill=BOTH, expand=True) frames[1].pack(side=TOP, fill=X, expand=True, pady=2) return frame @@ -350,223 +377,235 @@ #widget creation #body - frame=self.tabPages.pages['General'].frame + frame = self.tabPages.pages['General'].frame #body section frames - frameRun=LabelFrame(frame,borderwidth=2,relief=GROOVE, - text=' Startup Preferences ') - frameSave=LabelFrame(frame,borderwidth=2,relief=GROOVE, - text=' Autosave Preferences ') - frameWinSize=Frame(frame,borderwidth=2,relief=GROOVE) - frameParaSize=Frame(frame,borderwidth=2,relief=GROOVE) - frameEncoding=Frame(frame,borderwidth=2,relief=GROOVE) - frameHelp=LabelFrame(frame,borderwidth=2,relief=GROOVE, - text=' Additional Help Sources ') + frameRun = LabelFrame(frame, borderwidth=2, relief=GROOVE, + text=' Startup Preferences ') + frameSave = LabelFrame(frame, borderwidth=2, relief=GROOVE, + text=' Autosave Preferences ') + frameWinSize = Frame(frame, borderwidth=2, relief=GROOVE) + frameParaSize = Frame(frame, borderwidth=2, relief=GROOVE) + frameEncoding = Frame(frame, borderwidth=2, relief=GROOVE) + frameHelp = LabelFrame(frame, borderwidth=2, relief=GROOVE, + text=' Additional Help Sources ') #frameRun - labelRunChoiceTitle=Label(frameRun,text='At Startup') - radioStartupEdit=Radiobutton(frameRun,variable=self.startupEdit, - value=1,command=self.SetKeysType,text="Open Edit Window") - radioStartupShell=Radiobutton(frameRun,variable=self.startupEdit, - value=0,command=self.SetKeysType,text='Open Shell Window') + labelRunChoiceTitle = Label(frameRun, text='At Startup') + radioStartupEdit = Radiobutton( + frameRun, variable=self.startupEdit, value=1, + command=self.SetKeysType, text="Open Edit Window") + radioStartupShell = Radiobutton( + frameRun, variable=self.startupEdit, value=0, + command=self.SetKeysType, text='Open Shell Window') #frameSave - labelRunSaveTitle=Label(frameSave,text='At Start of Run (F5) ') - radioSaveAsk=Radiobutton(frameSave,variable=self.autoSave, - value=0,command=self.SetKeysType,text="Prompt to Save") - radioSaveAuto=Radiobutton(frameSave,variable=self.autoSave, - value=1,command=self.SetKeysType,text='No Prompt') + labelRunSaveTitle = Label(frameSave, text='At Start of Run (F5) ') + radioSaveAsk = Radiobutton( + frameSave, variable=self.autoSave, value=0, + command=self.SetKeysType, text="Prompt to Save") + radioSaveAuto = Radiobutton( + frameSave, variable=self.autoSave, value=1, + command=self.SetKeysType, text='No Prompt') #frameWinSize - labelWinSizeTitle=Label(frameWinSize,text='Initial Window Size'+ - ' (in characters)') - labelWinWidthTitle=Label(frameWinSize,text='Width') - entryWinWidth=Entry(frameWinSize,textvariable=self.winWidth, - width=3) - labelWinHeightTitle=Label(frameWinSize,text='Height') - entryWinHeight=Entry(frameWinSize,textvariable=self.winHeight, - width=3) + labelWinSizeTitle = Label( + frameWinSize, text='Initial Window Size (in characters)') + labelWinWidthTitle = Label(frameWinSize, text='Width') + entryWinWidth = Entry( + frameWinSize, textvariable=self.winWidth, width=3) + labelWinHeightTitle = Label(frameWinSize, text='Height') + entryWinHeight = Entry( + frameWinSize, textvariable=self.winHeight, width=3) #paragraphFormatWidth - labelParaWidthTitle=Label(frameParaSize,text='Paragraph reformat'+ - ' width (in characters)') - entryParaWidth=Entry(frameParaSize,textvariable=self.paraWidth, - width=3) + labelParaWidthTitle = Label( + frameParaSize, text='Paragraph reformat width (in characters)') + entryParaWidth = Entry( + frameParaSize, textvariable=self.paraWidth, width=3) #frameEncoding - labelEncodingTitle=Label(frameEncoding,text="Default Source Encoding") - radioEncLocale=Radiobutton(frameEncoding,variable=self.encoding, - value="locale",text="Locale-defined") - radioEncUTF8=Radiobutton(frameEncoding,variable=self.encoding, - value="utf-8",text="UTF-8") - radioEncNone=Radiobutton(frameEncoding,variable=self.encoding, - value="none",text="None") + labelEncodingTitle = Label( + frameEncoding, text="Default Source Encoding") + radioEncLocale = Radiobutton( + frameEncoding, variable=self.encoding, + value="locale", text="Locale-defined") + radioEncUTF8 = Radiobutton( + frameEncoding, variable=self.encoding, + value="utf-8", text="UTF-8") + radioEncNone = Radiobutton( + frameEncoding, variable=self.encoding, + value="none", text="None") #frameHelp - frameHelpList=Frame(frameHelp) - frameHelpListButtons=Frame(frameHelpList) - scrollHelpList=Scrollbar(frameHelpList) - self.listHelp=Listbox(frameHelpList,height=5,takefocus=FALSE, + frameHelpList = Frame(frameHelp) + frameHelpListButtons = Frame(frameHelpList) + scrollHelpList = Scrollbar(frameHelpList) + self.listHelp = Listbox( + frameHelpList, height=5, takefocus=FALSE, exportselection=FALSE) scrollHelpList.config(command=self.listHelp.yview) self.listHelp.config(yscrollcommand=scrollHelpList.set) - self.listHelp.bind('',self.HelpSourceSelected) - self.buttonHelpListEdit=Button(frameHelpListButtons,text='Edit', - state=DISABLED,width=8,command=self.HelpListItemEdit) - self.buttonHelpListAdd=Button(frameHelpListButtons,text='Add', - width=8,command=self.HelpListItemAdd) - self.buttonHelpListRemove=Button(frameHelpListButtons,text='Remove', - state=DISABLED,width=8,command=self.HelpListItemRemove) + self.listHelp.bind('', self.HelpSourceSelected) + self.buttonHelpListEdit = Button( + frameHelpListButtons, text='Edit', state=DISABLED, + width=8, command=self.HelpListItemEdit) + self.buttonHelpListAdd = Button( + frameHelpListButtons, text='Add', + width=8, command=self.HelpListItemAdd) + self.buttonHelpListRemove = Button( + frameHelpListButtons, text='Remove', state=DISABLED, + width=8, command=self.HelpListItemRemove) #widget packing #body - frameRun.pack(side=TOP,padx=5,pady=5,fill=X) - frameSave.pack(side=TOP,padx=5,pady=5,fill=X) - frameWinSize.pack(side=TOP,padx=5,pady=5,fill=X) - frameParaSize.pack(side=TOP,padx=5,pady=5,fill=X) - frameEncoding.pack(side=TOP,padx=5,pady=5,fill=X) - frameHelp.pack(side=TOP,padx=5,pady=5,expand=TRUE,fill=BOTH) + frameRun.pack(side=TOP, padx=5, pady=5, fill=X) + frameSave.pack(side=TOP, padx=5, pady=5, fill=X) + frameWinSize.pack(side=TOP, padx=5, pady=5, fill=X) + frameParaSize.pack(side=TOP, padx=5, pady=5, fill=X) + frameEncoding.pack(side=TOP, padx=5, pady=5, fill=X) + frameHelp.pack(side=TOP, padx=5, pady=5, expand=TRUE, fill=BOTH) #frameRun - labelRunChoiceTitle.pack(side=LEFT,anchor=W,padx=5,pady=5) - radioStartupShell.pack(side=RIGHT,anchor=W,padx=5,pady=5) - radioStartupEdit.pack(side=RIGHT,anchor=W,padx=5,pady=5) + labelRunChoiceTitle.pack(side=LEFT, anchor=W, padx=5, pady=5) + radioStartupShell.pack(side=RIGHT, anchor=W, padx=5, pady=5) + radioStartupEdit.pack(side=RIGHT, anchor=W, padx=5, pady=5) #frameSave - labelRunSaveTitle.pack(side=LEFT,anchor=W,padx=5,pady=5) - radioSaveAuto.pack(side=RIGHT,anchor=W,padx=5,pady=5) - radioSaveAsk.pack(side=RIGHT,anchor=W,padx=5,pady=5) + labelRunSaveTitle.pack(side=LEFT, anchor=W, padx=5, pady=5) + radioSaveAuto.pack(side=RIGHT, anchor=W, padx=5, pady=5) + radioSaveAsk.pack(side=RIGHT, anchor=W, padx=5, pady=5) #frameWinSize - labelWinSizeTitle.pack(side=LEFT,anchor=W,padx=5,pady=5) - entryWinHeight.pack(side=RIGHT,anchor=E,padx=10,pady=5) - labelWinHeightTitle.pack(side=RIGHT,anchor=E,pady=5) - entryWinWidth.pack(side=RIGHT,anchor=E,padx=10,pady=5) - labelWinWidthTitle.pack(side=RIGHT,anchor=E,pady=5) + labelWinSizeTitle.pack(side=LEFT, anchor=W, padx=5, pady=5) + entryWinHeight.pack(side=RIGHT, anchor=E, padx=10, pady=5) + labelWinHeightTitle.pack(side=RIGHT, anchor=E, pady=5) + entryWinWidth.pack(side=RIGHT, anchor=E, padx=10, pady=5) + labelWinWidthTitle.pack(side=RIGHT, anchor=E, pady=5) #paragraphFormatWidth - labelParaWidthTitle.pack(side=LEFT,anchor=W,padx=5,pady=5) - entryParaWidth.pack(side=RIGHT,anchor=E,padx=10,pady=5) + labelParaWidthTitle.pack(side=LEFT, anchor=W, padx=5, pady=5) + entryParaWidth.pack(side=RIGHT, anchor=E, padx=10, pady=5) #frameEncoding - labelEncodingTitle.pack(side=LEFT,anchor=W,padx=5,pady=5) - radioEncNone.pack(side=RIGHT,anchor=E,pady=5) - radioEncUTF8.pack(side=RIGHT,anchor=E,pady=5) - radioEncLocale.pack(side=RIGHT,anchor=E,pady=5) + labelEncodingTitle.pack(side=LEFT, anchor=W, padx=5, pady=5) + radioEncNone.pack(side=RIGHT, anchor=E, pady=5) + radioEncUTF8.pack(side=RIGHT, anchor=E, pady=5) + radioEncLocale.pack(side=RIGHT, anchor=E, pady=5) #frameHelp - frameHelpListButtons.pack(side=RIGHT,padx=5,pady=5,fill=Y) - frameHelpList.pack(side=TOP,padx=5,pady=5,expand=TRUE,fill=BOTH) - scrollHelpList.pack(side=RIGHT,anchor=W,fill=Y) - self.listHelp.pack(side=LEFT,anchor=E,expand=TRUE,fill=BOTH) - self.buttonHelpListEdit.pack(side=TOP,anchor=W,pady=5) - self.buttonHelpListAdd.pack(side=TOP,anchor=W) - self.buttonHelpListRemove.pack(side=TOP,anchor=W,pady=5) + frameHelpListButtons.pack(side=RIGHT, padx=5, pady=5, fill=Y) + frameHelpList.pack(side=TOP, padx=5, pady=5, expand=TRUE, fill=BOTH) + scrollHelpList.pack(side=RIGHT, anchor=W, fill=Y) + self.listHelp.pack(side=LEFT, anchor=E, expand=TRUE, fill=BOTH) + self.buttonHelpListEdit.pack(side=TOP, anchor=W, pady=5) + self.buttonHelpListAdd.pack(side=TOP, anchor=W) + self.buttonHelpListRemove.pack(side=TOP, anchor=W, pady=5) return frame def AttachVarCallbacks(self): - self.fontSize.trace_variable('w',self.VarChanged_fontSize) - self.fontName.trace_variable('w',self.VarChanged_fontName) - self.fontBold.trace_variable('w',self.VarChanged_fontBold) - self.spaceNum.trace_variable('w',self.VarChanged_spaceNum) - self.colour.trace_variable('w',self.VarChanged_colour) - self.builtinTheme.trace_variable('w',self.VarChanged_builtinTheme) - self.customTheme.trace_variable('w',self.VarChanged_customTheme) - self.themeIsBuiltin.trace_variable('w',self.VarChanged_themeIsBuiltin) - self.highlightTarget.trace_variable('w',self.VarChanged_highlightTarget) - self.keyBinding.trace_variable('w',self.VarChanged_keyBinding) - self.builtinKeys.trace_variable('w',self.VarChanged_builtinKeys) - self.customKeys.trace_variable('w',self.VarChanged_customKeys) - self.keysAreBuiltin.trace_variable('w',self.VarChanged_keysAreBuiltin) - self.winWidth.trace_variable('w',self.VarChanged_winWidth) - self.winHeight.trace_variable('w',self.VarChanged_winHeight) - self.paraWidth.trace_variable('w',self.VarChanged_paraWidth) - self.startupEdit.trace_variable('w',self.VarChanged_startupEdit) - self.autoSave.trace_variable('w',self.VarChanged_autoSave) - self.encoding.trace_variable('w',self.VarChanged_encoding) + self.fontSize.trace_variable('w', self.VarChanged_fontSize) + self.fontName.trace_variable('w', self.VarChanged_fontName) + self.fontBold.trace_variable('w', self.VarChanged_fontBold) + self.spaceNum.trace_variable('w', self.VarChanged_spaceNum) + self.colour.trace_variable('w', self.VarChanged_colour) + self.builtinTheme.trace_variable('w', self.VarChanged_builtinTheme) + self.customTheme.trace_variable('w', self.VarChanged_customTheme) + self.themeIsBuiltin.trace_variable('w', self.VarChanged_themeIsBuiltin) + self.highlightTarget.trace_variable('w', self.VarChanged_highlightTarget) + self.keyBinding.trace_variable('w', self.VarChanged_keyBinding) + self.builtinKeys.trace_variable('w', self.VarChanged_builtinKeys) + self.customKeys.trace_variable('w', self.VarChanged_customKeys) + self.keysAreBuiltin.trace_variable('w', self.VarChanged_keysAreBuiltin) + self.winWidth.trace_variable('w', self.VarChanged_winWidth) + self.winHeight.trace_variable('w', self.VarChanged_winHeight) + self.paraWidth.trace_variable('w', self.VarChanged_paraWidth) + self.startupEdit.trace_variable('w', self.VarChanged_startupEdit) + self.autoSave.trace_variable('w', self.VarChanged_autoSave) + self.encoding.trace_variable('w', self.VarChanged_encoding) - def VarChanged_fontSize(self,*params): - value=self.fontSize.get() - self.AddChangedItem('main','EditorWindow','font-size',value) + def VarChanged_fontSize(self, *params): + value = self.fontSize.get() + self.AddChangedItem('main', 'EditorWindow', 'font-size', value) - def VarChanged_fontName(self,*params): - value=self.fontName.get() - self.AddChangedItem('main','EditorWindow','font',value) + def VarChanged_fontName(self, *params): + value = self.fontName.get() + self.AddChangedItem('main', 'EditorWindow', 'font', value) - def VarChanged_fontBold(self,*params): - value=self.fontBold.get() - self.AddChangedItem('main','EditorWindow','font-bold',value) + def VarChanged_fontBold(self, *params): + value = self.fontBold.get() + self.AddChangedItem('main', 'EditorWindow', 'font-bold', value) - def VarChanged_spaceNum(self,*params): - value=self.spaceNum.get() - self.AddChangedItem('main','Indent','num-spaces',value) + def VarChanged_spaceNum(self, *params): + value = self.spaceNum.get() + self.AddChangedItem('main', 'Indent', 'num-spaces', value) - def VarChanged_colour(self,*params): + def VarChanged_colour(self, *params): self.OnNewColourSet() - def VarChanged_builtinTheme(self,*params): - value=self.builtinTheme.get() - self.AddChangedItem('main','Theme','name',value) + def VarChanged_builtinTheme(self, *params): + value = self.builtinTheme.get() + self.AddChangedItem('main', 'Theme', 'name', value) self.PaintThemeSample() - def VarChanged_customTheme(self,*params): - value=self.customTheme.get() + def VarChanged_customTheme(self, *params): + value = self.customTheme.get() if value != '- no custom themes -': - self.AddChangedItem('main','Theme','name',value) + self.AddChangedItem('main', 'Theme', 'name', value) self.PaintThemeSample() - def VarChanged_themeIsBuiltin(self,*params): - value=self.themeIsBuiltin.get() - self.AddChangedItem('main','Theme','default',value) + def VarChanged_themeIsBuiltin(self, *params): + value = self.themeIsBuiltin.get() + self.AddChangedItem('main', 'Theme', 'default', value) if value: self.VarChanged_builtinTheme() else: self.VarChanged_customTheme() - def VarChanged_highlightTarget(self,*params): + def VarChanged_highlightTarget(self, *params): self.SetHighlightTarget() - def VarChanged_keyBinding(self,*params): - value=self.keyBinding.get() - keySet=self.customKeys.get() - event=self.listBindings.get(ANCHOR).split()[0] + def VarChanged_keyBinding(self, *params): + value = self.keyBinding.get() + keySet = self.customKeys.get() + event = self.listBindings.get(ANCHOR).split()[0] if idleConf.IsCoreBinding(event): #this is a core keybinding - self.AddChangedItem('keys',keySet,event,value) + self.AddChangedItem('keys', keySet, event, value) else: #this is an extension key binding - extName=idleConf.GetExtnNameForEvent(event) - extKeybindSection=extName+'_cfgBindings' - self.AddChangedItem('extensions',extKeybindSection,event,value) + extName = idleConf.GetExtnNameForEvent(event) + extKeybindSection = extName + '_cfgBindings' + self.AddChangedItem('extensions', extKeybindSection, event, value) - def VarChanged_builtinKeys(self,*params): - value=self.builtinKeys.get() - self.AddChangedItem('main','Keys','name',value) + def VarChanged_builtinKeys(self, *params): + value = self.builtinKeys.get() + self.AddChangedItem('main', 'Keys', 'name', value) self.LoadKeysList(value) - def VarChanged_customKeys(self,*params): - value=self.customKeys.get() + def VarChanged_customKeys(self, *params): + value = self.customKeys.get() if value != '- no custom keys -': - self.AddChangedItem('main','Keys','name',value) + self.AddChangedItem('main', 'Keys', 'name', value) self.LoadKeysList(value) - def VarChanged_keysAreBuiltin(self,*params): - value=self.keysAreBuiltin.get() - self.AddChangedItem('main','Keys','default',value) + def VarChanged_keysAreBuiltin(self, *params): + value = self.keysAreBuiltin.get() + self.AddChangedItem('main', 'Keys', 'default', value) if value: self.VarChanged_builtinKeys() else: self.VarChanged_customKeys() - def VarChanged_winWidth(self,*params): - value=self.winWidth.get() - self.AddChangedItem('main','EditorWindow','width',value) + def VarChanged_winWidth(self, *params): + value = self.winWidth.get() + self.AddChangedItem('main', 'EditorWindow', 'width', value) - def VarChanged_winHeight(self,*params): - value=self.winHeight.get() - self.AddChangedItem('main','EditorWindow','height',value) + def VarChanged_winHeight(self, *params): + value = self.winHeight.get() + self.AddChangedItem('main', 'EditorWindow', 'height', value) - def VarChanged_paraWidth(self,*params): - value=self.paraWidth.get() - self.AddChangedItem('main','FormatParagraph','paragraph',value) + def VarChanged_paraWidth(self, *params): + value = self.paraWidth.get() + self.AddChangedItem('main', 'FormatParagraph', 'paragraph', value) - def VarChanged_startupEdit(self,*params): - value=self.startupEdit.get() - self.AddChangedItem('main','General','editor-on-startup',value) + def VarChanged_startupEdit(self, *params): + value = self.startupEdit.get() + self.AddChangedItem('main', 'General', 'editor-on-startup', value) - def VarChanged_autoSave(self,*params): - value=self.autoSave.get() - self.AddChangedItem('main','General','autosave',value) + def VarChanged_autoSave(self, *params): + value = self.autoSave.get() + self.AddChangedItem('main', 'General', 'autosave', value) - def VarChanged_encoding(self,*params): - value=self.encoding.get() - self.AddChangedItem('main','EditorWindow','encoding',value) + def VarChanged_encoding(self, *params): + value = self.encoding.get() + self.AddChangedItem('main', 'EditorWindow', 'encoding', value) def ResetChangedItems(self): #When any config item is changed in this dialog, an entry @@ -574,24 +613,25 @@ #dictionary. The key should be the config file section name and the #value a dictionary, whose key:value pairs are item=value pairs for #that config file section. - self.changedItems={'main':{},'highlight':{},'keys':{},'extensions':{}} + self.changedItems = {'main':{}, 'highlight':{}, 'keys':{}, + 'extensions':{}} - def AddChangedItem(self,type,section,item,value): - value=str(value) #make sure we use a string - if section not in self.changedItems[type]: - self.changedItems[type][section]={} - self.changedItems[type][section][item]=value + def AddChangedItem(self, typ, section, item, value): + value = str(value) #make sure we use a string + if section not in self.changedItems[typ]: + self.changedItems[typ][section] = {} + self.changedItems[typ][section][item] = value def GetDefaultItems(self): - dItems={'main':{},'highlight':{},'keys':{},'extensions':{}} + dItems={'main':{}, 'highlight':{}, 'keys':{}, 'extensions':{}} for configType in dItems: - sections=idleConf.GetSectionList('default',configType) + sections = idleConf.GetSectionList('default', configType) for section in sections: - dItems[configType][section]={} - options=idleConf.defaultCfg[configType].GetOptionList(section) + dItems[configType][section] = {} + options = idleConf.defaultCfg[configType].GetOptionList(section) for option in options: - dItems[configType][section][option]=( - idleConf.defaultCfg[configType].Get(section,option)) + dItems[configType][section][option] = ( + idleConf.defaultCfg[configType].Get(section, option)) return dItems def SetThemeType(self): @@ -617,26 +657,26 @@ self.buttonDeleteCustomKeys.config(state=NORMAL) def GetNewKeys(self): - listIndex=self.listBindings.index(ANCHOR) - binding=self.listBindings.get(listIndex) - bindName=binding.split()[0] #first part, up to first space + listIndex = self.listBindings.index(ANCHOR) + binding = self.listBindings.get(listIndex) + bindName = binding.split()[0] #first part, up to first space if self.keysAreBuiltin.get(): - currentKeySetName=self.builtinKeys.get() + currentKeySetName = self.builtinKeys.get() else: - currentKeySetName=self.customKeys.get() - currentBindings=idleConf.GetCurrentKeySet() + currentKeySetName = self.customKeys.get() + currentBindings = idleConf.GetCurrentKeySet() if currentKeySetName in self.changedItems['keys']: #unsaved changes - keySetChanges=self.changedItems['keys'][currentKeySetName] + keySetChanges = self.changedItems['keys'][currentKeySetName] for event in keySetChanges: - currentBindings[event]=keySetChanges[event].split() - currentKeySequences=currentBindings.values() - newKeys=GetKeysDialog(self,'Get New Keys',bindName, + currentBindings[event] = keySetChanges[event].split() + currentKeySequences = currentBindings.values() + newKeys = GetKeysDialog(self, 'Get New Keys', bindName, currentKeySequences).result if newKeys: #new keys were specified if self.keysAreBuiltin.get(): #current key set is a built-in - message=('Your changes will be saved as a new Custom Key Set. '+ - 'Enter a name for your new Custom Key Set below.') - newKeySet=self.GetNewKeysName(message) + message = ('Your changes will be saved as a new Custom Key Set.' + ' Enter a name for your new Custom Key Set below.') + newKeySet = self.GetNewKeysName(message) if not newKeySet: #user cancelled custom key set creation self.listBindings.select_set(listIndex) self.listBindings.select_anchor(listIndex) @@ -644,7 +684,7 @@ else: #create new custom key set based on previously active key set self.CreateNewKeySet(newKeySet) self.listBindings.delete(listIndex) - self.listBindings.insert(listIndex,bindName+' - '+newKeys) + self.listBindings.insert(listIndex, bindName+' - '+newKeys) self.listBindings.select_set(listIndex) self.listBindings.select_anchor(listIndex) self.keyBinding.set(newKeys) @@ -652,65 +692,65 @@ self.listBindings.select_set(listIndex) self.listBindings.select_anchor(listIndex) - def GetNewKeysName(self,message): - usedNames=(idleConf.GetSectionList('user','keys')+ - idleConf.GetSectionList('default','keys')) - newKeySet=GetCfgSectionNameDialog(self,'New Custom Key Set', - message,usedNames).result + def GetNewKeysName(self, message): + usedNames = (idleConf.GetSectionList('user', 'keys') + + idleConf.GetSectionList('default', 'keys')) + newKeySet = GetCfgSectionNameDialog( + self, 'New Custom Key Set', message, usedNames).result return newKeySet def SaveAsNewKeySet(self): - newKeysName=self.GetNewKeysName('New Key Set Name:') + newKeysName = self.GetNewKeysName('New Key Set Name:') if newKeysName: self.CreateNewKeySet(newKeysName) - def KeyBindingSelected(self,event): + def KeyBindingSelected(self, event): self.buttonNewKeys.config(state=NORMAL) - def CreateNewKeySet(self,newKeySetName): + def CreateNewKeySet(self, newKeySetName): #creates new custom key set based on the previously active key set, #and makes the new key set active if self.keysAreBuiltin.get(): - prevKeySetName=self.builtinKeys.get() + prevKeySetName = self.builtinKeys.get() else: - prevKeySetName=self.customKeys.get() - prevKeys=idleConf.GetCoreKeys(prevKeySetName) - newKeys={} + prevKeySetName = self.customKeys.get() + prevKeys = idleConf.GetCoreKeys(prevKeySetName) + newKeys = {} for event in prevKeys: #add key set to changed items - eventName=event[2:-2] #trim off the angle brackets - binding=' '.join(prevKeys[event]) - newKeys[eventName]=binding + eventName = event[2:-2] #trim off the angle brackets + binding = ' '.join(prevKeys[event]) + newKeys[eventName] = binding #handle any unsaved changes to prev key set if prevKeySetName in self.changedItems['keys']: - keySetChanges=self.changedItems['keys'][prevKeySetName] + keySetChanges = self.changedItems['keys'][prevKeySetName] for event in keySetChanges: - newKeys[event]=keySetChanges[event] + newKeys[event] = keySetChanges[event] #save the new theme - self.SaveNewKeySet(newKeySetName,newKeys) + self.SaveNewKeySet(newKeySetName, newKeys) #change gui over to the new key set - customKeyList=idleConf.GetSectionList('user','keys') + customKeyList = idleConf.GetSectionList('user', 'keys') customKeyList.sort() - self.optMenuKeysCustom.SetMenu(customKeyList,newKeySetName) + self.optMenuKeysCustom.SetMenu(customKeyList, newKeySetName) self.keysAreBuiltin.set(0) self.SetKeysType() - def LoadKeysList(self,keySetName): - reselect=0 - newKeySet=0 + def LoadKeysList(self, keySetName): + reselect = 0 + newKeySet = 0 if self.listBindings.curselection(): - reselect=1 - listIndex=self.listBindings.index(ANCHOR) - keySet=idleConf.GetKeySet(keySetName) - bindNames=keySet.keys() + reselect = 1 + listIndex = self.listBindings.index(ANCHOR) + keySet = idleConf.GetKeySet(keySetName) + bindNames = keySet.keys() bindNames.sort() - self.listBindings.delete(0,END) + self.listBindings.delete(0, END) for bindName in bindNames: - key=' '.join(keySet[bindName]) #make key(s) into a string - bindName=bindName[2:-2] #trim off the angle brackets + key = ' '.join(keySet[bindName]) #make key(s) into a string + bindName = bindName[2:-2] #trim off the angle brackets if keySetName in self.changedItems['keys']: #handle any unsaved changes to this key set if bindName in self.changedItems['keys'][keySetName]: - key=self.changedItems['keys'][keySetName][bindName] + key = self.changedItems['keys'][keySetName][bindName] self.listBindings.insert(END, bindName+' - '+key) if reselect: self.listBindings.see(listIndex) @@ -719,9 +759,9 @@ def DeleteCustomKeys(self): keySetName=self.customKeys.get() - if not tkMessageBox.askyesno('Delete Key Set','Are you sure you wish '+ - 'to delete the key set %r ?' % (keySetName), - parent=self): + delmsg = 'Are you sure you wish to delete the key set %r ?' + if not tkMessageBox.askyesno( + 'Delete Key Set', delmsg % keySetName, parent=self): return #remove key set from config idleConf.userCfg['keys'].remove_section(keySetName) @@ -730,25 +770,25 @@ #write changes idleConf.userCfg['keys'].Save() #reload user key set list - itemList=idleConf.GetSectionList('user','keys') + itemList = idleConf.GetSectionList('user', 'keys') itemList.sort() if not itemList: self.radioKeysCustom.config(state=DISABLED) - self.optMenuKeysCustom.SetMenu(itemList,'- no custom keys -') + self.optMenuKeysCustom.SetMenu(itemList, '- no custom keys -') else: - self.optMenuKeysCustom.SetMenu(itemList,itemList[0]) + self.optMenuKeysCustom.SetMenu(itemList, itemList[0]) #revert to default key set - self.keysAreBuiltin.set(idleConf.defaultCfg['main'].Get('Keys','default')) - self.builtinKeys.set(idleConf.defaultCfg['main'].Get('Keys','name')) + self.keysAreBuiltin.set(idleConf.defaultCfg['main'].Get('Keys', 'default')) + self.builtinKeys.set(idleConf.defaultCfg['main'].Get('Keys', 'name')) #user can't back out of these changes, they must be applied now self.Apply() self.SetKeysType() def DeleteCustomTheme(self): - themeName=self.customTheme.get() - if not tkMessageBox.askyesno('Delete Theme','Are you sure you wish '+ - 'to delete the theme %r ?' % (themeName,), - parent=self): + themeName = self.customTheme.get() + delmsg = 'Are you sure you wish to delete the theme %r ?' + if not tkMessageBox.askyesno( + 'Delete Theme', delmsg % themeName, parent=self): return #remove theme from config idleConf.userCfg['highlight'].remove_section(themeName) @@ -757,153 +797,149 @@ #write changes idleConf.userCfg['highlight'].Save() #reload user theme list - itemList=idleConf.GetSectionList('user','highlight') + itemList = idleConf.GetSectionList('user', 'highlight') itemList.sort() if not itemList: self.radioThemeCustom.config(state=DISABLED) - self.optMenuThemeCustom.SetMenu(itemList,'- no custom themes -') + self.optMenuThemeCustom.SetMenu(itemList, '- no custom themes -') else: - self.optMenuThemeCustom.SetMenu(itemList,itemList[0]) + self.optMenuThemeCustom.SetMenu(itemList, itemList[0]) #revert to default theme - self.themeIsBuiltin.set(idleConf.defaultCfg['main'].Get('Theme','default')) - self.builtinTheme.set(idleConf.defaultCfg['main'].Get('Theme','name')) + self.themeIsBuiltin.set(idleConf.defaultCfg['main'].Get('Theme', 'default')) + self.builtinTheme.set(idleConf.defaultCfg['main'].Get('Theme', 'name')) #user can't back out of these changes, they must be applied now self.Apply() self.SetThemeType() def GetColour(self): - target=self.highlightTarget.get() - prevColour=self.frameColourSet.cget('bg') - rgbTuplet, colourString = tkColorChooser.askcolor(parent=self, - title='Pick new colour for : '+target,initialcolor=prevColour) - if colourString and (colourString!=prevColour): + target = self.highlightTarget.get() + prevColour = self.frameColourSet.cget('bg') + rgbTuplet, colourString = tkColorChooser.askcolor( + parent=self, title='Pick new colour for : '+target, + initialcolor=prevColour) + if colourString and (colourString != prevColour): #user didn't cancel, and they chose a new colour - if self.themeIsBuiltin.get(): #current theme is a built-in - message=('Your changes will be saved as a new Custom Theme. '+ - 'Enter a name for your new Custom Theme below.') - newTheme=self.GetNewThemeName(message) - if not newTheme: #user cancelled custom theme creation + if self.themeIsBuiltin.get(): #current theme is a built-in + message = ('Your changes will be saved as a new Custom Theme. ' + 'Enter a name for your new Custom Theme below.') + newTheme = self.GetNewThemeName(message) + if not newTheme: #user cancelled custom theme creation return - else: #create new custom theme based on previously active theme + else: #create new custom theme based on previously active theme self.CreateNewTheme(newTheme) self.colour.set(colourString) - else: #current theme is user defined + else: #current theme is user defined self.colour.set(colourString) def OnNewColourSet(self): newColour=self.colour.get() - self.frameColourSet.config(bg=newColour)#set sample - if self.fgHilite.get(): plane='foreground' - else: plane='background' - sampleElement=self.themeElements[self.highlightTarget.get()][0] + self.frameColourSet.config(bg=newColour) #set sample + plane ='foreground' if self.fgHilite.get() else 'background' + sampleElement = self.themeElements[self.highlightTarget.get()][0] self.textHighlightSample.tag_config(sampleElement, **{plane:newColour}) - theme=self.customTheme.get() - themeElement=sampleElement+'-'+plane - self.AddChangedItem('highlight',theme,themeElement,newColour) + theme = self.customTheme.get() + themeElement = sampleElement + '-' + plane + self.AddChangedItem('highlight', theme, themeElement, newColour) - def GetNewThemeName(self,message): - usedNames=(idleConf.GetSectionList('user','highlight')+ - idleConf.GetSectionList('default','highlight')) - newTheme=GetCfgSectionNameDialog(self,'New Custom Theme', - message,usedNames).result + def GetNewThemeName(self, message): + usedNames = (idleConf.GetSectionList('user', 'highlight') + + idleConf.GetSectionList('default', 'highlight')) + newTheme = GetCfgSectionNameDialog( + self, 'New Custom Theme', message, usedNames).result return newTheme def SaveAsNewTheme(self): - newThemeName=self.GetNewThemeName('New Theme Name:') + newThemeName = self.GetNewThemeName('New Theme Name:') if newThemeName: self.CreateNewTheme(newThemeName) - def CreateNewTheme(self,newThemeName): + def CreateNewTheme(self, newThemeName): #creates new custom theme based on the previously active theme, #and makes the new theme active if self.themeIsBuiltin.get(): - themeType='default' - themeName=self.builtinTheme.get() + themeType = 'default' + themeName = self.builtinTheme.get() else: - themeType='user' - themeName=self.customTheme.get() - newTheme=idleConf.GetThemeDict(themeType,themeName) + themeType = 'user' + themeName = self.customTheme.get() + newTheme = idleConf.GetThemeDict(themeType, themeName) #apply any of the old theme's unsaved changes to the new theme if themeName in self.changedItems['highlight']: - themeChanges=self.changedItems['highlight'][themeName] + themeChanges = self.changedItems['highlight'][themeName] for element in themeChanges: - newTheme[element]=themeChanges[element] + newTheme[element] = themeChanges[element] #save the new theme - self.SaveNewTheme(newThemeName,newTheme) + self.SaveNewTheme(newThemeName, newTheme) #change gui over to the new theme - customThemeList=idleConf.GetSectionList('user','highlight') + customThemeList = idleConf.GetSectionList('user', 'highlight') customThemeList.sort() - self.optMenuThemeCustom.SetMenu(customThemeList,newThemeName) + self.optMenuThemeCustom.SetMenu(customThemeList, newThemeName) self.themeIsBuiltin.set(0) self.SetThemeType() - def OnListFontButtonRelease(self,event): + def OnListFontButtonRelease(self, event): font = self.listFontName.get(ANCHOR) self.fontName.set(font.lower()) self.SetFontSample() - def SetFontSample(self,event=None): - fontName=self.fontName.get() - if self.fontBold.get(): - fontWeight=tkFont.BOLD - else: - fontWeight=tkFont.NORMAL + def SetFontSample(self, event=None): + fontName = self.fontName.get() + fontWeight = tkFont.BOLD if self.fontBold.get() else tkFont.NORMAL newFont = (fontName, self.fontSize.get(), fontWeight) self.labelFontSample.config(font=newFont) self.textHighlightSample.configure(font=newFont) def SetHighlightTarget(self): - if self.highlightTarget.get()=='Cursor': #bg not possible + if self.highlightTarget.get() == 'Cursor': #bg not possible self.radioFg.config(state=DISABLED) self.radioBg.config(state=DISABLED) self.fgHilite.set(1) - else: #both fg and bg can be set + else: #both fg and bg can be set self.radioFg.config(state=NORMAL) self.radioBg.config(state=NORMAL) self.fgHilite.set(1) self.SetColourSample() - def SetColourSampleBinding(self,*args): + def SetColourSampleBinding(self, *args): self.SetColourSample() def SetColourSample(self): #set the colour smaple area - tag=self.themeElements[self.highlightTarget.get()][0] - if self.fgHilite.get(): plane='foreground' - else: plane='background' - colour=self.textHighlightSample.tag_cget(tag,plane) + tag = self.themeElements[self.highlightTarget.get()][0] + plane = 'foreground' if self.fgHilite.get() else 'background' + colour = self.textHighlightSample.tag_cget(tag, plane) self.frameColourSet.config(bg=colour) def PaintThemeSample(self): - if self.themeIsBuiltin.get(): #a default theme - theme=self.builtinTheme.get() - else: #a user theme - theme=self.customTheme.get() + if self.themeIsBuiltin.get(): #a default theme + theme = self.builtinTheme.get() + else: #a user theme + theme = self.customTheme.get() for elementTitle in self.themeElements: - element=self.themeElements[elementTitle][0] - colours=idleConf.GetHighlight(theme,element) - if element=='cursor': #cursor sample needs special painting - colours['background']=idleConf.GetHighlight(theme, - 'normal', fgBg='bg') + element = self.themeElements[elementTitle][0] + colours = idleConf.GetHighlight(theme, element) + if element == 'cursor': #cursor sample needs special painting + colours['background'] = idleConf.GetHighlight( + theme, 'normal', fgBg='bg') #handle any unsaved changes to this theme if theme in self.changedItems['highlight']: - themeDict=self.changedItems['highlight'][theme] - if element+'-foreground' in themeDict: - colours['foreground']=themeDict[element+'-foreground'] - if element+'-background' in themeDict: - colours['background']=themeDict[element+'-background'] + themeDict = self.changedItems['highlight'][theme] + if element + '-foreground' in themeDict: + colours['foreground'] = themeDict[element + '-foreground'] + if element + '-background' in themeDict: + colours['background'] = themeDict[element + '-background'] self.textHighlightSample.tag_config(element, **colours) self.SetColourSample() - def HelpSourceSelected(self,event): + def HelpSourceSelected(self, event): self.SetHelpListButtonStates() def SetHelpListButtonStates(self): - if self.listHelp.size()<1: #no entries in list + if self.listHelp.size() < 1: #no entries in list self.buttonHelpListEdit.config(state=DISABLED) self.buttonHelpListRemove.config(state=DISABLED) else: #there are some entries - if self.listHelp.curselection(): #there currently is a selection + if self.listHelp.curselection(): #there currently is a selection self.buttonHelpListEdit.config(state=NORMAL) self.buttonHelpListRemove.config(state=NORMAL) else: #there currently is not a selection @@ -911,28 +947,29 @@ self.buttonHelpListRemove.config(state=DISABLED) def HelpListItemAdd(self): - helpSource=GetHelpSourceDialog(self,'New Help Source').result + helpSource = GetHelpSourceDialog(self, 'New Help Source').result if helpSource: - self.userHelpList.append( (helpSource[0],helpSource[1]) ) - self.listHelp.insert(END,helpSource[0]) + self.userHelpList.append((helpSource[0], helpSource[1])) + self.listHelp.insert(END, helpSource[0]) self.UpdateUserHelpChangedItems() self.SetHelpListButtonStates() def HelpListItemEdit(self): - itemIndex=self.listHelp.index(ANCHOR) - helpSource=self.userHelpList[itemIndex] - newHelpSource=GetHelpSourceDialog(self,'Edit Help Source', - menuItem=helpSource[0],filePath=helpSource[1]).result - if (not newHelpSource) or (newHelpSource==helpSource): + itemIndex = self.listHelp.index(ANCHOR) + helpSource = self.userHelpList[itemIndex] + newHelpSource = GetHelpSourceDialog( + self, 'Edit Help Source', menuItem=helpSource[0], + filePath=helpSource[1]).result + if (not newHelpSource) or (newHelpSource == helpSource): return #no changes - self.userHelpList[itemIndex]=newHelpSource + self.userHelpList[itemIndex] = newHelpSource self.listHelp.delete(itemIndex) - self.listHelp.insert(itemIndex,newHelpSource[0]) + self.listHelp.insert(itemIndex, newHelpSource[0]) self.UpdateUserHelpChangedItems() self.SetHelpListButtonStates() def HelpListItemRemove(self): - itemIndex=self.listHelp.index(ANCHOR) + itemIndex = self.listHelp.index(ANCHOR) del(self.userHelpList[itemIndex]) self.listHelp.delete(itemIndex) self.UpdateUserHelpChangedItems() @@ -941,18 +978,19 @@ def UpdateUserHelpChangedItems(self): "Clear and rebuild the HelpFiles section in self.changedItems" self.changedItems['main']['HelpFiles'] = {} - for num in range(1,len(self.userHelpList)+1): - self.AddChangedItem('main','HelpFiles',str(num), + for num in range(1, len(self.userHelpList) + 1): + self.AddChangedItem( + 'main', 'HelpFiles', str(num), ';'.join(self.userHelpList[num-1][:2])) def LoadFontCfg(self): ##base editor font selection list - fonts=list(tkFont.families(self)) + fonts = list(tkFont.families(self)) fonts.sort() for font in fonts: - self.listFontName.insert(END,font) - configuredFont=idleConf.GetOption('main','EditorWindow','font', - default='courier') + self.listFontName.insert(END, font) + configuredFont = idleConf.GetOption( + 'main', 'EditorWindow', 'font', default='courier') lc_configuredFont = configuredFont.lower() self.fontName.set(lc_configuredFont) lc_fonts = [s.lower() for s in fonts] @@ -962,107 +1000,107 @@ self.listFontName.select_set(currentFontIndex) self.listFontName.select_anchor(currentFontIndex) ##font size dropdown - fontSize=idleConf.GetOption('main', 'EditorWindow', 'font-size', - type='int', default='10') - self.optMenuFontSize.SetMenu(('7','8','9','10','11','12','13','14', - '16','18','20','22'), fontSize ) + fontSize = idleConf.GetOption( + 'main', 'EditorWindow', 'font-size', type='int', default='10') + self.optMenuFontSize.SetMenu(('7', '8', '9', '10', '11', '12', '13', + '14', '16', '18', '20', '22'), fontSize ) ##fontWeight - self.fontBold.set(idleConf.GetOption('main','EditorWindow', - 'font-bold',default=0,type='bool')) + self.fontBold.set(idleConf.GetOption( + 'main', 'EditorWindow', 'font-bold', default=0, type='bool')) ##font sample self.SetFontSample() def LoadTabCfg(self): ##indent sizes - spaceNum=idleConf.GetOption('main','Indent','num-spaces', - default=4,type='int') + spaceNum = idleConf.GetOption( + 'main', 'Indent', 'num-spaces', default=4, type='int') self.spaceNum.set(spaceNum) def LoadThemeCfg(self): ##current theme type radiobutton - self.themeIsBuiltin.set(idleConf.GetOption('main','Theme','default', - type='bool',default=1)) + self.themeIsBuiltin.set(idleConf.GetOption( + 'main', 'Theme', 'default', type='bool', default=1)) ##currently set theme - currentOption=idleConf.CurrentTheme() + currentOption = idleConf.CurrentTheme() ##load available theme option menus if self.themeIsBuiltin.get(): #default theme selected - itemList=idleConf.GetSectionList('default','highlight') + itemList = idleConf.GetSectionList('default', 'highlight') itemList.sort() - self.optMenuThemeBuiltin.SetMenu(itemList,currentOption) - itemList=idleConf.GetSectionList('user','highlight') + self.optMenuThemeBuiltin.SetMenu(itemList, currentOption) + itemList = idleConf.GetSectionList('user', 'highlight') itemList.sort() if not itemList: self.radioThemeCustom.config(state=DISABLED) self.customTheme.set('- no custom themes -') else: - self.optMenuThemeCustom.SetMenu(itemList,itemList[0]) + self.optMenuThemeCustom.SetMenu(itemList, itemList[0]) else: #user theme selected - itemList=idleConf.GetSectionList('user','highlight') + itemList = idleConf.GetSectionList('user', 'highlight') itemList.sort() - self.optMenuThemeCustom.SetMenu(itemList,currentOption) - itemList=idleConf.GetSectionList('default','highlight') + self.optMenuThemeCustom.SetMenu(itemList, currentOption) + itemList = idleConf.GetSectionList('default', 'highlight') itemList.sort() - self.optMenuThemeBuiltin.SetMenu(itemList,itemList[0]) + self.optMenuThemeBuiltin.SetMenu(itemList, itemList[0]) self.SetThemeType() ##load theme element option menu - themeNames=self.themeElements.keys() + themeNames = self.themeElements.keys() themeNames.sort(key=lambda x: self.themeElements[x][1]) - self.optMenuHighlightTarget.SetMenu(themeNames,themeNames[0]) + self.optMenuHighlightTarget.SetMenu(themeNames, themeNames[0]) self.PaintThemeSample() self.SetHighlightTarget() def LoadKeyCfg(self): ##current keys type radiobutton - self.keysAreBuiltin.set(idleConf.GetOption('main','Keys','default', - type='bool',default=1)) + self.keysAreBuiltin.set(idleConf.GetOption( + 'main', 'Keys', 'default', type='bool', default=1)) ##currently set keys - currentOption=idleConf.CurrentKeys() + currentOption = idleConf.CurrentKeys() ##load available keyset option menus if self.keysAreBuiltin.get(): #default theme selected - itemList=idleConf.GetSectionList('default','keys') + itemList = idleConf.GetSectionList('default', 'keys') itemList.sort() - self.optMenuKeysBuiltin.SetMenu(itemList,currentOption) - itemList=idleConf.GetSectionList('user','keys') + self.optMenuKeysBuiltin.SetMenu(itemList, currentOption) + itemList = idleConf.GetSectionList('user', 'keys') itemList.sort() if not itemList: self.radioKeysCustom.config(state=DISABLED) self.customKeys.set('- no custom keys -') else: - self.optMenuKeysCustom.SetMenu(itemList,itemList[0]) + self.optMenuKeysCustom.SetMenu(itemList, itemList[0]) else: #user key set selected - itemList=idleConf.GetSectionList('user','keys') + itemList = idleConf.GetSectionList('user', 'keys') itemList.sort() - self.optMenuKeysCustom.SetMenu(itemList,currentOption) - itemList=idleConf.GetSectionList('default','keys') + self.optMenuKeysCustom.SetMenu(itemList, currentOption) + itemList = idleConf.GetSectionList('default', 'keys') itemList.sort() - self.optMenuKeysBuiltin.SetMenu(itemList,itemList[0]) + self.optMenuKeysBuiltin.SetMenu(itemList, itemList[0]) self.SetKeysType() ##load keyset element list - keySetName=idleConf.CurrentKeys() + keySetName = idleConf.CurrentKeys() self.LoadKeysList(keySetName) def LoadGeneralCfg(self): #startup state - self.startupEdit.set(idleConf.GetOption('main','General', - 'editor-on-startup',default=1,type='bool')) + self.startupEdit.set(idleConf.GetOption( + 'main', 'General', 'editor-on-startup', default=1, type='bool')) #autosave state - self.autoSave.set(idleConf.GetOption('main', 'General', 'autosave', - default=0, type='bool')) + self.autoSave.set(idleConf.GetOption( + 'main', 'General', 'autosave', default=0, type='bool')) #initial window size - self.winWidth.set(idleConf.GetOption('main','EditorWindow','width', - type='int')) - self.winHeight.set(idleConf.GetOption('main','EditorWindow','height', - type='int')) + self.winWidth.set(idleConf.GetOption( + 'main', 'EditorWindow', 'width', type='int')) + self.winHeight.set(idleConf.GetOption( + 'main', 'EditorWindow', 'height', type='int')) #initial paragraph reformat size - self.paraWidth.set(idleConf.GetOption('main','FormatParagraph','paragraph', - type='int')) + self.paraWidth.set(idleConf.GetOption( + 'main', 'FormatParagraph', 'paragraph', type='int')) # default source encoding - self.encoding.set(idleConf.GetOption('main', 'EditorWindow', - 'encoding', default='none')) + self.encoding.set(idleConf.GetOption( + 'main', 'EditorWindow', 'encoding', default='none')) # additional help sources self.userHelpList = idleConf.GetAllExtraHelpSourcesList() for helpItem in self.userHelpList: - self.listHelp.insert(END,helpItem[0]) + self.listHelp.insert(END, helpItem[0]) self.SetHelpListButtonStates() def LoadConfigs(self): @@ -1080,7 +1118,7 @@ ### general page self.LoadGeneralCfg() - def SaveNewKeySet(self,keySetName,keySet): + def SaveNewKeySet(self, keySetName, keySet): """ save a newly created core key set. keySetName - string, the name of the new key set @@ -1089,10 +1127,10 @@ if not idleConf.userCfg['keys'].has_section(keySetName): idleConf.userCfg['keys'].add_section(keySetName) for event in keySet: - value=keySet[event] - idleConf.userCfg['keys'].SetOption(keySetName,event,value) + value = keySet[event] + idleConf.userCfg['keys'].SetOption(keySetName, event, value) - def SaveNewTheme(self,themeName,theme): + def SaveNewTheme(self, themeName, theme): """ save a newly created theme. themeName - string, the name of the new theme @@ -1101,16 +1139,16 @@ if not idleConf.userCfg['highlight'].has_section(themeName): idleConf.userCfg['highlight'].add_section(themeName) for element in theme: - value=theme[element] - idleConf.userCfg['highlight'].SetOption(themeName,element,value) + value = theme[element] + idleConf.userCfg['highlight'].SetOption(themeName, element, value) - def SetUserValue(self,configType,section,item,value): - if idleConf.defaultCfg[configType].has_option(section,item): - if idleConf.defaultCfg[configType].Get(section,item)==value: + def SetUserValue(self, configType, section, item, value): + if idleConf.defaultCfg[configType].has_option(section, item): + if idleConf.defaultCfg[configType].Get(section, item) == value: #the setting equals a default setting, remove it from user cfg - return idleConf.userCfg[configType].RemoveOption(section,item) + return idleConf.userCfg[configType].RemoveOption(section, item) #if we got here set the option - return idleConf.userCfg[configType].SetOption(section,item,value) + return idleConf.userCfg[configType].SetOption(section, item, value) def SaveAllChangedConfigs(self): "Save configuration changes to the user config file." @@ -1124,7 +1162,7 @@ cfgTypeHasChanges = True for item in self.changedItems[configType][section]: value = self.changedItems[configType][section][item] - if self.SetUserValue(configType,section,item,value): + if self.SetUserValue(configType, section, item, value): cfgTypeHasChanges = True if cfgTypeHasChanges: idleConf.userCfg[configType].Save() @@ -1136,7 +1174,7 @@ def DeactivateCurrentConfig(self): #Before a config is saved, some cleanup of current #config must be done - remove the previous keybindings - winInstances=self.parent.instance_dict + winInstances = self.parent.instance_dict for instance in winInstances: instance.RemoveKeybindings() -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Aug 4 05:03:48 2014 From: python-checkins at python.org (terry.reedy) Date: Mon, 4 Aug 2014 05:03:48 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E4=29=3A_PEP_8_spacing_?= =?utf-8?q?in_idlelib=2EconfigDialog=3A_mostly_a_=3D_b_in_assignments=2C?= Message-ID: <3hRP7S5rj6z7Lq6@mail.python.org> http://hg.python.org/cpython/rev/b5466a75e203 changeset: 91979:b5466a75e203 branch: 3.4 parent: 91976:c689156580ca user: Terry Jan Reedy date: Sun Aug 03 23:02:58 2014 -0400 summary: PEP 8 spacing in idlelib.configDialog: mostly a = b in assignments, a, b in arg lists, and hanging indents for long arg lists. files: Lib/idlelib/configDialog.py | 1118 +++++++++++----------- 1 files changed, 576 insertions(+), 542 deletions(-) diff --git a/Lib/idlelib/configDialog.py b/Lib/idlelib/configDialog.py --- a/Lib/idlelib/configDialog.py +++ b/Lib/idlelib/configDialog.py @@ -31,42 +31,44 @@ """ Toplevel.__init__(self, parent) self.parent = parent + if _htest: + parent.instance_dict = {} self.wm_withdraw() self.configure(borderwidth=5) self.title('IDLE Preferences') - if _htest: - parent.instance_dict = {} - self.geometry("+%d+%d" % (parent.winfo_rootx()+20, - parent.winfo_rooty()+(30 if not _htest else 150))) + self.geometry( + "+%d+%d" % (parent.winfo_rootx() + 20, + parent.winfo_rooty() + (30 if not _htest else 150))) #Theme Elements. Each theme element key is its display name. #The first value of the tuple is the sample area tag name. #The second value is the display name list sort index. - self.themeElements={'Normal Text':('normal','00'), - 'Python Keywords':('keyword','01'), - 'Python Definitions':('definition','02'), + self.themeElements={ + 'Normal Text':('normal', '00'), + 'Python Keywords':('keyword', '01'), + 'Python Definitions':('definition', '02'), 'Python Builtins':('builtin', '03'), - 'Python Comments':('comment','04'), - 'Python Strings':('string','05'), - 'Selected Text':('hilite','06'), - 'Found Text':('hit','07'), - 'Cursor':('cursor','08'), - 'Error Text':('error','09'), - 'Shell Normal Text':('console','10'), - 'Shell Stdout Text':('stdout','11'), - 'Shell Stderr Text':('stderr','12'), + 'Python Comments':('comment', '04'), + 'Python Strings':('string', '05'), + 'Selected Text':('hilite', '06'), + 'Found Text':('hit', '07'), + 'Cursor':('cursor', '08'), + 'Error Text':('error', '09'), + 'Shell Normal Text':('console', '10'), + 'Shell Stdout Text':('stdout', '11'), + 'Shell Stderr Text':('stderr', '12'), } self.ResetChangedItems() #load initial values in changed items dict self.CreateWidgets() - self.resizable(height=FALSE,width=FALSE) + self.resizable(height=FALSE, width=FALSE) self.transient(parent) self.grab_set() self.protocol("WM_DELETE_WINDOW", self.Cancel) self.tabPages.focus_set() #key bindings for this dialog - #self.bind('',self.Cancel) #dismiss dialog, no save - #self.bind('',self.Apply) #apply changes, save - #self.bind('',self.Help) #context help + #self.bind('', self.Cancel) #dismiss dialog, no save + #self.bind('', self.Apply) #apply changes, save + #self.bind('', self.Help) #context help self.LoadConfigs() self.AttachVarCallbacks() #avoid callbacks during LoadConfigs @@ -76,40 +78,40 @@ def CreateWidgets(self): self.tabPages = TabbedPageSet(self, - page_names=['Fonts/Tabs','Highlighting','Keys','General']) - frameActionButtons = Frame(self,pady=2) + page_names=['Fonts/Tabs', 'Highlighting', 'Keys', 'General']) + frameActionButtons = Frame(self, pady=2) #action buttons if macosxSupport.isAquaTk(): # Changing the default padding on OSX results in unreadable # text in the buttons - paddingArgs={} + paddingArgs = {} else: - paddingArgs={'padx':6, 'pady':3} + paddingArgs = {'padx':6, 'pady':3} # Comment out button creation and packing until implement self.Help -## self.buttonHelp = Button(frameActionButtons,text='Help', -## command=self.Help,takefocus=FALSE, +## self.buttonHelp = Button(frameActionButtons, text='Help', +## command=self.Help, takefocus=FALSE, ## **paddingArgs) - self.buttonOk = Button(frameActionButtons,text='Ok', - command=self.Ok,takefocus=FALSE, - **paddingArgs) - self.buttonApply = Button(frameActionButtons,text='Apply', - command=self.Apply,takefocus=FALSE, - **paddingArgs) - self.buttonCancel = Button(frameActionButtons,text='Cancel', - command=self.Cancel,takefocus=FALSE, - **paddingArgs) + self.buttonOk = Button( + frameActionButtons, text='Ok', + command=self.Ok, takefocus=FALSE, **paddingArgs) + self.buttonApply = Button( + frameActionButtons, text='Apply', + command=self.Apply, takefocus=FALSE, **paddingArgs) + self.buttonCancel = Button( + frameActionButtons, text='Cancel', + command=self.Cancel, takefocus=FALSE, **paddingArgs) self.CreatePageFontTab() self.CreatePageHighlight() self.CreatePageKeys() self.CreatePageGeneral() -## self.buttonHelp.pack(side=RIGHT,padx=5) - self.buttonOk.pack(side=LEFT,padx=5) - self.buttonApply.pack(side=LEFT,padx=5) - self.buttonCancel.pack(side=LEFT,padx=5) +## self.buttonHelp.pack(side=RIGHT, padx=5) + self.buttonOk.pack(side=LEFT, padx=5) + self.buttonApply.pack(side=LEFT, padx=5) + self.buttonCancel.pack(side=LEFT, padx=5) frameActionButtons.pack(side=BOTTOM) Frame(self, height=2, borderwidth=0).pack(side=BOTTOM) - self.tabPages.pack(side=TOP,expand=TRUE,fill=BOTH) + self.tabPages.pack(side=TOP, expand=TRUE, fill=BOTH) def CreatePageFontTab(self): parent = self.parent @@ -117,63 +119,66 @@ self.fontBold = BooleanVar(parent) self.fontName = StringVar(parent) self.spaceNum = IntVar(parent) - self.editFont = tkFont.Font(parent,('courier',10,'normal')) + self.editFont = tkFont.Font(parent, ('courier', 10, 'normal')) ##widget creation #body frame - frame=self.tabPages.pages['Fonts/Tabs'].frame + frame = self.tabPages.pages['Fonts/Tabs'].frame #body section frames - frameFont=LabelFrame(frame,borderwidth=2,relief=GROOVE, - text=' Base Editor Font ') - frameIndent=LabelFrame(frame,borderwidth=2,relief=GROOVE, - text=' Indentation Width ') + frameFont = LabelFrame( + frame, borderwidth=2, relief=GROOVE, text=' Base Editor Font ') + frameIndent = LabelFrame( + frame, borderwidth=2, relief=GROOVE, text=' Indentation Width ') #frameFont - frameFontName=Frame(frameFont) - frameFontParam=Frame(frameFont) - labelFontNameTitle=Label(frameFontName,justify=LEFT, - text='Font Face :') - self.listFontName=Listbox(frameFontName,height=5,takefocus=FALSE, - exportselection=FALSE) - self.listFontName.bind('',self.OnListFontButtonRelease) - scrollFont=Scrollbar(frameFontName) + frameFontName = Frame(frameFont) + frameFontParam = Frame(frameFont) + labelFontNameTitle = Label( + frameFontName, justify=LEFT, text='Font Face :') + self.listFontName = Listbox( + frameFontName, height=5, takefocus=FALSE, exportselection=FALSE) + self.listFontName.bind( + '', self.OnListFontButtonRelease) + scrollFont = Scrollbar(frameFontName) scrollFont.config(command=self.listFontName.yview) self.listFontName.config(yscrollcommand=scrollFont.set) - labelFontSizeTitle=Label(frameFontParam,text='Size :') - self.optMenuFontSize=DynOptionMenu(frameFontParam,self.fontSize,None, - command=self.SetFontSample) - checkFontBold=Checkbutton(frameFontParam,variable=self.fontBold, - onvalue=1,offvalue=0,text='Bold',command=self.SetFontSample) - frameFontSample=Frame(frameFont,relief=SOLID,borderwidth=1) - self.labelFontSample=Label(frameFontSample, - text='AaBbCcDdEe\nFfGgHhIiJjK\n1234567890\n#:+=(){}[]', - justify=LEFT,font=self.editFont) + labelFontSizeTitle = Label(frameFontParam, text='Size :') + self.optMenuFontSize = DynOptionMenu( + frameFontParam, self.fontSize, None, command=self.SetFontSample) + checkFontBold = Checkbutton( + frameFontParam, variable=self.fontBold, onvalue=1, + offvalue=0, text='Bold', command=self.SetFontSample) + frameFontSample = Frame(frameFont, relief=SOLID, borderwidth=1) + self.labelFontSample = Label( + frameFontSample, justify=LEFT, font=self.editFont, + text='AaBbCcDdEe\nFfGgHhIiJjK\n1234567890\n#:+=(){}[]') #frameIndent - frameIndentSize=Frame(frameIndent) - labelSpaceNumTitle=Label(frameIndentSize, justify=LEFT, - text='Python Standard: 4 Spaces!') - self.scaleSpaceNum=Scale(frameIndentSize, variable=self.spaceNum, - orient='horizontal', - tickinterval=2, from_=2, to=16) + frameIndentSize = Frame(frameIndent) + labelSpaceNumTitle = Label( + frameIndentSize, justify=LEFT, + text='Python Standard: 4 Spaces!') + self.scaleSpaceNum = Scale( + frameIndentSize, variable=self.spaceNum, + orient='horizontal', tickinterval=2, from_=2, to=16) #widget packing #body - frameFont.pack(side=LEFT,padx=5,pady=5,expand=TRUE,fill=BOTH) - frameIndent.pack(side=LEFT,padx=5,pady=5,fill=Y) + frameFont.pack(side=LEFT, padx=5, pady=5, expand=TRUE, fill=BOTH) + frameIndent.pack(side=LEFT, padx=5, pady=5, fill=Y) #frameFont - frameFontName.pack(side=TOP,padx=5,pady=5,fill=X) - frameFontParam.pack(side=TOP,padx=5,pady=5,fill=X) - labelFontNameTitle.pack(side=TOP,anchor=W) - self.listFontName.pack(side=LEFT,expand=TRUE,fill=X) - scrollFont.pack(side=LEFT,fill=Y) - labelFontSizeTitle.pack(side=LEFT,anchor=W) - self.optMenuFontSize.pack(side=LEFT,anchor=W) - checkFontBold.pack(side=LEFT,anchor=W,padx=20) - frameFontSample.pack(side=TOP,padx=5,pady=5,expand=TRUE,fill=BOTH) - self.labelFontSample.pack(expand=TRUE,fill=BOTH) + frameFontName.pack(side=TOP, padx=5, pady=5, fill=X) + frameFontParam.pack(side=TOP, padx=5, pady=5, fill=X) + labelFontNameTitle.pack(side=TOP, anchor=W) + self.listFontName.pack(side=LEFT, expand=TRUE, fill=X) + scrollFont.pack(side=LEFT, fill=Y) + labelFontSizeTitle.pack(side=LEFT, anchor=W) + self.optMenuFontSize.pack(side=LEFT, anchor=W) + checkFontBold.pack(side=LEFT, anchor=W, padx=20) + frameFontSample.pack(side=TOP, padx=5, pady=5, expand=TRUE, fill=BOTH) + self.labelFontSample.pack(expand=TRUE, fill=BOTH) #frameIndent - frameIndentSize.pack(side=TOP,fill=X) - labelSpaceNumTitle.pack(side=TOP,anchor=W,padx=5) - self.scaleSpaceNum.pack(side=TOP,padx=5,fill=X) + frameIndentSize.pack(side=TOP, fill=X) + labelSpaceNumTitle.pack(side=TOP, anchor=W, padx=5) + self.scaleSpaceNum.pack(side=TOP, padx=5, fill=X) return frame def CreatePageHighlight(self): @@ -188,84 +193,100 @@ ##widget creation #body frame - frame=self.tabPages.pages['Highlighting'].frame + frame = self.tabPages.pages['Highlighting'].frame #body section frames - frameCustom=LabelFrame(frame,borderwidth=2,relief=GROOVE, - text=' Custom Highlighting ') - frameTheme=LabelFrame(frame,borderwidth=2,relief=GROOVE, - text=' Highlighting Theme ') + frameCustom = LabelFrame(frame, borderwidth=2, relief=GROOVE, + text=' Custom Highlighting ') + frameTheme = LabelFrame(frame, borderwidth=2, relief=GROOVE, + text=' Highlighting Theme ') #frameCustom - self.textHighlightSample=Text(frameCustom,relief=SOLID,borderwidth=1, - font=('courier',12,''),cursor='hand2',width=21,height=11, - takefocus=FALSE,highlightthickness=0,wrap=NONE) + self.textHighlightSample=Text( + frameCustom, relief=SOLID, borderwidth=1, + font=('courier', 12, ''), cursor='hand2', width=21, height=11, + takefocus=FALSE, highlightthickness=0, wrap=NONE) text=self.textHighlightSample - text.bind('',lambda e: 'break') - text.bind('',lambda e: 'break') - textAndTags=(('#you can click here','comment'),('\n','normal'), - ('#to choose items','comment'),('\n','normal'),('def','keyword'), - (' ','normal'),('func','definition'),('(param):','normal'), - ('\n ','normal'),('"""string"""','string'),('\n var0 = ','normal'), - ("'string'",'string'),('\n var1 = ','normal'),("'selected'",'hilite'), - ('\n var2 = ','normal'),("'found'",'hit'), - ('\n var3 = ','normal'),('list', 'builtin'), ('(','normal'), - ('None', 'keyword'),(')\n\n','normal'), - (' error ','error'),(' ','normal'),('cursor |','cursor'), - ('\n ','normal'),('shell','console'),(' ','normal'),('stdout','stdout'), - (' ','normal'),('stderr','stderr'),('\n','normal')) + text.bind('', lambda e: 'break') + text.bind('', lambda e: 'break') + textAndTags=( + ('#you can click here', 'comment'), ('\n', 'normal'), + ('#to choose items', 'comment'), ('\n', 'normal'), + ('def', 'keyword'), (' ', 'normal'), + ('func', 'definition'), ('(param):\n ', 'normal'), + ('"""string"""', 'string'), ('\n var0 = ', 'normal'), + ("'string'", 'string'), ('\n var1 = ', 'normal'), + ("'selected'", 'hilite'), ('\n var2 = ', 'normal'), + ("'found'", 'hit'), ('\n var3 = ', 'normal'), + ('list', 'builtin'), ('(', 'normal'), + ('None', 'keyword'), (')\n\n', 'normal'), + (' error ', 'error'), (' ', 'normal'), + ('cursor |', 'cursor'), ('\n ', 'normal'), + ('shell', 'console'), (' ', 'normal'), + ('stdout', 'stdout'), (' ', 'normal'), + ('stderr', 'stderr'), ('\n', 'normal')) for txTa in textAndTags: - text.insert(END,txTa[0],txTa[1]) + text.insert(END, txTa[0], txTa[1]) for element in self.themeElements: - text.tag_bind(self.themeElements[element][0],'', - lambda event,elem=element: event.widget.winfo_toplevel() - .highlightTarget.set(elem)) + def tem(event, elem=element): + event.widget.winfo_toplevel().highlightTarget.set(elem) + text.tag_bind( + self.themeElements[element][0], '', tem) text.config(state=DISABLED) - self.frameColourSet=Frame(frameCustom,relief=SOLID,borderwidth=1) - frameFgBg=Frame(frameCustom) - buttonSetColour=Button(self.frameColourSet,text='Choose Colour for :', - command=self.GetColour,highlightthickness=0) - self.optMenuHighlightTarget=DynOptionMenu(self.frameColourSet, - self.highlightTarget,None,highlightthickness=0)#,command=self.SetHighlightTargetBinding - self.radioFg=Radiobutton(frameFgBg,variable=self.fgHilite, - value=1,text='Foreground',command=self.SetColourSampleBinding) - self.radioBg=Radiobutton(frameFgBg,variable=self.fgHilite, - value=0,text='Background',command=self.SetColourSampleBinding) + self.frameColourSet = Frame(frameCustom, relief=SOLID, borderwidth=1) + frameFgBg = Frame(frameCustom) + buttonSetColour = Button( + self.frameColourSet, text='Choose Colour for :', + command=self.GetColour, highlightthickness=0) + self.optMenuHighlightTarget = DynOptionMenu( + self.frameColourSet, self.highlightTarget, None, + highlightthickness=0) #, command=self.SetHighlightTargetBinding + self.radioFg = Radiobutton( + frameFgBg, variable=self.fgHilite, value=1, + text='Foreground', command=self.SetColourSampleBinding) + self.radioBg=Radiobutton( + frameFgBg, variable=self.fgHilite, value=0, + text='Background', command=self.SetColourSampleBinding) self.fgHilite.set(1) - buttonSaveCustomTheme=Button(frameCustom, - text='Save as New Custom Theme',command=self.SaveAsNewTheme) + buttonSaveCustomTheme = Button( + frameCustom, text='Save as New Custom Theme', + command=self.SaveAsNewTheme) #frameTheme - labelTypeTitle=Label(frameTheme,text='Select : ') - self.radioThemeBuiltin=Radiobutton(frameTheme,variable=self.themeIsBuiltin, - value=1,command=self.SetThemeType,text='a Built-in Theme') - self.radioThemeCustom=Radiobutton(frameTheme,variable=self.themeIsBuiltin, - value=0,command=self.SetThemeType,text='a Custom Theme') - self.optMenuThemeBuiltin=DynOptionMenu(frameTheme, - self.builtinTheme,None,command=None) - self.optMenuThemeCustom=DynOptionMenu(frameTheme, - self.customTheme,None,command=None) - self.buttonDeleteCustomTheme=Button(frameTheme,text='Delete Custom Theme', + labelTypeTitle = Label(frameTheme, text='Select : ') + self.radioThemeBuiltin = Radiobutton( + frameTheme, variable=self.themeIsBuiltin, value=1, + command=self.SetThemeType, text='a Built-in Theme') + self.radioThemeCustom = Radiobutton( + frameTheme, variable=self.themeIsBuiltin, value=0, + command=self.SetThemeType, text='a Custom Theme') + self.optMenuThemeBuiltin = DynOptionMenu( + frameTheme, self.builtinTheme, None, command=None) + self.optMenuThemeCustom=DynOptionMenu( + frameTheme, self.customTheme, None, command=None) + self.buttonDeleteCustomTheme=Button( + frameTheme, text='Delete Custom Theme', command=self.DeleteCustomTheme) ##widget packing #body - frameCustom.pack(side=LEFT,padx=5,pady=5,expand=TRUE,fill=BOTH) - frameTheme.pack(side=LEFT,padx=5,pady=5,fill=Y) + frameCustom.pack(side=LEFT, padx=5, pady=5, expand=TRUE, fill=BOTH) + frameTheme.pack(side=LEFT, padx=5, pady=5, fill=Y) #frameCustom - self.frameColourSet.pack(side=TOP,padx=5,pady=5,expand=TRUE,fill=X) - frameFgBg.pack(side=TOP,padx=5,pady=0) - self.textHighlightSample.pack(side=TOP,padx=5,pady=5,expand=TRUE, - fill=BOTH) - buttonSetColour.pack(side=TOP,expand=TRUE,fill=X,padx=8,pady=4) - self.optMenuHighlightTarget.pack(side=TOP,expand=TRUE,fill=X,padx=8,pady=3) - self.radioFg.pack(side=LEFT,anchor=E) - self.radioBg.pack(side=RIGHT,anchor=W) - buttonSaveCustomTheme.pack(side=BOTTOM,fill=X,padx=5,pady=5) + self.frameColourSet.pack(side=TOP, padx=5, pady=5, expand=TRUE, fill=X) + frameFgBg.pack(side=TOP, padx=5, pady=0) + self.textHighlightSample.pack( + side=TOP, padx=5, pady=5, expand=TRUE, fill=BOTH) + buttonSetColour.pack(side=TOP, expand=TRUE, fill=X, padx=8, pady=4) + self.optMenuHighlightTarget.pack( + side=TOP, expand=TRUE, fill=X, padx=8, pady=3) + self.radioFg.pack(side=LEFT, anchor=E) + self.radioBg.pack(side=RIGHT, anchor=W) + buttonSaveCustomTheme.pack(side=BOTTOM, fill=X, padx=5, pady=5) #frameTheme - labelTypeTitle.pack(side=TOP,anchor=W,padx=5,pady=5) - self.radioThemeBuiltin.pack(side=TOP,anchor=W,padx=5) - self.radioThemeCustom.pack(side=TOP,anchor=W,padx=5,pady=2) - self.optMenuThemeBuiltin.pack(side=TOP,fill=X,padx=5,pady=5) - self.optMenuThemeCustom.pack(side=TOP,fill=X,anchor=W,padx=5,pady=5) - self.buttonDeleteCustomTheme.pack(side=TOP,fill=X,padx=5,pady=5) + labelTypeTitle.pack(side=TOP, anchor=W, padx=5, pady=5) + self.radioThemeBuiltin.pack(side=TOP, anchor=W, padx=5) + self.radioThemeCustom.pack(side=TOP, anchor=W, padx=5, pady=2) + self.optMenuThemeBuiltin.pack(side=TOP, fill=X, padx=5, pady=5) + self.optMenuThemeCustom.pack(side=TOP, fill=X, anchor=W, padx=5, pady=5) + self.buttonDeleteCustomTheme.pack(side=TOP, fill=X, padx=5, pady=5) return frame def CreatePageKeys(self): @@ -278,63 +299,69 @@ ##widget creation #body frame - frame=self.tabPages.pages['Keys'].frame + frame = self.tabPages.pages['Keys'].frame #body section frames - frameCustom=LabelFrame(frame,borderwidth=2,relief=GROOVE, - text=' Custom Key Bindings ') - frameKeySets=LabelFrame(frame,borderwidth=2,relief=GROOVE, - text=' Key Set ') + frameCustom = LabelFrame( + frame, borderwidth=2, relief=GROOVE, + text=' Custom Key Bindings ') + frameKeySets = LabelFrame( + frame, borderwidth=2, relief=GROOVE, text=' Key Set ') #frameCustom - frameTarget=Frame(frameCustom) - labelTargetTitle=Label(frameTarget,text='Action - Key(s)') - scrollTargetY=Scrollbar(frameTarget) - scrollTargetX=Scrollbar(frameTarget,orient=HORIZONTAL) - self.listBindings=Listbox(frameTarget,takefocus=FALSE, - exportselection=FALSE) - self.listBindings.bind('',self.KeyBindingSelected) + frameTarget = Frame(frameCustom) + labelTargetTitle = Label(frameTarget, text='Action - Key(s)') + scrollTargetY = Scrollbar(frameTarget) + scrollTargetX = Scrollbar(frameTarget, orient=HORIZONTAL) + self.listBindings = Listbox( + frameTarget, takefocus=FALSE, exportselection=FALSE) + self.listBindings.bind('', self.KeyBindingSelected) scrollTargetY.config(command=self.listBindings.yview) scrollTargetX.config(command=self.listBindings.xview) self.listBindings.config(yscrollcommand=scrollTargetY.set) self.listBindings.config(xscrollcommand=scrollTargetX.set) - self.buttonNewKeys=Button(frameCustom,text='Get New Keys for Selection', - command=self.GetNewKeys,state=DISABLED) + self.buttonNewKeys = Button( + frameCustom, text='Get New Keys for Selection', + command=self.GetNewKeys, state=DISABLED) #frameKeySets frames = [Frame(frameKeySets, padx=2, pady=2, borderwidth=0) for i in range(2)] - self.radioKeysBuiltin=Radiobutton(frames[0],variable=self.keysAreBuiltin, - value=1,command=self.SetKeysType,text='Use a Built-in Key Set') - self.radioKeysCustom=Radiobutton(frames[0],variable=self.keysAreBuiltin, - value=0,command=self.SetKeysType,text='Use a Custom Key Set') - self.optMenuKeysBuiltin=DynOptionMenu(frames[0], - self.builtinKeys,None,command=None) - self.optMenuKeysCustom=DynOptionMenu(frames[0], - self.customKeys,None,command=None) - self.buttonDeleteCustomKeys=Button(frames[1],text='Delete Custom Key Set', + self.radioKeysBuiltin = Radiobutton( + frames[0], variable=self.keysAreBuiltin, value=1, + command=self.SetKeysType, text='Use a Built-in Key Set') + self.radioKeysCustom = Radiobutton( + frames[0], variable=self.keysAreBuiltin, value=0, + command=self.SetKeysType, text='Use a Custom Key Set') + self.optMenuKeysBuiltin = DynOptionMenu( + frames[0], self.builtinKeys, None, command=None) + self.optMenuKeysCustom = DynOptionMenu( + frames[0], self.customKeys, None, command=None) + self.buttonDeleteCustomKeys = Button( + frames[1], text='Delete Custom Key Set', command=self.DeleteCustomKeys) - buttonSaveCustomKeys=Button(frames[1], - text='Save as New Custom Key Set',command=self.SaveAsNewKeySet) + buttonSaveCustomKeys = Button( + frames[1], text='Save as New Custom Key Set', + command=self.SaveAsNewKeySet) ##widget packing #body - frameCustom.pack(side=BOTTOM,padx=5,pady=5,expand=TRUE,fill=BOTH) - frameKeySets.pack(side=BOTTOM,padx=5,pady=5,fill=BOTH) + frameCustom.pack(side=BOTTOM, padx=5, pady=5, expand=TRUE, fill=BOTH) + frameKeySets.pack(side=BOTTOM, padx=5, pady=5, fill=BOTH) #frameCustom - self.buttonNewKeys.pack(side=BOTTOM,fill=X,padx=5,pady=5) - frameTarget.pack(side=LEFT,padx=5,pady=5,expand=TRUE,fill=BOTH) + self.buttonNewKeys.pack(side=BOTTOM, fill=X, padx=5, pady=5) + frameTarget.pack(side=LEFT, padx=5, pady=5, expand=TRUE, fill=BOTH) #frame target - frameTarget.columnconfigure(0,weight=1) - frameTarget.rowconfigure(1,weight=1) - labelTargetTitle.grid(row=0,column=0,columnspan=2,sticky=W) - self.listBindings.grid(row=1,column=0,sticky=NSEW) - scrollTargetY.grid(row=1,column=1,sticky=NS) - scrollTargetX.grid(row=2,column=0,sticky=EW) + frameTarget.columnconfigure(0, weight=1) + frameTarget.rowconfigure(1, weight=1) + labelTargetTitle.grid(row=0, column=0, columnspan=2, sticky=W) + self.listBindings.grid(row=1, column=0, sticky=NSEW) + scrollTargetY.grid(row=1, column=1, sticky=NS) + scrollTargetX.grid(row=2, column=0, sticky=EW) #frameKeySets self.radioKeysBuiltin.grid(row=0, column=0, sticky=W+NS) self.radioKeysCustom.grid(row=1, column=0, sticky=W+NS) self.optMenuKeysBuiltin.grid(row=0, column=1, sticky=NSEW) self.optMenuKeysCustom.grid(row=1, column=1, sticky=NSEW) - self.buttonDeleteCustomKeys.pack(side=LEFT,fill=X,expand=True,padx=2) - buttonSaveCustomKeys.pack(side=LEFT,fill=X,expand=True,padx=2) + self.buttonDeleteCustomKeys.pack(side=LEFT, fill=X, expand=True, padx=2) + buttonSaveCustomKeys.pack(side=LEFT, fill=X, expand=True, padx=2) frames[0].pack(side=TOP, fill=BOTH, expand=True) frames[1].pack(side=TOP, fill=X, expand=True, pady=2) return frame @@ -352,208 +379,216 @@ #widget creation #body - frame=self.tabPages.pages['General'].frame + frame = self.tabPages.pages['General'].frame #body section frames - frameRun=LabelFrame(frame,borderwidth=2,relief=GROOVE, - text=' Startup Preferences ') - frameSave=LabelFrame(frame,borderwidth=2,relief=GROOVE, - text=' Autosave Preferences ') - frameWinSize=Frame(frame,borderwidth=2,relief=GROOVE) - frameParaSize=Frame(frame,borderwidth=2,relief=GROOVE) - frameHelp=LabelFrame(frame,borderwidth=2,relief=GROOVE, - text=' Additional Help Sources ') + frameRun = LabelFrame(frame, borderwidth=2, relief=GROOVE, + text=' Startup Preferences ') + frameSave = LabelFrame(frame, borderwidth=2, relief=GROOVE, + text=' Autosave Preferences ') + frameWinSize = Frame(frame, borderwidth=2, relief=GROOVE) + frameParaSize = Frame(frame, borderwidth=2, relief=GROOVE) + frameHelp = LabelFrame(frame, borderwidth=2, relief=GROOVE, + text=' Additional Help Sources ') #frameRun - labelRunChoiceTitle=Label(frameRun,text='At Startup') - radioStartupEdit=Radiobutton(frameRun,variable=self.startupEdit, - value=1,command=self.SetKeysType,text="Open Edit Window") - radioStartupShell=Radiobutton(frameRun,variable=self.startupEdit, - value=0,command=self.SetKeysType,text='Open Shell Window') + labelRunChoiceTitle = Label(frameRun, text='At Startup') + radioStartupEdit = Radiobutton( + frameRun, variable=self.startupEdit, value=1, + command=self.SetKeysType, text="Open Edit Window") + radioStartupShell = Radiobutton( + frameRun, variable=self.startupEdit, value=0, + command=self.SetKeysType, text='Open Shell Window') #frameSave - labelRunSaveTitle=Label(frameSave,text='At Start of Run (F5) ') - radioSaveAsk=Radiobutton(frameSave,variable=self.autoSave, - value=0,command=self.SetKeysType,text="Prompt to Save") - radioSaveAuto=Radiobutton(frameSave,variable=self.autoSave, - value=1,command=self.SetKeysType,text='No Prompt') + labelRunSaveTitle = Label(frameSave, text='At Start of Run (F5) ') + radioSaveAsk = Radiobutton( + frameSave, variable=self.autoSave, value=0, + command=self.SetKeysType, text="Prompt to Save") + radioSaveAuto = Radiobutton( + frameSave, variable=self.autoSave, value=1, + command=self.SetKeysType, text='No Prompt') #frameWinSize - labelWinSizeTitle=Label(frameWinSize,text='Initial Window Size'+ - ' (in characters)') - labelWinWidthTitle=Label(frameWinSize,text='Width') - entryWinWidth=Entry(frameWinSize,textvariable=self.winWidth, - width=3) - labelWinHeightTitle=Label(frameWinSize,text='Height') - entryWinHeight=Entry(frameWinSize,textvariable=self.winHeight, - width=3) + labelWinSizeTitle = Label( + frameWinSize, text='Initial Window Size (in characters)') + labelWinWidthTitle = Label(frameWinSize, text='Width') + entryWinWidth = Entry( + frameWinSize, textvariable=self.winWidth, width=3) + labelWinHeightTitle = Label(frameWinSize, text='Height') + entryWinHeight = Entry( + frameWinSize, textvariable=self.winHeight, width=3) #paragraphFormatWidth - labelParaWidthTitle=Label(frameParaSize,text='Paragraph reformat'+ - ' width (in characters)') - entryParaWidth=Entry(frameParaSize,textvariable=self.paraWidth, - width=3) + labelParaWidthTitle = Label( + frameParaSize, text='Paragraph reformat width (in characters)') + entryParaWidth = Entry( + frameParaSize, textvariable=self.paraWidth, width=3) #frameHelp - frameHelpList=Frame(frameHelp) - frameHelpListButtons=Frame(frameHelpList) - scrollHelpList=Scrollbar(frameHelpList) - self.listHelp=Listbox(frameHelpList,height=5,takefocus=FALSE, + frameHelpList = Frame(frameHelp) + frameHelpListButtons = Frame(frameHelpList) + scrollHelpList = Scrollbar(frameHelpList) + self.listHelp = Listbox( + frameHelpList, height=5, takefocus=FALSE, exportselection=FALSE) scrollHelpList.config(command=self.listHelp.yview) self.listHelp.config(yscrollcommand=scrollHelpList.set) - self.listHelp.bind('',self.HelpSourceSelected) - self.buttonHelpListEdit=Button(frameHelpListButtons,text='Edit', - state=DISABLED,width=8,command=self.HelpListItemEdit) - self.buttonHelpListAdd=Button(frameHelpListButtons,text='Add', - width=8,command=self.HelpListItemAdd) - self.buttonHelpListRemove=Button(frameHelpListButtons,text='Remove', - state=DISABLED,width=8,command=self.HelpListItemRemove) + self.listHelp.bind('', self.HelpSourceSelected) + self.buttonHelpListEdit = Button( + frameHelpListButtons, text='Edit', state=DISABLED, + width=8, command=self.HelpListItemEdit) + self.buttonHelpListAdd = Button( + frameHelpListButtons, text='Add', + width=8, command=self.HelpListItemAdd) + self.buttonHelpListRemove = Button( + frameHelpListButtons, text='Remove', state=DISABLED, + width=8, command=self.HelpListItemRemove) #widget packing #body - frameRun.pack(side=TOP,padx=5,pady=5,fill=X) - frameSave.pack(side=TOP,padx=5,pady=5,fill=X) - frameWinSize.pack(side=TOP,padx=5,pady=5,fill=X) - frameParaSize.pack(side=TOP,padx=5,pady=5,fill=X) - frameHelp.pack(side=TOP,padx=5,pady=5,expand=TRUE,fill=BOTH) + frameRun.pack(side=TOP, padx=5, pady=5, fill=X) + frameSave.pack(side=TOP, padx=5, pady=5, fill=X) + frameWinSize.pack(side=TOP, padx=5, pady=5, fill=X) + frameParaSize.pack(side=TOP, padx=5, pady=5, fill=X) + frameHelp.pack(side=TOP, padx=5, pady=5, expand=TRUE, fill=BOTH) #frameRun - labelRunChoiceTitle.pack(side=LEFT,anchor=W,padx=5,pady=5) - radioStartupShell.pack(side=RIGHT,anchor=W,padx=5,pady=5) - radioStartupEdit.pack(side=RIGHT,anchor=W,padx=5,pady=5) + labelRunChoiceTitle.pack(side=LEFT, anchor=W, padx=5, pady=5) + radioStartupShell.pack(side=RIGHT, anchor=W, padx=5, pady=5) + radioStartupEdit.pack(side=RIGHT, anchor=W, padx=5, pady=5) #frameSave - labelRunSaveTitle.pack(side=LEFT,anchor=W,padx=5,pady=5) - radioSaveAuto.pack(side=RIGHT,anchor=W,padx=5,pady=5) - radioSaveAsk.pack(side=RIGHT,anchor=W,padx=5,pady=5) + labelRunSaveTitle.pack(side=LEFT, anchor=W, padx=5, pady=5) + radioSaveAuto.pack(side=RIGHT, anchor=W, padx=5, pady=5) + radioSaveAsk.pack(side=RIGHT, anchor=W, padx=5, pady=5) #frameWinSize - labelWinSizeTitle.pack(side=LEFT,anchor=W,padx=5,pady=5) - entryWinHeight.pack(side=RIGHT,anchor=E,padx=10,pady=5) - labelWinHeightTitle.pack(side=RIGHT,anchor=E,pady=5) - entryWinWidth.pack(side=RIGHT,anchor=E,padx=10,pady=5) - labelWinWidthTitle.pack(side=RIGHT,anchor=E,pady=5) + labelWinSizeTitle.pack(side=LEFT, anchor=W, padx=5, pady=5) + entryWinHeight.pack(side=RIGHT, anchor=E, padx=10, pady=5) + labelWinHeightTitle.pack(side=RIGHT, anchor=E, pady=5) + entryWinWidth.pack(side=RIGHT, anchor=E, padx=10, pady=5) + labelWinWidthTitle.pack(side=RIGHT, anchor=E, pady=5) #paragraphFormatWidth - labelParaWidthTitle.pack(side=LEFT,anchor=W,padx=5,pady=5) - entryParaWidth.pack(side=RIGHT,anchor=E,padx=10,pady=5) + labelParaWidthTitle.pack(side=LEFT, anchor=W, padx=5, pady=5) + entryParaWidth.pack(side=RIGHT, anchor=E, padx=10, pady=5) #frameHelp - frameHelpListButtons.pack(side=RIGHT,padx=5,pady=5,fill=Y) - frameHelpList.pack(side=TOP,padx=5,pady=5,expand=TRUE,fill=BOTH) - scrollHelpList.pack(side=RIGHT,anchor=W,fill=Y) - self.listHelp.pack(side=LEFT,anchor=E,expand=TRUE,fill=BOTH) - self.buttonHelpListEdit.pack(side=TOP,anchor=W,pady=5) - self.buttonHelpListAdd.pack(side=TOP,anchor=W) - self.buttonHelpListRemove.pack(side=TOP,anchor=W,pady=5) + frameHelpListButtons.pack(side=RIGHT, padx=5, pady=5, fill=Y) + frameHelpList.pack(side=TOP, padx=5, pady=5, expand=TRUE, fill=BOTH) + scrollHelpList.pack(side=RIGHT, anchor=W, fill=Y) + self.listHelp.pack(side=LEFT, anchor=E, expand=TRUE, fill=BOTH) + self.buttonHelpListEdit.pack(side=TOP, anchor=W, pady=5) + self.buttonHelpListAdd.pack(side=TOP, anchor=W) + self.buttonHelpListRemove.pack(side=TOP, anchor=W, pady=5) return frame def AttachVarCallbacks(self): - self.fontSize.trace_variable('w',self.VarChanged_fontSize) - self.fontName.trace_variable('w',self.VarChanged_fontName) - self.fontBold.trace_variable('w',self.VarChanged_fontBold) - self.spaceNum.trace_variable('w',self.VarChanged_spaceNum) - self.colour.trace_variable('w',self.VarChanged_colour) - self.builtinTheme.trace_variable('w',self.VarChanged_builtinTheme) - self.customTheme.trace_variable('w',self.VarChanged_customTheme) - self.themeIsBuiltin.trace_variable('w',self.VarChanged_themeIsBuiltin) - self.highlightTarget.trace_variable('w',self.VarChanged_highlightTarget) - self.keyBinding.trace_variable('w',self.VarChanged_keyBinding) - self.builtinKeys.trace_variable('w',self.VarChanged_builtinKeys) - self.customKeys.trace_variable('w',self.VarChanged_customKeys) - self.keysAreBuiltin.trace_variable('w',self.VarChanged_keysAreBuiltin) - self.winWidth.trace_variable('w',self.VarChanged_winWidth) - self.winHeight.trace_variable('w',self.VarChanged_winHeight) - self.paraWidth.trace_variable('w',self.VarChanged_paraWidth) - self.startupEdit.trace_variable('w',self.VarChanged_startupEdit) - self.autoSave.trace_variable('w',self.VarChanged_autoSave) - self.encoding.trace_variable('w',self.VarChanged_encoding) + self.fontSize.trace_variable('w', self.VarChanged_fontSize) + self.fontName.trace_variable('w', self.VarChanged_fontName) + self.fontBold.trace_variable('w', self.VarChanged_fontBold) + self.spaceNum.trace_variable('w', self.VarChanged_spaceNum) + self.colour.trace_variable('w', self.VarChanged_colour) + self.builtinTheme.trace_variable('w', self.VarChanged_builtinTheme) + self.customTheme.trace_variable('w', self.VarChanged_customTheme) + self.themeIsBuiltin.trace_variable('w', self.VarChanged_themeIsBuiltin) + self.highlightTarget.trace_variable('w', self.VarChanged_highlightTarget) + self.keyBinding.trace_variable('w', self.VarChanged_keyBinding) + self.builtinKeys.trace_variable('w', self.VarChanged_builtinKeys) + self.customKeys.trace_variable('w', self.VarChanged_customKeys) + self.keysAreBuiltin.trace_variable('w', self.VarChanged_keysAreBuiltin) + self.winWidth.trace_variable('w', self.VarChanged_winWidth) + self.winHeight.trace_variable('w', self.VarChanged_winHeight) + self.paraWidth.trace_variable('w', self.VarChanged_paraWidth) + self.startupEdit.trace_variable('w', self.VarChanged_startupEdit) + self.autoSave.trace_variable('w', self.VarChanged_autoSave) + self.encoding.trace_variable('w', self.VarChanged_encoding) - def VarChanged_fontSize(self,*params): - value=self.fontSize.get() - self.AddChangedItem('main','EditorWindow','font-size',value) + def VarChanged_fontSize(self, *params): + value = self.fontSize.get() + self.AddChangedItem('main', 'EditorWindow', 'font-size', value) - def VarChanged_fontName(self,*params): - value=self.fontName.get() - self.AddChangedItem('main','EditorWindow','font',value) + def VarChanged_fontName(self, *params): + value = self.fontName.get() + self.AddChangedItem('main', 'EditorWindow', 'font', value) - def VarChanged_fontBold(self,*params): - value=self.fontBold.get() - self.AddChangedItem('main','EditorWindow','font-bold',value) + def VarChanged_fontBold(self, *params): + value = self.fontBold.get() + self.AddChangedItem('main', 'EditorWindow', 'font-bold', value) - def VarChanged_spaceNum(self,*params): - value=self.spaceNum.get() - self.AddChangedItem('main','Indent','num-spaces',value) + def VarChanged_spaceNum(self, *params): + value = self.spaceNum.get() + self.AddChangedItem('main', 'Indent', 'num-spaces', value) - def VarChanged_colour(self,*params): + def VarChanged_colour(self, *params): self.OnNewColourSet() - def VarChanged_builtinTheme(self,*params): - value=self.builtinTheme.get() - self.AddChangedItem('main','Theme','name',value) + def VarChanged_builtinTheme(self, *params): + value = self.builtinTheme.get() + self.AddChangedItem('main', 'Theme', 'name', value) self.PaintThemeSample() - def VarChanged_customTheme(self,*params): - value=self.customTheme.get() + def VarChanged_customTheme(self, *params): + value = self.customTheme.get() if value != '- no custom themes -': - self.AddChangedItem('main','Theme','name',value) + self.AddChangedItem('main', 'Theme', 'name', value) self.PaintThemeSample() - def VarChanged_themeIsBuiltin(self,*params): - value=self.themeIsBuiltin.get() - self.AddChangedItem('main','Theme','default',value) + def VarChanged_themeIsBuiltin(self, *params): + value = self.themeIsBuiltin.get() + self.AddChangedItem('main', 'Theme', 'default', value) if value: self.VarChanged_builtinTheme() else: self.VarChanged_customTheme() - def VarChanged_highlightTarget(self,*params): + def VarChanged_highlightTarget(self, *params): self.SetHighlightTarget() - def VarChanged_keyBinding(self,*params): - value=self.keyBinding.get() - keySet=self.customKeys.get() - event=self.listBindings.get(ANCHOR).split()[0] + def VarChanged_keyBinding(self, *params): + value = self.keyBinding.get() + keySet = self.customKeys.get() + event = self.listBindings.get(ANCHOR).split()[0] if idleConf.IsCoreBinding(event): #this is a core keybinding - self.AddChangedItem('keys',keySet,event,value) + self.AddChangedItem('keys', keySet, event, value) else: #this is an extension key binding - extName=idleConf.GetExtnNameForEvent(event) - extKeybindSection=extName+'_cfgBindings' - self.AddChangedItem('extensions',extKeybindSection,event,value) + extName = idleConf.GetExtnNameForEvent(event) + extKeybindSection = extName + '_cfgBindings' + self.AddChangedItem('extensions', extKeybindSection, event, value) - def VarChanged_builtinKeys(self,*params): - value=self.builtinKeys.get() - self.AddChangedItem('main','Keys','name',value) + def VarChanged_builtinKeys(self, *params): + value = self.builtinKeys.get() + self.AddChangedItem('main', 'Keys', 'name', value) self.LoadKeysList(value) - def VarChanged_customKeys(self,*params): - value=self.customKeys.get() + def VarChanged_customKeys(self, *params): + value = self.customKeys.get() if value != '- no custom keys -': - self.AddChangedItem('main','Keys','name',value) + self.AddChangedItem('main', 'Keys', 'name', value) self.LoadKeysList(value) - def VarChanged_keysAreBuiltin(self,*params): - value=self.keysAreBuiltin.get() - self.AddChangedItem('main','Keys','default',value) + def VarChanged_keysAreBuiltin(self, *params): + value = self.keysAreBuiltin.get() + self.AddChangedItem('main', 'Keys', 'default', value) if value: self.VarChanged_builtinKeys() else: self.VarChanged_customKeys() - def VarChanged_winWidth(self,*params): - value=self.winWidth.get() - self.AddChangedItem('main','EditorWindow','width',value) + def VarChanged_winWidth(self, *params): + value = self.winWidth.get() + self.AddChangedItem('main', 'EditorWindow', 'width', value) - def VarChanged_winHeight(self,*params): - value=self.winHeight.get() - self.AddChangedItem('main','EditorWindow','height',value) + def VarChanged_winHeight(self, *params): + value = self.winHeight.get() + self.AddChangedItem('main', 'EditorWindow', 'height', value) - def VarChanged_paraWidth(self,*params): - value=self.paraWidth.get() - self.AddChangedItem('main','FormatParagraph','paragraph',value) + def VarChanged_paraWidth(self, *params): + value = self.paraWidth.get() + self.AddChangedItem('main', 'FormatParagraph', 'paragraph', value) - def VarChanged_startupEdit(self,*params): - value=self.startupEdit.get() - self.AddChangedItem('main','General','editor-on-startup',value) + def VarChanged_startupEdit(self, *params): + value = self.startupEdit.get() + self.AddChangedItem('main', 'General', 'editor-on-startup', value) - def VarChanged_autoSave(self,*params): - value=self.autoSave.get() - self.AddChangedItem('main','General','autosave',value) + def VarChanged_autoSave(self, *params): + value = self.autoSave.get() + self.AddChangedItem('main', 'General', 'autosave', value) - def VarChanged_encoding(self,*params): - value=self.encoding.get() - self.AddChangedItem('main','EditorWindow','encoding',value) + def VarChanged_encoding(self, *params): + value = self.encoding.get() + self.AddChangedItem('main', 'EditorWindow', 'encoding', value) def ResetChangedItems(self): #When any config item is changed in this dialog, an entry @@ -561,24 +596,25 @@ #dictionary. The key should be the config file section name and the #value a dictionary, whose key:value pairs are item=value pairs for #that config file section. - self.changedItems={'main':{},'highlight':{},'keys':{},'extensions':{}} + self.changedItems = {'main':{}, 'highlight':{}, 'keys':{}, + 'extensions':{}} - def AddChangedItem(self,type,section,item,value): - value=str(value) #make sure we use a string - if section not in self.changedItems[type]: - self.changedItems[type][section]={} - self.changedItems[type][section][item]=value + def AddChangedItem(self, typ, section, item, value): + value = str(value) #make sure we use a string + if section not in self.changedItems[typ]: + self.changedItems[typ][section] = {} + self.changedItems[typ][section][item] = value def GetDefaultItems(self): - dItems={'main':{},'highlight':{},'keys':{},'extensions':{}} + dItems={'main':{}, 'highlight':{}, 'keys':{}, 'extensions':{}} for configType in dItems: - sections=idleConf.GetSectionList('default',configType) + sections = idleConf.GetSectionList('default', configType) for section in sections: - dItems[configType][section]={} - options=idleConf.defaultCfg[configType].GetOptionList(section) + dItems[configType][section] = {} + options = idleConf.defaultCfg[configType].GetOptionList(section) for option in options: - dItems[configType][section][option]=( - idleConf.defaultCfg[configType].Get(section,option)) + dItems[configType][section][option] = ( + idleConf.defaultCfg[configType].Get(section, option)) return dItems def SetThemeType(self): @@ -604,26 +640,26 @@ self.buttonDeleteCustomKeys.config(state=NORMAL) def GetNewKeys(self): - listIndex=self.listBindings.index(ANCHOR) - binding=self.listBindings.get(listIndex) - bindName=binding.split()[0] #first part, up to first space + listIndex = self.listBindings.index(ANCHOR) + binding = self.listBindings.get(listIndex) + bindName = binding.split()[0] #first part, up to first space if self.keysAreBuiltin.get(): - currentKeySetName=self.builtinKeys.get() + currentKeySetName = self.builtinKeys.get() else: - currentKeySetName=self.customKeys.get() - currentBindings=idleConf.GetCurrentKeySet() + currentKeySetName = self.customKeys.get() + currentBindings = idleConf.GetCurrentKeySet() if currentKeySetName in self.changedItems['keys']: #unsaved changes - keySetChanges=self.changedItems['keys'][currentKeySetName] + keySetChanges = self.changedItems['keys'][currentKeySetName] for event in keySetChanges: - currentBindings[event]=keySetChanges[event].split() + currentBindings[event] = keySetChanges[event].split() currentKeySequences = list(currentBindings.values()) - newKeys=GetKeysDialog(self,'Get New Keys',bindName, + newKeys = GetKeysDialog(self, 'Get New Keys', bindName, currentKeySequences).result if newKeys: #new keys were specified if self.keysAreBuiltin.get(): #current key set is a built-in - message=('Your changes will be saved as a new Custom Key Set. '+ - 'Enter a name for your new Custom Key Set below.') - newKeySet=self.GetNewKeysName(message) + message = ('Your changes will be saved as a new Custom Key Set.' + ' Enter a name for your new Custom Key Set below.') + newKeySet = self.GetNewKeysName(message) if not newKeySet: #user cancelled custom key set creation self.listBindings.select_set(listIndex) self.listBindings.select_anchor(listIndex) @@ -631,7 +667,7 @@ else: #create new custom key set based on previously active key set self.CreateNewKeySet(newKeySet) self.listBindings.delete(listIndex) - self.listBindings.insert(listIndex,bindName+' - '+newKeys) + self.listBindings.insert(listIndex, bindName+' - '+newKeys) self.listBindings.select_set(listIndex) self.listBindings.select_anchor(listIndex) self.keyBinding.set(newKeys) @@ -639,65 +675,65 @@ self.listBindings.select_set(listIndex) self.listBindings.select_anchor(listIndex) - def GetNewKeysName(self,message): - usedNames=(idleConf.GetSectionList('user','keys')+ - idleConf.GetSectionList('default','keys')) - newKeySet=GetCfgSectionNameDialog(self,'New Custom Key Set', - message,usedNames).result + def GetNewKeysName(self, message): + usedNames = (idleConf.GetSectionList('user', 'keys') + + idleConf.GetSectionList('default', 'keys')) + newKeySet = GetCfgSectionNameDialog( + self, 'New Custom Key Set', message, usedNames).result return newKeySet def SaveAsNewKeySet(self): - newKeysName=self.GetNewKeysName('New Key Set Name:') + newKeysName = self.GetNewKeysName('New Key Set Name:') if newKeysName: self.CreateNewKeySet(newKeysName) - def KeyBindingSelected(self,event): + def KeyBindingSelected(self, event): self.buttonNewKeys.config(state=NORMAL) - def CreateNewKeySet(self,newKeySetName): + def CreateNewKeySet(self, newKeySetName): #creates new custom key set based on the previously active key set, #and makes the new key set active if self.keysAreBuiltin.get(): - prevKeySetName=self.builtinKeys.get() + prevKeySetName = self.builtinKeys.get() else: - prevKeySetName=self.customKeys.get() - prevKeys=idleConf.GetCoreKeys(prevKeySetName) - newKeys={} + prevKeySetName = self.customKeys.get() + prevKeys = idleConf.GetCoreKeys(prevKeySetName) + newKeys = {} for event in prevKeys: #add key set to changed items - eventName=event[2:-2] #trim off the angle brackets - binding=' '.join(prevKeys[event]) - newKeys[eventName]=binding + eventName = event[2:-2] #trim off the angle brackets + binding = ' '.join(prevKeys[event]) + newKeys[eventName] = binding #handle any unsaved changes to prev key set if prevKeySetName in self.changedItems['keys']: - keySetChanges=self.changedItems['keys'][prevKeySetName] + keySetChanges = self.changedItems['keys'][prevKeySetName] for event in keySetChanges: - newKeys[event]=keySetChanges[event] + newKeys[event] = keySetChanges[event] #save the new theme - self.SaveNewKeySet(newKeySetName,newKeys) + self.SaveNewKeySet(newKeySetName, newKeys) #change gui over to the new key set - customKeyList=idleConf.GetSectionList('user','keys') + customKeyList = idleConf.GetSectionList('user', 'keys') customKeyList.sort() - self.optMenuKeysCustom.SetMenu(customKeyList,newKeySetName) + self.optMenuKeysCustom.SetMenu(customKeyList, newKeySetName) self.keysAreBuiltin.set(0) self.SetKeysType() - def LoadKeysList(self,keySetName): - reselect=0 - newKeySet=0 + def LoadKeysList(self, keySetName): + reselect = 0 + newKeySet = 0 if self.listBindings.curselection(): - reselect=1 - listIndex=self.listBindings.index(ANCHOR) - keySet=idleConf.GetKeySet(keySetName) + reselect = 1 + listIndex = self.listBindings.index(ANCHOR) + keySet = idleConf.GetKeySet(keySetName) bindNames = list(keySet.keys()) bindNames.sort() - self.listBindings.delete(0,END) + self.listBindings.delete(0, END) for bindName in bindNames: - key=' '.join(keySet[bindName]) #make key(s) into a string - bindName=bindName[2:-2] #trim off the angle brackets + key = ' '.join(keySet[bindName]) #make key(s) into a string + bindName = bindName[2:-2] #trim off the angle brackets if keySetName in self.changedItems['keys']: #handle any unsaved changes to this key set if bindName in self.changedItems['keys'][keySetName]: - key=self.changedItems['keys'][keySetName][bindName] + key = self.changedItems['keys'][keySetName][bindName] self.listBindings.insert(END, bindName+' - '+key) if reselect: self.listBindings.see(listIndex) @@ -706,9 +742,9 @@ def DeleteCustomKeys(self): keySetName=self.customKeys.get() - if not tkMessageBox.askyesno('Delete Key Set','Are you sure you wish '+ - 'to delete the key set %r ?' % (keySetName), - parent=self): + delmsg = 'Are you sure you wish to delete the key set %r ?' + if not tkMessageBox.askyesno( + 'Delete Key Set', delmsg % keySetName, parent=self): return #remove key set from config idleConf.userCfg['keys'].remove_section(keySetName) @@ -717,25 +753,25 @@ #write changes idleConf.userCfg['keys'].Save() #reload user key set list - itemList=idleConf.GetSectionList('user','keys') + itemList = idleConf.GetSectionList('user', 'keys') itemList.sort() if not itemList: self.radioKeysCustom.config(state=DISABLED) - self.optMenuKeysCustom.SetMenu(itemList,'- no custom keys -') + self.optMenuKeysCustom.SetMenu(itemList, '- no custom keys -') else: - self.optMenuKeysCustom.SetMenu(itemList,itemList[0]) + self.optMenuKeysCustom.SetMenu(itemList, itemList[0]) #revert to default key set - self.keysAreBuiltin.set(idleConf.defaultCfg['main'].Get('Keys','default')) - self.builtinKeys.set(idleConf.defaultCfg['main'].Get('Keys','name')) + self.keysAreBuiltin.set(idleConf.defaultCfg['main'].Get('Keys', 'default')) + self.builtinKeys.set(idleConf.defaultCfg['main'].Get('Keys', 'name')) #user can't back out of these changes, they must be applied now self.Apply() self.SetKeysType() def DeleteCustomTheme(self): - themeName=self.customTheme.get() - if not tkMessageBox.askyesno('Delete Theme','Are you sure you wish '+ - 'to delete the theme %r ?' % (themeName,), - parent=self): + themeName = self.customTheme.get() + delmsg = 'Are you sure you wish to delete the theme %r ?' + if not tkMessageBox.askyesno( + 'Delete Theme', delmsg % themeName, parent=self): return #remove theme from config idleConf.userCfg['highlight'].remove_section(themeName) @@ -744,153 +780,149 @@ #write changes idleConf.userCfg['highlight'].Save() #reload user theme list - itemList=idleConf.GetSectionList('user','highlight') + itemList = idleConf.GetSectionList('user', 'highlight') itemList.sort() if not itemList: self.radioThemeCustom.config(state=DISABLED) - self.optMenuThemeCustom.SetMenu(itemList,'- no custom themes -') + self.optMenuThemeCustom.SetMenu(itemList, '- no custom themes -') else: - self.optMenuThemeCustom.SetMenu(itemList,itemList[0]) + self.optMenuThemeCustom.SetMenu(itemList, itemList[0]) #revert to default theme - self.themeIsBuiltin.set(idleConf.defaultCfg['main'].Get('Theme','default')) - self.builtinTheme.set(idleConf.defaultCfg['main'].Get('Theme','name')) + self.themeIsBuiltin.set(idleConf.defaultCfg['main'].Get('Theme', 'default')) + self.builtinTheme.set(idleConf.defaultCfg['main'].Get('Theme', 'name')) #user can't back out of these changes, they must be applied now self.Apply() self.SetThemeType() def GetColour(self): - target=self.highlightTarget.get() - prevColour=self.frameColourSet.cget('bg') - rgbTuplet, colourString = tkColorChooser.askcolor(parent=self, - title='Pick new colour for : '+target,initialcolor=prevColour) - if colourString and (colourString!=prevColour): + target = self.highlightTarget.get() + prevColour = self.frameColourSet.cget('bg') + rgbTuplet, colourString = tkColorChooser.askcolor( + parent=self, title='Pick new colour for : '+target, + initialcolor=prevColour) + if colourString and (colourString != prevColour): #user didn't cancel, and they chose a new colour - if self.themeIsBuiltin.get(): #current theme is a built-in - message=('Your changes will be saved as a new Custom Theme. '+ - 'Enter a name for your new Custom Theme below.') - newTheme=self.GetNewThemeName(message) - if not newTheme: #user cancelled custom theme creation + if self.themeIsBuiltin.get(): #current theme is a built-in + message = ('Your changes will be saved as a new Custom Theme. ' + 'Enter a name for your new Custom Theme below.') + newTheme = self.GetNewThemeName(message) + if not newTheme: #user cancelled custom theme creation return - else: #create new custom theme based on previously active theme + else: #create new custom theme based on previously active theme self.CreateNewTheme(newTheme) self.colour.set(colourString) - else: #current theme is user defined + else: #current theme is user defined self.colour.set(colourString) def OnNewColourSet(self): newColour=self.colour.get() - self.frameColourSet.config(bg=newColour)#set sample - if self.fgHilite.get(): plane='foreground' - else: plane='background' - sampleElement=self.themeElements[self.highlightTarget.get()][0] + self.frameColourSet.config(bg=newColour) #set sample + plane ='foreground' if self.fgHilite.get() else 'background' + sampleElement = self.themeElements[self.highlightTarget.get()][0] self.textHighlightSample.tag_config(sampleElement, **{plane:newColour}) - theme=self.customTheme.get() - themeElement=sampleElement+'-'+plane - self.AddChangedItem('highlight',theme,themeElement,newColour) + theme = self.customTheme.get() + themeElement = sampleElement + '-' + plane + self.AddChangedItem('highlight', theme, themeElement, newColour) - def GetNewThemeName(self,message): - usedNames=(idleConf.GetSectionList('user','highlight')+ - idleConf.GetSectionList('default','highlight')) - newTheme=GetCfgSectionNameDialog(self,'New Custom Theme', - message,usedNames).result + def GetNewThemeName(self, message): + usedNames = (idleConf.GetSectionList('user', 'highlight') + + idleConf.GetSectionList('default', 'highlight')) + newTheme = GetCfgSectionNameDialog( + self, 'New Custom Theme', message, usedNames).result return newTheme def SaveAsNewTheme(self): - newThemeName=self.GetNewThemeName('New Theme Name:') + newThemeName = self.GetNewThemeName('New Theme Name:') if newThemeName: self.CreateNewTheme(newThemeName) - def CreateNewTheme(self,newThemeName): + def CreateNewTheme(self, newThemeName): #creates new custom theme based on the previously active theme, #and makes the new theme active if self.themeIsBuiltin.get(): - themeType='default' - themeName=self.builtinTheme.get() + themeType = 'default' + themeName = self.builtinTheme.get() else: - themeType='user' - themeName=self.customTheme.get() - newTheme=idleConf.GetThemeDict(themeType,themeName) + themeType = 'user' + themeName = self.customTheme.get() + newTheme = idleConf.GetThemeDict(themeType, themeName) #apply any of the old theme's unsaved changes to the new theme if themeName in self.changedItems['highlight']: - themeChanges=self.changedItems['highlight'][themeName] + themeChanges = self.changedItems['highlight'][themeName] for element in themeChanges: - newTheme[element]=themeChanges[element] + newTheme[element] = themeChanges[element] #save the new theme - self.SaveNewTheme(newThemeName,newTheme) + self.SaveNewTheme(newThemeName, newTheme) #change gui over to the new theme - customThemeList=idleConf.GetSectionList('user','highlight') + customThemeList = idleConf.GetSectionList('user', 'highlight') customThemeList.sort() - self.optMenuThemeCustom.SetMenu(customThemeList,newThemeName) + self.optMenuThemeCustom.SetMenu(customThemeList, newThemeName) self.themeIsBuiltin.set(0) self.SetThemeType() - def OnListFontButtonRelease(self,event): + def OnListFontButtonRelease(self, event): font = self.listFontName.get(ANCHOR) self.fontName.set(font.lower()) self.SetFontSample() - def SetFontSample(self,event=None): - fontName=self.fontName.get() - if self.fontBold.get(): - fontWeight=tkFont.BOLD - else: - fontWeight=tkFont.NORMAL + def SetFontSample(self, event=None): + fontName = self.fontName.get() + fontWeight = tkFont.BOLD if self.fontBold.get() else tkFont.NORMAL newFont = (fontName, self.fontSize.get(), fontWeight) self.labelFontSample.config(font=newFont) self.textHighlightSample.configure(font=newFont) def SetHighlightTarget(self): - if self.highlightTarget.get()=='Cursor': #bg not possible + if self.highlightTarget.get() == 'Cursor': #bg not possible self.radioFg.config(state=DISABLED) self.radioBg.config(state=DISABLED) self.fgHilite.set(1) - else: #both fg and bg can be set + else: #both fg and bg can be set self.radioFg.config(state=NORMAL) self.radioBg.config(state=NORMAL) self.fgHilite.set(1) self.SetColourSample() - def SetColourSampleBinding(self,*args): + def SetColourSampleBinding(self, *args): self.SetColourSample() def SetColourSample(self): #set the colour smaple area - tag=self.themeElements[self.highlightTarget.get()][0] - if self.fgHilite.get(): plane='foreground' - else: plane='background' - colour=self.textHighlightSample.tag_cget(tag,plane) + tag = self.themeElements[self.highlightTarget.get()][0] + plane = 'foreground' if self.fgHilite.get() else 'background' + colour = self.textHighlightSample.tag_cget(tag, plane) self.frameColourSet.config(bg=colour) def PaintThemeSample(self): - if self.themeIsBuiltin.get(): #a default theme - theme=self.builtinTheme.get() - else: #a user theme - theme=self.customTheme.get() + if self.themeIsBuiltin.get(): #a default theme + theme = self.builtinTheme.get() + else: #a user theme + theme = self.customTheme.get() for elementTitle in self.themeElements: - element=self.themeElements[elementTitle][0] - colours=idleConf.GetHighlight(theme,element) - if element=='cursor': #cursor sample needs special painting - colours['background']=idleConf.GetHighlight(theme, - 'normal', fgBg='bg') + element = self.themeElements[elementTitle][0] + colours = idleConf.GetHighlight(theme, element) + if element == 'cursor': #cursor sample needs special painting + colours['background'] = idleConf.GetHighlight( + theme, 'normal', fgBg='bg') #handle any unsaved changes to this theme if theme in self.changedItems['highlight']: - themeDict=self.changedItems['highlight'][theme] - if element+'-foreground' in themeDict: - colours['foreground']=themeDict[element+'-foreground'] - if element+'-background' in themeDict: - colours['background']=themeDict[element+'-background'] + themeDict = self.changedItems['highlight'][theme] + if element + '-foreground' in themeDict: + colours['foreground'] = themeDict[element + '-foreground'] + if element + '-background' in themeDict: + colours['background'] = themeDict[element + '-background'] self.textHighlightSample.tag_config(element, **colours) self.SetColourSample() - def HelpSourceSelected(self,event): + def HelpSourceSelected(self, event): self.SetHelpListButtonStates() def SetHelpListButtonStates(self): - if self.listHelp.size()<1: #no entries in list + if self.listHelp.size() < 1: #no entries in list self.buttonHelpListEdit.config(state=DISABLED) self.buttonHelpListRemove.config(state=DISABLED) else: #there are some entries - if self.listHelp.curselection(): #there currently is a selection + if self.listHelp.curselection(): #there currently is a selection self.buttonHelpListEdit.config(state=NORMAL) self.buttonHelpListRemove.config(state=NORMAL) else: #there currently is not a selection @@ -898,28 +930,29 @@ self.buttonHelpListRemove.config(state=DISABLED) def HelpListItemAdd(self): - helpSource=GetHelpSourceDialog(self,'New Help Source').result + helpSource = GetHelpSourceDialog(self, 'New Help Source').result if helpSource: - self.userHelpList.append( (helpSource[0],helpSource[1]) ) - self.listHelp.insert(END,helpSource[0]) + self.userHelpList.append((helpSource[0], helpSource[1])) + self.listHelp.insert(END, helpSource[0]) self.UpdateUserHelpChangedItems() self.SetHelpListButtonStates() def HelpListItemEdit(self): - itemIndex=self.listHelp.index(ANCHOR) - helpSource=self.userHelpList[itemIndex] - newHelpSource=GetHelpSourceDialog(self,'Edit Help Source', - menuItem=helpSource[0],filePath=helpSource[1]).result - if (not newHelpSource) or (newHelpSource==helpSource): + itemIndex = self.listHelp.index(ANCHOR) + helpSource = self.userHelpList[itemIndex] + newHelpSource = GetHelpSourceDialog( + self, 'Edit Help Source', menuItem=helpSource[0], + filePath=helpSource[1]).result + if (not newHelpSource) or (newHelpSource == helpSource): return #no changes - self.userHelpList[itemIndex]=newHelpSource + self.userHelpList[itemIndex] = newHelpSource self.listHelp.delete(itemIndex) - self.listHelp.insert(itemIndex,newHelpSource[0]) + self.listHelp.insert(itemIndex, newHelpSource[0]) self.UpdateUserHelpChangedItems() self.SetHelpListButtonStates() def HelpListItemRemove(self): - itemIndex=self.listHelp.index(ANCHOR) + itemIndex = self.listHelp.index(ANCHOR) del(self.userHelpList[itemIndex]) self.listHelp.delete(itemIndex) self.UpdateUserHelpChangedItems() @@ -928,18 +961,19 @@ def UpdateUserHelpChangedItems(self): "Clear and rebuild the HelpFiles section in self.changedItems" self.changedItems['main']['HelpFiles'] = {} - for num in range(1,len(self.userHelpList)+1): - self.AddChangedItem('main','HelpFiles',str(num), + for num in range(1, len(self.userHelpList) + 1): + self.AddChangedItem( + 'main', 'HelpFiles', str(num), ';'.join(self.userHelpList[num-1][:2])) def LoadFontCfg(self): ##base editor font selection list - fonts=list(tkFont.families(self)) + fonts = list(tkFont.families(self)) fonts.sort() for font in fonts: - self.listFontName.insert(END,font) - configuredFont=idleConf.GetOption('main','EditorWindow','font', - default='courier') + self.listFontName.insert(END, font) + configuredFont = idleConf.GetOption( + 'main', 'EditorWindow', 'font', default='courier') lc_configuredFont = configuredFont.lower() self.fontName.set(lc_configuredFont) lc_fonts = [s.lower() for s in fonts] @@ -949,107 +983,107 @@ self.listFontName.select_set(currentFontIndex) self.listFontName.select_anchor(currentFontIndex) ##font size dropdown - fontSize=idleConf.GetOption('main', 'EditorWindow', 'font-size', - type='int', default='10') - self.optMenuFontSize.SetMenu(('7','8','9','10','11','12','13','14', - '16','18','20','22'), fontSize ) + fontSize = idleConf.GetOption( + 'main', 'EditorWindow', 'font-size', type='int', default='10') + self.optMenuFontSize.SetMenu(('7', '8', '9', '10', '11', '12', '13', + '14', '16', '18', '20', '22'), fontSize ) ##fontWeight - self.fontBold.set(idleConf.GetOption('main','EditorWindow', - 'font-bold',default=0,type='bool')) + self.fontBold.set(idleConf.GetOption( + 'main', 'EditorWindow', 'font-bold', default=0, type='bool')) ##font sample self.SetFontSample() def LoadTabCfg(self): ##indent sizes - spaceNum=idleConf.GetOption('main','Indent','num-spaces', - default=4,type='int') + spaceNum = idleConf.GetOption( + 'main', 'Indent', 'num-spaces', default=4, type='int') self.spaceNum.set(spaceNum) def LoadThemeCfg(self): ##current theme type radiobutton - self.themeIsBuiltin.set(idleConf.GetOption('main','Theme','default', - type='bool',default=1)) + self.themeIsBuiltin.set(idleConf.GetOption( + 'main', 'Theme', 'default', type='bool', default=1)) ##currently set theme - currentOption=idleConf.CurrentTheme() + currentOption = idleConf.CurrentTheme() ##load available theme option menus if self.themeIsBuiltin.get(): #default theme selected - itemList=idleConf.GetSectionList('default','highlight') + itemList = idleConf.GetSectionList('default', 'highlight') itemList.sort() - self.optMenuThemeBuiltin.SetMenu(itemList,currentOption) - itemList=idleConf.GetSectionList('user','highlight') + self.optMenuThemeBuiltin.SetMenu(itemList, currentOption) + itemList = idleConf.GetSectionList('user', 'highlight') itemList.sort() if not itemList: self.radioThemeCustom.config(state=DISABLED) self.customTheme.set('- no custom themes -') else: - self.optMenuThemeCustom.SetMenu(itemList,itemList[0]) + self.optMenuThemeCustom.SetMenu(itemList, itemList[0]) else: #user theme selected - itemList=idleConf.GetSectionList('user','highlight') + itemList = idleConf.GetSectionList('user', 'highlight') itemList.sort() - self.optMenuThemeCustom.SetMenu(itemList,currentOption) - itemList=idleConf.GetSectionList('default','highlight') + self.optMenuThemeCustom.SetMenu(itemList, currentOption) + itemList = idleConf.GetSectionList('default', 'highlight') itemList.sort() - self.optMenuThemeBuiltin.SetMenu(itemList,itemList[0]) + self.optMenuThemeBuiltin.SetMenu(itemList, itemList[0]) self.SetThemeType() ##load theme element option menu themeNames = list(self.themeElements.keys()) themeNames.sort(key=lambda x: self.themeElements[x][1]) - self.optMenuHighlightTarget.SetMenu(themeNames,themeNames[0]) + self.optMenuHighlightTarget.SetMenu(themeNames, themeNames[0]) self.PaintThemeSample() self.SetHighlightTarget() def LoadKeyCfg(self): ##current keys type radiobutton - self.keysAreBuiltin.set(idleConf.GetOption('main','Keys','default', - type='bool',default=1)) + self.keysAreBuiltin.set(idleConf.GetOption( + 'main', 'Keys', 'default', type='bool', default=1)) ##currently set keys - currentOption=idleConf.CurrentKeys() + currentOption = idleConf.CurrentKeys() ##load available keyset option menus if self.keysAreBuiltin.get(): #default theme selected - itemList=idleConf.GetSectionList('default','keys') + itemList = idleConf.GetSectionList('default', 'keys') itemList.sort() - self.optMenuKeysBuiltin.SetMenu(itemList,currentOption) - itemList=idleConf.GetSectionList('user','keys') + self.optMenuKeysBuiltin.SetMenu(itemList, currentOption) + itemList = idleConf.GetSectionList('user', 'keys') itemList.sort() if not itemList: self.radioKeysCustom.config(state=DISABLED) self.customKeys.set('- no custom keys -') else: - self.optMenuKeysCustom.SetMenu(itemList,itemList[0]) + self.optMenuKeysCustom.SetMenu(itemList, itemList[0]) else: #user key set selected - itemList=idleConf.GetSectionList('user','keys') + itemList = idleConf.GetSectionList('user', 'keys') itemList.sort() - self.optMenuKeysCustom.SetMenu(itemList,currentOption) - itemList=idleConf.GetSectionList('default','keys') + self.optMenuKeysCustom.SetMenu(itemList, currentOption) + itemList = idleConf.GetSectionList('default', 'keys') itemList.sort() - self.optMenuKeysBuiltin.SetMenu(itemList,itemList[0]) + self.optMenuKeysBuiltin.SetMenu(itemList, itemList[0]) self.SetKeysType() ##load keyset element list - keySetName=idleConf.CurrentKeys() + keySetName = idleConf.CurrentKeys() self.LoadKeysList(keySetName) def LoadGeneralCfg(self): #startup state - self.startupEdit.set(idleConf.GetOption('main','General', - 'editor-on-startup',default=1,type='bool')) + self.startupEdit.set(idleConf.GetOption( + 'main', 'General', 'editor-on-startup', default=1, type='bool')) #autosave state - self.autoSave.set(idleConf.GetOption('main', 'General', 'autosave', - default=0, type='bool')) + self.autoSave.set(idleConf.GetOption( + 'main', 'General', 'autosave', default=0, type='bool')) #initial window size - self.winWidth.set(idleConf.GetOption('main','EditorWindow','width', - type='int')) - self.winHeight.set(idleConf.GetOption('main','EditorWindow','height', - type='int')) + self.winWidth.set(idleConf.GetOption( + 'main', 'EditorWindow', 'width', type='int')) + self.winHeight.set(idleConf.GetOption( + 'main', 'EditorWindow', 'height', type='int')) #initial paragraph reformat size - self.paraWidth.set(idleConf.GetOption('main','FormatParagraph','paragraph', - type='int')) + self.paraWidth.set(idleConf.GetOption( + 'main', 'FormatParagraph', 'paragraph', type='int')) # default source encoding - self.encoding.set(idleConf.GetOption('main', 'EditorWindow', - 'encoding', default='none')) + self.encoding.set(idleConf.GetOption( + 'main', 'EditorWindow', 'encoding', default='none')) # additional help sources self.userHelpList = idleConf.GetAllExtraHelpSourcesList() for helpItem in self.userHelpList: - self.listHelp.insert(END,helpItem[0]) + self.listHelp.insert(END, helpItem[0]) self.SetHelpListButtonStates() def LoadConfigs(self): @@ -1067,7 +1101,7 @@ ### general page self.LoadGeneralCfg() - def SaveNewKeySet(self,keySetName,keySet): + def SaveNewKeySet(self, keySetName, keySet): """ save a newly created core key set. keySetName - string, the name of the new key set @@ -1076,10 +1110,10 @@ if not idleConf.userCfg['keys'].has_section(keySetName): idleConf.userCfg['keys'].add_section(keySetName) for event in keySet: - value=keySet[event] - idleConf.userCfg['keys'].SetOption(keySetName,event,value) + value = keySet[event] + idleConf.userCfg['keys'].SetOption(keySetName, event, value) - def SaveNewTheme(self,themeName,theme): + def SaveNewTheme(self, themeName, theme): """ save a newly created theme. themeName - string, the name of the new theme @@ -1088,16 +1122,16 @@ if not idleConf.userCfg['highlight'].has_section(themeName): idleConf.userCfg['highlight'].add_section(themeName) for element in theme: - value=theme[element] - idleConf.userCfg['highlight'].SetOption(themeName,element,value) + value = theme[element] + idleConf.userCfg['highlight'].SetOption(themeName, element, value) - def SetUserValue(self,configType,section,item,value): - if idleConf.defaultCfg[configType].has_option(section,item): - if idleConf.defaultCfg[configType].Get(section,item)==value: + def SetUserValue(self, configType, section, item, value): + if idleConf.defaultCfg[configType].has_option(section, item): + if idleConf.defaultCfg[configType].Get(section, item) == value: #the setting equals a default setting, remove it from user cfg - return idleConf.userCfg[configType].RemoveOption(section,item) + return idleConf.userCfg[configType].RemoveOption(section, item) #if we got here set the option - return idleConf.userCfg[configType].SetOption(section,item,value) + return idleConf.userCfg[configType].SetOption(section, item, value) def SaveAllChangedConfigs(self): "Save configuration changes to the user config file." @@ -1111,7 +1145,7 @@ cfgTypeHasChanges = True for item in self.changedItems[configType][section]: value = self.changedItems[configType][section][item] - if self.SetUserValue(configType,section,item,value): + if self.SetUserValue(configType, section, item, value): cfgTypeHasChanges = True if cfgTypeHasChanges: idleConf.userCfg[configType].Save() -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Aug 4 05:03:50 2014 From: python-checkins at python.org (terry.reedy) Date: Mon, 4 Aug 2014 05:03:50 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Merge_with_3=2E4?= Message-ID: <3hRP7V685tz7Lnd@mail.python.org> http://hg.python.org/cpython/rev/df83b29309f6 changeset: 91980:df83b29309f6 parent: 91977:a2d01ed713cb parent: 91979:b5466a75e203 user: Terry Jan Reedy date: Sun Aug 03 23:03:16 2014 -0400 summary: Merge with 3.4 files: Lib/idlelib/configDialog.py | 1118 +++++++++++----------- 1 files changed, 576 insertions(+), 542 deletions(-) diff --git a/Lib/idlelib/configDialog.py b/Lib/idlelib/configDialog.py --- a/Lib/idlelib/configDialog.py +++ b/Lib/idlelib/configDialog.py @@ -31,42 +31,44 @@ """ Toplevel.__init__(self, parent) self.parent = parent + if _htest: + parent.instance_dict = {} self.wm_withdraw() self.configure(borderwidth=5) self.title('IDLE Preferences') - if _htest: - parent.instance_dict = {} - self.geometry("+%d+%d" % (parent.winfo_rootx()+20, - parent.winfo_rooty()+(30 if not _htest else 150))) + self.geometry( + "+%d+%d" % (parent.winfo_rootx() + 20, + parent.winfo_rooty() + (30 if not _htest else 150))) #Theme Elements. Each theme element key is its display name. #The first value of the tuple is the sample area tag name. #The second value is the display name list sort index. - self.themeElements={'Normal Text':('normal','00'), - 'Python Keywords':('keyword','01'), - 'Python Definitions':('definition','02'), + self.themeElements={ + 'Normal Text':('normal', '00'), + 'Python Keywords':('keyword', '01'), + 'Python Definitions':('definition', '02'), 'Python Builtins':('builtin', '03'), - 'Python Comments':('comment','04'), - 'Python Strings':('string','05'), - 'Selected Text':('hilite','06'), - 'Found Text':('hit','07'), - 'Cursor':('cursor','08'), - 'Error Text':('error','09'), - 'Shell Normal Text':('console','10'), - 'Shell Stdout Text':('stdout','11'), - 'Shell Stderr Text':('stderr','12'), + 'Python Comments':('comment', '04'), + 'Python Strings':('string', '05'), + 'Selected Text':('hilite', '06'), + 'Found Text':('hit', '07'), + 'Cursor':('cursor', '08'), + 'Error Text':('error', '09'), + 'Shell Normal Text':('console', '10'), + 'Shell Stdout Text':('stdout', '11'), + 'Shell Stderr Text':('stderr', '12'), } self.ResetChangedItems() #load initial values in changed items dict self.CreateWidgets() - self.resizable(height=FALSE,width=FALSE) + self.resizable(height=FALSE, width=FALSE) self.transient(parent) self.grab_set() self.protocol("WM_DELETE_WINDOW", self.Cancel) self.tabPages.focus_set() #key bindings for this dialog - #self.bind('',self.Cancel) #dismiss dialog, no save - #self.bind('',self.Apply) #apply changes, save - #self.bind('',self.Help) #context help + #self.bind('', self.Cancel) #dismiss dialog, no save + #self.bind('', self.Apply) #apply changes, save + #self.bind('', self.Help) #context help self.LoadConfigs() self.AttachVarCallbacks() #avoid callbacks during LoadConfigs @@ -76,40 +78,40 @@ def CreateWidgets(self): self.tabPages = TabbedPageSet(self, - page_names=['Fonts/Tabs','Highlighting','Keys','General']) - frameActionButtons = Frame(self,pady=2) + page_names=['Fonts/Tabs', 'Highlighting', 'Keys', 'General']) + frameActionButtons = Frame(self, pady=2) #action buttons if macosxSupport.isAquaTk(): # Changing the default padding on OSX results in unreadable # text in the buttons - paddingArgs={} + paddingArgs = {} else: - paddingArgs={'padx':6, 'pady':3} + paddingArgs = {'padx':6, 'pady':3} # Comment out button creation and packing until implement self.Help -## self.buttonHelp = Button(frameActionButtons,text='Help', -## command=self.Help,takefocus=FALSE, +## self.buttonHelp = Button(frameActionButtons, text='Help', +## command=self.Help, takefocus=FALSE, ## **paddingArgs) - self.buttonOk = Button(frameActionButtons,text='Ok', - command=self.Ok,takefocus=FALSE, - **paddingArgs) - self.buttonApply = Button(frameActionButtons,text='Apply', - command=self.Apply,takefocus=FALSE, - **paddingArgs) - self.buttonCancel = Button(frameActionButtons,text='Cancel', - command=self.Cancel,takefocus=FALSE, - **paddingArgs) + self.buttonOk = Button( + frameActionButtons, text='Ok', + command=self.Ok, takefocus=FALSE, **paddingArgs) + self.buttonApply = Button( + frameActionButtons, text='Apply', + command=self.Apply, takefocus=FALSE, **paddingArgs) + self.buttonCancel = Button( + frameActionButtons, text='Cancel', + command=self.Cancel, takefocus=FALSE, **paddingArgs) self.CreatePageFontTab() self.CreatePageHighlight() self.CreatePageKeys() self.CreatePageGeneral() -## self.buttonHelp.pack(side=RIGHT,padx=5) - self.buttonOk.pack(side=LEFT,padx=5) - self.buttonApply.pack(side=LEFT,padx=5) - self.buttonCancel.pack(side=LEFT,padx=5) +## self.buttonHelp.pack(side=RIGHT, padx=5) + self.buttonOk.pack(side=LEFT, padx=5) + self.buttonApply.pack(side=LEFT, padx=5) + self.buttonCancel.pack(side=LEFT, padx=5) frameActionButtons.pack(side=BOTTOM) Frame(self, height=2, borderwidth=0).pack(side=BOTTOM) - self.tabPages.pack(side=TOP,expand=TRUE,fill=BOTH) + self.tabPages.pack(side=TOP, expand=TRUE, fill=BOTH) def CreatePageFontTab(self): parent = self.parent @@ -117,63 +119,66 @@ self.fontBold = BooleanVar(parent) self.fontName = StringVar(parent) self.spaceNum = IntVar(parent) - self.editFont = tkFont.Font(parent,('courier',10,'normal')) + self.editFont = tkFont.Font(parent, ('courier', 10, 'normal')) ##widget creation #body frame - frame=self.tabPages.pages['Fonts/Tabs'].frame + frame = self.tabPages.pages['Fonts/Tabs'].frame #body section frames - frameFont=LabelFrame(frame,borderwidth=2,relief=GROOVE, - text=' Base Editor Font ') - frameIndent=LabelFrame(frame,borderwidth=2,relief=GROOVE, - text=' Indentation Width ') + frameFont = LabelFrame( + frame, borderwidth=2, relief=GROOVE, text=' Base Editor Font ') + frameIndent = LabelFrame( + frame, borderwidth=2, relief=GROOVE, text=' Indentation Width ') #frameFont - frameFontName=Frame(frameFont) - frameFontParam=Frame(frameFont) - labelFontNameTitle=Label(frameFontName,justify=LEFT, - text='Font Face :') - self.listFontName=Listbox(frameFontName,height=5,takefocus=FALSE, - exportselection=FALSE) - self.listFontName.bind('',self.OnListFontButtonRelease) - scrollFont=Scrollbar(frameFontName) + frameFontName = Frame(frameFont) + frameFontParam = Frame(frameFont) + labelFontNameTitle = Label( + frameFontName, justify=LEFT, text='Font Face :') + self.listFontName = Listbox( + frameFontName, height=5, takefocus=FALSE, exportselection=FALSE) + self.listFontName.bind( + '', self.OnListFontButtonRelease) + scrollFont = Scrollbar(frameFontName) scrollFont.config(command=self.listFontName.yview) self.listFontName.config(yscrollcommand=scrollFont.set) - labelFontSizeTitle=Label(frameFontParam,text='Size :') - self.optMenuFontSize=DynOptionMenu(frameFontParam,self.fontSize,None, - command=self.SetFontSample) - checkFontBold=Checkbutton(frameFontParam,variable=self.fontBold, - onvalue=1,offvalue=0,text='Bold',command=self.SetFontSample) - frameFontSample=Frame(frameFont,relief=SOLID,borderwidth=1) - self.labelFontSample=Label(frameFontSample, - text='AaBbCcDdEe\nFfGgHhIiJjK\n1234567890\n#:+=(){}[]', - justify=LEFT,font=self.editFont) + labelFontSizeTitle = Label(frameFontParam, text='Size :') + self.optMenuFontSize = DynOptionMenu( + frameFontParam, self.fontSize, None, command=self.SetFontSample) + checkFontBold = Checkbutton( + frameFontParam, variable=self.fontBold, onvalue=1, + offvalue=0, text='Bold', command=self.SetFontSample) + frameFontSample = Frame(frameFont, relief=SOLID, borderwidth=1) + self.labelFontSample = Label( + frameFontSample, justify=LEFT, font=self.editFont, + text='AaBbCcDdEe\nFfGgHhIiJjK\n1234567890\n#:+=(){}[]') #frameIndent - frameIndentSize=Frame(frameIndent) - labelSpaceNumTitle=Label(frameIndentSize, justify=LEFT, - text='Python Standard: 4 Spaces!') - self.scaleSpaceNum=Scale(frameIndentSize, variable=self.spaceNum, - orient='horizontal', - tickinterval=2, from_=2, to=16) + frameIndentSize = Frame(frameIndent) + labelSpaceNumTitle = Label( + frameIndentSize, justify=LEFT, + text='Python Standard: 4 Spaces!') + self.scaleSpaceNum = Scale( + frameIndentSize, variable=self.spaceNum, + orient='horizontal', tickinterval=2, from_=2, to=16) #widget packing #body - frameFont.pack(side=LEFT,padx=5,pady=5,expand=TRUE,fill=BOTH) - frameIndent.pack(side=LEFT,padx=5,pady=5,fill=Y) + frameFont.pack(side=LEFT, padx=5, pady=5, expand=TRUE, fill=BOTH) + frameIndent.pack(side=LEFT, padx=5, pady=5, fill=Y) #frameFont - frameFontName.pack(side=TOP,padx=5,pady=5,fill=X) - frameFontParam.pack(side=TOP,padx=5,pady=5,fill=X) - labelFontNameTitle.pack(side=TOP,anchor=W) - self.listFontName.pack(side=LEFT,expand=TRUE,fill=X) - scrollFont.pack(side=LEFT,fill=Y) - labelFontSizeTitle.pack(side=LEFT,anchor=W) - self.optMenuFontSize.pack(side=LEFT,anchor=W) - checkFontBold.pack(side=LEFT,anchor=W,padx=20) - frameFontSample.pack(side=TOP,padx=5,pady=5,expand=TRUE,fill=BOTH) - self.labelFontSample.pack(expand=TRUE,fill=BOTH) + frameFontName.pack(side=TOP, padx=5, pady=5, fill=X) + frameFontParam.pack(side=TOP, padx=5, pady=5, fill=X) + labelFontNameTitle.pack(side=TOP, anchor=W) + self.listFontName.pack(side=LEFT, expand=TRUE, fill=X) + scrollFont.pack(side=LEFT, fill=Y) + labelFontSizeTitle.pack(side=LEFT, anchor=W) + self.optMenuFontSize.pack(side=LEFT, anchor=W) + checkFontBold.pack(side=LEFT, anchor=W, padx=20) + frameFontSample.pack(side=TOP, padx=5, pady=5, expand=TRUE, fill=BOTH) + self.labelFontSample.pack(expand=TRUE, fill=BOTH) #frameIndent - frameIndentSize.pack(side=TOP,fill=X) - labelSpaceNumTitle.pack(side=TOP,anchor=W,padx=5) - self.scaleSpaceNum.pack(side=TOP,padx=5,fill=X) + frameIndentSize.pack(side=TOP, fill=X) + labelSpaceNumTitle.pack(side=TOP, anchor=W, padx=5) + self.scaleSpaceNum.pack(side=TOP, padx=5, fill=X) return frame def CreatePageHighlight(self): @@ -188,84 +193,100 @@ ##widget creation #body frame - frame=self.tabPages.pages['Highlighting'].frame + frame = self.tabPages.pages['Highlighting'].frame #body section frames - frameCustom=LabelFrame(frame,borderwidth=2,relief=GROOVE, - text=' Custom Highlighting ') - frameTheme=LabelFrame(frame,borderwidth=2,relief=GROOVE, - text=' Highlighting Theme ') + frameCustom = LabelFrame(frame, borderwidth=2, relief=GROOVE, + text=' Custom Highlighting ') + frameTheme = LabelFrame(frame, borderwidth=2, relief=GROOVE, + text=' Highlighting Theme ') #frameCustom - self.textHighlightSample=Text(frameCustom,relief=SOLID,borderwidth=1, - font=('courier',12,''),cursor='hand2',width=21,height=11, - takefocus=FALSE,highlightthickness=0,wrap=NONE) + self.textHighlightSample=Text( + frameCustom, relief=SOLID, borderwidth=1, + font=('courier', 12, ''), cursor='hand2', width=21, height=11, + takefocus=FALSE, highlightthickness=0, wrap=NONE) text=self.textHighlightSample - text.bind('',lambda e: 'break') - text.bind('',lambda e: 'break') - textAndTags=(('#you can click here','comment'),('\n','normal'), - ('#to choose items','comment'),('\n','normal'),('def','keyword'), - (' ','normal'),('func','definition'),('(param):','normal'), - ('\n ','normal'),('"""string"""','string'),('\n var0 = ','normal'), - ("'string'",'string'),('\n var1 = ','normal'),("'selected'",'hilite'), - ('\n var2 = ','normal'),("'found'",'hit'), - ('\n var3 = ','normal'),('list', 'builtin'), ('(','normal'), - ('None', 'keyword'),(')\n\n','normal'), - (' error ','error'),(' ','normal'),('cursor |','cursor'), - ('\n ','normal'),('shell','console'),(' ','normal'),('stdout','stdout'), - (' ','normal'),('stderr','stderr'),('\n','normal')) + text.bind('', lambda e: 'break') + text.bind('', lambda e: 'break') + textAndTags=( + ('#you can click here', 'comment'), ('\n', 'normal'), + ('#to choose items', 'comment'), ('\n', 'normal'), + ('def', 'keyword'), (' ', 'normal'), + ('func', 'definition'), ('(param):\n ', 'normal'), + ('"""string"""', 'string'), ('\n var0 = ', 'normal'), + ("'string'", 'string'), ('\n var1 = ', 'normal'), + ("'selected'", 'hilite'), ('\n var2 = ', 'normal'), + ("'found'", 'hit'), ('\n var3 = ', 'normal'), + ('list', 'builtin'), ('(', 'normal'), + ('None', 'keyword'), (')\n\n', 'normal'), + (' error ', 'error'), (' ', 'normal'), + ('cursor |', 'cursor'), ('\n ', 'normal'), + ('shell', 'console'), (' ', 'normal'), + ('stdout', 'stdout'), (' ', 'normal'), + ('stderr', 'stderr'), ('\n', 'normal')) for txTa in textAndTags: - text.insert(END,txTa[0],txTa[1]) + text.insert(END, txTa[0], txTa[1]) for element in self.themeElements: - text.tag_bind(self.themeElements[element][0],'', - lambda event,elem=element: event.widget.winfo_toplevel() - .highlightTarget.set(elem)) + def tem(event, elem=element): + event.widget.winfo_toplevel().highlightTarget.set(elem) + text.tag_bind( + self.themeElements[element][0], '', tem) text.config(state=DISABLED) - self.frameColourSet=Frame(frameCustom,relief=SOLID,borderwidth=1) - frameFgBg=Frame(frameCustom) - buttonSetColour=Button(self.frameColourSet,text='Choose Colour for :', - command=self.GetColour,highlightthickness=0) - self.optMenuHighlightTarget=DynOptionMenu(self.frameColourSet, - self.highlightTarget,None,highlightthickness=0)#,command=self.SetHighlightTargetBinding - self.radioFg=Radiobutton(frameFgBg,variable=self.fgHilite, - value=1,text='Foreground',command=self.SetColourSampleBinding) - self.radioBg=Radiobutton(frameFgBg,variable=self.fgHilite, - value=0,text='Background',command=self.SetColourSampleBinding) + self.frameColourSet = Frame(frameCustom, relief=SOLID, borderwidth=1) + frameFgBg = Frame(frameCustom) + buttonSetColour = Button( + self.frameColourSet, text='Choose Colour for :', + command=self.GetColour, highlightthickness=0) + self.optMenuHighlightTarget = DynOptionMenu( + self.frameColourSet, self.highlightTarget, None, + highlightthickness=0) #, command=self.SetHighlightTargetBinding + self.radioFg = Radiobutton( + frameFgBg, variable=self.fgHilite, value=1, + text='Foreground', command=self.SetColourSampleBinding) + self.radioBg=Radiobutton( + frameFgBg, variable=self.fgHilite, value=0, + text='Background', command=self.SetColourSampleBinding) self.fgHilite.set(1) - buttonSaveCustomTheme=Button(frameCustom, - text='Save as New Custom Theme',command=self.SaveAsNewTheme) + buttonSaveCustomTheme = Button( + frameCustom, text='Save as New Custom Theme', + command=self.SaveAsNewTheme) #frameTheme - labelTypeTitle=Label(frameTheme,text='Select : ') - self.radioThemeBuiltin=Radiobutton(frameTheme,variable=self.themeIsBuiltin, - value=1,command=self.SetThemeType,text='a Built-in Theme') - self.radioThemeCustom=Radiobutton(frameTheme,variable=self.themeIsBuiltin, - value=0,command=self.SetThemeType,text='a Custom Theme') - self.optMenuThemeBuiltin=DynOptionMenu(frameTheme, - self.builtinTheme,None,command=None) - self.optMenuThemeCustom=DynOptionMenu(frameTheme, - self.customTheme,None,command=None) - self.buttonDeleteCustomTheme=Button(frameTheme,text='Delete Custom Theme', + labelTypeTitle = Label(frameTheme, text='Select : ') + self.radioThemeBuiltin = Radiobutton( + frameTheme, variable=self.themeIsBuiltin, value=1, + command=self.SetThemeType, text='a Built-in Theme') + self.radioThemeCustom = Radiobutton( + frameTheme, variable=self.themeIsBuiltin, value=0, + command=self.SetThemeType, text='a Custom Theme') + self.optMenuThemeBuiltin = DynOptionMenu( + frameTheme, self.builtinTheme, None, command=None) + self.optMenuThemeCustom=DynOptionMenu( + frameTheme, self.customTheme, None, command=None) + self.buttonDeleteCustomTheme=Button( + frameTheme, text='Delete Custom Theme', command=self.DeleteCustomTheme) ##widget packing #body - frameCustom.pack(side=LEFT,padx=5,pady=5,expand=TRUE,fill=BOTH) - frameTheme.pack(side=LEFT,padx=5,pady=5,fill=Y) + frameCustom.pack(side=LEFT, padx=5, pady=5, expand=TRUE, fill=BOTH) + frameTheme.pack(side=LEFT, padx=5, pady=5, fill=Y) #frameCustom - self.frameColourSet.pack(side=TOP,padx=5,pady=5,expand=TRUE,fill=X) - frameFgBg.pack(side=TOP,padx=5,pady=0) - self.textHighlightSample.pack(side=TOP,padx=5,pady=5,expand=TRUE, - fill=BOTH) - buttonSetColour.pack(side=TOP,expand=TRUE,fill=X,padx=8,pady=4) - self.optMenuHighlightTarget.pack(side=TOP,expand=TRUE,fill=X,padx=8,pady=3) - self.radioFg.pack(side=LEFT,anchor=E) - self.radioBg.pack(side=RIGHT,anchor=W) - buttonSaveCustomTheme.pack(side=BOTTOM,fill=X,padx=5,pady=5) + self.frameColourSet.pack(side=TOP, padx=5, pady=5, expand=TRUE, fill=X) + frameFgBg.pack(side=TOP, padx=5, pady=0) + self.textHighlightSample.pack( + side=TOP, padx=5, pady=5, expand=TRUE, fill=BOTH) + buttonSetColour.pack(side=TOP, expand=TRUE, fill=X, padx=8, pady=4) + self.optMenuHighlightTarget.pack( + side=TOP, expand=TRUE, fill=X, padx=8, pady=3) + self.radioFg.pack(side=LEFT, anchor=E) + self.radioBg.pack(side=RIGHT, anchor=W) + buttonSaveCustomTheme.pack(side=BOTTOM, fill=X, padx=5, pady=5) #frameTheme - labelTypeTitle.pack(side=TOP,anchor=W,padx=5,pady=5) - self.radioThemeBuiltin.pack(side=TOP,anchor=W,padx=5) - self.radioThemeCustom.pack(side=TOP,anchor=W,padx=5,pady=2) - self.optMenuThemeBuiltin.pack(side=TOP,fill=X,padx=5,pady=5) - self.optMenuThemeCustom.pack(side=TOP,fill=X,anchor=W,padx=5,pady=5) - self.buttonDeleteCustomTheme.pack(side=TOP,fill=X,padx=5,pady=5) + labelTypeTitle.pack(side=TOP, anchor=W, padx=5, pady=5) + self.radioThemeBuiltin.pack(side=TOP, anchor=W, padx=5) + self.radioThemeCustom.pack(side=TOP, anchor=W, padx=5, pady=2) + self.optMenuThemeBuiltin.pack(side=TOP, fill=X, padx=5, pady=5) + self.optMenuThemeCustom.pack(side=TOP, fill=X, anchor=W, padx=5, pady=5) + self.buttonDeleteCustomTheme.pack(side=TOP, fill=X, padx=5, pady=5) return frame def CreatePageKeys(self): @@ -278,63 +299,69 @@ ##widget creation #body frame - frame=self.tabPages.pages['Keys'].frame + frame = self.tabPages.pages['Keys'].frame #body section frames - frameCustom=LabelFrame(frame,borderwidth=2,relief=GROOVE, - text=' Custom Key Bindings ') - frameKeySets=LabelFrame(frame,borderwidth=2,relief=GROOVE, - text=' Key Set ') + frameCustom = LabelFrame( + frame, borderwidth=2, relief=GROOVE, + text=' Custom Key Bindings ') + frameKeySets = LabelFrame( + frame, borderwidth=2, relief=GROOVE, text=' Key Set ') #frameCustom - frameTarget=Frame(frameCustom) - labelTargetTitle=Label(frameTarget,text='Action - Key(s)') - scrollTargetY=Scrollbar(frameTarget) - scrollTargetX=Scrollbar(frameTarget,orient=HORIZONTAL) - self.listBindings=Listbox(frameTarget,takefocus=FALSE, - exportselection=FALSE) - self.listBindings.bind('',self.KeyBindingSelected) + frameTarget = Frame(frameCustom) + labelTargetTitle = Label(frameTarget, text='Action - Key(s)') + scrollTargetY = Scrollbar(frameTarget) + scrollTargetX = Scrollbar(frameTarget, orient=HORIZONTAL) + self.listBindings = Listbox( + frameTarget, takefocus=FALSE, exportselection=FALSE) + self.listBindings.bind('', self.KeyBindingSelected) scrollTargetY.config(command=self.listBindings.yview) scrollTargetX.config(command=self.listBindings.xview) self.listBindings.config(yscrollcommand=scrollTargetY.set) self.listBindings.config(xscrollcommand=scrollTargetX.set) - self.buttonNewKeys=Button(frameCustom,text='Get New Keys for Selection', - command=self.GetNewKeys,state=DISABLED) + self.buttonNewKeys = Button( + frameCustom, text='Get New Keys for Selection', + command=self.GetNewKeys, state=DISABLED) #frameKeySets frames = [Frame(frameKeySets, padx=2, pady=2, borderwidth=0) for i in range(2)] - self.radioKeysBuiltin=Radiobutton(frames[0],variable=self.keysAreBuiltin, - value=1,command=self.SetKeysType,text='Use a Built-in Key Set') - self.radioKeysCustom=Radiobutton(frames[0],variable=self.keysAreBuiltin, - value=0,command=self.SetKeysType,text='Use a Custom Key Set') - self.optMenuKeysBuiltin=DynOptionMenu(frames[0], - self.builtinKeys,None,command=None) - self.optMenuKeysCustom=DynOptionMenu(frames[0], - self.customKeys,None,command=None) - self.buttonDeleteCustomKeys=Button(frames[1],text='Delete Custom Key Set', + self.radioKeysBuiltin = Radiobutton( + frames[0], variable=self.keysAreBuiltin, value=1, + command=self.SetKeysType, text='Use a Built-in Key Set') + self.radioKeysCustom = Radiobutton( + frames[0], variable=self.keysAreBuiltin, value=0, + command=self.SetKeysType, text='Use a Custom Key Set') + self.optMenuKeysBuiltin = DynOptionMenu( + frames[0], self.builtinKeys, None, command=None) + self.optMenuKeysCustom = DynOptionMenu( + frames[0], self.customKeys, None, command=None) + self.buttonDeleteCustomKeys = Button( + frames[1], text='Delete Custom Key Set', command=self.DeleteCustomKeys) - buttonSaveCustomKeys=Button(frames[1], - text='Save as New Custom Key Set',command=self.SaveAsNewKeySet) + buttonSaveCustomKeys = Button( + frames[1], text='Save as New Custom Key Set', + command=self.SaveAsNewKeySet) ##widget packing #body - frameCustom.pack(side=BOTTOM,padx=5,pady=5,expand=TRUE,fill=BOTH) - frameKeySets.pack(side=BOTTOM,padx=5,pady=5,fill=BOTH) + frameCustom.pack(side=BOTTOM, padx=5, pady=5, expand=TRUE, fill=BOTH) + frameKeySets.pack(side=BOTTOM, padx=5, pady=5, fill=BOTH) #frameCustom - self.buttonNewKeys.pack(side=BOTTOM,fill=X,padx=5,pady=5) - frameTarget.pack(side=LEFT,padx=5,pady=5,expand=TRUE,fill=BOTH) + self.buttonNewKeys.pack(side=BOTTOM, fill=X, padx=5, pady=5) + frameTarget.pack(side=LEFT, padx=5, pady=5, expand=TRUE, fill=BOTH) #frame target - frameTarget.columnconfigure(0,weight=1) - frameTarget.rowconfigure(1,weight=1) - labelTargetTitle.grid(row=0,column=0,columnspan=2,sticky=W) - self.listBindings.grid(row=1,column=0,sticky=NSEW) - scrollTargetY.grid(row=1,column=1,sticky=NS) - scrollTargetX.grid(row=2,column=0,sticky=EW) + frameTarget.columnconfigure(0, weight=1) + frameTarget.rowconfigure(1, weight=1) + labelTargetTitle.grid(row=0, column=0, columnspan=2, sticky=W) + self.listBindings.grid(row=1, column=0, sticky=NSEW) + scrollTargetY.grid(row=1, column=1, sticky=NS) + scrollTargetX.grid(row=2, column=0, sticky=EW) #frameKeySets self.radioKeysBuiltin.grid(row=0, column=0, sticky=W+NS) self.radioKeysCustom.grid(row=1, column=0, sticky=W+NS) self.optMenuKeysBuiltin.grid(row=0, column=1, sticky=NSEW) self.optMenuKeysCustom.grid(row=1, column=1, sticky=NSEW) - self.buttonDeleteCustomKeys.pack(side=LEFT,fill=X,expand=True,padx=2) - buttonSaveCustomKeys.pack(side=LEFT,fill=X,expand=True,padx=2) + self.buttonDeleteCustomKeys.pack(side=LEFT, fill=X, expand=True, padx=2) + buttonSaveCustomKeys.pack(side=LEFT, fill=X, expand=True, padx=2) frames[0].pack(side=TOP, fill=BOTH, expand=True) frames[1].pack(side=TOP, fill=X, expand=True, pady=2) return frame @@ -352,208 +379,216 @@ #widget creation #body - frame=self.tabPages.pages['General'].frame + frame = self.tabPages.pages['General'].frame #body section frames - frameRun=LabelFrame(frame,borderwidth=2,relief=GROOVE, - text=' Startup Preferences ') - frameSave=LabelFrame(frame,borderwidth=2,relief=GROOVE, - text=' Autosave Preferences ') - frameWinSize=Frame(frame,borderwidth=2,relief=GROOVE) - frameParaSize=Frame(frame,borderwidth=2,relief=GROOVE) - frameHelp=LabelFrame(frame,borderwidth=2,relief=GROOVE, - text=' Additional Help Sources ') + frameRun = LabelFrame(frame, borderwidth=2, relief=GROOVE, + text=' Startup Preferences ') + frameSave = LabelFrame(frame, borderwidth=2, relief=GROOVE, + text=' Autosave Preferences ') + frameWinSize = Frame(frame, borderwidth=2, relief=GROOVE) + frameParaSize = Frame(frame, borderwidth=2, relief=GROOVE) + frameHelp = LabelFrame(frame, borderwidth=2, relief=GROOVE, + text=' Additional Help Sources ') #frameRun - labelRunChoiceTitle=Label(frameRun,text='At Startup') - radioStartupEdit=Radiobutton(frameRun,variable=self.startupEdit, - value=1,command=self.SetKeysType,text="Open Edit Window") - radioStartupShell=Radiobutton(frameRun,variable=self.startupEdit, - value=0,command=self.SetKeysType,text='Open Shell Window') + labelRunChoiceTitle = Label(frameRun, text='At Startup') + radioStartupEdit = Radiobutton( + frameRun, variable=self.startupEdit, value=1, + command=self.SetKeysType, text="Open Edit Window") + radioStartupShell = Radiobutton( + frameRun, variable=self.startupEdit, value=0, + command=self.SetKeysType, text='Open Shell Window') #frameSave - labelRunSaveTitle=Label(frameSave,text='At Start of Run (F5) ') - radioSaveAsk=Radiobutton(frameSave,variable=self.autoSave, - value=0,command=self.SetKeysType,text="Prompt to Save") - radioSaveAuto=Radiobutton(frameSave,variable=self.autoSave, - value=1,command=self.SetKeysType,text='No Prompt') + labelRunSaveTitle = Label(frameSave, text='At Start of Run (F5) ') + radioSaveAsk = Radiobutton( + frameSave, variable=self.autoSave, value=0, + command=self.SetKeysType, text="Prompt to Save") + radioSaveAuto = Radiobutton( + frameSave, variable=self.autoSave, value=1, + command=self.SetKeysType, text='No Prompt') #frameWinSize - labelWinSizeTitle=Label(frameWinSize,text='Initial Window Size'+ - ' (in characters)') - labelWinWidthTitle=Label(frameWinSize,text='Width') - entryWinWidth=Entry(frameWinSize,textvariable=self.winWidth, - width=3) - labelWinHeightTitle=Label(frameWinSize,text='Height') - entryWinHeight=Entry(frameWinSize,textvariable=self.winHeight, - width=3) + labelWinSizeTitle = Label( + frameWinSize, text='Initial Window Size (in characters)') + labelWinWidthTitle = Label(frameWinSize, text='Width') + entryWinWidth = Entry( + frameWinSize, textvariable=self.winWidth, width=3) + labelWinHeightTitle = Label(frameWinSize, text='Height') + entryWinHeight = Entry( + frameWinSize, textvariable=self.winHeight, width=3) #paragraphFormatWidth - labelParaWidthTitle=Label(frameParaSize,text='Paragraph reformat'+ - ' width (in characters)') - entryParaWidth=Entry(frameParaSize,textvariable=self.paraWidth, - width=3) + labelParaWidthTitle = Label( + frameParaSize, text='Paragraph reformat width (in characters)') + entryParaWidth = Entry( + frameParaSize, textvariable=self.paraWidth, width=3) #frameHelp - frameHelpList=Frame(frameHelp) - frameHelpListButtons=Frame(frameHelpList) - scrollHelpList=Scrollbar(frameHelpList) - self.listHelp=Listbox(frameHelpList,height=5,takefocus=FALSE, + frameHelpList = Frame(frameHelp) + frameHelpListButtons = Frame(frameHelpList) + scrollHelpList = Scrollbar(frameHelpList) + self.listHelp = Listbox( + frameHelpList, height=5, takefocus=FALSE, exportselection=FALSE) scrollHelpList.config(command=self.listHelp.yview) self.listHelp.config(yscrollcommand=scrollHelpList.set) - self.listHelp.bind('',self.HelpSourceSelected) - self.buttonHelpListEdit=Button(frameHelpListButtons,text='Edit', - state=DISABLED,width=8,command=self.HelpListItemEdit) - self.buttonHelpListAdd=Button(frameHelpListButtons,text='Add', - width=8,command=self.HelpListItemAdd) - self.buttonHelpListRemove=Button(frameHelpListButtons,text='Remove', - state=DISABLED,width=8,command=self.HelpListItemRemove) + self.listHelp.bind('', self.HelpSourceSelected) + self.buttonHelpListEdit = Button( + frameHelpListButtons, text='Edit', state=DISABLED, + width=8, command=self.HelpListItemEdit) + self.buttonHelpListAdd = Button( + frameHelpListButtons, text='Add', + width=8, command=self.HelpListItemAdd) + self.buttonHelpListRemove = Button( + frameHelpListButtons, text='Remove', state=DISABLED, + width=8, command=self.HelpListItemRemove) #widget packing #body - frameRun.pack(side=TOP,padx=5,pady=5,fill=X) - frameSave.pack(side=TOP,padx=5,pady=5,fill=X) - frameWinSize.pack(side=TOP,padx=5,pady=5,fill=X) - frameParaSize.pack(side=TOP,padx=5,pady=5,fill=X) - frameHelp.pack(side=TOP,padx=5,pady=5,expand=TRUE,fill=BOTH) + frameRun.pack(side=TOP, padx=5, pady=5, fill=X) + frameSave.pack(side=TOP, padx=5, pady=5, fill=X) + frameWinSize.pack(side=TOP, padx=5, pady=5, fill=X) + frameParaSize.pack(side=TOP, padx=5, pady=5, fill=X) + frameHelp.pack(side=TOP, padx=5, pady=5, expand=TRUE, fill=BOTH) #frameRun - labelRunChoiceTitle.pack(side=LEFT,anchor=W,padx=5,pady=5) - radioStartupShell.pack(side=RIGHT,anchor=W,padx=5,pady=5) - radioStartupEdit.pack(side=RIGHT,anchor=W,padx=5,pady=5) + labelRunChoiceTitle.pack(side=LEFT, anchor=W, padx=5, pady=5) + radioStartupShell.pack(side=RIGHT, anchor=W, padx=5, pady=5) + radioStartupEdit.pack(side=RIGHT, anchor=W, padx=5, pady=5) #frameSave - labelRunSaveTitle.pack(side=LEFT,anchor=W,padx=5,pady=5) - radioSaveAuto.pack(side=RIGHT,anchor=W,padx=5,pady=5) - radioSaveAsk.pack(side=RIGHT,anchor=W,padx=5,pady=5) + labelRunSaveTitle.pack(side=LEFT, anchor=W, padx=5, pady=5) + radioSaveAuto.pack(side=RIGHT, anchor=W, padx=5, pady=5) + radioSaveAsk.pack(side=RIGHT, anchor=W, padx=5, pady=5) #frameWinSize - labelWinSizeTitle.pack(side=LEFT,anchor=W,padx=5,pady=5) - entryWinHeight.pack(side=RIGHT,anchor=E,padx=10,pady=5) - labelWinHeightTitle.pack(side=RIGHT,anchor=E,pady=5) - entryWinWidth.pack(side=RIGHT,anchor=E,padx=10,pady=5) - labelWinWidthTitle.pack(side=RIGHT,anchor=E,pady=5) + labelWinSizeTitle.pack(side=LEFT, anchor=W, padx=5, pady=5) + entryWinHeight.pack(side=RIGHT, anchor=E, padx=10, pady=5) + labelWinHeightTitle.pack(side=RIGHT, anchor=E, pady=5) + entryWinWidth.pack(side=RIGHT, anchor=E, padx=10, pady=5) + labelWinWidthTitle.pack(side=RIGHT, anchor=E, pady=5) #paragraphFormatWidth - labelParaWidthTitle.pack(side=LEFT,anchor=W,padx=5,pady=5) - entryParaWidth.pack(side=RIGHT,anchor=E,padx=10,pady=5) + labelParaWidthTitle.pack(side=LEFT, anchor=W, padx=5, pady=5) + entryParaWidth.pack(side=RIGHT, anchor=E, padx=10, pady=5) #frameHelp - frameHelpListButtons.pack(side=RIGHT,padx=5,pady=5,fill=Y) - frameHelpList.pack(side=TOP,padx=5,pady=5,expand=TRUE,fill=BOTH) - scrollHelpList.pack(side=RIGHT,anchor=W,fill=Y) - self.listHelp.pack(side=LEFT,anchor=E,expand=TRUE,fill=BOTH) - self.buttonHelpListEdit.pack(side=TOP,anchor=W,pady=5) - self.buttonHelpListAdd.pack(side=TOP,anchor=W) - self.buttonHelpListRemove.pack(side=TOP,anchor=W,pady=5) + frameHelpListButtons.pack(side=RIGHT, padx=5, pady=5, fill=Y) + frameHelpList.pack(side=TOP, padx=5, pady=5, expand=TRUE, fill=BOTH) + scrollHelpList.pack(side=RIGHT, anchor=W, fill=Y) + self.listHelp.pack(side=LEFT, anchor=E, expand=TRUE, fill=BOTH) + self.buttonHelpListEdit.pack(side=TOP, anchor=W, pady=5) + self.buttonHelpListAdd.pack(side=TOP, anchor=W) + self.buttonHelpListRemove.pack(side=TOP, anchor=W, pady=5) return frame def AttachVarCallbacks(self): - self.fontSize.trace_variable('w',self.VarChanged_fontSize) - self.fontName.trace_variable('w',self.VarChanged_fontName) - self.fontBold.trace_variable('w',self.VarChanged_fontBold) - self.spaceNum.trace_variable('w',self.VarChanged_spaceNum) - self.colour.trace_variable('w',self.VarChanged_colour) - self.builtinTheme.trace_variable('w',self.VarChanged_builtinTheme) - self.customTheme.trace_variable('w',self.VarChanged_customTheme) - self.themeIsBuiltin.trace_variable('w',self.VarChanged_themeIsBuiltin) - self.highlightTarget.trace_variable('w',self.VarChanged_highlightTarget) - self.keyBinding.trace_variable('w',self.VarChanged_keyBinding) - self.builtinKeys.trace_variable('w',self.VarChanged_builtinKeys) - self.customKeys.trace_variable('w',self.VarChanged_customKeys) - self.keysAreBuiltin.trace_variable('w',self.VarChanged_keysAreBuiltin) - self.winWidth.trace_variable('w',self.VarChanged_winWidth) - self.winHeight.trace_variable('w',self.VarChanged_winHeight) - self.paraWidth.trace_variable('w',self.VarChanged_paraWidth) - self.startupEdit.trace_variable('w',self.VarChanged_startupEdit) - self.autoSave.trace_variable('w',self.VarChanged_autoSave) - self.encoding.trace_variable('w',self.VarChanged_encoding) + self.fontSize.trace_variable('w', self.VarChanged_fontSize) + self.fontName.trace_variable('w', self.VarChanged_fontName) + self.fontBold.trace_variable('w', self.VarChanged_fontBold) + self.spaceNum.trace_variable('w', self.VarChanged_spaceNum) + self.colour.trace_variable('w', self.VarChanged_colour) + self.builtinTheme.trace_variable('w', self.VarChanged_builtinTheme) + self.customTheme.trace_variable('w', self.VarChanged_customTheme) + self.themeIsBuiltin.trace_variable('w', self.VarChanged_themeIsBuiltin) + self.highlightTarget.trace_variable('w', self.VarChanged_highlightTarget) + self.keyBinding.trace_variable('w', self.VarChanged_keyBinding) + self.builtinKeys.trace_variable('w', self.VarChanged_builtinKeys) + self.customKeys.trace_variable('w', self.VarChanged_customKeys) + self.keysAreBuiltin.trace_variable('w', self.VarChanged_keysAreBuiltin) + self.winWidth.trace_variable('w', self.VarChanged_winWidth) + self.winHeight.trace_variable('w', self.VarChanged_winHeight) + self.paraWidth.trace_variable('w', self.VarChanged_paraWidth) + self.startupEdit.trace_variable('w', self.VarChanged_startupEdit) + self.autoSave.trace_variable('w', self.VarChanged_autoSave) + self.encoding.trace_variable('w', self.VarChanged_encoding) - def VarChanged_fontSize(self,*params): - value=self.fontSize.get() - self.AddChangedItem('main','EditorWindow','font-size',value) + def VarChanged_fontSize(self, *params): + value = self.fontSize.get() + self.AddChangedItem('main', 'EditorWindow', 'font-size', value) - def VarChanged_fontName(self,*params): - value=self.fontName.get() - self.AddChangedItem('main','EditorWindow','font',value) + def VarChanged_fontName(self, *params): + value = self.fontName.get() + self.AddChangedItem('main', 'EditorWindow', 'font', value) - def VarChanged_fontBold(self,*params): - value=self.fontBold.get() - self.AddChangedItem('main','EditorWindow','font-bold',value) + def VarChanged_fontBold(self, *params): + value = self.fontBold.get() + self.AddChangedItem('main', 'EditorWindow', 'font-bold', value) - def VarChanged_spaceNum(self,*params): - value=self.spaceNum.get() - self.AddChangedItem('main','Indent','num-spaces',value) + def VarChanged_spaceNum(self, *params): + value = self.spaceNum.get() + self.AddChangedItem('main', 'Indent', 'num-spaces', value) - def VarChanged_colour(self,*params): + def VarChanged_colour(self, *params): self.OnNewColourSet() - def VarChanged_builtinTheme(self,*params): - value=self.builtinTheme.get() - self.AddChangedItem('main','Theme','name',value) + def VarChanged_builtinTheme(self, *params): + value = self.builtinTheme.get() + self.AddChangedItem('main', 'Theme', 'name', value) self.PaintThemeSample() - def VarChanged_customTheme(self,*params): - value=self.customTheme.get() + def VarChanged_customTheme(self, *params): + value = self.customTheme.get() if value != '- no custom themes -': - self.AddChangedItem('main','Theme','name',value) + self.AddChangedItem('main', 'Theme', 'name', value) self.PaintThemeSample() - def VarChanged_themeIsBuiltin(self,*params): - value=self.themeIsBuiltin.get() - self.AddChangedItem('main','Theme','default',value) + def VarChanged_themeIsBuiltin(self, *params): + value = self.themeIsBuiltin.get() + self.AddChangedItem('main', 'Theme', 'default', value) if value: self.VarChanged_builtinTheme() else: self.VarChanged_customTheme() - def VarChanged_highlightTarget(self,*params): + def VarChanged_highlightTarget(self, *params): self.SetHighlightTarget() - def VarChanged_keyBinding(self,*params): - value=self.keyBinding.get() - keySet=self.customKeys.get() - event=self.listBindings.get(ANCHOR).split()[0] + def VarChanged_keyBinding(self, *params): + value = self.keyBinding.get() + keySet = self.customKeys.get() + event = self.listBindings.get(ANCHOR).split()[0] if idleConf.IsCoreBinding(event): #this is a core keybinding - self.AddChangedItem('keys',keySet,event,value) + self.AddChangedItem('keys', keySet, event, value) else: #this is an extension key binding - extName=idleConf.GetExtnNameForEvent(event) - extKeybindSection=extName+'_cfgBindings' - self.AddChangedItem('extensions',extKeybindSection,event,value) + extName = idleConf.GetExtnNameForEvent(event) + extKeybindSection = extName + '_cfgBindings' + self.AddChangedItem('extensions', extKeybindSection, event, value) - def VarChanged_builtinKeys(self,*params): - value=self.builtinKeys.get() - self.AddChangedItem('main','Keys','name',value) + def VarChanged_builtinKeys(self, *params): + value = self.builtinKeys.get() + self.AddChangedItem('main', 'Keys', 'name', value) self.LoadKeysList(value) - def VarChanged_customKeys(self,*params): - value=self.customKeys.get() + def VarChanged_customKeys(self, *params): + value = self.customKeys.get() if value != '- no custom keys -': - self.AddChangedItem('main','Keys','name',value) + self.AddChangedItem('main', 'Keys', 'name', value) self.LoadKeysList(value) - def VarChanged_keysAreBuiltin(self,*params): - value=self.keysAreBuiltin.get() - self.AddChangedItem('main','Keys','default',value) + def VarChanged_keysAreBuiltin(self, *params): + value = self.keysAreBuiltin.get() + self.AddChangedItem('main', 'Keys', 'default', value) if value: self.VarChanged_builtinKeys() else: self.VarChanged_customKeys() - def VarChanged_winWidth(self,*params): - value=self.winWidth.get() - self.AddChangedItem('main','EditorWindow','width',value) + def VarChanged_winWidth(self, *params): + value = self.winWidth.get() + self.AddChangedItem('main', 'EditorWindow', 'width', value) - def VarChanged_winHeight(self,*params): - value=self.winHeight.get() - self.AddChangedItem('main','EditorWindow','height',value) + def VarChanged_winHeight(self, *params): + value = self.winHeight.get() + self.AddChangedItem('main', 'EditorWindow', 'height', value) - def VarChanged_paraWidth(self,*params): - value=self.paraWidth.get() - self.AddChangedItem('main','FormatParagraph','paragraph',value) + def VarChanged_paraWidth(self, *params): + value = self.paraWidth.get() + self.AddChangedItem('main', 'FormatParagraph', 'paragraph', value) - def VarChanged_startupEdit(self,*params): - value=self.startupEdit.get() - self.AddChangedItem('main','General','editor-on-startup',value) + def VarChanged_startupEdit(self, *params): + value = self.startupEdit.get() + self.AddChangedItem('main', 'General', 'editor-on-startup', value) - def VarChanged_autoSave(self,*params): - value=self.autoSave.get() - self.AddChangedItem('main','General','autosave',value) + def VarChanged_autoSave(self, *params): + value = self.autoSave.get() + self.AddChangedItem('main', 'General', 'autosave', value) - def VarChanged_encoding(self,*params): - value=self.encoding.get() - self.AddChangedItem('main','EditorWindow','encoding',value) + def VarChanged_encoding(self, *params): + value = self.encoding.get() + self.AddChangedItem('main', 'EditorWindow', 'encoding', value) def ResetChangedItems(self): #When any config item is changed in this dialog, an entry @@ -561,24 +596,25 @@ #dictionary. The key should be the config file section name and the #value a dictionary, whose key:value pairs are item=value pairs for #that config file section. - self.changedItems={'main':{},'highlight':{},'keys':{},'extensions':{}} + self.changedItems = {'main':{}, 'highlight':{}, 'keys':{}, + 'extensions':{}} - def AddChangedItem(self,type,section,item,value): - value=str(value) #make sure we use a string - if section not in self.changedItems[type]: - self.changedItems[type][section]={} - self.changedItems[type][section][item]=value + def AddChangedItem(self, typ, section, item, value): + value = str(value) #make sure we use a string + if section not in self.changedItems[typ]: + self.changedItems[typ][section] = {} + self.changedItems[typ][section][item] = value def GetDefaultItems(self): - dItems={'main':{},'highlight':{},'keys':{},'extensions':{}} + dItems={'main':{}, 'highlight':{}, 'keys':{}, 'extensions':{}} for configType in dItems: - sections=idleConf.GetSectionList('default',configType) + sections = idleConf.GetSectionList('default', configType) for section in sections: - dItems[configType][section]={} - options=idleConf.defaultCfg[configType].GetOptionList(section) + dItems[configType][section] = {} + options = idleConf.defaultCfg[configType].GetOptionList(section) for option in options: - dItems[configType][section][option]=( - idleConf.defaultCfg[configType].Get(section,option)) + dItems[configType][section][option] = ( + idleConf.defaultCfg[configType].Get(section, option)) return dItems def SetThemeType(self): @@ -604,26 +640,26 @@ self.buttonDeleteCustomKeys.config(state=NORMAL) def GetNewKeys(self): - listIndex=self.listBindings.index(ANCHOR) - binding=self.listBindings.get(listIndex) - bindName=binding.split()[0] #first part, up to first space + listIndex = self.listBindings.index(ANCHOR) + binding = self.listBindings.get(listIndex) + bindName = binding.split()[0] #first part, up to first space if self.keysAreBuiltin.get(): - currentKeySetName=self.builtinKeys.get() + currentKeySetName = self.builtinKeys.get() else: - currentKeySetName=self.customKeys.get() - currentBindings=idleConf.GetCurrentKeySet() + currentKeySetName = self.customKeys.get() + currentBindings = idleConf.GetCurrentKeySet() if currentKeySetName in self.changedItems['keys']: #unsaved changes - keySetChanges=self.changedItems['keys'][currentKeySetName] + keySetChanges = self.changedItems['keys'][currentKeySetName] for event in keySetChanges: - currentBindings[event]=keySetChanges[event].split() + currentBindings[event] = keySetChanges[event].split() currentKeySequences = list(currentBindings.values()) - newKeys=GetKeysDialog(self,'Get New Keys',bindName, + newKeys = GetKeysDialog(self, 'Get New Keys', bindName, currentKeySequences).result if newKeys: #new keys were specified if self.keysAreBuiltin.get(): #current key set is a built-in - message=('Your changes will be saved as a new Custom Key Set. '+ - 'Enter a name for your new Custom Key Set below.') - newKeySet=self.GetNewKeysName(message) + message = ('Your changes will be saved as a new Custom Key Set.' + ' Enter a name for your new Custom Key Set below.') + newKeySet = self.GetNewKeysName(message) if not newKeySet: #user cancelled custom key set creation self.listBindings.select_set(listIndex) self.listBindings.select_anchor(listIndex) @@ -631,7 +667,7 @@ else: #create new custom key set based on previously active key set self.CreateNewKeySet(newKeySet) self.listBindings.delete(listIndex) - self.listBindings.insert(listIndex,bindName+' - '+newKeys) + self.listBindings.insert(listIndex, bindName+' - '+newKeys) self.listBindings.select_set(listIndex) self.listBindings.select_anchor(listIndex) self.keyBinding.set(newKeys) @@ -639,65 +675,65 @@ self.listBindings.select_set(listIndex) self.listBindings.select_anchor(listIndex) - def GetNewKeysName(self,message): - usedNames=(idleConf.GetSectionList('user','keys')+ - idleConf.GetSectionList('default','keys')) - newKeySet=GetCfgSectionNameDialog(self,'New Custom Key Set', - message,usedNames).result + def GetNewKeysName(self, message): + usedNames = (idleConf.GetSectionList('user', 'keys') + + idleConf.GetSectionList('default', 'keys')) + newKeySet = GetCfgSectionNameDialog( + self, 'New Custom Key Set', message, usedNames).result return newKeySet def SaveAsNewKeySet(self): - newKeysName=self.GetNewKeysName('New Key Set Name:') + newKeysName = self.GetNewKeysName('New Key Set Name:') if newKeysName: self.CreateNewKeySet(newKeysName) - def KeyBindingSelected(self,event): + def KeyBindingSelected(self, event): self.buttonNewKeys.config(state=NORMAL) - def CreateNewKeySet(self,newKeySetName): + def CreateNewKeySet(self, newKeySetName): #creates new custom key set based on the previously active key set, #and makes the new key set active if self.keysAreBuiltin.get(): - prevKeySetName=self.builtinKeys.get() + prevKeySetName = self.builtinKeys.get() else: - prevKeySetName=self.customKeys.get() - prevKeys=idleConf.GetCoreKeys(prevKeySetName) - newKeys={} + prevKeySetName = self.customKeys.get() + prevKeys = idleConf.GetCoreKeys(prevKeySetName) + newKeys = {} for event in prevKeys: #add key set to changed items - eventName=event[2:-2] #trim off the angle brackets - binding=' '.join(prevKeys[event]) - newKeys[eventName]=binding + eventName = event[2:-2] #trim off the angle brackets + binding = ' '.join(prevKeys[event]) + newKeys[eventName] = binding #handle any unsaved changes to prev key set if prevKeySetName in self.changedItems['keys']: - keySetChanges=self.changedItems['keys'][prevKeySetName] + keySetChanges = self.changedItems['keys'][prevKeySetName] for event in keySetChanges: - newKeys[event]=keySetChanges[event] + newKeys[event] = keySetChanges[event] #save the new theme - self.SaveNewKeySet(newKeySetName,newKeys) + self.SaveNewKeySet(newKeySetName, newKeys) #change gui over to the new key set - customKeyList=idleConf.GetSectionList('user','keys') + customKeyList = idleConf.GetSectionList('user', 'keys') customKeyList.sort() - self.optMenuKeysCustom.SetMenu(customKeyList,newKeySetName) + self.optMenuKeysCustom.SetMenu(customKeyList, newKeySetName) self.keysAreBuiltin.set(0) self.SetKeysType() - def LoadKeysList(self,keySetName): - reselect=0 - newKeySet=0 + def LoadKeysList(self, keySetName): + reselect = 0 + newKeySet = 0 if self.listBindings.curselection(): - reselect=1 - listIndex=self.listBindings.index(ANCHOR) - keySet=idleConf.GetKeySet(keySetName) + reselect = 1 + listIndex = self.listBindings.index(ANCHOR) + keySet = idleConf.GetKeySet(keySetName) bindNames = list(keySet.keys()) bindNames.sort() - self.listBindings.delete(0,END) + self.listBindings.delete(0, END) for bindName in bindNames: - key=' '.join(keySet[bindName]) #make key(s) into a string - bindName=bindName[2:-2] #trim off the angle brackets + key = ' '.join(keySet[bindName]) #make key(s) into a string + bindName = bindName[2:-2] #trim off the angle brackets if keySetName in self.changedItems['keys']: #handle any unsaved changes to this key set if bindName in self.changedItems['keys'][keySetName]: - key=self.changedItems['keys'][keySetName][bindName] + key = self.changedItems['keys'][keySetName][bindName] self.listBindings.insert(END, bindName+' - '+key) if reselect: self.listBindings.see(listIndex) @@ -706,9 +742,9 @@ def DeleteCustomKeys(self): keySetName=self.customKeys.get() - if not tkMessageBox.askyesno('Delete Key Set','Are you sure you wish '+ - 'to delete the key set %r ?' % (keySetName), - parent=self): + delmsg = 'Are you sure you wish to delete the key set %r ?' + if not tkMessageBox.askyesno( + 'Delete Key Set', delmsg % keySetName, parent=self): return #remove key set from config idleConf.userCfg['keys'].remove_section(keySetName) @@ -717,25 +753,25 @@ #write changes idleConf.userCfg['keys'].Save() #reload user key set list - itemList=idleConf.GetSectionList('user','keys') + itemList = idleConf.GetSectionList('user', 'keys') itemList.sort() if not itemList: self.radioKeysCustom.config(state=DISABLED) - self.optMenuKeysCustom.SetMenu(itemList,'- no custom keys -') + self.optMenuKeysCustom.SetMenu(itemList, '- no custom keys -') else: - self.optMenuKeysCustom.SetMenu(itemList,itemList[0]) + self.optMenuKeysCustom.SetMenu(itemList, itemList[0]) #revert to default key set - self.keysAreBuiltin.set(idleConf.defaultCfg['main'].Get('Keys','default')) - self.builtinKeys.set(idleConf.defaultCfg['main'].Get('Keys','name')) + self.keysAreBuiltin.set(idleConf.defaultCfg['main'].Get('Keys', 'default')) + self.builtinKeys.set(idleConf.defaultCfg['main'].Get('Keys', 'name')) #user can't back out of these changes, they must be applied now self.Apply() self.SetKeysType() def DeleteCustomTheme(self): - themeName=self.customTheme.get() - if not tkMessageBox.askyesno('Delete Theme','Are you sure you wish '+ - 'to delete the theme %r ?' % (themeName,), - parent=self): + themeName = self.customTheme.get() + delmsg = 'Are you sure you wish to delete the theme %r ?' + if not tkMessageBox.askyesno( + 'Delete Theme', delmsg % themeName, parent=self): return #remove theme from config idleConf.userCfg['highlight'].remove_section(themeName) @@ -744,153 +780,149 @@ #write changes idleConf.userCfg['highlight'].Save() #reload user theme list - itemList=idleConf.GetSectionList('user','highlight') + itemList = idleConf.GetSectionList('user', 'highlight') itemList.sort() if not itemList: self.radioThemeCustom.config(state=DISABLED) - self.optMenuThemeCustom.SetMenu(itemList,'- no custom themes -') + self.optMenuThemeCustom.SetMenu(itemList, '- no custom themes -') else: - self.optMenuThemeCustom.SetMenu(itemList,itemList[0]) + self.optMenuThemeCustom.SetMenu(itemList, itemList[0]) #revert to default theme - self.themeIsBuiltin.set(idleConf.defaultCfg['main'].Get('Theme','default')) - self.builtinTheme.set(idleConf.defaultCfg['main'].Get('Theme','name')) + self.themeIsBuiltin.set(idleConf.defaultCfg['main'].Get('Theme', 'default')) + self.builtinTheme.set(idleConf.defaultCfg['main'].Get('Theme', 'name')) #user can't back out of these changes, they must be applied now self.Apply() self.SetThemeType() def GetColour(self): - target=self.highlightTarget.get() - prevColour=self.frameColourSet.cget('bg') - rgbTuplet, colourString = tkColorChooser.askcolor(parent=self, - title='Pick new colour for : '+target,initialcolor=prevColour) - if colourString and (colourString!=prevColour): + target = self.highlightTarget.get() + prevColour = self.frameColourSet.cget('bg') + rgbTuplet, colourString = tkColorChooser.askcolor( + parent=self, title='Pick new colour for : '+target, + initialcolor=prevColour) + if colourString and (colourString != prevColour): #user didn't cancel, and they chose a new colour - if self.themeIsBuiltin.get(): #current theme is a built-in - message=('Your changes will be saved as a new Custom Theme. '+ - 'Enter a name for your new Custom Theme below.') - newTheme=self.GetNewThemeName(message) - if not newTheme: #user cancelled custom theme creation + if self.themeIsBuiltin.get(): #current theme is a built-in + message = ('Your changes will be saved as a new Custom Theme. ' + 'Enter a name for your new Custom Theme below.') + newTheme = self.GetNewThemeName(message) + if not newTheme: #user cancelled custom theme creation return - else: #create new custom theme based on previously active theme + else: #create new custom theme based on previously active theme self.CreateNewTheme(newTheme) self.colour.set(colourString) - else: #current theme is user defined + else: #current theme is user defined self.colour.set(colourString) def OnNewColourSet(self): newColour=self.colour.get() - self.frameColourSet.config(bg=newColour)#set sample - if self.fgHilite.get(): plane='foreground' - else: plane='background' - sampleElement=self.themeElements[self.highlightTarget.get()][0] + self.frameColourSet.config(bg=newColour) #set sample + plane ='foreground' if self.fgHilite.get() else 'background' + sampleElement = self.themeElements[self.highlightTarget.get()][0] self.textHighlightSample.tag_config(sampleElement, **{plane:newColour}) - theme=self.customTheme.get() - themeElement=sampleElement+'-'+plane - self.AddChangedItem('highlight',theme,themeElement,newColour) + theme = self.customTheme.get() + themeElement = sampleElement + '-' + plane + self.AddChangedItem('highlight', theme, themeElement, newColour) - def GetNewThemeName(self,message): - usedNames=(idleConf.GetSectionList('user','highlight')+ - idleConf.GetSectionList('default','highlight')) - newTheme=GetCfgSectionNameDialog(self,'New Custom Theme', - message,usedNames).result + def GetNewThemeName(self, message): + usedNames = (idleConf.GetSectionList('user', 'highlight') + + idleConf.GetSectionList('default', 'highlight')) + newTheme = GetCfgSectionNameDialog( + self, 'New Custom Theme', message, usedNames).result return newTheme def SaveAsNewTheme(self): - newThemeName=self.GetNewThemeName('New Theme Name:') + newThemeName = self.GetNewThemeName('New Theme Name:') if newThemeName: self.CreateNewTheme(newThemeName) - def CreateNewTheme(self,newThemeName): + def CreateNewTheme(self, newThemeName): #creates new custom theme based on the previously active theme, #and makes the new theme active if self.themeIsBuiltin.get(): - themeType='default' - themeName=self.builtinTheme.get() + themeType = 'default' + themeName = self.builtinTheme.get() else: - themeType='user' - themeName=self.customTheme.get() - newTheme=idleConf.GetThemeDict(themeType,themeName) + themeType = 'user' + themeName = self.customTheme.get() + newTheme = idleConf.GetThemeDict(themeType, themeName) #apply any of the old theme's unsaved changes to the new theme if themeName in self.changedItems['highlight']: - themeChanges=self.changedItems['highlight'][themeName] + themeChanges = self.changedItems['highlight'][themeName] for element in themeChanges: - newTheme[element]=themeChanges[element] + newTheme[element] = themeChanges[element] #save the new theme - self.SaveNewTheme(newThemeName,newTheme) + self.SaveNewTheme(newThemeName, newTheme) #change gui over to the new theme - customThemeList=idleConf.GetSectionList('user','highlight') + customThemeList = idleConf.GetSectionList('user', 'highlight') customThemeList.sort() - self.optMenuThemeCustom.SetMenu(customThemeList,newThemeName) + self.optMenuThemeCustom.SetMenu(customThemeList, newThemeName) self.themeIsBuiltin.set(0) self.SetThemeType() - def OnListFontButtonRelease(self,event): + def OnListFontButtonRelease(self, event): font = self.listFontName.get(ANCHOR) self.fontName.set(font.lower()) self.SetFontSample() - def SetFontSample(self,event=None): - fontName=self.fontName.get() - if self.fontBold.get(): - fontWeight=tkFont.BOLD - else: - fontWeight=tkFont.NORMAL + def SetFontSample(self, event=None): + fontName = self.fontName.get() + fontWeight = tkFont.BOLD if self.fontBold.get() else tkFont.NORMAL newFont = (fontName, self.fontSize.get(), fontWeight) self.labelFontSample.config(font=newFont) self.textHighlightSample.configure(font=newFont) def SetHighlightTarget(self): - if self.highlightTarget.get()=='Cursor': #bg not possible + if self.highlightTarget.get() == 'Cursor': #bg not possible self.radioFg.config(state=DISABLED) self.radioBg.config(state=DISABLED) self.fgHilite.set(1) - else: #both fg and bg can be set + else: #both fg and bg can be set self.radioFg.config(state=NORMAL) self.radioBg.config(state=NORMAL) self.fgHilite.set(1) self.SetColourSample() - def SetColourSampleBinding(self,*args): + def SetColourSampleBinding(self, *args): self.SetColourSample() def SetColourSample(self): #set the colour smaple area - tag=self.themeElements[self.highlightTarget.get()][0] - if self.fgHilite.get(): plane='foreground' - else: plane='background' - colour=self.textHighlightSample.tag_cget(tag,plane) + tag = self.themeElements[self.highlightTarget.get()][0] + plane = 'foreground' if self.fgHilite.get() else 'background' + colour = self.textHighlightSample.tag_cget(tag, plane) self.frameColourSet.config(bg=colour) def PaintThemeSample(self): - if self.themeIsBuiltin.get(): #a default theme - theme=self.builtinTheme.get() - else: #a user theme - theme=self.customTheme.get() + if self.themeIsBuiltin.get(): #a default theme + theme = self.builtinTheme.get() + else: #a user theme + theme = self.customTheme.get() for elementTitle in self.themeElements: - element=self.themeElements[elementTitle][0] - colours=idleConf.GetHighlight(theme,element) - if element=='cursor': #cursor sample needs special painting - colours['background']=idleConf.GetHighlight(theme, - 'normal', fgBg='bg') + element = self.themeElements[elementTitle][0] + colours = idleConf.GetHighlight(theme, element) + if element == 'cursor': #cursor sample needs special painting + colours['background'] = idleConf.GetHighlight( + theme, 'normal', fgBg='bg') #handle any unsaved changes to this theme if theme in self.changedItems['highlight']: - themeDict=self.changedItems['highlight'][theme] - if element+'-foreground' in themeDict: - colours['foreground']=themeDict[element+'-foreground'] - if element+'-background' in themeDict: - colours['background']=themeDict[element+'-background'] + themeDict = self.changedItems['highlight'][theme] + if element + '-foreground' in themeDict: + colours['foreground'] = themeDict[element + '-foreground'] + if element + '-background' in themeDict: + colours['background'] = themeDict[element + '-background'] self.textHighlightSample.tag_config(element, **colours) self.SetColourSample() - def HelpSourceSelected(self,event): + def HelpSourceSelected(self, event): self.SetHelpListButtonStates() def SetHelpListButtonStates(self): - if self.listHelp.size()<1: #no entries in list + if self.listHelp.size() < 1: #no entries in list self.buttonHelpListEdit.config(state=DISABLED) self.buttonHelpListRemove.config(state=DISABLED) else: #there are some entries - if self.listHelp.curselection(): #there currently is a selection + if self.listHelp.curselection(): #there currently is a selection self.buttonHelpListEdit.config(state=NORMAL) self.buttonHelpListRemove.config(state=NORMAL) else: #there currently is not a selection @@ -898,28 +930,29 @@ self.buttonHelpListRemove.config(state=DISABLED) def HelpListItemAdd(self): - helpSource=GetHelpSourceDialog(self,'New Help Source').result + helpSource = GetHelpSourceDialog(self, 'New Help Source').result if helpSource: - self.userHelpList.append( (helpSource[0],helpSource[1]) ) - self.listHelp.insert(END,helpSource[0]) + self.userHelpList.append((helpSource[0], helpSource[1])) + self.listHelp.insert(END, helpSource[0]) self.UpdateUserHelpChangedItems() self.SetHelpListButtonStates() def HelpListItemEdit(self): - itemIndex=self.listHelp.index(ANCHOR) - helpSource=self.userHelpList[itemIndex] - newHelpSource=GetHelpSourceDialog(self,'Edit Help Source', - menuItem=helpSource[0],filePath=helpSource[1]).result - if (not newHelpSource) or (newHelpSource==helpSource): + itemIndex = self.listHelp.index(ANCHOR) + helpSource = self.userHelpList[itemIndex] + newHelpSource = GetHelpSourceDialog( + self, 'Edit Help Source', menuItem=helpSource[0], + filePath=helpSource[1]).result + if (not newHelpSource) or (newHelpSource == helpSource): return #no changes - self.userHelpList[itemIndex]=newHelpSource + self.userHelpList[itemIndex] = newHelpSource self.listHelp.delete(itemIndex) - self.listHelp.insert(itemIndex,newHelpSource[0]) + self.listHelp.insert(itemIndex, newHelpSource[0]) self.UpdateUserHelpChangedItems() self.SetHelpListButtonStates() def HelpListItemRemove(self): - itemIndex=self.listHelp.index(ANCHOR) + itemIndex = self.listHelp.index(ANCHOR) del(self.userHelpList[itemIndex]) self.listHelp.delete(itemIndex) self.UpdateUserHelpChangedItems() @@ -928,18 +961,19 @@ def UpdateUserHelpChangedItems(self): "Clear and rebuild the HelpFiles section in self.changedItems" self.changedItems['main']['HelpFiles'] = {} - for num in range(1,len(self.userHelpList)+1): - self.AddChangedItem('main','HelpFiles',str(num), + for num in range(1, len(self.userHelpList) + 1): + self.AddChangedItem( + 'main', 'HelpFiles', str(num), ';'.join(self.userHelpList[num-1][:2])) def LoadFontCfg(self): ##base editor font selection list - fonts=list(tkFont.families(self)) + fonts = list(tkFont.families(self)) fonts.sort() for font in fonts: - self.listFontName.insert(END,font) - configuredFont=idleConf.GetOption('main','EditorWindow','font', - default='courier') + self.listFontName.insert(END, font) + configuredFont = idleConf.GetOption( + 'main', 'EditorWindow', 'font', default='courier') lc_configuredFont = configuredFont.lower() self.fontName.set(lc_configuredFont) lc_fonts = [s.lower() for s in fonts] @@ -949,107 +983,107 @@ self.listFontName.select_set(currentFontIndex) self.listFontName.select_anchor(currentFontIndex) ##font size dropdown - fontSize=idleConf.GetOption('main', 'EditorWindow', 'font-size', - type='int', default='10') - self.optMenuFontSize.SetMenu(('7','8','9','10','11','12','13','14', - '16','18','20','22'), fontSize ) + fontSize = idleConf.GetOption( + 'main', 'EditorWindow', 'font-size', type='int', default='10') + self.optMenuFontSize.SetMenu(('7', '8', '9', '10', '11', '12', '13', + '14', '16', '18', '20', '22'), fontSize ) ##fontWeight - self.fontBold.set(idleConf.GetOption('main','EditorWindow', - 'font-bold',default=0,type='bool')) + self.fontBold.set(idleConf.GetOption( + 'main', 'EditorWindow', 'font-bold', default=0, type='bool')) ##font sample self.SetFontSample() def LoadTabCfg(self): ##indent sizes - spaceNum=idleConf.GetOption('main','Indent','num-spaces', - default=4,type='int') + spaceNum = idleConf.GetOption( + 'main', 'Indent', 'num-spaces', default=4, type='int') self.spaceNum.set(spaceNum) def LoadThemeCfg(self): ##current theme type radiobutton - self.themeIsBuiltin.set(idleConf.GetOption('main','Theme','default', - type='bool',default=1)) + self.themeIsBuiltin.set(idleConf.GetOption( + 'main', 'Theme', 'default', type='bool', default=1)) ##currently set theme - currentOption=idleConf.CurrentTheme() + currentOption = idleConf.CurrentTheme() ##load available theme option menus if self.themeIsBuiltin.get(): #default theme selected - itemList=idleConf.GetSectionList('default','highlight') + itemList = idleConf.GetSectionList('default', 'highlight') itemList.sort() - self.optMenuThemeBuiltin.SetMenu(itemList,currentOption) - itemList=idleConf.GetSectionList('user','highlight') + self.optMenuThemeBuiltin.SetMenu(itemList, currentOption) + itemList = idleConf.GetSectionList('user', 'highlight') itemList.sort() if not itemList: self.radioThemeCustom.config(state=DISABLED) self.customTheme.set('- no custom themes -') else: - self.optMenuThemeCustom.SetMenu(itemList,itemList[0]) + self.optMenuThemeCustom.SetMenu(itemList, itemList[0]) else: #user theme selected - itemList=idleConf.GetSectionList('user','highlight') + itemList = idleConf.GetSectionList('user', 'highlight') itemList.sort() - self.optMenuThemeCustom.SetMenu(itemList,currentOption) - itemList=idleConf.GetSectionList('default','highlight') + self.optMenuThemeCustom.SetMenu(itemList, currentOption) + itemList = idleConf.GetSectionList('default', 'highlight') itemList.sort() - self.optMenuThemeBuiltin.SetMenu(itemList,itemList[0]) + self.optMenuThemeBuiltin.SetMenu(itemList, itemList[0]) self.SetThemeType() ##load theme element option menu themeNames = list(self.themeElements.keys()) themeNames.sort(key=lambda x: self.themeElements[x][1]) - self.optMenuHighlightTarget.SetMenu(themeNames,themeNames[0]) + self.optMenuHighlightTarget.SetMenu(themeNames, themeNames[0]) self.PaintThemeSample() self.SetHighlightTarget() def LoadKeyCfg(self): ##current keys type radiobutton - self.keysAreBuiltin.set(idleConf.GetOption('main','Keys','default', - type='bool',default=1)) + self.keysAreBuiltin.set(idleConf.GetOption( + 'main', 'Keys', 'default', type='bool', default=1)) ##currently set keys - currentOption=idleConf.CurrentKeys() + currentOption = idleConf.CurrentKeys() ##load available keyset option menus if self.keysAreBuiltin.get(): #default theme selected - itemList=idleConf.GetSectionList('default','keys') + itemList = idleConf.GetSectionList('default', 'keys') itemList.sort() - self.optMenuKeysBuiltin.SetMenu(itemList,currentOption) - itemList=idleConf.GetSectionList('user','keys') + self.optMenuKeysBuiltin.SetMenu(itemList, currentOption) + itemList = idleConf.GetSectionList('user', 'keys') itemList.sort() if not itemList: self.radioKeysCustom.config(state=DISABLED) self.customKeys.set('- no custom keys -') else: - self.optMenuKeysCustom.SetMenu(itemList,itemList[0]) + self.optMenuKeysCustom.SetMenu(itemList, itemList[0]) else: #user key set selected - itemList=idleConf.GetSectionList('user','keys') + itemList = idleConf.GetSectionList('user', 'keys') itemList.sort() - self.optMenuKeysCustom.SetMenu(itemList,currentOption) - itemList=idleConf.GetSectionList('default','keys') + self.optMenuKeysCustom.SetMenu(itemList, currentOption) + itemList = idleConf.GetSectionList('default', 'keys') itemList.sort() - self.optMenuKeysBuiltin.SetMenu(itemList,itemList[0]) + self.optMenuKeysBuiltin.SetMenu(itemList, itemList[0]) self.SetKeysType() ##load keyset element list - keySetName=idleConf.CurrentKeys() + keySetName = idleConf.CurrentKeys() self.LoadKeysList(keySetName) def LoadGeneralCfg(self): #startup state - self.startupEdit.set(idleConf.GetOption('main','General', - 'editor-on-startup',default=1,type='bool')) + self.startupEdit.set(idleConf.GetOption( + 'main', 'General', 'editor-on-startup', default=1, type='bool')) #autosave state - self.autoSave.set(idleConf.GetOption('main', 'General', 'autosave', - default=0, type='bool')) + self.autoSave.set(idleConf.GetOption( + 'main', 'General', 'autosave', default=0, type='bool')) #initial window size - self.winWidth.set(idleConf.GetOption('main','EditorWindow','width', - type='int')) - self.winHeight.set(idleConf.GetOption('main','EditorWindow','height', - type='int')) + self.winWidth.set(idleConf.GetOption( + 'main', 'EditorWindow', 'width', type='int')) + self.winHeight.set(idleConf.GetOption( + 'main', 'EditorWindow', 'height', type='int')) #initial paragraph reformat size - self.paraWidth.set(idleConf.GetOption('main','FormatParagraph','paragraph', - type='int')) + self.paraWidth.set(idleConf.GetOption( + 'main', 'FormatParagraph', 'paragraph', type='int')) # default source encoding - self.encoding.set(idleConf.GetOption('main', 'EditorWindow', - 'encoding', default='none')) + self.encoding.set(idleConf.GetOption( + 'main', 'EditorWindow', 'encoding', default='none')) # additional help sources self.userHelpList = idleConf.GetAllExtraHelpSourcesList() for helpItem in self.userHelpList: - self.listHelp.insert(END,helpItem[0]) + self.listHelp.insert(END, helpItem[0]) self.SetHelpListButtonStates() def LoadConfigs(self): @@ -1067,7 +1101,7 @@ ### general page self.LoadGeneralCfg() - def SaveNewKeySet(self,keySetName,keySet): + def SaveNewKeySet(self, keySetName, keySet): """ save a newly created core key set. keySetName - string, the name of the new key set @@ -1076,10 +1110,10 @@ if not idleConf.userCfg['keys'].has_section(keySetName): idleConf.userCfg['keys'].add_section(keySetName) for event in keySet: - value=keySet[event] - idleConf.userCfg['keys'].SetOption(keySetName,event,value) + value = keySet[event] + idleConf.userCfg['keys'].SetOption(keySetName, event, value) - def SaveNewTheme(self,themeName,theme): + def SaveNewTheme(self, themeName, theme): """ save a newly created theme. themeName - string, the name of the new theme @@ -1088,16 +1122,16 @@ if not idleConf.userCfg['highlight'].has_section(themeName): idleConf.userCfg['highlight'].add_section(themeName) for element in theme: - value=theme[element] - idleConf.userCfg['highlight'].SetOption(themeName,element,value) + value = theme[element] + idleConf.userCfg['highlight'].SetOption(themeName, element, value) - def SetUserValue(self,configType,section,item,value): - if idleConf.defaultCfg[configType].has_option(section,item): - if idleConf.defaultCfg[configType].Get(section,item)==value: + def SetUserValue(self, configType, section, item, value): + if idleConf.defaultCfg[configType].has_option(section, item): + if idleConf.defaultCfg[configType].Get(section, item) == value: #the setting equals a default setting, remove it from user cfg - return idleConf.userCfg[configType].RemoveOption(section,item) + return idleConf.userCfg[configType].RemoveOption(section, item) #if we got here set the option - return idleConf.userCfg[configType].SetOption(section,item,value) + return idleConf.userCfg[configType].SetOption(section, item, value) def SaveAllChangedConfigs(self): "Save configuration changes to the user config file." @@ -1111,7 +1145,7 @@ cfgTypeHasChanges = True for item in self.changedItems[configType][section]: value = self.changedItems[configType][section][item] - if self.SetUserValue(configType,section,item,value): + if self.SetUserValue(configType, section, item, value): cfgTypeHasChanges = True if cfgTypeHasChanges: idleConf.userCfg[configType].Save() -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Aug 4 07:36:39 2014 From: python-checkins at python.org (raymond.hettinger) Date: Mon, 4 Aug 2014 07:36:39 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Use_reversed=28=29_instead?= =?utf-8?q?_of_creating_a_new_temporary_list=2E?= Message-ID: <3hRSWq1lylz7LjW@mail.python.org> http://hg.python.org/cpython/rev/d2c71c4385ff changeset: 91981:d2c71c4385ff user: Raymond Hettinger date: Sun Aug 03 22:36:32 2014 -0700 summary: Use reversed() instead of creating a new temporary list. files: Lib/difflib.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/difflib.py b/Lib/difflib.py --- a/Lib/difflib.py +++ b/Lib/difflib.py @@ -1410,7 +1410,7 @@ change_re.sub(record_sub_info,markers) # process each tuple inserting our special marks that won't be # noticed by an xml/html escaper. - for key,(begin,end) in sub_info[::-1]: + for key,(begin,end) in reversed(sub_info): text = text[0:begin]+'\0'+key+text[begin:end]+'\1'+text[end:] text = text[2:] # Handle case of add/delete entire line -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Aug 4 07:41:06 2014 From: python-checkins at python.org (raymond.hettinger) Date: Mon, 4 Aug 2014 07:41:06 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Make_the_import_private_to?= =?utf-8?q?_keep_the_global_namespace_clean=2E?= Message-ID: <3hRScy059Vz7LjZ@mail.python.org> http://hg.python.org/cpython/rev/484e86c57298 changeset: 91982:484e86c57298 user: Raymond Hettinger date: Sun Aug 03 22:40:59 2014 -0700 summary: Make the import private to keep the global namespace clean. files: Lib/difflib.py | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/difflib.py b/Lib/difflib.py --- a/Lib/difflib.py +++ b/Lib/difflib.py @@ -30,7 +30,7 @@ 'Differ','IS_CHARACTER_JUNK', 'IS_LINE_JUNK', 'context_diff', 'unified_diff', 'HtmlDiff', 'Match'] -import heapq +from heapq import nlargest as _nlargest from collections import namedtuple as _namedtuple Match = _namedtuple('Match', 'a b size') @@ -729,7 +729,7 @@ result.append((s.ratio(), x)) # Move the best scorers to head of list - result = heapq.nlargest(n, result) + result = _nlargest(n, result) # Strip scores for the best n matches return [x for score, x in result] -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Aug 4 07:49:14 2014 From: python-checkins at python.org (raymond.hettinger) Date: Mon, 4 Aug 2014 07:49:14 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Use_two-argument_form_of_n?= =?utf-8?q?ext=28=29_and_use_a_return-statement_instead_of_an?= Message-ID: <3hRSpL6Ng5z7LjZ@mail.python.org> http://hg.python.org/cpython/rev/d7d5572edb15 changeset: 91983:d7d5572edb15 user: Raymond Hettinger date: Sun Aug 03 22:49:07 2014 -0700 summary: Use two-argument form of next() and use a return-statement instead of an explicit raise StopIteration files: Lib/difflib.py | 7 ++----- 1 files changed, 2 insertions(+), 5 deletions(-) diff --git a/Lib/difflib.py b/Lib/difflib.py --- a/Lib/difflib.py +++ b/Lib/difflib.py @@ -1448,10 +1448,7 @@ # are a concatenation of the first character of each of the 4 lines # so we can do some very readable comparisons. while len(lines) < 4: - try: - lines.append(next(diff_lines_iterator)) - except StopIteration: - lines.append('X') + lines.append(next(diff_lines_iterator, 'X')) s = ''.join([line[0] for line in lines]) if s.startswith('X'): # When no more lines, pump out any remaining blank lines so the @@ -1514,7 +1511,7 @@ num_blanks_to_yield -= 1 yield ('','\n'),None,True if s.startswith('X'): - raise StopIteration + return else: yield from_line,to_line,True -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Aug 4 08:39:26 2014 From: python-checkins at python.org (raymond.hettinger) Date: Mon, 4 Aug 2014 08:39:26 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E4=29=3A_Improve_regex_?= =?utf-8?q?tokenizer_example_by_using_re=2Efinditer=28=29=2E?= Message-ID: <3hRTwG4nqBz7LjW@mail.python.org> http://hg.python.org/cpython/rev/3bb625249bb7 changeset: 91984:3bb625249bb7 branch: 3.4 parent: 91979:b5466a75e203 user: Raymond Hettinger date: Sun Aug 03 23:38:54 2014 -0700 summary: Improve regex tokenizer example by using re.finditer(). Also, improve variable names and fix column numbers in the generated output. files: Doc/library/re.rst | 75 +++++++++++++++++---------------- 1 files changed, 38 insertions(+), 37 deletions(-) diff --git a/Doc/library/re.rst b/Doc/library/re.rst --- a/Doc/library/re.rst +++ b/Doc/library/re.rst @@ -1333,7 +1333,7 @@ Token = collections.namedtuple('Token', ['typ', 'value', 'line', 'column']) - def tokenize(s): + def tokenize(code): keywords = {'IF', 'THEN', 'ENDIF', 'FOR', 'NEXT', 'GOSUB', 'RETURN'} token_specification = [ ('NUMBER', r'\d+(\.\d*)?'), # Integer or decimal number @@ -1343,26 +1343,27 @@ ('OP', r'[+\-*/]'), # Arithmetic operators ('NEWLINE', r'\n'), # Line endings ('SKIP', r'[ \t]+'), # Skip over spaces and tabs + ('MISMATCH',r'.'), # Any other character ] tok_regex = '|'.join('(?P<%s>%s)' % pair for pair in token_specification) get_token = re.compile(tok_regex).match - line = 1 - pos = line_start = 0 - mo = get_token(s) - while mo is not None: - typ = mo.lastgroup - if typ == 'NEWLINE': - line_start = pos - line += 1 - elif typ != 'SKIP': - val = mo.group(typ) - if typ == 'ID' and val in keywords: - typ = val - yield Token(typ, val, line, mo.start()-line_start) - pos = mo.end() - mo = get_token(s, pos) - if pos != len(s): - raise RuntimeError('Unexpected character %r on line %d' %(s[pos], line)) + line_num = 1 + line_start = 0 + for mo in re.finditer(tok_regex, code): + kind = mo.lastgroup + value = mo.group(kind) + if kind == 'NEWLINE': + line_start = mo.end() + line_num += 1 + elif kind == 'SKIP': + pass + elif kind == 'MISMATCH': + raise RuntimeError('%r unexpected on line %d' % (value, line_num)) + else: + if kind == 'ID' and value in keywords: + kind = value + column = mo.start() - line_start + yield Token(kind, value, line_num, column) statements = ''' IF quantity THEN @@ -1376,22 +1377,22 @@ The tokenizer produces the following output:: - Token(typ='IF', value='IF', line=2, column=5) - Token(typ='ID', value='quantity', line=2, column=8) - Token(typ='THEN', value='THEN', line=2, column=17) - Token(typ='ID', value='total', line=3, column=9) - Token(typ='ASSIGN', value=':=', line=3, column=15) - Token(typ='ID', value='total', line=3, column=18) - Token(typ='OP', value='+', line=3, column=24) - Token(typ='ID', value='price', line=3, column=26) - Token(typ='OP', value='*', line=3, column=32) - Token(typ='ID', value='quantity', line=3, column=34) - Token(typ='END', value=';', line=3, column=42) - Token(typ='ID', value='tax', line=4, column=9) - Token(typ='ASSIGN', value=':=', line=4, column=13) - Token(typ='ID', value='price', line=4, column=16) - Token(typ='OP', value='*', line=4, column=22) - Token(typ='NUMBER', value='0.05', line=4, column=24) - Token(typ='END', value=';', line=4, column=28) - Token(typ='ENDIF', value='ENDIF', line=5, column=5) - Token(typ='END', value=';', line=5, column=10) + Token(typ='IF', value='IF', line=2, column=4) + Token(typ='ID', value='quantity', line=2, column=7) + Token(typ='THEN', value='THEN', line=2, column=16) + Token(typ='ID', value='total', line=3, column=8) + Token(typ='ASSIGN', value=':=', line=3, column=14) + Token(typ='ID', value='total', line=3, column=17) + Token(typ='OP', value='+', line=3, column=23) + Token(typ='ID', value='price', line=3, column=25) + Token(typ='OP', value='*', line=3, column=31) + Token(typ='ID', value='quantity', line=3, column=33) + Token(typ='END', value=';', line=3, column=41) + Token(typ='ID', value='tax', line=4, column=8) + Token(typ='ASSIGN', value=':=', line=4, column=12) + Token(typ='ID', value='price', line=4, column=15) + Token(typ='OP', value='*', line=4, column=21) + Token(typ='NUMBER', value='0.05', line=4, column=23) + Token(typ='END', value=';', line=4, column=27) + Token(typ='ENDIF', value='ENDIF', line=5, column=4) + Token(typ='END', value=';', line=5, column=9) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Aug 4 08:39:28 2014 From: python-checkins at python.org (raymond.hettinger) Date: Mon, 4 Aug 2014 08:39:28 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_merge?= Message-ID: <3hRTwJ0pKtz7LjW@mail.python.org> http://hg.python.org/cpython/rev/90db391ce7a5 changeset: 91985:90db391ce7a5 parent: 91983:d7d5572edb15 parent: 91984:3bb625249bb7 user: Raymond Hettinger date: Sun Aug 03 23:39:20 2014 -0700 summary: merge files: Doc/library/re.rst | 75 +++++++++++++++++---------------- 1 files changed, 38 insertions(+), 37 deletions(-) diff --git a/Doc/library/re.rst b/Doc/library/re.rst --- a/Doc/library/re.rst +++ b/Doc/library/re.rst @@ -1333,7 +1333,7 @@ Token = collections.namedtuple('Token', ['typ', 'value', 'line', 'column']) - def tokenize(s): + def tokenize(code): keywords = {'IF', 'THEN', 'ENDIF', 'FOR', 'NEXT', 'GOSUB', 'RETURN'} token_specification = [ ('NUMBER', r'\d+(\.\d*)?'), # Integer or decimal number @@ -1343,26 +1343,27 @@ ('OP', r'[+\-*/]'), # Arithmetic operators ('NEWLINE', r'\n'), # Line endings ('SKIP', r'[ \t]+'), # Skip over spaces and tabs + ('MISMATCH',r'.'), # Any other character ] tok_regex = '|'.join('(?P<%s>%s)' % pair for pair in token_specification) get_token = re.compile(tok_regex).match - line = 1 - pos = line_start = 0 - mo = get_token(s) - while mo is not None: - typ = mo.lastgroup - if typ == 'NEWLINE': - line_start = pos - line += 1 - elif typ != 'SKIP': - val = mo.group(typ) - if typ == 'ID' and val in keywords: - typ = val - yield Token(typ, val, line, mo.start()-line_start) - pos = mo.end() - mo = get_token(s, pos) - if pos != len(s): - raise RuntimeError('Unexpected character %r on line %d' %(s[pos], line)) + line_num = 1 + line_start = 0 + for mo in re.finditer(tok_regex, code): + kind = mo.lastgroup + value = mo.group(kind) + if kind == 'NEWLINE': + line_start = mo.end() + line_num += 1 + elif kind == 'SKIP': + pass + elif kind == 'MISMATCH': + raise RuntimeError('%r unexpected on line %d' % (value, line_num)) + else: + if kind == 'ID' and value in keywords: + kind = value + column = mo.start() - line_start + yield Token(kind, value, line_num, column) statements = ''' IF quantity THEN @@ -1376,22 +1377,22 @@ The tokenizer produces the following output:: - Token(typ='IF', value='IF', line=2, column=5) - Token(typ='ID', value='quantity', line=2, column=8) - Token(typ='THEN', value='THEN', line=2, column=17) - Token(typ='ID', value='total', line=3, column=9) - Token(typ='ASSIGN', value=':=', line=3, column=15) - Token(typ='ID', value='total', line=3, column=18) - Token(typ='OP', value='+', line=3, column=24) - Token(typ='ID', value='price', line=3, column=26) - Token(typ='OP', value='*', line=3, column=32) - Token(typ='ID', value='quantity', line=3, column=34) - Token(typ='END', value=';', line=3, column=42) - Token(typ='ID', value='tax', line=4, column=9) - Token(typ='ASSIGN', value=':=', line=4, column=13) - Token(typ='ID', value='price', line=4, column=16) - Token(typ='OP', value='*', line=4, column=22) - Token(typ='NUMBER', value='0.05', line=4, column=24) - Token(typ='END', value=';', line=4, column=28) - Token(typ='ENDIF', value='ENDIF', line=5, column=5) - Token(typ='END', value=';', line=5, column=10) + Token(typ='IF', value='IF', line=2, column=4) + Token(typ='ID', value='quantity', line=2, column=7) + Token(typ='THEN', value='THEN', line=2, column=16) + Token(typ='ID', value='total', line=3, column=8) + Token(typ='ASSIGN', value=':=', line=3, column=14) + Token(typ='ID', value='total', line=3, column=17) + Token(typ='OP', value='+', line=3, column=23) + Token(typ='ID', value='price', line=3, column=25) + Token(typ='OP', value='*', line=3, column=31) + Token(typ='ID', value='quantity', line=3, column=33) + Token(typ='END', value=';', line=3, column=41) + Token(typ='ID', value='tax', line=4, column=8) + Token(typ='ASSIGN', value=':=', line=4, column=12) + Token(typ='ID', value='price', line=4, column=15) + Token(typ='OP', value='*', line=4, column=21) + Token(typ='NUMBER', value='0.05', line=4, column=23) + Token(typ='END', value=';', line=4, column=27) + Token(typ='ENDIF', value='ENDIF', line=5, column=4) + Token(typ='END', value=';', line=5, column=9) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Aug 4 08:45:06 2014 From: python-checkins at python.org (raymond.hettinger) Date: Mon, 4 Aug 2014 08:45:06 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E4=29=3A_Fix_markup=2E?= Message-ID: <3hRV2p2mdyzSn4@mail.python.org> http://hg.python.org/cpython/rev/42ca62b6547a changeset: 91986:42ca62b6547a branch: 3.4 parent: 91984:3bb625249bb7 user: Raymond Hettinger date: Sun Aug 03 23:44:30 2014 -0700 summary: Fix markup. files: Doc/library/argparse.rst | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/library/argparse.rst b/Doc/library/argparse.rst --- a/Doc/library/argparse.rst +++ b/Doc/library/argparse.rst @@ -1235,7 +1235,7 @@ Action classes implement the Action API, a callable which returns a callable which processes arguments from the command-line. Any object which follows this API may be passed as the ``action`` parameter to -:method:`add_argument`. +:meth:`add_argument`. .. class:: Action(option_strings, dest, nargs=None, const=None, default=None, type=None, choices=None, required=False, help=None, @@ -1244,7 +1244,7 @@ Action objects are used by an ArgumentParser to represent the information needed to parse a single argument from one or more strings from the command line. The Action class must accept the two positional arguments -plus any keyword arguments passed to :method:`ArgumentParser.add_argument` +plus any keyword arguments passed to :meth:`ArgumentParser.add_argument` except for the ``action`` itself. Instances of Action (or return value of any callable to the ``action`` -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Aug 4 08:45:07 2014 From: python-checkins at python.org (raymond.hettinger) Date: Mon, 4 Aug 2014 08:45:07 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_merge?= Message-ID: <3hRV2q4lj3zSn4@mail.python.org> http://hg.python.org/cpython/rev/65018d952340 changeset: 91987:65018d952340 parent: 91985:90db391ce7a5 parent: 91986:42ca62b6547a user: Raymond Hettinger date: Sun Aug 03 23:44:59 2014 -0700 summary: merge files: Doc/library/argparse.rst | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/library/argparse.rst b/Doc/library/argparse.rst --- a/Doc/library/argparse.rst +++ b/Doc/library/argparse.rst @@ -1235,7 +1235,7 @@ Action classes implement the Action API, a callable which returns a callable which processes arguments from the command-line. Any object which follows this API may be passed as the ``action`` parameter to -:method:`add_argument`. +:meth:`add_argument`. .. class:: Action(option_strings, dest, nargs=None, const=None, default=None, type=None, choices=None, required=False, help=None, @@ -1244,7 +1244,7 @@ Action objects are used by an ArgumentParser to represent the information needed to parse a single argument from one or more strings from the command line. The Action class must accept the two positional arguments -plus any keyword arguments passed to :method:`ArgumentParser.add_argument` +plus any keyword arguments passed to :meth:`ArgumentParser.add_argument` except for the ``action`` itself. Instances of Action (or return value of any callable to the ``action`` -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Aug 4 09:21:42 2014 From: python-checkins at python.org (raymond.hettinger) Date: Mon, 4 Aug 2014 09:21:42 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E4=29=3A_Remove_unused_?= =?utf-8?q?leftover_stray_line?= Message-ID: <3hRVs20p4Vz7Lmv@mail.python.org> http://hg.python.org/cpython/rev/a42f14ff0f9a changeset: 91988:a42f14ff0f9a branch: 3.4 parent: 91986:42ca62b6547a user: Raymond Hettinger date: Mon Aug 04 00:21:11 2014 -0700 summary: Remove unused leftover stray line files: Doc/library/re.rst | 1 - 1 files changed, 0 insertions(+), 1 deletions(-) diff --git a/Doc/library/re.rst b/Doc/library/re.rst --- a/Doc/library/re.rst +++ b/Doc/library/re.rst @@ -1346,7 +1346,6 @@ ('MISMATCH',r'.'), # Any other character ] tok_regex = '|'.join('(?P<%s>%s)' % pair for pair in token_specification) - get_token = re.compile(tok_regex).match line_num = 1 line_start = 0 for mo in re.finditer(tok_regex, code): -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Aug 4 09:21:43 2014 From: python-checkins at python.org (raymond.hettinger) Date: Mon, 4 Aug 2014 09:21:43 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_merge?= Message-ID: <3hRVs32kk7z7Lp3@mail.python.org> http://hg.python.org/cpython/rev/a64806257119 changeset: 91989:a64806257119 parent: 91987:65018d952340 parent: 91988:a42f14ff0f9a user: Raymond Hettinger date: Mon Aug 04 00:21:36 2014 -0700 summary: merge files: Doc/library/re.rst | 1 - 1 files changed, 0 insertions(+), 1 deletions(-) diff --git a/Doc/library/re.rst b/Doc/library/re.rst --- a/Doc/library/re.rst +++ b/Doc/library/re.rst @@ -1346,7 +1346,6 @@ ('MISMATCH',r'.'), # Any other character ] tok_regex = '|'.join('(?P<%s>%s)' % pair for pair in token_specification) - get_token = re.compile(tok_regex).match line_num = 1 line_start = 0 for mo in re.finditer(tok_regex, code): -- Repository URL: http://hg.python.org/cpython From solipsis at pitrou.net Mon Aug 4 10:31:26 2014 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Mon, 04 Aug 2014 10:31:26 +0200 Subject: [Python-checkins] Daily reference leaks (a2d01ed713cb): sum=-337 Message-ID: results for a2d01ed713cb on branch "default" -------------------------------------------- test_asyncio leaked [-318, -106, 159] references, sum=-265 test_asyncio leaked [-90, -28, 47] memory blocks, sum=-71 test_collections leaked [-2, -2, 0] references, sum=-4 test_functools leaked [0, 0, 3] memory blocks, sum=3 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/cpython/refleaks/reflog2ES7Rl', '-x'] From python-checkins at python.org Mon Aug 4 16:02:10 2014 From: python-checkins at python.org (ezio.melotti) Date: Mon, 4 Aug 2014 16:02:10 +0200 (CEST) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogIzE4NTg4OiB1cGRh?= =?utf-8?q?te_the_timeit_examples_to_be_consistent=2E?= Message-ID: <3hRgl655gmz7LmD@mail.python.org> http://hg.python.org/cpython/rev/c39457a07caa changeset: 91990:c39457a07caa branch: 3.4 parent: 91988:a42f14ff0f9a user: Ezio Melotti date: Mon Aug 04 17:01:16 2014 +0300 summary: #18588: update the timeit examples to be consistent. files: Doc/library/timeit.rst | 19 ++++++++++--------- 1 files changed, 10 insertions(+), 9 deletions(-) diff --git a/Doc/library/timeit.rst b/Doc/library/timeit.rst --- a/Doc/library/timeit.rst +++ b/Doc/library/timeit.rst @@ -28,22 +28,23 @@ .. code-block:: sh - $ python -m timeit '"-".join(str(n) for n in range(100))' - 10000 loops, best of 3: 40.3 usec per loop - $ python -m timeit '"-".join([str(n) for n in range(100)])' - 10000 loops, best of 3: 33.4 usec per loop - $ python -m timeit '"-".join(map(str, range(100)))' - 10000 loops, best of 3: 25.2 usec per loop + $ python3 -m timeit '"-".join(str(n) for n in range(100))' + 10000 loops, best of 3: 30.2 usec per loop + $ python3 -m timeit '"-".join([str(n) for n in range(100)])' + 10000 loops, best of 3: 27.5 usec per loop + $ python3 -m timeit '"-".join(map(str, range(100)))' + 10000 loops, best of 3: 23.2 usec per loop This can be achieved from the :ref:`python-interface` with:: >>> import timeit >>> timeit.timeit('"-".join(str(n) for n in range(100))', number=10000) - 0.8187260627746582 + 0.3018611848820001 >>> timeit.timeit('"-".join([str(n) for n in range(100)])', number=10000) - 0.7288308143615723 + 0.2727368790656328 >>> timeit.timeit('"-".join(map(str, range(100)))', number=10000) - 0.5858950614929199 + 0.23702679807320237 + Note however that :mod:`timeit` will automatically determine the number of repetitions only when the command-line interface is used. In the -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Aug 4 16:02:11 2014 From: python-checkins at python.org (ezio.melotti) Date: Mon, 4 Aug 2014 16:02:11 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?b?KTogIzE4NTg4OiBtZXJnZSB3aXRoIDMuNC4=?= Message-ID: <3hRgl801p2z7Lps@mail.python.org> http://hg.python.org/cpython/rev/45b208ae9eab changeset: 91991:45b208ae9eab parent: 91989:a64806257119 parent: 91990:c39457a07caa user: Ezio Melotti date: Mon Aug 04 17:01:48 2014 +0300 summary: #18588: merge with 3.4. files: Doc/library/timeit.rst | 19 ++++++++++--------- 1 files changed, 10 insertions(+), 9 deletions(-) diff --git a/Doc/library/timeit.rst b/Doc/library/timeit.rst --- a/Doc/library/timeit.rst +++ b/Doc/library/timeit.rst @@ -28,22 +28,23 @@ .. code-block:: sh - $ python -m timeit '"-".join(str(n) for n in range(100))' - 10000 loops, best of 3: 40.3 usec per loop - $ python -m timeit '"-".join([str(n) for n in range(100)])' - 10000 loops, best of 3: 33.4 usec per loop - $ python -m timeit '"-".join(map(str, range(100)))' - 10000 loops, best of 3: 25.2 usec per loop + $ python3 -m timeit '"-".join(str(n) for n in range(100))' + 10000 loops, best of 3: 30.2 usec per loop + $ python3 -m timeit '"-".join([str(n) for n in range(100)])' + 10000 loops, best of 3: 27.5 usec per loop + $ python3 -m timeit '"-".join(map(str, range(100)))' + 10000 loops, best of 3: 23.2 usec per loop This can be achieved from the :ref:`python-interface` with:: >>> import timeit >>> timeit.timeit('"-".join(str(n) for n in range(100))', number=10000) - 0.8187260627746582 + 0.3018611848820001 >>> timeit.timeit('"-".join([str(n) for n in range(100)])', number=10000) - 0.7288308143615723 + 0.2727368790656328 >>> timeit.timeit('"-".join(map(str, range(100)))', number=10000) - 0.5858950614929199 + 0.23702679807320237 + Note however that :mod:`timeit` will automatically determine the number of repetitions only when the command-line interface is used. In the -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Aug 4 16:23:34 2014 From: python-checkins at python.org (ezio.melotti) Date: Mon, 4 Aug 2014 16:23:34 +0200 (CEST) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogIzIwOTc3OiBmaXgg?= =?utf-8?q?undefined_name_in_the_email_module=2E__Patch_by_Rose_Ames=2E?= Message-ID: <3hRhCp6p4vz7MRx@mail.python.org> http://hg.python.org/cpython/rev/9ec2b429a607 changeset: 91992:9ec2b429a607 branch: 3.4 parent: 91990:c39457a07caa user: Ezio Melotti date: Mon Aug 04 17:16:49 2014 +0300 summary: #20977: fix undefined name in the email module. Patch by Rose Ames. files: Lib/email/_header_value_parser.py | 6 ++-- Lib/test/test_email/test__header_value_parser.py | 12 ++++++++++ Misc/ACKS | 1 + 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/Lib/email/_header_value_parser.py b/Lib/email/_header_value_parser.py --- a/Lib/email/_header_value_parser.py +++ b/Lib/email/_header_value_parser.py @@ -2897,7 +2897,7 @@ try: token, value = get_token(value) except errors.HeaderParseError: - ctype.defects.append(errors.InvalidHeaderDefect( + disp_header.defects.append(errors.InvalidHeaderDefect( "Expected content disposition but found {!r}".format(value))) _find_mime_parameters(disp_header, value) return disp_header @@ -2928,8 +2928,8 @@ try: token, value = get_token(value) except errors.HeaderParseError: - ctype.defects.append(errors.InvalidHeaderDefect( - "Expected content trnasfer encoding but found {!r}".format(value))) + cte_header.defects.append(errors.InvalidHeaderDefect( + "Expected content transfer encoding but found {!r}".format(value))) else: cte_header.append(token) cte_header.cte = token.value.strip().lower() diff --git a/Lib/test/test_email/test__header_value_parser.py b/Lib/test/test_email/test__header_value_parser.py --- a/Lib/test/test_email/test__header_value_parser.py +++ b/Lib/test/test_email/test__header_value_parser.py @@ -2443,6 +2443,18 @@ self.assertEqual(str(address_list.addresses[1]), str(address_list.mailboxes[2])) + def test_invalid_content_disposition(self): + content_disp = self._test_parse_x( + parser.parse_content_disposition_header, + ";attachment", "; attachment", ";attachment", + [errors.InvalidHeaderDefect]*2 + ) + + def test_invalid_content_transfer_encoding(self): + cte = self._test_parse_x( + parser.parse_content_transfer_encoding_header, + ";foo", ";foo", ";foo", [errors.InvalidHeaderDefect]*3 + ) @parameterize class Test_parse_mime_version(TestParserMixin, TestEmailBase): diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -35,6 +35,7 @@ Kevin Altis Skyler Leigh Amador Joe Amenta +Rose Ames A. Amoroso Mark Anacker Shashwat Anand -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Aug 4 16:23:37 2014 From: python-checkins at python.org (ezio.melotti) Date: Mon, 4 Aug 2014 16:23:37 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?b?KTogIzIwOTc3OiBtZXJnZSB3aXRoIDMuNC4=?= Message-ID: <3hRhCs4m5qz7MSc@mail.python.org> http://hg.python.org/cpython/rev/944fc499ccd3 changeset: 91993:944fc499ccd3 parent: 91991:45b208ae9eab parent: 91992:9ec2b429a607 user: Ezio Melotti date: Mon Aug 04 17:17:21 2014 +0300 summary: #20977: merge with 3.4. files: Lib/email/_header_value_parser.py | 6 ++-- Lib/test/test_email/test__header_value_parser.py | 12 ++++++++++ Misc/ACKS | 1 + 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/Lib/email/_header_value_parser.py b/Lib/email/_header_value_parser.py --- a/Lib/email/_header_value_parser.py +++ b/Lib/email/_header_value_parser.py @@ -2897,7 +2897,7 @@ try: token, value = get_token(value) except errors.HeaderParseError: - ctype.defects.append(errors.InvalidHeaderDefect( + disp_header.defects.append(errors.InvalidHeaderDefect( "Expected content disposition but found {!r}".format(value))) _find_mime_parameters(disp_header, value) return disp_header @@ -2928,8 +2928,8 @@ try: token, value = get_token(value) except errors.HeaderParseError: - ctype.defects.append(errors.InvalidHeaderDefect( - "Expected content trnasfer encoding but found {!r}".format(value))) + cte_header.defects.append(errors.InvalidHeaderDefect( + "Expected content transfer encoding but found {!r}".format(value))) else: cte_header.append(token) cte_header.cte = token.value.strip().lower() diff --git a/Lib/test/test_email/test__header_value_parser.py b/Lib/test/test_email/test__header_value_parser.py --- a/Lib/test/test_email/test__header_value_parser.py +++ b/Lib/test/test_email/test__header_value_parser.py @@ -2443,6 +2443,18 @@ self.assertEqual(str(address_list.addresses[1]), str(address_list.mailboxes[2])) + def test_invalid_content_disposition(self): + content_disp = self._test_parse_x( + parser.parse_content_disposition_header, + ";attachment", "; attachment", ";attachment", + [errors.InvalidHeaderDefect]*2 + ) + + def test_invalid_content_transfer_encoding(self): + cte = self._test_parse_x( + parser.parse_content_transfer_encoding_header, + ";foo", ";foo", ";foo", [errors.InvalidHeaderDefect]*3 + ) @parameterize class Test_parse_mime_version(TestParserMixin, TestEmailBase): diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -35,6 +35,7 @@ Kevin Altis Skyler Leigh Amador Joe Amenta +Rose Ames A. Amoroso Mark Anacker Shashwat Anand -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Aug 4 18:19:12 2014 From: python-checkins at python.org (zach.ware) Date: Mon, 4 Aug 2014 18:19:12 +0200 (CEST) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzIyMTA0?= =?utf-8?q?=3A_Don=27t_hold_a_reference_to_the_loaded_TestSuite_in_runtest?= =?utf-8?q?=5Finner?= Message-ID: <3hRknD0T7hz7Lxk@mail.python.org> http://hg.python.org/cpython/rev/9bca86812857 changeset: 91994:9bca86812857 branch: 3.4 parent: 91992:9ec2b429a607 user: Zachary Ware date: Mon Aug 04 11:15:10 2014 -0500 summary: Issue #22104: Don't hold a reference to the loaded TestSuite in runtest_inner files: Lib/test/regrtest.py | 6 ++++-- Misc/NEWS | 3 +++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/Lib/test/regrtest.py b/Lib/test/regrtest.py --- a/Lib/test/regrtest.py +++ b/Lib/test/regrtest.py @@ -1273,8 +1273,10 @@ # tests. If not, use normal unittest test loading. test_runner = getattr(the_module, "test_main", None) if test_runner is None: - tests = unittest.TestLoader().loadTestsFromModule(the_module) - test_runner = lambda: support.run_unittest(tests) + def test_runner(): + loader = unittest.TestLoader() + tests = loader.loadTestsFromModule(the_module) + support.run_unittest(tests) test_runner() if huntrleaks: refleak = dash_R(the_module, test, test_runner, huntrleaks) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -239,6 +239,9 @@ Tests ----- +- Issue #22104: regrtest.py no longer holds a reference to the suite of tests + loaded from test modules that don't define test_main(). + - Issue #22002: Added ``load_package_tests`` function to test.support and used it to implement/augment test discovery in test_asyncio, test_email, test_importlib, test_json, and test_tools. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Aug 4 18:19:13 2014 From: python-checkins at python.org (zach.ware) Date: Mon, 4 Aug 2014 18:19:13 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Closes_=2322104=3A_Merge_with_3=2E4?= Message-ID: <3hRknF2fc5z7M2Q@mail.python.org> http://hg.python.org/cpython/rev/7bc53cf8b2df changeset: 91995:7bc53cf8b2df parent: 91993:944fc499ccd3 parent: 91994:9bca86812857 user: Zachary Ware date: Mon Aug 04 11:18:23 2014 -0500 summary: Closes #22104: Merge with 3.4 files: Lib/test/regrtest.py | 6 ++++-- Misc/NEWS | 3 +++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/Lib/test/regrtest.py b/Lib/test/regrtest.py --- a/Lib/test/regrtest.py +++ b/Lib/test/regrtest.py @@ -1273,8 +1273,10 @@ # tests. If not, use normal unittest test loading. test_runner = getattr(the_module, "test_main", None) if test_runner is None: - tests = unittest.TestLoader().loadTestsFromModule(the_module) - test_runner = lambda: support.run_unittest(tests) + def test_runner(): + loader = unittest.TestLoader() + tests = loader.loadTestsFromModule(the_module) + support.run_unittest(tests) test_runner() if huntrleaks: refleak = dash_R(the_module, test, test_runner, huntrleaks) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -802,6 +802,9 @@ Tests ----- +- Issue #22104: regrtest.py no longer holds a reference to the suite of tests + loaded from test modules that don't define test_main(). + - Issue #22111: Assorted cleanups in test_imaplib. Patch by Milan Oberkirch. - Issue #22002: Added ``load_package_tests`` function to test.support and used -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Aug 4 18:36:06 2014 From: python-checkins at python.org (ezio.melotti) Date: Mon, 4 Aug 2014 18:36:06 +0200 (CEST) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogIzE4MDM0OiB1cGRh?= =?utf-8?q?te_FAQ_to_suggest_importlib=2Eimport=5Fmodule_instead_of_=5F=5F?= =?utf-8?b?aW1wb3J0X18u?= Message-ID: <3hRl8k41QJz7Lrn@mail.python.org> http://hg.python.org/cpython/rev/815f1a69283e changeset: 91996:815f1a69283e branch: 3.4 parent: 91994:9bca86812857 user: Ezio Melotti date: Mon Aug 04 19:34:29 2014 +0300 summary: #18034: update FAQ to suggest importlib.import_module instead of __import__. Patch by Wouter van Heyst. files: Doc/faq/programming.rst | 15 +++------------ Misc/ACKS | 1 + 2 files changed, 4 insertions(+), 12 deletions(-) diff --git a/Doc/faq/programming.rst b/Doc/faq/programming.rst --- a/Doc/faq/programming.rst +++ b/Doc/faq/programming.rst @@ -1786,19 +1786,10 @@ __import__('x.y.z') returns ; how do I get z? --------------------------------------------------------- -Try:: +Consider using the convenience function :func:`~importlib.import_module` from +:mod:`importlib` instead:: - __import__('x.y.z').y.z - -For more realistic situations, you may have to do something like :: - - m = __import__(s) - for i in s.split(".")[1:]: - m = getattr(m, i) - -See :mod:`importlib` for a convenience function called -:func:`~importlib.import_module`. - + z = importlib.import_module('x.y.z') When I edit an imported module and reimport it, the changes don't show up. Why does this happen? diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -549,6 +549,7 @@ Magnus L. Hetland Raymond Hettinger Kevan Heydon +Wouter van Heyst Kelsey Hightower Jason Hildebrand Richie Hindle -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Aug 4 18:36:07 2014 From: python-checkins at python.org (ezio.melotti) Date: Mon, 4 Aug 2014 18:36:07 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?b?KTogIzE4MDM0OiBtZXJnZSB3aXRoIDMuNC4=?= Message-ID: <3hRl8l61Rzz7LsK@mail.python.org> http://hg.python.org/cpython/rev/f78ef3819d67 changeset: 91997:f78ef3819d67 parent: 91995:7bc53cf8b2df parent: 91996:815f1a69283e user: Ezio Melotti date: Mon Aug 04 19:34:57 2014 +0300 summary: #18034: merge with 3.4. files: Doc/faq/programming.rst | 15 +++------------ Misc/ACKS | 1 + 2 files changed, 4 insertions(+), 12 deletions(-) diff --git a/Doc/faq/programming.rst b/Doc/faq/programming.rst --- a/Doc/faq/programming.rst +++ b/Doc/faq/programming.rst @@ -1786,19 +1786,10 @@ __import__('x.y.z') returns ; how do I get z? --------------------------------------------------------- -Try:: +Consider using the convenience function :func:`~importlib.import_module` from +:mod:`importlib` instead:: - __import__('x.y.z').y.z - -For more realistic situations, you may have to do something like :: - - m = __import__(s) - for i in s.split(".")[1:]: - m = getattr(m, i) - -See :mod:`importlib` for a convenience function called -:func:`~importlib.import_module`. - + z = importlib.import_module('x.y.z') When I edit an imported module and reimport it, the changes don't show up. Why does this happen? diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -553,6 +553,7 @@ Magnus L. Hetland Raymond Hettinger Kevan Heydon +Wouter van Heyst Kelsey Hightower Jason Hildebrand Richie Hindle -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Aug 4 18:36:09 2014 From: python-checkins at python.org (ezio.melotti) Date: Mon, 4 Aug 2014 18:36:09 +0200 (CEST) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogIzE4MDM0OiB1cGRh?= =?utf-8?q?te_FAQ_to_suggest_importlib=2Eimport=5Fmodule_instead_of_=5F=5F?= =?utf-8?b?aW1wb3J0X18u?= Message-ID: <3hRl8n0tvLz7Lsm@mail.python.org> http://hg.python.org/cpython/rev/46c7a724b487 changeset: 91998:46c7a724b487 branch: 2.7 parent: 91978:50722d2f08c7 user: Ezio Melotti date: Mon Aug 04 19:34:29 2014 +0300 summary: #18034: update FAQ to suggest importlib.import_module instead of __import__. Patch by Wouter van Heyst. files: Doc/faq/programming.rst | 17 ++++------------- Misc/ACKS | 1 + 2 files changed, 5 insertions(+), 13 deletions(-) diff --git a/Doc/faq/programming.rst b/Doc/faq/programming.rst --- a/Doc/faq/programming.rst +++ b/Doc/faq/programming.rst @@ -1925,19 +1925,10 @@ __import__('x.y.z') returns ; how do I get z? --------------------------------------------------------- -Try:: - - __import__('x.y.z').y.z - -For more realistic situations, you may have to do something like :: - - m = __import__(s) - for i in s.split(".")[1:]: - m = getattr(m, i) - -See :mod:`importlib` for a convenience function called -:func:`~importlib.import_module`. - +Consider using the convenience function :func:`~importlib.import_module` from +:mod:`importlib` instead:: + + z = importlib.import_module('x.y.z') When I edit an imported module and reimport it, the changes don't show up. Why does this happen? diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -545,6 +545,7 @@ Magnus L. Hetland Raymond Hettinger Kevan Heydon +Wouter van Heyst Kelsey Hightower Jason Hildebrand Richie Hindle -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Aug 5 01:24:53 2014 From: python-checkins at python.org (ezio.melotti) Date: Tue, 5 Aug 2014 01:24:53 +0200 (CEST) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogIzExOTU1OiBzaG93?= =?utf-8?q?_the_list_of_args_in_case_of_error_in_test=5Fargparse=2E?= Message-ID: <3hRwDP3b2Dz7Lk3@mail.python.org> http://hg.python.org/cpython/rev/9a410ae785ff changeset: 91999:9a410ae785ff branch: 3.4 parent: 91996:815f1a69283e user: Ezio Melotti date: Tue Aug 05 02:24:03 2014 +0300 summary: #11955: show the list of args in case of error in test_argparse. files: Lib/test/test_argparse.py | 4 ++-- 1 files changed, 2 insertions(+), 2 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 @@ -235,8 +235,8 @@ parser = self._get_parser(tester) for args_str in tester.failures: args = args_str.split() - raises = tester.assertRaises - raises(ArgumentParserError, parser.parse_args, args) + with tester.assertRaises(ArgumentParserError, msg=args): + parser.parse_args(args) def test_successes(self, tester): parser = self._get_parser(tester) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Aug 5 01:24:54 2014 From: python-checkins at python.org (ezio.melotti) Date: Tue, 5 Aug 2014 01:24:54 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?b?KTogIzExOTU1OiBtZXJnZSB3aXRoIDMuNC4=?= Message-ID: <3hRwDQ5fJcz7LkJ@mail.python.org> http://hg.python.org/cpython/rev/25e634756f79 changeset: 92000:25e634756f79 parent: 91997:f78ef3819d67 parent: 91999:9a410ae785ff user: Ezio Melotti date: Tue Aug 05 02:24:28 2014 +0300 summary: #11955: merge with 3.4. files: Lib/test/test_argparse.py | 4 ++-- 1 files changed, 2 insertions(+), 2 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 @@ -226,8 +226,8 @@ parser = self._get_parser(tester) for args_str in tester.failures: args = args_str.split() - raises = tester.assertRaises - raises(ArgumentParserError, parser.parse_args, args) + with tester.assertRaises(ArgumentParserError, msg=args): + parser.parse_args(args) def test_successes(self, tester): parser = self._get_parser(tester) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Aug 5 06:04:28 2014 From: python-checkins at python.org (larry.hastings) Date: Tue, 5 Aug 2014 06:04:28 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2320170=3A_Convert_?= =?utf-8?q?posixmodule_to_use_Argument_Clinic=2E?= Message-ID: <3hS2R0408Gz7LkF@mail.python.org> http://hg.python.org/cpython/rev/0c57aba6b1a3 changeset: 92001:0c57aba6b1a3 user: Larry Hastings date: Tue Aug 05 14:04:04 2014 +1000 summary: Issue #20170: Convert posixmodule to use Argument Clinic. files: Misc/NEWS | 2 + Modules/posixmodule.c | 12993 +++++++++++++++++++-------- 2 files changed, 9183 insertions(+), 3812 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,8 @@ Core and Builtins ----------------- +- Issue #20170: Convert posixmodule to use Argument Clinic. + - Issue #22077: Improve index error messages for bytearrays, bytes, lists, and tuples by adding 'or slices'. Added ', not = 1400 /* Microsoft CRT in VS2005 and higher will verify that a filehandle is @@ -1298,16 +1312,26 @@ /* POSIX generic methods */ -static PyObject * -posix_fildes(PyObject *fdobj, int (*func)(int)) +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; - fd = PyObject_AsFileDescriptor(fdobj); - if (fd < 0) - return NULL; - if (!_PyVerify_fd(fd)) - return posix_error(); Py_BEGIN_ALLOW_THREADS res = (*func)(fd); Py_END_ALLOW_THREADS @@ -1317,30 +1341,6 @@ return Py_None; } -static PyObject * -posix_1str(const char *func_name, PyObject *args, char *format, - int (*func)(const char*)) -{ - path_t path; - int res; - memset(&path, 0, sizeof(path)); - path.function_name = func_name; - if (!PyArg_ParseTuple(args, format, - path_converter, &path)) - return NULL; - Py_BEGIN_ALLOW_THREADS - res = (*func)(path.narrow); - Py_END_ALLOW_THREADS - if (res < 0) { - path_error(&path); - path_cleanup(&path); - return NULL; - } - path_cleanup(&path); - Py_INCREF(Py_None); - return Py_None; -} - #ifdef MS_WINDOWS /* This is a reimplementation of the C library's chdir function, @@ -2113,10 +2113,12 @@ 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\ -If newval is True, future calls to stat() return floats, if it is False,\n\ -future calls return ints. \n\ -If newval is omitted, return the current setting.\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) { @@ -2346,11 +2348,176 @@ 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 OS_STAT_DIR_FD_CONVERTER dir_fd_converter -#else - #define OS_STAT_DIR_FD_CONVERTER dir_fd_unavailable -#endif + #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] @@ -2366,22 +2533,25 @@ 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 is not unspecified: + if self.default not in (unspecified, None): fail("Can't specify a default to the path_t converter!") - if self.c_default is not None: - fail("Can't specify a c_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.c_default = 'PATH_T_INITIALIZE("{}", "{}", {}, {})'.format( self.function.name, + self.name, strify(self.nullable), strify(self.allow_fd), ) @@ -2392,15 +2562,78 @@ class dir_fd_converter(CConverter): type = 'int' - converter = 'OS_STAT_DIR_FD_CONVERTER' - - def converter_init(self): + + 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 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=5c9f456f53244fc3]*/ +/*[python end generated code: output=da39a3ee5e6b4b0d input=147ba8f52a05aca4]*/ /*[clinic input] @@ -2411,7 +2644,7 @@ * - dir_fd : dir_fd = None + 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. @@ -2467,13 +2700,13 @@ { PyObject *return_value = NULL; static char *_keywords[] = {"path", "dir_fd", "follow_symlinks", NULL}; - path_t path = PATH_T_INITIALIZE("stat", 0, 1); + 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, OS_STAT_DIR_FD_CONVERTER, &dir_fd, &follow_symlinks)) + path_converter, &path, FSTATAT_DIR_FD_CONVERTER, &dir_fd, &follow_symlinks)) goto exit; return_value = os_stat_impl(module, &path, dir_fd, follow_symlinks); @@ -2486,49 +2719,74 @@ static PyObject * os_stat_impl(PyModuleDef *module, path_t *path, int dir_fd, int follow_symlinks) -/*[clinic end generated code: output=f1dcaa5e24db9882 input=5ae155bd475fd20a]*/ +/*[clinic end generated code: output=0e9f9508fa0c0607 input=099d356c306fa24a]*/ { return posix_do_stat("stat", path, dir_fd, follow_symlinks); } -PyDoc_STRVAR(posix_lstat__doc__, -"lstat(path, *, dir_fd=None) -> stat result\n\n\ -Like stat(), but do not follow symbolic links.\n\ -Equivalent to stat(path, follow_symlinks=False)."); - -static PyObject * -posix_lstat(PyObject *self, PyObject *args, PyObject *kwargs) -{ - static char *keywords[] = {"path", "dir_fd", NULL}; - path_t path; + +/*[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" +"\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]*/ +{ int follow_symlinks = 0; - PyObject *return_value; - - memset(&path, 0, sizeof(path)); - path.function_name = "lstat"; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&|$O&:lstat", keywords, - path_converter, &path, -#ifdef HAVE_FSTATAT - dir_fd_converter, &dir_fd -#else - dir_fd_unavailable, &dir_fd -#endif - )) - return NULL; - return_value = posix_do_stat("lstat", &path, dir_fd, follow_symlinks); - path_cleanup(&path); - return return_value; -} - - -#ifdef HAVE_FACCESSAT - #define OS_ACCESS_DIR_FD_CONVERTER dir_fd_converter -#else - #define OS_ACCESS_DIR_FD_CONVERTER dir_fd_unavailable -#endif -/*[clinic input] -os.access + 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. @@ -2539,7 +2797,7 @@ * - dir_fd : dir_fd = None + 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. @@ -2601,7 +2859,7 @@ #define OS_ACCESS_METHODDEF \ {"access", (PyCFunction)os_access, METH_VARARGS|METH_KEYWORDS, os_access__doc__}, -static PyObject * +static int os_access_impl(PyModuleDef *module, path_t *path, int mode, int dir_fd, int effective_ids, int follow_symlinks); static PyObject * @@ -2609,17 +2867,21 @@ { PyObject *return_value = NULL; static char *_keywords[] = {"path", "mode", "dir_fd", "effective_ids", "follow_symlinks", NULL}; - path_t path = PATH_T_INITIALIZE("access", 0, 1); + 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, OS_STAT_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); + 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 */ @@ -2628,11 +2890,11 @@ return return_value; } -static PyObject * +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=a6ed4f151be9df0f input=2e2e7594371f5b7e]*/ -{ - PyObject *return_value = NULL; +/*[clinic end generated code: output=dfd404666906f012 input=b75a756797af45ec]*/ +{ + int return_value; #ifdef MS_WINDOWS DWORD attr; @@ -2642,11 +2904,11 @@ #ifndef HAVE_FACCESSAT if (follow_symlinks_specified("access", follow_symlinks)) - goto exit; + return -1; if (effective_ids) { argument_unavailable_error("access", "effective_ids"); - goto exit; + return -1; } #endif @@ -2666,11 +2928,10 @@ * * or it's a directory. * (Directories cannot be read-only on Windows.) */ - return_value = PyBool_FromLong( - (attr != INVALID_FILE_ATTRIBUTES) && + return_value = (attr != INVALID_FILE_ATTRIBUTES) && (!(mode & 2) || !(attr & FILE_ATTRIBUTE_READONLY) || - (attr & FILE_ATTRIBUTE_DIRECTORY))); + (attr & FILE_ATTRIBUTE_DIRECTORY)); #else Py_BEGIN_ALLOW_THREADS @@ -2689,12 +2950,9 @@ #endif result = access(path->narrow, mode); Py_END_ALLOW_THREADS - return_value = PyBool_FromLong(!result); -#endif - -#ifndef HAVE_FACCESSAT -exit: -#endif + return_value = !result; +#endif + return return_value; } @@ -2713,7 +2971,6 @@ #ifdef HAVE_TTYNAME - /*[clinic input] os.ttyname -> DecodeFSDefault @@ -2771,17 +3028,36 @@ posix_error(); return ret; } -#else -#define OS_TTYNAME_METHODDEF #endif #ifdef HAVE_CTERMID -PyDoc_STRVAR(posix_ctermid__doc__, -"ctermid() -> string\n\n\ -Return the name of the controlling terminal for this process."); - -static PyObject * -posix_ctermid(PyObject *self, PyObject *noargs) +/*[clinic input] +os.ctermid + +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]*/ { char *ret; char buffer[L_ctermid]; @@ -2795,106 +3071,234 @@ return posix_error(); return PyUnicode_DecodeFSDefault(buffer); } -#endif - -PyDoc_STRVAR(posix_chdir__doc__, -"chdir(path)\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."); - -static PyObject * -posix_chdir(PyObject *self, PyObject *args, PyObject *kwargs) -{ - path_t path; +#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]*/ + +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]*/ +{ int result; - PyObject *return_value = NULL; - static char *keywords[] = {"path", NULL}; - - memset(&path, 0, sizeof(path)); - path.function_name = "chdir"; + + 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 - path.allow_fd = 1; -#endif - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&:chdir", keywords, - path_converter, &path - )) - return NULL; - - 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 + 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 - if (path.fd != -1) - result = fchdir(path.fd); - else -#endif - result = chdir(path.narrow); -#endif - Py_END_ALLOW_THREADS - - if (result) { - return_value = path_error(&path); - goto exit; - } - - return_value = Py_None; - Py_INCREF(Py_None); - -exit: - path_cleanup(&path); - return return_value; -} - -#ifdef HAVE_FCHDIR -PyDoc_STRVAR(posix_fchdir__doc__, -"fchdir(fd)\n\n\ -Change to the directory of the given file descriptor. fd must be\n\ -opened on a directory, not a file. Equivalent to os.chdir(fd)."); - -static PyObject * -posix_fchdir(PyObject *self, PyObject *fdobj) -{ - return posix_fildes(fdobj, 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]*/ + +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]*/ +{ + return posix_fildes_fd(fd, fchdir); } #endif /* HAVE_FCHDIR */ -PyDoc_STRVAR(posix_chmod__doc__, -"chmod(path, mode, *, dir_fd=None, follow_symlinks=True)\n\n\ -Change the access permissions of a file.\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, chmod 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."); - -static PyObject * -posix_chmod(PyObject *self, PyObject *args, PyObject *kwargs) -{ - path_t path; +/*[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]*/ + +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]*/ +{ int result; - PyObject *return_value = NULL; - static char *keywords[] = {"path", "mode", "dir_fd", - "follow_symlinks", NULL}; #ifdef MS_WINDOWS DWORD attr; @@ -2904,33 +3308,17 @@ int fchmodat_nofollow_unsupported = 0; #endif - memset(&path, 0, sizeof(path)); - path.function_name = "chmod"; -#ifdef HAVE_FCHMOD - path.allow_fd = 1; -#endif - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&i|$O&p:chmod", keywords, - path_converter, &path, - &mode, -#ifdef HAVE_FCHMODAT - dir_fd_converter, &dir_fd, -#else - dir_fd_unavailable, &dir_fd, -#endif - &follow_symlinks)) - return NULL; - #if !(defined(HAVE_FCHMODAT) || defined(HAVE_LCHMOD)) if (follow_symlinks_specified("chmod", follow_symlinks)) - goto exit; -#endif - -#ifdef MS_WINDOWS - Py_BEGIN_ALLOW_THREADS - if (path.wide) - attr = GetFileAttributesW(path.wide); - else - attr = GetFileAttributesA(path.narrow); + 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 { @@ -2938,27 +3326,26 @@ attr &= ~FILE_ATTRIBUTE_READONLY; else attr |= FILE_ATTRIBUTE_READONLY; - if (path.wide) - result = SetFileAttributesW(path.wide, attr); + if (path->wide) + result = SetFileAttributesW(path->wide, attr); else - result = SetFileAttributesA(path.narrow, attr); + result = SetFileAttributesA(path->narrow, attr); } Py_END_ALLOW_THREADS if (!result) { - return_value = path_error(&path); - goto exit; + return path_error(path); } #else /* MS_WINDOWS */ Py_BEGIN_ALLOW_THREADS #ifdef HAVE_FCHMOD - if (path.fd != -1) - result = fchmod(path.fd, mode); + 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); + result = lchmod(path->narrow, mode); else #endif #ifdef HAVE_FCHMODAT @@ -2973,7 +3360,7 @@ * 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, + result = fchmodat(dir_fd, path->narrow, mode, follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW); /* * But wait! We can't throw the exception without allowing threads, @@ -2986,7 +3373,7 @@ } else #endif - result = chmod(path.narrow, mode); + result = chmod(path->narrow, mode); Py_END_ALLOW_THREADS if (result) { @@ -3000,31 +3387,63 @@ } else #endif - return_value = path_error(&path); - goto exit; - } -#endif - - Py_INCREF(Py_None); - return_value = Py_None; -exit: - path_cleanup(&path); - return return_value; + return path_error(path); + } +#endif + + Py_RETURN_NONE; } #ifdef HAVE_FCHMOD -PyDoc_STRVAR(posix_fchmod__doc__, -"fchmod(fd, mode)\n\n\ -Change the access permissions of the file given by file\n\ -descriptor fd. Equivalent to os.chmod(fd, mode)."); - -static PyObject * -posix_fchmod(PyObject *self, PyObject *args) -{ - int fd, mode, res; - if (!PyArg_ParseTuple(args, "ii:fchmod", &fd, &mode)) - return NULL; +/*[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]*/ + +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]*/ +{ + int res; Py_BEGIN_ALLOW_THREADS res = fchmod(fd, mode); Py_END_ALLOW_THREADS @@ -3034,238 +3453,529 @@ } #endif /* HAVE_FCHMOD */ + #ifdef HAVE_LCHMOD PyDoc_STRVAR(posix_lchmod__doc__, -"lchmod(path, mode)\n\n\ -Change the access permissions of a file. If path is a symlink, this\n\ -affects the link itself rather than the target.\n\ -Equivalent to chmod(path, mode, follow_symlinks=False)."); - -static PyObject * -posix_lchmod(PyObject *self, PyObject *args) -{ - path_t path; - int i; +/*[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]*/ + +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]*/ +{ int res; - memset(&path, 0, sizeof(path)); - path.function_name = "lchmod"; - if (!PyArg_ParseTuple(args, "O&i:lchmod", - path_converter, &path, &i)) - return NULL; Py_BEGIN_ALLOW_THREADS res = lchmod(path.narrow, i); Py_END_ALLOW_THREADS if (res < 0) { - path_error(&path); - path_cleanup(&path); - return NULL; - } - path_cleanup(&path); + path_error(path); + return NULL; + } Py_RETURN_NONE; } #endif /* HAVE_LCHMOD */ #ifdef HAVE_CHFLAGS -PyDoc_STRVAR(posix_chflags__doc__, -"chflags(path, flags, *, follow_symlinks=True)\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."); - -static PyObject * -posix_chflags(PyObject *self, PyObject *args, PyObject *kwargs) -{ - path_t path; +/*[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]*/ + +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]*/ +{ int result; - PyObject *return_value = NULL; - static char *keywords[] = {"path", "flags", "follow_symlinks", NULL}; - - memset(&path, 0, sizeof(path)); - path.function_name = "chflags"; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&k|$i:chflags", keywords, - path_converter, &path, - &flags, &follow_symlinks)) - return NULL; #ifndef HAVE_LCHFLAGS if (follow_symlinks_specified("chflags", follow_symlinks)) - goto exit; + 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_value = path_error(&path); - goto exit; - } - - return_value = Py_None; - Py_INCREF(Py_None); - -exit: + 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]*/ + +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; -} -#endif /* HAVE_CHFLAGS */ - -#ifdef HAVE_LCHFLAGS -PyDoc_STRVAR(posix_lchflags__doc__, -"lchflags(path, flags)\n\n\ -Set file flags.\n\ -This function will not follow symbolic links.\n\ -Equivalent to chflags(path, flags, follow_symlinks=False)."); - -static PyObject * -posix_lchflags(PyObject *self, PyObject *args) -{ - path_t path; - unsigned long flags; + + 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; - memset(&path, 0, sizeof(path)); - path.function_name = "lchflags"; - if (!PyArg_ParseTuple(args, "O&k:lchflags", - path_converter, &path, &flags)) - return NULL; Py_BEGIN_ALLOW_THREADS res = lchflags(path.narrow, flags); Py_END_ALLOW_THREADS if (res < 0) { - path_error(&path); - path_cleanup(&path); - return NULL; - } + 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]*/ + +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]*/ +{ + 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_LCHFLAGS */ - -#ifdef HAVE_CHROOT -PyDoc_STRVAR(posix_chroot__doc__, -"chroot(path)\n\n\ -Change root directory to path."); - -static PyObject * -posix_chroot(PyObject *self, PyObject *args) -{ - return posix_1str("chroot", args, "O&:chroot", chroot); -} -#endif +#endif /* HAVE_CHROOT */ + #ifdef HAVE_FSYNC -PyDoc_STRVAR(posix_fsync__doc__, -"fsync(fildes)\n\n\ -force write of file with filedescriptor to disk."); - -static PyObject * -posix_fsync(PyObject *self, PyObject *fdobj) -{ - return posix_fildes(fdobj, fsync); +/*[clinic input] +os.fsync + + fd: fildes + +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]*/ +{ + return posix_fildes_fd(fd, fsync); } #endif /* HAVE_FSYNC */ + #ifdef HAVE_SYNC -PyDoc_STRVAR(posix_sync__doc__, -"sync()\n\n\ -Force write of everything to disk."); - -static PyObject * -posix_sync(PyObject *self, PyObject *noargs) +/*[clinic input] +os.sync + +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]*/ { Py_BEGIN_ALLOW_THREADS sync(); Py_END_ALLOW_THREADS Py_RETURN_NONE; } -#endif +#endif /* HAVE_SYNC */ + #ifdef HAVE_FDATASYNC - #ifdef __hpux extern int fdatasync(int); /* On HP-UX, in libc but not in unistd.h */ #endif -PyDoc_STRVAR(posix_fdatasync__doc__, -"fdatasync(fildes)\n\n\ -force write of file with filedescriptor to disk.\n\ - does not force update of metadata."); - -static PyObject * -posix_fdatasync(PyObject *self, PyObject *fdobj) -{ - return posix_fildes(fdobj, fdatasync); +/*[clinic input] +os.fdatasync + + fd: fildes + +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]*/ +{ + return posix_fildes_fd(fd, fdatasync); } #endif /* HAVE_FDATASYNC */ #ifdef HAVE_CHOWN -PyDoc_STRVAR(posix_chown__doc__, -"chown(path, uid, gid, *, dir_fd=None, follow_symlinks=True)\n\n\ -Change the owner and group id of path to the numeric uid and gid.\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."); - -static PyObject * -posix_chown(PyObject *self, PyObject *args, PyObject *kwargs) -{ - path_t path; +/*[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]*/ + +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]*/ +{ int result; - PyObject *return_value = NULL; - static char *keywords[] = {"path", "uid", "gid", "dir_fd", - "follow_symlinks", NULL}; - - memset(&path, 0, sizeof(path)); - path.function_name = "chown"; -#ifdef HAVE_FCHOWN - path.allow_fd = 1; -#endif - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&O&O&|$O&p:chown", keywords, - path_converter, &path, - _Py_Uid_Converter, &uid, - _Py_Gid_Converter, &gid, -#ifdef HAVE_FCHOWNAT - dir_fd_converter, &dir_fd, -#else - dir_fd_unavailable, &dir_fd, -#endif - &follow_symlinks)) - return NULL; #if !(defined(HAVE_LCHOWN) || defined(HAVE_FCHOWNAT)) if (follow_symlinks_specified("chown", follow_symlinks)) - goto exit; -#endif - if (dir_fd_and_fd_invalid("chown", dir_fd, path.fd) || - fd_and_follow_symlinks_invalid("chown", path.fd, follow_symlinks)) - goto exit; + 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__ /* @@ -3276,61 +3986,90 @@ */ if ((!follow_symlinks) && (lchown == NULL)) { follow_symlinks_specified("chown", follow_symlinks); - goto exit; + return NULL; } #endif Py_BEGIN_ALLOW_THREADS #ifdef HAVE_FCHOWN - if (path.fd != -1) - result = fchown(path.fd, uid, gid); + 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); + 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, + 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_value = path_error(&path); - goto exit; - } - - return_value = Py_None; - Py_INCREF(Py_None); - -exit: - path_cleanup(&path); - return return_value; + 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 -PyDoc_STRVAR(posix_fchown__doc__, -"fchown(fd, uid, gid)\n\n\ -Change the owner and group id of the file given by file descriptor\n\ -fd to the numeric uid and gid. Equivalent to os.chown(fd, uid, gid)."); - -static PyObject * -posix_fchown(PyObject *self, PyObject *args) -{ +/*[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]*/ + +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]*/ +{ int res; - if (!PyArg_ParseTuple(args, "iO&O&:fchown", &fd, - _Py_Uid_Converter, &uid, - _Py_Gid_Converter, &gid)) - return NULL; Py_BEGIN_ALLOW_THREADS res = fchown(fd, uid, gid); Py_END_ALLOW_THREADS @@ -3340,38 +4079,70 @@ } #endif /* HAVE_FCHOWN */ + #ifdef HAVE_LCHOWN -PyDoc_STRVAR(posix_lchown__doc__, -"lchown(path, uid, gid)\n\n\ -Change the owner and group id of path to the numeric uid and gid.\n\ -This function will not follow symbolic links.\n\ -Equivalent to os.chown(path, uid, gid, follow_symlinks=False)."); - -static PyObject * -posix_lchown(PyObject *self, PyObject *args) -{ - path_t path; +/*[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]*/ + +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]*/ +{ int res; - memset(&path, 0, sizeof(path)); - path.function_name = "lchown"; - if (!PyArg_ParseTuple(args, "O&O&O&:lchown", - path_converter, &path, - _Py_Uid_Converter, &uid, - _Py_Gid_Converter, &gid)) - return NULL; - Py_BEGIN_ALLOW_THREADS - res = lchown(path.narrow, uid, gid); + Py_BEGIN_ALLOW_THREADS + res = lchown(path->narrow, uid, gid); Py_END_ALLOW_THREADS if (res < 0) { - path_error(&path); - path_cleanup(&path); - return NULL; - } - path_cleanup(&path); - Py_INCREF(Py_None); - return Py_None; + return path_error(path); + } + Py_RETURN_NONE; } #endif /* HAVE_LCHOWN */ @@ -3428,148 +4199,209 @@ return PyUnicode_DecodeFSDefault(buf); } -PyDoc_STRVAR(posix_getcwd__doc__, -"getcwd() -> path\n\n\ -Return a unicode string representing the current working directory."); - -static PyObject * -posix_getcwd_unicode(PyObject *self) + +/*[clinic input] +os.getcwd + +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]*/ { return posix_getcwd(0); } -PyDoc_STRVAR(posix_getcwdb__doc__, -"getcwdb() -> path\n\n\ -Return a bytes string representing the current working directory."); - -static PyObject * -posix_getcwd_bytes(PyObject *self) + +/*[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" +"\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]*/ { return posix_getcwd(1); } + #if ((!defined(HAVE_LINK)) && defined(MS_WINDOWS)) #define HAVE_LINK 1 #endif #ifdef HAVE_LINK -PyDoc_STRVAR(posix_link__doc__, -"link(src, dst, *, src_dir_fd=None, dst_dir_fd=None, follow_symlinks=True)\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."); - -static PyObject * -posix_link(PyObject *self, PyObject *args, PyObject *kwargs) -{ - path_t src, dst; +/*[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]*/ + +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; - PyObject *return_value = NULL; - static char *keywords[] = {"src", "dst", "src_dir_fd", "dst_dir_fd", - "follow_symlinks", NULL}; + + 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]*/ +{ #ifdef MS_WINDOWS BOOL result; #else int result; #endif - memset(&src, 0, sizeof(src)); - memset(&dst, 0, sizeof(dst)); - src.function_name = "link"; - dst.function_name = "link"; - 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)) - return NULL; - #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"); - goto exit; - } -#endif - - if ((src.narrow && dst.wide) || (src.wide && dst.narrow)) { + 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"); - goto exit; - } - -#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_value = path_error2(&src, &dst); - goto exit; - } + 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, + 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_value = path_error2(&src, &dst); - goto exit; - } -#endif - - return_value = Py_None; - Py_INCREF(Py_None); - -exit: - path_cleanup(&src); - path_cleanup(&dst); - return return_value; -} -#endif - - - -PyDoc_STRVAR(posix_listdir__doc__, -"listdir(path='.') -> list_of_filenames\n\n\ -Return a list containing the names of the files in the directory.\n\ -The list is in arbitrary order. It does not include the special\n\ -entries '.' and '..' even if they are present 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\ -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."); + 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) { - static char *keywords[] = {"path", NULL}; PyObject *v; HANDLE hFindFile = INVALID_HANDLE_VALUE; BOOL result; @@ -3828,38 +4660,85 @@ } /* end of _posix_listdir */ #endif /* which OS */ -static PyObject * -posix_listdir(PyObject *self, PyObject *args, PyObject *kwargs) -{ - path_t path; - PyObject *list = NULL; - static char *keywords[] = {"path", NULL}; - PyObject *return_value; - - memset(&path, 0, sizeof(path)); - path.function_name = "listdir"; - path.nullable = 1; -#ifdef HAVE_FDOPENDIR - path.allow_fd = 1; - path.fd = -1; -#endif - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O&:listdir", keywords, - path_converter, &path)) { - return NULL; - } - + +/*[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]*/ + +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]*/ +{ #if defined(MS_WINDOWS) && !defined(HAVE_OPENDIR) - return_value = _listdir_windows_no_opendir(&path, list); -#else - return_value = _posix_listdir(&path, list); -#endif - path_cleanup(&path); - return return_value; + 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) { @@ -3915,25 +4794,59 @@ Py_FileSystemDefaultEncoding, NULL); } return PyBytes_FromString(outbuf); -} /* end of posix__getfullpathname */ - - - -/* A helper function for samepath on windows */ -static PyObject * -posix__getfinalpathname(PyObject *self, PyObject *args) +} + + +/*[clinic input] +os._getfinalpathname + + path: unicode + / + +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]*/ { HANDLE hFile; int buf_size; wchar_t *target_path; int result_length; - PyObject *po, *result; - wchar_t *path; - - if (!PyArg_ParseTuple(args, "U|:_getfinalpathname", &po)) - return NULL; - path = PyUnicode_AsUnicode(po); - if (path == NULL) + PyObject *result; + wchar_t *path_wchar; + + path_wchar = PyUnicode_AsUnicode(path); + if (path_wchar == NULL) return NULL; if(!check_GetFinalPathNameByHandle()) { @@ -3944,7 +4857,7 @@ } hFile = CreateFileW( - path, + path_wchar, 0, /* desired access */ 0, /* share mode */ NULL, /* security attributes */ @@ -3954,14 +4867,14 @@ NULL); if(hFile == INVALID_HANDLE_VALUE) - return win32_error_object("CreateFileW", po); + return win32_error_object("CreateFileW", path); /* We have a good handle to the target, use it to determine the target path name. */ buf_size = Py_GetFinalPathNameByHandleW(hFile, 0, 0, VOLUME_NAME_NT); if(!buf_size) - return win32_error_object("GetFinalPathNameByHandle", po); + return win32_error_object("GetFinalPathNameByHandle", path); target_path = (wchar_t *)PyMem_Malloc((buf_size+1)*sizeof(wchar_t)); if(!target_path) @@ -3970,21 +4883,21 @@ result_length = Py_GetFinalPathNameByHandleW(hFile, target_path, buf_size, VOLUME_NAME_DOS); if(!result_length) - return win32_error_object("GetFinalPathNamyByHandle", po); + return win32_error_object("GetFinalPathNamyByHandle", path); if(!CloseHandle(hFile)) - return win32_error_object("CloseHandle", po); + return win32_error_object("CloseHandle", path); target_path[result_length] = 0; result = PyUnicode_FromWideChar(target_path, result_length); PyMem_Free(target_path); return result; - -} /* end of posix__getfinalpathname */ +} 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) { @@ -4021,22 +4934,55 @@ Py_RETURN_FALSE; } -PyDoc_STRVAR(posix__getvolumepathname__doc__, -"Return volume mount point of the specified path."); - -/* A helper function for ismount on windows */ -static PyObject * -posix__getvolumepathname(PyObject *self, PyObject *args) -{ - PyObject *po, *result; - wchar_t *path, *mountpath=NULL; + +/*[clinic input] +os._getvolumepathname + + path: unicode + +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]*/ +{ + PyObject *result; + wchar_t *path_wchar, *mountpath=NULL; size_t buflen; BOOL ret; - if (!PyArg_ParseTuple(args, "U|:_getvolumepathname", &po)) - return NULL; - path = PyUnicode_AsUnicodeAndSize(po, &buflen); - if (path == NULL) + path_wchar = PyUnicode_AsUnicodeAndSize(path, &buflen); + if (path_wchar == NULL) return NULL; buflen += 1; @@ -4053,12 +4999,12 @@ return PyErr_NoMemory(); Py_BEGIN_ALLOW_THREADS - ret = GetVolumePathNameW(path, mountpath, + ret = GetVolumePathNameW(path_wchar, mountpath, Py_SAFE_DOWNCAST(buflen, size_t, DWORD)); Py_END_ALLOW_THREADS if (!ret) { - result = win32_error_object("_getvolumepathname", po); + result = win32_error_object("_getvolumepathname", path); goto exit; } result = PyUnicode_FromWideChar(mountpath, wcslen(mountpath)); @@ -4067,78 +5013,107 @@ PyMem_Free(mountpath); return result; } -/* end of posix__getvolumepathname */ #endif /* MS_WINDOWS */ -PyDoc_STRVAR(posix_mkdir__doc__, -"mkdir(path, mode=0o777, *, dir_fd=None)\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."); - -static PyObject * -posix_mkdir(PyObject *self, PyObject *args, PyObject *kwargs) -{ - path_t path; - int mode = 0777; + +/*[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]*/ + +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; - static char *keywords[] = {"path", "mode", "dir_fd", NULL}; - PyObject *return_value = NULL; + + 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]*/ +{ int result; - memset(&path, 0, sizeof(path)); - path.function_name = "mkdir"; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&|i$O&:mkdir", keywords, - path_converter, &path, &mode, -#ifdef HAVE_MKDIRAT - dir_fd_converter, &dir_fd -#else - dir_fd_unavailable, &dir_fd -#endif - )) - return NULL; - -#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_value = path_error(&path); - goto exit; - } +#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); + 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_value = path_error(&path); - goto exit; - } -#endif - return_value = Py_None; - Py_INCREF(Py_None); -exit: - path_cleanup(&path); - return return_value; + 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; } @@ -4149,17 +5124,48 @@ #ifdef HAVE_NICE -PyDoc_STRVAR(posix_nice__doc__, -"nice(inc) -> new_priority\n\n\ -Decrease the priority of process by inc and return the new priority."); - -static PyObject * -posix_nice(PyObject *self, PyObject *args) -{ - int increment, value; - - if (!PyArg_ParseTuple(args, "i:nice", &increment)) - return NULL; +/*[clinic input] +os.nice + + increment: int + / + +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]*/ +{ + int value; /* There are two flavours of 'nice': one that returns the new priority (as required by almost all standards out there) and the @@ -4186,17 +5192,51 @@ #ifdef HAVE_GETPRIORITY -PyDoc_STRVAR(posix_getpriority__doc__, -"getpriority(which, who) -> current_priority\n\n\ -Get program scheduling priority."); - -static PyObject * -posix_getpriority(PyObject *self, PyObject *args) -{ - int which, who, retval; - - if (!PyArg_ParseTuple(args, "ii", &which, &who)) - return NULL; +/*[clinic input] +os.getpriority + + which: int + who: int + +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]*/ +{ + int retval; + errno = 0; retval = getpriority(which, who); if (errno != 0) @@ -4207,18 +5247,54 @@ #ifdef HAVE_SETPRIORITY -PyDoc_STRVAR(posix_setpriority__doc__, -"setpriority(which, who, prio) -> None\n\n\ -Set program scheduling priority."); - -static PyObject * -posix_setpriority(PyObject *self, PyObject *args) -{ - int which, who, prio, retval; - - if (!PyArg_ParseTuple(args, "iii", &which, &who, &prio)) - return NULL; - retval = setpriority(which, who, prio); +/*[clinic input] +os.setpriority + + which: int + who: int + priority: int + +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]*/ +{ + int retval; + + retval = setpriority(which, who, priority); if (retval == -1) return posix_error(); Py_RETURN_NONE; @@ -4227,17 +5303,10 @@ static PyObject * -internal_rename(PyObject *args, PyObject *kwargs, int is_replace) +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"; - path_t src; - path_t dst; - int src_dir_fd = DEFAULT_DIR_FD; - int dst_dir_fd = DEFAULT_DIR_FD; int dir_fd_specified; - PyObject *return_value = NULL; - char format[24]; - static char *keywords[] = {"src", "dst", "src_dir_fd", "dst_dir_fd", NULL}; #ifdef MS_WINDOWS BOOL result; @@ -4246,210 +5315,419 @@ int result; #endif - memset(&src, 0, sizeof(src)); - memset(&dst, 0, sizeof(dst)); - src.function_name = function_name; - dst.function_name = function_name; - strcpy(format, "O&O&|$O&O&:"); - strcat(format, function_name); - if (!PyArg_ParseTupleAndKeywords(args, kwargs, format, keywords, - path_converter, &src, - path_converter, &dst, - dir_fd_converter, &src_dir_fd, - dir_fd_converter, &dst_dir_fd)) - return NULL; - 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"); - goto exit; - } -#endif - - if ((src.narrow && dst.wide) || (src.wide && dst.narrow)) { + 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); - goto exit; - } - -#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_value = path_error2(&src, &dst); - goto exit; - } + 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_value = path_error2(&src, &dst); - goto exit; - } -#endif - - Py_INCREF(Py_None); - return_value = Py_None; -exit: + 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]*/ + +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; -} - -PyDoc_STRVAR(posix_rename__doc__, -"rename(src, dst, *, src_dir_fd=None, dst_dir_fd=None)\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."); - -static PyObject * -posix_rename(PyObject *self, PyObject *args, PyObject *kwargs) -{ - return internal_rename(args, kwargs, 0); -} - -PyDoc_STRVAR(posix_replace__doc__, -"replace(src, dst, *, src_dir_fd=None, dst_dir_fd=None)\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."); - -static PyObject * -posix_replace(PyObject *self, PyObject *args, PyObject *kwargs) -{ - return internal_rename(args, kwargs, 1); -} - -PyDoc_STRVAR(posix_rmdir__doc__, -"rmdir(path, *, dir_fd=None)\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."); - -static PyObject * -posix_rmdir(PyObject *self, PyObject *args, PyObject *kwargs) -{ - path_t path; + + 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" +"\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]*/ +{ + 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" +"\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; - static char *keywords[] = {"path", "dir_fd", NULL}; + + 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]*/ +{ int result; - PyObject *return_value = NULL; - - memset(&path, 0, sizeof(path)); - path.function_name = "rmdir"; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&|$O&:rmdir", keywords, - path_converter, &path, -#ifdef HAVE_UNLINKAT - dir_fd_converter, &dir_fd -#else - dir_fd_unavailable, &dir_fd -#endif - )) - return NULL; - - Py_BEGIN_ALLOW_THREADS -#ifdef MS_WINDOWS - if (path.wide) - result = RemoveDirectoryW(path.wide); - else - result = RemoveDirectoryA(path.narrow); + + 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_value = path_error(&path); - goto exit; - } - - return_value = Py_None; - Py_INCREF(Py_None); - -exit: - path_cleanup(&path); - return return_value; + 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 -PyDoc_STRVAR(posix_system__doc__, -"system(command) -> exit_status\n\n\ -Execute the command (a string) in a subshell."); - -static PyObject * -posix_system(PyObject *self, PyObject *args) -{ - long sts; -#ifdef MS_WINDOWS - wchar_t *command; - if (!PyArg_ParseTuple(args, "u:system", &command)) - return NULL; - - Py_BEGIN_ALLOW_THREADS - sts = _wsystem(command); - Py_END_ALLOW_THREADS -#else - PyObject *command_obj; - char *command; - if (!PyArg_ParseTuple(args, "O&:system", - PyUnicode_FSConverter, &command_obj)) - return NULL; - - command = PyBytes_AsString(command_obj); - Py_BEGIN_ALLOW_THREADS - sts = system(command); - Py_END_ALLOW_THREADS - Py_DECREF(command_obj); -#endif - return PyLong_FromLong(sts); -} -#endif - - -PyDoc_STRVAR(posix_umask__doc__, -"umask(new_mask) -> old_mask\n\n\ -Set the current numeric umask and return the previous umask."); - -static PyObject * -posix_umask(PyObject *self, PyObject *args) -{ - int i; - if (!PyArg_ParseTuple(args, "i:umask", &i)) - return NULL; - i = (int)umask(i); +#ifdef MS_WINDOWS +/*[clinic input] +os.system -> long + + command: Py_UNICODE + +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]*/ +{ + 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]*/ + +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]*/ +{ + 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]*/ + +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]*/ +{ + int i = (int)umask(mask); if (i < 0) return posix_error(); return PyLong_FromLong((long)i); @@ -4494,81 +5772,147 @@ } #endif /* MS_WINDOWS */ -PyDoc_STRVAR(posix_unlink__doc__, -"unlink(path, *, dir_fd=None)\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."); - -PyDoc_STRVAR(posix_remove__doc__, -"remove(path, *, dir_fd=None)\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."); - -static PyObject * -posix_unlink(PyObject *self, PyObject *args, PyObject *kwargs) -{ - path_t path; + +/*[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" +"\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; - static char *keywords[] = {"path", "dir_fd", NULL}; + + 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]*/ +{ int result; - PyObject *return_value = NULL; - - memset(&path, 0, sizeof(path)); - path.function_name = "unlink"; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&|$O&:unlink", keywords, - path_converter, &path, -#ifdef HAVE_UNLINKAT - dir_fd_converter, &dir_fd -#else - dir_fd_unavailable, &dir_fd -#endif - )) - return NULL; - - Py_BEGIN_ALLOW_THREADS -#ifdef MS_WINDOWS - if (path.wide) - result = Py_DeleteFileW(path.wide); - else - result = DeleteFileA(path.narrow); + + 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); + result = unlinkat(dir_fd, path->narrow, 0); else #endif /* HAVE_UNLINKAT */ - result = unlink(path.narrow); -#endif - Py_END_ALLOW_THREADS - - if (result) { - return_value = path_error(&path); - goto exit; - } - - return_value = Py_None; - Py_INCREF(Py_None); - -exit: + 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" +"\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; -} - - -PyDoc_STRVAR(posix_uname__doc__, -"uname() -> uname_result\n\n\ -Return an object identifying the current operating system.\n\ -The object behaves like a named tuple with the following fields:\n\ - (sysname, nodename, release, version, machine)"); + + 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"}, @@ -4598,8 +5942,40 @@ #ifdef HAVE_UNAME -static PyObject * -posix_uname(PyObject *self, PyObject *noargs) +/*[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]*/ + +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]*/ { struct utsname u; int res; @@ -4638,31 +6014,6 @@ #endif /* HAVE_UNAME */ -PyDoc_STRVAR(posix_utime__doc__, -"utime(path, times=None, *, ns=None, dir_fd=None, follow_symlinks=True)\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."); typedef struct { int now; @@ -4748,6 +6099,9 @@ #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)) @@ -4766,6 +6120,9 @@ #endif } + #define PATH_UTIME_HAVE_FD 1 +#else + #define PATH_UTIME_HAVE_FD 0 #endif @@ -4831,19 +6188,108 @@ return result; } -static PyObject * -posix_utime(PyObject *self, PyObject *args, PyObject *kwargs) -{ - path_t path; + +/*[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]*/ + +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; - char *keywords[] = {"path", "times", "ns", "dir_fd", - "follow_symlinks", NULL}; - - utime_t utime; - + + 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]*/ +{ #ifdef MS_WINDOWS HANDLE hFile; FILETIME atime, mtime; @@ -4852,25 +6298,9 @@ #endif PyObject *return_value = NULL; - - memset(&path, 0, sizeof(path)); - path.function_name = "utime"; + utime_t utime; + memset(&utime, 0, sizeof(utime_t)); -#if UTIME_HAVE_FD - path.allow_fd = 1; -#endif - if (!PyArg_ParseTupleAndKeywords(args, kwargs, - "O&|O$OO&p:utime", keywords, - path_converter, &path, - ×, &ns, -#if UTIME_HAVE_DIR_FD - dir_fd_converter, &dir_fd, -#else - dir_fd_unavailable, &dir_fd, -#endif - &follow_symlinks - )) - return NULL; if (times && (times != Py_None) && ns) { PyErr_SetString(PyExc_ValueError, @@ -4924,9 +6354,9 @@ 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)) + 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) @@ -4940,17 +6370,17 @@ #ifdef MS_WINDOWS Py_BEGIN_ALLOW_THREADS - if (path.wide) - hFile = CreateFileW(path.wide, FILE_WRITE_ATTRIBUTES, 0, + 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, + 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); + path_error(path); goto exit; } @@ -4975,23 +6405,23 @@ #if UTIME_HAVE_NOFOLLOW_SYMLINKS if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD)) - result = utime_nofollow_symlinks(&utime, path.narrow); + 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); + 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); + if (path->fd != -1) + result = utime_fd(&utime, path->fd); + else +#endif + + result = utime_default(&utime, path->narrow); Py_END_ALLOW_THREADS @@ -5007,7 +6437,6 @@ return_value = Py_None; exit: - path_cleanup(&path); #ifdef MS_WINDOWS if (hFile != INVALID_HANDLE_VALUE) CloseHandle(hFile); @@ -5017,17 +6446,49 @@ /* Process operations */ -PyDoc_STRVAR(posix__exit__doc__, -"_exit(status)\n\n\ -Exit to the system with specified status, without normal exit processing."); - -static PyObject * -posix__exit(PyObject *self, PyObject *args) -{ - int sts; - if (!PyArg_ParseTuple(args, "i:_exit", &sts)) - return NULL; - _exit(sts); + +/*[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" +"\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]*/ +{ + _exit(status); return NULL; /* Make gcc -Wall happy */ } @@ -5165,96 +6626,160 @@ } #endif + #ifdef HAVE_EXECV -PyDoc_STRVAR(posix_execv__doc__, -"execv(path, args)\n\n\ -Execute an executable path with arguments, replacing current process.\n\ -\n\ - path: path of executable file\n\ - args: tuple or list of strings"); - -static PyObject * -posix_execv(PyObject *self, PyObject *args) -{ - PyObject *opath; - char *path; +/*[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]*/ + +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]*/ +{ + char *path_char; char **argvlist; Py_ssize_t argc; /* execv has two arguments: (path, argv), where argv is a list or tuple of strings. */ - if (!PyArg_ParseTuple(args, "O&O:execv", - PyUnicode_FSConverter, - &opath, &argv)) - return NULL; - path = PyBytes_AsString(opath); + 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"); - Py_DECREF(opath); return NULL; } argc = PySequence_Size(argv); if (argc < 1) { PyErr_SetString(PyExc_ValueError, "execv() arg 2 must not be empty"); - Py_DECREF(opath); return NULL; } argvlist = parse_arglist(argv, &argc); if (argvlist == NULL) { - Py_DECREF(opath); - return NULL; - } - - execv(path, argvlist); + return NULL; + } + + execv(path_char, argvlist); /* If we get here it's definitely an error */ free_string_array(argvlist, argc); - Py_DECREF(opath); return posix_error(); } -PyDoc_STRVAR(posix_execve__doc__, -"execve(path, args, env)\n\n\ -Execute a path with arguments and environment, replacing current process.\n\ -\n\ - path: path of executable file\n\ - args: tuple or list of arguments\n\ - env: dictionary of strings mapping to strings\n\ -\n\ -On some platforms, you may specify an open file descriptor for path;\n\ - execve will execute the program the file descriptor is open to.\n\ - If this functionality is unavailable, using it raises NotImplementedError."); - -static PyObject * -posix_execve(PyObject *self, PyObject *args, PyObject *kwargs) -{ - path_t path; - PyObject *argv, *env; + +/*[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]*/ + +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]*/ +{ char **argvlist = NULL; char **envlist; Py_ssize_t argc, envc; - static char *keywords[] = {"path", "argv", "environment", NULL}; /* execve has three arguments: (path, argv, env), where argv is a list or tuple of strings and env is a dictionary like posix.environ. */ - memset(&path, 0, sizeof(path)); - path.function_name = "execve"; -#ifdef HAVE_FEXECVE - path.allow_fd = 1; -#endif - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&OO:execve", keywords, - path_converter, &path, - &argv, &env - )) - return NULL; - if (!PyList_Check(argv) && !PyTuple_Check(argv)) { PyErr_SetString(PyExc_TypeError, "execve: argv must be a tuple or list"); @@ -5277,15 +6802,15 @@ goto fail; #ifdef HAVE_FEXECVE - if (path.fd > -1) - fexecve(path.fd, argvlist, envlist); - else -#endif - execve(path.narrow, argvlist, envlist); + 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); + path_error(path); while (--envc >= 0) PyMem_DEL(envlist[envc]); @@ -5293,29 +6818,73 @@ fail: if (argvlist) free_string_array(argvlist, argc); - path_cleanup(&path); return NULL; } #endif /* HAVE_EXECV */ #ifdef HAVE_SPAWNV -PyDoc_STRVAR(posix_spawnv__doc__, -"spawnv(mode, path, args)\n\n\ -Execute the program 'path' in a new process.\n\ -\n\ - mode: mode of process creation\n\ - path: path of executable file\n\ - args: tuple or list of strings"); - -static PyObject * -posix_spawnv(PyObject *self, PyObject *args) -{ - PyObject *opath; - char *path; +/*[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]*/ + +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]*/ +{ + char *path_char; char **argvlist; - int mode, i; + int i; Py_ssize_t argc; Py_intptr_t spawnval; PyObject *(*getitem)(PyObject *, Py_ssize_t); @@ -5323,11 +6892,7 @@ /* spawnv has three arguments: (mode, path, argv), where argv is a list or tuple of strings. */ - if (!PyArg_ParseTuple(args, "iO&O:spawnv", &mode, - PyUnicode_FSConverter, - &opath, &argv)) - return NULL; - path = PyBytes_AsString(opath); + path_char = PyBytes_AsString(path); if (PyList_Check(argv)) { argc = PyList_Size(argv); getitem = PyList_GetItem; @@ -5339,13 +6904,11 @@ else { PyErr_SetString(PyExc_TypeError, "spawnv() arg 2 must be a tuple or list"); - Py_DECREF(opath); return NULL; } argvlist = PyMem_NEW(char *, argc+1); if (argvlist == NULL) { - Py_DECREF(opath); return PyErr_NoMemory(); } for (i = 0; i < argc; i++) { @@ -5355,7 +6918,6 @@ PyErr_SetString( PyExc_TypeError, "spawnv() arg 2 must contain only strings"); - Py_DECREF(opath); return NULL; } } @@ -5365,11 +6927,10 @@ mode = _P_OVERLAY; Py_BEGIN_ALLOW_THREADS - spawnval = _spawnv(mode, path, argvlist); + spawnval = _spawnv(mode, path_char, argvlist); Py_END_ALLOW_THREADS free_string_array(argvlist, argc); - Py_DECREF(opath); if (spawnval == -1) return posix_error(); @@ -5378,25 +6939,73 @@ } -PyDoc_STRVAR(posix_spawnve__doc__, -"spawnve(mode, path, args, env)\n\n\ -Execute the program 'path' in a new process.\n\ -\n\ - mode: mode of process creation\n\ - path: path of executable file\n\ - args: tuple or list of arguments\n\ - env: dictionary of strings mapping to strings"); - -static PyObject * -posix_spawnve(PyObject *self, PyObject *args) -{ - PyObject *opath; - char *path; - PyObject *argv, *env; +/*[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]*/ + +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]*/ +{ + char *path_char; char **argvlist; char **envlist; PyObject *res = NULL; - int mode; Py_ssize_t argc, i, envc; Py_intptr_t spawnval; PyObject *(*getitem)(PyObject *, Py_ssize_t); @@ -5406,11 +7015,7 @@ argv is a list or tuple of strings and env is a dictionary like posix.environ. */ - if (!PyArg_ParseTuple(args, "iO&OO:spawnve", &mode, - PyUnicode_FSConverter, - &opath, &argv, &env)) - return NULL; - path = PyBytes_AsString(opath); + path_char = PyBytes_AsString(path); if (PyList_Check(argv)) { argc = PyList_Size(argv); getitem = PyList_GetItem; @@ -5454,7 +7059,7 @@ mode = _P_OVERLAY; Py_BEGIN_ALLOW_THREADS - spawnval = _spawnve(mode, path, argvlist, envlist); + spawnval = _spawnve(mode, path_char, argvlist, envlist); Py_END_ALLOW_THREADS if (spawnval == -1) @@ -5468,7 +7073,6 @@ fail_1: free_string_array(argvlist, lastarg); fail_0: - Py_DECREF(opath); return res; } @@ -5476,14 +7080,37 @@ #ifdef HAVE_FORK1 -PyDoc_STRVAR(posix_fork1__doc__, -"fork1() -> pid\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."); - -static PyObject * -posix_fork1(PyObject *self, PyObject *noargs) +/*[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]*/ + +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]*/ { pid_t pid; int result = 0; @@ -5506,17 +7133,41 @@ } return PyLong_FromPid(pid); } -#endif +#endif /* HAVE_FORK1 */ #ifdef HAVE_FORK -PyDoc_STRVAR(posix_fork__doc__, -"fork() -> pid\n\n\ -Fork a child process.\n\ -Return 0 to child process and PID of child to parent process."); - -static PyObject * -posix_fork(PyObject *self, PyObject *noargs) +/*[clinic input] +os.fork + +Fork a child process. + +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]*/ { pid_t pid; int result = 0; @@ -5539,92 +7190,221 @@ } return PyLong_FromPid(pid); } -#endif +#endif /* HAVE_FORK */ + #ifdef HAVE_SCHED_H - #ifdef HAVE_SCHED_GET_PRIORITY_MAX - -PyDoc_STRVAR(posix_sched_get_priority_max__doc__, -"sched_get_priority_max(policy)\n\n\ -Get the maximum scheduling priority for *policy*."); - -static PyObject * -posix_sched_get_priority_max(PyObject *self, PyObject *args) -{ - int policy, max; - - if (!PyArg_ParseTuple(args, "i:sched_get_priority_max", &policy)) - return NULL; +/*[clinic input] +os.sched_get_priority_max + + policy: int + +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]*/ +{ + int max; + max = sched_get_priority_max(policy); if (max < 0) return posix_error(); return PyLong_FromLong(max); } -PyDoc_STRVAR(posix_sched_get_priority_min__doc__, -"sched_get_priority_min(policy)\n\n\ -Get the minimum scheduling priority for *policy*."); - -static PyObject * -posix_sched_get_priority_min(PyObject *self, PyObject *args) -{ - int policy, min; - - if (!PyArg_ParseTuple(args, "i:sched_get_priority_min", &policy)) - return NULL; - min = sched_get_priority_min(policy); + +/*[clinic input] +os.sched_get_priority_min + + policy: int + +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]*/ +{ + 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 - -PyDoc_STRVAR(posix_sched_getscheduler__doc__, -"sched_getscheduler(pid)\n\n\ -Get the scheduling policy for the process with a PID of *pid*.\n\ -Passing a PID of 0 returns the scheduling policy for the calling process."); - -static PyObject * -posix_sched_getscheduler(PyObject *self, PyObject *args) -{ +/*[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]*/ + +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]*/ +{ int policy; - if (!PyArg_ParseTuple(args, _Py_PARSE_PID ":sched_getscheduler", &pid)) - return NULL; policy = sched_getscheduler(pid); if (policy < 0) return posix_error(); return PyLong_FromLong(policy); } - -#endif +#endif /* HAVE_SCHED_SETSCHEDULER */ + #if defined(HAVE_SCHED_SETSCHEDULER) || defined(HAVE_SCHED_SETPARAM) - -static PyObject * -sched_param_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) -{ - PyObject *res, *priority; - static char *kwlist[] = {"sched_priority", NULL}; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O:sched_param", kwlist, &priority)) - return NULL; +/*[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]*/ + +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]*/ +{ + PyObject *res; + res = PyStructSequence_New(type); if (!res) return NULL; - Py_INCREF(priority); - PyStructSequence_SET_ITEM(res, 0, priority); + Py_INCREF(sched_priority); + PyStructSequence_SET_ITEM(res, 0, sched_priority); return res; } -PyDoc_STRVAR(sched_param__doc__, -"sched_param(sched_priority): A scheduling parameter.\n\n\ -Current has only one field: sched_priority"); static PyStructSequence_Field sched_param_fields[] = { {"sched_priority", "the scheduling priority"}, @@ -5633,7 +7413,7 @@ static PyStructSequence_Desc sched_param_desc = { "sched_param", /* name */ - sched_param__doc__, /* doc */ + os_sched_param__doc__, /* doc */ sched_param_fields, 1 }; @@ -5657,158 +7437,353 @@ res->sched_priority = Py_SAFE_DOWNCAST(priority, long, int); return 1; } - -#endif +#endif /* defined(HAVE_SCHED_SETSCHEDULER) || defined(HAVE_SCHED_SETPARAM) */ + #ifdef HAVE_SCHED_SETSCHEDULER - -PyDoc_STRVAR(posix_sched_setscheduler__doc__, -"sched_setscheduler(pid, policy, param)\n\n\ -Set the scheduling policy, *policy*, for *pid*.\n\ -If *pid* is 0, the calling process is changed.\n\ -*param* is an instance of sched_param."); - -static PyObject * -posix_sched_setscheduler(PyObject *self, PyObject *args) -{ +/*[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]*/ + +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)) - return NULL; - + 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]*/ +{ /* ** 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, ¶m) == -1) + if (sched_setscheduler(pid, policy, param) == -1) return posix_error(); Py_RETURN_NONE; } - -#endif +#endif /* HAVE_SCHED_SETSCHEDULER*/ + #ifdef HAVE_SCHED_SETPARAM - -PyDoc_STRVAR(posix_sched_getparam__doc__, -"sched_getparam(pid) -> sched_param\n\n\ -Returns scheduling parameters for the process with *pid* as an instance of the\n\ -sched_param class. A PID of 0 means the calling process."); - -static PyObject * -posix_sched_getparam(PyObject *self, PyObject *args) -{ +/*[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]*/ + +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]*/ +{ + 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]*/ + +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; - PyObject *res, *priority; - - if (!PyArg_ParseTuple(args, _Py_PARSE_PID ":sched_getparam", &pid)) - return NULL; - if (sched_getparam(pid, ¶m)) - return posix_error(); - res = PyStructSequence_New(&SchedParamType); - if (!res) - return NULL; - priority = PyLong_FromLong(param.sched_priority); - if (!priority) { - Py_DECREF(res); - return NULL; - } - PyStructSequence_SET_ITEM(res, 0, priority); - return res; -} - -PyDoc_STRVAR(posix_sched_setparam__doc__, -"sched_setparam(pid, param)\n\n\ -Set scheduling parameters for a process with PID *pid*.\n\ -A PID of 0 means the calling process."); - -static PyObject * -posix_sched_setparam(PyObject *self, PyObject *args) -{ + + 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]*/ +{ + 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]*/ + +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; - struct sched_param param; - - if (!PyArg_ParseTuple(args, _Py_PARSE_PID "O&:sched_setparam", - &pid, &convert_sched_param, ¶m)) - return NULL; - if (sched_setparam(pid, ¶m)) + 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]*/ +{ + 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]*/ + +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]*/ +{ + if (sched_yield()) return posix_error(); Py_RETURN_NONE; } -#endif - -#ifdef HAVE_SCHED_RR_GET_INTERVAL - -PyDoc_STRVAR(posix_sched_rr_get_interval__doc__, -"sched_rr_get_interval(pid) -> float\n\n\ -Return the round-robin quantum for the process with PID *pid* in seconds."); - -static PyObject * -posix_sched_rr_get_interval(PyObject *self, PyObject *args) -{ - pid_t pid; - struct timespec interval; - - if (!PyArg_ParseTuple(args, _Py_PARSE_PID ":sched_rr_get_interval", &pid)) - return NULL; - if (sched_rr_get_interval(pid, &interval)) - return posix_error(); - return PyFloat_FromDouble((double)interval.tv_sec + 1e-9*interval.tv_nsec); -} - -#endif - -PyDoc_STRVAR(posix_sched_yield__doc__, -"sched_yield()\n\n\ -Voluntarily relinquish the CPU."); - -static PyObject * -posix_sched_yield(PyObject *self, PyObject *noargs) -{ - 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; -PyDoc_STRVAR(posix_sched_setaffinity__doc__, -"sched_setaffinity(pid, cpu_set)\n\n\ -Set the affinity of the process with PID *pid* to *cpu_set*."); - -static PyObject * -posix_sched_setaffinity(PyObject *self, PyObject *args) -{ +/*[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]*/ + +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]*/ +{ int ncpus; size_t setsize; - cpu_set_t *mask = NULL; - PyObject *iterable, *iterator = NULL, *item; - - if (!PyArg_ParseTuple(args, _Py_PARSE_PID "O:sched_setaffinity", - &pid, &iterable)) - return NULL; - - iterator = PyObject_GetIter(iterable); + 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); - mask = CPU_ALLOC(ncpus); - if (mask == NULL) { + cpu_set = CPU_ALLOC(ncpus); + if (cpu_set == NULL) { PyErr_NoMemory(); goto error; } - CPU_ZERO_S(setsize, mask); + CPU_ZERO_S(setsize, cpu_set); while ((item = PyIter_Next(iterator))) { long cpu; @@ -5849,48 +7824,80 @@ } newsetsize = CPU_ALLOC_SIZE(newncpus); CPU_ZERO_S(newsetsize, newmask); - memcpy(newmask, mask, setsize); - CPU_FREE(mask); + memcpy(newmask, cpu_set, setsize); + CPU_FREE(cpu_set); setsize = newsetsize; - mask = newmask; + cpu_set = newmask; ncpus = newncpus; } - CPU_SET_S(cpu, setsize, mask); + CPU_SET_S(cpu, setsize, cpu_set); } Py_CLEAR(iterator); - if (sched_setaffinity(pid, setsize, mask)) { + if (sched_setaffinity(pid, setsize, cpu_set)) { posix_error(); goto error; } - CPU_FREE(mask); + CPU_FREE(cpu_set); Py_RETURN_NONE; error: - if (mask) - CPU_FREE(mask); + if (cpu_set) + CPU_FREE(cpu_set); Py_XDECREF(iterator); return NULL; } -PyDoc_STRVAR(posix_sched_getaffinity__doc__, -"sched_getaffinity(pid, ncpus) -> cpu_set\n\n\ -Return the affinity of the process with PID *pid*.\n\ -The returned cpu_set will be of size *ncpus*."); - -static PyObject * -posix_sched_getaffinity(PyObject *self, PyObject *args) -{ + +/*[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]*/ + +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]*/ +{ int cpu, ncpus, count; size_t setsize; cpu_set_t *mask = NULL; PyObject *res = NULL; - if (!PyArg_ParseTuple(args, _Py_PARSE_PID ":sched_getaffinity", - &pid)) - return NULL; - ncpus = NCPUS_START; while (1) { setsize = CPU_ALLOC_SIZE(ncpus); @@ -5940,6 +7947,47 @@ #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) @@ -5966,13 +8014,41 @@ #endif #endif /* defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_DEV_PTMX */ + #if defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX) -PyDoc_STRVAR(posix_openpty__doc__, -"openpty() -> (master_fd, slave_fd)\n\n\ -Open a pseudo-terminal, returning open fd's for both master and slave end.\n"); - -static PyObject * -posix_openpty(PyObject *self, PyObject *noargs) +/*[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]*/ + +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]*/ { int master_fd = -1, slave_fd = -1; #ifndef HAVE_OPENPTY @@ -6061,15 +8137,45 @@ } #endif /* defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX) */ + #ifdef HAVE_FORKPTY -PyDoc_STRVAR(posix_forkpty__doc__, -"forkpty() -> (pid, master_fd)\n\n\ -Fork a new process with a new pseudo-terminal as controlling tty.\n\n\ -Like fork(), return 0 as pid to child process, and PID of child to parent.\n\ -To both, return fd of newly opened pseudo-terminal.\n"); - -static PyObject * -posix_forkpty(PyObject *self, PyObject *noargs) +/*[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]*/ + +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]*/ { int master_fd = -1, result = 0; pid_t pid; @@ -6093,59 +8199,145 @@ } return Py_BuildValue("(Ni)", PyLong_FromPid(pid), master_fd); } -#endif +#endif /* HAVE_FORKPTY */ #ifdef HAVE_GETEGID -PyDoc_STRVAR(posix_getegid__doc__, -"getegid() -> egid\n\n\ -Return the current process's effective group id."); - -static PyObject * -posix_getegid(PyObject *self, PyObject *noargs) +/*[clinic input] +os.getegid + +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]*/ { return _PyLong_FromGid(getegid()); } -#endif +#endif /* HAVE_GETEGID */ #ifdef HAVE_GETEUID -PyDoc_STRVAR(posix_geteuid__doc__, -"geteuid() -> euid\n\n\ -Return the current process's effective user id."); - -static PyObject * -posix_geteuid(PyObject *self, PyObject *noargs) +/*[clinic input] +os.geteuid + +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]*/ { return _PyLong_FromUid(geteuid()); } -#endif +#endif /* HAVE_GETEUID */ #ifdef HAVE_GETGID -PyDoc_STRVAR(posix_getgid__doc__, -"getgid() -> gid\n\n\ -Return the current process's group id."); - -static PyObject * -posix_getgid(PyObject *self, PyObject *noargs) +/*[clinic input] +os.getgid + +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]*/ { return _PyLong_FromGid(getgid()); } -#endif - - -PyDoc_STRVAR(posix_getpid__doc__, -"getpid() -> pid\n\n\ -Return the current process id"); - -static PyObject * -posix_getpid(PyObject *self, PyObject *noargs) +#endif /* HAVE_GETGID */ + + +/*[clinic input] +os.getpid + +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]*/ { 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\ @@ -6218,15 +8410,37 @@ return list; } -#endif +#endif /* HAVE_GETGROUPLIST */ + #ifdef HAVE_GETGROUPS -PyDoc_STRVAR(posix_getgroups__doc__, -"getgroups() -> list of group IDs\n\n\ -Return list of supplemental group IDs for the process."); - -static PyObject * -posix_getgroups(PyObject *self, PyObject *noargs) +/*[clinic input] +os.getgroups + +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]*/ { PyObject *result = NULL; @@ -6325,7 +8539,7 @@ return result; } -#endif +#endif /* HAVE_GETGROUPS */ #ifdef HAVE_INITGROUPS PyDoc_STRVAR(posix_initgroups__doc__, @@ -6334,6 +8548,7 @@ 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) { @@ -6366,20 +8581,52 @@ Py_INCREF(Py_None); return Py_None; } -#endif +#endif /* HAVE_INITGROUPS */ + #ifdef HAVE_GETPGID -PyDoc_STRVAR(posix_getpgid__doc__, -"getpgid(pid) -> pgid\n\n\ -Call the system call getpgid()."); - -static PyObject * -posix_getpgid(PyObject *self, PyObject *args) -{ - pid_t pid, pgid; - if (!PyArg_ParseTuple(args, _Py_PARSE_PID ":getpgid", &pid)) - return NULL; - pgid = getpgid(pid); +/*[clinic input] +os.getpgid + + pid: pid_t + +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]*/ +{ + pid_t pgid = getpgid(pid); if (pgid < 0) return posix_error(); return PyLong_FromPid(pgid); @@ -6388,12 +8635,33 @@ #ifdef HAVE_GETPGRP -PyDoc_STRVAR(posix_getpgrp__doc__, -"getpgrp() -> pgrp\n\n\ -Return the current process group id."); - -static PyObject * -posix_getpgrp(PyObject *self, PyObject *noargs) +/*[clinic input] +os.getpgrp + +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]*/ { #ifdef GETPGRP_HAVE_ARG return PyLong_FromPid(getpgrp(0)); @@ -6405,12 +8673,33 @@ #ifdef HAVE_SETPGRP -PyDoc_STRVAR(posix_setpgrp__doc__, -"setpgrp()\n\n\ -Make this process the process group leader."); - -static PyObject * -posix_setpgrp(PyObject *self, PyObject *noargs) +/*[clinic input] +os.setpgrp + +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]*/ { #ifdef SETPGRP_HAVE_ARG if (setpgrp(0, 0) < 0) @@ -6421,7 +8710,6 @@ Py_INCREF(Py_None); return Py_None; } - #endif /* HAVE_SETPGRP */ #ifdef HAVE_GETPPID @@ -6468,14 +8756,40 @@ } #endif /*MS_WINDOWS*/ -PyDoc_STRVAR(posix_getppid__doc__, -"getppid() -> ppid\n\n\ -Return the parent's process id. If the parent process has already exited,\n\ -Windows machines will still return its id; others systems will return the id\n\ -of the 'init' process (1)."); - -static PyObject * -posix_getppid(PyObject *self, PyObject *noargs) + +/*[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]*/ + +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]*/ { #ifdef MS_WINDOWS return win32_getppid(); @@ -6487,12 +8801,33 @@ #ifdef HAVE_GETLOGIN -PyDoc_STRVAR(posix_getlogin__doc__, -"getlogin() -> string\n\n\ -Return the actual login name."); - -static PyObject * -posix_getlogin(PyObject *self, PyObject *noargs) +/*[clinic input] +os.getlogin + +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]*/ { PyObject *result = NULL; #ifdef MS_WINDOWS @@ -6525,77 +8860,101 @@ } #endif /* HAVE_GETLOGIN */ + #ifdef HAVE_GETUID -PyDoc_STRVAR(posix_getuid__doc__, -"getuid() -> uid\n\n\ -Return the current process's user id."); - -static PyObject * -posix_getuid(PyObject *self, PyObject *noargs) +/*[clinic input] +os.getuid + +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]*/ { return _PyLong_FromUid(getuid()); } -#endif - +#endif /* HAVE_GETUID */ + + +#ifdef MS_WINDOWS +#define HAVE_KILL +#endif /* MS_WINDOWS */ #ifdef HAVE_KILL -PyDoc_STRVAR(posix_kill__doc__, -"kill(pid, sig)\n\n\ -Kill a process with a signal."); - -static PyObject * -posix_kill(PyObject *self, PyObject *args) -{ +/*[clinic input] +os.kill + + pid: pid_t + signal: Py_ssize_t + / + +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; - int sig; - if (!PyArg_ParseTuple(args, _Py_PARSE_PID "i:kill", &pid, &sig)) - return NULL; - if (kill(pid, sig) == -1) - return posix_error(); - Py_INCREF(Py_None); - return Py_None; -} -#endif - -#ifdef HAVE_KILLPG -PyDoc_STRVAR(posix_killpg__doc__, -"killpg(pgid, sig)\n\n\ -Kill a process group with a signal."); - -static PyObject * -posix_killpg(PyObject *self, PyObject *args) -{ - int sig; - pid_t pgid; - /* 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 (!PyArg_ParseTuple(args, _Py_PARSE_PID "i:killpg", &pgid, &sig)) - return NULL; - if (killpg(pgid, sig) == -1) - return posix_error(); - Py_INCREF(Py_None); - return Py_None; -} -#endif - -#ifdef MS_WINDOWS -PyDoc_STRVAR(win32_kill__doc__, -"kill(pid, sig)\n\n\ -Kill a process with a signal."); - -static PyObject * -win32_kill(PyObject *self, PyObject *args) + 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]*/ +#ifndef MS_WINDOWS +{ + if (kill(pid, (int)signal) == -1) + return posix_error(); + Py_RETURN_NONE; +} +#else /* !MS_WINDOWS */ { PyObject *result; - pid_t pid; - DWORD sig, err; + DWORD sig = (DWORD)signal; + DWORD err; HANDLE handle; - if (!PyArg_ParseTuple(args, _Py_PARSE_PID "k:kill", &pid, &sig)) - return NULL; - /* 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) { @@ -6626,159 +8985,439 @@ CloseHandle(handle); return result; } -#endif /* MS_WINDOWS */ +#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]*/ + +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]*/ +{ + /* 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 -PyDoc_STRVAR(posix_plock__doc__, -"plock(op)\n\n\ +/*[clinic input] +os.plock + op: int + / + Lock program segments into memory."); - -static PyObject * -posix_plock(PyObject *self, PyObject *args) -{ +[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)) - return NULL; + + 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]*/ +{ if (plock(op) == -1) return posix_error(); - Py_INCREF(Py_None); - return Py_None; -} -#endif + Py_RETURN_NONE; +} +#endif /* HAVE_PLOCK */ + #ifdef HAVE_SETUID -PyDoc_STRVAR(posix_setuid__doc__, -"setuid(uid)\n\n\ -Set the current process's user id."); - -static PyObject * -posix_setuid(PyObject *self, PyObject *args) -{ +/*[clinic input] +os.setuid + + uid: uid_t + / + +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)) - return NULL; + + 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]*/ +{ if (setuid(uid) < 0) return posix_error(); - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; } #endif /* HAVE_SETUID */ #ifdef HAVE_SETEUID -PyDoc_STRVAR(posix_seteuid__doc__, -"seteuid(uid)\n\n\ -Set the current process's effective user id."); - -static PyObject * -posix_seteuid (PyObject *self, PyObject *args) -{ +/*[clinic input] +os.seteuid + + euid: uid_t + / + +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)) - return NULL; - if (seteuid(euid) < 0) { + + 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]*/ +{ + 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]*/ + +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]*/ +{ + 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]*/ + +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]*/ +{ + if (setreuid(ruid, euid) < 0) { return posix_error(); } else { Py_INCREF(Py_None); return Py_None; } } -#endif /* HAVE_SETEUID */ - -#ifdef HAVE_SETEGID -PyDoc_STRVAR(posix_setegid__doc__, -"setegid(gid)\n\n\ -Set the current process's effective group id."); - -static PyObject * -posix_setegid (PyObject *self, PyObject *args) -{ +#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]*/ + +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&:setegid", _Py_Gid_Converter, &egid)) - return NULL; - if (setegid(egid) < 0) { - return posix_error(); - } else { - Py_INCREF(Py_None); - return Py_None; - } -} -#endif /* HAVE_SETEGID */ - -#ifdef HAVE_SETREUID -PyDoc_STRVAR(posix_setreuid__doc__, -"setreuid(ruid, euid)\n\n\ -Set the current process's real and effective user ids."); - -static PyObject * -posix_setreuid (PyObject *self, PyObject *args) -{ - uid_t ruid, euid; - if (!PyArg_ParseTuple(args, "O&O&:setreuid", - _Py_Uid_Converter, &ruid, - _Py_Uid_Converter, &euid)) - return NULL; - if (setreuid(ruid, euid) < 0) { - return posix_error(); - } else { - Py_INCREF(Py_None); - return Py_None; - } -} -#endif /* HAVE_SETREUID */ - -#ifdef HAVE_SETREGID -PyDoc_STRVAR(posix_setregid__doc__, -"setregid(rgid, egid)\n\n\ -Set the current process's real and effective group ids."); - -static PyObject * -posix_setregid (PyObject *self, PyObject *args) -{ - gid_t rgid, egid; - if (!PyArg_ParseTuple(args, "O&O&:setregid", - _Py_Gid_Converter, &rgid, - _Py_Gid_Converter, &egid)) - return NULL; - if (setregid(rgid, egid) < 0) { - return posix_error(); - } else { - Py_INCREF(Py_None); - return Py_None; - } + + 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]*/ +{ + if (setregid(rgid, egid) < 0) + return posix_error(); + Py_RETURN_NONE; } #endif /* HAVE_SETREGID */ + #ifdef HAVE_SETGID -PyDoc_STRVAR(posix_setgid__doc__, -"setgid(gid)\n\n\ -Set the current process's group id."); - -static PyObject * -posix_setgid(PyObject *self, PyObject *args) -{ +/*[clinic input] +os.setgid + gid: gid_t + / + +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)) - return NULL; + + 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]*/ +{ if (setgid(gid) < 0) return posix_error(); - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; } #endif /* HAVE_SETGID */ + #ifdef HAVE_SETGROUPS -PyDoc_STRVAR(posix_setgroups__doc__, -"setgroups(list)\n\n\ -Set the groups of the current process to list."); - -static PyObject * -posix_setgroups(PyObject *self, PyObject *groups) +/*[clinic input] +os.setgroups + + groups: object + / + +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]*/ { int i, len; gid_t grouplist[MAX_GROUPS]; @@ -6879,23 +9518,59 @@ } #endif /* HAVE_WAIT3 || HAVE_WAIT4 */ + #ifdef HAVE_WAIT3 -PyDoc_STRVAR(posix_wait3__doc__, -"wait3(options) -> (pid, status, rusage)\n\n\ -Wait for completion of a child process."); - -static PyObject * -posix_wait3(PyObject *self, PyObject *args) +/*[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]*/ + +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]*/ { pid_t pid; - int options; struct rusage ru; WAIT_TYPE status; WAIT_STATUS_INT(status) = 0; - if (!PyArg_ParseTuple(args, "i:wait3", &options)) - return NULL; - Py_BEGIN_ALLOW_THREADS pid = wait3(&status, options, &ru); Py_END_ALLOW_THREADS @@ -6904,23 +9579,62 @@ } #endif /* HAVE_WAIT3 */ + #ifdef HAVE_WAIT4 -PyDoc_STRVAR(posix_wait4__doc__, -"wait4(pid, options) -> (pid, status, rusage)\n\n\ -Wait for completion of a given child process."); - -static PyObject * -posix_wait4(PyObject *self, PyObject *args) -{ +/*[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]*/ + +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]*/ +{ struct rusage ru; WAIT_TYPE status; WAIT_STATUS_INT(status) = 0; - if (!PyArg_ParseTuple(args, _Py_PARSE_PID "i:wait4", &pid, &options)) - return NULL; - Py_BEGIN_ALLOW_THREADS pid = wait4(pid, &status, options, &ru); Py_END_ALLOW_THREADS @@ -6929,28 +9643,76 @@ } #endif /* HAVE_WAIT4 */ + #if defined(HAVE_WAITID) && !defined(__APPLE__) -PyDoc_STRVAR(posix_waitid__doc__, -"waitid(idtype, id, options) -> waitid_result\n\n\ -Wait for the completion of one or more child processes.\n\n\ -idtype can be P_PID, P_PGID or P_ALL.\n\ -id specifies the pid to wait on.\n\ -options is constructed from the ORing of one or more of WEXITED, WSTOPPED\n\ -or WCONTINUED and additionally may be ORed with WNOHANG or WNOWAIT.\n\ -Returns either waitid_result or None if WNOHANG is specified and there are\n\ -no children in a waitable state."); - -static PyObject * -posix_waitid(PyObject *self, PyObject *args) -{ - PyObject *result; +/*[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]*/ + +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, res; + 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]*/ +{ + PyObject *result; + int res; siginfo_t si; si.si_pid = 0; - if (!PyArg_ParseTuple(args, "i" _Py_PARSE_PID "i:waitid", &idtype, &id, &options)) - return NULL; + Py_BEGIN_ALLOW_THREADS res = waitid(idtype, id, &si, options); Py_END_ALLOW_THREADS @@ -6976,23 +9738,65 @@ return result; } -#endif - -#ifdef HAVE_WAITPID -PyDoc_STRVAR(posix_waitpid__doc__, -"waitpid(pid, options) -> (pid, status)\n\n\ -Wait for completion of a given child process."); - -static PyObject * -posix_waitpid(PyObject *self, PyObject *args) -{ +#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" +"--\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]*/ +{ WAIT_TYPE status; WAIT_STATUS_INT(status) = 0; - if (!PyArg_ParseTuple(args, _Py_PARSE_PID "i:waitpid", &pid, &options)) - return NULL; Py_BEGIN_ALLOW_THREADS pid = waitpid(pid, &status, options); Py_END_ALLOW_THREADS @@ -7001,22 +9805,62 @@ return Py_BuildValue("Ni", PyLong_FromPid(pid), WAIT_STATUS_INT(status)); } - #elif defined(HAVE_CWAIT) - /* MS C has a variant of waitpid() that's usable for most purposes. */ -PyDoc_STRVAR(posix_waitpid__doc__, -"waitpid(pid, options) -> (pid, status << 8)\n\n" -"Wait for completion of a given process. options is ignored on Windows."); - -static PyObject * -posix_waitpid(PyObject *self, PyObject *args) -{ +/*[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]*/ + +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 status, options; - - if (!PyArg_ParseTuple(args, _Py_PARSE_INTPTR "i:waitpid", &pid, &options)) - return NULL; + 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]*/ +{ + int status; + Py_BEGIN_ALLOW_THREADS pid = _cwait(&status, pid, options); Py_END_ALLOW_THREADS @@ -7026,15 +9870,43 @@ /* shift the status left a byte so this is more like the POSIX waitpid */ return Py_BuildValue(_Py_PARSE_INTPTR "i", pid, status << 8); } -#endif /* HAVE_WAITPID || HAVE_CWAIT */ +#endif + #ifdef HAVE_WAIT -PyDoc_STRVAR(posix_wait__doc__, -"wait() -> (pid, status)\n\n\ -Wait for completion of a child process."); - -static PyObject * -posix_wait(PyObject *self, PyObject *noargs) +/*[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]*/ + +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]*/ { pid_t pid; WAIT_TYPE status; @@ -7048,7 +9920,7 @@ return Py_BuildValue("Ni", PyLong_FromPid(pid), WAIT_STATUS_INT(status)); } -#endif +#endif /* HAVE_WAIT */ #if defined(HAVE_READLINK) || defined(MS_WINDOWS) @@ -7064,6 +9936,7 @@ #ifdef HAVE_READLINK +/* AC 3.5: merge win32 and not together */ static PyObject * posix_readlink(PyObject *self, PyObject *args, PyObject *kwargs) { @@ -7078,12 +9951,7 @@ path.function_name = "readlink"; if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&|$O&:readlink", keywords, path_converter, &path, -#ifdef HAVE_READLINKAT - dir_fd_converter, &dir_fd -#else - dir_fd_unavailable, &dir_fd -#endif - )) + READLINKAT_DIR_FD_CONVERTER, &dir_fd)) return NULL; Py_BEGIN_ALLOW_THREADS @@ -7109,23 +9977,86 @@ 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 -PyDoc_STRVAR(posix_symlink__doc__, -"symlink(src, dst, target_is_directory=False, *, dir_fd=None)\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."); #if defined(MS_WINDOWS) @@ -7271,189 +10202,148 @@ && src_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ); } - -#endif - -static PyObject * -posix_symlink(PyObject *self, PyObject *args, PyObject *kwargs) -{ - path_t src; - path_t dst; +#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]*/ + +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; - int target_is_directory = 0; - static char *keywords[] = {"src", "dst", "target_is_directory", - "dir_fd", NULL}; - PyObject *return_value; + + 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]*/ +{ #ifdef MS_WINDOWS DWORD result; #else int result; #endif - memset(&src, 0, sizeof(src)); - src.function_name = "symlink"; - src.argument_name = "src"; - memset(&dst, 0, sizeof(dst)); - dst.function_name = "symlink"; - dst.argument_name = "dst"; - #ifdef MS_WINDOWS if (!check_CreateSymbolicLink()) { PyErr_SetString(PyExc_NotImplementedError, "CreateSymbolicLink functions not found"); - return NULL; + return NULL; } if (!win32_can_symlink) { PyErr_SetString(PyExc_OSError, "symbolic link privilege not held"); - return NULL; - } -#endif - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&O&|i$O&:symlink", - keywords, - path_converter, &src, - path_converter, &dst, - &target_is_directory, -#ifdef HAVE_SYMLINKAT - dir_fd_converter, &dir_fd -#else - dir_fd_unavailable, &dir_fd -#endif - )) - return NULL; - - if ((src.narrow && dst.wide) || (src.wide && dst.narrow)) { + 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_value = NULL; - goto exit; - } - -#ifdef MS_WINDOWS - - Py_BEGIN_ALLOW_THREADS - if (dst.wide) { + 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 |= _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 |= _check_dirA(src->narrow, dst->narrow); + result = Py_CreateSymbolicLinkA(dst->narrow, src->narrow, target_is_directory); } Py_END_ALLOW_THREADS - if (!result) { - return_value = path_error2(&src, &dst); - goto exit; - } + 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_value = path_error2(&src, &dst); - goto exit; - } -#endif - - return_value = Py_None; - Py_INCREF(Py_None); - goto exit; /* silence "unused label" warning */ -exit: - path_cleanup(&src); - path_cleanup(&dst); - return return_value; -} - + 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 */ -#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) */ static PyStructSequence_Field times_result_fields[] = { @@ -7519,15 +10409,48 @@ return value; } -PyDoc_STRVAR(posix_times__doc__, -"times() -> times_result\n\n\ -Return an object containing floating point numbers indicating process\n\ -times. The object behaves like a named tuple with these fields:\n\ - (utime, stime, cutime, cstime, elapsed_time)"); - -#if defined(MS_WINDOWS) -static PyObject * -posix_times(PyObject *self, PyObject *noargs) + +#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]*/ + +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]*/ +#ifdef MS_WINDOWS { FILETIME create, exit, kernel, user; HANDLE hProc; @@ -7547,12 +10470,10 @@ (double)0, (double)0); } -#else /* Not Windows */ -#define NEED_TICKS_PER_SECOND -static long ticks_per_second = -1; -static PyObject * -posix_times(PyObject *self, PyObject *noargs) -{ +#else /* MS_WINDOWS */ +{ + + struct tms t; clock_t c; errno = 0; @@ -7566,23 +10487,53 @@ (double)t.tms_cstime / ticks_per_second, (double)c / ticks_per_second); } -#endif - +#endif /* MS_WINDOWS */ #endif /* HAVE_TIMES */ #ifdef HAVE_GETSID -PyDoc_STRVAR(posix_getsid__doc__, -"getsid(pid) -> sid\n\n\ -Call the system call getsid()."); - -static PyObject * -posix_getsid(PyObject *self, PyObject *args) -{ +/*[clinic input] +os.getsid + + pid: pid_t + / + +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]*/ +{ int sid; - if (!PyArg_ParseTuple(args, _Py_PARSE_PID ":getsid", &pid)) - return NULL; sid = getsid(pid); if (sid < 0) return posix_error(); @@ -7592,76 +10543,189 @@ #ifdef HAVE_SETSID -PyDoc_STRVAR(posix_setsid__doc__, -"setsid()\n\n\ -Call the system call setsid()."); - -static PyObject * -posix_setsid(PyObject *self, PyObject *noargs) +/*[clinic input] +os.setsid + +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]*/ { if (setsid() < 0) return posix_error(); - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; } #endif /* HAVE_SETSID */ + #ifdef HAVE_SETPGID -PyDoc_STRVAR(posix_setpgid__doc__, -"setpgid(pid, pgrp)\n\n\ -Call the system call setpgid()."); - -static PyObject * -posix_setpgid(PyObject *self, PyObject *args) -{ +/*[clinic input] +os.setpgid + + pid: pid_t + pgrp: pid_t + / + +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; - int pgrp; - if (!PyArg_ParseTuple(args, _Py_PARSE_PID "i:setpgid", &pid, &pgrp)) - return NULL; + 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]*/ +{ if (setpgid(pid, pgrp) < 0) return posix_error(); - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; } #endif /* HAVE_SETPGID */ #ifdef HAVE_TCGETPGRP -PyDoc_STRVAR(posix_tcgetpgrp__doc__, -"tcgetpgrp(fd) -> pgid\n\n\ -Return the process group associated with the terminal given by a fd."); - -static PyObject * -posix_tcgetpgrp(PyObject *self, PyObject *args) -{ +/*[clinic input] +os.tcgetpgrp + + fd: int + / + +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]*/ +{ + 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]*/ + +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:tcgetpgrp", &fd)) - return NULL; - pgid = tcgetpgrp(fd); - if (pgid < 0) - return posix_error(); - return PyLong_FromPid(pgid); -} -#endif /* HAVE_TCGETPGRP */ - - -#ifdef HAVE_TCSETPGRP -PyDoc_STRVAR(posix_tcsetpgrp__doc__, -"tcsetpgrp(fd, pgid)\n\n\ -Set the process group associated with the terminal given by a fd."); - -static PyObject * -posix_tcsetpgrp(PyObject *self, PyObject *args) -{ - int fd; - pid_t pgid; - if (!PyArg_ParseTuple(args, "i" _Py_PARSE_PID ":tcsetpgrp", &fd, &pgid)) - return NULL; + + 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]*/ +{ if (tcsetpgrp(fd, pgid) < 0) return posix_error(); - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; } #endif /* HAVE_TCSETPGRP */ @@ -7671,44 +10735,81 @@ extern int _Py_open_cloexec_works; #endif -PyDoc_STRVAR(posix_open__doc__, -"open(path, flags, mode=0o777, *, dir_fd=None)\n\n\ -Open a file for low level IO. Returns a file handle (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."); - -static PyObject * -posix_open(PyObject *self, PyObject *args, PyObject *kwargs) -{ - path_t path; + +/*[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]*/ + +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 = 0777; + 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]*/ +{ int fd; - PyObject *return_value = NULL; - static char *keywords[] = {"path", "flags", "mode", "dir_fd", NULL}; + #ifdef O_CLOEXEC int *atomic_flag_works = &_Py_open_cloexec_works; #elif !defined(MS_WINDOWS) int *atomic_flag_works = NULL; #endif - memset(&path, 0, sizeof(path)); - path.function_name = "open"; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&i|i$O&:open", keywords, - path_converter, &path, - &flags, &mode, -#ifdef HAVE_OPENAT - dir_fd_converter, &dir_fd -#else - dir_fd_unavailable, &dir_fd -#endif - )) - return NULL; - #ifdef MS_WINDOWS flags |= O_NOINHERIT; #elif defined(O_CLOEXEC) @@ -7717,51 +10818,76 @@ Py_BEGIN_ALLOW_THREADS #ifdef MS_WINDOWS - if (path.wide) - fd = _wopen(path.wide, flags, mode); + 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); + fd = openat(dir_fd, path->narrow, flags, mode); + else +#endif + fd = open(path->narrow, flags, mode); Py_END_ALLOW_THREADS if (fd == -1) { - PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path.object); - goto exit; + PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path->object); + return -1; } #ifndef MS_WINDOWS if (_Py_set_inheritable(fd, 0, atomic_flag_works) < 0) { close(fd); - goto exit; - } -#endif - - return_value = PyLong_FromLong((long)fd); - -exit: - path_cleanup(&path); - return return_value; -} - -PyDoc_STRVAR(posix_close__doc__, -"close(fd)\n\n\ -Close a file descriptor (for low level IO)."); - -/* -The underscore at end of function name avoids a name clash with the libc -function posix_close. -*/ -static PyObject * -posix_close_(PyObject *self, PyObject *args) -{ - int fd, res; - if (!PyArg_ParseTuple(args, "i:close", &fd)) - return NULL; + 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" +"\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]*/ +{ + int res; if (!_PyVerify_fd(fd)) return posix_error(); Py_BEGIN_ALLOW_THREADS @@ -7769,23 +10895,56 @@ Py_END_ALLOW_THREADS if (res < 0) return posix_error(); - Py_INCREF(Py_None); - return Py_None; -} - - -PyDoc_STRVAR(posix_closerange__doc__, -"closerange(fd_low, fd_high)\n\n\ -Closes all file descriptors in [fd_low, fd_high), ignoring errors."); - -static PyObject * -posix_closerange(PyObject *self, PyObject *args) -{ - int fd_from, fd_to, i; - if (!PyArg_ParseTuple(args, "ii:closerange", &fd_from, &fd_to)) - return NULL; - Py_BEGIN_ALLOW_THREADS - for (i = fd_from; i < fd_to; i++) + 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" +"\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]*/ +{ + int i; + Py_BEGIN_ALLOW_THREADS + for (i = fd_low; i < fd_high; i++) if (_PyVerify_fd(i)) close(i); Py_END_ALLOW_THREADS @@ -7793,36 +10952,99 @@ } -PyDoc_STRVAR(posix_dup__doc__, -"dup(fd) -> fd2\n\n\ -Return a duplicate of a file descriptor."); - -static PyObject * -posix_dup(PyObject *self, PyObject *args) -{ +/*[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" +"\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; - - if (!PyArg_ParseTuple(args, "i:dup", &fd)) - return NULL; - - fd = _Py_dup(fd); - if (fd == -1) - return NULL; - - return PyLong_FromLong((long)fd); -} - - -PyDoc_STRVAR(posix_dup2__doc__, -"dup2(old_fd, new_fd)\n\n\ -Duplicate file descriptor."); - -static PyObject * -posix_dup2(PyObject *self, PyObject *args, PyObject *kwargs) -{ - static char *keywords[] = {"fd", "fd2", "inheritable", NULL}; - int fd, fd2; + 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]*/ +{ + 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" +"\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]*/ +{ int res; #if defined(HAVE_DUP3) && \ !(defined(HAVE_FCNTL_H) && defined(F_DUP2FD_CLOEXEC)) @@ -7830,10 +11052,6 @@ int dup3_works = -1; #endif - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii|i:dup2", keywords, - &fd, &fd2, &inheritable)) - return NULL; - if (!_PyVerify_fd_dup2(fd, fd2)) return posix_error(); @@ -7894,30 +11112,71 @@ #endif - Py_INCREF(Py_None); - return Py_None; -} + Py_RETURN_NONE; +} + #ifdef HAVE_LOCKF -PyDoc_STRVAR(posix_lockf__doc__, -"lockf(fd, cmd, len)\n\n\ -Apply, test or remove a POSIX lock on an open file descriptor.\n\n\ -fd is an open file descriptor.\n\ -cmd specifies the command to use - one of F_LOCK, F_TLOCK, F_ULOCK or\n\ -F_TEST.\n\ -len specifies the section of the file to lock."); - -static PyObject * -posix_lockf(PyObject *self, PyObject *args) -{ - int fd, cmd, res; - off_t len; - if (!PyArg_ParseTuple(args, "iiO&:lockf", - &fd, &cmd, _parse_off_t, &len)) - return NULL; - - Py_BEGIN_ALLOW_THREADS - res = lockf(fd, cmd, len); +/*[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]*/ + +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]*/ +{ + int res; + + Py_BEGIN_ALLOW_THREADS + res = lockf(fd, command, length); Py_END_ALLOW_THREADS if (res < 0) @@ -7925,102 +11184,175 @@ Py_RETURN_NONE; } -#endif - - -PyDoc_STRVAR(posix_lseek__doc__, -"lseek(fd, pos, how) -> newpos\n\n\ -Set the current position of a file descriptor.\n\ -Return the new cursor position in bytes, starting from the beginning."); - -static PyObject * -posix_lseek(PyObject *self, PyObject *args) -{ - int fd, how; -#ifdef MS_WINDOWS - PY_LONG_LONG pos, res; -#else - off_t pos, res; -#endif - PyObject *posobj; - if (!PyArg_ParseTuple(args, "iOi:lseek", &fd, &posobj, &how)) - return NULL; +#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]*/ + +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]*/ +{ + 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; + case 0: how = SEEK_SET; break; + case 1: how = SEEK_CUR; break; + case 2: how = SEEK_END; break; } #endif /* SEEK_END */ -#if !defined(HAVE_LARGEFILE_SUPPORT) - pos = PyLong_AsLong(posobj); -#else - pos = PyLong_AsLongLong(posobj); -#endif if (PyErr_Occurred()) - return NULL; - - if (!_PyVerify_fd(fd)) - return posix_error(); - Py_BEGIN_ALLOW_THREADS -#ifdef MS_WINDOWS - res = _lseeki64(fd, pos, how); -#else - res = lseek(fd, pos, how); -#endif - Py_END_ALLOW_THREADS - if (res < 0) - return posix_error(); - -#if !defined(HAVE_LARGEFILE_SUPPORT) - return PyLong_FromLong(res); -#else - return PyLong_FromLongLong(res); -#endif -} - - -PyDoc_STRVAR(posix_read__doc__, -"read(fd, buffersize) -> bytes\n\n\ -Read a file descriptor."); - -static PyObject * -posix_read(PyObject *self, PyObject *args) -{ + 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" +"\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 size; + 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]*/ +{ Py_ssize_t n; PyObject *buffer; - if (!PyArg_ParseTuple(args, "in:read", &fd, &size)) - return NULL; + + if (length < 0) { + errno = EINVAL; + return posix_error(); + } if (!_PyVerify_fd(fd)) return posix_error(); -#ifdef MS_WINDOWS - if (size > INT_MAX) - size = INT_MAX; -#endif - if (size < 0) { - errno = EINVAL; - return posix_error(); - } - buffer = PyBytes_FromStringAndSize((char *)NULL, size); + +#ifdef MS_WINDOWS + #define READ_CAST (int) + if (length > INT_MAX) + length = INT_MAX; +#else + #define READ_CAST +#endif + + buffer = PyBytes_FromStringAndSize((char *)NULL, length); if (buffer == NULL) return NULL; Py_BEGIN_ALLOW_THREADS -#ifdef MS_WINDOWS - n = read(fd, PyBytes_AS_STRING(buffer), (int)size); -#else - n = read(fd, PyBytes_AS_STRING(buffer), size); -#endif - Py_END_ALLOW_THREADS + n = read(fd, PyBytes_AS_STRING(buffer), READ_CAST length); + Py_END_ALLOW_THREADS + if (n < 0) { Py_DECREF(buffer); return posix_error(); } - if (n != size) + + if (n != length) _PyBytes_Resize(&buffer, n); + return buffer; } @@ -8082,70 +11414,163 @@ } #endif + #ifdef HAVE_READV -PyDoc_STRVAR(posix_readv__doc__, -"readv(fd, buffers) -> bytesread\n\n\ -Read from a file descriptor fd into a number of mutable, bytes-like\n\ -objects (\"buffers\"). readv will transfer data into each buffer\n\ -until it is full and then move on to the next buffer in the sequence\n\ -to hold the rest of the data.\n\n\ -readv returns the total number of bytes read (which may be less than\n\ -the total capacity of all the buffers."); - -static PyObject * -posix_readv(PyObject *self, PyObject *args) -{ - int fd, cnt; +/*[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]*/ + +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]*/ +{ + int cnt; Py_ssize_t n; - PyObject *seq; struct iovec *iov; Py_buffer *buf; - if (!PyArg_ParseTuple(args, "iO:readv", &fd, &seq)) - return NULL; - if (!PySequence_Check(seq)) { + if (!PySequence_Check(buffers)) { PyErr_SetString(PyExc_TypeError, "readv() arg 2 must be a sequence"); - return NULL; - } - cnt = PySequence_Size(seq); - - if (iov_setup(&iov, &buf, seq, cnt, PyBUF_WRITABLE) < 0) - return NULL; + return -1; + } + + cnt = PySequence_Size(buffers); + + if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_WRITABLE) < 0) + return -1; Py_BEGIN_ALLOW_THREADS n = readv(fd, iov, cnt); Py_END_ALLOW_THREADS iov_cleanup(iov, buf, cnt); - if (n < 0) - return posix_error(); - - return PyLong_FromSsize_t(n); -} -#endif + if (n < 0) { + posix_error(); + return -1; + } + + return n; +} +#endif /* HAVE_READV */ + #ifdef HAVE_PREAD -PyDoc_STRVAR(posix_pread__doc__, -"pread(fd, buffersize, offset) -> string\n\n\ -Read from a file descriptor, fd, at a position of offset. It will read up\n\ -to buffersize number of bytes. The file offset remains unchanged."); - -static PyObject * -posix_pread(PyObject *self, PyObject *args) -{ - int fd, size; - off_t offset; +/*[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]*/ + +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]*/ +{ Py_ssize_t n; PyObject *buffer; - if (!PyArg_ParseTuple(args, "iiO&:pread", &fd, &size, _parse_off_t, &offset)) - return NULL; - - if (size < 0) { + + if (length < 0) { errno = EINVAL; return posix_error(); } - buffer = PyBytes_FromStringAndSize((char *)NULL, size); + buffer = PyBytes_FromStringAndSize((char *)NULL, length); if (buffer == NULL) return NULL; if (!_PyVerify_fd(fd)) { @@ -8153,49 +11578,92 @@ return posix_error(); } Py_BEGIN_ALLOW_THREADS - n = pread(fd, PyBytes_AS_STRING(buffer), size, offset); + n = pread(fd, PyBytes_AS_STRING(buffer), length, offset); Py_END_ALLOW_THREADS if (n < 0) { Py_DECREF(buffer); return posix_error(); } - if (n != size) + if (n != length) _PyBytes_Resize(&buffer, n); return buffer; } -#endif - -PyDoc_STRVAR(posix_write__doc__, -"write(fd, data) -> byteswritten\n\n\ -Write bytes to a file descriptor."); - -static PyObject * -posix_write(PyObject *self, PyObject *args) -{ - Py_buffer pbuf; +#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]*/ + +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_ssize_t size, len; - - if (!PyArg_ParseTuple(args, "iy*:write", &fd, &pbuf)) - return NULL; + 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]*/ +{ + Py_ssize_t size; + Py_ssize_t len = data->len; + if (!_PyVerify_fd(fd)) { - PyBuffer_Release(&pbuf); - return posix_error(); - } - len = pbuf.len; + posix_error(); + return -1; + } + Py_BEGIN_ALLOW_THREADS #ifdef MS_WINDOWS if (len > INT_MAX) len = INT_MAX; - size = write(fd, pbuf.buf, (int)len); -#else - size = write(fd, pbuf.buf, len); -#endif - Py_END_ALLOW_THREADS - PyBuffer_Release(&pbuf); - if (size < 0) - return posix_error(); - return PyLong_FromSsize_t(size); + size = write(fd, data->buf, (int)len); +#else + size = write(fd, data->buf, len); +#endif + Py_END_ALLOW_THREADS + if (size < 0) { + posix_error(); + return -1; + } + return size; } #ifdef HAVE_SENDFILE @@ -8205,6 +11673,7 @@ -> 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) { @@ -8230,10 +11699,10 @@ #ifdef __APPLE__ if (!PyArg_ParseTupleAndKeywords(args, kwdict, "iiO&O&|OOi:sendfile", - keywords, &out, &in, _parse_off_t, &offset, _parse_off_t, &sbytes, + 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, _parse_off_t, &offset, &len, + keywords, &out, &in, Py_off_t_converter, &offset, &len, #endif &headers, &trailers, &flags)) return NULL; @@ -8326,7 +11795,7 @@ return Py_BuildValue("n", ret); } #endif - if (!_parse_off_t(offobj, &offset)) + if (!Py_off_t_converter(offobj, &offset)) return NULL; Py_BEGIN_ALLOW_THREADS ret = sendfile(out, in, &offset, count); @@ -8336,21 +11805,59 @@ return Py_BuildValue("n", ret); #endif } -#endif - -PyDoc_STRVAR(posix_fstat__doc__, -"fstat(fd) -> stat result\n\n\ -Like stat(), but for an open file descriptor.\n\ -Equivalent to stat(fd=fd)."); - -static PyObject * -posix_fstat(PyObject *self, PyObject *args) -{ +#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" +"\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]*/ +{ STRUCT_STAT st; int res; - if (!PyArg_ParseTuple(args, "i:fstat", &fd)) - return NULL; + Py_BEGIN_ALLOW_THREADS res = FSTAT(fd, &st); Py_END_ALLOW_THREADS @@ -8365,29 +11872,97 @@ return _pystat_fromstructstat(&st); } -PyDoc_STRVAR(posix_isatty__doc__, -"isatty(fd) -> bool\n\n\ -Return True if the file descriptor 'fd' is an open file descriptor\n\ -connected to the slave end of a terminal."); - -static PyObject * -posix_isatty(PyObject *self, PyObject *args) -{ + +/*[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" +"\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; - if (!PyArg_ParseTuple(args, "i:isatty", &fd)) - return NULL; + 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]*/ +{ if (!_PyVerify_fd(fd)) - return PyBool_FromLong(0); - return PyBool_FromLong(isatty(fd)); -} + return 0; + return isatty(fd); +} + #ifdef HAVE_PIPE -PyDoc_STRVAR(posix_pipe__doc__, -"pipe() -> (read_end, write_end)\n\n\ -Create a pipe."); - -static PyObject * -posix_pipe(PyObject *self, PyObject *noargs) +/*[clinic input] +os.pipe + +Create a pipe. + +Returns a tuple of two file descriptors: + (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]*/ { int fds[2]; #ifdef MS_WINDOWS @@ -8455,25 +12030,64 @@ } #endif /* HAVE_PIPE */ + #ifdef HAVE_PIPE2 -PyDoc_STRVAR(posix_pipe2__doc__, -"pipe2(flags) -> (read_end, write_end)\n\n\ -Create a pipe with flags set atomically.\n\ -flags can be constructed by ORing together one or more of these values:\n\ -O_NONBLOCK, O_CLOEXEC.\n\ -"); - -static PyObject * -posix_pipe2(PyObject *self, PyObject *arg) -{ +/*[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]*/ + +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]*/ +{ int fds[2]; int res; - flags = _PyLong_AsInt(arg); - if (flags == -1 && PyErr_Occurred()) - return NULL; - res = pipe2(fds, flags); if (res != 0) return posix_error(); @@ -8481,487 +12095,984 @@ } #endif /* HAVE_PIPE2 */ + #ifdef HAVE_WRITEV -PyDoc_STRVAR(posix_writev__doc__, -"writev(fd, buffers) -> byteswritten\n\n\ -Write the contents of *buffers* to file descriptor *fd*. *buffers*\n\ -must be a sequence of bytes-like objects.\n\n\ -writev writes the contents of each object to the file descriptor\n\ -and returns the total number of bytes written."); - -static PyObject * -posix_writev(PyObject *self, PyObject *args) -{ - int fd, cnt; - Py_ssize_t res; - PyObject *seq; +/*[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]*/ + +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]*/ +{ + int cnt; + Py_ssize_t result; struct iovec *iov; Py_buffer *buf; - if (!PyArg_ParseTuple(args, "iO:writev", &fd, &seq)) - return NULL; - if (!PySequence_Check(seq)) { + + if (!PySequence_Check(buffers)) { PyErr_SetString(PyExc_TypeError, "writev() arg 2 must be a sequence"); - return NULL; - } - cnt = PySequence_Size(seq); - - if (iov_setup(&iov, &buf, seq, cnt, PyBUF_SIMPLE) < 0) { - return NULL; - } - - Py_BEGIN_ALLOW_THREADS - res = writev(fd, iov, cnt); + return -1; + } + cnt = PySequence_Size(buffers); + + if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_SIMPLE) < 0) { + return -1; + } + + Py_BEGIN_ALLOW_THREADS + result = writev(fd, iov, cnt); Py_END_ALLOW_THREADS iov_cleanup(iov, buf, cnt); - if (res < 0) - return posix_error(); - - return PyLong_FromSsize_t(res); -} -#endif + if (result < 0) + posix_error(); + + return result; +} +#endif /* HAVE_WRITEV */ + #ifdef HAVE_PWRITE -PyDoc_STRVAR(posix_pwrite__doc__, -"pwrite(fd, string, offset) -> byteswritten\n\n\ -Write string to a file descriptor, fd, from offset, leaving the file\n\ -offset unchanged."); - -static PyObject * -posix_pwrite(PyObject *self, PyObject *args) -{ - Py_buffer pbuf; +/*[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]*/ + +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; - off_t offset; + 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]*/ +{ Py_ssize_t size; - if (!PyArg_ParseTuple(args, "iy*O&:pwrite", &fd, &pbuf, _parse_off_t, &offset)) - return NULL; - if (!_PyVerify_fd(fd)) { - PyBuffer_Release(&pbuf); - return posix_error(); - } - Py_BEGIN_ALLOW_THREADS - size = pwrite(fd, pbuf.buf, (size_t)pbuf.len, offset); - Py_END_ALLOW_THREADS - PyBuffer_Release(&pbuf); + posix_error(); + return -1; + } + + Py_BEGIN_ALLOW_THREADS + size = pwrite(fd, buffer->buf, (size_t)buffer->len, offset); + Py_END_ALLOW_THREADS + if (size < 0) - return posix_error(); - return PyLong_FromSsize_t(size); -} -#endif + posix_error(); + return size; +} +#endif /* HAVE_PWRITE */ + #ifdef HAVE_MKFIFO -PyDoc_STRVAR(posix_mkfifo__doc__, -"mkfifo(path, mode=0o666, *, dir_fd=None)\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."); - -static PyObject * -posix_mkfifo(PyObject *self, PyObject *args, PyObject *kwargs) -{ - path_t path; - int mode = 0666; +/*[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]*/ + +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]*/ +{ int result; - PyObject *return_value = NULL; - static char *keywords[] = {"path", "mode", "dir_fd", NULL}; - - memset(&path, 0, sizeof(path)); - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&|i$O&:mkfifo", keywords, - path_converter, &path, - &mode, -#ifdef HAVE_MKFIFOAT - dir_fd_converter, &dir_fd -#else - dir_fd_unavailable, &dir_fd -#endif - )) - return NULL; 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 - - if (result < 0) { - return_value = posix_error(); - goto exit; - } - - return_value = Py_None; - Py_INCREF(Py_None); - -exit: - path_cleanup(&path); - return return_value; -} -#endif + result = mkfifoat(dir_fd, path->narrow, mode); + else +#endif + result = mkfifo(path->narrow, mode); + Py_END_ALLOW_THREADS + + if (result < 0) + return posix_error(); + + Py_RETURN_NONE; +} +#endif /* HAVE_MKFIFO */ + #if defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV) -PyDoc_STRVAR(posix_mknod__doc__, -"mknod(filename, mode=0o600, device=0, *, dir_fd=None)\n\n\ -Create a filesystem node (file, device special file or named pipe)\n\ -named filename. 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. For S_IFCHR and S_IFBLK,\n\ -device defines the newly created device special file (probably using\n\ -os.makedev()), otherwise it 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."); - - -static PyObject * -posix_mknod(PyObject *self, PyObject *args, PyObject *kwargs) -{ - path_t path; - int mode = 0666; +/*[clinic input] +os.mknod + + path: path_t + mode: int=0o600 + device: int=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]*/ + +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, int 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; int device = 0; int dir_fd = DEFAULT_DIR_FD; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, + "O&|ii$O&:mknod", _keywords, + path_converter, &path, &mode, &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, int device, int dir_fd) +/*[clinic end generated code: output=c688739c15ca7bbb input=30e02126aba9732e]*/ +{ int result; - PyObject *return_value = NULL; - static char *keywords[] = {"path", "mode", "device", "dir_fd", NULL}; - - memset(&path, 0, sizeof(path)); - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&|ii$O&:mknod", keywords, - path_converter, &path, - &mode, &device, -#ifdef HAVE_MKNODAT - dir_fd_converter, &dir_fd -#else - dir_fd_unavailable, &dir_fd -#endif - )) - return NULL; 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 - - if (result < 0) { - return_value = posix_error(); - goto exit; - } - - return_value = Py_None; - Py_INCREF(Py_None); - -exit: + result = mknodat(dir_fd, path->narrow, mode, device); + else +#endif + result = mknod(path->narrow, mode, device); + Py_END_ALLOW_THREADS + + if (result < 0) + return posix_error(); + + Py_RETURN_NONE; +} +#endif /* defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV) */ + + +#ifdef HAVE_DEVICE_MACROS +/*[clinic input] +os.major -> unsigned_int + + device: int + / + +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, int device); + +static PyObject * +os_major(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + int device; + unsigned int _return_value; + + if (!PyArg_ParseTuple(args, + "i:major", + &device)) + goto exit; + _return_value = os_major_impl(module, device); + if ((_return_value == -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, int device) +/*[clinic end generated code: output=f60d3cc3d5d20325 input=ea48820b7e10d310]*/ +{ + return major(device); +} + + +/*[clinic input] +os.minor -> unsigned_int + + device: int + / + +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, int device); + +static PyObject * +os_minor(PyModuleDef *module, PyObject *args) +{ + PyObject *return_value = NULL; + int device; + unsigned int _return_value; + + if (!PyArg_ParseTuple(args, + "i:minor", + &device)) + goto exit; + _return_value = os_minor_impl(module, device); + if ((_return_value == -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, int device) +/*[clinic end generated code: output=71eca1d5149c2a07 input=089733ebbf9754e8]*/ +{ + return minor(device); +} + + +/*[clinic input] +os.makedev -> unsigned_int + + major: int + minor: int + / + +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 unsigned int +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; + unsigned int _return_value; + + if (!PyArg_ParseTuple(args, + "ii:makedev", + &major, &minor)) + goto exit; + _return_value = os_makedev_impl(module, major, minor); + if ((_return_value == -1) && PyErr_Occurred()) + goto exit; + return_value = PyLong_FromUnsignedLong((unsigned long)_return_value); + +exit: + return return_value; +} + +static unsigned int +os_makedev_impl(PyModuleDef *module, int major, int minor) +/*[clinic end generated code: output=e04dc5723a98cd3b input=f55bf7cffb028a08]*/ +{ + 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]*/ + +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]*/ +{ + int result; + + Py_BEGIN_ALLOW_THREADS + result = ftruncate(fd, length); + Py_END_ALLOW_THREADS + if (result < 0) + return posix_error(); + 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]*/ + +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; -} -#endif - -#ifdef HAVE_DEVICE_MACROS -PyDoc_STRVAR(posix_major__doc__, -"major(device) -> major number\n\ -Extracts a device major number from a raw device number."); - -static PyObject * -posix_major(PyObject *self, PyObject *args) -{ - int device; - if (!PyArg_ParseTuple(args, "i:major", &device)) - return NULL; - return PyLong_FromLong((long)major(device)); -} - -PyDoc_STRVAR(posix_minor__doc__, -"minor(device) -> minor number\n\ -Extracts a device minor number from a raw device number."); - -static PyObject * -posix_minor(PyObject *self, PyObject *args) -{ - int device; - if (!PyArg_ParseTuple(args, "i:minor", &device)) - return NULL; - return PyLong_FromLong((long)minor(device)); -} - -PyDoc_STRVAR(posix_makedev__doc__, -"makedev(major, minor) -> device number\n\ -Composes a raw device number from the major and minor device numbers."); - -static PyObject * -posix_makedev(PyObject *self, PyObject *args) -{ - int major, minor; - if (!PyArg_ParseTuple(args, "ii:makedev", &major, &minor)) - return NULL; - return PyLong_FromLong((long)makedev(major, minor)); -} -#endif /* device macros */ - - + + 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 -PyDoc_STRVAR(posix_ftruncate__doc__, -"ftruncate(fd, length)\n\n\ -Truncate a file to a specified length."); - -static PyObject * -posix_ftruncate(PyObject *self, PyObject *args) -{ + 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 */ + + +#ifdef HAVE_POSIX_FALLOCATE +/*[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]*/ + +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; - off_t length; - int res; - - if (!PyArg_ParseTuple(args, "iO&:ftruncate", &fd, _parse_off_t, &length)) - return NULL; - - Py_BEGIN_ALLOW_THREADS - res = ftruncate(fd, length); - Py_END_ALLOW_THREADS - if (res < 0) - return posix_error(); - Py_INCREF(Py_None); - return Py_None; -} -#endif - -#ifdef HAVE_TRUNCATE -PyDoc_STRVAR(posix_truncate__doc__, -"truncate(path, length)\n\n\ -Truncate the file given by path to length 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."); - -static PyObject * -posix_truncate(PyObject *self, PyObject *args, PyObject *kwargs) -{ - path_t path; - off_t length; - int res; - PyObject *result = NULL; - static char *keywords[] = {"path", "length", NULL}; - - memset(&path, 0, sizeof(path)); - path.function_name = "truncate"; -#ifdef HAVE_FTRUNCATE - path.allow_fd = 1; -#endif - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&O&:truncate", keywords, - path_converter, &path, - _parse_off_t, &length)) - return NULL; - - Py_BEGIN_ALLOW_THREADS -#ifdef HAVE_FTRUNCATE - if (path.fd != -1) - res = ftruncate(path.fd, length); - else -#endif - res = truncate(path.narrow, length); - Py_END_ALLOW_THREADS - if (res < 0) - result = path_error(&path); - else { - Py_INCREF(Py_None); - result = Py_None; - } - path_cleanup(&path); - return result; -} -#endif - -#ifdef HAVE_POSIX_FALLOCATE -PyDoc_STRVAR(posix_posix_fallocate__doc__, -"posix_fallocate(fd, offset, len)\n\n\ -Ensures that enough disk space is allocated for the file specified by fd\n\ -starting from offset and continuing for len bytes."); - -static PyObject * -posix_posix_fallocate(PyObject *self, PyObject *args) -{ - off_t len, offset; - int res, fd; - - if (!PyArg_ParseTuple(args, "iO&O&:posix_fallocate", - &fd, _parse_off_t, &offset, _parse_off_t, &len)) - return NULL; - - Py_BEGIN_ALLOW_THREADS - res = posix_fallocate(fd, offset, len); - Py_END_ALLOW_THREADS - if (res != 0) { - errno = res; + 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]*/ +{ + int result; + + Py_BEGIN_ALLOW_THREADS + result = posix_fallocate(fd, offset, length); + Py_END_ALLOW_THREADS + if (result != 0) { + errno = result; return posix_error(); } Py_RETURN_NONE; } -#endif +#endif /* HAVE_POSIX_FALLOCATE */ + #ifdef HAVE_POSIX_FADVISE -PyDoc_STRVAR(posix_posix_fadvise__doc__, -"posix_fadvise(fd, offset, len, advice)\n\n\ -Announces 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 len 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."); - -static PyObject * -posix_posix_fadvise(PyObject *self, PyObject *args) -{ - off_t len, offset; - int res, fd, advice; - - if (!PyArg_ParseTuple(args, "iO&O&i:posix_fadvise", - &fd, _parse_off_t, &offset, _parse_off_t, &len, &advice)) - return NULL; - - Py_BEGIN_ALLOW_THREADS - res = posix_fadvise(fd, offset, len, advice); - Py_END_ALLOW_THREADS - if (res != 0) { - errno = res; +/*[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]*/ + +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]*/ +{ + int result; + + Py_BEGIN_ALLOW_THREADS + result = posix_fadvise(fd, offset, length, advice); + Py_END_ALLOW_THREADS + if (result != 0) { + errno = result; return posix_error(); } Py_RETURN_NONE; } -#endif +#endif /* HAVE_POSIX_FADVISE */ #ifdef HAVE_PUTENV -PyDoc_STRVAR(posix_putenv__doc__, -"putenv(key, value)\n\n\ -Change or add an environment variable."); /* 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 PyObject * -posix_putenv(PyObject *self, PyObject *args) -{ - PyObject *newstr = NULL; -#ifdef MS_WINDOWS - PyObject *os1, *os2; - wchar_t *newenv; - - if (!PyArg_ParseTuple(args, - "UU:putenv", - &os1, &os2)) - return NULL; - - newstr = PyUnicode_FromFormat("%U=%U", os1, os2); - if (newstr == NULL) { +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]*/ + +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]*/ +{ + wchar_t *env; + + PyObject *unicode = PyUnicode_FromFormat("%U=%U", name, value); + if (unicode == NULL) { PyErr_NoMemory(); - goto error; - } - if (_MAX_ENV < PyUnicode_GET_LENGTH(newstr)) { + 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; } - newenv = PyUnicode_AsUnicode(newstr); - if (newenv == NULL) + env = PyUnicode_AsUnicode(unicode); + if (env == NULL) goto error; - if (_wputenv(newenv)) { + if (_wputenv(env)) { posix_error(); goto error; } -#else - PyObject *os1, *os2; - char *s1, *s2; - char *newenv; - - if (!PyArg_ParseTuple(args, - "O&O&:putenv", - PyUnicode_FSConverter, &os1, - PyUnicode_FSConverter, &os2)) - return NULL; - s1 = PyBytes_AsString(os1); - s2 = PyBytes_AsString(os2); - - newstr = PyBytes_FromFormat("%s=%s", s1, s2); - if (newstr == NULL) { + + 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]*/ + +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]*/ +{ + 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(); - goto error; - } - - newenv = PyBytes_AS_STRING(newstr); - if (putenv(newenv)) { - posix_error(); - goto error; - } -#endif - - /* 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, os1, newstr)) { - /* really not much we can do; just leak */ - PyErr_Clear(); - } - else { - Py_DECREF(newstr); - } - -#ifndef MS_WINDOWS - Py_DECREF(os1); - Py_DECREF(os2); -#endif + 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; - -error: -#ifndef MS_WINDOWS - Py_DECREF(os1); - Py_DECREF(os2); -#endif - Py_XDECREF(newstr); - return NULL; -} -#endif /* putenv */ +} +#endif /* MS_WINDOWS */ +#endif /* HAVE_PUTENV */ + #ifdef HAVE_UNSETENV -PyDoc_STRVAR(posix_unsetenv__doc__, -"unsetenv(key)\n\n\ -Delete an environment variable."); - -static PyObject * -posix_unsetenv(PyObject *self, PyObject *args) -{ - PyObject *name; +/*[clinic input] +os.unsetenv + name: FSConverter + / + +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]*/ +{ #ifndef HAVE_BROKEN_UNSETENV int err; #endif - if (!PyArg_ParseTuple(args, "O&:unsetenv", - - PyUnicode_FSConverter, &name)) - return NULL; - #ifdef HAVE_BROKEN_UNSETENV unsetenv(PyBytes_AS_STRING(name)); #else err = unsetenv(PyBytes_AS_STRING(name)); - if (err) { - Py_DECREF(name); - return posix_error(); - } + if (err) + return posix_error(); #endif /* Remove the key from posix_putenv_garbage; @@ -8973,23 +13084,53 @@ /* really not much we can do; just leak */ PyErr_Clear(); } - Py_DECREF(name); Py_RETURN_NONE; } -#endif /* unsetenv */ - -PyDoc_STRVAR(posix_strerror__doc__, -"strerror(code) -> string\n\n\ -Translate an error code to a message string."); - -static PyObject * -posix_strerror(PyObject *self, PyObject *args) -{ +#endif /* HAVE_UNSETENV */ + + +/*[clinic input] +os.strerror + + code: int + / + +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; - char *message; - if (!PyArg_ParseTuple(args, "i:strerror", &code)) - return NULL; - message = strerror(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]*/ +{ + char *message = strerror(code); if (message == NULL) { PyErr_SetString(PyExc_ValueError, "strerror() argument out of range"); @@ -9000,158 +13141,470 @@ #ifdef HAVE_SYS_WAIT_H - #ifdef WCOREDUMP -PyDoc_STRVAR(posix_WCOREDUMP__doc__, -"WCOREDUMP(status) -> bool\n\n\ -Return True if the process returning 'status' was dumped to a core file."); - -static PyObject * -posix_WCOREDUMP(PyObject *self, PyObject *args) -{ - WAIT_TYPE status; - WAIT_STATUS_INT(status) = 0; - - if (!PyArg_ParseTuple(args, "i:WCOREDUMP", &WAIT_STATUS_INT(status))) - return NULL; - - return PyBool_FromLong(WCOREDUMP(status)); +/*[clinic input] +os.WCOREDUMP -> bool + + status: int + / + +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]*/ +{ + WAIT_TYPE wait_status; + WAIT_STATUS_INT(wait_status) = status; + return WCOREDUMP(wait_status); } #endif /* WCOREDUMP */ + #ifdef WIFCONTINUED -PyDoc_STRVAR(posix_WIFCONTINUED__doc__, -"WIFCONTINUED(status) -> bool\n\n\ -Return True if the process returning 'status' was continued from a\n\ -job control stop."); - -static PyObject * -posix_WIFCONTINUED(PyObject *self, PyObject *args) -{ - WAIT_TYPE status; - WAIT_STATUS_INT(status) = 0; - - if (!PyArg_ParseTuple(args, "i:WCONTINUED", &WAIT_STATUS_INT(status))) - return NULL; - - return PyBool_FromLong(WIFCONTINUED(status)); +/*[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]*/ + +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]*/ +{ + WAIT_TYPE wait_status; + WAIT_STATUS_INT(wait_status) = status; + return WIFCONTINUED(wait_status); } #endif /* WIFCONTINUED */ + #ifdef WIFSTOPPED -PyDoc_STRVAR(posix_WIFSTOPPED__doc__, -"WIFSTOPPED(status) -> bool\n\n\ -Return True if the process returning 'status' was stopped."); - -static PyObject * -posix_WIFSTOPPED(PyObject *self, PyObject *args) -{ - WAIT_TYPE status; - WAIT_STATUS_INT(status) = 0; - - if (!PyArg_ParseTuple(args, "i:WIFSTOPPED", &WAIT_STATUS_INT(status))) - return NULL; - - return PyBool_FromLong(WIFSTOPPED(status)); +/*[clinic input] +os.WIFSTOPPED -> bool + + status: int + +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]*/ +{ + WAIT_TYPE wait_status; + WAIT_STATUS_INT(wait_status) = status; + return WIFSTOPPED(wait_status); } #endif /* WIFSTOPPED */ + #ifdef WIFSIGNALED -PyDoc_STRVAR(posix_WIFSIGNALED__doc__, -"WIFSIGNALED(status) -> bool\n\n\ -Return True if the process returning 'status' was terminated by a signal."); - -static PyObject * -posix_WIFSIGNALED(PyObject *self, PyObject *args) -{ - WAIT_TYPE status; - WAIT_STATUS_INT(status) = 0; - - if (!PyArg_ParseTuple(args, "i:WIFSIGNALED", &WAIT_STATUS_INT(status))) - return NULL; - - return PyBool_FromLong(WIFSIGNALED(status)); +/*[clinic input] +os.WIFSIGNALED -> bool + + status: int + +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]*/ +{ + WAIT_TYPE wait_status; + WAIT_STATUS_INT(wait_status) = status; + return WIFSIGNALED(wait_status); } #endif /* WIFSIGNALED */ + #ifdef WIFEXITED -PyDoc_STRVAR(posix_WIFEXITED__doc__, -"WIFEXITED(status) -> bool\n\n\ -Return true if the process returning 'status' exited using the exit()\n\ -system call."); - -static PyObject * -posix_WIFEXITED(PyObject *self, PyObject *args) -{ - WAIT_TYPE status; - WAIT_STATUS_INT(status) = 0; - - if (!PyArg_ParseTuple(args, "i:WIFEXITED", &WAIT_STATUS_INT(status))) - return NULL; - - return PyBool_FromLong(WIFEXITED(status)); +/*[clinic input] +os.WIFEXITED -> bool + + status: int + +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]*/ +{ + WAIT_TYPE wait_status; + WAIT_STATUS_INT(wait_status) = status; + return WIFEXITED(wait_status); } #endif /* WIFEXITED */ + #ifdef WEXITSTATUS -PyDoc_STRVAR(posix_WEXITSTATUS__doc__, -"WEXITSTATUS(status) -> integer\n\n\ -Return the process return code from 'status'."); - -static PyObject * -posix_WEXITSTATUS(PyObject *self, PyObject *args) -{ - WAIT_TYPE status; - WAIT_STATUS_INT(status) = 0; - - if (!PyArg_ParseTuple(args, "i:WEXITSTATUS", &WAIT_STATUS_INT(status))) - return NULL; - - return Py_BuildValue("i", WEXITSTATUS(status)); +/*[clinic input] +os.WEXITSTATUS -> int + + status: int + +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]*/ +{ + WAIT_TYPE wait_status; + WAIT_STATUS_INT(wait_status) = status; + return WEXITSTATUS(wait_status); } #endif /* WEXITSTATUS */ + #ifdef WTERMSIG -PyDoc_STRVAR(posix_WTERMSIG__doc__, -"WTERMSIG(status) -> integer\n\n\ -Return the signal that terminated the process that provided the 'status'\n\ -value."); - -static PyObject * -posix_WTERMSIG(PyObject *self, PyObject *args) -{ - WAIT_TYPE status; - WAIT_STATUS_INT(status) = 0; - - if (!PyArg_ParseTuple(args, "i:WTERMSIG", &WAIT_STATUS_INT(status))) - return NULL; - - return Py_BuildValue("i", WTERMSIG(status)); +/*[clinic input] +os.WTERMSIG -> int + + status: int + +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]*/ +{ + WAIT_TYPE wait_status; + WAIT_STATUS_INT(wait_status) = status; + return WTERMSIG(wait_status); } #endif /* WTERMSIG */ + #ifdef WSTOPSIG -PyDoc_STRVAR(posix_WSTOPSIG__doc__, -"WSTOPSIG(status) -> integer\n\n\ -Return the signal that stopped the process that provided\n\ -the 'status' value."); - -static PyObject * -posix_WSTOPSIG(PyObject *self, PyObject *args) -{ - WAIT_TYPE status; - WAIT_STATUS_INT(status) = 0; - - if (!PyArg_ParseTuple(args, "i:WSTOPSIG", &WAIT_STATUS_INT(status))) - return NULL; - - return Py_BuildValue("i", WSTOPSIG(status)); +/*[clinic input] +os.WSTOPSIG -> int + + status: int + +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]*/ +{ + 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 @@ -9203,104 +13656,192 @@ return v; } -PyDoc_STRVAR(posix_fstatvfs__doc__, -"fstatvfs(fd) -> statvfs result\n\n\ -Perform an fstatvfs system call on the given fd.\n\ -Equivalent to statvfs(fd)."); - -static PyObject * -posix_fstatvfs(PyObject *self, PyObject *args) -{ - int fd, res; + +/*[clinic input] +os.fstatvfs + fd: int + / + +Perform an fstatvfs system call on the given fd. + +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]*/ +{ + int result; struct statvfs st; - if (!PyArg_ParseTuple(args, "i:fstatvfs", &fd)) - return NULL; - Py_BEGIN_ALLOW_THREADS - res = fstatvfs(fd, &st); - Py_END_ALLOW_THREADS - if (res != 0) + Py_BEGIN_ALLOW_THREADS + result = fstatvfs(fd, &st); + Py_END_ALLOW_THREADS + if (result != 0) return posix_error(); return _pystatvfs_fromstructstatvfs(st); } -#endif /* HAVE_FSTATVFS && HAVE_SYS_STATVFS_H */ +#endif /* defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H) */ #if defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H) #include - -PyDoc_STRVAR(posix_statvfs__doc__, -"statvfs(path)\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."); - -static PyObject * -posix_statvfs(PyObject *self, PyObject *args, PyObject *kwargs) -{ - static char *keywords[] = {"path", NULL}; - path_t path; +/*[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]*/ + +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]*/ +{ int result; - PyObject *return_value = NULL; struct statvfs st; - memset(&path, 0, sizeof(path)); - path.function_name = "statvfs"; + Py_BEGIN_ALLOW_THREADS #ifdef HAVE_FSTATVFS - path.allow_fd = 1; -#endif - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&:statvfs", keywords, - path_converter, &path - )) - return NULL; - - Py_BEGIN_ALLOW_THREADS -#ifdef HAVE_FSTATVFS - if (path.fd != -1) { + if (path->fd != -1) { #ifdef __APPLE__ /* handle weak-linking on Mac OS X 10.3 */ if (fstatvfs == NULL) { - fd_specified("statvfs", path.fd); - goto exit; - } -#endif - result = fstatvfs(path.fd, &st); - } - else -#endif - result = statvfs(path.narrow, &st); + 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_value = path_error(&path); - goto exit; - } - - return_value = _pystatvfs_fromstructstatvfs(st); - -exit: - path_cleanup(&path); - return return_value; -} -#endif /* HAVE_STATVFS */ - -#ifdef MS_WINDOWS -PyDoc_STRVAR(win32__getdiskusage__doc__, -"_getdiskusage(path) -> (total, free)\n\n\ -Return disk usage statistics about the given path as (total, free) tuple."); - -static PyObject * -win32__getdiskusage(PyObject *self, PyObject *args) + 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]*/ + +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]*/ { BOOL retval; ULARGE_INTEGER _, total, free; - const wchar_t *path; - - if (! PyArg_ParseTuple(args, "u", &path)) - return NULL; Py_BEGIN_ALLOW_THREADS retval = GetDiskFreeSpaceExW(path, &_, &total, &free); @@ -9310,7 +13851,7 @@ return Py_BuildValue("(LL)", total.QuadPart, free.QuadPart); } -#endif +#endif /* MS_WINDOWS */ /* This is used for fpathconf(), pathconf(), confstr() and sysconf(). @@ -9467,81 +14008,149 @@ } #endif + #ifdef HAVE_FPATHCONF -PyDoc_STRVAR(posix_fpathconf__doc__, -"fpathconf(fd, name) -> integer\n\n\ -Return the configuration limit name for the file descriptor fd.\n\ -If there is no limit, return -1."); - -static PyObject * -posix_fpathconf(PyObject *self, PyObject *args) -{ - PyObject *result = NULL; - int name, fd; - - if (PyArg_ParseTuple(args, "iO&:fpathconf", &fd, - conv_path_confname, &name)) { - long limit; - - errno = 0; - limit = fpathconf(fd, name); - if (limit == -1 && errno != 0) - posix_error(); - else - result = PyLong_FromLong(limit); - } - return result; -} -#endif +/*[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]*/ + +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]*/ +{ + long limit; + + errno = 0; + limit = fpathconf(fd, name); + if (limit == -1 && errno != 0) + posix_error(); + + return limit; +} +#endif /* HAVE_FPATHCONF */ #ifdef HAVE_PATHCONF -PyDoc_STRVAR(posix_pathconf__doc__, -"pathconf(path, name) -> integer\n\n\ -Return the configuration limit name for the file or directory path.\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."); - -static PyObject * -posix_pathconf(PyObject *self, PyObject *args, PyObject *kwargs) -{ - path_t path; - PyObject *result = NULL; +/*[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]*/ + +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; - static char *keywords[] = {"path", "name", NULL}; - - memset(&path, 0, sizeof(path)); - path.function_name = "pathconf"; -#ifdef HAVE_FPATHCONF - path.allow_fd = 1; -#endif - if (PyArg_ParseTupleAndKeywords(args, kwargs, "O&O&:pathconf", keywords, - path_converter, &path, - conv_path_confname, &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]*/ +{ long limit; errno = 0; #ifdef HAVE_FPATHCONF - if (path.fd != -1) - limit = fpathconf(path.fd, name); - else -#endif - limit = pathconf(path.narrow, name); + 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 - result = path_error(&path); - } - else - result = PyLong_FromLong(limit); - } - path_cleanup(&path); - return result; -} -#endif + path_error(path); + } + + return limit; +} +#endif /* HAVE_PATHCONF */ #ifdef HAVE_CONFSTR static struct constdef posix_constants_confstr[] = { @@ -9705,21 +14314,52 @@ / sizeof(struct constdef)); } -PyDoc_STRVAR(posix_confstr__doc__, -"confstr(name) -> string\n\n\ -Return a string-valued system configuration variable."); - -static PyObject * -posix_confstr(PyObject *self, PyObject *args) + +/*[clinic input] +os.confstr + + name: confstr_confname + / + +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]*/ { PyObject *result = NULL; - int name; char buffer[255]; size_t len; - if (!PyArg_ParseTuple(args, "O&:confstr", conv_confstr_confname, &name)) - return NULL; - errno = 0; len = confstr(name, buffer, sizeof(buffer)); if (len == 0) { @@ -9744,7 +14384,7 @@ result = PyUnicode_DecodeFSDefaultAndSize(buffer, len-1); return result; } -#endif +#endif /* HAVE_CONFSTR */ #ifdef HAVE_SYSCONF @@ -10251,29 +14891,60 @@ / sizeof(struct constdef)); } -PyDoc_STRVAR(posix_sysconf__doc__, -"sysconf(name) -> integer\n\n\ -Return an integer-valued system configuration variable."); - -static PyObject * -posix_sysconf(PyObject *self, PyObject *args) -{ - PyObject *result = NULL; + +/*[clinic input] +os.sysconf -> long + name: sysconf_confname + / + +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; - - if (PyArg_ParseTuple(args, "O&:sysconf", conv_sysconf_confname, &name)) { - long value; - - errno = 0; - value = sysconf(name); - if (value == -1 && errno != 0) - posix_error(); - else - result = PyLong_FromLong(value); - } - return result; -} -#endif + 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]*/ +{ + 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 @@ -10350,13 +15021,39 @@ } -PyDoc_STRVAR(posix_abort__doc__, -"abort() -> does not return!\n\n\ -Abort the interpreter immediately. This 'dumps core' or otherwise fails\n\ -in the hardest way possible on the hosting operating system."); - -static PyObject * -posix_abort(PyObject *self, PyObject *noargs) +/*[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]*/ + +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]*/ { abort(); /*NOTREACHED*/ @@ -10365,9 +15062,11 @@ } #ifdef MS_WINDOWS +/* AC 3.5: change to path_t? but that might change exceptions */ PyDoc_STRVAR(win32_startfile__doc__, -"startfile(filepath [, operation]) - Start a file with its associated\n\ -application.\n\ +"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\ @@ -10457,17 +15156,45 @@ Py_INCREF(Py_None); return Py_None; } -#endif +#endif /* MS_WINDOWS */ + #ifdef HAVE_GETLOADAVG -PyDoc_STRVAR(posix_getloadavg__doc__, -"getloadavg() -> (float, float, float)\n\n\ -Return the number of processes in the system run queue averaged over\n\ -the last 1, 5, and 15 minutes or raises OSError if the load average\n\ -was unobtainable"); - -static PyObject * -posix_getloadavg(PyObject *self, PyObject *noargs) +/*[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]*/ + +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]*/ { double loadavg[3]; if (getloadavg(loadavg, 3)!=3) { @@ -10476,72 +15203,193 @@ } else return Py_BuildValue("ddd", loadavg[0], loadavg[1], loadavg[2]); } -#endif - -PyDoc_STRVAR(device_encoding__doc__, -"device_encoding(fd) -> str\n\n\ -Return a string describing the encoding of the device\n\ -if the output is a terminal; else return None."); - -static PyObject * -device_encoding(PyObject *self, PyObject *args) -{ +#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]*/ + +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_ParseTuple(args, "i:device_encoding", &fd)) - return NULL; - + 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]*/ +{ return _Py_device_encoding(fd); } + #ifdef HAVE_SETRESUID -PyDoc_STRVAR(posix_setresuid__doc__, -"setresuid(ruid, euid, suid)\n\n\ -Set the current process's real, effective, and saved user ids."); - -static PyObject* -posix_setresuid (PyObject *self, PyObject *args) -{ - /* We assume uid_t is no larger than a long. */ - uid_t ruid, euid, suid; - if (!PyArg_ParseTuple(args, "O&O&O&:setresuid", - _Py_Uid_Converter, &ruid, - _Py_Uid_Converter, &euid, - _Py_Uid_Converter, &suid)) - return NULL; +/*[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]*/ + +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]*/ +{ if (setresuid(ruid, euid, suid) < 0) return posix_error(); Py_RETURN_NONE; } -#endif +#endif /* HAVE_SETRESUID */ + #ifdef HAVE_SETRESGID -PyDoc_STRVAR(posix_setresgid__doc__, -"setresgid(rgid, egid, sgid)\n\n\ -Set the current process's real, effective, and saved group ids."); - -static PyObject* -posix_setresgid (PyObject *self, PyObject *args) -{ - gid_t rgid, egid, sgid; - if (!PyArg_ParseTuple(args, "O&O&O&:setresgid", - _Py_Gid_Converter, &rgid, - _Py_Gid_Converter, &egid, - _Py_Gid_Converter, &sgid)) - return NULL; +/*[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]*/ + +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]*/ +{ if (setresgid(rgid, egid, sgid) < 0) return posix_error(); Py_RETURN_NONE; } -#endif +#endif /* HAVE_SETRESGID */ + #ifdef HAVE_GETRESUID -PyDoc_STRVAR(posix_getresuid__doc__, -"getresuid() -> (ruid, euid, suid)\n\n\ -Get tuple of the current process's real, effective, and saved user ids."); - -static PyObject* -posix_getresuid (PyObject *self, PyObject *noargs) +/*[clinic input] +os.getresuid + +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]*/ { uid_t ruid, euid, suid; if (getresuid(&ruid, &euid, &suid) < 0) @@ -10550,59 +15398,116 @@ _PyLong_FromUid(euid), _PyLong_FromUid(suid)); } -#endif +#endif /* HAVE_GETRESUID */ + #ifdef HAVE_GETRESGID -PyDoc_STRVAR(posix_getresgid__doc__, -"getresgid() -> (rgid, egid, sgid)\n\n\ -Get tuple of the current process's real, effective, and saved group ids."); - -static PyObject* -posix_getresgid (PyObject *self, PyObject *noargs) -{ - uid_t rgid, egid, sgid; +/*[clinic input] +os.getresgid + +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]*/ +{ + 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 +#endif /* HAVE_GETRESGID */ + #ifdef USE_XATTRS - -PyDoc_STRVAR(posix_getxattr__doc__, -"getxattr(path, attribute, *, follow_symlinks=True) -> value\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."); - -static PyObject * -posix_getxattr(PyObject *self, PyObject *args, PyObject *kwargs) -{ - path_t path; - path_t attribute; +/*[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]*/ + +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]*/ +{ + Py_ssize_t i; PyObject *buffer = NULL; - int i; - static char *keywords[] = {"path", "attribute", "follow_symlinks", NULL}; - - memset(&path, 0, sizeof(path)); - memset(&attribute, 0, sizeof(attribute)); - path.function_name = "getxattr"; - attribute.function_name = "getxattr"; - path.allow_fd = 1; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&O&|$p:getxattr", keywords, - path_converter, &path, - path_converter, &attribute, - &follow_symlinks)) - return NULL; - - if (fd_and_follow_symlinks_invalid("getxattr", path.fd, follow_symlinks)) - goto exit; + + if (fd_and_follow_symlinks_invalid("getxattr", path->fd, follow_symlinks)) + return NULL; for (i = 0; ; i++) { void *ptr; @@ -10610,30 +15515,29 @@ 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); - goto exit; + path_error(path); + return NULL; } buffer = PyBytes_FromStringAndSize(NULL, buffer_size); if (!buffer) - goto exit; + return NULL; ptr = PyBytes_AS_STRING(buffer); Py_BEGIN_ALLOW_THREADS; - if (path.fd >= 0) - result = fgetxattr(path.fd, attribute.narrow, ptr, buffer_size); + 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); + result = getxattr(path->narrow, attribute->narrow, ptr, buffer_size); else - result = lgetxattr(path.narrow, attribute.narrow, ptr, buffer_size); + result = lgetxattr(path->narrow, attribute->narrow, ptr, buffer_size); Py_END_ALLOW_THREADS; if (result < 0) { Py_DECREF(buffer); - buffer = NULL; if (errno == ERANGE) continue; - path_error(&path); - goto exit; + path_error(path); + return NULL; } if (result != buffer_size) { @@ -10643,168 +15547,259 @@ break; } -exit: - path_cleanup(&path); - path_cleanup(&attribute); return buffer; } -PyDoc_STRVAR(posix_setxattr__doc__, -"setxattr(path, attribute, value, flags=0, *, follow_symlinks=True)\n\n\ -Set extended attribute attribute on path to value.\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."); - -static PyObject * -posix_setxattr(PyObject *self, PyObject *args, PyObject *kwargs) -{ - path_t path; - path_t attribute; - Py_buffer value; + +/*[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]*/ + +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; - int result; - PyObject *return_value = NULL; - static char *keywords[] = {"path", "attribute", "value", - "flags", "follow_symlinks", NULL}; - - memset(&path, 0, sizeof(path)); - path.function_name = "setxattr"; - path.allow_fd = 1; - memset(&attribute, 0, sizeof(attribute)); - memset(&value, 0, sizeof(value)); - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&O&y*|i$p:setxattr", - keywords, - path_converter, &path, - path_converter, &attribute, - &value, &flags, - &follow_symlinks)) - return NULL; - - if (fd_and_follow_symlinks_invalid("setxattr", path.fd, follow_symlinks)) - goto exit; + + 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]*/ +{ + 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); + 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); + 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) { - return_value = path_error(&path); - goto exit; - } - - return_value = Py_None; - Py_INCREF(return_value); - -exit: + 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]*/ + +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); - PyBuffer_Release(&value); - - return return_value; -} - -PyDoc_STRVAR(posix_removexattr__doc__, -"removexattr(path, attribute, *, follow_symlinks=True)\n\n\ -Remove extended attribute attribute on path.\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."); - -static PyObject * -posix_removexattr(PyObject *self, PyObject *args, PyObject *kwargs) -{ - path_t path; - path_t 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]*/ +{ + 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]*/ + +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; - int result; - PyObject *return_value = NULL; - static char *keywords[] = {"path", "attribute", "follow_symlinks", NULL}; - - memset(&path, 0, sizeof(path)); - path.function_name = "removexattr"; - memset(&attribute, 0, sizeof(attribute)); - attribute.function_name = "removexattr"; - path.allow_fd = 1; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&O&|$p:removexattr", - keywords, - path_converter, &path, - path_converter, &attribute, - &follow_symlinks)) - return NULL; - - if (fd_and_follow_symlinks_invalid("removexattr", path.fd, follow_symlinks)) - goto exit; - - 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_value = path_error(&path); - goto exit; - } - - return_value = Py_None; - Py_INCREF(return_value); - -exit: + + 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); - path_cleanup(&attribute); - - return return_value; -} - -PyDoc_STRVAR(posix_listxattr__doc__, -"listxattr(path='.', *, follow_symlinks=True)\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."); - -static PyObject * -posix_listxattr(PyObject *self, PyObject *args, PyObject *kwargs) -{ - path_t path; - int follow_symlinks = 1; + + 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; - char *name; - static char *keywords[] = {"path", "follow_symlinks", NULL}; - - memset(&path, 0, sizeof(path)); - path.function_name = "listxattr"; - path.allow_fd = 1; - path.fd = -1; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O&$p:listxattr", keywords, - path_converter, &path, - &follow_symlinks)) - return NULL; - - if (fd_and_follow_symlinks_invalid("listxattr", path.fd, follow_symlinks)) - goto exit; - - name = path.narrow ? path.narrow : "."; + + 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; @@ -10812,7 +15807,7 @@ Py_ssize_t buffer_size = buffer_sizes[i]; if (!buffer_size) { /* ERANGE */ - path_error(&path); + path_error(path); break; } buffer = PyMem_MALLOC(buffer_size); @@ -10822,8 +15817,8 @@ } Py_BEGIN_ALLOW_THREADS; - if (path.fd > -1) - length = flistxattr(path.fd, buffer, buffer_size); + if (path->fd > -1) + length = flistxattr(path->fd, buffer, buffer_size); else if (follow_symlinks) length = listxattr(name, buffer, buffer_size); else @@ -10836,7 +15831,7 @@ buffer = NULL; continue; } - path_error(&path); + path_error(path); break; } @@ -10869,43 +15864,71 @@ break; } exit: - path_cleanup(&path); if (buffer) PyMem_FREE(buffer); return result; } - #endif /* USE_XATTRS */ -PyDoc_STRVAR(posix_urandom__doc__, -"urandom(n) -> str\n\n\ -Return n random bytes suitable for cryptographic use."); - -static PyObject * -posix_urandom(PyObject *self, PyObject *args) -{ +/*[clinic input] +os.urandom + + size: Py_ssize_t + / + +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; - PyObject *result; - int ret; - - /* Read arguments */ - if (!PyArg_ParseTuple(args, "n:urandom", &size)) - return NULL; + + 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]*/ +{ + PyObject *bytes; + int result; + if (size < 0) return PyErr_Format(PyExc_ValueError, "negative argument not allowed"); - result = PyBytes_FromStringAndSize(NULL, size); - if (result == NULL) - return NULL; - - ret = _PyOS_URandom(PyBytes_AS_STRING(result), - PyBytes_GET_SIZE(result)); - if (ret == -1) { - Py_DECREF(result); - return NULL; - } - return result; + 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 */ @@ -10929,6 +15952,7 @@ }; #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" \ @@ -11014,13 +16038,34 @@ } #endif /* defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL) */ -PyDoc_STRVAR(posix_cpu_count__doc__, -"cpu_count() -> integer\n\n\ -Return the number of CPUs in the system, or None if this value cannot be\n\ -established."); - -static PyObject * -posix_cpu_count(PyObject *self) + +/*[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" +"\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]*/ { int ncpu = 0; #ifdef MS_WINDOWS @@ -11049,45 +16094,106 @@ Py_RETURN_NONE; } -PyDoc_STRVAR(get_inheritable__doc__, - "get_inheritable(fd) -> bool\n" \ - "\n" \ - "Get the close-on-exe flag of the specified file descriptor."); - -static PyObject* -posix_get_inheritable(PyObject *self, PyObject *args) -{ + +/*[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" +"\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]*/ +{ + 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" +"\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, "i:get_inheritable", &fd)) - return NULL; - + 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]*/ +{ if (!_PyVerify_fd(fd)) return posix_error(); - inheritable = _Py_get_inheritable(fd); - if (inheritable < 0) - return NULL; - return PyBool_FromLong(inheritable); -} - -PyDoc_STRVAR(set_inheritable__doc__, - "set_inheritable(fd, inheritable)\n" \ - "\n" \ - "Set the inheritable flag of the specified file descriptor."); - -static PyObject* -posix_set_inheritable(PyObject *self, PyObject *args) -{ - int fd, inheritable; - - if (!PyArg_ParseTuple(args, "ii:set_inheritable", &fd, &inheritable)) - return NULL; - - if (!_PyVerify_fd(fd)) - return posix_error(); - if (_Py_set_inheritable(fd, inheritable, NULL) < 0) return NULL; Py_RETURN_NONE; @@ -11095,56 +16201,111 @@ #ifdef MS_WINDOWS -PyDoc_STRVAR(get_handle_inheritable__doc__, - "get_handle_inheritable(fd) -> bool\n" \ - "\n" \ - "Get the close-on-exe flag of the specified file descriptor."); - -static PyObject* -posix_get_handle_inheritable(PyObject *self, PyObject *args) -{ +/*[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]*/ + +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]*/ +{ DWORD flags; - if (!PyArg_ParseTuple(args, _Py_PARSE_INTPTR ":get_handle_inheritable", &handle)) - return NULL; - if (!GetHandleInformation((HANDLE)handle, &flags)) { PyErr_SetFromWindowsErr(0); - return NULL; - } - - return PyBool_FromLong(flags & HANDLE_FLAG_INHERIT); -} - -PyDoc_STRVAR(set_handle_inheritable__doc__, - "set_handle_inheritable(fd, inheritable)\n" \ - "\n" \ - "Set the inheritable flag of the specified handle."); - -static PyObject* -posix_set_handle_inheritable(PyObject *self, PyObject *args) -{ - int inheritable = 1; + 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]*/ + +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; - DWORD flags; - - if (!PyArg_ParseTuple(args, _Py_PARSE_INTPTR "i:set_handle_inheritable", - &handle, &inheritable)) - return NULL; - - if (inheritable) - flags = HANDLE_FLAG_INHERIT; - else - flags = 0; + 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]*/ +{ + 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 */ - +#endif /* MS_WINDOWS */ #ifndef MS_WINDOWS PyDoc_STRVAR(get_blocking__doc__, @@ -11203,7 +16364,479 @@ #ifndef OS_TTYNAME_METHODDEF #define OS_TTYNAME_METHODDEF #endif /* !defined(OS_TTYNAME_METHODDEF) */ -/*[clinic end generated code: output=5d071bbc8f49ea12 input=524ce2e021e4eba6]*/ + +#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_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_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_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=52a6140b0b052ce6 input=524ce2e021e4eba6]*/ static PyMethodDef posix_methods[] = { @@ -11211,71 +16844,26 @@ OS_STAT_METHODDEF OS_ACCESS_METHODDEF OS_TTYNAME_METHODDEF - - {"chdir", (PyCFunction)posix_chdir, - METH_VARARGS | METH_KEYWORDS, - posix_chdir__doc__}, -#ifdef HAVE_CHFLAGS - {"chflags", (PyCFunction)posix_chflags, - METH_VARARGS | METH_KEYWORDS, - posix_chflags__doc__}, -#endif /* HAVE_CHFLAGS */ - {"chmod", (PyCFunction)posix_chmod, - METH_VARARGS | METH_KEYWORDS, - posix_chmod__doc__}, -#ifdef HAVE_FCHMOD - {"fchmod", posix_fchmod, METH_VARARGS, posix_fchmod__doc__}, -#endif /* HAVE_FCHMOD */ -#ifdef HAVE_CHOWN - {"chown", (PyCFunction)posix_chown, - METH_VARARGS | METH_KEYWORDS, - posix_chown__doc__}, -#endif /* HAVE_CHOWN */ -#ifdef HAVE_LCHMOD - {"lchmod", posix_lchmod, METH_VARARGS, posix_lchmod__doc__}, -#endif /* HAVE_LCHMOD */ -#ifdef HAVE_FCHOWN - {"fchown", posix_fchown, METH_VARARGS, posix_fchown__doc__}, -#endif /* HAVE_FCHOWN */ -#ifdef HAVE_LCHFLAGS - {"lchflags", posix_lchflags, METH_VARARGS, posix_lchflags__doc__}, -#endif /* HAVE_LCHFLAGS */ -#ifdef HAVE_LCHOWN - {"lchown", posix_lchown, METH_VARARGS, posix_lchown__doc__}, -#endif /* HAVE_LCHOWN */ -#ifdef HAVE_CHROOT - {"chroot", posix_chroot, METH_VARARGS, posix_chroot__doc__}, -#endif -#ifdef HAVE_CTERMID - {"ctermid", posix_ctermid, METH_NOARGS, posix_ctermid__doc__}, -#endif - {"getcwd", (PyCFunction)posix_getcwd_unicode, - METH_NOARGS, posix_getcwd__doc__}, - {"getcwdb", (PyCFunction)posix_getcwd_bytes, - METH_NOARGS, posix_getcwdb__doc__}, -#if defined(HAVE_LINK) || defined(MS_WINDOWS) - {"link", (PyCFunction)posix_link, - METH_VARARGS | METH_KEYWORDS, - posix_link__doc__}, -#endif /* HAVE_LINK */ - {"listdir", (PyCFunction)posix_listdir, - METH_VARARGS | METH_KEYWORDS, - posix_listdir__doc__}, - {"lstat", (PyCFunction)posix_lstat, - METH_VARARGS | METH_KEYWORDS, - posix_lstat__doc__}, - {"mkdir", (PyCFunction)posix_mkdir, - METH_VARARGS | METH_KEYWORDS, - posix_mkdir__doc__}, -#ifdef HAVE_NICE - {"nice", posix_nice, METH_VARARGS, posix_nice__doc__}, -#endif /* HAVE_NICE */ -#ifdef HAVE_GETPRIORITY - {"getpriority", posix_getpriority, METH_VARARGS, posix_getpriority__doc__}, -#endif /* HAVE_GETPRIORITY */ -#ifdef HAVE_SETPRIORITY - {"setpriority", posix_setpriority, METH_VARARGS, posix_setpriority__doc__}, -#endif /* HAVE_SETPRIORITY */ + 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, @@ -11286,376 +16874,157 @@ METH_VARARGS | METH_KEYWORDS, readlink__doc__}, #endif /* !defined(HAVE_READLINK) && defined(MS_WINDOWS) */ - {"rename", (PyCFunction)posix_rename, - METH_VARARGS | METH_KEYWORDS, - posix_rename__doc__}, - {"replace", (PyCFunction)posix_replace, - METH_VARARGS | METH_KEYWORDS, - posix_replace__doc__}, - {"rmdir", (PyCFunction)posix_rmdir, - METH_VARARGS | METH_KEYWORDS, - posix_rmdir__doc__}, + OS_RENAME_METHODDEF + OS_REPLACE_METHODDEF + OS_RMDIR_METHODDEF {"stat_float_times", stat_float_times, METH_VARARGS, stat_float_times__doc__}, -#if defined(HAVE_SYMLINK) - {"symlink", (PyCFunction)posix_symlink, - METH_VARARGS | METH_KEYWORDS, - posix_symlink__doc__}, -#endif /* HAVE_SYMLINK */ -#ifdef HAVE_SYSTEM - {"system", posix_system, METH_VARARGS, posix_system__doc__}, -#endif - {"umask", posix_umask, METH_VARARGS, posix_umask__doc__}, -#ifdef HAVE_UNAME - {"uname", posix_uname, METH_NOARGS, posix_uname__doc__}, -#endif /* HAVE_UNAME */ - {"unlink", (PyCFunction)posix_unlink, - METH_VARARGS | METH_KEYWORDS, - posix_unlink__doc__}, - {"remove", (PyCFunction)posix_unlink, - METH_VARARGS | METH_KEYWORDS, - posix_remove__doc__}, - {"utime", (PyCFunction)posix_utime, - METH_VARARGS | METH_KEYWORDS, posix_utime__doc__}, -#ifdef HAVE_TIMES - {"times", posix_times, METH_NOARGS, posix_times__doc__}, -#endif /* HAVE_TIMES */ - {"_exit", posix__exit, METH_VARARGS, posix__exit__doc__}, -#ifdef HAVE_EXECV - {"execv", posix_execv, METH_VARARGS, posix_execv__doc__}, - {"execve", (PyCFunction)posix_execve, - METH_VARARGS | METH_KEYWORDS, - posix_execve__doc__}, -#endif /* HAVE_EXECV */ -#ifdef HAVE_SPAWNV - {"spawnv", posix_spawnv, METH_VARARGS, posix_spawnv__doc__}, - {"spawnve", posix_spawnve, METH_VARARGS, posix_spawnve__doc__}, -#endif /* HAVE_SPAWNV */ -#ifdef HAVE_FORK1 - {"fork1", posix_fork1, METH_NOARGS, posix_fork1__doc__}, -#endif /* HAVE_FORK1 */ -#ifdef HAVE_FORK - {"fork", posix_fork, METH_NOARGS, posix_fork__doc__}, -#endif /* HAVE_FORK */ -#ifdef HAVE_SCHED_H -#ifdef HAVE_SCHED_GET_PRIORITY_MAX - {"sched_get_priority_max", posix_sched_get_priority_max, METH_VARARGS, posix_sched_get_priority_max__doc__}, - {"sched_get_priority_min", posix_sched_get_priority_min, METH_VARARGS, posix_sched_get_priority_min__doc__}, -#endif -#ifdef HAVE_SCHED_SETPARAM - {"sched_getparam", posix_sched_getparam, METH_VARARGS, posix_sched_getparam__doc__}, -#endif -#ifdef HAVE_SCHED_SETSCHEDULER - {"sched_getscheduler", posix_sched_getscheduler, METH_VARARGS, posix_sched_getscheduler__doc__}, -#endif -#ifdef HAVE_SCHED_RR_GET_INTERVAL - {"sched_rr_get_interval", posix_sched_rr_get_interval, METH_VARARGS, posix_sched_rr_get_interval__doc__}, -#endif -#ifdef HAVE_SCHED_SETPARAM - {"sched_setparam", posix_sched_setparam, METH_VARARGS, posix_sched_setparam__doc__}, -#endif -#ifdef HAVE_SCHED_SETSCHEDULER - {"sched_setscheduler", posix_sched_setscheduler, METH_VARARGS, posix_sched_setscheduler__doc__}, -#endif - {"sched_yield", posix_sched_yield, METH_NOARGS, posix_sched_yield__doc__}, -#ifdef HAVE_SCHED_SETAFFINITY - {"sched_setaffinity", posix_sched_setaffinity, METH_VARARGS, posix_sched_setaffinity__doc__}, - {"sched_getaffinity", posix_sched_getaffinity, METH_VARARGS, posix_sched_getaffinity__doc__}, -#endif -#endif /* HAVE_SCHED_H */ -#if defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX) - {"openpty", posix_openpty, METH_NOARGS, posix_openpty__doc__}, -#endif /* HAVE_OPENPTY || HAVE__GETPTY || HAVE_DEV_PTMX */ -#ifdef HAVE_FORKPTY - {"forkpty", posix_forkpty, METH_NOARGS, posix_forkpty__doc__}, -#endif /* HAVE_FORKPTY */ -#ifdef HAVE_GETEGID - {"getegid", posix_getegid, METH_NOARGS, posix_getegid__doc__}, -#endif /* HAVE_GETEGID */ -#ifdef HAVE_GETEUID - {"geteuid", posix_geteuid, METH_NOARGS, posix_geteuid__doc__}, -#endif /* HAVE_GETEUID */ -#ifdef HAVE_GETGID - {"getgid", posix_getgid, METH_NOARGS, posix_getgid__doc__}, -#endif /* HAVE_GETGID */ + 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 -#ifdef HAVE_GETGROUPS - {"getgroups", posix_getgroups, METH_NOARGS, posix_getgroups__doc__}, -#endif - {"getpid", posix_getpid, METH_NOARGS, posix_getpid__doc__}, -#ifdef HAVE_GETPGRP - {"getpgrp", posix_getpgrp, METH_NOARGS, posix_getpgrp__doc__}, -#endif /* HAVE_GETPGRP */ -#ifdef HAVE_GETPPID - {"getppid", posix_getppid, METH_NOARGS, posix_getppid__doc__}, -#endif /* HAVE_GETPPID */ -#ifdef HAVE_GETUID - {"getuid", posix_getuid, METH_NOARGS, posix_getuid__doc__}, -#endif /* HAVE_GETUID */ -#ifdef HAVE_GETLOGIN - {"getlogin", posix_getlogin, METH_NOARGS, posix_getlogin__doc__}, -#endif -#ifdef HAVE_KILL - {"kill", posix_kill, METH_VARARGS, posix_kill__doc__}, -#endif /* HAVE_KILL */ -#ifdef HAVE_KILLPG - {"killpg", posix_killpg, METH_VARARGS, posix_killpg__doc__}, -#endif /* HAVE_KILLPG */ -#ifdef HAVE_PLOCK - {"plock", posix_plock, METH_VARARGS, posix_plock__doc__}, -#endif /* HAVE_PLOCK */ + 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__}, - {"kill", win32_kill, METH_VARARGS, win32_kill__doc__}, -#endif -#ifdef HAVE_SETUID - {"setuid", posix_setuid, METH_VARARGS, posix_setuid__doc__}, -#endif /* HAVE_SETUID */ -#ifdef HAVE_SETEUID - {"seteuid", posix_seteuid, METH_VARARGS, posix_seteuid__doc__}, -#endif /* HAVE_SETEUID */ -#ifdef HAVE_SETEGID - {"setegid", posix_setegid, METH_VARARGS, posix_setegid__doc__}, -#endif /* HAVE_SETEGID */ -#ifdef HAVE_SETREUID - {"setreuid", posix_setreuid, METH_VARARGS, posix_setreuid__doc__}, -#endif /* HAVE_SETREUID */ -#ifdef HAVE_SETREGID - {"setregid", posix_setregid, METH_VARARGS, posix_setregid__doc__}, -#endif /* HAVE_SETREGID */ -#ifdef HAVE_SETGID - {"setgid", posix_setgid, METH_VARARGS, posix_setgid__doc__}, -#endif /* HAVE_SETGID */ -#ifdef HAVE_SETGROUPS - {"setgroups", posix_setgroups, METH_O, posix_setgroups__doc__}, -#endif /* HAVE_SETGROUPS */ +#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 */ -#ifdef HAVE_GETPGID - {"getpgid", posix_getpgid, METH_VARARGS, posix_getpgid__doc__}, -#endif /* HAVE_GETPGID */ -#ifdef HAVE_SETPGRP - {"setpgrp", posix_setpgrp, METH_NOARGS, posix_setpgrp__doc__}, -#endif /* HAVE_SETPGRP */ -#ifdef HAVE_WAIT - {"wait", posix_wait, METH_NOARGS, posix_wait__doc__}, -#endif /* HAVE_WAIT */ -#ifdef HAVE_WAIT3 - {"wait3", posix_wait3, METH_VARARGS, posix_wait3__doc__}, -#endif /* HAVE_WAIT3 */ -#ifdef HAVE_WAIT4 - {"wait4", posix_wait4, METH_VARARGS, posix_wait4__doc__}, -#endif /* HAVE_WAIT4 */ -#if defined(HAVE_WAITID) && !defined(__APPLE__) - {"waitid", posix_waitid, METH_VARARGS, posix_waitid__doc__}, -#endif -#if defined(HAVE_WAITPID) || defined(HAVE_CWAIT) - {"waitpid", posix_waitpid, METH_VARARGS, posix_waitpid__doc__}, -#endif /* HAVE_WAITPID */ -#ifdef HAVE_GETSID - {"getsid", posix_getsid, METH_VARARGS, posix_getsid__doc__}, -#endif /* HAVE_GETSID */ -#ifdef HAVE_SETSID - {"setsid", posix_setsid, METH_NOARGS, posix_setsid__doc__}, -#endif /* HAVE_SETSID */ -#ifdef HAVE_SETPGID - {"setpgid", posix_setpgid, METH_VARARGS, posix_setpgid__doc__}, -#endif /* HAVE_SETPGID */ -#ifdef HAVE_TCGETPGRP - {"tcgetpgrp", posix_tcgetpgrp, METH_VARARGS, posix_tcgetpgrp__doc__}, -#endif /* HAVE_TCGETPGRP */ -#ifdef HAVE_TCSETPGRP - {"tcsetpgrp", posix_tcsetpgrp, METH_VARARGS, posix_tcsetpgrp__doc__}, -#endif /* HAVE_TCSETPGRP */ - {"open", (PyCFunction)posix_open,\ - METH_VARARGS | METH_KEYWORDS, - posix_open__doc__}, - {"close", posix_close_, METH_VARARGS, posix_close__doc__}, - {"closerange", posix_closerange, METH_VARARGS, posix_closerange__doc__}, - {"device_encoding", device_encoding, METH_VARARGS, device_encoding__doc__}, - {"dup", posix_dup, METH_VARARGS, posix_dup__doc__}, - {"dup2", (PyCFunction)posix_dup2, - METH_VARARGS | METH_KEYWORDS, posix_dup2__doc__}, -#ifdef HAVE_LOCKF - {"lockf", posix_lockf, METH_VARARGS, posix_lockf__doc__}, -#endif - {"lseek", posix_lseek, METH_VARARGS, posix_lseek__doc__}, - {"read", posix_read, METH_VARARGS, posix_read__doc__}, -#ifdef HAVE_READV - {"readv", posix_readv, METH_VARARGS, posix_readv__doc__}, -#endif -#ifdef HAVE_PREAD - {"pread", posix_pread, METH_VARARGS, posix_pread__doc__}, -#endif - {"write", posix_write, METH_VARARGS, posix_write__doc__}, -#ifdef HAVE_WRITEV - {"writev", posix_writev, METH_VARARGS, posix_writev__doc__}, -#endif -#ifdef HAVE_PWRITE - {"pwrite", posix_pwrite, METH_VARARGS, posix_pwrite__doc__}, -#endif + 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 - {"fstat", posix_fstat, METH_VARARGS, posix_fstat__doc__}, - {"isatty", posix_isatty, METH_VARARGS, posix_isatty__doc__}, -#ifdef HAVE_PIPE - {"pipe", posix_pipe, METH_NOARGS, posix_pipe__doc__}, -#endif -#ifdef HAVE_PIPE2 - {"pipe2", posix_pipe2, METH_O, posix_pipe2__doc__}, -#endif -#ifdef HAVE_MKFIFO - {"mkfifo", (PyCFunction)posix_mkfifo, - METH_VARARGS | METH_KEYWORDS, - posix_mkfifo__doc__}, -#endif -#if defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV) - {"mknod", (PyCFunction)posix_mknod, - METH_VARARGS | METH_KEYWORDS, - posix_mknod__doc__}, -#endif -#ifdef HAVE_DEVICE_MACROS - {"major", posix_major, METH_VARARGS, posix_major__doc__}, - {"minor", posix_minor, METH_VARARGS, posix_minor__doc__}, - {"makedev", posix_makedev, METH_VARARGS, posix_makedev__doc__}, -#endif -#ifdef HAVE_FTRUNCATE - {"ftruncate", posix_ftruncate, METH_VARARGS, posix_ftruncate__doc__}, -#endif -#ifdef HAVE_TRUNCATE - {"truncate", (PyCFunction)posix_truncate, - METH_VARARGS | METH_KEYWORDS, - posix_truncate__doc__}, -#endif -#ifdef HAVE_POSIX_FALLOCATE - {"posix_fallocate", posix_posix_fallocate, METH_VARARGS, posix_posix_fallocate__doc__}, -#endif -#ifdef HAVE_POSIX_FADVISE - {"posix_fadvise", posix_posix_fadvise, METH_VARARGS, posix_posix_fadvise__doc__}, -#endif -#ifdef HAVE_PUTENV - {"putenv", posix_putenv, METH_VARARGS, posix_putenv__doc__}, -#endif -#ifdef HAVE_UNSETENV - {"unsetenv", posix_unsetenv, METH_VARARGS, posix_unsetenv__doc__}, -#endif - {"strerror", posix_strerror, METH_VARARGS, posix_strerror__doc__}, -#ifdef HAVE_FCHDIR - {"fchdir", posix_fchdir, METH_O, posix_fchdir__doc__}, -#endif -#ifdef HAVE_FSYNC - {"fsync", posix_fsync, METH_O, posix_fsync__doc__}, -#endif -#ifdef HAVE_SYNC - {"sync", posix_sync, METH_NOARGS, posix_sync__doc__}, -#endif -#ifdef HAVE_FDATASYNC - {"fdatasync", posix_fdatasync, METH_O, posix_fdatasync__doc__}, -#endif -#ifdef HAVE_SYS_WAIT_H -#ifdef WCOREDUMP - {"WCOREDUMP", posix_WCOREDUMP, METH_VARARGS, posix_WCOREDUMP__doc__}, -#endif /* WCOREDUMP */ -#ifdef WIFCONTINUED - {"WIFCONTINUED",posix_WIFCONTINUED, METH_VARARGS, posix_WIFCONTINUED__doc__}, -#endif /* WIFCONTINUED */ -#ifdef WIFSTOPPED - {"WIFSTOPPED", posix_WIFSTOPPED, METH_VARARGS, posix_WIFSTOPPED__doc__}, -#endif /* WIFSTOPPED */ -#ifdef WIFSIGNALED - {"WIFSIGNALED", posix_WIFSIGNALED, METH_VARARGS, posix_WIFSIGNALED__doc__}, -#endif /* WIFSIGNALED */ -#ifdef WIFEXITED - {"WIFEXITED", posix_WIFEXITED, METH_VARARGS, posix_WIFEXITED__doc__}, -#endif /* WIFEXITED */ -#ifdef WEXITSTATUS - {"WEXITSTATUS", posix_WEXITSTATUS, METH_VARARGS, posix_WEXITSTATUS__doc__}, -#endif /* WEXITSTATUS */ -#ifdef WTERMSIG - {"WTERMSIG", posix_WTERMSIG, METH_VARARGS, posix_WTERMSIG__doc__}, -#endif /* WTERMSIG */ -#ifdef WSTOPSIG - {"WSTOPSIG", posix_WSTOPSIG, METH_VARARGS, posix_WSTOPSIG__doc__}, -#endif /* WSTOPSIG */ -#endif /* HAVE_SYS_WAIT_H */ -#if defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H) - {"fstatvfs", posix_fstatvfs, METH_VARARGS, posix_fstatvfs__doc__}, -#endif -#if defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H) - {"statvfs", (PyCFunction)posix_statvfs, - METH_VARARGS | METH_KEYWORDS, - posix_statvfs__doc__}, -#endif -#ifdef HAVE_CONFSTR - {"confstr", posix_confstr, METH_VARARGS, posix_confstr__doc__}, -#endif -#ifdef HAVE_SYSCONF - {"sysconf", posix_sysconf, METH_VARARGS, posix_sysconf__doc__}, -#endif -#ifdef HAVE_FPATHCONF - {"fpathconf", posix_fpathconf, METH_VARARGS, posix_fpathconf__doc__}, -#endif -#ifdef HAVE_PATHCONF - {"pathconf", (PyCFunction)posix_pathconf, - METH_VARARGS | METH_KEYWORDS, - posix_pathconf__doc__}, -#endif - {"abort", posix_abort, METH_NOARGS, posix_abort__doc__}, + 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}, - {"_getfinalpathname", posix__getfinalpathname, METH_VARARGS, NULL}, {"_isdir", posix__isdir, METH_VARARGS, posix__isdir__doc__}, - {"_getdiskusage", win32__getdiskusage, METH_VARARGS, win32__getdiskusage__doc__}, - {"_getvolumepathname", posix__getvolumepathname, METH_VARARGS, posix__getvolumepathname__doc__}, -#endif -#ifdef HAVE_GETLOADAVG - {"getloadavg", posix_getloadavg, METH_NOARGS, posix_getloadavg__doc__}, -#endif - {"urandom", posix_urandom, METH_VARARGS, posix_urandom__doc__}, -#ifdef HAVE_SETRESUID - {"setresuid", posix_setresuid, METH_VARARGS, posix_setresuid__doc__}, -#endif -#ifdef HAVE_SETRESGID - {"setresgid", posix_setresgid, METH_VARARGS, posix_setresgid__doc__}, -#endif -#ifdef HAVE_GETRESUID - {"getresuid", posix_getresuid, METH_NOARGS, posix_getresuid__doc__}, -#endif -#ifdef HAVE_GETRESGID - {"getresgid", posix_getresgid, METH_NOARGS, posix_getresgid__doc__}, -#endif - -#ifdef USE_XATTRS - {"setxattr", (PyCFunction)posix_setxattr, - METH_VARARGS | METH_KEYWORDS, - posix_setxattr__doc__}, - {"getxattr", (PyCFunction)posix_getxattr, - METH_VARARGS | METH_KEYWORDS, - posix_getxattr__doc__}, - {"removexattr", (PyCFunction)posix_removexattr, - METH_VARARGS | METH_KEYWORDS, - posix_removexattr__doc__}, - {"listxattr", (PyCFunction)posix_listxattr, - METH_VARARGS | METH_KEYWORDS, - posix_listxattr__doc__}, -#endif +#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 - {"cpu_count", (PyCFunction)posix_cpu_count, - METH_NOARGS, posix_cpu_count__doc__}, - {"get_inheritable", posix_get_inheritable, METH_VARARGS, get_inheritable__doc__}, - {"set_inheritable", posix_set_inheritable, METH_VARARGS, set_inheritable__doc__}, -#ifdef MS_WINDOWS - {"get_handle_inheritable", posix_get_handle_inheritable, - METH_VARARGS, get_handle_inheritable__doc__}, - {"set_handle_inheritable", posix_set_handle_inheritable, - METH_VARARGS, set_handle_inheritable__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__}, @@ -12324,7 +17693,7 @@ sched_param_desc.name = MODNAME ".sched_param"; if (PyStructSequence_InitType2(&SchedParamType, &sched_param_desc) < 0) return NULL; - SchedParamType.tp_new = sched_param_new; + SchedParamType.tp_new = os_sched_param; #endif /* initialize TerminalSize_info */ -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Aug 5 06:15:03 2014 From: python-checkins at python.org (berker.peksag) Date: Tue, 5 Aug 2014 06:15:03 +0200 (CEST) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzE2MDM3?= =?utf-8?q?=3A_HTTPMessage=2Ereadheaders=28=29_raises_an_HTTPException_whe?= =?utf-8?q?n_more?= Message-ID: <3hS2gC5W2Rz7Ljt@mail.python.org> http://hg.python.org/cpython/rev/5e310c6a8520 changeset: 92002:5e310c6a8520 branch: 2.7 parent: 91998:46c7a724b487 user: Berker Peksag date: Tue Aug 05 07:15:57 2014 +0300 summary: Issue #16037: HTTPMessage.readheaders() raises an HTTPException when more than 100 headers are read. Patch by Jyrki Pulliainen and Daniel Eriksson. files: Lib/httplib.py | 6 ++++++ Lib/test/test_httplib.py | 7 +++++++ Misc/NEWS | 3 +++ 3 files changed, 16 insertions(+), 0 deletions(-) diff --git a/Lib/httplib.py b/Lib/httplib.py --- a/Lib/httplib.py +++ b/Lib/httplib.py @@ -215,6 +215,10 @@ # maximal line length when calling readline(). _MAXLINE = 65536 +# maximum amount of headers accepted +_MAXHEADERS = 100 + + class HTTPMessage(mimetools.Message): def addheader(self, key, value): @@ -271,6 +275,8 @@ elif self.seekable: tell = self.fp.tell while True: + if len(hlist) > _MAXHEADERS: + raise HTTPException("got more than %d headers" % _MAXHEADERS) if tell: try: startofline = tell() 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 @@ -262,6 +262,13 @@ if resp.read() != "": self.fail("Did not expect response from HEAD request") + def test_too_many_headers(self): + headers = '\r\n'.join('Header%d: foo' % i for i in xrange(200)) + '\r\n' + text = ('HTTP/1.1 200 OK\r\n' + headers) + s = FakeSocket(text) + r = httplib.HTTPResponse(s) + self.assertRaises(httplib.HTTPException, r.begin) + def test_send_file(self): expected = 'GET /foo HTTP/1.1\r\nHost: example.com\r\n' \ 'Accept-Encoding: identity\r\nContent-Length:' diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -19,6 +19,9 @@ Library ------- +- Issue #16037: HTTPMessage.readheaders() raises an HTTPException when more + than 100 headers are read. Patch by Jyrki Pulliainen and Daniel Eriksson. + - Issue #21580: Now Tkinter correctly handles binary "data" and "maskdata" configure options of tkinter.PhotoImage. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Aug 5 07:15:45 2014 From: python-checkins at python.org (ezio.melotti) Date: Tue, 5 Aug 2014 07:15:45 +0200 (CEST) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogIzIxOTI4OiBjbGFy?= =?utf-8?q?ify_functools=2Ewraps_docs=2E?= Message-ID: <3hS41F30nFz7Ljt@mail.python.org> http://hg.python.org/cpython/rev/9e3c367b45a1 changeset: 92003:9e3c367b45a1 branch: 3.4 parent: 91999:9a410ae785ff user: Ezio Melotti date: Tue Aug 05 08:14:28 2014 +0300 summary: #21928: clarify functools.wraps docs. files: Doc/library/functools.rst | 7 ++++--- 1 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Doc/library/functools.rst b/Doc/library/functools.rst --- a/Doc/library/functools.rst +++ b/Doc/library/functools.rst @@ -413,9 +413,10 @@ .. decorator:: wraps(wrapped, assigned=WRAPPER_ASSIGNMENTS, updated=WRAPPER_UPDATES) - This is a convenience function for invoking ``partial(update_wrapper, - wrapped=wrapped, assigned=assigned, updated=updated)`` as a function decorator - when defining a wrapper function. For example: + This is a convenience function for invoking :func:`update_wrapper` as a + function decorator when defining a wrapper function. It is equivalent to + ``partial(update_wrapper, wrapped=wrapped, assigned=assigned, updated=updated)``. + For example:: >>> from functools import wraps >>> def my_decorator(f): -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Aug 5 07:15:46 2014 From: python-checkins at python.org (ezio.melotti) Date: Tue, 5 Aug 2014 07:15:46 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?b?KTogIzIxOTI4OiBtZXJnZSB3aXRoIDMuNC4=?= Message-ID: <3hS41G5Brlz7LkR@mail.python.org> http://hg.python.org/cpython/rev/5a58f6e793cc changeset: 92004:5a58f6e793cc parent: 92001:0c57aba6b1a3 parent: 92003:9e3c367b45a1 user: Ezio Melotti date: Tue Aug 05 08:14:59 2014 +0300 summary: #21928: merge with 3.4. files: Doc/library/functools.rst | 7 ++++--- 1 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Doc/library/functools.rst b/Doc/library/functools.rst --- a/Doc/library/functools.rst +++ b/Doc/library/functools.rst @@ -413,9 +413,10 @@ .. decorator:: wraps(wrapped, assigned=WRAPPER_ASSIGNMENTS, updated=WRAPPER_UPDATES) - This is a convenience function for invoking ``partial(update_wrapper, - wrapped=wrapped, assigned=assigned, updated=updated)`` as a function decorator - when defining a wrapper function. For example: + This is a convenience function for invoking :func:`update_wrapper` as a + function decorator when defining a wrapper function. It is equivalent to + ``partial(update_wrapper, wrapped=wrapped, assigned=assigned, updated=updated)``. + For example:: >>> from functools import wraps >>> def my_decorator(f): -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Aug 5 07:15:48 2014 From: python-checkins at python.org (ezio.melotti) Date: Tue, 5 Aug 2014 07:15:48 +0200 (CEST) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogIzIxOTI4OiBjbGFy?= =?utf-8?q?ify_functools=2Ewraps_docs=2E?= Message-ID: <3hS41J0M6lz7LnC@mail.python.org> http://hg.python.org/cpython/rev/6cbd08fbdf77 changeset: 92005:6cbd08fbdf77 branch: 2.7 parent: 92002:5e310c6a8520 user: Ezio Melotti date: Tue Aug 05 08:14:28 2014 +0300 summary: #21928: clarify functools.wraps docs. files: Doc/library/functools.rst | 7 ++++--- 1 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Doc/library/functools.rst b/Doc/library/functools.rst --- a/Doc/library/functools.rst +++ b/Doc/library/functools.rst @@ -124,9 +124,10 @@ .. function:: wraps(wrapped[, assigned][, updated]) - This is a convenience function for invoking ``partial(update_wrapper, - wrapped=wrapped, assigned=assigned, updated=updated)`` as a function decorator - when defining a wrapper function. For example: + This is a convenience function for invoking :func:`update_wrapper` as a + function decorator when defining a wrapper function. It is equivalent to + ``partial(update_wrapper, wrapped=wrapped, assigned=assigned, updated=updated)``. + For example:: >>> from functools import wraps >>> def my_decorator(f): -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Aug 5 08:00:23 2014 From: python-checkins at python.org (larry.hastings) Date: Tue, 5 Aug 2014 08:00:23 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Fix_for_AMD_FreeBSD_9_buil?= =?utf-8?q?dbot_=28hopefully=29=2C_broken_by_my_last_checkin=2E?= Message-ID: <3hS50l2mT3z7Ljv@mail.python.org> http://hg.python.org/cpython/rev/98634bc8b3c3 changeset: 92006:98634bc8b3c3 parent: 92004:5a58f6e793cc user: Larry Hastings date: Tue Aug 05 16:00:03 2014 +1000 summary: Fix for AMD FreeBSD 9 buildbot (hopefully), broken by my last checkin. files: Modules/posixmodule.c | 1 - 1 files changed, 0 insertions(+), 1 deletions(-) diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -3455,7 +3455,6 @@ #ifdef HAVE_LCHMOD -PyDoc_STRVAR(posix_lchmod__doc__, /*[clinic input] os.lchmod -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Aug 5 08:06:26 2014 From: python-checkins at python.org (larry.hastings) Date: Tue, 5 Aug 2014 08:06:26 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython=3A_More_fixes_for_the_unhappy?= =?utf-8?q?_AMD_FreeBSD_9_buildbot=2E__Fingers_crossed=2E?= Message-ID: <3hS57k5TQPz7LjZ@mail.python.org> http://hg.python.org/cpython/rev/9c057a0567a7 changeset: 92007:9c057a0567a7 user: Larry Hastings date: Tue Aug 05 16:06:16 2014 +1000 summary: More fixes for the unhappy AMD FreeBSD 9 buildbot. Fingers crossed. 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 @@ -3509,7 +3509,7 @@ { int res; Py_BEGIN_ALLOW_THREADS - res = lchmod(path.narrow, i); + res = lchmod(path->narrow, mode); Py_END_ALLOW_THREADS if (res < 0) { path_error(path); @@ -3661,7 +3661,7 @@ { int res; Py_BEGIN_ALLOW_THREADS - res = lchflags(path.narrow, flags); + res = lchflags(path->narrow, flags); Py_END_ALLOW_THREADS if (res < 0) { return path_error(path); -- Repository URL: http://hg.python.org/cpython From dw+python-dev at hmmz.org Sun Aug 3 00:13:39 2014 From: dw+python-dev at hmmz.org (David Wilson) Date: Sat, 2 Aug 2014 22:13:39 +0000 Subject: [Python-checkins] [Python-Dev] cpython: Issue #22003: When initialized from a bytes object, io.BytesIO() now In-Reply-To: References: <3hNDzH5WHWz7Ljk@mail.python.org> Message-ID: <20140802221339.GA12662@k2> Thanks for spotting, There is a new patch in http://bugs.python.org/issue22125 to fix the warnings. David From solipsis at pitrou.net Tue Aug 5 10:32:22 2014 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Tue, 05 Aug 2014 10:32:22 +0200 Subject: [Python-checkins] Daily reference leaks (25e634756f79): sum=20996 Message-ID: results for 25e634756f79 on branch "default" -------------------------------------------- test_codecs leaked [5825, 5825, 5825] references, sum=17475 test_codecs leaked [1172, 1174, 1174] memory blocks, sum=3520 test_collections leaked [0, 2, 0] references, sum=2 test_functools leaked [0, 0, 3] memory blocks, sum=3 test_site leaked [-2, 0, 0] references, sum=-2 test_site leaked [-2, 0, 0] memory blocks, sum=-2 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/cpython/refleaks/reflogasN6_U', '-x'] From python-checkins at python.org Tue Aug 5 11:35:21 2014 From: python-checkins at python.org (vinay.sajip) Date: Tue, 5 Aug 2014 11:35:21 +0200 (CEST) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzIyMTMw?= =?utf-8?q?=3A_Corrected_fileConfig=28=29_documentation=2E?= Message-ID: <3hS9mn38SZz7LjM@mail.python.org> http://hg.python.org/cpython/rev/17e1af9ad66c changeset: 92008:17e1af9ad66c branch: 2.7 parent: 92005:6cbd08fbdf77 user: Vinay Sajip date: Tue Aug 05 10:32:06 2014 +0100 summary: Issue #22130: Corrected fileConfig() documentation. files: Doc/library/logging.config.rst | 2 +- 1 files changed, 1 insertions(+), 1 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 @@ -92,7 +92,7 @@ :param disable_existing_loggers: If specified as ``False``, loggers which exist when this call is made are left - alone. The default is ``True`` because this + enabled. The default is ``True`` because this enables old behaviour in a backward- compatible way. This behaviour is to disable any existing loggers unless they or -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Aug 5 11:35:22 2014 From: python-checkins at python.org (vinay.sajip) Date: Tue, 5 Aug 2014 11:35:22 +0200 (CEST) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzIyMTMw?= =?utf-8?q?=3A_Corrected_fileConfig=28=29_documentation=2E?= Message-ID: <3hS9mp5Jvnz7LjZ@mail.python.org> http://hg.python.org/cpython/rev/734d5ab0ce6a changeset: 92009:734d5ab0ce6a branch: 3.4 parent: 92003:9e3c367b45a1 user: Vinay Sajip date: Tue Aug 05 10:34:16 2014 +0100 summary: Issue #22130: Corrected fileConfig() documentation. files: Doc/library/logging.config.rst | 2 +- 1 files changed, 1 insertions(+), 1 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 @@ -105,7 +105,7 @@ :param disable_existing_loggers: If specified as ``False``, loggers which exist when this call is made are left - alone. The default is ``True`` because this + enabled. The default is ``True`` because this enables old behaviour in a backward- compatible way. This behaviour is to disable any existing loggers unless they or -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Aug 5 11:35:24 2014 From: python-checkins at python.org (vinay.sajip) Date: Tue, 5 Aug 2014 11:35:24 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Closes_=2322130=3A_Merged_documentation_update_from_3=2E?= =?utf-8?q?4=2E?= Message-ID: <3hS9mr0JGDz7Ljs@mail.python.org> http://hg.python.org/cpython/rev/29665ab293fa changeset: 92010:29665ab293fa parent: 92007:9c057a0567a7 parent: 92009:734d5ab0ce6a user: Vinay Sajip date: Tue Aug 05 10:35:05 2014 +0100 summary: Closes #22130: Merged documentation update from 3.4. files: Doc/library/logging.config.rst | 2 +- 1 files changed, 1 insertions(+), 1 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 @@ -105,7 +105,7 @@ :param disable_existing_loggers: If specified as ``False``, loggers which exist when this call is made are left - alone. The default is ``True`` because this + enabled. The default is ``True`` because this enables old behaviour in a backward- compatible way. This behaviour is to disable any existing loggers unless they or -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Aug 5 11:55:41 2014 From: python-checkins at python.org (larry.hastings) Date: Tue, 5 Aug 2014 11:55:41 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2322120=3A_For_func?= =?utf-8?q?tions_using_an_unsigned_integer_return_converter=2C?= Message-ID: <3hSBDF4H17z7LjX@mail.python.org> http://hg.python.org/cpython/rev/9c949e0115e2 changeset: 92011:9c949e0115e2 user: Larry Hastings date: Tue Aug 05 19:55:21 2014 +1000 summary: Issue #22120: For functions using an unsigned integer return converter, Argument Clinic now generates a cast to that type for the comparison to -1 in the generated code. (This supresses a compilation warning.) files: Misc/NEWS | 4 ++++ Modules/clinic/binascii.c.h | 4 ++-- Modules/posixmodule.c | 12 ++++++------ Tools/clinic/clinic.py | 6 +++++- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -882,6 +882,10 @@ Tools/Demos ----------- +- Issue #22120: For functions using an unsigned integer return converter, + Argument Clinic now generates a cast to that type for the comparison + to -1 in the generated code. (This supresses a compilation warning.) + - Issue #18974: Tools/scripts/diff.py now uses argparse instead of optparse. - Issue #21906: Make Tools/scripts/md5sum.py work in Python 3. 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 @@ -320,7 +320,7 @@ &data, &crc)) goto exit; _return_value = binascii_crc32_impl(module, &data, crc); - if ((_return_value == -1) && PyErr_Occurred()) + if ((_return_value == (unsigned int)-1) && PyErr_Occurred()) goto exit; return_value = PyLong_FromUnsignedLong((unsigned long)_return_value); @@ -475,4 +475,4 @@ return return_value; } -/*[clinic end generated code: output=68e2bcc6956b6213 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=53cd6b379c745220 input=a9049054013a1b77]*/ diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -12465,7 +12465,7 @@ &device)) goto exit; _return_value = os_major_impl(module, device); - if ((_return_value == -1) && PyErr_Occurred()) + if ((_return_value == (unsigned int)-1) && PyErr_Occurred()) goto exit; return_value = PyLong_FromUnsignedLong((unsigned long)_return_value); @@ -12475,7 +12475,7 @@ static unsigned int os_major_impl(PyModuleDef *module, int device) -/*[clinic end generated code: output=f60d3cc3d5d20325 input=ea48820b7e10d310]*/ +/*[clinic end generated code: output=52e6743300dcf4ad input=ea48820b7e10d310]*/ { return major(device); } @@ -12514,7 +12514,7 @@ &device)) goto exit; _return_value = os_minor_impl(module, device); - if ((_return_value == -1) && PyErr_Occurred()) + if ((_return_value == (unsigned int)-1) && PyErr_Occurred()) goto exit; return_value = PyLong_FromUnsignedLong((unsigned long)_return_value); @@ -12524,7 +12524,7 @@ static unsigned int os_minor_impl(PyModuleDef *module, int device) -/*[clinic end generated code: output=71eca1d5149c2a07 input=089733ebbf9754e8]*/ +/*[clinic end generated code: output=aebe4bd7f455b755 input=089733ebbf9754e8]*/ { return minor(device); } @@ -12565,7 +12565,7 @@ &major, &minor)) goto exit; _return_value = os_makedev_impl(module, major, minor); - if ((_return_value == -1) && PyErr_Occurred()) + if ((_return_value == (unsigned int)-1) && PyErr_Occurred()) goto exit; return_value = PyLong_FromUnsignedLong((unsigned long)_return_value); @@ -12575,7 +12575,7 @@ static unsigned int os_makedev_impl(PyModuleDef *module, int major, int minor) -/*[clinic end generated code: output=e04dc5723a98cd3b input=f55bf7cffb028a08]*/ +/*[clinic end generated code: output=5cb79d9c9eac58b0 input=f55bf7cffb028a08]*/ { return makedev(major, minor); } diff --git a/Tools/clinic/clinic.py b/Tools/clinic/clinic.py --- a/Tools/clinic/clinic.py +++ b/Tools/clinic/clinic.py @@ -2865,10 +2865,11 @@ type = 'long' conversion_fn = 'PyLong_FromLong' cast = '' + unsigned_cast = '' def render(self, function, data): self.declare(data) - self.err_occurred_if("_return_value == -1", data) + self.err_occurred_if("_return_value == {}-1".format(self.unsigned_cast), data) data.return_conversion.append( ''.join(('return_value = ', self.conversion_fn, '(', self.cast, '_return_value);\n'))) @@ -2889,10 +2890,12 @@ class unsigned_long_return_converter(long_return_converter): type = 'unsigned long' conversion_fn = 'PyLong_FromUnsignedLong' + unsigned_cast = '(unsigned long)' class unsigned_int_return_converter(unsigned_long_return_converter): type = 'unsigned int' cast = '(unsigned long)' + unsigned_cast = '(unsigned int)' class Py_ssize_t_return_converter(long_return_converter): type = 'Py_ssize_t' @@ -2901,6 +2904,7 @@ class size_t_return_converter(long_return_converter): type = 'size_t' conversion_fn = 'PyLong_FromSize_t' + unsigned_cast = '(size_t)' class double_return_converter(CReturnConverter): -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Aug 5 16:11:08 2014 From: python-checkins at python.org (martin.v.loewis) Date: Tue, 5 Aug 2014 16:11:08 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2322127=3A_Bypass_I?= =?utf-8?q?DNA_for_pure-ASCII_host_names_=28in_particular_for_numeric?= Message-ID: <3hSHv00WnPz7Lk4@mail.python.org> http://hg.python.org/cpython/rev/bc991d4f9ce7 changeset: 92012:bc991d4f9ce7 user: Martin v. L?wis date: Tue Aug 05 16:10:38 2014 +0200 summary: Issue #22127: Bypass IDNA for pure-ASCII host names (in particular for numeric IPs). files: Misc/NEWS | 3 + Modules/socketmodule.c | 85 ++++++++++++++++++++++++++--- 2 files changed, 78 insertions(+), 10 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -671,6 +671,9 @@ Extension Modules ----------------- +- Issue #22127: Bypass IDNA for pure-ASCII host names + (in particular for numeric IPs). + - Issue #21407: _decimal: The module now supports function signatures. - Issue #21276: posixmodule: Don't define USE_XATTRS on KFreeBSD and the Hurd. diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -1213,6 +1213,71 @@ } } +/* Helper for getsockaddrarg: bypass IDNA for ASCII-only host names + (in particular, numeric IP addresses). */ +struct maybe_idna { + PyObject *obj; + char *buf; +}; + +static void +idna_cleanup(struct maybe_idna *data) +{ + Py_CLEAR(data->obj); +} + +static int +idna_converter(PyObject *obj, struct maybe_idna *data) +{ + size_t len; + PyObject *obj2, *obj3; + if (obj == NULL) { + idna_cleanup(data); + return 1; + } + data->obj = NULL; + len = -1; + if (PyBytes_Check(obj)) { + data->buf = PyBytes_AsString(obj); + len = PyBytes_Size(obj); + } + else if (PyByteArray_Check(obj)) { + data->buf = PyByteArray_AsString(obj); + len = PyByteArray_Size(obj); + } + else if (PyUnicode_Check(obj) && PyUnicode_READY(obj) == 0 && PyUnicode_IS_COMPACT_ASCII(obj)) { + data->buf = PyUnicode_DATA(obj); + len = PyUnicode_GET_LENGTH(obj); + } + else { + obj2 = PyUnicode_FromObject(obj); + if (!obj2) { + PyErr_Format(PyExc_TypeError, "string or unicode text buffer expected, not %s", + obj->ob_type->tp_name); + return 0; + } + obj3 = PyUnicode_AsEncodedString(obj2, "idna", NULL); + Py_DECREF(obj2); + if (!obj3) { + PyErr_SetString(PyExc_TypeError, "encoding of hostname failed"); + return 0; + } + if (!PyBytes_Check(obj3)) { + Py_DECREF(obj2); + PyErr_SetString(PyExc_TypeError, "encoding of hostname failed to return bytes"); + return 0; + } + data->obj = obj3; + data->buf = PyBytes_AS_STRING(obj3); + len = PyBytes_GET_SIZE(obj3); + } + if (strlen(data->buf) != len) { + Py_CLEAR(data->obj); + PyErr_SetString(PyExc_TypeError, "host name must not contain NUL character"); + return 0; + } + return Py_CLEANUP_SUPPORTED; +} /* Parse a socket address argument according to the socket object's address family. Return 1 if the address was in the proper format, @@ -1307,7 +1372,7 @@ case AF_INET: { struct sockaddr_in* addr; - char *host; + struct maybe_idna host = {NULL, NULL}; int port, result; if (!PyTuple_Check(args)) { PyErr_Format( @@ -1317,13 +1382,13 @@ Py_TYPE(args)->tp_name); return 0; } - if (!PyArg_ParseTuple(args, "eti:getsockaddrarg", - "idna", &host, &port)) + if (!PyArg_ParseTuple(args, "O&i:getsockaddrarg", + idna_converter, &host, &port)) return 0; addr=(struct sockaddr_in*)addr_ret; - result = setipaddr(host, (struct sockaddr *)addr, + result = setipaddr(host.buf, (struct sockaddr *)addr, sizeof(*addr), AF_INET); - PyMem_Free(host); + idna_cleanup(&host); if (result < 0) return 0; if (port < 0 || port > 0xffff) { @@ -1342,7 +1407,7 @@ case AF_INET6: { struct sockaddr_in6* addr; - char *host; + struct maybe_idna host = {NULL, NULL}; int port, result; unsigned int flowinfo, scope_id; flowinfo = scope_id = 0; @@ -1354,15 +1419,15 @@ Py_TYPE(args)->tp_name); return 0; } - if (!PyArg_ParseTuple(args, "eti|II", - "idna", &host, &port, &flowinfo, + if (!PyArg_ParseTuple(args, "O&i|II", + idna_converter, &host, &port, &flowinfo, &scope_id)) { return 0; } addr = (struct sockaddr_in6*)addr_ret; - result = setipaddr(host, (struct sockaddr *)addr, + result = setipaddr(host.buf, (struct sockaddr *)addr, sizeof(*addr), AF_INET6); - PyMem_Free(host); + idna_cleanup(&host); if (result < 0) return 0; if (port < 0 || port > 0xffff) { -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Aug 5 16:11:09 2014 From: python-checkins at python.org (martin.v.loewis) Date: Tue, 5 Aug 2014 16:11:09 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2322127=3A_Bypass_I?= =?utf-8?q?DNA_for_pure-ASCII_host_names_=28in_particular_for_numeric?= Message-ID: <3hSHv12TM4z7LkW@mail.python.org> http://hg.python.org/cpython/rev/0b477934e0a1 changeset: 92013:0b477934e0a1 user: Martin v. L?wis date: Tue Aug 05 16:11:06 2014 +0200 summary: Issue #22127: Bypass IDNA for pure-ASCII host names (in particular for numeric IPs). files: Misc/NEWS | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -671,7 +671,7 @@ Extension Modules ----------------- -- Issue #22127: Bypass IDNA for pure-ASCII host names +- Issue #22127: Bypass IDNA for pure-ASCII host names in the socket module (in particular for numeric IPs). - Issue #21407: _decimal: The module now supports function signatures. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Aug 5 16:14:02 2014 From: python-checkins at python.org (martin.v.loewis) Date: Tue, 5 Aug 2014 16:14:02 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2322127=3A_fix_typo?= =?utf-8?q?=2E?= Message-ID: <3hSHyL6qmzz7Ljs@mail.python.org> http://hg.python.org/cpython/rev/49085b746029 changeset: 92014:49085b746029 user: Martin v. L?wis date: Tue Aug 05 16:13:50 2014 +0200 summary: Issue #22127: fix typo. 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 @@ -1263,7 +1263,7 @@ return 0; } if (!PyBytes_Check(obj3)) { - Py_DECREF(obj2); + Py_DECREF(obj3); PyErr_SetString(PyExc_TypeError, "encoding of hostname failed to return bytes"); return 0; } -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Aug 5 17:28:57 2014 From: python-checkins at python.org (barry.warsaw) Date: Tue, 5 Aug 2014 17:28:57 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython=3A_-_Issue_=2321539=3A_Add_a_?= =?utf-8?q?*exists=5Fok*_argument_to_=60Pathlib=2Emkdir=28=29=60_to_mimic?= Message-ID: <3hSKcn03CRz7Lk8@mail.python.org> http://hg.python.org/cpython/rev/8af80d68bcdc changeset: 92015:8af80d68bcdc user: Barry Warsaw date: Tue Aug 05 11:28:12 2014 -0400 summary: - Issue #21539: Add a *exists_ok* argument to `Pathlib.mkdir()` to mimic `mkdir -p` and `os.makedirs()` functionality. When true, ignore FileExistsErrors. Patch by Berker Peksag. (With minor cleanups, additional tests, doc tweaks, etc. by Barry) Also: * Remove some unused imports in test_pathlib.py reported by pyflakes. files: Doc/library/pathlib.rst | 12 +++++- Lib/pathlib.py | 11 ++++- Lib/test/test_pathlib.py | 58 ++++++++++++++++++++++++-- Lib/test/test_platform.py | 2 +- Misc/NEWS | 4 + 5 files changed, 78 insertions(+), 9 deletions(-) diff --git a/Doc/library/pathlib.rst b/Doc/library/pathlib.rst --- a/Doc/library/pathlib.rst +++ b/Doc/library/pathlib.rst @@ -791,7 +791,7 @@ the symbolic link's information rather than its target's. -.. method:: Path.mkdir(mode=0o777, parents=False) +.. method:: Path.mkdir(mode=0o777, parents=False, exist_ok=False) Create a new directory at this given path. If *mode* is given, it is combined with the process' ``umask`` value to determine the file mode @@ -805,6 +805,16 @@ If *parents* is false (the default), a missing parent raises :exc:`FileNotFoundError`. + If *exist_ok* is false (the default), an :exc:`FileExistsError` is + raised if the target directory already exists. + + If *exist_ok* is true, :exc:`FileExistsError` exceptions will be + ignored (same behavior as the POSIX ``mkdir -p`` command), but only if the + last path component is not an existing non-directory file. + + .. versionchanged:: 3.5 + The *exist_ok* parameter was added. + .. method:: Path.open(mode='r', buffering=-1, encoding=None, errors=None, newline=None) diff --git a/Lib/pathlib.py b/Lib/pathlib.py --- a/Lib/pathlib.py +++ b/Lib/pathlib.py @@ -1106,14 +1106,21 @@ fd = self._raw_open(flags, mode) os.close(fd) - def mkdir(self, mode=0o777, parents=False): + def mkdir(self, mode=0o777, parents=False, exist_ok=False): if self._closed: self._raise_closed() if not parents: - self._accessor.mkdir(self, mode) + try: + self._accessor.mkdir(self, mode) + except FileExistsError: + if not exist_ok or not self.is_dir(): + raise else: try: self._accessor.mkdir(self, mode) + except FileExistsError: + if not exist_ok or not self.is_dir(): + raise except OSError as e: if e.errno != ENOENT: raise diff --git a/Lib/test/test_pathlib.py b/Lib/test/test_pathlib.py --- a/Lib/test/test_pathlib.py +++ b/Lib/test/test_pathlib.py @@ -4,13 +4,10 @@ import errno import pathlib import pickle -import shutil import socket import stat -import sys import tempfile import unittest -from contextlib import contextmanager from test import support TESTFN = support.TESTFN @@ -743,7 +740,6 @@ self.assertEqual(P('//Some/SHARE/a/B'), P('//somE/share/A/b')) def test_as_uri(self): - from urllib.parse import quote_from_bytes P = self.cls with self.assertRaises(ValueError): P('/a/b').as_uri() @@ -1617,6 +1613,59 @@ # the parent's permissions follow the default process settings self.assertEqual(stat.S_IMODE(p.parent.stat().st_mode), mode) + def test_mkdir_exist_ok(self): + p = self.cls(BASE, 'dirB') + st_ctime_first = p.stat().st_ctime + self.assertTrue(p.exists()) + self.assertTrue(p.is_dir()) + with self.assertRaises(FileExistsError) as cm: + p.mkdir() + self.assertEqual(cm.exception.errno, errno.EEXIST) + p.mkdir(exist_ok=True) + self.assertTrue(p.exists()) + self.assertEqual(p.stat().st_ctime, st_ctime_first) + + def test_mkdir_exist_ok_with_parent(self): + p = self.cls(BASE, 'dirC') + self.assertTrue(p.exists()) + with self.assertRaises(FileExistsError) as cm: + p.mkdir() + self.assertEqual(cm.exception.errno, errno.EEXIST) + p = p / 'newdirC' + p.mkdir(parents=True) + st_ctime_first = p.stat().st_ctime + self.assertTrue(p.exists()) + with self.assertRaises(FileExistsError) as cm: + p.mkdir(parents=True) + self.assertEqual(cm.exception.errno, errno.EEXIST) + p.mkdir(parents=True, exist_ok=True) + self.assertTrue(p.exists()) + self.assertEqual(p.stat().st_ctime, st_ctime_first) + + def test_mkdir_with_child_file(self): + p = self.cls(BASE, 'dirB', 'fileB') + self.assertTrue(p.exists()) + # An exception is raised when the last path component is an existing + # regular file, regardless of whether exist_ok is true or not. + with self.assertRaises(FileExistsError) as cm: + p.mkdir(parents=True) + self.assertEqual(cm.exception.errno, errno.EEXIST) + with self.assertRaises(FileExistsError) as cm: + p.mkdir(parents=True, exist_ok=True) + self.assertEqual(cm.exception.errno, errno.EEXIST) + + def test_mkdir_no_parents_file(self): + p = self.cls(BASE, 'fileA') + self.assertTrue(p.exists()) + # An exception is raised when the last path component is an existing + # regular file, regardless of whether exist_ok is true or not. + with self.assertRaises(FileExistsError) as cm: + p.mkdir() + self.assertEqual(cm.exception.errno, errno.EEXIST) + with self.assertRaises(FileExistsError) as cm: + p.mkdir(exist_ok=True) + self.assertEqual(cm.exception.errno, errno.EEXIST) + @with_symlinks def test_symlink_to(self): P = self.cls(BASE) @@ -1852,7 +1901,6 @@ @with_symlinks def test_resolve_loop(self): # Loop detection for broken symlinks under POSIX - P = self.cls # Loops with relative symlinks os.symlink('linkX/inside', join('linkX')) self._check_symlink_loop(BASE, 'linkX') diff --git a/Lib/test/test_platform.py b/Lib/test/test_platform.py --- a/Lib/test/test_platform.py +++ b/Lib/test/test_platform.py @@ -307,7 +307,7 @@ with mock.patch('platform._UNIXCONFDIR', tempdir): distname, version, distid = platform.linux_distribution() - self.assertEqual(distname, 'Fedora') + self.assertEqual(distname, 'Fedora') self.assertEqual(version, '19') self.assertEqual(distid, 'Schr\xf6dinger\u2019s Cat') diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -123,6 +123,10 @@ Library ------- +- Issue #21539: Add a *exists_ok* argument to `Pathlib.mkdir()` to mimic + `mkdir -p` and `os.makedirs()` functionality. When true, ignore + FileExistsErrors. Patch by Berker Peksag. + - Issue #21047: set the default value for the *convert_charrefs* argument of HTMLParser to True. Patch by Berker Peksag. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Aug 5 17:56:54 2014 From: python-checkins at python.org (martin.v.loewis) Date: Tue, 5 Aug 2014 17:56:54 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2321972=3A_Make_it_?= =?utf-8?q?clear_that_the_PEP_401_future_import_works=2C?= Message-ID: <3hSLF260q2z7LjM@mail.python.org> http://hg.python.org/cpython/rev/57740d19f5c2 changeset: 92016:57740d19f5c2 user: Martin v. L?wis date: Tue Aug 05 17:56:52 2014 +0200 summary: Issue #21972: Make it clear that the PEP 401 future import works, despite the PEP being rejected. files: Grammar/Grammar | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Grammar/Grammar b/Grammar/Grammar --- a/Grammar/Grammar +++ b/Grammar/Grammar @@ -89,7 +89,7 @@ not_test: 'not' not_test | comparison comparison: expr (comp_op expr)* # <> isn't actually a valid comparison operator in Python. It's here for the -# sake of a __future__ import described in PEP 401 +# sake of a __future__ import described in PEP 401 (which really works :-) comp_op: '<'|'>'|'=='|'>='|'<='|'<>'|'!='|'in'|'not' 'in'|'is'|'is' 'not' star_expr: '*' expr expr: xor_expr ('|' xor_expr)* -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Aug 5 18:55:11 2014 From: python-checkins at python.org (zach.ware) Date: Tue, 5 Aug 2014 18:55:11 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Closes_=2322136=3A_Fix_MSV?= =?utf-8?q?C_compiler_warnings_introduced_by_=2322085?= Message-ID: <3hSMXH68ZMz7Ll6@mail.python.org> http://hg.python.org/cpython/rev/7ed237478fcc changeset: 92017:7ed237478fcc user: Zachary Ware date: Tue Aug 05 11:54:34 2014 -0500 summary: Closes #22136: Fix MSVC compiler warnings introduced by #22085 files: Modules/_tkinter.c | 14 +++++++------- 1 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Modules/_tkinter.c b/Modules/_tkinter.c --- a/Modules/_tkinter.c +++ b/Modules/_tkinter.c @@ -228,13 +228,13 @@ 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 *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) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Aug 5 21:02:30 2014 From: python-checkins at python.org (zach.ware) Date: Tue, 5 Aug 2014 21:02:30 +0200 (CEST) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzIyMTQ2?= =?utf-8?q?=3A_Fix_typo_in_=5F=5Fbuild=5Fclass=5F=5F_error_message?= Message-ID: <3hSQMB0pN0z7LjN@mail.python.org> http://hg.python.org/cpython/rev/de287a94b486 changeset: 92018:de287a94b486 branch: 3.4 parent: 92009:734d5ab0ce6a user: Zachary Ware date: Tue Aug 05 14:01:10 2014 -0500 summary: Issue #22146: Fix typo in __build_class__ error message files: Python/bltinmodule.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -69,7 +69,7 @@ func = PyTuple_GET_ITEM(args, 0); /* Better be callable */ if (!PyFunction_Check(func)) { PyErr_SetString(PyExc_TypeError, - "__build__class__: func must be a function"); + "__build_class__: func must be a function"); return NULL; } name = PyTuple_GET_ITEM(args, 1); -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Aug 5 21:02:31 2014 From: python-checkins at python.org (zach.ware) Date: Tue, 5 Aug 2014 21:02:31 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Closes_=2322146=3A_Merge_with_3=2E4?= Message-ID: <3hSQMC2WbVz7Ljv@mail.python.org> http://hg.python.org/cpython/rev/d85fcf23549e changeset: 92019:d85fcf23549e parent: 92017:7ed237478fcc parent: 92018:de287a94b486 user: Zachary Ware date: Tue Aug 05 14:02:11 2014 -0500 summary: Closes #22146: Merge with 3.4 files: Python/bltinmodule.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -69,7 +69,7 @@ func = PyTuple_GET_ITEM(args, 0); /* Better be callable */ if (!PyFunction_Check(func)) { PyErr_SetString(PyExc_TypeError, - "__build__class__: func must be a function"); + "__build_class__: func must be a function"); return NULL; } name = PyTuple_GET_ITEM(args, 1); -- Repository URL: http://hg.python.org/cpython From solipsis at pitrou.net Wed Aug 6 10:26:17 2014 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Wed, 06 Aug 2014 10:26:17 +0200 Subject: [Python-checkins] Daily reference leaks (d85fcf23549e): sum=21055 Message-ID: results for d85fcf23549e on branch "default" -------------------------------------------- test_codecs leaked [5825, 5825, 5825] references, sum=17475 test_codecs leaked [1172, 1174, 1174] memory blocks, sum=3520 test_collections leaked [-2, 0, 0] references, sum=-2 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 test_site leaked [2, 0, 0] references, sum=2 test_site leaked [2, 0, 0] memory blocks, sum=2 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/cpython/refleaks/reflog6xPaUM', '-x'] From python-checkins at python.org Wed Aug 6 16:55:47 2014 From: python-checkins at python.org (serhiy.storchaka) Date: Wed, 6 Aug 2014 16:55:47 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Move_misplaced_Misc/NEWS_e?= =?utf-8?q?ntries_to_correct_locations=2E?= Message-ID: <3hSwr34qmsz7Ljb@mail.python.org> http://hg.python.org/cpython/rev/bb02acd9e9e9 changeset: 92020:bb02acd9e9e9 user: Serhiy Storchaka date: Wed Aug 06 17:45:35 2014 +0300 summary: Move misplaced Misc/NEWS entries to correct locations. Eliminate deprecated the "Extension Modules" section. files: Misc/NEWS | 45 +++++++++++++++++++++--------------------- 1 files changed, 22 insertions(+), 23 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,16 +10,10 @@ Core and Builtins ----------------- -- Issue #20170: Convert posixmodule to use Argument Clinic. - - Issue #22077: Improve index error messages for bytearrays, bytes, lists, and tuples by adding 'or slices'. Added ', not http://hg.python.org/cpython/rev/c46ad743bcb4 changeset: 92021:c46ad743bcb4 branch: 2.7 parent: 92008:17e1af9ad66c user: Serhiy Storchaka date: Wed Aug 06 17:50:22 2014 +0300 summary: Issue #21975: Fixed crash when using uninitialized sqlite3.Row (in particular when unpickling pickled sqlite3.Row). sqlite3.Row is now initialized in the __new__() method. files: Misc/NEWS | 4 ++++ Modules/_sqlite/row.c | 28 +++++++++++++++++----------- 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -19,6 +19,10 @@ Library ------- +- Issue #21975: Fixed crash when using uninitialized sqlite3.Row (in particular + when unpickling pickled sqlite3.Row). sqlite3.Row is now initialized in the + __new__() method. + - Issue #16037: HTTPMessage.readheaders() raises an HTTPException when more than 100 headers are read. Patch by Jyrki Pulliainen and Daniel Eriksson. diff --git a/Modules/_sqlite/row.c b/Modules/_sqlite/row.c --- a/Modules/_sqlite/row.c +++ b/Modules/_sqlite/row.c @@ -33,35 +33,41 @@ Py_TYPE(self)->tp_free((PyObject*)self); } -int pysqlite_row_init(pysqlite_Row* self, PyObject* args, PyObject* kwargs) +static PyObject * +pysqlite_row_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) { + pysqlite_Row *self; PyObject* data; pysqlite_Cursor* cursor; - self->data = 0; - self->description = 0; + assert(type != NULL && type->tp_alloc != NULL); - if (!PyArg_ParseTuple(args, "OO", &cursor, &data)) { - return -1; - } + if (!_PyArg_NoKeywords("Row()", kwargs)) + return NULL; + if (!PyArg_ParseTuple(args, "OO", &cursor, &data)) + return NULL; if (!PyObject_IsInstance((PyObject*)cursor, (PyObject*)&pysqlite_CursorType)) { PyErr_SetString(PyExc_TypeError, "instance of cursor required for first argument"); - return -1; + return NULL; } if (!PyTuple_Check(data)) { PyErr_SetString(PyExc_TypeError, "tuple required for second argument"); - return -1; + return NULL; } + self = (pysqlite_Row *) type->tp_alloc(type, 0); + if (self == NULL) + return NULL; + Py_INCREF(data); self->data = data; Py_INCREF(cursor->description); self->description = cursor->description; - return 0; + return (PyObject *) self; } PyObject* pysqlite_row_item(pysqlite_Row* self, Py_ssize_t idx) @@ -263,7 +269,7 @@ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ - (initproc)pysqlite_row_init, /* tp_init */ + 0, /* tp_init */ 0, /* tp_alloc */ 0, /* tp_new */ 0 /* tp_free */ @@ -271,7 +277,7 @@ extern int pysqlite_row_setup_types(void) { - pysqlite_RowType.tp_new = PyType_GenericNew; + pysqlite_RowType.tp_new = pysqlite_row_new; pysqlite_RowType.tp_as_mapping = &pysqlite_row_as_mapping; pysqlite_RowType.tp_as_sequence = &pysqlite_row_as_sequence; return PyType_Ready(&pysqlite_RowType); -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Aug 6 16:55:50 2014 From: python-checkins at python.org (serhiy.storchaka) Date: Wed, 6 Aug 2014 16:55:50 +0200 (CEST) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzIxOTc1?= =?utf-8?q?=3A_Fixed_crash_when_using_uninitialized_sqlite3=2ERow_=28in_pa?= =?utf-8?q?rticular?= Message-ID: <3hSwr60mhVz7LlB@mail.python.org> http://hg.python.org/cpython/rev/c1ca1c4c131b changeset: 92022:c1ca1c4c131b branch: 3.4 parent: 92018:de287a94b486 user: Serhiy Storchaka date: Wed Aug 06 17:50:39 2014 +0300 summary: Issue #21975: Fixed crash when using uninitialized sqlite3.Row (in particular when unpickling pickled sqlite3.Row). sqlite3.Row is now initialized in the __new__() method. files: Misc/NEWS | 4 ++++ Modules/_sqlite/row.c | 28 +++++++++++++++++----------- 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -27,6 +27,10 @@ Library ------- +- Issue #21975: Fixed crash when using uninitialized sqlite3.Row (in particular + when unpickling pickled sqlite3.Row). sqlite3.Row is now initialized in the + __new__() method. + - Issue #21580: Now Tkinter correctly handles bytes arguments passed to Tk. In particular this allows to initialize images from binary data. diff --git a/Modules/_sqlite/row.c b/Modules/_sqlite/row.c --- a/Modules/_sqlite/row.c +++ b/Modules/_sqlite/row.c @@ -32,35 +32,41 @@ Py_TYPE(self)->tp_free((PyObject*)self); } -int pysqlite_row_init(pysqlite_Row* self, PyObject* args, PyObject* kwargs) +static PyObject * +pysqlite_row_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) { + pysqlite_Row *self; PyObject* data; pysqlite_Cursor* cursor; - self->data = 0; - self->description = 0; + assert(type != NULL && type->tp_alloc != NULL); - if (!PyArg_ParseTuple(args, "OO", &cursor, &data)) { - return -1; - } + if (!_PyArg_NoKeywords("Row()", kwargs)) + return NULL; + if (!PyArg_ParseTuple(args, "OO", &cursor, &data)) + return NULL; if (!PyObject_IsInstance((PyObject*)cursor, (PyObject*)&pysqlite_CursorType)) { PyErr_SetString(PyExc_TypeError, "instance of cursor required for first argument"); - return -1; + return NULL; } if (!PyTuple_Check(data)) { PyErr_SetString(PyExc_TypeError, "tuple required for second argument"); - return -1; + return NULL; } + self = (pysqlite_Row *) type->tp_alloc(type, 0); + if (self == NULL) + return NULL; + Py_INCREF(data); self->data = data; Py_INCREF(cursor->description); self->description = cursor->description; - return 0; + return (PyObject *) self; } PyObject* pysqlite_row_item(pysqlite_Row* self, Py_ssize_t idx) @@ -260,7 +266,7 @@ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ - (initproc)pysqlite_row_init, /* tp_init */ + 0, /* tp_init */ 0, /* tp_alloc */ 0, /* tp_new */ 0 /* tp_free */ @@ -268,7 +274,7 @@ extern int pysqlite_row_setup_types(void) { - pysqlite_RowType.tp_new = PyType_GenericNew; + pysqlite_RowType.tp_new = pysqlite_row_new; pysqlite_RowType.tp_as_mapping = &pysqlite_row_as_mapping; pysqlite_RowType.tp_as_sequence = &pysqlite_row_as_sequence; return PyType_Ready(&pysqlite_RowType); -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Aug 6 16:55:51 2014 From: python-checkins at python.org (serhiy.storchaka) Date: Wed, 6 Aug 2014 16:55:51 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2321975=3A_Fixed_crash_when_using_uninitialized_s?= =?utf-8?q?qlite3=2ERow_=28in_particular?= Message-ID: <3hSwr72Q1Dz7LkD@mail.python.org> http://hg.python.org/cpython/rev/9244ed41057a changeset: 92023:9244ed41057a parent: 92020:bb02acd9e9e9 parent: 92022:c1ca1c4c131b user: Serhiy Storchaka date: Wed Aug 06 17:51:58 2014 +0300 summary: Issue #21975: Fixed crash when using uninitialized sqlite3.Row (in particular when unpickling pickled sqlite3.Row). sqlite3.Row is now initialized in the __new__() method. files: Misc/NEWS | 4 ++++ Modules/_sqlite/row.c | 28 +++++++++++++++++----------- 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -112,6 +112,10 @@ Library ------- +- Issue #21975: Fixed crash when using uninitialized sqlite3.Row (in particular + when unpickling pickled sqlite3.Row). sqlite3.Row is now initialized in the + __new__() method. + - Issue #20170: Convert posixmodule to use Argument Clinic. - Issue #21539: Add a *exists_ok* argument to `Pathlib.mkdir()` to mimic diff --git a/Modules/_sqlite/row.c b/Modules/_sqlite/row.c --- a/Modules/_sqlite/row.c +++ b/Modules/_sqlite/row.c @@ -32,35 +32,41 @@ Py_TYPE(self)->tp_free((PyObject*)self); } -int pysqlite_row_init(pysqlite_Row* self, PyObject* args, PyObject* kwargs) +static PyObject * +pysqlite_row_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) { + pysqlite_Row *self; PyObject* data; pysqlite_Cursor* cursor; - self->data = 0; - self->description = 0; + assert(type != NULL && type->tp_alloc != NULL); - if (!PyArg_ParseTuple(args, "OO", &cursor, &data)) { - return -1; - } + if (!_PyArg_NoKeywords("Row()", kwargs)) + return NULL; + if (!PyArg_ParseTuple(args, "OO", &cursor, &data)) + return NULL; if (!PyObject_IsInstance((PyObject*)cursor, (PyObject*)&pysqlite_CursorType)) { PyErr_SetString(PyExc_TypeError, "instance of cursor required for first argument"); - return -1; + return NULL; } if (!PyTuple_Check(data)) { PyErr_SetString(PyExc_TypeError, "tuple required for second argument"); - return -1; + return NULL; } + self = (pysqlite_Row *) type->tp_alloc(type, 0); + if (self == NULL) + return NULL; + Py_INCREF(data); self->data = data; Py_INCREF(cursor->description); self->description = cursor->description; - return 0; + return (PyObject *) self; } PyObject* pysqlite_row_item(pysqlite_Row* self, Py_ssize_t idx) @@ -260,7 +266,7 @@ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ - (initproc)pysqlite_row_init, /* tp_init */ + 0, /* tp_init */ 0, /* tp_alloc */ 0, /* tp_new */ 0 /* tp_free */ @@ -268,7 +274,7 @@ extern int pysqlite_row_setup_types(void) { - pysqlite_RowType.tp_new = PyType_GenericNew; + pysqlite_RowType.tp_new = pysqlite_row_new; pysqlite_RowType.tp_as_mapping = &pysqlite_row_as_mapping; pysqlite_RowType.tp_as_sequence = &pysqlite_row_as_sequence; return PyType_Ready(&pysqlite_RowType); -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Aug 6 17:32:20 2014 From: python-checkins at python.org (serhiy.storchaka) Date: Wed, 6 Aug 2014 17:32:20 +0200 (CEST) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzE4MDA0?= =?utf-8?q?=3A_test=5Foverflow_in_test=5Flist_by_mistake_consumed_40_GiB_o?= =?utf-8?q?f_memory?= Message-ID: <3hSxfD34rZz7LjX@mail.python.org> http://hg.python.org/cpython/rev/217485e80a32 changeset: 92024:217485e80a32 branch: 2.7 parent: 92021:c46ad743bcb4 user: Serhiy Storchaka date: Wed Aug 06 18:31:54 2014 +0300 summary: Issue #18004: test_overflow in test_list by mistake consumed 40 GiB of memory on 64-bit systems. files: Lib/test/test_list.py | 2 +- Misc/NEWS | 3 +++ 2 files changed, 4 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_list.py b/Lib/test/test_list.py --- a/Lib/test/test_list.py +++ b/Lib/test/test_list.py @@ -53,7 +53,7 @@ def test_overflow(self): lst = [4, 5, 6, 7] - n = int((sys.maxint*2+2) // len(lst)) + n = int((sys.maxsize*2+2) // len(lst)) def mul(a, b): return a * b def imul(a, b): a *= b self.assertRaises((MemoryError, OverflowError), mul, lst, n) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -74,6 +74,9 @@ Tests ----- +- Issue #18004: test_overflow in test_list by mistake consumed 40 GiB of memory + on 64-bit systems. + - Issue #21976: Fix test_ssl to accept LibreSSL version strings. Thanks to William Orr. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Aug 6 17:51:11 2014 From: python-checkins at python.org (serhiy.storchaka) Date: Wed, 6 Aug 2014 17:51:11 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=235411=3A_Added_sup?= =?utf-8?q?port_for_the_=22xztar=22_format_in_the_shutil_module=2E?= Message-ID: <3hSy3z34sMz7LjX@mail.python.org> http://hg.python.org/cpython/rev/e57db221b6c4 changeset: 92025:e57db221b6c4 parent: 92023:9244ed41057a user: Serhiy Storchaka date: Wed Aug 06 18:50:19 2014 +0300 summary: Issue #5411: Added support for the "xztar" format in the shutil module. files: Doc/library/shutil.rst | 8 +++++++- Lib/shutil.py | 27 +++++++++++++++++++++++---- Lib/test/test_shutil.py | 8 ++++++++ Misc/NEWS | 2 ++ 4 files changed, 40 insertions(+), 5 deletions(-) diff --git a/Doc/library/shutil.rst b/Doc/library/shutil.rst --- a/Doc/library/shutil.rst +++ b/Doc/library/shutil.rst @@ -469,7 +469,8 @@ *base_name* is the name of the file to create, including the path, minus any format-specific extension. *format* is the archive format: one of - "zip", "tar", "bztar" (if the :mod:`bz2` module is available) or "gztar". + "zip", "tar", "bztar" (if the :mod:`bz2` module is available), "xztar" + (if the :mod:`lzma` module is available) or "gztar". *root_dir* is a directory that will be the root directory of the archive; for example, we typically chdir into *root_dir* before creating the @@ -487,6 +488,9 @@ *logger* must be an object compatible with :pep:`282`, usually an instance of :class:`logging.Logger`. + .. versionchanged:: 3.4 + Added support for the *xztar* format. + .. function:: get_archive_formats() @@ -497,6 +501,7 @@ - *gztar*: gzip'ed tar-file - *bztar*: bzip2'ed tar-file (if the :mod:`bz2` module is available.) + - *xztar*: xz'ed tar-file (if the :mod:`lzma` module is available.) - *tar*: uncompressed tar file - *zip*: ZIP file @@ -567,6 +572,7 @@ - *gztar*: gzip'ed tar-file - *bztar*: bzip2'ed tar-file (if the :mod:`bz2` module is available.) + - *xztar*: xz'ed tar-file (if the :mod:`lzma` module is available.) - *tar*: uncompressed tar file - *zip*: ZIP file diff --git a/Lib/shutil.py b/Lib/shutil.py --- a/Lib/shutil.py +++ b/Lib/shutil.py @@ -21,6 +21,13 @@ _BZ2_SUPPORTED = False try: + import lzma + del lzma + _LZMA_SUPPORTED = True +except ImportError: + _LZMA_SUPPORTED = False + +try: from pwd import getpwnam except ImportError: getpwnam = None @@ -580,14 +587,14 @@ """Create a (possibly compressed) tar file from all the files under 'base_dir'. - 'compress' must be "gzip" (the default), "bzip2", or None. + 'compress' must be "gzip" (the default), "bzip2", "xz", or None. 'owner' and 'group' can be used to define an owner and a group for the archive that is being built. If not provided, the current owner and group will be used. The output tar file will be named 'base_name' + ".tar", possibly plus - the appropriate compression extension (".gz", or ".bz2"). + the appropriate compression extension (".gz", ".bz2", or ".xz"). Returns the output filename. """ @@ -598,6 +605,10 @@ tar_compression['bzip2'] = 'bz2' compress_ext['bzip2'] = '.bz2' + if _LZMA_SUPPORTED: + tar_compression['xz'] = 'xz' + compress_ext['xz'] = '.xz' + # flags for compression program, each element of list will be an argument if compress is not None and compress not in compress_ext: raise ValueError("bad value for 'compress', or compression format not " @@ -684,6 +695,10 @@ _ARCHIVE_FORMATS['bztar'] = (_make_tarball, [('compress', 'bzip2')], "bzip2'ed tar-file") +if _LZMA_SUPPORTED: + _ARCHIVE_FORMATS['xztar'] = (_make_tarball, [('compress', 'xz')], + "xz'ed tar-file") + def get_archive_formats(): """Returns a list of supported formats for archiving and unarchiving. @@ -872,7 +887,7 @@ zip.close() def _unpack_tarfile(filename, extract_dir): - """Unpack tar/tar.gz/tar.bz2 `filename` to `extract_dir` + """Unpack tar/tar.gz/tar.bz2/tar.xz `filename` to `extract_dir` """ try: tarobj = tarfile.open(filename) @@ -891,9 +906,13 @@ } if _BZ2_SUPPORTED: - _UNPACK_FORMATS['bztar'] = (['.bz2'], _unpack_tarfile, [], + _UNPACK_FORMATS['bztar'] = (['.tar.bz2', '.tbz2'], _unpack_tarfile, [], "bzip2'ed tar-file") +if _LZMA_SUPPORTED: + _UNPACK_FORMATS['xztar'] = (['.tar.xz', '.txz'], _unpack_tarfile, [], + "xz'ed tar-file") + def _find_unpack_format(filename): for name, info in _UNPACK_FORMATS.items(): for extension in info[0]: diff --git a/Lib/test/test_shutil.py b/Lib/test/test_shutil.py --- a/Lib/test/test_shutil.py +++ b/Lib/test/test_shutil.py @@ -32,6 +32,12 @@ except ImportError: BZ2_SUPPORTED = False +try: + import lzma + LZMA_SUPPORTED = True +except ImportError: + LZMA_SUPPORTED = False + TESTFN2 = TESTFN + "2" try: @@ -1156,6 +1162,8 @@ formats = ['tar', 'gztar', 'zip'] if BZ2_SUPPORTED: formats.append('bztar') + if LZMA_SUPPORTED: + formats.append('xztar') for format in formats: tmpdir = self.mkdtemp() diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -112,6 +112,8 @@ Library ------- +- Issue #5411: Added support for the "xztar" format in the shutil module. + - Issue #21975: Fixed crash when using uninitialized sqlite3.Row (in particular when unpickling pickled sqlite3.Row). sqlite3.Row is now initialized in the __new__() method. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Aug 6 17:56:25 2014 From: python-checkins at python.org (serhiy.storchaka) Date: Wed, 6 Aug 2014 17:56:25 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=235411=3A_Fixed_ver?= =?utf-8?q?sion_number=2E?= Message-ID: <3hSyB154mVz7Ljb@mail.python.org> http://hg.python.org/cpython/rev/a47996c10579 changeset: 92026:a47996c10579 user: Serhiy Storchaka date: Wed Aug 06 18:55:54 2014 +0300 summary: Issue #5411: Fixed version number. files: Doc/library/shutil.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/library/shutil.rst b/Doc/library/shutil.rst --- a/Doc/library/shutil.rst +++ b/Doc/library/shutil.rst @@ -488,7 +488,7 @@ *logger* must be an object compatible with :pep:`282`, usually an instance of :class:`logging.Logger`. - .. versionchanged:: 3.4 + .. versionchanged:: 3.5 Added support for the *xztar* format. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Aug 7 01:34:50 2014 From: python-checkins at python.org (antoine.pitrou) Date: Thu, 7 Aug 2014 01:34:50 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2322116=3A_C_functi?= =?utf-8?q?ons_and_methods_=28of_the_=27builtin=5Ffunction=5For=5Fmethod?= =?utf-8?q?=27?= Message-ID: <3hT8Ly5MNSz7LjX@mail.python.org> http://hg.python.org/cpython/rev/87f940e85cb0 changeset: 92027:87f940e85cb0 user: Antoine Pitrou date: Wed Aug 06 19:31:40 2014 -0400 summary: Issue #22116: C functions and methods (of the 'builtin_function_or_method' type) can now be weakref'ed. Patch by Wei Wu. files: Include/methodobject.h | 1 + Lib/test/test_sys.py | 2 +- Lib/test/test_weakref.py | 12 ++++++++++++ Misc/ACKS | 1 + Misc/NEWS | 3 +++ Modules/_testcapimodule.c | 16 ++++++++++++++++ Objects/methodobject.c | 6 +++++- 7 files changed, 39 insertions(+), 2 deletions(-) diff --git a/Include/methodobject.h b/Include/methodobject.h --- a/Include/methodobject.h +++ b/Include/methodobject.h @@ -77,6 +77,7 @@ PyMethodDef *m_ml; /* Description of the C function to call */ PyObject *m_self; /* Passed as 'self' arg to the C func, can be NULL */ PyObject *m_module; /* The __module__ attribute, can be anything */ + PyObject *m_weakreflist; /* List of weak references */ } PyCFunctionObject; #endif diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py --- a/Lib/test/test_sys.py +++ b/Lib/test/test_sys.py @@ -784,7 +784,7 @@ # buffer # XXX # builtin_function_or_method - check(len, size('3P')) # XXX check layout + check(len, size('4P')) # XXX check layout # bytearray samples = [b'', b'u'*100000] for sample in samples: diff --git a/Lib/test/test_weakref.py b/Lib/test/test_weakref.py --- a/Lib/test/test_weakref.py +++ b/Lib/test/test_weakref.py @@ -92,6 +92,18 @@ self.check_basic_callback(create_function) self.check_basic_callback(create_bound_method) + @support.cpython_only + def test_cfunction(self): + import _testcapi + create_cfunction = _testcapi.create_cfunction + f = create_cfunction() + wr = weakref.ref(f) + self.assertIs(wr(), f) + del f + self.assertIsNone(wr()) + self.check_basic_ref(create_cfunction) + self.check_basic_callback(create_cfunction) + def test_multiple_callbacks(self): o = C() ref1 = weakref.ref(o, self.callback) diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -1484,6 +1484,7 @@ Darren Worrall Thomas Wouters Daniel Wozniak +Wei Wu Heiko Wundram Doug Wyatt Robert Xiao diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,9 @@ Core and Builtins ----------------- +- Issue #22116: C functions and methods (of the 'builtin_function_or_method' + type) can now be weakref'ed. Patch by Wei Wu. + - Issue #22077: Improve index error messages for bytearrays, bytes, lists, and tuples by adding 'or slices'. Added ', not m_weakreflist = NULL; op->m_ml = ml; Py_XINCREF(self); op->m_self = self; @@ -147,6 +148,9 @@ meth_dealloc(PyCFunctionObject *m) { _PyObject_GC_UNTRACK(m); + if (m->m_weakreflist != NULL) { + PyObject_ClearWeakRefs((PyObject*) m); + } Py_XDECREF(m->m_self); Py_XDECREF(m->m_module); if (numfree < PyCFunction_MAXFREELIST) { @@ -352,7 +356,7 @@ (traverseproc)meth_traverse, /* tp_traverse */ 0, /* tp_clear */ meth_richcompare, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ + offsetof(PyCFunctionObject, m_weakreflist), /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ meth_methods, /* tp_methods */ -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Aug 7 02:29:55 2014 From: python-checkins at python.org (ezio.melotti) Date: Thu, 7 Aug 2014 02:29:55 +0200 (CEST) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogIzIyMDkyOiB1c2Ug?= =?utf-8?q?absolute_imports_in_unittest_tests=2E__Patch_by_Vajrasky_Kok=2E?= Message-ID: <3hT9ZW0Grhz7LjT@mail.python.org> http://hg.python.org/cpython/rev/668f6938fb1c changeset: 92028:668f6938fb1c branch: 3.4 parent: 92022:c1ca1c4c131b user: Ezio Melotti date: Thu Aug 07 03:20:22 2014 +0300 summary: #22092: use absolute imports in unittest tests. Patch by Vajrasky Kok. files: Lib/unittest/test/test_case.py | 2 +- Lib/unittest/test/test_discovery.py | 1 + Lib/unittest/test/test_functiontestcase.py | 2 +- Lib/unittest/test/test_program.py | 1 + Lib/unittest/test/test_runner.py | 3 ++- Lib/unittest/test/test_skipping.py | 2 +- Lib/unittest/test/test_suite.py | 2 +- 7 files changed, 8 insertions(+), 5 deletions(-) diff --git a/Lib/unittest/test/test_case.py b/Lib/unittest/test/test_case.py --- a/Lib/unittest/test/test_case.py +++ b/Lib/unittest/test/test_case.py @@ -14,7 +14,7 @@ import unittest -from .support import ( +from unittest.test.support import ( TestEquality, TestHashing, LoggingResult, LegacyLoggingResult, ResultWithNoStartTestRunStopTestRun ) diff --git a/Lib/unittest/test/test_discovery.py b/Lib/unittest/test/test_discovery.py --- a/Lib/unittest/test/test_discovery.py +++ b/Lib/unittest/test/test_discovery.py @@ -6,6 +6,7 @@ from test import support import unittest +import unittest.test class TestableTestProgram(unittest.TestProgram): diff --git a/Lib/unittest/test/test_functiontestcase.py b/Lib/unittest/test/test_functiontestcase.py --- a/Lib/unittest/test/test_functiontestcase.py +++ b/Lib/unittest/test/test_functiontestcase.py @@ -1,6 +1,6 @@ import unittest -from .support import LoggingResult +from unittest.test.support import LoggingResult class Test_FunctionTestCase(unittest.TestCase): diff --git a/Lib/unittest/test/test_program.py b/Lib/unittest/test/test_program.py --- a/Lib/unittest/test/test_program.py +++ b/Lib/unittest/test/test_program.py @@ -4,6 +4,7 @@ import sys from test import support import unittest +import unittest.test class Test_TestProgram(unittest.TestCase): diff --git a/Lib/unittest/test/test_runner.py b/Lib/unittest/test/test_runner.py --- a/Lib/unittest/test/test_runner.py +++ b/Lib/unittest/test/test_runner.py @@ -7,7 +7,8 @@ import unittest from unittest.case import _Outcome -from .support import LoggingResult, ResultWithNoStartTestRunStopTestRun +from unittest.test.support import (LoggingResult, + ResultWithNoStartTestRunStopTestRun) class TestCleanUp(unittest.TestCase): diff --git a/Lib/unittest/test/test_skipping.py b/Lib/unittest/test/test_skipping.py --- a/Lib/unittest/test/test_skipping.py +++ b/Lib/unittest/test/test_skipping.py @@ -1,6 +1,6 @@ import unittest -from .support import LoggingResult +from unittest.test.support import LoggingResult class Test_TestSkipping(unittest.TestCase): diff --git a/Lib/unittest/test/test_suite.py b/Lib/unittest/test/test_suite.py --- a/Lib/unittest/test/test_suite.py +++ b/Lib/unittest/test/test_suite.py @@ -3,7 +3,7 @@ import gc import sys import weakref -from .support import LoggingResult, TestEquality +from unittest.test.support import LoggingResult, TestEquality ### Support code for Test_TestSuite -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Aug 7 02:29:56 2014 From: python-checkins at python.org (ezio.melotti) Date: Thu, 7 Aug 2014 02:29:56 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?b?KTogIzIyMDkyOiBtZXJnZSB3aXRoIDMuNC4=?= Message-ID: <3hT9ZX27N9z7Lkf@mail.python.org> http://hg.python.org/cpython/rev/09f56fdcacf1 changeset: 92029:09f56fdcacf1 parent: 92027:87f940e85cb0 parent: 92028:668f6938fb1c user: Ezio Melotti date: Thu Aug 07 03:28:26 2014 +0300 summary: #22092: merge with 3.4. files: Lib/unittest/test/test_case.py | 2 +- Lib/unittest/test/test_discovery.py | 1 + Lib/unittest/test/test_functiontestcase.py | 2 +- Lib/unittest/test/test_program.py | 1 + Lib/unittest/test/test_runner.py | 3 ++- Lib/unittest/test/test_skipping.py | 2 +- Lib/unittest/test/test_suite.py | 2 +- 7 files changed, 8 insertions(+), 5 deletions(-) diff --git a/Lib/unittest/test/test_case.py b/Lib/unittest/test/test_case.py --- a/Lib/unittest/test/test_case.py +++ b/Lib/unittest/test/test_case.py @@ -14,7 +14,7 @@ import unittest -from .support import ( +from unittest.test.support import ( TestEquality, TestHashing, LoggingResult, LegacyLoggingResult, ResultWithNoStartTestRunStopTestRun ) diff --git a/Lib/unittest/test/test_discovery.py b/Lib/unittest/test/test_discovery.py --- a/Lib/unittest/test/test_discovery.py +++ b/Lib/unittest/test/test_discovery.py @@ -6,6 +6,7 @@ from test import support import unittest +import unittest.test class TestableTestProgram(unittest.TestProgram): diff --git a/Lib/unittest/test/test_functiontestcase.py b/Lib/unittest/test/test_functiontestcase.py --- a/Lib/unittest/test/test_functiontestcase.py +++ b/Lib/unittest/test/test_functiontestcase.py @@ -1,6 +1,6 @@ import unittest -from .support import LoggingResult +from unittest.test.support import LoggingResult class Test_FunctionTestCase(unittest.TestCase): diff --git a/Lib/unittest/test/test_program.py b/Lib/unittest/test/test_program.py --- a/Lib/unittest/test/test_program.py +++ b/Lib/unittest/test/test_program.py @@ -4,6 +4,7 @@ import sys from test import support import unittest +import unittest.test class Test_TestProgram(unittest.TestCase): diff --git a/Lib/unittest/test/test_runner.py b/Lib/unittest/test/test_runner.py --- a/Lib/unittest/test/test_runner.py +++ b/Lib/unittest/test/test_runner.py @@ -7,7 +7,8 @@ import unittest from unittest.case import _Outcome -from .support import LoggingResult, ResultWithNoStartTestRunStopTestRun +from unittest.test.support import (LoggingResult, + ResultWithNoStartTestRunStopTestRun) class TestCleanUp(unittest.TestCase): diff --git a/Lib/unittest/test/test_skipping.py b/Lib/unittest/test/test_skipping.py --- a/Lib/unittest/test/test_skipping.py +++ b/Lib/unittest/test/test_skipping.py @@ -1,6 +1,6 @@ import unittest -from .support import LoggingResult +from unittest.test.support import LoggingResult class Test_TestSkipping(unittest.TestCase): diff --git a/Lib/unittest/test/test_suite.py b/Lib/unittest/test/test_suite.py --- a/Lib/unittest/test/test_suite.py +++ b/Lib/unittest/test/test_suite.py @@ -3,7 +3,7 @@ import gc import sys import weakref -from .support import LoggingResult, TestEquality +from unittest.test.support import LoggingResult, TestEquality ### Support code for Test_TestSuite -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Aug 7 02:29:57 2014 From: python-checkins at python.org (ezio.melotti) Date: Thu, 7 Aug 2014 02:29:57 +0200 (CEST) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogIzIyMDkyOiB1c2Ug?= =?utf-8?q?absolute_imports_in_unittest_tests=2E__Patch_by_Vajrasky_Kok=2E?= Message-ID: <3hT9ZY3tmZz7LlS@mail.python.org> http://hg.python.org/cpython/rev/6e5a2ac30c7e changeset: 92030:6e5a2ac30c7e branch: 2.7 parent: 92024:217485e80a32 user: Ezio Melotti date: Thu Aug 07 03:20:22 2014 +0300 summary: #22092: use absolute imports in unittest tests. Patch by Vajrasky Kok. files: Lib/unittest/test/test_case.py | 2 +- Lib/unittest/test/test_discovery.py | 1 + Lib/unittest/test/test_functiontestcase.py | 2 +- Lib/unittest/test/test_program.py | 1 + Lib/unittest/test/test_runner.py | 3 ++- Lib/unittest/test/test_skipping.py | 2 +- Lib/unittest/test/test_suite.py | 2 +- 7 files changed, 8 insertions(+), 5 deletions(-) diff --git a/Lib/unittest/test/test_case.py b/Lib/unittest/test/test_case.py --- a/Lib/unittest/test/test_case.py +++ b/Lib/unittest/test/test_case.py @@ -9,7 +9,7 @@ import unittest -from .support import ( +from unittest.test.support import ( TestEquality, TestHashing, LoggingResult, ResultWithNoStartTestRunStopTestRun ) diff --git a/Lib/unittest/test/test_discovery.py b/Lib/unittest/test/test_discovery.py --- a/Lib/unittest/test/test_discovery.py +++ b/Lib/unittest/test/test_discovery.py @@ -3,6 +3,7 @@ import sys import unittest +import unittest.test class TestDiscovery(unittest.TestCase): diff --git a/Lib/unittest/test/test_functiontestcase.py b/Lib/unittest/test/test_functiontestcase.py --- a/Lib/unittest/test/test_functiontestcase.py +++ b/Lib/unittest/test/test_functiontestcase.py @@ -1,6 +1,6 @@ import unittest -from .support import LoggingResult +from unittest.test.support import LoggingResult class Test_FunctionTestCase(unittest.TestCase): diff --git a/Lib/unittest/test/test_program.py b/Lib/unittest/test/test_program.py --- a/Lib/unittest/test/test_program.py +++ b/Lib/unittest/test/test_program.py @@ -3,6 +3,7 @@ import os import sys import unittest +import unittest.test class Test_TestProgram(unittest.TestCase): diff --git a/Lib/unittest/test/test_runner.py b/Lib/unittest/test/test_runner.py --- a/Lib/unittest/test/test_runner.py +++ b/Lib/unittest/test/test_runner.py @@ -3,7 +3,8 @@ from cStringIO import StringIO import pickle -from .support import LoggingResult, ResultWithNoStartTestRunStopTestRun +from unittest.test.support import (LoggingResult, + ResultWithNoStartTestRunStopTestRun) class TestCleanUp(unittest.TestCase): diff --git a/Lib/unittest/test/test_skipping.py b/Lib/unittest/test/test_skipping.py --- a/Lib/unittest/test/test_skipping.py +++ b/Lib/unittest/test/test_skipping.py @@ -1,6 +1,6 @@ import unittest -from .support import LoggingResult +from unittest.test.support import LoggingResult class Test_TestSkipping(unittest.TestCase): diff --git a/Lib/unittest/test/test_suite.py b/Lib/unittest/test/test_suite.py --- a/Lib/unittest/test/test_suite.py +++ b/Lib/unittest/test/test_suite.py @@ -1,7 +1,7 @@ import unittest import sys -from .support import LoggingResult, TestEquality +from unittest.test.support import LoggingResult, TestEquality ### Support code for Test_TestSuite -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Aug 7 06:21:44 2014 From: python-checkins at python.org (zach.ware) Date: Thu, 7 Aug 2014 06:21:44 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Update_prepare=5Fssl=2Epy_?= =?utf-8?q?script_to_generate_the_=2Easm_files=2E?= Message-ID: <3hTGk05r19z7Ljb@mail.python.org> http://hg.python.org/cpython/rev/5e1f07b09dd7 changeset: 92031:5e1f07b09dd7 parent: 92029:09f56fdcacf1 user: Zachary Ware date: Wed Aug 06 22:47:23 2014 -0500 summary: Update prepare_ssl.py script to generate the .asm files. files: PCbuild/prepare_ssl.py | 39 +++++++++++++++++++++++------ 1 files changed, 31 insertions(+), 8 deletions(-) diff --git a/PCbuild/prepare_ssl.py b/PCbuild/prepare_ssl.py --- a/PCbuild/prepare_ssl.py +++ b/PCbuild/prepare_ssl.py @@ -81,6 +81,35 @@ fout.write(line) os.unlink(m32) +def create_asms(makefile): + #create a custom makefile out of the provided one + asm_makefile = os.path.splitext(makefile)[0] + '.asm.mak' + with open(makefile) as fin: + with open(asm_makefile, 'w') as fout: + for line in fin: + # Keep everything up to the install target (it's convenient) + if line.startswith('install: all'): + break + else: + fout.write(line) + asms = [] + for line in fin: + if '.asm' in line and line.strip().endswith('.pl'): + asms.append(line.split(':')[0]) + while line.strip(): + fout.write(line) + line = next(fin) + fout.write('\n') + + fout.write('asms: $(TMP_D) ') + fout.write(' '.join(asms)) + fout.write('\n') + + os.system('nmake /f {} PERL=perl asms'.format(asm_makefile)) + os.unlink(asm_makefile) + + + def fix_makefile(makefile): """Fix some stuff in all makefiles """ @@ -164,14 +193,8 @@ else: print(makefile, 'already exists!') - # If the assembler files don't exist in tmpXX, copy them there - if os.path.exists("asm"+dirsuffix): - if not os.path.exists("tmp"+dirsuffix): - os.mkdir("tmp"+dirsuffix) - for f in os.listdir("asm"+dirsuffix): - if not f.endswith(".asm"): continue - if os.path.isfile(r"tmp%s\%s" % (dirsuffix, f)): continue - shutil.copy(r"asm%s\%s" % (dirsuffix, f), "tmp"+dirsuffix) + print('creating asms...') + create_asms(makefile) def main(): if len(sys.argv) == 1: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Aug 7 06:21:46 2014 From: python-checkins at python.org (zach.ware) Date: Thu, 7 Aug 2014 06:21:46 +0200 (CEST) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzIyMTYw?= =?utf-8?q?=3A_Update_OpenSSL_to_1=2E0=2E1i_for_the_Windows_build=2E?= Message-ID: <3hTGk209jqz7LjV@mail.python.org> http://hg.python.org/cpython/rev/cbcb10123451 changeset: 92032:cbcb10123451 branch: 2.7 parent: 92030:6e5a2ac30c7e user: Zachary Ware date: Wed Aug 06 23:17:20 2014 -0500 summary: Issue #22160: Update OpenSSL to 1.0.1i for the Windows build. files: Misc/NEWS | 5 +++++ PCbuild/pyproject.vsprops | 2 +- Tools/buildbot/external-common.bat | 5 +++-- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -89,6 +89,11 @@ - Issue #15759: "make suspicious", "make linkcheck" and "make doctest" in Doc/ now display special message when and only when there are failures. +Windows +------- + +- Issue #22160: The bundled version of OpenSSL has been updated to 1.0.1i. + What's New in Python 2.7.8? =========================== diff --git a/PCbuild/pyproject.vsprops b/PCbuild/pyproject.vsprops --- a/PCbuild/pyproject.vsprops +++ b/PCbuild/pyproject.vsprops @@ -82,7 +82,7 @@ /> http://hg.python.org/cpython/rev/8219664dd2e4 changeset: 92033:8219664dd2e4 branch: 3.4 parent: 92028:668f6938fb1c user: Zachary Ware date: Wed Aug 06 23:19:29 2014 -0500 summary: Issue #22160: Update OpenSSL to 1.0.1i for the Windows build. files: Misc/NEWS | 4 ++-- PCbuild/pyproject.props | 2 +- Tools/buildbot/external-common.bat | 8 ++++---- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -283,8 +283,8 @@ Windows ------- -- Issue #21671, CVE-2014-0224: The bundled version of OpenSSL has been - updated to 1.0.1h. +- Issue #21671, #22160, CVE-2014-0224: The bundled version of OpenSSL has been + updated to 1.0.1i. - Issue #10747: Use versioned labels in the Windows start menu. Patch by Olive Kilburn. 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.1h + $(externalsDir)\openssl-1.0.1i $(externalsDir)\tcltk $(externalsDir)\tcltk64 $(tcltkDir)\lib\tcl86t.lib;$(tcltkDir)\lib\tk86t.lib 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 @@ -11,7 +11,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.1h rd /s/q openssl-1.0.1h + at rem if exist openssl-1.0.1i rd /s/q openssl-1.0.1i @rem if exist sqlite-3.7.12 rd /s/q sqlite-3.7.12 @rem bzip @@ -21,9 +21,9 @@ ) @rem OpenSSL -if not exist openssl-1.0.1h ( - rd /s/q openssl-1.0.1g - svn export http://svn.python.org/projects/external/openssl-1.0.1h +if not exist openssl-1.0.1i ( + rd /s/q openssl-1.0.1h + svn export http://svn.python.org/projects/external/openssl-1.0.1i ) @rem tcl/tk -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Aug 7 06:21:48 2014 From: python-checkins at python.org (zach.ware) Date: Thu, 7 Aug 2014 06:21:48 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2322160=3A_Update_O?= =?utf-8?q?penSSL_to_1=2E0=2E1i_for_the_Windows_build=2E?= Message-ID: <3hTGk43lHTz7Lky@mail.python.org> http://hg.python.org/cpython/rev/275da9f9d7d7 changeset: 92034:275da9f9d7d7 parent: 92031:5e1f07b09dd7 user: Zachary Ware date: Wed Aug 06 23:21:03 2014 -0500 summary: Issue #22160: Update OpenSSL to 1.0.1i for the Windows build. files: Misc/NEWS | 4 ++-- PCbuild/get_externals.bat | 2 +- PCbuild/pyproject.props | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -925,8 +925,8 @@ - Issue #21907: Improved the batch scripts provided for building Python. -- Issue #21671, CVE-2014-0224: The bundled version of OpenSSL has been - updated to 1.0.1h. +- Issue #21671, #22160, CVE-2014-0224: The bundled version of OpenSSL has been + updated to 1.0.1i. - Issue #10747: Use versioned labels in the Windows start menu. Patch by Olive Kilburn. diff --git a/PCbuild/get_externals.bat b/PCbuild/get_externals.bat --- a/PCbuild/get_externals.bat +++ b/PCbuild/get_externals.bat @@ -51,7 +51,7 @@ for %%e in ( bzip2-1.0.6 - openssl-1.0.1h + openssl-1.0.1i tcl-8.6.1.0 tk-8.6.1.0 tix-8.4.3.4 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.1h + $(externalsDir)\openssl-1.0.1i $(externalsDir)\tcl-8.6.1.0 $(externalsDir)\tk-8.6.1.0 $(externalsDir)\tix-8.4.3.4 -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Aug 7 07:50:34 2014 From: python-checkins at python.org (benjamin.peterson) Date: Thu, 7 Aug 2014 07:50:34 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython=3A_add_matrix_multiplication_?= =?utf-8?q?operator_to_correct_lists_=28closes_=2322142=29?= Message-ID: <3hTJhV74Fvz7Ljj@mail.python.org> http://hg.python.org/cpython/rev/0bc58b4c0562 changeset: 92035:0bc58b4c0562 user: Benjamin Peterson date: Wed Aug 06 22:50:30 2014 -0700 summary: add matrix multiplication operator to correct lists (closes #22142) files: Doc/reference/lexical_analysis.rst | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/reference/lexical_analysis.rst b/Doc/reference/lexical_analysis.rst --- a/Doc/reference/lexical_analysis.rst +++ b/Doc/reference/lexical_analysis.rst @@ -689,7 +689,7 @@ The following tokens are operators:: - + - * ** / // % + + - * ** / // % @ << >> & | ^ ~ < > <= >= == != @@ -705,7 +705,7 @@ ( ) [ ] { } , : . ; @ = -> - += -= *= /= //= %= + += -= *= /= //= %= @= &= |= ^= >>= <<= **= The period can also occur in floating-point and imaginary literals. A sequence -- Repository URL: http://hg.python.org/cpython From solipsis at pitrou.net Thu Aug 7 10:27:50 2014 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Thu, 07 Aug 2014 10:27:50 +0200 Subject: [Python-checkins] Daily reference leaks (09f56fdcacf1): sum=21004 Message-ID: results for 09f56fdcacf1 on branch "default" -------------------------------------------- test_codecs leaked [5825, 5825, 5825] references, sum=17475 test_codecs leaked [1172, 1174, 1174] memory blocks, sum=3520 test_collections leaked [0, 2, 0] references, sum=2 test_functools leaked [0, 0, 3] memory blocks, sum=3 test_site leaked [0, 2, 0] references, sum=2 test_site leaked [0, 2, 0] memory blocks, sum=2 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/cpython/refleaks/reflogdA4OO6', '-x'] From bcannon at gmail.com Thu Aug 7 16:04:04 2014 From: bcannon at gmail.com (Brett Cannon) Date: Thu, 07 Aug 2014 14:04:04 +0000 Subject: [Python-checkins] Daily reference leaks (09f56fdcacf1): sum=21004 References: Message-ID: test_codecs is not happy. Looking at the subject lines of commit emails from the past day I don't see any obvious cause. On Thu Aug 07 2014 at 4:35:05 AM wrote: > results for 09f56fdcacf1 on branch "default" > -------------------------------------------- > > test_codecs leaked [5825, 5825, 5825] references, sum=17475 > test_codecs leaked [1172, 1174, 1174] memory blocks, sum=3520 > test_collections leaked [0, 2, 0] references, sum=2 > test_functools leaked [0, 0, 3] memory blocks, sum=3 > test_site leaked [0, 2, 0] references, sum=2 > test_site leaked [0, 2, 0] memory blocks, sum=2 > > > Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', > '3:3:/home/antoine/cpython/refleaks/reflogdA4OO6', '-x'] > _______________________________________________ > 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 Thu Aug 7 18:11:31 2014 From: python-checkins at python.org (zach.ware) Date: Thu, 7 Aug 2014 18:11:31 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Null_merge_with_3=2E4?= Message-ID: <3hTZSz3cxdz7LjX@mail.python.org> http://hg.python.org/cpython/rev/3b1c44248635 changeset: 92036:3b1c44248635 parent: 92035:0bc58b4c0562 parent: 92033:8219664dd2e4 user: Zachary Ware date: Thu Aug 07 11:11:11 2014 -0500 summary: Null merge with 3.4 files: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Aug 7 18:40:02 2014 From: python-checkins at python.org (serhiy.storchaka) Date: Thu, 7 Aug 2014 18:40:02 +0200 (CEST) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzIwMDU2?= =?utf-8?q?=3A_Fixed_deprecation_warning_about_bytes_path_in_test=5Fshutil?= =?utf-8?q?_on?= Message-ID: <3hTb5t2KKqz7Ljf@mail.python.org> http://hg.python.org/cpython/rev/e306cf07046a changeset: 92037:e306cf07046a branch: 3.4 parent: 92033:8219664dd2e4 user: Serhiy Storchaka date: Thu Aug 07 19:38:37 2014 +0300 summary: Issue #20056: Fixed deprecation warning about bytes path in test_shutil on Windows. Path by Vajrasky Kok. files: Lib/test/test_shutil.py | 5 ++++- 1 files changed, 4 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_shutil.py b/Lib/test/test_shutil.py --- a/Lib/test/test_shutil.py +++ b/Lib/test/test_shutil.py @@ -10,6 +10,7 @@ import errno import functools import subprocess +from contextlib import ExitStack from test import support from test.support import TESTFN from os.path import splitdrive @@ -116,7 +117,9 @@ write_file(os.path.join(victim, 'somefile'), 'foo') victim = os.fsencode(victim) self.assertIsInstance(victim, bytes) - shutil.rmtree(victim) + win = (os.name == 'nt') + with self.assertWarns(DeprecationWarning) if win else ExitStack(): + shutil.rmtree(victim) @support.skip_unless_symlink def test_rmtree_fails_on_symlink(self): -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Aug 7 18:40:03 2014 From: python-checkins at python.org (serhiy.storchaka) Date: Thu, 7 Aug 2014 18:40:03 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2320056=3A_Fixed_deprecation_warning_about_bytes_?= =?utf-8?q?path_in_test=5Fshutil_on?= Message-ID: <3hTb5v44ptz7LjQ@mail.python.org> http://hg.python.org/cpython/rev/8480179d2a7f changeset: 92038:8480179d2a7f parent: 92036:3b1c44248635 parent: 92037:e306cf07046a user: Serhiy Storchaka date: Thu Aug 07 19:39:30 2014 +0300 summary: Issue #20056: Fixed deprecation warning about bytes path in test_shutil on Windows. Path by Vajrasky Kok. files: Lib/test/test_shutil.py | 5 ++++- 1 files changed, 4 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_shutil.py b/Lib/test/test_shutil.py --- a/Lib/test/test_shutil.py +++ b/Lib/test/test_shutil.py @@ -10,6 +10,7 @@ import errno import functools import subprocess +from contextlib import ExitStack from test import support from test.support import TESTFN from os.path import splitdrive @@ -122,7 +123,9 @@ write_file(os.path.join(victim, 'somefile'), 'foo') victim = os.fsencode(victim) self.assertIsInstance(victim, bytes) - shutil.rmtree(victim) + win = (os.name == 'nt') + with self.assertWarns(DeprecationWarning) if win else ExitStack(): + shutil.rmtree(victim) @support.skip_unless_symlink def test_rmtree_fails_on_symlink(self): -- Repository URL: http://hg.python.org/cpython From zachary.ware+pydev at gmail.com Thu Aug 7 19:16:03 2014 From: zachary.ware+pydev at gmail.com (Zachary Ware) Date: Thu, 7 Aug 2014 12:16:03 -0500 Subject: [Python-checkins] Daily reference leaks (09f56fdcacf1): sum=21004 In-Reply-To: References: Message-ID: On Thu, Aug 7, 2014 at 9:04 AM, Brett Cannon wrote: > test_codecs is not happy. Looking at the subject lines of commit emails from > the past day I don't see any obvious cause. Looks like this was caused by the change I made to regrtest in [1] to fix refleak testing in test_asyncio [2]. I'm looking into it, but haven't found any kind of reason for it yet. -- Zach [1] http://hg.python.org/cpython/rev/7bc53cf8b2df [2] http://bugs.python.org/issue22104 From zachary.ware+pydev at gmail.com Thu Aug 7 22:51:24 2014 From: zachary.ware+pydev at gmail.com (Zachary Ware) Date: Thu, 7 Aug 2014 15:51:24 -0500 Subject: [Python-checkins] Daily reference leaks (09f56fdcacf1): sum=21004 In-Reply-To: References: Message-ID: On Thu, Aug 7, 2014 at 12:16 PM, Zachary Ware wrote: > On Thu, Aug 7, 2014 at 9:04 AM, Brett Cannon wrote: >> test_codecs is not happy. Looking at the subject lines of commit emails from >> the past day I don't see any obvious cause. > > Looks like this was caused by the change I made to regrtest in [1] to > fix refleak testing in test_asyncio [2]. I'm looking into it, but > haven't found any kind of reason for it yet. I've created http://bugs.python.org/issue22166 to keep track of this and report my findings thus far. -- Zach From solipsis at pitrou.net Fri Aug 8 10:31:00 2014 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Fri, 08 Aug 2014 10:31:00 +0200 Subject: [Python-checkins] Daily reference leaks (8480179d2a7f): sum=20994 Message-ID: results for 8480179d2a7f on branch "default" -------------------------------------------- test_codecs leaked [5825, 5825, 5825] references, sum=17475 test_codecs leaked [1172, 1174, 1174] memory blocks, sum=3520 test_functools leaked [0, 0, 3] memory blocks, sum=3 test_site leaked [-2, 2, -2] references, sum=-2 test_site leaked [-2, 2, -2] memory blocks, sum=-2 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/cpython/refleaks/reflogNGe6KA', '-x'] From python-checkins at python.org Fri Aug 8 12:59:07 2014 From: python-checkins at python.org (nick.coghlan) Date: Fri, 8 Aug 2014 12:59:07 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?peps=3A_Update_PEP_440_based_on_pip_p?= =?utf-8?q?roof_of_concept?= Message-ID: <3hV3V30ZWPz7LjM@mail.python.org> http://hg.python.org/peps/rev/257822378672 changeset: 5514:257822378672 user: Nick Coghlan date: Fri Aug 08 20:58:55 2014 +1000 summary: Update PEP 440 based on pip proof of concept files: pep-0440.txt | 195 ++++++++++++++++++++++++-------------- 1 files changed, 121 insertions(+), 74 deletions(-) diff --git a/pep-0440.txt b/pep-0440.txt --- a/pep-0440.txt +++ b/pep-0440.txt @@ -11,7 +11,7 @@ Content-Type: text/x-rst Created: 18 Mar 2013 Post-History: 30 Mar 2013, 27 May 2013, 20 Jun 2013, - 21 Dec 2013, 28 Jan 2014 + 21 Dec 2013, 28 Jan 2014, 08 Aug 2014 Replaces: 386 @@ -24,13 +24,6 @@ This document addresses several limitations of the previous attempt at a standardized approach to versioning, as described in PEP 345 and PEP 386. -.. note:: - - This PEP was broken out of the metadata 2.0 specification in PEP 426. - - Unlike PEP 426, the notes that remain in this document are intended as - part of the final specification (except for this one). - Definitions =========== @@ -409,20 +402,22 @@ Pre-release separators ~~~~~~~~~~~~~~~~~~~~~~ -Pre-releases should allow either a ``.`` or a ``-`` separator between the +Pre-releases should allow a ``.``, ``-``, or ``_`` separator between the release segment and the pre-release segment. The normal form for this is without a separator. This allows versions such as ``1.1.a1`` or ``1.1-a1`` -which would be normalized to ``1.1a1``. +which would be normalized to ``1.1a1``. It should also allow a seperator to +be used between the pre-release signifier and the numeral. This allows versions +such as ``1.0a.1`` which would be normalized to ``1.0a1``. Pre-release spelling ~~~~~~~~~~~~~~~~~~~~ -Pre-releases allow the additional spellings of alpha, beta, and rc for a, b, -and c respectively. This allows versions such as ``1.1alpha1``, ``1.1beta2``, -or ``1.1rc3`` which normalize to ``1.1a1``, ``1.1b2``, and ``1.1c3``. In every -case the additional spelling should be considered equivalent to their normal -forms. +Pre-releases allow the additional spellings of ``alpha``, ``beta``, ``rc``, +``pre``, and ``preview`` for ``a``, ``b``, ``c``, ``c``, and ``c`` respectively. +This allows versions such as ``1.1alpha1``, ``1.1beta2``, or ``1.1rc3`` which +normalize to ``1.1a1``, ``1.1b2``, and ``1.1c3``. In every case the additional +spelling should be considered equivalent to their normal forms. Implicit pre-release number @@ -436,10 +431,21 @@ Post release separators ~~~~~~~~~~~~~~~~~~~~~~~ -Post releases allow either a ``.`` or a ``-`` separator as well as omitting the +Post releases allow a ``.``,``-``, or ``_`` separator as well as omitting the separator all together. The normal form of this is with the ``.`` separator. This allows versions such as ``1.2-post2`` or ``1.2post2`` which normalize to -``1.2.post2``. +``1.2.post2``. Like the pre-release seperator this also allows an optional +separator between the post release signifier and the numeral. This allows +versions like ``1.2.post-2`` which would normalize to ``1.2.post2``. + + +Post release spelling +~~~~~~~~~~~~~~~~~~~~~ + +Post-releases allow the additional spellings of ``rev`` and ``r``. This allows +versions such as ``1.0-r4`` which normalizes to ``1.0.post4``. As with the +pre-releases the additional spellings should be considered equivalent to their +normal forms. Implicit post release number @@ -450,10 +456,21 @@ allows versions such as ``1.2.post`` which is normalized to ``1.2.post0``. +Implicit post releases +~~~~~~~~~~~~~~~~~~~~~~ + +Post releases allow omitting the ``post`` signifier all together. When using +this form the separator MUST be ``-`` and no other form is allowed. This allows +versions such as ``1.0-1`` to be normalized to ``1.0.post1``. This particular +normalization MUST NOT be used in conjunction with the implicit post release +number rule. In other words ``1.0-`` is *not* a valid version and it does *not* +normalize to ``1.0.post0``. + + Development release separators ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Development releases allow either a ``.`` or a ``-`` separator as well as +Development releases allow a ``.``, ``-``, or a ``_`` separator as well as omitting the separator all together. The normal form of this is with the ``.`` separator. This allows versions such as ``1.2-dev2`` or ``1.2dev2`` which normalize to ``1.2.dev2``. @@ -468,6 +485,33 @@ ``1.2.dev0``. +Local version segments +~~~~~~~~~~~~~~~~~~~~~~ + +With a local version, in addition to the use of ``.`` as a separator of +segments, the use of ``-`` and ``_`` is also acceptable. The normal form is +using the ``.`` character. This allows versions such as ``1.0+ubuntu-1`` to be +normalized to ``1.0+ubuntu.1``. + + +Preceding v character +~~~~~~~~~~~~~~~~~~~~~ + +In order to support the common version notation of ``v1.0`` versions may be +preceded by a single literal ``v`` character. This character MUST be ignored +for all purposes and should be omitted from all normalized forms of the +version. The same version with and without the ``v`` is considered equivalent. + + +Leading and Trailing Whitespace +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Leading and trailing whitespace must be silently ignored and removed from all +normalized forms of a version. This includes ``" "``, ``\t``, ``\n``, ``\r``, +``\f``, and ``\v``. This allows accidental whitespace to be handled sensibly, +such as a version like ``1.0\n`` which normalizes to ``1.0``. + + Examples of compliant version schemes ------------------------------------- @@ -1098,10 +1142,6 @@ * Moved the description of version specifiers into the versioning PEP -* Added the "source label" concept to better handle projects that wish to - use a non-compliant versioning scheme internally, especially those based - on DVCS hashes - * Added the "direct reference" concept as a standard notation for direct references to resources (rather than each tool needing to invent its own) @@ -1123,6 +1163,10 @@ * Explicit support for date based versions +* Explicit normalisation rules to improve compatibility with + existing version metadata on PyPI where it doesn't introduce + ambiguity + * Implicitly exclude pre-releases unless they're already present or needed to satisfy a dependency @@ -1133,11 +1177,10 @@ The rationale for major changes is given in the following sections. - Changing the version scheme --------------------------- -The key change in the version scheme in this PEP relative to that in +One key change in the version scheme in this PEP relative to that in PEP 386 is to sort top level developmental releases like ``X.Y.devN`` ahead of alpha releases like ``X.Ya1``. This is a far more logical sort order, as projects already using both development releases and alphas/betas/release @@ -1165,51 +1208,17 @@ a couple of projects with version identifiers differing only in a trailing ``\n`` character were found on PyPI. +Various other normalisation rules were also added as described in the +separate section on version normalisation below. + `Appendix A` shows detailed results of an analysis of PyPI distribution -version information, as collected on 19th February, 2013. This analysis -compares the behavior of the explicitly ordered version schemes defined in -this PEP and PEP 386 with the de facto standard defined by the behavior -of setuptools. These metrics are useful, as the intent of both PEPs is to -follow existing setuptools behavior as closely as is feasible, while -still throwing exceptions for unorderable versions (rather than trying -to guess an appropriate order as setuptools does). - -Overall, the percentage of compatible distributions improves from 97.7% -with PEP 386 to 98.7% with this PEP. While the number of projects affected -in practice was small, some of the affected projects are in widespread use -(such as Pinax and selenium). The surprising ordering discrepancy also -concerned developers and acted as an unnecessary barrier to adoption of -the new metadata standard, even for projects that weren't directly affected. - -The data also shows that the pre-release sorting discrepancies are seen -only when analyzing *all* versions from PyPI, rather than when analyzing -public versions. This is largely due to the fact that PyPI normally reports -only the most recent version for each project (unless maintainers -explicitly configure their project to display additional versions). However, -installers that need to satisfy detailed version constraints often need -to look at all available versions, as they may need to retrieve an older -release. - -Even this PEP doesn't completely eliminate the sorting differences relative -to setuptools: - -* Sorts differently (after translations): 38 / 28194 (0.13 %) -* Sorts differently (no translations): 2 / 28194 (0.01 %) - -The two remaining sort order discrepancies picked up by the analysis are due -to a pair of projects which have PyPI releases ending with a carriage -return, alongside releases with the same version number, only *without* the -trailing carriage return. - -The sorting discrepancies after translation relate mainly to differences -in the handling of pre-releases where the standard mechanism is considered -to be an improvement. For example, the existing pkg_resources scheme will -sort "1.1beta1" *after* "1.1b2", whereas the suggested standard translation -for "1.1beta1" is "1.1b1", which sorts *before* "1.1b2". Similarly, the -pkg_resources scheme will sort "-dev-N" pre-releases differently from -"devN" pre-releases when they occur within the same release, while the -scheme in this PEP requires normalizing both representations to ".devN" and -sorting them by the numeric component. +version information, as collected on 8th August, 2014. This analysis +compares the behavior of the explicitly ordered version scheme defined in +this PEP with the de facto standard defined by the behavior of setuptools. +These metrics are useful, as the intent of this PEP is to follow existing +setuptools behavior as closely as is feasible, while still throwing +exceptions for unorderable versions (rather than trying to guess an +appropriate order as setuptools does). A more opinionated description of the versioning scheme @@ -1381,7 +1390,42 @@ ``pkg_resources.parse_version`` from parsing it as a prerelease, which is important for enabling a successful migration to the new, more structured, versioning scheme. The plus was chosen instead of a tilde because of the -significance of the tilde in Debian's version algorithm. +significance of the tilde in Debian's version ordering algorithm. + + +Providing explicit version normalization rules +---------------------------------------------- + +Historically, the de facto standard for parsing versions in Python has been the +``pkg_resources.parse_version`` command from the setuptools project. This does +not attempt to reject *any* version and instead tries to make something +meaningful, with varying levels of success, out of whatever it is given. It has +a few simple rules but otherwise it more or less relies largely on string +comparison. + +The normalization rules provided in this PEP exist primarily to either increase +the compatability with ``pkg_resources.parse_version``, particularly in +documented use cases such as ``rev``, ``r``, ``pre``, etc or to do something +more reasonable with versions that already exist on PyPI. + +All possible normalization rules were weighed against whether or not they were +*likely* to cause any ambiguity (e.g. while someone might devise a scheme where +``v1.0`` and ``1.0`` are considered distinct releases, the likelihood of anyone +actually doing that, much less on any scale that is noticeable, is fairly low). +They were also weighed against how ``pkg_resources.parse_version`` treated a +particular version string, especially with regards to how it was sorted. Finally +each rule was weighed against the kinds of additional versions it allowed, how +"ugly" those versions looked, how hard there were to parse (both mentally and +mechanically) and how much additional compatibility it would bring. + +The breadth of possible normalizations were kept to things that could easily +be implemented as part of the parsing of the version and not pre-parsing +transformations applied to the versions. This was done to limit the side +effects of each transformation as simple search and replace style transforms +increase the likelihood of ambiguous or "junk" versions. + +For an extended discussion on the various types of normalizations that were +considered, please see the proof of concept for PEP 440 within pip [4]_. References @@ -1399,6 +1443,9 @@ .. [3] Pessimistic version constraint http://docs.rubygems.org/read/chapter/16 +.. [4] Proof of Concept: PEP 440 within pip + https://github.com/pypa/pip/pull/1894 + Appendix A ========== @@ -1406,11 +1453,11 @@ Metadata v2.0 guidelines versus setuptools:: $ invoke check.pep440 - Total Version Compatibility: 231807/239450 (96.81%) - Total Sorting Compatibility (Unfiltered): 43095/45505 (94.70%) - Total Sorting Compatibility (Filtered): 45481/45505 (99.95%) - Projects with No Compatible Versions: 802/45505 (1.76%) - Projects with Differing Latest Version: 1163/45505 (2.56%) + Total Version Compatibility: 245806/250521 (98.12%) + Total Sorting Compatibility (Unfiltered): 45441/47114 (96.45%) + Total Sorting Compatibility (Filtered): 47057/47114 (99.88%) + Projects with No Compatible Versions: 498/47114 (1.06%) + Projects with Differing Latest Version: 688/47114 (1.46%) Copyright -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Fri Aug 8 13:07:57 2014 From: python-checkins at python.org (nick.coghlan) Date: Fri, 8 Aug 2014 13:07:57 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?peps=3A_Clarify_PEP_8_point_about_pre?= =?utf-8?q?ferring_def_statements?= Message-ID: <3hV3hF0KC9z7LjQ@mail.python.org> http://hg.python.org/peps/rev/0cf5442ec2a9 changeset: 5515:0cf5442ec2a9 user: Nick Coghlan date: Fri Aug 08 21:07:46 2014 +1000 summary: Clarify PEP 8 point about preferring def statements files: pep-0008.txt | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/pep-0008.txt b/pep-0008.txt --- a/pep-0008.txt +++ b/pep-0008.txt @@ -948,7 +948,7 @@ that confusion doesn't arise in other contexts. - Always use a def statement instead of an assignment statement that binds - a lambda expression directly to a name. + a lambda expression directly to an identifier. Yes:: -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Fri Aug 8 16:24:43 2014 From: python-checkins at python.org (ezio.melotti) Date: Fri, 8 Aug 2014 16:24:43 +0200 (CEST) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogIzIyMTcwOiBhdm9p?= =?utf-8?q?d_printing_newlines_twice_in_tutorial_example=2E?= Message-ID: <3hV83H5sQtz7LjW@mail.python.org> http://hg.python.org/cpython/rev/35db84720d8d changeset: 92039:35db84720d8d branch: 3.4 parent: 92037:e306cf07046a user: Ezio Melotti date: Fri Aug 08 17:23:32 2014 +0300 summary: #22170: avoid printing newlines twice in tutorial example. files: Doc/tutorial/classes.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/tutorial/classes.rst b/Doc/tutorial/classes.rst --- a/Doc/tutorial/classes.rst +++ b/Doc/tutorial/classes.rst @@ -802,7 +802,7 @@ for char in "123": print(char) for line in open("myfile.txt"): - print(line) + print(line, end='') This style of access is clear, concise, and convenient. The use of iterators pervades and unifies Python. Behind the scenes, the :keyword:`for` statement -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Aug 8 16:24:45 2014 From: python-checkins at python.org (ezio.melotti) Date: Fri, 8 Aug 2014 16:24:45 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?b?KTogIzIyMTcwOiBtZXJnZSB3aXRoIDMuNC4=?= Message-ID: <3hV83K0PLyz7LkM@mail.python.org> http://hg.python.org/cpython/rev/79e469ae13b7 changeset: 92040:79e469ae13b7 parent: 92038:8480179d2a7f parent: 92039:35db84720d8d user: Ezio Melotti date: Fri Aug 08 17:24:06 2014 +0300 summary: #22170: merge with 3.4. files: Doc/tutorial/classes.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/tutorial/classes.rst b/Doc/tutorial/classes.rst --- a/Doc/tutorial/classes.rst +++ b/Doc/tutorial/classes.rst @@ -802,7 +802,7 @@ for char in "123": print(char) for line in open("myfile.txt"): - print(line) + print(line, end='') This style of access is clear, concise, and convenient. The use of iterators pervades and unifies Python. Behind the scenes, the :keyword:`for` statement -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Aug 8 20:35:43 2014 From: python-checkins at python.org (zach.ware) Date: Fri, 8 Aug 2014 20:35:43 +0200 (CEST) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy40KTogSXNzdWUgIzIyMDYw?= =?utf-8?q?=3A_Clean_up/simplify_test=5Fctypes=2C_use_test_discovery?= Message-ID: <3hVFcv19PMz7LjM@mail.python.org> http://hg.python.org/cpython/rev/fc99cf3615bb changeset: 92041:fc99cf3615bb branch: 3.4 parent: 92039:35db84720d8d user: Zachary Ware date: Fri Aug 08 13:32:16 2014 -0500 summary: Issue #22060: Clean up/simplify test_ctypes, use test discovery files: Lib/ctypes/test/__init__.py | 216 +---------------- Lib/ctypes/test/__main__.py | 4 + Lib/ctypes/test/runtests.py | 19 - Lib/ctypes/test/test_find.py | 72 ++-- Lib/ctypes/test/test_loading.py | 41 +- Lib/ctypes/test/test_python_api.py | 5 - Lib/ctypes/test/test_win32.py | 2 - Lib/test/test_ctypes.py | 12 +- Misc/NEWS | 3 + 9 files changed, 73 insertions(+), 301 deletions(-) diff --git a/Lib/ctypes/test/__init__.py b/Lib/ctypes/test/__init__.py --- a/Lib/ctypes/test/__init__.py +++ b/Lib/ctypes/test/__init__.py @@ -1,216 +1,14 @@ -import os, sys, unittest, getopt, time +import os +import unittest +from test import support -use_resources = [] - -import ctypes +# skip tests if _ctypes was not built +ctypes = support.import_module('ctypes') ctypes_symbols = dir(ctypes) def need_symbol(name): return unittest.skipUnless(name in ctypes_symbols, '{!r} is required'.format(name)) - -class ResourceDenied(unittest.SkipTest): - """Test skipped because it requested a disallowed resource. - - This is raised when a test calls requires() for a resource that - has not be enabled. Resources are defined by test modules. - """ - -def is_resource_enabled(resource): - """Test whether a resource is enabled. - - If the caller's module is __main__ then automatically return True.""" - if sys._getframe().f_back.f_globals.get("__name__") == "__main__": - return True - result = use_resources is not None and \ - (resource in use_resources or "*" in use_resources) - if not result: - _unavail[resource] = None - return result - -_unavail = {} -def requires(resource, msg=None): - """Raise ResourceDenied if the specified resource is not available. - - If the caller's module is __main__ then automatically return True.""" - # see if the caller's module is __main__ - if so, treat as if - # the resource was set - if sys._getframe().f_back.f_globals.get("__name__") == "__main__": - return - if not is_resource_enabled(resource): - if msg is None: - msg = "Use of the `%s' resource not enabled" % resource - raise ResourceDenied(msg) - -def find_package_modules(package, mask): - import fnmatch - if (package.__loader__ is not None and - hasattr(package.__loader__, '_files')): - path = package.__name__.replace(".", os.path.sep) - mask = os.path.join(path, mask) - for fnm in package.__loader__._files.keys(): - if fnmatch.fnmatchcase(fnm, mask): - yield os.path.splitext(fnm)[0].replace(os.path.sep, ".") - else: - path = package.__path__[0] - for fnm in os.listdir(path): - if fnmatch.fnmatchcase(fnm, mask): - yield "%s.%s" % (package.__name__, os.path.splitext(fnm)[0]) - -def get_tests(package, mask, verbosity, exclude=()): - """Return a list of skipped test modules, and a list of test cases.""" - tests = [] - skipped = [] - for modname in find_package_modules(package, mask): - if modname.split(".")[-1] in exclude: - skipped.append(modname) - if verbosity > 1: - print("Skipped %s: excluded" % modname, file=sys.stderr) - continue - try: - mod = __import__(modname, globals(), locals(), ['*']) - except (ResourceDenied, unittest.SkipTest) as detail: - skipped.append(modname) - if verbosity > 1: - print("Skipped %s: %s" % (modname, detail), file=sys.stderr) - continue - for name in dir(mod): - if name.startswith("_"): - continue - o = getattr(mod, name) - if type(o) is type(unittest.TestCase) and issubclass(o, unittest.TestCase): - tests.append(o) - return skipped, tests - -def usage(): - print(__doc__) - return 1 - -def test_with_refcounts(runner, verbosity, testcase): - """Run testcase several times, tracking reference counts.""" - import gc - import ctypes - ptc = ctypes._pointer_type_cache.copy() - cfc = ctypes._c_functype_cache.copy() - wfc = ctypes._win_functype_cache.copy() - - # when searching for refcount leaks, we have to manually reset any - # caches that ctypes has. - def cleanup(): - ctypes._pointer_type_cache = ptc.copy() - ctypes._c_functype_cache = cfc.copy() - ctypes._win_functype_cache = wfc.copy() - gc.collect() - - test = unittest.makeSuite(testcase) - for i in range(5): - rc = sys.gettotalrefcount() - runner.run(test) - cleanup() - COUNT = 5 - refcounts = [None] * COUNT - for i in range(COUNT): - rc = sys.gettotalrefcount() - runner.run(test) - cleanup() - refcounts[i] = sys.gettotalrefcount() - rc - if filter(None, refcounts): - print("%s leaks:\n\t" % testcase, refcounts) - elif verbosity: - print("%s: ok." % testcase) - -class TestRunner(unittest.TextTestRunner): - def run(self, test, skipped): - "Run the given test case or test suite." - # Same as unittest.TextTestRunner.run, except that it reports - # skipped tests. - result = self._makeResult() - startTime = time.time() - test(result) - stopTime = time.time() - timeTaken = stopTime - startTime - result.printErrors() - self.stream.writeln(result.separator2) - run = result.testsRun - if _unavail: #skipped: - requested = list(_unavail.keys()) - requested.sort() - self.stream.writeln("Ran %d test%s in %.3fs (%s module%s skipped)" % - (run, run != 1 and "s" or "", timeTaken, - len(skipped), - len(skipped) != 1 and "s" or "")) - self.stream.writeln("Unavailable resources: %s" % ", ".join(requested)) - else: - self.stream.writeln("Ran %d test%s in %.3fs" % - (run, run != 1 and "s" or "", timeTaken)) - self.stream.writeln() - if not result.wasSuccessful(): - self.stream.write("FAILED (") - failed, errored = map(len, (result.failures, result.errors)) - if failed: - self.stream.write("failures=%d" % failed) - if errored: - if failed: self.stream.write(", ") - self.stream.write("errors=%d" % errored) - self.stream.writeln(")") - else: - self.stream.writeln("OK") - return result - - -def main(*packages): - try: - opts, args = getopt.getopt(sys.argv[1:], "rqvu:x:") - except getopt.error: - return usage() - - verbosity = 1 - search_leaks = False - exclude = [] - for flag, value in opts: - if flag == "-q": - verbosity -= 1 - elif flag == "-v": - verbosity += 1 - elif flag == "-r": - try: - sys.gettotalrefcount - except AttributeError: - print("-r flag requires Python debug build", file=sys.stderr) - return -1 - search_leaks = True - elif flag == "-u": - use_resources.extend(value.split(",")) - elif flag == "-x": - exclude.extend(value.split(",")) - - mask = "test_*.py" - if args: - mask = args[0] - - for package in packages: - run_tests(package, mask, verbosity, search_leaks, exclude) - - -def run_tests(package, mask, verbosity, search_leaks, exclude): - skipped, testcases = get_tests(package, mask, verbosity, exclude) - runner = TestRunner(verbosity=verbosity) - - suites = [unittest.makeSuite(o) for o in testcases] - suite = unittest.TestSuite(suites) - result = runner.run(suite, skipped) - - if search_leaks: - # hunt for refcount leaks - runner = BasicTestRunner() - for t in testcases: - test_with_refcounts(runner, verbosity, t) - - return bool(result.errors) - -class BasicTestRunner: - def run(self, test): - result = unittest.TestResult() - test(result) - return result +def load_tests(*args): + return support.load_package_tests(os.path.dirname(__file__), *args) diff --git a/Lib/ctypes/test/__main__.py b/Lib/ctypes/test/__main__.py new file mode 100644 --- /dev/null +++ b/Lib/ctypes/test/__main__.py @@ -0,0 +1,4 @@ +from ctypes.test import load_tests +import unittest + +unittest.main() diff --git a/Lib/ctypes/test/runtests.py b/Lib/ctypes/test/runtests.py deleted file mode 100644 --- a/Lib/ctypes/test/runtests.py +++ /dev/null @@ -1,19 +0,0 @@ -"""Usage: runtests.py [-q] [-r] [-v] [-u resources] [mask] - -Run all tests found in this directory, and print a summary of the results. -Command line flags: - -q quiet mode: don't print anything while the tests are running - -r run tests repeatedly, look for refcount leaks - -u - Add resources to the lits of allowed resources. '*' allows all - resources. - -v verbose mode: print the test currently executed - -x - Exclude specified tests. - mask mask to select filenames containing testcases, wildcards allowed -""" -import sys -import ctypes.test - -if __name__ == "__main__": - sys.exit(ctypes.test.main(ctypes.test)) diff --git a/Lib/ctypes/test/test_find.py b/Lib/ctypes/test/test_find.py --- a/Lib/ctypes/test/test_find.py +++ b/Lib/ctypes/test/test_find.py @@ -1,60 +1,58 @@ import unittest import os import sys +import test.support from ctypes import * from ctypes.util import find_library -from ctypes.test import is_resource_enabled - -if sys.platform == "win32": - lib_gl = find_library("OpenGL32") - lib_glu = find_library("Glu32") - lib_gle = None -elif sys.platform == "darwin": - lib_gl = lib_glu = find_library("OpenGL") - lib_gle = None -else: - lib_gl = find_library("GL") - lib_glu = find_library("GLU") - lib_gle = find_library("gle") - -## print, for debugging -if is_resource_enabled("printing"): - if lib_gl or lib_glu or lib_gle: - print("OpenGL libraries:") - for item in (("GL", lib_gl), - ("GLU", lib_glu), - ("gle", lib_gle)): - print("\t", item) - # On some systems, loading the OpenGL libraries needs the RTLD_GLOBAL mode. class Test_OpenGL_libs(unittest.TestCase): - def setUp(self): - self.gl = self.glu = self.gle = None + @classmethod + def setUpClass(cls): + lib_gl = lib_glu = lib_gle = None + if sys.platform == "win32": + lib_gl = find_library("OpenGL32") + lib_glu = find_library("Glu32") + elif sys.platform == "darwin": + lib_gl = lib_glu = find_library("OpenGL") + else: + lib_gl = find_library("GL") + lib_glu = find_library("GLU") + lib_gle = find_library("gle") + + ## print, for debugging + if test.support.verbose: + print("OpenGL libraries:") + for item in (("GL", lib_gl), + ("GLU", lib_glu), + ("gle", lib_gle)): + print("\t", item) + + cls.gl = cls.glu = cls.gle = None if lib_gl: - self.gl = CDLL(lib_gl, mode=RTLD_GLOBAL) + cls.gl = CDLL(lib_gl, mode=RTLD_GLOBAL) if lib_glu: - self.glu = CDLL(lib_glu, RTLD_GLOBAL) + cls.glu = CDLL(lib_glu, RTLD_GLOBAL) if lib_gle: try: - self.gle = CDLL(lib_gle) + cls.gle = CDLL(lib_gle) except OSError: pass - @unittest.skipUnless(lib_gl, 'lib_gl not available') def test_gl(self): - if self.gl: - self.gl.glClearIndex + if self.gl is None: + self.skipTest('lib_gl not available') + self.gl.glClearIndex - @unittest.skipUnless(lib_glu, 'lib_glu not available') def test_glu(self): - if self.glu: - self.glu.gluBeginCurve + if self.glu is None: + self.skipTest('lib_glu not available') + self.glu.gluBeginCurve - @unittest.skipUnless(lib_gle, 'lib_gle not available') def test_gle(self): - if self.gle: - self.gle.gleGetJoinStyle + if self.gle is None: + self.skipTest('lib_gle not available') + self.gle.gleGetJoinStyle # On platforms where the default shared library suffix is '.so', # at least some libraries can be loaded as attributes of the cdll diff --git a/Lib/ctypes/test/test_loading.py b/Lib/ctypes/test/test_loading.py --- a/Lib/ctypes/test/test_loading.py +++ b/Lib/ctypes/test/test_loading.py @@ -1,37 +1,42 @@ from ctypes import * -import sys, unittest import os +import sys +import unittest +import test.support from ctypes.util import find_library -from ctypes.test import is_resource_enabled libc_name = None -if os.name == "nt": - libc_name = find_library("c") -elif os.name == "ce": - libc_name = "coredll" -elif sys.platform == "cygwin": - libc_name = "cygwin1.dll" -else: - libc_name = find_library("c") -if is_resource_enabled("printing"): - print("libc_name is", libc_name) +def setUpModule(): + global libc_name + if os.name == "nt": + libc_name = find_library("c") + elif os.name == "ce": + libc_name = "coredll" + elif sys.platform == "cygwin": + libc_name = "cygwin1.dll" + else: + libc_name = find_library("c") + + if test.support.verbose: + print("libc_name is", libc_name) class LoaderTest(unittest.TestCase): unknowndll = "xxrandomnamexx" - @unittest.skipUnless(libc_name is not None, 'could not find libc') def test_load(self): + if libc_name is None: + self.skipTest('could not find libc') CDLL(libc_name) CDLL(os.path.basename(libc_name)) self.assertRaises(OSError, CDLL, self.unknowndll) - @unittest.skipUnless(libc_name is not None, 'could not find libc') - @unittest.skipUnless(libc_name is not None and - os.path.basename(libc_name) == "libc.so.6", - 'wrong libc path for test') def test_load_version(self): + if libc_name is None: + self.skipTest('could not find libc') + if os.path.basename(libc_name) != 'libc.so.6': + self.skipTest('wrong libc path for test') cdll.LoadLibrary("libc.so.6") # linux uses version, libc 9 should not exist self.assertRaises(OSError, cdll.LoadLibrary, "libc.so.9") @@ -48,7 +53,7 @@ 'test specific to Windows (NT/CE)') def test_load_library(self): self.assertIsNotNone(libc_name) - if is_resource_enabled("printing"): + if test.support.verbose: print(find_library("kernel32")) print(find_library("user32")) diff --git a/Lib/ctypes/test/test_python_api.py b/Lib/ctypes/test/test_python_api.py --- a/Lib/ctypes/test/test_python_api.py +++ b/Lib/ctypes/test/test_python_api.py @@ -1,7 +1,6 @@ from ctypes import * import unittest, sys from test import support -from ctypes.test import requires ################################################################ # This section should be moved into ctypes\__init__.py, when it's ready. @@ -39,12 +38,8 @@ del pyob self.assertEqual(grc(s), refcnt) - # This test is unreliable, because it is possible that code in - # unittest changes the refcount of the '42' integer. So, it - # is disabled by default. @support.refcount_test def test_PyLong_Long(self): - requires("refcount") ref42 = grc(42) pythonapi.PyLong_FromLong.restype = py_object self.assertEqual(pythonapi.PyLong_FromLong(42), 42) diff --git a/Lib/ctypes/test/test_win32.py b/Lib/ctypes/test/test_win32.py --- a/Lib/ctypes/test/test_win32.py +++ b/Lib/ctypes/test/test_win32.py @@ -1,7 +1,6 @@ # Windows specific tests from ctypes import * -from ctypes.test import requires import unittest, sys from test import support @@ -42,7 +41,6 @@ @unittest.skipIf(sys.executable.endswith('_d.exe'), "SEH not enabled in debug builds") def test_SEH(self): - requires("SEH") # Call functions with invalid arguments, and make sure # that access violations are trapped and raise an # exception. diff --git a/Lib/test/test_ctypes.py b/Lib/test/test_ctypes.py --- a/Lib/test/test_ctypes.py +++ b/Lib/test/test_ctypes.py @@ -1,16 +1,6 @@ import unittest -from test.support import import_module - -# Skip tests if _ctypes module was not built. -import_module('_ctypes') - -import ctypes.test - -def load_tests(*args): - skipped, testcases = ctypes.test.get_tests(ctypes.test, "test_*.py", verbosity=0) - suites = [unittest.makeSuite(t) for t in testcases] - return unittest.TestSuite(suites) +from ctypes.test import load_tests if __name__ == "__main__": unittest.main() diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -243,6 +243,9 @@ Tests ----- +- Issue #22060: test_ctypes has been somewhat cleaned up and simplified; it + now uses unittest test discovery to find its tests. + - Issue #22104: regrtest.py no longer holds a reference to the suite of tests loaded from test modules that don't define test_main(). -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Aug 8 20:35:44 2014 From: python-checkins at python.org (zach.ware) Date: Fri, 8 Aug 2014 20:35:44 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E4_-=3E_default?= =?utf-8?q?=29=3A_Closes_=2322060=3A_Merge_with_3=2E4?= Message-ID: <3hVFcw5Ds7z7LjN@mail.python.org> http://hg.python.org/cpython/rev/748fb6d622e8 changeset: 92042:748fb6d622e8 parent: 92040:79e469ae13b7 parent: 92041:fc99cf3615bb user: Zachary Ware date: Fri Aug 08 13:35:11 2014 -0500 summary: Closes #22060: Merge with 3.4 files: Lib/ctypes/test/__init__.py | 216 +---------------- Lib/ctypes/test/__main__.py | 4 + Lib/ctypes/test/runtests.py | 19 - Lib/ctypes/test/test_find.py | 72 ++-- Lib/ctypes/test/test_loading.py | 41 +- Lib/ctypes/test/test_python_api.py | 5 - Lib/ctypes/test/test_win32.py | 2 - Lib/test/test_ctypes.py | 12 +- Misc/NEWS | 3 + 9 files changed, 73 insertions(+), 301 deletions(-) diff --git a/Lib/ctypes/test/__init__.py b/Lib/ctypes/test/__init__.py --- a/Lib/ctypes/test/__init__.py +++ b/Lib/ctypes/test/__init__.py @@ -1,216 +1,14 @@ -import os, sys, unittest, getopt, time +import os +import unittest +from test import support -use_resources = [] - -import ctypes +# skip tests if _ctypes was not built +ctypes = support.import_module('ctypes') ctypes_symbols = dir(ctypes) def need_symbol(name): return unittest.skipUnless(name in ctypes_symbols, '{!r} is required'.format(name)) - -class ResourceDenied(unittest.SkipTest): - """Test skipped because it requested a disallowed resource. - - This is raised when a test calls requires() for a resource that - has not be enabled. Resources are defined by test modules. - """ - -def is_resource_enabled(resource): - """Test whether a resource is enabled. - - If the caller's module is __main__ then automatically return True.""" - if sys._getframe().f_back.f_globals.get("__name__") == "__main__": - return True - result = use_resources is not None and \ - (resource in use_resources or "*" in use_resources) - if not result: - _unavail[resource] = None - return result - -_unavail = {} -def requires(resource, msg=None): - """Raise ResourceDenied if the specified resource is not available. - - If the caller's module is __main__ then automatically return True.""" - # see if the caller's module is __main__ - if so, treat as if - # the resource was set - if sys._getframe().f_back.f_globals.get("__name__") == "__main__": - return - if not is_resource_enabled(resource): - if msg is None: - msg = "Use of the `%s' resource not enabled" % resource - raise ResourceDenied(msg) - -def find_package_modules(package, mask): - import fnmatch - if (package.__loader__ is not None and - hasattr(package.__loader__, '_files')): - path = package.__name__.replace(".", os.path.sep) - mask = os.path.join(path, mask) - for fnm in package.__loader__._files.keys(): - if fnmatch.fnmatchcase(fnm, mask): - yield os.path.splitext(fnm)[0].replace(os.path.sep, ".") - else: - path = package.__path__[0] - for fnm in os.listdir(path): - if fnmatch.fnmatchcase(fnm, mask): - yield "%s.%s" % (package.__name__, os.path.splitext(fnm)[0]) - -def get_tests(package, mask, verbosity, exclude=()): - """Return a list of skipped test modules, and a list of test cases.""" - tests = [] - skipped = [] - for modname in find_package_modules(package, mask): - if modname.split(".")[-1] in exclude: - skipped.append(modname) - if verbosity > 1: - print("Skipped %s: excluded" % modname, file=sys.stderr) - continue - try: - mod = __import__(modname, globals(), locals(), ['*']) - except (ResourceDenied, unittest.SkipTest) as detail: - skipped.append(modname) - if verbosity > 1: - print("Skipped %s: %s" % (modname, detail), file=sys.stderr) - continue - for name in dir(mod): - if name.startswith("_"): - continue - o = getattr(mod, name) - if type(o) is type(unittest.TestCase) and issubclass(o, unittest.TestCase): - tests.append(o) - return skipped, tests - -def usage(): - print(__doc__) - return 1 - -def test_with_refcounts(runner, verbosity, testcase): - """Run testcase several times, tracking reference counts.""" - import gc - import ctypes - ptc = ctypes._pointer_type_cache.copy() - cfc = ctypes._c_functype_cache.copy() - wfc = ctypes._win_functype_cache.copy() - - # when searching for refcount leaks, we have to manually reset any - # caches that ctypes has. - def cleanup(): - ctypes._pointer_type_cache = ptc.copy() - ctypes._c_functype_cache = cfc.copy() - ctypes._win_functype_cache = wfc.copy() - gc.collect() - - test = unittest.makeSuite(testcase) - for i in range(5): - rc = sys.gettotalrefcount() - runner.run(test) - cleanup() - COUNT = 5 - refcounts = [None] * COUNT - for i in range(COUNT): - rc = sys.gettotalrefcount() - runner.run(test) - cleanup() - refcounts[i] = sys.gettotalrefcount() - rc - if filter(None, refcounts): - print("%s leaks:\n\t" % testcase, refcounts) - elif verbosity: - print("%s: ok." % testcase) - -class TestRunner(unittest.TextTestRunner): - def run(self, test, skipped): - "Run the given test case or test suite." - # Same as unittest.TextTestRunner.run, except that it reports - # skipped tests. - result = self._makeResult() - startTime = time.time() - test(result) - stopTime = time.time() - timeTaken = stopTime - startTime - result.printErrors() - self.stream.writeln(result.separator2) - run = result.testsRun - if _unavail: #skipped: - requested = list(_unavail.keys()) - requested.sort() - self.stream.writeln("Ran %d test%s in %.3fs (%s module%s skipped)" % - (run, run != 1 and "s" or "", timeTaken, - len(skipped), - len(skipped) != 1 and "s" or "")) - self.stream.writeln("Unavailable resources: %s" % ", ".join(requested)) - else: - self.stream.writeln("Ran %d test%s in %.3fs" % - (run, run != 1 and "s" or "", timeTaken)) - self.stream.writeln() - if not result.wasSuccessful(): - self.stream.write("FAILED (") - failed, errored = map(len, (result.failures, result.errors)) - if failed: - self.stream.write("failures=%d" % failed) - if errored: - if failed: self.stream.write(", ") - self.stream.write("errors=%d" % errored) - self.stream.writeln(")") - else: - self.stream.writeln("OK") - return result - - -def main(*packages): - try: - opts, args = getopt.getopt(sys.argv[1:], "rqvu:x:") - except getopt.error: - return usage() - - verbosity = 1 - search_leaks = False - exclude = [] - for flag, value in opts: - if flag == "-q": - verbosity -= 1 - elif flag == "-v": - verbosity += 1 - elif flag == "-r": - try: - sys.gettotalrefcount - except AttributeError: - print("-r flag requires Python debug build", file=sys.stderr) - return -1 - search_leaks = True - elif flag == "-u": - use_resources.extend(value.split(",")) - elif flag == "-x": - exclude.extend(value.split(",")) - - mask = "test_*.py" - if args: - mask = args[0] - - for package in packages: - run_tests(package, mask, verbosity, search_leaks, exclude) - - -def run_tests(package, mask, verbosity, search_leaks, exclude): - skipped, testcases = get_tests(package, mask, verbosity, exclude) - runner = TestRunner(verbosity=verbosity) - - suites = [unittest.makeSuite(o) for o in testcases] - suite = unittest.TestSuite(suites) - result = runner.run(suite, skipped) - - if search_leaks: - # hunt for refcount leaks - runner = BasicTestRunner() - for t in testcases: - test_with_refcounts(runner, verbosity, t) - - return bool(result.errors) - -class BasicTestRunner: - def run(self, test): - result = unittest.TestResult() - test(result) - return result +def load_tests(*args): + return support.load_package_tests(os.path.dirname(__file__), *args) diff --git a/Lib/ctypes/test/__main__.py b/Lib/ctypes/test/__main__.py new file mode 100644 --- /dev/null +++ b/Lib/ctypes/test/__main__.py @@ -0,0 +1,4 @@ +from ctypes.test import load_tests +import unittest + +unittest.main() diff --git a/Lib/ctypes/test/runtests.py b/Lib/ctypes/test/runtests.py deleted file mode 100644 --- a/Lib/ctypes/test/runtests.py +++ /dev/null @@ -1,19 +0,0 @@ -"""Usage: runtests.py [-q] [-r] [-v] [-u resources] [mask] - -Run all tests found in this directory, and print a summary of the results. -Command line flags: - -q quiet mode: don't print anything while the tests are running - -r run tests repeatedly, look for refcount leaks - -u - Add resources to the lits of allowed resources. '*' allows all - resources. - -v verbose mode: print the test currently executed - -x - Exclude specified tests. - mask mask to select filenames containing testcases, wildcards allowed -""" -import sys -import ctypes.test - -if __name__ == "__main__": - sys.exit(ctypes.test.main(ctypes.test)) diff --git a/Lib/ctypes/test/test_find.py b/Lib/ctypes/test/test_find.py --- a/Lib/ctypes/test/test_find.py +++ b/Lib/ctypes/test/test_find.py @@ -1,60 +1,58 @@ import unittest import os import sys +import test.support from ctypes import * from ctypes.util import find_library -from ctypes.test import is_resource_enabled - -if sys.platform == "win32": - lib_gl = find_library("OpenGL32") - lib_glu = find_library("Glu32") - lib_gle = None -elif sys.platform == "darwin": - lib_gl = lib_glu = find_library("OpenGL") - lib_gle = None -else: - lib_gl = find_library("GL") - lib_glu = find_library("GLU") - lib_gle = find_library("gle") - -## print, for debugging -if is_resource_enabled("printing"): - if lib_gl or lib_glu or lib_gle: - print("OpenGL libraries:") - for item in (("GL", lib_gl), - ("GLU", lib_glu), - ("gle", lib_gle)): - print("\t", item) - # On some systems, loading the OpenGL libraries needs the RTLD_GLOBAL mode. class Test_OpenGL_libs(unittest.TestCase): - def setUp(self): - self.gl = self.glu = self.gle = None + @classmethod + def setUpClass(cls): + lib_gl = lib_glu = lib_gle = None + if sys.platform == "win32": + lib_gl = find_library("OpenGL32") + lib_glu = find_library("Glu32") + elif sys.platform == "darwin": + lib_gl = lib_glu = find_library("OpenGL") + else: + lib_gl = find_library("GL") + lib_glu = find_library("GLU") + lib_gle = find_library("gle") + + ## print, for debugging + if test.support.verbose: + print("OpenGL libraries:") + for item in (("GL", lib_gl), + ("GLU", lib_glu), + ("gle", lib_gle)): + print("\t", item) + + cls.gl = cls.glu = cls.gle = None if lib_gl: - self.gl = CDLL(lib_gl, mode=RTLD_GLOBAL) + cls.gl = CDLL(lib_gl, mode=RTLD_GLOBAL) if lib_glu: - self.glu = CDLL(lib_glu, RTLD_GLOBAL) + cls.glu = CDLL(lib_glu, RTLD_GLOBAL) if lib_gle: try: - self.gle = CDLL(lib_gle) + cls.gle = CDLL(lib_gle) except OSError: pass - @unittest.skipUnless(lib_gl, 'lib_gl not available') def test_gl(self): - if self.gl: - self.gl.glClearIndex + if self.gl is None: + self.skipTest('lib_gl not available') + self.gl.glClearIndex - @unittest.skipUnless(lib_glu, 'lib_glu not available') def test_glu(self): - if self.glu: - self.glu.gluBeginCurve + if self.glu is None: + self.skipTest('lib_glu not available') + self.glu.gluBeginCurve - @unittest.skipUnless(lib_gle, 'lib_gle not available') def test_gle(self): - if self.gle: - self.gle.gleGetJoinStyle + if self.gle is None: + self.skipTest('lib_gle not available') + self.gle.gleGetJoinStyle # On platforms where the default shared library suffix is '.so', # at least some libraries can be loaded as attributes of the cdll diff --git a/Lib/ctypes/test/test_loading.py b/Lib/ctypes/test/test_loading.py --- a/Lib/ctypes/test/test_loading.py +++ b/Lib/ctypes/test/test_loading.py @@ -1,37 +1,42 @@ from ctypes import * -import sys, unittest import os +import sys +import unittest +import test.support from ctypes.util import find_library -from ctypes.test import is_resource_enabled libc_name = None -if os.name == "nt": - libc_name = find_library("c") -elif os.name == "ce": - libc_name = "coredll" -elif sys.platform == "cygwin": - libc_name = "cygwin1.dll" -else: - libc_name = find_library("c") -if is_resource_enabled("printing"): - print("libc_name is", libc_name) +def setUpModule(): + global libc_name + if os.name == "nt": + libc_name = find_library("c") + elif os.name == "ce": + libc_name = "coredll" + elif sys.platform == "cygwin": + libc_name = "cygwin1.dll" + else: + libc_name = find_library("c") + + if test.support.verbose: + print("libc_name is", libc_name) class LoaderTest(unittest.TestCase): unknowndll = "xxrandomnamexx" - @unittest.skipUnless(libc_name is not None, 'could not find libc') def test_load(self): + if libc_name is None: + self.skipTest('could not find libc') CDLL(libc_name) CDLL(os.path.basename(libc_name)) self.assertRaises(OSError, CDLL, self.unknowndll) - @unittest.skipUnless(libc_name is not None, 'could not find libc') - @unittest.skipUnless(libc_name is not None and - os.path.basename(libc_name) == "libc.so.6", - 'wrong libc path for test') def test_load_version(self): + if libc_name is None: + self.skipTest('could not find libc') + if os.path.basename(libc_name) != 'libc.so.6': + self.skipTest('wrong libc path for test') cdll.LoadLibrary("libc.so.6") # linux uses version, libc 9 should not exist self.assertRaises(OSError, cdll.LoadLibrary, "libc.so.9") @@ -48,7 +53,7 @@ 'test specific to Windows (NT/CE)') def test_load_library(self): self.assertIsNotNone(libc_name) - if is_resource_enabled("printing"): + if test.support.verbose: print(find_library("kernel32")) print(find_library("user32")) diff --git a/Lib/ctypes/test/test_python_api.py b/Lib/ctypes/test/test_python_api.py --- a/Lib/ctypes/test/test_python_api.py +++ b/Lib/ctypes/test/test_python_api.py @@ -1,7 +1,6 @@ from ctypes import * import unittest, sys from test import support -from ctypes.test import requires ################################################################ # This section should be moved into ctypes\__init__.py, when it's ready. @@ -39,12 +38,8 @@ del pyob self.assertEqual(grc(s), refcnt) - # This test is unreliable, because it is possible that code in - # unittest changes the refcount of the '42' integer. So, it - # is disabled by default. @support.refcount_test def test_PyLong_Long(self): - requires("refcount") ref42 = grc(42) pythonapi.PyLong_FromLong.restype = py_object self.assertEqual(pythonapi.PyLong_FromLong(42), 42) diff --git a/Lib/ctypes/test/test_win32.py b/Lib/ctypes/test/test_win32.py --- a/Lib/ctypes/test/test_win32.py +++ b/Lib/ctypes/test/test_win32.py @@ -1,7 +1,6 @@ # Windows specific tests from ctypes import * -from ctypes.test import requires import unittest, sys from test import support @@ -42,7 +41,6 @@ @unittest.skipIf(sys.executable.endswith('_d.exe'), "SEH not enabled in debug builds") def test_SEH(self): - requires("SEH") # Call functions with invalid arguments, and make sure # that access violations are trapped and raise an # exception. diff --git a/Lib/test/test_ctypes.py b/Lib/test/test_ctypes.py --- a/Lib/test/test_ctypes.py +++ b/Lib/test/test_ctypes.py @@ -1,16 +1,6 @@ import unittest -from test.support import import_module - -# Skip tests if _ctypes module was not built. -import_module('_ctypes') - -import ctypes.test - -def load_tests(*args): - skipped, testcases = ctypes.test.get_tests(ctypes.test, "test_*.py", verbosity=0) - suites = [unittest.makeSuite(t) for t in testcases] - return unittest.TestSuite(suites) +from ctypes.test import load_tests if __name__ == "__main__": unittest.main() diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -819,6 +819,9 @@ Tests ----- +- Issue #22060: test_ctypes has been somewhat cleaned up and simplified; it + now uses unittest test discovery to find its tests. + - Issue #22104: regrtest.py no longer holds a reference to the suite of tests loaded from test modules that don't define test_main(). -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Aug 9 05:34:08 2014 From: python-checkins at python.org (terry.reedy) Date: Sat, 9 Aug 2014 05:34:08 +0200 (CEST) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzE0MTA1?= =?utf-8?q?=3A_Stop_removing_breakpoints_from_Idle_editors=2E?= Message-ID: <3hVTZ8124yzQXg@mail.python.org> http://hg.python.org/cpython/rev/76ca8569a04c changeset: 92043:76ca8569a04c branch: 2.7 parent: 92032:cbcb10123451 user: Terry Jan Reedy date: Fri Aug 08 23:33:11 2014 -0400 summary: Issue #14105: Stop removing breakpoints from Idle editors. Move BREAK tag configuration to PyShellEditorWindow. files: Lib/idlelib/ColorDelegator.py | 1 - Lib/idlelib/PyShell.py | 10 ++++++++++ 2 files changed, 10 insertions(+), 1 deletions(-) diff --git a/Lib/idlelib/ColorDelegator.py b/Lib/idlelib/ColorDelegator.py --- a/Lib/idlelib/ColorDelegator.py +++ b/Lib/idlelib/ColorDelegator.py @@ -74,7 +74,6 @@ "DEFINITION": idleConf.GetHighlight(theme, "definition"), "SYNC": {'background':None,'foreground':None}, "TODO