From webhook-mailer at python.org Sun Jul 1 03:02:55 2018 From: webhook-mailer at python.org (INADA Naoki) Date: Sun, 01 Jul 2018 07:02:55 -0000 Subject: [Python-checkins] bpo-30660: Doc: Optimize PNG files by optipng (GH-8032) Message-ID: https://github.com/python/cpython/commit/c6cd164cffedb306a4c6644d9d03072f24da246d commit: c6cd164cffedb306a4c6644d9d03072f24da246d branch: master author: INADA Naoki committer: GitHub date: 2018-07-01T16:02:52+09:00 summary: bpo-30660: Doc: Optimize PNG files by optipng (GH-8032) Using OptiPNG 0.7.7. Used command is: `find . -name '*.png' | xargs optipng -o7` files: M Doc/faq/python-video-icon.png M Doc/howto/logging_flow.png M Doc/library/hashlib-blake2-tree.png M Doc/library/pathlib-inheritance.png M Doc/library/tulip_coro.png M Doc/library/turtle-star.png M Doc/using/win_installer.png diff --git a/Doc/faq/python-video-icon.png b/Doc/faq/python-video-icon.png index 4de54b403d7c..265da50c7b38 100644 Binary files a/Doc/faq/python-video-icon.png and b/Doc/faq/python-video-icon.png differ diff --git a/Doc/howto/logging_flow.png b/Doc/howto/logging_flow.png old mode 100755 new mode 100644 index a88382309a18..fac4acd77553 Binary files a/Doc/howto/logging_flow.png and b/Doc/howto/logging_flow.png differ diff --git a/Doc/library/hashlib-blake2-tree.png b/Doc/library/hashlib-blake2-tree.png index 010dcbafe7c6..73e849444ed7 100644 Binary files a/Doc/library/hashlib-blake2-tree.png and b/Doc/library/hashlib-blake2-tree.png differ diff --git a/Doc/library/pathlib-inheritance.png b/Doc/library/pathlib-inheritance.png index b81c3deb6049..f0e8d0213418 100644 Binary files a/Doc/library/pathlib-inheritance.png and b/Doc/library/pathlib-inheritance.png differ diff --git a/Doc/library/tulip_coro.png b/Doc/library/tulip_coro.png index 36ced8ddbfd9..aad41c93015d 100644 Binary files a/Doc/library/tulip_coro.png and b/Doc/library/tulip_coro.png differ diff --git a/Doc/library/turtle-star.png b/Doc/library/turtle-star.png index caf36a3ab3a5..0961e1e2153f 100644 Binary files a/Doc/library/turtle-star.png and b/Doc/library/turtle-star.png differ diff --git a/Doc/using/win_installer.png b/Doc/using/win_installer.png index 00c88a830feb..0d2250c186c4 100644 Binary files a/Doc/using/win_installer.png and b/Doc/using/win_installer.png differ From solipsis at pitrou.net Sun Jul 1 05:08:23 2018 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Sun, 01 Jul 2018 09:08:23 +0000 Subject: [Python-checkins] Daily reference leaks (4243df51fe43): sum=14 Message-ID: <20180701090823.1.6DFBC51E00254D9B@psf.io> results for 4243df51fe43 on branch "default" -------------------------------------------- test_asyncio leaked [0, 3, 0] memory blocks, sum=3 test_collections leaked [0, 0, 7] memory blocks, sum=7 test_functools leaked [0, 3, 1] memory blocks, sum=4 test_multiprocessing_forkserver leaked [1, -2, 1] memory blocks, sum=0 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogtx74e6', '--timeout', '7200'] From webhook-mailer at python.org Mon Jul 2 04:57:54 2018 From: webhook-mailer at python.org (Vinay Sajip) Date: Mon, 02 Jul 2018 08:57:54 -0000 Subject: [Python-checkins] bpo-33978: Close existing handlers before logging (re-)configuration. (GH-8008) Message-ID: https://github.com/python/cpython/commit/087570af6d5d39b51bdd5e660a53903960e58678 commit: 087570af6d5d39b51bdd5e660a53903960e58678 branch: master author: Xtreak committer: Vinay Sajip date: 2018-07-02T09:57:46+01:00 summary: bpo-33978: Close existing handlers before logging (re-)configuration. (GH-8008) files: A Misc/NEWS.d/next/Library/2018-06-29-12-23-34.bpo-33978.y4csIw.rst M Lib/logging/config.py M Lib/test/test_logging.py diff --git a/Lib/logging/config.py b/Lib/logging/config.py index 1b0facaf6269..fa1a398aee2a 100644 --- a/Lib/logging/config.py +++ b/Lib/logging/config.py @@ -73,8 +73,8 @@ def fileConfig(fname, defaults=None, disable_existing_loggers=True): # critical section logging._acquireLock() try: - logging._handlers.clear() - del logging._handlerList[:] + _clearExistingHandlers() + # Handlers add themselves to logging._handlers handlers = _install_handlers(cp, formatters) _install_loggers(cp, handlers, disable_existing_loggers) @@ -265,6 +265,14 @@ def _install_loggers(cp, handlers, disable_existing): # logger.disabled = 1 _handle_existing_loggers(existing, child_loggers, disable_existing) + +def _clearExistingHandlers(): + """Clear and close existing handlers""" + logging._handlers.clear() + logging.shutdown(logging._handlerList[:]) + del logging._handlerList[:] + + IDENTIFIER = re.compile('^[a-z_][a-z0-9_]*$', re.I) @@ -524,8 +532,7 @@ def configure(self): else: disable_existing = config.pop('disable_existing_loggers', True) - logging._handlers.clear() - del logging._handlerList[:] + _clearExistingHandlers() # Do formatters first - they don't refer to anything else formatters = config.get('formatters', EMPTY_DICT) diff --git a/Lib/test/test_logging.py b/Lib/test/test_logging.py index b3618bd2ad99..a3731fa47939 100644 --- a/Lib/test/test_logging.py +++ b/Lib/test/test_logging.py @@ -1089,6 +1089,7 @@ class ConfigFileTest(BaseTest): """Reading logging config from a .ini-style config file.""" + check_no_resource_warning = support.check_no_resource_warning expected_log_pat = r"^(\w+) \+\+ (\w+)$" # config0 is a standard configuration. @@ -1297,6 +1298,27 @@ class ConfigFileTest(BaseTest): datefmt= """ + # config 8, check for resource warning + config8 = r""" + [loggers] + keys=root + + [handlers] + keys=file + + [formatters] + keys= + + [logger_root] + level=DEBUG + handlers=file + + [handler_file] + class=FileHandler + level=DEBUG + args=("{tempfile}",) + """ + disable_test = """ [loggers] keys=root @@ -1442,6 +1464,29 @@ def test_config7_ok(self): # Original logger output is empty. self.assert_log_lines([]) + def test_config8_ok(self): + + def cleanup(h1, fn): + h1.close() + os.remove(fn) + + with self.check_no_resource_warning(): + fd, fn = tempfile.mkstemp(".log", "test_logging-X-") + os.close(fd) + + # Replace single backslash with double backslash in windows + # to avoid unicode error during string formatting + if os.name == "nt": + fn = fn.replace("\\", "\\\\") + + config8 = self.config8.format(tempfile=fn) + + self.apply_config(config8) + self.apply_config(config8) + + handler = logging.root.handlers[0] + self.addCleanup(cleanup, handler, fn) + def test_logger_disabling(self): self.apply_config(self.disable_test) logger = logging.getLogger('some_pristine_logger') @@ -2022,6 +2067,7 @@ class ConfigDictTest(BaseTest): """Reading logging config from a dictionary.""" + check_no_resource_warning = support.check_no_resource_warning expected_log_pat = r"^(\w+) \+\+ (\w+)$" # config0 is a standard configuration. @@ -2896,6 +2942,35 @@ def test_config14_ok(self): logging.warning('Exclamation') self.assertTrue(output.getvalue().endswith('Exclamation!\n')) + def test_config15_ok(self): + + def cleanup(h1, fn): + h1.close() + os.remove(fn) + + with self.check_no_resource_warning(): + fd, fn = tempfile.mkstemp(".log", "test_logging-X-") + os.close(fd) + + config = { + "version": 1, + "handlers": { + "file": { + "class": "logging.FileHandler", + "filename": fn + } + }, + "root": { + "handlers": ["file"] + } + } + + self.apply_config(config) + self.apply_config(config) + + handler = logging.root.handlers[0] + self.addCleanup(cleanup, handler, fn) + def setup_via_listener(self, text, verify=None): text = text.encode("utf-8") # Ask for a randomly assigned port (by using port 0) diff --git a/Misc/NEWS.d/next/Library/2018-06-29-12-23-34.bpo-33978.y4csIw.rst b/Misc/NEWS.d/next/Library/2018-06-29-12-23-34.bpo-33978.y4csIw.rst new file mode 100644 index 000000000000..12638957ee38 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-06-29-12-23-34.bpo-33978.y4csIw.rst @@ -0,0 +1,2 @@ +Closed existing logging handlers before reconfiguration via fileConfig +and dictConfig. Patch by Karthikeyan Singaravelan. From solipsis at pitrou.net Mon Jul 2 05:09:13 2018 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Mon, 02 Jul 2018 09:09:13 +0000 Subject: [Python-checkins] Daily reference leaks (4243df51fe43): sum=1 Message-ID: <20180702090913.1.CCE1BEA3D28B77AB@psf.io> results for 4243df51fe43 on branch "default" -------------------------------------------- test_asyncio leaked [0, 3, 0] memory blocks, sum=3 test_collections leaked [-7, 8, -7] memory blocks, sum=-6 test_functools leaked [0, 3, 1] memory blocks, sum=4 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogKxVLCs', '--timeout', '7200'] From webhook-mailer at python.org Mon Jul 2 05:35:13 2018 From: webhook-mailer at python.org (Vinay Sajip) Date: Mon, 02 Jul 2018 09:35:13 -0000 Subject: [Python-checkins] bpo-33978: Close existing handlers before logging (re-)configuration. (GH-8008) (GH-8044) Message-ID: https://github.com/python/cpython/commit/6f49afc3d983350f4f04d221a26573721f23c475 commit: 6f49afc3d983350f4f04d221a26573721f23c475 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Vinay Sajip date: 2018-07-02T10:35:09+01:00 summary: bpo-33978: Close existing handlers before logging (re-)configuration. (GH-8008) (GH-8044) (cherry picked from commit 087570af6d5d39b51bdd5e660a53903960e58678) Co-authored-by: Xtreak files: A Misc/NEWS.d/next/Library/2018-06-29-12-23-34.bpo-33978.y4csIw.rst M Lib/logging/config.py M Lib/test/test_logging.py diff --git a/Lib/logging/config.py b/Lib/logging/config.py index 1b0facaf6269..fa1a398aee2a 100644 --- a/Lib/logging/config.py +++ b/Lib/logging/config.py @@ -73,8 +73,8 @@ def fileConfig(fname, defaults=None, disable_existing_loggers=True): # critical section logging._acquireLock() try: - logging._handlers.clear() - del logging._handlerList[:] + _clearExistingHandlers() + # Handlers add themselves to logging._handlers handlers = _install_handlers(cp, formatters) _install_loggers(cp, handlers, disable_existing_loggers) @@ -265,6 +265,14 @@ def _install_loggers(cp, handlers, disable_existing): # logger.disabled = 1 _handle_existing_loggers(existing, child_loggers, disable_existing) + +def _clearExistingHandlers(): + """Clear and close existing handlers""" + logging._handlers.clear() + logging.shutdown(logging._handlerList[:]) + del logging._handlerList[:] + + IDENTIFIER = re.compile('^[a-z_][a-z0-9_]*$', re.I) @@ -524,8 +532,7 @@ def configure(self): else: disable_existing = config.pop('disable_existing_loggers', True) - logging._handlers.clear() - del logging._handlerList[:] + _clearExistingHandlers() # Do formatters first - they don't refer to anything else formatters = config.get('formatters', EMPTY_DICT) diff --git a/Lib/test/test_logging.py b/Lib/test/test_logging.py index 0fa3892e57a3..62ec4b514852 100644 --- a/Lib/test/test_logging.py +++ b/Lib/test/test_logging.py @@ -1089,6 +1089,7 @@ class ConfigFileTest(BaseTest): """Reading logging config from a .ini-style config file.""" + check_no_resource_warning = support.check_no_resource_warning expected_log_pat = r"^(\w+) \+\+ (\w+)$" # config0 is a standard configuration. @@ -1297,6 +1298,27 @@ class ConfigFileTest(BaseTest): datefmt= """ + # config 8, check for resource warning + config8 = r""" + [loggers] + keys=root + + [handlers] + keys=file + + [formatters] + keys= + + [logger_root] + level=DEBUG + handlers=file + + [handler_file] + class=FileHandler + level=DEBUG + args=("{tempfile}",) + """ + disable_test = """ [loggers] keys=root @@ -1442,6 +1464,29 @@ def test_config7_ok(self): # Original logger output is empty. self.assert_log_lines([]) + def test_config8_ok(self): + + def cleanup(h1, fn): + h1.close() + os.remove(fn) + + with self.check_no_resource_warning(): + fd, fn = tempfile.mkstemp(".log", "test_logging-X-") + os.close(fd) + + # Replace single backslash with double backslash in windows + # to avoid unicode error during string formatting + if os.name == "nt": + fn = fn.replace("\\", "\\\\") + + config8 = self.config8.format(tempfile=fn) + + self.apply_config(config8) + self.apply_config(config8) + + handler = logging.root.handlers[0] + self.addCleanup(cleanup, handler, fn) + def test_logger_disabling(self): self.apply_config(self.disable_test) logger = logging.getLogger('some_pristine_logger') @@ -2022,6 +2067,7 @@ class ConfigDictTest(BaseTest): """Reading logging config from a dictionary.""" + check_no_resource_warning = support.check_no_resource_warning expected_log_pat = r"^(\w+) \+\+ (\w+)$" # config0 is a standard configuration. @@ -2896,6 +2942,35 @@ def test_config14_ok(self): logging.warning('Exclamation') self.assertTrue(output.getvalue().endswith('Exclamation!\n')) + def test_config15_ok(self): + + def cleanup(h1, fn): + h1.close() + os.remove(fn) + + with self.check_no_resource_warning(): + fd, fn = tempfile.mkstemp(".log", "test_logging-X-") + os.close(fd) + + config = { + "version": 1, + "handlers": { + "file": { + "class": "logging.FileHandler", + "filename": fn + } + }, + "root": { + "handlers": ["file"] + } + } + + self.apply_config(config) + self.apply_config(config) + + handler = logging.root.handlers[0] + self.addCleanup(cleanup, handler, fn) + def setup_via_listener(self, text, verify=None): text = text.encode("utf-8") # Ask for a randomly assigned port (by using port 0) diff --git a/Misc/NEWS.d/next/Library/2018-06-29-12-23-34.bpo-33978.y4csIw.rst b/Misc/NEWS.d/next/Library/2018-06-29-12-23-34.bpo-33978.y4csIw.rst new file mode 100644 index 000000000000..12638957ee38 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-06-29-12-23-34.bpo-33978.y4csIw.rst @@ -0,0 +1,2 @@ +Closed existing logging handlers before reconfiguration via fileConfig +and dictConfig. Patch by Karthikeyan Singaravelan. From webhook-mailer at python.org Mon Jul 2 05:35:55 2018 From: webhook-mailer at python.org (Vinay Sajip) Date: Mon, 02 Jul 2018 09:35:55 -0000 Subject: [Python-checkins] [3.6] bpo-33978: Close existing handlers before logging (re-)configuration. (GH-8008). (GH-8045) Message-ID: https://github.com/python/cpython/commit/b6c1989168efeb8b6320bec958e7e339270ac0ce commit: b6c1989168efeb8b6320bec958e7e339270ac0ce branch: 3.6 author: Xtreak committer: Vinay Sajip date: 2018-07-02T10:35:52+01:00 summary: [3.6] bpo-33978: Close existing handlers before logging (re-)configuration. (GH-8008). (GH-8045) (cherry picked from commit 087570af6d5d39b51bdd5e660a53903960e58678) Co-authored-by: Xtreak files: A Misc/NEWS.d/next/Library/2018-06-29-12-23-34.bpo-33978.y4csIw.rst M Lib/logging/config.py M Lib/test/test_logging.py diff --git a/Lib/logging/config.py b/Lib/logging/config.py index 8a99923bf31e..cabddc58cf05 100644 --- a/Lib/logging/config.py +++ b/Lib/logging/config.py @@ -78,8 +78,8 @@ def fileConfig(fname, defaults=None, disable_existing_loggers=True): # critical section logging._acquireLock() try: - logging._handlers.clear() - del logging._handlerList[:] + _clearExistingHandlers() + # Handlers add themselves to logging._handlers handlers = _install_handlers(cp, formatters) _install_loggers(cp, handlers, disable_existing_loggers) @@ -268,6 +268,14 @@ def _install_loggers(cp, handlers, disable_existing): # logger.disabled = 1 _handle_existing_loggers(existing, child_loggers, disable_existing) + +def _clearExistingHandlers(): + """Clear and close existing handlers""" + logging._handlers.clear() + logging.shutdown(logging._handlerList[:]) + del logging._handlerList[:] + + IDENTIFIER = re.compile('^[a-z_][a-z0-9_]*$', re.I) @@ -527,8 +535,7 @@ def configure(self): else: disable_existing = config.pop('disable_existing_loggers', True) - logging._handlers.clear() - del logging._handlerList[:] + _clearExistingHandlers() # Do formatters first - they don't refer to anything else formatters = config.get('formatters', EMPTY_DICT) diff --git a/Lib/test/test_logging.py b/Lib/test/test_logging.py index d341ef8779bd..36d88ac63781 100644 --- a/Lib/test/test_logging.py +++ b/Lib/test/test_logging.py @@ -1076,6 +1076,7 @@ class ConfigFileTest(BaseTest): """Reading logging config from a .ini-style config file.""" + check_no_resource_warning = support.check_no_resource_warning expected_log_pat = r"^(\w+) \+\+ (\w+)$" # config0 is a standard configuration. @@ -1284,6 +1285,27 @@ class ConfigFileTest(BaseTest): datefmt= """ + # config 8, check for resource warning + config8 = r""" + [loggers] + keys=root + + [handlers] + keys=file + + [formatters] + keys= + + [logger_root] + level=DEBUG + handlers=file + + [handler_file] + class=FileHandler + level=DEBUG + args=("{tempfile}",) + """ + disable_test = """ [loggers] keys=root @@ -1429,6 +1451,29 @@ def test_config7_ok(self): # Original logger output is empty. self.assert_log_lines([]) + def test_config8_ok(self): + + def cleanup(h1, fn): + h1.close() + os.remove(fn) + + with self.check_no_resource_warning(): + fd, fn = tempfile.mkstemp(".log", "test_logging-X-") + os.close(fd) + + # Replace single backslash with double backslash in windows + # to avoid unicode error during string formatting + if os.name == "nt": + fn = fn.replace("\\", "\\\\") + + config8 = self.config8.format(tempfile=fn) + + self.apply_config(config8) + self.apply_config(config8) + + handler = logging.root.handlers[0] + self.addCleanup(cleanup, handler, fn) + def test_logger_disabling(self): self.apply_config(self.disable_test) logger = logging.getLogger('some_pristine_logger') @@ -1977,6 +2022,7 @@ class ConfigDictTest(BaseTest): """Reading logging config from a dictionary.""" + check_no_resource_warning = support.check_no_resource_warning expected_log_pat = r"^(\w+) \+\+ (\w+)$" # config0 is a standard configuration. @@ -2851,6 +2897,35 @@ def test_config14_ok(self): logging.warning('Exclamation') self.assertTrue(output.getvalue().endswith('Exclamation!\n')) + def test_config15_ok(self): + + def cleanup(h1, fn): + h1.close() + os.remove(fn) + + with self.check_no_resource_warning(): + fd, fn = tempfile.mkstemp(".log", "test_logging-X-") + os.close(fd) + + config = { + "version": 1, + "handlers": { + "file": { + "class": "logging.FileHandler", + "filename": fn + } + }, + "root": { + "handlers": ["file"] + } + } + + self.apply_config(config) + self.apply_config(config) + + handler = logging.root.handlers[0] + self.addCleanup(cleanup, handler, fn) + @unittest.skipUnless(threading, 'listen() needs threading to work') def setup_via_listener(self, text, verify=None): text = text.encode("utf-8") diff --git a/Misc/NEWS.d/next/Library/2018-06-29-12-23-34.bpo-33978.y4csIw.rst b/Misc/NEWS.d/next/Library/2018-06-29-12-23-34.bpo-33978.y4csIw.rst new file mode 100644 index 000000000000..12638957ee38 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-06-29-12-23-34.bpo-33978.y4csIw.rst @@ -0,0 +1,2 @@ +Closed existing logging handlers before reconfiguration via fileConfig +and dictConfig. Patch by Karthikeyan Singaravelan. From webhook-mailer at python.org Mon Jul 2 06:22:02 2018 From: webhook-mailer at python.org (Eric V. Smith) Date: Mon, 02 Jul 2018 10:22:02 -0000 Subject: [Python-checkins] bpo-33961: Adjusted dataclasses docs to correct exceptions raised. (GH-7917) Message-ID: https://github.com/python/cpython/commit/24d74bd8377d38528566437e70fcd72229695ac7 commit: 24d74bd8377d38528566437e70fcd72229695ac7 branch: 3.7 author: Chris Cogdon committer: Eric V. Smith date: 2018-07-02T06:21:50-04:00 summary: bpo-33961: Adjusted dataclasses docs to correct exceptions raised. (GH-7917) files: M Doc/library/dataclasses.rst diff --git a/Doc/library/dataclasses.rst b/Doc/library/dataclasses.rst index b26f6422db91..9835c480d0ea 100644 --- a/Doc/library/dataclasses.rst +++ b/Doc/library/dataclasses.rst @@ -60,8 +60,9 @@ Module-level decorators, classes, and functions The :func:`dataclass` decorator will add various "dunder" methods to the class, described below. If any of the added methods already - exist on the class, a :exc:`TypeError` will be raised. The decorator - returns the same class that is called on: no new class is created. + exist on the class, the behavior depends on the parameter, as documented + below. The decorator returns the same class that is called on; no new + class is created. If :func:`dataclass` is used just as a simple decorator with no parameters, it acts as if it has the default values documented in this @@ -115,7 +116,7 @@ Module-level decorators, classes, and functions If the class already defines any of :meth:`__lt__`, :meth:`__le__`, :meth:`__gt__`, or :meth:`__ge__`, then - :exc:`ValueError` is raised. + :exc:`TypeError` is raised. - ``unsafe_hash``: If ``False`` (the default), a :meth:`__hash__` method is generated according to how ``eq`` and ``frozen`` are set. From webhook-mailer at python.org Mon Jul 2 15:56:31 2018 From: webhook-mailer at python.org (larryhastings) Date: Mon, 02 Jul 2018 19:56:31 -0000 Subject: [Python-checkins] Doc: Backport language switcher (bpo-33700, bpo-31045) (#8048) Message-ID: https://github.com/python/cpython/commit/1b141b9553424971639bde281feb1d4e4e586dbe commit: 1b141b9553424971639bde281feb1d4e4e586dbe branch: 3.5 author: Julien Palard committer: larryhastings date: 2018-07-02T12:56:28-07:00 summary: Doc: Backport language switcher (bpo-33700, bpo-31045) (#8048) files: A Doc/tools/static/switchers.js D Doc/tools/static/version_switch.js M Doc/Makefile M Doc/conf.py M Doc/tools/templates/layout.html diff --git a/Doc/Makefile b/Doc/Makefile index 7f3e216c70e8..5c9c2e798f1f 100644 --- a/Doc/Makefile +++ b/Doc/Makefile @@ -184,12 +184,12 @@ serve: # for development releases: always build autobuild-dev: - make dist SPHINXOPTS='$(SPHINXOPTS) -Ea -A daily=1 -A versionswitcher=1' + make dist SPHINXOPTS='$(SPHINXOPTS) -Ea -A daily=1 -A switcher=1' -make suspicious # for quick rebuilds (HTML only) autobuild-dev-html: - make html SPHINXOPTS='$(SPHINXOPTS) -Ea -A daily=1 -A versionswitcher=1' + make html SPHINXOPTS='$(SPHINXOPTS) -Ea -A daily=1 -A switcher=1' # for stable releases: only build if not in pre-release stage (alpha, beta) # release candidate downloads are okay, since the stable tree can be in that stage diff --git a/Doc/conf.py b/Doc/conf.py index 4145fd5a90a7..f7073d116a48 100644 --- a/Doc/conf.py +++ b/Doc/conf.py @@ -90,13 +90,17 @@ # ------------------------ # Get LaTeX to handle Unicode correctly -latex_elements = {'inputenc': r'\usepackage[utf8x]{inputenc}', 'utf8extra': ''} +latex_elements = { + 'inputenc': r'\usepackage[utf8x]{inputenc}', + 'utf8extra': '', + 'fontenc': r'\usepackage[T1,T2A]{fontenc}', +} # Additional stuff for the LaTeX preamble. latex_elements['preamble'] = r''' \authoraddress{ - \strong{Python Software Foundation}\\ - Email: \email{docs at python.org} + \sphinxstrong{Python Software Foundation}\\ + Email: \sphinxemail{docs at python.org} } \let\Verbatim=\OriginalVerbatim \let\endVerbatim=\endOriginalVerbatim @@ -106,7 +110,7 @@ latex_elements['papersize'] = 'a4' # The font size ('10pt', '11pt' or '12pt'). -latex_elements['font_size'] = '10pt' +latex_elements['pointsize'] = '10pt' # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, author, document class [howto/manual]). diff --git a/Doc/tools/static/switchers.js b/Doc/tools/static/switchers.js new file mode 100644 index 000000000000..d885ff2bbf21 --- /dev/null +++ b/Doc/tools/static/switchers.js @@ -0,0 +1,147 @@ +(function() { + 'use strict'; + + // Parses versions in URL segments like: + // "3", "dev", "release/2.7" or "3.6rc2" + var version_regexs = [ + '(?:\\d)', + '(?:\\d\\.\\d[\\w\\d\\.]*)', + '(?:dev)', + '(?:release/\\d.\\d[\\x\\d\\.]*)']; + + var all_versions = { + '3.8': 'dev (3.8)', + '3.7': '3.7', + '3.6': '3.6', + '3.5': '3.5', + '2.7': '2.7', + }; + + var all_languages = { + 'en': 'English', + 'fr': 'French', + 'ja': 'Japanese', + 'ko': 'Korean', + }; + + function build_version_select(current_version, current_release) { + var buf = [''); + return buf.join(''); + } + + function build_language_select(current_language) { + var buf = [''); + return buf.join(''); + } + + function navigate_to_first_existing(urls) { + // Navigate to the first existing URL in urls. + var url = urls.shift(); + if (urls.length == 0) { + window.location.href = url; + return; + } + $.ajax({ + url: url, + success: function() { + window.location.href = url; + }, + error: function() { + navigate_to_first_existing(urls); + } + }); + } + + function on_version_switch() { + var selected_version = $(this).children('option:selected').attr('value') + '/'; + var url = window.location.href; + var current_language = language_segment_from_url(url); + var current_version = version_segment_in_url(url); + var new_url = url.replace('.org/' + current_language + current_version, + '.org/' + current_language + selected_version); + if (new_url != url) { + navigate_to_first_existing([ + new_url, + url.replace('.org/' + current_language + current_version, + '.org/' + selected_version), + 'https://docs.python.org/' + current_language + selected_version, + 'https://docs.python.org/' + selected_version, + 'https://docs.python.org/' + ]); + } + } + + function on_language_switch() { + var selected_language = $(this).children('option:selected').attr('value') + '/'; + var url = window.location.href; + var current_language = language_segment_from_url(url); + var current_version = version_segment_in_url(url); + if (selected_language == 'en/') // Special 'default' case for english. + selected_language = ''; + var new_url = url.replace('.org/' + current_language + current_version, + '.org/' + selected_language + current_version); + if (new_url != url) { + navigate_to_first_existing([ + new_url, + 'https://docs.python.org/' + ]); + } + } + + // Returns the path segment of the language as a string, like 'fr/' + // or '' if not found. + function language_segment_from_url(url) { + var language_regexp = '\.org/([a-z]{2}(?:-[a-z]{2})?/)'; + var match = url.match(language_regexp); + if (match !== null) + return match[1]; + return ''; + } + + // Returns the path segment of the version as a string, like '3.6/' + // or '' if not found. + function version_segment_in_url(url) { + var language_segment = '(?:[a-z]{2}(?:-[a-z]{2})?/)'; + var version_segment = '(?:(?:' + version_regexs.join('|') + ')/)'; + var version_regexp = '\\.org/' + language_segment + '?(' + version_segment + ')'; + var match = url.match(version_regexp); + if (match !== null) + return match[1]; + return '' + } + + $(document).ready(function() { + var release = DOCUMENTATION_OPTIONS.VERSION; + var language_segment = language_segment_from_url(window.location.href); + var current_language = language_segment.replace(/\/+$/g, '') || 'en'; + var version = release.substr(0, 3); + var version_select = build_version_select(version, release); + + $('.version_switcher_placeholder').html(version_select); + $('.version_switcher_placeholder select').bind('change', on_version_switch); + + var language_select = build_language_select(current_language); + + $('.language_switcher_placeholder').html(language_select); + $('.language_switcher_placeholder select').bind('change', on_language_switch); + }); +})(); diff --git a/Doc/tools/static/version_switch.js b/Doc/tools/static/version_switch.js deleted file mode 100644 index 0c17aa9dd54d..000000000000 --- a/Doc/tools/static/version_switch.js +++ /dev/null @@ -1,66 +0,0 @@ -(function() { - 'use strict'; - - var all_versions = { - '3.8': 'dev (3.8)', - '3.7': '3.7', - '3.6': '3.6', - '3.5': '3.5', - '2.7': '2.7', - }; - - function build_select(current_version, current_release) { - var buf = [''); - return buf.join(''); - } - - function patch_url(url, new_version) { - var url_re = /\.org\/(\d|py3k|dev|((release\/)?\d\.\d[\w\d\.]*))\//, - new_url = url.replace(url_re, '.org/' + new_version + '/'); - - if (new_url == url && !new_url.match(url_re)) { - // python 2 url without version? - new_url = url.replace(/\.org\//, '.org/' + new_version + '/'); - } - return new_url; - } - - function on_switch() { - var selected = $(this).children('option:selected').attr('value'); - - var url = window.location.href, - new_url = patch_url(url, selected); - - if (new_url != url) { - // check beforehand if url exists, else redirect to version's start page - $.ajax({ - url: new_url, - success: function() { - window.location.href = new_url; - }, - error: function() { - window.location.href = 'https://docs.python.org/' + selected; - } - }); - } - } - - $(document).ready(function() { - var release = DOCUMENTATION_OPTIONS.VERSION; - var version = release.substr(0, 3); - var select = build_select(version, release); - - $('.version_switcher_placeholder').html(select); - $('.version_switcher_placeholder select').bind('change', on_switch); - }); -})(); diff --git a/Doc/tools/templates/layout.html b/Doc/tools/templates/layout.html index 640d8b304932..c2106678ac60 100644 --- a/Doc/tools/templates/layout.html +++ b/Doc/tools/templates/layout.html @@ -4,7 +4,8 @@ style="vertical-align: middle; margin-top: -1px"/>
  • Python{{ reldelim1 }}
  • - {%- if versionswitcher is defined %} + {%- if switchers is defined %} + {{ language or 'en' }} {{ release }} {% trans %}Documentation {% endtrans %}{{ reldelim1 }} {%- else %} @@ -41,7 +42,7 @@ {% if builder != "htmlhelp" %} {% if not embedded %}{% endif %} - {% if versionswitcher is defined and not embedded %}{% endif %} + {% if switchers is defined and not embedded %}{% endif %} {% if pagename == 'whatsnew/changelog' and not embedded %}