diff options
author | Benjamin Peterson <benjamin@python.org> | 2016-06-09 06:18:56 (GMT) |
---|---|---|
committer | Benjamin Peterson <benjamin@python.org> | 2016-06-09 06:18:56 (GMT) |
commit | cff5ec6be36b0eef010d8b2afc444e60838217d0 (patch) | |
tree | c8293641f48268eccb6c1c96752fa7ba98033acf /Lib | |
parent | b3e073cbb3af2999e6e589f55ec2fc8a109fdc14 (diff) | |
parent | d5982d0433ec29fbacf9c05ddd5fd8ed884af6bd (diff) | |
download | cpython-cff5ec6be36b0eef010d8b2afc444e60838217d0.zip cpython-cff5ec6be36b0eef010d8b2afc444e60838217d0.tar.gz cpython-cff5ec6be36b0eef010d8b2afc444e60838217d0.tar.bz2 |
merge heads
Diffstat (limited to 'Lib')
-rw-r--r-- | Lib/BaseHTTPServer.py | 21 | ||||
-rw-r--r-- | Lib/idlelib/NEWS.txt | 3 | ||||
-rw-r--r-- | Lib/idlelib/idle_test/__init__.py | 6 | ||||
-rwxr-xr-x | Lib/platform.py | 15 | ||||
-rw-r--r-- | Lib/test/test_httpservers.py | 38 | ||||
-rw-r--r-- | Lib/test/test_platform.py | 16 | ||||
-rw-r--r-- | Lib/test/test_turtle.py | 435 |
7 files changed, 525 insertions, 9 deletions
diff --git a/Lib/BaseHTTPServer.py b/Lib/BaseHTTPServer.py index deaf2f9..3df3323 100644 --- a/Lib/BaseHTTPServer.py +++ b/Lib/BaseHTTPServer.py @@ -362,14 +362,25 @@ class BaseHTTPRequestHandler(SocketServer.StreamRequestHandler): message = short explain = long self.log_error("code %d, message %s", code, message) - # using _quote_html to prevent Cross Site Scripting attacks (see bug #1100201) - content = (self.error_message_format % - {'code': code, 'message': _quote_html(message), 'explain': explain}) self.send_response(code, message) - self.send_header("Content-Type", self.error_content_type) self.send_header('Connection', 'close') + + # Message body is omitted for cases described in: + # - RFC7230: 3.3. 1xx, 204(No Content), 304(Not Modified) + # - RFC7231: 6.3.6. 205(Reset Content) + content = None + if code >= 200 and code not in (204, 205, 304): + # HTML encode to prevent Cross Site Scripting attacks + # (see bug #1100201) + content = (self.error_message_format % { + 'code': code, + 'message': _quote_html(message), + 'explain': explain + }) + self.send_header("Content-Type", self.error_content_type) self.end_headers() - if self.command != 'HEAD' and code >= 200 and code not in (204, 304): + + if self.command != 'HEAD' and content: self.wfile.write(content) error_message_format = DEFAULT_ERROR_MESSAGE diff --git a/Lib/idlelib/NEWS.txt b/Lib/idlelib/NEWS.txt index a6c478d..94716a1 100644 --- a/Lib/idlelib/NEWS.txt +++ b/Lib/idlelib/NEWS.txt @@ -2,6 +2,9 @@ What's New in IDLE 2.7.12? ========================== *Release date: 2015-06-30?* +- Issue #24759: Make clear in idlelib.idle_test.__init__ that the directory + is a private implementation of test.test_idle and tool for maintainers. + - Issue #26673: When tk reports font size as 0, change to size 10. Such fonts on Linux prevented the configuration dialog from opening. diff --git a/Lib/idlelib/idle_test/__init__.py b/Lib/idlelib/idle_test/__init__.py index 1bc9536..845c92d 100644 --- a/Lib/idlelib/idle_test/__init__.py +++ b/Lib/idlelib/idle_test/__init__.py @@ -1,3 +1,9 @@ +'''idlelib.idle_test is a private implementation of test.test_idle, +which tests the IDLE application as part of the stdlib test suite. +Run IDLE tests alone with "python -m test.test_idle". +This package and its contained modules are subject to change and +any direct use is at your own risk. +''' from os.path import dirname def load_tests(loader, standard_tests, pattern): diff --git a/Lib/platform.py b/Lib/platform.py index 3cf2303..63455ce 100755 --- a/Lib/platform.py +++ b/Lib/platform.py @@ -1314,9 +1314,11 @@ def processor(): ### Various APIs for extracting information from sys.version _sys_version_parser = re.compile( - r'([\w.+]+)\s*' - '\(#?([^,]+),\s*([\w ]+),\s*([\w :]+)\)\s*' - '\[([^\]]+)\]?') + r'([\w.+]+)\s*' # "version<space>" + r'\(#?([^,]+)' # "(#buildno" + r'(?:,\s*([\w ]*)' # ", builddate" + r'(?:,\s*([\w :]*))?)?\)\s*' # ", buildtime)<space>" + r'\[([^\]]+)\]?') # "[compiler]" _ironpython_sys_version_parser = re.compile( r'IronPython\s*' @@ -1395,6 +1397,8 @@ def _sys_version(sys_version=None): 'failed to parse Jython sys.version: %s' % repr(sys_version)) version, buildno, builddate, buildtime, _ = match.groups() + if builddate is None: + builddate = '' compiler = sys.platform elif "PyPy" in sys_version: @@ -1417,7 +1421,10 @@ def _sys_version(sys_version=None): version, buildno, builddate, buildtime, compiler = \ match.groups() name = 'CPython' - builddate = builddate + ' ' + buildtime + if builddate is None: + builddate = '' + elif buildtime: + builddate = builddate + ' ' + buildtime if hasattr(sys, 'subversion'): # sys.subversion was added in Python 2.5 diff --git a/Lib/test/test_httpservers.py b/Lib/test/test_httpservers.py index 672c187..1b6339d 100644 --- a/Lib/test/test_httpservers.py +++ b/Lib/test/test_httpservers.py @@ -178,6 +178,12 @@ class BaseHTTPServerTestCase(BaseTestCase): self.send_header('Connection', 'close') self.end_headers() + def do_SEND_ERROR(self): + self.send_error(int(self.path[1:])) + + def do_HEAD(self): + self.send_error(int(self.path[1:])) + def setUp(self): BaseTestCase.setUp(self) self.con = httplib.HTTPConnection('localhost', self.PORT) @@ -276,6 +282,38 @@ class BaseHTTPServerTestCase(BaseTestCase): res = self.con.getresponse() self.assertEqual(res.status, 999) + def test_send_error(self): + allow_transfer_encoding_codes = (205, 304) + for code in (101, 102, 204, 205, 304): + self.con.request('SEND_ERROR', '/{}'.format(code)) + res = self.con.getresponse() + self.assertEqual(code, res.status) + self.assertEqual(None, res.getheader('Content-Length')) + self.assertEqual(None, res.getheader('Content-Type')) + if code not in allow_transfer_encoding_codes: + self.assertEqual(None, res.getheader('Transfer-Encoding')) + + data = res.read() + self.assertEqual(b'', data) + + def test_head_via_send_error(self): + allow_transfer_encoding_codes = (205, 304) + for code in (101, 200, 204, 205, 304): + self.con.request('HEAD', '/{}'.format(code)) + res = self.con.getresponse() + self.assertEqual(code, res.status) + if code == 200: + self.assertEqual(None, res.getheader('Content-Length')) + self.assertIn('text/html', res.getheader('Content-Type')) + else: + self.assertEqual(None, res.getheader('Content-Length')) + self.assertEqual(None, res.getheader('Content-Type')) + if code not in allow_transfer_encoding_codes: + self.assertEqual(None, res.getheader('Transfer-Encoding')) + + data = res.read() + self.assertEqual(b'', data) + class SimpleHTTPServerTestCase(BaseTestCase): class request_handler(NoLogRequestHandler, SimpleHTTPRequestHandler): diff --git a/Lib/test/test_platform.py b/Lib/test/test_platform.py index 331995f..f754550 100644 --- a/Lib/test/test_platform.py +++ b/Lib/test/test_platform.py @@ -67,6 +67,22 @@ class PlatformTest(unittest.TestCase): ('IronPython', '1.0.60816', '', '', '', '', '.NET 2.0.50727.42')), ('IronPython 1.0 (1.0.61005.1977) on .NET 2.0.50727.42', ('IronPython', '1.0.0', '', '', '', '', '.NET 2.0.50727.42')), + ('2.4.3 (truncation, date, t) \n[GCC]', + ('CPython', '2.4.3', '', '', 'truncation', 'date t', 'GCC')), + ('2.4.3 (truncation, date, ) \n[GCC]', + ('CPython', '2.4.3', '', '', 'truncation', 'date', 'GCC')), + ('2.4.3 (truncation, date,) \n[GCC]', + ('CPython', '2.4.3', '', '', 'truncation', 'date', 'GCC')), + ('2.4.3 (truncation, date) \n[GCC]', + ('CPython', '2.4.3', '', '', 'truncation', 'date', 'GCC')), + ('2.4.3 (truncation, d) \n[GCC]', + ('CPython', '2.4.3', '', '', 'truncation', 'd', 'GCC')), + ('2.4.3 (truncation, ) \n[GCC]', + ('CPython', '2.4.3', '', '', 'truncation', '', 'GCC')), + ('2.4.3 (truncation,) \n[GCC]', + ('CPython', '2.4.3', '', '', 'truncation', '', 'GCC')), + ('2.4.3 (truncation) \n[GCC]', + ('CPython', '2.4.3', '', '', 'truncation', '', 'GCC')), ): # branch and revision are not "parsed", but fetched # from sys.subversion. Ignore them diff --git a/Lib/test/test_turtle.py b/Lib/test/test_turtle.py new file mode 100644 index 0000000..8f8434c --- /dev/null +++ b/Lib/test/test_turtle.py @@ -0,0 +1,435 @@ +import pickle +import unittest +from test import test_support as support + +turtle = support.import_module('turtle') +Vec2D = turtle.Vec2D + +test_config = """\ +width = 0.75 +height = 0.8 +canvwidth = 500 +canvheight = 200 +leftright = 100 +topbottom = 100 +mode = world +colormode = 255 +delay = 100 +undobuffersize = 10000 +shape = circle +pencolor = red +fillcolor = blue +resizemode = auto +visible = None +language = english +exampleturtle = turtle +examplescreen = screen +title = Python Turtle Graphics +using_IDLE = '' +""" + +test_config_two = """\ +# Comments! +# Testing comments! +pencolor = red +fillcolor = blue +visible = False +language = english +# Some more +# comments +using_IDLE = False +""" + +invalid_test_config = """ +pencolor = red +fillcolor: blue +visible = False +""" + + +class TurtleConfigTest(unittest.TestCase): + + def get_cfg_file(self, cfg_str): + self.addCleanup(support.unlink, support.TESTFN) + with open(support.TESTFN, 'w') as f: + f.write(cfg_str) + return support.TESTFN + + def test_config_dict(self): + + cfg_name = self.get_cfg_file(test_config) + parsed_cfg = turtle.config_dict(cfg_name) + + expected = { + 'width' : 0.75, + 'height' : 0.8, + 'canvwidth' : 500, + 'canvheight': 200, + 'leftright': 100, + 'topbottom': 100, + 'mode': 'world', + 'colormode': 255, + 'delay': 100, + 'undobuffersize': 10000, + 'shape': 'circle', + 'pencolor' : 'red', + 'fillcolor' : 'blue', + 'resizemode' : 'auto', + 'visible' : None, + 'language': 'english', + 'exampleturtle': 'turtle', + 'examplescreen': 'screen', + 'title': 'Python Turtle Graphics', + 'using_IDLE': '', + } + + self.assertEqual(parsed_cfg, expected) + + def test_partial_config_dict_with_commments(self): + + cfg_name = self.get_cfg_file(test_config_two) + parsed_cfg = turtle.config_dict(cfg_name) + + expected = { + 'pencolor': 'red', + 'fillcolor': 'blue', + 'visible': False, + 'language': 'english', + 'using_IDLE': False, + } + + self.assertEqual(parsed_cfg, expected) + + def test_config_dict_invalid(self): + + cfg_name = self.get_cfg_file(invalid_test_config) + + with support.captured_stdout() as stdout: + parsed_cfg = turtle.config_dict(cfg_name) + + err_msg = stdout.getvalue() + + self.assertIn('Bad line in config-file ', err_msg) + self.assertIn('fillcolor: blue', err_msg) + + self.assertEqual(parsed_cfg, { + 'pencolor': 'red', + 'visible': False, + }) + + +class VectorComparisonMixin: + + def assertVectorsAlmostEqual(self, vec1, vec2): + if len(vec1) != len(vec2): + self.fail("Tuples are not of equal size") + for idx, (i, j) in enumerate(zip(vec1, vec2)): + self.assertAlmostEqual( + i, j, msg='values at index {} do not match'.format(idx)) + + +class TestVec2D(VectorComparisonMixin, unittest.TestCase): + + def test_constructor(self): + vec = Vec2D(0.5, 2) + self.assertEqual(vec[0], 0.5) + self.assertEqual(vec[1], 2) + self.assertIsInstance(vec, Vec2D) + + self.assertRaises(TypeError, Vec2D) + self.assertRaises(TypeError, Vec2D, 0) + self.assertRaises(TypeError, Vec2D, (0, 1)) + self.assertRaises(TypeError, Vec2D, vec) + self.assertRaises(TypeError, Vec2D, 0, 1, 2) + + def test_repr(self): + vec = Vec2D(0.567, 1.234) + self.assertEqual(repr(vec), '(0.57,1.23)') + + def test_equality(self): + vec1 = Vec2D(0, 1) + vec2 = Vec2D(0.0, 1) + vec3 = Vec2D(42, 1) + self.assertEqual(vec1, vec2) + self.assertEqual(vec1, tuple(vec1)) + self.assertEqual(tuple(vec1), vec1) + self.assertNotEqual(vec1, vec3) + self.assertNotEqual(vec2, vec3) + + def test_pickling(self): + vec = Vec2D(0.5, 2) + for proto in range(pickle.HIGHEST_PROTOCOL + 1): + pickled = pickle.dumps(vec, protocol=proto) + unpickled = pickle.loads(pickled) + self.assertEqual(unpickled, vec) + self.assertIsInstance(unpickled, Vec2D) + + def _assert_arithmetic_cases(self, test_cases, lambda_operator): + for test_case in test_cases: + ((first, second), expected) = test_case + + op1 = Vec2D(*first) + op2 = Vec2D(*second) + + result = lambda_operator(op1, op2) + + expected = Vec2D(*expected) + + self.assertVectorsAlmostEqual(result, expected) + + def test_vector_addition(self): + + test_cases = [ + (((0, 0), (1, 1)), (1.0, 1.0)), + (((-1, 0), (2, 2)), (1, 2)), + (((1.5, 0), (1, 1)), (2.5, 1)), + ] + + self._assert_arithmetic_cases(test_cases, lambda x, y: x + y) + + def test_vector_subtraction(self): + + test_cases = [ + (((0, 0), (1, 1)), (-1, -1)), + (((10.625, 0.125), (10, 0)), (0.625, 0.125)), + ] + + self._assert_arithmetic_cases(test_cases, lambda x, y: x - y) + + def test_vector_multiply(self): + + vec1 = Vec2D(10, 10) + vec2 = Vec2D(0.5, 3) + answer = vec1 * vec2 + expected = 35 + self.assertAlmostEqual(answer, expected) + + vec = Vec2D(0.5, 3) + answer = vec * 10 + expected = Vec2D(5, 30) + self.assertVectorsAlmostEqual(answer, expected) + + def test_vector_negative(self): + vec = Vec2D(10, -10) + expected = (-10, 10) + self.assertVectorsAlmostEqual(-vec, expected) + + def test_distance(self): + vec = Vec2D(6, 8) + expected = 10 + self.assertEqual(abs(vec), expected) + + vec = Vec2D(0, 0) + expected = 0 + self.assertEqual(abs(vec), expected) + + vec = Vec2D(2.5, 6) + expected = 6.5 + self.assertEqual(abs(vec), expected) + + def test_rotate(self): + + cases = [ + (((0, 0), 0), (0, 0)), + (((0, 1), 90), (-1, 0)), + (((0, 1), -90), (1, 0)), + (((1, 0), 180), (-1, 0)), + (((1, 0), 360), (1, 0)), + ] + + for case in cases: + (vec, rot), expected = case + vec = Vec2D(*vec) + got = vec.rotate(rot) + self.assertVectorsAlmostEqual(got, expected) + + +class TestTNavigator(VectorComparisonMixin, unittest.TestCase): + + def setUp(self): + self.nav = turtle.TNavigator() + + def test_goto(self): + self.nav.goto(100, -100) + self.assertAlmostEqual(self.nav.xcor(), 100) + self.assertAlmostEqual(self.nav.ycor(), -100) + + def test_pos(self): + self.assertEqual(self.nav.pos(), self.nav._position) + self.nav.goto(100, -100) + self.assertEqual(self.nav.pos(), self.nav._position) + + def test_left(self): + self.assertEqual(self.nav._orient, (1.0, 0)) + self.nav.left(90) + self.assertVectorsAlmostEqual(self.nav._orient, (0.0, 1.0)) + + def test_right(self): + self.assertEqual(self.nav._orient, (1.0, 0)) + self.nav.right(90) + self.assertVectorsAlmostEqual(self.nav._orient, (0, -1.0)) + + def test_reset(self): + self.nav.goto(100, -100) + self.assertAlmostEqual(self.nav.xcor(), 100) + self.assertAlmostEqual(self.nav.ycor(), -100) + self.nav.reset() + self.assertAlmostEqual(self.nav.xcor(), 0) + self.assertAlmostEqual(self.nav.ycor(), 0) + + def test_forward(self): + self.nav.forward(150) + expected = Vec2D(150, 0) + self.assertVectorsAlmostEqual(self.nav.position(), expected) + + self.nav.reset() + self.nav.left(90) + self.nav.forward(150) + expected = Vec2D(0, 150) + self.assertVectorsAlmostEqual(self.nav.position(), expected) + + self.assertRaises(TypeError, self.nav.forward, 'skldjfldsk') + + def test_backwards(self): + self.nav.back(200) + expected = Vec2D(-200, 0) + self.assertVectorsAlmostEqual(self.nav.position(), expected) + + self.nav.reset() + self.nav.right(90) + self.nav.back(200) + expected = Vec2D(0, 200) + self.assertVectorsAlmostEqual(self.nav.position(), expected) + + def test_distance(self): + self.nav.forward(100) + expected = 100 + self.assertAlmostEqual(self.nav.distance(Vec2D(0,0)), expected) + + def test_radians_and_degrees(self): + self.nav.left(90) + self.assertAlmostEqual(self.nav.heading(), 90) + self.nav.radians() + self.assertAlmostEqual(self.nav.heading(), 1.57079633) + self.nav.degrees() + self.assertAlmostEqual(self.nav.heading(), 90) + + def test_towards(self): + + coordinates = [ + # coordinates, expected + ((100, 0), 0.0), + ((100, 100), 45.0), + ((0, 100), 90.0), + ((-100, 100), 135.0), + ((-100, 0), 180.0), + ((-100, -100), 225.0), + ((0, -100), 270.0), + ((100, -100), 315.0), + ] + + for (x, y), expected in coordinates: + self.assertEqual(self.nav.towards(x, y), expected) + self.assertEqual(self.nav.towards((x, y)), expected) + self.assertEqual(self.nav.towards(Vec2D(x, y)), expected) + + def test_heading(self): + + self.nav.left(90) + self.assertAlmostEqual(self.nav.heading(), 90) + self.nav.left(45) + self.assertAlmostEqual(self.nav.heading(), 135) + self.nav.right(1.6) + self.assertAlmostEqual(self.nav.heading(), 133.4) + self.assertRaises(TypeError, self.nav.right, 'sdkfjdsf') + self.nav.reset() + + rotations = [10, 20, 170, 300] + result = sum(rotations) % 360 + for num in rotations: + self.nav.left(num) + self.assertEqual(self.nav.heading(), result) + self.nav.reset() + + result = (360-sum(rotations)) % 360 + for num in rotations: + self.nav.right(num) + self.assertEqual(self.nav.heading(), result) + self.nav.reset() + + rotations = [10, 20, -170, 300, -210, 34.3, -50.2, -10, -29.98, 500] + sum_so_far = 0 + for num in rotations: + if num < 0: + self.nav.right(abs(num)) + else: + self.nav.left(num) + sum_so_far += num + self.assertAlmostEqual(self.nav.heading(), sum_so_far % 360) + + def test_setheading(self): + self.nav.setheading(102.32) + self.assertAlmostEqual(self.nav.heading(), 102.32) + self.nav.setheading(-123.23) + self.assertAlmostEqual(self.nav.heading(), (-123.23) % 360) + self.nav.setheading(-1000.34) + self.assertAlmostEqual(self.nav.heading(), (-1000.34) % 360) + self.nav.setheading(300000) + self.assertAlmostEqual(self.nav.heading(), 300000%360) + + def test_positions(self): + self.nav.forward(100) + self.nav.left(90) + self.nav.forward(-200) + self.assertVectorsAlmostEqual(self.nav.pos(), (100.0, -200.0)) + + def test_setx_and_sety(self): + self.nav.setx(-1023.2334) + self.nav.sety(193323.234) + self.assertVectorsAlmostEqual(self.nav.pos(), (-1023.2334, 193323.234)) + + def test_home(self): + self.nav.left(30) + self.nav.forward(-100000) + self.nav.home() + self.assertVectorsAlmostEqual(self.nav.pos(), (0,0)) + self.assertAlmostEqual(self.nav.heading(), 0) + + def test_distance_method(self): + self.assertAlmostEqual(self.nav.distance(30, 40), 50) + vec = Vec2D(0.22, .001) + self.assertAlmostEqual(self.nav.distance(vec), 0.22000227271553355) + another_turtle = turtle.TNavigator() + another_turtle.left(90) + another_turtle.forward(10000) + self.assertAlmostEqual(self.nav.distance(another_turtle), 10000) + + +class TestTPen(unittest.TestCase): + + def test_pendown_and_penup(self): + + tpen = turtle.TPen() + + self.assertTrue(tpen.isdown()) + tpen.penup() + self.assertFalse(tpen.isdown()) + tpen.pendown() + self.assertTrue(tpen.isdown()) + + def test_showturtle_hideturtle_and_isvisible(self): + + tpen = turtle.TPen() + + self.assertTrue(tpen.isvisible()) + tpen.hideturtle() + self.assertFalse(tpen.isvisible()) + tpen.showturtle() + self.assertTrue(tpen.isvisible()) + + +def test_main(): + support.run_unittest(TurtleConfigTest, TestVec2D, TestTNavigator, TestTPen) + +if __name__ == '__main__': + test_main() |