summaryrefslogtreecommitdiff
path: root/Lib
diff options
context:
space:
mode:
authorSerhiy Storchaka <storchaka@gmail.com>2018-08-06 17:34:46 +0300
committerGitHub <noreply@github.com>2018-08-06 17:34:46 +0300
commit278d975ce158608f6be491c561247d4701c842be (patch)
treebfd564e6124df2cd9e2f63f76fa0c6fa8fdc3602 /Lib
parentbpo-34273: Change 'Fixed point' to 'Fixed-point notation'. (GH-8673) (diff)
downloadcpython-278d975ce158608f6be491c561247d4701c842be.tar.gz
cpython-278d975ce158608f6be491c561247d4701c842be.tar.bz2
cpython-278d975ce158608f6be491c561247d4701c842be.zip
[3.6] bpo-34272: Move argument parsing tests from test_capi to test_getargs2. (GH-8567). (GH-8690)
(cherry picked from commit 8f7bb100d0fa7fb2714f3953b5b627878277c7c6)
Diffstat (limited to 'Lib')
-rw-r--r--Lib/test/test_capi.py293
-rw-r--r--Lib/test/test_getargs2.py180
2 files changed, 182 insertions, 291 deletions
diff --git a/Lib/test/test_capi.py b/Lib/test/test_capi.py
index 2725333e7e9..ae3bcb92057 100644
--- a/Lib/test/test_capi.py
+++ b/Lib/test/test_capi.py
@@ -5,7 +5,6 @@ import os
import pickle
import random
import re
-import string
import subprocess
import sys
import sysconfig
@@ -373,289 +372,6 @@ class SubinterpreterTest(unittest.TestCase):
self.assertNotEqual(pickle.load(f), id(builtins))
-# Bug #6012
-class Test6012(unittest.TestCase):
- def test(self):
- self.assertEqual(_testcapi.argparsing("Hello", "World"), 1)
-
-
-class EmbeddingTests(unittest.TestCase):
- def setUp(self):
- here = os.path.abspath(__file__)
- basepath = os.path.dirname(os.path.dirname(os.path.dirname(here)))
- exename = "_testembed"
- if sys.platform.startswith("win"):
- ext = ("_d" if "_d" in sys.executable else "") + ".exe"
- exename += ext
- exepath = os.path.dirname(sys.executable)
- else:
- exepath = os.path.join(basepath, "Programs")
- self.test_exe = exe = os.path.join(exepath, exename)
- if not os.path.exists(exe):
- self.skipTest("%r doesn't exist" % exe)
- # This is needed otherwise we get a fatal error:
- # "Py_Initialize: Unable to get the locale encoding
- # LookupError: no codec search functions registered: can't find encoding"
- self.oldcwd = os.getcwd()
- os.chdir(basepath)
-
- def tearDown(self):
- os.chdir(self.oldcwd)
-
- def run_embedded_interpreter(self, *args, env=None):
- """Runs a test in the embedded interpreter"""
- cmd = [self.test_exe]
- cmd.extend(args)
- if env is not None and sys.platform == 'win32':
- # Windows requires at least the SYSTEMROOT environment variable to
- # start Python.
- env = env.copy()
- env['SYSTEMROOT'] = os.environ['SYSTEMROOT']
-
- p = subprocess.Popen(cmd,
- stdout=subprocess.PIPE,
- stderr=subprocess.PIPE,
- universal_newlines=True,
- env=env)
- (out, err) = p.communicate()
- self.assertEqual(p.returncode, 0,
- "bad returncode %d, stderr is %r" %
- (p.returncode, err))
- return out, err
-
- def test_repeated_init_and_subinterpreters(self):
- # This is just a "don't crash" test
- out, err = self.run_embedded_interpreter('repeated_init_and_subinterpreters')
- if support.verbose:
- print()
- print(out)
- print(err)
-
- @staticmethod
- def _get_default_pipe_encoding():
- rp, wp = os.pipe()
- try:
- with os.fdopen(wp, 'w') as w:
- default_pipe_encoding = w.encoding
- finally:
- os.close(rp)
- return default_pipe_encoding
-
- def test_forced_io_encoding(self):
- # Checks forced configuration of embedded interpreter IO streams
- env = dict(os.environ, PYTHONIOENCODING="utf-8:surrogateescape")
- out, err = self.run_embedded_interpreter("forced_io_encoding", env=env)
- if support.verbose:
- print()
- print(out)
- print(err)
- expected_stream_encoding = "utf-8"
- expected_errors = "surrogateescape"
- expected_pipe_encoding = self._get_default_pipe_encoding()
- expected_output = '\n'.join([
- "--- Use defaults ---",
- "Expected encoding: default",
- "Expected errors: default",
- "stdin: {in_encoding}:{errors}",
- "stdout: {out_encoding}:{errors}",
- "stderr: {out_encoding}:backslashreplace",
- "--- Set errors only ---",
- "Expected encoding: default",
- "Expected errors: ignore",
- "stdin: {in_encoding}:ignore",
- "stdout: {out_encoding}:ignore",
- "stderr: {out_encoding}:backslashreplace",
- "--- Set encoding only ---",
- "Expected encoding: latin-1",
- "Expected errors: default",
- "stdin: latin-1:{errors}",
- "stdout: latin-1:{errors}",
- "stderr: latin-1:backslashreplace",
- "--- Set encoding and errors ---",
- "Expected encoding: latin-1",
- "Expected errors: replace",
- "stdin: latin-1:replace",
- "stdout: latin-1:replace",
- "stderr: latin-1:backslashreplace"])
- expected_output = expected_output.format(
- in_encoding=expected_stream_encoding,
- out_encoding=expected_stream_encoding,
- errors=expected_errors)
- # This is useful if we ever trip over odd platform behaviour
- self.maxDiff = None
- self.assertEqual(out.strip(), expected_output)
-
- def test_pre_initialization_api(self):
- """
- Checks the few parts of the C-API that work before the runtine
- is initialized (via Py_Initialize()).
- """
- env = dict(os.environ, PYTHONPATH=os.pathsep.join(sys.path))
- out, err = self.run_embedded_interpreter("pre_initialization_api", env=env)
- self.assertEqual(out, '')
- self.assertEqual(err, '')
-
-
-class SkipitemTest(unittest.TestCase):
-
- def test_skipitem(self):
- """
- If this test failed, you probably added a new "format unit"
- in Python/getargs.c, but neglected to update our poor friend
- skipitem() in the same file. (If so, shame on you!)
-
- With a few exceptions**, this function brute-force tests all
- printable ASCII*** characters (32 to 126 inclusive) as format units,
- checking to see that PyArg_ParseTupleAndKeywords() return consistent
- errors both when the unit is attempted to be used and when it is
- skipped. If the format unit doesn't exist, we'll get one of two
- specific error messages (one for used, one for skipped); if it does
- exist we *won't* get that error--we'll get either no error or some
- other error. If we get the specific "does not exist" error for one
- test and not for the other, there's a mismatch, and the test fails.
-
- ** Some format units have special funny semantics and it would
- be difficult to accommodate them here. Since these are all
- well-established and properly skipped in skipitem() we can
- get away with not testing them--this test is really intended
- to catch *new* format units.
-
- *** Python C source files must be ASCII. Therefore it's impossible
- to have non-ASCII format units.
-
- """
- empty_tuple = ()
- tuple_1 = (0,)
- dict_b = {'b':1}
- keywords = ["a", "b"]
-
- for i in range(32, 127):
- c = chr(i)
-
- # skip parentheses, the error reporting is inconsistent about them
- # skip 'e', it's always a two-character code
- # skip '|' and '$', they don't represent arguments anyway
- if c in '()e|$':
- continue
-
- # test the format unit when not skipped
- format = c + "i"
- try:
- _testcapi.parse_tuple_and_keywords(tuple_1, dict_b,
- format, keywords)
- when_not_skipped = False
- except SystemError as e:
- s = "argument 1 (impossible<bad format char>)"
- when_not_skipped = (str(e) == s)
- except TypeError:
- when_not_skipped = False
-
- # test the format unit when skipped
- optional_format = "|" + format
- try:
- _testcapi.parse_tuple_and_keywords(empty_tuple, dict_b,
- optional_format, keywords)
- when_skipped = False
- except SystemError as e:
- s = "impossible<bad format char>: '{}'".format(format)
- when_skipped = (str(e) == s)
-
- message = ("test_skipitem_parity: "
- "detected mismatch between convertsimple and skipitem "
- "for format unit '{}' ({}), not skipped {}, skipped {}".format(
- c, i, when_skipped, when_not_skipped))
- self.assertIs(when_skipped, when_not_skipped, message)
-
- def test_skipitem_with_suffix(self):
- parse = _testcapi.parse_tuple_and_keywords
- empty_tuple = ()
- tuple_1 = (0,)
- dict_b = {'b':1}
- keywords = ["a", "b"]
-
- supported = ('s#', 's*', 'z#', 'z*', 'u#', 'Z#', 'y#', 'y*', 'w#', 'w*')
- for c in string.ascii_letters:
- for c2 in '#*':
- f = c + c2
- with self.subTest(format=f):
- optional_format = "|" + f + "i"
- if f in supported:
- parse(empty_tuple, dict_b, optional_format, keywords)
- else:
- with self.assertRaisesRegex(SystemError,
- 'impossible<bad format char>'):
- parse(empty_tuple, dict_b, optional_format, keywords)
-
- for c in map(chr, range(32, 128)):
- f = 'e' + c
- optional_format = "|" + f + "i"
- with self.subTest(format=f):
- if c in 'st':
- parse(empty_tuple, dict_b, optional_format, keywords)
- else:
- with self.assertRaisesRegex(SystemError,
- 'impossible<bad format char>'):
- parse(empty_tuple, dict_b, optional_format, keywords)
-
- def test_parse_tuple_and_keywords(self):
- # Test handling errors in the parse_tuple_and_keywords helper itself
- self.assertRaises(TypeError, _testcapi.parse_tuple_and_keywords,
- (), {}, 42, [])
- self.assertRaises(ValueError, _testcapi.parse_tuple_and_keywords,
- (), {}, '', 42)
- self.assertRaises(ValueError, _testcapi.parse_tuple_and_keywords,
- (), {}, '', [''] * 42)
- self.assertRaises(ValueError, _testcapi.parse_tuple_and_keywords,
- (), {}, '', [42])
-
- def test_bad_use(self):
- # Test handling invalid format and keywords in
- # PyArg_ParseTupleAndKeywords()
- self.assertRaises(SystemError, _testcapi.parse_tuple_and_keywords,
- (1,), {}, '||O', ['a'])
- self.assertRaises(SystemError, _testcapi.parse_tuple_and_keywords,
- (1, 2), {}, '|O|O', ['a', 'b'])
- self.assertRaises(SystemError, _testcapi.parse_tuple_and_keywords,
- (), {'a': 1}, '$$O', ['a'])
- self.assertRaises(SystemError, _testcapi.parse_tuple_and_keywords,
- (), {'a': 1, 'b': 2}, '$O$O', ['a', 'b'])
- self.assertRaises(SystemError, _testcapi.parse_tuple_and_keywords,
- (), {'a': 1}, '$|O', ['a'])
- self.assertRaises(SystemError, _testcapi.parse_tuple_and_keywords,
- (), {'a': 1, 'b': 2}, '$O|O', ['a', 'b'])
- self.assertRaises(SystemError, _testcapi.parse_tuple_and_keywords,
- (1,), {}, '|O', ['a', 'b'])
- self.assertRaises(SystemError, _testcapi.parse_tuple_and_keywords,
- (1,), {}, '|OO', ['a'])
- self.assertRaises(SystemError, _testcapi.parse_tuple_and_keywords,
- (), {}, '|$O', [''])
- self.assertRaises(SystemError, _testcapi.parse_tuple_and_keywords,
- (), {}, '|OO', ['a', ''])
-
- def test_positional_only(self):
- parse = _testcapi.parse_tuple_and_keywords
-
- parse((1, 2, 3), {}, 'OOO', ['', '', 'a'])
- parse((1, 2), {'a': 3}, 'OOO', ['', '', 'a'])
- with self.assertRaisesRegex(TypeError,
- r'Function takes at least 2 positional arguments \(1 given\)'):
- parse((1,), {'a': 3}, 'OOO', ['', '', 'a'])
- parse((1,), {}, 'O|OO', ['', '', 'a'])
- with self.assertRaisesRegex(TypeError,
- r'Function takes at least 1 positional arguments \(0 given\)'):
- parse((), {}, 'O|OO', ['', '', 'a'])
- parse((1, 2), {'a': 3}, 'OO$O', ['', '', 'a'])
- with self.assertRaisesRegex(TypeError,
- r'Function takes exactly 2 positional arguments \(1 given\)'):
- parse((1,), {'a': 3}, 'OO$O', ['', '', 'a'])
- parse((1,), {}, 'O|O$O', ['', '', 'a'])
- with self.assertRaisesRegex(TypeError,
- r'Function takes at least 1 positional arguments \(0 given\)'):
- parse((), {}, 'O|O$O', ['', '', 'a'])
- with self.assertRaisesRegex(SystemError, r'Empty parameter name after \$'):
- parse((1,), {}, 'O|$OO', ['', '', 'a'])
- with self.assertRaisesRegex(SystemError, 'Empty keyword'):
- parse((1,), {}, 'O|OO', ['', 'a', ''])
@unittest.skipUnless(threading, 'Threading required for this test.')
@@ -684,12 +400,9 @@ class TestThreadState(unittest.TestCase):
class Test_testcapi(unittest.TestCase):
- def test__testcapi(self):
- for name in dir(_testcapi):
- if name.startswith('test_'):
- with self.subTest("internal", name=name):
- test = getattr(_testcapi, name)
- test()
+ locals().update((name, getattr(_testcapi, name))
+ for name in dir(_testcapi)
+ if name.startswith('test_') and not name.endswith('_code'))
class PyMemDebugTests(unittest.TestCase):
diff --git a/Lib/test/test_getargs2.py b/Lib/test/test_getargs2.py
index d14a6ee31fd..cdc4cbf7199 100644
--- a/Lib/test/test_getargs2.py
+++ b/Lib/test/test_getargs2.py
@@ -1,9 +1,10 @@
import unittest
import math
+import string
import sys
from test import support
# Skip this test if the _testcapi module isn't available.
-support.import_module('_testcapi')
+_testcapi = support.import_module('_testcapi')
from _testcapi import getargs_keywords, getargs_keyword_only
# > How about the following counterproposal. This also changes some of
@@ -954,5 +955,182 @@ class Object_TestCase(unittest.TestCase):
self.assertRaises(TypeError, getargs_U, None)
+# Bug #6012
+class Test6012(unittest.TestCase):
+ def test(self):
+ self.assertEqual(_testcapi.argparsing("Hello", "World"), 1)
+
+
+class SkipitemTest(unittest.TestCase):
+
+ def test_skipitem(self):
+ """
+ If this test failed, you probably added a new "format unit"
+ in Python/getargs.c, but neglected to update our poor friend
+ skipitem() in the same file. (If so, shame on you!)
+
+ With a few exceptions**, this function brute-force tests all
+ printable ASCII*** characters (32 to 126 inclusive) as format units,
+ checking to see that PyArg_ParseTupleAndKeywords() return consistent
+ errors both when the unit is attempted to be used and when it is
+ skipped. If the format unit doesn't exist, we'll get one of two
+ specific error messages (one for used, one for skipped); if it does
+ exist we *won't* get that error--we'll get either no error or some
+ other error. If we get the specific "does not exist" error for one
+ test and not for the other, there's a mismatch, and the test fails.
+
+ ** Some format units have special funny semantics and it would
+ be difficult to accommodate them here. Since these are all
+ well-established and properly skipped in skipitem() we can
+ get away with not testing them--this test is really intended
+ to catch *new* format units.
+
+ *** Python C source files must be ASCII. Therefore it's impossible
+ to have non-ASCII format units.
+
+ """
+ empty_tuple = ()
+ tuple_1 = (0,)
+ dict_b = {'b':1}
+ keywords = ["a", "b"]
+
+ for i in range(32, 127):
+ c = chr(i)
+
+ # skip parentheses, the error reporting is inconsistent about them
+ # skip 'e', it's always a two-character code
+ # skip '|' and '$', they don't represent arguments anyway
+ if c in '()e|$':
+ continue
+
+ # test the format unit when not skipped
+ format = c + "i"
+ try:
+ _testcapi.parse_tuple_and_keywords(tuple_1, dict_b,
+ format, keywords)
+ when_not_skipped = False
+ except SystemError as e:
+ s = "argument 1 (impossible<bad format char>)"
+ when_not_skipped = (str(e) == s)
+ except TypeError:
+ when_not_skipped = False
+
+ # test the format unit when skipped
+ optional_format = "|" + format
+ try:
+ _testcapi.parse_tuple_and_keywords(empty_tuple, dict_b,
+ optional_format, keywords)
+ when_skipped = False
+ except SystemError as e:
+ s = "impossible<bad format char>: '{}'".format(format)
+ when_skipped = (str(e) == s)
+
+ message = ("test_skipitem_parity: "
+ "detected mismatch between convertsimple and skipitem "
+ "for format unit '{}' ({}), not skipped {}, skipped {}".format(
+ c, i, when_skipped, when_not_skipped))
+ self.assertIs(when_skipped, when_not_skipped, message)
+
+ def test_skipitem_with_suffix(self):
+ parse = _testcapi.parse_tuple_and_keywords
+ empty_tuple = ()
+ tuple_1 = (0,)
+ dict_b = {'b':1}
+ keywords = ["a", "b"]
+
+ supported = ('s#', 's*', 'z#', 'z*', 'u#', 'Z#', 'y#', 'y*', 'w#', 'w*')
+ for c in string.ascii_letters:
+ for c2 in '#*':
+ f = c + c2
+ with self.subTest(format=f):
+ optional_format = "|" + f + "i"
+ if f in supported:
+ parse(empty_tuple, dict_b, optional_format, keywords)
+ else:
+ with self.assertRaisesRegex(SystemError,
+ 'impossible<bad format char>'):
+ parse(empty_tuple, dict_b, optional_format, keywords)
+
+ for c in map(chr, range(32, 128)):
+ f = 'e' + c
+ optional_format = "|" + f + "i"
+ with self.subTest(format=f):
+ if c in 'st':
+ parse(empty_tuple, dict_b, optional_format, keywords)
+ else:
+ with self.assertRaisesRegex(SystemError,
+ 'impossible<bad format char>'):
+ parse(empty_tuple, dict_b, optional_format, keywords)
+
+
+class ParseTupleAndKeywords_Test(unittest.TestCase):
+
+ def test_parse_tuple_and_keywords(self):
+ # Test handling errors in the parse_tuple_and_keywords helper itself
+ self.assertRaises(TypeError, _testcapi.parse_tuple_and_keywords,
+ (), {}, 42, [])
+ self.assertRaises(ValueError, _testcapi.parse_tuple_and_keywords,
+ (), {}, '', 42)
+ self.assertRaises(ValueError, _testcapi.parse_tuple_and_keywords,
+ (), {}, '', [''] * 42)
+ self.assertRaises(ValueError, _testcapi.parse_tuple_and_keywords,
+ (), {}, '', [42])
+
+ def test_bad_use(self):
+ # Test handling invalid format and keywords in
+ # PyArg_ParseTupleAndKeywords()
+ self.assertRaises(SystemError, _testcapi.parse_tuple_and_keywords,
+ (1,), {}, '||O', ['a'])
+ self.assertRaises(SystemError, _testcapi.parse_tuple_and_keywords,
+ (1, 2), {}, '|O|O', ['a', 'b'])
+ self.assertRaises(SystemError, _testcapi.parse_tuple_and_keywords,
+ (), {'a': 1}, '$$O', ['a'])
+ self.assertRaises(SystemError, _testcapi.parse_tuple_and_keywords,
+ (), {'a': 1, 'b': 2}, '$O$O', ['a', 'b'])
+ self.assertRaises(SystemError, _testcapi.parse_tuple_and_keywords,
+ (), {'a': 1}, '$|O', ['a'])
+ self.assertRaises(SystemError, _testcapi.parse_tuple_and_keywords,
+ (), {'a': 1, 'b': 2}, '$O|O', ['a', 'b'])
+ self.assertRaises(SystemError, _testcapi.parse_tuple_and_keywords,
+ (1,), {}, '|O', ['a', 'b'])
+ self.assertRaises(SystemError, _testcapi.parse_tuple_and_keywords,
+ (1,), {}, '|OO', ['a'])
+ self.assertRaises(SystemError, _testcapi.parse_tuple_and_keywords,
+ (), {}, '|$O', [''])
+ self.assertRaises(SystemError, _testcapi.parse_tuple_and_keywords,
+ (), {}, '|OO', ['a', ''])
+
+ def test_positional_only(self):
+ parse = _testcapi.parse_tuple_and_keywords
+
+ parse((1, 2, 3), {}, 'OOO', ['', '', 'a'])
+ parse((1, 2), {'a': 3}, 'OOO', ['', '', 'a'])
+ with self.assertRaisesRegex(TypeError,
+ r'Function takes at least 2 positional arguments \(1 given\)'):
+ parse((1,), {'a': 3}, 'OOO', ['', '', 'a'])
+ parse((1,), {}, 'O|OO', ['', '', 'a'])
+ with self.assertRaisesRegex(TypeError,
+ r'Function takes at least 1 positional arguments \(0 given\)'):
+ parse((), {}, 'O|OO', ['', '', 'a'])
+ parse((1, 2), {'a': 3}, 'OO$O', ['', '', 'a'])
+ with self.assertRaisesRegex(TypeError,
+ r'Function takes exactly 2 positional arguments \(1 given\)'):
+ parse((1,), {'a': 3}, 'OO$O', ['', '', 'a'])
+ parse((1,), {}, 'O|O$O', ['', '', 'a'])
+ with self.assertRaisesRegex(TypeError,
+ r'Function takes at least 1 positional arguments \(0 given\)'):
+ parse((), {}, 'O|O$O', ['', '', 'a'])
+ with self.assertRaisesRegex(SystemError, r'Empty parameter name after \$'):
+ parse((1,), {}, 'O|$OO', ['', '', 'a'])
+ with self.assertRaisesRegex(SystemError, 'Empty keyword'):
+ parse((1,), {}, 'O|OO', ['', 'a', ''])
+
+
+class Test_testcapi(unittest.TestCase):
+ locals().update((name, getattr(_testcapi, name))
+ for name in dir(_testcapi)
+ if name.startswith('test_') and name.endswith('_code'))
+
+
if __name__ == "__main__":
unittest.main()