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 | |
parent | b3e073cbb3af2999e6e589f55ec2fc8a109fdc14 (diff) | |
parent | d5982d0433ec29fbacf9c05ddd5fd8ed884af6bd (diff) | |
download | cpython-cff5ec6be36b0eef010d8b2afc444e60838217d0.zip cpython-cff5ec6be36b0eef010d8b2afc444e60838217d0.tar.gz cpython-cff5ec6be36b0eef010d8b2afc444e60838217d0.tar.bz2 |
merge heads
-rw-r--r-- | Doc/distributing/index.rst | 2 | ||||
-rw-r--r-- | Doc/distutils/index.rst | 11 | ||||
-rw-r--r-- | Doc/install/index.rst | 11 | ||||
-rw-r--r-- | Doc/library/basehttpserver.rst | 5 | ||||
-rw-r--r-- | Doc/library/distutils.rst | 48 | ||||
-rw-r--r-- | Doc/reference/simple_stmts.rst | 2 | ||||
-rw-r--r-- | Doc/tools/templates/indexcontent.html | 8 | ||||
-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 | ||||
-rwxr-xr-x | Mac/BuildScript/build-installer.py | 6 | ||||
-rw-r--r-- | Makefile.pre.in | 7 | ||||
-rw-r--r-- | Misc/ACKS | 1 | ||||
-rw-r--r-- | Misc/NEWS | 28 | ||||
-rw-r--r-- | Objects/typeobject.c | 6 |
19 files changed, 620 insertions, 49 deletions
diff --git a/Doc/distributing/index.rst b/Doc/distributing/index.rst index d51ff99..82ecd2c 100644 --- a/Doc/distributing/index.rst +++ b/Doc/distributing/index.rst @@ -61,7 +61,7 @@ Key terms extensions, to be installed on a system without needing to be built locally. -.. _setuptools: https://setuptools.pypa.io/en/latest/setuptools.html +.. _setuptools: https://setuptools.readthedocs.io/en/latest/ .. _wheel: https://wheel.readthedocs.org Open source licensing and collaboration diff --git a/Doc/distutils/index.rst b/Doc/distutils/index.rst index 1f21e14..a697f50 100644 --- a/Doc/distutils/index.rst +++ b/Doc/distutils/index.rst @@ -1,12 +1,17 @@ .. _distutils-index: -############################### - Distributing Python Modules -############################### +############################################## + Distributing Python Modules (Legacy version) +############################################## :Authors: Greg Ward, Anthony Baxter :Email: distutils-sig@python.org +.. seealso:: + + :ref:`distributing-index` + The up to date module distribution documentations + This document describes the Python Distribution Utilities ("Distutils") from the module developer's point of view, describing how to use the Distutils to make Python modules and extensions easily available to a wider audience with diff --git a/Doc/install/index.rst b/Doc/install/index.rst index 893db1e..029aff5 100644 --- a/Doc/install/index.rst +++ b/Doc/install/index.rst @@ -2,14 +2,19 @@ .. _install-index: -***************************** - Installing Python Modules -***************************** +******************************************** + Installing Python Modules (Legacy version) +******************************************** :Author: Greg Ward .. TODO: Fill in XXX comments +.. seealso:: + + :ref:`installing-index` + The up to date module installation documentations + .. The audience for this document includes people who don't know anything about Python and aren't about to learn the language just in order to install and maintain it for their users, i.e. system administrators. diff --git a/Doc/library/basehttpserver.rst b/Doc/library/basehttpserver.rst index 01776af..0c663fe 100644 --- a/Doc/library/basehttpserver.rst +++ b/Doc/library/basehttpserver.rst @@ -197,7 +197,10 @@ to a handler. Code to create and run the server looks like this:: Sends and logs a complete error reply to the client. The numeric *code* specifies the HTTP error code, with *message* as optional, more specific text. A complete set of headers is sent, followed by text composed using the - :attr:`error_message_format` class variable. + :attr:`error_message_format` class variable. The body will be empty + if the method is HEAD or the response code is one of the following: + ``1xx``, ``204 No Content``, ``205 Reset Content``, + ``304 Not Modified``. .. method:: send_response(code[, message]) diff --git a/Doc/library/distutils.rst b/Doc/library/distutils.rst index 534faab..12ad8c0 100644 --- a/Doc/library/distutils.rst +++ b/Doc/library/distutils.rst @@ -1,10 +1,9 @@ - :mod:`distutils` --- Building and installing Python modules =========================================================== .. module:: distutils - :synopsis: Support for building and installing Python modules into an existing Python - installation. + :synopsis: Support for building and installing Python modules into an + existing Python installation. .. sectionauthor:: Fred L. Drake, Jr. <fdrake@acm.org> @@ -13,18 +12,31 @@ additional modules into a Python installation. The new modules may be either 100%-pure Python, or may be extension modules written in C, or may be collections of Python packages which include modules coded in both Python and C. -This package is discussed in two separate chapters: - - -.. seealso:: - - :ref:`distutils-index` - The manual for developers and packagers of Python modules. This describes how - to prepare :mod:`distutils`\ -based packages so that they may be easily - installed into an existing Python installation. - - :ref:`install-index` - An "administrators" manual which includes information on installing modules into - an existing Python installation. You do not need to be a Python programmer to - read this manual. - +Most Python users will *not* want to use this module directly, but instead +use the cross-version tools maintained by the Python Packaging Authority. In +particular, +`setuptools <https://setuptools.readthedocs.io/en/latest/>`__ is an +enhanced alternative to :mod:`distutils` that provides: + +* support for declaring project dependencies +* additional mechanisms for configuring which files to include in source + releases (including plugins for integration with version control systems) +* the ability to declare project "entry points", which can be used as the + basis for application plugin systems +* the ability to automatically generate Windows command line executables at + installation time rather than needing to prebuild them +* consistent behaviour across all supported Python versions + +The recommended `pip <https://pip.pypa.io/>`__ installer runs all +``setup.py`` scripts with ``setuptools``, even if the script itself only +imports ``distutils``. Refer to the +`Python Packaging User Guide <https://packaging.python.org>`_ for more +information. + +For the benefits of packaging tool authors and users seeking a deeper +understanding of the details of the current packaging and distribution +system, the legacy :mod:`distutils` based user documentation and API +reference remain available: + +* :ref:`install-index` +* :ref:`distutils-index` diff --git a/Doc/reference/simple_stmts.rst b/Doc/reference/simple_stmts.rst index 2c0b8db..848bb9e 100644 --- a/Doc/reference/simple_stmts.rst +++ b/Doc/reference/simple_stmts.rst @@ -87,7 +87,7 @@ attributes or items of mutable objects: target_list: `target` ("," `target`)* [","] target: `identifier` : | "(" `target_list` ")" - : | "[" `target_list` "]" + : | "[" [`target_list`] "]" : | `attributeref` : | `subscription` : | `slicing` diff --git a/Doc/tools/templates/indexcontent.html b/Doc/tools/templates/indexcontent.html index 3da2605..6488c16 100644 --- a/Doc/tools/templates/indexcontent.html +++ b/Doc/tools/templates/indexcontent.html @@ -16,14 +16,14 @@ <p class="biglink"><a class="biglink" href="{{ pathto("howto/index") }}">{% trans %}Python HOWTOs{% endtrans %}</a><br/> <span class="linkdescr">{% trans %}in-depth documents on specific topics{% endtrans %}</span></p> </td><td width="50%"> + <p class="biglink"><a class="biglink" href="{{ pathto("installing/index") }}">{% trans %}Installing Python Modules{% endtrans %}</a><br/> + <span class="linkdescr">{% trans %}installing from the Python Package Index & other sources{% endtrans %}</span></p> + <p class="biglink"><a class="biglink" href="{{ pathto("distributing/index") }}">{% trans %}Distributing Python Modules{% endtrans %}</a><br/> + <span class="linkdescr">{% trans %}publishing modules for installation by others{% endtrans %}</span></p> <p class="biglink"><a class="biglink" href="{{ pathto("extending/index") }}">{% trans %}Extending and Embedding{% endtrans %}</a><br/> <span class="linkdescr">{% trans %}tutorial for C/C++ programmers{% endtrans %}</span></p> <p class="biglink"><a class="biglink" href="{{ pathto("c-api/index") }}">{% trans %}Python/C API{% endtrans %}</a><br/> <span class="linkdescr">{% trans %}reference for C/C++ programmers{% endtrans %}</span></p> - <p class="biglink"><a class="biglink" href="{{ pathto("install/index") }}">{% trans %}Installing Python Modules{% endtrans %}</a><br/> - <span class="linkdescr">{% trans %}information for installers & sys-admins{% endtrans %}</span></p> - <p class="biglink"><a class="biglink" href="{{ pathto("distutils/index") }}">{% trans %}Distributing Python Modules{% endtrans %}</a><br/> - <span class="linkdescr">{% trans %}sharing modules with others{% endtrans %}</span></p> <p class="biglink"><a class="biglink" href="{{ pathto("faq/index") }}">{% trans %}FAQs{% endtrans %}</a><br/> <span class="linkdescr">{% trans %}frequently asked questions (with answers!){% endtrans %}</span></p> </td></tr> 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() diff --git a/Mac/BuildScript/build-installer.py b/Mac/BuildScript/build-installer.py index 2304fef..553d64e 100755 --- a/Mac/BuildScript/build-installer.py +++ b/Mac/BuildScript/build-installer.py @@ -242,9 +242,9 @@ def library_recipes(): result.extend([ dict( - name="OpenSSL 1.0.2g", - url="https://www.openssl.org/source/openssl-1.0.2g.tar.gz", - checksum='f3c710c045cdee5fd114feb69feba7aa', + name="OpenSSL 1.0.2h", + url="https://www.openssl.org/source/openssl-1.0.2h.tar.gz", + checksum='9392e65072ce4b614c1392eefc1f23d0', patches=[ "openssl_sdk_makedepend.patch", ], diff --git a/Makefile.pre.in b/Makefile.pre.in index 5aeb502..dffc0b9 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -682,16 +682,19 @@ Modules/pwdmodule.o: $(srcdir)/Modules/pwdmodule.c $(srcdir)/Modules/posixmodule $(GRAMMAR_H): $(GRAMMAR_INPUT) $(PGEN) @$(MKDIR_P) Include + # Avoid copying the file onto itself for an in-tree build if test "$(cross_compiling)" != "yes"; then \ $(PGEN) $(GRAMMAR_INPUT) $(GRAMMAR_H) $(GRAMMAR_C); \ else \ - cp $(srcdir)/Include/graminit.h $(GRAMMAR_H); \ + cp $(srcdir)/Include/graminit.h $(GRAMMAR_H).tmp; \ + mv $(GRAMMAR_H).tmp $(GRAMMAR_H); \ fi $(GRAMMAR_C): $(GRAMMAR_H) if test "$(cross_compiling)" != "yes"; then \ touch $(GRAMMAR_C); \ else \ - cp $(srcdir)/Python/graminit.c $(GRAMMAR_C); \ + cp $(srcdir)/Python/graminit.c $(GRAMMAR_C).tmp; \ + mv $(GRAMMAR_C).tmp $(GRAMMAR_C); \ fi $(PGEN): $(PGENOBJS) @@ -741,6 +741,7 @@ Peter A. Koren Марк Коренберг Vlad Korolev Anna Koroliuk +Susumu Koshiba Joseph Koshy Daniel Kozan Jerzy Kozera @@ -18,7 +18,7 @@ Core and Builtins Some compilers and toolchains are known to not produce stable code when using LTO, be sure to test things thoroughly before relying on it. It can provide a few % speed up over profile-opt alone. - + - Issue #26168: Fixed possible refleaks in failing Py_BuildValue() with the "N" format unit. @@ -92,6 +92,14 @@ Core and Builtins Library ------- +- Issue #25738: Stop BaseHTTPServer.BaseHTTPRequestHandler.send_error() from + sending a message body for 205 Reset Content. Also, don't send the + Content-Type header field in responses that don't have a body. Based on + patch by Susumu Koshiba. + +- Issue #21313: Fix the "platform" module to tolerate when sys.version + contains truncated build information. + - Issue #27211: Fix possible memory corruption in io.IOBase.readline(). - Issue #27114: Fix SSLContext._load_windows_store_certs fails with @@ -263,6 +271,8 @@ Library IDLE ---- +- 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. @@ -293,9 +303,18 @@ Documentation functions together, and add more details such as what underlying Readline functions and variables are accessed. +- Issue #26014: Guide users to the newer packaging documentation as was done + for Python 3.x. In particular, the top-level 2.7 documentation page now + links to the newer installer and distributions pages rather than the + legacy install and Distutils pages; these are still linked to in the + library/distutils doc page. + Tests ----- +- Issue #21916: Added tests for the turtle module. Patch by ingrid, + Gregory Loyse and Jelle Zijlstra. + - Issue #25940: Changed test_ssl to use self-signed.pythontest.net. This avoids relying on svn.python.org, which recently changed root certificate. @@ -312,6 +331,9 @@ Build - Issue #19450: Update Windows builds to use SQLite 3.8.11.0. +- Issue #27229: Fix the cross-compiling pgen rule for in-tree builds. Patch + by Xavier de Gaye. + - Issue #17603: Avoid error about nonexistant fileblocks.o file by using a lower-level check for st_blocks in struct stat. @@ -333,8 +355,8 @@ Build - Issue #25696: Fix installation of Python on UNIX with make -j9. -- Issue #26465: Update OS X 10.5+ 32-bit-only installer to build - and link with OpenSSL 1.0.2g. +- Issue #26930: Update OS X 10.5+ 32-bit-only installer to build + and link with OpenSSL 1.0.2h. - Issue #26268: Update Windows builds to use OpenSSL 1.0.2f. diff --git a/Objects/typeobject.c b/Objects/typeobject.c index d78f298..cae5118 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -2430,7 +2430,11 @@ type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds) Py_DECREF(type); return NULL; } - PyDict_SetItemString(dict, "__new__", tmp); + if (PyDict_SetItemString(dict, "__new__", tmp) < 0) { + Py_DECREF(tmp); + Py_DECREF(type); + return NULL; + } Py_DECREF(tmp); } |