From f4ced1b4f0be208c15f186559ad3763568996cd3 Mon Sep 17 00:00:00 2001 From: AA Turner <9087854+AA-Turner@users.noreply.github.com> Date: Fri, 24 Apr 2020 23:19:24 +0100 Subject: [PATCH 001/108] Current state - RFC2822 headers work - Contents page generated - Title autogeneration not working - PEP 0 not started --- _templates/layout.html | 4 ++ build.py | 15 ++++++ pepreader/__init__.py | 14 ++++++ peps/conf.py | 103 +++++++++++++++++++++++++++++++++++++++++ peps/index.rst | 27 +++++++++++ 5 files changed, 163 insertions(+) create mode 100644 _templates/layout.html create mode 100644 build.py create mode 100644 pepreader/__init__.py create mode 100644 peps/conf.py create mode 100644 peps/index.rst diff --git a/_templates/layout.html b/_templates/layout.html new file mode 100644 index 00000000000..2bd13e35d6d --- /dev/null +++ b/_templates/layout.html @@ -0,0 +1,4 @@ +{% extends "!layout.html" %} + +{# Set the delimiter after the short title on the rel-bar #} +{% set reldelim1 = ' 🡢' %} \ No newline at end of file diff --git a/build.py b/build.py new file mode 100644 index 00000000000..aae70f95aa9 --- /dev/null +++ b/build.py @@ -0,0 +1,15 @@ +# Build script for Sphinx documentation + +from pathlib import Path +from sphinx.application import Sphinx + +if __name__ == '__main__': + root_directory = Path('.').absolute() + docs_directory = Path(root_directory, 'peps') + source_directory = configuration_directory = docs_directory + build_directory = Path(root_directory, '_build') + doctree_directory = Path(build_directory, '.doctrees') + builder = 'html' + + app = Sphinx(source_directory, configuration_directory, build_directory, doctree_directory, builder) + app.build(force_all=True) diff --git a/pepreader/__init__.py b/pepreader/__init__.py new file mode 100644 index 00000000000..b22124725e2 --- /dev/null +++ b/pepreader/__init__.py @@ -0,0 +1,14 @@ +"""Docutils CommonMark parser""" +from sphinx.application import Sphinx + +__version__ = '1.0.0' + + +def setup(app: Sphinx): + """Initialize Sphinx extension.""" + from .pep_parser import PEPParser, PEPTitleCollector + + # app.add_env_collector(PEPTitleCollector) + app.add_source_parser(PEPParser) + + return {'version': __version__, 'parallel_read_safe': True} \ No newline at end of file diff --git a/peps/conf.py b/peps/conf.py new file mode 100644 index 00000000000..26cb5a1e8bb --- /dev/null +++ b/peps/conf.py @@ -0,0 +1,103 @@ +# Configuration file for the Sphinx documentation builder. + +# -- Path setup -------------------------------------------------------------- + +import docutils +from docutils.readers import standalone +from docutils.transforms import frontmatter, references, misc + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +# +# import os +# import sys +# sys.path.insert(0, os.path.abspath('.')) + + +# -- Project information ----------------------------------------------------- + +project = 'peps' +copyright = '2020, AUTHNAME' +author = 'AUTHNAME' + +# The full version, including alpha/beta/rc tags +release = '1.0.0' + +html_title = "Python Enhancement Proposals (PEPs)" +html_short_title = "PEPs Home" # +html_show_copyright = False +html_show_sphinx = False + +# -- General configuration --------------------------------------------------- + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. +extensions = ["pepreader"] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The file extensions of source files. Sphinx considers the files with +# these suffixes as sources. +source_suffix = { + '.rst': 'pep', + '.txt': 'pep', +} + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +# This pattern also affects html_static_path and html_extra_path. +exclude_patterns = [ + '_build', + 'Thumbs.db', + '.DS_Store', + 'venv', + 'build', + 'README.rst', + 'CONTRIBUTING.rst' +] + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'sphinx' + +# -- Options for HTML output ------------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +# +html_theme = 'classic' + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +# html_static_path = ['_static'] + + +def new_get_transforms(self): + # Replicate result of standalone.Reader.get_transforms() + transforms = docutils.readers.Reader.get_transforms(self) + [ + references.Substitutions, + references.PropagateTargets, + frontmatter.DocTitle, + frontmatter.SectionSubTitle, + frontmatter.DocInfo, + references.AnonymousHyperlinks, + references.IndirectHyperlinks, + references.Footnotes, + references.ExternalTargets, + references.InternalTargets, + references.DanglingReferences, + misc.Transitions, + ] + + # Explicitly remove these transforms, as we implement PEP-specific pre-processing + # transforms.remove(frontmatter.DocTitle) + # transforms.remove(frontmatter.SectionSubTitle) + transforms.remove(frontmatter.DocInfo) + + return transforms + + +standalone.Reader.get_transforms = new_get_transforms diff --git a/peps/index.rst b/peps/index.rst new file mode 100644 index 00000000000..8c23bf7359a --- /dev/null +++ b/peps/index.rst @@ -0,0 +1,27 @@ +PEP: 9999 +Title: Sphinx Index + +.. peps documentation master file, created by + sphinx-quickstart on Thu Apr 23 17:23:18 2020. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +Welcome to peps's documentation! +================================ + +.. toctree:: + :maxdepth: 3 + :titlesonly: + :glob: + :caption: Contents: + + pep-* + + + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` From f83e08f69b187d29c7d8bc5f9a4712526428acd4 Mon Sep 17 00:00:00 2001 From: AA Turner <9087854+AA-Turner@users.noreply.github.com> Date: Sat, 25 Apr 2020 17:19:47 +0100 Subject: [PATCH 002/108] Fix title generation Also add pep_parser as I missed it --- pepreader/__init__.py | 3 +- pepreader/pep_parser.py | 179 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 180 insertions(+), 2 deletions(-) create mode 100644 pepreader/pep_parser.py diff --git a/pepreader/__init__.py b/pepreader/__init__.py index b22124725e2..1568c24623a 100644 --- a/pepreader/__init__.py +++ b/pepreader/__init__.py @@ -6,9 +6,8 @@ def setup(app: Sphinx): """Initialize Sphinx extension.""" - from .pep_parser import PEPParser, PEPTitleCollector + from .pep_parser import PEPParser - # app.add_env_collector(PEPTitleCollector) app.add_source_parser(PEPParser) return {'version': __version__, 'parallel_read_safe': True} \ No newline at end of file diff --git a/pepreader/pep_parser.py b/pepreader/pep_parser.py new file mode 100644 index 00000000000..0e4250dac80 --- /dev/null +++ b/pepreader/pep_parser.py @@ -0,0 +1,179 @@ +import re + +from docutils import nodes, utils +from docutils.transforms import peps, Transform, parts +from sphinx import parsers +from docutils.parsers.rst import states + + +class DataError(Exception): + pass + + +class PEPParser(parsers.RSTParser): + supported = ("pep", "python-enhancement-proposal") + + def __init__(self): + super().__init__(rfc2822=True) + + def get_transforms(self): + transforms = super().get_transforms() + transforms.extend([ + PEPHeaders, + PEPTitle, + PEPContents, + ]) + return transforms + + +# PEPHeaders is identical to docutils.transforms.peps.Headers excepting bdfl-delegate, sponsor & superseeded-by +class PEPHeaders(Transform): + + """ + Process fields in a PEP's initial RFC-2822 header. + """ + + default_priority = 360 + + pep_url = "pep-%04d" + pep_cvs_url = "https://github.com/python/peps/blob/master/pep-%04d.txt" + + rcs_keyword_substitutions = [(re.compile(r"\$[a-zA-Z]+: (.+) \$$"), r"\1")] + + def apply(self): + if not len(self.document): + # @@@ replace these DataErrors with proper system messages + raise DataError("Document tree is empty.") + + header = self.document[0] + if not isinstance(header, nodes.field_list) or "rfc2822" not in header["classes"]: + raise DataError("Document does not begin with an RFC-2822 header; it is not a PEP.") + + cvs_url = None + pep = None + pep_field = header[0] + if pep_field[0].astext().lower() == "pep": # should be the first field + value = pep_field[1].astext() + try: + pep = int(value) + cvs_url = self.pep_cvs_url % pep + except ValueError: + pep = value + msg = self.document.reporter.warning( + f"'PEP' header must contain an integer; '{pep}' is an invalid value.", + base_node=pep_field, + ) + msgid = self.document.set_id(msg) + prb = nodes.problematic(value, value or "(none)", refid=msgid) + prbid = self.document.set_id(prb) + msg.add_backref(prbid) + if len(pep_field[1]): + pep_field[1][0][:] = [prb] + else: + pep_field[1] += nodes.paragraph("", "", prb) + + if pep is None: + raise DataError('Document does not contain an RFC-2822 "PEP" ' "header.") + + if pep == 0: + # Special processing for PEP 0. + pending = nodes.pending(peps.PEPZero) + self.document.insert(1, pending) + self.document.note_pending(pending) + + # If there are less than two headers in the preamble, or if Title is absent + if len(header) < 2 or header[1][0].astext().lower() != "title": + raise DataError("No title!") + + for field in header: + name = field[0].astext().lower() + body = field[1] + if len(body) > 1: + raise DataError(f"PEP header field body contains multiple elements:\n{field.pformat(level=1)}") + elif len(body) == 1: + if not isinstance(body[0], nodes.paragraph): + raise DataError(f"PEP header field body may only contain a single paragraph:\n{field.pformat(level=1)}") + else: + # body is empty + continue + + para = body[0] + if name in ("author", "bdfl-delegate", "sponsor"): + for node in para: + if isinstance(node, nodes.reference): + node.replace_self(peps.mask_email(node)) + elif name == "discussions-to": + for node in para: + if isinstance(node, nodes.reference): + node.replace_self(peps.mask_email(node, pep)) + elif name in ("replaces", "superseded-by", "requires"): + newbody = [] + space = nodes.Text(" ") + for refpep in re.split(r",?\s+", body.astext()): + pepno = int(refpep) + newbody.append(nodes.reference( + refpep, refpep, + refuri=(self.document.settings.pep_base_url + + self.pep_url % pepno))) + newbody.append(space) + para[:] = newbody[:-1] # drop trailing space + elif name == "last-modified": + utils.clean_rcs_keywords(para, self.rcs_keyword_substitutions) + if cvs_url: + date = para.astext() + para[:] = [nodes.reference("", date, refuri=cvs_url)] + elif name == "content-type": + pep_type = para.astext() + uri = self.document.settings.pep_base_url + self.pep_url % 12 + para[:] = [nodes.reference("", pep_type, refuri=uri)] + elif name == "version" and len(body): + utils.clean_rcs_keywords(para, self.rcs_keyword_substitutions) + + +class PEPTitle(Transform): + + """ + Insert an empty table of contents topic and a transform placeholder into + the document after the RFC 2822 header. + """ + + default_priority = 370 + + def apply(self): + title_str = 'PEP INDEX TTL TST' + pep_title_node = nodes.section() + + textnode = nodes.Text(title_str, title_str) + titlenode = nodes.title(title_str, '', textnode) + name = states.normalize_name(titlenode.astext()) + pep_title_node['names'].append(name) + pep_title_node += titlenode + + document_children = self.document.children + self.document.children = [pep_title_node] + pep_title_node.extend(document_children) + + self.document.note_implicit_target(pep_title_node, pep_title_node) + + +class PEPContents(Transform): + + """ + Insert an empty table of contents topic and a transform placeholder into + the document after the RFC 2822 header. + """ + + default_priority = 380 + + def apply(self): + title = nodes.title('', 'contents') + topic = nodes.topic('', title, classes=['contents']) + name = nodes.fully_normalize_name('contents') + if not self.document.has_name(name): + topic['names'].append(name) + self.document.note_implicit_target(topic) + pending = nodes.pending(parts.Contents) + topic += pending + self.document.children[0].insert(1, topic) + self.document.note_pending(pending) + From 9cd91e461236f3aad7fb36ea903adec283a76ac6 Mon Sep 17 00:00:00 2001 From: AA Turner <9087854+AA-Turner@users.noreply.github.com> Date: Sat, 25 Apr 2020 17:20:49 +0100 Subject: [PATCH 003/108] Fix contents section location --- pepreader/pep_parser.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pepreader/pep_parser.py b/pepreader/pep_parser.py index 0e4250dac80..c0ac6041d53 100644 --- a/pepreader/pep_parser.py +++ b/pepreader/pep_parser.py @@ -174,6 +174,6 @@ def apply(self): self.document.note_implicit_target(topic) pending = nodes.pending(parts.Contents) topic += pending - self.document.children[0].insert(1, topic) + self.document.children[0].insert(2, topic) self.document.note_pending(pending) From 4a36065d4d792ff0c4d1ca6e4647a94aabde8b22 Mon Sep 17 00:00:00 2001 From: AA Turner <9087854+AA-Turner@users.noreply.github.com> Date: Sat, 25 Apr 2020 23:42:34 +0100 Subject: [PATCH 004/108] Clarify contents page --- peps/index.rst => contents.rst | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) rename peps/index.rst => contents.rst (57%) diff --git a/peps/index.rst b/contents.rst similarity index 57% rename from peps/index.rst rename to contents.rst index 8c23bf7359a..ce25a569a64 100644 --- a/peps/index.rst +++ b/contents.rst @@ -1,27 +1,16 @@ PEP: 9999 -Title: Sphinx Index +Title: Sphinx Index Page .. peps documentation master file, created by sphinx-quickstart on Thu Apr 23 17:23:18 2020. You can adapt this file completely to your liking, but it should at least contain the root `toctree` directive. -Welcome to peps's documentation! -================================ .. toctree:: :maxdepth: 3 :titlesonly: :glob: - :caption: Contents: + :caption: Sphinx Table of Contents: - pep-* - - - -Indices and tables -================== - -* :ref:`genindex` -* :ref:`modindex` -* :ref:`search` + pep-* \ No newline at end of file From 62edb6e0c15504fbc834781a4e49ead0d39164fc Mon Sep 17 00:00:00 2001 From: AA Turner <9087854+AA-Turner@users.noreply.github.com> Date: Sat, 25 Apr 2020 23:43:46 +0100 Subject: [PATCH 005/108] Split pep_parser to files --- pepreader/__init__.py | 1 + pepreader/pep_contents.py | 24 ++++++ pepreader/pep_headers.py | 113 ++++++++++++++++++++++++++ pepreader/pep_parser.py | 164 +------------------------------------- pepreader/pep_title.py | 46 +++++++++++ 5 files changed, 188 insertions(+), 160 deletions(-) create mode 100644 pepreader/pep_contents.py create mode 100644 pepreader/pep_headers.py create mode 100644 pepreader/pep_title.py diff --git a/pepreader/__init__.py b/pepreader/__init__.py index 1568c24623a..33c02d5f360 100644 --- a/pepreader/__init__.py +++ b/pepreader/__init__.py @@ -7,6 +7,7 @@ def setup(app: Sphinx): """Initialize Sphinx extension.""" from .pep_parser import PEPParser + from .generate_pep_index import create_pep_zero app.add_source_parser(PEPParser) diff --git a/pepreader/pep_contents.py b/pepreader/pep_contents.py new file mode 100644 index 00000000000..fd4e9c2a620 --- /dev/null +++ b/pepreader/pep_contents.py @@ -0,0 +1,24 @@ +from docutils import nodes +from docutils.transforms import Transform, parts + + +class PEPContents(Transform): + + """ + Insert an empty table of contents topic and a transform placeholder into + the document after the RFC 2822 header. + """ + + default_priority = 380 + + def apply(self): + title = nodes.title('', 'contents') + topic = nodes.topic('', title, classes=['contents']) + name = nodes.fully_normalize_name('contents') + if not self.document.has_name(name): + topic['names'].append(name) + self.document.note_implicit_target(topic) + pending = nodes.pending(parts.Contents) + topic += pending + self.document.children[0].insert(2, topic) + self.document.note_pending(pending) diff --git a/pepreader/pep_headers.py b/pepreader/pep_headers.py new file mode 100644 index 00000000000..3b602df43c0 --- /dev/null +++ b/pepreader/pep_headers.py @@ -0,0 +1,113 @@ +import re + +from docutils import nodes, utils +from docutils.transforms import peps, Transform + + +class DataError(Exception): + pass + + +# PEPHeaders is identical to docutils.transforms.peps.Headers excepting bdfl-delegate, sponsor & superseeded-by +class PEPHeaders(Transform): + + """ + Process fields in a PEP's initial RFC-2822 header. + """ + + default_priority = 330 + + pep_url = "pep-%04d" + pep_cvs_url = "https://github.com/python/peps/blob/master/pep-%04d.txt" + + rcs_keyword_substitutions = [(re.compile(r"\$[a-zA-Z]+: (.+) \$$"), r"\1")] + + def apply(self): + if not len(self.document): + # @@@ replace these DataErrors with proper system messages + raise DataError("Document tree is empty.") + + header = self.document[0] + if not isinstance(header, nodes.field_list) or "rfc2822" not in header["classes"]: + raise DataError("Document does not begin with an RFC-2822 header; it is not a PEP.") + + cvs_url = None + pep = None + pep_field = header[0] + if pep_field[0].astext().lower() == "pep": # should be the first field + value = pep_field[1].astext() + try: + pep = int(value) + cvs_url = self.pep_cvs_url % pep + except ValueError: + pep = value + msg = self.document.reporter.warning( + f"'PEP' header must contain an integer; '{pep}' is an invalid value.", + base_node=pep_field, + ) + msgid = self.document.set_id(msg) + prb = nodes.problematic(value, value or "(none)", refid=msgid) + prbid = self.document.set_id(prb) + msg.add_backref(prbid) + if len(pep_field[1]): + pep_field[1][0][:] = [prb] + else: + pep_field[1] += nodes.paragraph("", "", prb) + + if pep is None: + raise DataError('Document does not contain an RFC-2822 "PEP" ' "header.") + + if pep == 0: + # Special processing for PEP 0. + pending = nodes.pending(peps.PEPZero) + self.document.insert(1, pending) + self.document.note_pending(pending) + + # If there are less than two headers in the preamble, or if Title is absent + if len(header) < 2 or header[1][0].astext().lower() != "title": + raise DataError("No title!") + + for field in header: + name = field[0].astext().lower() + body = field[1] + if len(body) > 1: + raise DataError(f"PEP header field body contains multiple elements:\n{field.pformat(level=1)}") + elif len(body) == 1: + if not isinstance(body[0], nodes.paragraph): + raise DataError(f"PEP header field body may only contain a single paragraph:\n{field.pformat(level=1)}") + else: + # body is empty + continue + + para = body[0] + if name in ("author", "bdfl-delegate", "sponsor"): + for node in para: + if isinstance(node, nodes.reference): + node.replace_self(peps.mask_email(node)) + elif name == "discussions-to": + for node in para: + if isinstance(node, nodes.reference): + node.replace_self(peps.mask_email(node, pep)) + elif name in ("replaces", "superseded-by", "requires"): + newbody = [] + space = nodes.Text(" ") + for refpep in re.split(r",?\s+", body.astext()): + pepno = int(refpep) + newbody.append(nodes.reference( + refpep, refpep, + refuri=(self.document.settings.pep_base_url + + self.pep_url % pepno))) + newbody.append(space) + para[:] = newbody[:-1] # drop trailing space + elif name == "last-modified": + utils.clean_rcs_keywords(para, self.rcs_keyword_substitutions) + if cvs_url: + date = para.astext() + para[:] = [nodes.reference("", date, refuri=cvs_url)] + elif name == "content-type": + pep_type = para.astext() + uri = self.document.settings.pep_base_url + self.pep_url % 12 + para[:] = [nodes.reference("", pep_type, refuri=uri)] + elif name == "version" and len(body): + utils.clean_rcs_keywords(para, self.rcs_keyword_substitutions) + diff --git a/pepreader/pep_parser.py b/pepreader/pep_parser.py index c0ac6041d53..da6f29c98c9 100644 --- a/pepreader/pep_parser.py +++ b/pepreader/pep_parser.py @@ -1,13 +1,10 @@ -import re - -from docutils import nodes, utils -from docutils.transforms import peps, Transform, parts from sphinx import parsers -from docutils.parsers.rst import states +from .pep_headers import PEPHeaders +from .pep_title import PEPTitle +from .pep_contents import PEPContents + -class DataError(Exception): - pass class PEPParser(parsers.RSTParser): @@ -24,156 +21,3 @@ def get_transforms(self): PEPContents, ]) return transforms - - -# PEPHeaders is identical to docutils.transforms.peps.Headers excepting bdfl-delegate, sponsor & superseeded-by -class PEPHeaders(Transform): - - """ - Process fields in a PEP's initial RFC-2822 header. - """ - - default_priority = 360 - - pep_url = "pep-%04d" - pep_cvs_url = "https://github.com/python/peps/blob/master/pep-%04d.txt" - - rcs_keyword_substitutions = [(re.compile(r"\$[a-zA-Z]+: (.+) \$$"), r"\1")] - - def apply(self): - if not len(self.document): - # @@@ replace these DataErrors with proper system messages - raise DataError("Document tree is empty.") - - header = self.document[0] - if not isinstance(header, nodes.field_list) or "rfc2822" not in header["classes"]: - raise DataError("Document does not begin with an RFC-2822 header; it is not a PEP.") - - cvs_url = None - pep = None - pep_field = header[0] - if pep_field[0].astext().lower() == "pep": # should be the first field - value = pep_field[1].astext() - try: - pep = int(value) - cvs_url = self.pep_cvs_url % pep - except ValueError: - pep = value - msg = self.document.reporter.warning( - f"'PEP' header must contain an integer; '{pep}' is an invalid value.", - base_node=pep_field, - ) - msgid = self.document.set_id(msg) - prb = nodes.problematic(value, value or "(none)", refid=msgid) - prbid = self.document.set_id(prb) - msg.add_backref(prbid) - if len(pep_field[1]): - pep_field[1][0][:] = [prb] - else: - pep_field[1] += nodes.paragraph("", "", prb) - - if pep is None: - raise DataError('Document does not contain an RFC-2822 "PEP" ' "header.") - - if pep == 0: - # Special processing for PEP 0. - pending = nodes.pending(peps.PEPZero) - self.document.insert(1, pending) - self.document.note_pending(pending) - - # If there are less than two headers in the preamble, or if Title is absent - if len(header) < 2 or header[1][0].astext().lower() != "title": - raise DataError("No title!") - - for field in header: - name = field[0].astext().lower() - body = field[1] - if len(body) > 1: - raise DataError(f"PEP header field body contains multiple elements:\n{field.pformat(level=1)}") - elif len(body) == 1: - if not isinstance(body[0], nodes.paragraph): - raise DataError(f"PEP header field body may only contain a single paragraph:\n{field.pformat(level=1)}") - else: - # body is empty - continue - - para = body[0] - if name in ("author", "bdfl-delegate", "sponsor"): - for node in para: - if isinstance(node, nodes.reference): - node.replace_self(peps.mask_email(node)) - elif name == "discussions-to": - for node in para: - if isinstance(node, nodes.reference): - node.replace_self(peps.mask_email(node, pep)) - elif name in ("replaces", "superseded-by", "requires"): - newbody = [] - space = nodes.Text(" ") - for refpep in re.split(r",?\s+", body.astext()): - pepno = int(refpep) - newbody.append(nodes.reference( - refpep, refpep, - refuri=(self.document.settings.pep_base_url - + self.pep_url % pepno))) - newbody.append(space) - para[:] = newbody[:-1] # drop trailing space - elif name == "last-modified": - utils.clean_rcs_keywords(para, self.rcs_keyword_substitutions) - if cvs_url: - date = para.astext() - para[:] = [nodes.reference("", date, refuri=cvs_url)] - elif name == "content-type": - pep_type = para.astext() - uri = self.document.settings.pep_base_url + self.pep_url % 12 - para[:] = [nodes.reference("", pep_type, refuri=uri)] - elif name == "version" and len(body): - utils.clean_rcs_keywords(para, self.rcs_keyword_substitutions) - - -class PEPTitle(Transform): - - """ - Insert an empty table of contents topic and a transform placeholder into - the document after the RFC 2822 header. - """ - - default_priority = 370 - - def apply(self): - title_str = 'PEP INDEX TTL TST' - pep_title_node = nodes.section() - - textnode = nodes.Text(title_str, title_str) - titlenode = nodes.title(title_str, '', textnode) - name = states.normalize_name(titlenode.astext()) - pep_title_node['names'].append(name) - pep_title_node += titlenode - - document_children = self.document.children - self.document.children = [pep_title_node] - pep_title_node.extend(document_children) - - self.document.note_implicit_target(pep_title_node, pep_title_node) - - -class PEPContents(Transform): - - """ - Insert an empty table of contents topic and a transform placeholder into - the document after the RFC 2822 header. - """ - - default_priority = 380 - - def apply(self): - title = nodes.title('', 'contents') - topic = nodes.topic('', title, classes=['contents']) - name = nodes.fully_normalize_name('contents') - if not self.document.has_name(name): - topic['names'].append(name) - self.document.note_implicit_target(topic) - pending = nodes.pending(parts.Contents) - topic += pending - self.document.children[0].insert(2, topic) - self.document.note_pending(pending) - diff --git a/pepreader/pep_title.py b/pepreader/pep_title.py new file mode 100644 index 00000000000..c27dffbf8a8 --- /dev/null +++ b/pepreader/pep_title.py @@ -0,0 +1,46 @@ +from docutils import nodes +from docutils.transforms import Transform +from docutils.parsers.rst import states, Directive + + +class PEPTitle(Transform): + + """ + Insert an empty table of contents topic and a transform placeholder into + the document after the RFC 2822 header. + """ + + # needs to run before docutils.transforms.frontmatter.DocInfo + default_priority = 335 + + def apply(self): + # Directory to hold the PEP's RFC2822 header details, to extract a titke string + pep_header_details = {} + + # Iterate through the header fields, which are the first section of the document + for field in self.document[0]: + row_attributes = {} + for sub in field: + # Hold details of the attribute's tag against its details + row_attributes[sub.tagname] = sub.rawsource + # Collapse the dictionary by removing tag names + pep_header_details[row_attributes["field_name"]] = row_attributes["field_body"] + + # Create the title string for the PEP + pep_number = int(pep_header_details["PEP"]) + pep_title = pep_header_details["Title"] + pep_title_string = f"PEP {pep_number} -- {pep_title}" + + # Generate the title section node and its properties + pep_title_node = nodes.section() + textnode = nodes.Text(pep_title_string, pep_title_string) + titlenode = nodes.title(pep_title_string, '', textnode) + name = states.normalize_name(titlenode.astext()) + pep_title_node['names'].append(name) + pep_title_node += titlenode + + # Insert the title node as the root element, move children down + document_children = self.document.children + self.document.children = [pep_title_node] + pep_title_node.extend(document_children) + self.document.note_implicit_target(pep_title_node, pep_title_node) From eb795e00082dbce2e19c7f0a7bcd7605d8f2926c Mon Sep 17 00:00:00 2001 From: AA Turner <9087854+AA-Turner@users.noreply.github.com> Date: Sat, 25 Apr 2020 23:43:59 +0100 Subject: [PATCH 006/108] Update conf --- peps/conf.py => conf.py | 49 ++++++++--------------------------------- 1 file changed, 9 insertions(+), 40 deletions(-) rename peps/conf.py => conf.py (57%) diff --git a/peps/conf.py b/conf.py similarity index 57% rename from peps/conf.py rename to conf.py index 26cb5a1e8bb..c39229a3ff2 100644 --- a/peps/conf.py +++ b/conf.py @@ -2,30 +2,24 @@ # -- Path setup -------------------------------------------------------------- -import docutils -from docutils.readers import standalone -from docutils.transforms import frontmatter, references, misc -# If extensions (or modules to document with autodoc) are in another directory, -# add these directories to sys.path here. If the directory is relative to the -# documentation root, use os.path.abspath to make it absolute, like shown here. -# -# import os -# import sys -# sys.path.insert(0, os.path.abspath('.')) +import os +import sys +sys.path.append(os.path.abspath('.')) # -- Project information ----------------------------------------------------- -project = 'peps' +project = 'PEPs' copyright = '2020, AUTHNAME' author = 'AUTHNAME' # The full version, including alpha/beta/rc tags release = '1.0.0' +version = "1.x" html_title = "Python Enhancement Proposals (PEPs)" -html_short_title = "PEPs Home" # +html_short_title = "PEPs Home" html_show_copyright = False html_show_sphinx = False @@ -56,7 +50,8 @@ 'venv', 'build', 'README.rst', - 'CONTRIBUTING.rst' + 'CONTRIBUTING.rst', + 'requirements.txt', ] # The name of the Pygments (syntax highlighting) style to use. @@ -74,30 +69,4 @@ # so a file named "default.css" will overwrite the builtin "default.css". # html_static_path = ['_static'] - -def new_get_transforms(self): - # Replicate result of standalone.Reader.get_transforms() - transforms = docutils.readers.Reader.get_transforms(self) + [ - references.Substitutions, - references.PropagateTargets, - frontmatter.DocTitle, - frontmatter.SectionSubTitle, - frontmatter.DocInfo, - references.AnonymousHyperlinks, - references.IndirectHyperlinks, - references.Footnotes, - references.ExternalTargets, - references.InternalTargets, - references.DanglingReferences, - misc.Transitions, - ] - - # Explicitly remove these transforms, as we implement PEP-specific pre-processing - # transforms.remove(frontmatter.DocTitle) - # transforms.remove(frontmatter.SectionSubTitle) - transforms.remove(frontmatter.DocInfo) - - return transforms - - -standalone.Reader.get_transforms = new_get_transforms +master_doc = 'contents' \ No newline at end of file From a13f959acc48cfd3b9f4411808f8fa0991c601b5 Mon Sep 17 00:00:00 2001 From: AA Turner <9087854+AA-Turner@users.noreply.github.com> Date: Sat, 25 Apr 2020 23:53:24 +0100 Subject: [PATCH 007/108] clean imports --- pepreader/pep_contents.py | 5 +++-- pepreader/pep_headers.py | 8 +++++--- pepreader/pep_parser.py | 12 ++++++------ pepreader/pep_title.py | 6 +++--- 4 files changed, 17 insertions(+), 14 deletions(-) diff --git a/pepreader/pep_contents.py b/pepreader/pep_contents.py index fd4e9c2a620..ac2c44f7e61 100644 --- a/pepreader/pep_contents.py +++ b/pepreader/pep_contents.py @@ -1,8 +1,9 @@ from docutils import nodes -from docutils.transforms import Transform, parts +from docutils import transforms +from docutils.transforms import parts -class PEPContents(Transform): +class PEPContents(transforms.Transform): """ Insert an empty table of contents topic and a transform placeholder into diff --git a/pepreader/pep_headers.py b/pepreader/pep_headers.py index 3b602df43c0..098352a8c34 100644 --- a/pepreader/pep_headers.py +++ b/pepreader/pep_headers.py @@ -1,7 +1,9 @@ import re -from docutils import nodes, utils -from docutils.transforms import peps, Transform +from docutils import nodes +from docutils import utils +from docutils import transforms +from docutils.transforms import peps class DataError(Exception): @@ -9,7 +11,7 @@ class DataError(Exception): # PEPHeaders is identical to docutils.transforms.peps.Headers excepting bdfl-delegate, sponsor & superseeded-by -class PEPHeaders(Transform): +class PEPHeaders(transforms.Transform): """ Process fields in a PEP's initial RFC-2822 header. diff --git a/pepreader/pep_parser.py b/pepreader/pep_parser.py index da6f29c98c9..92a69720cb6 100644 --- a/pepreader/pep_parser.py +++ b/pepreader/pep_parser.py @@ -1,7 +1,7 @@ from sphinx import parsers -from .pep_headers import PEPHeaders -from .pep_title import PEPTitle -from .pep_contents import PEPContents +from . import pep_headers +from . import pep_title +from . import pep_contents @@ -16,8 +16,8 @@ def __init__(self): def get_transforms(self): transforms = super().get_transforms() transforms.extend([ - PEPHeaders, - PEPTitle, - PEPContents, + pep_headers.PEPHeaders, + pep_title.PEPTitle, + pep_contents.PEPContents, ]) return transforms diff --git a/pepreader/pep_title.py b/pepreader/pep_title.py index c27dffbf8a8..6364e42287d 100644 --- a/pepreader/pep_title.py +++ b/pepreader/pep_title.py @@ -1,9 +1,9 @@ from docutils import nodes -from docutils.transforms import Transform -from docutils.parsers.rst import states, Directive +import docutils.transforms as transforms +from docutils.parsers.rst import states -class PEPTitle(Transform): +class PEPTitle(transforms.Transform): """ Insert an empty table of contents topic and a transform placeholder into From c7b9cea83620086123586b4832c56070505282e0 Mon Sep 17 00:00:00 2001 From: AA Turner <9087854+AA-Turner@users.noreply.github.com> Date: Sun, 26 Apr 2020 02:53:30 +0100 Subject: [PATCH 008/108] get pep 0 generation to work --- genpepindex.py | 68 ---- pep0/__init__.py | 1 - pep0/output.py | 290 ------------------ pepreader/__init__.py | 5 +- pepreader/generate_pep_index.py | 58 ++++ pep0/pep.py => pepreader/pep0.py | 176 +++++------ .../pep0_constants.py | 13 +- pepreader/pep0_writer.py | 286 +++++++++++++++++ 8 files changed, 443 insertions(+), 454 deletions(-) delete mode 100755 genpepindex.py delete mode 100644 pep0/__init__.py delete mode 100644 pep0/output.py create mode 100644 pepreader/generate_pep_index.py rename pep0/pep.py => pepreader/pep0.py (59%) rename pep0/constants.py => pepreader/pep0_constants.py (76%) create mode 100644 pepreader/pep0_writer.py diff --git a/genpepindex.py b/genpepindex.py deleted file mode 100755 index 2ab6698a05a..00000000000 --- a/genpepindex.py +++ /dev/null @@ -1,68 +0,0 @@ -#!/usr/bin/env python -"""Auto-generate PEP 0 (PEP index). - -Generating the PEP index is a multi-step process. To begin, you must first -parse the PEP files themselves, which in and of itself takes a couple of steps: - - 1. Parse metadata. - 2. Validate metadata. - -With the PEP information collected, to create the index itself you must: - - 1. Output static text. - 2. Format an entry for the PEP. - 3. Output the PEP (both by category and numerical index). - -""" -from __future__ import absolute_import, with_statement -from __future__ import print_function - -import sys -import os -import codecs - -from operator import attrgetter - -from pep0.output import write_pep0 -from pep0.pep import PEP, PEPError - - -def main(argv): - if not argv[1:]: - path = '.' - else: - path = argv[1] - - peps = [] - if os.path.isdir(path): - for file_path in os.listdir(path): - if file_path.startswith('pep-0000.'): - continue - abs_file_path = os.path.join(path, file_path) - if not os.path.isfile(abs_file_path): - continue - if file_path.startswith("pep-") and file_path.endswith((".txt", "rst")): - with codecs.open(abs_file_path, 'r', encoding='UTF-8') as pep_file: - try: - pep = PEP(pep_file) - if pep.number != int(file_path[4:-4]): - raise PEPError('PEP number does not match file name', - file_path, pep.number) - peps.append(pep) - except PEPError as e: - errmsg = "Error processing PEP %s (%s), excluding:" % \ - (e.number, e.filename) - print(errmsg, e, file=sys.stderr) - sys.exit(1) - peps.sort(key=attrgetter('number')) - elif os.path.isfile(path): - with open(path, 'r') as pep_file: - peps.append(PEP(pep_file)) - else: - raise ValueError("argument must be a directory or file path") - - with codecs.open('pep-0000.rst', 'w', encoding='UTF-8') as pep0_file: - write_pep0(peps, pep0_file) - -if __name__ == "__main__": - main(sys.argv) diff --git a/pep0/__init__.py b/pep0/__init__.py deleted file mode 100644 index b7db25411d0..00000000000 --- a/pep0/__init__.py +++ /dev/null @@ -1 +0,0 @@ -# Empty diff --git a/pep0/output.py b/pep0/output.py deleted file mode 100644 index 10024c221b8..00000000000 --- a/pep0/output.py +++ /dev/null @@ -1,290 +0,0 @@ -"""Code to handle the output of PEP 0.""" -from __future__ import absolute_import -from __future__ import print_function -import datetime -import sys -import unicodedata - -from operator import attrgetter - -from . import constants -from .pep import PEP, PEPError - -# This is a list of reserved PEP numbers. Reservations are not to be used for -# the normal PEP number allocation process - just give out the next available -# PEP number. These are for "special" numbers that may be used for semantic, -# humorous, or other such reasons, e.g. 401, 666, 754. -# -# PEP numbers may only be reserved with the approval of a PEP editor. Fields -# here are the PEP number being reserved and the claimants for the PEP. -# Although the output is sorted when PEP 0 is generated, please keep this list -# sorted as well. -RESERVED = [ - (801, 'Warsaw'), - ] - - -indent = u' ' - -def emit_column_headers(output): - """Output the column headers for the PEP indices.""" - column_headers = {'status': '.', 'type': '.', 'number': 'PEP', - 'title': 'PEP Title', 'authors': 'PEP Author(s)'} - print(constants.table_separator, file=output) - print(constants.column_format % column_headers, file=output) - print(constants.table_separator, file=output) - - -def sort_peps(peps): - """Sort PEPs into meta, informational, accepted, open, finished, - and essentially dead.""" - meta = [] - info = [] - provisional = [] - accepted = [] - open_ = [] - finished = [] - historical = [] - deferred = [] - dead = [] - for pep in peps: - # Order of 'if' statement important. Key Status values take precedence - # over Type value, and vice-versa. - if pep.status == 'Draft': - open_.append(pep) - elif pep.status == 'Deferred': - deferred.append(pep) - elif pep.type_ == 'Process': - if pep.status == "Active": - meta.append(pep) - elif pep.status in ("Withdrawn", "Rejected"): - dead.append(pep) - else: - historical.append(pep) - elif pep.status in ('Rejected', 'Withdrawn', - 'Incomplete', 'Superseded'): - dead.append(pep) - elif pep.type_ == 'Informational': - # Hack until the conflict between the use of "Final" - # for both API definition PEPs and other (actually - # obsolete) PEPs is addressed - if (pep.status == "Active" or - "Release Schedule" not in pep.title): - info.append(pep) - else: - historical.append(pep) - elif pep.status == 'Provisional': - provisional.append(pep) - elif pep.status in ('Accepted', 'Active'): - accepted.append(pep) - elif pep.status == 'Final': - finished.append(pep) - else: - raise PEPError("unsorted (%s/%s)" % - (pep.type_, pep.status), - pep.filename, pep.number) - return (meta, info, provisional, accepted, open_, - finished, historical, deferred, dead) - - -def verify_email_addresses(peps): - authors_dict = {} - for pep in peps: - for author in pep.authors: - # If this is the first time we have come across an author, add them. - if author not in authors_dict: - authors_dict[author] = [author.email] - else: - found_emails = authors_dict[author] - # If no email exists for the author, use the new value. - if not found_emails[0]: - authors_dict[author] = [author.email] - # If the new email is an empty string, move on. - elif not author.email: - continue - # If the email has not been seen, add it to the list. - elif author.email not in found_emails: - authors_dict[author].append(author.email) - - valid_authors_dict = {} - too_many_emails = [] - for author, emails in authors_dict.items(): - if len(emails) > 1: - too_many_emails.append((author.first_last, emails)) - else: - valid_authors_dict[author] = emails[0] - if too_many_emails: - err_output = [] - for author, emails in too_many_emails: - err_output.append(" %s: %r" % (author, emails)) - raise ValueError("some authors have more than one email address " - "listed:\n" + '\n'.join(err_output)) - - return valid_authors_dict - - -def sort_authors(authors_dict): - authors_list = list(authors_dict.keys()) - authors_list.sort(key=attrgetter('sort_by')) - return authors_list - -def normalized_last_first(name): - return len(unicodedata.normalize('NFC', name.last_first)) - -def emit_title(text, anchor, output, *, symbol="="): - print(".. _{anchor}:\n".format(anchor=anchor), file=output) - print(text, file=output) - print(symbol*len(text), file=output) - print(file=output) - -def emit_subtitle(text, anchor, output): - emit_title(text, anchor, output, symbol="-") - -def emit_pep_category(output, category, anchor, peps): - emit_subtitle(category, anchor, output) - emit_column_headers(output) - for pep in peps: - print(pep, file=output) - print(constants.table_separator, file=output) - print(file=output) - -def write_pep0(peps, output=sys.stdout): - # PEP metadata - today = datetime.date.today().strftime("%Y-%m-%d") - print(constants.header % today, file=output) - print(file=output) - # Introduction - emit_title("Introduction", "intro", output) - print(constants.intro, file=output) - print(file=output) - # PEPs by category - (meta, info, provisional, accepted, open_, - finished, historical, deferred, dead) = sort_peps(peps) - emit_title("Index by Category", "by-category", output) - emit_pep_category( - category="Meta-PEPs (PEPs about PEPs or Processes)", - anchor="by-category-meta", - peps=meta, - output=output, - ) - emit_pep_category( - category="Other Informational PEPs", - anchor="by-category-other-info", - peps=info, - output=output, - ) - emit_pep_category( - category="Provisional PEPs (provisionally accepted; interface may still change)", - anchor="by-category-provisional", - peps=provisional, - output=output, - ) - emit_pep_category( - category="Accepted PEPs (accepted; may not be implemented yet)", - anchor="by-category-accepted", - peps=accepted, - output=output, - ) - emit_pep_category( - category="Open PEPs (under consideration)", - anchor="by-category-open", - peps=open_, - output=output, - ) - emit_pep_category( - category="Finished PEPs (done, with a stable interface)", - anchor="by-category-finished", - peps=finished, - output=output, - ) - emit_pep_category( - category="Historical Meta-PEPs and Informational PEPs", - anchor="by-category-historical", - peps=historical, - output=output, - ) - emit_pep_category( - category="Deferred PEPs (postponed pending further research or updates)", - anchor="by-category-deferred", - peps=deferred, - output=output, - ) - emit_pep_category( - category="Abandoned, Withdrawn, and Rejected PEPs", - anchor="by-category-abandoned", - peps=dead, - output=output, - ) - print(file=output) - # PEPs by number - emit_title("Numerical Index", "by-pep-number", output) - emit_column_headers(output) - prev_pep = 0 - for pep in peps: - if pep.number - prev_pep > 1: - print(file=output) - print(constants.text_type(pep), file=output) - prev_pep = pep.number - print(constants.table_separator, file=output) - print(file=output) - # Reserved PEP numbers - emit_title('Reserved PEP Numbers', "reserved", output) - emit_column_headers(output) - for number, claimants in sorted(RESERVED): - print(constants.column_format % { - 'type': '.', - 'status': '.', - 'number': number, - 'title': 'RESERVED', - 'authors': claimants, - }, file=output) - print(constants.table_separator, file=output) - print(file=output) - # PEP types key - emit_title("PEP Types Key", "type-key", output) - for type_ in sorted(PEP.type_values): - print(u" %s - %s PEP" % (type_[0], type_), file=output) - print(file=output) - print(file=output) - # PEP status key - emit_title("PEP Status Key", "status-key", output) - for status in sorted(PEP.status_values): - # Draft PEPs have no status displayed, Active shares a key with Accepted - if status in ("Active", "Draft"): - continue - if status == "Accepted": - msg = " A - Accepted (Standards Track only) or Active proposal" - else: - msg = " {status[0]} - {status} proposal".format(status=status) - print(msg, file=output) - print(file=output) - - print(file=output) - # PEP owners - emit_title("Authors/Owners", "authors", output) - authors_dict = verify_email_addresses(peps) - max_name = max(authors_dict.keys(), key=normalized_last_first) - max_name_len = len(max_name.last_first) - author_table_separator = "="*max_name_len + " " + "="*len("email address") - print(author_table_separator, file=output) - _author_header_fmt = "{name:{max_name_len}} Email Address" - print(_author_header_fmt.format(name="Name", max_name_len=max_name_len), file=output) - print(author_table_separator, file=output) - sorted_authors = sort_authors(authors_dict) - _author_fmt = "{author.last_first:{max_name_len}} {author_email}" - for author in sorted_authors: - # Use the email from authors_dict instead of the one from 'author' as - # the author instance may have an empty email. - _entry = _author_fmt.format( - author=author, - author_email=authors_dict[author], - max_name_len=max_name_len, - ) - print(_entry, file=output) - print(author_table_separator, file=output) - print(file=output) - print(file=output) - # References for introduction footnotes - emit_title("References", "references", output) - print(constants.references, file=output) - print(constants.footer, file=output) diff --git a/pepreader/__init__.py b/pepreader/__init__.py index 33c02d5f360..0b844fff03c 100644 --- a/pepreader/__init__.py +++ b/pepreader/__init__.py @@ -1,4 +1,4 @@ -"""Docutils CommonMark parser""" +"""Sphinx extensions for performant PEP processing""" from sphinx.application import Sphinx __version__ = '1.0.0' @@ -9,6 +9,7 @@ def setup(app: Sphinx): from .pep_parser import PEPParser from .generate_pep_index import create_pep_zero + app.connect("env-before-read-docs", create_pep_zero) app.add_source_parser(PEPParser) - return {'version': __version__, 'parallel_read_safe': True} \ No newline at end of file + return {'version': __version__, 'parallel_read_safe': True, 'parallel_write_safe': True} diff --git a/pepreader/generate_pep_index.py b/pepreader/generate_pep_index.py new file mode 100644 index 00000000000..3ae3da29659 --- /dev/null +++ b/pepreader/generate_pep_index.py @@ -0,0 +1,58 @@ +"""Automatically create PEP 0 (the PEP index) + +This file generates and writes the PEP index to disk, ready for later +processing by Sphinx. Firstly, we parse the individual PEP files, getting the +RFC2822 header, and parsing and then validating that metadata. + +After collecting and validating all the PEP data, the creation of the index +itself is in three steps: + + 1. Output static text. + 2. Format an entry for the PEP. + 3. Output the PEP (both by the category and numerical index). + +We then add the newly created PEP 0 file to two Sphinx environment variables +to allow it to be processed as normal. + +""" +import re +from operator import attrgetter +from pathlib import Path + +from . import pep0 +from . import pep0_writer + + +def create_pep_zero(_, env, docnames): + # app is unneeded by this function + + # Read from root directory + path = Path('.') + + pep_zero_filename = 'pep-0000' + peps = [] + pep_pat = re.compile(r"pep-\d{4}") # Path.match() doesn't support regular expressions + + for file_path in path.iterdir(): + if not file_path.is_file(): + continue # Skip directories etc. + if file_path.match('pep-0000*'): + continue # Skip pre-existing PEP 0 files + if pep_pat.match(str(file_path)) and file_path.suffix in (".txt", ".rst"): + file_path_absolute = path.joinpath(file_path).absolute() + pep_text = file_path_absolute.read_text("UTF8") + pep = pep0.PEP(pep_text, file_path_absolute) + if pep.number != int(file_path.stem[4:]): + raise pep0.PEPError(f'PEP number does not match file name ({file_path})', file_path, pep.number) + peps.append(pep) + peps.sort(key=attrgetter('number')) + + pep_writer = pep0_writer.PEPZeroWriter() + pep0_text = pep_writer.write_pep0(peps) + with open(pep_zero_filename + ".rst", 'w', encoding='UTF-8') as pep0_file: + pep0_file.write(pep0_text) + + # Add to files for builder + docnames.insert(1, pep_zero_filename) + # Add to files for writer + env.found_docs.add(pep_zero_filename) diff --git a/pep0/pep.py b/pepreader/pep0.py similarity index 59% rename from pep0/pep.py rename to pepreader/pep0.py index e01518df539..29359173973 100644 --- a/pep0/pep.py +++ b/pepreader/pep0.py @@ -1,18 +1,15 @@ # -*- coding: utf-8 -*- """Code for handling object representation of a PEP.""" -from __future__ import absolute_import import re -import sys import textwrap import unicodedata from email.parser import HeaderParser -from . import constants +from . import pep0_constants class PEPError(Exception): - def __init__(self, error, pep_file, pep_number=None): super(PEPError, self).__init__(error) self.filename = pep_file @@ -21,9 +18,9 @@ def __init__(self, error, pep_file, pep_number=None): def __str__(self): error_msg = super(PEPError, self).__str__() if self.number is not None: - return "PEP %d: %r" % (self.number, error_msg) + return f"PEP {self.number}: {error_msg}" else: - return "(%s): %r" % (self.filename, error_msg) + return f"({self.filename}): {error_msg}" class PEPParseError(PEPError): @@ -69,16 +66,16 @@ def __init__(self, author_and_email_tuple): name_sep = name.index(last_name_fragment) self.first = name[:name_sep].rstrip() self.last = last_name_fragment - if self.last[1] == u'.': + if self.last[1] == ".": # Add an escape to avoid docutils turning `v.` into `22.`. - self.last = u'\\' + self.last + self.last = "\\" + self.last self.suffix = suffix if not self.first: self.last_first = self.last else: - self.last_first = u', '.join([self.last, self.first]) + self.last_first = ", ".join([self.last, self.first]) if self.suffix: - self.last_first += u', ' + self.suffix + self.last_first += ", " + self.suffix if self.last == "van Rossum": # Special case for our beloved BDFL. :) if self.first == "Guido": @@ -86,8 +83,8 @@ def __init__(self, author_and_email_tuple): elif self.first == "Just": self.nick = "JvR" else: - raise ValueError("unknown van Rossum %r!" % self) - self.last_first += " (%s)" % (self.nick,) + raise ValueError(f"unknown van Rossum {self}!") + self.last_first += f" ({self.nick})" else: self.nick = self.last @@ -102,14 +99,15 @@ def sort_by(self): name_parts = self.last.split() for index, part in enumerate(name_parts): if part[0].isupper(): - base = u' '.join(name_parts[index:]).lower() + base = " ".join(name_parts[index:]).lower() break else: # If no capitals, use the whole string base = self.last.lower() - return unicodedata.normalize('NFKD', base).encode('ASCII', 'ignore') + return unicodedata.normalize("NFKD", base) - def _last_name(self, full_name): + @staticmethod + def _last_name(full_name): """Find the last name (or nickname) of a full name. If no last name (e.g, 'Aahz') then return the full name. If there is @@ -118,7 +116,7 @@ def _last_name(self, full_name): through a comma, then drop the suffix. """ - name_partition = full_name.partition(u',') + name_partition = full_name.partition(",") no_suffix = name_partition[0].strip() suffix = name_partition[2].strip() name_parts = no_suffix.split() @@ -128,7 +126,7 @@ def _last_name(self, full_name): else: assert part_count > 2 if name_parts[-2].islower(): - return u' '.join(name_parts[-2:]), suffix + return " ".join(name_parts[-2:]), suffix else: return name_parts[-1], suffix @@ -159,117 +157,118 @@ class PEP(object): # The various RFC 822 headers that are supported. # The second item in the nested tuples represents if the header is # required or not. - headers = (('PEP', True), ('Title', True), ('Version', False), - ('Last-Modified', False), ('Author', True), - ('Sponsor', False), ('BDFL-Delegate', False), - ('Discussions-To', False), ('Status', True), ('Type', True), - ('Content-Type', False), ('Requires', False), - ('Created', True), ('Python-Version', False), - ('Post-History', False), ('Replaces', False), - ('Superseded-By', False), ('Resolution', False), - ) + headers = ( + ("PEP", True), ("Title", True), ("Version", False), + ("Last-Modified", False), ("Author", True), ("Sponsor", False), + ("BDFL-Delegate", False), ("Discussions-To", False), ("Status", True), + ("Type", True), ("Content-Type", False), ("Requires", False), + ("Created", True), ("Python-Version", False), ("Post-History", False), + ("Replaces", False), ("Superseded-By", False), ("Resolution", False), + ) # Valid values for the Type header. - type_values = (u"Standards Track", u"Informational", u"Process") + type_values = ("Standards Track", "Informational", "Process") # Valid values for the Status header. # Active PEPs can only be for Informational or Process PEPs. - status_values = (u"Accepted", u"Provisional", - u"Rejected", u"Withdrawn", u"Deferred", - u"Final", u"Active", u"Draft", u"Superseded") + status_values = ( + "Accepted", "Provisional", "Rejected", "Withdrawn", + "Deferred", "Final", "Active", "Draft", "Superseded", + ) - def __init__(self, pep_file): + def __init__(self, pep_file: str, filename: str): """Init object from an open PEP file object.""" # Parse the headers. - self.filename = pep_file + self.filename = filename pep_parser = HeaderParser() - metadata = pep_parser.parse(pep_file) + metadata = pep_parser.parsestr(pep_file) header_order = iter(self.headers) + current_header = "" try: for header_name in metadata.keys(): current_header, required = next(header_order) while header_name != current_header and not required: current_header, required = next(header_order) if header_name != current_header: - raise PEPError("did not deal with " - "%r before having to handle %r" % - (header_name, current_header), - pep_file.name) + raise PEPError( + "did not deal with " + f"{header_name} before having to handle {current_header}", + filename, + ) except StopIteration: - raise PEPError("headers missing or out of order", - pep_file.name) + raise PEPError("headers missing or out of order", filename) required = False try: while not required: current_header, required = next(header_order) else: - raise PEPError("PEP is missing its %r" % (current_header,), - pep_file.name) + raise PEPError(f"PEP is missing its '{current_header}' header", filename) except StopIteration: pass # 'PEP'. try: - self.number = int(metadata['PEP']) + self.number = int(metadata["PEP"]) except ValueError: - raise PEPParseError("PEP number isn't an integer", pep_file.name) + raise PEPParseError("PEP number isn't an integer", filename) # 'Title'. - self.title = metadata['Title'] + self.title = metadata["Title"] # 'Type'. - type_ = metadata['Type'] + type_ = metadata["Type"] if type_ not in self.type_values: - raise PEPError('%r is not a valid Type value' % (type_,), - pep_file.name, self.number) + raise PEPError(f"{type_} is not a valid Type value", filename, self.number) self.type_ = type_ # 'Status'. - status = metadata['Status'] + status = metadata["Status"] if status not in self.status_values: if status == "April Fool!": # See PEP 401 :) status = "Rejected" else: - raise PEPError("%r is not a valid Status value" % - (status,), pep_file.name, self.number) + raise PEPError(f"{status} is not a valid Status value", filename, self.number) # Special case for Active PEPs. - if (status == u"Active" and - self.type_ not in ("Process", "Informational")): - raise PEPError("Only Process and Informational PEPs may " - "have an Active status", pep_file.name, - self.number) + if status == "Active" and self.type_ not in ("Process", "Informational"): + raise PEPError( + "Only Process and Informational PEPs may " "have an Active status", + filename, + self.number, + ) # Special case for Provisional PEPs. - if (status == u"Provisional" and self.type_ != "Standards Track"): - raise PEPError("Only Standards Track PEPs may " - "have a Provisional status", pep_file.name, - self.number) + if status == "Provisional" and self.type_ != "Standards Track": + raise PEPError( + "Only Standards Track PEPs may " "have a Provisional status", + filename, + self.number, + ) self.status = status # 'Author'. - authors_and_emails = self._parse_author(metadata['Author']) + authors_and_emails = self._parse_author(metadata["Author"]) if len(authors_and_emails) < 1: - raise PEPError("no authors found", pep_file.name, - self.number) + raise PEPError("no authors found", filename, self.number) self.authors = list(map(Author, authors_and_emails)) - def _parse_author(self, data): + @staticmethod + def _parse_author(data): """Return a list of author names and emails.""" # XXX Consider using email.utils.parseaddr (doesn't work with names # lacking an email address. - angled = constants.text_type(r'(?P.+?) <(?P.+?)>') - paren = constants.text_type(r'(?P.+?) \((?P.+?)\)') - simple = constants.text_type(r'(?P[^,]+)') + angled = pep0_constants.text_type(r"(?P.+?) <(?P.+?)>") + paren = pep0_constants.text_type(r"(?P.+?) \((?P.+?)\)") + simple = pep0_constants.text_type(r"(?P[^,]+)") author_list = [] for regex in (angled, paren, simple): # Watch out for commas separating multiple names. - regex += r'(,\s*)?' + regex += r"(,\s*)?" for match in re.finditer(regex, data): # Watch out for suffixes like 'Jr.' when they are comma-separated # from the name and thus cause issues when *all* names are only # separated by commas. match_dict = match.groupdict() - author = match_dict['author'] - if not author.partition(' ')[1] and author.endswith('.'): + author = match_dict["author"] + if not author.partition(" ")[1] and author.endswith("."): prev_author = author_list.pop() - author = ', '.join([prev_author, author]) - if u'email' not in match_dict: - email = '' + author = ", ".join([prev_author, author]) + if "email" not in match_dict: + email = "" else: - email = match_dict['email'] + email = match_dict["email"] author_list.append((author, email)) else: # If authors were found then stop searching as only expect one @@ -280,36 +279,37 @@ def _parse_author(self, data): @property def type_abbr(self): - """Return the how the type is to be represented in the index.""" + """Return how the type is to be represented in the index.""" return self.type_[0].upper() @property def status_abbr(self): """Return how the status should be represented in the index.""" - if self.status in ('Draft', 'Active'): - return u' ' + if self.status in ("Draft", "Active"): + return " " else: return self.status[0].upper() @property def author_abbr(self): """Return the author list as a comma-separated with only last names.""" - return u', '.join(x.nick for x in self.authors) + return ", ".join(x.nick for x in self.authors) @property def title_abbr(self): """Shorten the title to be no longer than the max title length.""" - if len(self.title) <= constants.title_length: + if len(self.title) <= pep0_constants.title_length: return self.title - wrapped_title = textwrap.wrap(self.title, constants.title_length - 4) - return wrapped_title[0] + u' ...' + wrapped_title = textwrap.wrap(self.title, pep0_constants.title_length - 4) + return wrapped_title[0] + " ..." - def __unicode__(self): + def __str__(self): """Return the line entry for the PEP.""" - pep_info = {'type': self.type_abbr, 'number': str(self.number), - 'title': self.title_abbr, 'status': self.status_abbr, - 'authors': self.author_abbr} - return constants.column_format % pep_info - - if sys.version_info[0] > 2: - __str__ = __unicode__ + pep_info = { + "type": self.type_abbr, + "number": str(self.number), + "title": self.title_abbr, + "status": self.status_abbr, + "authors": self.author_abbr, + } + return pep0_constants.column_format(**pep_info) diff --git a/pep0/constants.py b/pepreader/pep0_constants.py similarity index 76% rename from pep0/constants.py rename to pepreader/pep0_constants.py index e40293f44a9..57e96e9e1d7 100644 --- a/pep0/constants.py +++ b/pepreader/pep0_constants.py @@ -1,17 +1,20 @@ # -*- coding: utf-8 -*- +from functools import partial text_type = str title_length = 55 author_length = 40 table_separator = "== ==== " + "="*title_length + " " + "="*author_length -column_format = ( - '%(type)1s%(status)1s %(number)4s %(title)-{title_length}s %(authors)-s' -).format(title_length=title_length) +# column format is called as a function with a mapping containing field values +column_format = partial( + "{type}{status}{number: >5} {title: <{title_length}} {authors}".format, + title_length=title_length +) header = """\ PEP: 0 Title: Index of Python Enhancement Proposals (PEPs) Version: N/A -Last-Modified: %s +Last-Modified: {last_modified} Author: python-dev Status: Active Type: Informational @@ -31,7 +34,7 @@ .. [2] View PEP history online: https://github.com/python/peps """ -footer = """ \ +footer = """\ .. Local Variables: mode: indented-text diff --git a/pepreader/pep0_writer.py b/pepreader/pep0_writer.py new file mode 100644 index 00000000000..04902b9da7c --- /dev/null +++ b/pepreader/pep0_writer.py @@ -0,0 +1,286 @@ +"""Code to handle the output of PEP 0.""" +import datetime +import unicodedata + +from operator import attrgetter + +from . import pep0_constants +from . import pep0 + +# Type annotations +from typing import List + + +class PEPZeroWriter: + # This is a list of reserved PEP numbers. Reservations are not to be used for + # the normal PEP number allocation process - just give out the next available + # PEP number. These are for "special" numbers that may be used for semantic, + # humorous, or other such reasons, e.g. 401, 666, 754. + # + # PEP numbers may only be reserved with the approval of a PEP editor. Fields + # here are the PEP number being reserved and the claimants for the PEP. + # Although the output is sorted when PEP 0 is generated, please keep this list + # sorted as well. + RESERVED = [ + (801, "Warsaw"), + ] + + def __init__(self): + self._output: List[str] = [] + + def output(self, content): + # Appends content argument to the _output list + self._output.append(content) + + def emit_newline(self): + self.output('') + + def emit_table_separator(self): + self.output(pep0_constants.table_separator) + + def emit_author_table_separator(self, max_name_len): + author_table_separator = "=" * max_name_len + " " + "=" * len("email address") + self.output(author_table_separator) + + def emit_column_headers(self): + """Output the column headers for the PEP indices.""" + column_headers = { + "status": ".", + "type": ".", + "number": "PEP", + "title": "PEP Title", + "authors": "PEP Author(s)", + } + self.emit_table_separator() + self.output(pep0_constants.column_format(**column_headers)) + self.emit_table_separator() + + @staticmethod + def sort_peps(peps): + """Sort PEPs into meta, informational, accepted, open, finished, + and essentially dead.""" + meta = [] + info = [] + provisional = [] + accepted = [] + open_ = [] + finished = [] + historical = [] + deferred = [] + dead = [] + for pep in peps: + # Order of 'if' statement important. Key Status values take precedence + # over Type value, and vice-versa. + if pep.status == "Draft": + open_.append(pep) + elif pep.status == "Deferred": + deferred.append(pep) + elif pep.type_ == "Process": + if pep.status == "Active": + meta.append(pep) + elif pep.status in ("Withdrawn", "Rejected"): + dead.append(pep) + else: + historical.append(pep) + elif pep.status in ("Rejected", "Withdrawn", "Incomplete", "Superseded"): + dead.append(pep) + elif pep.type_ == "Informational": + # Hack until the conflict between the use of "Final" + # for both API definition PEPs and other (actually + # obsolete) PEPs is addressed + if pep.status == "Active" or "Release Schedule" not in pep.title: + info.append(pep) + else: + historical.append(pep) + elif pep.status == "Provisional": + provisional.append(pep) + elif pep.status in ("Accepted", "Active"): + accepted.append(pep) + elif pep.status == "Final": + finished.append(pep) + else: + raise pep0.PEPError(f"unsorted ({pep.type_}/{pep.status})", pep.filename, pep.number) + return meta, info, provisional, accepted, open_, finished, historical, deferred, dead + + @staticmethod + def verify_email_addresses(peps): + authors_dict = {} + for pep in peps: + for author in pep.authors: + # If this is the first time we have come across an author, add them. + if author not in authors_dict: + authors_dict[author] = [author.email] + else: + found_emails = authors_dict[author] + # If no email exists for the author, use the new value. + if not found_emails[0]: + authors_dict[author] = [author.email] + # If the new email is an empty string, move on. + elif not author.email: + continue + # If the email has not been seen, add it to the list. + elif author.email not in found_emails: + authors_dict[author].append(author.email) + + valid_authors_dict = {} + too_many_emails = [] + for author, emails in authors_dict.items(): + if len(emails) > 1: + too_many_emails.append((author.first_last, emails)) + else: + valid_authors_dict[author] = emails[0] + if too_many_emails: + err_output = [] + for author, emails in too_many_emails: + err_output.append(f" {author}: {emails}") + raise ValueError( + "some authors have more than one email address listed:\n" + + "\n".join(err_output) + ) + + return valid_authors_dict + + @staticmethod + def sort_authors(authors_dict): + authors_list = list(authors_dict.keys()) + authors_list.sort(key=attrgetter("sort_by")) + return authors_list + + @staticmethod + def normalized_last_first(name): + return len(unicodedata.normalize("NFC", name.last_first)) + + def emit_title(self, text, anchor, *, symbol="="): + self.output(".. _{anchor}:\n".format(anchor=anchor)) + self.output(text) + self.output(symbol * len(text)) + self.emit_newline() + + def emit_subtitle(self, text, anchor): + self.emit_title(text, anchor, symbol="-") + + def emit_pep_category(self, category, anchor, peps): + self.emit_subtitle(category, anchor) + self.emit_column_headers() + for pep in peps: + self.output(pep) + self.emit_table_separator() + self.emit_newline() + + def write_pep0(self, peps: list): + + # PEP metadata + today = datetime.date.today().strftime("%Y-%m-%d") + self.output(pep0_constants.header.format(last_modified=today)) + self.emit_newline() + + # Introduction + self.emit_title("Introduction", "intro") + self.output(pep0_constants.intro) + self.emit_newline() + + # PEPs by category + self.emit_title("Index by Category", "by-category") + (meta, info, provisional, accepted, open_, + finished, historical, deferred, dead) = self.sort_peps(peps) + pep_categories = [ + ("Meta-PEPs (PEPs about PEPs or Processes)", "by-category-meta", meta), + ("Other Informational PEPs", "by-category-other-info", info), + ("Provisional PEPs (provisionally accepted; interface may still change)", "by-category-provisional", provisional), + ("Accepted PEPs (accepted; may not be implemented yet)", "by-category-accepted", accepted), + ("Open PEPs (under consideration)", "by-category-open", open_), + ("Finished PEPs (done, with a stable interface)", "by-category-finished", finished), + ("Historical Meta-PEPs and Informational PEPs", "by-category-historical", historical), + ("Deferred PEPs (postponed pending further research or updates)", "by-category-deferred", deferred), + ("Abandoned, Withdrawn, and Rejected PEPs", "by-category-abandoned", dead), + ] + for pep_category in pep_categories: + category = pep_category[0] + anchor = pep_category[1] + peps = pep_category[2] + self.emit_pep_category(category, anchor, peps) + + self.emit_newline() + + # PEPs by number + self.emit_title("Numerical Index", "by-pep-number") + self.emit_column_headers() + prev_pep = 0 + for pep in peps: + if pep.number - prev_pep > 1: + self.emit_newline() + self.output(pep0_constants.text_type(pep)) + prev_pep = pep.number + + self.emit_table_separator() + self.emit_newline() + + # Reserved PEP numbers + self.emit_title("Reserved PEP Numbers", "reserved") + self.emit_column_headers() + for number, claimants in sorted(self.RESERVED): + self.output(pep0_constants.column_format(**{ + "type": ".", + "status": ".", + "number": number, + "title": "RESERVED", + "authors": claimants, + })) + + self.emit_table_separator() + self.emit_newline() + + # PEP types key + self.emit_title("PEP Types Key", "type-key") + for type_ in sorted(pep0.PEP.type_values): + self.output(f" {type_[0]} - {type_} PEP") + self.emit_newline() + + self.emit_newline() + + # PEP status key + self.emit_title("PEP Status Key", "status-key") + for status in sorted(pep0.PEP.status_values): + # Draft PEPs have no status displayed, Active shares a key with Accepted + if status in ("Active", "Draft"): + continue + if status == "Accepted": + msg = " A - Accepted (Standards Track only) or Active proposal" + else: + msg = " {status[0]} - {status} proposal".format(status=status) + self.output(msg) + self.emit_newline() + + self.emit_newline() + + # PEP owners + self.emit_title("Authors/Owners", "authors") + authors_dict = self.verify_email_addresses(peps) + max_name = max(authors_dict.keys(), key=self.normalized_last_first) + max_name_len = len(max_name.last_first) + self.emit_author_table_separator(max_name_len) + _author_header_fmt = f"{'Name':{max_name_len}} Email Address" + self.output(_author_header_fmt) + self.emit_author_table_separator(max_name_len) + sorted_authors = self.sort_authors(authors_dict) + _author_fmt = "{author.last_first:{max_name_len}} {author_email}" + for author in sorted_authors: + # Use the email from authors_dict instead of the one from 'author' as + # the author instance may have an empty email. + _entry = _author_fmt.format( + author=author, + author_email=authors_dict[author], + max_name_len=max_name_len, + ) + self.output(_entry) + self.emit_author_table_separator(max_name_len) + self.emit_newline() + self.emit_newline() + + # References for introduction footnotes + self.emit_title("References", "references") + self.output(pep0_constants.references) + self.output(pep0_constants.footer) + + pep0_string = '\n'.join([str(s) for s in self._output]) + return pep0_string From 94033634d460d610dc754f1ae13a6e91ef37c4b2 Mon Sep 17 00:00:00 2001 From: AA Turner <9087854+AA-Turner@users.noreply.github.com> Date: Sun, 26 Apr 2020 03:28:56 +0100 Subject: [PATCH 009/108] Update build and Makefile --- Makefile | 34 ++++++++-------------------------- build.py | 10 +++++----- 2 files changed, 13 insertions(+), 31 deletions(-) diff --git a/Makefile b/Makefile index 213bb75325f..3c86efd9ce1 100644 --- a/Makefile +++ b/Makefile @@ -3,26 +3,12 @@ # # Not really important, but convenient. -PEP2HTML=pep2html.py - PYTHON=python3 -.SUFFIXES: .txt .html .rst - -.txt.html: - @$(PYTHON) $(PEP2HTML) $< - -.rst.html: - @$(PYTHON) $(PEP2HTML) $< - -TARGETS= $(patsubst %.rst,%.html,$(wildcard pep-????.rst)) $(patsubst %.txt,%.html,$(wildcard pep-????.txt)) pep-0000.html - -all: pep-0000.rst $(TARGETS) - -$(TARGETS): pep2html.py +all: sphinx -pep-0000.rst: $(wildcard pep-????.txt) $(wildcard pep-????.rst) $(wildcard pep0/*.py) genpepindex.py - $(PYTHON) genpepindex.py . +sphinx: + sphinx-build -j auto -b html . build rss: $(PYTHON) pep2rss.py . @@ -32,7 +18,6 @@ install: clean: -rm pep-0000.rst - -rm pep-0000.txt -rm *.html -rm -rf build @@ -41,13 +26,10 @@ update: venv: $(PYTHON) -m venv venv - ./venv/bin/python -m pip install -U docutils + ./venv/bin/python -m pip install -U docutils sphinx package: all rss - mkdir -p build/peps - cp pep-*.txt build/peps/ - cp pep-*.rst build/peps/ - cp *.html build/peps/ - cp *.png build/peps/ - cp *.rss build/peps/ - tar -C build -czf build/peps.tar.gz peps + mkdir -p package/peps + cp -R build/. package/peps + cp *.rss package/peps + tar -C package -czf package/peps.tar.gz peps diff --git a/build.py b/build.py index aae70f95aa9..7e24223597b 100644 --- a/build.py +++ b/build.py @@ -5,11 +5,11 @@ if __name__ == '__main__': root_directory = Path('.').absolute() - docs_directory = Path(root_directory, 'peps') - source_directory = configuration_directory = docs_directory - build_directory = Path(root_directory, '_build') - doctree_directory = Path(build_directory, '.doctrees') + source_directory = root_directory + configuration_directory = source_directory + build_directory = root_directory / 'build' + doctree_directory = build_directory / '.doctrees' builder = 'html' app = Sphinx(source_directory, configuration_directory, build_directory, doctree_directory, builder) - app.build(force_all=True) + app.build() From 88e20a2ea0ed5bbbf9c6fa691a3666684ca5aac6 Mon Sep 17 00:00:00 2001 From: AA Turner <9087854+AA-Turner@users.noreply.github.com> Date: Sun, 26 Apr 2020 03:37:38 +0100 Subject: [PATCH 010/108] Misc cleanup --- conf.py | 13 ++++++------- pepreader/pep_headers.py | 1 - pepreader/pep_parser.py | 3 --- 3 files changed, 6 insertions(+), 11 deletions(-) diff --git a/conf.py b/conf.py index c39229a3ff2..70aeb93e0da 100644 --- a/conf.py +++ b/conf.py @@ -3,20 +3,19 @@ # -- Path setup -------------------------------------------------------------- -import os import sys -sys.path.append(os.path.abspath('.')) +from pathlib import Path +sys.path.append(Path('.').absolute()) # -- Project information ----------------------------------------------------- project = 'PEPs' -copyright = '2020, AUTHNAME' -author = 'AUTHNAME' +copyright = '2020, PEP Authors' +author = 'PEP Authors' # The full version, including alpha/beta/rc tags -release = '1.0.0' -version = "1.x" +# release = '1.0.0' html_title = "Python Enhancement Proposals (PEPs)" html_short_title = "PEPs Home" @@ -69,4 +68,4 @@ # so a file named "default.css" will overwrite the builtin "default.css". # html_static_path = ['_static'] -master_doc = 'contents' \ No newline at end of file +master_doc = 'contents' diff --git a/pepreader/pep_headers.py b/pepreader/pep_headers.py index 098352a8c34..a5f3ce92c52 100644 --- a/pepreader/pep_headers.py +++ b/pepreader/pep_headers.py @@ -112,4 +112,3 @@ def apply(self): para[:] = [nodes.reference("", pep_type, refuri=uri)] elif name == "version" and len(body): utils.clean_rcs_keywords(para, self.rcs_keyword_substitutions) - diff --git a/pepreader/pep_parser.py b/pepreader/pep_parser.py index 92a69720cb6..ad320d3e786 100644 --- a/pepreader/pep_parser.py +++ b/pepreader/pep_parser.py @@ -4,9 +4,6 @@ from . import pep_contents - - - class PEPParser(parsers.RSTParser): supported = ("pep", "python-enhancement-proposal") From e6869ca4c4a6d982a270a16bd92ad7b85ca5b2e3 Mon Sep 17 00:00:00 2001 From: AA Turner <9087854+AA-Turner@users.noreply.github.com> Date: Sun, 26 Apr 2020 03:41:11 +0100 Subject: [PATCH 011/108] Add sphinx dependency --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index a2632a6fba6..acf7162b569 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,7 +7,7 @@ dist: xenial cache: pip before_install: - - pip install docutils + - pip install docutils sphinx script: - make -j$(nproc) From 4080e62977c6a4afa3af0e11bd69f03de07780d3 Mon Sep 17 00:00:00 2001 From: AA Turner <9087854+AA-Turner@users.noreply.github.com> Date: Sun, 26 Apr 2020 04:26:45 +0100 Subject: [PATCH 012/108] update makefile --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 3c86efd9ce1..27bfbd07767 100644 --- a/Makefile +++ b/Makefile @@ -8,7 +8,7 @@ PYTHON=python3 all: sphinx sphinx: - sphinx-build -j auto -b html . build + $(PYTHON) build.py rss: $(PYTHON) pep2rss.py . From af0dfc3e5210cf6da4d9983b3c4ef3a12f97c659 Mon Sep 17 00:00:00 2001 From: AA Turner <9087854+AA-Turner@users.noreply.github.com> Date: Sun, 26 Apr 2020 07:14:50 +0100 Subject: [PATCH 013/108] fix for read the docs --- conf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conf.py b/conf.py index 70aeb93e0da..17a4200d663 100644 --- a/conf.py +++ b/conf.py @@ -5,7 +5,7 @@ import sys from pathlib import Path -sys.path.append(Path('.').absolute()) +sys.path.extend(str(Path('./pepreader').absolute())) # -- Project information ----------------------------------------------------- From 531e860f5b7b502c6d51c9041b42289e02ca6ff8 Mon Sep 17 00:00:00 2001 From: AA Turner <9087854+AA-Turner@users.noreply.github.com> Date: Sun, 26 Apr 2020 07:53:19 +0100 Subject: [PATCH 014/108] updates for contents - exclude contents in transforms - add custom text in contents.rst --- contents.rst | 16 ++++++++++------ pepreader/pep_contents.py | 4 ++++ pepreader/pep_headers.py | 5 +++++ pepreader/pep_title.py | 5 +++++ 4 files changed, 24 insertions(+), 6 deletions(-) diff --git a/contents.rst b/contents.rst index ce25a569a64..1c8b3c2e276 100644 --- a/contents.rst +++ b/contents.rst @@ -1,15 +1,19 @@ -PEP: 9999 -Title: Sphinx Index Page -.. peps documentation master file, created by - sphinx-quickstart on Thu Apr 23 17:23:18 2020. - You can adapt this file completely to your liking, but it should at least - contain the root `toctree` directive. +Python Enhancement Proposals (PEPs) +*********************************** + + + +Welcome! + +To get started, have a look at the :doc:`PEP Index` + .. toctree:: :maxdepth: 3 :titlesonly: + :hidden: :glob: :caption: Sphinx Table of Contents: diff --git a/pepreader/pep_contents.py b/pepreader/pep_contents.py index ac2c44f7e61..cb1b7ed92bc 100644 --- a/pepreader/pep_contents.py +++ b/pepreader/pep_contents.py @@ -1,3 +1,4 @@ +from pathlib import Path from docutils import nodes from docutils import transforms from docutils.transforms import parts @@ -13,6 +14,9 @@ class PEPContents(transforms.Transform): default_priority = 380 def apply(self): + if not Path(self.document["source"]).match("pep-*"): + # not a PEP file + return title = nodes.title('', 'contents') topic = nodes.topic('', title, classes=['contents']) name = nodes.fully_normalize_name('contents') diff --git a/pepreader/pep_headers.py b/pepreader/pep_headers.py index a5f3ce92c52..55658fd345e 100644 --- a/pepreader/pep_headers.py +++ b/pepreader/pep_headers.py @@ -1,4 +1,5 @@ import re +from pathlib import Path from docutils import nodes from docutils import utils @@ -29,6 +30,10 @@ def apply(self): # @@@ replace these DataErrors with proper system messages raise DataError("Document tree is empty.") + if not Path(self.document["source"]).match("pep-*"): + # not a PEP file + return + header = self.document[0] if not isinstance(header, nodes.field_list) or "rfc2822" not in header["classes"]: raise DataError("Document does not begin with an RFC-2822 header; it is not a PEP.") diff --git a/pepreader/pep_title.py b/pepreader/pep_title.py index 6364e42287d..db9ac0e25f0 100644 --- a/pepreader/pep_title.py +++ b/pepreader/pep_title.py @@ -1,3 +1,4 @@ +from pathlib import Path from docutils import nodes import docutils.transforms as transforms from docutils.parsers.rst import states @@ -14,6 +15,10 @@ class PEPTitle(transforms.Transform): default_priority = 335 def apply(self): + if not Path(self.document["source"]).match("pep-*"): + # not a PEP file + return + # Directory to hold the PEP's RFC2822 header details, to extract a titke string pep_header_details = {} From c9e1c14f32abc2275645df13526824702f4f65a8 Mon Sep 17 00:00:00 2001 From: AA Turner <9087854+AA-Turner@users.noreply.github.com> Date: Sun, 26 Apr 2020 17:36:21 +0100 Subject: [PATCH 015/108] support pythondotorg build process --- Makefile | 5 ++++- package.py | 40 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 package.py diff --git a/Makefile b/Makefile index 27bfbd07767..98af7c7fd3b 100644 --- a/Makefile +++ b/Makefile @@ -30,6 +30,9 @@ venv: package: all rss mkdir -p package/peps - cp -R build/. package/peps + $(PYTHON) package.py + cp pep-*.txt build/peps/ + cp pep-*.rst build/peps/ + cp *.png build/peps/ cp *.rss package/peps tar -C package -czf package/peps.tar.gz peps diff --git a/package.py b/package.py new file mode 100644 index 00000000000..3f35ee56dd6 --- /dev/null +++ b/package.py @@ -0,0 +1,40 @@ +"""Transforms Sphinx HTML output into python.org input format""" + +from bs4 import BeautifulSoup +from pathlib import Path + +if __name__ == '__main__': + root_path = Path(".") + html_path = root_path.joinpath('_build') + package_path = root_path.joinpath("package/peps") + package_path.mkdir(parents=True, exist_ok=True) + + for file_path in html_path.glob("pep-*"): + if file_path.suffix not in '.html': + continue + + soup = BeautifulSoup(file_path.read_text(encoding="UTF8"), 'lxml') + contents = soup.find('div', class_="body").div + dl = contents.find('dl') + for tag in dl.findChildren(): + if tag.name == "dt": + tag.name = "th" + tag.find_next_sibling().name = "td" + tag.attrs['class'] = 'field-name' + tag.find_next_sibling()['class'] = 'field-body' + tr = soup.new_tag("tr", **{'class': 'field'}) + tag.insert_before(tr) + tr.insert(0, tag.find_next_sibling()) + tr.insert(0, tag) + + dl.name = 'tbody' + tbl = soup.new_tag('table', **{'class': dl['class']}) + dl.wrap(tbl) + dl['class'] = [] + tbl.insert(0, soup.new_tag("col", **{'class': "field-body"})) + tbl.insert(0, soup.new_tag("col", **{'class': "field-name"})) + + write_path = Path('./package/peps') / file_path.name + write_path.write_text(str(contents), encoding="UTF8") + + del soup, contents, dl, tbl From 3dd68a177ab79dd3275af8b3e4b4f46572e13763 Mon Sep 17 00:00:00 2001 From: AA Turner <9087854+AA-Turner@users.noreply.github.com> Date: Mon, 27 Apr 2020 18:59:25 +0100 Subject: [PATCH 016/108] fix urls for read the docs --- docutils.conf | 4 +-- pepreader/__init__.py | 3 ++ pepreader/pep_headers.py | 14 ++++---- pepreader/pep_role.py | 13 +++++++ pepreader/pep_zero.py | 76 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 102 insertions(+), 8 deletions(-) create mode 100644 pepreader/pep_role.py create mode 100644 pepreader/pep_zero.py diff --git a/docutils.conf b/docutils.conf index e2f4c8cc16e..b9b28283358 100644 --- a/docutils.conf +++ b/docutils.conf @@ -15,7 +15,7 @@ template: pyramid-pep-template embed-stylesheet: 0 # path to PEPs, for template: -pep-home: /dev/peps/ +pep-home: / # base URL for PEP references (no host so mirrors work): -pep-base-url: /dev/peps/ +pep-base-url: / diff --git a/pepreader/__init__.py b/pepreader/__init__.py index 0b844fff03c..95496374c82 100644 --- a/pepreader/__init__.py +++ b/pepreader/__init__.py @@ -2,14 +2,17 @@ from sphinx.application import Sphinx __version__ = '1.0.0' +pep_url = "pep-{:0>4}.html" def setup(app: Sphinx): """Initialize Sphinx extension.""" from .pep_parser import PEPParser from .generate_pep_index import create_pep_zero + from .pep_role import PEPRole app.connect("env-before-read-docs", create_pep_zero) app.add_source_parser(PEPParser) + app.add_role('pep', PEPRole()) return {'version': __version__, 'parallel_read_safe': True, 'parallel_write_safe': True} diff --git a/pepreader/pep_headers.py b/pepreader/pep_headers.py index 55658fd345e..49cceacf190 100644 --- a/pepreader/pep_headers.py +++ b/pepreader/pep_headers.py @@ -5,6 +5,8 @@ from docutils import utils from docutils import transforms from docutils.transforms import peps +from pepreader import pep_zero +import pepreader class DataError(Exception): @@ -20,8 +22,8 @@ class PEPHeaders(transforms.Transform): default_priority = 330 - pep_url = "pep-%04d" - pep_cvs_url = "https://github.com/python/peps/blob/master/pep-%04d.txt" + pep_url = pepreader.pep_url + pep_cvs_url = "https://github.com/python/peps/blob/master/pep-{:0>4}.txt" rcs_keyword_substitutions = [(re.compile(r"\$[a-zA-Z]+: (.+) \$$"), r"\1")] @@ -45,7 +47,7 @@ def apply(self): value = pep_field[1].astext() try: pep = int(value) - cvs_url = self.pep_cvs_url % pep + cvs_url = self.pep_cvs_url.format(pep) except ValueError: pep = value msg = self.document.reporter.warning( @@ -66,7 +68,7 @@ def apply(self): if pep == 0: # Special processing for PEP 0. - pending = nodes.pending(peps.PEPZero) + pending = nodes.pending(pep_zero.PEPZero) self.document.insert(1, pending) self.document.note_pending(pending) @@ -103,7 +105,7 @@ def apply(self): newbody.append(nodes.reference( refpep, refpep, refuri=(self.document.settings.pep_base_url - + self.pep_url % pepno))) + + self.pep_url.format(pepno)))) newbody.append(space) para[:] = newbody[:-1] # drop trailing space elif name == "last-modified": @@ -113,7 +115,7 @@ def apply(self): para[:] = [nodes.reference("", date, refuri=cvs_url)] elif name == "content-type": pep_type = para.astext() - uri = self.document.settings.pep_base_url + self.pep_url % 12 + uri = self.document.settings.pep_base_url + self.pep_url.format(12) para[:] = [nodes.reference("", pep_type, refuri=uri)] elif name == "version" and len(body): utils.clean_rcs_keywords(para, self.rcs_keyword_substitutions) diff --git a/pepreader/pep_role.py b/pepreader/pep_role.py new file mode 100644 index 00000000000..341c19f1849 --- /dev/null +++ b/pepreader/pep_role.py @@ -0,0 +1,13 @@ +from sphinx import roles +import pepreader + + +class PEPRole(roles.PEP): + + def build_uri(self) -> str: + base_url = self.inliner.document.settings.pep_base_url + ret = self.target.split('#', 1) + if len(ret) == 2: + return base_url + (pepreader.pep_url + '#{}').format(int(ret[0]), ret[1]) + else: + return base_url + pepreader.pep_url.format(int(ret[0])) \ No newline at end of file diff --git a/pepreader/pep_zero.py b/pepreader/pep_zero.py new file mode 100644 index 00000000000..a487bfcbbb3 --- /dev/null +++ b/pepreader/pep_zero.py @@ -0,0 +1,76 @@ +from docutils import nodes +from docutils import transforms +from docutils.transforms import peps +import pepreader + + +class PEPZero(transforms.Transform): + + """ + Special processing for PEP 0. + """ + + default_priority = 760 + + def apply(self): + visitor = PEPZeroSpecial(self.document) + self.document.walk(visitor) + self.startnode.parent.remove(self.startnode) + + +class PEPZeroSpecial(nodes.SparseNodeVisitor): + + """ + Perform the special processing needed by PEP 0: + + - Mask email addresses. + + - Link PEP numbers in the second column of 4-column tables to the PEPs + themselves. + """ + + pep_url = pepreader.pep_url + + def __init__(self, document): + super().__init__(document) + self.pep_table = None + self.entry = None + + def unknown_visit(self, node): + pass + + @staticmethod + def visit_reference(node): + node.replace_self(peps.mask_email(node)) + + @staticmethod + def visit_field_list(node): + if 'rfc2822' in node['classes']: + raise nodes.SkipNode + + def visit_tgroup(self, node): + self.pep_table = node['cols'] == 4 + self.entry = 0 + + def visit_colspec(self, node): + self.entry += 1 + if self.pep_table and self.entry == 2: + node['classes'].append('num') + + def visit_row(self, node): + self.entry = 0 + + def visit_entry(self, node): + self.entry += 1 + if self.pep_table and self.entry == 2 and len(node) == 1: + node['classes'].append('num') + p = node[0] + if isinstance(p, nodes.paragraph) and len(p) == 1: + text = p.astext() + try: + pep = int(text) + ref = (self.document.settings.pep_base_url + + self.pep_url.format(pep)) + p[0] = nodes.reference(text, text, refuri=ref) + except ValueError: + pass From ab28391cd47a68011f26449d3668eda324a30fb2 Mon Sep 17 00:00:00 2001 From: AA Turner <9087854+AA-Turner@users.noreply.github.com> Date: Mon, 27 Apr 2020 19:08:08 +0100 Subject: [PATCH 017/108] fix import error --- pepreader/pep_role.py | 36 ++++++++++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/pepreader/pep_role.py b/pepreader/pep_role.py index 341c19f1849..fa1572a0fa0 100644 --- a/pepreader/pep_role.py +++ b/pepreader/pep_role.py @@ -1,8 +1,40 @@ -from sphinx import roles +from typing import List, Tuple + +from docutils import nodes +from docutils.nodes import Node, system_message + +from sphinx import addnodes +from sphinx.locale import _ +from sphinx.util.docutils import ReferenceRole + import pepreader -class PEPRole(roles.PEP): +class PEPRole(ReferenceRole): + def run(self) -> Tuple[List[Node], List[system_message]]: + target_id = 'index-%s' % self.env.new_serialno('index') + entries = [('single', _('Python Enhancement Proposals; PEP %s') % self.target, + target_id, '', None)] + + index = addnodes.index(entries=entries) + target = nodes.target('', '', ids=[target_id]) + self.inliner.document.note_explicit_target(target) + + try: + refuri = self.build_uri() + reference = nodes.reference('', '', internal=False, refuri=refuri, classes=['pep']) + if self.has_explicit_title: + reference += nodes.strong(self.title, self.title) + else: + title = "PEP " + self.title + reference += nodes.strong(title, title) + except ValueError: + msg = self.inliner.reporter.error('invalid PEP number %s' % self.target, + line=self.lineno) + prb = self.inliner.problematic(self.rawtext, self.rawtext, msg) + return [prb], [msg] + + return [index, target, reference], [] def build_uri(self) -> str: base_url = self.inliner.document.settings.pep_base_url From 1d6471754b0a33cfe9372998669d214e117900c2 Mon Sep 17 00:00:00 2001 From: AA Turner <9087854+AA-Turner@users.noreply.github.com> Date: Mon, 27 Apr 2020 19:27:10 +0100 Subject: [PATCH 018/108] make compatible with read the docs - RtD still runs sphinx 1.8.5 so we have had to add compatibility --- pepreader/pep_role.py | 85 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 82 insertions(+), 3 deletions(-) diff --git a/pepreader/pep_role.py b/pepreader/pep_role.py index fa1572a0fa0..84463875a35 100644 --- a/pepreader/pep_role.py +++ b/pepreader/pep_role.py @@ -1,16 +1,95 @@ -from typing import List, Tuple +import re + +from typing import List, Tuple, Dict from docutils import nodes from docutils.nodes import Node, system_message +from docutils.parsers.rst.states import Inliner +from docutils.utils import unescape from sphinx import addnodes +from sphinx.errors import SphinxError from sphinx.locale import _ -from sphinx.util.docutils import ReferenceRole import pepreader +if False: + # For type annotation + from typing import Type # for python3.5.1 + from sphinx.builders import Builder + from sphinx.config import Config + from sphinx.environment import BuildEnvironment + +class PEPRole: + """A base class for reference roles. + + The reference roles can accpet ``link title `` style as a text for + the role. The parsed result; link title and target will be stored to + ``self.title`` and ``self.target``. + """ + has_explicit_title = None #: A boolean indicates the role has explicit title or not. + disabled = False #: A boolean indicates the reference is disabled. + title = None #: The link title for the interpreted text. + target = None #: The link target for the interpreted text. + + # \x00 means the "<" was backslash-escaped + explicit_title_re = re.compile(r'^(.+?)\s*(?$', re.DOTALL) + + # From ReferenceRole + def __call__(self, name: str, rawtext: str, text: str, lineno: int, + inliner: Inliner, options: Dict = {}, content: List[str] = [] + ) -> Tuple[List[Node], List[system_message]]: + # if the first character is a bang, don't cross-reference at all + self.disabled = text.startswith('!') + + matched = self.explicit_title_re.match(text) + if matched: + self.has_explicit_title = True + self.title = unescape(matched.group(1)) + self.target = unescape(matched.group(2)) + else: + self.has_explicit_title = False + self.title = unescape(text) + self.target = unescape(text) + + # From SphinxRole + self.rawtext = rawtext + self.text = unescape(text) + self.lineno = lineno + self.inliner = inliner + self.options = options + self.content = content + + # guess role type + if name: + self.name = name.lower() + else: + self.name = self.env.temp_data.get('default_role') + if not self.name: + self.name = self.env.config.default_role + if not self.name: + raise SphinxError('cannot determine default role!') + + return self.run() + + @property + def env(self) -> "BuildEnvironment": + """Reference to the :class:`.BuildEnvironment` object.""" + return self.inliner.document.settings.env + + @property + def config(self) -> "Config": + """Reference to the :class:`.Config` object.""" + return self.env.config + + def get_source_info(self, lineno: int = None) -> Tuple[str, int]: + if lineno is None: + lineno = self.lineno + return self.inliner.reporter.get_source_and_line(lineno) # type: ignore + + def set_source_info(self, node: Node, lineno: int = None) -> None: + node.source, node.line = self.get_source_info(lineno) -class PEPRole(ReferenceRole): def run(self) -> Tuple[List[Node], List[system_message]]: target_id = 'index-%s' % self.env.new_serialno('index') entries = [('single', _('Python Enhancement Proposals; PEP %s') % self.target, From 9d57d7fc1c44953ebcfa0683f9a2ffb2d6773e3d Mon Sep 17 00:00:00 2001 From: AA Turner <9087854+AA-Turner@users.noreply.github.com> Date: Mon, 27 Apr 2020 19:37:00 +0100 Subject: [PATCH 019/108] update base url --- docutils.conf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docutils.conf b/docutils.conf index b9b28283358..8becc5f3062 100644 --- a/docutils.conf +++ b/docutils.conf @@ -15,7 +15,7 @@ template: pyramid-pep-template embed-stylesheet: 0 # path to PEPs, for template: -pep-home: / +pep-home: /en/latest/ # base URL for PEP references (no host so mirrors work): -pep-base-url: / +pep-base-url: /en/latest/ From e88699f0dbb6f1fd4593fd38b5db585aac930360 Mon Sep 17 00:00:00 2001 From: AA Turner <9087854+AA-Turner@users.noreply.github.com> Date: Mon, 27 Apr 2020 20:19:56 +0100 Subject: [PATCH 020/108] Fix numerical index (pep list was being overwritten) --- pepreader/pep0_writer.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pepreader/pep0_writer.py b/pepreader/pep0_writer.py index 04902b9da7c..e7ec7b072b7 100644 --- a/pepreader/pep0_writer.py +++ b/pepreader/pep0_writer.py @@ -197,8 +197,8 @@ def write_pep0(self, peps: list): for pep_category in pep_categories: category = pep_category[0] anchor = pep_category[1] - peps = pep_category[2] - self.emit_pep_category(category, anchor, peps) + peps_in_category = pep_category[2] + self.emit_pep_category(category, anchor, peps_in_category) self.emit_newline() From cfafa99f36f395a35398837bd0b453e995e6d70f Mon Sep 17 00:00:00 2001 From: AA Turner <9087854+AA-Turner@users.noreply.github.com> Date: Mon, 27 Apr 2020 23:35:10 +0100 Subject: [PATCH 021/108] Fix name parsing --- pepreader/pep0.py | 87 +++++++++++++++++++++++++++++++++-------------- 1 file changed, 61 insertions(+), 26 deletions(-) diff --git a/pepreader/pep0.py b/pepreader/pep0.py index 29359173973..ddcff82ac99 100644 --- a/pepreader/pep0.py +++ b/pepreader/pep0.py @@ -59,23 +59,29 @@ class Author(object): def __init__(self, author_and_email_tuple): """Parse the name and email address of an author.""" + self.first = self.last = '' + name, email = author_and_email_tuple self.first_last = name.strip() self.email = email.lower() - last_name_fragment, suffix = self._last_name(name) - name_sep = name.index(last_name_fragment) - self.first = name[:name_sep].rstrip() - self.last = last_name_fragment - if self.last[1] == ".": - # Add an escape to avoid docutils turning `v.` into `22.`. - self.last = "\\" + self.last - self.suffix = suffix - if not self.first: - self.last_first = self.last + + name_dict = self._parse_name(name) + self.suffix = name_dict.get("suffix") + if name_dict.get("name"): + self.last_first = name_dict["name"] + self.nick = name_dict["name"] else: + self.first = name_dict["forename"].rstrip() + self.last = name_dict["surname"] + if self.last[1] == ".": + # Add an escape to avoid docutils turning `v.` into `22.`. + self.last = "\\" + self.last self.last_first = ", ".join([self.last, self.first]) - if self.suffix: - self.last_first += ", " + self.suffix + self.nick = self.last + + if self.suffix: + self.last_first += ", " + self.suffix + if self.last == "van Rossum": # Special case for our beloved BDFL. :) if self.first == "Guido": @@ -85,8 +91,6 @@ def __init__(self, author_and_email_tuple): else: raise ValueError(f"unknown van Rossum {self}!") self.last_first += f" ({self.nick})" - else: - self.nick = self.last def __hash__(self): return hash(self.first_last) @@ -107,7 +111,7 @@ def sort_by(self): return unicodedata.normalize("NFKD", base) @staticmethod - def _last_name(full_name): + def _parse_name(full_name): """Find the last name (or nickname) of a full name. If no last name (e.g, 'Aahz') then return the full name. If there is @@ -116,19 +120,50 @@ def _last_name(full_name): through a comma, then drop the suffix. """ - name_partition = full_name.partition(",") - no_suffix = name_partition[0].strip() - suffix = name_partition[2].strip() - name_parts = no_suffix.split() - part_count = len(name_parts) - if part_count == 1 or part_count == 2: - return name_parts[-1], suffix - else: - assert part_count > 2 + possible_suffixes = ["Jr", "Jr.", "II", "III"] + special_cases = ["The Python core team and community"] + + if full_name in special_cases: + return {"name": full_name} + + suffix_partition = full_name.partition(",") + pre_suffix = suffix_partition[0].strip() + suffix = suffix_partition[2].strip() + + name_parts = pre_suffix.split(" ") + num_parts = len(name_parts) + name = {"suffix": suffix} + + if num_parts == 0: + raise ValueError("Name is empty!") + elif num_parts == 1: + name.update({"name": name_parts[0]}) + elif num_parts == 2: + name.update({"forename": name_parts[0], "surname": name_parts[1]}) + elif num_parts > 2: + # handles III etc. + if name_parts[-1] in possible_suffixes: + new_suffix = " ".join([*name_parts[-1:], suffix]).strip() + name_parts.pop(-1) + name.update(suffix=new_suffix) + + # handles von, van, v. etc. if name_parts[-2].islower(): - return " ".join(name_parts[-2:]), suffix + forename = " ".join(name_parts[:-2]) + surname = " ".join(name_parts[-2:]) + name.update({"forename": forename, "surname": surname}) + # handles double surnames after a middle initial (e.g. + elif any(s.endswith(".") for s in name_parts): + split_position = [i for i, x in enumerate(name_parts) if x.endswith(".")][-1] + 1 + forename = " ".join(name_parts[:split_position]) + surname = " ".join(name_parts[split_position:]) + name.update({"forename": forename, "surname": surname}) else: - return name_parts[-1], suffix + forename = " ".join(name_parts[:-1]) + surname = " ".join(name_parts[-1:]) + name.update({"forename": forename, "surname": surname}) + + return name class PEP(object): From d5fe06fbb0fc19cc142a3dfc46c51b8089c97007 Mon Sep 17 00:00:00 2001 From: AA Turner <9087854+AA-Turner@users.noreply.github.com> Date: Tue, 28 Apr 2020 02:24:36 +0100 Subject: [PATCH 022/108] Update name parsing in PEP 0 --- pepreader/pep0.py | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/pepreader/pep0.py b/pepreader/pep0.py index ddcff82ac99..190eb17d02f 100644 --- a/pepreader/pep0.py +++ b/pepreader/pep0.py @@ -112,12 +112,14 @@ def sort_by(self): @staticmethod def _parse_name(full_name): - """Find the last name (or nickname) of a full name. + """Decompose a full name into parts. - If no last name (e.g, 'Aahz') then return the full name. If there is - a leading, lowercase portion to the last name (e.g., 'van' or 'von') - then include it. If there is a suffix (e.g., 'Jr.') that is appended - through a comma, then drop the suffix. + If a mononym (e.g, 'Aahz') then return the full name. If there are + suffixes in the name (e.g. ', Jr.' or 'III'), then find and extract + them. If there is a middle initial followed by a full stop, then + combine the following words into a surname (e.g. N. Vander Weele). If + there is a leading, lowercase portion to the last name (e.g. 'van' or + 'von') then include it in the surname. """ possible_suffixes = ["Jr", "Jr.", "II", "III"] @@ -137,9 +139,9 @@ def _parse_name(full_name): if num_parts == 0: raise ValueError("Name is empty!") elif num_parts == 1: - name.update({"name": name_parts[0]}) + name.update(name=name_parts[0]) elif num_parts == 2: - name.update({"forename": name_parts[0], "surname": name_parts[1]}) + name.update(forename=name_parts[0], surname=name_parts[1]) elif num_parts > 2: # handles III etc. if name_parts[-1] in possible_suffixes: @@ -151,17 +153,19 @@ def _parse_name(full_name): if name_parts[-2].islower(): forename = " ".join(name_parts[:-2]) surname = " ".join(name_parts[-2:]) - name.update({"forename": forename, "surname": surname}) - # handles double surnames after a middle initial (e.g. + name.update(forename=forename, surname=surname) + + # handles double surnames after a middle initial (e.g. N. Vander Weele) elif any(s.endswith(".") for s in name_parts): split_position = [i for i, x in enumerate(name_parts) if x.endswith(".")][-1] + 1 forename = " ".join(name_parts[:split_position]) surname = " ".join(name_parts[split_position:]) - name.update({"forename": forename, "surname": surname}) + name.update(forename=forename, surname=surname) + else: forename = " ".join(name_parts[:-1]) surname = " ".join(name_parts[-1:]) - name.update({"forename": forename, "surname": surname}) + name.update(forename=forename, surname=surname) return name From 0b2c7a41e3f54f8166e14d28d96a88499696c657 Mon Sep 17 00:00:00 2001 From: AA Turner <9087854+AA-Turner@users.noreply.github.com> Date: Tue, 28 Apr 2020 02:25:00 +0100 Subject: [PATCH 023/108] Include requirements file --- pepreader/pep_role.py | 117 ++---------------------------------------- requirements.txt | 4 ++ 2 files changed, 7 insertions(+), 114 deletions(-) create mode 100644 requirements.txt diff --git a/pepreader/pep_role.py b/pepreader/pep_role.py index 84463875a35..b4632668a87 100644 --- a/pepreader/pep_role.py +++ b/pepreader/pep_role.py @@ -1,119 +1,8 @@ -import re - -from typing import List, Tuple, Dict - -from docutils import nodes -from docutils.nodes import Node, system_message -from docutils.parsers.rst.states import Inliner -from docutils.utils import unescape - -from sphinx import addnodes -from sphinx.errors import SphinxError -from sphinx.locale import _ - +from sphinx import roles import pepreader -if False: - # For type annotation - from typing import Type # for python3.5.1 - from sphinx.builders import Builder - from sphinx.config import Config - from sphinx.environment import BuildEnvironment - -class PEPRole: - """A base class for reference roles. - - The reference roles can accpet ``link title `` style as a text for - the role. The parsed result; link title and target will be stored to - ``self.title`` and ``self.target``. - """ - has_explicit_title = None #: A boolean indicates the role has explicit title or not. - disabled = False #: A boolean indicates the reference is disabled. - title = None #: The link title for the interpreted text. - target = None #: The link target for the interpreted text. - - # \x00 means the "<" was backslash-escaped - explicit_title_re = re.compile(r'^(.+?)\s*(?$', re.DOTALL) - - # From ReferenceRole - def __call__(self, name: str, rawtext: str, text: str, lineno: int, - inliner: Inliner, options: Dict = {}, content: List[str] = [] - ) -> Tuple[List[Node], List[system_message]]: - # if the first character is a bang, don't cross-reference at all - self.disabled = text.startswith('!') - - matched = self.explicit_title_re.match(text) - if matched: - self.has_explicit_title = True - self.title = unescape(matched.group(1)) - self.target = unescape(matched.group(2)) - else: - self.has_explicit_title = False - self.title = unescape(text) - self.target = unescape(text) - - # From SphinxRole - self.rawtext = rawtext - self.text = unescape(text) - self.lineno = lineno - self.inliner = inliner - self.options = options - self.content = content - - # guess role type - if name: - self.name = name.lower() - else: - self.name = self.env.temp_data.get('default_role') - if not self.name: - self.name = self.env.config.default_role - if not self.name: - raise SphinxError('cannot determine default role!') - - return self.run() - - @property - def env(self) -> "BuildEnvironment": - """Reference to the :class:`.BuildEnvironment` object.""" - return self.inliner.document.settings.env - - @property - def config(self) -> "Config": - """Reference to the :class:`.Config` object.""" - return self.env.config - - def get_source_info(self, lineno: int = None) -> Tuple[str, int]: - if lineno is None: - lineno = self.lineno - return self.inliner.reporter.get_source_and_line(lineno) # type: ignore - - def set_source_info(self, node: Node, lineno: int = None) -> None: - node.source, node.line = self.get_source_info(lineno) - - def run(self) -> Tuple[List[Node], List[system_message]]: - target_id = 'index-%s' % self.env.new_serialno('index') - entries = [('single', _('Python Enhancement Proposals; PEP %s') % self.target, - target_id, '', None)] - - index = addnodes.index(entries=entries) - target = nodes.target('', '', ids=[target_id]) - self.inliner.document.note_explicit_target(target) - - try: - refuri = self.build_uri() - reference = nodes.reference('', '', internal=False, refuri=refuri, classes=['pep']) - if self.has_explicit_title: - reference += nodes.strong(self.title, self.title) - else: - title = "PEP " + self.title - reference += nodes.strong(title, title) - except ValueError: - msg = self.inliner.reporter.error('invalid PEP number %s' % self.target, - line=self.lineno) - prb = self.inliner.problematic(self.rawtext, self.rawtext, msg) - return [prb], [msg] - return [index, target, reference], [] +class PEPRole(roles.PEP): def build_uri(self) -> str: base_url = self.inliner.document.settings.pep_base_url @@ -121,4 +10,4 @@ def build_uri(self) -> str: if len(ret) == 2: return base_url + (pepreader.pep_url + '#{}').format(int(ret[0]), ret[1]) else: - return base_url + pepreader.pep_url.format(int(ret[0])) \ No newline at end of file + return base_url + pepreader.pep_url.format(int(ret[0])) diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 00000000000..241e78f21e3 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,4 @@ +# Requirements for building PEPs with Sphinx + +sphinx >= 3.0.3 +docutils >= 0.16 From 31fe99cf41bb7323a956fd03121971aa91dda3a3 Mon Sep 17 00:00:00 2001 From: AA Turner <9087854+AA-Turner@users.noreply.github.com> Date: Tue, 28 Apr 2020 02:26:38 +0100 Subject: [PATCH 024/108] Update ToC to remove title --- pepreader/pep_contents.py | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/pepreader/pep_contents.py b/pepreader/pep_contents.py index cb1b7ed92bc..623f99b2ea3 100644 --- a/pepreader/pep_contents.py +++ b/pepreader/pep_contents.py @@ -17,13 +17,37 @@ def apply(self): if not Path(self.document["source"]).match("pep-*"): # not a PEP file return - title = nodes.title('', 'contents') + title = nodes.title('', 'Contents') topic = nodes.topic('', title, classes=['contents']) name = nodes.fully_normalize_name('contents') if not self.document.has_name(name): topic['names'].append(name) self.document.note_implicit_target(topic) - pending = nodes.pending(parts.Contents) + pending = nodes.pending(Contents) topic += pending self.document.children[0].insert(2, topic) self.document.note_pending(pending) + + +class Contents(parts.Contents): + def apply(self): + try: # let the writer (or output software) build the contents list? + toc_by_writer = self.document.settings.use_latex_toc + except AttributeError: + toc_by_writer = False + + details = self.startnode.details + startnode = self.document[0] + self.toc_id = self.startnode.parent['ids'][0] + self.backlinks = self.document.settings.toc_backlinks + + if toc_by_writer: + # move customization settings to the parent node + self.startnode.parent.attributes.update(details) + self.startnode.parent.remove(self.startnode) + else: + contents = self.build_contents(startnode) + if len(contents): + self.startnode.replace_self(contents) + else: + self.startnode.parent.parent.remove(self.startnode.parent) From 1fb311213a2b38ab3c9e61fbb69ab0792efe27e2 Mon Sep 17 00:00:00 2001 From: AA Turner <9087854+AA-Turner@users.noreply.github.com> Date: Tue, 28 Apr 2020 02:50:07 +0100 Subject: [PATCH 025/108] Update Contents class --- pepreader/pep_contents.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/pepreader/pep_contents.py b/pepreader/pep_contents.py index 623f99b2ea3..b64e13ff7f2 100644 --- a/pepreader/pep_contents.py +++ b/pepreader/pep_contents.py @@ -30,8 +30,14 @@ def apply(self): class Contents(parts.Contents): + def __init__(self, document, startnode=None): + super().__init__(document, startnode) + self.toc_id = None + self.backlinks = None + def apply(self): - try: # let the writer (or output software) build the contents list? + # let the writer (or output software) build the contents list? + try: toc_by_writer = self.document.settings.use_latex_toc except AttributeError: toc_by_writer = False From cd600b4b96f6604c65b59d36aa2f68b6fcf09778 Mon Sep 17 00:00:00 2001 From: AA Turner <9087854+AA-Turner@users.noreply.github.com> Date: Tue, 28 Apr 2020 03:27:09 +0100 Subject: [PATCH 026/108] =?UTF-8?q?Fixes=20as=20per=20=C3=89ric=20Araujo's?= =?UTF-8?q?=20comments?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pepreader/pep0.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pepreader/pep0.py b/pepreader/pep0.py index 190eb17d02f..065c572dc82 100644 --- a/pepreader/pep0.py +++ b/pepreader/pep0.py @@ -67,7 +67,7 @@ def __init__(self, author_and_email_tuple): name_dict = self._parse_name(name) self.suffix = name_dict.get("suffix") - if name_dict.get("name"): + if "name" in name_dict: self.last_first = name_dict["name"] self.nick = name_dict["name"] else: @@ -89,7 +89,7 @@ def __init__(self, author_and_email_tuple): elif self.first == "Just": self.nick = "JvR" else: - raise ValueError(f"unknown van Rossum {self}!") + raise ValueError(f"unknown van Rossum ({name})!") self.last_first += f" ({self.nick})" def __hash__(self): From 6bf48d5c797567b0fbb05e0bfea1a54f476b0c49 Mon Sep 17 00:00:00 2001 From: AA Turner <9087854+AA-Turner@users.noreply.github.com> Date: Tue, 28 Apr 2020 03:38:48 +0100 Subject: [PATCH 027/108] move Travis CI to use requirements.txt --- .travis.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index acf7162b569..de77ffe6dc1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,12 +2,15 @@ language: python python: - 3.7 - 3.7-dev + - 3.8 + - 3.8-dev dist: xenial cache: pip before_install: - - pip install docutils sphinx + - pip install -r requirements.txt + script: - make -j$(nproc) From 3c31d041254c671842511cfd8ee08e47ab4d3d94 Mon Sep 17 00:00:00 2001 From: AA Turner <9087854+AA-Turner@users.noreply.github.com> Date: Tue, 28 Apr 2020 18:07:22 +0100 Subject: [PATCH 028/108] Update build to include 3.8 and sanity checks --- .travis.yml | 50 ++++++++++++++++++++++++++++++++++++++++++++++++ build.py | 37 +++++++++++++++++++++++++++++++++-- requirements.txt | 3 +++ 3 files changed, 88 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index de77ffe6dc1..cd417f56049 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,6 +14,56 @@ before_install: script: - make -j$(nproc) + +jobs: + fast_finish: true + + include: + # Main run, tests build, RSS, and packaging + - name: "3.7 Makefile Build" + python: 3.7 + env: COMMAND="make -j$(nproc)" + + # Tests build on 3.7-dev + - name: "3.7-dev Build Test" + python: 3.7-dev + env: COMMAND="./build.py" + + # Tests build on 3.8 + - name: "3.8 Build Test" + python: 3.8 + env: COMMAND="./build.py" + + # Tests build on 3.8-dev + - name: "3.8-dev Build Test" + python: 3.8-dev + env: COMMAND="./build.py" + + # Tests build with Fail on Warning + - name: "3.8 Fail on Warning" + python: 3.8 + env: + - COMMAND="./build.py -f" + - FAIL_ALLOWED=true + + # Tests build with Fail on Warning (Nitpicky) + - name: "3.8 Fail on Warning Nitpicky" + python: 3.8 + env: + - COMMAND="./build.py -f -n" + - FAIL_ALLOWED=true + + # Checks link references within PEPs + - name: "3.8 Check Links" + python: 3.8 + env: + - COMMAND="./build.py -c" + - FAIL_ALLOWED=true + + allow_failures: + # Note test failure, but pass the build + - env: FAIL_ALLOWED=true + deploy: provider: script script: bash deploy.bash diff --git a/build.py b/build.py index 7e24223597b..69eb6c9ac48 100644 --- a/build.py +++ b/build.py @@ -1,15 +1,48 @@ # Build script for Sphinx documentation +import argparse from pathlib import Path from sphinx.application import Sphinx + +def create_parser(): + + parser = argparse.ArgumentParser(description="Build PEP documents") + arguments = [ + ('-b', '--builder', 'store'), + ('-d', '--dir-html', 'store_true'), + ('-c', '--check-links', 'store_true'), + ('-f', '--fail-on-warning', 'store_true'), + ('-n', '--nitpicky', 'store_true'), + ] + for arg in arguments: + parser.add_argument(arg[0], arg[1], action=arg[2]) + + return parser.parse_args() + + if __name__ == '__main__': + args = create_parser() + root_directory = Path('.').absolute() source_directory = root_directory configuration_directory = source_directory build_directory = root_directory / 'build' doctree_directory = build_directory / '.doctrees' - builder = 'html' - app = Sphinx(source_directory, configuration_directory, build_directory, doctree_directory, builder) + if args.check_links: + builder = 'linkcheck' + elif args.dir_html: + builder = 'dirhtml' + else: + builder = 'html' + + config_overrides = {} + if args.nitpicky: + config_overrides['nitpicky'] = True + + app = Sphinx( + source_directory, configuration_directory, build_directory, doctree_directory, builder, + confoverrides=config_overrides, warningiserror=args.fail_on_warning, keep_going=args.fail_on_warning, + ) app.build() diff --git a/requirements.txt b/requirements.txt index 241e78f21e3..ad88d51c43b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,3 +2,6 @@ sphinx >= 3.0.3 docutils >= 0.16 + +# For packaging to current python.org standards +bs4 \ No newline at end of file From f77967338c52ee66a88e4c69de76e169dece9a03 Mon Sep 17 00:00:00 2001 From: AA Turner <9087854+AA-Turner@users.noreply.github.com> Date: Tue, 28 Apr 2020 18:07:31 +0100 Subject: [PATCH 029/108] Move to author metadata lookup for PEP index --- AUTHORS.csv | 249 ++++++++++++++++++++++++++++++++ pepreader/generate_pep_index.py | 11 +- pepreader/pep0.py | 95 +----------- 3 files changed, 266 insertions(+), 89 deletions(-) create mode 100644 AUTHORS.csv diff --git a/AUTHORS.csv b/AUTHORS.csv new file mode 100644 index 00000000000..55a712b0fe0 --- /dev/null +++ b/AUTHORS.csv @@ -0,0 +1,249 @@ +"Full Name"; "Surname First"; "Name Reference" +"Aahz"; "Aahz"; "Aahz" +"James C. Ahlstrom"; "Ahlstrom, James C."; "Ahlstrom" +"Jim Althoff"; "Althoff, Jim"; "Althoff" +"Kevin Altis"; "Altis, Kevin"; "Altis" +"Chris Angelico"; "Angelico, Chris"; "Angelico" +"Philipp Angerer"; "Angerer, Philipp"; "Angerer" +"David Ascher"; "Ascher, David"; "Ascher" +"Peter Astrand"; "Astrand, Peter"; "Astrand" +"Carl Banks"; "Banks, Carl"; "Banks" +"Christopher Barker"; "Barker, Christopher"; "Barker" +"Paul Barrett"; "Barrett, Paul"; "Barrett" +"Facundo Batista"; "Batista, Facundo"; "Batista" +"Anthony Baxter"; "Baxter, Anthony"; "Baxter" +"Stefan Behnel"; "Behnel, Stefan"; "Behnel" +"Thomas Bellman"; "Bellman, Thomas"; "Bellman" +"Alexander Belopolsky"; "Belopolsky, Alexander"; "Belopolsky" +"Eli Bendersky"; "Bendersky, Eli"; "Bendersky" +"Cory Benfield"; "Benfield, Cory"; "Benfield" +"Steven Bethard"; "Bethard, Steven"; "Bethard" +"Stéphane Bidoul"; "Bidoul, Stéphane"; "Bidoul" +"Stefano Borini"; "Borini, Stefano"; "Borini" +"Georg Brandl"; "Brandl, Georg"; "Brandl" +"Erik M. Bray"; "Bray, Erik M."; "Bray" +"Gerald Britton"; "Britton, Gerald"; "Britton" +"Oleg Broytman"; "Broytman, Oleg"; "Broytman" +"Benoit Bryon"; "Bryon, Benoit"; "Bryon" +"Brandt Bucher"; "Bucher, Brandt"; "Bucher" +"Brett Cannon"; "Cannon, Brett"; "Cannon" +"Justin Cappos"; "Cappos, Justin"; "Cappos" +"Josiah Carlson"; "Carlson, Josiah"; "Carlson" +"W Isaac Carroll"; "Carroll, W Isaac"; "Carroll" +"Matt Chisholm"; "Chisholm, Matt"; "Chisholm" +"Nick Coghlan"; "Coghlan, Nick"; "Coghlan" +"Dave Cole"; "Cole, Dave"; "Cole" +"Robert Collins"; "Collins, Robert"; "Collins" +"Paul Colomiets"; "Colomiets, Paul"; "Colomiets" +"Mario Corchero"; "Corchero, Mario"; "Corchero" +"Christopher A. Craig"; "Craig, Christopher A."; "Craig" +"Laura Creighton"; "Creighton, Laura"; "Creighton" +"Steven D'Aprano"; "D'Aprano, Steven"; "D'Aprano" +"Kushal Das"; "Das, Kushal"; "Das" +"Ned Deily"; "Deily, Ned"; "Deily" +"Tim Delaney"; "Delaney, Tim"; "Delaney" +"Lois Anne DeLong"; "DeLong, Lois Anne"; "DeLong" +"Jeroen Demeyer"; "Demeyer, Jeroen"; "Demeyer" +"Vladimir Diaz"; "Diaz, Vladimir"; "Diaz" +"Jack Diederich"; "Diederich, Jack"; "Diederich" +"Steve Dower"; "Dower, Steve"; "Dower" +"Walter Dörwald"; "Dörwald, Walter"; "Dörwald" +"Fred L. Drake, Jr."; "Drake, Fred L., Jr."; "Drake" +"Michael P. Dubner"; "Dubner, Michael P."; "Dubner" +"Paul F. Dubois"; "Dubois, Paul F."; "Dubois" +"Ernest W. Durbin III"; "Durbin, Ernest W., III"; "Durbin" +"P.J. Eby"; "Eby, P.J."; "Eby" +"Phillip J. Eby"; "Eby, Phillip J."; "Eby" +"Tal Einat"; "Einat, Tal"; "Einat" +"Micah Elliott"; "Elliott, Micah"; "Elliott" +"Jeff Epler"; "Epler, Jeff"; "Epler" +"David Eppstein"; "Eppstein, David"; "Eppstein" +"Clark C. Evans"; "Evans, Clark C."; "Evans" +"Gregory Ewing"; "Ewing, Gregory"; "Ewing" +"Greg Ewing"; "Ewing, Greg"; "Ewing" +"Martijn Faassen"; "Faassen, Martijn"; "Faassen" +"Ben Finney"; "Finney, Ben"; "Finney" +"Michael Foord"; "Foord, Michael"; "Foord" +"Ethan Furman"; "Furman, Ethan"; "Furman" +"Pablo Galindo"; "Galindo, Pablo"; "Galindo" +"Paul Ganssle"; "Ganssle, Paul"; "Ganssle" +"Alex Gaynor"; "Gaynor, Alex"; "Gaynor" +"Pradyun Gedam"; "Gedam, Pradyun"; "Gedam" +"Damien George"; "George, Damien"; "George" +"Frédéric B. Giacometti"; "Giacometti, Frédéric B."; "Giacometti" +"Scott Gilbert"; "Gilbert, Scott"; "Gilbert" +"Ryan Gonzalez"; "Gonzalez, Ryan"; "Gonzalez" +"David Goodger"; "Goodger, David"; "Goodger" +"Grant Griffin"; "Griffin, Grant"; "Griffin" +"Mark E. Haase"; "Haase, Mark E."; "Haase" +"Mark Hammond"; "Hammond, Mark"; "Hammond" +"Peter Harris"; "Harris, Peter"; "Harris" +"Larry Hastings"; "Hastings, Larry"; "Hastings" +"Christian Heimes"; "Heimes, Christian"; "Heimes" +"Thomas Heller"; "Heller, Thomas"; "Heller" +"Doug Hellmann"; "Hellmann, Doug"; "Hellmann" +"Magnus Lie Hetland"; "Hetland, Magnus Lie"; "Hetland" +"Raymond Hettinger"; "Hettinger, Raymond"; "Hettinger" +"Neil Hodgson"; "Hodgson, Neil"; "Hodgson" +"Daniel Holth"; "Holth, Daniel"; "Holth" +"Philip House"; "House, Philip"; "House" +"Laurens Van Houtven"; "Van Houtven, Laurens"; "Houtven" +"Ben Hoyt"; "Hoyt, Ben"; "Hoyt" +"Miro Hrončok"; "Hrončok, Miro"; "Hrončok" +"Michael Hudson"; "Hudson, Michael"; "Hudson" +"Jeremy Hylton"; "Hylton, Jeremy"; "Hylton" +"Inada Naoki"; "Inada, Naoki"; "Inada" +"Dustin Ingram"; "Ingram, Dustin"; "Ingram" +"Atsuo Ishimoto"; "Ishimoto, Atsuo"; "Ishimoto" +"Jack Jansen"; "Jansen, Jack"; "Jansen" +"Chris Jerdonek"; "Jerdonek, Chris"; "Jerdonek" +"Joseph Jevnik"; "Jevnik, Joseph"; "Jevnik" +"Jim J. Jewett"; "Jewett, Jim J."; "Jewett" +"Jim Jewett"; "Jewett, Jim"; "Jewett" +"Ewa Jodlowska"; "Jodlowska, Ewa"; "Jodlowska" +"Richard Jones"; "Jones, Richard"; "Jones" +"Konstantin Kashin"; "Kashin, Konstantin"; "Kashin" +"Reid Kleckner"; "Kleckner, Reid"; "Kleckner" +"Thomas Kluyver"; "Kluyver, Thomas"; "Kluyver" +"Stepan Koltsov"; "Koltsov, Stepan"; "Koltsov" +"Stefan Krah"; "Krah, Stefan"; "Krah" +"Sebastian Kreft"; "Kreft, Sebastian"; "Kreft" +"Holger Krekel"; "Krekel, Holger"; "Krekel" +"A.M. Kuchling"; "Kuchling, A.M."; "Kuchling" +"Trishank Karthik Kuppusamy"; "Kuppusamy, Trishank Karthik"; "Kuppusamy" +"Robert Kuska"; "Kuska, Robert"; "Kuska" +"Joshua Landau"; "Landau, Joshua"; "Landau" +"Łukasz Langa"; "Langa, Łukasz"; "Langa" +"Michael Lee"; "Lee, Michael"; "Lee" +"Jukka Lehtosalo"; "Lehtosalo, Jukka"; "Lehtosalo" +"Marc-André Lemburg"; "Lemburg, Marc-André"; "Lemburg" +"Ivan Levkivskyi"; "Levkivskyi, Ivan"; "Levkivskyi" +"Gregory Lielens"; "Lielens, Gregory"; "Lielens" +"Björn Lindqvist"; "Lindqvist, Björn"; "Lindqvist" +"Joshua Lock"; "Lock, Joshua"; "Lock" +"Tony Lownds"; "Lownds, Tony"; "Lownds" +"Martin von Löwis"; "von Löwis, Martin"; "von Löwis" +"Martin v. Löwis"; "\v. Löwis, Martin"; "\v. Löwis" +"Mariatta"; "Mariatta"; "Mariatta" +"Alex Martelli"; "Martelli, Alex"; "Martelli" +"Joseph Martinot-Lagarde"; "Martinot-Lagarde, Joseph"; "Martinot-Lagarde" +"Lino Mastrodomenico"; "Mastrodomenico, Lino"; "Mastrodomenico" +"Patrick Maupin"; "Maupin, Patrick"; "Maupin" +"Andrew McClelland"; "McClelland, Andrew"; "McClelland" +"Charles R. McCreary"; "McCreary, Charles R."; "McCreary" +"Chris McDonough"; "McDonough, Chris"; "McDonough" +"Robert T. McGibbon"; "McGibbon, Robert T."; "McGibbon" +"Gordon McMillan"; "McMillan, Gordon"; "McMillan" +"Andrew McNamara"; "McNamara, Andrew"; "McNamara" +"Ezio Melotti"; "Melotti, Ezio"; "Melotti" +"Mark Mendoza"; "Mendoza, Mark"; "Mendoza" +"Markus Meskanen"; "Meskanen, Markus"; "Meskanen" +"Mike Meyer"; "Meyer, Mike"; "Meyer" +"Carl Meyer"; "Meyer, Carl"; "Meyer" +"Trent Mick"; "Mick, Trent"; "Mick" +"Mike G. Miller"; "Miller, Mike G."; "Miller" +"Skip Montanaro"; "Montanaro, Skip"; "Montanaro" +"Peter Moody"; "Moody, Peter"; "Moody" +"Marina Moore"; "Moore, Marina"; "Moore" +"Paul Moore"; "Moore, Paul"; "Moore" +"R David Murray"; "Murray, R David"; "Murray" +"Charles-François Natali"; "Natali, Charles-François"; "Natali" +"Lysandros Nikolaou"; "Nikolaou, Lysandros"; "Nikolaou" +"Jesse Noller"; "Noller, Jesse"; "Noller" +"Ben North"; "North, Ben"; "North" +"Neal Norwitz"; "Norwitz, Neal"; "Norwitz" +"Dirkjan Ochtman"; "Ochtman, Dirkjan"; "Ochtman" +"Travis Oliphant"; "Oliphant, Travis"; "Oliphant" +"Jason Orendorff"; "Orendorff, Jason"; "Orendorff" +"Tomáš Orsava"; "Orsava, Tomáš"; "Orsava" +"Richard Oudkerk"; "Oudkerk, Richard"; "Oudkerk" +"Ronald Oussoren"; "Oussoren, Ronald"; "Oussoren" +"Julien Palard"; "Palard, Julien"; "Palard" +"Samuele Pedroni"; "Pedroni, Samuele"; "Pedroni" +"Berker Peksag"; "Peksag, Berker"; "Peksag" +"Michel Pelletier"; "Pelletier, Michel"; "Pelletier" +"Tim Peters"; "Peters, Tim"; "Peters" +"Benjamin Peterson"; "Peterson, Benjamin"; "Peterson" +"Jason Petrone"; "Petrone, Jason"; "Petrone" +"Antoine Pitrou"; "Pitrou, Antoine"; "Pitrou" +"Marcel Plch"; "Plch, Marcel"; "Plch" +"James Polley"; "Polley, James"; "Polley" +"Philippe PRADOS"; "Prados, Philippe"; "Prados" +"Elvis Pranskevichus"; "Pranskevichus, Elvis"; "Pranskevichus" +"Paul Prescod"; "Prescod, Paul"; "Prescod" +"(James) Eric Pruitt"; "Pruitt, (James) Eric"; "Pruitt" +"Lukas Puehringer"; "Puehringer, Lukas"; "Puehringer" +"Brian Quinlan"; "Quinlan, Brian"; "Quinlan" +"Terry Reedy"; "Reedy, Terry"; "Reedy" +"Lennart Regebro"; "Regebro, Lennart"; "Regebro" +"Sean Reifschneider"; "Reifschneider, Sean"; "Reifschneider" +"Christian R. Reis"; "Reis, Christian R."; "Reis" +"Jonathan Riehl"; "Riehl, Jonathan"; "Riehl" +"Lisa Roach"; "Roach, Lisa"; "Roach" +"Andre Roberge"; "Roberge, Andre"; "Roberge" +"Armin Ronacher"; "Ronacher, Armin"; "Ronacher" +"Guido van Rossum"; "van Rossum, Guido (GvR)"; "GvR" +"Just van Rossum"; "van Rossum, Just (JvR)"; "JvR" +"Todd Rovito"; "Rovito, Todd"; "Rovito" +"Lie Ryan"; "Ryan, Lie"; "Ryan" +"Vinay Sajip"; "Sajip, Vinay"; "Sajip" +"Pablo Galindo Salgado"; "Salgado, Pablo Galindo"; "Salgado" +"Neil Schemenauer"; "Schemenauer, Neil"; "Schemenauer" +"Peter Schneider-Kamp"; "Schneider-Kamp, Peter"; "Schneider-Kamp" +"Ed Schofield"; "Schofield, Ed"; "Schofield" +"Yury Selivanov"; "Selivanov, Yury"; "Selivanov" +"Jiwon Seo"; "Seo, Jiwon"; "Seo" +"Mark Shannon"; "Shannon, Mark"; "Shannon" +"Cameron Simpson"; "Simpson, Cameron"; "Simpson" +"Greg Slodkowicz"; "Slodkowicz, Greg"; "Slodkowicz" +"Nathaniel J. Smith"; "Smith, Nathaniel J."; "Smith" +"Gregory P. Smith"; "Smith, Gregory P."; "Smith" +"Kevin D. Smith"; "Smith, Kevin D."; "Smith" +"Ethan Smith"; "Smith, Ethan"; "Smith" +"Nathaniel Smith"; "Smith, Nathaniel"; "Smith" +"Eric V. Smith"; "Smith, Eric V."; "Smith" +"Eric Snow"; "Snow, Eric"; "Snow" +"Calvin Spealman"; "Spealman, Calvin"; "Spealman" +"Kerrick Staley"; "Staley, Kerrick"; "Staley" +"Greg Stein"; "Stein, Greg"; "Stein" +"Victor Stinner"; "Stinner, Victor"; "Stinner" +"Serhiy Storchaka"; "Storchaka, Serhiy"; "Storchaka" +"Donald Stufft"; "Stufft, Donald"; "Stufft" +"Daniel Stutzbach"; "Stutzbach, Daniel"; "Stutzbach" +"Michael J. Sullivan"; "Sullivan, Michael J."; "Sullivan" +"Roman Suzi"; "Suzi, Roman"; "Suzi" +"Dennis Sweeney"; "Sweeney, Dennis"; "Sweeney" +"Talin"; "Talin"; "Talin" +"Steven Taschuk"; "Taschuk, Steven"; "Taschuk" +"Batuhan Taskaya"; "Taskaya, Batuhan"; "Taskaya" +"Martin Teichmann"; "Teichmann, Martin"; "Teichmann" +"The Python core team and community"; "The Python core team and community"; "The Python core team and community" +"Geoffrey Thomas"; "Thomas, Geoffrey"; "Thomas" +"Oren Tirosh"; "Tirosh, Oren"; "Tirosh" +"Stephen J. Turnbull"; "Turnbull, Stephen J."; "Turnbull" +"Daniel Urban"; "Urban, Daniel"; "Urban" +"Eric N. Vander Weele"; "Vander Weele, Eric N."; "Vander Weele" +"Till Varoquaux"; "Varoquaux, Till"; "Varoquaux" +"Alexandre Vassalotti"; "Vassalotti, Alexandre"; "Vassalotti" +"Mike Verdone"; "Verdone, Mike"; "Verdone" +"Dino Viehland"; "Viehland, Dino"; "Viehland" +"Petr Viktorin"; "Viktorin, Petr"; "Viktorin" +"Zachary Ware"; "Ware, Zachary"; "Ware" +"Gregory R. Warnes"; "Warnes, Gregory R."; "Warnes" +"Barry Warsaw"; "Warsaw, Barry"; "Warsaw" +"Terence Way"; "Way, Terence"; "Way" +"Cliff Wells"; "Wells, Cliff"; "Wells" +"Jervis Whitley"; "Whitley, Jervis"; "Whitley" +"Mark Williams"; "Williams, Mark"; "Williams" +"Carol Willing"; "Willing, Carol"; "Willing" +"Greg Wilson"; "Wilson, Greg"; "Wilson" +"Collin Winter"; "Winter, Collin"; "Winter" +"Thomas Wouters"; "Wouters, Thomas"; "Wouters" +"Masayuki Yamamoto"; "Yamamoto, Masayuki"; "Yamamoto" +"Jeffrey Yasskin"; "Yasskin, Jeffrey"; "Yasskin" +"Ka-Ping Yee"; "Yee, Ka-Ping"; "Yee" +"Moshe Zadka"; "Zadka, Moshe"; "Zadka" +"Koos Zevenhoven"; "Zevenhoven, Koos"; "Zevenhoven" +"Huaiyu Zhu"; "Zhu, Huaiyu"; "Zhu" +"Shannon Zhu"; "Zhu, Shannon"; "Zhu" +"Tarek Ziadé"; "Ziadé, Tarek"; "Ziadé" \ No newline at end of file diff --git a/pepreader/generate_pep_index.py b/pepreader/generate_pep_index.py index 3ae3da29659..34149cbf23a 100644 --- a/pepreader/generate_pep_index.py +++ b/pepreader/generate_pep_index.py @@ -16,6 +16,7 @@ """ import re +import csv from operator import attrgetter from pathlib import Path @@ -33,6 +34,14 @@ def create_pep_zero(_, env, docnames): peps = [] pep_pat = re.compile(r"pep-\d{4}") # Path.match() doesn't support regular expressions + with open("AUTHORS.csv", "r", encoding="UTF8") as f: + read = csv.DictReader(f, delimiter=";") + author_data = {} + for line in read: + full_name = line.pop("Full Name").strip().strip("\"") + details = {k.strip().strip("\""): v.strip().strip("\"") for k, v in line.items()} + author_data[full_name] = details + for file_path in path.iterdir(): if not file_path.is_file(): continue # Skip directories etc. @@ -41,7 +50,7 @@ def create_pep_zero(_, env, docnames): if pep_pat.match(str(file_path)) and file_path.suffix in (".txt", ".rst"): file_path_absolute = path.joinpath(file_path).absolute() pep_text = file_path_absolute.read_text("UTF8") - pep = pep0.PEP(pep_text, file_path_absolute) + pep = pep0.PEP(pep_text, file_path_absolute, author_data) if pep.number != int(file_path.stem[4:]): raise pep0.PEPError(f'PEP number does not match file name ({file_path})', file_path, pep.number) peps.append(pep) diff --git a/pepreader/pep0.py b/pepreader/pep0.py index 065c572dc82..bd69929e5d4 100644 --- a/pepreader/pep0.py +++ b/pepreader/pep0.py @@ -57,7 +57,7 @@ class Author(object): The author's email address. """ - def __init__(self, author_and_email_tuple): + def __init__(self, author_and_email_tuple, authors_lookup): """Parse the name and email address of an author.""" self.first = self.last = '' @@ -65,32 +65,10 @@ def __init__(self, author_and_email_tuple): self.first_last = name.strip() self.email = email.lower() - name_dict = self._parse_name(name) - self.suffix = name_dict.get("suffix") - if "name" in name_dict: - self.last_first = name_dict["name"] - self.nick = name_dict["name"] - else: - self.first = name_dict["forename"].rstrip() - self.last = name_dict["surname"] - if self.last[1] == ".": - # Add an escape to avoid docutils turning `v.` into `22.`. - self.last = "\\" + self.last - self.last_first = ", ".join([self.last, self.first]) - self.nick = self.last - - if self.suffix: - self.last_first += ", " + self.suffix - - if self.last == "van Rossum": - # Special case for our beloved BDFL. :) - if self.first == "Guido": - self.nick = "GvR" - elif self.first == "Just": - self.nick = "JvR" - else: - raise ValueError(f"unknown van Rossum ({name})!") - self.last_first += f" ({self.nick})" + name_dict = authors_lookup[self.first_last] + + self.last_first = name_dict["Surname First"] + self.nick = name_dict["Name Reference"] def __hash__(self): return hash(self.first_last) @@ -110,65 +88,6 @@ def sort_by(self): base = self.last.lower() return unicodedata.normalize("NFKD", base) - @staticmethod - def _parse_name(full_name): - """Decompose a full name into parts. - - If a mononym (e.g, 'Aahz') then return the full name. If there are - suffixes in the name (e.g. ', Jr.' or 'III'), then find and extract - them. If there is a middle initial followed by a full stop, then - combine the following words into a surname (e.g. N. Vander Weele). If - there is a leading, lowercase portion to the last name (e.g. 'van' or - 'von') then include it in the surname. - - """ - possible_suffixes = ["Jr", "Jr.", "II", "III"] - special_cases = ["The Python core team and community"] - - if full_name in special_cases: - return {"name": full_name} - - suffix_partition = full_name.partition(",") - pre_suffix = suffix_partition[0].strip() - suffix = suffix_partition[2].strip() - - name_parts = pre_suffix.split(" ") - num_parts = len(name_parts) - name = {"suffix": suffix} - - if num_parts == 0: - raise ValueError("Name is empty!") - elif num_parts == 1: - name.update(name=name_parts[0]) - elif num_parts == 2: - name.update(forename=name_parts[0], surname=name_parts[1]) - elif num_parts > 2: - # handles III etc. - if name_parts[-1] in possible_suffixes: - new_suffix = " ".join([*name_parts[-1:], suffix]).strip() - name_parts.pop(-1) - name.update(suffix=new_suffix) - - # handles von, van, v. etc. - if name_parts[-2].islower(): - forename = " ".join(name_parts[:-2]) - surname = " ".join(name_parts[-2:]) - name.update(forename=forename, surname=surname) - - # handles double surnames after a middle initial (e.g. N. Vander Weele) - elif any(s.endswith(".") for s in name_parts): - split_position = [i for i, x in enumerate(name_parts) if x.endswith(".")][-1] + 1 - forename = " ".join(name_parts[:split_position]) - surname = " ".join(name_parts[split_position:]) - name.update(forename=forename, surname=surname) - - else: - forename = " ".join(name_parts[:-1]) - surname = " ".join(name_parts[-1:]) - name.update(forename=forename, surname=surname) - - return name - class PEP(object): @@ -213,7 +132,7 @@ class PEP(object): "Deferred", "Final", "Active", "Draft", "Superseded", ) - def __init__(self, pep_file: str, filename: str): + def __init__(self, pep_file: str, filename: str, author_lookup: dict): """Init object from an open PEP file object.""" # Parse the headers. self.filename = filename @@ -281,7 +200,7 @@ def __init__(self, pep_file: str, filename: str): authors_and_emails = self._parse_author(metadata["Author"]) if len(authors_and_emails) < 1: raise PEPError("no authors found", filename, self.number) - self.authors = list(map(Author, authors_and_emails)) + self.authors = [Author(author_email, author_lookup) for author_email in authors_and_emails] @staticmethod def _parse_author(data): From cc2eb9e1f24092f8c8f50f0eaeb08f214677cbfa Mon Sep 17 00:00:00 2001 From: AA Turner <9087854+AA-Turner@users.noreply.github.com> Date: Tue, 28 Apr 2020 18:11:18 +0100 Subject: [PATCH 030/108] update .travis.yml --- .travis.yml | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index cd417f56049..eef1983de19 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,13 +8,9 @@ dist: xenial cache: pip -before_install: +install: - pip install -r requirements.txt -script: - - make -j$(nproc) - - jobs: fast_finish: true From 992ec430d99cfe869ba8fc00b0bc3562c1dd407c Mon Sep 17 00:00:00 2001 From: AA Turner <9087854+AA-Turner@users.noreply.github.com> Date: Tue, 28 Apr 2020 18:40:38 +0100 Subject: [PATCH 031/108] Lint travis config with config.travis-ci.com --- .travis.yml | 41 ++++++++++++++++++----------------------- 1 file changed, 18 insertions(+), 23 deletions(-) diff --git a/.travis.yml b/.travis.yml index eef1983de19..e016326011b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,15 +1,11 @@ language: python -python: - - 3.7 - - 3.7-dev - - 3.8 - - 3.8-dev +os: linux dist: xenial cache: pip install: - - pip install -r requirements.txt + - pip install -r requirements.txt jobs: fast_finish: true @@ -19,6 +15,13 @@ jobs: - name: "3.7 Makefile Build" python: 3.7 env: COMMAND="make -j$(nproc)" + deploy: + provider: script + script: bash deploy.bash + skip_cleanup: true + on: + branch: master + repo: python/peps # Tests build on 3.7-dev - name: "3.7-dev Build Test" @@ -44,26 +47,18 @@ jobs: # Tests build with Fail on Warning (Nitpicky) - name: "3.8 Fail on Warning Nitpicky" - python: 3.8 - env: - - COMMAND="./build.py -f -n" - - FAIL_ALLOWED=true + python: 3.8 + env: + - COMMAND="./build.py -f -n" + - FAIL_ALLOWED=true # Checks link references within PEPs - name: "3.8 Check Links" - python: 3.8 - env: - - COMMAND="./build.py -c" - - FAIL_ALLOWED=true + python: 3.8 + env: + - COMMAND="./build.py -c" + - FAIL_ALLOWED=true allow_failures: # Note test failure, but pass the build - - env: FAIL_ALLOWED=true - -deploy: - provider: script - script: bash deploy.bash - skip_cleanup: true - on: - branch: master - repo: python/peps + - env: FAIL_ALLOWED=true \ No newline at end of file From 12e8a9648ed18185dcd52edcee1d50bca9d9cff5 Mon Sep 17 00:00:00 2001 From: AA Turner <9087854+AA-Turner@users.noreply.github.com> Date: Tue, 28 Apr 2020 18:47:10 +0100 Subject: [PATCH 032/108] oops... --- .travis.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index e016326011b..482078dba9d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -61,4 +61,6 @@ jobs: allow_failures: # Note test failure, but pass the build - - env: FAIL_ALLOWED=true \ No newline at end of file + - env: FAIL_ALLOWED=true + +script: $COMMAND \ No newline at end of file From a92fa4c9a094edd8df06f6dde894c4776dc697c4 Mon Sep 17 00:00:00 2001 From: AA Turner <9087854+AA-Turner@users.noreply.github.com> Date: Tue, 28 Apr 2020 19:19:08 +0100 Subject: [PATCH 033/108] Correct command calls --- .travis.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.travis.yml b/.travis.yml index 482078dba9d..b4c93e7e9f0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -26,37 +26,37 @@ jobs: # Tests build on 3.7-dev - name: "3.7-dev Build Test" python: 3.7-dev - env: COMMAND="./build.py" + env: COMMAND="python3 ./build.py" # Tests build on 3.8 - name: "3.8 Build Test" python: 3.8 - env: COMMAND="./build.py" + env: COMMAND="python3 ./build.py" # Tests build on 3.8-dev - name: "3.8-dev Build Test" python: 3.8-dev - env: COMMAND="./build.py" + env: COMMAND="python3 ./build.py" # Tests build with Fail on Warning - name: "3.8 Fail on Warning" python: 3.8 env: - - COMMAND="./build.py -f" + - COMMAND="python3 ./build.py -f" - FAIL_ALLOWED=true # Tests build with Fail on Warning (Nitpicky) - name: "3.8 Fail on Warning Nitpicky" python: 3.8 env: - - COMMAND="./build.py -f -n" + - COMMAND="python3 ./build.py -f -n" - FAIL_ALLOWED=true # Checks link references within PEPs - name: "3.8 Check Links" python: 3.8 env: - - COMMAND="./build.py -c" + - COMMAND="python3 ./build.py -c" - FAIL_ALLOWED=true allow_failures: From d72d4f44688ae81fa224ee0095c90b41d1d5e59e Mon Sep 17 00:00:00 2001 From: AA Turner <9087854+AA-Turner@users.noreply.github.com> Date: Thu, 30 Apr 2020 00:41:54 +0100 Subject: [PATCH 034/108] Move CSV to comma separated --- .travis.yml | 3 +- AUTHORS.csv | 498 ++++++++++++++++---------------- pepreader/generate_pep_index.py | 2 +- 3 files changed, 252 insertions(+), 251 deletions(-) diff --git a/.travis.yml b/.travis.yml index b4c93e7e9f0..ede903d0486 100644 --- a/.travis.yml +++ b/.travis.yml @@ -61,6 +61,7 @@ jobs: allow_failures: # Note test failure, but pass the build - - env: FAIL_ALLOWED=true + - env: + - FAIL_ALLOWED=true script: $COMMAND \ No newline at end of file diff --git a/AUTHORS.csv b/AUTHORS.csv index 55a712b0fe0..0270e4383c4 100644 --- a/AUTHORS.csv +++ b/AUTHORS.csv @@ -1,249 +1,249 @@ -"Full Name"; "Surname First"; "Name Reference" -"Aahz"; "Aahz"; "Aahz" -"James C. Ahlstrom"; "Ahlstrom, James C."; "Ahlstrom" -"Jim Althoff"; "Althoff, Jim"; "Althoff" -"Kevin Altis"; "Altis, Kevin"; "Altis" -"Chris Angelico"; "Angelico, Chris"; "Angelico" -"Philipp Angerer"; "Angerer, Philipp"; "Angerer" -"David Ascher"; "Ascher, David"; "Ascher" -"Peter Astrand"; "Astrand, Peter"; "Astrand" -"Carl Banks"; "Banks, Carl"; "Banks" -"Christopher Barker"; "Barker, Christopher"; "Barker" -"Paul Barrett"; "Barrett, Paul"; "Barrett" -"Facundo Batista"; "Batista, Facundo"; "Batista" -"Anthony Baxter"; "Baxter, Anthony"; "Baxter" -"Stefan Behnel"; "Behnel, Stefan"; "Behnel" -"Thomas Bellman"; "Bellman, Thomas"; "Bellman" -"Alexander Belopolsky"; "Belopolsky, Alexander"; "Belopolsky" -"Eli Bendersky"; "Bendersky, Eli"; "Bendersky" -"Cory Benfield"; "Benfield, Cory"; "Benfield" -"Steven Bethard"; "Bethard, Steven"; "Bethard" -"Stéphane Bidoul"; "Bidoul, Stéphane"; "Bidoul" -"Stefano Borini"; "Borini, Stefano"; "Borini" -"Georg Brandl"; "Brandl, Georg"; "Brandl" -"Erik M. Bray"; "Bray, Erik M."; "Bray" -"Gerald Britton"; "Britton, Gerald"; "Britton" -"Oleg Broytman"; "Broytman, Oleg"; "Broytman" -"Benoit Bryon"; "Bryon, Benoit"; "Bryon" -"Brandt Bucher"; "Bucher, Brandt"; "Bucher" -"Brett Cannon"; "Cannon, Brett"; "Cannon" -"Justin Cappos"; "Cappos, Justin"; "Cappos" -"Josiah Carlson"; "Carlson, Josiah"; "Carlson" -"W Isaac Carroll"; "Carroll, W Isaac"; "Carroll" -"Matt Chisholm"; "Chisholm, Matt"; "Chisholm" -"Nick Coghlan"; "Coghlan, Nick"; "Coghlan" -"Dave Cole"; "Cole, Dave"; "Cole" -"Robert Collins"; "Collins, Robert"; "Collins" -"Paul Colomiets"; "Colomiets, Paul"; "Colomiets" -"Mario Corchero"; "Corchero, Mario"; "Corchero" -"Christopher A. Craig"; "Craig, Christopher A."; "Craig" -"Laura Creighton"; "Creighton, Laura"; "Creighton" -"Steven D'Aprano"; "D'Aprano, Steven"; "D'Aprano" -"Kushal Das"; "Das, Kushal"; "Das" -"Ned Deily"; "Deily, Ned"; "Deily" -"Tim Delaney"; "Delaney, Tim"; "Delaney" -"Lois Anne DeLong"; "DeLong, Lois Anne"; "DeLong" -"Jeroen Demeyer"; "Demeyer, Jeroen"; "Demeyer" -"Vladimir Diaz"; "Diaz, Vladimir"; "Diaz" -"Jack Diederich"; "Diederich, Jack"; "Diederich" -"Steve Dower"; "Dower, Steve"; "Dower" -"Walter Dörwald"; "Dörwald, Walter"; "Dörwald" -"Fred L. Drake, Jr."; "Drake, Fred L., Jr."; "Drake" -"Michael P. Dubner"; "Dubner, Michael P."; "Dubner" -"Paul F. Dubois"; "Dubois, Paul F."; "Dubois" -"Ernest W. Durbin III"; "Durbin, Ernest W., III"; "Durbin" -"P.J. Eby"; "Eby, P.J."; "Eby" -"Phillip J. Eby"; "Eby, Phillip J."; "Eby" -"Tal Einat"; "Einat, Tal"; "Einat" -"Micah Elliott"; "Elliott, Micah"; "Elliott" -"Jeff Epler"; "Epler, Jeff"; "Epler" -"David Eppstein"; "Eppstein, David"; "Eppstein" -"Clark C. Evans"; "Evans, Clark C."; "Evans" -"Gregory Ewing"; "Ewing, Gregory"; "Ewing" -"Greg Ewing"; "Ewing, Greg"; "Ewing" -"Martijn Faassen"; "Faassen, Martijn"; "Faassen" -"Ben Finney"; "Finney, Ben"; "Finney" -"Michael Foord"; "Foord, Michael"; "Foord" -"Ethan Furman"; "Furman, Ethan"; "Furman" -"Pablo Galindo"; "Galindo, Pablo"; "Galindo" -"Paul Ganssle"; "Ganssle, Paul"; "Ganssle" -"Alex Gaynor"; "Gaynor, Alex"; "Gaynor" -"Pradyun Gedam"; "Gedam, Pradyun"; "Gedam" -"Damien George"; "George, Damien"; "George" -"Frédéric B. Giacometti"; "Giacometti, Frédéric B."; "Giacometti" -"Scott Gilbert"; "Gilbert, Scott"; "Gilbert" -"Ryan Gonzalez"; "Gonzalez, Ryan"; "Gonzalez" -"David Goodger"; "Goodger, David"; "Goodger" -"Grant Griffin"; "Griffin, Grant"; "Griffin" -"Mark E. Haase"; "Haase, Mark E."; "Haase" -"Mark Hammond"; "Hammond, Mark"; "Hammond" -"Peter Harris"; "Harris, Peter"; "Harris" -"Larry Hastings"; "Hastings, Larry"; "Hastings" -"Christian Heimes"; "Heimes, Christian"; "Heimes" -"Thomas Heller"; "Heller, Thomas"; "Heller" -"Doug Hellmann"; "Hellmann, Doug"; "Hellmann" -"Magnus Lie Hetland"; "Hetland, Magnus Lie"; "Hetland" -"Raymond Hettinger"; "Hettinger, Raymond"; "Hettinger" -"Neil Hodgson"; "Hodgson, Neil"; "Hodgson" -"Daniel Holth"; "Holth, Daniel"; "Holth" -"Philip House"; "House, Philip"; "House" -"Laurens Van Houtven"; "Van Houtven, Laurens"; "Houtven" -"Ben Hoyt"; "Hoyt, Ben"; "Hoyt" -"Miro Hrončok"; "Hrončok, Miro"; "Hrončok" -"Michael Hudson"; "Hudson, Michael"; "Hudson" -"Jeremy Hylton"; "Hylton, Jeremy"; "Hylton" -"Inada Naoki"; "Inada, Naoki"; "Inada" -"Dustin Ingram"; "Ingram, Dustin"; "Ingram" -"Atsuo Ishimoto"; "Ishimoto, Atsuo"; "Ishimoto" -"Jack Jansen"; "Jansen, Jack"; "Jansen" -"Chris Jerdonek"; "Jerdonek, Chris"; "Jerdonek" -"Joseph Jevnik"; "Jevnik, Joseph"; "Jevnik" -"Jim J. Jewett"; "Jewett, Jim J."; "Jewett" -"Jim Jewett"; "Jewett, Jim"; "Jewett" -"Ewa Jodlowska"; "Jodlowska, Ewa"; "Jodlowska" -"Richard Jones"; "Jones, Richard"; "Jones" -"Konstantin Kashin"; "Kashin, Konstantin"; "Kashin" -"Reid Kleckner"; "Kleckner, Reid"; "Kleckner" -"Thomas Kluyver"; "Kluyver, Thomas"; "Kluyver" -"Stepan Koltsov"; "Koltsov, Stepan"; "Koltsov" -"Stefan Krah"; "Krah, Stefan"; "Krah" -"Sebastian Kreft"; "Kreft, Sebastian"; "Kreft" -"Holger Krekel"; "Krekel, Holger"; "Krekel" -"A.M. Kuchling"; "Kuchling, A.M."; "Kuchling" -"Trishank Karthik Kuppusamy"; "Kuppusamy, Trishank Karthik"; "Kuppusamy" -"Robert Kuska"; "Kuska, Robert"; "Kuska" -"Joshua Landau"; "Landau, Joshua"; "Landau" -"Łukasz Langa"; "Langa, Łukasz"; "Langa" -"Michael Lee"; "Lee, Michael"; "Lee" -"Jukka Lehtosalo"; "Lehtosalo, Jukka"; "Lehtosalo" -"Marc-André Lemburg"; "Lemburg, Marc-André"; "Lemburg" -"Ivan Levkivskyi"; "Levkivskyi, Ivan"; "Levkivskyi" -"Gregory Lielens"; "Lielens, Gregory"; "Lielens" -"Björn Lindqvist"; "Lindqvist, Björn"; "Lindqvist" -"Joshua Lock"; "Lock, Joshua"; "Lock" -"Tony Lownds"; "Lownds, Tony"; "Lownds" -"Martin von Löwis"; "von Löwis, Martin"; "von Löwis" -"Martin v. Löwis"; "\v. Löwis, Martin"; "\v. Löwis" -"Mariatta"; "Mariatta"; "Mariatta" -"Alex Martelli"; "Martelli, Alex"; "Martelli" -"Joseph Martinot-Lagarde"; "Martinot-Lagarde, Joseph"; "Martinot-Lagarde" -"Lino Mastrodomenico"; "Mastrodomenico, Lino"; "Mastrodomenico" -"Patrick Maupin"; "Maupin, Patrick"; "Maupin" -"Andrew McClelland"; "McClelland, Andrew"; "McClelland" -"Charles R. McCreary"; "McCreary, Charles R."; "McCreary" -"Chris McDonough"; "McDonough, Chris"; "McDonough" -"Robert T. McGibbon"; "McGibbon, Robert T."; "McGibbon" -"Gordon McMillan"; "McMillan, Gordon"; "McMillan" -"Andrew McNamara"; "McNamara, Andrew"; "McNamara" -"Ezio Melotti"; "Melotti, Ezio"; "Melotti" -"Mark Mendoza"; "Mendoza, Mark"; "Mendoza" -"Markus Meskanen"; "Meskanen, Markus"; "Meskanen" -"Mike Meyer"; "Meyer, Mike"; "Meyer" -"Carl Meyer"; "Meyer, Carl"; "Meyer" -"Trent Mick"; "Mick, Trent"; "Mick" -"Mike G. Miller"; "Miller, Mike G."; "Miller" -"Skip Montanaro"; "Montanaro, Skip"; "Montanaro" -"Peter Moody"; "Moody, Peter"; "Moody" -"Marina Moore"; "Moore, Marina"; "Moore" -"Paul Moore"; "Moore, Paul"; "Moore" -"R David Murray"; "Murray, R David"; "Murray" -"Charles-François Natali"; "Natali, Charles-François"; "Natali" -"Lysandros Nikolaou"; "Nikolaou, Lysandros"; "Nikolaou" -"Jesse Noller"; "Noller, Jesse"; "Noller" -"Ben North"; "North, Ben"; "North" -"Neal Norwitz"; "Norwitz, Neal"; "Norwitz" -"Dirkjan Ochtman"; "Ochtman, Dirkjan"; "Ochtman" -"Travis Oliphant"; "Oliphant, Travis"; "Oliphant" -"Jason Orendorff"; "Orendorff, Jason"; "Orendorff" -"Tomáš Orsava"; "Orsava, Tomáš"; "Orsava" -"Richard Oudkerk"; "Oudkerk, Richard"; "Oudkerk" -"Ronald Oussoren"; "Oussoren, Ronald"; "Oussoren" -"Julien Palard"; "Palard, Julien"; "Palard" -"Samuele Pedroni"; "Pedroni, Samuele"; "Pedroni" -"Berker Peksag"; "Peksag, Berker"; "Peksag" -"Michel Pelletier"; "Pelletier, Michel"; "Pelletier" -"Tim Peters"; "Peters, Tim"; "Peters" -"Benjamin Peterson"; "Peterson, Benjamin"; "Peterson" -"Jason Petrone"; "Petrone, Jason"; "Petrone" -"Antoine Pitrou"; "Pitrou, Antoine"; "Pitrou" -"Marcel Plch"; "Plch, Marcel"; "Plch" -"James Polley"; "Polley, James"; "Polley" -"Philippe PRADOS"; "Prados, Philippe"; "Prados" -"Elvis Pranskevichus"; "Pranskevichus, Elvis"; "Pranskevichus" -"Paul Prescod"; "Prescod, Paul"; "Prescod" -"(James) Eric Pruitt"; "Pruitt, (James) Eric"; "Pruitt" -"Lukas Puehringer"; "Puehringer, Lukas"; "Puehringer" -"Brian Quinlan"; "Quinlan, Brian"; "Quinlan" -"Terry Reedy"; "Reedy, Terry"; "Reedy" -"Lennart Regebro"; "Regebro, Lennart"; "Regebro" -"Sean Reifschneider"; "Reifschneider, Sean"; "Reifschneider" -"Christian R. Reis"; "Reis, Christian R."; "Reis" -"Jonathan Riehl"; "Riehl, Jonathan"; "Riehl" -"Lisa Roach"; "Roach, Lisa"; "Roach" -"Andre Roberge"; "Roberge, Andre"; "Roberge" -"Armin Ronacher"; "Ronacher, Armin"; "Ronacher" -"Guido van Rossum"; "van Rossum, Guido (GvR)"; "GvR" -"Just van Rossum"; "van Rossum, Just (JvR)"; "JvR" -"Todd Rovito"; "Rovito, Todd"; "Rovito" -"Lie Ryan"; "Ryan, Lie"; "Ryan" -"Vinay Sajip"; "Sajip, Vinay"; "Sajip" -"Pablo Galindo Salgado"; "Salgado, Pablo Galindo"; "Salgado" -"Neil Schemenauer"; "Schemenauer, Neil"; "Schemenauer" -"Peter Schneider-Kamp"; "Schneider-Kamp, Peter"; "Schneider-Kamp" -"Ed Schofield"; "Schofield, Ed"; "Schofield" -"Yury Selivanov"; "Selivanov, Yury"; "Selivanov" -"Jiwon Seo"; "Seo, Jiwon"; "Seo" -"Mark Shannon"; "Shannon, Mark"; "Shannon" -"Cameron Simpson"; "Simpson, Cameron"; "Simpson" -"Greg Slodkowicz"; "Slodkowicz, Greg"; "Slodkowicz" -"Nathaniel J. Smith"; "Smith, Nathaniel J."; "Smith" -"Gregory P. Smith"; "Smith, Gregory P."; "Smith" -"Kevin D. Smith"; "Smith, Kevin D."; "Smith" -"Ethan Smith"; "Smith, Ethan"; "Smith" -"Nathaniel Smith"; "Smith, Nathaniel"; "Smith" -"Eric V. Smith"; "Smith, Eric V."; "Smith" -"Eric Snow"; "Snow, Eric"; "Snow" -"Calvin Spealman"; "Spealman, Calvin"; "Spealman" -"Kerrick Staley"; "Staley, Kerrick"; "Staley" -"Greg Stein"; "Stein, Greg"; "Stein" -"Victor Stinner"; "Stinner, Victor"; "Stinner" -"Serhiy Storchaka"; "Storchaka, Serhiy"; "Storchaka" -"Donald Stufft"; "Stufft, Donald"; "Stufft" -"Daniel Stutzbach"; "Stutzbach, Daniel"; "Stutzbach" -"Michael J. Sullivan"; "Sullivan, Michael J."; "Sullivan" -"Roman Suzi"; "Suzi, Roman"; "Suzi" -"Dennis Sweeney"; "Sweeney, Dennis"; "Sweeney" -"Talin"; "Talin"; "Talin" -"Steven Taschuk"; "Taschuk, Steven"; "Taschuk" -"Batuhan Taskaya"; "Taskaya, Batuhan"; "Taskaya" -"Martin Teichmann"; "Teichmann, Martin"; "Teichmann" -"The Python core team and community"; "The Python core team and community"; "The Python core team and community" -"Geoffrey Thomas"; "Thomas, Geoffrey"; "Thomas" -"Oren Tirosh"; "Tirosh, Oren"; "Tirosh" -"Stephen J. Turnbull"; "Turnbull, Stephen J."; "Turnbull" -"Daniel Urban"; "Urban, Daniel"; "Urban" -"Eric N. Vander Weele"; "Vander Weele, Eric N."; "Vander Weele" -"Till Varoquaux"; "Varoquaux, Till"; "Varoquaux" -"Alexandre Vassalotti"; "Vassalotti, Alexandre"; "Vassalotti" -"Mike Verdone"; "Verdone, Mike"; "Verdone" -"Dino Viehland"; "Viehland, Dino"; "Viehland" -"Petr Viktorin"; "Viktorin, Petr"; "Viktorin" -"Zachary Ware"; "Ware, Zachary"; "Ware" -"Gregory R. Warnes"; "Warnes, Gregory R."; "Warnes" -"Barry Warsaw"; "Warsaw, Barry"; "Warsaw" -"Terence Way"; "Way, Terence"; "Way" -"Cliff Wells"; "Wells, Cliff"; "Wells" -"Jervis Whitley"; "Whitley, Jervis"; "Whitley" -"Mark Williams"; "Williams, Mark"; "Williams" -"Carol Willing"; "Willing, Carol"; "Willing" -"Greg Wilson"; "Wilson, Greg"; "Wilson" -"Collin Winter"; "Winter, Collin"; "Winter" -"Thomas Wouters"; "Wouters, Thomas"; "Wouters" -"Masayuki Yamamoto"; "Yamamoto, Masayuki"; "Yamamoto" -"Jeffrey Yasskin"; "Yasskin, Jeffrey"; "Yasskin" -"Ka-Ping Yee"; "Yee, Ka-Ping"; "Yee" -"Moshe Zadka"; "Zadka, Moshe"; "Zadka" -"Koos Zevenhoven"; "Zevenhoven, Koos"; "Zevenhoven" -"Huaiyu Zhu"; "Zhu, Huaiyu"; "Zhu" -"Shannon Zhu"; "Zhu, Shannon"; "Zhu" -"Tarek Ziadé"; "Ziadé, Tarek"; "Ziadé" \ No newline at end of file +"Full Name", "Surname First", "Name Reference" +"Aahz", "Aahz", "Aahz" +"James C. Ahlstrom", "Ahlstrom, James C.", "Ahlstrom" +"Jim Althoff", "Althoff, Jim", "Althoff" +"Kevin Altis", "Altis, Kevin", "Altis" +"Chris Angelico", "Angelico, Chris", "Angelico" +"Philipp Angerer", "Angerer, Philipp", "Angerer" +"David Ascher", "Ascher, David", "Ascher" +"Peter Astrand", "Astrand, Peter", "Astrand" +"Carl Banks", "Banks, Carl", "Banks" +"Christopher Barker", "Barker, Christopher", "Barker" +"Paul Barrett", "Barrett, Paul", "Barrett" +"Facundo Batista", "Batista, Facundo", "Batista" +"Anthony Baxter", "Baxter, Anthony", "Baxter" +"Stefan Behnel", "Behnel, Stefan", "Behnel" +"Thomas Bellman", "Bellman, Thomas", "Bellman" +"Alexander Belopolsky", "Belopolsky, Alexander", "Belopolsky" +"Eli Bendersky", "Bendersky, Eli", "Bendersky" +"Cory Benfield", "Benfield, Cory", "Benfield" +"Steven Bethard", "Bethard, Steven", "Bethard" +"Stéphane Bidoul", "Bidoul, Stéphane", "Bidoul" +"Stefano Borini", "Borini, Stefano", "Borini" +"Georg Brandl", "Brandl, Georg", "Brandl" +"Erik M. Bray", "Bray, Erik M.", "Bray" +"Gerald Britton", "Britton, Gerald", "Britton" +"Oleg Broytman", "Broytman, Oleg", "Broytman" +"Benoit Bryon", "Bryon, Benoit", "Bryon" +"Brandt Bucher", "Bucher, Brandt", "Bucher" +"Brett Cannon", "Cannon, Brett", "Cannon" +"Justin Cappos", "Cappos, Justin", "Cappos" +"Josiah Carlson", "Carlson, Josiah", "Carlson" +"W Isaac Carroll", "Carroll, W Isaac", "Carroll" +"Matt Chisholm", "Chisholm, Matt", "Chisholm" +"Nick Coghlan", "Coghlan, Nick", "Coghlan" +"Dave Cole", "Cole, Dave", "Cole" +"Robert Collins", "Collins, Robert", "Collins" +"Paul Colomiets", "Colomiets, Paul", "Colomiets" +"Mario Corchero", "Corchero, Mario", "Corchero" +"Christopher A. Craig", "Craig, Christopher A.", "Craig" +"Laura Creighton", "Creighton, Laura", "Creighton" +"Steven D'Aprano", "D'Aprano, Steven", "D'Aprano" +"Kushal Das", "Das, Kushal", "Das" +"Ned Deily", "Deily, Ned", "Deily" +"Tim Delaney", "Delaney, Tim", "Delaney" +"Lois Anne DeLong", "DeLong, Lois Anne", "DeLong" +"Jeroen Demeyer", "Demeyer, Jeroen", "Demeyer" +"Vladimir Diaz", "Diaz, Vladimir", "Diaz" +"Jack Diederich", "Diederich, Jack", "Diederich" +"Steve Dower", "Dower, Steve", "Dower" +"Walter Dörwald", "Dörwald, Walter", "Dörwald" +"Fred L. Drake, Jr.", "Drake, Fred L., Jr.", "Drake" +"Michael P. Dubner", "Dubner, Michael P.", "Dubner" +"Paul F. Dubois", "Dubois, Paul F.", "Dubois" +"Ernest W. Durbin III", "Durbin, Ernest W., III", "Durbin" +"P.J. Eby", "Eby, P.J.", "Eby" +"Phillip J. Eby", "Eby, Phillip J.", "Eby" +"Tal Einat", "Einat, Tal", "Einat" +"Micah Elliott", "Elliott, Micah", "Elliott" +"Jeff Epler", "Epler, Jeff", "Epler" +"David Eppstein", "Eppstein, David", "Eppstein" +"Clark C. Evans", "Evans, Clark C.", "Evans" +"Gregory Ewing", "Ewing, Gregory", "Ewing" +"Greg Ewing", "Ewing, Greg", "Ewing" +"Martijn Faassen", "Faassen, Martijn", "Faassen" +"Ben Finney", "Finney, Ben", "Finney" +"Michael Foord", "Foord, Michael", "Foord" +"Ethan Furman", "Furman, Ethan", "Furman" +"Pablo Galindo", "Galindo, Pablo", "Galindo" +"Paul Ganssle", "Ganssle, Paul", "Ganssle" +"Alex Gaynor", "Gaynor, Alex", "Gaynor" +"Pradyun Gedam", "Gedam, Pradyun", "Gedam" +"Damien George", "George, Damien", "George" +"Frédéric B. Giacometti", "Giacometti, Frédéric B.", "Giacometti" +"Scott Gilbert", "Gilbert, Scott", "Gilbert" +"Ryan Gonzalez", "Gonzalez, Ryan", "Gonzalez" +"David Goodger", "Goodger, David", "Goodger" +"Grant Griffin", "Griffin, Grant", "Griffin" +"Mark E. Haase", "Haase, Mark E.", "Haase" +"Mark Hammond", "Hammond, Mark", "Hammond" +"Peter Harris", "Harris, Peter", "Harris" +"Larry Hastings", "Hastings, Larry", "Hastings" +"Christian Heimes", "Heimes, Christian", "Heimes" +"Thomas Heller", "Heller, Thomas", "Heller" +"Doug Hellmann", "Hellmann, Doug", "Hellmann" +"Magnus Lie Hetland", "Hetland, Magnus Lie", "Hetland" +"Raymond Hettinger", "Hettinger, Raymond", "Hettinger" +"Neil Hodgson", "Hodgson, Neil", "Hodgson" +"Daniel Holth", "Holth, Daniel", "Holth" +"Philip House", "House, Philip", "House" +"Laurens Van Houtven", "Van Houtven, Laurens", "Houtven" +"Ben Hoyt", "Hoyt, Ben", "Hoyt" +"Miro Hrončok", "Hrončok, Miro", "Hrončok" +"Michael Hudson", "Hudson, Michael", "Hudson" +"Jeremy Hylton", "Hylton, Jeremy", "Hylton" +"Inada Naoki", "Inada, Naoki", "Inada" +"Dustin Ingram", "Ingram, Dustin", "Ingram" +"Atsuo Ishimoto", "Ishimoto, Atsuo", "Ishimoto" +"Jack Jansen", "Jansen, Jack", "Jansen" +"Chris Jerdonek", "Jerdonek, Chris", "Jerdonek" +"Joseph Jevnik", "Jevnik, Joseph", "Jevnik" +"Jim J. Jewett", "Jewett, Jim J.", "Jewett" +"Jim Jewett", "Jewett, Jim", "Jewett" +"Ewa Jodlowska", "Jodlowska, Ewa", "Jodlowska" +"Richard Jones", "Jones, Richard", "Jones" +"Konstantin Kashin", "Kashin, Konstantin", "Kashin" +"Reid Kleckner", "Kleckner, Reid", "Kleckner" +"Thomas Kluyver", "Kluyver, Thomas", "Kluyver" +"Stepan Koltsov", "Koltsov, Stepan", "Koltsov" +"Stefan Krah", "Krah, Stefan", "Krah" +"Sebastian Kreft", "Kreft, Sebastian", "Kreft" +"Holger Krekel", "Krekel, Holger", "Krekel" +"A.M. Kuchling", "Kuchling, A.M.", "Kuchling" +"Trishank Karthik Kuppusamy", "Kuppusamy, Trishank Karthik", "Kuppusamy" +"Robert Kuska", "Kuska, Robert", "Kuska" +"Joshua Landau", "Landau, Joshua", "Landau" +"Łukasz Langa", "Langa, Łukasz", "Langa" +"Michael Lee", "Lee, Michael", "Lee" +"Jukka Lehtosalo", "Lehtosalo, Jukka", "Lehtosalo" +"Marc-André Lemburg", "Lemburg, Marc-André", "Lemburg" +"Ivan Levkivskyi", "Levkivskyi, Ivan", "Levkivskyi" +"Gregory Lielens", "Lielens, Gregory", "Lielens" +"Björn Lindqvist", "Lindqvist, Björn", "Lindqvist" +"Joshua Lock", "Lock, Joshua", "Lock" +"Tony Lownds", "Lownds, Tony", "Lownds" +"Martin von Löwis", "von Löwis, Martin", "von Löwis" +"Martin v. Löwis", "\v. Löwis, Martin", "\v. Löwis" +"Mariatta", "Mariatta", "Mariatta" +"Alex Martelli", "Martelli, Alex", "Martelli" +"Joseph Martinot-Lagarde", "Martinot-Lagarde, Joseph", "Martinot-Lagarde" +"Lino Mastrodomenico", "Mastrodomenico, Lino", "Mastrodomenico" +"Patrick Maupin", "Maupin, Patrick", "Maupin" +"Andrew McClelland", "McClelland, Andrew", "McClelland" +"Charles R. McCreary", "McCreary, Charles R.", "McCreary" +"Chris McDonough", "McDonough, Chris", "McDonough" +"Robert T. McGibbon", "McGibbon, Robert T.", "McGibbon" +"Gordon McMillan", "McMillan, Gordon", "McMillan" +"Andrew McNamara", "McNamara, Andrew", "McNamara" +"Ezio Melotti", "Melotti, Ezio", "Melotti" +"Mark Mendoza", "Mendoza, Mark", "Mendoza" +"Markus Meskanen", "Meskanen, Markus", "Meskanen" +"Mike Meyer", "Meyer, Mike", "Meyer" +"Carl Meyer", "Meyer, Carl", "Meyer" +"Trent Mick", "Mick, Trent", "Mick" +"Mike G. Miller", "Miller, Mike G.", "Miller" +"Skip Montanaro", "Montanaro, Skip", "Montanaro" +"Peter Moody", "Moody, Peter", "Moody" +"Marina Moore", "Moore, Marina", "Moore" +"Paul Moore", "Moore, Paul", "Moore" +"R David Murray", "Murray, R David", "Murray" +"Charles-François Natali", "Natali, Charles-François", "Natali" +"Lysandros Nikolaou", "Nikolaou, Lysandros", "Nikolaou" +"Jesse Noller", "Noller, Jesse", "Noller" +"Ben North", "North, Ben", "North" +"Neal Norwitz", "Norwitz, Neal", "Norwitz" +"Dirkjan Ochtman", "Ochtman, Dirkjan", "Ochtman" +"Travis Oliphant", "Oliphant, Travis", "Oliphant" +"Jason Orendorff", "Orendorff, Jason", "Orendorff" +"Tomáš Orsava", "Orsava, Tomáš", "Orsava" +"Richard Oudkerk", "Oudkerk, Richard", "Oudkerk" +"Ronald Oussoren", "Oussoren, Ronald", "Oussoren" +"Julien Palard", "Palard, Julien", "Palard" +"Samuele Pedroni", "Pedroni, Samuele", "Pedroni" +"Berker Peksag", "Peksag, Berker", "Peksag" +"Michel Pelletier", "Pelletier, Michel", "Pelletier" +"Tim Peters", "Peters, Tim", "Peters" +"Benjamin Peterson", "Peterson, Benjamin", "Peterson" +"Jason Petrone", "Petrone, Jason", "Petrone" +"Antoine Pitrou", "Pitrou, Antoine", "Pitrou" +"Marcel Plch", "Plch, Marcel", "Plch" +"James Polley", "Polley, James", "Polley" +"Philippe PRADOS", "Prados, Philippe", "Prados" +"Elvis Pranskevichus", "Pranskevichus, Elvis", "Pranskevichus" +"Paul Prescod", "Prescod, Paul", "Prescod" +"(James) Eric Pruitt", "Pruitt, (James) Eric", "Pruitt" +"Lukas Puehringer", "Puehringer, Lukas", "Puehringer" +"Brian Quinlan", "Quinlan, Brian", "Quinlan" +"Terry Reedy", "Reedy, Terry", "Reedy" +"Lennart Regebro", "Regebro, Lennart", "Regebro" +"Sean Reifschneider", "Reifschneider, Sean", "Reifschneider" +"Christian R. Reis", "Reis, Christian R.", "Reis" +"Jonathan Riehl", "Riehl, Jonathan", "Riehl" +"Lisa Roach", "Roach, Lisa", "Roach" +"Andre Roberge", "Roberge, Andre", "Roberge" +"Armin Ronacher", "Ronacher, Armin", "Ronacher" +"Guido van Rossum", "van Rossum, Guido (GvR)", "GvR" +"Just van Rossum", "van Rossum, Just (JvR)", "JvR" +"Todd Rovito", "Rovito, Todd", "Rovito" +"Lie Ryan", "Ryan, Lie", "Ryan" +"Vinay Sajip", "Sajip, Vinay", "Sajip" +"Pablo Galindo Salgado", "Salgado, Pablo Galindo", "Salgado" +"Neil Schemenauer", "Schemenauer, Neil", "Schemenauer" +"Peter Schneider-Kamp", "Schneider-Kamp, Peter", "Schneider-Kamp" +"Ed Schofield", "Schofield, Ed", "Schofield" +"Yury Selivanov", "Selivanov, Yury", "Selivanov" +"Jiwon Seo", "Seo, Jiwon", "Seo" +"Mark Shannon", "Shannon, Mark", "Shannon" +"Cameron Simpson", "Simpson, Cameron", "Simpson" +"Greg Slodkowicz", "Slodkowicz, Greg", "Slodkowicz" +"Nathaniel J. Smith", "Smith, Nathaniel J.", "Smith" +"Gregory P. Smith", "Smith, Gregory P.", "Smith" +"Kevin D. Smith", "Smith, Kevin D.", "Smith" +"Ethan Smith", "Smith, Ethan", "Smith" +"Nathaniel Smith", "Smith, Nathaniel", "Smith" +"Eric V. Smith", "Smith, Eric V.", "Smith" +"Eric Snow", "Snow, Eric", "Snow" +"Calvin Spealman", "Spealman, Calvin", "Spealman" +"Kerrick Staley", "Staley, Kerrick", "Staley" +"Greg Stein", "Stein, Greg", "Stein" +"Victor Stinner", "Stinner, Victor", "Stinner" +"Serhiy Storchaka", "Storchaka, Serhiy", "Storchaka" +"Donald Stufft", "Stufft, Donald", "Stufft" +"Daniel Stutzbach", "Stutzbach, Daniel", "Stutzbach" +"Michael J. Sullivan", "Sullivan, Michael J.", "Sullivan" +"Roman Suzi", "Suzi, Roman", "Suzi" +"Dennis Sweeney", "Sweeney, Dennis", "Sweeney" +"Talin", "Talin", "Talin" +"Steven Taschuk", "Taschuk, Steven", "Taschuk" +"Batuhan Taskaya", "Taskaya, Batuhan", "Taskaya" +"Martin Teichmann", "Teichmann, Martin", "Teichmann" +"The Python core team and community", "The Python core team and community", "The Python core team and community" +"Geoffrey Thomas", "Thomas, Geoffrey", "Thomas" +"Oren Tirosh", "Tirosh, Oren", "Tirosh" +"Stephen J. Turnbull", "Turnbull, Stephen J.", "Turnbull" +"Daniel Urban", "Urban, Daniel", "Urban" +"Eric N. Vander Weele", "Vander Weele, Eric N.", "Vander Weele" +"Till Varoquaux", "Varoquaux, Till", "Varoquaux" +"Alexandre Vassalotti", "Vassalotti, Alexandre", "Vassalotti" +"Mike Verdone", "Verdone, Mike", "Verdone" +"Dino Viehland", "Viehland, Dino", "Viehland" +"Petr Viktorin", "Viktorin, Petr", "Viktorin" +"Zachary Ware", "Ware, Zachary", "Ware" +"Gregory R. Warnes", "Warnes, Gregory R.", "Warnes" +"Barry Warsaw", "Warsaw, Barry", "Warsaw" +"Terence Way", "Way, Terence", "Way" +"Cliff Wells", "Wells, Cliff", "Wells" +"Jervis Whitley", "Whitley, Jervis", "Whitley" +"Mark Williams", "Williams, Mark", "Williams" +"Carol Willing", "Willing, Carol", "Willing" +"Greg Wilson", "Wilson, Greg", "Wilson" +"Collin Winter", "Winter, Collin", "Winter" +"Thomas Wouters", "Wouters, Thomas", "Wouters" +"Masayuki Yamamoto", "Yamamoto, Masayuki", "Yamamoto" +"Jeffrey Yasskin", "Yasskin, Jeffrey", "Yasskin" +"Ka-Ping Yee", "Yee, Ka-Ping", "Yee" +"Moshe Zadka", "Zadka, Moshe", "Zadka" +"Koos Zevenhoven", "Zevenhoven, Koos", "Zevenhoven" +"Huaiyu Zhu", "Zhu, Huaiyu", "Zhu" +"Shannon Zhu", "Zhu, Shannon", "Zhu" +"Tarek Ziadé", "Ziadé, Tarek", "Ziadé" \ No newline at end of file diff --git a/pepreader/generate_pep_index.py b/pepreader/generate_pep_index.py index 34149cbf23a..5933478e0f0 100644 --- a/pepreader/generate_pep_index.py +++ b/pepreader/generate_pep_index.py @@ -35,7 +35,7 @@ def create_pep_zero(_, env, docnames): pep_pat = re.compile(r"pep-\d{4}") # Path.match() doesn't support regular expressions with open("AUTHORS.csv", "r", encoding="UTF8") as f: - read = csv.DictReader(f, delimiter=";") + read = csv.DictReader(f, quotechar='"', skipinitialspace=True) author_data = {} for line in read: full_name = line.pop("Full Name").strip().strip("\"") From 0057861d439c04721f36e22100b5dcb81f663087 Mon Sep 17 00:00:00 2001 From: AA Turner <9087854+AA-Turner@users.noreply.github.com> Date: Thu, 30 Apr 2020 01:39:05 +0100 Subject: [PATCH 035/108] Allow Failures in Travis --- .travis.yml | 15 +++++---------- build.py | 2 +- pepreader/__init__.py | 2 +- 3 files changed, 7 insertions(+), 12 deletions(-) diff --git a/.travis.yml b/.travis.yml index ede903d0486..0481ac55230 100644 --- a/.travis.yml +++ b/.travis.yml @@ -45,13 +45,6 @@ jobs: - COMMAND="python3 ./build.py -f" - FAIL_ALLOWED=true - # Tests build with Fail on Warning (Nitpicky) - - name: "3.8 Fail on Warning Nitpicky" - python: 3.8 - env: - - COMMAND="python3 ./build.py -f -n" - - FAIL_ALLOWED=true - # Checks link references within PEPs - name: "3.8 Check Links" python: 3.8 @@ -60,8 +53,10 @@ jobs: - FAIL_ALLOWED=true allow_failures: - # Note test failure, but pass the build - - env: - - FAIL_ALLOWED=true + # Note test failure, but pass the build as a whole + - name: "3.8 Fail on Warning" + + # Check links can fail as it is dependent on external pages + - name: "3.8 Check Links" script: $COMMAND \ No newline at end of file diff --git a/build.py b/build.py index 69eb6c9ac48..9ba00630f9c 100644 --- a/build.py +++ b/build.py @@ -43,6 +43,6 @@ def create_parser(): app = Sphinx( source_directory, configuration_directory, build_directory, doctree_directory, builder, - confoverrides=config_overrides, warningiserror=args.fail_on_warning, keep_going=args.fail_on_warning, + confoverrides=config_overrides, warningiserror=args.fail_on_warning, ) app.build() diff --git a/pepreader/__init__.py b/pepreader/__init__.py index 95496374c82..f7529f3c431 100644 --- a/pepreader/__init__.py +++ b/pepreader/__init__.py @@ -13,6 +13,6 @@ def setup(app: Sphinx): app.connect("env-before-read-docs", create_pep_zero) app.add_source_parser(PEPParser) - app.add_role('pep', PEPRole()) + app.add_role('pep', PEPRole(), override=True) return {'version': __version__, 'parallel_read_safe': True, 'parallel_write_safe': True} From 2f3b15eb44f733d3ba12395a2964c20393cba956 Mon Sep 17 00:00:00 2001 From: AA Turner <9087854+AA-Turner@users.noreply.github.com> Date: Fri, 1 May 2020 06:27:34 +0100 Subject: [PATCH 036/108] Update Makefile --- .travis.yml | 12 ++++++------ Makefile | 9 ++++++--- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/.travis.yml b/.travis.yml index 0481ac55230..d21497097f0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,7 +14,7 @@ jobs: # Main run, tests build, RSS, and packaging - name: "3.7 Makefile Build" python: 3.7 - env: COMMAND="make -j$(nproc)" + env: COMMAND="make sphinx -j$(nproc)" deploy: provider: script script: bash deploy.bash @@ -26,30 +26,30 @@ jobs: # Tests build on 3.7-dev - name: "3.7-dev Build Test" python: 3.7-dev - env: COMMAND="python3 ./build.py" + env: COMMAND="make sphinx -j$(nproc)" # Tests build on 3.8 - name: "3.8 Build Test" python: 3.8 - env: COMMAND="python3 ./build.py" + env: COMMAND="make sphinx -j$(nproc)" # Tests build on 3.8-dev - name: "3.8-dev Build Test" python: 3.8-dev - env: COMMAND="python3 ./build.py" + env: COMMAND="make sphinx -j$(nproc)" # Tests build with Fail on Warning - name: "3.8 Fail on Warning" python: 3.8 env: - - COMMAND="python3 ./build.py -f" + - COMMAND="make fail_on_warning -j$(nproc)" - FAIL_ALLOWED=true # Checks link references within PEPs - name: "3.8 Check Links" python: 3.8 env: - - COMMAND="python3 ./build.py -c" + - COMMAND="make check_links -j$(nproc)" - FAIL_ALLOWED=true allow_failures: diff --git a/Makefile b/Makefile index 98af7c7fd3b..2bba494ca65 100644 --- a/Makefile +++ b/Makefile @@ -10,12 +10,15 @@ all: sphinx sphinx: $(PYTHON) build.py +fail_on_warning: + $(PYTHON) build.py -f + +check_links: + $(PYTHON) build.py -c + rss: $(PYTHON) pep2rss.py . -install: - echo "Installing is not necessary anymore. It will be done in post-commit." - clean: -rm pep-0000.rst -rm *.html From 7351d99c22ec836acc31cbcfb241a2987dbdc302 Mon Sep 17 00:00:00 2001 From: AA Turner <9087854+AA-Turner@users.noreply.github.com> Date: Fri, 1 May 2020 06:32:17 +0100 Subject: [PATCH 037/108] Re-organise extension - Add custom HTML Translator - Add ReST Target Footnotes - Add module configuration file --- conf.py | 4 +- pep_extensions/__init__.py | 21 +++++++ pep_extensions/config.py | 8 +++ .../pep_processor}/pep_contents.py | 0 .../pep_processor}/pep_headers.py | 24 ++++---- .../pep_processor/pep_html_translator.py | 30 ++++++++++ .../pep_processor}/pep_parser.py | 9 ++- .../pep_processor}/pep_role.py | 8 ++- .../pep_processor/pep_target_notes.py | 60 +++++++++++++++++++ .../pep_processor}/pep_title.py | 0 .../pep_processor}/pep_zero.py | 8 +-- .../pepzero}/generate_pep_index.py | 0 {pepreader => pep_extensions/pepzero}/pep0.py | 6 +- .../pepzero}/pep0_constants.py | 4 +- .../pepzero}/pep0_writer.py | 2 +- pepreader/__init__.py | 18 ------ 16 files changed, 154 insertions(+), 48 deletions(-) create mode 100644 pep_extensions/__init__.py create mode 100644 pep_extensions/config.py rename {pepreader => pep_extensions/pep_processor}/pep_contents.py (100%) rename {pepreader => pep_extensions/pep_processor}/pep_headers.py (87%) create mode 100644 pep_extensions/pep_processor/pep_html_translator.py rename {pepreader => pep_extensions/pep_processor}/pep_parser.py (62%) rename {pepreader => pep_extensions/pep_processor}/pep_role.py (52%) create mode 100644 pep_extensions/pep_processor/pep_target_notes.py rename {pepreader => pep_extensions/pep_processor}/pep_title.py (100%) rename {pepreader => pep_extensions/pep_processor}/pep_zero.py (93%) rename {pepreader => pep_extensions/pepzero}/generate_pep_index.py (100%) rename {pepreader => pep_extensions/pepzero}/pep0.py (97%) rename {pepreader => pep_extensions/pepzero}/pep0_constants.py (96%) rename {pepreader => pep_extensions/pepzero}/pep0_writer.py (99%) delete mode 100644 pepreader/__init__.py diff --git a/conf.py b/conf.py index 17a4200d663..57b6b6a1a87 100644 --- a/conf.py +++ b/conf.py @@ -5,7 +5,7 @@ import sys from pathlib import Path -sys.path.extend(str(Path('./pepreader').absolute())) +sys.path.extend(str(Path('./pep_extensions').absolute())) # -- Project information ----------------------------------------------------- @@ -27,7 +27,7 @@ # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. -extensions = ["pepreader"] +extensions = ["pep_extensions"] # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] diff --git a/pep_extensions/__init__.py b/pep_extensions/__init__.py new file mode 100644 index 00000000000..0dfc24c3762 --- /dev/null +++ b/pep_extensions/__init__.py @@ -0,0 +1,21 @@ +"""Sphinx extensions for performant PEP processing""" +from sphinx.application import Sphinx + +from pep_extensions.config import __version__ + +from pep_extensions.pep_processor import pep_parser +from pep_extensions.pep_processor import pep_role +from pep_extensions.pep_processor import pep_html_translator + +from pep_extensions.pepzero.generate_pep_index import create_pep_zero + + +def setup(app: Sphinx): + """Initialize Sphinx extension.""" + + app.add_source_parser(pep_parser.PEPParser) + app.add_role('pep', pep_role.PEPRole(), override=True) + app.set_translator("html", pep_html_translator.PEPTranslator) + app.connect("env-before-read-docs", create_pep_zero) + + return {'version': __version__, 'parallel_read_safe': True, 'parallel_write_safe': True} diff --git a/pep_extensions/config.py b/pep_extensions/config.py new file mode 100644 index 00000000000..7a6b6d97aa1 --- /dev/null +++ b/pep_extensions/config.py @@ -0,0 +1,8 @@ +"""Misc. config variables for the PEP extensions module.""" +import re + +__version__ = '1.0.0' +pep_stem = "pep-{:0>4}" +pep_url = f"{pep_stem}.html" +pep_vcs_url = f"https://github.com/python/peps/blob/master/{pep_stem}.txt" +rcs_keyword_substitutions = [(re.compile(r"\$[a-zA-Z]+: (.+) \$$"), r"\1")] \ No newline at end of file diff --git a/pepreader/pep_contents.py b/pep_extensions/pep_processor/pep_contents.py similarity index 100% rename from pepreader/pep_contents.py rename to pep_extensions/pep_processor/pep_contents.py diff --git a/pepreader/pep_headers.py b/pep_extensions/pep_processor/pep_headers.py similarity index 87% rename from pepreader/pep_headers.py rename to pep_extensions/pep_processor/pep_headers.py index 49cceacf190..1b308f6048b 100644 --- a/pepreader/pep_headers.py +++ b/pep_extensions/pep_processor/pep_headers.py @@ -5,8 +5,13 @@ from docutils import utils from docutils import transforms from docutils.transforms import peps -from pepreader import pep_zero -import pepreader + +from pep_extensions.pep_processor import pep_zero +import pep_extensions.config + +pep_url = pep_extensions.config.pep_url +pep_vcs_url = pep_extensions.config.pep_vcs_url +rcs_keyword_substitutions = pep_extensions.config.rcs_keyword_substitutions class DataError(Exception): @@ -22,11 +27,6 @@ class PEPHeaders(transforms.Transform): default_priority = 330 - pep_url = pepreader.pep_url - pep_cvs_url = "https://github.com/python/peps/blob/master/pep-{:0>4}.txt" - - rcs_keyword_substitutions = [(re.compile(r"\$[a-zA-Z]+: (.+) \$$"), r"\1")] - def apply(self): if not len(self.document): # @@@ replace these DataErrors with proper system messages @@ -47,7 +47,7 @@ def apply(self): value = pep_field[1].astext() try: pep = int(value) - cvs_url = self.pep_cvs_url.format(pep) + cvs_url = pep_vcs_url.format(pep) except ValueError: pep = value msg = self.document.reporter.warning( @@ -105,17 +105,17 @@ def apply(self): newbody.append(nodes.reference( refpep, refpep, refuri=(self.document.settings.pep_base_url - + self.pep_url.format(pepno)))) + + pep_url.format(pepno)))) newbody.append(space) para[:] = newbody[:-1] # drop trailing space elif name == "last-modified": - utils.clean_rcs_keywords(para, self.rcs_keyword_substitutions) + utils.clean_rcs_keywords(para, rcs_keyword_substitutions) if cvs_url: date = para.astext() para[:] = [nodes.reference("", date, refuri=cvs_url)] elif name == "content-type": pep_type = para.astext() - uri = self.document.settings.pep_base_url + self.pep_url.format(12) + uri = self.document.settings.pep_base_url + pep_url.format(12) para[:] = [nodes.reference("", pep_type, refuri=uri)] elif name == "version" and len(body): - utils.clean_rcs_keywords(para, self.rcs_keyword_substitutions) + utils.clean_rcs_keywords(para, rcs_keyword_substitutions) diff --git a/pep_extensions/pep_processor/pep_html_translator.py b/pep_extensions/pep_processor/pep_html_translator.py new file mode 100644 index 00000000000..50bc13618f1 --- /dev/null +++ b/pep_extensions/pep_processor/pep_html_translator.py @@ -0,0 +1,30 @@ +from docutils.nodes import Node +import sphinx.writers.html5 as html5 + + +class PEPTranslator(html5.HTML5Translator): + def depart_label(self, node): + if not self.settings.footnote_backlinks: + self.body.append('') + self.body.append('\n
') + return + + # If only one reference to this footnote + back_references = node.parent['backrefs'] + if len(back_references) == 1: + self.body.append('') + + # Close the tag + self.body.append('') + + # If more than one reference + if len(back_references) > 1: + back_links = [f'{i}' for (i, ref) in enumerate(back_references, 1)] + back_links_str = ", ".join(back_links) + self.body.append(f" ({back_links_str}) ") + + # Close the def tags + self.body.append('\n
') + + def unknown_visit(self, node: Node) -> None: + pass diff --git a/pepreader/pep_parser.py b/pep_extensions/pep_processor/pep_parser.py similarity index 62% rename from pepreader/pep_parser.py rename to pep_extensions/pep_processor/pep_parser.py index ad320d3e786..d0e2d033465 100644 --- a/pepreader/pep_parser.py +++ b/pep_extensions/pep_processor/pep_parser.py @@ -1,7 +1,9 @@ from sphinx import parsers -from . import pep_headers -from . import pep_title -from . import pep_contents + +from pep_extensions.pep_processor import pep_headers +from pep_extensions.pep_processor import pep_title +from pep_extensions.pep_processor import pep_contents +from pep_extensions.pep_processor import pep_target_notes class PEPParser(parsers.RSTParser): @@ -16,5 +18,6 @@ def get_transforms(self): pep_headers.PEPHeaders, pep_title.PEPTitle, pep_contents.PEPContents, + pep_target_notes.PEPTargetNotes, ]) return transforms diff --git a/pepreader/pep_role.py b/pep_extensions/pep_processor/pep_role.py similarity index 52% rename from pepreader/pep_role.py rename to pep_extensions/pep_processor/pep_role.py index b4632668a87..92ecbb729d5 100644 --- a/pepreader/pep_role.py +++ b/pep_extensions/pep_processor/pep_role.py @@ -1,5 +1,7 @@ from sphinx import roles -import pepreader +import pep_extensions.config + +pep_url = pep_extensions.config.pep_url class PEPRole(roles.PEP): @@ -8,6 +10,6 @@ def build_uri(self) -> str: base_url = self.inliner.document.settings.pep_base_url ret = self.target.split('#', 1) if len(ret) == 2: - return base_url + (pepreader.pep_url + '#{}').format(int(ret[0]), ret[1]) + return base_url + (pep_url + '#{}').format(int(ret[0]), ret[1]) else: - return base_url + pepreader.pep_url.format(int(ret[0])) + return base_url + pep_url.format(int(ret[0])) diff --git a/pep_extensions/pep_processor/pep_target_notes.py b/pep_extensions/pep_processor/pep_target_notes.py new file mode 100644 index 00000000000..b85cbf20e34 --- /dev/null +++ b/pep_extensions/pep_processor/pep_target_notes.py @@ -0,0 +1,60 @@ +from pathlib import Path + +import docutils.transforms as transforms +from docutils.transforms import references +from docutils.transforms import misc +from docutils import nodes + + +class PEPTargetNotes(transforms.Transform): + + """ + Locate the "References" section, insert a placeholder for an external + target footnote insertion transform at the end, and schedule the + transform to run immediately. + """ + + default_priority = 520 + + def apply(self): + if not Path(self.document["source"]).match("pep-*"): + # not a PEP file + return + + doc = self.document[0] + i = len(doc) - 1 + refsect = copyright = None + while i >= 0 and isinstance(doc[i], nodes.section): + title_words = doc[i][0].astext().lower().split() + if 'references' in title_words: + refsect = doc[i] + break + elif 'copyright' in title_words: + copyright = i + i -= 1 + if not refsect: + refsect = nodes.section() + refsect += nodes.title('', 'References') + self.document.set_id(refsect) + if copyright: + # Put the new "References" section before "Copyright": + doc.insert(copyright, refsect) + else: + # Put the new "References" section at end of doc: + doc.append(refsect) + pending = nodes.pending(references.TargetNotes) + refsect.append(pending) + self.document.note_pending(pending, 0) + pending = nodes.pending(misc.CallBack, details={'callback': self.cleanup_callback}) + refsect.append(pending) + self.document.note_pending(pending, 1) + + @staticmethod + def cleanup_callback(pending): + """ + Remove an empty "References" section. + + Called after the `references.TargetNotes` transform is complete. + """ + if len(pending.parent) == 2: # and <pending> + pending.parent.parent.remove(pending.parent) diff --git a/pepreader/pep_title.py b/pep_extensions/pep_processor/pep_title.py similarity index 100% rename from pepreader/pep_title.py rename to pep_extensions/pep_processor/pep_title.py diff --git a/pepreader/pep_zero.py b/pep_extensions/pep_processor/pep_zero.py similarity index 93% rename from pepreader/pep_zero.py rename to pep_extensions/pep_processor/pep_zero.py index a487bfcbbb3..ce4132a03a8 100644 --- a/pepreader/pep_zero.py +++ b/pep_extensions/pep_processor/pep_zero.py @@ -1,7 +1,9 @@ from docutils import nodes from docutils import transforms from docutils.transforms import peps -import pepreader +import pep_extensions.config + +pep_url = pep_extensions.config.pep_url class PEPZero(transforms.Transform): @@ -29,8 +31,6 @@ class PEPZeroSpecial(nodes.SparseNodeVisitor): themselves. """ - pep_url = pepreader.pep_url - def __init__(self, document): super().__init__(document) self.pep_table = None @@ -70,7 +70,7 @@ def visit_entry(self, node): try: pep = int(text) ref = (self.document.settings.pep_base_url - + self.pep_url.format(pep)) + + pep_url.format(pep)) p[0] = nodes.reference(text, text, refuri=ref) except ValueError: pass diff --git a/pepreader/generate_pep_index.py b/pep_extensions/pepzero/generate_pep_index.py similarity index 100% rename from pepreader/generate_pep_index.py rename to pep_extensions/pepzero/generate_pep_index.py diff --git a/pepreader/pep0.py b/pep_extensions/pepzero/pep0.py similarity index 97% rename from pepreader/pep0.py rename to pep_extensions/pepzero/pep0.py index bd69929e5d4..1d18272b10c 100644 --- a/pepreader/pep0.py +++ b/pep_extensions/pepzero/pep0.py @@ -207,9 +207,9 @@ def _parse_author(data): """Return a list of author names and emails.""" # XXX Consider using email.utils.parseaddr (doesn't work with names # lacking an email address. - angled = pep0_constants.text_type(r"(?P<author>.+?) <(?P<email>.+?)>") - paren = pep0_constants.text_type(r"(?P<email>.+?) \((?P<author>.+?)\)") - simple = pep0_constants.text_type(r"(?P<author>[^,]+)") + angled = "(?P<author>.+?) <(?P<email>.+?)>" + paren = "(?P<email>.+?) \((?P<author>.+?)\)" + simple = "(?P<author>[^,]+)" author_list = [] for regex in (angled, paren, simple): # Watch out for commas separating multiple names. diff --git a/pepreader/pep0_constants.py b/pep_extensions/pepzero/pep0_constants.py similarity index 96% rename from pepreader/pep0_constants.py rename to pep_extensions/pepzero/pep0_constants.py index 57e96e9e1d7..83bfe1b08eb 100644 --- a/pepreader/pep0_constants.py +++ b/pep_extensions/pepzero/pep0_constants.py @@ -1,9 +1,9 @@ -# -*- coding: utf-8 -*- from functools import partial -text_type = str + title_length = 55 author_length = 40 table_separator = "== ==== " + "="*title_length + " " + "="*author_length + # column format is called as a function with a mapping containing field values column_format = partial( "{type}{status}{number: >5} {title: <{title_length}} {authors}".format, diff --git a/pepreader/pep0_writer.py b/pep_extensions/pepzero/pep0_writer.py similarity index 99% rename from pepreader/pep0_writer.py rename to pep_extensions/pepzero/pep0_writer.py index e7ec7b072b7..39345c477c4 100644 --- a/pepreader/pep0_writer.py +++ b/pep_extensions/pepzero/pep0_writer.py @@ -209,7 +209,7 @@ def write_pep0(self, peps: list): for pep in peps: if pep.number - prev_pep > 1: self.emit_newline() - self.output(pep0_constants.text_type(pep)) + self.output(str(pep)) prev_pep = pep.number self.emit_table_separator() diff --git a/pepreader/__init__.py b/pepreader/__init__.py deleted file mode 100644 index f7529f3c431..00000000000 --- a/pepreader/__init__.py +++ /dev/null @@ -1,18 +0,0 @@ -"""Sphinx extensions for performant PEP processing""" -from sphinx.application import Sphinx - -__version__ = '1.0.0' -pep_url = "pep-{:0>4}.html" - - -def setup(app: Sphinx): - """Initialize Sphinx extension.""" - from .pep_parser import PEPParser - from .generate_pep_index import create_pep_zero - from .pep_role import PEPRole - - app.connect("env-before-read-docs", create_pep_zero) - app.add_source_parser(PEPParser) - app.add_role('pep', PEPRole(), override=True) - - return {'version': __version__, 'parallel_read_safe': True, 'parallel_write_safe': True} From 4f6ea10827a8dccf44a56a33378ead6aace520a6 Mon Sep 17 00:00:00 2001 From: AA Turner <9087854+AA-Turner@users.noreply.github.com> Date: Sat, 2 May 2020 00:27:28 +0100 Subject: [PATCH 038/108] Update Makefile --- Makefile | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/Makefile b/Makefile index 2bba494ca65..ee3d290a7f1 100644 --- a/Makefile +++ b/Makefile @@ -1,12 +1,10 @@ -# Rules to only make the required HTML versions, not all of them, -# without the user having to keep track of which. -# -# Not really important, but convenient. - -PYTHON=python3 +# Builds PEP files to HTML using sphinx +# Also contains testing targets all: sphinx +PYTHON=python3 + sphinx: $(PYTHON) build.py @@ -19,11 +17,6 @@ check_links: rss: $(PYTHON) pep2rss.py . -clean: - -rm pep-0000.rst - -rm *.html - -rm -rf build - update: git pull https://github.com/python/peps.git From f08e9ff6c00104d3787a5df329d36473b9cd354a Mon Sep 17 00:00:00 2001 From: AA Turner <9087854+AA-Turner@users.noreply.github.com> Date: Fri, 15 May 2020 22:20:44 +0100 Subject: [PATCH 039/108] Improve packaging process (for transforms to pydotorg standards) --- .gitignore | 3 +- conf.py | 2 +- package.py | 89 +++++++++++++++++++++++++++++++++++++++++++----- requirements.txt | 3 +- 4 files changed, 86 insertions(+), 11 deletions(-) diff --git a/.gitignore b/.gitignore index 0be4dea5de6..7bdede6a092 100644 --- a/.gitignore +++ b/.gitignore @@ -9,4 +9,5 @@ __pycache__ *env .vscode *.swp -/build +build +package diff --git a/conf.py b/conf.py index 57b6b6a1a87..55c80936bdf 100644 --- a/conf.py +++ b/conf.py @@ -60,7 +60,7 @@ # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. -# + html_theme = 'classic' # Add any paths that contain custom static files (such as style sheets) here, diff --git a/package.py b/package.py index 3f35ee56dd6..98941d724cb 100644 --- a/package.py +++ b/package.py @@ -1,7 +1,7 @@ """Transforms Sphinx HTML output into python.org input format""" -from bs4 import BeautifulSoup from pathlib import Path +from bs4 import BeautifulSoup if __name__ == '__main__': root_path = Path(".") @@ -12,29 +12,102 @@ for file_path in html_path.glob("pep-*"): if file_path.suffix not in '.html': continue + print(file_path.stem) soup = BeautifulSoup(file_path.read_text(encoding="UTF8"), 'lxml') contents = soup.find('div', class_="body").div + + # Removes <p> tags from list item elements + for tag in contents.findAll("li"): + try: + tag.p.unwrap() + except AttributeError: + # If no <p> tag to unwrap + pass + + # Removes all permalink elements + [tag.decompose() for tag in contents.findAll(class_="headerlink")] + + # Replace brackets class with [ and ] + for tag in contents.findAll("a", class_="brackets"): + tag.insert(0, "[") + tag.append("]") + tag["class"].remove("brackets") + + # Remove Sphinx Header + contents.h1.decompose() + + # Promotes all remaining headers + for level in range(6 - 1): + h_level = level + 2 + headers = contents.findAll(f"h{h_level}") + for header in headers: + header.name = f"h{h_level - 1}" + dl = contents.find('dl') + + # Adds horizontal rule + dl.insert_after(soup.new_tag("hr")) + + # Parses the PEP Info box to transform to pydotorg standards for tag in dl.findChildren(): if tag.name == "dt": tag.name = "th" - tag.find_next_sibling().name = "td" + tag.string += ":" tag.attrs['class'] = 'field-name' - tag.find_next_sibling()['class'] = 'field-body' + value_tag = tag.find_next_sibling() + value_tag.name = "td" + value_tag.string = value_tag.text.strip("\n") + value_tag['class'] = 'field-body' + + # Wrap the key-value pair in a <tr> element tr = soup.new_tag("tr", **{'class': 'field'}) tag.insert_before(tr) - tr.insert(0, tag.find_next_sibling()) + tr.insert(0, value_tag) tr.insert(0, tag) dl.name = 'tbody' - tbl = soup.new_tag('table', **{'class': dl['class']}) + + classes = dl['class'] + classes.remove("simple") + classes.append("docutils") + del dl['class'] + tbl = soup.new_tag('table', **{'class': classes}) dl.wrap(tbl) - dl['class'] = [] tbl.insert(0, soup.new_tag("col", **{'class': "field-body"})) tbl.insert(0, soup.new_tag("col", **{'class': "field-name"})) + # Fix footnotes/references + dl_refs = contents.findAll('dl', class_="footnote brackets") + + for ref in dl_refs: + footnote_rows = [] + for tag in ref.findChildren(): + if tag.name == "dt": + tag.name = "td" + tag.attrs['class'] = 'label' + if tag.span and "brackets" in tag.span.get("class"): + tag.span.insert(0, "[") + tag.span.append("]") + tag.span.unwrap() + + value_tag = tag.find_next_sibling() + value_tag.name = "td" + value_tag.string = value_tag.text.strip("\n") + + # Wrap the key-value pair in a <tr> element + tr = soup.new_tag("tr") + tr.insert(0, value_tag) + tr.insert(0, tag) + footnote_rows.append(tr) + ref.name = 'table' + ref["class"] = "docutils footnote" + ref.contents = footnote_rows + # TODO combine all tables into one (relianbt on fixingf PEP8 table mismatch) + + # Writes transformed HTML write_path = Path('./package/peps') / file_path.name - write_path.write_text(str(contents), encoding="UTF8") + html = [str(i) for i in contents.contents] + write_path.write_text(str("".join(html)), encoding="UTF8") - del soup, contents, dl, tbl + del soup, contents, headers, dl, tbl, dl_refs, html diff --git a/requirements.txt b/requirements.txt index ad88d51c43b..51ddbfe60bc 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,4 +4,5 @@ sphinx >= 3.0.3 docutils >= 0.16 # For packaging to current python.org standards -bs4 \ No newline at end of file +bs4 +lxml \ No newline at end of file From 1e8ea36fa67d614ba5ee7746f719a1872089cd1e Mon Sep 17 00:00:00 2001 From: AA Turner <9087854+AA-Turner@users.noreply.github.com> Date: Sat, 16 May 2020 00:17:18 +0100 Subject: [PATCH 040/108] Transform <code> to <tt> --- package.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/package.py b/package.py index 98941d724cb..7b10a32c0c9 100644 --- a/package.py +++ b/package.py @@ -34,6 +34,11 @@ tag.append("]") tag["class"].remove("brackets") + # Reformat <code> tags to <tt> + for tag in list(contents.findAll("code")): + tag.name = "tt" + [x.unwrap() if x.name else x for x in tag.contents] + # Remove Sphinx Header contents.h1.decompose() From 72064dae383e2a89236e34230987f57a6d21e54b Mon Sep 17 00:00:00 2001 From: AA Turner <9087854+AA-Turner@users.noreply.github.com> Date: Sat, 16 May 2020 00:31:45 +0100 Subject: [PATCH 041/108] Transform literal blocks --- package.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/package.py b/package.py index 7b10a32c0c9..c5a4131c123 100644 --- a/package.py +++ b/package.py @@ -39,6 +39,13 @@ tag.name = "tt" [x.unwrap() if x.name else x for x in tag.contents] + for tag in contents.findAll("div", class_="highlight-default"): + tag.div.unwrap() + tag.pre.unwrap() + tag.name = "pre" + tag["class"] = "literal-block" + tag.string = "\n" + tag.text.strip() + "\n" + # Remove Sphinx Header contents.h1.decompose() From 108615e0b9a5b491198cb32d6dabcecd303f9d2a Mon Sep 17 00:00:00 2001 From: AA Turner <9087854+AA-Turner@users.noreply.github.com> Date: Sat, 16 May 2020 01:01:17 +0100 Subject: [PATCH 042/108] Transform blockquotes --- package.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/package.py b/package.py index c5a4131c123..96a30e01653 100644 --- a/package.py +++ b/package.py @@ -39,6 +39,7 @@ tag.name = "tt" [x.unwrap() if x.name else x for x in tag.contents] + # Reformat code literal blocks for tag in contents.findAll("div", class_="highlight-default"): tag.div.unwrap() tag.pre.unwrap() @@ -46,6 +47,12 @@ tag["class"] = "literal-block" tag.string = "\n" + tag.text.strip() + "\n" + # Transform blockquotes + for tag in contents.findAll("blockquote"): + tag.div.unwrap() + if tag.p: + tag.p.unwrap() + # Remove Sphinx Header contents.h1.decompose() From 441b35f31027843d237d0cfc8b3589c4303c2532 Mon Sep 17 00:00:00 2001 From: AA Turner <9087854+AA-Turner@users.noreply.github.com> Date: Sat, 16 May 2020 01:23:21 +0100 Subject: [PATCH 043/108] Fix author sort --- pep_extensions/pepzero/pep0.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/pep_extensions/pepzero/pep0.py b/pep_extensions/pepzero/pep0.py index 1d18272b10c..7ab4d852b7b 100644 --- a/pep_extensions/pepzero/pep0.py +++ b/pep_extensions/pepzero/pep0.py @@ -59,8 +59,6 @@ class Author(object): def __init__(self, author_and_email_tuple, authors_lookup): """Parse the name and email address of an author.""" - self.first = self.last = '' - name, email = author_and_email_tuple self.first_last = name.strip() self.email = email.lower() @@ -78,14 +76,15 @@ def __eq__(self, other): @property def sort_by(self): - name_parts = self.last.split() + last = self.last_first.split(",")[0] + name_parts = last.split() for index, part in enumerate(name_parts): if part[0].isupper(): base = " ".join(name_parts[index:]).lower() break else: # If no capitals, use the whole string - base = self.last.lower() + base = last.lower() return unicodedata.normalize("NFKD", base) From d4092056309c722b2b7d48a00f0a5f62c1a6f4a7 Mon Sep 17 00:00:00 2001 From: AA Turner <9087854+AA-Turner@users.noreply.github.com> Date: Sat, 16 May 2020 01:24:01 +0100 Subject: [PATCH 044/108] PEP0 transforms --- package.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/package.py b/package.py index 96a30e01653..2de5fffb289 100644 --- a/package.py +++ b/package.py @@ -17,6 +17,11 @@ soup = BeautifulSoup(file_path.read_text(encoding="UTF8"), 'lxml') contents = soup.find('div', class_="body").div + # Handle PEP 0 + if int(file_path.stem[-4:]) == 0: + [tag.p.unwrap() if tag.p else tag for tag in contents.findAll("th")] + [tag.p.unwrap() if tag.p else tag for tag in contents.findAll("td")] + # Removes <p> tags from list item elements for tag in contents.findAll("li"): try: From fa77eb01bb73abeeb722de6d15f361abfdd79198 Mon Sep 17 00:00:00 2001 From: AA Turner <9087854+AA-Turner@users.noreply.github.com> Date: Sat, 16 May 2020 01:52:32 +0100 Subject: [PATCH 045/108] Fix minor regression in blocktest code --- package.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.py b/package.py index 2de5fffb289..a7ceb6f4712 100644 --- a/package.py +++ b/package.py @@ -55,7 +55,7 @@ # Transform blockquotes for tag in contents.findAll("blockquote"): tag.div.unwrap() - if tag.p: + if tag.p and len(tag.contents) == 1: tag.p.unwrap() # Remove Sphinx Header From 761e66f24b8b6a4469aa6483c22bdb0475d5a8dc Mon Sep 17 00:00:00 2001 From: AA Turner <9087854+AA-Turner@users.noreply.github.com> Date: Sat, 16 May 2020 02:31:17 +0100 Subject: [PATCH 046/108] Fix minor regression in li/p code --- package.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/package.py b/package.py index a7ceb6f4712..994b56cde87 100644 --- a/package.py +++ b/package.py @@ -24,11 +24,10 @@ # Removes <p> tags from list item elements for tag in contents.findAll("li"): - try: + if tag.p and len(tag.contents) == 1: + tag.p.unwrap() + elif "ul" in [t.name for t in tag.contents]: tag.p.unwrap() - except AttributeError: - # If no <p> tag to unwrap - pass # Removes all permalink elements [tag.decompose() for tag in contents.findAll(class_="headerlink")] From c42e5f6654b6dbf1a130d3599bfc1d352ed6de76 Mon Sep 17 00:00:00 2001 From: AA Turner <9087854+AA-Turner@users.noreply.github.com> Date: Wed, 17 Jun 2020 19:48:08 +0100 Subject: [PATCH 047/108] Try again on theming - starting over! --- _templates/layout.html | 4 --- conf.py | 5 ++-- pep_extensions/theme/layout.html | 13 +++++++++ .../theme/static/pep.css | 0 pep_extensions/theme/theme.conf | 28 +++++++++++++++++++ 5 files changed, 44 insertions(+), 6 deletions(-) delete mode 100644 _templates/layout.html create mode 100644 pep_extensions/theme/layout.html rename pep.css => pep_extensions/theme/static/pep.css (100%) create mode 100644 pep_extensions/theme/theme.conf diff --git a/_templates/layout.html b/_templates/layout.html deleted file mode 100644 index 2bd13e35d6d..00000000000 --- a/_templates/layout.html +++ /dev/null @@ -1,4 +0,0 @@ -{% extends "!layout.html" %} - -{# Set the delimiter after the short title on the rel-bar #} -{% set reldelim1 = ' 🡢' %} \ No newline at end of file diff --git a/conf.py b/conf.py index 55c80936bdf..cc6d6372887 100644 --- a/conf.py +++ b/conf.py @@ -30,7 +30,7 @@ extensions = ["pep_extensions"] # Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] +templates_path = ['pep_extensions/theme'] # The file extensions of source files. Sphinx considers the files with # these suffixes as sources. @@ -61,7 +61,8 @@ # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. -html_theme = 'classic' +html_theme_path = ["pep_extensions"] +html_theme = "theme" # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, diff --git a/pep_extensions/theme/layout.html b/pep_extensions/theme/layout.html new file mode 100644 index 00000000000..4b1a5bbc8d5 --- /dev/null +++ b/pep_extensions/theme/layout.html @@ -0,0 +1,13 @@ +{% extends "!layout.html" %} + + +{# Set the stylesheets #} +{% block linktags %} +{{ super() }} +<link href="https://www.python.org/static/stylesheets/style.css" rel="stylesheet"> +<link href="https://www.python.org/static/stylesheets/mq.css" rel="stylesheet"> +{% endblock %} + + +{# Set the delimiter after the short title on the rel-bar #} +{% set reldelim1 = ' 🡢' %} \ No newline at end of file diff --git a/pep.css b/pep_extensions/theme/static/pep.css similarity index 100% rename from pep.css rename to pep_extensions/theme/static/pep.css diff --git a/pep_extensions/theme/theme.conf b/pep_extensions/theme/theme.conf new file mode 100644 index 00000000000..95acf079627 --- /dev/null +++ b/pep_extensions/theme/theme.conf @@ -0,0 +1,28 @@ +[theme] +inherit = default +pygments_style = sphinx +pygments_dark_style = monokai + +[options] +bodyfont = 'Lucida Grande', Arial, sans-serif +headfont = 'Lucida Grande', Arial, sans-serif +footerbgcolor = white +footertextcolor = white +relbarbgcolor = white +relbartextcolor = white +relbarlinkcolor = white +sidebarbgcolor = white +sidebartextcolor = white +sidebarlinkcolor = white +bgcolor = white +textcolor = white +linkcolor = white +visitedlinkcolor = white +headtextcolor = white +headbgcolor = white +headlinkcolor = white + +root_name = Python +root_url = https://www.python.org/ +root_icon = +root_include_title = True \ No newline at end of file From 62132700319f26158f9d69dd0c07a5aed9da0028 Mon Sep 17 00:00:00 2001 From: AA Turner <9087854+AA-Turner@users.noreply.github.com> Date: Sun, 21 Jun 2020 19:33:31 +0100 Subject: [PATCH 048/108] Type hinting: pep_zero.py --- pep_extensions/pep_processor/pep_zero.py | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/pep_extensions/pep_processor/pep_zero.py b/pep_extensions/pep_processor/pep_zero.py index ce4132a03a8..fd31e6994ec 100644 --- a/pep_extensions/pep_processor/pep_zero.py +++ b/pep_extensions/pep_processor/pep_zero.py @@ -26,41 +26,40 @@ class PEPZeroSpecial(nodes.SparseNodeVisitor): Perform the special processing needed by PEP 0: - Mask email addresses. - - Link PEP numbers in the second column of 4-column tables to the PEPs themselves. """ - def __init__(self, document): + def __init__(self, document: nodes.document): super().__init__(document) - self.pep_table = None - self.entry = None + self.pep_table: int = 0 + self.entry: int = 0 - def unknown_visit(self, node): + def unknown_visit(self, node: nodes.Node) -> None: pass @staticmethod - def visit_reference(node): + def visit_reference(node: nodes.reference) -> None: node.replace_self(peps.mask_email(node)) @staticmethod - def visit_field_list(node): + def visit_field_list(node: nodes.field_list) -> None: if 'rfc2822' in node['classes']: raise nodes.SkipNode - def visit_tgroup(self, node): + def visit_tgroup(self, node: nodes.tgroup) -> None: self.pep_table = node['cols'] == 4 self.entry = 0 - def visit_colspec(self, node): + def visit_colspec(self, node: nodes.colspec) -> None: self.entry += 1 if self.pep_table and self.entry == 2: node['classes'].append('num') - def visit_row(self, node): + def visit_row(self, _node: nodes.row) -> None: self.entry = 0 - def visit_entry(self, node): + def visit_entry(self, node: nodes.entry) -> None: self.entry += 1 if self.pep_table and self.entry == 2 and len(node) == 1: node['classes'].append('num') @@ -69,8 +68,7 @@ def visit_entry(self, node): text = p.astext() try: pep = int(text) - ref = (self.document.settings.pep_base_url - + pep_url.format(pep)) + ref = self.document.settings.pep_base_url + pep_url.format(pep) p[0] = nodes.reference(text, text, refuri=ref) except ValueError: pass From 9aaff1fb595adabd6e6ad5bbd604e517a62b8561 Mon Sep 17 00:00:00 2001 From: AA Turner <9087854+AA-Turner@users.noreply.github.com> Date: Sun, 21 Jun 2020 19:37:43 +0100 Subject: [PATCH 049/108] clean imports in PEPTargetNotes --- .../pep_processor/pep_target_notes.py | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/pep_extensions/pep_processor/pep_target_notes.py b/pep_extensions/pep_processor/pep_target_notes.py index b85cbf20e34..548c837c538 100644 --- a/pep_extensions/pep_processor/pep_target_notes.py +++ b/pep_extensions/pep_processor/pep_target_notes.py @@ -1,9 +1,9 @@ from pathlib import Path -import docutils.transforms as transforms -from docutils.transforms import references -from docutils.transforms import misc from docutils import nodes +from docutils import transforms +from docutils.transforms import misc +from docutils.transforms import references class PEPTargetNotes(transforms.Transform): @@ -23,30 +23,30 @@ def apply(self): doc = self.document[0] i = len(doc) - 1 - refsect = copyright = None + reference_section = copyright = None while i >= 0 and isinstance(doc[i], nodes.section): title_words = doc[i][0].astext().lower().split() if 'references' in title_words: - refsect = doc[i] + reference_section = doc[i] break elif 'copyright' in title_words: copyright = i i -= 1 - if not refsect: - refsect = nodes.section() - refsect += nodes.title('', 'References') - self.document.set_id(refsect) + if not reference_section: + reference_section = nodes.section() + reference_section += nodes.title('', 'References') + self.document.set_id(reference_section) if copyright: # Put the new "References" section before "Copyright": - doc.insert(copyright, refsect) + doc.insert(copyright, reference_section) else: # Put the new "References" section at end of doc: - doc.append(refsect) + doc.append(reference_section) pending = nodes.pending(references.TargetNotes) - refsect.append(pending) + reference_section.append(pending) self.document.note_pending(pending, 0) pending = nodes.pending(misc.CallBack, details={'callback': self.cleanup_callback}) - refsect.append(pending) + reference_section.append(pending) self.document.note_pending(pending, 1) @staticmethod From 62e25369e5e5f3c7424a3563499bb82fc2a3a034 Mon Sep 17 00:00:00 2001 From: AA Turner <9087854+AA-Turner@users.noreply.github.com> Date: Sun, 21 Jun 2020 19:39:23 +0100 Subject: [PATCH 050/108] Add github source link transform --- pep_extensions/pep_processor/pep_target_notes.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/pep_extensions/pep_processor/pep_target_notes.py b/pep_extensions/pep_processor/pep_target_notes.py index 548c837c538..84893dcf93d 100644 --- a/pep_extensions/pep_processor/pep_target_notes.py +++ b/pep_extensions/pep_processor/pep_target_notes.py @@ -5,6 +5,7 @@ from docutils.transforms import misc from docutils.transforms import references +import pep_extensions.config as pep_config class PEPTargetNotes(transforms.Transform): @@ -17,7 +18,8 @@ class PEPTargetNotes(transforms.Transform): default_priority = 520 def apply(self): - if not Path(self.document["source"]).match("pep-*"): + pep_source_path = Path(self.document["source"]) + if not pep_source_path.match("pep-*"): # not a PEP file return @@ -49,6 +51,8 @@ def apply(self): reference_section.append(pending) self.document.note_pending(pending, 1) + self.add_source_link(pep_source_path) + @staticmethod def cleanup_callback(pending): """ @@ -58,3 +62,9 @@ def cleanup_callback(pending): """ if len(pending.parent) == 2: # <title> and <pending> pending.parent.parent.remove(pending.parent) + + def add_source_link(self, pep_source_path: Path) -> None: + source_link = pep_config.pep_vcs_url.format(pep_source_path.name) + link_node = nodes.reference("", source_link, refuri=source_link) + span_node = nodes.inline("", "Source: ", link_node) + self.document.append(span_node) From 15696fb8d74d7aa36e959b286f7642eb18c1197f Mon Sep 17 00:00:00 2001 From: AA Turner <9087854+AA-Turner@users.noreply.github.com> Date: Sun, 21 Jun 2020 19:40:36 +0100 Subject: [PATCH 051/108] Rename pep_target_notes.py to better reflect role --- .../{pep_target_notes.py => pep_footer.py} | 18 ++++++++++++++---- pep_extensions/pep_processor/pep_parser.py | 4 ++-- 2 files changed, 16 insertions(+), 6 deletions(-) rename pep_extensions/pep_processor/{pep_target_notes.py => pep_footer.py} (82%) diff --git a/pep_extensions/pep_processor/pep_target_notes.py b/pep_extensions/pep_processor/pep_footer.py similarity index 82% rename from pep_extensions/pep_processor/pep_target_notes.py rename to pep_extensions/pep_processor/pep_footer.py index 84893dcf93d..40129b58dd8 100644 --- a/pep_extensions/pep_processor/pep_target_notes.py +++ b/pep_extensions/pep_processor/pep_footer.py @@ -7,12 +7,22 @@ import pep_extensions.config as pep_config -class PEPTargetNotes(transforms.Transform): + +class PEPFooter(transforms.Transform): """ - Locate the "References" section, insert a placeholder for an external - target footnote insertion transform at the end, and schedule the - transform to run immediately. + Relevant footer transforms for PEPs, including appending external + links to footnotes and creating a link to the (GitHub) source. + + TargetNotes: + Locate the "References" section, insert a placeholder at the end + for an external target footnote insertion transform, and schedule + the transform to run immediately. + + Source Link: + Create the link to the source file from the document source path, + and append the text to the end of the document. + """ default_priority = 520 diff --git a/pep_extensions/pep_processor/pep_parser.py b/pep_extensions/pep_processor/pep_parser.py index d0e2d033465..be87d6ff109 100644 --- a/pep_extensions/pep_processor/pep_parser.py +++ b/pep_extensions/pep_processor/pep_parser.py @@ -3,7 +3,7 @@ from pep_extensions.pep_processor import pep_headers from pep_extensions.pep_processor import pep_title from pep_extensions.pep_processor import pep_contents -from pep_extensions.pep_processor import pep_target_notes +from pep_extensions.pep_processor import pep_footer class PEPParser(parsers.RSTParser): @@ -18,6 +18,6 @@ def get_transforms(self): pep_headers.PEPHeaders, pep_title.PEPTitle, pep_contents.PEPContents, - pep_target_notes.PEPTargetNotes, + pep_footer.PEPFooter, ]) return transforms From c9da1534312073ef5873bbcc9b8ab0f1741004e0 Mon Sep 17 00:00:00 2001 From: AA Turner <9087854+AA-Turner@users.noreply.github.com> Date: Sun, 21 Jun 2020 19:42:25 +0100 Subject: [PATCH 052/108] Remove header fields as per pydotorg converters --- pep_extensions/config.py | 4 +--- pep_extensions/pep_processor/pep_headers.py | 25 ++++++--------------- 2 files changed, 8 insertions(+), 21 deletions(-) diff --git a/pep_extensions/config.py b/pep_extensions/config.py index 7a6b6d97aa1..a83be45a232 100644 --- a/pep_extensions/config.py +++ b/pep_extensions/config.py @@ -1,8 +1,6 @@ """Misc. config variables for the PEP extensions module.""" -import re __version__ = '1.0.0' pep_stem = "pep-{:0>4}" pep_url = f"{pep_stem}.html" -pep_vcs_url = f"https://github.com/python/peps/blob/master/{pep_stem}.txt" -rcs_keyword_substitutions = [(re.compile(r"\$[a-zA-Z]+: (.+) \$$"), r"\1")] \ No newline at end of file +pep_vcs_url = "https://github.com/python/peps/blob/master/{}" diff --git a/pep_extensions/pep_processor/pep_headers.py b/pep_extensions/pep_processor/pep_headers.py index 1b308f6048b..052a470dab6 100644 --- a/pep_extensions/pep_processor/pep_headers.py +++ b/pep_extensions/pep_processor/pep_headers.py @@ -2,7 +2,6 @@ from pathlib import Path from docutils import nodes -from docutils import utils from docutils import transforms from docutils.transforms import peps @@ -10,8 +9,6 @@ import pep_extensions.config pep_url = pep_extensions.config.pep_url -pep_vcs_url = pep_extensions.config.pep_vcs_url -rcs_keyword_substitutions = pep_extensions.config.rcs_keyword_substitutions class DataError(Exception): @@ -40,14 +37,12 @@ def apply(self): if not isinstance(header, nodes.field_list) or "rfc2822" not in header["classes"]: raise DataError("Document does not begin with an RFC-2822 header; it is not a PEP.") - cvs_url = None pep = None pep_field = header[0] if pep_field[0].astext().lower() == "pep": # should be the first field value = pep_field[1].astext() try: pep = int(value) - cvs_url = pep_vcs_url.format(pep) except ValueError: pep = value msg = self.document.reporter.warning( @@ -76,6 +71,7 @@ def apply(self): if len(header) < 2 or header[1][0].astext().lower() != "title": raise DataError("No title!") + fields_to_remove = [] for field in header: name = field[0].astext().lower() body = field[1] @@ -104,18 +100,11 @@ def apply(self): pepno = int(refpep) newbody.append(nodes.reference( refpep, refpep, - refuri=(self.document.settings.pep_base_url - + pep_url.format(pepno)))) + refuri=(self.document.settings.pep_base_url + pep_url.format(pepno)))) newbody.append(space) para[:] = newbody[:-1] # drop trailing space - elif name == "last-modified": - utils.clean_rcs_keywords(para, rcs_keyword_substitutions) - if cvs_url: - date = para.astext() - para[:] = [nodes.reference("", date, refuri=cvs_url)] - elif name == "content-type": - pep_type = para.astext() - uri = self.document.settings.pep_base_url + pep_url.format(12) - para[:] = [nodes.reference("", pep_type, refuri=uri)] - elif name == "version" and len(body): - utils.clean_rcs_keywords(para, rcs_keyword_substitutions) + elif name in ("last-modified", "content-type", "version"): + fields_to_remove.append(field) + + for field in fields_to_remove: + field.parent.remove(field) From 7a348b388486111b1f1384476c5e55b74353617a Mon Sep 17 00:00:00 2001 From: AA Turner <9087854+AA-Turner@users.noreply.github.com> Date: Sun, 21 Jun 2020 19:43:45 +0100 Subject: [PATCH 053/108] prevent unneeded source copying --- build.py | 1 + 1 file changed, 1 insertion(+) diff --git a/build.py b/build.py index 9ba00630f9c..fb4f64ef353 100644 --- a/build.py +++ b/build.py @@ -45,4 +45,5 @@ def create_parser(): source_directory, configuration_directory, build_directory, doctree_directory, builder, confoverrides=config_overrides, warningiserror=args.fail_on_warning, ) + app.builder.copysource = False # Prevent unneeded source copying - we link direct to VCS app.build() From 1e733119d95d390892a152ce12b04585b99417a6 Mon Sep 17 00:00:00 2001 From: AA Turner <9087854+AA-Turner@users.noreply.github.com> Date: Sun, 21 Jun 2020 19:44:08 +0100 Subject: [PATCH 054/108] Clean up docutils.conf --- docutils.conf | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/docutils.conf b/docutils.conf index 8becc5f3062..9af15466166 100644 --- a/docutils.conf +++ b/docutils.conf @@ -2,20 +2,8 @@ # See http://docutils.sf.net/docs/tools.html [general] -# These entries are for the page footer: -source-link: 1 -datestamp: %Y-%m-%d %H:%M UTC -generator: 1 - -# use the local stylesheet -stylesheet: pep.css -template: pyramid-pep-template - -# link to the stylesheet; don't embed it -embed-stylesheet: 0 - -# path to PEPs, for template: +# path to PEPs, for template: [TODO REMOVE; UNNEEDED FOR SPHINX] pep-home: /en/latest/ # base URL for PEP references (no host so mirrors work): -pep-base-url: /en/latest/ +pep-base-url: From ee3e9a5d4d3b3d4438571a05c62e21ce1da4266f Mon Sep 17 00:00:00 2001 From: AA Turner <9087854+AA-Turner@users.noreply.github.com> Date: Sun, 21 Jun 2020 19:44:49 +0100 Subject: [PATCH 055/108] Clean contents.rst - emphasise that we only use it for Sphinx --- contents.rst | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/contents.rst b/contents.rst index 1c8b3c2e276..658655e4044 100644 --- a/contents.rst +++ b/contents.rst @@ -3,11 +3,7 @@ Python Enhancement Proposals (PEPs) *********************************** - -Welcome! - -To get started, have a look at the :doc:`PEP Index<pep-0000>` - +This is an internal Sphinx page, please go to the :doc:`PEP Index<pep-0000>`. .. toctree:: @@ -15,6 +11,6 @@ To get started, have a look at the :doc:`PEP Index<pep-0000>` :titlesonly: :hidden: :glob: - :caption: Sphinx Table of Contents: + :caption: PEP Table of Contents (needed for Sphinx): pep-* \ No newline at end of file From 841fa31bf1935dd97be3f328c1f7c45843cca27d Mon Sep 17 00:00:00 2001 From: AA Turner <9087854+AA-Turner@users.noreply.github.com> Date: Sun, 21 Jun 2020 19:45:54 +0100 Subject: [PATCH 056/108] PEP header styling changes --- pep_extensions/pep_processor/pep_contents.py | 4 ++++ pep_extensions/pep_processor/pep_title.py | 3 ++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/pep_extensions/pep_processor/pep_contents.py b/pep_extensions/pep_processor/pep_contents.py index b64e13ff7f2..bd336deeb29 100644 --- a/pep_extensions/pep_processor/pep_contents.py +++ b/pep_extensions/pep_processor/pep_contents.py @@ -28,6 +28,10 @@ def apply(self): self.document.children[0].insert(2, topic) self.document.note_pending(pending) + # Add horizontal rule before contents + transition = nodes.transition() + self.document[0].insert(2, transition) + class Contents(parts.Contents): def __init__(self, document, startnode=None): diff --git a/pep_extensions/pep_processor/pep_title.py b/pep_extensions/pep_processor/pep_title.py index db9ac0e25f0..f0fa5a2ccaf 100644 --- a/pep_extensions/pep_processor/pep_title.py +++ b/pep_extensions/pep_processor/pep_title.py @@ -19,7 +19,7 @@ def apply(self): # not a PEP file return - # Directory to hold the PEP's RFC2822 header details, to extract a titke string + # Directory to hold the PEP's RFC2822 header details, to extract a title string pep_header_details = {} # Iterate through the header fields, which are the first section of the document @@ -40,6 +40,7 @@ def apply(self): pep_title_node = nodes.section() textnode = nodes.Text(pep_title_string, pep_title_string) titlenode = nodes.title(pep_title_string, '', textnode) + titlenode['classes'].append("page-title") name = states.normalize_name(titlenode.astext()) pep_title_node['names'].append(name) pep_title_node += titlenode From 25b76ff8483425ae2ad22f8eedf59442e3ff1d78 Mon Sep 17 00:00:00 2001 From: AA Turner <9087854+AA-Turner@users.noreply.github.com> Date: Sun, 21 Jun 2020 19:56:55 +0100 Subject: [PATCH 057/108] Add custom paragraph and ordered list visitors (based on html4css1 writer) --- .../pep_processor/pep_html_translator.py | 63 ++++++++++++++++++- 1 file changed, 60 insertions(+), 3 deletions(-) diff --git a/pep_extensions/pep_processor/pep_html_translator.py b/pep_extensions/pep_processor/pep_html_translator.py index 50bc13618f1..f4d45a347ea 100644 --- a/pep_extensions/pep_processor/pep_html_translator.py +++ b/pep_extensions/pep_processor/pep_html_translator.py @@ -1,9 +1,66 @@ -from docutils.nodes import Node +from docutils import nodes import sphinx.writers.html5 as html5 +import re class PEPTranslator(html5.HTML5Translator): - def depart_label(self, node): + compact_field_list = True + phrases_and_newlines = re.compile(r'[^\n]+|\n') + + def __init__(self, *args): + super(PEPTranslator, self).__init__(*args) + self.compact_simple: bool = False + + # Omit <p> tags to produce visually compact lists + def should_be_compact_paragraph(self, node: nodes.paragraph) -> bool: + """Determine if <p> tags around paragraph ``node`` can be omitted.""" + + # Never compact paragraphs in document or compound. + if isinstance(node.parent, (nodes.document, nodes.compound)): + return False + + # Check for custom attributes in paragraph. + for key, value in node.non_default_attributes().items(): + if key != 'classes' or value not in ([], ['first'], ['last'], ['first', 'last']): + return False + + # Only first paragraph can be compact (ignoring initial label & invisible nodes) + first = isinstance(node.parent[0], nodes.label) + visible_siblings = [child for child in node.parent.children[first:] if not isinstance(child, nodes.Invisible)] + if visible_siblings[0] is not node: + return False + + if self.compact_simple or self.compact_field_list: + return True + + parent_length = sum([1 for n in node.parent if not isinstance(n, (nodes.Invisible, nodes.label))]) + if self.compact_p and parent_length == 1: + return True + + return False + + def visit_enumerated_list(self, node: nodes.enumerated_list) -> None: + self.context.append(self.compact_simple) + self.compact_simple = self.is_compactable(node) + super().visit_enumerated_list(node) + + def depart_enumerated_list(self, node: nodes.enumerated_list) -> None: + self.compact_simple = self.context.pop() + super().depart_enumerated_list(node) + + def visit_paragraph(self, node: nodes.paragraph) -> None: + """Remove <p> tags if possible (PEPs historically h )""" + if self.should_be_compact_paragraph(node): + self.context.append('') + else: + self.body.append(self.starttag(node, 'p', '')) + self.context.append('</p>\n') + + def depart_paragraph(self, _: nodes.paragraph) -> None: + """Add corresponding end tag from `visit_paragraph`. Node param isn't needed.""" + self.body.append(self.context.pop()) + + def depart_label(self, node) -> None: if not self.settings.footnote_backlinks: self.body.append('</span>') self.body.append('</dt>\n<dd>') @@ -26,5 +83,5 @@ def depart_label(self, node): # Close the def tags self.body.append('</dt>\n<dd>') - def unknown_visit(self, node: Node) -> None: + def unknown_visit(self, node: nodes.Node) -> None: pass From 4ced4a0705d40097c47dc462e693a6913fe6f622 Mon Sep 17 00:00:00 2001 From: AA Turner <9087854+AA-Turner@users.noreply.github.com> Date: Sun, 21 Jun 2020 19:58:01 +0100 Subject: [PATCH 058/108] Add jinja2 filter for PEP Ids --- conf.py | 1 + pep_extensions/pep_processor/pep_jinja2.py | 30 ++++++++++++++++++++++ 2 files changed, 31 insertions(+) create mode 100644 pep_extensions/pep_processor/pep_jinja2.py diff --git a/conf.py b/conf.py index cc6d6372887..735db64544c 100644 --- a/conf.py +++ b/conf.py @@ -21,6 +21,7 @@ html_short_title = "PEPs Home" html_show_copyright = False html_show_sphinx = False +template_bridge = "pep_extensions.pep_processor.pep_jinja2.PEPTemplateLoader" # -- General configuration --------------------------------------------------- diff --git a/pep_extensions/pep_processor/pep_jinja2.py b/pep_extensions/pep_processor/pep_jinja2.py new file mode 100644 index 00000000000..656014a7617 --- /dev/null +++ b/pep_extensions/pep_processor/pep_jinja2.py @@ -0,0 +1,30 @@ +from __future__ import annotations + +import re +from sphinx import jinja2glue +from typing import TYPE_CHECKING, List + +import pep_extensions.config as pep_config + +if TYPE_CHECKING: + # For type annotation + from sphinx.builders import Builder + from sphinx.theming import Theme + +pep_title_pat = re.compile(r"(PEP \d+).*", flags=re.IGNORECASE) + + +def _pep_id(pep_full_title: str) -> str: + matches = pep_title_pat.match(pep_full_title.strip()) + if not matches: + return "" + pep_short_title = matches.group(1).strip() + pep_num = pep_short_title[4:] + pep_id = pep_config.pep_stem.format(pep_num).replace("-", " ").upper() + return pep_id + + +class PEPTemplateLoader(jinja2glue.BuiltinTemplateLoader): + def init(self, builder: Builder, theme: Theme = None, dirs: List[str] = None) -> None: + super(PEPTemplateLoader, self).init(builder, theme, dirs) + self.environment.filters['pep_id'] = _pep_id \ No newline at end of file From d5aab3bb02d0a5e3fb1160aa2edc533489bf5834 Mon Sep 17 00:00:00 2001 From: AA Turner <9087854+AA-Turner@users.noreply.github.com> Date: Sun, 21 Jun 2020 20:00:50 +0100 Subject: [PATCH 059/108] Add math2html maths processor --- conf.py | 2 +- pep_extensions/__init__.py | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/conf.py b/conf.py index 735db64544c..d09717488e4 100644 --- a/conf.py +++ b/conf.py @@ -64,7 +64,7 @@ html_theme_path = ["pep_extensions"] html_theme = "theme" - +html_math_renderer = "math2html" # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". diff --git a/pep_extensions/__init__.py b/pep_extensions/__init__.py index 0dfc24c3762..47b692a5053 100644 --- a/pep_extensions/__init__.py +++ b/pep_extensions/__init__.py @@ -1,12 +1,11 @@ """Sphinx extensions for performant PEP processing""" from sphinx.application import Sphinx +from docutils.writers.html5_polyglot import HTMLTranslator from pep_extensions.config import __version__ - +from pep_extensions.pep_processor import pep_html_translator from pep_extensions.pep_processor import pep_parser from pep_extensions.pep_processor import pep_role -from pep_extensions.pep_processor import pep_html_translator - from pep_extensions.pepzero.generate_pep_index import create_pep_zero @@ -17,5 +16,6 @@ def setup(app: Sphinx): app.add_role('pep', pep_role.PEPRole(), override=True) app.set_translator("html", pep_html_translator.PEPTranslator) app.connect("env-before-read-docs", create_pep_zero) + app.add_html_math_renderer('math2html', (HTMLTranslator.visit_math, None), (HTMLTranslator.visit_math_block, None)) # NoQA return {'version': __version__, 'parallel_read_safe': True, 'parallel_write_safe': True} From 6fd979592b3caef144a7e475692b585b48abe70f Mon Sep 17 00:00:00 2001 From: AA Turner <9087854+AA-Turner@users.noreply.github.com> Date: Sun, 21 Jun 2020 20:01:35 +0100 Subject: [PATCH 060/108] Reduce page weight - remove jQuery and underscore.js --- pep_extensions/__init__.py | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/pep_extensions/__init__.py b/pep_extensions/__init__.py index 47b692a5053..a929ca94dfa 100644 --- a/pep_extensions/__init__.py +++ b/pep_extensions/__init__.py @@ -1,4 +1,5 @@ """Sphinx extensions for performant PEP processing""" +import sphinx.builders.html from sphinx.application import Sphinx from docutils.writers.html5_polyglot import HTMLTranslator @@ -9,7 +10,19 @@ from pep_extensions.pepzero.generate_pep_index import create_pep_zero -def setup(app: Sphinx): +# Monkeypatch StandaloneHTMLBuilder to not include JS libraries (underscore.js & jQuery) +def init_less_js(self) -> None: + js_files = [('doctools.js', {}), ('language_data.js', {}), ] + js_files.extend([*self.app.registry.js_files, *self.get_builder_config('js_files', 'html')]) + js_files.append(('translations.js',) if self.config.language and self._get_translations_js() else (None, {})) + for filename, attrs in js_files: + self.add_js_file(filename, **attrs) + + +sphinx.builders.html.StandaloneHTMLBuilder.init_js_files = init_less_js + + +def setup(app: Sphinx) -> dict: """Initialize Sphinx extension.""" app.add_source_parser(pep_parser.PEPParser) From 3bfadb22eeccc1d2d726854a752e9e27da3549bf Mon Sep 17 00:00:00 2001 From: AA Turner <9087854+AA-Turner@users.noreply.github.com> Date: Sun, 21 Jun 2020 20:02:54 +0100 Subject: [PATCH 061/108] Add pydotorg base styles (and fix fonts) --- pep_extensions/theme/static/Flux-Regular.ttf | Bin 0 -> 61832 bytes ...urceSansPro-Bold-webfont.be855452e565.woff | Bin 0 -> 26256 bytes ...SourceSansPro-It-webfont.1aa29ac0f190.woff | Bin 0 -> 27964 bytes ...eSansPro-Regular-webfont.fd0d51605201.woff | Bin 0 -> 26392 bytes pep_extensions/theme/static/mq.css | 2673 ++++++++++ pep_extensions/theme/static/style.css | 4501 +++++++++++++++++ 6 files changed, 7174 insertions(+) create mode 100644 pep_extensions/theme/static/Flux-Regular.ttf create mode 100644 pep_extensions/theme/static/SourceSansPro-Bold-webfont.be855452e565.woff create mode 100644 pep_extensions/theme/static/SourceSansPro-It-webfont.1aa29ac0f190.woff create mode 100644 pep_extensions/theme/static/SourceSansPro-Regular-webfont.fd0d51605201.woff create mode 100644 pep_extensions/theme/static/mq.css create mode 100644 pep_extensions/theme/static/style.css diff --git a/pep_extensions/theme/static/Flux-Regular.ttf b/pep_extensions/theme/static/Flux-Regular.ttf new file mode 100644 index 0000000000000000000000000000000000000000..948382896ccca33cd14e0d82a3a399f23b4d0e34 GIT binary patch literal 61832 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 G|K9<?*H8NZ literal 0 HcmV?d00001 diff --git a/pep_extensions/theme/static/SourceSansPro-Bold-webfont.be855452e565.woff b/pep_extensions/theme/static/SourceSansPro-Bold-webfont.be855452e565.woff new file mode 100644 index 0000000000000000000000000000000000000000..58510a7b6bcf54841dbc6a89b2e4a408d90153e7 GIT binary patch literal 26256 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 Tfa*9W!MKqdM6>~LGbsK50n#l& literal 0 HcmV?d00001 diff --git a/pep_extensions/theme/static/SourceSansPro-It-webfont.1aa29ac0f190.woff b/pep_extensions/theme/static/SourceSansPro-It-webfont.1aa29ac0f190.woff new file mode 100644 index 0000000000000000000000000000000000000000..3cd960220baf812a5d77980d8d16cf1fa109d96b GIT binary patch literal 27964 zcmY&;V{k4_)a?`7wsm4VIk8S`+jeqd+qP}nwrv|HcD}s#yZ6VPs#P<4&05pl)l)UQ zcaN*As3-sk@N-!608surPpAHG{NMHee+UXFiU0sWr9Uj+59Gof6MRHPm85^T)1MgU z2e<|hU(sU1BBB5QFz8Q={{uoG3;?K@oUGyxM+yKy(E<SI{bJt#NW~PD1pxpUr5_E= z4;Wg%Tfbx#>6v~w-=A3P2YTkdS<Hsk`gT9u=1)6*KbX(y5(G7LaUui&;PiepGXDW) z3*O$u&eZyctNqc`{j_C_&`4ims_*#YMKJo&K>lAKnp(M={BTwPfbvg23-#(?T%yg4 z^?x)*jXxUZAFzFf?oFBfkU!jiV<Y+jDeMK<v6;1#8vtMo`}2G?005-a6iTec%GU5l zXZqs@n)<;qUlWFzwZ7X=yXGuEKEnS13=ec^qi=2e!~KjGh~dXC$^b7FXlLu_1OQkB z{&2@X+;Y^HWt5$R@sHQ)r+<LiAKucV1UAHN-B8a+Pj44sfDX<FUObt&_>upy$pcP~ z!JdN%-kmuZ&jXGI&IXS7qXI5J)YtoH2?Q#Hsh|YZc0fY|0RQ>*^o#)h30befgl~~u z?;4a{_yB%uu!sM1@4sh*7(o5_4fH_!Q+`hZA2R{~@X|oI|9P8IEv=MRkVZ^zstKH} z@YxUzQF>7!TZ@!Z^&k<%MvDf+XwTcDfGDIT4%%e^73G1sg3#vX!bNEE;)*c1xq+ZU zljX#LYVc&z$@Ck)>dFJ@sJ2*=vqY0rJZoR{js~*7rZ2Zrx-5~)w|l;xvpw(~k0&!Z zT}_8bh(+$K*9c`ki$gSx#uxa%hUm%=2_6k1SDzm0Ps%8Kx}~74CC*SnN=QUrz4pg& z=DN9!g++~F2YI@(eNXC7=(CY#Fl6!+_bMIPIB64I`b;x-xVB_^+fF@qKNi}~XdkBU zz6LkWuI{ey`DD-hpP4#;OH<eqxc%+Qx$8Vb(JiwLvrVee5%uEs#Ons!Dc0T>lI-rA z=;&^v4VTo)nue3`Ndem+>>%4xY>uqP-0{WNb;=G#ki8vobpqA-g*niNffc1Y{6_CL zE|xx*R%7eC>7S|vVjHI~N;8G=6i$|;o-sZ9rhc(>L;M2ggOHtjg64tK4XWv5uEod> zI@!IbMaT}p*vq&@_JnyF0D58Tg#8As=_M4_T`*TAcGj>sJX=cA3SrmddlaefeGtcM zcS<8)vlL`9upo^|=327|Hs=0(BDNj`#o8i!zFYP^S!sZ%TvS+Zk7Y3czw+LzLhYzz zEQpL|T5oP<A|Fpxaght-6qH7)mo(e3gjdwHU=7O>N=PtM2q0%ROCutwqijgbAJZt* zlx{aF7{@GDDq!+Y{H5%T-_SDWQNVp5K+0|yq_CWPW8s2GMbyGuS#fLOkzyrLeFn4b zGVkr1?t;geYpK!8^DhoaJECdW!8Q9)L9{1#G5^zIeMQcLf5th|GV!@iM6Ef`5a)dl z><zD=3Zfe}W&q{EBc$1NPkDUVm36a97kA}c{&5`syf)x<@=^JBl{d`PN(DXoZDqnj zB&TG|%<NT+MIGB)u(KD$lCFJD@KQIBC{2+ILKk(F$U~L%`zn%;bJwP@N8B=KS>5*O zEOteTwxiPfAZ>+%lTye#x^2UIt{U`e(p4m+evy9VVo1_@oghKQ%>uJ&*&kDFB4S$7 zidaR<r&<0<8OXUF&1L2Tm#9j_I5gsVL1C59QD`J}A|q##ij1VNe<VZn5oJ}u)Vq>N z>oJSuA4g($5-eDDMK?s%B!kX@t<i`pNba#~*luj&`Uc#BR${4ZGn3vXPs|NDX`hpq zDMF)eNMG>Xpgss4d-86PPxvoPJn*s%D^x~Zz_J6XdzQDbmqDg`oG)CL0VjJRFXWw| zJN}<`fbNhF!kLQE5B4{2_^O)pe*;Kc5+s#OF_ay{nyI`Je<aX6&TzR8p`M2PR%5fB z4LfHHD|wG#e8q}^Az~8uM?8$GlYpU(h`1XNb(IemY?0s;jlkY*u~ljkI2GtKPP^3c z<6mF8!?raK<<&`LeX-q<D-(14-;L<i$RG|m%aVlj0y+WbhazXm5UXP+N8ES84-+a_ zgreT00&U~13@>RPAWq{HyHr@<vJuSAVN0LY{3$#nJHoP0abf8u%zA%oW$QS{G(p+Y zwvP2_;WWps>HdPnAIXVIv3R#QkSEO=_UmytYALiY{mOrP*ew`4ge7IErJh(PseGQp zJt#QVwK1Q33V)VqhCAcMZkVZsl7mm@O$?rYH{a1a#{S}09X}6qHf{`Fv|0XZ=I?W0 zdAf9xs~xd%BiKoI0b3HMVDvUAN-P|TnS>INdbBH4$eIeWK5x=P*5(r4q?pcbS^pUJ zIdUG>$iOz0(@H$79lnvMv!~TPL=o_dB0ZBcT{|X|I@>cRc<R9XsFc%yuB2;)fj@MJ z@`|E*y_eWcPSb+Jhbf;JAB)rEeDspDTG`d4+&i;slYK$3(`g{~AIcnC|A)p-mUUGp zn(17@@EdL<xtN&3bE~OC4vhIfyxMt`xg>8DQWvv&7Y63|+fos{xMh9#It-9ZS&+-b z&&`l2`<17@)|RF6frIH7Z&lG)`K<>p{-*baOoBP#Gx!1r9|O1#1xZnh{^#qa#VP{H ztHrTtGWRq12TXA{!iD_5Xw=BvxRMR3!}zsGIq}1+LNiITs`G|OakKef=5yg(2{UJL zHLRb<2aDTNNJ|55l@xnR4{cLu75tCr`eja4d@Nyf0qv?TvOKho(V<42&D0yOpPSdq zEcdK6GjCHc4I4H^te2CVBW#YC)LxZGGYxK*`=L!19s2oqcGJAf_KRwwTGof&^Vf*) za1-nN9O{24t~iNwUWOi&pTtNT4#zKK`O(~9+DhDuG?RS9>dNHJl1<-ryv?yX9usXp zbGkRVIil!>_$EJsO~0G+JxaH=TZU=>p+@I?AKO0Bu(u40O&itK^jHns*!FFrOWsS3 zE|FwDNZnaYd<5-(U5A@+7wxy#7k^ppB+wI)q;hc288K8uf~@t>VR==Tq0iat4$aa0 z4J6l$c;`KzS*CdGu<OJ>kQKPtfco`!l%Cj#Jgh>}q`k<Y%y+G(L!cN{?ECX}%?I3x z0QHn#L-1-vFK%;)j+)3cO>)@4F(b{qVB!UQa-S0?CM6DT&5|z@!o-)UK24-P^`xs_ zm^s(hC^E-w3xt~7JSU@IJ5BCDnOtvzjBYe-tYdthAwzl6C9ZwnGE~Tk)m}-ldRbYv z$J$QS7wpbi@?S@(sg=uV?DLVIftA*wcR&S8NM-N*LhXW+T%Om7{z#CU4dX3?E9<kd z9(dXz^f<L&$fg~df~B9T3P?^Rkh=r_Xi8J=?`1#1`k6<!XCS#E-AV_iwaHHbIa0XX zOqy<_9ox8@y$usNx*dq5dEoIQh+GA4$m3BGz4AtX^TTY-xxYA+WVYMU*Veg_kx%j} zcO0er8!advH{i_1{HgRa@eA8koK<2C>IiF>^4BAW92Fcu&_{`x`rA4Tn$z(Y$q5(T ze()G$ZWCi}5UoA5s<V4|a-!fLbkEPeA%8f;FO=mdR}OC`EgSZc+u)1MY_y2kdr_xi zsSgzyq=I`rX}H8bNwHzrCUUNipI@=kKAG4Xc7AtEot;?7=oWE)5?{Vxb~jM>$f|Zr zs_Ilw>t?ZL@C&egLoC0>9zRs2FYp(0dU0E}(&3qT1@LTJbi#Or7(M#{9YdBx|0Hey zFIO{|)t@!gbFjaM(%+qspcyla)zbqCXa4v`AVsA4$qKW_AuRvX>TeHl`1vLI`7Na$ zU4DnaHvDE0VqZ`XW+CSX2Pd~tF)=|mks(J10|$2j2L~4gr?hjjcQ7_Gl6#rzAHIzN zA{{Ht>+R*hA|3fiUBVZqVqgFQKrO*l|8LG`;;V=CV?yKrIb`&IrGdrqZ3GVhjveZg z8@bJ4Os(@j!(6}vqXR<%qXOduBLiav^8%v|atmS&mqftyZusf#VqR~pFC%1mynw)O z0YL%q@_FRy_<!Hu-!b0=Z@RZTCpX_cHTbwbcBg$`5byYx-n9pP!4MM!Ec^^TKH_^+ z7mB47p}>(=uy#k0e}4NzX#>qx&{SGo;$~`X@^pHB0Q(E}6XzT3BgZSuGu1oXL5E9@ z|0=gQ$4=K+=W74^1|BRrOkQkqjGnBr%+~Dk1RpIkO;>Gmji0Tv&DZVy1>`5tN0g_( zhZHA2$5?0o4=N1S`YLNH!E{oy(`>B1XhOAGr^)2%%^8QyX1m>ZBl^n2<z{O{E-^mc zy~RLZ;3=V=COBFhb_f>s>_~6rXpy0EbtyFy!r)|iTgt*B%lq_p$+E>px2G;)Zx<<e z1OcDVV_MGr9$rXF*3nk=J21>kv4rtY8nY|gz?@;wZ)xS<uz*YYkpC7*Uq7oDkOMG& zKnTDB;0$mFcmR9=0e~pL0wDh<_5%a~A_1v@OhEQeTnwlLtN}Iv34mCDF~AOx4oC(# z0$c%x01dz&fEmE%zjsSpzC%V+0C5Wr0mN@`m5_5CwIMAQ_$G)=oUod%f7Hd0Q*b>> z>(D@}7ebCuKH$j`+>BDOP&yzMhLq1wHZ(DfH7uWno4dhrI*nOsJg(f;yz8XQ5nX)G zCcq@ao1$=C#1~@zF-lZ)y^n;Jjrs3UyH`(4p9#y64EAsL8O?Da(FK`Y^s6=>CjNju zzV8Vhh=631^lS}NBHqAWPi7nQTh;<~*G~c6Ixa0Z@L<#hrOn3?rSb3NV=Zf}W;W(@ zS34qN{#0-?i>j#K3precfBB*fpd4PUD&feBEBVKS?ev+nmy~FkyIt&ZE@`+{3nd+Q zf#7SEv;9L33ZQ}>Xv3JKgaQLre=!OUl7<M%aJts>Q_1ng2Qu2m&ri4NSNYi=vNDuT zE#P)fnka5)hA?;|iQR6|568pv)#tH^2Chb{LF)m>#mXyp=M6j3M*y`gela7G>AAmM z=~4h!akC-O8(U`?Mxyy=@38H>8V_xiYn_PXb+{_CDxD=B3(=eI93aWY1nuS4?M|I| z`4s%Vf{Va`O9$zT-HzJ+p3`t1RNjUmShHnqs6+pG2LM0-pzm)0g4_CH7o4ZkQX0Sa zj91!o3b$=qCq;rj@_uUM7-BIAy+Amoq9oN6z4QW$wEAEu@jRxXH&ur5T4<s|IAu{N zi}7n64Zq|~R-`zU1!7qdjTBYIhgyoW`f`&wZM%VX-{GB4w&V35aw37Nr~9=}YR8l5 zEYj!96P^?I?it7I`>xEvCC5xR>GA{6>E1OC_7f5?Eq@X%HKhFVIfla2aui|T7*C}p zoZ!%SH2G0W3BC~KaQz@^@2Moz)3$R8edE8^du#N%ujnT*nz-QtDje!)Q>q9A%sro& zIti#AMMC!Q<@tSu*psSw;Vf=1YF`_Vmr^L6=2%Ky$ra(Ix3`xk)ssd(qZAeRH4;ch zOE5l{Mc<z9BCR&cG<Uvh26usI9Xz|W+`N0BxDh?tA6L13dk!Ngw`866jx_m344Swy zF)ONRUon$)eZ~oE1_aL{#zjmNDW!pqZD@vCNLuB}(IaTvRlPgyRlg*GNrfv(2@}Dh z+y@Dw+yi+OWNG^GuL6)j%(uIf&8C`;r}l>I7g`X^H*}NFtMRzR=;D1oPkF|;yfoBu z;d)+(k;LfCMfw?|58SHH-ZVRPEsiQPBRm47QU%^5`i9#E8RR#Sf;^;I4`HdQEn-V8 z9AT-NA+tHf)tvu^C?O<xR9$^uP}0fU`(j=N<eyK10ZjyK0-WTFy;QF1w|Q|~W^h$u z=|p;MhKi+QR7_txgY_iL@xw%-1Q+t%M3(&BM5LeJ^0SQ3`_qrzNS}^2#)SMYM&tHe zbGHTw8(|#twvZb?E;9QC8uBH!htmXbKoy-?`;zZ!%KSadej~dnsvYG%Y6&Od3YBZy zx||U-*UKLp2f_9eQtuO%AR}c&h*{CG#JbhW%l{<}7N2{nAI=NU$2)=(<Zk;MMY=k< z6hBfQvhO#h8b7iZF#<~&1$HO*<ZPQWL$%@CeKb9h{wJnvfQh}U{R*b|u@sJpg?QLc z+)2}CEQi6ZMJ{PCJmw`m<)?BoYJm>9d4h?}@K*n4uW+o-T@T#XMni(bydY;0aIsi< z*7Hq_6QQNf2;WanUEDX&aM<z<RP#%{-T*IfN69Jx`C|}}WBCvW0s5C^7s*?{H#49- ziwr@nz7oH4#&^p!fFSm4P9#Q$XMg79Y^K-NcwxuCCoScT`?ah`(U+fDF7<7UxRcHf zL^NS(m^^S2X4QTz2zi{IlBOK@nE*B@Jpm@1WH^Z?g?LDrdXixXMb(Oqja$!+N5D-a z2+)~7Oy~v13*<Hgoc&vQdwY2c?7d^719HVncct3DtI7i!zOt)Fc43+BX5;r@jU_?c z7DAjkLL7b-f-Zu&&vWdupvwVF^}q`<om-bUhuLmh*=7w#exexayQM|8srXnz5+WvP z6Y6jUOMWn}n*?ibE!ZZ5&n-2(**0x^-rpxlIGn<H$sz5s#Bqz#-SYipW!1i=fd*Oa zSH>o$qB~!$bKta~Lm=5vIO0ryu}+=f6%;#MR<3Yd+1_Wj<1ojWF}fC0$<js|YiDqy znZ)|WIH)7P7aIGaBZUT-1Ik{Fc(kf)9p);9$~3mFWZ@`vZ$tCi!QFdwXa?>qQcP+% zx~ugri-pbR=w@#3Io)lf?M9=u_>trXwwg0*z6Ku)u~)w?skd*7*N+ekR{HC*oj1pc zu!g)QS{#C}_0Eutlq<FR3;#z9Q-4CSFio#d+5k#gzqN~yHU;qeV{R?tz-E5#@@--` zs^ide-xhIUT7Pz1VYFRZh+`4fCdox~zt-Qq;2dBXi3lZ%drsw*D!t}V;@r?TbQu%8 zdgylBLrdXhw?rkBi7*5lOP(;E<Me47e!A`vyC9~_t-BzU3oPtS5<IJgsq7k8)oI}Q zc8CaJ>0?nlU{WtjB~LEZ1FFx%XkPaxD?ZFBlphm!dw?5hpMP6uK43dg&Lv|f@Rj@p zcs#d*?gnSN>r1Xqt&->6&C#CZk5jU22kbvH?pq03efp-kZ&MaVeQdL5!BP7wh_Ym} zlxv73k-;xOsQ}q+<V=YHNN(7-QgZgOmZvb#_>qmHi7R9gQzu^QI#7;-72f8EZN-;L zmoDh*mrBd|Qvh=592MQOfK2`Ip<-DsVeyEhr4!86t^h@`M?Q~o6cY#<fKs}$aZ(_3 zg+D`%5i30YGmkkV*>&<%`)z5MH>16~MP7T!W#oK&pri%QyS>5r)AhNj@|4*9D=MR4 zu9yya^{t}0TG@l%g}zL8!F}cGB+*)Uak_IA_mWn(&Uxp0IT|hGyXs5A`>X$WSlUO$ zd1QeBVeTtoV)2W;;BiH|huGI2lbroyn1A^8f}G#@lG6g>t<m}eX5M`ocwGvW`aY4+ z2<I26qn%lTQOn3on^8~PO~;2!gvw51Wx{A-T#gv=TwDXmMI&zy6&WjTTesMT==SJ` z$1GUE<X3iFNDsx{4$7`=($FRyL&_BCT5IL~^NmHx3zIjid52nY)}qerQ*>u(7Wk{3 zU`DN+qys$NG}W;9JfXe!!`XBwac44W8VI9u1=EL@yj`2}nE!z-gTJ?3C+Hi{R?MrR zH_696&P1d!V}Fp0XvUE)_Y9qu=l3-?TX+fj47csyu3YnJ>bS!N=6EGKsn&*mK6|ps zi=jnooU#VRLJNRP@@+5fv;jN?WJrlHLr7Uhb7%4GQaM(zL?!rP;7(f9tsy#dwg!hI zCNEof1Nm-vJ8-uz^{Iy7^%c=Xqc!ixoy;BYRi4Zh-<=m1+e(ZDG}Qr}oebTeKuCfK zj%k1Q1OU0$;Sg570Z4JH>XuUZ-~rRjL2?Xkc-?Twz{td_^Y}?<V_UPfp*Y`UPusD% z8*BJ$DNgkTpbOK$<ol@@W)G<gy2()rFi;dGM7Fe{(W{&w7rP&&j^Tsu!D;(K|0mQ@ zsbz;dUtbi9?o~H!(w{$?@8-6SvA>7yE6Dr{06phjJqr&dJr86CLlH~4M$EI$xLJb7 z<Y~7gSSNn)*b)e;heVw+Fs1LRlvPaRJ6En3On$;7bzYpj7!ZDet#H4)1;U2n4T?rQ z0j0o{OBBm#6+Kx*{^?|b0_RDR=IVX1V<9$UyU}xGNjri3?A?V0Z^W)XhJnyiX^r3Z zuor>j^FgO>Z?^FDJ=<LSst983BIQ2YEJ~+8l$=H@lnYKN_WK(dn?;i}XwihA>kcu9 zo@ZAofu^rhdFr~t4*LG1ycfum0;E%q>Ear$kLl$@&+0Giu5TTA3~J{`@^f$b^~7L& zmkLJ*jp>)zm8E>Jtq`}1f8?FKAf`uY+kUJ;SgA~+91!KLW%&kgA-ccXCIjbUrzffu zos2!QDor&|!PIqeF%#y&uJ=NjQlxSFP+}xdfhxJj#&_QA?QT~EJ1rMe?YmsA=g=0v zW_NJSm^s<ig!khg2?@)Ub+QiR3=`h<=4yN0jd5ouPx^tEtDt5ueL6DWRW=|aqwrFb zRQYL0Vba+_Dy1@*E{0G@rjI8gR?xSCbkGOWLAlVUtxE;R``$zDEhr4^zh>6zG!rq~ zI^oJO*7bd-)TDehkO!AGH!@b@W--P+_7<<aU6$xq9`>pZBZ}1cOWXVl?-eK!X!Tw9 z+Ve|2_3rK-@9EkX9ta`QeN|EjpA))vO5aAYSLm3AFeiK2rf(&wh!7P&b+>YjDWP&R zq0;Lp%HtI!l+d-3m}e<fu2es^2}IFe4(k3~7Q%GU-ru4;{TLwV4X^~(Zah35Gafxc zlPr2A7<dn-gNDG>M!uvF;zZMAU>%os=X0s*h*9X8Z-UUo_T@=YOw&flOM6C?yJ^w} z0s-<*w_;B>+c_OIHWORx35B+PW&H-{zeuj0VVnniR$!hwyHYA?2`G2ag6cjHhwnH> ziBmL($Q%?5p$JC|aV1lE7mwAa^lRnIwFC913I@`TumrV)>_59FFiuf>8PIz>erXa7 zI{0nWw;^r{ylWTGvcs5-NGzx36$e~GVS)hTnA53QXe`H_depg!XwGzQeek+#+<pxY zUx_vP@crBV7YuT^`joxx&idgMW7%~S#*5L!4u!Ykayp@zo1(sndOe}lFJ%h1nq=T> z1zw&z%bp)t>i#dl{ojNIkRT%iebKGXu4`L@|JYuW0;URVt&X$$f&J3qZ!x1#W=E9L z;+F*WX>u&L2z@0M9#J9g*I$fe8$h<#ZZ(}xwm0h^2hS)T(fn&&R!7VTG*PxWGYQ&8 zB=pzjr}HxAk1#nN$Ei=t5Mu0Kheoy|>p{{YW+6H!9CeVxL*S?3=9JjZxIiAD16t7{ z2ZEVtjsZdJ;9FXkkHC48Ek{dmQN|sbp$GM?NB=z7%`lo!)-^*U2nas#hOC{PCJQoS zsP}%ghO`DkkR^c-LyIY)khA<M3$54EOTaRM={J{CDIqp;go7JhE(7S@2?V|(DF?qI z_2tBs9w^*t&!pjI<9g(>{5is$wr|S;yCjE@#BxdyVl}S;_akv6qk>YoGX{^r*ww;9 zGr=o6_blkSd9@68u^TCp&bZcmWIvL+(Rg@@OUfD<3y7+UiNg~1oLp?PUy+*Ou|Ml5 zz6N=pp`5AKYRF?=Zl%Q4k&<bC99+4y^|E8lcqcl2x6u|$Zw;guI&c&KkRd$?D~VZ| z<53CXT$pev9Ez=8KVV@hhz0f|$;BbdB?nGf=Y~s@pu0{Al)k$#f1^_Vo25HXUPaX4 z>#=<2K5FW?XqJ1NeKI59>-hAZjp2S3yV3qPIUG!<z^m1=yE|=2`W}$d6de~6I8x@l zXv1?WbqVu!b=8lBT|t9=(1xZ<dba50# X4I${(0;g{ZACz@E>xgJm*nnTY3!-@G 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 AB>(^b literal 0 HcmV?d00001 diff --git a/pep_extensions/theme/static/SourceSansPro-Regular-webfont.fd0d51605201.woff b/pep_extensions/theme/static/SourceSansPro-Regular-webfont.fd0d51605201.woff new file mode 100644 index 0000000000000000000000000000000000000000..6732daada5bc1ca4a36c5cc2a61ced6738533742 GIT binary patch literal 26392 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 literal 0 HcmV?d00001 diff --git a/pep_extensions/theme/static/mq.css b/pep_extensions/theme/static/mq.css new file mode 100644 index 00000000000..516242da337 --- /dev/null +++ b/pep_extensions/theme/static/mq.css @@ -0,0 +1,2673 @@ +@charset "UTF-8"; +.container, +.row, +.pep-list-header, +.pep-index-list li, +.info-key, +.listing-company, +.list-recent-jobs li { + *zoom: 1; +} +.container:after, +.row:after, +.pep-list-header:after, +.pep-index-list li:after, +.info-key:after, +.listing-company:after, +.list-recent-jobs li:after { + content: ""; + display: table; + clear: both; +} +.container, +.row, +.pep-list-header, +.pep-index-list li, +.info-key, +.listing-company, +.list-recent-jobs li { + *zoom: 1; +} +.container:after, +.row:after, +.pep-list-header:after, +.pep-index-list li:after, +.info-key:after, +.listing-company:after, +.list-recent-jobs li:after { + content: ""; + display: table; + clear: both; +} +@media (max-width: 24.9375em) { + .search-field:focus { + width: 9em; + } +} +@media (max-width: 30em) { + body:after { + content: "animatebody"; + display: none; + speak: none; + } + .slideshow { + display: none; + } +} +@media (min-width: 25em) { + body:after { + content: "animatebody"; + display: none; + speak: none; + } + .introduction { + font-size: 1.3125em; + } + .content-wrapper .container { + padding: 1em 1.5em; + } + .shrubbery .give-me-more { + display: block; + } + .widget-title .prompt, + .listing-company .prompt { + display: inline; + } +} +@media (min-width: 30em) { + body:after { + content: "animatebody"; + display: none; + speak: none; + } + .options-bar .breaker { + display: none; + } + .adjust-font-size { + border-left: 1px solid #2d3e4d; + } + .search-the-site { + border-right: 1px solid #070a0c; + } +} +@media (min-width: 32.5em) { + body:after { + content: "animatebody"; + display: none; + speak: none; + } + body { + /*text-rendering: optimizeLegibility;*/ + } + .col-row .column { + float: left; + } + .two-col > .column, + .four-col > .column { + width: 50%; + } + .two-col > .double-col, + .four-col > .double-col { + width: 100%; + } + .two-col > div:nth-of-type(2n + 3), + .four-col > div:nth-of-type(2n + 3) { + clear: left; + } + .meta-navigation, + .main-header, + .main-navigation, + .content-wrapper, + .main-footer { + clear: both; + } + .container { + max-width: 75em; + width: 100%; + margin: 0 auto; + padding: 0; + } + .introduction { + font-size: 1.5em; + } + .success-stories-widget blockquote { + font-size: 1.125em; + padding: 1em 1.4em 1.3em; + } + input[type="submit"], + input[type="reset"], + button, + .button, + a.button { + display: inline-block; + vertical-align: baseline; + width: auto; + } + .search-field:focus { + width: 8em; + } +} +@media (min-width: 39.9375em) and (max-width: 58.75em) { + body:after { + content: "drawer_navigation"; + display: none; + speak: none; + } + .main-navigation { + text-align: center; + overflow: visible; + } + .main-navigation .menu { + margin-bottom: 0; + } + .main-navigation .tier-1 > a, + .main-navigation .tier-2 > a { + display: block; + padding: 0.5em 1.5em 0.4em 1em; + position: relative; + } + .main-navigation .tier-1 { + display: block; + width: 100%; + } + .main-navigation .tier-1 > a { + text-align: center; + } + .main-navigation .tier-2 > a { + text-align: left; + } + .main-navigation .menu { + *zoom: 1; + } + .main-navigation .menu:after { + content: ""; + display: table; + clear: both; + } + .main-navigation .tier-1 { + position: relative; + } + .main-navigation .subnav { + position: absolute; + z-index: 100; + text-align: left; + } + .no-touch .main-navigation .subnav { + min-width: 100%; + display: none; + -moz-transition: all 0s ease; + -o-transition: all 0s ease; + -webkit-transition: all 0s ease; + transition: all 0s ease; + } + .touch .main-navigation .subnav { + top: 120%; + display: none; + opacity: 0; + -moz-transition: opacity 0.25s ease-in-out; + -o-transition: opacity 0.25s ease-in-out; + -webkit-transition: opacity 0.25s ease-in-out; + transition: opacity 0.25s ease-in-out; + -moz-box-shadow: 0 0.25em 0.75em rgba(0, 0, 0, 0.6); + -webkit-box-shadow: 0 0.25em 0.75em rgba(0, 0, 0, 0.6); + box-shadow: 0 0.25em 0.75em rgba(0, 0, 0, 0.6); + } + .touch .main-navigation .subnav:before { + position: absolute; + content: ""; + width: 0; + height: 0; + border-color: transparent; + border-style: solid; + border-width: 0.75em; + top: -1.45em; + display: block; + } + .no-touch .main-navigation .element-1:hover .subnav, + .no-touch .main-navigation .element-1:focus .subnav, + .no-touch .main-navigation .element-2:hover .subnav, + .no-touch .main-navigation .element-2:focus .subnav, + .no-touch .main-navigation .element-3:hover .subnav, + .no-touch .main-navigation .element-3:focus .subnav, + .no-touch .main-navigation .element-4:hover .subnav, + .no-touch .main-navigation .element-4:focus .subnav { + left: 0; + display: initial; + -moz-transition-delay: 0.25s; + -o-transition-delay: 0.25s; + -webkit-transition-delay: 0.25s; + transition-delay: 0.25s; + } + .no-touch .main-navigation .element-5:hover .subnav, + .no-touch .main-navigation .element-5:focus .subnav, + .no-touch .main-navigation .element-6:hover .subnav, + .no-touch .main-navigation .element-6:focus .subnav, + .no-touch .main-navigation .element-7:hover .subnav, + .no-touch .main-navigation .element-7:focus .subnav, + .no-touch .main-navigation .element-8:hover .subnav, + .no-touch .main-navigation .element-8:focus .subnav, + .no-touch .main-navigation .last:hover .subnav, + .no-touch .main-navigation .last:focus .subnav { + right: 0; + display: initial; + -moz-transition-delay: 0.25s; + -o-transition-delay: 0.25s; + -webkit-transition-delay: 0.25s; + transition-delay: 0.25s; + } + .touch .main-navigation .element-1:hover .subnav, + .touch .main-navigation .element-1 .subnav.touched, + .touch .main-navigation .element-2:hover .subnav, + .touch .main-navigation .element-2 .subnav.touched, + .touch .main-navigation .element-3:hover .subnav, + .touch .main-navigation .element-3 .subnav.touched, + .touch .main-navigation .element-4:hover .subnav, + .touch .main-navigation .element-4 .subnav.touched { + display: block; + opacity: 1; + left: 0; + } + .touch .main-navigation .element-1 .subnav:before, + .touch .main-navigation .element-2 .subnav:before, + .touch .main-navigation .element-3 .subnav:before, + .touch .main-navigation .element-4 .subnav:before { + left: 1.5em; + } + .touch .main-navigation .element-5:hover .subnav, + .touch .main-navigation .element-5 .subnav.touched, + .touch .main-navigation .element-6:hover .subnav, + .touch .main-navigation .element-6 .subnav.touched, + .touch .main-navigation .element-7:hover .subnav, + .touch .main-navigation .element-7 .subnav.touched, + .touch .main-navigation .element-8:hover .subnav, + .touch .main-navigation .element-8 .subnav.touched, + .touch .main-navigation .last:hover .subnav, + .touch .main-navigation .last .subnav.touched { + display: block; + opacity: 1; + right: 0; + } + .touch .main-navigation .element-5 .subnav:before, + .touch .main-navigation .element-6 .subnav:before, + .touch .main-navigation .element-7 .subnav:before, + .touch .main-navigation .element-8 .subnav:before, + .touch .main-navigation .last .subnav:before { + left: auto; + right: 1.5em; + } + .main-navigation .tier-2 { + display: block; + min-width: 100%; + } + .main-navigation .tier-2 a { + white-space: nowrap; + } + .no-touch .main-navigation { + display: block; + clear: both; + text-align: center; + -moz-border-radius: 8px 8px 0 0; + -webkit-border-radius: 8px; + border-radius: 8px 8px 0 0; + -moz-box-shadow: 0 0 10px rgba(0, 0, 0, 0.2); + -webkit-box-shadow: 0 0 10px rgba(0, 0, 0, 0.2); + box-shadow: 0 0 10px rgba(0, 0, 0, 0.2); + } + .no-touch .main-navigation .tier-1 { + float: left; + width: 33.333333%; + } + .no-touch .main-navigation .tier-1.element-6:not(.unstacked), + .no-touch .main-navigation .tier-1.element-7:not(.unstacked) { + width: 16.6666665%; + } + .no-touch .main-navigation .tier-1.element-1 { + -moz-border-radius-topleft: 8px; + -webkit-border-top-left-radius: 8px; + border-top-left-radius: 8px; + } + .no-touch .main-navigation .tier-1.element-1 > a { + -moz-border-radius-topleft: 7px; + -webkit-border-top-left-radius: 7px; + border-top-left-radius: 7px; + } + .no-touch .main-navigation .tier-1.element-3 { + -moz-border-radius-topright: 8px; + -webkit-border-top-right-radius: 8px; + border-top-right-radius: 8px; + border-right: 0; + } + .no-touch .main-navigation .tier-1.element-3 > a { + -moz-border-radius-topright: 7px; + -webkit-border-top-right-radius: 7px; + border-top-right-radius: 7px; + border-right: 0; + } + .no-touch .main-navigation .tier-1.element-7 { + border-right: 0; + } + .no-touch .main-navigation .tier-2 { + font-size: 0.875em; + } + .no-touch .main-navigation .tier-2 > a { + border-right: 1px solid rgba(255, 255, 255, 0.8); + } + .no-touch .main-navigation .subnav { + -moz-box-shadow: 0 0.5em 0.5em rgba(0, 0, 0, 0.3); + -webkit-box-shadow: 0 0.5em 0.5em rgba(0, 0, 0, 0.3); + box-shadow: 0 0.5em 0.5em rgba(0, 0, 0, 0.3); + } + .no-touch .default-page .main-navigation { + position: relative; + margin-bottom: -0.0625em; + } +} +@media (min-width: 40em) { + body:after { + content: "drawer_navigation"; + display: none; + speak: none; + } + .touch body, + .touch #touchnav-wrapper { + position: relative; + width: 100%; + } + .touch .default-page .main-header { + position: static; + } + .touch .main-navigation { + display: block; + position: absolute; + top: 0; + left: -260px; + width: 260px; + height: 100%; + overflow: scroll; + text-align: center; + font-size: 1.125em; + } + .touch .main-navigation a { + text-align: center; + padding: 0.65em 1.25em 0.55em; + } + .touch .main-navigation .tier-2 { + font-size: 0.875em; + } + .touch .main-navigation .subnav { + position: static; + display: block; + opacity: 1; + border-top: 0; + -moz-box-shadow: none; + -webkit-box-shadow: none; + box-shadow: none; + } + .touch #touchnav-wrapper { + -moz-transition: -moz-transform 300ms ease; + -o-transition: -o-transform 300ms ease; + -webkit-transition: -webkit-transform 300ms ease; + transition: transform 300ms ease; + -moz-transform: translate3d(0, 0, 0); + -ms-transform: translate3d(0, 0, 0); + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + -webkit-backface-visibility: hidden; + } + .touch .show-sidemenu #touchnav-wrapper { + -moz-transform: translate3d(260px, 0, 0); + -ms-transform: translate3d(260px, 0, 0); + -webkit-transform: translate3d(260px, 0, 0); + transform: translate3d(260px, 0, 0); + } + .three-col > .column { + width: 33.3333%; + } + .three-col > .double-col { + width: 66.6666%; + } + .three-col > div:nth-of-type(3n + 4) { + clear: left; + } + .meta-navigation { + text-align: left; + } + .meta-navigation .say-no-more { + display: none; + visibility: hidden; + } + .meta-navigation .jump-link { + display: none; + } + .meta-navigation li { + float: left; + width: 16.6666667%; + border-left: 1px solid #273643; + border-right: 1px solid #11171d; + } + .site-headline { + float: left; + } + .options-bar-container { + float: right; + } + .donate-button { + display: inline; + margin: 0 0.5em 0 0; + position: relative; + top: 19px; + } + .options-bar { + float: right; + width: auto; + } + .touch .main-navigation .subnav:before { + border-color: transparent; + } + .search-field { + -moz-transition: width 0.3s ease-in-out; + -o-transition: width 0.3s ease-in-out; + -webkit-transition: width 0.3s ease-in-out; + transition: width 0.3s ease-in-out; + } + .search-field:focus { + width: 6em; + margin-right: 0.5em; + } + .no-touch .search-button { + display: inline; + } + .slide-copy p { + font-size: 1em; + } + .introduction { + padding: 0 1.5em; + } + .call-to-action { + font-size: 1.5em; + } + .fontface .call-to-action { + font-size: 1.725em; + } + .fontface .call-to-action span:before { + font-size: 0.875em; + } + .header-banner { + padding: 1em; + } + .home .header-banner, + .default-page .header-banner { + padding: 0; + } + .about-banner, + .download-for-current-os, + .documentation-banner, + .welcome-to-the-foundation { + padding-left: 8.51064%; + padding-right: 8.51064%; + } + .default-page .main-header { + position: relative; + z-index: 10; + } + .with-supernav .super-navigation { + display: none; + } + .python-navigation { + background-color: #2d618c; + *zoom: 1; + filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#FF3776AB',endColorstr='#FF2D618C'); + background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIzMCUiIHN0b3AtY29sb3I9IiMzNzc2YWIiLz48c3RvcCBvZmZzZXQ9Ijk1JSIgc3RvcC1jb2xvcj0iIzJkNjE4YyIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=="); + background-size: 100%; + background-image: -webkit-gradient( + linear, + 50% 0, + 50% 100%, + color-stop(30%, #3776ab), + color-stop(95%, #2d618c) + ); + background-image: -moz-linear-gradient(#3776ab 30%, #2d618c 95%); + background-image: -webkit-linear-gradient(#3776ab 30%, #2d618c 95%); + background-image: linear-gradient(#3776ab 30%, #2d618c 95%); + border-top: 1px solid #629ccd; + border-bottom: 1px solid #18334b; + } + .python-navigation .tier-1 { + border-top: 1px solid #4f90c6; + border-right: 1px solid #2b5b84; + border-bottom: 1px solid #1e415e; + border-left: 1px solid #4f90c6; + } + .python-navigation .tier-1 > a { + color: #e6e8ea; + background-color: transparent; + border-top: 1px solid transparent; + border-bottom: 1px solid transparent; + letter-spacing: 0.01em; + } + .python-navigation .tier-1 > a:hover, + .python-navigation .tier-1 > a:focus, + .python-navigation .tier-1 > a .tier-1:hover > a { + color: #fff; + background-color: #2d618c; + *zoom: 1; + filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#FF326B9C',endColorstr='#FF2D618C'); + background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiMzMjZiOWMiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iIzJkNjE4YyIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=="); + background-size: 100%; + background-image: -webkit-gradient( + linear, + 50% 0, + 50% 100%, + color-stop(10%, #326b9c), + color-stop(90%, #2d618c) + ); + background-image: -moz-linear-gradient(#326b9c 10%, #2d618c 90%); + background-image: -webkit-linear-gradient(#326b9c 10%, #2d618c 90%); + background-image: linear-gradient(#326b9c 10%, #2d618c 90%); + border-top: 1px solid #3776ab; + border-bottom: 1px solid #2d618c; + } + .python-navigation .subnav { + border-top: 1px solid #18334b; + background-color: #d6e5f2; + *zoom: 1; + filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#FFBBD4E9',endColorstr='#FFD6E5F2'); + background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiNiYmQ0ZTkiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iI2Q2ZTVmMiIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=="); + background-size: 100%; + background-image: -webkit-gradient( + linear, + 50% 0, + 50% 100%, + color-stop(10%, #bbd4e9), + color-stop(90%, #d6e5f2) + ); + background-image: -moz-linear-gradient(#bbd4e9 10%, #d6e5f2 90%); + background-image: -webkit-linear-gradient(#bbd4e9 10%, #d6e5f2 90%); + background-image: linear-gradient(#bbd4e9 10%, #d6e5f2 90%); + -moz-box-shadow: inset 0 0 20px rgba(55, 118, 171, 0.15); + -webkit-box-shadow: inset 0 0 20px rgba(55, 118, 171, 0.15); + box-shadow: inset 0 0 20px rgba(55, 118, 171, 0.15); + } + .touch .python-navigation .subnav:before { + border-color: transparent transparent #bbd4e9 transparent; + } + .python-navigation .tier-2 > a { + color: rgba(51, 51, 51, 0.9); + border-top: 1px solid rgba(55, 118, 171, 0.25); + border-bottom: 1px solid transparent; + } + .python-navigation .tier-2 > a:hover, + .python-navigation .tier-2 > a:focus { + background: rgba(255, 255, 255, 0.35); + color: rgba(34, 34, 34, 0.9); + } + .python-navigation .tier-2:last-child > a { + border-bottom: 1px solid rgba(55, 118, 171, 0.25); + } + .python-navigation .current_item { + color: #fff; + background-color: #244e71; + *zoom: 1; + filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#FF2B5B84',endColorstr='#FF244E71'); + background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiMyYjViODQiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iIzI0NGU3MSIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=="); + background-size: 100%; + background-image: -webkit-gradient( + linear, + 50% 0, + 50% 100%, + color-stop(10%, #2b5b84), + color-stop(90%, #244e71) + ); + background-image: -moz-linear-gradient(#2b5b84 10%, #244e71 90%); + background-image: -webkit-linear-gradient(#2b5b84 10%, #244e71 90%); + background-image: linear-gradient(#2b5b84 10%, #244e71 90%); + } + .python-navigation .super-navigation { + color: #666; + border: 1px solid #89b4d9; + background-color: #d6e5f2; + *zoom: 1; + filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#FFFCFDFE',endColorstr='#FFD6E5F2'); + background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiNmY2ZkZmUiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iI2Q2ZTVmMiIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=="); + background-size: 100%; + background-image: -webkit-gradient( + linear, + 50% 0, + 50% 100%, + color-stop(10%, #fcfdfe), + color-stop(90%, #d6e5f2) + ); + background-image: -moz-linear-gradient(#fcfdfe 10%, #d6e5f2 90%); + background-image: -webkit-linear-gradient(#fcfdfe 10%, #d6e5f2 90%); + background-image: linear-gradient(#fcfdfe 10%, #d6e5f2 90%); + } + .python-navigation .super-navigation a:not(.button) { + color: #3776ab; + } + .python-navigation .super-navigation h4 { + color: #316998; + } + .psf-navigation { + background-color: #646565; + *zoom: 1; + filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#FF78797A',endColorstr='#FF646565'); + background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIzMCUiIHN0b3AtY29sb3I9IiM3ODc5N2EiLz48c3RvcCBvZmZzZXQ9Ijk1JSIgc3RvcC1jb2xvcj0iIzY0NjU2NSIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=="); + background-size: 100%; + background-image: -webkit-gradient( + linear, + 50% 0, + 50% 100%, + color-stop(30%, #78797a), + color-stop(95%, #646565) + ); + background-image: -moz-linear-gradient(#78797a 30%, #646565 95%); + background-image: -webkit-linear-gradient(#78797a 30%, #646565 95%); + background-image: linear-gradient(#78797a 30%, #646565 95%); + border-top: 1px solid #9e9fa0; + border-bottom: 1px solid #39393a; + } + .psf-navigation .tier-1 { + border-top: 1px solid #929393; + border-right: 1px solid #5f6060; + border-bottom: 1px solid #454647; + border-left: 1px solid #929393; + } + .psf-navigation .tier-1 > a { + color: #e6e8ea; + background-color: transparent; + border-top: 1px solid transparent; + border-bottom: 1px solid transparent; + letter-spacing: 0.01em; + } + .psf-navigation .tier-1 > a:hover, + .psf-navigation .tier-1 > a:focus, + .psf-navigation .tier-1 > a .tier-1:hover > a { + color: #fff; + background-color: #646565; + *zoom: 1; + filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#FF6E6F70',endColorstr='#FF646565'); + background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiM2ZTZmNzAiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iIzY0NjU2NSIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=="); + background-size: 100%; + background-image: -webkit-gradient( + linear, + 50% 0, + 50% 100%, + color-stop(10%, #6e6f70), + color-stop(90%, #646565) + ); + background-image: -moz-linear-gradient(#6e6f70 10%, #646565 90%); + background-image: -webkit-linear-gradient(#6e6f70 10%, #646565 90%); + background-image: linear-gradient(#6e6f70 10%, #646565 90%); + border-top: 1px solid #78797a; + border-bottom: 1px solid #646565; + } + .psf-navigation .subnav { + border-top: 1px solid #39393a; + background-color: #ececec; + *zoom: 1; + filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#FFDADADA',endColorstr='#FFECECEC'); + background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiNkYWRhZGEiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iI2VjZWNlYyIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=="); + background-size: 100%; + background-image: -webkit-gradient( + linear, + 50% 0, + 50% 100%, + color-stop(10%, #dadada), + color-stop(90%, #ececec) + ); + background-image: -moz-linear-gradient(#dadada 10%, #ececec 90%); + background-image: -webkit-linear-gradient(#dadada 10%, #ececec 90%); + background-image: linear-gradient(#dadada 10%, #ececec 90%); + -moz-box-shadow: inset 0 0 20px rgba(120, 121, 122, 0.15); + -webkit-box-shadow: inset 0 0 20px rgba(120, 121, 122, 0.15); + box-shadow: inset 0 0 20px rgba(120, 121, 122, 0.15); + } + .touch .psf-navigation .subnav:before { + border-color: transparent transparent #dadada transparent; + } + .psf-navigation .tier-2 > a { + color: rgba(51, 51, 51, 0.9); + border-top: 1px solid rgba(120, 121, 122, 0.25); + border-bottom: 1px solid transparent; + } + .psf-navigation .tier-2 > a:hover, + .psf-navigation .tier-2 > a:focus { + background: rgba(255, 255, 255, 0.35); + color: rgba(34, 34, 34, 0.9); + } + .psf-navigation .tier-2:last-child > a { + border-bottom: 1px solid rgba(120, 121, 122, 0.25); + } + .psf-navigation .current_item { + color: #fff; + background-color: #525353; + *zoom: 1; + filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#FF5F6060',endColorstr='#FF525353'); + background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiM1ZjYwNjAiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iIzUyNTM1MyIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=="); + background-size: 100%; + background-image: -webkit-gradient( + linear, + 50% 0, + 50% 100%, + color-stop(10%, #5f6060), + color-stop(90%, #525353) + ); + background-image: -moz-linear-gradient(#5f6060 10%, #525353 90%); + background-image: -webkit-linear-gradient(#5f6060 10%, #525353 90%); + background-image: linear-gradient(#5f6060 10%, #525353 90%); + } + .psf-navigation .super-navigation { + color: #666; + border: 1px solid #b8b9b9; + background-color: #ececec; + *zoom: 1; + filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#FFFFFFFF',endColorstr='#FFECECEC'); + background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiNmZmZmZmYiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iI2VjZWNlYyIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=="); + background-size: 100%; + background-image: -webkit-gradient( + linear, + 50% 0, + 50% 100%, + color-stop(10%, #fff), + color-stop(90%, #ececec) + ); + background-image: -moz-linear-gradient(#fff 10%, #ececec 90%); + background-image: -webkit-linear-gradient(#fff 10%, #ececec 90%); + background-image: linear-gradient(#fff 10%, #ececec 90%); + } + .psf-navigation .super-navigation a:not(.button) { + color: #78797a; + } + .psf-navigation .super-navigation h4 { + color: #6b6c6d; + } + .docs-navigation { + background-color: #ffc91a; + *zoom: 1; + filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#FFFFD343',endColorstr='#FFFFC91A'); + background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIzMCUiIHN0b3AtY29sb3I9IiNmZmQzNDMiLz48c3RvcCBvZmZzZXQ9Ijk1JSIgc3RvcC1jb2xvcj0iI2ZmYzkxYSIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=="); + background-size: 100%; + background-image: -webkit-gradient( + linear, + 50% 0, + 50% 100%, + color-stop(30%, #ffd343), + color-stop(95%, #ffc91a) + ); + background-image: -moz-linear-gradient(#ffd343 30%, #ffc91a 95%); + background-image: -webkit-linear-gradient(#ffd343 30%, #ffc91a 95%); + background-image: linear-gradient(#ffd343 30%, #ffc91a 95%); + border-top: 1px solid #ffe590; + border-bottom: 1px solid #c39500; + } + .docs-navigation .tier-1 { + border-top: 1px solid #ffdf76; + border-right: 1px solid #ffc710; + border-bottom: 1px solid #dca900; + border-left: 1px solid #ffdf76; + } + .docs-navigation .tier-1 > a { + color: #333; + background-color: transparent; + border-top: 1px solid transparent; + border-bottom: 1px solid transparent; + letter-spacing: 0.01em; + } + .docs-navigation .tier-1 > a:hover, + .docs-navigation .tier-1 > a:focus, + .docs-navigation .tier-1 > a .tier-1:hover > a { + color: #fff; + background-color: #ffc91a; + *zoom: 1; + filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#FFFFCE2F',endColorstr='#FFFFC91A'); + background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiNmZmNlMmYiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iI2ZmYzkxYSIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=="); + background-size: 100%; + background-image: -webkit-gradient( + linear, + 50% 0, + 50% 100%, + color-stop(10%, #ffce2f), + color-stop(90%, #ffc91a) + ); + background-image: -moz-linear-gradient(#ffce2f 10%, #ffc91a 90%); + background-image: -webkit-linear-gradient(#ffce2f 10%, #ffc91a 90%); + background-image: linear-gradient(#ffce2f 10%, #ffc91a 90%); + border-top: 1px solid #ffd343; + border-bottom: 1px solid #ffc91a; + } + .docs-navigation .subnav { + border-top: 1px solid #c39500; + background-color: white; + *zoom: 1; + filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#FFFFFFFF',endColorstr='#FFFFFFFF'); + background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiNmZmZmZmYiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iI2ZmZmZmZiIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=="); + background-size: 100%; + background-image: -webkit-gradient( + linear, + 50% 0, + 50% 100%, + color-stop(10%, #fff), + color-stop(90%, #fff) + ); + background-image: -moz-linear-gradient(#fff 10%, #fff 90%); + background-image: -webkit-linear-gradient(#fff 10%, #fff 90%); + background-image: linear-gradient(#fff 10%, #fff 90%); + -moz-box-shadow: inset 0 0 20px rgba(255, 211, 67, 0.15); + -webkit-box-shadow: inset 0 0 20px rgba(255, 211, 67, 0.15); + box-shadow: inset 0 0 20px rgba(255, 211, 67, 0.15); + } + .touch .docs-navigation .subnav:before { + border-color: transparent transparent white transparent; + } + .docs-navigation .tier-2 > a { + color: rgba(51, 51, 51, 0.9); + border-top: 1px solid rgba(255, 211, 67, 0.25); + border-bottom: 1px solid transparent; + } + .docs-navigation .tier-2 > a:hover, + .docs-navigation .tier-2 > a:focus { + background: rgba(255, 255, 255, 0.35); + color: rgba(34, 34, 34, 0.9); + } + .docs-navigation .tier-2:last-child > a { + border-bottom: 1px solid rgba(255, 211, 67, 0.25); + } + .docs-navigation .current_item { + color: #fff; + background-color: #f6bc00; + *zoom: 1; + filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#FFFFC710',endColorstr='#FFF6BC00'); + background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiNmZmM3MTAiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iI2Y2YmMwMCIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=="); + background-size: 100%; + background-image: -webkit-gradient( + linear, + 50% 0, + 50% 100%, + color-stop(10%, #ffc710), + color-stop(90%, #f6bc00) + ); + background-image: -moz-linear-gradient(#ffc710 10%, #f6bc00 90%); + background-image: -webkit-linear-gradient(#ffc710 10%, #f6bc00 90%); + background-image: linear-gradient(#ffc710 10%, #f6bc00 90%); + } + .docs-navigation .super-navigation { + color: #666; + border: 1px solid #fff1c3; + background-color: white; + *zoom: 1; + filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#FFFFFFFF',endColorstr='#FFFFFFFF'); + background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiNmZmZmZmYiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iI2ZmZmZmZiIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=="); + background-size: 100%; + background-image: -webkit-gradient( + linear, + 50% 0, + 50% 100%, + color-stop(10%, #fff), + color-stop(90%, #fff) + ); + background-image: -moz-linear-gradient(#fff 10%, #fff 90%); + background-image: -webkit-linear-gradient(#fff 10%, #fff 90%); + background-image: linear-gradient(#fff 10%, #fff 90%); + } + .docs-navigation .super-navigation a:not(.button) { + color: #ffd343; + } + .docs-navigation .super-navigation h4 { + color: #ffcd2a; + } + .pypl-navigation { + background-color: #6c9238; + *zoom: 1; + filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#FF82B043',endColorstr='#FF6C9238'); + background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIzMCUiIHN0b3AtY29sb3I9IiM4MmIwNDMiLz48c3RvcCBvZmZzZXQ9Ijk1JSIgc3RvcC1jb2xvcj0iIzZjOTIzOCIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=="); + background-size: 100%; + background-image: -webkit-gradient( + linear, + 50% 0, + 50% 100%, + color-stop(30%, #82b043), + color-stop(95%, #6c9238) + ); + background-image: -moz-linear-gradient(#82b043 30%, #6c9238 95%); + background-image: -webkit-linear-gradient(#82b043 30%, #6c9238 95%); + background-image: linear-gradient(#82b043 30%, #6c9238 95%); + border-top: 1px solid #a6ca75; + border-bottom: 1px solid #3e5420; + } + .pypl-navigation .tier-1 { + border-top: 1px solid #9bc363; + border-right: 1px solid #678b35; + border-bottom: 1px solid #4b6627; + border-left: 1px solid #9bc363; + } + .pypl-navigation .tier-1 > a { + color: #e6e8ea; + background-color: transparent; + border-top: 1px solid transparent; + border-bottom: 1px solid transparent; + letter-spacing: 0.01em; + } + .pypl-navigation .tier-1 > a:hover, + .pypl-navigation .tier-1 > a:focus, + .pypl-navigation .tier-1 > a .tier-1:hover > a { + color: #fff; + background-color: #6c9238; + *zoom: 1; + filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#FF77A13D',endColorstr='#FF6C9238'); + background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiM3N2ExM2QiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iIzZjOTIzOCIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=="); + background-size: 100%; + background-image: -webkit-gradient( + linear, + 50% 0, + 50% 100%, + color-stop(10%, #77a13d), + color-stop(90%, #6c9238) + ); + background-image: -moz-linear-gradient(#77a13d 10%, #6c9238 90%); + background-image: -webkit-linear-gradient(#77a13d 10%, #6c9238 90%); + background-image: linear-gradient(#77a13d 10%, #6c9238 90%); + border-top: 1px solid #82b043; + border-bottom: 1px solid #6c9238; + } + .pypl-navigation .subnav { + border-top: 1px solid #3e5420; + background-color: #eef5e4; + *zoom: 1; + filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#FFDDEBCA',endColorstr='#FFEEF5E4'); + background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiNkZGViY2EiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iI2VlZjVlNCIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=="); + background-size: 100%; + background-image: -webkit-gradient( + linear, + 50% 0, + 50% 100%, + color-stop(10%, #ddebca), + color-stop(90%, #eef5e4) + ); + background-image: -moz-linear-gradient(#ddebca 10%, #eef5e4 90%); + background-image: -webkit-linear-gradient(#ddebca 10%, #eef5e4 90%); + background-image: linear-gradient(#ddebca 10%, #eef5e4 90%); + -moz-box-shadow: inset 0 0 20px rgba(130, 176, 67, 0.15); + -webkit-box-shadow: inset 0 0 20px rgba(130, 176, 67, 0.15); + box-shadow: inset 0 0 20px rgba(130, 176, 67, 0.15); + } + .touch .pypl-navigation .subnav:before { + border-color: transparent transparent #ddebca transparent; + } + .pypl-navigation .tier-2 > a { + color: rgba(51, 51, 51, 0.9); + border-top: 1px solid rgba(130, 176, 67, 0.25); + border-bottom: 1px solid transparent; + } + .pypl-navigation .tier-2 > a:hover, + .pypl-navigation .tier-2 > a:focus { + background: rgba(255, 255, 255, 0.35); + color: rgba(34, 34, 34, 0.9); + } + .pypl-navigation .tier-2:last-child > a { + border-bottom: 1px solid rgba(130, 176, 67, 0.25); + } + .pypl-navigation .current_item { + color: #fff; + background-color: #59792e; + *zoom: 1; + filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#FF678B35',endColorstr='#FF59792E'); + background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiM2NzhiMzUiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iIzU5NzkyZSIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=="); + background-size: 100%; + background-image: -webkit-gradient( + linear, + 50% 0, + 50% 100%, + color-stop(10%, #678b35), + color-stop(90%, #59792e) + ); + background-image: -moz-linear-gradient(#678b35 10%, #59792e 90%); + background-image: -webkit-linear-gradient(#678b35 10%, #59792e 90%); + background-image: linear-gradient(#678b35 10%, #59792e 90%); + } + .pypl-navigation .super-navigation { + color: #666; + border: 1px solid #bed99a; + background-color: #eef5e4; + *zoom: 1; + filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#FFFFFFFF',endColorstr='#FFEEF5E4'); + background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiNmZmZmZmYiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iI2VlZjVlNCIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=="); + background-size: 100%; + background-image: -webkit-gradient( + linear, + 50% 0, + 50% 100%, + color-stop(10%, #fff), + color-stop(90%, #eef5e4) + ); + background-image: -moz-linear-gradient(#fff 10%, #eef5e4 90%); + background-image: -webkit-linear-gradient(#fff 10%, #eef5e4 90%); + background-image: linear-gradient(#fff 10%, #eef5e4 90%); + } + .pypl-navigation .super-navigation a:not(.button) { + color: #82b043; + } + .pypl-navigation .super-navigation h4 { + color: #749e3c; + } + .jobs-navigation { + background-color: #8b5792; + *zoom: 1; + filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#FFA06BA7',endColorstr='#FF8B5792'); + background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIzMCUiIHN0b3AtY29sb3I9IiNhMDZiYTciLz48c3RvcCBvZmZzZXQ9Ijk1JSIgc3RvcC1jb2xvcj0iIzhiNTc5MiIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=="); + background-size: 100%; + background-image: -webkit-gradient( + linear, + 50% 0, + 50% 100%, + color-stop(30%, #a06ba7), + color-stop(95%, #8b5792) + ); + background-image: -moz-linear-gradient(#a06ba7 30%, #8b5792 95%); + background-image: -webkit-linear-gradient(#a06ba7 30%, #8b5792 95%); + background-image: linear-gradient(#a06ba7 30%, #8b5792 95%); + border-top: 1px solid #bf9bc4; + border-bottom: 1px solid #58375c; + } + .jobs-navigation .tier-1 { + border-top: 1px solid #b58bba; + border-right: 1px solid #85538c; + border-bottom: 1px solid #67406c; + border-left: 1px solid #b58bba; + } + .jobs-navigation .tier-1 > a { + color: #e6e8ea; + background-color: transparent; + border-top: 1px solid transparent; + border-bottom: 1px solid transparent; + letter-spacing: 0.01em; + } + .jobs-navigation .tier-1 > a:hover, + .jobs-navigation .tier-1 > a:focus, + .jobs-navigation .tier-1 > a .tier-1:hover > a { + color: #fff; + background-color: #8b5792; + *zoom: 1; + filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#FF985F9F',endColorstr='#FF8B5792'); + background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiM5ODVmOWYiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iIzhiNTc5MiIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=="); + background-size: 100%; + background-image: -webkit-gradient( + linear, + 50% 0, + 50% 100%, + color-stop(10%, #985f9f), + color-stop(90%, #8b5792) + ); + background-image: -moz-linear-gradient(#985f9f 10%, #8b5792 90%); + background-image: -webkit-linear-gradient(#985f9f 10%, #8b5792 90%); + background-image: linear-gradient(#985f9f 10%, #8b5792 90%); + border-top: 1px solid #a06ba7; + border-bottom: 1px solid #8b5792; + } + .jobs-navigation .subnav { + border-top: 1px solid #58375c; + background-color: #fcfbfd; + *zoom: 1; + filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#FFEEE5EF',endColorstr='#FFFCFBFD'); + background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiNlZWU1ZWYiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iI2ZjZmJmZCIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=="); + background-size: 100%; + background-image: -webkit-gradient( + linear, + 50% 0, + 50% 100%, + color-stop(10%, #eee5ef), + color-stop(90%, #fcfbfd) + ); + background-image: -moz-linear-gradient(#eee5ef 10%, #fcfbfd 90%); + background-image: -webkit-linear-gradient(#eee5ef 10%, #fcfbfd 90%); + background-image: linear-gradient(#eee5ef 10%, #fcfbfd 90%); + -moz-box-shadow: inset 0 0 20px rgba(160, 107, 167, 0.15); + -webkit-box-shadow: inset 0 0 20px rgba(160, 107, 167, 0.15); + box-shadow: inset 0 0 20px rgba(160, 107, 167, 0.15); + } + .touch .jobs-navigation .subnav:before { + border-color: transparent transparent #eee5ef transparent; + } + .jobs-navigation .tier-2 > a { + color: rgba(51, 51, 51, 0.9); + border-top: 1px solid rgba(160, 107, 167, 0.25); + border-bottom: 1px solid transparent; + } + .jobs-navigation .tier-2 > a:hover, + .jobs-navigation .tier-2 > a:focus { + background: rgba(255, 255, 255, 0.35); + color: rgba(34, 34, 34, 0.9); + } + .jobs-navigation .tier-2:last-child > a { + border-bottom: 1px solid rgba(160, 107, 167, 0.25); + } + .jobs-navigation .current_item { + color: #fff; + background-color: #764a7c; + *zoom: 1; + filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#FF85538C',endColorstr='#FF764A7C'); + background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiM4NTUzOGMiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iIzc2NGE3YyIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=="); + background-size: 100%; + background-image: -webkit-gradient( + linear, + 50% 0, + 50% 100%, + color-stop(10%, #85538c), + color-stop(90%, #764a7c) + ); + background-image: -moz-linear-gradient(#85538c 10%, #764a7c 90%); + background-image: -webkit-linear-gradient(#85538c 10%, #764a7c 90%); + background-image: linear-gradient(#85538c 10%, #764a7c 90%); + } + .jobs-navigation .super-navigation { + color: #666; + border: 1px solid #d3bbd7; + background-color: #fcfbfd; + *zoom: 1; + filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#FFFFFFFF',endColorstr='#FFFCFBFD'); + background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiNmZmZmZmYiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iI2ZjZmJmZCIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=="); + background-size: 100%; + background-image: -webkit-gradient( + linear, + 50% 0, + 50% 100%, + color-stop(10%, #fff), + color-stop(90%, #fcfbfd) + ); + background-image: -moz-linear-gradient(#fff 10%, #fcfbfd 90%); + background-image: -webkit-linear-gradient(#fff 10%, #fcfbfd 90%); + background-image: linear-gradient(#fff 10%, #fcfbfd 90%); + } + .jobs-navigation .super-navigation a:not(.button) { + color: #a06ba7; + } + .jobs-navigation .super-navigation h4 { + color: #945d9c; + } + .shop-navigation { + background-color: #9e4650; + *zoom: 1; + filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#FFB55863',endColorstr='#FF9E4650'); + background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIzMCUiIHN0b3AtY29sb3I9IiNiNTU4NjMiLz48c3RvcCBvZmZzZXQ9Ijk1JSIgc3RvcC1jb2xvcj0iIzllNDY1MCIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=="); + background-size: 100%; + background-image: -webkit-gradient( + linear, + 50% 0, + 50% 100%, + color-stop(30%, #b55863), + color-stop(95%, #9e4650) + ); + background-image: -moz-linear-gradient(#b55863 30%, #9e4650 95%); + background-image: -webkit-linear-gradient(#b55863 30%, #9e4650 95%); + background-image: linear-gradient(#b55863 30%, #9e4650 95%); + border-top: 1px solid #cc8d95; + border-bottom: 1px solid #622b32; + } + .shop-navigation .tier-1 { + border-top: 1px solid #c57b84; + border-right: 1px solid #97434d; + border-bottom: 1px solid #74333b; + border-left: 1px solid #c57b84; + } + .shop-navigation .tier-1 > a { + color: #e6e8ea; + background-color: transparent; + border-top: 1px solid transparent; + border-bottom: 1px solid transparent; + letter-spacing: 0.01em; + } + .shop-navigation .tier-1 > a:hover, + .shop-navigation .tier-1 > a:focus, + .shop-navigation .tier-1 > a .tier-1:hover > a { + color: #fff; + background-color: #9e4650; + *zoom: 1; + filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#FFAC4C58',endColorstr='#FF9E4650'); + background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiNhYzRjNTgiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iIzllNDY1MCIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=="); + background-size: 100%; + background-image: -webkit-gradient( + linear, + 50% 0, + 50% 100%, + color-stop(10%, #ac4c58), + color-stop(90%, #9e4650) + ); + background-image: -moz-linear-gradient(#ac4c58 10%, #9e4650 90%); + background-image: -webkit-linear-gradient(#ac4c58 10%, #9e4650 90%); + background-image: linear-gradient(#ac4c58 10%, #9e4650 90%); + border-top: 1px solid #b55863; + border-bottom: 1px solid #9e4650; + } + .shop-navigation .subnav { + border-top: 1px solid #622b32; + background-color: #fbf7f8; + *zoom: 1; + filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#FFF1DEE0',endColorstr='#FFFBF7F8'); + background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiNmMWRlZTAiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iI2ZiZjdmOCIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=="); + background-size: 100%; + background-image: -webkit-gradient( + linear, + 50% 0, + 50% 100%, + color-stop(10%, #f1dee0), + color-stop(90%, #fbf7f8) + ); + background-image: -moz-linear-gradient(#f1dee0 10%, #fbf7f8 90%); + background-image: -webkit-linear-gradient(#f1dee0 10%, #fbf7f8 90%); + background-image: linear-gradient(#f1dee0 10%, #fbf7f8 90%); + -moz-box-shadow: inset 0 0 20px rgba(181, 88, 99, 0.15); + -webkit-box-shadow: inset 0 0 20px rgba(181, 88, 99, 0.15); + box-shadow: inset 0 0 20px rgba(181, 88, 99, 0.15); + } + .touch .shop-navigation .subnav:before { + border-color: transparent transparent #f1dee0 transparent; + } + .shop-navigation .tier-2 > a { + color: rgba(51, 51, 51, 0.9); + border-top: 1px solid rgba(181, 88, 99, 0.25); + border-bottom: 1px solid transparent; + } + .shop-navigation .tier-2 > a:hover, + .shop-navigation .tier-2 > a:focus { + background: rgba(255, 255, 255, 0.35); + color: rgba(34, 34, 34, 0.9); + } + .shop-navigation .tier-2:last-child > a { + border-bottom: 1px solid rgba(181, 88, 99, 0.25); + } + .shop-navigation .current_item { + color: #fff; + background-color: #853b44; + *zoom: 1; + filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#FF97434D',endColorstr='#FF853B44'); + background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiM5NzQzNGQiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iIzg1M2I0NCIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=="); + background-size: 100%; + background-image: -webkit-gradient( + linear, + 50% 0, + 50% 100%, + color-stop(10%, #97434d), + color-stop(90%, #853b44) + ); + background-image: -moz-linear-gradient(#97434d 10%, #853b44 90%); + background-image: -webkit-linear-gradient(#97434d 10%, #853b44 90%); + background-image: linear-gradient(#97434d 10%, #853b44 90%); + } + .shop-navigation .super-navigation { + color: #666; + border: 1px solid #dcb0b6; + background-color: #fbf7f8; + *zoom: 1; + filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#FFFFFFFF',endColorstr='#FFFBF7F8'); + background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiNmZmZmZmYiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iI2ZiZjdmOCIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=="); + background-size: 100%; + background-image: -webkit-gradient( + linear, + 50% 0, + 50% 100%, + color-stop(10%, #fff), + color-stop(90%, #fbf7f8) + ); + background-image: -moz-linear-gradient(#fff 10%, #fbf7f8 90%); + background-image: -webkit-linear-gradient(#fff 10%, #fbf7f8 90%); + background-image: linear-gradient(#fff 10%, #fbf7f8 90%); + } + .shop-navigation .super-navigation a:not(.button) { + color: #b55863; + } + .shop-navigation .super-navigation h4 { + color: #a94b56; + } + .default-page .content-wrapper { + padding-top: 2em; + } + .main-content.with-left-sidebar { + width: 65.95745%; + float: right; + margin-right: 0; + #margin-left: -20px; + } + .main-content.with-right-sidebar { + width: 65.95745%; + float: left; + margin-right: 2.12766%; + } + .text { + font-size: 0.9375em; + } + .left-sidebar { + width: 31.91489%; + float: left; + margin-right: 2.12766%; + margin-top: 1em; + } + .right-sidebar { + width: 31.91489%; + float: right; + margin-right: 0; + #margin-left: -20px; + } + .left-sidebar .small-widget, + .left-sidebar .medium-widget, + .left-sidebar .triple-widget, + .right-sidebar .small-widget, + .right-sidebar .medium-widget, + .right-sidebar .triple-widget { + float: none; + width: auto; + margin-right: auto; + #margin-left: auto; + } + .row { + margin-bottom: 1em; + } + .small-widget { + width: 48.93617%; + float: left; + margin-right: 2.12766%; + } + .small-widget:nth-child(2), + .small-widget.last { + margin-right: 0; + } + .triple-widget { + width: 31.91489%; + float: left; + margin-right: 2.12766%; + } + .triple-widget.last { + margin-right: 0; + } + .most-recent-posts { + width: 74.46809%; + float: left; + margin-right: 2.12766%; + } + .pep-widget, + .psf-widget, + .python-needs-you-widget { + padding: 1.5em 1.75em; + clear: both; + } + .pep-list-header, + .pep-index-list li, + .info-key { + margin: 0 -0.5em; + } + .pep-list-header { + display: block; + } + .pep-index-list .label { + display: none; + } + .pep-index-list a { + display: block; + } + .pep-index-list li { + border-bottom: 1px solid #e3e7ec; + margin-bottom: 0; + } + .pep-type, + .pep-num, + .pep-title, + .pep-owner { + float: left; + border-bottom: 0; + } + .pep-type { + width: 15%; + } + .pep-num { + width: 10%; + } + .pep-title { + width: 50%; + } + .pep-owner { + width: 25%; + } + .jobs-intro { + padding-top: 2em; + padding-bottom: 2em; + } + .listing-company-category:before { + content: "Category: "; + color: #666; + } + .listing-job-title:before { + content: "Title: "; + color: #666; + } + .listing-job-type:before { + content: "Looking for: "; + color: #666; + } + .release-number, + .release-date, + .release-download, + .release-enhancements { + -moz-box-orient: vertical; + display: inline-block; + margin-right: -4px; + vertical-align: middle; + } + .release-number { + width: 20%; + } + .release-date { + width: 30%; + } + .release-download { + width: 25%; + } + .release-enhancements { + width: 25%; + } + .release-version, + .release-status, + .release-start, + .release-end, + .release-pep { + -moz-box-orient: vertical; + display: inline-block; + margin-right: -4px; + vertical-align: middle; + } + .release-version { + width: 15%; + } + .release-status { + width: 20%; + } + .release-start { + width: 25%; + } + .release-end { + width: 25%; + } + .release-pep { + width: 15%; + } + .previous-next { + overflow: hidden; + *zoom: 1; + } + .previous-next a { + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + box-sizing: border-box; + } + .previous-next .prev-button { + width: 48.93617%; + float: left; + margin-right: 2.12766%; + } + .previous-next .next-button { + width: 48.93617%; + float: right; + margin-right: 0; + #margin-left: -20px; + } + .main-footer .jump-link { + display: none; + } + .sitemap .tier-1 { + float: left; + width: 50%; + } + .sitemap .tier-1:nth-child(odd) { + clear: left; + } + .sitemap .tier-1:nth-child(even) { + border-left: 1px solid #f7f7f8; + } + .sitemap .tier-1.element-7 { + clear: none; + } + .footer-links { + clear: both; + text-align: center; + } + .footer-links li { + display: inline-block; + } +} +@media (min-width: 50em) { + body:after { + content: "drawer_navigation"; + display: none; + speak: none; + } + .site-headline { + margin: 0.25em 0 0.5em; + } + .site-headline a .python-logo { + width: 255.2px; + height: 72.16px; + } + .site-headline a .psf-logo { + width: 293.92px; + height: 72.16px; + } + .donate-button { + top: 33px; + } + .options-bar { + margin: 0.875em 0; + } + .search-field { + background: #fff; + padding: 0.4em 0.5em 0.3em; + margin-right: 0.5em; + width: 11em; + } + .search-field:focus { + width: 13em; + } + .home .header-banner { + margin: 0 2em 0 1em; + } + .slideshow .slides li { + overflow: hidden; + *zoom: 1; + } + .slide-code, + .slide-copy { + float: left; + width: 50%; + min-height: 280px; + } + .slide-code { + position: relative; + line-height: 1.5; + } + .js .launch-shell { + display: block; + } + .flexslide .launch-shell { + display: block; + position: absolute; + top: 1.25em; + right: 52%; + z-index: 50; + } + .flexslide .launch-shell span, + .flexslide .launch-shell a { + display: inline-block; + } + .flexslide .launch-shell .button { + padding-bottom: 0.2em; + } + .flexslide .launch-shell .button .message { + opacity: 0; + position: absolute; + top: -9999px; + right: 2.6em; + white-space: nowrap; + padding: 0.4em 0.75em 0.35em; + color: #999; + background-color: #1f1f1f; + *zoom: 1; + filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#FF333333',endColorstr='#FF1F1F1F'); + background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiMzMzMzMzMiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iIzFmMWYxZiIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=="); + background-size: 100%; + background-image: -webkit-gradient( + linear, + 50% 0, + 50% 100%, + color-stop(10%, #333), + color-stop(90%, #1f1f1f) + ); + background-image: -moz-linear-gradient(#333 10%, #1f1f1f 90%); + background-image: -webkit-linear-gradient(#333 10%, #1f1f1f 90%); + background-image: linear-gradient(#333 10%, #1f1f1f 90%); + border-top: 1px solid #444; + border-right: 1px solid #444; + border-bottom: 1px solid #444; + border-left: 1px solid #444; + -moz-border-radius: 6px; + -webkit-border-radius: 6px; + border-radius: 6px; + -moz-box-shadow: 1px 1px 1px rgba(0, 0, 0, 0.05); + -webkit-box-shadow: 1px 1px 1px rgba(0, 0, 0, 0.05); + box-shadow: 1px 1px 1px rgba(0, 0, 0, 0.05); + -moz-transition: opacity 0.25s ease-in-out, top 0s linear 0.25s; + -o-transition: opacity 0.25s ease-in-out, top 0s linear 0.25s; + -webkit-transition: opacity 0.25s ease-in-out, top 0s linear; + -webkit-transition-delay: 0s, 0.25s; + transition: opacity 0.25s ease-in-out, top 0s linear 0.25s; + } + .flexslide .launch-shell .button:hover .message { + opacity: 1; + top: 0; + -moz-transition: opacity 0.25s ease-in-out, top 0s linear; + -o-transition: opacity 0.25s ease-in-out, top 0s linear; + -webkit-transition: opacity 0.25s ease-in-out, top 0s linear; + transition: opacity 0.25s ease-in-out, top 0s linear; + } + .introduction { + text-align: center; + } + .introduction .breaker { + display: block; + width: 100%; + height: 1px; + font-size: 1px; + line-height: 1px; + } + .main-header .container { + padding-bottom: 0; + } + .header-banner { + padding: 0 0 0 1em; + margin: 0 -1em 0 0; + } + .about-banner, + .download-for-current-os, + .documentation-banner, + .community-banner { + padding-left: 0; + padding-right: 51.06383%; + padding-top: 1em; + } + .about-banner { + background: 120% 0 no-repeat url(../img/landing-about.png?1576869008) + transparent; + min-height: 345px; + padding-bottom: 3.5em; + margin-bottom: -2.5em; + } + .download-for-current-os { + background: 130% 0 no-repeat url(../img/landing-downloads.png?1576869008) + transparent; + min-height: 345px; + padding-bottom: 4em; + margin-bottom: -3em; + } + .documentation-banner { + background: 130% 0 no-repeat url(../img/landing-docs.png?1576869008) + transparent; + padding-bottom: 1em; + } + .community-banner { + text-align: left; + background: 110% 0 no-repeat url(../img/landing-community.png?1576869008) + transparent; + min-height: 345px; + padding-bottom: 2em; + margin-bottom: -1.25em; + } + .welcome-to-the-foundation { + padding-top: 2em; + padding-bottom: 2em; + } + .welcome-message { + text-align: left; + position: absolute; + left: 0; + width: 23.40426%; + margin-top: 0.56875em; + } + .latest-blog-post, + .featured-event, + .jobs-intro { + position: relative; + text-align: left; + min-height: 130px; + } + .latest-blog-post .call-to-action, + .featured-event .call-to-action, + .jobs-intro .call-to-action { + margin-left: 34.04255%; + } + .latest-blog-post .date-posted, + .latest-blog-post .event-date, + .featured-event .date-posted, + .featured-event .event-date, + .jobs-intro .date-posted, + .jobs-intro .event-date { + position: absolute; + left: 0; + width: 31.91489%; + } + .latest-blog-post .date-posted time, + .featured-event .date-posted time, + .jobs-intro .date-posted time { + position: relative; + top: 30px; + } + .latest-blog-post .excerpt, + .featured-event .excerpt, + .jobs-intro .excerpt { + margin-left: 34.04255%; + } + .home .content-wrapper .container { + padding-top: 2.5em; + } + .main-content.with-left-sidebar { + width: 74.46809%; + float: right; + margin-right: 0; + #margin-left: -20px; + } + .main-content.with-right-sidebar { + width: 74.46809%; + float: left; + margin-right: 2.12766%; + } + .left-sidebar { + width: 23.40426%; + float: left; + margin-right: 2.12766%; + } + .right-sidebar { + width: 23.40426%; + float: right; + margin-right: 0; + #margin-left: -20px; + } + .featured-success-story .success-quote:before, + .featured-success-story .success-quote:after { + font-size: 2.375em; + } + .quote-by, + .quote-by-organization { + display: -moz-inline-stack; + display: inline-block; + vertical-align: baseline; + } + .lt-ie8 .quote-by, + .lt-ie8 .quote-by-organization { + vertical-align: auto; + zoom: 1; + display: inline; + } + .quote-by-organization:before { + content: ", "; + margin-left: -0.25em; + } + .activity-feed { + position: absolute; + right: 0; + } + .psf-widget, + .python-needs-you-widget { + min-height: 14em; + position: relative; + } + .psf-widget .python-logo, + .python-needs-you-widget .python-logo { + position: absolute; + top: 0.5em; + right: 1em; + width: 210px; + height: 210px; + background: top left no-repeat url(../img/python-logo-large.png?1576869008) + transparent; + } + .psf-widget .widget-title, + .psf-widget p, + .python-needs-you-widget .widget-title, + .python-needs-you-widget p { + margin-right: 34.04255%; + } + .triple-widget { + width: 31.91489%; + float: left; + margin-right: 2.12766%; + } + .triple-widget.last { + margin-right: 0; + } + .list-recent-events .event-title, + .list-recent-events p, + .list-recent-posts .event-title, + .list-recent-posts p { + margin-left: 25.53191%; + } + .list-recent-events time, + .list-recent-posts time { + position: absolute; + top: 0.3em; + left: 0; + width: 23.40426%; + } + .list-recent-jobs .listing-company-category a, + .list-recent-jobs .listing-job-type a { + white-space: nowrap; + } + .list-recent-jobs .listing-posted { + width: 48.93617%; + float: left; + margin-right: 2.12766%; + margin-right: 0; + } + .list-recent-jobs .listing-company-category { + width: 48.93617%; + float: right; + margin-right: 0; + #margin-left: -20px; + text-align: right; + clear: none; + } + .list-recent-jobs .listing-actions { + clear: both; + overflow: hidden; + *zoom: 1; + padding-top: 0.9375em; + text-align: right; + } + .listing-company .listing-company-name { + width: 57.44681%; + float: left; + margin-right: 2.12766%; + } + .listing-company .listing-company-name a:hover:after, + .listing-company .listing-company-name a:focus:after { + color: #666; + content: " View Details"; + font-size: 0.75em; + } + .listing-company .listing-location { + width: 40.42553%; + float: right; + margin-right: 0; + #margin-left: -20px; + text-align: right; + } + .job-meta { + width: 48.93617%; + float: left; + margin-right: 2.12766%; + margin-bottom: 0; + } + .job-tags { + width: 48.93617%; + float: right; + margin-right: 0; + #margin-left: -20px; + } + .wide-form ul { + margin-left: 24%; + } + .wide-form p { + overflow: hidden; + *zoom: 1; + } + .wide-form p label, + .wide-form p textarea { + display: inline-block; + vertical-align: top; + } + .wide-form p label { + width: 24%; + } + .wide-form p input[type="text"], + .wide-form p input[type="password"], + .wide-form p input[type="search"], + .wide-form p input[type="email"], + .wide-form p input[type="url"], + .wide-form p input[type="tel"] { + width: 75%; + display: inline-block; + vertical-align: top; + } + .wide-form p textarea { + width: 75%; + } + .wide-form p button { + margin-left: 24%; + } + .wide-form p button + button { + margin-left: 0; + } + .jobs-form ul { + margin-top: -3.25em; + *zoom: 1; + } + .jobs-form ul:after { + content: ""; + display: table; + clear: both; + } + .jobs-form ul li { + float: left; + width: 33%; + } + .jobs-form ul.errorlist { + margin-top: 0; + } + .sitemap, + .footer-links, + .copyright { + font-size: 0.875em; + } + .sitemap .tier-1 { + width: 32.97872%; + border-left: 0; + border-right: 0; + } + .sitemap .tier-1:nth-child(odd), + .sitemap .tier-1:nth-child(even) { + clear: none; + border-left: 0; + border-right: 0; + } + .sitemap .tier-1.element-1, + .sitemap .tier-1.element-2, + .sitemap .tier-1.element-4, + .sitemap .tier-1.element-5, + .sitemap .tier-1.element-8 { + border-right: 1px solid #d5d6d8; + } + .sitemap .tier-1.element-2, + .sitemap .tier-1.element-3, + .sitemap .tier-1.element-5, + .sitemap .tier-1.element-6, + .sitemap .tier-1.element-7, + .sitemap .tier-1.element-8, + .sitemap .tier-1.element-9 { + border-left: 1px solid #f7f7f8; + } + .footer-links .say-no-more { + display: inline; + visibility: visible; + } + .flex-slideshow.default-slideshow .caption-wrapper { + position: absolute; + top: 1em; + left: 1em; + bottom: 2em; + width: 33%; + padding: 0.75em; + overflow: hidden; + background: #e6e8ea; + background: rgba(255, 255, 255, 0.75); + } + .flex-control-nav { + padding-bottom: 1.5em; + } +} +@media (min-width: 58.75em) { + body:after { + content: "drawer_navigation load_supernavs"; + display: none; + speak: none; + } + .main-navigation { + text-align: center; + overflow: visible; + } + .main-navigation .menu { + margin-bottom: 0; + } + .main-navigation .tier-1 > a, + .main-navigation .tier-2 > a { + display: block; + padding: 0.5em 1.5em 0.4em 1em; + position: relative; + } + .main-navigation .tier-1 { + display: block; + width: 100%; + } + .main-navigation .tier-1 > a { + text-align: center; + } + .main-navigation .tier-2 > a { + text-align: left; + } + .main-navigation .menu { + *zoom: 1; + } + .main-navigation .menu:after { + content: ""; + display: table; + clear: both; + } + .main-navigation .tier-1 { + position: relative; + } + .main-navigation .subnav { + position: absolute; + z-index: 100; + text-align: left; + } + .no-touch .main-navigation .subnav { + min-width: 100%; + display: none; + -moz-transition: all 0s ease; + -o-transition: all 0s ease; + -webkit-transition: all 0s ease; + transition: all 0s ease; + } + .touch .main-navigation .subnav { + top: 120%; + display: none; + opacity: 0; + -moz-transition: opacity 0.25s ease-in-out; + -o-transition: opacity 0.25s ease-in-out; + -webkit-transition: opacity 0.25s ease-in-out; + transition: opacity 0.25s ease-in-out; + -moz-box-shadow: 0 0.25em 0.75em rgba(0, 0, 0, 0.6); + -webkit-box-shadow: 0 0.25em 0.75em rgba(0, 0, 0, 0.6); + box-shadow: 0 0.25em 0.75em rgba(0, 0, 0, 0.6); + } + .touch .main-navigation .subnav:before { + position: absolute; + content: ""; + width: 0; + height: 0; + border-color: transparent; + border-style: solid; + border-width: 0.75em; + top: -1.45em; + display: block; + } + .no-touch .main-navigation .element-1:hover .subnav, + .no-touch .main-navigation .element-1:focus .subnav, + .no-touch .main-navigation .element-2:hover .subnav, + .no-touch .main-navigation .element-2:focus .subnav, + .no-touch .main-navigation .element-3:hover .subnav, + .no-touch .main-navigation .element-3:focus .subnav, + .no-touch .main-navigation .element-4:hover .subnav, + .no-touch .main-navigation .element-4:focus .subnav { + left: 0; + display: initial; + -moz-transition-delay: 0.25s; + -o-transition-delay: 0.25s; + -webkit-transition-delay: 0.25s; + transition-delay: 0.25s; + } + .no-touch .main-navigation .element-5:hover .subnav, + .no-touch .main-navigation .element-5:focus .subnav, + .no-touch .main-navigation .element-6:hover .subnav, + .no-touch .main-navigation .element-6:focus .subnav, + .no-touch .main-navigation .element-7:hover .subnav, + .no-touch .main-navigation .element-7:focus .subnav, + .no-touch .main-navigation .element-8:hover .subnav, + .no-touch .main-navigation .element-8:focus .subnav, + .no-touch .main-navigation .last:hover .subnav, + .no-touch .main-navigation .last:focus .subnav { + right: 0; + display: initial; + -moz-transition-delay: 0.25s; + -o-transition-delay: 0.25s; + -webkit-transition-delay: 0.25s; + transition-delay: 0.25s; + } + .touch .main-navigation .element-1:hover .subnav, + .touch .main-navigation .element-1 .subnav.touched, + .touch .main-navigation .element-2:hover .subnav, + .touch .main-navigation .element-2 .subnav.touched, + .touch .main-navigation .element-3:hover .subnav, + .touch .main-navigation .element-3 .subnav.touched, + .touch .main-navigation .element-4:hover .subnav, + .touch .main-navigation .element-4 .subnav.touched { + display: block; + opacity: 1; + left: 0; + } + .touch .main-navigation .element-1 .subnav:before, + .touch .main-navigation .element-2 .subnav:before, + .touch .main-navigation .element-3 .subnav:before, + .touch .main-navigation .element-4 .subnav:before { + left: 1.5em; + } + .touch .main-navigation .element-5:hover .subnav, + .touch .main-navigation .element-5 .subnav.touched, + .touch .main-navigation .element-6:hover .subnav, + .touch .main-navigation .element-6 .subnav.touched, + .touch .main-navigation .element-7:hover .subnav, + .touch .main-navigation .element-7 .subnav.touched, + .touch .main-navigation .element-8:hover .subnav, + .touch .main-navigation .element-8 .subnav.touched, + .touch .main-navigation .last:hover .subnav, + .touch .main-navigation .last .subnav.touched { + display: block; + opacity: 1; + right: 0; + } + .touch .main-navigation .element-5 .subnav:before, + .touch .main-navigation .element-6 .subnav:before, + .touch .main-navigation .element-7 .subnav:before, + .touch .main-navigation .element-8 .subnav:before, + .touch .main-navigation .last .subnav:before { + left: auto; + right: 1.5em; + } + .main-navigation .tier-2 { + display: block; + min-width: 100%; + } + .main-navigation .tier-2 a { + white-space: nowrap; + } + .no-touch .main-navigation { + display: block; + text-align: center; + font-size: 1.125em; + -moz-border-radius: 8px; + -webkit-border-radius: 8px; + border-radius: 8px; + -moz-box-shadow: 0 0 10px rgba(0, 0, 0, 0.2); + -webkit-box-shadow: 0 0 10px rgba(0, 0, 0, 0.2); + box-shadow: 0 0 10px rgba(0, 0, 0, 0.2); + } + .no-touch .main-navigation .menu { + text-align: center; + } + .no-touch .main-navigation .tier-1 { + float: none; + border-top: 0; + border-bottom: 0; + width: auto; + margin: 0 -5px 0 0; + display: -moz-inline-stack; + display: inline-block; + vertical-align: baseline; + border-right: 1px solid rgba(0, 0, 0, 0.2); + border-left: 1px solid rgba(255, 255, 255, 0.1); + } + .lt-ie8 .no-touch .main-navigation .tier-1 { + vertical-align: auto; + zoom: 1; + display: inline; + } + .no-touch .main-navigation .tier-1.element-1 { + border-left: 0; + } + .no-touch .main-navigation .tier-1.last { + border-right: 0; + } + .no-touch .main-navigation .tier-1.element-6, + .no-touch .main-navigation .tier-1.element-7 { + width: auto; + } + .no-touch .main-navigation .tier-1 > a { + padding: 0.65em 1.25em 0.55em; + } + .no-touch .main-navigation .tier-2 { + font-size: 0.875em; + } + .no-touch .default-page .main-navigation { + position: relative; + margin-bottom: -1.375em; + } + .four-col > .column { + width: 25%; + } + .four-col > .double-col { + width: 50%; + } + .four-col > div:nth-of-type(2n + 3) { + clear: none; + } + .four-col > div:nth-of-type(4n + 5) { + clear: left; + } + .site-headline a .python-logo { + width: 290px; + height: 82px; + } + .site-headline a .psf-logo { + width: 334px; + height: 82px; + } + .search-field { + width: 14em; + } + .search-field:focus { + width: 18em; + margin-right: 0.5em; + } + .donate-button { + top: 38px; + } + .options-bar { + margin: 1.3125em 0; + } + .with-supernav .subnav { + display: none; + border-right: 1px solid rgba(102, 102, 102, 0.3); + } + .with-supernav .super-navigation { + display: block; + } + .super-navigation { + color: #666; + position: absolute; + top: 0; + width: 28em; + min-height: 100%; + text-align: left; + padding: 1.5em 1.75em; + border-top: 1px solid rgba(255, 255, 255, 0.8); + border-left: 1px solid rgba(255, 255, 255, 0.8); + } + .main-navigation .super-navigation a:not(.button) { + padding: 0; + border: 0; + } + .main-navigation .super-navigation a:not(.button):hover, + .main-navigation .super-navigation a:not(.button):focus { + border: 0; + background: transparent; + } + .main-navigation .super-navigation a:not(.button):hover, + .main-navigation .super-navigation a:not(.button):focus { + color: #1e2933; + } + .super-navigation h2, + .super-navigation h3, + .super-navigation h4, + .super-navigation h5 { + margin-top: 0; + } + #community .super-navigation h4, + #blog .super-navigation h4, + #events .super-navigation h4 { + font-family: Flux, "Source Sans Pro", Arial, sans-serif; + font-weight: 700; + font-size: 1.3125em; + line-height: 1.25em; + margin-bottom: 0; + } + .super-navigation p.date-posted { + color: #666; + font-size: 0.625em !important; + font-style: italic; + } + .super-navigation p.excert { + font-size: 0.625em; + line-height: 1.3em; + } + .super-navigation p.quote-by { + color: #3776ab; + } + .tier-1.element-1 .super-navigation, + .tier-1.element-2 .super-navigation, + .tier-1.element-3 .super-navigation { + left: 100.25%; + } + .tier-1.element-4 .super-navigation, + .tier-1.element-5 .super-navigation, + .tier-1.element-6 .super-navigation, + .tier-1.element-7 .super-navigation { + left: -28em; + } + .super-navigation .menu { + text-align: left; + } + .about-banner, + .download-for-current-os, + .documentation-banner { + padding-left: 0; + padding-right: 42.55319%; + } + .about-banner p:last-child, + .download-for-current-os p:last-child, + .documentation-banner p:last-child { + margin-bottom: 0; + } + .about-banner p, + .documentation-banner p, + .community-banner p { + margin-right: 14.81481%; + } + .about-banner, + .documentation-banner { + background-position: 110% 0; + } + .download-for-current-os { + background-position: 115% 0; + padding-bottom: 6em; + margin-bottom: -3em; + } + .community-banner { + background-position: 100% 0; + } + .featured-success-story .success-quote { + margin-left: 8.51064%; + margin-right: 8.51064%; + } + .main-content.with-left-sidebar { + padding-left: 3.19149%; + padding-right: 3.19149%; + } + .single-event-title { + font-size: 2em; + } + .fontface .single-event-title { + font-size: 2.3em; + } + .fontface .single-event-title span:before { + font-size: 0.875em; + } + .text > p:first-of-type { + color: #666; + font-size: 1.125em; + line-height: 1.6875; + margin-bottom: 1.25em; + } + .small-widget p, + .small-widget li, + .medium-widget p, + .medium-widget li, + .psf-widget p, + .psf-widget li, + .python-needs-you-widget p, + .python-needs-you-widget li, + .documentation-help p, + .documentation-help li { + font-size: 0.9375em; + } + .small-widget { + width: 23.40426%; + float: left; + margin-right: 2.12766%; + } + .small-widget:nth-child(2) { + margin-right: 2.12766%; + } + .medium-widget { + width: 48.93617%; + float: left; + margin-right: 2.12766%; + } + .small-widget.last, + .medium-widget.last { + float: right; + margin-right: 0; + } + .blog-widget li, + .event-widget li, + .most-recent-posts li { + padding-left: 7em; + } + .blog-widget .say-no-more, + .event-widget .say-no-more, + .most-recent-posts .say-no-more { + display: inline; + visibility: visible; + } + .pep-widget, + .psf-widget, + .python-needs-you-widget { + padding: 1.5em 1.75em; + } + .psf-widget .widget-title, + .psf-widget p, + .python-needs-you-widget .widget-title, + .python-needs-you-widget p { + margin-right: 25.53191%; + } + .mapped-events h2 { + margin-top: 0.5em; + } + .tag-wrapper { + display: inline; + } + .welcome-message { + width: 23.40426%; + } + .latest-blog-post .call-to-action, + .featured-event .call-to-action, + .jobs-intro .call-to-action { + margin-left: 25.53191%; + } + .latest-blog-post .date-posted, + .latest-blog-post .event-date, + .featured-event .date-posted, + .featured-event .event-date, + .jobs-intro .date-posted, + .jobs-intro .event-date { + width: 23.40426%; + } + .latest-blog-post .excerpt, + .featured-event .excerpt, + .jobs-intro .excerpt { + margin-left: 25.53191%; + } + .subscription-channels li { + display: -moz-inline-stack; + display: inline-block; + vertical-align: baseline; + width: 30%; + } + .lt-ie8 .subscription-channels li { + vertical-align: auto; + zoom: 1; + display: inline; + } + .pep-widget .widget-title { + position: relative; + padding-right: 6em; + } + .rss-link { + position: absolute; + top: 0; + right: 0; + } + .sitemap a { + text-align: left; + } + .sitemap .tier-1 { + width: 16.6667%; + border: 0; + } + .sitemap .tier-1.element-1, + .sitemap .tier-1.element-2, + .sitemap .tier-1.element-3, + .sitemap .tier-1.element-4, + .sitemap .tier-1.element-5, + .sitemap .tier-1.element-6, + .sitemap .tier-1.element-7, + .sitemap .tier-1.element-8, + .sitemap .tier-1.element-9, + .sitemap .tier-1.element-10 { + border: 0; + } + .sitemap .subnav, + .sitemap .subnav li { + border: 0; + } + .footer-links a { + padding: 0.3em 0.75em; + } + .flex-slideshow.home-slideshow .caption-wrapper { + float: left; + width: 49%; + } + .flex-slideshow.default-slideshow .caption-wrapper { + top: 2em; + left: 2em; + bottom: 3em; + width: 25%; + padding: 1em; + } + .flex-viewport { + padding-bottom: 0.5em; + } + .touch .flex-viewport { + padding-bottom: 1em; + } + .default-slideshow .flex-control-nav { + text-align: right; + } + .home-slideshow .flex-control-nav { + position: absolute; + bottom: 0; + right: 0; + width: 49%; + padding: 0.5em; + text-align: right; + } + .home-slideshow .flex-direction-nav .flex-prev, + .home-slideshow .flex-direction-nav .flex-next { + top: 40%; + font-size: 1.5em; + filter: progid:DXImageTransform.Microsoft.Alpha(enabled=false); + opacity: 1; + } + .home-slideshow .flex-direction-nav .flex-prev { + left: -0.75em; + } + .home-slideshow .flex-direction-nav .flex-next { + right: -0.75em; + } + .touch body, + .touch #touchnav-wrapper { + position: relative; + width: 100%; + } + .touch .default-page .main-header { + position: static; + } + .touch .main-navigation { + display: block; + position: absolute; + top: 0; + left: -260px; + width: 260px; + height: 100%; + overflow: scroll; + text-align: center; + font-size: 1.125em; + } + .touch .main-navigation a { + text-align: center; + padding: 0.65em 1.25em 0.55em; + } + .touch .main-navigation .tier-2 { + font-size: 0.875em; + } + .touch .main-navigation .subnav { + position: static; + display: block; + opacity: 1; + border-top: 0; + -moz-box-shadow: none; + -webkit-box-shadow: none; + box-shadow: none; + } + .touch #touchnav-wrapper { + -moz-transition: -moz-transform 300ms ease; + -o-transition: -o-transform 300ms ease; + -webkit-transition: -webkit-transform 300ms ease; + transition: transform 300ms ease; + -moz-transform: translate3d(0, 0, 0); + -ms-transform: translate3d(0, 0, 0); + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + -webkit-backface-visibility: hidden; + } + .touch .show-sidemenu #touchnav-wrapper { + -moz-transform: translate3d(260px, 0, 0); + -ms-transform: translate3d(260px, 0, 0); + -webkit-transform: translate3d(260px, 0, 0); + transform: translate3d(260px, 0, 0); + } +} +@media (min-width: 64em) { + body:after { + content: "drawer_navigation load_supernavs"; + display: none; + speak: none; + } + .about-banner { + background-position: 100% 0; + } + .download-for-current-os { + background-position: 105% 0; + } + .download-for-current-os p { + margin-right: 14.81481%; + } + .documentation-banner { + background-position: 110% 0; + min-height: 345px; + } + .documentation-banner .call-to-action { + margin-right: 8.51064%; + } + .documentation-banner p { + margin-right: 0; + } + .community-banner { + padding-left: 0; + padding-right: 51.06383%; + } + .community-banner p { + margin-right: 0; + } + .latest-blog-post .call-to-action, + .featured-event .call-to-action, + .jobs-intro .call-to-action { + margin-left: 25.53191%; + margin-right: 8.51064%; + } + .latest-blog-post .excerpt, + .featured-event .excerpt, + .jobs-intro .excerpt { + margin-left: 25.53191%; + margin-right: 8.51064%; + } + .psf-widget .widget-title, + .psf-widget p { + margin-right: 34.04255%; + } + .mapped-events h2 { + margin-top: 1em; + } + .default-page .main-content.with-left-sidebar { + padding-left: 8.51064%; + padding-right: 8.51064%; + } + .event-description, + .job-description { + padding-left: 8.51064%; + padding-right: 8.51064%; + } +} +@media (min-width: 75em) { + body:after { + content: "drawer_navigation load_supernavs"; + display: none; + speak: none; + } + .about-banner, + .community-banner { + padding-left: 8.51064%; + padding-right: 51.06383%; + } + .about-banner { + background-position: 85% 0; + } + .download-for-current-os { + padding-left: 8.51064%; + padding-right: 42.55319%; + background-position: 95% 0; + padding-bottom: 6em; + margin-bottom: -3em; + } + .download-for-current-os p { + margin-right: 17.3913%; + } + .documentation-banner { + padding-left: 8.51064%; + padding-right: 42.55319%; + background-position: 100% 0; + } + .documentation-banner .call-to-action { + margin-right: 17.3913%; + } + .community-banner { + background-position: 90% 0; + } +} +@-ms-viewport { + width: device-width; +} +@viewport { + width: device-width; +} diff --git a/pep_extensions/theme/static/style.css b/pep_extensions/theme/static/style.css new file mode 100644 index 00000000000..6ecebee69b6 --- /dev/null +++ b/pep_extensions/theme/static/style.css @@ -0,0 +1,4501 @@ +@charset "UTF-8"; +/*@import url('https://fonts.googleapis.com/css2?family=Source+Sans+Pro:ital,wght@0,400;0,700;1,400&display=swap');*/ +@font-face{ + font-family: "Source Sans Pro"; + src:url("SourceSansPro-Regular-webfont.fd0d51605201.woff") format("woff"); + font-weight: normal; + font-style: normal +} +@font-face{ + font-family: "Source Sans Pro"; + src:url("SourceSansPro-Bold-webfont.be855452e565.woff") format("woff"); + font-weight: 700; + font-style: normal +} +@font-face{font-family: "Source Sans Pro"; + src:url("SourceSansPro-It-webfont.1aa29ac0f190.woff") format("woff"); + font-weight: normal; + font-style: italic +} +@font-face { + font-family: 'Flux'; + src: url('Flux-Regular.ttf') format('truetype'); + font-weight: normal; + font-style: normal; +} + +.psf-widget, +.python-needs-you-widget, +.main-header, +.site-base { + background-color: #2b5b84; + *zoom: 1; + filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#FF1E415E',endColorstr='#FF2B5B84'); + background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiMxZTQxNWUiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iIzJiNWI4NCIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=="); + background-size: 100%; + background-image: -webkit-gradient( + linear, + 50% 0, + 50% 100%, + color-stop(10%, #1e415e), + color-stop(90%, #2b5b84) + ); + background-image: -moz-linear-gradient(#1e415e 10%, #2b5b84 90%); + background-image: -webkit-linear-gradient(#1e415e 10%, #2b5b84 90%); + background-image: linear-gradient(#1e415e 10%, #2b5b84 90%); + -moz-box-shadow: inset 0 0 50px rgba(0, 0, 0, 0.03), + inset 0 0 20px rgba(0, 0, 0, 0.03); + -webkit-box-shadow: inset 0 0 50px rgba(0, 0, 0, 0.03), + inset 0 0 20px rgba(0, 0, 0, 0.03); + box-shadow: inset 0 0 50px rgba(0, 0, 0, 0.03), + inset 0 0 20px rgba(0, 0, 0, 0.03); +} +.psf-widget, +.python-needs-you-widget { + margin-bottom: 0.5em; + padding: 1.25em; + *zoom: 1; +} +.psf-widget:after, +.python-needs-you-widget:after { + content: ""; + display: table; + clear: both; +} +.pep-widget, +.most-recent-events .more-by-location, +.more-by-location { + background-color: #d8dbde; + *zoom: 1; + filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#FFE6E8EA',endColorstr='#FFD8DBDE'); + background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiNlNmU4ZWEiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iI2Q4ZGJkZSIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=="); + background-size: 100%; + background-image: -webkit-gradient( + linear, + 50% 0, + 50% 100%, + color-stop(10%, #e6e8ea), + color-stop(90%, #d8dbde) + ); + background-image: -moz-linear-gradient(#e6e8ea 10%, #d8dbde 90%); + background-image: -webkit-linear-gradient(#e6e8ea 10%, #d8dbde 90%); + background-image: linear-gradient(#e6e8ea 10%, #d8dbde 90%); + -moz-box-shadow: inset 0 0 10px rgba(0, 0, 0, 0.01); + -webkit-box-shadow: inset 0 0 10px rgba(0, 0, 0, 0.01); + box-shadow: inset 0 0 10px rgba(0, 0, 0, 0.01); +} +.pep-widget, +.most-recent-events .more-by-location { + border: 1px solid #caccce; + margin-bottom: 0.5em; + padding: 1.25em; + *zoom: 1; +} +.pep-widget:after, +.most-recent-events .more-by-location:after { + content: ""; + display: table; + clear: both; +} +.single-event-date { + background-color: #ffdd6c; + *zoom: 1; + filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#FFFFE89F',endColorstr='#FFFFDD6C'); + background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiNmZmU4OWYiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iI2ZmZGQ2YyIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=="); + background-size: 100%; + background-image: -webkit-gradient( + linear, + 50% 0, + 50% 100%, + color-stop(10%, #ffe89f), + color-stop(90%, #ffdd6c) + ); + background-image: -moz-linear-gradient(#ffe89f 10%, #ffdd6c 90%); + background-image: -webkit-linear-gradient(#ffe89f 10%, #ffdd6c 90%); + background-image: linear-gradient(#ffe89f 10%, #ffdd6c 90%); + -moz-box-shadow: inset 0 0 10px rgba(0, 0, 0, 0.05); + -webkit-box-shadow: inset 0 0 10px rgba(0, 0, 0, 0.05); + box-shadow: inset 0 0 10px rgba(0, 0, 0, 0.05); +} +.single-event-date { + border: 1px solid #ffcc24; + margin-bottom: 0.5em; + padding: 1.25em; + *zoom: 1; +} +.single-event-date:after { + content: ""; + display: table; + clear: both; +} +.psf-widget .button, +.python-needs-you-widget .button, +.donate-button, +.header-banner .button, +.header-banner a.button, +a.delete, +form.deletion-form button[type="submit"], +button[type="submit"], +.search-button, +#dive-into-python .flex-control-paging a, +.text form button, +.text form input[type="submit"], +.sidebar-widget form button, +.sidebar-widget form input[type="submit"], +input[type="submit"], +input[type="reset"], +button, +a.button, +.button { + cursor: pointer; + color: #4d4d4d !important; + font-weight: normal; + margin-bottom: 0.4375em; + padding: 0.4em 0.75em 0.35em; + text-align: left; + white-space: nowrap; + text-shadow: 1px 1px 1px rgba(255, 255, 255, 0.3); + background-color: #ccc; + *zoom: 1; + filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#FFD9D9D9',endColorstr='#FFCCCCCC'); + background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiNkOWQ5ZDkiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iI2NjY2NjYyIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=="); + background-size: 100%; + background-image: -webkit-gradient( + linear, + 50% 0, + 50% 100%, + color-stop(10%, #d9d9d9), + color-stop(90%, #ccc) + ); + background-image: -moz-linear-gradient(#d9d9d9 10%, #ccc 90%); + background-image: -webkit-linear-gradient(#d9d9d9 10%, #ccc 90%); + background-image: linear-gradient(#d9d9d9 10%, #ccc 90%); + border-top: 1px solid #caccce; + border-right: 1px solid #caccce; + border-bottom: 1px solid #999; + border-left: 1px solid #caccce; + -moz-border-radius: 6px; + -webkit-border-radius: 6px; + border-radius: 6px; + -moz-box-shadow: 1px 1px 1px rgba(0, 0, 0, 0.05), + inset 0 0 5px rgba(255, 255, 255, 0.5); + -webkit-box-shadow: 1px 1px 1px rgba(0, 0, 0, 0.05), + inset 0 0 5px rgba(255, 255, 255, 0.5); + box-shadow: 1px 1px 1px rgba(0, 0, 0, 0.05), + inset 0 0 5px rgba(255, 255, 255, 0.5); +} +.donate-button:hover, +a.delete:hover, +form.deletion-form button[type="submit"]:hover, +.search-button:hover, +#dive-into-python .flex-control-paging a:hover, +.text form button:hover, +.text form input[type="submit"]:hover, +.sidebar-widget form button:hover, +.sidebar-widget form input[type="submit"]:hover, +input[type="submit"]:hover, +input[type="reset"]:hover, +button:hover, +.button:hover, +.donate-button:focus, +a.delete:focus, +form.deletion-form button[type="submit"]:focus, +.search-button:focus, +#dive-into-python .flex-control-paging a:focus, +.text form button:focus, +.text form input[type="submit"]:focus, +.sidebar-widget form button:focus, +.sidebar-widget form input[type="submit"]:focus, +input[type="submit"]:focus, +input[type="reset"]:focus, +button:focus, +.button:focus, +.donate-button:active, +a.delete:active, +form.deletion-form button[type="submit"]:active, +.search-button:active, +#dive-into-python .flex-control-paging a:active, +.text form button:active, +.text form input[type="submit"]:active, +.sidebar-widget form button:active, +.sidebar-widget form input[type="submit"]:active, +input[type="submit"]:active, +input[type="reset"]:active, +button:active, +.button:active { + color: #1a1a1a !important; + background-color: #d9d9d9; + *zoom: 1; + filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#FFE6E6E6',endColorstr='#FFD9D9D9'); + background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiNlNmU2ZTYiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iI2Q5ZDlkOSIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=="); + background-size: 100%; + background-image: -webkit-gradient( + linear, + 50% 0, + 50% 100%, + color-stop(10%, #e6e6e6), + color-stop(90%, #d9d9d9) + ); + background-image: -moz-linear-gradient(#e6e6e6 10%, #d9d9d9 90%); + background-image: -webkit-linear-gradient(#e6e6e6 10%, #d9d9d9 90%); + background-image: linear-gradient(#e6e6e6 10%, #d9d9d9 90%); +} +.psf-widget .button, +.python-needs-you-widget .button, +.donate-button, +.header-banner .button, +.header-banner a.button { + background-color: #ffd343; + *zoom: 1; + filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#FFFFDF76',endColorstr='#FFFFD343'); + background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiNmZmRmNzYiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iI2ZmZDM0MyIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=="); + background-size: 100%; + background-image: -webkit-gradient( + linear, + 50% 0, + 50% 100%, + color-stop(10%, #ffdf76), + color-stop(90%, #ffd343) + ); + background-image: -moz-linear-gradient(#ffdf76 10%, #ffd343 90%); + background-image: -webkit-linear-gradient(#ffdf76 10%, #ffd343 90%); + background-image: linear-gradient(#ffdf76 10%, #ffd343 90%); + border-top: 1px solid #dca900; + border-right: 1px solid #dca900; + border-bottom: 1px solid #dca900; + border-left: 1px solid #dca900; +} +.psf-widget .button:hover, +.python-needs-you-widget .button:hover, +.donate-button:hover, +.header-banner .button:hover, +.psf-widget .button:active, +.python-needs-you-widget .button:active, +.donate-button:active, +.header-banner .button:active { + background-color: inherit; + background-color: #ffd343; + *zoom: 1; + filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#FFFFEBA9',endColorstr='#FFFFD343'); + background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiNmZmViYTkiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iI2ZmZDM0MyIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=="); + background-size: 100%; + background-image: -webkit-gradient( + linear, + 50% 0, + 50% 100%, + color-stop(10%, #ffeba9), + color-stop(90%, #ffd343) + ); + background-image: -moz-linear-gradient(#ffeba9 10%, #ffd343 90%); + background-image: -webkit-linear-gradient(#ffeba9 10%, #ffd343 90%); + background-image: linear-gradient(#ffeba9 10%, #ffd343 90%); +} +a.delete, +form.deletion-form button[type="submit"] { + background-color: #b55863; + *zoom: 1; + filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#FFC57B84',endColorstr='#FFB55863'); + background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiNjNTdiODQiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iI2I1NTg2MyIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=="); + background-size: 100%; + background-image: -webkit-gradient( + linear, + 50% 0, + 50% 100%, + color-stop(10%, #c57b84), + color-stop(90%, #b55863) + ); + background-image: -moz-linear-gradient(#c57b84 10%, #b55863 90%); + background-image: -webkit-linear-gradient(#c57b84 10%, #b55863 90%); + background-image: linear-gradient(#c57b84 10%, #b55863 90%); + border-top: 1px solid #74333b; + border-right: 1px solid #74333b; + border-bottom: 1px solid #74333b; + border-left: 1px solid #74333b; + color: #fff !important; +} +a.delete:hover, +form.deletion-form button[type="submit"]:hover, +a.delete:active, +form.deletion-form button[type="submit"]:active { + background-color: inherit; + color: #fff !important; + background-color: #b55863; + *zoom: 1; + filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#FFD49FA5',endColorstr='#FFB55863'); + background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiNkNDlmYTUiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iI2I1NTg2MyIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=="); + background-size: 100%; + background-image: -webkit-gradient( + linear, + 50% 0, + 50% 100%, + color-stop(10%, #d49fa5), + color-stop(90%, #b55863) + ); + background-image: -moz-linear-gradient(#d49fa5 10%, #b55863 90%); + background-image: -webkit-linear-gradient(#d49fa5 10%, #b55863 90%); + background-image: linear-gradient(#d49fa5 10%, #b55863 90%); +} +button[type="submit"], +.search-button, +#dive-into-python .flex-control-paging a, +.text form button, +.text form input[type="submit"], +.sidebar-widget form button, +.sidebar-widget form input[type="submit"] { + color: #e6e8ea !important; + text-shadow: none; + background-color: #2b5b84; + *zoom: 1; + filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#FF3776AB',endColorstr='#FF2B5B84'); + background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiMzNzc2YWIiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iIzJiNWI4NCIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=="); + background-size: 100%; + background-image: -webkit-gradient( + linear, + 50% 0, + 50% 100%, + color-stop(10%, #3776ab), + color-stop(90%, #2b5b84) + ); + background-image: -moz-linear-gradient(#3776ab 10%, #2b5b84 90%); + background-image: -webkit-linear-gradient(#3776ab 10%, #2b5b84 90%); + background-image: linear-gradient(#3776ab 10%, #2b5b84 90%); + border-top: 1px solid #3d83be; + border-right: 1px solid #3776ab; + border-bottom: 1px solid #3776ab; + border-left: 1px solid #3d83be; + -moz-box-shadow: inset 0 0 5px rgba(55, 118, 171, 0.2); + -webkit-box-shadow: inset 0 0 5px rgba(55, 118, 171, 0.2); + box-shadow: inset 0 0 5px rgba(55, 118, 171, 0.2); +} +button[type="submit"]:hover, +.search-button:hover, +#dive-into-python .flex-control-paging a:hover, +.text form button:hover, +.text form input[type="submit"]:hover, +.sidebar-widget form button:hover, +.sidebar-widget form input[type="submit"]:hover, +button[type="submit"]:active, +.search-button:active, +#dive-into-python .flex-control-paging a:active, +.text form button:active, +.text form input[type="submit"]:active, +.sidebar-widget form button:active, +.sidebar-widget form input[type="submit"]:active { + background: inherit; + color: #f2f4f6 !important; + background-color: #244e71; + *zoom: 1; + filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#FF316998',endColorstr='#FF244E71'); + background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiMzMTY5OTgiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iIzI0NGU3MSIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=="); + background-size: 100%; + background-image: -webkit-gradient( + linear, + 50% 0, + 50% 100%, + color-stop(10%, #316998), + color-stop(90%, #244e71) + ); + background-image: -moz-linear-gradient(#316998 10%, #244e71 90%); + background-image: -webkit-linear-gradient(#316998 10%, #244e71 90%); + background-image: linear-gradient(#316998 10%, #244e71 90%); +} +.header-banner a:not(.button), +.header-banner a:not(.readmore), +.text a:not(.button), +.sidebar-widget a:not(.button), +.active-user-list a { + border-bottom: 1px solid #ffdf76; + text-decoration: none; +} +.header-banner a:hover:not(.button), +.header-banner a:hover:not(.readmore), +.text a:hover:not(.button), +.sidebar-widget a:hover:not(.button), +.active-user-list a:hover, +.header-banner a:focus:not(.button), +.header-banner a:focus:not(.readmore), +.text a:focus:not(.button), +.sidebar-widget a:focus:not(.button), +.active-user-list a:focus { + border-bottom-color: #ffd343; +} +.blog-widget li, +.event-widget li, +.most-recent-posts li { + border-top: 1px solid #caccce; + padding-left: 4em; + padding-top: 0.4375em; + padding-bottom: 0.4375em; + position: relative; +} +.blog-widget li time, +.event-widget li time, +.most-recent-posts li time { + position: absolute; + top: 50%; + left: 0; + margin-top: -0.75em; +} +.pagination a { + display: block; + color: #999; + padding: 0.5em 0.75em 0.4em; + border: 1px solid #caccce; + background-color: transparent; +} +form, +.header-banner, +.success-stories-widget .quote-from { + *zoom: 1; +} +form:after, +.header-banner:after, +.success-stories-widget .quote-from:after { + content: ""; + display: table; + clear: both; +} +html, +body, +div, +span, +object, +iframe, +h1, +h2, +h3, +h4, +h5, +h6, +p, +blockquote, +pre, +abbr, +address, +cite, +code, +del, +dfn, +em, +img, +ins, +kbd, +q, +samp, +small, +strong, +sub, +sup, +var, +b, +i, +dl, +dt, +dd, +ol, +ul, +li, +fieldset, +form, +label, +legend, +table, +caption, +tbody, +tfoot, +thead, +tr, +th, +td, +article, +aside, +canvas, +details, +figcaption, +figure, +footer, +header, +hgroup, +menu, +nav, +section, +summary, +time, +mark, +audio, +video { + margin: 0; + padding: 0; + border: 0; + font-size: 100%; + font: inherit; + vertical-align: baseline; +} +article, +aside, +details, +figcaption, +figure, +footer, +header, +hgroup, +menu, +nav, +section, +form { + display: block; +} +blockquote { + quotes: none; +} +blockquote:before, +blockquote:after { + content: ""; + content: none; +} +q { + display: inline; +} +q:before { + content: "“"; +} +q:after { + content: "”"; +} +q q:before { + content: "‘"; +} +q q:after { + content: "’"; +} +ins { + background-color: #ddd; + color: #222; + text-decoration: none; +} +mark { + display: inline-block; + padding: 0 0.25em; + margin: 0 -0.125em; + background-color: #ffb; +} +s, +strike, +del { + text-decoration: line-through; +} +abbr[title], +dfn[title] { + cursor: help; +} +table { + width: 100%; + border-collapse: collapse; + border-spacing: 0; +} +th, +td { + text-align: left; + vertical-align: top; +} +hr { + display: block; + height: 1px; + border: 0; + border-top: 1px solid #caccce; + margin: 1.75em 0; + padding: 0; +} +input, +button, +select { + display: inline-block; + vertical-align: middle; + cursor: pointer; +} +html { + font-size: 100%; + -webkit-text-size-adjust: 100%; + -ms-text-size-adjust: 100%; + overflow-y: scroll; + -webkit-font-smoothing: antialiased; + margin: 0; +} +body { + *font-size: small; + /*text-rendering: optimizeSpeed;*/ +} +select, +input, +textarea, +button { + font: 99%; + -webkit-font-smoothing: antialiased; + margin: 0; +} +h1, +h2, +h3, +h4, +h5, +h6 { + font-weight: normal; +} +ul, +ol { + margin-left: 1.5em; +} +ul { + list-style: square; +} +ol { + list-style: decimal; +} +ol ol { + list-style: upper-alpha; +} +ol ol ol { + list-style: lower-roman; +} +ol ol ol ol { + list-style: lower-alpha; +} +nav ul, +menu ul, +.menu, +form ul, +.errorlist, +.text form label + ul, +.sidebar-widget form label + ul, +.tabs { + margin-left: 0; + list-style: none; + list-style-image: none; +} +small { + font-size: 85%; +} +b, +strong, +th { + font-weight: 700; +} +i, +em, +cite { + font-style: italic; +} +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; +} +sup { + top: -0.5em; +} +sub { + bottom: -0.25em; +} +pre, +code, +kbd, +samp, +var { + font-family: Consolas, "Lucida Console", "Liberation Mono", "DejaVu Sans Mono", + "Bitstream Vera Sans Mono", "Courier New", monospace, sans-serif; +} +pre { + white-space: pre-wrap; + white-space: -moz-pre-wrap !important; + white-space: -pre-wrap; + white-space: -o-pre-wrap; + word-wrap: break-word; +} +code { + color: #11a611; +} +var { + font-style: italic; +} +textarea { + overflow: auto; + vertical-align: top; + resize: vertical; +} +.ie7 legend { + border: 0; + padding: 0; + white-space: normal; + *margin-left: -7px; +} +input[type="radio"] { + vertical-align: text-bottom; +} +input[type="checkbox"] { + vertical-align: baseline; +} +.ie7 input[type="checkbox"] { + vertical-align: bottom; +} +button, +input[type="button"], +input[type="reset"], +input[type="submit"] { + cursor: pointer; + -webkit-appearance: button; + -moz-appearance: button; +} +.lt-ie8 button, +.lt-ie8 input[type="button"], +.lt-ie8 input[type="reset"], +.lt-ie8 input[type="submit"] { + overflow: visible; +} +button[disabled], +input[disabled] { + cursor: default; +} +input[type="checkbox"], +input[type="radio"] { + padding: 0; + *width: 13px; + *height: 13px; +} +input[type="search"] { + -webkit-appearance: textfield; +} +input[type="search"]::-webkit-search-decoration, +input[type="search"]::-webkit-search-cancel-button { + -webkit-appearance: none; +} +.no-boxshadow input:invalid, +.no-boxshadow textarea:invalid { + background-color: #f0dddd; +} +.ie7 img { + -ms-interpolation-mode: bicubic; +} +abbr.initialism { + speak: spell-out; +} +abbr.truncation { + speak: normal; +} +@-ms-viewport { + width: device-width; +} +canvas { + -ms-touch-action: double-tap-zoom; +} +svg:not(:root) { + overflow: hidden; +} +html { + background-color: #2b5b84; + font: normal 100%/1.625 "Source Sans Pro", Arial, sans-serif; +} +body { + color: #444; + background-color: #fff; +} +body:after { + content: "small"; + display: none; +} +body, +input, +textarea, +select, +button { + color: #444; + font: normal 100%/1.625 "Source Sans Pro", Arial, sans-serif; +} +* { + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + box-sizing: border-box; +} +a, +a:active, +a:visited, +a:hover, +a:visited:hover { + color: #3776ab; + text-decoration: none; +} +a:hover, +a:focus { + color: #1e2933; +} +.touch a[href^="tel:"] { + border-bottom: 1px dotted #444; +} +a img { + display: block; + margin: 0 auto; +} +::-moz-selection { + background: #3776ab; + color: #fff; + text-shadow: none; +} +::selection { + background: #3776ab; + color: #fff; + text-shadow: none; +} +a:link { + -webkit-tap-highlight-color: #1e2933; +} +img, +embed, +object, +video { + max-width: 100%; +} +.giga { + font-size: 2.5em; +} +.fontface .giga { + font-size: 2.875em; +} +.fontface .giga span:before { + font-size: 0.875em; +} +.mega { + font-size: 2.25em; +} +.fontface .mega { + font-size: 2.5875em; +} +.fontface .mega span:before { + font-size: 0.875em; +} +.kilo { + font-size: 2em; +} +.fontface .kilo { + font-size: 2.3em; +} +.fontface .kilo span:before { + font-size: 0.875em; +} +h1, +.alpha { + color: #3776ab; + font-weight: 700; + font-family: "Source Sans Pro", Arial, sans-serif; + line-height: 1em; + font-size: 1.75em; + margin-bottom: 0.4375em; +} +h2, +.beta { + color: #999; + font-family: "Source Sans Pro", Arial, sans-serif; + font-size: 1.5em; + margin-top: 1.3125em; + margin-bottom: 0.32813em; +} +h3, +.chi { + color: #222; + font-size: 1.3125em; + margin-top: 1.75em; + margin-bottom: 0.4375em; +} +h4, +.delta { + color: #222; + font-weight: 700; + font-family: "Source Sans Pro", Arial, sans-serif; + font-size: 1.125em; + margin-top: 1.3125em; + margin-bottom: 0.4375em; +} +h5, +.epsilon { + color: #222; + font-weight: 700; + font-family: "Source Sans Pro", Arial, sans-serif; + text-transform: uppercase; + letter-spacing: 0.0625em; + margin-top: 1.75em; +} +h6, +.gamma { + color: #222; + font-weight: 700; + font-family: "Source Sans Pro", Arial, sans-serif; + margin-top: 1.75em; +} +blockquote { + position: relative; + font: italic 1.125em Georgia, serif; + line-height: 2; + padding-top: 1.3125em; + padding-bottom: 1.3125em; + border-top: 3px solid #ffeba9; + border-bottom: 3px solid #ffeba9; + margin-bottom: 1.3125em; +} +blockquote footer { + font: normal 0.77778em "Source Sans Pro", Arial, sans-serif; +} +blockquote em { + font-style: normal; +} +dl { + border-top: 1px solid #e6e8ea; +} +dl dt { + font-weight: 700; + font-family: "Source Sans Pro", Arial, sans-serif; + border-bottom: 1px solid #e6e8ea; +} +dl dd { + padding-left: 1.5em; + border-bottom: 1px solid #caccce; +} +.errorlist { + color: #b55863; + margin-bottom: 0; +} +.errorlist + label { + margin-top: 0; +} +.error-message { + color: #b55863; +} +label { + display: block; + color: #999; + font-weight: bold; + margin-top: 0.875em; + margin-top: 0.21875em; +} +label.active { + color: #3776ab; +} +input, +textarea { + width: 100%; + padding: 0.65em; + border: 1px solid #caccce; + -moz-border-radius: 6px; + -webkit-border-radius: 6px; + border-radius: 6px; +} +input, +textarea, +select { + margin-bottom: 0.875em; +} +input[type="checkbox"], +input[type="radio"] { + width: auto; + border: 0; + margin-right: 0.25em; +} +input[type="radio"] { + margin-bottom: 0.25em; +} +.no-touch input:focus { + -moz-box-shadow: 0 0 10px rgba(0, 0, 0, 0.2); + -webkit-box-shadow: 0 0 10px rgba(0, 0, 0, 0.2); + box-shadow: 0 0 10px rgba(0, 0, 0, 0.2); +} +input[required="required"] { + border-color: #b55863; +} +input[required="required"]:focus { + -moz-box-shadow: 0 0 10px rgba(255, 0, 0, 0.5); + -webkit-box-shadow: 0 0 10px rgba(255, 0, 0, 0.5); + box-shadow: 0 0 10px rgba(255, 0, 0, 0.5); +} +::-webkit-input-placeholder { + color: #999; + font-style: italic; +} +input:-moz-placeholder { + color: #999; + font-style: italic; +} +input[type="submit"], +input[type="reset"], +button, +a.button, +.button { + display: block; +} +input[type="reset"], +button.secondaryAction[type="submit"] { + background-color: #999; + *zoom: 1; + filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#FFB3B3B3',endColorstr='#FF999999'); + background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiNiM2IzYjMiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iIzk5OTk5OSIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=="); + background-size: 100%; + background-image: -webkit-gradient( + linear, + 50% 0, + 50% 100%, + color-stop(10%, #b3b3b3), + color-stop(90%, #999) + ); + background-image: -moz-linear-gradient(#b3b3b3 10%, #999 90%); + background-image: -webkit-linear-gradient(#b3b3b3 10%, #999 90%); + background-image: linear-gradient(#b3b3b3 10%, #999 90%); + border-top: 1px solid #caccce; + border-right: 1px solid #999; + border-bottom: 1px solid gray; + border-left: 1px solid #999; +} +input[type="reset"]:hover, +input[type="reset"]:focus, +input[type="reset"]:active, +button.secondaryAction[type="submit"]:hover, +button.secondaryAction[type="submit"]:focus, +button.secondaryAction[type="submit"]:active { + color: #fff; + background-color: #b3b3b3; + *zoom: 1; + filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#FF999999',endColorstr='#FFB3B3B3'); + background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiM5OTk5OTkiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iI2IzYjNiMyIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=="); + background-size: 100%; + background-image: -webkit-gradient( + linear, + 50% 0, + 50% 100%, + color-stop(10%, #999), + color-stop(90%, #b3b3b3) + ); + background-image: -moz-linear-gradient(#999 10%, #b3b3b3 90%); + background-image: -webkit-linear-gradient(#999 10%, #b3b3b3 90%); + background-image: linear-gradient(#999 10%, #b3b3b3 90%); +} +input[type="image"] { + width: auto; +} +b, +strong { + font-weight: 700; + font-family: "Source Sans Pro", Arial, sans-serif; +} +i, +em { + font-family: "Source Sans Pro", Arial, sans-serif; + font-style: italic; +} +abbr, +dfn { + border-bottom: 1px dotted #3776ab; +} +.col-row { + margin: -1em; + overflow: hidden; + *zoom: 1; +} +.column, +.not-column { + padding-left: 1em; + padding-right: 1em; +} +.column { + padding-bottom: 1.75em; +} +h1.not-column { + padding-left: 0.57143em; + padding-right: 0.57143em; +} +h2.not-column { + padding-left: 0.66667em; + padding-right: 0.66667em; +} +.pre, +.rss-link { + white-space: nowrap; +} +.say-no-more { + display: none; + visibility: hidden; +} +.prompt, +.readmore:before, +.give-me-more a:before { + font-family: Flux, "Source Sans Pro", Arial, sans-serif; + font-size: 120%; + letter-spacing: -0.0625em; +} +.readmore, +.give-me-more a { + white-space: nowrap; +} +.readmore:before, +.give-me-more a:before { + content: ">>>"; + margin-right: 0.25em; +} +.larger { + font-size: 120%; +} +.indent { + padding-left: 2em; +} +.top-bar a:hover, +.top-bar a:focus, +.python .top-bar .python-meta a, +.psf .top-bar .psf-meta a, +.docs .top-bar .docs-meta a, +.pypi .top-bar .pypi-meta a, +.jobs .top-bar .jobs-meta a, +.shop .top-bar .shop-meta a { + color: #fff; + background-color: #1f2a32; + *zoom: 1; + filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#FF13191E',endColorstr='#FF1F2A32'); + background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiMxMzE5MWUiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iIzFmMmEzMiIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=="); + background-size: 100%; + background-image: -webkit-gradient( + linear, + 50% 0, + 50% 100%, + color-stop(10%, #13191e), + color-stop(90%, #1f2a32) + ); + background-image: -moz-linear-gradient(#13191e 10%, #1f2a32 90%); + background-image: -webkit-linear-gradient(#13191e 10%, #1f2a32 90%); + background-image: linear-gradient(#13191e 10%, #1f2a32 90%); +} +.top-bar a:hover:before, +.top-bar a:focus:before, +.python .top-bar .python-meta a:before, +.psf .top-bar .psf-meta a:before, +.docs .top-bar .docs-meta a:before, +.pypi .top-bar .pypi-meta a:before, +.jobs .top-bar .jobs-meta a:before, +.shop .top-bar .shop-meta a:before { + left: 50%; +} +.top-bar { + color: #bbb; + background-color: #1e2933; + border-bottom: 1px solid #1f3b47; +} +.top-bar a { + position: relative; + display: block; + color: #999; + background: transparent; + text-align: center; + padding: 0.5em 0.75em 0.4em; + font-size: 1em; + line-height: 1.75em; +} +.top-bar a:before { + position: absolute; + content: ""; + width: 0; + height: 0; + border-color: transparent; + border-style: solid; + border-width: 0.5em; + border-right-color: transparent; + border-bottom-color: transparent; + border-left-color: transparent; + top: 0; + left: -9999px; + margin-left: -0.25em; +} +.top-bar li { + border-top: 3px solid #3776ab; +} +.top-bar .python-meta, +.top-bar .python-meta a:before { + border-top-color: #3776ab; +} +.top-bar .psf-meta, +.top-bar .psf-meta a:before { + border-top-color: #78797a; +} +.top-bar .docs-meta, +.top-bar .docs-meta a:before { + border-top-color: #ffd343; +} +.top-bar .pypi-meta, +.top-bar .pypi-meta a:before { + border-top-color: #82b043; +} +.top-bar .jobs-meta, +.top-bar .jobs-meta a:before { + border-top-color: #a06ba7; +} +.top-bar .shop-meta, +.top-bar .shop-meta a:before { + border-top-color: #b55863; +} +.meta-navigation { + text-align: center; +} +.meta-navigation .menu, +.meta-navigation form ul, +form .meta-navigation ul, +.meta-navigation .errorlist, +.meta-navigation .text form label + ul, +.text form .meta-navigation label + ul, +.meta-navigation .sidebar-widget form label + ul, +.sidebar-widget form .meta-navigation label + ul { + margin-bottom: 0; +} +.meta-navigation .say-no-more { + display: inline; + visibility: visible; +} +.meta-navigation .jump-link { + background-color: #11171d; +} +.main-header { + border-top: 1px solid #191919; + border-bottom: 1px solid #444; +} +.main-header .container { + text-align: center; + padding: 0.75em 1em; +} +.site-headline { + color: #fff; + margin: 0.15em auto 0.2em; +} +.site-headline a { + display: block; + margin: 0 auto; +} +.site-headline a .python-logo { + width: 217.5px; + height: 61.5px; +} +.site-headline a .psf-logo { + width: 250.5px; + height: 61.5px; +} +.options-bar-container { + float: none; +} +.donate-button { + display: block; + text-align: center; + position: relative; + top: 0; + margin: 1em 0.7em; +} +.options-bar { + width: 100%; + color: #bbb; + margin-bottom: 1.3125em; + border-top: 1px solid #2d3e4d; + border-bottom: 1px solid #070a0c; + background-color: #1e2933; + line-height: 1em; + -moz-border-radius: 6px; + -webkit-border-radius: 6px; + border-radius: 6px; +} +.options-bar form { + padding: 0.35em 0.2em 0.3em; +} +.options-bar .breaker { + display: block; + width: 100%; + height: 1px; + font-size: 1px; + line-height: 1px; + border-top: 1px solid #070a0c; + border-bottom: 1px solid #2d3e4d; +} +.options-bar .subnav { + display: none; +} +#site-map-link, +.jump-to-menu, +.search-the-site, +.icon-search, +.icon-search:before, +input#s, +.adjust-font-size, +.winkwink-nudgenudge, +.account-signin { + display: -moz-inline-stack; + display: inline-block; + vertical-align: middle; +} +.lt-ie8 #site-map-link, +.lt-ie8 .jump-to-menu, +.lt-ie8 .search-the-site, +.lt-ie8 .icon-search, +.lt-ie8 .icon-search:before, +.lt-ie8 input#s, +.lt-ie8 .adjust-font-size, +.lt-ie8 .winkwink-nudgenudge, +.lt-ie8 .account-signin { + vertical-align: auto; + zoom: 1; + display: inline; +} +.touch .search-the-site, +.winkwink-nudgenudge, +.account-signin { + border-left: 1px solid #2d3e4d; +} +.touch #site-map-link, +.jump-to-menu, +.adjust-font-size, +.winkwink-nudgenudge { + border-right: 1px solid #070a0c; +} +#site-map-link { + color: #bbb; +} +#site-map-link:hover, +#site-map-link:focus { + color: #fff; +} +.no-touch #site-map-link { + display: none; +} +.menu-icon { + display: inline-block; + font-size: 1.25em; + margin: -0.125em -0.125em 0 0; +} +.search-the-site { + text-align: left; + padding: 0.35em 0.2em 0.3em; +} +.search-the-site .icon-search:before { + font-size: 1.75em; + margin: 0 0.125em 0 0.25em; +} +.search-the-site .no-touch { + border-left: 0; +} +.search-field { + width: 4.5em; + margin-bottom: 0; + color: #bbb; + background-color: transparent; + border: 0; + margin: 0.125em 0; + padding: 0.4em 0 0.3em; + -moz-border-radius: 0; + -webkit-border-radius: 0; + border-radius: 0; +} +.search-field::-webkit-input-placeholder { + color: #bbb; + font-style: normal; +} +.search-field:-moz-placeholder { + color: #bbb; + font-style: normal; +} +.search-field:focus { + background-color: #fff; + color: #444; + padding: 0.4em 0.5em 0.3em; +} +.search-field:blur { + color: #bbb; +} +.search-button { + margin-right: 0.2em; + margin-bottom: 0; + text-shadow: none; +} +.touch .search-button { + display: none; +} +.no-touch .adjust-font-size { + display: none; +} +.adjust-font-size, +.winkwink-nudgenudge, +.account-signin { + text-align: center; + overflow: visible; +} +.adjust-font-size .menu, +.adjust-font-size form ul, +form .adjust-font-size ul, +.adjust-font-size .errorlist, +.adjust-font-size .text form label + ul, +.text form .adjust-font-size label + ul, +.adjust-font-size .sidebar-widget form label + ul, +.sidebar-widget form .adjust-font-size label + ul, +.winkwink-nudgenudge .menu, +.winkwink-nudgenudge form ul, +form .winkwink-nudgenudge ul, +.winkwink-nudgenudge .errorlist, +.winkwink-nudgenudge .text form label + ul, +.text form .winkwink-nudgenudge label + ul, +.winkwink-nudgenudge .sidebar-widget form label + ul, +.sidebar-widget form .winkwink-nudgenudge label + ul, +.account-signin .menu, +.account-signin form ul, +form .account-signin ul, +.account-signin .errorlist, +.account-signin .text form label + ul, +.text form .account-signin label + ul, +.account-signin .sidebar-widget form label + ul, +.sidebar-widget form .account-signin label + ul { + margin-bottom: 0; +} +.adjust-font-size .tier-1 > a, +.adjust-font-size .tier-2 > a, +.winkwink-nudgenudge .tier-1 > a, +.winkwink-nudgenudge .tier-2 > a, +.account-signin .tier-1 > a, +.account-signin .tier-2 > a { + display: block; + padding: 0.5em 1.5em 0.4em 1em; + position: relative; +} +.adjust-font-size .tier-1, +.winkwink-nudgenudge .tier-1, +.account-signin .tier-1 { + display: block; + width: 100%; +} +.adjust-font-size .tier-1 > a, +.winkwink-nudgenudge .tier-1 > a, +.account-signin .tier-1 > a { + text-align: center; +} +.adjust-font-size .tier-2 > a, +.winkwink-nudgenudge .tier-2 > a, +.account-signin .tier-2 > a { + text-align: left; +} +.adjust-font-size .menu, +.adjust-font-size form ul, +form .adjust-font-size ul, +.adjust-font-size .errorlist, +.adjust-font-size .text form label + ul, +.text form .adjust-font-size label + ul, +.adjust-font-size .sidebar-widget form label + ul, +.sidebar-widget form .adjust-font-size label + ul, +.winkwink-nudgenudge .menu, +.winkwink-nudgenudge form ul, +form .winkwink-nudgenudge ul, +.winkwink-nudgenudge .errorlist, +.winkwink-nudgenudge .text form label + ul, +.text form .winkwink-nudgenudge label + ul, +.winkwink-nudgenudge .sidebar-widget form label + ul, +.sidebar-widget form .winkwink-nudgenudge label + ul, +.account-signin .menu, +.account-signin form ul, +form .account-signin ul, +.account-signin .errorlist, +.account-signin .text form label + ul, +.text form .account-signin label + ul, +.account-signin .sidebar-widget form label + ul, +.sidebar-widget form .account-signin label + ul { + *zoom: 1; +} +.adjust-font-size .menu:after, +.adjust-font-size form ul:after, +form .adjust-font-size ul:after, +.adjust-font-size .errorlist:after, +.adjust-font-size .text form label + ul:after, +.text form .adjust-font-size label + ul:after, +.adjust-font-size .sidebar-widget form label + ul:after, +.sidebar-widget form .adjust-font-size label + ul:after, +.winkwink-nudgenudge .menu:after, +.winkwink-nudgenudge form ul:after, +form .winkwink-nudgenudge ul:after, +.winkwink-nudgenudge .errorlist:after, +.winkwink-nudgenudge .text form label + ul:after, +.text form .winkwink-nudgenudge label + ul:after, +.winkwink-nudgenudge .sidebar-widget form label + ul:after, +.sidebar-widget form .winkwink-nudgenudge label + ul:after, +.account-signin .menu:after, +.account-signin form ul:after, +form .account-signin ul:after, +.account-signin .errorlist:after, +.account-signin .text form label + ul:after, +.text form .account-signin label + ul:after, +.account-signin .sidebar-widget form label + ul:after, +.sidebar-widget form .account-signin label + ul:after { + content: ""; + display: table; + clear: both; +} +.adjust-font-size .tier-1, +.winkwink-nudgenudge .tier-1, +.account-signin .tier-1 { + position: relative; +} +.adjust-font-size .subnav, +.winkwink-nudgenudge .subnav, +.account-signin .subnav { + position: absolute; + z-index: 100; + text-align: left; +} +.no-touch .adjust-font-size .subnav, +.no-touch .winkwink-nudgenudge .subnav, +.no-touch .account-signin .subnav { + min-width: 100%; + display: none; + -moz-transition: all 0s ease; + -o-transition: all 0s ease; + -webkit-transition: all 0s ease; + transition: all 0s ease; +} +.touch .adjust-font-size .subnav, +.touch .winkwink-nudgenudge .subnav, +.touch .account-signin .subnav { + top: 120%; + display: none; + opacity: 0; + -moz-transition: opacity 0.25s ease-in-out; + -o-transition: opacity 0.25s ease-in-out; + -webkit-transition: opacity 0.25s ease-in-out; + transition: opacity 0.25s ease-in-out; + -moz-box-shadow: 0 0.25em 0.75em rgba(0, 0, 0, 0.6); + -webkit-box-shadow: 0 0.25em 0.75em rgba(0, 0, 0, 0.6); + box-shadow: 0 0.25em 0.75em rgba(0, 0, 0, 0.6); +} +.touch .adjust-font-size .subnav:before, +.touch .winkwink-nudgenudge .subnav:before, +.touch .account-signin .subnav:before { + position: absolute; + content: ""; + width: 0; + height: 0; + border-color: transparent; + border-style: solid; + border-width: 0.75em; + top: -1.45em; + display: block; +} +.no-touch .adjust-font-size .element-1:hover .subnav, +.no-touch .adjust-font-size .element-1:focus .subnav, +.no-touch .adjust-font-size .element-2:hover .subnav, +.no-touch .adjust-font-size .element-2:focus .subnav, +.no-touch .adjust-font-size .element-3:hover .subnav, +.no-touch .adjust-font-size .element-3:focus .subnav, +.no-touch .adjust-font-size .element-4:hover .subnav, +.no-touch .adjust-font-size .element-4:focus .subnav, +.no-touch .winkwink-nudgenudge .element-1:hover .subnav, +.no-touch .winkwink-nudgenudge .element-1:focus .subnav, +.no-touch .winkwink-nudgenudge .element-2:hover .subnav, +.no-touch .winkwink-nudgenudge .element-2:focus .subnav, +.no-touch .winkwink-nudgenudge .element-3:hover .subnav, +.no-touch .winkwink-nudgenudge .element-3:focus .subnav, +.no-touch .winkwink-nudgenudge .element-4:hover .subnav, +.no-touch .winkwink-nudgenudge .element-4:focus .subnav, +.no-touch .account-signin .element-1:hover .subnav, +.no-touch .account-signin .element-1:focus .subnav, +.no-touch .account-signin .element-2:hover .subnav, +.no-touch .account-signin .element-2:focus .subnav, +.no-touch .account-signin .element-3:hover .subnav, +.no-touch .account-signin .element-3:focus .subnav, +.no-touch .account-signin .element-4:hover .subnav, +.no-touch .account-signin .element-4:focus .subnav { + left: 0; + display: initial; + -moz-transition-delay: 0.25s; + -o-transition-delay: 0.25s; + -webkit-transition-delay: 0.25s; + transition-delay: 0.25s; +} +.no-touch .adjust-font-size .element-5:hover .subnav, +.no-touch .adjust-font-size .element-5:focus .subnav, +.no-touch .adjust-font-size .element-6:hover .subnav, +.no-touch .adjust-font-size .element-6:focus .subnav, +.no-touch .adjust-font-size .element-7:hover .subnav, +.no-touch .adjust-font-size .element-7:focus .subnav, +.no-touch .adjust-font-size .element-8:hover .subnav, +.no-touch .adjust-font-size .element-8:focus .subnav, +.no-touch .adjust-font-size .last:hover .subnav, +.no-touch .adjust-font-size .last:focus .subnav, +.no-touch .winkwink-nudgenudge .element-5:hover .subnav, +.no-touch .winkwink-nudgenudge .element-5:focus .subnav, +.no-touch .winkwink-nudgenudge .element-6:hover .subnav, +.no-touch .winkwink-nudgenudge .element-6:focus .subnav, +.no-touch .winkwink-nudgenudge .element-7:hover .subnav, +.no-touch .winkwink-nudgenudge .element-7:focus .subnav, +.no-touch .winkwink-nudgenudge .element-8:hover .subnav, +.no-touch .winkwink-nudgenudge .element-8:focus .subnav, +.no-touch .winkwink-nudgenudge .last:hover .subnav, +.no-touch .winkwink-nudgenudge .last:focus .subnav, +.no-touch .account-signin .element-5:hover .subnav, +.no-touch .account-signin .element-5:focus .subnav, +.no-touch .account-signin .element-6:hover .subnav, +.no-touch .account-signin .element-6:focus .subnav, +.no-touch .account-signin .element-7:hover .subnav, +.no-touch .account-signin .element-7:focus .subnav, +.no-touch .account-signin .element-8:hover .subnav, +.no-touch .account-signin .element-8:focus .subnav, +.no-touch .account-signin .last:hover .subnav, +.no-touch .account-signin .last:focus .subnav { + right: 0; + display: initial; + -moz-transition-delay: 0.25s; + -o-transition-delay: 0.25s; + -webkit-transition-delay: 0.25s; + transition-delay: 0.25s; +} +.touch .adjust-font-size .element-1:hover .subnav, +.touch .adjust-font-size .element-1 .subnav.touched, +.touch .adjust-font-size .element-2:hover .subnav, +.touch .adjust-font-size .element-2 .subnav.touched, +.touch .adjust-font-size .element-3:hover .subnav, +.touch .adjust-font-size .element-3 .subnav.touched, +.touch .adjust-font-size .element-4:hover .subnav, +.touch .adjust-font-size .element-4 .subnav.touched, +.touch .winkwink-nudgenudge .element-1:hover .subnav, +.touch .winkwink-nudgenudge .element-1 .subnav.touched, +.touch .winkwink-nudgenudge .element-2:hover .subnav, +.touch .winkwink-nudgenudge .element-2 .subnav.touched, +.touch .winkwink-nudgenudge .element-3:hover .subnav, +.touch .winkwink-nudgenudge .element-3 .subnav.touched, +.touch .winkwink-nudgenudge .element-4:hover .subnav, +.touch .winkwink-nudgenudge .element-4 .subnav.touched, +.touch .account-signin .element-1:hover .subnav, +.touch .account-signin .element-1 .subnav.touched, +.touch .account-signin .element-2:hover .subnav, +.touch .account-signin .element-2 .subnav.touched, +.touch .account-signin .element-3:hover .subnav, +.touch .account-signin .element-3 .subnav.touched, +.touch .account-signin .element-4:hover .subnav, +.touch .account-signin .element-4 .subnav.touched { + display: block; + opacity: 1; + left: 0; +} +.touch .adjust-font-size .element-1 .subnav:before, +.touch .adjust-font-size .element-2 .subnav:before, +.touch .adjust-font-size .element-3 .subnav:before, +.touch .adjust-font-size .element-4 .subnav:before, +.touch .winkwink-nudgenudge .element-1 .subnav:before, +.touch .winkwink-nudgenudge .element-2 .subnav:before, +.touch .winkwink-nudgenudge .element-3 .subnav:before, +.touch .winkwink-nudgenudge .element-4 .subnav:before, +.touch .account-signin .element-1 .subnav:before, +.touch .account-signin .element-2 .subnav:before, +.touch .account-signin .element-3 .subnav:before, +.touch .account-signin .element-4 .subnav:before { + left: 1.5em; +} +.touch .adjust-font-size .element-5:hover .subnav, +.touch .adjust-font-size .element-5 .subnav.touched, +.touch .adjust-font-size .element-6:hover .subnav, +.touch .adjust-font-size .element-6 .subnav.touched, +.touch .adjust-font-size .element-7:hover .subnav, +.touch .adjust-font-size .element-7 .subnav.touched, +.touch .adjust-font-size .element-8:hover .subnav, +.touch .adjust-font-size .element-8 .subnav.touched, +.touch .adjust-font-size .last:hover .subnav, +.touch .adjust-font-size .last .subnav.touched, +.touch .winkwink-nudgenudge .element-5:hover .subnav, +.touch .winkwink-nudgenudge .element-5 .subnav.touched, +.touch .winkwink-nudgenudge .element-6:hover .subnav, +.touch .winkwink-nudgenudge .element-6 .subnav.touched, +.touch .winkwink-nudgenudge .element-7:hover .subnav, +.touch .winkwink-nudgenudge .element-7 .subnav.touched, +.touch .winkwink-nudgenudge .element-8:hover .subnav, +.touch .winkwink-nudgenudge .element-8 .subnav.touched, +.touch .winkwink-nudgenudge .last:hover .subnav, +.touch .winkwink-nudgenudge .last .subnav.touched, +.touch .account-signin .element-5:hover .subnav, +.touch .account-signin .element-5 .subnav.touched, +.touch .account-signin .element-6:hover .subnav, +.touch .account-signin .element-6 .subnav.touched, +.touch .account-signin .element-7:hover .subnav, +.touch .account-signin .element-7 .subnav.touched, +.touch .account-signin .element-8:hover .subnav, +.touch .account-signin .element-8 .subnav.touched, +.touch .account-signin .last:hover .subnav, +.touch .account-signin .last .subnav.touched { + display: block; + opacity: 1; + right: 0; +} +.touch .adjust-font-size .element-5 .subnav:before, +.touch .adjust-font-size .element-6 .subnav:before, +.touch .adjust-font-size .element-7 .subnav:before, +.touch .adjust-font-size .element-8 .subnav:before, +.touch .adjust-font-size .last .subnav:before, +.touch .winkwink-nudgenudge .element-5 .subnav:before, +.touch .winkwink-nudgenudge .element-6 .subnav:before, +.touch .winkwink-nudgenudge .element-7 .subnav:before, +.touch .winkwink-nudgenudge .element-8 .subnav:before, +.touch .winkwink-nudgenudge .last .subnav:before, +.touch .account-signin .element-5 .subnav:before, +.touch .account-signin .element-6 .subnav:before, +.touch .account-signin .element-7 .subnav:before, +.touch .account-signin .element-8 .subnav:before, +.touch .account-signin .last .subnav:before { + left: auto; + right: 1.5em; +} +.adjust-font-size .tier-2, +.winkwink-nudgenudge .tier-2, +.account-signin .tier-2 { + display: block; + min-width: 100%; +} +.adjust-font-size .tier-2 a, +.winkwink-nudgenudge .tier-2 a, +.account-signin .tier-2 a { + white-space: nowrap; +} +.adjust-font-size a, +.winkwink-nudgenudge a, +.account-signin a { + color: #bbb; + background-color: transparent; +} +.adjust-font-size .tier-1, +.winkwink-nudgenudge .tier-1, +.account-signin .tier-1 { + float: none; +} +.adjust-font-size .tier-1:hover > a, +.winkwink-nudgenudge .tier-1:hover > a, +.account-signin .tier-1:hover > a { + color: #555; + background-color: #caccce; +} +.adjust-font-size .subnav, +.winkwink-nudgenudge .subnav, +.account-signin .subnav { + background-color: #caccce; +} +.adjust-font-size .subnav a, +.winkwink-nudgenudge .subnav a, +.account-signin .subnav a { + color: #555; +} +.adjust-font-size .subnav a:hover, +.adjust-font-size .subnav a:focus, +.winkwink-nudgenudge .subnav a:hover, +.winkwink-nudgenudge .subnav a:focus, +.account-signin .subnav a:hover, +.account-signin .subnav a:focus { + color: #e6e8ea; + background-color: #999; +} +.touch .adjust-font-size .subnav a .tier-2, +.touch .winkwink-nudgenudge .subnav a .tier-2, +.touch .account-signin .subnav a .tier-2 { + padding-top: 0.75em; + padding-bottom: 0.6em; +} +.adjust-font-size .subnav .text-reset, +.winkwink-nudgenudge .subnav .text-reset, +.account-signin .subnav .text-reset { + color: #888; +} +.touch .adjust-font-size .subnav, +.touch .winkwink-nudgenudge .subnav, +.touch .account-signin .subnav { + top: 135%; + border: 3px solid #666; +} +.touch .adjust-font-size .subnav:before, +.touch .winkwink-nudgenudge .subnav:before, +.touch .account-signin .subnav:before { + top: -1.6em; + border-color: transparent transparent #666 transparent; +} +.adjust-font-size :hover .subnav, +.winkwink-nudgenudge :hover .subnav, +.account-signin :hover .subnav { + display: block; +} +.account-signin { + display: none; +} +.account-signin-authenticated { + display: inline-block; +} +.psf .account-signin, +.jobs .account-signin { + display: inline-block; +} +#site-map-link, +.adjust-font-size .tier-1 > a, +.winkwink-nudgenudge .tier-1 > a, +.account-signin .tier-1 > a { + padding: 1em 1em 0.875em; +} +.main-navigation { + display: none; + margin-bottom: 1px; +} +.header-banner { + clear: both; + margin: 0 1em; + position: relative; +} +.header-banner img { + display: block; + margin: 0 auto; +} +.header-banner p { + color: #e6e8ea; +} +.header-banner a:not(.button), +.header-banner a:not(.readmore) { + color: #ffd343; +} +.header-banner a:not(.button):hover, +.header-banner a:not(.button):focus, +.header-banner a:not(.readmore):hover, +.header-banner a:not(.readmore):focus { + color: #fff; +} +.home .slideshow { + margin: 0 auto; + max-width: 61.25em; + background: #1e2933; + -moz-box-shadow: inset 0 0 30px rgba(0, 0, 0, 0.6); + -webkit-box-shadow: inset 0 0 30px rgba(0, 0, 0, 0.6); + box-shadow: inset 0 0 30px rgba(0, 0, 0, 0.6); +} +.slide-code, +.slide-copy { + text-align: left; +} +.slide-code { + overflow: auto; + padding: 1.25em 1.5em; +} +.slide-code code { + display: inline-block; + color: #11a611; +} +.slide-code code .comment { + color: #666; +} +.slide-code code .output { + color: #ddd; +} +.js .launch-shell, +.no-js .launch-shell { + display: none; +} +.slide-copy { + background: #1c3b56; + padding: 1.25em 2.5em; +} +.slide-copy h1 { + color: #ffd343; + font-size: 1.3125em; + font-weight: 700; + font-family: "Source Sans Pro", Arial, sans-serif; +} +#dive-into-python .flex-control-paging { + position: absolute; + bottom: 0; + left: 50%; + padding: 0 0 1em; + margin-left: 0; + width: 50%; + max-width: 30.75em; +} +#dive-into-python .flex-control-paging a { + filter: alpha(opacity=70); + opacity: 0.7; +} +#dive-into-python .flex-control-paging a:hover, +#dive-into-python .flex-control-paging a:focus { + filter: progid:DXImageTransform.Microsoft.Alpha(enabled=false); + opacity: 1; +} +#dive-into-python .flex-control-paging .flex-active { + color: #ffd343 !important; + filter: progid:DXImageTransform.Microsoft.Alpha(enabled=false); + opacity: 1; +} +.introduction { + color: #caccce; + font-size: 1.25em; + text-align: left; + padding: 0.25em 0.5em; + margin-top: 0.875em; + margin-bottom: 0.875em; +} +.introduction p { + line-height: 1.4em; + margin-bottom: 0; +} +.introduction a, +.introduction a:link, +.introduction a:visited { + color: #ffd343; + text-decoration: underline; +} +.introduction a:hover, +.introduction a:focus, +.introduction a:link:hover, +.introduction a:link:focus, +.introduction a:visited:hover, +.introduction a:visited:focus { + color: #fff; +} +.introduction .breaker { + display: none; +} +.about-banner, +.download-for-current-os, +.documentation-banner, +.latest-blog-post, +.featured-event, +.jobs-intro { + text-align: left; +} +.call-to-action { + color: #ffd343; + font-size: 1.125em; + line-height: 1.25em; + margin-top: 0.4375em; + margin-bottom: 0.4375em; +} +.call-to-action a { + color: #ffd343; + border-bottom: 2px dotted #3776ab; + line-height: 1.35em; +} +.call-to-action a:hover, +.call-to-action a:focus { + color: #e6e8ea; +} +.content-wrapper { + padding: 0; + background-color: #f9f9f9; + *zoom: 1; + filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#FFFCFCFC',endColorstr='#FFF9F9F9'); + background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiNmY2ZjZmMiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iI2Y5ZjlmOSIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=="); + background-size: 100%; + background-image: -webkit-gradient( + linear, + 50% 0, + 50% 100%, + color-stop(10%, #fcfcfc), + color-stop(90%, #f9f9f9) + ); + background-image: -moz-linear-gradient(#fcfcfc 10%, #f9f9f9 90%); + background-image: -webkit-linear-gradient(#fcfcfc 10%, #f9f9f9 90%); + background-image: linear-gradient(#fcfcfc 10%, #f9f9f9 90%); +} +.content-wrapper .container { + padding: 0.25em; +} +.main-content { + padding-bottom: 1.75em; +} +.main-content > article { + margin-top: 1.3125em; + padding-bottom: 1.75em; +} +.page-title { + color: #666; + word-spacing: 0.15em; + font-size: 2em; +} +.fontface .page-title { + font-size: 2.3em; +} +.fontface .page-title span:before { + font-size: 0.875em; +} +.event-form .page-title { + margin-top: 0 !important; +} +.default-title { + word-spacing: 0.15em; +} +.text { + font-size: 1em; +} +.text .giga, +.text .mega, +.text .kilo { + color: #3776ab; +} +.sidebar-widget { + padding-bottom: 1.3125em; +} +.text h1, +.sidebar-widget h1 { + margin-top: 1em; + margin-bottom: 0.25em; +} +.text .default-title, +.text .page-title, +.sidebar-widget .default-title, +.sidebar-widget .page-title { + margin-top: 1.3125em; + margin-bottom: 0.875em; +} +.text p, +.text pre, +.text ul, +.text ol, +.text dl, +.text blockquote, +.text address, +.text form, +.text table, +.text figure, +.sidebar-widget p, +.sidebar-widget pre, +.sidebar-widget ul, +.sidebar-widget ol, +.sidebar-widget dl, +.sidebar-widget blockquote, +.sidebar-widget address, +.sidebar-widget form, +.sidebar-widget table, +.sidebar-widget figure { + margin-bottom: 1.3125em; + line-height: 1.875; +} +.text p, +.text dd, +.text blockquote, +.text address, +.sidebar-widget p, +.sidebar-widget dd, +.sidebar-widget blockquote, +.sidebar-widget address { + -webkit-hyphens: auto; + -moz-hyphens: auto; + -ms-hyphens: auto; + -o-hyphens: auto; + hyphens: auto; +} +.text p tt, +.text p var, +.text p code, +.text p kbd, +.text p abbr, +.text p acronym, +.text dd tt, +.text dd var, +.text dd code, +.text dd kbd, +.text dd abbr, +.text dd acronym, +.text blockquote tt, +.text blockquote var, +.text blockquote code, +.text blockquote kbd, +.text blockquote abbr, +.text blockquote acronym, +.text address tt, +.text address var, +.text address code, +.text address kbd, +.text address abbr, +.text address acronym, +.sidebar-widget p tt, +.sidebar-widget p var, +.sidebar-widget p code, +.sidebar-widget p kbd, +.sidebar-widget p abbr, +.sidebar-widget p acronym, +.sidebar-widget dd tt, +.sidebar-widget dd var, +.sidebar-widget dd code, +.sidebar-widget dd kbd, +.sidebar-widget dd abbr, +.sidebar-widget dd acronym, +.sidebar-widget blockquote tt, +.sidebar-widget blockquote var, +.sidebar-widget blockquote code, +.sidebar-widget blockquote kbd, +.sidebar-widget blockquote abbr, +.sidebar-widget blockquote acronym, +.sidebar-widget address tt, +.sidebar-widget address var, +.sidebar-widget address code, +.sidebar-widget address kbd, +.sidebar-widget address abbr, +.sidebar-widget address acronym { + -webkit-hyphens: none; + -moz-hyphens: none; + -ms-hyphens: none; + -o-hyphens: none; + hyphens: none; +} +.text li > ul, +.text li > ol, +.sidebar-widget li > ul, +.sidebar-widget li > ol { + margin-bottom: 0; +} +.text li, +.sidebar-widget li { + line-height: 1.65em; + margin: 0.2625em 0; +} +.text blockquote, +.sidebar-widget blockquote { + padding-left: 3em; + padding-right: 1em; +} +.text form, +.sidebar-widget form { + line-height: 1.625em; + margin-bottom: 1.3125em; +} +.text form button, +.text form input[type="submit"], +.sidebar-widget form button, +.sidebar-widget form input[type="submit"] { + font-size: 1.125em; + padding: 0.4em 1em 0.35em; +} +.text a:not(.button), +.sidebar-widget a:not(.button) { + display: inline; +} +.text nav a, +.text .menu a, +.text form ul a, +form .text ul a, +.text .errorlist a, +.text form label + ul a, +.text .sidebar-widget form label + ul a, +.sidebar-widget form .text label + ul a, +.text input[type="submit"], +.text input[type="reset"], +.text input[type="button"], +.text button, +.text .prompt, +.text .readmore:before, +.text .give-me-more a:before, +.give-me-more .text a:before, +.text nav a:hover, +.text .menu a:hover, +.text form ul a:hover, +form .text ul a:hover, +.text .errorlist a:hover, +.text form label + ul a:hover, +.text .sidebar-widget form label + ul a:hover, +.sidebar-widget form .text label + ul a:hover, +.text input[type="submit"]:hover, +.text input[type="reset"]:hover, +.text input[type="button"]:hover, +.text .prompt:hover, +.text .readmore:hover:before, +.text .give-me-more a:hover:before, +.give-me-more .text a:hover:before, +.text nav a:focus, +.text .menu a:focus, +.text form ul a:focus, +form .text ul a:focus, +.text .errorlist a:focus, +.text form label + ul a:focus, +.text .sidebar-widget form label + ul a:focus, +.sidebar-widget form .text label + ul a:focus, +.text input[type="submit"]:focus, +.text input[type="reset"]:focus, +.text input[type="button"]:focus, +.text .prompt:focus, +.text .readmore:focus:before, +.text .give-me-more a:focus:before, +.give-me-more .text a:focus:before, +.sidebar-widget nav a, +.sidebar-widget .menu a, +.sidebar-widget form ul a, +form .sidebar-widget ul a, +.sidebar-widget .errorlist a, +.sidebar-widget .text form label + ul a, +.text form .sidebar-widget label + ul a, +.sidebar-widget form label + ul a, +.sidebar-widget input[type="submit"], +.sidebar-widget input[type="reset"], +.sidebar-widget input[type="button"], +.sidebar-widget button, +.sidebar-widget .prompt, +.sidebar-widget .readmore:before, +.sidebar-widget .give-me-more a:before, +.give-me-more .sidebar-widget a:before, +.sidebar-widget nav a:hover, +.sidebar-widget .menu a:hover, +.sidebar-widget form ul a:hover, +form .sidebar-widget ul a:hover, +.sidebar-widget .errorlist a:hover, +.sidebar-widget .text form label + ul a:hover, +.text form .sidebar-widget label + ul a:hover, +.sidebar-widget form label + ul a:hover, +.sidebar-widget input[type="submit"]:hover, +.sidebar-widget input[type="reset"]:hover, +.sidebar-widget input[type="button"]:hover, +.sidebar-widget .prompt:hover, +.sidebar-widget .readmore:hover:before, +.sidebar-widget .give-me-more a:hover:before, +.give-me-more .sidebar-widget a:hover:before, +.sidebar-widget nav a:focus, +.sidebar-widget .menu a:focus, +.sidebar-widget form ul a:focus, +form .sidebar-widget ul a:focus, +.sidebar-widget .errorlist a:focus, +.sidebar-widget .text form label + ul a:focus, +.text form .sidebar-widget label + ul a:focus, +.sidebar-widget form label + ul a:focus, +.sidebar-widget input[type="submit"]:focus, +.sidebar-widget input[type="reset"]:focus, +.sidebar-widget input[type="button"]:focus, +.sidebar-widget .prompt:focus, +.sidebar-widget .readmore:focus:before, +.sidebar-widget .give-me-more a:focus:before, +.give-me-more .sidebar-widget a:focus:before { + border-bottom: 0; +} +.text figcaption, +.sidebar-widget figcaption { + font-style: italic; + font-size: 0.875em; +} +.text abbr[title], +.text dfn[title], +.sidebar-widget abbr[title], +.sidebar-widget dfn[title] { + border-bottom: 1px dotted #3776ab; +} +.text abbr[title], +.sidebar-widget abbr[title] { + font-size: 0.875em; + text-transform: uppercase; + letter-spacing: 0.125em; +} +.text var, +.sidebar-widget var { + color: #222; + font-size: 104%; + font-weight: 700; +} +.text code, +.text kbd, +.text samp, +.sidebar-widget code, +.sidebar-widget kbd, +.sidebar-widget samp { + display: inline-block; +} +.text code, +.text samp, +.sidebar-widget code, +.sidebar-widget samp { + border: 0; +} +.text samp, +.sidebar-widget samp { + border-bottom: 1px solid #caccce; + background-color: #e6e8ea; + padding: 0.125em 0.375em 0; + margin: 0 0.25em; +} +.text code, +.text kbd, +.sidebar-widget code, +.sidebar-widget kbd { + padding: 0.125em 0.375em 0; + margin: 0 -0.0625em; + background: #e6e8ea; + background: rgba(230, 232, 234, 0.5); + -moz-box-shadow: 0 0 0.5em rgba(0, 0, 0, 0.1) inset; + -webkit-box-shadow: 0 0 0.5em rgba(0, 0, 0, 0.1) inset; + box-shadow: 0 0 0.5em rgba(0, 0, 0, 0.1) inset; + -moz-border-radius: 6px; + -webkit-border-radius: 6px; + border-radius: 6px; +} +.text pre, +.sidebar-widget pre { + padding: 0.5em; + border-left: 5px solid #11a611; + background: #e6e8ea; + -moz-box-shadow: 0 0 0.5em rgba(0, 0, 0, 0.1) inset; + -webkit-box-shadow: 0 0 0.5em rgba(0, 0, 0, 0.1) inset; + box-shadow: 0 0 0.5em rgba(0, 0, 0, 0.1) inset; +} +.text pre code, +.sidebar-widget pre code { + display: block; + padding: 0; + margin: 0; + -moz-box-shadow: 0; + -webkit-box-shadow: 0; + box-shadow: 0; + -moz-border-radius: 0; + -webkit-border-radius: 0; + border-radius: 0; +} +.text s, +.text strike, +.text del, +.sidebar-widget s, +.sidebar-widget strike, +.sidebar-widget del { + color: #999; +} +table caption { + caption-side: top; + color: #444; + font-size: 1.125em; + text-align: left; + margin-bottom: 1.75em; +} +table thead, +table tfoot { + border-bottom: 1px solid #ddd; +} +table tr { + background-color: #f6f6f6; +} +table tr th { + background-color: #f0f0f0; +} +table tr:nth-of-type(even), +table tr.even { + background-color: #f0f0f0; +} +table th, +table td { + padding: 0.25em 0.5em 0.2em; + border-left: 2px solid #fff; +} +table th:first-child, +table td:first-child { + border-left: none; +} +table tfoot { + border-top: 1px solid #ddd; +} +.row-title { + border-top: 5px solid #d4dbe1; + padding: 0.75em 1em 0.5em; +} +.small-widget, +.download-list-widget, +.active-release-list-widget, +.most-recent-events, +.triple-widget, +.most-recent-posts, +.medium-widget, +.sidebar-widget { + border-top: 5px solid #e6e8ea; + padding: 1.25em; +} +.small-widget h4, +.download-list-widget h4, +.active-release-list-widget h4, +.most-recent-events h4, +.triple-widget h4, +.most-recent-posts h4, +.medium-widget h4, +.sidebar-widget h4 { + border-top: 1px solid #e6e8ea; + margin-top: 1.75em; + padding-top: 0.5em; +} +.small-widget p, +.download-list-widget p, +.active-release-list-widget p, +.most-recent-events p, +.triple-widget p, +.most-recent-posts p, +.medium-widget p, +.sidebar-widget p, +.small-widget ul, +.download-list-widget ul, +.active-release-list-widget ul, +.most-recent-events ul, +.triple-widget ul, +.most-recent-posts ul, +.medium-widget ul, +.sidebar-widget ul { + margin-bottom: 0.875em; +} +.small-widget p:last-child, +.download-list-widget p:last-child, +.active-release-list-widget p:last-child, +.most-recent-events p:last-child, +.triple-widget p:last-child, +.most-recent-posts p:last-child, +.medium-widget p:last-child, +.sidebar-widget p:last-child, +.small-widget ul:last-child, +.download-list-widget ul:last-child, +.active-release-list-widget ul:last-child, +.most-recent-events ul:last-child, +.triple-widget ul:last-child, +.most-recent-posts ul:last-child, +.medium-widget ul:last-child, +.sidebar-widget ul:last-child { + margin-bottom: 0; +} +.small-widget li > a, +.download-list-widget li > a, +.active-release-list-widget li > a, +.most-recent-events li > a, +.triple-widget li > a, +.most-recent-posts li > a, +.medium-widget li > a, +.sidebar-widget li > a { + display: inline-block; +} +.widget-title, +.listing-company { + color: #444; + line-height: 1.25em; + margin: 0 0 0.1em; + font-family: Flux, "Source Sans Pro", Arial, sans-serif; + font-size: 1.3125em; +} +.fontface .widget-title, +.fontface .listing-company { + font-size: 1.50938em; +} +.fontface .widget-title span:before, +.fontface .listing-company span:before { + font-size: 0.875em; +} +.widget-title .prompt, +.widget-title .readmore:before, +.widget-title .give-me-more a:before, +.give-me-more .widget-title a:before, +.listing-company .prompt, +.listing-company .readmore:before, +.listing-company .give-me-more a:before, +.give-me-more .listing-company a:before { + display: none; +} +.widget-title > span, +.listing-company > span { + margin-right: 0.25em; +} +.widget-title > span:before, +.listing-company > span:before { + color: #999; +} +.python .small-widget, +.python .download-list-widget, +.python .active-release-list-widget, +.python .most-recent-events, +.python .triple-widget, +.python .most-recent-posts, +.python .medium-widget, +.python .sidebar-widget { + border-top: 4px solid #75a8d3; +} +.psf-home .small-widget, +.psf-home .download-list-widget, +.psf-home .active-release-list-widget, +.psf-home .most-recent-events, +.psf-home .triple-widget, +.psf-home .most-recent-posts, +.psf-home .medium-widget, +.psf-home .sidebar-widget { + border-top: 5px solid #caccce; +} +.docs .small-widget, +.docs .download-list-widget, +.docs .active-release-list-widget, +.docs .most-recent-events, +.docs .triple-widget, +.docs .most-recent-posts, +.docs .medium-widget, +.docs .sidebar-widget { + border-top: 5px solid #ffd343; +} +.pypl .small-widget, +.pypl .download-list-widget, +.pypl .active-release-list-widget, +.pypl .most-recent-events, +.pypl .triple-widget, +.pypl .most-recent-posts, +.pypl .medium-widget, +.pypl .sidebar-widget { + border-top: 5px solid #82b043; +} +.jobs .small-widget, +.jobs .download-list-widget, +.jobs .active-release-list-widget, +.jobs .most-recent-events, +.jobs .triple-widget, +.jobs .most-recent-posts, +.jobs .medium-widget, +.jobs .sidebar-widget { + border-top: 5px solid #c9abcd; +} +.shop .small-widget, +.shop .download-list-widget, +.shop .active-release-list-widget, +.shop .most-recent-events, +.shop .triple-widget, +.shop .most-recent-posts, +.shop .medium-widget, +.shop .sidebar-widget { + border-top: 5px solid #b55863; +} +.python .widget-title > span:before, +.python .listing-company > span:before { + color: #3776ab; +} +.psf .widget-title > span:before, +.psf .listing-company > span:before { + color: #78797a; +} +.docs .widget-title > span:before, +.docs .listing-company > span:before { + color: #ffd343; +} +.pypl .widget-title > span:before, +.pypl .listing-company > span:before { + color: #82b043; +} +.jobs .widget-title > span:before, +.jobs .listing-company > span:before { + color: #a06ba7; +} +.shop .widget-title > span:before, +.shop .listing-company > span:before { + color: #b55863; +} +.download-widget p:last-child a { + white-space: nowrap; +} +.time-posted { + display: block; + font-size: 0.875em; + font-style: italic; + margin-bottom: 0.75em; +} +.blog-name { + display: block; + font-weight: 700; + font-family: "Source Sans Pro", Arial, sans-serif; + letter-spacing: 0.01em; +} +.success-stories-widget blockquote { + color: #666; + background-color: #ffe590; + padding: 0.7em 1em 0.875em; + margin-bottom: 0.4375em; + font-size: 1em; + line-height: 1.75em; + background-color: #ffdf76; + *zoom: 1; + filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#FFFFE590',endColorstr='#FFFFDF76'); + background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiNmZmU1OTAiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iI2ZmZGY3NiIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=="); + background-size: 100%; + background-image: -webkit-gradient( + linear, + 50% 0, + 50% 100%, + color-stop(10%, #ffe590), + color-stop(90%, #ffdf76) + ); + background-image: -moz-linear-gradient(#ffe590 10%, #ffdf76 90%); + background-image: -webkit-linear-gradient(#ffe590 10%, #ffdf76 90%); + background-image: linear-gradient(#ffe590 10%, #ffdf76 90%); + -moz-border-radius: 6px; + -webkit-border-radius: 6px; + border-radius: 6px; +} +.success-stories-widget blockquote:after { + position: absolute; + content: ""; + width: 0; + height: 0; + border-color: transparent; + border-style: solid; + border-width: 1.5em; + left: 20%; + bottom: -2.875em; + border-top-color: #ffdf76; +} +.success-stories-widget blockquote a { + color: #666; +} +.success-stories-widget blockquote a:hover, +.success-stories-widget blockquote a:focus, +.success-stories-widget blockquote a:active { + color: #3776ab; +} +.success-stories-widget .quote-from td { + padding: 0.5em; + vertical-align: middle; +} +.success-stories-widget .quote-from img { + max-height: 5em; +} +.success-stories-widget .quote-from p { + font-size: 0.875em; +} +.applications-widget { + padding-left: 0.75em; +} +.applications-widget ul { + border-top: 1px solid #caccce; +} +.applications-widget li { + padding: 0.5em 0 0.4em; + border-bottom: 1px solid #caccce; +} +.shrubbery { + position: relative; +} +.shrubbery .give-me-more { + color: #caccce; + display: none; + position: absolute; + top: 0.25em; + right: 0.25em; +} +.shrubbery .give-me-more a { + color: #999; +} +.shrubbery .give-me-more a:hover, +.shrubbery .give-me-more a:active { + color: #666; +} +.draft-preview { + color: #b55863; + font-weight: 700; + font-family: "Source Sans Pro", Arial, sans-serif; +} +.pep-widget { + margin-bottom: 1.3125em; +} +.pep-widget .widget-title { + color: #737373; + margin-bottom: 0.35em; + font-size: 1.125em; +} +.fontface .pep-widget .widget-title { + font-size: 1.29375em; +} +.fontface .pep-widget .widget-title span:before { + font-size: 0.875em; +} +.pep-widget .widget-title a { + color: #3776ab; +} +.pep-widget .widget-title a:hover, +.pep-widget .widget-title a:active { + color: #1f3b47; +} +.pep-widget .pep-number { + color: #666; + font-weight: 700; + font-family: "Source Sans Pro", Arial, sans-serif; + display: inline-block; + width: 3em; +} +.pep-list { + border-top: 1px solid #caccce; + line-height: 1.2em; + margin: 0; +} +.pep-list li { + display: block; + line-height: 1.35em; +} +.pep-list li a { + display: block; + color: #3776ab; + background-color: #f2f4f6; + border-bottom: 1px solid #e6eaee; + padding: 0.6em 0.75em 0.5em; +} +.pep-list li a:hover, +.pep-list li a:focus, +.pep-list li a:active { + color: #222; + background-color: #fefefe; +} +.rss-link { + line-height: 1em; +} +.rss-link span:before { + color: #cc9547; +} +.pep-list-header { + font-weight: 700; + font-family: "Source Sans Pro", Arial, sans-serif; + display: none; +} +.pep-index-list { + margin-bottom: 2.625em; +} +.pep-index-list .label { + font-weight: 700; + font-family: "Source Sans Pro", Arial, sans-serif; + display: inline-block; + width: 20%; +} +.pep-index-list li { + background-color: #f2f4f6; + border-bottom: 1px solid #caccce; +} +.pep-index-list a { + display: inline-block; + color: #3776ab; +} +.pep-index-list a:hover, +.pep-index-list a:focus, +.pep-index-list a:active { + color: #222; +} +.pep-type, +.pep-num, +.pep-title, +.pep-owner { + padding: 0.5em 0.5em 0.4em; + border-bottom: 1px solid #e3e7ec; +} +.footnote .label { + width: 4em; +} +.info-key dt, +.info-key dd { + display: block; + float: left; + padding: 0.5em 0.5em 0.4em; +} +.info-key dt { + width: 25%; +} +.info-key dd { + width: 75%; + border-bottom: 1px solid #e6e8ea; +} +.pep-owner-header { + margin: 0 -0.5em; + overflow: hidden; + *zoom: 1; +} +.pep-owner-header .label { + font-weight: 700; + font-family: "Source Sans Pro", Arial, sans-serif; + float: left; + width: 50%; + padding: 0.25em 0.5em 0.2em; +} +.pep-owner-list li { + background-color: #f2f4f6; + border-bottom: 1px solid #caccce; + overflow: hidden; + *zoom: 1; +} +.pep-owner-list li:hover { + background-color: #fefefe; +} +.pep-owner-list .owner-name, +.pep-owner-list .owner-email { + float: left; + width: 50%; + padding: 0.5em 0.5em 0.4em; +} +.featured-success-story { + padding: 1.3125em 0; + background: center -230px no-repeat url(../img/success-glow2.png?1576869008) transparent; +} +.featured-success-story img { + padding: 10px 30px; +} +.featured-success-story .success-quote { + color: #ffd343; + font-size: 1.625em; + line-height: 1.5; + position: static; + text-shadow: 0 0 4px rgba(0, 0, 0, 0.5); +} +.featured-success-story .success-quote:before, +.featured-success-story .success-quote:after { + color: #4f90c6; + font-style: normal; + font-size: 2em; + line-height: 0; + vertical-align: text-bottom; + position: static; +} +.featured-success-story .success-quote:before { + content: "“"; + top: auto; + left: auto; + margin-left: -0.2em; +} +.featured-success-story .success-quote:after { + content: "”"; + bottom: auto; + right: auto; + margin-right: -0.2em; +} +a.activity-feed { + border-bottom: 0; + font-size: 0.75em; +} +a.activity-feed span { + margin-right: 0.25em; +} +p.quote-by { + color: #e6e8ea; + margin-bottom: 0; +} +p.quote-by-organization { + color: #e6e8ea; +} +.newest-success-stories { + padding-top: 1.3125em; +} +.newest-success-stories .widget-title { + position: relative; +} +.story-header { + background-color: #f2f4f6; + margin: -1.3em 0 0; + overflow: hidden; + max-height: 24em; + border-bottom: 3px solid #ffd343; +} +.story-header img { + display: block; + margin: 0 auto; + min-width: 100%; +} +.welcome-message { + font-family: "Source Sans Pro", Arial, sans-serif; + font-size: 1.125em; + color: #ffc710; + margin-top: 0; + margin-bottom: 0.875em; +} +.fontface .welcome-message { + font-size: 1.125em; +} +.latest-blog-post .date-posted, +.latest-blog-post .event-date, +.featured-event .date-posted, +.featured-event .event-date { + color: #a8a8a8; +} +.latest-blog-post p.excerpt, +.featured-event p.excerpt { + max-width: none; +} +.latest-blog-post .readmore, +.featured-event .readmore { + color: #ffd343; +} +.latest-blog-post .readmore:hover, +.latest-blog-post .readmore:focus, +.featured-event .readmore:hover, +.featured-event .readmore:focus { + color: #fff; +} +.most-recent-posts li time { + position: relative; +} +.just-missed { + color: #3776ab; + margin-top: 1.3125em; +} +.list-recent-events, +.list-recent-posts { + border-top: 1px solid #ddd; +} +.list-recent-events li, +.list-recent-posts li { + position: relative; + border-bottom: 1px solid #ddd; + padding: 0 0 0.75em; +} +.list-recent-events li .date-start, +.list-recent-events li .date-end, +.list-recent-events li .single-date, +.list-recent-events li .time-start, +.list-recent-events li .time-end, +.list-recent-events li .year, +.list-recent-posts li .date-start, +.list-recent-posts li .date-end, +.list-recent-posts li .single-date, +.list-recent-posts li .time-start, +.list-recent-posts li .time-end, +.list-recent-posts li .year { + position: relative; + top: 0; +} +.list-recent-events .event-title, +.list-recent-posts .event-title { + font-size: 1.25em; + line-height: 1.3em; + margin-top: 0.4375em; +} +.single-event-date { + margin-top: 0.75em; + margin-bottom: 1.25em; + padding: 0.5em 0.75em; +} +.event-description { + padding: 1.3125em 0; +} +.more-by-location { + margin-bottom: 0; +} +.community-success-stories blockquote { + padding: 0; + color: #666; + line-height: 1.5; +} +.community-success-stories blockquote:before { + content: ""; +} +.python-weekly { + background-color: #f2f4f6; + -moz-border-radius: 0 0 8px 8px; + -webkit-border-radius: 0; + border-radius: 0 0 8px 8px; + padding: 0.75em 1em; +} +.twitter-stream li { + background-color: #f2f4f6; + line-height: 1.3; + padding: 0.5em; + margin-bottom: 0.25em; +} +.twitter-stream li .view-on-twitter { + font-weight: 700; + font-family: "Source Sans Pro", Arial, sans-serif; + font-size: 0.85714em; +} +.twitteruser { + font-weight: 700; + font-family: "Source Sans Pro", Arial, sans-serif; +} +.twittermention { + color: #3776ab; +} +.mapped-events { + border-top: 3px solid #e6e8ea; +} +.mapped-events .medium-widget { + border-top: 0; +} +.tag-wrapper { + display: block; +} +.tag-wrapper .tag { + white-space: nowrap; + color: #666; + font-size: 0.875em; + vertical-align: baseline; + padding: 0.2em 0.4em 0.1em; + background-color: #e6e8ea; + border-top: 1px solid #f2f4f6; + border-bottom: 1px solid #caccce; +} +.tag-wrapper .tag:hover, +.tag-wrapper .tag:focus { + color: #444; + background-color: #d0d4d7; + border-top: 1px solid #dae0e5; + border-bottom: 1px solid #b5b8ba; +} +.git-avatar, +.git-repo { + display: inline-block; + vertical-align: bottom; +} +.git-avatar { + margin-right: 0.5em; +} +.git-repo { + padding-bottom: 0.25em; +} +.list-row-headings { + font-weight: 700; + font-family: "Source Sans Pro", Arial, sans-serif; + padding: 0.5em 0.5em 0.4em 0.75em; + margin-right: 1.25em; +} +.list-row-container { + border: 1px solid #caccce; +} +.list-row-container li { + padding: 0.5em 0.5em 0.4em 0.75em; + margin-right: 0; +} +.list-row-container li:nth-child(odd) { + background-color: #f2f4f6; +} +.pagination, +.previous-next { + display: block; + width: 100%; + text-align: center; + padding-top: 1.3125em; +} +.pagination li { + line-height: 2; + display: -moz-inline-stack; + display: inline-block; + vertical-align: baseline; +} +.lt-ie8 .pagination li { + vertical-align: auto; + zoom: 1; + display: inline; +} +.pagination a:hover, +.pagination a:focus { + color: #333; + background-color: #ffd343; +} +.pagination a.active { + color: #e6e8ea; + background-color: #3776ab; +} +.pagination a.disabled, +.pagination a.disabled:hover, +.pagination a.disabled:focus { + color: #caccce; + background-color: transparent; +} +.pagination .previous a, +.pagination .next a, +.pagination .previous a:hover, +.pagination .next a:hover, +.pagination .previous a:focus, +.pagination .next a:focus { + border: 0; +} +.previous-next .prev-button, +.previous-next .next-button { + display: block; + padding: 0.5em 0.75em 0.4em; + margin-bottom: 0.875em; +} +.previous-next .prev-button:not(.disabled):hover, +.previous-next .prev-button:not(.disabled):focus, +.previous-next .next-button:not(.disabled):hover, +.previous-next .next-button:not(.disabled):focus { + color: #333; + background-color: #ffd343; +} +.previous-next .prev-button-text, +.previous-next .next-button-text { + display: block; + border-bottom: 1px solid #caccce; + padding-bottom: 0.5em; +} +.previous-next .prevnext-description { + display: block; + padding-top: 0.5em; +} +.previous-next .disabled .prev-button-text, +.previous-next .disabled .next-button-text { + color: #caccce; + border-bottom: 0; +} +.previous-next .icon-arrow-right, +.previous-next .icon-arrow-left { + vertical-align: bottom; +} +.single-event .previous-next { + margin-top: 1.3125em; + border-top: 1px solid #caccce; +} +.release-number, +.release-date, +.release-download, +.release-enhancements { + display: block; +} +.release-number { + font-weight: 700; + font-family: "Source Sans Pro", Arial, sans-serif; +} +.release-version, +.release-status, +.release-start, +.release-end, +.release-pep { + display: block; +} +.release-version { + font-weight: 700; + font-family: "Source Sans Pro", Arial, sans-serif; +} +.active-release-list-widget .list-row-headings, +.active-release-list-widget .list-row-container li { + font-size: 0.875em; +} +.active-release-list-widget .list-row-container { + margin-bottom: 0.5em; +} +.download-list-widget .list-row-headings, +.download-list-widget .list-row-container li { + font-size: 0.875em; +} +.download-list-widget .list-row-container { + margin-bottom: 0.5em; +} +.no-touch .download-list-widget .list-row-container { + height: 16.75em; + overflow-y: scroll; +} +.main-content .psf-widget a:not(.button), +.main-content .python-needs-you-widget a:not(.button) { + color: #ffd343; +} +.main-content .psf-widget a:not(.button):hover, +.main-content .psf-widget a:not(.button):focus, +.main-content .python-needs-you-widget a:not(.button):hover, +.main-content .python-needs-you-widget a:not(.button):focus { + color: #fff1c3; +} +.psf-widget .widget-title, +.psf-widget .readmore, +.psf-widget .readmore:before, +.python-needs-you-widget .widget-title, +.python-needs-you-widget .readmore, +.python-needs-you-widget .readmore:before { + color: #ffd343; +} +.psf-widget .widget-title:hover, +.psf-widget .widget-title:focus, +.psf-widget .readmore:hover, +.psf-widget .readmore:focus, +.psf-widget .readmore:before:hover, +.psf-widget .readmore:before:focus, +.python-needs-you-widget .widget-title:hover, +.python-needs-you-widget .widget-title:focus, +.python-needs-you-widget .readmore:hover, +.python-needs-you-widget .readmore:focus, +.python-needs-you-widget .readmore:before:hover, +.python-needs-you-widget .readmore:before:focus { + color: #fff; +} +.psf-widget p, +.python-needs-you-widget p { + color: #caccce; +} +.psf-widget .click-these, +.python-needs-you-widget .click-these { + margin-bottom: 0; +} +.user-feedback { + padding: 0.75em 1em 0.65em; + margin-bottom: 1.3125em; + -moz-border-radius: 6px; + -webkit-border-radius: 6px; + border-radius: 6px; +} +.user-feedback p { + margin-bottom: 0; +} +.user-feedback a { + text-decoration: underline; +} +.user-feedback a:hover, +.user-feedback a:focus { + color: #222; +} +.level-general { + background-color: #e9f1f8; + border: 1px solid #c2d9ec; +} +.level-notice { + background-color: #fff7dc; + border: 2px solid #ffd343; +} +.level-notice span { + color: #dca900; +} +.level-error { + background-color: #ecd4d7; + border: 2px solid #b55863; +} +.level-error span { + color: #b55863; +} +.level-success { + background-color: #d6e7bf; + border: 2px solid #82b043; +} +.level-success span { + color: #82b043; + margin-right: 0.5em; +} +.left-sidebar .sidebar-widget { + margin-bottom: 0.875em; +} +.left-sidebar .twitter-widget { + padding: 0; +} +.left-sidebar .twtr-doc { + padding: 0.75em; +} +.jobs-form p { + padding: 0 0.3125em; +} +.jobs-form .required { + background-color: #f8f0f1; + padding-top: 0.625em; +} +.list-recent-jobs li { + padding: 0.875em 0.5em; +} +.listing-company .listing-new { + display: inline-block; + color: #fff; + background-color: #b55863; + font-size: 0.58333em; + text-transform: uppercase; + letter-spacing: 0.0625em; + padding: 0.45em 0.5em 0; + margin-right: 0.25em; +} +.listing-company .listing-removed { + display: inline-block; + color: #fff; + background-color: #666; + font-size: 0.58333em; + text-transform: uppercase; + letter-spacing: 0.0625em; + padding: 0.45em 0.5em 0; + margin-right: 0.25em; +} +.listing-company .listing-location a { + color: #999; +} +.listing-company .listing-location a:hover, +.listing-company .listing-location a:focus { + color: #3776ab; +} +.listing-company-category, +.listing-job-type, +.listing-posted { + clear: both; + display: block; +} +.listing-company .company-name { + font-size: 125%; +} +.job-post-meta { + clear: both; + border: 1px solid #caccce; + padding: 0.875em 0.5em; + overflow: hidden; + *zoom: 1; +} +.job-post-meta span { + display: block; +} +.job-post-meta .listing-actions { + border-top: 1px solid #caccce; + clear: both; + padding-top: 1.25em; + text-align: right; +} +.job-tags { + margin-bottom: 0; +} +.breadcrumbs { + padding: 0.5em 0; + border-bottom: 1px solid #caccce; +} +.breadcrumbs li { + display: -moz-inline-stack; + display: inline-block; + vertical-align: baseline; +} +.lt-ie8 .breadcrumbs li { + vertical-align: auto; + zoom: 1; + display: inline; +} +.breadcrumbs .prompt, +.breadcrumbs .readmore:before, +.breadcrumbs .give-me-more a:before, +.give-me-more .breadcrumbs a:before { + margin-left: 0.5em; +} +.section-navigation { + border-top: 3px solid #75a8d3; + background-color: #e1ecf5; + padding: 0.875em 0.75em 0.875em; +} +.section-navigation h2:first-child { + margin-top: 0.65625em; +} +.section-navigation h3:first-child { + margin-top: 0.65625em; +} +.section-nav a { + display: block; + padding: 0.3em 0 0.2em; +} +.psf-sidebar-widget { + color: #f2f4f6; + background-color: #3776ab; + *zoom: 1; + filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#FF2B5B84',endColorstr='#FF3776AB'); + background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiMyYjViODQiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iIzM3NzZhYiIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=="); + background-size: 100%; + background-image: -webkit-gradient( + linear, + 50% 0, + 50% 100%, + color-stop(10%, #2b5b84), + color-stop(90%, #3776ab) + ); + background-image: -moz-linear-gradient(#2b5b84 10%, #3776ab 90%); + background-image: -webkit-linear-gradient(#2b5b84 10%, #3776ab 90%); + background-image: linear-gradient(#2b5b84 10%, #3776ab 90%); +} +.psf-sidebar-widget .widget-title { + color: #ffd343; + margin-top: 0.4375em; +} +.psf-sidebar-widget .widget-title a { + color: #ffd343; +} +.psf-sidebar-widget .widget-title a:hover, +.psf-sidebar-widget .widget-title a:focus { + color: #fff; +} +.user-profile-controls { + border-bottom: 1px solid #caccce; + margin-bottom: 2em; +} +.user-profile-controls li { + display: -moz-inline-stack; + display: inline-block; + vertical-align: baseline; + margin-right: 0.75em; +} +.lt-ie8 .user-profile-controls li { + vertical-align: auto; + zoom: 1; + display: inline; +} +.user-profile-controls + .return-link { + margin-top: -1.3125em; +} +.return-link { + padding-bottom: 2.1875em; +} +.active-user-list .user-name, +.active-user-list .user-location, +.active-user-list .user-psfmember-status { + display: inline-block; + vertical-align: top; +} +.active-user-list .user-name { + width: 25%; +} +.active-user-list .user-location { + width: 40%; +} +.active-user-list .user-psfmember-status { + width: 25%; +} +.profile-label { + color: #999; +} +.psf-codeofconduct { + font-size: 0.875em; + padding: 0.5em 1em; + margin-bottom: 1em; + background-color: #fff; + -moz-box-shadow: 0.25em 0.25em 0.75em rgba(0, 0, 0, 0.15); + -webkit-box-shadow: 0.25em 0.25em 0.75em rgba(0, 0, 0, 0.15); + box-shadow: 0.25em 0.25em 0.75em rgba(0, 0, 0, 0.15); +} +.horizontal-menu { + padding-bottom: 1.3125em; +} +.horizontal-menu ul, +.horizontal-menu ol { + list-style: none; + margin-left: 0; +} +.horizontal-menu li { + margin-right: 1em; + display: -moz-inline-stack; + display: inline-block; + vertical-align: baseline; +} +.lt-ie8 .horizontal-menu li { + vertical-align: auto; + zoom: 1; + display: inline; +} +.main-footer .jump-link, +.sitemap a, +.footer-links a { + display: block; + text-align: center; + padding: 0.5em 0.75em 0.4em; +} +.main-footer { + clear: both; + color: #666; + background-color: #e6e8ea; + border-top: 1px solid #d8dbde; +} +.main-footer .container { + padding: 0 0.75em 0.75em; +} +.main-footer a { + color: #666; +} +.main-footer a:hover, +.main-footer a:focus { + color: #444; +} +.main-footer .jump-link { + background-color: #e0e3e5; +} +.main-footer a.jump-link { + margin: 0.75em 0; + border-top: 1px solid #e6e8ea; + border-bottom: 1px solid #dbdee1; +} +.main-footer a.jump-link:hover, +.main-footer a.jump-link:focus { + background-color: #dbdee1; + border-top: 1px solid #e0e3e5; + border-bottom: 1px solid #d5d9dc; +} +.sitemap { + padding-bottom: 0.5em; +} +.sitemap .tier-1 { + margin-bottom: 1.3125em; +} +.sitemap .tier-1 > a { + color: #3776ab; + padding: 0.4em 0.5em 0.3em; + font-weight: 700; + font-family: Flux, "Source Sans Pro", Arial, sans-serif; + font-size: 1.25em; + margin-top: 0.875em; + margin-bottom: 0; +} +.sitemap .tier-1 > a:hover, +.sitemap .tier-1 > a:focus { + color: #222; +} +.sitemap .subnav { + font-size: 1em; + margin-bottom: 0; + border-top: 1px solid #d5d6d8; + border-bottom: 1px solid #f7f7f8; +} +.sitemap .subnav li { + border-top: 1px solid #f7f7f8; + border-bottom: 1px solid #d5d6d8; +} +.sitemap .subnav a:hover, +.sitemap .subnav a:focus { + background-color: #ecedef; +} +.site-base { + border-top: 1px solid #111; +} +.site-base .container { + padding: 1em; +} +.footer-links { + margin-bottom: 0.5em; +} +.footer-links a { + color: #89b4d9; + font-weight: 700; + font-family: Flux, "Source Sans Pro", Arial, sans-serif; + font-size: 1.125em; +} +.fontface .footer-links a { + font-size: 1.29375em; +} +.fontface .footer-links a span:before { + font-size: 0.875em; +} +.footer-links a:hover, +.footer-links a:focus { + color: #fff7dc; + text-shadow: 0 0 5px rgba(255, 211, 67, 0.2); +} +.copyright { + clear: both; + color: #75a8d3; + font-size: 0.75em; + text-align: center; + margin-bottom: 0; +} +.copyright a { + border-bottom: 1px dotted #4f90c6; + color: #75a8d3; +} +.copyright a:hover, +.copyright a:focus { + color: #fff; + text-decoration: none; +} +#python-status-indicator { + border-radius: 99px; + display: inline-block; + height: 12px; + width: 12px; +} +.python-status-indicator-none { + background-color: #008000; +} +.python-status-indicator-minor { + background-color: #ff0; +} +.python-status-indicator-major { + background-color: #ffa500; +} +.python-status-indicator-critical { + background-color: #f00; +} +.python-status-indicator-default { + background-color: #808080; +} +div.note { + background-color: #eee; + border: 1px solid #ccc; + padding: 0.3125em 0.625em; + margin-bottom: 1.5625em; +} +div.note > p { + margin-bottom: 0; +} +p.admonition-title { + font-weight: bold; +} +p.admonition-title:after { + content: ":"; +} +div.warning, +form.deletion-form { + background-color: #ffe4e4; + border: 1px solid #f66; + padding: 0.3125em 0.625em; + margin-bottom: 1.5625em; +} +div.warning > p, +form.deletion-form > p { + margin-bottom: 0; +} +form.deletion-form { + border-radius: 0.625em; + padding: 0.9375em; +} +form.deletion-form button[type="submit"] { + margin-top: 0.625em; +} +form.deletion-form label { + color: #b55863; +} +div.sidebar { + margin: 0 0 0.5em 1em; + border: 1px solid #ddb; + padding: 0.4375em 0.4375em 0 0.4375em; + background-color: #ffe; + width: 40%; + float: right; +} +div.sidebar > p.sidebar-title { + font-size: 1em; + font-weight: bold; + margin-top: 0; +} +div.sidebar > p { + font-size: 0.9375em; + margin-top: 0.625em; + margin-bottom: 0; +} +img.align-right { + float: right; + margin-left: 1.25em; +} +span.highlighted { + background-color: yellow; +} +.text .flex-slideshow ul, +.text .flex-slideshow ol { + margin-bottom: 0; +} +.generatedcontent .text .flex-slideshow ul li:before { + content: ""; + display: none; +} +.loading .flex-slideshow { + opacity: 0; +} +.flex-slideshow { + position: relative; +} +.flex-slideshow .slides { + *zoom: 1; +} +.flex-slideshow .slides:after { + content: ""; + display: table; + clear: both; +} +.flex-slideshow .slides > li { + display: none; + -webkit-backface-visibility: hidden; +} +* html .flex-slideshow .slides { + height: 1%; +} +.no-js .flex-slideshow .slides > li:first-child { + display: block; +} +.flex-slideshow .slide-container { + position: relative; +} +.flex-slideshow .frame-wrapper { + margin-bottom: 0.75em; +} +.flex-slideshow .caption-wrapper h2 { + margin-top: 0; +} +.flex-slideshow .caption-wrapper p { + min-height: 1.75em; +} +.flex-control-nav li, +.flex-direction-nav li { + display: inline-block; +} +.flex-control-nav a, +.flex-direction-nav a { + cursor: pointer; + display: block; +} +.flex-control-nav { + text-align: center; + padding: 0 2.5em; +} +.flex-control-nav a { + font-size: 1em; + line-height: 1em; + color: #888; + margin-left: 0.5em; +} +.flex-control-nav a:hover, +.flex-control-nav a:focus { + color: #444; + background-color: #ccc; + border-color: #bbb; +} +.text .flex-control-nav a { + text-decoration: none; +} +.flex-control-nav .flex-active { + color: #666; + background-color: #fff; +} +.touch .flex-control-nav a { + padding: 0.5em 0.75em; +} +.flex-direction-nav { + height: 0; +} +.touch .flex-direction-nav { + display: none; +} +.flex-direction-nav .flex-prev, +.flex-direction-nav .flex-next { + position: absolute; + bottom: -0.25em; + font-size: 1.25em; + font-weight: bold; + line-height: 1em; + color: #999; +} +.flex-direction-nav .flex-prev:hover, +.flex-direction-nav .flex-prev:focus, +.flex-direction-nav .flex-next:hover, +.flex-direction-nav .flex-next:focus { + filter: progid:DXImageTransform.Microsoft.Alpha(enabled=false); + opacity: 1; +} +.text .flex-direction-nav .flex-prev, +.text .flex-direction-nav .flex-next { + text-decoration: none; +} +.flex-direction-nav .flex-prev { + left: 0; +} +.flex-direction-nav .flex-next { + right: 0; +} +.home-slideshow .flex-direction-nav .flex-prev, +.home-slideshow .flex-direction-nav .flex-next { + top: 33%; + bottom: auto; + filter: alpha(opacity=70); + opacity: 0.7; +} +.home-slideshow .flex-direction-nav .flex-prev:hover, +.home-slideshow .flex-direction-nav .flex-prev:focus, +.home-slideshow .flex-direction-nav .flex-next:hover, +.home-slideshow .flex-direction-nav .flex-next:focus { + filter: progid:DXImageTransform.Microsoft.Alpha(enabled=false); + opacity: 1; +} +.home-slideshow .flex-direction-nav .flex-prev { + left: 0.75em; +} +.home-slideshow .flex-direction-nav .flex-next { + right: 0.75em; +} +.home-slideshow .flex-direction-nav .flex-prev:hover, +.home-slideshow .flex-direction-nav .flex-next:hover { + background-color: #e6e8ea; +} +@media print { + .flex-control-nav, + .flex-direction-nav, + .flex-control-paging { + display: none; + } +} +#nojs, +#oldie-warning { + padding: 0.75em 0.75em 0.65em; + text-align: center; + background-color: #c33; +} +#nojs p, +#oldie-warning p { + color: #e6e6e6; + font-weight: bold; + margin: 0; +} +#nojs a, +#oldie-warning a { + color: #e6e6e6; + text-decoration: underline; +} +#nojs a:hover, +#nojs a:focus, +#oldie-warning a:hover, +#oldie-warning a:focus { + color: #fff; + text-decoration: none; +} +#oldie-warning { + background-color: #ff7; +} +#oldie-warning p { + color: #444; +} +#oldie-warning a { + color: #444; +} +#oldie-warning a:hover, +#oldie-warning a:focus { + color: #000; +} +.js #nojs { + display: none; +} +.ir { + display: block; + text-indent: -9999px; + overflow: hidden; + background-repeat: no-repeat; + text-align: left; + direction: ltr; +} +.hidden { + display: none; + visibility: hidden; +} +.screen-reader-text { + border: 0; + clip: rect(0 0 0 0); + height: 1px; + margin: -1px; + overflow: hidden; + padding: 0; + position: absolute; + width: 1px; +} +.screen-reader-text.focusable:active, +.screen-reader-text.focusable:focus { + clip: auto; + height: auto; + margin: 0; + overflow: visible; + position: static; + width: auto; +} +.invisible { + visibility: hidden; +} +@media print { + *, + *:before, + *:after { + background: transparent !important; + color: #000 !important; + box-shadow: none !important; + text-shadow: none !important; + } + body { + font-size: 10pt; + line-height: 1.67; + } + a, + a:visited { + text-decoration: underline !important; + } + *[role="main"] a[href]:after { + content: " (" attr(href) ")"; + font-size: 75%; + } + *[role="main"] abbr[title]:after { + content: " (" attr(title) ")"; + font-size: 75%; + } + .ir a:after, + a[href^="javascript:"]:after, + a[href^="#"]:after { + content: ""; + } + pre, + blockquote { + border: 1px solid #999; + page-break-inside: avoid; + } + thead { + display: table-header-group; + } + tr, + img { + page-break-inside: avoid; + } + img { + max-width: 100% !important; + } + @page { + margin: 0.5cm; + } + p, + h2, + h3 { + orphans: 3; + widows: 3; + } + h1, + h2, + h3 { + page-break-after: avoid; + } + .do-not-print, + .screen-reader-text, + .invisible, + .jump-to-menu, + .jump-link, + #site-map-link { + display: none; + } + .say-no-more { + display: inline; + visibility: visible; + } + .blog-widget li, + .event-widget li { + padding-left: 6em; + } + .site-headline a { + display: block; + } + .site-headline a .python-logo, + .site-headline a .psf-logo { + display: none; + } + .python .site-headline a:before { + width: 290px; + height: 82px; + content: url(../img/python-logo_print.png?1576869008); + } + .psf .site-headline a:before { + width: 334px; + height: 82px; + content: url(../img/psf-logo_print.png?1576869008); + } +} +.icon-megaphone, +.icon-python-alt, +.icon-pypi, +.icon-news, +.icon-moderate, +.icon-mercurial, +.icon-jobs, +.icon-help, +.icon-download, +.icon-documentation, +.icon-community, +.icon-code, +.icon-close, +.icon-calendar, +.icon-beginner, +.icon-advanced, +.icon-sitemap, +.icon-search, +.icon-search-alt, +.icon-python, +.icon-github, +.icon-get-started, +.icon-feed, +.icon-facebook, +.icon-email, +.icon-arrow-up, +.icon-arrow-right, +.icon-arrow-left, +.icon-arrow-down, +.errorlist:before, +.icon-freenode, +.icon-alert, +.icon-versions, +.icon-twitter, +.icon-thumbs-up, +.icon-thumbs-down, +.icon-text-resize, +.icon-success-stories, +.icon-statistics, +.icon-stack-overflow { + font-family: "Pythonicon"; + speak: none; + font-style: normal; + font-weight: normal; + font-variant: normal; + text-transform: none; + line-height: 1; + margin-right: 0.5em; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} +.icon-megaphone span, +.icon-python-alt span, +.icon-pypi span, +.icon-news span, +.icon-moderate span, +.icon-mercurial span, +.icon-jobs span, +.icon-help span, +.icon-download span, +.icon-documentation span, +.icon-community span, +.icon-code span, +.icon-close span, +.icon-calendar span, +.icon-beginner span, +.icon-advanced span, +.icon-sitemap span, +.icon-search span, +.icon-search-alt span, +.icon-python span, +.icon-github span, +.icon-get-started span, +.icon-feed span, +.icon-facebook span, +.icon-email span, +.icon-arrow-up span, +.icon-arrow-right span, +.icon-arrow-left span, +.icon-arrow-down span, +.errorlist:before span, +.icon-freenode span, +.icon-alert span, +.icon-versions span, +.icon-twitter span, +.icon-thumbs-up span, +.icon-thumbs-down span, +.icon-text-resize span, +.icon-success-stories span, +.icon-statistics span, +.icon-stack-overflow span { + display: none; +} +@font-face { + font-family: "Pythonicon"; + src: url(Pythonicon.eot); +} +@font-face { + font-family: "Pythonicon"; + src: url(data:application/x-font-ttf;charset=utf-8;base64,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) + format("truetype"), + url(data:application/font-woff;charset=utf-8;base64,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) + format("woff"); + font-weight: normal; + font-style: normal; +} +.icon-megaphone:before { + content: "\e600"; +} +.icon-python-alt:before { + content: "\e601"; +} +.icon-pypi:before { + content: "\e602"; +} +.icon-news:before { + content: "\e603"; +} +.icon-moderate:before { + content: "\e604"; +} +.icon-mercurial:before { + content: "\e605"; +} +.icon-jobs:before { + content: "\e606"; +} +.icon-help:before { + content: "\3f"; +} +.icon-download:before { + content: "\e609"; +} +.icon-documentation:before { + content: "\e60a"; +} +.icon-community:before { + content: "\e60b"; +} +.icon-code:before { + content: "\e60c"; +} +.icon-close:before { + content: "\58"; +} +.icon-calendar:before { + content: "\e60e"; +} +.icon-beginner:before { + content: "\e60f"; +} +.icon-advanced:before { + content: "\e610"; +} +.icon-sitemap:before { + content: "\e611"; +} +.icon-search-alt:before { + content: "\e612"; +} +.icon-search:before { + content: "\e613"; +} +.icon-python:before { + content: "\e614"; +} +.icon-github:before { + content: "\e615"; +} +.icon-get-started:before { + content: "\e616"; +} +.icon-feed:before { + content: "\e617"; +} +.icon-facebook:before { + content: "\e618"; +} +.icon-email:before { + content: "\e619"; +} +.icon-arrow-up:before { + content: "\e61a"; +} +.icon-arrow-right:before { + content: "\e61b"; +} +.icon-arrow-left:before { + content: "\e61c"; +} +.icon-arrow-down:before, +.errorlist:before { + content: "\e61d"; +} +.icon-freenode:before { + content: "\e61e"; +} +.icon-alert:before { + content: "\e61f"; +} +.icon-versions:before { + content: "\e620"; +} +.icon-twitter:before { + content: "\e621"; +} +.icon-thumbs-up:before { + content: "\e622"; +} +.icon-thumbs-down:before { + content: "\e623"; +} +.icon-text-resize:before { + content: "\e624"; +} +.icon-success-stories:before { + content: "\e625"; +} +.icon-statistics:before { + content: "\e626"; +} +.icon-stack-overflow:before { + content: "\e627"; +} +.no-fontface .icon-megaphone:before, +.no-fontface .icon-python-alt:before, +.no-fontface .icon-pypi:before, +.no-fontface .icon-news:before, +.no-fontface .icon-moderate:before, +.no-fontface .icon-mercurial:before, +.no-fontface .icon-jobs:before, +.no-fontface .icon-help:before, +.no-fontface .icon-download:before, +.no-fontface .icon-documentation:before, +.no-fontface .icon-community:before, +.no-fontface .icon-code:before, +.no-fontface .icon-close:before, +.no-fontface .icon-calendar:before, +.no-fontface .icon-beginner:before, +.no-fontface .icon-advanced:before, +.no-fontface .icon-sitemap:before, +.no-fontface .icon-search:before, +.no-fontface .icon-search-alt:before, +.no-fontface .icon-python:before, +.no-fontface .icon-github:before, +.no-fontface .icon-get-started:before, +.no-fontface .icon-feed:before, +.no-fontface .icon-facebook:before, +.no-fontface .icon-email:before, +.no-fontface .icon-arrow-up:before, +.no-fontface .icon-arrow-right:before, +.no-fontface .icon-arrow-left:before, +.no-fontface .icon-arrow-down:before, +.no-fontface .errorlist:before, +.no-fontface .icon-freenode:before, +.no-fontface .icon-alert:before, +.no-fontface .icon-versions:before, +.no-fontface .icon-twitter:before, +.no-fontface .icon-thumbs-up:before, +.no-fontface .icon-thumbs-down:before, +.no-fontface .icon-text-resize:before, +.no-fontface .icon-success-stories:before, +.no-fontface .icon-statistics:before, +.no-fontface .icon-stack-overflow:before, +.no-svg .icon-megaphone:before, +.no-svg .icon-python-alt:before, +.no-svg .icon-pypi:before, +.no-svg .icon-news:before, +.no-svg .icon-moderate:before, +.no-svg .icon-mercurial:before, +.no-svg .icon-jobs:before, +.no-svg .icon-help:before, +.no-svg .icon-download:before, +.no-svg .icon-documentation:before, +.no-svg .icon-community:before, +.no-svg .icon-code:before, +.no-svg .icon-close:before, +.no-svg .icon-calendar:before, +.no-svg .icon-beginner:before, +.no-svg .icon-advanced:before, +.no-svg .icon-sitemap:before, +.no-svg .icon-search:before, +.no-svg .icon-search-alt:before, +.no-svg .icon-python:before, +.no-svg .icon-github:before, +.no-svg .icon-get-started:before, +.no-svg .icon-feed:before, +.no-svg .icon-facebook:before, +.no-svg .icon-email:before, +.no-svg .icon-arrow-up:before, +.no-svg .icon-arrow-right:before, +.no-svg .icon-arrow-left:before, +.no-svg .icon-arrow-down:before, +.no-svg .errorlist:before, +.no-svg .icon-freenode:before, +.no-svg .icon-alert:before, +.no-svg .icon-versions:before, +.no-svg .icon-twitter:before, +.no-svg .icon-thumbs-up:before, +.no-svg .icon-thumbs-down:before, +.no-svg .icon-text-resize:before, +.no-svg .icon-success-stories:before, +.no-svg .icon-statistics:before, +.no-svg .icon-stack-overflow:before, +.no-generatedcontent .icon-megaphone:before, +.no-generatedcontent .icon-python-alt:before, +.no-generatedcontent .icon-pypi:before, +.no-generatedcontent .icon-news:before, +.no-generatedcontent .icon-moderate:before, +.no-generatedcontent .icon-mercurial:before, +.no-generatedcontent .icon-jobs:before, +.no-generatedcontent .icon-help:before, +.no-generatedcontent .icon-download:before, +.no-generatedcontent .icon-documentation:before, +.no-generatedcontent .icon-community:before, +.no-generatedcontent .icon-code:before, +.no-generatedcontent .icon-close:before, +.no-generatedcontent .icon-calendar:before, +.no-generatedcontent .icon-beginner:before, +.no-generatedcontent .icon-advanced:before, +.no-generatedcontent .icon-sitemap:before, +.no-generatedcontent .icon-search:before, +.no-generatedcontent .icon-search-alt:before, +.no-generatedcontent .icon-python:before, +.no-generatedcontent .icon-github:before, +.no-generatedcontent .icon-get-started:before, +.no-generatedcontent .icon-feed:before, +.no-generatedcontent .icon-facebook:before, +.no-generatedcontent .icon-email:before, +.no-generatedcontent .icon-arrow-up:before, +.no-generatedcontent .icon-arrow-right:before, +.no-generatedcontent .icon-arrow-left:before, +.no-generatedcontent .icon-arrow-down:before, +.no-generatedcontent .errorlist:before, +.no-generatedcontent .icon-freenode:before, +.no-generatedcontent .icon-alert:before, +.no-generatedcontent .icon-versions:before, +.no-generatedcontent .icon-twitter:before, +.no-generatedcontent .icon-thumbs-up:before, +.no-generatedcontent .icon-thumbs-down:before, +.no-generatedcontent .icon-text-resize:before, +.no-generatedcontent .icon-success-stories:before, +.no-generatedcontent .icon-statistics:before, +.no-generatedcontent .icon-stack-overflow:before { + display: none; + margin-right: 0; +} +.no-fontface .icon-megaphone span, +.no-fontface .icon-python-alt span, +.no-fontface .icon-pypi span, +.no-fontface .icon-news span, +.no-fontface .icon-moderate span, +.no-fontface .icon-mercurial span, +.no-fontface .icon-jobs span, +.no-fontface .icon-help span, +.no-fontface .icon-download span, +.no-fontface .icon-documentation span, +.no-fontface .icon-community span, +.no-fontface .icon-code span, +.no-fontface .icon-close span, +.no-fontface .icon-calendar span, +.no-fontface .icon-beginner span, +.no-fontface .icon-advanced span, +.no-fontface .icon-sitemap span, +.no-fontface .icon-search span, +.no-fontface .icon-search-alt span, +.no-fontface .icon-python span, +.no-fontface .icon-github span, +.no-fontface .icon-get-started span, +.no-fontface .icon-feed span, +.no-fontface .icon-facebook span, +.no-fontface .icon-email span, +.no-fontface .icon-arrow-up span, +.no-fontface .icon-arrow-right span, +.no-fontface .icon-arrow-left span, +.no-fontface .icon-arrow-down span, +.no-fontface .errorlist:before span, +.no-fontface .icon-freenode span, +.no-fontface .icon-alert span, +.no-fontface .icon-versions span, +.no-fontface .icon-twitter span, +.no-fontface .icon-thumbs-up span, +.no-fontface .icon-thumbs-down span, +.no-fontface .icon-text-resize span, +.no-fontface .icon-success-stories span, +.no-fontface .icon-statistics span, +.no-fontface .icon-stack-overflow span, +.no-svg .icon-megaphone span, +.no-svg .icon-python-alt span, +.no-svg .icon-pypi span, +.no-svg .icon-news span, +.no-svg .icon-moderate span, +.no-svg .icon-mercurial span, +.no-svg .icon-jobs span, +.no-svg .icon-help span, +.no-svg .icon-download span, +.no-svg .icon-documentation span, +.no-svg .icon-community span, +.no-svg .icon-code span, +.no-svg .icon-close span, +.no-svg .icon-calendar span, +.no-svg .icon-beginner span, +.no-svg .icon-advanced span, +.no-svg .icon-sitemap span, +.no-svg .icon-search span, +.no-svg .icon-search-alt span, +.no-svg .icon-python span, +.no-svg .icon-github span, +.no-svg .icon-get-started span, +.no-svg .icon-feed span, +.no-svg .icon-facebook span, +.no-svg .icon-email span, +.no-svg .icon-arrow-up span, +.no-svg .icon-arrow-right span, +.no-svg .icon-arrow-left span, +.no-svg .icon-arrow-down span, +.no-svg .errorlist:before span, +.no-svg .icon-freenode span, +.no-svg .icon-alert span, +.no-svg .icon-versions span, +.no-svg .icon-twitter span, +.no-svg .icon-thumbs-up span, +.no-svg .icon-thumbs-down span, +.no-svg .icon-text-resize span, +.no-svg .icon-success-stories span, +.no-svg .icon-statistics span, +.no-svg .icon-stack-overflow span, +.no-generatedcontent .icon-megaphone span, +.no-generatedcontent .icon-python-alt span, +.no-generatedcontent .icon-pypi span, +.no-generatedcontent .icon-news span, +.no-generatedcontent .icon-moderate span, +.no-generatedcontent .icon-mercurial span, +.no-generatedcontent .icon-jobs span, +.no-generatedcontent .icon-help span, +.no-generatedcontent .icon-download span, +.no-generatedcontent .icon-documentation span, +.no-generatedcontent .icon-community span, +.no-generatedcontent .icon-code span, +.no-generatedcontent .icon-close span, +.no-generatedcontent .icon-calendar span, +.no-generatedcontent .icon-beginner span, +.no-generatedcontent .icon-advanced span, +.no-generatedcontent .icon-sitemap span, +.no-generatedcontent .icon-search span, +.no-generatedcontent .icon-search-alt span, +.no-generatedcontent .icon-python span, +.no-generatedcontent .icon-github span, +.no-generatedcontent .icon-get-started span, +.no-generatedcontent .icon-feed span, +.no-generatedcontent .icon-facebook span, +.no-generatedcontent .icon-email span, +.no-generatedcontent .icon-arrow-up span, +.no-generatedcontent .icon-arrow-right span, +.no-generatedcontent .icon-arrow-left span, +.no-generatedcontent .icon-arrow-down span, +.no-generatedcontent .errorlist:before span, +.no-generatedcontent .icon-freenode span, +.no-generatedcontent .icon-alert span, +.no-generatedcontent .icon-versions span, +.no-generatedcontent .icon-twitter span, +.no-generatedcontent .icon-thumbs-up span, +.no-generatedcontent .icon-thumbs-down span, +.no-generatedcontent .icon-text-resize span, +.no-generatedcontent .icon-success-stories span, +.no-generatedcontent .icon-statistics span, +.no-generatedcontent .icon-stack-overflow span { + display: inline; +} +.ie8 .icon-megaphone:before, +.ie8 .icon-python-alt:before, +.ie8 .icon-pypi:before, +.ie8 .icon-news:before, +.ie8 .icon-moderate:before, +.ie8 .icon-mercurial:before, +.ie8 .icon-jobs:before, +.ie8 .icon-help:before, +.ie8 .icon-download:before, +.ie8 .icon-documentation:before, +.ie8 .icon-community:before, +.ie8 .icon-code:before, +.ie8 .icon-close:before, +.ie8 .icon-calendar:before, +.ie8 .icon-beginner:before, +.ie8 .icon-advanced:before, +.ie8 .icon-sitemap:before, +.ie8 .icon-search:before, +.ie8 .icon-search-alt:before, +.ie8 .icon-python:before, +.ie8 .icon-github:before, +.ie8 .icon-get-started:before, +.ie8 .icon-feed:before, +.ie8 .icon-facebook:before, +.ie8 .icon-email:before, +.ie8 .icon-arrow-up:before, +.ie8 .icon-arrow-right:before, +.ie8 .icon-arrow-left:before, +.ie8 .icon-arrow-down:before, +.ie8 .errorlist:before, +.ie8 .icon-freenode:before, +.ie8 .icon-alert:before, +.ie8 .icon-versions:before, +.ie8 .icon-twitter:before, +.ie8 .icon-thumbs-up:before, +.ie8 .icon-thumbs-down:before, +.ie8 .icon-text-resize:before, +.ie8 .icon-success-stories:before, +.ie8 .icon-statistics:before, +.ie8 .icon-stack-overflow:before { + display: inline; +} +.ie8 .icon-megaphone span, +.ie8 .icon-python-alt span, +.ie8 .icon-pypi span, +.ie8 .icon-news span, +.ie8 .icon-moderate span, +.ie8 .icon-mercurial span, +.ie8 .icon-jobs span, +.ie8 .icon-help span, +.ie8 .icon-download span, +.ie8 .icon-documentation span, +.ie8 .icon-community span, +.ie8 .icon-code span, +.ie8 .icon-close span, +.ie8 .icon-calendar span, +.ie8 .icon-beginner span, +.ie8 .icon-advanced span, +.ie8 .icon-sitemap span, +.ie8 .icon-search span, +.ie8 .icon-search-alt span, +.ie8 .icon-python span, +.ie8 .icon-github span, +.ie8 .icon-get-started span, +.ie8 .icon-feed span, +.ie8 .icon-facebook span, +.ie8 .icon-email span, +.ie8 .icon-arrow-up span, +.ie8 .icon-arrow-right span, +.ie8 .icon-arrow-left span, +.ie8 .icon-arrow-down span, +.ie8 .errorlist:before span, +.ie8 .icon-freenode span, +.ie8 .icon-alert span, +.ie8 .icon-versions span, +.ie8 .icon-twitter span, +.ie8 .icon-thumbs-up span, +.ie8 .icon-thumbs-down span, +.ie8 .icon-text-resize span, +.ie8 .icon-success-stories span, +.ie8 .icon-statistics span, +.ie8 .icon-stack-overflow span { + display: none; +} + From 022a561a22d15ca23db0668f6a1496a306e8e090 Mon Sep 17 00:00:00 2001 From: AA Turner <9087854+AA-Turner@users.noreply.github.com> Date: Sun, 21 Jun 2020 20:03:14 +0100 Subject: [PATCH 062/108] Add favicon --- conf.py | 1 + pep_extensions/theme/static/py.png | Bin 0 -> 695 bytes 2 files changed, 1 insertion(+) create mode 100644 pep_extensions/theme/static/py.png diff --git a/conf.py b/conf.py index d09717488e4..3a495c82fc0 100644 --- a/conf.py +++ b/conf.py @@ -64,6 +64,7 @@ html_theme_path = ["pep_extensions"] html_theme = "theme" +html_favicon = Path(html_theme_path[0], html_theme, "static/py.png").as_posix() html_math_renderer = "math2html" # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, diff --git a/pep_extensions/theme/static/py.png b/pep_extensions/theme/static/py.png new file mode 100644 index 0000000000000000000000000000000000000000..93e4a02c3d321c545898a2ebb8873c26dd8a9e5b GIT binary patch literal 695 zcmV;o0!aOdP)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV00001b5ch_0Itp) z=>Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2iOD~ z5jY_RGbdgE00K8jL_t(I%Vm>KNL4`;hrfH@vv+$Uln|xSCTLTOHmzE;5FTwpDtJ)a zz)exE-2_34AR^i+ZCXeh7m*-F5k*FrmbSHs%rX_!{PXUec{69`w(#D(>Vd<+%=bIz zH_V)XUD5sE?K5ebbKaSDu}#Dnq^Y!3`tis9>wSO*T+WBP3wS3NNBU~*PAtw^yjZ+< zQ5yK0z%d{y@_Pz6YdL>s7$<f+t<8@+fNGI119U%pf7@GoT&xO=P6mx?ltsrSXAI%K zN<B?|&R2lajslk-eR%D}cBNjxdjg<TZh=Y_f)Y;b4u|PneZkvUi*DSnoO*XJ^xk!C zSv5OtXPJkn%~8N2387O_8GQrjEa#vvh<xGRY3jAp@tdh9eFMu=wHl&85<;)qfsXPH zv9;*N+UWfF@YDI}S8IR(DPZQtY9|l2N-s`<OF$BU{beyt?Zrk;ENXpuXkwsuaO3B# zE3MIqOQBQIe^_Gj?uf#R)<6(Ck=fk(pUIcc<6pf!ZB>6Y^hI$}5GUX?Ns>+iCUiRP z7h|*&%kQa?wQA%pYzqpaf*4?WM!x_ygY0K@07rplx^QhGhnE)r4wbx0x11<&3V?63 z=F8ch)p6iQ88E;iumPmSZif%JIwIgKh$T3)*ab8ImGLVf;IoYtVAb11Z&@wm>96=S z)!B<I0N=AU*)t1`jrF?K@n>&hojbAPoik&f)Lp;=N!HK;X~5oyfJ49$pbcorTyADv dm$H!t;2#0MumAjv0Ga>*002ovPDHLkV1gIiH5UK? literal 0 HcmV?d00001 From c5ba162632b9b404bd05d6e1e994d24330c4dc27 Mon Sep 17 00:00:00 2001 From: AA Turner <9087854+AA-Turner@users.noreply.github.com> Date: Sun, 21 Jun 2020 20:03:48 +0100 Subject: [PATCH 063/108] Clean theme.conf --- conf.py | 3 --- pep_extensions/theme/theme.conf | 25 ++----------------------- 2 files changed, 2 insertions(+), 26 deletions(-) diff --git a/conf.py b/conf.py index 3a495c82fc0..f68cf23b3a0 100644 --- a/conf.py +++ b/conf.py @@ -54,9 +54,6 @@ 'requirements.txt', ] -# The name of the Pygments (syntax highlighting) style to use. -pygments_style = 'sphinx' - # -- Options for HTML output ------------------------------------------------- # The theme to use for HTML and HTML Help pages. See the documentation for diff --git a/pep_extensions/theme/theme.conf b/pep_extensions/theme/theme.conf index 95acf079627..8a5ba9581bf 100644 --- a/pep_extensions/theme/theme.conf +++ b/pep_extensions/theme/theme.conf @@ -1,28 +1,7 @@ [theme] -inherit = default +inherit = basic pygments_style = sphinx pygments_dark_style = monokai [options] -bodyfont = 'Lucida Grande', Arial, sans-serif -headfont = 'Lucida Grande', Arial, sans-serif -footerbgcolor = white -footertextcolor = white -relbarbgcolor = white -relbartextcolor = white -relbarlinkcolor = white -sidebarbgcolor = white -sidebartextcolor = white -sidebarlinkcolor = white -bgcolor = white -textcolor = white -linkcolor = white -visitedlinkcolor = white -headtextcolor = white -headbgcolor = white -headlinkcolor = white - -root_name = Python -root_url = https://www.python.org/ -root_icon = -root_include_title = True \ No newline at end of file +root_url = https://www.python.org/ \ No newline at end of file From 68f87c72209a86a87a68217f6f3e723148205473 Mon Sep 17 00:00:00 2001 From: AA Turner <9087854+AA-Turner@users.noreply.github.com> Date: Sun, 21 Jun 2020 20:04:34 +0100 Subject: [PATCH 064/108] Add custom breadcrumbs template to mirror pydotorg --- pep_extensions/theme/breadcrumbs.html | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 pep_extensions/theme/breadcrumbs.html diff --git a/pep_extensions/theme/breadcrumbs.html b/pep_extensions/theme/breadcrumbs.html new file mode 100644 index 00000000000..4336d2d00d8 --- /dev/null +++ b/pep_extensions/theme/breadcrumbs.html @@ -0,0 +1,8 @@ +<ul class="breadcrumbs menu" role="directory" aria-label="breadcrumbs navigation"> + {% block breadcrumbs %} + <li><a href="{{ theme_root_url }}" title="The Python Programming Language">Python</a><span class="prompt">>>></span></li> + <li><a href="{{ theme_root_url }}dev/">Python Developer's Guide</a><span class="prompt">>>></span></li> + <li><a href="{{ pathto("pep-0000") }}">PEP Index</a><span class="prompt">>>></span></li> + <li>{{ title }}</li> + {% endblock %} +</ul> \ No newline at end of file From 9d82e6b75b9909e75c48bfa6890540b46f484b34 Mon Sep 17 00:00:00 2001 From: AA Turner <9087854+AA-Turner@users.noreply.github.com> Date: Sun, 21 Jun 2020 20:04:58 +0100 Subject: [PATCH 065/108] Remove jQuery from the search page --- pep_extensions/theme/search.html | 41 ++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 pep_extensions/theme/search.html diff --git a/pep_extensions/theme/search.html b/pep_extensions/theme/search.html new file mode 100644 index 00000000000..6187d6d02e4 --- /dev/null +++ b/pep_extensions/theme/search.html @@ -0,0 +1,41 @@ +{% extends "basic/search.html" %} +{%- block scripts %} + {{ super() }} + <script src="{{ pathto('_static/searchtools.js', 1) }}"></script> +{%- endblock %} +{% block body %} + <h1 id="search-documentation">{{ _('Search') }}</h1> + <div id="fallback" class="admonition warning"> + <script>document.getElementById("fallback").style.display = "none";</script> + <p> + {% trans %}Please activate JavaScript to enable the search + functionality.{% endtrans %} + </p> + </div> + <p> + {% trans %}Searching for multiple words only shows matches that contain + all words.{% endtrans %} + </p> + <form action="" method="get"> + <input type="text" name="q" aria-labelledby="search-documentation" value="" /> + <input type="submit" value="{{ _('search') }}" /> + <span id="search-progress" style="padding-left: 10px"></span> + </form> + {% if search_performed %} + <h2>{{ _('Search Results') }}</h2> + {% if not search_results %} + <p>{{ _('Your search did not match any documents. Please make sure that all words are spelled correctly and that you\'ve selected enough categories.') }}</p> + {% endif %} + {% endif %} + <div id="search-results"> + {% if search_results %} + <ul> + {% for href, caption, context in search_results %} + <li><a href="{{ pathto(item.href) }}">{{ caption }}</a> + <div class="context">{{ context|e }}</div> + </li> + {% endfor %} + </ul> + {% endif %} + </div> +{% endblock %} \ No newline at end of file From 371a61d1f9f577ac75e4ae0f25b10146b8bceb85 Mon Sep 17 00:00:00 2001 From: AA Turner <9087854+AA-Turner@users.noreply.github.com> Date: Sun, 21 Jun 2020 20:05:27 +0100 Subject: [PATCH 066/108] Add custom sidebar templates --- pep_extensions/theme/customsidebar.html | 47 +++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 pep_extensions/theme/customsidebar.html diff --git a/pep_extensions/theme/customsidebar.html b/pep_extensions/theme/customsidebar.html new file mode 100644 index 00000000000..220a7b64b5e --- /dev/null +++ b/pep_extensions/theme/customsidebar.html @@ -0,0 +1,47 @@ +<h6>Python Enhancement Proposals</h6> + + +{# Search box #} +{%- if pagename != "search" and builder != "singlehtml" %} + <div id="searchbox" class="inline-search" style="display: none" role="search"> + <form class="search" action="{{ pathto('search') }}" method="get"> + <label for="q" style="position:absolute;width:1px;height:1px;overflow: hidden"> + {{ _('Quick search') }} + </label> + <input type="text" placeholder="{{ _('Quick search') }}" name="q" id="q" /> + <input type="submit" value="{{ _('Go') }}" enterkeyhint="go"/> + </form> + </div> + <script>document.getElementById("searchbox").style.display = 'block';</script> +{%- endif %} + +{# Source link #} +{%- if show_source and has_source and sourcename %} + <div class="source-link" role="note" aria-label="source link"> + <a href="https://github.com/python/peps/blob/master/{{sourcename}}">{{_('Page Source (GitHub)')}}</a> + </div> +{%- endif %} + +{# Navigation #} +{%- if title|pep_id|e and title|pep_id|e != "PEP 0000" %} +<div class="related" role="navigation" aria-label="related navigation"> + <h3>{{ _('Quick Navigation') }}</h3> + <nav> + <ul> + {%- if prev %} + <li class=""><a href="{{ prev.link|e }}">{{ prev.title|pep_id|striptags|e }}</a></li> + {%- endif %} + <li class=""><a title="PEP 0" href="{{ pathto('pep-0000') }}">PEP Index</a></li> + {%- if next %} + <li class=""><a href="{{ next.link|e }}">{{ next.title|pep_id|striptags|e }}</a></li> + {%- endif %} + </ul> + </nav> +</div> +{%- endif %} + +{# Table of Contents #} +{%- if display_toc %} +<h3>{{ _('Contents') }}</h3> +{{ toc }} +{%- endif %} \ No newline at end of file From da69c1aa1db47d1d05f54d356969a754253db828 Mon Sep 17 00:00:00 2001 From: AA Turner <9087854+AA-Turner@users.noreply.github.com> Date: Sun, 21 Jun 2020 20:06:23 +0100 Subject: [PATCH 067/108] subset of doctools.js and searchtools.js in plain ES6 --- pep_extensions/theme/static/doctools.js | 137 ++++++ pep_extensions/theme/static/searchtools.js | 530 +++++++++++++++++++++ 2 files changed, 667 insertions(+) create mode 100644 pep_extensions/theme/static/doctools.js create mode 100644 pep_extensions/theme/static/searchtools.js diff --git a/pep_extensions/theme/static/doctools.js b/pep_extensions/theme/static/doctools.js new file mode 100644 index 00000000000..d714cba0de2 --- /dev/null +++ b/pep_extensions/theme/static/doctools.js @@ -0,0 +1,137 @@ +/* + * doctools.js + * ~~~~~~~~~~~ + * + * Sphinx JavaScript utilities for all documentation. + * + * :copyright: Copyright 2007-2020 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ + +/** + * Footnote fixer + */ +document.querySelectorAll("span.brackets").forEach(el => { + if (!el.children.length) { + el.innerText = "[" + el.innerText + "]" + } +}) + +/** + * select a different prefix for underscore + */ + +const ready = (callback) => { + if (document.readyState !== "loading") callback(); + else document.addEventListener("DOMContentLoaded", callback); +} + +const removeElements = (elms) => {for (let el of elms) { el.remove() }} + +/** + * highlight a given string on a node by wrapping it in + * span elements with the given class name. + */ +const highlightText = function(text, className, curNode) { + function highlight(node, addItems) { + if (node.nodeType === 3) { // Text node + const val = node.nodeValue; + const parent = node.parentNode + const pos = val.toLowerCase().indexOf(text); + if (pos >= 0 + && !parent.classList.contains(className) + && !parent.classList.contains("nohighlight") + ) { + let span; + const closestNode = node.parentNode.closest("body, svg, foreignObject"); + const isInSVG = closestNode && closestNode.matches("svg") + if (isInSVG) { + span = document.createElementNS("http://www.w3.org/2000/svg", "tspan"); + } else { + span = document.createElement("span"); + span.classList.add(className); + } + + span.appendChild(document.createTextNode(val.substr(pos, text.length))); + parent.insertBefore(span, parent.insertBefore( + document.createTextNode(val.substr(pos + text.length)), + node.nextSibling)); + node.nodeValue = val.substr(0, pos); + if (isInSVG) { + const rect = document.createElementNS("http://www.w3.org/2000/svg", "rect"); + const bbox = parent.getBBox(); + rect.x.baseVal.value = bbox.x; + rect.y.baseVal.value = bbox.y; + rect.width.baseVal.value = bbox.width; + rect.height.baseVal.value = bbox.height; + rect.setAttribute('class', className); + addItems.push({ + "parent": node.parentNode, + "target": rect}); + } + } + } + else if (node.matches("button, select, textarea")) { + node.childNodes.forEach(el => highlight(el, addItems)); + } + else if (node.nodeType === 1) + { + node.childNodes.forEach(el => highlight(el, addItems)); + } + } + let addItems = []; + // const content = document.querySelector('[role="main"]'); + highlight(curNode, addItems) + for (let i = 0; i < addItems.length; ++i) { + addItems[i].parent.insertAdjacentHTML("beforebegin", addItems[i].target) + } + return curNode; +}; + +/** + * Small JavaScript module for the documentation. + */ +const Documentation = { + init : function() { + this.highlightSearchWords(); + }, + + gettext : string => string, + + /** + * highlight the search words provided in the urle in the text + */ + highlightSearchWords : function() { + const urlParams = new URLSearchParams(window.location.search); + const terms = urlParams.get("highlight") ? urlParams.get("highlight").split(/\s+/) : []; + if (terms.length) { + window.setTimeout(() => { + terms.forEach(term => highlightText(term.toLowerCase(), 'highlighted', document.querySelector("body"))) + }, 10); + let hideMatches = document.createElement("p") + let hideMatchesLink = document.createElement("a") + hideMatches.classList.add("highlight-link") + hideMatchesLink.href = "javascript:Documentation.hideSearchWords()" + hideMatchesLink.innerText = _('Hide Search Matches') + hideMatchesLink.style.fontStyle = "italic" + hideMatches.appendChild(hideMatchesLink) + document.getElementById("searchbox").appendChild(hideMatches) + } + }, + + /** + * helper function to hide the search marks again + */ + hideSearchWords : function() { + removeElements(document.querySelectorAll("#searchbox .highlight-link")) + document.querySelectorAll("span.highlighted").forEach(el => el.classList.remove("highlighted")) + }, +}; + +// quick alias for translations +_ = Documentation.gettext; + +ready(() => { + Documentation.init(); +}); \ No newline at end of file diff --git a/pep_extensions/theme/static/searchtools.js b/pep_extensions/theme/static/searchtools.js new file mode 100644 index 00000000000..04007380c99 --- /dev/null +++ b/pep_extensions/theme/static/searchtools.js @@ -0,0 +1,530 @@ +/* + * searchtools.js + * ~~~~~~~~~~~~~~~~ + * + * Sphinx JavaScript utilities for the full-text search. + * + * :copyright: Copyright 2007-2020 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ + + +/** + * Simple result scoring code. + */ +const Scorer = { + // Implement the following function to further tweak the score for each result + // The function takes a result array [filename, title, anchor, descr, score] + // and returns the new score. + /* + score: function(result) { + return result[4]; + }, + */ + + // query matches the full name of an object + objNameMatch: 11, + // or matches in the last dotted part of the object name + objPartialMatch: 6, + // Additive scores depending on the priority of the object + objPrio: {0: 15, // used to be importantResults + 1: 5, // used to be objectResults + 2: -5}, // used to be unimportantResults + // Used when the priority is not in the mapping. + objPrioDefault: 0, + + // query found in title + title: 15, + partialTitle: 7, + // query found in terms + term: 5, + partialTerm: 2 +}; + + +if (!splitQuery) { + function splitQuery(query) { + return query.split(/\s+/); + } +} + + +const removeChildren = (elm) => { + while (elm.lastChild) { + elm.removeChild(elm.lastChild); + } +} +/** + * Search Module + */ +const Search = { + + _index: null, + _queued_query: null, + _pulse_status: -1, + + htmlToText: function (htmlString) { + const htmlElement = document.createElement('span'); + htmlElement.innerHTML = htmlString; + removeElements(htmlElement.getElementsByClassName('headerlink')); + const docContent = htmlElement.querySelector('[role="main"]'); + if (docContent === undefined) { + console.warn("Content block not found. Sphinx search tries to obtain it " + + "via '[role=main]'. Could you check your theme or template."); + return ""; + } + return docContent.textContent || docContent.innerText; + }, + + init: function () { + const urlParams = new URLSearchParams(window.location.search); + const query = urlParams.get("q"); + if (query) { + document.querySelector('input[name="q"]').value = query; + this.performSearch(query); + } + }, + + setIndex: function (index) { + let q; + this._index = index; + if ((q = this._queued_query) !== null) { + this._queued_query = null; + Search.query(q); + } + }, + + hasIndex: function () { + return this._index !== null; + }, + + deferQuery: function (query) { + this._queued_query = query; + }, + + stopPulse: function () { + this._pulse_status = 0; + }, + + startPulse: function () { + if (this._pulse_status >= 0) + return; + + function pulse() { + let i; + Search._pulse_status = (Search._pulse_status + 1) % 4; + let dotString = ''; + for (i = 0; i < Search._pulse_status; i++) + dotString += '.'; + Search.dots.innerText = dotString; + if (Search._pulse_status > -1) + window.setTimeout(pulse, 500); + } + + pulse(); + }, + + /** + * perform a search for something (or wait until index is loaded) + */ + performSearch: function (query) { + const dotsSpan = document.createElement("span"); + const searchText = document.createElement("h2"); + searchText.textContent = _('Searching'); + const searchSummary = document.createElement("p"); + searchSummary.classList.add("search-summary") + searchSummary.innerText = "" + const searchList = document.createElement("ul"); + searchList.classList.add("search") + + // create the required interface elements + this.out = document.getElementById("search-results"); + this.title = this.out.appendChild(searchText); + this.dots = this.title.appendChild(dotsSpan) + this.status = this.out.appendChild(searchSummary); + this.output = this.out.appendChild(searchList); + + document.getElementById("search-progress").innerText = _('Preparing search...') + this.startPulse(); + + // index already loaded, the browser was quick! + if (this.hasIndex()) + this.query(query); + else + this.deferQuery(query); + }, + + /** + * execute search (requires search index to be loaded) + */ + query: function (query) { + let i; + + // stem the searchterms and add them to the correct list + const stemmer = new Stemmer(); + const searchterms = []; + const excluded = []; + const hlterms = []; + const tmp = splitQuery(query); + const objectterms = []; + for (i = 0; i < tmp.length; i++) { + if (tmp[i] !== "") { + objectterms.push(tmp[i].toLowerCase()); + } + + // stopwords array is from language_data.js + if (stopwords.indexOf(tmp[i].toLowerCase()) !== -1 || tmp[i].match(/^\d+$/) || + tmp[i] === "") { + // skip this "word" + continue; + } + // stem the word + let word = stemmer.stemWord(tmp[i].toLowerCase()); + // prevent stemmer from cutting word smaller than two chars + if (word.length < 3 && tmp[i].length >= 3) { + word = tmp[i]; + } + let toAppend; + // select the correct list + if (word[0] === '-') { + toAppend = excluded; + word = word.substr(1); + } else { + toAppend = searchterms; + hlterms.push(tmp[i].toLowerCase()); + } + // only add if not already in the list + if (!toAppend.includes(word)) + toAppend.push(word); + } + const highlightstring = '?highlight=' + encodeURIComponent(hlterms.join(" ")); + + // console.debug('SEARCH: searching for:'); + // console.info('required: ', searchterms); + // console.info('excluded: ', excluded); + + // prepare search + const terms = this._index.terms; + const titleterms = this._index.titleterms; + + // array of [filename, title, anchor, descr, score] + let results = []; + removeChildren(document.getElementById("search-progress")) + + // lookup as object + for (i = 0; i < objectterms.length; i++) { + const others = [].concat(objectterms.slice(0, i), + objectterms.slice(i + 1, objectterms.length)); + results = results.concat(this.performObjectSearch(objectterms[i], others)); + } + + // lookup as search terms in fulltext + results = results.concat(this.performTermsSearch(searchterms, excluded, terms, titleterms)); + + // let the scorer override scores with a custom scoring function + if (Scorer.score) { + for (i = 0; i < results.length; i++) + results[i][4] = Scorer.score(results[i]); + } + + // now sort the results by score (in opposite order of appearance, since the + // display function below uses pop() to retrieve items) and then + // alphabetically + results.sort(function (a, b) { + let left = a[4]; + let right = b[4]; + if (left > right) { + return 1; + } else if (left < right) { + return -1; + } else { + // same score: sort alphabetically + left = a[1].toLowerCase(); + right = b[1].toLowerCase(); + return (left > right) ? -1 : ((left < right) ? 1 : 0); + } + }); + + // for debugging + //Search.lastresults = results.slice(); // a copy + //console.info('search results:', Search.lastresults); + + const resultCount = results.length + + function displayNextItem() { + const doc_builder = DOCUMENTATION_OPTIONS.BUILDER + const docUrlRoot = DOCUMENTATION_OPTIONS.URL_ROOT + const docFileSuffix = DOCUMENTATION_OPTIONS.FILE_SUFFIX + const docLinkSuffix = DOCUMENTATION_OPTIONS.LINK_SUFFIX + const docHasSource = DOCUMENTATION_OPTIONS.HAS_SOURCE + + // results left, load the summary and display it + // this is intended to be dynamic (don't sub resultsCount) + if (results.length) { + const item = results.pop(); + + let listItem = document.createElement("li") + let requestUrl = ""; + let linkUrl = ""; + if (doc_builder === 'dirhtml') { + // dirhtml builder + let dirname = item[0] + '/'; + if (dirname.match(/\/index\/$/)) { + dirname = dirname.substring(0, dirname.length - 6); + } else if (dirname === 'index/') { + dirname = ''; + } + requestUrl = docUrlRoot + dirname; + linkUrl = requestUrl; + + } else { + // normal html builders + requestUrl = docUrlRoot + item[0] + docFileSuffix; + linkUrl = item[0] + docLinkSuffix; + } + let linkEl = document.createElement("a") + linkEl.href = linkUrl + highlightstring + item[2] + linkEl.innerHTML = item[1] + listItem.appendChild(linkEl) + if (item[3]) { + let spanEl = document.createElement("span") + spanEl.innerText = " (" + item[3] + ')' + listItem.appendChild(spanEl) + Search.output.appendChild(listItem); + setTimeout(() => displayNextItem(), 5) + } else if (docHasSource) { + fetch(requestUrl) + .then(responseData => responseData.text()) + .then(data => { + if (data !== '' && data !== undefined) { + listItem.appendChild(Search.makeSearchSummary(data, searchterms, hlterms)); + } + Search.output.appendChild(listItem); + setTimeout(() => displayNextItem(), 5) + }) + } else { + // no source available, just display title + Search.output.appendChild(listItem); + setTimeout(() => displayNextItem(), 5) + } + } + // search finished, update title and status message + else { + Search.stopPulse(); + Search.title.innerText = _('Search Results'); + if (!resultCount) + Search.status.innerText = _('Your search did not match any documents. Please make sure that all words are spelled correctly and that you\'ve selected enough categories.'); + else + Search.status.innerText = _('Search finished, found %s page(s) matching the search query.').replace('%s', resultCount); + } + } + displayNextItem(); + }, + + /** + * search for object names + */ + performObjectSearch: function (object, otherterms) { + const filenames = this._index.filenames; + const docnames = this._index.docnames; + const objects = this._index.objects; + const objnames = this._index.objnames; + const titles = this._index.titles; + + let i; + const results = []; + + for (let prefix in objects) { + for (let name in objects[prefix]) { + const fullname = (prefix ? prefix + '.' : '') + name; + const fullnameLower = fullname.toLowerCase(); + if (fullnameLower.indexOf(object) > -1) { + let score = 0; + const parts = fullnameLower.split('.'); + // check for different match types: exact matches of full name or + // "last name" (i.e. last dotted part) + if (fullnameLower == object || parts[parts.length - 1] == object) { + score += Scorer.objNameMatch; + // matches in last name + } else if (parts[parts.length - 1].indexOf(object) > -1) { + score += Scorer.objPartialMatch; + } + const match = objects[prefix][name]; + const objname = objnames[match[1]][2]; + const title = titles[match[0]]; + // If more than one term searched for, we require other words to be + // found in the name/title/description + if (otherterms.length > 0) { + const haystack = (prefix + ' ' + name + ' ' + + objname + ' ' + title).toLowerCase(); + let allfound = true; + for (i = 0; i < otherterms.length; i++) { + if (haystack.indexOf(otherterms[i]) == -1) { + allfound = false; + break; + } + } + if (!allfound) { + continue; + } + } + const descr = objname + _(', in ') + title; + + let anchor = match[3]; + if (anchor === '') + anchor = fullname; + else if (anchor == '-') + anchor = objnames[match[1]][1] + '-' + fullname; + // add custom score for some objects according to scorer + if (Scorer.objPrio.hasOwnProperty(match[2])) { + score += Scorer.objPrio[match[2]]; + } else { + score += Scorer.objPrioDefault; + } + results.push([docnames[match[0]], fullname, '#' + anchor, descr, score, filenames[match[0]]]); + } + } + } + + return results; + }, + + /** + * search for full-text terms in the index + */ + performTermsSearch: function (searchterms, excluded, terms, titleterms) { + const docnames = this._index.docnames; + const filenames = this._index.filenames; + const titles = this._index.titles; + + let i, j, file; + const fileMap = {}; + const scoreMap = {}; + const results = []; + + // perform the search on the required terms + for (i = 0; i < searchterms.length; i++) { + const word = searchterms[i]; + let files = []; + const _o = [ + {files: terms[word], score: Scorer.term}, + {files: titleterms[word], score: Scorer.title} + ]; + // add support for partial matches + if (word.length > 2) { + let w; + for (w in terms) { + if (w.match(word) && !terms[word]) { + _o.push({files: terms[w], score: Scorer.partialTerm}) + } + } + for (w in titleterms) { + if (w.match(word) && !titleterms[word]) { + _o.push({files: titleterms[w], score: Scorer.partialTitle}) + } + } + } + + // no match but word was a required one + if (_o.every(o => o.files === undefined)) { + break; + } + // found search word in contents + _o.forEach(o => { + let _files = o.files; + if (_files === undefined) + return + + if (_files.length === undefined) + _files = [_files]; + files = files.concat(_files); + + // set score for the word in each file to Scorer.term + for (j = 0; j < _files.length; j++) { + file = _files[j]; + if (!(file in scoreMap)) + scoreMap[file] = {}; + scoreMap[file][word] = o.score; + } + }); + + // create the mapping + for (j = 0; j < files.length; j++) { + file = files[j]; + if (file in fileMap && fileMap[file].indexOf(word) === -1) + fileMap[file].push(word); + else + fileMap[file] = [word]; + } + } + + // now check if the files don't contain excluded terms + for (file in fileMap) { + let valid = true; + + // check if all requirements are matched + const filteredTermCount = // as search terms with length < 3 are discarded: ignore + searchterms.filter(function (term) { + return term.length > 2 + }).length; + if ( + fileMap[file].length != searchterms.length && + fileMap[file].length != filteredTermCount + ) continue; + + // ensure that none of the excluded terms is in the search result + for (i = 0; i < excluded.length; i++) { + if (terms[excluded[i]] === file || + titleterms[excluded[i]] === file || + (terms[excluded[i]] || []).includes(file) || + (titleterms[excluded[i]] || []).includes(file)) { + valid = false; + break; + } + } + + // if we have still a valid result we can add it to the result list + if (valid) { + // select one (max) score for the file. + // for better ranking, we should calculate ranking by using words statistics like basic tf-idf... + const score = Math.max(...fileMap[file].map(w => scoreMap[file][w])) + results.push([docnames[file], titles[file], '', null, score, filenames[file]]); + } + } + return results; + }, + + /** + * helper function to return a node containing the + * search summary for a given text. keywords is a list + * of stemmed words, hlwords is the list of normal, unstemmed + * words. the first one is used to find the occurrence, the + * latter for highlighting it. + */ + makeSearchSummary: function (htmlText, keywords, hlwords) { + const text = Search.htmlToText(htmlText); + const textLower = text.toLowerCase(); + let start = 0; + keywords.forEach(keyword => { + const i = textLower.indexOf(keyword.toLowerCase()); + if (i > -1) + start = i; + }) + start = Math.max(start - 120, 0); + const excerpt = ((start > 0) ? '...' : '') + + text.substr(start, 240).trim() + + ((start + 240 - text.length) ? '...' : ''); + let contextEl = document.createElement("div") + contextEl.classList.add("context") + contextEl.innerText = excerpt + hlwords.forEach(hlword => { + contextEl = highlightText(hlword, 'highlighted', contextEl); + }) + return contextEl; + } +}; + +ready(() => { + Search.init(); +}); From a4f227aba88323e641b181adb0a601fad2cdb519 Mon Sep 17 00:00:00 2001 From: AA Turner <9087854+AA-Turner@users.noreply.github.com> Date: Sun, 21 Jun 2020 20:07:33 +0100 Subject: [PATCH 068/108] Core layout template --- pep_extensions/theme/layout.html | 62 +++++++++++++++++++++++++++----- 1 file changed, 53 insertions(+), 9 deletions(-) diff --git a/pep_extensions/theme/layout.html b/pep_extensions/theme/layout.html index 4b1a5bbc8d5..4e1b60a6bce 100644 --- a/pep_extensions/theme/layout.html +++ b/pep_extensions/theme/layout.html @@ -1,13 +1,57 @@ -{% extends "!layout.html" %} +{% extends "basic/layout.html" %} +{% set html_tag = '<html lang="en-GB" class="fontface">' %} +{%- if not embedded %} + {%- set titlesuffix = " | "|safe + docstitle|e %} +{%- else %} + {%- set titlesuffix = "" %} +{%- endif %} -{# Set the stylesheets #} -{% block linktags %} -{{ super() }} -<link href="https://www.python.org/static/stylesheets/style.css" rel="stylesheet"> -<link href="https://www.python.org/static/stylesheets/mq.css" rel="stylesheet"> -{% endblock %} +{%- block css %} + <link href="{{ pathto('_static/style.css', 1) }}" rel="stylesheet"> + <link href="{{ pathto('_static/mq.css', 1) }}" rel="stylesheet"> + <link href="{{ pathto('_static/pep.css', 1) }}" rel="stylesheet"> + <link rel="stylesheet" href="{{ pathto('_static/pygments.css', 1) }}" type="text/css" /> +{%- endblock %} -{# Set the delimiter after the short title on the rel-bar #} -{% set reldelim1 = ' 🡢' %} \ No newline at end of file +{%- block body_tag %}<body class="python pages pep-page">{% endblock %} +{%- block header %}<header style="height: 219px; background-color: #2b5b84;"></header>{% endblock %} +{%- block relbar1 %}{% endblock %} +{%- block relbar2 %}{% endblock %} +{%- block sidebar2 %}{% endblock %} +{%- block content %} + <div id="touchnav-wrapper"> + <div id="content" class="content-wrapper"> + {%- block document %} + <div class="container"> + {%- if render_sidebar %} + <section class="main-content with-left-sidebar"> + {%- endif %} + {% include "breadcrumbs.html" %} + <article class="text" role="main"> + {% block body %} {% endblock %} + </article> + {%- if render_sidebar %} + </section> + <aside class="left-sidebar" role="navigation"> + {%- if logo %} + <p class="logo"><a href="{{ pathto(master_doc)|e }}"> + <img class="logo" src="{{ pathto('_static/' + logo, 1)|e }}" alt="Logo"/> + </a></p> + {%- endif %} + {% include "customsidebar.html" %} + </aside> + {%- endif %} + </div> + {%- endblock %} + <div class="clearer"></div> + </div> + </div> +{%- endblock %} +{%- block footer %} +<footer> + <div style="height: 553.5px; background-color: #e6e8ea; border-top: 1px solid #d8dbde;"></div> + <div style="height: 103.05px; background-color: #2b5b84;"></div> +</footer> +{%- endblock %} \ No newline at end of file From 494db5c51b5d8298fa7267a813f89fb4df84d819 Mon Sep 17 00:00:00 2001 From: AA Turner <9087854+AA-Turner@users.noreply.github.com> Date: Sun, 21 Jun 2020 20:08:20 +0100 Subject: [PATCH 069/108] clear PEP styles --- pep_extensions/theme/static/pep.css | 344 ---------------------------- 1 file changed, 344 deletions(-) diff --git a/pep_extensions/theme/static/pep.css b/pep_extensions/theme/static/pep.css index d75dff1d89d..e69de29bb2d 100644 --- a/pep_extensions/theme/static/pep.css +++ b/pep_extensions/theme/static/pep.css @@ -1,344 +0,0 @@ -/* -:Author: David Goodger -:Contact: goodger@python.org -:date: $Date$ -:version: $Revision$ -:copyright: This stylesheet has been placed in the public domain. - -Default cascading style sheet for the PEP HTML output of Docutils. -*/ - -/* "! important" is used here to override other ``margin-top`` and - ``margin-bottom`` styles that are later in the stylesheet or - more specific. See http://www.w3.org/TR/CSS1#the-cascade */ -.first { - margin-top: 0 ! important } - -.last, .with-subtitle { - margin-bottom: 0 ! important } - -.hidden { - display: none } - -.navigation { - width: 100% ; - background: #99ccff ; - margin-top: 0px ; - margin-bottom: 0px } - -.navigation .navicon { - width: 150px ; - height: 35px } - -.navigation .textlinks { - padding-left: 1em ; - text-align: left } - -.navigation td, .navigation th { - padding-left: 0em ; - padding-right: 0em ; - vertical-align: middle } - -.rfc2822 { - margin-top: 0.5em ; - margin-left: 0.5em ; - margin-right: 0.5em ; - margin-bottom: 0em } - -.rfc2822 td { - text-align: left } - -.rfc2822 th.field-name { - text-align: right ; - font-family: sans-serif ; - padding-right: 0.5em ; - font-weight: bold ; - margin-bottom: 0em } - -a.toc-backref { - text-decoration: none ; - color: black } - -blockquote.epigraph { - margin: 2em 5em ; } - -body { - margin: 0px ; - margin-bottom: 1em ; - padding: 0px } - -dl.docutils dd { - margin-bottom: 0.5em } - -div.section { - margin-left: 1em ; - margin-right: 1em ; - margin-bottom: 1.5em } - -div.section div.section { - margin-left: 0em ; - margin-right: 0em ; - margin-top: 1.5em } - -div.abstract { - margin: 2em 5em } - -div.abstract p.topic-title { - font-weight: bold ; - text-align: center } - -div.admonition, div.attention, div.caution, div.danger, div.error, -div.hint, div.important, div.note, div.tip, div.warning { - margin: 2em ; - border: medium outset ; - padding: 1em } - -div.admonition p.admonition-title, div.hint p.admonition-title, -div.important p.admonition-title, div.note p.admonition-title, -div.tip p.admonition-title { - font-weight: bold ; - font-family: sans-serif } - -div.attention p.admonition-title, div.caution p.admonition-title, -div.danger p.admonition-title, div.error p.admonition-title, -div.warning p.admonition-title { - color: red ; - font-weight: bold ; - font-family: sans-serif } - -/* Uncomment (and remove this text!) to get reduced vertical space in - compound paragraphs. -div.compound .compound-first, div.compound .compound-middle { - margin-bottom: 0.5em } - -div.compound .compound-last, div.compound .compound-middle { - margin-top: 0.5em } -*/ - -div.dedication { - margin: 2em 5em ; - text-align: center ; - font-style: italic } - -div.dedication p.topic-title { - font-weight: bold ; - font-style: normal } - -div.figure { - margin-left: 2em ; - margin-right: 2em } - -div.footer, div.header { - clear: both; - font-size: smaller } - -div.footer { - margin-left: 1em ; - margin-right: 1em } - -div.line-block { - display: block ; - margin-top: 1em ; - margin-bottom: 1em } - -div.line-block div.line-block { - margin-top: 0 ; - margin-bottom: 0 ; - margin-left: 1.5em } - -div.sidebar { - margin-left: 1em ; - border: medium outset ; - padding: 1em ; - background-color: #ffffee ; - width: 40% ; - float: right ; - clear: right } - -div.sidebar p.rubric { - font-family: sans-serif ; - font-size: medium } - -div.system-messages { - margin: 5em } - -div.system-messages h1 { - color: red } - -div.system-message { - border: medium outset ; - padding: 1em } - -div.system-message p.system-message-title { - color: red ; - font-weight: bold } - -div.topic { - margin: 2em } - -h1.section-subtitle, h2.section-subtitle, h3.section-subtitle, -h4.section-subtitle, h5.section-subtitle, h6.section-subtitle { - margin-top: 0.4em } - -h1 { - font-family: sans-serif ; - font-size: large } - -h2 { - font-family: sans-serif ; - font-size: medium } - -h3 { - font-family: sans-serif ; - font-size: small } - -h4 { - font-family: sans-serif ; - font-style: italic ; - font-size: small } - -h5 { - font-family: sans-serif; - font-size: x-small } - -h6 { - font-family: sans-serif; - font-style: italic ; - font-size: x-small } - -hr.docutils { - width: 75% } - -img.align-left { - clear: left } - -img.align-right { - clear: right } - -img.borderless { - border: 0 } - -ol.simple, ul.simple { - margin-bottom: 1em } - -ol.arabic { - list-style: decimal } - -ol.loweralpha { - list-style: lower-alpha } - -ol.upperalpha { - list-style: upper-alpha } - -ol.lowerroman { - list-style: lower-roman } - -ol.upperroman { - list-style: upper-roman } - -p.attribution { - text-align: right ; - margin-left: 50% } - -p.caption { - font-style: italic } - -p.credits { - font-style: italic ; - font-size: smaller } - -p.label { - white-space: nowrap } - -p.rubric { - font-weight: bold ; - font-size: larger ; - color: maroon ; - text-align: center } - -p.sidebar-title { - font-family: sans-serif ; - font-weight: bold ; - font-size: larger } - -p.sidebar-subtitle { - font-family: sans-serif ; - font-weight: bold } - -p.topic-title { - font-family: sans-serif ; - font-weight: bold } - -pre.address { - margin-bottom: 0 ; - margin-top: 0 ; - font-family: serif ; - font-size: 100% } - -pre.literal-block, pre.doctest-block { - margin-left: 2em ; - margin-right: 2em } - -span.classifier { - font-family: sans-serif ; - font-style: oblique } - -span.classifier-delimiter { - font-family: sans-serif ; - font-weight: bold } - -span.interpreted { - font-family: sans-serif } - -span.option { - white-space: nowrap } - -span.option-argument { - font-style: italic } - -span.pre { - white-space: pre } - -span.problematic { - color: red } - -span.section-subtitle { - /* font-size relative to parent (h1..h6 element) */ - font-size: 80% } - -table.citation { - border-left: solid 1px gray; - margin-left: 1px } - -table.docinfo { - margin: 2em 4em } - -table.docutils { - margin-top: 0.5em ; - margin-bottom: 0.5em } - -table.footnote { - border-left: solid 1px black; - margin-left: 1px } - -table.docutils td, table.docutils th, -table.docinfo td, table.docinfo th { - padding-left: 0.5em ; - padding-right: 0.5em ; - vertical-align: top } - -td.num { - text-align: right } - -th.field-name { - font-weight: bold ; - text-align: left ; - white-space: nowrap ; - padding-left: 0 } - -h1 tt.docutils, h2 tt.docutils, h3 tt.docutils, -h4 tt.docutils, h5 tt.docutils, h6 tt.docutils { - font-size: 100% } - -ul.auto-toc { - list-style-type: none } From 9b668935ea8df7fdf264278c6c5a8cd5a708736b Mon Sep 17 00:00:00 2001 From: AA Turner <9087854+AA-Turner@users.noreply.github.com> Date: Sun, 21 Jun 2020 20:08:50 +0100 Subject: [PATCH 070/108] PEP style overrides --- pep_extensions/theme/static/pep.css | 256 ++++++++++++++++++++++++++++ 1 file changed, 256 insertions(+) diff --git a/pep_extensions/theme/static/pep.css b/pep_extensions/theme/static/pep.css index e69de29bb2d..8fc8168ebf0 100644 --- a/pep_extensions/theme/static/pep.css +++ b/pep_extensions/theme/static/pep.css @@ -0,0 +1,256 @@ +/* + +TODO: PEPify links +TODO: PSF callout + +Explicitly don't reformat syntax highlighting as per pydotorg as pydotorg doesn't have it + */ + +/* Generic PEP page formatting */ + +.pep-page pre { + padding: .5em; + background: inherit; + border-left: 0; + -webkit-box-shadow: 0 0 0 0; + -moz-box-shadow: 0 0 0 0; + box-shadow: 0 0 0 0; +} +.pep-page pre.literal-block { + background-color: #e6e8ea; + border: 1px solid #ddd; + padding: 1em; + -webkit-box-shadow: 0 0 1em rgba( 0, 0, 0, 0.2 ); + -moz-box-shadow: 0 0 1em rgba( 0, 0, 0, 0.2 ); + box-shadow: 0 0 1em rgba( 0, 0, 0, 0.2 ); +} + +/* PEP Header Blocks*/ + +dl { + background-color: #f6f6f6; + display: grid; + grid-template-columns: fit-content(30%) auto; + line-height: 1.875; + width: 100%; + border-collapse: collapse; + border-spacing: 0; + margin: 0; + padding: 0; + border: 0; +} + +dl.rfc2822 { + grid-template-columns: fit-content(30%) auto; +} + +dl.footnote { + grid-template-columns: fit-content(10%) auto; +} +.footnote .label{ + width: inherit; +} + +dl > dt { + width: inherit; + margin: 0; + border: 0; + text-align: left; + vertical-align: top; + padding: .25em .5em .2em; +} + +dl.rfc2822 > dt { + font-weight: 700; + background-color: #f0f0f0; +} + +dl.rfc2822 > dt:after { + content: ":"; +} + +dl.footnote > dt { + font-weight: normal; +} + +dl > dd { + padding: .25em .5em .2em; + border: 0; + border-left: 2px solid #fff; + margin: 0; + text-align: left; + vertical-align: top; +} + +dl.rfc2822 > dd:nth-of-type(even) { + background-color: #f0f0f0; +} + +/* Link formatting */ + +h1:hover > a.headerlink, +h2:hover > a.headerlink, +h3:hover > a.headerlink, +h4:hover > a.headerlink, +h5:hover > a.headerlink, +h6:hover > a.headerlink, +dt:hover > a.headerlink, +caption:hover > a.headerlink, +p.caption:hover > a.headerlink, +div.code-block-caption:hover > a.headerlink { + visibility: visible; +} + +a.headerlink { + visibility: hidden; +} + +a.brackets:before, +span.brackets > a:before{ + content: "["; +} + +a.brackets:after, +span.brackets > a:after { + content: "]"; +} + +/* Header Formatting*/ +/* We need to move all header formatting up a level (e.g. h2=h1, h3=h2 etc, except h1) */ +h2{ + margin-top: 1em; + margin-bottom: .25em; + font-size: 1.75em; + line-height: 1em; + font-weight: 700; +} + +h3 { + font-size: 1.5em; + margin-top: 1.3125em; + margin-bottom: .32813em; +} + +h4 { + font-size: 1.3125em; + margin-top: 1.75em; + font-weight: normal; +} + +/* Code formatting (code literals and Pygments highlighting blocks) */ + +div.highlight > pre { + padding: 1em; +} + +code.literal { + padding: 0; + margin: 0; + border-radius: 0; + box-shadow: none; + background: none; + color: #444; /* Same as body colour */ + display: inline; +} + +/* Sidebar formatting */ + +aside.left-sidebar { + overflow-y: scroll; + position: sticky; + top: 0; + padding-right: 0.5em; + height: 100vh; + scrollbar-width: thin; /* CSS Standards, not *yet* widely supported */ + scrollbar-color: #ccc transparent; +} +/* Chrome/Edge/Safari vendor prefixes */ +aside.left-sidebar::-webkit-scrollbar { + width: 6px; +} +aside.left-sidebar::-webkit-scrollbar-track { + background: transparent; +} +aside.left-sidebar::-webkit-scrollbar-thumb { + background: #ccc; +} + +aside h3 { + margin-top: 0.5em; + margin-bottom: 0; + font-size: 1.2em; +} + +aside > h6 { + text-align: center; + margin: 0; +} + +div.source-link { + margin-top: 0.25em; + font-weight: 700; +} + +form.search > input { + margin: 0; + border-radius: 3px; + text-shadow: none; + box-shadow: none; +} +form.search > input[type="text"] { + width: 85%; + padding: 0 2px; + cursor: text; +} +form.search > input[type="submit"] { + width: 12%; + padding: 0 6px; + border: 1px solid #caccce; + background: #ccc; + text-align: center; + vertical-align: middle; +} + +div.related > nav > ul { + display: flex; + justify-content: space-between; + margin-left: 0; +} + +aside ul { + margin-left: 1em; + line-height: 22px; +} + +/*####################################################################################*/ +/* Styles explicitly just for matching current pydotorg for visual regression testing */ +/*####################################################################################*/ + +dl.footnote { + background-color: inherit; +} + +dl.footnote > dt, +dl.footnote > dd{ + background-color: #f6f6f6; +} + +div#references > dl.footnote > dt, +div#references > dl.footnote > dd { + margin-bottom: 1.3125em; +} + +div#references > dl.footnote > dt:last-of-type, +div#references > dl.footnote > dd:last-of-type { + margin-bottom: 0; +} + +div.highlight > pre { + box-shadow: 0 0 1em rgba( 0, 0, 0, 0.2 ); + border: 1px solid transparent; +} + +code.literal { + font-family: "Courier New", monospace; + font-size: 12.1833px; +} \ No newline at end of file From cd22dd78b4276fb24810bfa0452b786a4f4c4746 Mon Sep 17 00:00:00 2001 From: AA Turner <9087854+AA-Turner@users.noreply.github.com> Date: Sun, 21 Jun 2020 20:09:04 +0100 Subject: [PATCH 071/108] Misc conf.py changes --- conf.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/conf.py b/conf.py index f68cf23b3a0..5ac0538e8d0 100644 --- a/conf.py +++ b/conf.py @@ -17,8 +17,7 @@ # The full version, including alpha/beta/rc tags # release = '1.0.0' -html_title = "Python Enhancement Proposals (PEPs)" -html_short_title = "PEPs Home" +html_title = "PEPs.Python.org" html_show_copyright = False html_show_sphinx = False template_bridge = "pep_extensions.pep_processor.pep_jinja2.PEPTemplateLoader" @@ -49,9 +48,13 @@ '.DS_Store', 'venv', 'build', + "_build", + "_build-old", + "package", 'README.rst', 'CONTRIBUTING.rst', 'requirements.txt', + "output.txt", ] # -- Options for HTML output ------------------------------------------------- From ae8f9010955848a393cd600c04d81aec40a0d7b4 Mon Sep 17 00:00:00 2001 From: AA Turner <9087854+AA-Turner@users.noreply.github.com> Date: Sun, 21 Jun 2020 21:12:49 +0100 Subject: [PATCH 072/108] Check translator class used by RTD --- pep_extensions/pep_processor/pep_html_translator.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pep_extensions/pep_processor/pep_html_translator.py b/pep_extensions/pep_processor/pep_html_translator.py index f4d45a347ea..8feaa6f0296 100644 --- a/pep_extensions/pep_processor/pep_html_translator.py +++ b/pep_extensions/pep_processor/pep_html_translator.py @@ -1,7 +1,8 @@ from docutils import nodes import sphinx.writers.html5 as html5 import re - +import logging +logger = logging.getLogger("sphinx") class PEPTranslator(html5.HTML5Translator): compact_field_list = True @@ -9,6 +10,7 @@ class PEPTranslator(html5.HTML5Translator): def __init__(self, *args): super(PEPTranslator, self).__init__(*args) + logger.warning("PEP Translator") self.compact_simple: bool = False # Omit <p> tags to produce visually compact lists From a7f3736846502bf391d98f23ba287688ff1a443f Mon Sep 17 00:00:00 2001 From: AA Turner <9087854+AA-Turner@users.noreply.github.com> Date: Mon, 22 Jun 2020 01:52:41 +0100 Subject: [PATCH 073/108] Add make clean option --- Makefile | 7 ++++++- conf.py | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index ee3d290a7f1..e30104c63aa 100644 --- a/Makefile +++ b/Makefile @@ -17,12 +17,17 @@ check_links: rss: $(PYTHON) pep2rss.py . +clean: + rm pep-0000.rst + rm *.html + rm -rf build + update: git pull https://github.com/python/peps.git venv: $(PYTHON) -m venv venv - ./venv/bin/python -m pip install -U docutils sphinx + ./venv/bin/python -m pip install -r requirements.txt package: all rss mkdir -p package/peps diff --git a/conf.py b/conf.py index 5ac0538e8d0..c5d4546670a 100644 --- a/conf.py +++ b/conf.py @@ -27,7 +27,7 @@ # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. -extensions = ["pep_extensions"] +extensions = ["pep_extensions", "sphinx.ext.githubpages"] # Add any paths that contain templates here, relative to this directory. templates_path = ['pep_extensions/theme'] From 47c5a669b521c747bf37a3131a8246da562268fe Mon Sep 17 00:00:00 2001 From: AA Turner <9087854+AA-Turner@users.noreply.github.com> Date: Mon, 22 Jun 2020 01:53:04 +0100 Subject: [PATCH 074/108] Add GH pages --- .github/workflows/deploy-gh-pages.yaml | 49 ++++++++++++++++++++++++++ .travis.yml | 17 +++++---- 2 files changed, 57 insertions(+), 9 deletions(-) create mode 100644 .github/workflows/deploy-gh-pages.yaml diff --git a/.github/workflows/deploy-gh-pages.yaml b/.github/workflows/deploy-gh-pages.yaml new file mode 100644 index 00000000000..2fa253d934b --- /dev/null +++ b/.github/workflows/deploy-gh-pages.yaml @@ -0,0 +1,49 @@ +name: Deploy to GitHub Pages +on: [push] +jobs: + deploy-to-pages: + runs-on: ubuntu-latest + steps: + # If you're using actions/checkout@v2 you must set persist-credentials to false in most cases for the deployment to work correctly. + - name: Checkout 🛎️ + uses: actions/checkout@v2 + with: + persist-credentials: false + + - name: Set up Python (3.7) 🐍 + uses: actions/setup-python@v2 + with: + python-version: 3.7 + + - name: Cache pip 🧳 + uses: actions/cache@v2 + with: + # This path is specific to Ubuntu + path: ~/.cache/pip + # Look to see if there is a cache hit for the corresponding requirements file + key: ${{ runner.os }}-pip-${{ hashFiles('requirements.txt') }} + restore-keys: | + ${{ runner.os }}-pip- + ${{ runner.os }}- + + # This example project is built using npm and outputs the result to the 'build' folder. + # Replace with the commands required to build your project, or remove this step entirely if your site is pre-built. + - name: Install and Build 🔧 + run: | + set -x + python -m pip install --upgrade pip + pip install -r requirements.txt + make sphinx + + - name: Deploy 🚀 + uses: JamesIves/github-pages-deploy-action@releases/v3 + with: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + BRANCH: gh-pages # The branch the action should deploy to. + FOLDER: build # The folder the action should deploy. + +# TODO enable build only on master +#on: +# push: +# branches: +# - master \ No newline at end of file diff --git a/.travis.yml b/.travis.yml index d21497097f0..593cb0a73ce 100644 --- a/.travis.yml +++ b/.travis.yml @@ -43,20 +43,19 @@ jobs: python: 3.8 env: - COMMAND="make fail_on_warning -j$(nproc)" - - FAIL_ALLOWED=true - # Checks link references within PEPs - - name: "3.8 Check Links" - python: 3.8 - env: - - COMMAND="make check_links -j$(nproc)" - - FAIL_ALLOWED=true +# linkcheck takes far too long (upwards of an hour) +# # Checks link references within PEPs +# - name: "3.8 Check Links" +# python: 3.8 +# env: +# - COMMAND="make check_links -j$(nproc)" allow_failures: # Note test failure, but pass the build as a whole - name: "3.8 Fail on Warning" - # Check links can fail as it is dependent on external pages - - name: "3.8 Check Links" +# # Check links can fail as it is dependent on external pages +# - name: "3.8 Check Links" script: $COMMAND \ No newline at end of file From 12a30adaacb955f69cbb0e7a16a6a7c1e38bf9ca Mon Sep 17 00:00:00 2001 From: AA Turner <9087854+AA-Turner@users.noreply.github.com> Date: Mon, 22 Jun 2020 02:38:25 +0100 Subject: [PATCH 075/108] Add index file --- .github/workflows/deploy-gh-pages.yaml | 2 +- Makefile | 3 +++ build.py | 18 ++++++++++++++++++ 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/.github/workflows/deploy-gh-pages.yaml b/.github/workflows/deploy-gh-pages.yaml index 2fa253d934b..bf7e615a189 100644 --- a/.github/workflows/deploy-gh-pages.yaml +++ b/.github/workflows/deploy-gh-pages.yaml @@ -33,7 +33,7 @@ jobs: set -x python -m pip install --upgrade pip pip install -r requirements.txt - make sphinx + make pages - name: Deploy 🚀 uses: JamesIves/github-pages-deploy-action@releases/v3 diff --git a/Makefile b/Makefile index e30104c63aa..68230d34e5c 100644 --- a/Makefile +++ b/Makefile @@ -5,6 +5,9 @@ all: sphinx PYTHON=python3 +pages: sphinx + $(PYTHON) build.py --index-file + sphinx: $(PYTHON) build.py diff --git a/build.py b/build.py index fb4f64ef353..17cdbf5de1d 100644 --- a/build.py +++ b/build.py @@ -1,5 +1,6 @@ # Build script for Sphinx documentation +import shutil import argparse from pathlib import Path from sphinx.application import Sphinx @@ -14,6 +15,7 @@ def create_parser(): ('-c', '--check-links', 'store_true'), ('-f', '--fail-on-warning', 'store_true'), ('-n', '--nitpicky', 'store_true'), + ("-i", "--index-file", "store_true") ] for arg in arguments: parser.add_argument(arg[0], arg[1], action=arg[2]) @@ -21,6 +23,19 @@ def create_parser(): return parser.parse_args() +def create_index_file(html_content: Path): + index_file = "index.html" + index = html_content / index_file + + pep_zero = html_content / "pep-0000.html" + # `dirhtml` builder pep 0 path: + pep_zero_dir_builder = pep_zero.with_suffix("").joinpath(index_file) + if pep_zero.is_file(): + shutil.copy(pep_zero, index) + elif pep_zero_dir_builder.is_file(): + shutil.copy(pep_zero_dir_builder, index) + + if __name__ == '__main__': args = create_parser() @@ -47,3 +62,6 @@ def create_parser(): ) app.builder.copysource = False # Prevent unneeded source copying - we link direct to VCS app.build() + + if args.index_file: + create_index_file(build_directory) From 754b684028fc2b2346965974ec2daa6032558089 Mon Sep 17 00:00:00 2001 From: AA Turner <9087854+AA-Turner@users.noreply.github.com> Date: Mon, 22 Jun 2020 04:02:09 +0100 Subject: [PATCH 076/108] Clean up RSS generation --- PyRSS2Gen.py | 456 ----------------------------------------------- pep2rss.py | 117 ++++++------ requirements.txt | 3 +- 3 files changed, 62 insertions(+), 514 deletions(-) delete mode 100644 PyRSS2Gen.py diff --git a/PyRSS2Gen.py b/PyRSS2Gen.py deleted file mode 100644 index 65c1f098307..00000000000 --- a/PyRSS2Gen.py +++ /dev/null @@ -1,456 +0,0 @@ -"""PyRSS2Gen - A Python library for generating RSS 2.0 feeds.""" - -__name__ = "PyRSS2Gen" -__version__ = (1, 1, 0) -__author__ = "Andrew Dalke <dalke@dalkescientific.com>" - -_generator_name = __name__ + "-" + ".".join(map(str, __version__)) - -import datetime - -import sys - -if sys.version_info[0] == 3: - # Python 3 - basestring = str - from io import StringIO -else: - # Python 2 - try: - from cStringIO import StringIO - except ImportError: - # Very old (or memory constrained) systems might - # have left out the compiled C version. Fall back - # to the pure Python one. Haven't seen this sort - # of system since the early 2000s. - from StringIO import StringIO - -# Could make this the base class; will need to add 'publish' -class WriteXmlMixin: - def write_xml(self, outfile, encoding = "iso-8859-1"): - from xml.sax import saxutils - handler = saxutils.XMLGenerator(outfile, encoding) - handler.startDocument() - self.publish(handler) - handler.endDocument() - - def to_xml(self, encoding = "iso-8859-1"): - f = StringIO() - self.write_xml(f, encoding) - return f.getvalue() - - -def _element(handler, name, obj, d = {}): - if isinstance(obj, basestring) or obj is None: - # special-case handling to make the API easier - # to use for the common case. - handler.startElement(name, d) - if obj is not None: - handler.characters(obj) - handler.endElement(name) - else: - # It better know how to emit the correct XML. - obj.publish(handler) - -def _opt_element(handler, name, obj): - if obj is None: - return - _element(handler, name, obj) - - -def _format_date(dt): - """convert a datetime into an RFC 822 formatted date - - Input date must be in GMT. - """ - # Looks like: - # Sat, 07 Sep 2002 00:00:01 GMT - # Can't use strftime because that's locale dependent - # - # Isn't there a standard way to do this for Python? The - # rfc822 and email.Utils modules assume a timestamp. The - # following is based on the rfc822 module. - return "%s, %02d %s %04d %02d:%02d:%02d GMT" % ( - ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"][dt.weekday()], - dt.day, - ["Jan", "Feb", "Mar", "Apr", "May", "Jun", - "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"][dt.month-1], - dt.year, dt.hour, dt.minute, dt.second) - - -## -# A couple simple wrapper objects for the fields which -# take a simple value other than a string. -class IntElement: - """implements the 'publish' API for integers - - Takes the tag name and the integer value to publish. - - (Could be used for anything which uses str() to be published - to text for XML.) - """ - element_attrs = {} - def __init__(self, name, val): - self.name = name - self.val = val - def publish(self, handler): - handler.startElement(self.name, self.element_attrs) - handler.characters(str(self.val)) - handler.endElement(self.name) - -class DateElement: - """implements the 'publish' API for a datetime.datetime - - Takes the tag name and the datetime to publish. - - Converts the datetime to RFC 2822 timestamp (4-digit year). - """ - def __init__(self, name, dt): - self.name = name - self.dt = dt - def publish(self, handler): - _element(handler, self.name, _format_date(self.dt)) -#### - -class Category: - """Publish a category element""" - def __init__(self, category, domain = None): - self.category = category - self.domain = domain - def publish(self, handler): - d = {} - if self.domain is not None: - d["domain"] = self.domain - _element(handler, "category", self.category, d) - -class Cloud: - """Publish a cloud""" - def __init__(self, domain, port, path, - registerProcedure, protocol): - self.domain = domain - self.port = port - self.path = path - self.registerProcedure = registerProcedure - self.protocol = protocol - def publish(self, handler): - _element(handler, "cloud", None, { - "domain": self.domain, - "port": str(self.port), - "path": self.path, - "registerProcedure": self.registerProcedure, - "protocol": self.protocol}) - -class Image: - """Publish a channel Image""" - element_attrs = {} - def __init__(self, url, title, link, - width = None, height = None, description = None): - self.url = url - self.title = title - self.link = link - self.width = width - self.height = height - self.description = description - - def publish(self, handler): - handler.startElement("image", self.element_attrs) - - _element(handler, "url", self.url) - _element(handler, "title", self.title) - _element(handler, "link", self.link) - - width = self.width - if isinstance(width, int): - width = IntElement("width", width) - _opt_element(handler, "width", width) - - height = self.height - if isinstance(height, int): - height = IntElement("height", height) - _opt_element(handler, "height", height) - - _opt_element(handler, "description", self.description) - - handler.endElement("image") - -class Guid: - """Publish a guid - - Defaults to being a permalink, which is the assumption if it's - omitted. Hence strings are always permalinks. - """ - def __init__(self, guid, isPermaLink = 1): - self.guid = guid - self.isPermaLink = isPermaLink - def publish(self, handler): - d = {} - if self.isPermaLink: - d["isPermaLink"] = "true" - else: - d["isPermaLink"] = "false" - _element(handler, "guid", self.guid, d) - -class TextInput: - """Publish a textInput - - Apparently this is rarely used. - """ - element_attrs = {} - def __init__(self, title, description, name, link): - self.title = title - self.description = description - self.name = name - self.link = link - - def publish(self, handler): - handler.startElement("textInput", self.element_attrs) - _element(handler, "title", self.title) - _element(handler, "description", self.description) - _element(handler, "name", self.name) - _element(handler, "link", self.link) - handler.endElement("textInput") - - -class Enclosure: - """Publish an enclosure""" - def __init__(self, url, length, type): - self.url = url - self.length = length - self.type = type - def publish(self, handler): - _element(handler, "enclosure", None, - {"url": self.url, - "length": str(self.length), - "type": self.type, - }) - -class Source: - """Publish the item's original source, used by aggregators""" - def __init__(self, name, url): - self.name = name - self.url = url - def publish(self, handler): - _element(handler, "source", self.name, {"url": self.url}) - -class SkipHours: - """Publish the skipHours - - This takes a list of hours, as integers. - """ - element_attrs = {} - def __init__(self, hours): - self.hours = hours - def publish(self, handler): - if self.hours: - handler.startElement("skipHours", self.element_attrs) - for hour in self.hours: - _element(handler, "hour", str(hour)) - handler.endElement("skipHours") - -class SkipDays: - """Publish the skipDays - - This takes a list of days as strings. - """ - element_attrs = {} - def __init__(self, days): - self.days = days - def publish(self, handler): - if self.days: - handler.startElement("skipDays", self.element_attrs) - for day in self.days: - _element(handler, "day", day) - handler.endElement("skipDays") - -class RSS2(WriteXmlMixin): - """The main RSS class. - - Stores the channel attributes, with the "category" elements under - ".categories" and the RSS items under ".items". - """ - - rss_attrs = {"version": "2.0"} - element_attrs = {} - def __init__(self, - title, - link, - description, - - language = None, - copyright = None, - managingEditor = None, - webMaster = None, - pubDate = None, # a datetime, *in* *GMT* - lastBuildDate = None, # a datetime - - categories = None, # list of strings or Category - generator = _generator_name, - docs = "http://blogs.law.harvard.edu/tech/rss", - cloud = None, # a Cloud - ttl = None, # integer number of minutes - - image = None, # an Image - rating = None, # a string; I don't know how it's used - textInput = None, # a TextInput - skipHours = None, # a SkipHours with a list of integers - skipDays = None, # a SkipDays with a list of strings - - items = None, # list of RSSItems - ): - self.title = title - self.link = link - self.description = description - self.language = language - self.copyright = copyright - self.managingEditor = managingEditor - - self.webMaster = webMaster - self.pubDate = pubDate - self.lastBuildDate = lastBuildDate - - if categories is None: - categories = [] - self.categories = categories - self.generator = generator - self.docs = docs - self.cloud = cloud - self.ttl = ttl - self.image = image - self.rating = rating - self.textInput = textInput - self.skipHours = skipHours - self.skipDays = skipDays - - if items is None: - items = [] - self.items = items - - def publish(self, handler): - handler.startElement("rss", self.rss_attrs) - handler.startElement("channel", self.element_attrs) - _element(handler, "title", self.title) - _element(handler, "link", self.link) - _element(handler, "description", self.description) - - self.publish_extensions(handler) - - _opt_element(handler, "language", self.language) - _opt_element(handler, "copyright", self.copyright) - _opt_element(handler, "managingEditor", self.managingEditor) - _opt_element(handler, "webMaster", self.webMaster) - - pubDate = self.pubDate - if isinstance(pubDate, datetime.datetime): - pubDate = DateElement("pubDate", pubDate) - _opt_element(handler, "pubDate", pubDate) - - lastBuildDate = self.lastBuildDate - if isinstance(lastBuildDate, datetime.datetime): - lastBuildDate = DateElement("lastBuildDate", lastBuildDate) - _opt_element(handler, "lastBuildDate", lastBuildDate) - - for category in self.categories: - if isinstance(category, basestring): - category = Category(category) - category.publish(handler) - - _opt_element(handler, "generator", self.generator) - _opt_element(handler, "docs", self.docs) - - if self.cloud is not None: - self.cloud.publish(handler) - - ttl = self.ttl - if isinstance(self.ttl, int): - ttl = IntElement("ttl", ttl) - _opt_element(handler, "ttl", ttl) - - if self.image is not None: - self.image.publish(handler) - - _opt_element(handler, "rating", self.rating) - if self.textInput is not None: - self.textInput.publish(handler) - if self.skipHours is not None: - self.skipHours.publish(handler) - if self.skipDays is not None: - self.skipDays.publish(handler) - - for item in self.items: - item.publish(handler) - - handler.endElement("channel") - handler.endElement("rss") - - def publish_extensions(self, handler): - # Derived classes can hook into this to insert - # output after the three required fields. - pass - - - -class RSSItem(WriteXmlMixin): - """Publish an RSS Item""" - element_attrs = {} - def __init__(self, - title = None, # string - link = None, # url as string - description = None, # string - author = None, # email address as string - categories = None, # list of string or Category - comments = None, # url as string - enclosure = None, # an Enclosure - guid = None, # a unique string - pubDate = None, # a datetime - source = None, # a Source - ): - - if title is None and description is None: - raise TypeError( - "must define at least one of 'title' or 'description'") - self.title = title - self.link = link - self.description = description - self.author = author - if categories is None: - categories = [] - self.categories = categories - self.comments = comments - self.enclosure = enclosure - self.guid = guid - self.pubDate = pubDate - self.source = source - # It sure does get tedious typing these names three times... - - def publish(self, handler): - handler.startElement("item", self.element_attrs) - _opt_element(handler, "title", self.title) - _opt_element(handler, "link", self.link) - self.publish_extensions(handler) - _opt_element(handler, "description", self.description) - _opt_element(handler, "author", self.author) - - for category in self.categories: - if isinstance(category, basestring): - category = Category(category) - category.publish(handler) - - _opt_element(handler, "comments", self.comments) - if self.enclosure is not None: - self.enclosure.publish(handler) - _opt_element(handler, "guid", self.guid) - - pubDate = self.pubDate - if isinstance(pubDate, datetime.datetime): - pubDate = DateElement("pubDate", pubDate) - _opt_element(handler, "pubDate", pubDate) - - if self.source is not None: - self.source.publish(handler) - - handler.endElement("item") - - def publish_extensions(self, handler): - # Derived classes can hook into this to insert - # output after the title and link elements - pass diff --git a/pep2rss.py b/pep2rss.py index 71e2c413c52..bfc81d60b58 100755 --- a/pep2rss.py +++ b/pep2rss.py @@ -1,74 +1,77 @@ -#!/usr/bin/env python3 - -# usage: pep-hook.py $REPOS $REV +# usage: pep2rss.py $REPOS $REV # (standard post-commit args) -import os, glob, time, datetime, stat, re, sys -import PyRSS2Gen as rssgen +import datetime +import re +from pathlib import Path + +from feedgen import entry +from feedgen import feed -RSS_PATH = os.path.join(sys.argv[1], 'peps.rss') def firstline_startingwith(full_path, text): - for line in open(full_path, encoding="utf-8"): + for line in full_path.open(encoding="utf-8"): if line.startswith(text): return line[len(text):].strip() return None -# get list of peps with creation time -# (from "Created:" string in pep .rst or .txt) -peps = glob.glob('pep-*.txt') -peps.extend(glob.glob('pep-*.rst')) + def pep_creation_dt(full_path): - created_str = firstline_startingwith(full_path, 'Created:') - # bleh, I was hoping to avoid re but some PEPs editorialize - # on the Created line - m = re.search(r'''(\d+-\w+-\d{4})''', created_str) + created_str = firstline_startingwith(full_path, "Created:") + # bleh, I was hoping to avoid re but some PEPs editorialize on the Created line + m = re.search(r"(\d+-\w+-\d{4})", created_str) if not m: - # some older ones have an empty line, that's okay, if it's old - # we ipso facto don't care about it. - # "return None" would make the most sense but datetime objects - # refuse to compare with that. :-| - return datetime.datetime(*time.localtime(0)[:6]) + # some older ones have an empty line, that's okay, if it's old we ipso facto don't care about it. + # "return None" would make the most sense but datetime objects refuse to compare with that. :-| + return datetime.datetime.fromtimestamp(0, tz=datetime.timezone.utc) created_str = m.group(1) try: - t = time.strptime(created_str, '%d-%b-%Y') + dt = datetime.datetime.strptime(created_str, "%d-%b-%Y") except ValueError: - t = time.strptime(created_str, '%d-%B-%Y') - return datetime.datetime(*t[:6]) -peps_with_dt = [(pep_creation_dt(full_path), full_path) for full_path in peps] -# sort peps by date, newest first -peps_with_dt.sort(reverse=True) + dt = datetime.datetime.strptime(created_str, "%d-%B-%Y") + return dt.replace(tzinfo=datetime.timezone.utc) -# generate rss items for 10 most recent peps -items = [] -for dt, full_path in peps_with_dt[:10]: - try: - n = int(full_path.split('-')[-1].split('.')[0]) - except ValueError: - pass - title = firstline_startingwith(full_path, 'Title:') - author = firstline_startingwith(full_path, 'Author:') - url = 'http://www.python.org/dev/peps/pep-%0.4d' % n - item = rssgen.RSSItem( - title = 'PEP %d: %s' % (n, title), - link = url, - description = 'Author: %s' % author, - guid = rssgen.Guid(url), - pubDate = dt) - items.append(item) -# the rss envelope -desc = """ -Newest Python Enhancement Proposals (PEPs) - Information on new -language features, and some meta-information like release -procedure and schedules -""".strip() -rss = rssgen.RSS2( - title = 'Newest Python PEPs', - link = 'http://www.python.org/dev/peps', - description = desc, - lastBuildDate = datetime.datetime.now(), - items = items) +def main(): + # get list of peps with creation time (from "Created:" string in pep source) + peps_with_dt = [(pep_creation_dt(path), path) for path in Path().glob("pep-????.*")] + peps_with_dt.sort(reverse=True) # sort peps by date, newest first + + # generate rss items for 10 most recent peps + items = [] + for dt, full_path in peps_with_dt[:10]: + try: + n = int(full_path.stem.split("-")[-1]) + except ValueError: + continue + title = firstline_startingwith(full_path, "Title:") + author = firstline_startingwith(full_path, "Author:") + url = f"http://www.python.org/dev/peps/pep-{n:0>4}" + item = entry.FeedEntry() + item.title(f"PEP {n}: {title}") + item.link(href=url) + item.description(f"Author: {author}") + item.guid(url, permalink=True) + item.pubDate(dt) + items.append(item) + + # the rss envelope + desc = """ + Newest Python Enhancement Proposals (PEPs) - Information on new + language features, and some meta-information like release + procedure and schedules + """.strip() + fg = feed.FeedGenerator() + fg.language('en') + fg.title('Newest Python PEPs') + fg.link(href='http://www.python.org/dev/peps') + fg.description(desc) + fg.lastBuildDate(datetime.datetime.now(tz=datetime.timezone.utc)) + for item in reversed(items): + fg.add_entry(item) + + Path("peps.rss").write_bytes(fg.rss_str()) + -with open(RSS_PATH, 'w', encoding="utf-8") as fp: - fp.write(rss.to_xml(encoding="utf-8")) +if __name__ == "__main__": + main() diff --git a/requirements.txt b/requirements.txt index 51ddbfe60bc..9ba2d10b98d 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,8 @@ # Requirements for building PEPs with Sphinx -sphinx >= 3.0.3 +sphinx >= 3.1.1 docutils >= 0.16 +feedgen >= 0.9.0 # For RSS feed # For packaging to current python.org standards bs4 From 3ab124acefeb07ccf534c781fbf8e9b1f6fd83cc Mon Sep 17 00:00:00 2001 From: AA Turner <9087854+AA-Turner@users.noreply.github.com> Date: Mon, 22 Jun 2020 04:03:26 +0100 Subject: [PATCH 077/108] Remove old pyramid files --- pep2pyramid.py | 555 ------------------------------------------- pyramid-pep-template | 6 - style.css | 19 -- 3 files changed, 580 deletions(-) delete mode 100755 pep2pyramid.py delete mode 100644 pyramid-pep-template delete mode 100644 style.css diff --git a/pep2pyramid.py b/pep2pyramid.py deleted file mode 100755 index e41891da0f2..00000000000 --- a/pep2pyramid.py +++ /dev/null @@ -1,555 +0,0 @@ -#!/usr/bin/env python -""" -Convert PEPs to (X)HTML fragments for Pyramid - courtesy of /F - -Usage: %(PROGRAM)s [options] [<peps> ...] - -Options: - --d <DIR>, --destdir <DIR> - Specify the base destination directory for Pyramid files. - Default: %(SERVER_DEST_DIR_BASE)s - --f, --force - Force the rebuilding of output files, regardless of modification times. - --k, --keep-going - Continue building past errors if possible. - --q, --quiet - Turn off verbose messages. - --h, --help - Print this help message and exit. - -The optional arguments ``peps`` are either pep numbers or .txt files. -""" - -import sys -import os -import codecs -import re -import cgi -import glob -import getopt -import errno -import random -import time -import shutil - -REQUIRES = {'python': '2.2', - 'docutils': '0.5'} -PROGRAM = sys.argv[0] -SERVER_DEST_DIR_BASE = ( - '/data/ftp.python.org/pub/beta.python.org/build/data/dev/peps') -RFCURL = 'http://www.faqs.org/rfcs/rfc%d.html' -PEPCVSURL = 'http://hg.python.org/peps/file/tip/pep-%04d.txt' -PEPDIRURL = '/dev/peps/' -PEPURL = PEPDIRURL + 'pep-%04d' -PEPANCHOR = '<a href="' + PEPURL + '">%i</a>' - - -LOCALVARS = "Local Variables:" - -COMMENT = """<!-- -This HTML is auto-generated. DO NOT EDIT THIS FILE! If you are writing a new -PEP, see http://www.python.org/dev/peps/pep-0001 for instructions and links -to templates. DO NOT USE THIS HTML FILE AS YOUR TEMPLATE! --->""" - -# The generated HTML doesn't validate -- you cannot use <hr> and <h3> inside -# <pre> tags. But if I change that, the result doesn't look very nice... - -fixpat = re.compile("((https?|ftp):[-_a-zA-Z0-9/.+~:?#$=&,]+)|(pep-\d+(.txt)?)|" - "(RFC[- ]?(?P<rfcnum>\d+))|" - "(PEP\s+(?P<pepnum>\d+))|" - ".") - -CONTENT_HTML = """\ -<n:invisible n:data="content" n:render="mapping"> -<div id="breadcrumb" n:data="breadcrumb" n:render="breadcrumb" /> -<n:slot name="text"></n:slot> -</n:invisible> -""" - -CONTENT_YML = """\ ---- !fragment -# Type of template to use -template: content.html - -# The data to pass to the template -local: - content: - breadcrumb: !breadcrumb nav.yml nav - text: !htmlfile body.html -""" - -INDEX_YML = """\ ---- !fragment -template: index.html -# The data to pass to the template -local: - title: "%s" - content: !fragment content.yml -""" - -EMPTYSTRING = '' -SPACE = ' ' -COMMASPACE = ', ' - - -class Settings: - - # defaults: - verbose = True - keep_going = False - force_rebuild = False - dest_dir_base = SERVER_DEST_DIR_BASE - -settings = Settings() - - - -def usage(code, msg=''): - """Print usage message and exit. Uses stderr if code != 0.""" - if code == 0: - out = sys.stdout - else: - out = sys.stderr - print >> out, __doc__ % globals() - if msg: - print >> out, msg - sys.exit(code) - - - -def fixanchor(current, match): - text = match.group(0) - link = None - if (text.startswith('http:') or text.startswith('https:') - or text.startswith('ftp:')): - # Strip off trailing punctuation. Pattern taken from faqwiz. - ltext = list(text) - while ltext: - c = ltext.pop() - if c not in '();:,.?\'"<>': - ltext.append(c) - break - link = EMPTYSTRING.join(ltext) - elif text.endswith('.txt') and text <> current: - link = PEPDIRURL + os.path.splitext(text)[0] + '/' + text - elif text.startswith('pep-') and text <> current: - link = os.path.splitext(text)[0] + ".html" - elif text.startswith('PEP'): - pepnum = int(match.group('pepnum')) - link = PEPURL % pepnum - elif text.startswith('RFC'): - rfcnum = int(match.group('rfcnum')) - link = RFCURL % rfcnum - if link: - return '<a href="%s">%s</a>' % (cgi.escape(link), cgi.escape(text)) - return cgi.escape(match.group(0)) # really slow, but it works... - - - -NON_MASKED_EMAILS = [ - 'peps@python.org', - 'python-list@python.org', - 'python-dev@python.org', - ] - -def fixemail(address, pepno): - if address.lower() in NON_MASKED_EMAILS: - # return hyperlinked version of email address - return linkemail(address, pepno) - else: - # return masked version of email address - parts = address.split('@', 1) - return '%s at %s' % (parts[0], parts[1]) - - -def linkemail(address, pepno): - parts = address.split('@', 1) - return ('<a href="mailto:%s@%s?subject=PEP%%20%s">' - '%s at %s</a>' - % (parts[0], parts[1], pepno, parts[0], parts[1])) - - -def fixfile(inpath, input_lines, outfile): - from email.Utils import parseaddr - basename = os.path.basename(inpath) - infile = iter(input_lines) - # head - header = [] - pep = "" - title = "" - for line in infile: - if not line.strip(): - break - if line[0].strip(): - if ":" not in line: - break - key, value = line.split(":", 1) - value = value.strip() - header.append((key, value)) - else: - # continuation line - key, value = header[-1] - value = value + line - header[-1] = key, value - if key.lower() == "title": - title = value - elif key.lower() == "pep": - pep = value - - if pep: - title = "PEP " + pep + " -- " + title - r = random.choice(range(64)) - print >> outfile, COMMENT - print >> outfile, '<div class="header">\n<table border="0" class="rfc2822">' - for k, v in header: - if k.lower() in ('author', 'bdfl-delegate', 'discussions-to'): - mailtos = [] - for part in re.split(',\s*', v): - if '@' in part: - realname, addr = parseaddr(part) - if k.lower() == 'discussions-to': - m = linkemail(addr, pep) - else: - m = fixemail(addr, pep) - mailtos.append('%s <%s>' % (realname, m)) - elif part.startswith('http:'): - mailtos.append( - '<a href="%s">%s</a>' % (part, part)) - else: - mailtos.append(part) - v = COMMASPACE.join(mailtos) - elif k.lower() in ('replaces', 'superseded-by', 'requires'): - otherpeps = '' - for otherpep in re.split(',?\s+', v): - otherpep = int(otherpep) - otherpeps += PEPANCHOR % (otherpep, otherpep) - v = otherpeps - elif k.lower() in ('last-modified',): - date = v or time.strftime('%Y-%m-%d', - time.localtime(os.stat(inpath)[8])) - if date.startswith('$' 'Date: ') and date.endswith(' $'): - date = date[6:-2] - if basename == 'pep-0000.txt': - v = date - else: - try: - url = PEPCVSURL % int(pep) - v = '<a href="%s">%s</a> ' % (url, cgi.escape(date)) - except ValueError, error: - v = date - elif k.lower() == 'content-type': - url = PEPURL % 9 - pep_type = v or 'text/plain' - v = '<a href="%s">%s</a> ' % (url, cgi.escape(pep_type)) - elif k.lower() == 'version': - if v.startswith('$' 'Revision: ') and v.endswith(' $'): - v = cgi.escape(v[11:-2]) - else: - v = cgi.escape(v) - print >> outfile, (' <tr><th class="field-name">%s: </th>' - '<td>%s</td></tr>' % (cgi.escape(k), v)) - print >> outfile, '</table>' - print >> outfile, '</div>' - need_pre = 1 - for line in infile: - if line[0] == '\f': - continue - if line.strip() == LOCALVARS: - break - if line[0].strip(): - if not need_pre: - print >> outfile, '</pre>' - print >> outfile, '<h3>%s</h3>' % line.strip() - need_pre = 1 - elif not line.strip() and need_pre: - continue - else: - # PEP 0 has some special treatment - if basename == 'pep-0000.txt': - parts = line.split() - if len(parts) > 1 and re.match(r'\s*\d{1,4}', parts[1]): - # This is a PEP summary line, which we need to hyperlink - url = PEPURL % int(parts[1]) - if need_pre: - print >> outfile, '<pre>' - need_pre = 0 - print >> outfile, re.sub( - parts[1], - '<a href="/dev/peps/pep-%04d/">%s</a>' % (int(parts[1]), - parts[1]), line, 1), - continue - elif parts and '@' in parts[-1]: - # This is a pep email address line, so filter it. - url = fixemail(parts[-1], pep) - if need_pre: - print >> outfile, '<pre>' - need_pre = 0 - print >> outfile, re.sub( - parts[-1], url, line, 1), - continue - line = fixpat.sub(lambda x, c=inpath: fixanchor(c, x), line) - if need_pre: - print >> outfile, '<pre>' - need_pre = 0 - outfile.write(line) - if not need_pre: - print >> outfile, '</pre>' - return title - - -docutils_settings = None -"""Runtime settings object used by Docutils. Can be set by the client -application when this module is imported.""" - -def fix_rst_pep(inpath, input_lines, outfile): - from docutils import core - from docutils.transforms.peps import Headers - Headers.pep_cvs_url = PEPCVSURL - parts = core.publish_parts( - source=''.join(input_lines), - source_path=inpath, - destination_path=outfile.name, - reader_name='pep', - parser_name='restructuredtext', - writer_name='pep_html', - settings=docutils_settings, - # Allow Docutils traceback if there's an exception: - settings_overrides={'traceback': 1}) - outfile.write(parts['whole']) - title = 'PEP %s -- %s' % (parts['pepnum'], parts['title'][0]) - return title - - -def get_pep_type(input_lines): - """ - Return the Content-Type of the input. "text/plain" is the default. - Return ``None`` if the input is not a PEP. - """ - pep_type = None - for line in input_lines: - line = line.rstrip().lower() - if not line: - # End of the RFC 2822 header (first blank line). - break - elif line.startswith('content-type: '): - pep_type = line.split()[1] or 'text/plain' - break - elif line.startswith('pep: '): - # Default PEP type, used if no explicit content-type specified: - pep_type = 'text/plain' - return pep_type - - -def get_input_lines(inpath): - try: - infile = codecs.open(inpath, 'r', 'utf-8') - except IOError, e: - if e.errno <> errno.ENOENT: raise - print >> sys.stderr, 'Error: Skipping missing PEP file:', e.filename - sys.stderr.flush() - return None, None - lines = infile.read().splitlines(1) # handles x-platform line endings - infile.close() - return lines - - -def find_pep(pep_str): - """Find the .txt file indicated by a cmd line argument""" - if os.path.exists(pep_str): - return pep_str - num = int(pep_str) - return "pep-%04d.txt" % num - -def make_html(inpath): - input_lines = get_input_lines(inpath) - pep_type = get_pep_type(input_lines) - if pep_type is None: - print >> sys.stderr, 'Error: Input file %s is not a PEP.' % inpath - sys.stdout.flush() - return None - elif not PEP_TYPE_DISPATCH.has_key(pep_type): - print >> sys.stderr, ('Error: Unknown PEP type for input file %s: %s' - % (inpath, pep_type)) - sys.stdout.flush() - return None - elif PEP_TYPE_DISPATCH[pep_type] == None: - pep_type_error(inpath, pep_type) - return None - destDir, needSvn, pepnum = set_up_pyramid(inpath) - outpath = os.path.join(destDir, 'body.html') - if ( not settings.force_rebuild - and (os.path.exists(outpath) - and os.stat(inpath).st_mtime <= os.stat(outpath).st_mtime)): - if settings.verbose: - print "Skipping %s (outfile up to date)"%(inpath) - return - if settings.verbose: - print inpath, "(%s)" % pep_type, "->", outpath - sys.stdout.flush() - outfile = codecs.open(outpath, "w", "utf-8") - title = PEP_TYPE_DISPATCH[pep_type](inpath, input_lines, outfile) - outfile.close() - os.chmod(outfile.name, 0664) - write_pyramid_index(destDir, title) - # for PEP 0, copy body to parent directory as well - if pepnum == '0000': - shutil.copyfile(outpath, os.path.join(destDir, '..', 'body.html')) - # apparently we need the index.yml as well to generate <title> right - shutil.copyfile(os.path.join(destDir, 'index.yml'), - os.path.join(destDir, '..', 'index.yml')) - copy_aux_files(inpath, destDir) - return outpath - -def set_up_pyramid(inpath): - m = re.search(r'pep-(\d+)\.', inpath) - if not m: - print >>sys.stderr, "Can't find PEP number in file name." - sys.exit(1) - pepnum = m.group(1) - destDir = os.path.join(settings.dest_dir_base, 'pep-%s' % pepnum) - - needSvn = 0 - if not os.path.exists(destDir): - needSvn = 1 - os.makedirs(destDir) - - # write content.html - foofilename = os.path.join(destDir, 'content.html') - fp = codecs.open(foofilename, 'w', 'utf-8') - fp.write(CONTENT_HTML) - fp.close() - os.chmod(foofilename, 0664) - - # write content.yml - foofilename = os.path.join(destDir, 'content.yml') - fp = codecs.open(foofilename, 'w', 'utf-8') - fp.write(CONTENT_YML) - os.chmod(foofilename, 0664) - return destDir, needSvn, pepnum - -def write_pyramid_index(destDir, title): - filename = os.path.join(destDir, 'index.yml') - fp = codecs.open(filename, 'w', 'utf-8') - title = title.replace('\\', '\\\\') # Escape existing backslashes - fp.write(INDEX_YML % title.replace('"', '\\"')) - fp.close() - os.chmod(filename, 0664) - -def copy_aux_files(pep_path, dest_dir): - """ - Copy auxiliary files whose names match 'pep-XXXX-*.*'. - """ - dirname, pepname = os.path.split(pep_path) - base, ext = os.path.splitext(pepname) - files = glob.glob(os.path.join(dirname, base) + '-*.*') - for path in files: - filename = os.path.basename(path) - dest_path = os.path.join(dest_dir, filename) - print '%s -> %s' % (path, dest_path) - shutil.copy(path, dest_path) - - - -PEP_TYPE_DISPATCH = {'text/plain': fixfile, - 'text/x-rst': fix_rst_pep} -PEP_TYPE_MESSAGES = {} - -def check_requirements(): - # Check Python: - try: - from email.Utils import parseaddr - except ImportError: - PEP_TYPE_DISPATCH['text/plain'] = None - PEP_TYPE_MESSAGES['text/plain'] = ( - 'Python %s or better required for "%%(pep_type)s" PEP ' - 'processing; %s present (%%(inpath)s).' - % (REQUIRES['python'], sys.version.split()[0])) - # Check Docutils: - try: - import docutils - except ImportError: - PEP_TYPE_DISPATCH['text/x-rst'] = None - PEP_TYPE_MESSAGES['text/x-rst'] = ( - 'Docutils not present for "%(pep_type)s" PEP file %(inpath)s. ' - 'See README.txt for installation.') - else: - installed = [int(part) for part in docutils.__version__.split('.')] - required = [int(part) for part in REQUIRES['docutils'].split('.')] - if installed < required: - PEP_TYPE_DISPATCH['text/x-rst'] = None - PEP_TYPE_MESSAGES['text/x-rst'] = ( - 'Docutils must be reinstalled for "%%(pep_type)s" PEP ' - 'processing (%%(inpath)s). Version %s or better required; ' - '%s present. See README.txt for installation.' - % (REQUIRES['docutils'], docutils.__version__)) - -def pep_type_error(inpath, pep_type): - print >> sys.stderr, 'Error: ' + PEP_TYPE_MESSAGES[pep_type] % locals() - sys.stdout.flush() - - -def build_peps(args=None): - if args: - filenames = pep_filename_generator(args) - else: - # do them all - filenames = glob.glob("pep-*.txt") - filenames.sort() - for filename in filenames: - try: - make_html(filename) - except (KeyboardInterrupt, SystemExit): - raise - except: - print "While building PEPs: %s" % filename - if settings.keep_going: - ee, ev, et = sys.exc_info() - traceback.print_exception(ee, ev, et, file=sys.stdout) - print "--keep-going/-k specified, continuing" - continue - else: - raise - -def pep_filename_generator(args): - for pep in args: - filename = find_pep(pep) - yield filename - - -def main(argv=None): - check_requirements() - - if argv is None: - argv = sys.argv[1:] - - try: - opts, args = getopt.getopt( - argv, 'hd:fkq', - ['help', 'destdir=', 'force', 'keep-going', 'quiet']) - except getopt.error, msg: - usage(1, msg) - - for opt, arg in opts: - if opt in ('-h', '--help'): - usage(0) - elif opt in ('-d', '--destdir'): - settings.dest_dir_base = arg - elif opt in ('-f', '--force'): - settings.force_rebuild = True - elif opt in ('-k', '--keep-going'): - settings.force_rebuild = True - elif opt in ('-q', '--quiet'): - settings.verbose = False - - build_peps(args) - - - -if __name__ == "__main__": - main() diff --git a/pyramid-pep-template b/pyramid-pep-template deleted file mode 100644 index f65a5ab5ea9..00000000000 --- a/pyramid-pep-template +++ /dev/null @@ -1,6 +0,0 @@ -<!-- -This HTML is auto-generated. DO NOT EDIT THIS FILE! If you are writing a new -PEP, see http://www.python.org/dev/peps/pep-0001 for instructions and links -to templates. DO NOT USE THIS HTML FILE AS YOUR TEMPLATE! ---> -%(body)s diff --git a/style.css b/style.css deleted file mode 100644 index 064fe688cfd..00000000000 --- a/style.css +++ /dev/null @@ -1,19 +0,0 @@ -body { margin: 0px; - padding: 0px; } -.navigation { width: 100%; - background: #99ccff; } -.navigation .navicon { width: 150px; - height: 35; } -.navigation .textlinks { padding-left: 1em; - text-align: left; } - -.header { margin-top: 0.5em; } -.header, .content { margin-left: 1em; - margin-right: 1em; } - -.header table td { text-align: left; } -.header table th { text-align: right; - font-family: sans-serif; - padding-right: 0.5em; } - -h3 { font-family: sans-serif; } From 1d1d8dbc548b2ac02ab7df5e89bfcf368e255fe8 Mon Sep 17 00:00:00 2001 From: AA Turner <9087854+AA-Turner@users.noreply.github.com> Date: Mon, 22 Jun 2020 04:08:48 +0100 Subject: [PATCH 078/108] Re-organise pep_processor --- conf.py | 2 +- pep_extensions/__init__.py | 6 +++--- .../pep_processor/{ => html}/pep_html_translator.py | 4 +--- pep_extensions/pep_processor/{ => html}/pep_jinja2.py | 0 pep_extensions/pep_processor/{ => parsing}/pep_parser.py | 8 ++++---- pep_extensions/pep_processor/{ => parsing}/pep_role.py | 0 .../pep_processor/{ => transforms}/pep_contents.py | 0 .../pep_processor/{ => transforms}/pep_footer.py | 0 .../pep_processor/{ => transforms}/pep_headers.py | 2 +- .../pep_processor/{ => transforms}/pep_title.py | 0 pep_extensions/pep_processor/{ => transforms}/pep_zero.py | 0 11 files changed, 10 insertions(+), 12 deletions(-) rename pep_extensions/pep_processor/{ => html}/pep_html_translator.py (97%) rename pep_extensions/pep_processor/{ => html}/pep_jinja2.py (100%) rename pep_extensions/pep_processor/{ => parsing}/pep_parser.py (64%) rename pep_extensions/pep_processor/{ => parsing}/pep_role.py (100%) rename pep_extensions/pep_processor/{ => transforms}/pep_contents.py (100%) rename pep_extensions/pep_processor/{ => transforms}/pep_footer.py (100%) rename pep_extensions/pep_processor/{ => transforms}/pep_headers.py (98%) rename pep_extensions/pep_processor/{ => transforms}/pep_title.py (100%) rename pep_extensions/pep_processor/{ => transforms}/pep_zero.py (100%) diff --git a/conf.py b/conf.py index c5d4546670a..e5f05c4c2f5 100644 --- a/conf.py +++ b/conf.py @@ -20,7 +20,7 @@ html_title = "PEPs.Python.org" html_show_copyright = False html_show_sphinx = False -template_bridge = "pep_extensions.pep_processor.pep_jinja2.PEPTemplateLoader" +template_bridge = "pep_extensions.pep_processor.html.pep_jinja2.PEPTemplateLoader" # -- General configuration --------------------------------------------------- diff --git a/pep_extensions/__init__.py b/pep_extensions/__init__.py index a929ca94dfa..e3b39ea4b6a 100644 --- a/pep_extensions/__init__.py +++ b/pep_extensions/__init__.py @@ -4,9 +4,9 @@ from docutils.writers.html5_polyglot import HTMLTranslator from pep_extensions.config import __version__ -from pep_extensions.pep_processor import pep_html_translator -from pep_extensions.pep_processor import pep_parser -from pep_extensions.pep_processor import pep_role +from pep_extensions.pep_processor.html import pep_html_translator +from pep_extensions.pep_processor.parsing import pep_parser +from pep_extensions.pep_processor.parsing import pep_role from pep_extensions.pepzero.generate_pep_index import create_pep_zero diff --git a/pep_extensions/pep_processor/pep_html_translator.py b/pep_extensions/pep_processor/html/pep_html_translator.py similarity index 97% rename from pep_extensions/pep_processor/pep_html_translator.py rename to pep_extensions/pep_processor/html/pep_html_translator.py index 8feaa6f0296..f4d45a347ea 100644 --- a/pep_extensions/pep_processor/pep_html_translator.py +++ b/pep_extensions/pep_processor/html/pep_html_translator.py @@ -1,8 +1,7 @@ from docutils import nodes import sphinx.writers.html5 as html5 import re -import logging -logger = logging.getLogger("sphinx") + class PEPTranslator(html5.HTML5Translator): compact_field_list = True @@ -10,7 +9,6 @@ class PEPTranslator(html5.HTML5Translator): def __init__(self, *args): super(PEPTranslator, self).__init__(*args) - logger.warning("PEP Translator") self.compact_simple: bool = False # Omit <p> tags to produce visually compact lists diff --git a/pep_extensions/pep_processor/pep_jinja2.py b/pep_extensions/pep_processor/html/pep_jinja2.py similarity index 100% rename from pep_extensions/pep_processor/pep_jinja2.py rename to pep_extensions/pep_processor/html/pep_jinja2.py diff --git a/pep_extensions/pep_processor/pep_parser.py b/pep_extensions/pep_processor/parsing/pep_parser.py similarity index 64% rename from pep_extensions/pep_processor/pep_parser.py rename to pep_extensions/pep_processor/parsing/pep_parser.py index be87d6ff109..ef3dd4f73ad 100644 --- a/pep_extensions/pep_processor/pep_parser.py +++ b/pep_extensions/pep_processor/parsing/pep_parser.py @@ -1,9 +1,9 @@ from sphinx import parsers -from pep_extensions.pep_processor import pep_headers -from pep_extensions.pep_processor import pep_title -from pep_extensions.pep_processor import pep_contents -from pep_extensions.pep_processor import pep_footer +from pep_extensions.pep_processor.transforms import pep_headers +from pep_extensions.pep_processor.transforms import pep_title +from pep_extensions.pep_processor.transforms import pep_contents +from pep_extensions.pep_processor.transforms import pep_footer class PEPParser(parsers.RSTParser): diff --git a/pep_extensions/pep_processor/pep_role.py b/pep_extensions/pep_processor/parsing/pep_role.py similarity index 100% rename from pep_extensions/pep_processor/pep_role.py rename to pep_extensions/pep_processor/parsing/pep_role.py diff --git a/pep_extensions/pep_processor/pep_contents.py b/pep_extensions/pep_processor/transforms/pep_contents.py similarity index 100% rename from pep_extensions/pep_processor/pep_contents.py rename to pep_extensions/pep_processor/transforms/pep_contents.py diff --git a/pep_extensions/pep_processor/pep_footer.py b/pep_extensions/pep_processor/transforms/pep_footer.py similarity index 100% rename from pep_extensions/pep_processor/pep_footer.py rename to pep_extensions/pep_processor/transforms/pep_footer.py diff --git a/pep_extensions/pep_processor/pep_headers.py b/pep_extensions/pep_processor/transforms/pep_headers.py similarity index 98% rename from pep_extensions/pep_processor/pep_headers.py rename to pep_extensions/pep_processor/transforms/pep_headers.py index 052a470dab6..2d65f768f13 100644 --- a/pep_extensions/pep_processor/pep_headers.py +++ b/pep_extensions/pep_processor/transforms/pep_headers.py @@ -5,7 +5,7 @@ from docutils import transforms from docutils.transforms import peps -from pep_extensions.pep_processor import pep_zero +from pep_extensions.pep_processor.transforms import pep_zero import pep_extensions.config pep_url = pep_extensions.config.pep_url diff --git a/pep_extensions/pep_processor/pep_title.py b/pep_extensions/pep_processor/transforms/pep_title.py similarity index 100% rename from pep_extensions/pep_processor/pep_title.py rename to pep_extensions/pep_processor/transforms/pep_title.py diff --git a/pep_extensions/pep_processor/pep_zero.py b/pep_extensions/pep_processor/transforms/pep_zero.py similarity index 100% rename from pep_extensions/pep_processor/pep_zero.py rename to pep_extensions/pep_processor/transforms/pep_zero.py From 819b0cbbe5ae3310f58240b4292c5d2928a5f1a9 Mon Sep 17 00:00:00 2001 From: AA Turner <9087854+AA-Turner@users.noreply.github.com> Date: Mon, 22 Jun 2020 04:25:00 +0100 Subject: [PATCH 079/108] Rename pep zero generator files for consistency --- pep_extensions/__init__.py | 2 +- .../pep_0_constants.py} | 0 .../pep_0_parser.py} | 8 +++--- .../pep_0_writer.py} | 26 +++++++++---------- .../pep_index_generator.py} | 10 +++---- 5 files changed, 23 insertions(+), 23 deletions(-) rename pep_extensions/{pepzero/pep0_constants.py => pep_zero_generator/pep_0_constants.py} (100%) rename pep_extensions/{pepzero/pep0.py => pep_zero_generator/pep_0_parser.py} (97%) rename pep_extensions/{pepzero/pep0_writer.py => pep_zero_generator/pep_0_writer.py} (92%) rename pep_extensions/{pepzero/generate_pep_index.py => pep_zero_generator/pep_index_generator.py} (85%) diff --git a/pep_extensions/__init__.py b/pep_extensions/__init__.py index e3b39ea4b6a..48c93ee0f26 100644 --- a/pep_extensions/__init__.py +++ b/pep_extensions/__init__.py @@ -7,7 +7,7 @@ from pep_extensions.pep_processor.html import pep_html_translator from pep_extensions.pep_processor.parsing import pep_parser from pep_extensions.pep_processor.parsing import pep_role -from pep_extensions.pepzero.generate_pep_index import create_pep_zero +from pep_extensions.pep_zero_generator.pep_index_generator import create_pep_zero # Monkeypatch StandaloneHTMLBuilder to not include JS libraries (underscore.js & jQuery) diff --git a/pep_extensions/pepzero/pep0_constants.py b/pep_extensions/pep_zero_generator/pep_0_constants.py similarity index 100% rename from pep_extensions/pepzero/pep0_constants.py rename to pep_extensions/pep_zero_generator/pep_0_constants.py diff --git a/pep_extensions/pepzero/pep0.py b/pep_extensions/pep_zero_generator/pep_0_parser.py similarity index 97% rename from pep_extensions/pepzero/pep0.py rename to pep_extensions/pep_zero_generator/pep_0_parser.py index 7ab4d852b7b..118b0235706 100644 --- a/pep_extensions/pepzero/pep0.py +++ b/pep_extensions/pep_zero_generator/pep_0_parser.py @@ -6,7 +6,7 @@ from email.parser import HeaderParser -from . import pep0_constants +from pep_extensions.pep_zero_generator import pep_0_constants class PEPError(Exception): @@ -255,9 +255,9 @@ def author_abbr(self): @property def title_abbr(self): """Shorten the title to be no longer than the max title length.""" - if len(self.title) <= pep0_constants.title_length: + if len(self.title) <= pep_0_constants.title_length: return self.title - wrapped_title = textwrap.wrap(self.title, pep0_constants.title_length - 4) + wrapped_title = textwrap.wrap(self.title, pep_0_constants.title_length - 4) return wrapped_title[0] + " ..." def __str__(self): @@ -269,4 +269,4 @@ def __str__(self): "status": self.status_abbr, "authors": self.author_abbr, } - return pep0_constants.column_format(**pep_info) + return pep_0_constants.column_format(**pep_info) diff --git a/pep_extensions/pepzero/pep0_writer.py b/pep_extensions/pep_zero_generator/pep_0_writer.py similarity index 92% rename from pep_extensions/pepzero/pep0_writer.py rename to pep_extensions/pep_zero_generator/pep_0_writer.py index 39345c477c4..847e3224655 100644 --- a/pep_extensions/pepzero/pep0_writer.py +++ b/pep_extensions/pep_zero_generator/pep_0_writer.py @@ -4,8 +4,8 @@ from operator import attrgetter -from . import pep0_constants -from . import pep0 +from pep_extensions.pep_zero_generator import pep_0_constants +from pep_extensions.pep_zero_generator import pep_0_parser # Type annotations from typing import List @@ -36,7 +36,7 @@ def emit_newline(self): self.output('') def emit_table_separator(self): - self.output(pep0_constants.table_separator) + self.output(pep_0_constants.table_separator) def emit_author_table_separator(self, max_name_len): author_table_separator = "=" * max_name_len + " " + "=" * len("email address") @@ -52,7 +52,7 @@ def emit_column_headers(self): "authors": "PEP Author(s)", } self.emit_table_separator() - self.output(pep0_constants.column_format(**column_headers)) + self.output(pep_0_constants.column_format(**column_headers)) self.emit_table_separator() @staticmethod @@ -99,7 +99,7 @@ def sort_peps(peps): elif pep.status == "Final": finished.append(pep) else: - raise pep0.PEPError(f"unsorted ({pep.type_}/{pep.status})", pep.filename, pep.number) + raise pep_0_parser.PEPError(f"unsorted ({pep.type_}/{pep.status})", pep.filename, pep.number) return meta, info, provisional, accepted, open_, finished, historical, deferred, dead @staticmethod @@ -132,7 +132,7 @@ def verify_email_addresses(peps): if too_many_emails: err_output = [] for author, emails in too_many_emails: - err_output.append(f" {author}: {emails}") + err_output.append(" " * 4 + f"{author}: {emails}") raise ValueError( "some authors have more than one email address listed:\n" + "\n".join(err_output) @@ -171,12 +171,12 @@ def write_pep0(self, peps: list): # PEP metadata today = datetime.date.today().strftime("%Y-%m-%d") - self.output(pep0_constants.header.format(last_modified=today)) + self.output(pep_0_constants.header.format(last_modified=today)) self.emit_newline() # Introduction self.emit_title("Introduction", "intro") - self.output(pep0_constants.intro) + self.output(pep_0_constants.intro) self.emit_newline() # PEPs by category @@ -219,7 +219,7 @@ def write_pep0(self, peps: list): self.emit_title("Reserved PEP Numbers", "reserved") self.emit_column_headers() for number, claimants in sorted(self.RESERVED): - self.output(pep0_constants.column_format(**{ + self.output(pep_0_constants.column_format(**{ "type": ".", "status": ".", "number": number, @@ -232,7 +232,7 @@ def write_pep0(self, peps: list): # PEP types key self.emit_title("PEP Types Key", "type-key") - for type_ in sorted(pep0.PEP.type_values): + for type_ in sorted(pep_0_parser.PEP.type_values): self.output(f" {type_[0]} - {type_} PEP") self.emit_newline() @@ -240,7 +240,7 @@ def write_pep0(self, peps: list): # PEP status key self.emit_title("PEP Status Key", "status-key") - for status in sorted(pep0.PEP.status_values): + for status in sorted(pep_0_parser.PEP.status_values): # Draft PEPs have no status displayed, Active shares a key with Accepted if status in ("Active", "Draft"): continue @@ -279,8 +279,8 @@ def write_pep0(self, peps: list): # References for introduction footnotes self.emit_title("References", "references") - self.output(pep0_constants.references) - self.output(pep0_constants.footer) + self.output(pep_0_constants.references) + self.output(pep_0_constants.footer) pep0_string = '\n'.join([str(s) for s in self._output]) return pep0_string diff --git a/pep_extensions/pepzero/generate_pep_index.py b/pep_extensions/pep_zero_generator/pep_index_generator.py similarity index 85% rename from pep_extensions/pepzero/generate_pep_index.py rename to pep_extensions/pep_zero_generator/pep_index_generator.py index 5933478e0f0..d076628e313 100644 --- a/pep_extensions/pepzero/generate_pep_index.py +++ b/pep_extensions/pep_zero_generator/pep_index_generator.py @@ -20,8 +20,8 @@ from operator import attrgetter from pathlib import Path -from . import pep0 -from . import pep0_writer +from pep_extensions.pep_zero_generator import pep_0_parser +from pep_extensions.pep_zero_generator import pep_0_writer def create_pep_zero(_, env, docnames): @@ -50,13 +50,13 @@ def create_pep_zero(_, env, docnames): if pep_pat.match(str(file_path)) and file_path.suffix in (".txt", ".rst"): file_path_absolute = path.joinpath(file_path).absolute() pep_text = file_path_absolute.read_text("UTF8") - pep = pep0.PEP(pep_text, file_path_absolute, author_data) + pep = pep_0_parser.PEP(pep_text, file_path_absolute, author_data) if pep.number != int(file_path.stem[4:]): - raise pep0.PEPError(f'PEP number does not match file name ({file_path})', file_path, pep.number) + raise pep_0_parser.PEPError(f'PEP number does not match file name ({file_path})', file_path, pep.number) peps.append(pep) peps.sort(key=attrgetter('number')) - pep_writer = pep0_writer.PEPZeroWriter() + pep_writer = pep_0_writer.PEPZeroWriter() pep0_text = pep_writer.write_pep0(peps) with open(pep_zero_filename + ".rst", 'w', encoding='UTF-8') as pep0_file: pep0_file.write(pep0_text) From 54b94fb222d1dea35831363c3d4f373cac5fa23d Mon Sep 17 00:00:00 2001 From: AA Turner <9087854+AA-Turner@users.noreply.github.com> Date: Mon, 22 Jun 2020 04:48:13 +0100 Subject: [PATCH 080/108] Reorganise pep theme --- conf.py | 2 +- pep_extensions/__init__.py | 2 +- pep_extensions/theme/static/{ => css}/mq.css | 0 pep_extensions/theme/static/{ => css}/pep.css | 0 pep_extensions/theme/static/{ => css}/style.css | 8 ++++---- .../theme/static/{ => fonts}/Flux-Regular.ttf | Bin .../SourceSansPro-Bold-webfont.be855452e565.woff | Bin .../SourceSansPro-It-webfont.1aa29ac0f190.woff | Bin .../SourceSansPro-Regular-webfont.fd0d51605201.woff | Bin pep_extensions/theme/static/{ => js}/doctools.js | 0 pep_extensions/theme/static/{ => js}/searchtools.js | 0 .../theme/{ => templates}/breadcrumbs.html | 0 .../theme/{ => templates}/customsidebar.html | 0 pep_extensions/theme/{ => templates}/layout.html | 6 +++--- pep_extensions/theme/{ => templates}/search.html | 0 15 files changed, 9 insertions(+), 9 deletions(-) rename pep_extensions/theme/static/{ => css}/mq.css (100%) rename pep_extensions/theme/static/{ => css}/pep.css (100%) rename pep_extensions/theme/static/{ => css}/style.css (99%) rename pep_extensions/theme/static/{ => fonts}/Flux-Regular.ttf (100%) rename pep_extensions/theme/static/{ => fonts}/SourceSansPro-Bold-webfont.be855452e565.woff (100%) rename pep_extensions/theme/static/{ => fonts}/SourceSansPro-It-webfont.1aa29ac0f190.woff (100%) rename pep_extensions/theme/static/{ => fonts}/SourceSansPro-Regular-webfont.fd0d51605201.woff (100%) rename pep_extensions/theme/static/{ => js}/doctools.js (100%) rename pep_extensions/theme/static/{ => js}/searchtools.js (100%) rename pep_extensions/theme/{ => templates}/breadcrumbs.html (100%) rename pep_extensions/theme/{ => templates}/customsidebar.html (100%) rename pep_extensions/theme/{ => templates}/layout.html (90%) rename pep_extensions/theme/{ => templates}/search.html (100%) diff --git a/conf.py b/conf.py index e5f05c4c2f5..5578a15199e 100644 --- a/conf.py +++ b/conf.py @@ -30,7 +30,7 @@ extensions = ["pep_extensions", "sphinx.ext.githubpages"] # Add any paths that contain templates here, relative to this directory. -templates_path = ['pep_extensions/theme'] +templates_path = ['pep_extensions/theme/templates'] # The file extensions of source files. Sphinx considers the files with # these suffixes as sources. diff --git a/pep_extensions/__init__.py b/pep_extensions/__init__.py index 48c93ee0f26..8bab6b59306 100644 --- a/pep_extensions/__init__.py +++ b/pep_extensions/__init__.py @@ -12,7 +12,7 @@ # Monkeypatch StandaloneHTMLBuilder to not include JS libraries (underscore.js & jQuery) def init_less_js(self) -> None: - js_files = [('doctools.js', {}), ('language_data.js', {}), ] + js_files = [('js/doctools.js', {}), ('js/language_data.js', {}), ] js_files.extend([*self.app.registry.js_files, *self.get_builder_config('js_files', 'html')]) js_files.append(('translations.js',) if self.config.language and self._get_translations_js() else (None, {})) for filename, attrs in js_files: diff --git a/pep_extensions/theme/static/mq.css b/pep_extensions/theme/static/css/mq.css similarity index 100% rename from pep_extensions/theme/static/mq.css rename to pep_extensions/theme/static/css/mq.css diff --git a/pep_extensions/theme/static/pep.css b/pep_extensions/theme/static/css/pep.css similarity index 100% rename from pep_extensions/theme/static/pep.css rename to pep_extensions/theme/static/css/pep.css diff --git a/pep_extensions/theme/static/style.css b/pep_extensions/theme/static/css/style.css similarity index 99% rename from pep_extensions/theme/static/style.css rename to pep_extensions/theme/static/css/style.css index 6ecebee69b6..f16888e1f88 100644 --- a/pep_extensions/theme/static/style.css +++ b/pep_extensions/theme/static/css/style.css @@ -2,24 +2,24 @@ /*@import url('https://fonts.googleapis.com/css2?family=Source+Sans+Pro:ital,wght@0,400;0,700;1,400&display=swap');*/ @font-face{ font-family: "Source Sans Pro"; - src:url("SourceSansPro-Regular-webfont.fd0d51605201.woff") format("woff"); + src:url("../fonts/SourceSansPro-Regular-webfont.fd0d51605201.woff") format("woff"); font-weight: normal; font-style: normal } @font-face{ font-family: "Source Sans Pro"; - src:url("SourceSansPro-Bold-webfont.be855452e565.woff") format("woff"); + src:url("../fonts/SourceSansPro-Bold-webfont.be855452e565.woff") format("woff"); font-weight: 700; font-style: normal } @font-face{font-family: "Source Sans Pro"; - src:url("SourceSansPro-It-webfont.1aa29ac0f190.woff") format("woff"); + src:url("../fonts/SourceSansPro-It-webfont.1aa29ac0f190.woff") format("woff"); font-weight: normal; font-style: italic } @font-face { font-family: 'Flux'; - src: url('Flux-Regular.ttf') format('truetype'); + src: url('../fonts/Flux-Regular.ttf') format('truetype'); font-weight: normal; font-style: normal; } diff --git a/pep_extensions/theme/static/Flux-Regular.ttf b/pep_extensions/theme/static/fonts/Flux-Regular.ttf similarity index 100% rename from pep_extensions/theme/static/Flux-Regular.ttf rename to pep_extensions/theme/static/fonts/Flux-Regular.ttf diff --git a/pep_extensions/theme/static/SourceSansPro-Bold-webfont.be855452e565.woff b/pep_extensions/theme/static/fonts/SourceSansPro-Bold-webfont.be855452e565.woff similarity index 100% rename from pep_extensions/theme/static/SourceSansPro-Bold-webfont.be855452e565.woff rename to pep_extensions/theme/static/fonts/SourceSansPro-Bold-webfont.be855452e565.woff diff --git a/pep_extensions/theme/static/SourceSansPro-It-webfont.1aa29ac0f190.woff b/pep_extensions/theme/static/fonts/SourceSansPro-It-webfont.1aa29ac0f190.woff similarity index 100% rename from pep_extensions/theme/static/SourceSansPro-It-webfont.1aa29ac0f190.woff rename to pep_extensions/theme/static/fonts/SourceSansPro-It-webfont.1aa29ac0f190.woff diff --git a/pep_extensions/theme/static/SourceSansPro-Regular-webfont.fd0d51605201.woff b/pep_extensions/theme/static/fonts/SourceSansPro-Regular-webfont.fd0d51605201.woff similarity index 100% rename from pep_extensions/theme/static/SourceSansPro-Regular-webfont.fd0d51605201.woff rename to pep_extensions/theme/static/fonts/SourceSansPro-Regular-webfont.fd0d51605201.woff diff --git a/pep_extensions/theme/static/doctools.js b/pep_extensions/theme/static/js/doctools.js similarity index 100% rename from pep_extensions/theme/static/doctools.js rename to pep_extensions/theme/static/js/doctools.js diff --git a/pep_extensions/theme/static/searchtools.js b/pep_extensions/theme/static/js/searchtools.js similarity index 100% rename from pep_extensions/theme/static/searchtools.js rename to pep_extensions/theme/static/js/searchtools.js diff --git a/pep_extensions/theme/breadcrumbs.html b/pep_extensions/theme/templates/breadcrumbs.html similarity index 100% rename from pep_extensions/theme/breadcrumbs.html rename to pep_extensions/theme/templates/breadcrumbs.html diff --git a/pep_extensions/theme/customsidebar.html b/pep_extensions/theme/templates/customsidebar.html similarity index 100% rename from pep_extensions/theme/customsidebar.html rename to pep_extensions/theme/templates/customsidebar.html diff --git a/pep_extensions/theme/layout.html b/pep_extensions/theme/templates/layout.html similarity index 90% rename from pep_extensions/theme/layout.html rename to pep_extensions/theme/templates/layout.html index 4e1b60a6bce..b019b23102a 100644 --- a/pep_extensions/theme/layout.html +++ b/pep_extensions/theme/templates/layout.html @@ -9,9 +9,9 @@ {%- block css %} - <link href="{{ pathto('_static/style.css', 1) }}" rel="stylesheet"> - <link href="{{ pathto('_static/mq.css', 1) }}" rel="stylesheet"> - <link href="{{ pathto('_static/pep.css', 1) }}" rel="stylesheet"> + <link href="{{ pathto('_static/css/style.css', 1) }}" rel="stylesheet"> + <link href="{{ pathto('_static/css/mq.css', 1) }}" rel="stylesheet"> + <link href="{{ pathto('_static/css/pep.css', 1) }}" rel="stylesheet"> <link rel="stylesheet" href="{{ pathto('_static/pygments.css', 1) }}" type="text/css" /> {%- endblock %} diff --git a/pep_extensions/theme/search.html b/pep_extensions/theme/templates/search.html similarity index 100% rename from pep_extensions/theme/search.html rename to pep_extensions/theme/templates/search.html From 126195ab3b219fa6a29974a663d74c1a3d65f6d3 Mon Sep 17 00:00:00 2001 From: AA Turner <9087854+AA-Turner@users.noreply.github.com> Date: Mon, 22 Jun 2020 04:52:14 +0100 Subject: [PATCH 081/108] Clean conf.py --- conf.py | 37 ++++++++++++------------------------- 1 file changed, 12 insertions(+), 25 deletions(-) diff --git a/conf.py b/conf.py index 5578a15199e..6aebd887c4f 100644 --- a/conf.py +++ b/conf.py @@ -2,31 +2,21 @@ # -- Path setup -------------------------------------------------------------- - import sys from pathlib import Path sys.path.extend(str(Path('./pep_extensions').absolute())) - # -- Project information ----------------------------------------------------- project = 'PEPs' copyright = '2020, PEP Authors' author = 'PEP Authors' -# The full version, including alpha/beta/rc tags -# release = '1.0.0' - -html_title = "PEPs.Python.org" -html_show_copyright = False -html_show_sphinx = False -template_bridge = "pep_extensions.pep_processor.html.pep_jinja2.PEPTemplateLoader" +master_doc = 'contents' # -- General configuration --------------------------------------------------- -# Add any Sphinx extension module names here, as strings. They can be -# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom -# ones. +# Add any Sphinx extension module names here, as strings. extensions = ["pep_extensions", "sphinx.ext.githubpages"] # Add any paths that contain templates here, relative to this directory. @@ -39,9 +29,8 @@ '.txt': 'pep', } -# List of patterns, relative to source directory, that match files and -# directories to ignore when looking for source files. -# This pattern also affects html_static_path and html_extra_path. +# List of patterns, relative to source directory, to ignore when +# looking for source files. exclude_patterns = [ '_build', 'Thumbs.db', @@ -59,16 +48,14 @@ # -- Options for HTML output ------------------------------------------------- -# The theme to use for HTML and HTML Help pages. See the documentation for -# a list of builtin themes. +# HTML output settings +html_math_renderer = "math2html" +html_show_copyright = False +html_show_sphinx = False +html_title = "PEPs.Python.org" -html_theme_path = ["pep_extensions"] +# Theme settings html_theme = "theme" +html_theme_path = ["pep_extensions"] html_favicon = Path(html_theme_path[0], html_theme, "static/py.png").as_posix() -html_math_renderer = "math2html" -# Add any paths that contain custom static files (such as style sheets) here, -# relative to this directory. They are copied after the builtin static files, -# so a file named "default.css" will overwrite the builtin "default.css". -# html_static_path = ['_static'] - -master_doc = 'contents' +template_bridge = "pep_extensions.pep_processor.html.pep_jinja2.PEPTemplateLoader" From 2dddd9ccdcb0d1a952a044b4d4e080ffcc3614ee Mon Sep 17 00:00:00 2001 From: AA Turner <9087854+AA-Turner@users.noreply.github.com> Date: Mon, 22 Jun 2020 18:48:49 +0100 Subject: [PATCH 082/108] Clean imports --- pep_extensions/pep_zero_generator/pep_0_parser.py | 6 +++--- pep_extensions/pep_zero_generator/pep_0_writer.py | 7 +------ pep_extensions/pep_zero_generator/pep_index_generator.py | 9 +++++++-- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/pep_extensions/pep_zero_generator/pep_0_parser.py b/pep_extensions/pep_zero_generator/pep_0_parser.py index 118b0235706..56c6d4938b5 100644 --- a/pep_extensions/pep_zero_generator/pep_0_parser.py +++ b/pep_extensions/pep_zero_generator/pep_0_parser.py @@ -3,10 +3,10 @@ import re import textwrap import unicodedata - +from email.message import Message from email.parser import HeaderParser - -from pep_extensions.pep_zero_generator import pep_0_constants +from pathlib import Path +from typing import List, Tuple class PEPError(Exception): diff --git a/pep_extensions/pep_zero_generator/pep_0_writer.py b/pep_extensions/pep_zero_generator/pep_0_writer.py index 847e3224655..87994c27e32 100644 --- a/pep_extensions/pep_zero_generator/pep_0_writer.py +++ b/pep_extensions/pep_zero_generator/pep_0_writer.py @@ -1,13 +1,8 @@ """Code to handle the output of PEP 0.""" import datetime import unicodedata - +from functools import partial from operator import attrgetter - -from pep_extensions.pep_zero_generator import pep_0_constants -from pep_extensions.pep_zero_generator import pep_0_parser - -# Type annotations from typing import List diff --git a/pep_extensions/pep_zero_generator/pep_index_generator.py b/pep_extensions/pep_zero_generator/pep_index_generator.py index d076628e313..958927dd914 100644 --- a/pep_extensions/pep_zero_generator/pep_index_generator.py +++ b/pep_extensions/pep_zero_generator/pep_index_generator.py @@ -15,14 +15,19 @@ to allow it to be processed as normal. """ -import re +from __future__ import annotations + import csv -from operator import attrgetter +import re from pathlib import Path +from typing import TYPE_CHECKING, List from pep_extensions.pep_zero_generator import pep_0_parser from pep_extensions.pep_zero_generator import pep_0_writer +if TYPE_CHECKING: + from sphinx.application import Sphinx + from sphinx.environment import BuildEnvironment def create_pep_zero(_, env, docnames): # app is unneeded by this function From 821615954749ffac919b459006d927a4b26f01f2 Mon Sep 17 00:00:00 2001 From: AA Turner <9087854+AA-Turner@users.noreply.github.com> Date: Mon, 22 Jun 2020 18:49:59 +0100 Subject: [PATCH 083/108] Modern class defs --- pep_extensions/pep_zero_generator/pep_0_parser.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/pep_extensions/pep_zero_generator/pep_0_parser.py b/pep_extensions/pep_zero_generator/pep_0_parser.py index 56c6d4938b5..f840f4c1cdf 100644 --- a/pep_extensions/pep_zero_generator/pep_0_parser.py +++ b/pep_extensions/pep_zero_generator/pep_0_parser.py @@ -28,8 +28,7 @@ class PEPParseError(PEPError): pass -class Author(object): - +class Author: """Represent PEP authors. Attributes: @@ -88,8 +87,7 @@ def sort_by(self): return unicodedata.normalize("NFKD", base) -class PEP(object): - +class PEP: """Representation of PEPs. Attributes: From cf7fae20dd42105cbf05392215666e14c3dd9df0 Mon Sep 17 00:00:00 2001 From: AA Turner <9087854+AA-Turner@users.noreply.github.com> Date: Mon, 22 Jun 2020 18:52:44 +0100 Subject: [PATCH 084/108] Type hints --- .../pep_zero_generator/pep_0_parser.py | 34 ++++++++----------- .../pep_zero_generator/pep_0_writer.py | 2 +- .../pep_zero_generator/pep_index_generator.py | 7 ++-- 3 files changed, 19 insertions(+), 24 deletions(-) diff --git a/pep_extensions/pep_zero_generator/pep_0_parser.py b/pep_extensions/pep_zero_generator/pep_0_parser.py index f840f4c1cdf..747b04f5763 100644 --- a/pep_extensions/pep_zero_generator/pep_0_parser.py +++ b/pep_extensions/pep_zero_generator/pep_0_parser.py @@ -17,15 +17,9 @@ def __init__(self, error, pep_file, pep_number=None): def __str__(self): error_msg = super(PEPError, self).__str__() - if self.number is not None: - return f"PEP {self.number}: {error_msg}" - else: - return f"({self.filename}): {error_msg}" - - -class PEPParseError(PEPError): - - pass + error_msg = f"({self.filename}): {error_msg}" + pep_str = f"PEP {self.number}" + return f"{pep_str} {error_msg}" if self.number is not None else error_msg class Author: @@ -56,16 +50,16 @@ class Author: The author's email address. """ - def __init__(self, author_and_email_tuple, authors_lookup): + def __init__(self, author_and_email_tuple: Tuple[str, str], authors_lookup: dict): """Parse the name and email address of an author.""" name, email = author_and_email_tuple - self.first_last = name.strip() - self.email = email.lower() + self.first_last: str = name.strip() + self.email: str = email.lower() name_dict = authors_lookup[self.first_last] - self.last_first = name_dict["Surname First"] - self.nick = name_dict["Name Reference"] + self.last_first: str = name_dict["Surname First"] + self.nick: str = name_dict["Name Reference"] def __hash__(self): return hash(self.first_last) @@ -74,7 +68,7 @@ def __eq__(self, other): return self.first_last == other.first_last @property - def sort_by(self): + def sort_by(self) -> str: last = self.last_first.split(",")[0] name_parts = last.split() for index, part in enumerate(name_parts): @@ -200,7 +194,7 @@ def __init__(self, pep_file: str, filename: str, author_lookup: dict): self.authors = [Author(author_email, author_lookup) for author_email in authors_and_emails] @staticmethod - def _parse_author(data): + def _parse_author(data: str) -> list: """Return a list of author names and emails.""" # XXX Consider using email.utils.parseaddr (doesn't work with names # lacking an email address. @@ -233,12 +227,12 @@ def _parse_author(data): return author_list @property - def type_abbr(self): + def type_abbr(self) -> str: """Return how the type is to be represented in the index.""" return self.type_[0].upper() @property - def status_abbr(self): + def status_abbr(self) -> str: """Return how the status should be represented in the index.""" if self.status in ("Draft", "Active"): return " " @@ -246,12 +240,12 @@ def status_abbr(self): return self.status[0].upper() @property - def author_abbr(self): + def author_abbr(self) -> str: """Return the author list as a comma-separated with only last names.""" return ", ".join(x.nick for x in self.authors) @property - def title_abbr(self): + def title_abbr(self) -> str: """Shorten the title to be no longer than the max title length.""" if len(self.title) <= pep_0_constants.title_length: return self.title diff --git a/pep_extensions/pep_zero_generator/pep_0_writer.py b/pep_extensions/pep_zero_generator/pep_0_writer.py index 87994c27e32..4422e5c9d39 100644 --- a/pep_extensions/pep_zero_generator/pep_0_writer.py +++ b/pep_extensions/pep_zero_generator/pep_0_writer.py @@ -162,7 +162,7 @@ def emit_pep_category(self, category, anchor, peps): self.emit_table_separator() self.emit_newline() - def write_pep0(self, peps: list): + def write_pep0(self, peps: List[pep_0_parser.PEP]): # PEP metadata today = datetime.date.today().strftime("%Y-%m-%d") diff --git a/pep_extensions/pep_zero_generator/pep_index_generator.py b/pep_extensions/pep_zero_generator/pep_index_generator.py index 958927dd914..fccba0ffaed 100644 --- a/pep_extensions/pep_zero_generator/pep_index_generator.py +++ b/pep_extensions/pep_zero_generator/pep_index_generator.py @@ -29,14 +29,15 @@ from sphinx.application import Sphinx from sphinx.environment import BuildEnvironment -def create_pep_zero(_, env, docnames): - # app is unneeded by this function + +def create_pep_zero(_: Sphinx, env: BuildEnvironment, docnames: list): + # Sphinx app object is unneeded by this function # Read from root directory path = Path('.') pep_zero_filename = 'pep-0000' - peps = [] + peps: List[pep_0_parser.PEP] = [] pep_pat = re.compile(r"pep-\d{4}") # Path.match() doesn't support regular expressions with open("AUTHORS.csv", "r", encoding="UTF8") as f: From 2e2cb32f80412975d20b9878dbdf07fd8144e73e Mon Sep 17 00:00:00 2001 From: AA Turner <9087854+AA-Turner@users.noreply.github.com> Date: Mon, 22 Jun 2020 18:56:17 +0100 Subject: [PATCH 085/108] Compile regex --- pep_extensions/pep_zero_generator/pep_0_parser.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/pep_extensions/pep_zero_generator/pep_0_parser.py b/pep_extensions/pep_zero_generator/pep_0_parser.py index 747b04f5763..8b24b93cf8c 100644 --- a/pep_extensions/pep_zero_generator/pep_0_parser.py +++ b/pep_extensions/pep_zero_generator/pep_0_parser.py @@ -193,19 +193,19 @@ def __init__(self, pep_file: str, filename: str, author_lookup: dict): raise PEPError("no authors found", filename, self.number) self.authors = [Author(author_email, author_lookup) for author_email in authors_and_emails] + angled = re.compile(r"(?P<author>.+?) <(?P<email>.+?)>(,\s*)?") + paren = re.compile(r"(?P<email>.+?) \((?P<author>.+?)\)(,\s*)?") + simple = re.compile(r"(?P<author>[^,]+)(,\s*)?") + @staticmethod def _parse_author(data: str) -> list: """Return a list of author names and emails.""" # XXX Consider using email.utils.parseaddr (doesn't work with names # lacking an email address. - angled = "(?P<author>.+?) <(?P<email>.+?)>" - paren = "(?P<email>.+?) \((?P<author>.+?)\)" - simple = "(?P<author>[^,]+)" + author_list = [] - for regex in (angled, paren, simple): - # Watch out for commas separating multiple names. - regex += r"(,\s*)?" - for match in re.finditer(regex, data): + for regex in (PEP.angled, PEP.paren, PEP.simple): + for match in regex.finditer(data): # Watch out for suffixes like 'Jr.' when they are comma-separated # from the name and thus cause issues when *all* names are only # separated by commas. From d30356d1f358009f960aee268de8ad68bb61d8af Mon Sep 17 00:00:00 2001 From: AA Turner <9087854+AA-Turner@users.noreply.github.com> Date: Mon, 22 Jun 2020 18:58:27 +0100 Subject: [PATCH 086/108] PEPError helper method --- .../pep_zero_generator/pep_0_parser.py | 29 +++++++++++-------- 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/pep_extensions/pep_zero_generator/pep_0_parser.py b/pep_extensions/pep_zero_generator/pep_0_parser.py index 8b24b93cf8c..b7cf20cf81a 100644 --- a/pep_extensions/pep_zero_generator/pep_0_parser.py +++ b/pep_extensions/pep_zero_generator/pep_0_parser.py @@ -123,6 +123,10 @@ class PEP: "Deferred", "Final", "Active", "Draft", "Superseded", ) + def raise_pep_error(self, msg: str, pep_num: bool = False) -> None: + pep_number = self.number if pep_num else None + raise PEPError(msg, self.filename, pep_number=pep_number) + def __init__(self, pep_file: str, filename: str, author_lookup: dict): """Init object from an open PEP file object.""" # Parse the headers. @@ -156,29 +160,30 @@ def __init__(self, pep_file: str, filename: str, author_lookup: dict): try: self.number = int(metadata["PEP"]) except ValueError: - raise PEPParseError("PEP number isn't an integer", filename) + self.raise_pep_error("PEP number isn't an integer") + # 'Title'. self.title = metadata["Title"] + # 'Type'. type_ = metadata["Type"] if type_ not in self.type_values: - raise PEPError(f"{type_} is not a valid Type value", filename, self.number) + self.raise_pep_error(f"{type_} is not a valid Type value", pep_num=True) self.type_ = type_ + # 'Status'. status = metadata["Status"] if status not in self.status_values: - if status == "April Fool!": - # See PEP 401 :) + if status == "April Fool!": # See PEP 401 :) status = "Rejected" else: - raise PEPError(f"{status} is not a valid Status value", filename, self.number) + self.raise_pep_error(f"{status} is not a valid Status value", pep_num=True) + # Special case for Active PEPs. if status == "Active" and self.type_ not in ("Process", "Informational"): - raise PEPError( - "Only Process and Informational PEPs may " "have an Active status", - filename, - self.number, - ) + msg = "Only Process and Informational PEPs may have an Active status" + self.raise_pep_error(msg, pep_num=True) + # Special case for Provisional PEPs. if status == "Provisional" and self.type_ != "Standards Track": raise PEPError( @@ -190,8 +195,8 @@ def __init__(self, pep_file: str, filename: str, author_lookup: dict): # 'Author'. authors_and_emails = self._parse_author(metadata["Author"]) if len(authors_and_emails) < 1: - raise PEPError("no authors found", filename, self.number) - self.authors = [Author(author_email, author_lookup) for author_email in authors_and_emails] + raise self.raise_pep_error("no authors found", pep_num=True) + self.authors = [Author(email, author_lookup) for email in authors_and_emails] angled = re.compile(r"(?P<author>.+?) <(?P<email>.+?)>(,\s*)?") paren = re.compile(r"(?P<email>.+?) \((?P<author>.+?)\)(,\s*)?") From d0e57e0e3833f1f613ba4d86e874f7a915205333 Mon Sep 17 00:00:00 2001 From: AA Turner <9087854+AA-Turner@users.noreply.github.com> Date: Mon, 22 Jun 2020 19:02:16 +0100 Subject: [PATCH 087/108] Functionise --- .../pep_zero_generator/pep_0_parser.py | 68 +++++++++---------- 1 file changed, 34 insertions(+), 34 deletions(-) diff --git a/pep_extensions/pep_zero_generator/pep_0_parser.py b/pep_extensions/pep_zero_generator/pep_0_parser.py index b7cf20cf81a..fc98caa12aa 100644 --- a/pep_extensions/pep_zero_generator/pep_0_parser.py +++ b/pep_extensions/pep_zero_generator/pep_0_parser.py @@ -127,35 +127,36 @@ def raise_pep_error(self, msg: str, pep_num: bool = False) -> None: pep_number = self.number if pep_num else None raise PEPError(msg, self.filename, pep_number=pep_number) - def __init__(self, pep_file: str, filename: str, author_lookup: dict): - """Init object from an open PEP file object.""" + def __init__(self, filename: Path, author_lookup: dict, title_length: int): + """Init object from an open PEP file object. + + pep_file is full text of the PEP file, filename is path of the PEP file, author_lookup is author exceptions file + + """ + self.filename: Path = filename + self.number: int = 0 + self.title: str = "" + self.type_: str = "" + self.status: str = "" + self.authors: List[Author] = [] + self.title_length: int = title_length + # Parse the headers. - self.filename = filename pep_parser = HeaderParser() - metadata = pep_parser.parsestr(pep_file) - header_order = iter(self.headers) - current_header = "" - try: - for header_name in metadata.keys(): - current_header, required = next(header_order) - while header_name != current_header and not required: - current_header, required = next(header_order) - if header_name != current_header: - raise PEPError( - "did not deal with " - f"{header_name} before having to handle {current_header}", - filename, - ) - except StopIteration: - raise PEPError("headers missing or out of order", filename) - required = False - try: - while not required: - current_header, required = next(header_order) - else: - raise PEPError(f"PEP is missing its '{current_header}' header", filename) - except StopIteration: - pass + pep_text = filename.read_text("UTF8") + metadata = pep_parser.parsestr(pep_text) + self.parse_pep(metadata) + self.parse_authors(metadata["Author"], author_lookup) + + if self.number != int(filename.stem[4:]): + self.raise_pep_error(f'PEP number does not match file name ({filename})', pep_num=True) + + def parse_pep(self, metadata: Message) -> None: + required_header_misses = set(t[0] for t in self.headers if t[1]) - set(metadata.keys()) + if required_header_misses: + msg = f"PEP is missing required headers ({', '.join(sorted(required_header_misses))})" + self.raise_pep_error(msg) + # 'PEP'. try: self.number = int(metadata["PEP"]) @@ -186,14 +187,13 @@ def __init__(self, pep_file: str, filename: str, author_lookup: dict): # Special case for Provisional PEPs. if status == "Provisional" and self.type_ != "Standards Track": - raise PEPError( - "Only Standards Track PEPs may " "have a Provisional status", - filename, - self.number, - ) + msg = "Only Standards Track PEPs may have a Provisional status" + self.raise_pep_error(msg, pep_num=True) self.status = status - # 'Author'. - authors_and_emails = self._parse_author(metadata["Author"]) + + def parse_authors(self, author_header: str, author_lookup: dict) -> None: + """Parse Author header line""" + authors_and_emails = self._parse_author(author_header) if len(authors_and_emails) < 1: raise self.raise_pep_error("no authors found", pep_num=True) self.authors = [Author(email, author_lookup) for email in authors_and_emails] From 771d24e3621dc587b19642e10e50eb7fdd490ccc Mon Sep 17 00:00:00 2001 From: AA Turner <9087854+AA-Turner@users.noreply.github.com> Date: Mon, 22 Jun 2020 19:03:28 +0100 Subject: [PATCH 088/108] Move constants --- .../pep_zero_generator/pep_0_constants.py | 46 ---------------- .../pep_zero_generator/pep_0_parser.py | 12 ++--- .../pep_zero_generator/pep_0_writer.py | 54 +++++++++++++++---- .../pep_zero_generator/pep_index_generator.py | 6 +-- 4 files changed, 51 insertions(+), 67 deletions(-) diff --git a/pep_extensions/pep_zero_generator/pep_0_constants.py b/pep_extensions/pep_zero_generator/pep_0_constants.py index 83bfe1b08eb..e69de29bb2d 100644 --- a/pep_extensions/pep_zero_generator/pep_0_constants.py +++ b/pep_extensions/pep_zero_generator/pep_0_constants.py @@ -1,46 +0,0 @@ -from functools import partial - -title_length = 55 -author_length = 40 -table_separator = "== ==== " + "="*title_length + " " + "="*author_length - -# column format is called as a function with a mapping containing field values -column_format = partial( - "{type}{status}{number: >5} {title: <{title_length}} {authors}".format, - title_length=title_length -) - -header = """\ -PEP: 0 -Title: Index of Python Enhancement Proposals (PEPs) -Version: N/A -Last-Modified: {last_modified} -Author: python-dev <python-dev@python.org> -Status: Active -Type: Informational -Content-Type: text/x-rst -Created: 13-Jul-2000 -""" - -intro = """\ -This PEP contains the index of all Python Enhancement Proposals, -known as PEPs. PEP numbers are assigned by the PEP editors, and -once assigned are never changed [1_]. The version control history [2_] of -the PEP texts represent their historical record. -""" - -references = """\ -.. [1] PEP 1: PEP Purpose and Guidelines -.. [2] View PEP history online: https://github.com/python/peps -""" - -footer = """\ -.. - Local Variables: - mode: indented-text - indent-tabs-mode: nil - sentence-end-double-space: t - fill-column: 70 - coding: utf-8 - End:\ -""" diff --git a/pep_extensions/pep_zero_generator/pep_0_parser.py b/pep_extensions/pep_zero_generator/pep_0_parser.py index fc98caa12aa..7f5060ff3f9 100644 --- a/pep_extensions/pep_zero_generator/pep_0_parser.py +++ b/pep_extensions/pep_zero_generator/pep_0_parser.py @@ -252,18 +252,18 @@ def author_abbr(self) -> str: @property def title_abbr(self) -> str: """Shorten the title to be no longer than the max title length.""" - if len(self.title) <= pep_0_constants.title_length: + if len(self.title) <= self.title_length: return self.title - wrapped_title = textwrap.wrap(self.title, pep_0_constants.title_length - 4) + wrapped_title = textwrap.wrap(self.title, self.title_length - 4) return wrapped_title[0] + " ..." - def __str__(self): + @property + def pep(self) -> dict: """Return the line entry for the PEP.""" - pep_info = { + return { "type": self.type_abbr, - "number": str(self.number), + "number": self.number, "title": self.title_abbr, "status": self.status_abbr, "authors": self.author_abbr, } - return pep_0_constants.column_format(**pep_info) diff --git a/pep_extensions/pep_zero_generator/pep_0_writer.py b/pep_extensions/pep_zero_generator/pep_0_writer.py index 4422e5c9d39..473697af39c 100644 --- a/pep_extensions/pep_zero_generator/pep_0_writer.py +++ b/pep_extensions/pep_zero_generator/pep_0_writer.py @@ -5,6 +5,41 @@ from operator import attrgetter from typing import List +from pep_extensions.pep_zero_generator import pep_0_parser + +title_length = 55 +author_length = 40 +table_separator = "== ==== " + "="*title_length + " " + "="*author_length + +# column format is called as a function with a mapping containing field values +column_format = partial( + "{type}{status}{number: >5} {title: <{title_length}} {authors}".format, + title_length=title_length +) + +header = f"""\ +PEP: 0 +Title: Index of Python Enhancement Proposals (PEPs) +Last-Modified: {datetime.date.today().strftime("%Y-%m-%d")} +Author: python-dev <python-dev@python.org> +Status: Active +Type: Informational +Content-Type: text/x-rst +Created: 13-Jul-2000 +""" + +intro = """\ +This PEP contains the index of all Python Enhancement Proposals, +known as PEPs. PEP numbers are assigned by the PEP editors, and +once assigned are never changed [1_]. The version control history [2_] of +the PEP texts represent their historical record. +""" + +references = """\ +.. [1] PEP 1: PEP Purpose and Guidelines +.. [2] View PEP history online: https://github.com/python/peps +""" + class PEPZeroWriter: # This is a list of reserved PEP numbers. Reservations are not to be used for @@ -31,7 +66,7 @@ def emit_newline(self): self.output('') def emit_table_separator(self): - self.output(pep_0_constants.table_separator) + self.output(table_separator) def emit_author_table_separator(self, max_name_len): author_table_separator = "=" * max_name_len + " " + "=" * len("email address") @@ -47,7 +82,7 @@ def emit_column_headers(self): "authors": "PEP Author(s)", } self.emit_table_separator() - self.output(pep_0_constants.column_format(**column_headers)) + self.output(column_format(**column_headers)) self.emit_table_separator() @staticmethod @@ -165,19 +200,17 @@ def emit_pep_category(self, category, anchor, peps): def write_pep0(self, peps: List[pep_0_parser.PEP]): # PEP metadata - today = datetime.date.today().strftime("%Y-%m-%d") - self.output(pep_0_constants.header.format(last_modified=today)) + self.output(header) self.emit_newline() # Introduction self.emit_title("Introduction", "intro") - self.output(pep_0_constants.intro) + self.output(intro) self.emit_newline() # PEPs by category self.emit_title("Index by Category", "by-category") - (meta, info, provisional, accepted, open_, - finished, historical, deferred, dead) = self.sort_peps(peps) + (meta, info, provisional, accepted, open_, finished, historical, deferred, dead) = self.sort_peps(peps) pep_categories = [ ("Meta-PEPs (PEPs about PEPs or Processes)", "by-category-meta", meta), ("Other Informational PEPs", "by-category-other-info", info), @@ -204,7 +237,7 @@ def write_pep0(self, peps: List[pep_0_parser.PEP]): for pep in peps: if pep.number - prev_pep > 1: self.emit_newline() - self.output(str(pep)) + self.output(column_format(**pep.pep)) prev_pep = pep.number self.emit_table_separator() @@ -214,7 +247,7 @@ def write_pep0(self, peps: List[pep_0_parser.PEP]): self.emit_title("Reserved PEP Numbers", "reserved") self.emit_column_headers() for number, claimants in sorted(self.RESERVED): - self.output(pep_0_constants.column_format(**{ + self.output(column_format(**{ "type": ".", "status": ".", "number": number, @@ -274,8 +307,7 @@ def write_pep0(self, peps: List[pep_0_parser.PEP]): # References for introduction footnotes self.emit_title("References", "references") - self.output(pep_0_constants.references) - self.output(pep_0_constants.footer) + self.output(references) pep0_string = '\n'.join([str(s) for s in self._output]) return pep0_string diff --git a/pep_extensions/pep_zero_generator/pep_index_generator.py b/pep_extensions/pep_zero_generator/pep_index_generator.py index fccba0ffaed..80774a60a08 100644 --- a/pep_extensions/pep_zero_generator/pep_index_generator.py +++ b/pep_extensions/pep_zero_generator/pep_index_generator.py @@ -39,6 +39,7 @@ def create_pep_zero(_: Sphinx, env: BuildEnvironment, docnames: list): pep_zero_filename = 'pep-0000' peps: List[pep_0_parser.PEP] = [] pep_pat = re.compile(r"pep-\d{4}") # Path.match() doesn't support regular expressions + title_length = pep_0_writer.title_length with open("AUTHORS.csv", "r", encoding="UTF8") as f: read = csv.DictReader(f, quotechar='"', skipinitialspace=True) @@ -55,10 +56,7 @@ def create_pep_zero(_: Sphinx, env: BuildEnvironment, docnames: list): continue # Skip pre-existing PEP 0 files if pep_pat.match(str(file_path)) and file_path.suffix in (".txt", ".rst"): file_path_absolute = path.joinpath(file_path).absolute() - pep_text = file_path_absolute.read_text("UTF8") - pep = pep_0_parser.PEP(pep_text, file_path_absolute, author_data) - if pep.number != int(file_path.stem[4:]): - raise pep_0_parser.PEPError(f'PEP number does not match file name ({file_path})', file_path, pep.number) + pep = pep_0_parser.PEP(file_path_absolute, author_data, title_length) peps.append(pep) peps.sort(key=attrgetter('number')) From 8e82d03a895e0186a5a01aabfd57223dfab302f7 Mon Sep 17 00:00:00 2001 From: AA Turner <9087854+AA-Turner@users.noreply.github.com> Date: Mon, 22 Jun 2020 19:04:10 +0100 Subject: [PATCH 089/108] Small changes to pep_zero_generator --- pep_extensions/pep_zero_generator/pep_0_constants.py | 0 pep_extensions/pep_zero_generator/pep_0_parser.py | 2 ++ pep_extensions/pep_zero_generator/pep_index_generator.py | 5 ++--- 3 files changed, 4 insertions(+), 3 deletions(-) delete mode 100644 pep_extensions/pep_zero_generator/pep_0_constants.py diff --git a/pep_extensions/pep_zero_generator/pep_0_constants.py b/pep_extensions/pep_zero_generator/pep_0_constants.py deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/pep_extensions/pep_zero_generator/pep_0_parser.py b/pep_extensions/pep_zero_generator/pep_0_parser.py index 7f5060ff3f9..e8df40598f0 100644 --- a/pep_extensions/pep_zero_generator/pep_0_parser.py +++ b/pep_extensions/pep_zero_generator/pep_0_parser.py @@ -65,6 +65,8 @@ def __hash__(self): return hash(self.first_last) def __eq__(self, other): + if not isinstance(other, Author): + return NotImplemented return self.first_last == other.first_last @property diff --git a/pep_extensions/pep_zero_generator/pep_index_generator.py b/pep_extensions/pep_zero_generator/pep_index_generator.py index 80774a60a08..6d7a915828c 100644 --- a/pep_extensions/pep_zero_generator/pep_index_generator.py +++ b/pep_extensions/pep_zero_generator/pep_index_generator.py @@ -58,12 +58,11 @@ def create_pep_zero(_: Sphinx, env: BuildEnvironment, docnames: list): file_path_absolute = path.joinpath(file_path).absolute() pep = pep_0_parser.PEP(file_path_absolute, author_data, title_length) peps.append(pep) - peps.sort(key=attrgetter('number')) + peps.sort(key=lambda pep: pep.number) pep_writer = pep_0_writer.PEPZeroWriter() pep0_text = pep_writer.write_pep0(peps) - with open(pep_zero_filename + ".rst", 'w', encoding='UTF-8') as pep0_file: - pep0_file.write(pep0_text) + Path(f"{pep_zero_filename}.rst").write_text(pep0_text, encoding='UTF-8') # Add to files for builder docnames.insert(1, pep_zero_filename) From 2385dedde189c94ec6e7f88bfaaea02a8bdcd171 Mon Sep 17 00:00:00 2001 From: AA Turner <9087854+AA-Turner@users.noreply.github.com> Date: Mon, 22 Jun 2020 19:06:28 +0100 Subject: [PATCH 090/108] Update excludes --- conf.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/conf.py b/conf.py index 6aebd887c4f..4a9b9583373 100644 --- a/conf.py +++ b/conf.py @@ -32,18 +32,18 @@ # List of patterns, relative to source directory, to ignore when # looking for source files. exclude_patterns = [ - '_build', + # Windows: 'Thumbs.db', '.DS_Store', + # Python: 'venv', + 'requirements.txt', + # Sphinx: 'build', - "_build", - "_build-old", - "package", + "output.txt", # Linkcheck output + # Project: 'README.rst', 'CONTRIBUTING.rst', - 'requirements.txt', - "output.txt", ] # -- Options for HTML output ------------------------------------------------- From 1822c19f45d17462d5f1411574646f59da3dcf10 Mon Sep 17 00:00:00 2001 From: AA Turner <9087854+AA-Turner@users.noreply.github.com> Date: Mon, 22 Jun 2020 19:20:34 +0100 Subject: [PATCH 091/108] Conf updates --- conf.py | 9 ++------- docutils.conf | 9 --------- 2 files changed, 2 insertions(+), 16 deletions(-) delete mode 100644 docutils.conf diff --git a/conf.py b/conf.py index 4a9b9583373..eb3371a4fe8 100644 --- a/conf.py +++ b/conf.py @@ -9,9 +9,6 @@ # -- Project information ----------------------------------------------------- project = 'PEPs' -copyright = '2020, PEP Authors' -author = 'PEP Authors' - master_doc = 'contents' # -- General configuration --------------------------------------------------- @@ -22,15 +19,13 @@ # Add any paths that contain templates here, relative to this directory. templates_path = ['pep_extensions/theme/templates'] -# The file extensions of source files. Sphinx considers the files with -# these suffixes as sources. +# The file extensions of source files. Sphinx uses these suffixes as sources. source_suffix = { '.rst': 'pep', '.txt': 'pep', } -# List of patterns, relative to source directory, to ignore when -# looking for source files. +# List of patterns (relative to source dir) to ignore when looking for source files. exclude_patterns = [ # Windows: 'Thumbs.db', diff --git a/docutils.conf b/docutils.conf deleted file mode 100644 index 9af15466166..00000000000 --- a/docutils.conf +++ /dev/null @@ -1,9 +0,0 @@ -# Configuration file for Docutils. -# See http://docutils.sf.net/docs/tools.html - -[general] -# path to PEPs, for template: [TODO REMOVE; UNNEEDED FOR SPHINX] -pep-home: /en/latest/ - -# base URL for PEP references (no host so mirrors work): -pep-base-url: From 1e30f640e9d5f774040256ce2d1b7fc999c090af Mon Sep 17 00:00:00 2001 From: AA Turner <9087854+AA-Turner@users.noreply.github.com> Date: Fri, 14 Aug 2020 20:44:55 +0100 Subject: [PATCH 092/108] Update sphinx version --- requirements.txt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/requirements.txt b/requirements.txt index 9ba2d10b98d..ebc4cfbe5a7 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,6 +1,5 @@ # Requirements for building PEPs with Sphinx - -sphinx >= 3.1.1 +sphinx >= 3.2.1 docutils >= 0.16 feedgen >= 0.9.0 # For RSS feed From 4b79aaf6d77ae4e727f13f0e449c908c838335f5 Mon Sep 17 00:00:00 2001 From: AA Turner <9087854+AA-Turner@users.noreply.github.com> Date: Fri, 14 Aug 2020 20:45:16 +0100 Subject: [PATCH 093/108] Remove unneeded files --- deploy.bash | 6 - pep2html.py | 709 ---------------------------------------------------- roman.py | 81 ------ 3 files changed, 796 deletions(-) delete mode 100755 deploy.bash delete mode 100755 pep2html.py delete mode 100644 roman.py diff --git a/deploy.bash b/deploy.bash deleted file mode 100755 index c4350fa6cb8..00000000000 --- a/deploy.bash +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/bash -set -ex -make package -pip install awscli -aws s3 cp --acl public-read build/peps.tar.gz s3://pythondotorg-assets-staging/peps.tar.gz -aws s3 cp --acl public-read build/peps.tar.gz s3://pythondotorg-assets/peps.tar.gz diff --git a/pep2html.py b/pep2html.py deleted file mode 100755 index e525d82299c..00000000000 --- a/pep2html.py +++ /dev/null @@ -1,709 +0,0 @@ -#!/usr/bin/env python -"""Convert PEPs to (X)HTML - courtesy of /F - -Usage: %(PROGRAM)s [options] [<peps> ...] - -Options: - --u, --user - python.org username - --b, --browse - After generating the HTML, direct your web browser to view it - (using the Python webbrowser module). If both -i and -b are - given, this will browse the on-line HTML; otherwise it will - browse the local HTML. If no pep arguments are given, this - will browse PEP 0. - --i, --install - After generating the HTML, install it and the plaintext source file - (.txt) on python.org. In that case the user's name is used in the scp - and ssh commands, unless "-u username" is given (in which case, it is - used instead). Without -i, -u is ignored. - --l, --local - Same as -i/--install, except install on the local machine. Use this - when logged in to the python.org machine (dinsdale). - --q, --quiet - Turn off verbose messages. - --h, --help - Print this help message and exit. - -The optional arguments ``peps`` are either pep numbers, .rst or .txt files. -""" - -from __future__ import print_function, unicode_literals - -import sys -import os -import re -import glob -import getopt -import errno -import random -import time -from io import open -try: - from html import escape -except ImportError: - from cgi import escape - -from docutils import core, nodes, utils -from docutils.readers import standalone -from docutils.transforms import peps, references, misc, frontmatter, Transform -from docutils.parsers import rst - -class DataError(Exception): - pass - -REQUIRES = {'python': '2.6', - 'docutils': '0.2.7'} -PROGRAM = sys.argv[0] -RFCURL = 'http://www.faqs.org/rfcs/rfc%d.html' -PEPURL = 'pep-%04d.html' -PEPCVSURL = ('https://hg.python.org/peps/file/tip/pep-%04d.txt') -PEPDIRRUL = 'http://www.python.org/peps/' - - -HOST = "dinsdale.python.org" # host for update -HDIR = "/data/ftp.python.org/pub/www.python.org/peps" # target host directory -LOCALVARS = "Local Variables:" - -COMMENT = """<!-- -This HTML is auto-generated. DO NOT EDIT THIS FILE! If you are writing a new -PEP, see http://www.python.org/peps/pep-0001.html for instructions and links -to templates. DO NOT USE THIS HTML FILE AS YOUR TEMPLATE! --->""" - -# The generated HTML doesn't validate -- you cannot use <hr> and <h3> inside -# <pre> tags. But if I change that, the result doesn't look very nice... -DTD = ('<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"\n' - ' "http://www.w3.org/TR/REC-html40/loose.dtd">') - -fixpat = re.compile(r"((https?|ftp):[-_a-zA-Z0-9/.+~:?#$=&,]+)|(pep-\d+(.txt|.rst)?)|" - r"(RFC[- ]?(?P<rfcnum>\d+))|" - r"(PEP\s+(?P<pepnum>\d+))|" - r".") - -EMPTYSTRING = '' -SPACE = ' ' -COMMASPACE = ', ' - - - -def usage(code, msg=''): - """Print usage message and exit. Uses stderr if code != 0.""" - if code == 0: - out = sys.stdout - else: - out = sys.stderr - print(__doc__ % globals(), file=out) - if msg: - print(msg, file=out) - sys.exit(code) - - - -def fixanchor(current, match): - text = match.group(0) - link = None - if (text.startswith('http:') or text.startswith('https:') - or text.startswith('ftp:')): - # Strip off trailing punctuation. Pattern taken from faqwiz. - ltext = list(text) - while ltext: - c = ltext.pop() - if c not in '''();:,.?'"<>''': - ltext.append(c) - break - link = EMPTYSTRING.join(ltext) - elif text.startswith('pep-') and text != current: - link = os.path.splitext(text)[0] + ".html" - elif text.startswith('PEP'): - pepnum = int(match.group('pepnum')) - link = PEPURL % pepnum - elif text.startswith('RFC'): - rfcnum = int(match.group('rfcnum')) - link = RFCURL % rfcnum - if link: - return '<a href="%s">%s</a>' % (escape(link), escape(text)) - return escape(match.group(0)) # really slow, but it works... - - - -NON_MASKED_EMAILS = [ - 'peps@python.org', - 'python-list@python.org', - 'python-dev@python.org', - ] - -def fixemail(address, pepno): - if address.lower() in NON_MASKED_EMAILS: - # return hyperlinked version of email address - return linkemail(address, pepno) - else: - # return masked version of email address - parts = address.split('@', 1) - return '%s at %s' % (parts[0], parts[1]) - - -def linkemail(address, pepno): - parts = address.split('@', 1) - return ('<a href="mailto:%s@%s?subject=PEP%%20%s">' - '%s at %s</a>' - % (parts[0], parts[1], pepno, parts[0], parts[1])) - - -def fixfile(inpath, input_lines, outfile): - try: - from email.Utils import parseaddr - except ImportError: - from email.utils import parseaddr - basename = os.path.basename(inpath) - infile = iter(input_lines) - # convert plaintext pep to minimal XHTML markup - print(DTD, file=outfile) - print('<html>', file=outfile) - print(COMMENT, file=outfile) - print('<head>', file=outfile) - # head - header = [] - pep = "" - title = "" - for line in infile: - if not line.strip(): - break - if line[0].strip(): - if ":" not in line: - break - key, value = line.split(":", 1) - value = value.strip() - header.append((key, value)) - else: - # continuation line - key, value = header[-1] - value = value + line - header[-1] = key, value - if key.lower() == "title": - title = value - elif key.lower() == "pep": - pep = value - if pep: - title = "PEP " + pep + " -- " + title - if title: - print(' <title>%s' % escape(title), file=outfile) - r = random.choice(list(range(64))) - print(( - ' \n' - '\n' - '\n' - '\n' - '\n' - '', file=outfile) - print('
\n', file=outfile) - for k, v in header: - if k.lower() in ('author', 'bdfl-delegate', 'discussions-to', 'sponsor'): - mailtos = [] - for part in re.split(r',\s*', v): - if '@' in part: - realname, addr = parseaddr(part) - if k.lower() == 'discussions-to': - m = linkemail(addr, pep) - else: - m = fixemail(addr, pep) - mailtos.append('%s <%s>' % (realname, m)) - elif part.startswith('http:'): - mailtos.append( - '%s' % (part, part)) - else: - mailtos.append(part) - v = COMMASPACE.join(mailtos) - elif k.lower() in ('replaces', 'superseded-by', 'requires'): - otherpeps = '' - for otherpep in re.split(r',?\s+', v): - otherpep = int(otherpep) - otherpeps += '%i ' % (otherpep, - otherpep) - v = otherpeps - elif k.lower() in ('last-modified',): - date = v or time.strftime('%d-%b-%Y', - time.localtime(os.stat(inpath)[8])) - if date.startswith('$' 'Date: ') and date.endswith(' $'): - date = date[6:-2] - if basename == 'pep-0000.txt': - v = date - else: - try: - url = PEPCVSURL % int(pep) - v = '%s ' % (url, escape(date)) - except ValueError as error: - v = date - elif k.lower() in ('content-type',): - url = PEPURL % 9 - pep_type = v or 'text/plain' - v = '%s ' % (url, escape(pep_type)) - elif k.lower() == 'version': - if v.startswith('$' 'Revision: ') and v.endswith(' $'): - v = escape(v[11:-2]) - else: - v = escape(v) - print(' ' \ - % (escape(k), v), file=outfile) - print('
%s: %s
', file=outfile) - print('
', file=outfile) - print('
', file=outfile) - print('
', file=outfile) - need_pre = 1 - for line in infile: - if line[0] == '\f': - continue - if line.strip() == LOCALVARS: - break - if line[0].strip(): - if not need_pre: - print('', file=outfile) - print('

%s

' % line.strip(), file=outfile) - need_pre = 1 - elif not line.strip() and need_pre: - continue - else: - # PEP 0 has some special treatment - if basename == 'pep-0000.txt': - parts = line.split() - if len(parts) > 1 and re.match(r'\s*\d{1,4}', parts[1]): - # This is a PEP summary line, which we need to hyperlink - url = PEPURL % int(parts[1]) - if need_pre: - print('
', file=outfile)
-                        need_pre = 0
-                    print(re.sub(
-                        parts[1],
-                        '%s' % (url, parts[1]),
-                        line, 1), end='', file=outfile)
-                    continue
-                elif parts and '@' in parts[-1]:
-                    # This is a pep email address line, so filter it.
-                    url = fixemail(parts[-1], pep)
-                    if need_pre:
-                        print('
', file=outfile)
-                        need_pre = 0
-                    print(re.sub(
-                        parts[-1], url, line, 1), end='', file=outfile)
-                    continue
-            line = fixpat.sub(lambda x, c=inpath: fixanchor(c, x), line)
-            if need_pre:
-                print('
', file=outfile)
-                need_pre = 0
-            outfile.write(line)
-    if not need_pre:
-        print('
', file=outfile) - print('
', file=outfile) - print('', file=outfile) - print('', file=outfile) - - -docutils_settings = None -"""Runtime settings object used by Docutils. Can be set by the client -application when this module is imported.""" - -class PEPHeaders(Transform): - - """ - Process fields in a PEP's initial RFC-2822 header. - """ - - default_priority = 360 - - pep_url = 'pep-%04d' - pep_cvs_url = PEPCVSURL - rcs_keyword_substitutions = ( - (re.compile(r'\$' r'RCSfile: (.+),v \$$', re.IGNORECASE), r'\1'), - (re.compile(r'\$[a-zA-Z]+: (.+) \$$'), r'\1'),) - - def apply(self): - if not len(self.document): - # @@@ replace these DataErrors with proper system messages - raise DataError('Document tree is empty.') - header = self.document[0] - if not isinstance(header, nodes.field_list) or \ - 'rfc2822' not in header['classes']: - raise DataError('Document does not begin with an RFC-2822 ' - 'header; it is not a PEP.') - pep = None - for field in header: - if field[0].astext().lower() == 'pep': # should be the first field - value = field[1].astext() - try: - pep = int(value) - cvs_url = self.pep_cvs_url % pep - except ValueError: - pep = value - cvs_url = None - msg = self.document.reporter.warning( - '"PEP" header must contain an integer; "%s" is an ' - 'invalid value.' % pep, base_node=field) - msgid = self.document.set_id(msg) - prb = nodes.problematic(value, value or '(none)', - refid=msgid) - prbid = self.document.set_id(prb) - msg.add_backref(prbid) - if len(field[1]): - field[1][0][:] = [prb] - else: - field[1] += nodes.paragraph('', '', prb) - break - if pep is None: - raise DataError('Document does not contain an RFC-2822 "PEP" ' - 'header.') - if pep == 0: - # Special processing for PEP 0. - pending = nodes.pending(peps.PEPZero) - self.document.insert(1, pending) - self.document.note_pending(pending) - if len(header) < 2 or header[1][0].astext().lower() != 'title': - raise DataError('No title!') - for field in header: - name = field[0].astext().lower() - body = field[1] - if len(body) > 1: - raise DataError('PEP header field body contains multiple ' - 'elements:\n%s' % field.pformat(level=1)) - elif len(body) == 1: - if not isinstance(body[0], nodes.paragraph): - raise DataError('PEP header field body may only contain ' - 'a single paragraph:\n%s' - % field.pformat(level=1)) - elif name == 'last-modified': - date = time.strftime( - '%d-%b-%Y', - time.localtime(os.stat(self.document['source'])[8])) - if cvs_url: - body += nodes.paragraph( - '', '', nodes.reference('', date, refuri=cvs_url)) - else: - # empty - continue - para = body[0] - if name in ('author', 'bdfl-delegate', 'sponsor'): - for node in para: - if isinstance(node, nodes.reference): - node.replace_self(peps.mask_email(node)) - elif name == 'discussions-to': - for node in para: - if isinstance(node, nodes.reference): - node.replace_self(peps.mask_email(node, pep)) - elif name in ('replaces', 'superseded-by', 'requires'): - newbody = [] - space = nodes.Text(' ') - for refpep in re.split(r',?\s+', body.astext()): - pepno = int(refpep) - newbody.append(nodes.reference( - refpep, refpep, - refuri=(self.document.settings.pep_base_url - + self.pep_url % pepno))) - newbody.append(space) - para[:] = newbody[:-1] # drop trailing space - elif name == 'last-modified': - utils.clean_rcs_keywords(para, self.rcs_keyword_substitutions) - if cvs_url: - date = para.astext() - para[:] = [nodes.reference('', date, refuri=cvs_url)] - elif name == 'content-type': - pep_type = para.astext() - uri = self.document.settings.pep_base_url + self.pep_url % 12 - para[:] = [nodes.reference('', pep_type, refuri=uri)] - elif name == 'version' and len(body): - utils.clean_rcs_keywords(para, self.rcs_keyword_substitutions) - -class PEPReader(standalone.Reader): - - supported = ('pep',) - """Contexts this reader supports.""" - - settings_spec = ( - 'PEP Reader Option Defaults', - 'The --pep-references and --rfc-references options (for the ' - 'reStructuredText parser) are on by default.', - ()) - - config_section = 'pep reader' - config_section_dependencies = ('readers', 'standalone reader') - - def get_transforms(self): - transforms = standalone.Reader.get_transforms(self) - # We have PEP-specific frontmatter handling. - transforms.remove(frontmatter.DocTitle) - transforms.remove(frontmatter.SectionSubTitle) - transforms.remove(frontmatter.DocInfo) - transforms.extend([PEPHeaders, peps.Contents, peps.TargetNotes]) - return transforms - - settings_default_overrides = {'pep_references': 1, 'rfc_references': 1} - - inliner_class = rst.states.Inliner - - def __init__(self, parser=None, parser_name=None): - """`parser` should be ``None``.""" - if parser is None: - parser = rst.Parser(rfc2822=True, inliner=self.inliner_class()) - standalone.Reader.__init__(self, parser, '') - - -def fix_rst_pep(inpath, input_lines, outfile): - output = core.publish_string( - source=''.join(input_lines), - source_path=inpath, - destination_path=outfile.name, - reader=PEPReader(), - parser_name='restructuredtext', - writer_name='pep_html', - settings=docutils_settings, - # Allow Docutils traceback if there's an exception: - settings_overrides={'traceback': 1, 'halt_level': 2}) - outfile.write(output.decode('utf-8')) - - -def get_pep_type(input_lines): - """ - Return the Content-Type of the input. "text/plain" is the default. - Return ``None`` if the input is not a PEP. - """ - pep_type = None - for line in input_lines: - line = line.rstrip().lower() - if not line: - # End of the RFC 2822 header (first blank line). - break - elif line.startswith('content-type: '): - pep_type = line.split()[1] or 'text/plain' - break - elif line.startswith('pep: '): - # Default PEP type, used if no explicit content-type specified: - pep_type = 'text/plain' - return pep_type - - -def get_input_lines(inpath): - try: - infile = open(inpath, encoding='utf-8') - except IOError as e: - if e.errno != errno.ENOENT: raise - print('Error: Skipping missing PEP file:', e.filename, file=sys.stderr) - sys.stderr.flush() - return None - lines = infile.read().splitlines(1) # handles x-platform line endings - infile.close() - return lines - - -def find_pep(pep_str): - """Find the .rst or .txt file indicated by a cmd line argument""" - if os.path.exists(pep_str): - return pep_str - num = int(pep_str) - rstpath = "pep-%04d.rst" % num - if os.path.exists(rstpath): - return rstpath - return "pep-%04d.txt" % num - -def make_html(inpath, verbose=0): - input_lines = get_input_lines(inpath) - if input_lines is None: - return None - pep_type = get_pep_type(input_lines) - if pep_type is None: - print('Error: Input file %s is not a PEP.' % inpath, file=sys.stderr) - sys.stdout.flush() - return None - elif pep_type not in PEP_TYPE_DISPATCH: - print(('Error: Unknown PEP type for input file %s: %s' - % (inpath, pep_type)), file=sys.stderr) - sys.stdout.flush() - return None - elif PEP_TYPE_DISPATCH[pep_type] == None: - pep_type_error(inpath, pep_type) - return None - outpath = os.path.splitext(inpath)[0] + ".html" - if verbose: - print(inpath, "(%s)" % pep_type, "->", outpath) - sys.stdout.flush() - outfile = open(outpath, "w", encoding='utf-8') - PEP_TYPE_DISPATCH[pep_type](inpath, input_lines, outfile) - outfile.close() - os.chmod(outfile.name, 0o664) - return outpath - -def push_pep(htmlfiles, txtfiles, username, verbose, local=0): - quiet = "" - if local: - if verbose: - quiet = "-v" - target = HDIR - copy_cmd = "cp" - chmod_cmd = "chmod" - else: - if not verbose: - quiet = "-q" - if username: - username = username + "@" - target = username + HOST + ":" + HDIR - copy_cmd = "scp" - chmod_cmd = "ssh %s%s chmod" % (username, HOST) - files = htmlfiles[:] - files.extend(txtfiles) - files.append("style.css") - files.append("pep.css") - filelist = SPACE.join(files) - rc = os.system("%s %s %s %s" % (copy_cmd, quiet, filelist, target)) - if rc: - sys.exit(rc) -## rc = os.system("%s 664 %s/*" % (chmod_cmd, HDIR)) -## if rc: -## sys.exit(rc) - - -PEP_TYPE_DISPATCH = {'text/plain': fixfile, - 'text/x-rst': fix_rst_pep} -PEP_TYPE_MESSAGES = {} - -def check_requirements(): - # Check Python: - # This is pretty much covered by the __future__ imports... - if sys.version_info < (2, 6, 0): - PEP_TYPE_DISPATCH['text/plain'] = None - PEP_TYPE_MESSAGES['text/plain'] = ( - 'Python %s or better required for "%%(pep_type)s" PEP ' - 'processing; %s present (%%(inpath)s).' - % (REQUIRES['python'], sys.version.split()[0])) - # Check Docutils: - try: - import docutils - except ImportError: - PEP_TYPE_DISPATCH['text/x-rst'] = None - PEP_TYPE_MESSAGES['text/x-rst'] = ( - 'Docutils not present for "%(pep_type)s" PEP file %(inpath)s. ' - 'See README.rst for installation.') - else: - installed = [int(part) for part in docutils.__version__.split('.')] - required = [int(part) for part in REQUIRES['docutils'].split('.')] - if installed < required: - PEP_TYPE_DISPATCH['text/x-rst'] = None - PEP_TYPE_MESSAGES['text/x-rst'] = ( - 'Docutils must be reinstalled for "%%(pep_type)s" PEP ' - 'processing (%%(inpath)s). Version %s or better required; ' - '%s present. See README.rst for installation.' - % (REQUIRES['docutils'], docutils.__version__)) - -def pep_type_error(inpath, pep_type): - print('Error: ' + PEP_TYPE_MESSAGES[pep_type] % locals(), file=sys.stderr) - sys.stdout.flush() - - -def browse_file(pep): - import webbrowser - file = find_pep(pep) - if file.startswith('pep-') and file.endswith((".txt", '.rst')): - file = file[:-3] + "html" - file = os.path.abspath(file) - url = "file:" + file - webbrowser.open(url) - -def browse_remote(pep): - import webbrowser - file = find_pep(pep) - if file.startswith('pep-') and file.endswith((".txt", '.rst')): - file = file[:-3] + "html" - url = PEPDIRRUL + file - webbrowser.open(url) - - -def main(argv=None): - # defaults - update = 0 - local = 0 - username = '' - verbose = 1 - browse = 0 - - check_requirements() - - if argv is None: - argv = sys.argv[1:] - - try: - opts, args = getopt.getopt( - argv, 'bilhqu:', - ['browse', 'install', 'local', 'help', 'quiet', 'user=']) - except getopt.error as msg: - usage(1, msg) - - for opt, arg in opts: - if opt in ('-h', '--help'): - usage(0) - elif opt in ('-i', '--install'): - update = 1 - elif opt in ('-l', '--local'): - update = 1 - local = 1 - elif opt in ('-u', '--user'): - username = arg - elif opt in ('-q', '--quiet'): - verbose = 0 - elif opt in ('-b', '--browse'): - browse = 1 - - if args: - pep_list = [] - html = [] - for pep in args: - file = find_pep(pep) - pep_list.append(file) - newfile = make_html(file, verbose=verbose) - if newfile: - html.append(newfile) - if browse and not update: - browse_file(pep) - else: - # do them all - pep_list = [] - html = [] - files = glob.glob("pep-*.txt") + glob.glob("pep-*.rst") - files.sort() - for file in files: - pep_list.append(file) - newfile = make_html(file, verbose=verbose) - if newfile: - html.append(newfile) - if browse and not update: - browse_file("0") - - if update: - push_pep(html, pep_list, username, verbose, local=local) - if browse: - if args: - for pep in args: - browse_remote(pep) - else: - browse_remote("0") - - - -if __name__ == "__main__": - main() diff --git a/roman.py b/roman.py deleted file mode 100644 index 394a43ae9cb..00000000000 --- a/roman.py +++ /dev/null @@ -1,81 +0,0 @@ -"""Convert to and from Roman numerals""" - -__author__ = "Mark Pilgrim (f8dy@diveintopython.org)" -__version__ = "1.4" -__date__ = "8 August 2001" -__copyright__ = """Copyright (c) 2001 Mark Pilgrim - -This program is part of "Dive Into Python", a free Python tutorial for -experienced programmers. Visit http://diveintopython.org/ for the -latest version. - -This program is free software; you can redistribute it and/or modify -it under the terms of the Python 2.1.1 license, available at -http://www.python.org/2.1.1/license.html -""" - -import re - -# Define exceptions -class RomanError(Exception): pass -class OutOfRangeError(RomanError): pass -class NotIntegerError(RomanError): pass -class InvalidRomanNumeralError(RomanError): pass - -#Define digit mapping -romanNumeralMap = (('M', 1000), - ('CM', 900), - ('D', 500), - ('CD', 400), - ('C', 100), - ('XC', 90), - ('L', 50), - ('XL', 40), - ('X', 10), - ('IX', 9), - ('V', 5), - ('IV', 4), - ('I', 1)) - -def toRoman(n): - """convert integer to Roman numeral""" - if not (0 < n < 5000): - raise OutOfRangeError("number out of range (must be 1..4999)") - if int(n) != n: - raise NotIntegerError("decimals can not be converted") - - result = "" - for numeral, integer in romanNumeralMap: - while n >= integer: - result += numeral - n -= integer - return result - -#Define pattern to detect valid Roman numerals -romanNumeralPattern = re.compile(""" - ^ # beginning of string - M{0,4} # thousands - 0 to 4 M's - (CM|CD|D?C{0,3}) # hundreds - 900 (CM), 400 (CD), 0-300 (0 to 3 C's), - # or 500-800 (D, followed by 0 to 3 C's) - (XC|XL|L?X{0,3}) # tens - 90 (XC), 40 (XL), 0-30 (0 to 3 X's), - # or 50-80 (L, followed by 0 to 3 X's) - (IX|IV|V?I{0,3}) # ones - 9 (IX), 4 (IV), 0-3 (0 to 3 I's), - # or 5-8 (V, followed by 0 to 3 I's) - $ # end of string - """ ,re.VERBOSE) - -def fromRoman(s): - """convert Roman numeral to integer""" - if not s: - raise InvalidRomanNumeralError('Input can not be blank') - if not romanNumeralPattern.search(s): - raise InvalidRomanNumeralError('Invalid Roman numeral: %s' % s) - - result = 0 - index = 0 - for numeral, integer in romanNumeralMap: - while s[index:index+len(numeral)] == numeral: - result += integer - index += len(numeral) - return result - From 40d706affe91b98a35f5d0b523f42cdccb958b0a Mon Sep 17 00:00:00 2001 From: AA Turner <9087854+AA-Turner@users.noreply.github.com> Date: Fri, 14 Aug 2020 20:45:30 +0100 Subject: [PATCH 094/108] Fix typos --- package.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.py b/package.py index 994b56cde87..bcb8dda3f37 100644 --- a/package.py +++ b/package.py @@ -126,7 +126,7 @@ ref.name = 'table' ref["class"] = "docutils footnote" ref.contents = footnote_rows - # TODO combine all tables into one (relianbt on fixingf PEP8 table mismatch) + # TODO combine all tables into one (reliant on fixing PEP8 table mismatch) # Writes transformed HTML write_path = Path('./package/peps') / file_path.name From 61471594171760bb55b6a0c3868265c079ae78b8 Mon Sep 17 00:00:00 2001 From: AA Turner <9087854+AA-Turner@users.noreply.github.com> Date: Fri, 14 Aug 2020 20:46:59 +0100 Subject: [PATCH 095/108] Use pydotorg mathematics rendering --- pep_extensions/__init__.py | 15 ++++++++++----- pep_extensions/pep_processor/parsing/pep_role.py | 1 - 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/pep_extensions/__init__.py b/pep_extensions/__init__.py index 8bab6b59306..f03cfb6d996 100644 --- a/pep_extensions/__init__.py +++ b/pep_extensions/__init__.py @@ -25,10 +25,15 @@ def init_less_js(self) -> None: def setup(app: Sphinx) -> dict: """Initialize Sphinx extension.""" - app.add_source_parser(pep_parser.PEPParser) - app.add_role('pep', pep_role.PEPRole(), override=True) - app.set_translator("html", pep_html_translator.PEPTranslator) - app.connect("env-before-read-docs", create_pep_zero) - app.add_html_math_renderer('math2html', (HTMLTranslator.visit_math, None), (HTMLTranslator.visit_math_block, None)) # NoQA + app.add_source_parser(pep_parser.PEPParser) # Add PEP transforms + app.add_role('pep', pep_role.PEPRole(), override=True) # Transform PEP references to links + app.set_translator("html", pep_html_translator.PEPTranslator) # Docutils Node Visitor overrides + app.connect("env-before-read-docs", create_pep_zero) # PEP 0 hook + + # Mathematics rendering + def depart_maths(): pass # Satisfy type checker + inline_maths = (HTMLTranslator.visit_math, depart_maths) + block_maths = (HTMLTranslator.visit_math_block, depart_maths) + app.add_html_math_renderer('math2html', inline_maths, block_maths) # Render maths to HTML return {'version': __version__, 'parallel_read_safe': True, 'parallel_write_safe': True} diff --git a/pep_extensions/pep_processor/parsing/pep_role.py b/pep_extensions/pep_processor/parsing/pep_role.py index 92ecbb729d5..3cf4163f339 100644 --- a/pep_extensions/pep_processor/parsing/pep_role.py +++ b/pep_extensions/pep_processor/parsing/pep_role.py @@ -5,7 +5,6 @@ class PEPRole(roles.PEP): - def build_uri(self) -> str: base_url = self.inliner.document.settings.pep_base_url ret = self.target.split('#', 1) From b661ccc2b768a6916ffc681704849f4df430e176 Mon Sep 17 00:00:00 2001 From: AA Turner <9087854+AA-Turner@users.noreply.github.com> Date: Fri, 14 Aug 2020 20:50:36 +0100 Subject: [PATCH 096/108] Edits for style in __init__.py --- pep_extensions/__init__.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/pep_extensions/__init__.py b/pep_extensions/__init__.py index f03cfb6d996..5c5e5a20c60 100644 --- a/pep_extensions/__init__.py +++ b/pep_extensions/__init__.py @@ -12,9 +12,10 @@ # Monkeypatch StandaloneHTMLBuilder to not include JS libraries (underscore.js & jQuery) def init_less_js(self) -> None: - js_files = [('js/doctools.js', {}), ('js/language_data.js', {}), ] + js_files = [('js/doctools.js', {}), ('js/language_data.js', {})] js_files.extend([*self.app.registry.js_files, *self.get_builder_config('js_files', 'html')]) - js_files.append(('translations.js',) if self.config.language and self._get_translations_js() else (None, {})) + if self.config.language and self._get_translations_js(): + js_files.append(('translations.js',)) for filename, attrs in js_files: self.add_js_file(filename, **attrs) @@ -31,7 +32,7 @@ def setup(app: Sphinx) -> dict: app.connect("env-before-read-docs", create_pep_zero) # PEP 0 hook # Mathematics rendering - def depart_maths(): pass # Satisfy type checker + def depart_maths(): pass # Type checker wants a callable inline_maths = (HTMLTranslator.visit_math, depart_maths) block_maths = (HTMLTranslator.visit_math_block, depart_maths) app.add_html_math_renderer('math2html', inline_maths, block_maths) # Render maths to HTML From 270b82510c4437d074d6a3a70736125cacc06283 Mon Sep 17 00:00:00 2001 From: AA Turner <9087854+AA-Turner@users.noreply.github.com> Date: Fri, 14 Aug 2020 20:56:14 +0100 Subject: [PATCH 097/108] Clarify elements in build flow --- .github/workflows/deploy-gh-pages.yaml | 9 +-------- build.py | 5 ++--- 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/.github/workflows/deploy-gh-pages.yaml b/.github/workflows/deploy-gh-pages.yaml index bf7e615a189..eb9a4f2d8cf 100644 --- a/.github/workflows/deploy-gh-pages.yaml +++ b/.github/workflows/deploy-gh-pages.yaml @@ -26,8 +26,7 @@ jobs: ${{ runner.os }}-pip- ${{ runner.os }}- - # This example project is built using npm and outputs the result to the 'build' folder. - # Replace with the commands required to build your project, or remove this step entirely if your site is pre-built. + # Install dependencies and build PEPs using sphinx - name: Install and Build 🔧 run: | set -x @@ -41,9 +40,3 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} BRANCH: gh-pages # The branch the action should deploy to. FOLDER: build # The folder the action should deploy. - -# TODO enable build only on master -#on: -# push: -# branches: -# - master \ No newline at end of file diff --git a/build.py b/build.py index 17cdbf5de1d..e3970969316 100644 --- a/build.py +++ b/build.py @@ -24,12 +24,11 @@ def create_parser(): def create_index_file(html_content: Path): - index_file = "index.html" - index = html_content / index_file + index = html_content / "index.html" pep_zero = html_content / "pep-0000.html" # `dirhtml` builder pep 0 path: - pep_zero_dir_builder = pep_zero.with_suffix("").joinpath(index_file) + pep_zero_dir_builder = html_content / "pep-0000" / "index.html" if pep_zero.is_file(): shutil.copy(pep_zero, index) elif pep_zero_dir_builder.is_file(): From 4f151494141112813b4d371ad0ca40601e05fd23 Mon Sep 17 00:00:00 2001 From: AA Turner <9087854+AA-Turner@users.noreply.github.com> Date: Sat, 15 Aug 2020 02:17:03 +0100 Subject: [PATCH 098/108] Update pep2rss to closer match current output --- pep2rss.py | 56 ++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 37 insertions(+), 19 deletions(-) diff --git a/pep2rss.py b/pep2rss.py index bfc81d60b58..f56f26193b7 100755 --- a/pep2rss.py +++ b/pep2rss.py @@ -1,58 +1,68 @@ -# usage: pep2rss.py $REPOS $REV -# (standard post-commit args) - import datetime +import email.utils import re from pathlib import Path +import lxml.etree # Prevents AttributeError when importing `feedgen.util` +import feedgen.util + +if feedgen.util and lxml.etree: + # Monkeypatch format function + feedgen.util.formatRFC2822 = lambda dt: email.utils.format_datetime(dt, usegmt=True) + +from dateutil import parser from feedgen import entry from feedgen import feed -def firstline_startingwith(full_path, text): +def first_line_starting_with(full_path: Path, text: str) -> str: for line in full_path.open(encoding="utf-8"): if line.startswith(text): return line[len(text):].strip() - return None + return "" -def pep_creation_dt(full_path): - created_str = firstline_startingwith(full_path, "Created:") +def pep_creation_dt(full_path: Path) -> datetime.datetime: + created_str = first_line_starting_with(full_path, "Created:") # bleh, I was hoping to avoid re but some PEPs editorialize on the Created line - m = re.search(r"(\d+-\w+-\d{4})", created_str) + # (note as of Aug 2020 only PEP 102 has additional content on the Created line) + m = re.search(r"(\d+[- ][\w\d]+[- ]\d{2,4})", created_str) if not m: # some older ones have an empty line, that's okay, if it's old we ipso facto don't care about it. # "return None" would make the most sense but datetime objects refuse to compare with that. :-| return datetime.datetime.fromtimestamp(0, tz=datetime.timezone.utc) created_str = m.group(1) try: - dt = datetime.datetime.strptime(created_str, "%d-%b-%Y") - except ValueError: - dt = datetime.datetime.strptime(created_str, "%d-%B-%Y") + dt = parser.parse(created_str, dayfirst=True) + except (ValueError, OverflowError): + dt = datetime.datetime.fromtimestamp(0) return dt.replace(tzinfo=datetime.timezone.utc) def main(): + pep_dir = Path(__file__).parent # this must point to the directory with the PEP sources # get list of peps with creation time (from "Created:" string in pep source) - peps_with_dt = [(pep_creation_dt(path), path) for path in Path().glob("pep-????.*")] - peps_with_dt.sort(reverse=True) # sort peps by date, newest first + peps_with_dt = [(pep_creation_dt(path), path) for path in pep_dir.glob("pep-????.*")] + peps_with_dt.sort() # sort peps by date, newest first # generate rss items for 10 most recent peps items = [] - for dt, full_path in peps_with_dt[:10]: + for dt, full_path in peps_with_dt[-10:]: try: n = int(full_path.stem.split("-")[-1]) except ValueError: continue - title = firstline_startingwith(full_path, "Title:") - author = firstline_startingwith(full_path, "Author:") + title = first_line_starting_with(full_path, "Title:") + author = first_line_starting_with(full_path, "Author:") + parsed_authors = email.utils.getaddresses([author]) if "@" in author else [(author, "")] url = f"http://www.python.org/dev/peps/pep-{n:0>4}" item = entry.FeedEntry() item.title(f"PEP {n}: {title}") item.link(href=url) - item.description(f"Author: {author}") + item.description(f"Author: {author}") # TODO add PEP abstract ref GH-1085 item.guid(url, permalink=True) item.pubDate(dt) + item.author([dict(name=parsed_author[0], email=parsed_author[1]) for parsed_author in parsed_authors]) items.append(item) # the rss envelope @@ -61,16 +71,24 @@ def main(): language features, and some meta-information like release procedure and schedules """.strip() + + # Setup feed generator fg = feed.FeedGenerator() fg.language('en') + fg.generator("") + fg.docs("http://blogs.law.harvard.edu/tech/rss") + + # Add metadata fg.title('Newest Python PEPs') fg.link(href='http://www.python.org/dev/peps') fg.description(desc) fg.lastBuildDate(datetime.datetime.now(tz=datetime.timezone.utc)) - for item in reversed(items): + + # Add PEP information (ordered by newest first) + for item in items: fg.add_entry(item) - Path("peps.rss").write_bytes(fg.rss_str()) + Path("peps.rss").write_bytes(fg.rss_str(pretty=True)) if __name__ == "__main__": From e257372205310322260a35efd6400a1f94ebdb87 Mon Sep 17 00:00:00 2001 From: AA Turner <9087854+AA-Turner@users.noreply.github.com> Date: Sat, 15 Aug 2020 02:17:49 +0100 Subject: [PATCH 099/108] Use absolute path --- pep2rss.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pep2rss.py b/pep2rss.py index f56f26193b7..577f21f06aa 100755 --- a/pep2rss.py +++ b/pep2rss.py @@ -88,7 +88,7 @@ def main(): for item in items: fg.add_entry(item) - Path("peps.rss").write_bytes(fg.rss_str(pretty=True)) + pep_dir.joinpath("peps.rss").write_bytes(fg.rss_str(pretty=True)) if __name__ == "__main__": From c2633719a624e9f2744a80bb5d325ec5216cda58 Mon Sep 17 00:00:00 2001 From: AA Turner <9087854+AA-Turner@users.noreply.github.com> Date: Sat, 15 Aug 2020 02:27:40 +0100 Subject: [PATCH 100/108] Add venv to gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 7bdede6a092..67888fe6cf8 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,4 @@ __pycache__ *.swp build package +venv From 116f3a7761849d34ddcd9c60dee00c2907d79e23 Mon Sep 17 00:00:00 2001 From: AA Turner <9087854+AA-Turner@users.noreply.github.com> Date: Sat, 15 Aug 2020 02:53:25 +0100 Subject: [PATCH 101/108] Match current state of name parsing branch --- AUTHORS.csv | 261 +----------------- .../pep_zero_generator/pep_0_parser.py | 86 +++++- .../pep_zero_generator/pep_0_writer.py | 7 +- .../pep_zero_generator/pep_index_generator.py | 11 +- 4 files changed, 103 insertions(+), 262 deletions(-) diff --git a/AUTHORS.csv b/AUTHORS.csv index 0270e4383c4..c17ad10c73d 100644 --- a/AUTHORS.csv +++ b/AUTHORS.csv @@ -1,249 +1,12 @@ -"Full Name", "Surname First", "Name Reference" -"Aahz", "Aahz", "Aahz" -"James C. Ahlstrom", "Ahlstrom, James C.", "Ahlstrom" -"Jim Althoff", "Althoff, Jim", "Althoff" -"Kevin Altis", "Altis, Kevin", "Altis" -"Chris Angelico", "Angelico, Chris", "Angelico" -"Philipp Angerer", "Angerer, Philipp", "Angerer" -"David Ascher", "Ascher, David", "Ascher" -"Peter Astrand", "Astrand, Peter", "Astrand" -"Carl Banks", "Banks, Carl", "Banks" -"Christopher Barker", "Barker, Christopher", "Barker" -"Paul Barrett", "Barrett, Paul", "Barrett" -"Facundo Batista", "Batista, Facundo", "Batista" -"Anthony Baxter", "Baxter, Anthony", "Baxter" -"Stefan Behnel", "Behnel, Stefan", "Behnel" -"Thomas Bellman", "Bellman, Thomas", "Bellman" -"Alexander Belopolsky", "Belopolsky, Alexander", "Belopolsky" -"Eli Bendersky", "Bendersky, Eli", "Bendersky" -"Cory Benfield", "Benfield, Cory", "Benfield" -"Steven Bethard", "Bethard, Steven", "Bethard" -"Stéphane Bidoul", "Bidoul, Stéphane", "Bidoul" -"Stefano Borini", "Borini, Stefano", "Borini" -"Georg Brandl", "Brandl, Georg", "Brandl" -"Erik M. Bray", "Bray, Erik M.", "Bray" -"Gerald Britton", "Britton, Gerald", "Britton" -"Oleg Broytman", "Broytman, Oleg", "Broytman" -"Benoit Bryon", "Bryon, Benoit", "Bryon" -"Brandt Bucher", "Bucher, Brandt", "Bucher" -"Brett Cannon", "Cannon, Brett", "Cannon" -"Justin Cappos", "Cappos, Justin", "Cappos" -"Josiah Carlson", "Carlson, Josiah", "Carlson" -"W Isaac Carroll", "Carroll, W Isaac", "Carroll" -"Matt Chisholm", "Chisholm, Matt", "Chisholm" -"Nick Coghlan", "Coghlan, Nick", "Coghlan" -"Dave Cole", "Cole, Dave", "Cole" -"Robert Collins", "Collins, Robert", "Collins" -"Paul Colomiets", "Colomiets, Paul", "Colomiets" -"Mario Corchero", "Corchero, Mario", "Corchero" -"Christopher A. Craig", "Craig, Christopher A.", "Craig" -"Laura Creighton", "Creighton, Laura", "Creighton" -"Steven D'Aprano", "D'Aprano, Steven", "D'Aprano" -"Kushal Das", "Das, Kushal", "Das" -"Ned Deily", "Deily, Ned", "Deily" -"Tim Delaney", "Delaney, Tim", "Delaney" -"Lois Anne DeLong", "DeLong, Lois Anne", "DeLong" -"Jeroen Demeyer", "Demeyer, Jeroen", "Demeyer" -"Vladimir Diaz", "Diaz, Vladimir", "Diaz" -"Jack Diederich", "Diederich, Jack", "Diederich" -"Steve Dower", "Dower, Steve", "Dower" -"Walter Dörwald", "Dörwald, Walter", "Dörwald" -"Fred L. Drake, Jr.", "Drake, Fred L., Jr.", "Drake" -"Michael P. Dubner", "Dubner, Michael P.", "Dubner" -"Paul F. Dubois", "Dubois, Paul F.", "Dubois" -"Ernest W. Durbin III", "Durbin, Ernest W., III", "Durbin" -"P.J. Eby", "Eby, P.J.", "Eby" -"Phillip J. Eby", "Eby, Phillip J.", "Eby" -"Tal Einat", "Einat, Tal", "Einat" -"Micah Elliott", "Elliott, Micah", "Elliott" -"Jeff Epler", "Epler, Jeff", "Epler" -"David Eppstein", "Eppstein, David", "Eppstein" -"Clark C. Evans", "Evans, Clark C.", "Evans" -"Gregory Ewing", "Ewing, Gregory", "Ewing" -"Greg Ewing", "Ewing, Greg", "Ewing" -"Martijn Faassen", "Faassen, Martijn", "Faassen" -"Ben Finney", "Finney, Ben", "Finney" -"Michael Foord", "Foord, Michael", "Foord" -"Ethan Furman", "Furman, Ethan", "Furman" -"Pablo Galindo", "Galindo, Pablo", "Galindo" -"Paul Ganssle", "Ganssle, Paul", "Ganssle" -"Alex Gaynor", "Gaynor, Alex", "Gaynor" -"Pradyun Gedam", "Gedam, Pradyun", "Gedam" -"Damien George", "George, Damien", "George" -"Frédéric B. Giacometti", "Giacometti, Frédéric B.", "Giacometti" -"Scott Gilbert", "Gilbert, Scott", "Gilbert" -"Ryan Gonzalez", "Gonzalez, Ryan", "Gonzalez" -"David Goodger", "Goodger, David", "Goodger" -"Grant Griffin", "Griffin, Grant", "Griffin" -"Mark E. Haase", "Haase, Mark E.", "Haase" -"Mark Hammond", "Hammond, Mark", "Hammond" -"Peter Harris", "Harris, Peter", "Harris" -"Larry Hastings", "Hastings, Larry", "Hastings" -"Christian Heimes", "Heimes, Christian", "Heimes" -"Thomas Heller", "Heller, Thomas", "Heller" -"Doug Hellmann", "Hellmann, Doug", "Hellmann" -"Magnus Lie Hetland", "Hetland, Magnus Lie", "Hetland" -"Raymond Hettinger", "Hettinger, Raymond", "Hettinger" -"Neil Hodgson", "Hodgson, Neil", "Hodgson" -"Daniel Holth", "Holth, Daniel", "Holth" -"Philip House", "House, Philip", "House" -"Laurens Van Houtven", "Van Houtven, Laurens", "Houtven" -"Ben Hoyt", "Hoyt, Ben", "Hoyt" -"Miro Hrončok", "Hrončok, Miro", "Hrončok" -"Michael Hudson", "Hudson, Michael", "Hudson" -"Jeremy Hylton", "Hylton, Jeremy", "Hylton" -"Inada Naoki", "Inada, Naoki", "Inada" -"Dustin Ingram", "Ingram, Dustin", "Ingram" -"Atsuo Ishimoto", "Ishimoto, Atsuo", "Ishimoto" -"Jack Jansen", "Jansen, Jack", "Jansen" -"Chris Jerdonek", "Jerdonek, Chris", "Jerdonek" -"Joseph Jevnik", "Jevnik, Joseph", "Jevnik" -"Jim J. Jewett", "Jewett, Jim J.", "Jewett" -"Jim Jewett", "Jewett, Jim", "Jewett" -"Ewa Jodlowska", "Jodlowska, Ewa", "Jodlowska" -"Richard Jones", "Jones, Richard", "Jones" -"Konstantin Kashin", "Kashin, Konstantin", "Kashin" -"Reid Kleckner", "Kleckner, Reid", "Kleckner" -"Thomas Kluyver", "Kluyver, Thomas", "Kluyver" -"Stepan Koltsov", "Koltsov, Stepan", "Koltsov" -"Stefan Krah", "Krah, Stefan", "Krah" -"Sebastian Kreft", "Kreft, Sebastian", "Kreft" -"Holger Krekel", "Krekel, Holger", "Krekel" -"A.M. Kuchling", "Kuchling, A.M.", "Kuchling" -"Trishank Karthik Kuppusamy", "Kuppusamy, Trishank Karthik", "Kuppusamy" -"Robert Kuska", "Kuska, Robert", "Kuska" -"Joshua Landau", "Landau, Joshua", "Landau" -"Łukasz Langa", "Langa, Łukasz", "Langa" -"Michael Lee", "Lee, Michael", "Lee" -"Jukka Lehtosalo", "Lehtosalo, Jukka", "Lehtosalo" -"Marc-André Lemburg", "Lemburg, Marc-André", "Lemburg" -"Ivan Levkivskyi", "Levkivskyi, Ivan", "Levkivskyi" -"Gregory Lielens", "Lielens, Gregory", "Lielens" -"Björn Lindqvist", "Lindqvist, Björn", "Lindqvist" -"Joshua Lock", "Lock, Joshua", "Lock" -"Tony Lownds", "Lownds, Tony", "Lownds" -"Martin von Löwis", "von Löwis, Martin", "von Löwis" -"Martin v. Löwis", "\v. Löwis, Martin", "\v. Löwis" -"Mariatta", "Mariatta", "Mariatta" -"Alex Martelli", "Martelli, Alex", "Martelli" -"Joseph Martinot-Lagarde", "Martinot-Lagarde, Joseph", "Martinot-Lagarde" -"Lino Mastrodomenico", "Mastrodomenico, Lino", "Mastrodomenico" -"Patrick Maupin", "Maupin, Patrick", "Maupin" -"Andrew McClelland", "McClelland, Andrew", "McClelland" -"Charles R. McCreary", "McCreary, Charles R.", "McCreary" -"Chris McDonough", "McDonough, Chris", "McDonough" -"Robert T. McGibbon", "McGibbon, Robert T.", "McGibbon" -"Gordon McMillan", "McMillan, Gordon", "McMillan" -"Andrew McNamara", "McNamara, Andrew", "McNamara" -"Ezio Melotti", "Melotti, Ezio", "Melotti" -"Mark Mendoza", "Mendoza, Mark", "Mendoza" -"Markus Meskanen", "Meskanen, Markus", "Meskanen" -"Mike Meyer", "Meyer, Mike", "Meyer" -"Carl Meyer", "Meyer, Carl", "Meyer" -"Trent Mick", "Mick, Trent", "Mick" -"Mike G. Miller", "Miller, Mike G.", "Miller" -"Skip Montanaro", "Montanaro, Skip", "Montanaro" -"Peter Moody", "Moody, Peter", "Moody" -"Marina Moore", "Moore, Marina", "Moore" -"Paul Moore", "Moore, Paul", "Moore" -"R David Murray", "Murray, R David", "Murray" -"Charles-François Natali", "Natali, Charles-François", "Natali" -"Lysandros Nikolaou", "Nikolaou, Lysandros", "Nikolaou" -"Jesse Noller", "Noller, Jesse", "Noller" -"Ben North", "North, Ben", "North" -"Neal Norwitz", "Norwitz, Neal", "Norwitz" -"Dirkjan Ochtman", "Ochtman, Dirkjan", "Ochtman" -"Travis Oliphant", "Oliphant, Travis", "Oliphant" -"Jason Orendorff", "Orendorff, Jason", "Orendorff" -"Tomáš Orsava", "Orsava, Tomáš", "Orsava" -"Richard Oudkerk", "Oudkerk, Richard", "Oudkerk" -"Ronald Oussoren", "Oussoren, Ronald", "Oussoren" -"Julien Palard", "Palard, Julien", "Palard" -"Samuele Pedroni", "Pedroni, Samuele", "Pedroni" -"Berker Peksag", "Peksag, Berker", "Peksag" -"Michel Pelletier", "Pelletier, Michel", "Pelletier" -"Tim Peters", "Peters, Tim", "Peters" -"Benjamin Peterson", "Peterson, Benjamin", "Peterson" -"Jason Petrone", "Petrone, Jason", "Petrone" -"Antoine Pitrou", "Pitrou, Antoine", "Pitrou" -"Marcel Plch", "Plch, Marcel", "Plch" -"James Polley", "Polley, James", "Polley" -"Philippe PRADOS", "Prados, Philippe", "Prados" -"Elvis Pranskevichus", "Pranskevichus, Elvis", "Pranskevichus" -"Paul Prescod", "Prescod, Paul", "Prescod" -"(James) Eric Pruitt", "Pruitt, (James) Eric", "Pruitt" -"Lukas Puehringer", "Puehringer, Lukas", "Puehringer" -"Brian Quinlan", "Quinlan, Brian", "Quinlan" -"Terry Reedy", "Reedy, Terry", "Reedy" -"Lennart Regebro", "Regebro, Lennart", "Regebro" -"Sean Reifschneider", "Reifschneider, Sean", "Reifschneider" -"Christian R. Reis", "Reis, Christian R.", "Reis" -"Jonathan Riehl", "Riehl, Jonathan", "Riehl" -"Lisa Roach", "Roach, Lisa", "Roach" -"Andre Roberge", "Roberge, Andre", "Roberge" -"Armin Ronacher", "Ronacher, Armin", "Ronacher" -"Guido van Rossum", "van Rossum, Guido (GvR)", "GvR" -"Just van Rossum", "van Rossum, Just (JvR)", "JvR" -"Todd Rovito", "Rovito, Todd", "Rovito" -"Lie Ryan", "Ryan, Lie", "Ryan" -"Vinay Sajip", "Sajip, Vinay", "Sajip" -"Pablo Galindo Salgado", "Salgado, Pablo Galindo", "Salgado" -"Neil Schemenauer", "Schemenauer, Neil", "Schemenauer" -"Peter Schneider-Kamp", "Schneider-Kamp, Peter", "Schneider-Kamp" -"Ed Schofield", "Schofield, Ed", "Schofield" -"Yury Selivanov", "Selivanov, Yury", "Selivanov" -"Jiwon Seo", "Seo, Jiwon", "Seo" -"Mark Shannon", "Shannon, Mark", "Shannon" -"Cameron Simpson", "Simpson, Cameron", "Simpson" -"Greg Slodkowicz", "Slodkowicz, Greg", "Slodkowicz" -"Nathaniel J. Smith", "Smith, Nathaniel J.", "Smith" -"Gregory P. Smith", "Smith, Gregory P.", "Smith" -"Kevin D. Smith", "Smith, Kevin D.", "Smith" -"Ethan Smith", "Smith, Ethan", "Smith" -"Nathaniel Smith", "Smith, Nathaniel", "Smith" -"Eric V. Smith", "Smith, Eric V.", "Smith" -"Eric Snow", "Snow, Eric", "Snow" -"Calvin Spealman", "Spealman, Calvin", "Spealman" -"Kerrick Staley", "Staley, Kerrick", "Staley" -"Greg Stein", "Stein, Greg", "Stein" -"Victor Stinner", "Stinner, Victor", "Stinner" -"Serhiy Storchaka", "Storchaka, Serhiy", "Storchaka" -"Donald Stufft", "Stufft, Donald", "Stufft" -"Daniel Stutzbach", "Stutzbach, Daniel", "Stutzbach" -"Michael J. Sullivan", "Sullivan, Michael J.", "Sullivan" -"Roman Suzi", "Suzi, Roman", "Suzi" -"Dennis Sweeney", "Sweeney, Dennis", "Sweeney" -"Talin", "Talin", "Talin" -"Steven Taschuk", "Taschuk, Steven", "Taschuk" -"Batuhan Taskaya", "Taskaya, Batuhan", "Taskaya" -"Martin Teichmann", "Teichmann, Martin", "Teichmann" -"The Python core team and community", "The Python core team and community", "The Python core team and community" -"Geoffrey Thomas", "Thomas, Geoffrey", "Thomas" -"Oren Tirosh", "Tirosh, Oren", "Tirosh" -"Stephen J. Turnbull", "Turnbull, Stephen J.", "Turnbull" -"Daniel Urban", "Urban, Daniel", "Urban" -"Eric N. Vander Weele", "Vander Weele, Eric N.", "Vander Weele" -"Till Varoquaux", "Varoquaux, Till", "Varoquaux" -"Alexandre Vassalotti", "Vassalotti, Alexandre", "Vassalotti" -"Mike Verdone", "Verdone, Mike", "Verdone" -"Dino Viehland", "Viehland, Dino", "Viehland" -"Petr Viktorin", "Viktorin, Petr", "Viktorin" -"Zachary Ware", "Ware, Zachary", "Ware" -"Gregory R. Warnes", "Warnes, Gregory R.", "Warnes" -"Barry Warsaw", "Warsaw, Barry", "Warsaw" -"Terence Way", "Way, Terence", "Way" -"Cliff Wells", "Wells, Cliff", "Wells" -"Jervis Whitley", "Whitley, Jervis", "Whitley" -"Mark Williams", "Williams, Mark", "Williams" -"Carol Willing", "Willing, Carol", "Willing" -"Greg Wilson", "Wilson, Greg", "Wilson" -"Collin Winter", "Winter, Collin", "Winter" -"Thomas Wouters", "Wouters, Thomas", "Wouters" -"Masayuki Yamamoto", "Yamamoto, Masayuki", "Yamamoto" -"Jeffrey Yasskin", "Yasskin, Jeffrey", "Yasskin" -"Ka-Ping Yee", "Yee, Ka-Ping", "Yee" -"Moshe Zadka", "Zadka, Moshe", "Zadka" -"Koos Zevenhoven", "Zevenhoven, Koos", "Zevenhoven" -"Huaiyu Zhu", "Zhu, Huaiyu", "Zhu" -"Shannon Zhu", "Zhu, Shannon", "Zhu" -"Tarek Ziadé", "Ziadé, Tarek", "Ziadé" \ No newline at end of file +Full Name, Surname First, Name Reference +Ernest W. Durbin III, "Durbin, Ernest W., III", Durbin +Inada Naoki, "Inada, Naoki", Inada +Guido van Rossum, "van Rossum, Guido (GvR)", GvR +Just van Rossum, "van Rossum, Just (JvR)", JvR +The Python core team and community, The Python core team and community, python-dev +P.J. Eby, "Eby, Phillip J.", Eby +Greg Ewing, "Ewing, Gregory", Ewing +Jim Jewett, "Jewett, Jim J.", Jewett +Nathaniel Smith, "Smith, Nathaniel J.", Smith +Martin v. Löwis, "von Löwis, Martin", von Löwis + diff --git a/pep_extensions/pep_zero_generator/pep_0_parser.py b/pep_extensions/pep_zero_generator/pep_0_parser.py index e8df40598f0..12c2d7c7ff1 100644 --- a/pep_extensions/pep_zero_generator/pep_0_parser.py +++ b/pep_extensions/pep_zero_generator/pep_0_parser.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """Code for handling object representation of a PEP.""" import re import textwrap @@ -50,16 +49,38 @@ class Author: The author's email address. """ - def __init__(self, author_and_email_tuple: Tuple[str, str], authors_lookup: dict): + def __init__(self, author_and_email_tuple: Tuple[str, str], authors_exceptions: dict): """Parse the name and email address of an author.""" + self.first = self.last = '' + name, email = author_and_email_tuple self.first_last: str = name.strip() self.email: str = email.lower() - name_dict = authors_lookup[self.first_last] + name_dict = authors_exceptions.get(self.first_last) + if name_dict: + self.last_first = name_dict["Surname First"] + self.nick = self.last = name_dict["Name Reference"] + else: + self.set_name_parts() + + def set_name_parts(self): + name_dict = self._parse_name(self.first_last) + suffix = name_dict.get("suffix") + if "name" in name_dict: + self.last_first = name_dict["name"] + self.nick = name_dict["name"] + else: + self.first = name_dict["forename"].rstrip() + self.last = name_dict["surname"] + if self.last[1] == ".": + # Add an escape to avoid docutils turning `v.` into `22.`. + self.last = "\\" + self.last + self.last_first = ", ".join([self.last, self.first]) + self.nick = self.last - self.last_first: str = name_dict["Surname First"] - self.nick: str = name_dict["Name Reference"] + if suffix: + self.last_first += f", {suffix}" def __hash__(self): return hash(self.first_last) @@ -82,6 +103,61 @@ def sort_by(self) -> str: base = last.lower() return unicodedata.normalize("NFKD", base) + @staticmethod + def _parse_name(full_name): + """Decompose a full name into parts. + + If a mononym (e.g, 'Aahz') then return the full name. If there are + suffixes in the name (e.g. ', Jr.' or 'III'), then find and extract + them. If there is a middle initial followed by a full stop, then + combine the following words into a surname (e.g. N. Vander Weele). If + there is a leading, lowercase portion to the last name (e.g. 'van' or + 'von') then include it in the surname. + + """ + possible_suffixes = ["Jr", "Jr.", "II", "III"] + + suffix_partition = full_name.partition(",") + pre_suffix = suffix_partition[0].strip() + suffix = suffix_partition[2].strip() + + name_parts = pre_suffix.split(" ") + num_parts = len(name_parts) + name = {"suffix": suffix} + + if num_parts == 0: + raise ValueError("Name is empty!") + elif num_parts == 1: + name.update(name=name_parts[0]) + elif num_parts == 2: + name.update(forename=name_parts[0], surname=name_parts[1]) + elif num_parts > 2: + # handles III etc. + if name_parts[-1] in possible_suffixes: + new_suffix = " ".join([*name_parts[-1:], suffix]).strip() + name_parts.pop(-1) + name.update(suffix=new_suffix) + + # handles von, van, v. etc. + if name_parts[-2].islower(): + forename = " ".join(name_parts[:-2]) + surname = " ".join(name_parts[-2:]) + name.update(forename=forename, surname=surname) + + # handles double surnames after a middle initial (e.g. N. Vander Weele) + elif any(s.endswith(".") for s in name_parts): + split_position = [i for i, x in enumerate(name_parts) if x.endswith(".")][-1] + 1 + forename = " ".join(name_parts[:split_position]) + surname = " ".join(name_parts[split_position:]) + name.update(forename=forename, surname=surname) + + else: + forename = " ".join(name_parts[:-1]) + surname = " ".join(name_parts[-1:]) + name.update(forename=forename, surname=surname) + + return name + class PEP: """Representation of PEPs. diff --git a/pep_extensions/pep_zero_generator/pep_0_writer.py b/pep_extensions/pep_zero_generator/pep_0_writer.py index 473697af39c..368a200b2a8 100644 --- a/pep_extensions/pep_zero_generator/pep_0_writer.py +++ b/pep_extensions/pep_zero_generator/pep_0_writer.py @@ -2,6 +2,7 @@ import datetime import unicodedata from functools import partial +from itertools import groupby from operator import attrgetter from typing import List @@ -172,9 +173,9 @@ def verify_email_addresses(peps): @staticmethod def sort_authors(authors_dict): - authors_list = list(authors_dict.keys()) - authors_list.sort(key=attrgetter("sort_by")) - return authors_list + authors_list = sorted(authors_dict.keys(), key=attrgetter("sort_by")) + unique_authors = [next(a) for k, a in groupby(authors_list, key=attrgetter("last_first"))] + return unique_authors @staticmethod def normalized_last_first(name): diff --git a/pep_extensions/pep_zero_generator/pep_index_generator.py b/pep_extensions/pep_zero_generator/pep_index_generator.py index 6d7a915828c..82abc7eb8e5 100644 --- a/pep_extensions/pep_zero_generator/pep_index_generator.py +++ b/pep_extensions/pep_zero_generator/pep_index_generator.py @@ -41,13 +41,14 @@ def create_pep_zero(_: Sphinx, env: BuildEnvironment, docnames: list): pep_pat = re.compile(r"pep-\d{4}") # Path.match() doesn't support regular expressions title_length = pep_0_writer.title_length + # AUTHORS.csv is an exception file for PEP0 name parsing with open("AUTHORS.csv", "r", encoding="UTF8") as f: read = csv.DictReader(f, quotechar='"', skipinitialspace=True) - author_data = {} + author_exception_data = {} for line in read: - full_name = line.pop("Full Name").strip().strip("\"") - details = {k.strip().strip("\""): v.strip().strip("\"") for k, v in line.items()} - author_data[full_name] = details + full_name = line.pop("Full Name").strip() + details = {k.strip(): v.strip() for k, v in line.items()} + author_exception_data[full_name] = details for file_path in path.iterdir(): if not file_path.is_file(): @@ -56,7 +57,7 @@ def create_pep_zero(_: Sphinx, env: BuildEnvironment, docnames: list): continue # Skip pre-existing PEP 0 files if pep_pat.match(str(file_path)) and file_path.suffix in (".txt", ".rst"): file_path_absolute = path.joinpath(file_path).absolute() - pep = pep_0_parser.PEP(file_path_absolute, author_data, title_length) + pep = pep_0_parser.PEP(file_path_absolute, author_exception_data, title_length) peps.append(pep) peps.sort(key=lambda pep: pep.number) From e37b5d2d8e40462665d1d3974865ae87ca7d194a Mon Sep 17 00:00:00 2001 From: AA Turner <9087854+AA-Turner@users.noreply.github.com> Date: Sat, 15 Aug 2020 02:53:42 +0100 Subject: [PATCH 102/108] Makefile should be generating rss! --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 68230d34e5c..83905470a54 100644 --- a/Makefile +++ b/Makefile @@ -5,7 +5,7 @@ all: sphinx PYTHON=python3 -pages: sphinx +pages: rss $(PYTHON) build.py --index-file sphinx: From c44d852964ba3f72cbc1468ca5e411e6556e808b Mon Sep 17 00:00:00 2001 From: AA Turner <9087854+AA-Turner@users.noreply.github.com> Date: Sat, 15 Aug 2020 03:08:34 +0100 Subject: [PATCH 103/108] PEP 249 style is different --- pep_extensions/theme/static/css/pep.css | 1 + 1 file changed, 1 insertion(+) diff --git a/pep_extensions/theme/static/css/pep.css b/pep_extensions/theme/static/css/pep.css index 8fc8168ebf0..412e85cdc13 100644 --- a/pep_extensions/theme/static/css/pep.css +++ b/pep_extensions/theme/static/css/pep.css @@ -2,6 +2,7 @@ TODO: PEPify links TODO: PSF callout +TODO: match style PEP 249 Explicitly don't reformat syntax highlighting as per pydotorg as pydotorg doesn't have it */ From ad4c6a13ed10ed11845a5cd0c8c549e5c4322003 Mon Sep 17 00:00:00 2001 From: AA Turner <9087854+AA-Turner@users.noreply.github.com> Date: Sat, 15 Aug 2020 05:11:08 +0100 Subject: [PATCH 104/108] Implemented auto-linking with the PEP pattern --- pep_extensions/__init__.py | 9 +++++++++ pep_extensions/theme/static/css/pep.css | 1 - 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/pep_extensions/__init__.py b/pep_extensions/__init__.py index 5c5e5a20c60..d4ba9e9c92d 100644 --- a/pep_extensions/__init__.py +++ b/pep_extensions/__init__.py @@ -1,6 +1,7 @@ """Sphinx extensions for performant PEP processing""" import sphinx.builders.html from sphinx.application import Sphinx +from sphinx.environment import default_settings from docutils.writers.html5_polyglot import HTMLTranslator from pep_extensions.config import __version__ @@ -9,6 +10,14 @@ from pep_extensions.pep_processor.parsing import pep_role from pep_extensions.pep_zero_generator.pep_index_generator import create_pep_zero +# Monkeypatch sphinx.environment.default_settings as Sphinx doesn't allow custom settings or Readers +default_settings.update({ + 'pep_references': True, + 'rfc_references': True, + "pep_base_url": "", + "pep_file_url_template": "pep-%04d.html" +}) + # Monkeypatch StandaloneHTMLBuilder to not include JS libraries (underscore.js & jQuery) def init_less_js(self) -> None: diff --git a/pep_extensions/theme/static/css/pep.css b/pep_extensions/theme/static/css/pep.css index 412e85cdc13..119c02a4e94 100644 --- a/pep_extensions/theme/static/css/pep.css +++ b/pep_extensions/theme/static/css/pep.css @@ -1,6 +1,5 @@ /* -TODO: PEPify links TODO: PSF callout TODO: match style PEP 249 From 65867847f5475b08772a260b8a0f3db784f05bf6 Mon Sep 17 00:00:00 2001 From: AA Turner <9087854+AA-Turner@users.noreply.github.com> Date: Sat, 15 Aug 2020 05:20:53 +0100 Subject: [PATCH 105/108] Definition list styling only applies to headers and footnotes --- pep_extensions/theme/static/css/pep.css | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/pep_extensions/theme/static/css/pep.css b/pep_extensions/theme/static/css/pep.css index 119c02a4e94..c4f7cf948eb 100644 --- a/pep_extensions/theme/static/css/pep.css +++ b/pep_extensions/theme/static/css/pep.css @@ -1,7 +1,6 @@ /* TODO: PSF callout -TODO: match style PEP 249 Explicitly don't reformat syntax highlighting as per pydotorg as pydotorg doesn't have it */ @@ -27,7 +26,8 @@ Explicitly don't reformat syntax highlighting as per pydotorg as pydotorg doesn' /* PEP Header Blocks*/ -dl { +dl.rfc2822, +dl.footnote { background-color: #f6f6f6; display: grid; grid-template-columns: fit-content(30%) auto; @@ -51,7 +51,8 @@ dl.footnote { width: inherit; } -dl > dt { +dl.rfc2822 > dt, +dl.footnote > dt { width: inherit; margin: 0; border: 0; @@ -73,7 +74,8 @@ dl.footnote > dt { font-weight: normal; } -dl > dd { +dl.rfc2822 > dd, +dl.footnote > dd { padding: .25em .5em .2em; border: 0; border-left: 2px solid #fff; From ae53f01b8d9c9be5dba769ae4068ec14071343f8 Mon Sep 17 00:00:00 2001 From: AA Turner <9087854+AA-Turner@users.noreply.github.com> Date: Sat, 15 Aug 2020 06:42:54 +0100 Subject: [PATCH 106/108] Add last-modified date to footer re python/pythondotorg#1564 --- pep_extensions/config.py | 1 + .../pep_processor/transforms/pep_footer.py | 21 ++++++++++++++++++- pep_extensions/theme/static/css/pep.css | 5 +++++ 3 files changed, 26 insertions(+), 1 deletion(-) diff --git a/pep_extensions/config.py b/pep_extensions/config.py index a83be45a232..f5c05dca1ad 100644 --- a/pep_extensions/config.py +++ b/pep_extensions/config.py @@ -4,3 +4,4 @@ pep_stem = "pep-{:0>4}" pep_url = f"{pep_stem}.html" pep_vcs_url = "https://github.com/python/peps/blob/master/{}" +pep_commits_url = "https://github.com/python/peps/commits/master/{}" diff --git a/pep_extensions/pep_processor/transforms/pep_footer.py b/pep_extensions/pep_processor/transforms/pep_footer.py index 40129b58dd8..71a259cac0b 100644 --- a/pep_extensions/pep_processor/transforms/pep_footer.py +++ b/pep_extensions/pep_processor/transforms/pep_footer.py @@ -1,3 +1,5 @@ +import datetime +import subprocess from pathlib import Path from docutils import nodes @@ -62,9 +64,10 @@ def apply(self): self.document.note_pending(pending, 1) self.add_source_link(pep_source_path) + self.add_commit_history_info(pep_source_path) @staticmethod - def cleanup_callback(pending): + def cleanup_callback(pending: nodes.pending): """ Remove an empty "References" section. @@ -78,3 +81,19 @@ def add_source_link(self, pep_source_path: Path) -> None: link_node = nodes.reference("", source_link, refuri=source_link) span_node = nodes.inline("", "Source: ", link_node) self.document.append(span_node) + + def add_commit_history_info(self, pep_source_path: Path) -> None: + args = ['git', '--no-pager', 'log', '-1', '--format=%at', pep_source_path.name] + try: + b = subprocess.check_output(args) + since_epoch = b.decode("UTF-8").strip() + dt = datetime.datetime.utcfromtimestamp(float(since_epoch)) + except (subprocess.CalledProcessError, ValueError): + return None + + dt.replace(tzinfo=datetime.timezone.utc) + commit_link = pep_config.pep_commits_url.format(pep_source_path.name) + link_node = nodes.reference("", dt.isoformat(), refuri=commit_link) + span_node = nodes.inline("", f"Last modified: ", link_node) + self.document.append(nodes.line("", "", classes=['zero-height'])) + self.document.append(span_node) \ No newline at end of file diff --git a/pep_extensions/theme/static/css/pep.css b/pep_extensions/theme/static/css/pep.css index c4f7cf948eb..8e3a4dcaef0 100644 --- a/pep_extensions/theme/static/css/pep.css +++ b/pep_extensions/theme/static/css/pep.css @@ -1,6 +1,7 @@ /* TODO: PSF callout +TODO: Refs PEP 310 Explicitly don't reformat syntax highlighting as per pydotorg as pydotorg doesn't have it */ @@ -255,4 +256,8 @@ div.highlight > pre { code.literal { font-family: "Courier New", monospace; font-size: 12.1833px; +} + +div.zero-height{ + line-height: 0; } \ No newline at end of file From 8f03eeba19334652d5b260fc21b7ab252b7d3b29 Mon Sep 17 00:00:00 2001 From: AA Turner <9087854+AA-Turner@users.noreply.github.com> Date: Sat, 15 Aug 2020 06:57:43 +0100 Subject: [PATCH 107/108] Add sphinx support - pythondotorg compat. Contains: - core, - package.py --- build.py | 15 - conf.py | 12 +- pep_extensions/__init__.py | 49 - pep_extensions/config.py | 7 - .../pep_processor/html/pep_html_translator.py | 87 - .../pep_processor/html/pep_jinja2.py | 30 - .../pep_processor/parsing/pep_parser.py | 23 - .../pep_processor/parsing/pep_role.py | 14 - .../pep_processor/transforms/pep_contents.py | 63 - .../pep_processor/transforms/pep_footer.py | 99 - .../pep_processor/transforms/pep_headers.py | 110 - .../pep_processor/transforms/pep_title.py | 52 - .../pep_processor/transforms/pep_zero.py | 74 - .../pep_zero_generator/pep_0_parser.py | 347 -- .../pep_zero_generator/pep_0_writer.py | 314 -- .../pep_zero_generator/pep_index_generator.py | 71 - pep_extensions/theme/static/css/mq.css | 2673 ---------- pep_extensions/theme/static/css/pep.css | 263 - pep_extensions/theme/static/css/style.css | 4501 ----------------- .../theme/static/fonts/Flux-Regular.ttf | Bin 61832 -> 0 bytes ...urceSansPro-Bold-webfont.be855452e565.woff | Bin 26256 -> 0 bytes ...SourceSansPro-It-webfont.1aa29ac0f190.woff | Bin 27964 -> 0 bytes ...eSansPro-Regular-webfont.fd0d51605201.woff | Bin 26392 -> 0 bytes pep_extensions/theme/static/js/doctools.js | 137 - pep_extensions/theme/static/js/searchtools.js | 530 -- pep_extensions/theme/static/py.png | Bin 695 -> 0 bytes .../theme/templates/breadcrumbs.html | 8 - .../theme/templates/customsidebar.html | 47 - pep_extensions/theme/templates/layout.html | 57 - pep_extensions/theme/templates/search.html | 41 - pep_extensions/theme/theme.conf | 7 - 31 files changed, 1 insertion(+), 9630 deletions(-) delete mode 100644 pep_extensions/__init__.py delete mode 100644 pep_extensions/config.py delete mode 100644 pep_extensions/pep_processor/html/pep_html_translator.py delete mode 100644 pep_extensions/pep_processor/html/pep_jinja2.py delete mode 100644 pep_extensions/pep_processor/parsing/pep_parser.py delete mode 100644 pep_extensions/pep_processor/parsing/pep_role.py delete mode 100644 pep_extensions/pep_processor/transforms/pep_contents.py delete mode 100644 pep_extensions/pep_processor/transforms/pep_footer.py delete mode 100644 pep_extensions/pep_processor/transforms/pep_headers.py delete mode 100644 pep_extensions/pep_processor/transforms/pep_title.py delete mode 100644 pep_extensions/pep_processor/transforms/pep_zero.py delete mode 100644 pep_extensions/pep_zero_generator/pep_0_parser.py delete mode 100644 pep_extensions/pep_zero_generator/pep_0_writer.py delete mode 100644 pep_extensions/pep_zero_generator/pep_index_generator.py delete mode 100644 pep_extensions/theme/static/css/mq.css delete mode 100644 pep_extensions/theme/static/css/pep.css delete mode 100644 pep_extensions/theme/static/css/style.css delete mode 100644 pep_extensions/theme/static/fonts/Flux-Regular.ttf delete mode 100644 pep_extensions/theme/static/fonts/SourceSansPro-Bold-webfont.be855452e565.woff delete mode 100644 pep_extensions/theme/static/fonts/SourceSansPro-It-webfont.1aa29ac0f190.woff delete mode 100644 pep_extensions/theme/static/fonts/SourceSansPro-Regular-webfont.fd0d51605201.woff delete mode 100644 pep_extensions/theme/static/js/doctools.js delete mode 100644 pep_extensions/theme/static/js/searchtools.js delete mode 100644 pep_extensions/theme/static/py.png delete mode 100644 pep_extensions/theme/templates/breadcrumbs.html delete mode 100644 pep_extensions/theme/templates/customsidebar.html delete mode 100644 pep_extensions/theme/templates/layout.html delete mode 100644 pep_extensions/theme/templates/search.html delete mode 100644 pep_extensions/theme/theme.conf diff --git a/build.py b/build.py index e3970969316..869bf205aae 100644 --- a/build.py +++ b/build.py @@ -23,18 +23,6 @@ def create_parser(): return parser.parse_args() -def create_index_file(html_content: Path): - index = html_content / "index.html" - - pep_zero = html_content / "pep-0000.html" - # `dirhtml` builder pep 0 path: - pep_zero_dir_builder = html_content / "pep-0000" / "index.html" - if pep_zero.is_file(): - shutil.copy(pep_zero, index) - elif pep_zero_dir_builder.is_file(): - shutil.copy(pep_zero_dir_builder, index) - - if __name__ == '__main__': args = create_parser() @@ -61,6 +49,3 @@ def create_index_file(html_content: Path): ) app.builder.copysource = False # Prevent unneeded source copying - we link direct to VCS app.build() - - if args.index_file: - create_index_file(build_directory) diff --git a/conf.py b/conf.py index eb3371a4fe8..5011d01de83 100644 --- a/conf.py +++ b/conf.py @@ -4,7 +4,6 @@ import sys from pathlib import Path -sys.path.extend(str(Path('./pep_extensions').absolute())) # -- Project information ----------------------------------------------------- @@ -14,10 +13,7 @@ # -- General configuration --------------------------------------------------- # Add any Sphinx extension module names here, as strings. -extensions = ["pep_extensions", "sphinx.ext.githubpages"] - -# Add any paths that contain templates here, relative to this directory. -templates_path = ['pep_extensions/theme/templates'] +extensions = ["sphinx.ext.githubpages"] # The file extensions of source files. Sphinx uses these suffixes as sources. source_suffix = { @@ -48,9 +44,3 @@ html_show_copyright = False html_show_sphinx = False html_title = "PEPs.Python.org" - -# Theme settings -html_theme = "theme" -html_theme_path = ["pep_extensions"] -html_favicon = Path(html_theme_path[0], html_theme, "static/py.png").as_posix() -template_bridge = "pep_extensions.pep_processor.html.pep_jinja2.PEPTemplateLoader" diff --git a/pep_extensions/__init__.py b/pep_extensions/__init__.py deleted file mode 100644 index d4ba9e9c92d..00000000000 --- a/pep_extensions/__init__.py +++ /dev/null @@ -1,49 +0,0 @@ -"""Sphinx extensions for performant PEP processing""" -import sphinx.builders.html -from sphinx.application import Sphinx -from sphinx.environment import default_settings -from docutils.writers.html5_polyglot import HTMLTranslator - -from pep_extensions.config import __version__ -from pep_extensions.pep_processor.html import pep_html_translator -from pep_extensions.pep_processor.parsing import pep_parser -from pep_extensions.pep_processor.parsing import pep_role -from pep_extensions.pep_zero_generator.pep_index_generator import create_pep_zero - -# Monkeypatch sphinx.environment.default_settings as Sphinx doesn't allow custom settings or Readers -default_settings.update({ - 'pep_references': True, - 'rfc_references': True, - "pep_base_url": "", - "pep_file_url_template": "pep-%04d.html" -}) - - -# Monkeypatch StandaloneHTMLBuilder to not include JS libraries (underscore.js & jQuery) -def init_less_js(self) -> None: - js_files = [('js/doctools.js', {}), ('js/language_data.js', {})] - js_files.extend([*self.app.registry.js_files, *self.get_builder_config('js_files', 'html')]) - if self.config.language and self._get_translations_js(): - js_files.append(('translations.js',)) - for filename, attrs in js_files: - self.add_js_file(filename, **attrs) - - -sphinx.builders.html.StandaloneHTMLBuilder.init_js_files = init_less_js - - -def setup(app: Sphinx) -> dict: - """Initialize Sphinx extension.""" - - app.add_source_parser(pep_parser.PEPParser) # Add PEP transforms - app.add_role('pep', pep_role.PEPRole(), override=True) # Transform PEP references to links - app.set_translator("html", pep_html_translator.PEPTranslator) # Docutils Node Visitor overrides - app.connect("env-before-read-docs", create_pep_zero) # PEP 0 hook - - # Mathematics rendering - def depart_maths(): pass # Type checker wants a callable - inline_maths = (HTMLTranslator.visit_math, depart_maths) - block_maths = (HTMLTranslator.visit_math_block, depart_maths) - app.add_html_math_renderer('math2html', inline_maths, block_maths) # Render maths to HTML - - return {'version': __version__, 'parallel_read_safe': True, 'parallel_write_safe': True} diff --git a/pep_extensions/config.py b/pep_extensions/config.py deleted file mode 100644 index f5c05dca1ad..00000000000 --- a/pep_extensions/config.py +++ /dev/null @@ -1,7 +0,0 @@ -"""Misc. config variables for the PEP extensions module.""" - -__version__ = '1.0.0' -pep_stem = "pep-{:0>4}" -pep_url = f"{pep_stem}.html" -pep_vcs_url = "https://github.com/python/peps/blob/master/{}" -pep_commits_url = "https://github.com/python/peps/commits/master/{}" diff --git a/pep_extensions/pep_processor/html/pep_html_translator.py b/pep_extensions/pep_processor/html/pep_html_translator.py deleted file mode 100644 index f4d45a347ea..00000000000 --- a/pep_extensions/pep_processor/html/pep_html_translator.py +++ /dev/null @@ -1,87 +0,0 @@ -from docutils import nodes -import sphinx.writers.html5 as html5 -import re - - -class PEPTranslator(html5.HTML5Translator): - compact_field_list = True - phrases_and_newlines = re.compile(r'[^\n]+|\n') - - def __init__(self, *args): - super(PEPTranslator, self).__init__(*args) - self.compact_simple: bool = False - - # Omit

tags to produce visually compact lists - def should_be_compact_paragraph(self, node: nodes.paragraph) -> bool: - """Determine if

tags around paragraph ``node`` can be omitted.""" - - # Never compact paragraphs in document or compound. - if isinstance(node.parent, (nodes.document, nodes.compound)): - return False - - # Check for custom attributes in paragraph. - for key, value in node.non_default_attributes().items(): - if key != 'classes' or value not in ([], ['first'], ['last'], ['first', 'last']): - return False - - # Only first paragraph can be compact (ignoring initial label & invisible nodes) - first = isinstance(node.parent[0], nodes.label) - visible_siblings = [child for child in node.parent.children[first:] if not isinstance(child, nodes.Invisible)] - if visible_siblings[0] is not node: - return False - - if self.compact_simple or self.compact_field_list: - return True - - parent_length = sum([1 for n in node.parent if not isinstance(n, (nodes.Invisible, nodes.label))]) - if self.compact_p and parent_length == 1: - return True - - return False - - def visit_enumerated_list(self, node: nodes.enumerated_list) -> None: - self.context.append(self.compact_simple) - self.compact_simple = self.is_compactable(node) - super().visit_enumerated_list(node) - - def depart_enumerated_list(self, node: nodes.enumerated_list) -> None: - self.compact_simple = self.context.pop() - super().depart_enumerated_list(node) - - def visit_paragraph(self, node: nodes.paragraph) -> None: - """Remove

tags if possible (PEPs historically h )""" - if self.should_be_compact_paragraph(node): - self.context.append('') - else: - self.body.append(self.starttag(node, 'p', '')) - self.context.append('

\n') - - def depart_paragraph(self, _: nodes.paragraph) -> None: - """Add corresponding end tag from `visit_paragraph`. Node param isn't needed.""" - self.body.append(self.context.pop()) - - def depart_label(self, node) -> None: - if not self.settings.footnote_backlinks: - self.body.append('') - self.body.append('\n
') - return - - # If only one reference to this footnote - back_references = node.parent['backrefs'] - if len(back_references) == 1: - self.body.append('') - - # Close the tag - self.body.append('') - - # If more than one reference - if len(back_references) > 1: - back_links = [f'{i}' for (i, ref) in enumerate(back_references, 1)] - back_links_str = ", ".join(back_links) - self.body.append(f" ({back_links_str}) ") - - # Close the def tags - self.body.append('\n
') - - def unknown_visit(self, node: nodes.Node) -> None: - pass diff --git a/pep_extensions/pep_processor/html/pep_jinja2.py b/pep_extensions/pep_processor/html/pep_jinja2.py deleted file mode 100644 index 656014a7617..00000000000 --- a/pep_extensions/pep_processor/html/pep_jinja2.py +++ /dev/null @@ -1,30 +0,0 @@ -from __future__ import annotations - -import re -from sphinx import jinja2glue -from typing import TYPE_CHECKING, List - -import pep_extensions.config as pep_config - -if TYPE_CHECKING: - # For type annotation - from sphinx.builders import Builder - from sphinx.theming import Theme - -pep_title_pat = re.compile(r"(PEP \d+).*", flags=re.IGNORECASE) - - -def _pep_id(pep_full_title: str) -> str: - matches = pep_title_pat.match(pep_full_title.strip()) - if not matches: - return "" - pep_short_title = matches.group(1).strip() - pep_num = pep_short_title[4:] - pep_id = pep_config.pep_stem.format(pep_num).replace("-", " ").upper() - return pep_id - - -class PEPTemplateLoader(jinja2glue.BuiltinTemplateLoader): - def init(self, builder: Builder, theme: Theme = None, dirs: List[str] = None) -> None: - super(PEPTemplateLoader, self).init(builder, theme, dirs) - self.environment.filters['pep_id'] = _pep_id \ No newline at end of file diff --git a/pep_extensions/pep_processor/parsing/pep_parser.py b/pep_extensions/pep_processor/parsing/pep_parser.py deleted file mode 100644 index ef3dd4f73ad..00000000000 --- a/pep_extensions/pep_processor/parsing/pep_parser.py +++ /dev/null @@ -1,23 +0,0 @@ -from sphinx import parsers - -from pep_extensions.pep_processor.transforms import pep_headers -from pep_extensions.pep_processor.transforms import pep_title -from pep_extensions.pep_processor.transforms import pep_contents -from pep_extensions.pep_processor.transforms import pep_footer - - -class PEPParser(parsers.RSTParser): - supported = ("pep", "python-enhancement-proposal") - - def __init__(self): - super().__init__(rfc2822=True) - - def get_transforms(self): - transforms = super().get_transforms() - transforms.extend([ - pep_headers.PEPHeaders, - pep_title.PEPTitle, - pep_contents.PEPContents, - pep_footer.PEPFooter, - ]) - return transforms diff --git a/pep_extensions/pep_processor/parsing/pep_role.py b/pep_extensions/pep_processor/parsing/pep_role.py deleted file mode 100644 index 3cf4163f339..00000000000 --- a/pep_extensions/pep_processor/parsing/pep_role.py +++ /dev/null @@ -1,14 +0,0 @@ -from sphinx import roles -import pep_extensions.config - -pep_url = pep_extensions.config.pep_url - - -class PEPRole(roles.PEP): - def build_uri(self) -> str: - base_url = self.inliner.document.settings.pep_base_url - ret = self.target.split('#', 1) - if len(ret) == 2: - return base_url + (pep_url + '#{}').format(int(ret[0]), ret[1]) - else: - return base_url + pep_url.format(int(ret[0])) diff --git a/pep_extensions/pep_processor/transforms/pep_contents.py b/pep_extensions/pep_processor/transforms/pep_contents.py deleted file mode 100644 index bd336deeb29..00000000000 --- a/pep_extensions/pep_processor/transforms/pep_contents.py +++ /dev/null @@ -1,63 +0,0 @@ -from pathlib import Path -from docutils import nodes -from docutils import transforms -from docutils.transforms import parts - - -class PEPContents(transforms.Transform): - - """ - Insert an empty table of contents topic and a transform placeholder into - the document after the RFC 2822 header. - """ - - default_priority = 380 - - def apply(self): - if not Path(self.document["source"]).match("pep-*"): - # not a PEP file - return - title = nodes.title('', 'Contents') - topic = nodes.topic('', title, classes=['contents']) - name = nodes.fully_normalize_name('contents') - if not self.document.has_name(name): - topic['names'].append(name) - self.document.note_implicit_target(topic) - pending = nodes.pending(Contents) - topic += pending - self.document.children[0].insert(2, topic) - self.document.note_pending(pending) - - # Add horizontal rule before contents - transition = nodes.transition() - self.document[0].insert(2, transition) - - -class Contents(parts.Contents): - def __init__(self, document, startnode=None): - super().__init__(document, startnode) - self.toc_id = None - self.backlinks = None - - def apply(self): - # let the writer (or output software) build the contents list? - try: - toc_by_writer = self.document.settings.use_latex_toc - except AttributeError: - toc_by_writer = False - - details = self.startnode.details - startnode = self.document[0] - self.toc_id = self.startnode.parent['ids'][0] - self.backlinks = self.document.settings.toc_backlinks - - if toc_by_writer: - # move customization settings to the parent node - self.startnode.parent.attributes.update(details) - self.startnode.parent.remove(self.startnode) - else: - contents = self.build_contents(startnode) - if len(contents): - self.startnode.replace_self(contents) - else: - self.startnode.parent.parent.remove(self.startnode.parent) diff --git a/pep_extensions/pep_processor/transforms/pep_footer.py b/pep_extensions/pep_processor/transforms/pep_footer.py deleted file mode 100644 index 71a259cac0b..00000000000 --- a/pep_extensions/pep_processor/transforms/pep_footer.py +++ /dev/null @@ -1,99 +0,0 @@ -import datetime -import subprocess -from pathlib import Path - -from docutils import nodes -from docutils import transforms -from docutils.transforms import misc -from docutils.transforms import references - -import pep_extensions.config as pep_config - - -class PEPFooter(transforms.Transform): - - """ - Relevant footer transforms for PEPs, including appending external - links to footnotes and creating a link to the (GitHub) source. - - TargetNotes: - Locate the "References" section, insert a placeholder at the end - for an external target footnote insertion transform, and schedule - the transform to run immediately. - - Source Link: - Create the link to the source file from the document source path, - and append the text to the end of the document. - - """ - - default_priority = 520 - - def apply(self): - pep_source_path = Path(self.document["source"]) - if not pep_source_path.match("pep-*"): - # not a PEP file - return - - doc = self.document[0] - i = len(doc) - 1 - reference_section = copyright = None - while i >= 0 and isinstance(doc[i], nodes.section): - title_words = doc[i][0].astext().lower().split() - if 'references' in title_words: - reference_section = doc[i] - break - elif 'copyright' in title_words: - copyright = i - i -= 1 - if not reference_section: - reference_section = nodes.section() - reference_section += nodes.title('', 'References') - self.document.set_id(reference_section) - if copyright: - # Put the new "References" section before "Copyright": - doc.insert(copyright, reference_section) - else: - # Put the new "References" section at end of doc: - doc.append(reference_section) - pending = nodes.pending(references.TargetNotes) - reference_section.append(pending) - self.document.note_pending(pending, 0) - pending = nodes.pending(misc.CallBack, details={'callback': self.cleanup_callback}) - reference_section.append(pending) - self.document.note_pending(pending, 1) - - self.add_source_link(pep_source_path) - self.add_commit_history_info(pep_source_path) - - @staticmethod - def cleanup_callback(pending: nodes.pending): - """ - Remove an empty "References" section. - - Called after the `references.TargetNotes` transform is complete. - """ - if len(pending.parent) == 2: # and <pending> - pending.parent.parent.remove(pending.parent) - - def add_source_link(self, pep_source_path: Path) -> None: - source_link = pep_config.pep_vcs_url.format(pep_source_path.name) - link_node = nodes.reference("", source_link, refuri=source_link) - span_node = nodes.inline("", "Source: ", link_node) - self.document.append(span_node) - - def add_commit_history_info(self, pep_source_path: Path) -> None: - args = ['git', '--no-pager', 'log', '-1', '--format=%at', pep_source_path.name] - try: - b = subprocess.check_output(args) - since_epoch = b.decode("UTF-8").strip() - dt = datetime.datetime.utcfromtimestamp(float(since_epoch)) - except (subprocess.CalledProcessError, ValueError): - return None - - dt.replace(tzinfo=datetime.timezone.utc) - commit_link = pep_config.pep_commits_url.format(pep_source_path.name) - link_node = nodes.reference("", dt.isoformat(), refuri=commit_link) - span_node = nodes.inline("", f"Last modified: ", link_node) - self.document.append(nodes.line("", "", classes=['zero-height'])) - self.document.append(span_node) \ No newline at end of file diff --git a/pep_extensions/pep_processor/transforms/pep_headers.py b/pep_extensions/pep_processor/transforms/pep_headers.py deleted file mode 100644 index 2d65f768f13..00000000000 --- a/pep_extensions/pep_processor/transforms/pep_headers.py +++ /dev/null @@ -1,110 +0,0 @@ -import re -from pathlib import Path - -from docutils import nodes -from docutils import transforms -from docutils.transforms import peps - -from pep_extensions.pep_processor.transforms import pep_zero -import pep_extensions.config - -pep_url = pep_extensions.config.pep_url - - -class DataError(Exception): - pass - - -# PEPHeaders is identical to docutils.transforms.peps.Headers excepting bdfl-delegate, sponsor & superseeded-by -class PEPHeaders(transforms.Transform): - - """ - Process fields in a PEP's initial RFC-2822 header. - """ - - default_priority = 330 - - def apply(self): - if not len(self.document): - # @@@ replace these DataErrors with proper system messages - raise DataError("Document tree is empty.") - - if not Path(self.document["source"]).match("pep-*"): - # not a PEP file - return - - header = self.document[0] - if not isinstance(header, nodes.field_list) or "rfc2822" not in header["classes"]: - raise DataError("Document does not begin with an RFC-2822 header; it is not a PEP.") - - pep = None - pep_field = header[0] - if pep_field[0].astext().lower() == "pep": # should be the first field - value = pep_field[1].astext() - try: - pep = int(value) - except ValueError: - pep = value - msg = self.document.reporter.warning( - f"'PEP' header must contain an integer; '{pep}' is an invalid value.", - base_node=pep_field, - ) - msgid = self.document.set_id(msg) - prb = nodes.problematic(value, value or "(none)", refid=msgid) - prbid = self.document.set_id(prb) - msg.add_backref(prbid) - if len(pep_field[1]): - pep_field[1][0][:] = [prb] - else: - pep_field[1] += nodes.paragraph("", "", prb) - - if pep is None: - raise DataError('Document does not contain an RFC-2822 "PEP" ' "header.") - - if pep == 0: - # Special processing for PEP 0. - pending = nodes.pending(pep_zero.PEPZero) - self.document.insert(1, pending) - self.document.note_pending(pending) - - # If there are less than two headers in the preamble, or if Title is absent - if len(header) < 2 or header[1][0].astext().lower() != "title": - raise DataError("No title!") - - fields_to_remove = [] - for field in header: - name = field[0].astext().lower() - body = field[1] - if len(body) > 1: - raise DataError(f"PEP header field body contains multiple elements:\n{field.pformat(level=1)}") - elif len(body) == 1: - if not isinstance(body[0], nodes.paragraph): - raise DataError(f"PEP header field body may only contain a single paragraph:\n{field.pformat(level=1)}") - else: - # body is empty - continue - - para = body[0] - if name in ("author", "bdfl-delegate", "sponsor"): - for node in para: - if isinstance(node, nodes.reference): - node.replace_self(peps.mask_email(node)) - elif name == "discussions-to": - for node in para: - if isinstance(node, nodes.reference): - node.replace_self(peps.mask_email(node, pep)) - elif name in ("replaces", "superseded-by", "requires"): - newbody = [] - space = nodes.Text(" ") - for refpep in re.split(r",?\s+", body.astext()): - pepno = int(refpep) - newbody.append(nodes.reference( - refpep, refpep, - refuri=(self.document.settings.pep_base_url + pep_url.format(pepno)))) - newbody.append(space) - para[:] = newbody[:-1] # drop trailing space - elif name in ("last-modified", "content-type", "version"): - fields_to_remove.append(field) - - for field in fields_to_remove: - field.parent.remove(field) diff --git a/pep_extensions/pep_processor/transforms/pep_title.py b/pep_extensions/pep_processor/transforms/pep_title.py deleted file mode 100644 index f0fa5a2ccaf..00000000000 --- a/pep_extensions/pep_processor/transforms/pep_title.py +++ /dev/null @@ -1,52 +0,0 @@ -from pathlib import Path -from docutils import nodes -import docutils.transforms as transforms -from docutils.parsers.rst import states - - -class PEPTitle(transforms.Transform): - - """ - Insert an empty table of contents topic and a transform placeholder into - the document after the RFC 2822 header. - """ - - # needs to run before docutils.transforms.frontmatter.DocInfo - default_priority = 335 - - def apply(self): - if not Path(self.document["source"]).match("pep-*"): - # not a PEP file - return - - # Directory to hold the PEP's RFC2822 header details, to extract a title string - pep_header_details = {} - - # Iterate through the header fields, which are the first section of the document - for field in self.document[0]: - row_attributes = {} - for sub in field: - # Hold details of the attribute's tag against its details - row_attributes[sub.tagname] = sub.rawsource - # Collapse the dictionary by removing tag names - pep_header_details[row_attributes["field_name"]] = row_attributes["field_body"] - - # Create the title string for the PEP - pep_number = int(pep_header_details["PEP"]) - pep_title = pep_header_details["Title"] - pep_title_string = f"PEP {pep_number} -- {pep_title}" - - # Generate the title section node and its properties - pep_title_node = nodes.section() - textnode = nodes.Text(pep_title_string, pep_title_string) - titlenode = nodes.title(pep_title_string, '', textnode) - titlenode['classes'].append("page-title") - name = states.normalize_name(titlenode.astext()) - pep_title_node['names'].append(name) - pep_title_node += titlenode - - # Insert the title node as the root element, move children down - document_children = self.document.children - self.document.children = [pep_title_node] - pep_title_node.extend(document_children) - self.document.note_implicit_target(pep_title_node, pep_title_node) diff --git a/pep_extensions/pep_processor/transforms/pep_zero.py b/pep_extensions/pep_processor/transforms/pep_zero.py deleted file mode 100644 index fd31e6994ec..00000000000 --- a/pep_extensions/pep_processor/transforms/pep_zero.py +++ /dev/null @@ -1,74 +0,0 @@ -from docutils import nodes -from docutils import transforms -from docutils.transforms import peps -import pep_extensions.config - -pep_url = pep_extensions.config.pep_url - - -class PEPZero(transforms.Transform): - - """ - Special processing for PEP 0. - """ - - default_priority = 760 - - def apply(self): - visitor = PEPZeroSpecial(self.document) - self.document.walk(visitor) - self.startnode.parent.remove(self.startnode) - - -class PEPZeroSpecial(nodes.SparseNodeVisitor): - - """ - Perform the special processing needed by PEP 0: - - - Mask email addresses. - - Link PEP numbers in the second column of 4-column tables to the PEPs - themselves. - """ - - def __init__(self, document: nodes.document): - super().__init__(document) - self.pep_table: int = 0 - self.entry: int = 0 - - def unknown_visit(self, node: nodes.Node) -> None: - pass - - @staticmethod - def visit_reference(node: nodes.reference) -> None: - node.replace_self(peps.mask_email(node)) - - @staticmethod - def visit_field_list(node: nodes.field_list) -> None: - if 'rfc2822' in node['classes']: - raise nodes.SkipNode - - def visit_tgroup(self, node: nodes.tgroup) -> None: - self.pep_table = node['cols'] == 4 - self.entry = 0 - - def visit_colspec(self, node: nodes.colspec) -> None: - self.entry += 1 - if self.pep_table and self.entry == 2: - node['classes'].append('num') - - def visit_row(self, _node: nodes.row) -> None: - self.entry = 0 - - def visit_entry(self, node: nodes.entry) -> None: - self.entry += 1 - if self.pep_table and self.entry == 2 and len(node) == 1: - node['classes'].append('num') - p = node[0] - if isinstance(p, nodes.paragraph) and len(p) == 1: - text = p.astext() - try: - pep = int(text) - ref = self.document.settings.pep_base_url + pep_url.format(pep) - p[0] = nodes.reference(text, text, refuri=ref) - except ValueError: - pass diff --git a/pep_extensions/pep_zero_generator/pep_0_parser.py b/pep_extensions/pep_zero_generator/pep_0_parser.py deleted file mode 100644 index 12c2d7c7ff1..00000000000 --- a/pep_extensions/pep_zero_generator/pep_0_parser.py +++ /dev/null @@ -1,347 +0,0 @@ -"""Code for handling object representation of a PEP.""" -import re -import textwrap -import unicodedata -from email.message import Message -from email.parser import HeaderParser -from pathlib import Path -from typing import List, Tuple - - -class PEPError(Exception): - def __init__(self, error, pep_file, pep_number=None): - super(PEPError, self).__init__(error) - self.filename = pep_file - self.number = pep_number - - def __str__(self): - error_msg = super(PEPError, self).__str__() - error_msg = f"({self.filename}): {error_msg}" - pep_str = f"PEP {self.number}" - return f"{pep_str} {error_msg}" if self.number is not None else error_msg - - -class Author: - """Represent PEP authors. - - Attributes: - - + first_last : str - The author's full name. - - + last_first : str - Output the author's name in Last, First, Suffix order. - - + first : str - The author's first name. A middle initial may be included. - - + last : str - The author's last name. - - + suffix : str - A person's suffix (can be the empty string). - - + sort_by : str - Modification of the author's last name that should be used for - sorting. - - + email : str - The author's email address. - """ - - def __init__(self, author_and_email_tuple: Tuple[str, str], authors_exceptions: dict): - """Parse the name and email address of an author.""" - self.first = self.last = '' - - name, email = author_and_email_tuple - self.first_last: str = name.strip() - self.email: str = email.lower() - - name_dict = authors_exceptions.get(self.first_last) - if name_dict: - self.last_first = name_dict["Surname First"] - self.nick = self.last = name_dict["Name Reference"] - else: - self.set_name_parts() - - def set_name_parts(self): - name_dict = self._parse_name(self.first_last) - suffix = name_dict.get("suffix") - if "name" in name_dict: - self.last_first = name_dict["name"] - self.nick = name_dict["name"] - else: - self.first = name_dict["forename"].rstrip() - self.last = name_dict["surname"] - if self.last[1] == ".": - # Add an escape to avoid docutils turning `v.` into `22.`. - self.last = "\\" + self.last - self.last_first = ", ".join([self.last, self.first]) - self.nick = self.last - - if suffix: - self.last_first += f", {suffix}" - - def __hash__(self): - return hash(self.first_last) - - def __eq__(self, other): - if not isinstance(other, Author): - return NotImplemented - return self.first_last == other.first_last - - @property - def sort_by(self) -> str: - last = self.last_first.split(",")[0] - name_parts = last.split() - for index, part in enumerate(name_parts): - if part[0].isupper(): - base = " ".join(name_parts[index:]).lower() - break - else: - # If no capitals, use the whole string - base = last.lower() - return unicodedata.normalize("NFKD", base) - - @staticmethod - def _parse_name(full_name): - """Decompose a full name into parts. - - If a mononym (e.g, 'Aahz') then return the full name. If there are - suffixes in the name (e.g. ', Jr.' or 'III'), then find and extract - them. If there is a middle initial followed by a full stop, then - combine the following words into a surname (e.g. N. Vander Weele). If - there is a leading, lowercase portion to the last name (e.g. 'van' or - 'von') then include it in the surname. - - """ - possible_suffixes = ["Jr", "Jr.", "II", "III"] - - suffix_partition = full_name.partition(",") - pre_suffix = suffix_partition[0].strip() - suffix = suffix_partition[2].strip() - - name_parts = pre_suffix.split(" ") - num_parts = len(name_parts) - name = {"suffix": suffix} - - if num_parts == 0: - raise ValueError("Name is empty!") - elif num_parts == 1: - name.update(name=name_parts[0]) - elif num_parts == 2: - name.update(forename=name_parts[0], surname=name_parts[1]) - elif num_parts > 2: - # handles III etc. - if name_parts[-1] in possible_suffixes: - new_suffix = " ".join([*name_parts[-1:], suffix]).strip() - name_parts.pop(-1) - name.update(suffix=new_suffix) - - # handles von, van, v. etc. - if name_parts[-2].islower(): - forename = " ".join(name_parts[:-2]) - surname = " ".join(name_parts[-2:]) - name.update(forename=forename, surname=surname) - - # handles double surnames after a middle initial (e.g. N. Vander Weele) - elif any(s.endswith(".") for s in name_parts): - split_position = [i for i, x in enumerate(name_parts) if x.endswith(".")][-1] + 1 - forename = " ".join(name_parts[:split_position]) - surname = " ".join(name_parts[split_position:]) - name.update(forename=forename, surname=surname) - - else: - forename = " ".join(name_parts[:-1]) - surname = " ".join(name_parts[-1:]) - name.update(forename=forename, surname=surname) - - return name - - -class PEP: - """Representation of PEPs. - - Attributes: - - + number : int - PEP number. - - + title : str - PEP title. - - + type_ : str - The type of PEP. Can only be one of the values from - PEP.type_values. - - + status : str - The PEP's status. Value must be found in PEP.status_values. - - + authors : Sequence(Author) - A list of the authors. - """ - - # The various RFC 822 headers that are supported. - # The second item in the nested tuples represents if the header is - # required or not. - headers = ( - ("PEP", True), ("Title", True), ("Version", False), - ("Last-Modified", False), ("Author", True), ("Sponsor", False), - ("BDFL-Delegate", False), ("Discussions-To", False), ("Status", True), - ("Type", True), ("Content-Type", False), ("Requires", False), - ("Created", True), ("Python-Version", False), ("Post-History", False), - ("Replaces", False), ("Superseded-By", False), ("Resolution", False), - ) - # Valid values for the Type header. - type_values = ("Standards Track", "Informational", "Process") - # Valid values for the Status header. - # Active PEPs can only be for Informational or Process PEPs. - status_values = ( - "Accepted", "Provisional", "Rejected", "Withdrawn", - "Deferred", "Final", "Active", "Draft", "Superseded", - ) - - def raise_pep_error(self, msg: str, pep_num: bool = False) -> None: - pep_number = self.number if pep_num else None - raise PEPError(msg, self.filename, pep_number=pep_number) - - def __init__(self, filename: Path, author_lookup: dict, title_length: int): - """Init object from an open PEP file object. - - pep_file is full text of the PEP file, filename is path of the PEP file, author_lookup is author exceptions file - - """ - self.filename: Path = filename - self.number: int = 0 - self.title: str = "" - self.type_: str = "" - self.status: str = "" - self.authors: List[Author] = [] - self.title_length: int = title_length - - # Parse the headers. - pep_parser = HeaderParser() - pep_text = filename.read_text("UTF8") - metadata = pep_parser.parsestr(pep_text) - self.parse_pep(metadata) - self.parse_authors(metadata["Author"], author_lookup) - - if self.number != int(filename.stem[4:]): - self.raise_pep_error(f'PEP number does not match file name ({filename})', pep_num=True) - - def parse_pep(self, metadata: Message) -> None: - required_header_misses = set(t[0] for t in self.headers if t[1]) - set(metadata.keys()) - if required_header_misses: - msg = f"PEP is missing required headers ({', '.join(sorted(required_header_misses))})" - self.raise_pep_error(msg) - - # 'PEP'. - try: - self.number = int(metadata["PEP"]) - except ValueError: - self.raise_pep_error("PEP number isn't an integer") - - # 'Title'. - self.title = metadata["Title"] - - # 'Type'. - type_ = metadata["Type"] - if type_ not in self.type_values: - self.raise_pep_error(f"{type_} is not a valid Type value", pep_num=True) - self.type_ = type_ - - # 'Status'. - status = metadata["Status"] - if status not in self.status_values: - if status == "April Fool!": # See PEP 401 :) - status = "Rejected" - else: - self.raise_pep_error(f"{status} is not a valid Status value", pep_num=True) - - # Special case for Active PEPs. - if status == "Active" and self.type_ not in ("Process", "Informational"): - msg = "Only Process and Informational PEPs may have an Active status" - self.raise_pep_error(msg, pep_num=True) - - # Special case for Provisional PEPs. - if status == "Provisional" and self.type_ != "Standards Track": - msg = "Only Standards Track PEPs may have a Provisional status" - self.raise_pep_error(msg, pep_num=True) - self.status = status - - def parse_authors(self, author_header: str, author_lookup: dict) -> None: - """Parse Author header line""" - authors_and_emails = self._parse_author(author_header) - if len(authors_and_emails) < 1: - raise self.raise_pep_error("no authors found", pep_num=True) - self.authors = [Author(email, author_lookup) for email in authors_and_emails] - - angled = re.compile(r"(?P<author>.+?) <(?P<email>.+?)>(,\s*)?") - paren = re.compile(r"(?P<email>.+?) \((?P<author>.+?)\)(,\s*)?") - simple = re.compile(r"(?P<author>[^,]+)(,\s*)?") - - @staticmethod - def _parse_author(data: str) -> list: - """Return a list of author names and emails.""" - # XXX Consider using email.utils.parseaddr (doesn't work with names - # lacking an email address. - - author_list = [] - for regex in (PEP.angled, PEP.paren, PEP.simple): - for match in regex.finditer(data): - # Watch out for suffixes like 'Jr.' when they are comma-separated - # from the name and thus cause issues when *all* names are only - # separated by commas. - match_dict = match.groupdict() - author = match_dict["author"] - if not author.partition(" ")[1] and author.endswith("."): - prev_author = author_list.pop() - author = ", ".join([prev_author, author]) - if "email" not in match_dict: - email = "" - else: - email = match_dict["email"] - author_list.append((author, email)) - else: - # If authors were found then stop searching as only expect one - # style of author citation. - if author_list: - break - return author_list - - @property - def type_abbr(self) -> str: - """Return how the type is to be represented in the index.""" - return self.type_[0].upper() - - @property - def status_abbr(self) -> str: - """Return how the status should be represented in the index.""" - if self.status in ("Draft", "Active"): - return " " - else: - return self.status[0].upper() - - @property - def author_abbr(self) -> str: - """Return the author list as a comma-separated with only last names.""" - return ", ".join(x.nick for x in self.authors) - - @property - def title_abbr(self) -> str: - """Shorten the title to be no longer than the max title length.""" - if len(self.title) <= self.title_length: - return self.title - wrapped_title = textwrap.wrap(self.title, self.title_length - 4) - return wrapped_title[0] + " ..." - - @property - def pep(self) -> dict: - """Return the line entry for the PEP.""" - return { - "type": self.type_abbr, - "number": self.number, - "title": self.title_abbr, - "status": self.status_abbr, - "authors": self.author_abbr, - } diff --git a/pep_extensions/pep_zero_generator/pep_0_writer.py b/pep_extensions/pep_zero_generator/pep_0_writer.py deleted file mode 100644 index 368a200b2a8..00000000000 --- a/pep_extensions/pep_zero_generator/pep_0_writer.py +++ /dev/null @@ -1,314 +0,0 @@ -"""Code to handle the output of PEP 0.""" -import datetime -import unicodedata -from functools import partial -from itertools import groupby -from operator import attrgetter -from typing import List - -from pep_extensions.pep_zero_generator import pep_0_parser - -title_length = 55 -author_length = 40 -table_separator = "== ==== " + "="*title_length + " " + "="*author_length - -# column format is called as a function with a mapping containing field values -column_format = partial( - "{type}{status}{number: >5} {title: <{title_length}} {authors}".format, - title_length=title_length -) - -header = f"""\ -PEP: 0 -Title: Index of Python Enhancement Proposals (PEPs) -Last-Modified: {datetime.date.today().strftime("%Y-%m-%d")} -Author: python-dev <python-dev@python.org> -Status: Active -Type: Informational -Content-Type: text/x-rst -Created: 13-Jul-2000 -""" - -intro = """\ -This PEP contains the index of all Python Enhancement Proposals, -known as PEPs. PEP numbers are assigned by the PEP editors, and -once assigned are never changed [1_]. The version control history [2_] of -the PEP texts represent their historical record. -""" - -references = """\ -.. [1] PEP 1: PEP Purpose and Guidelines -.. [2] View PEP history online: https://github.com/python/peps -""" - - -class PEPZeroWriter: - # This is a list of reserved PEP numbers. Reservations are not to be used for - # the normal PEP number allocation process - just give out the next available - # PEP number. These are for "special" numbers that may be used for semantic, - # humorous, or other such reasons, e.g. 401, 666, 754. - # - # PEP numbers may only be reserved with the approval of a PEP editor. Fields - # here are the PEP number being reserved and the claimants for the PEP. - # Although the output is sorted when PEP 0 is generated, please keep this list - # sorted as well. - RESERVED = [ - (801, "Warsaw"), - ] - - def __init__(self): - self._output: List[str] = [] - - def output(self, content): - # Appends content argument to the _output list - self._output.append(content) - - def emit_newline(self): - self.output('') - - def emit_table_separator(self): - self.output(table_separator) - - def emit_author_table_separator(self, max_name_len): - author_table_separator = "=" * max_name_len + " " + "=" * len("email address") - self.output(author_table_separator) - - def emit_column_headers(self): - """Output the column headers for the PEP indices.""" - column_headers = { - "status": ".", - "type": ".", - "number": "PEP", - "title": "PEP Title", - "authors": "PEP Author(s)", - } - self.emit_table_separator() - self.output(column_format(**column_headers)) - self.emit_table_separator() - - @staticmethod - def sort_peps(peps): - """Sort PEPs into meta, informational, accepted, open, finished, - and essentially dead.""" - meta = [] - info = [] - provisional = [] - accepted = [] - open_ = [] - finished = [] - historical = [] - deferred = [] - dead = [] - for pep in peps: - # Order of 'if' statement important. Key Status values take precedence - # over Type value, and vice-versa. - if pep.status == "Draft": - open_.append(pep) - elif pep.status == "Deferred": - deferred.append(pep) - elif pep.type_ == "Process": - if pep.status == "Active": - meta.append(pep) - elif pep.status in ("Withdrawn", "Rejected"): - dead.append(pep) - else: - historical.append(pep) - elif pep.status in ("Rejected", "Withdrawn", "Incomplete", "Superseded"): - dead.append(pep) - elif pep.type_ == "Informational": - # Hack until the conflict between the use of "Final" - # for both API definition PEPs and other (actually - # obsolete) PEPs is addressed - if pep.status == "Active" or "Release Schedule" not in pep.title: - info.append(pep) - else: - historical.append(pep) - elif pep.status == "Provisional": - provisional.append(pep) - elif pep.status in ("Accepted", "Active"): - accepted.append(pep) - elif pep.status == "Final": - finished.append(pep) - else: - raise pep_0_parser.PEPError(f"unsorted ({pep.type_}/{pep.status})", pep.filename, pep.number) - return meta, info, provisional, accepted, open_, finished, historical, deferred, dead - - @staticmethod - def verify_email_addresses(peps): - authors_dict = {} - for pep in peps: - for author in pep.authors: - # If this is the first time we have come across an author, add them. - if author not in authors_dict: - authors_dict[author] = [author.email] - else: - found_emails = authors_dict[author] - # If no email exists for the author, use the new value. - if not found_emails[0]: - authors_dict[author] = [author.email] - # If the new email is an empty string, move on. - elif not author.email: - continue - # If the email has not been seen, add it to the list. - elif author.email not in found_emails: - authors_dict[author].append(author.email) - - valid_authors_dict = {} - too_many_emails = [] - for author, emails in authors_dict.items(): - if len(emails) > 1: - too_many_emails.append((author.first_last, emails)) - else: - valid_authors_dict[author] = emails[0] - if too_many_emails: - err_output = [] - for author, emails in too_many_emails: - err_output.append(" " * 4 + f"{author}: {emails}") - raise ValueError( - "some authors have more than one email address listed:\n" - + "\n".join(err_output) - ) - - return valid_authors_dict - - @staticmethod - def sort_authors(authors_dict): - authors_list = sorted(authors_dict.keys(), key=attrgetter("sort_by")) - unique_authors = [next(a) for k, a in groupby(authors_list, key=attrgetter("last_first"))] - return unique_authors - - @staticmethod - def normalized_last_first(name): - return len(unicodedata.normalize("NFC", name.last_first)) - - def emit_title(self, text, anchor, *, symbol="="): - self.output(".. _{anchor}:\n".format(anchor=anchor)) - self.output(text) - self.output(symbol * len(text)) - self.emit_newline() - - def emit_subtitle(self, text, anchor): - self.emit_title(text, anchor, symbol="-") - - def emit_pep_category(self, category, anchor, peps): - self.emit_subtitle(category, anchor) - self.emit_column_headers() - for pep in peps: - self.output(pep) - self.emit_table_separator() - self.emit_newline() - - def write_pep0(self, peps: List[pep_0_parser.PEP]): - - # PEP metadata - self.output(header) - self.emit_newline() - - # Introduction - self.emit_title("Introduction", "intro") - self.output(intro) - self.emit_newline() - - # PEPs by category - self.emit_title("Index by Category", "by-category") - (meta, info, provisional, accepted, open_, finished, historical, deferred, dead) = self.sort_peps(peps) - pep_categories = [ - ("Meta-PEPs (PEPs about PEPs or Processes)", "by-category-meta", meta), - ("Other Informational PEPs", "by-category-other-info", info), - ("Provisional PEPs (provisionally accepted; interface may still change)", "by-category-provisional", provisional), - ("Accepted PEPs (accepted; may not be implemented yet)", "by-category-accepted", accepted), - ("Open PEPs (under consideration)", "by-category-open", open_), - ("Finished PEPs (done, with a stable interface)", "by-category-finished", finished), - ("Historical Meta-PEPs and Informational PEPs", "by-category-historical", historical), - ("Deferred PEPs (postponed pending further research or updates)", "by-category-deferred", deferred), - ("Abandoned, Withdrawn, and Rejected PEPs", "by-category-abandoned", dead), - ] - for pep_category in pep_categories: - category = pep_category[0] - anchor = pep_category[1] - peps_in_category = pep_category[2] - self.emit_pep_category(category, anchor, peps_in_category) - - self.emit_newline() - - # PEPs by number - self.emit_title("Numerical Index", "by-pep-number") - self.emit_column_headers() - prev_pep = 0 - for pep in peps: - if pep.number - prev_pep > 1: - self.emit_newline() - self.output(column_format(**pep.pep)) - prev_pep = pep.number - - self.emit_table_separator() - self.emit_newline() - - # Reserved PEP numbers - self.emit_title("Reserved PEP Numbers", "reserved") - self.emit_column_headers() - for number, claimants in sorted(self.RESERVED): - self.output(column_format(**{ - "type": ".", - "status": ".", - "number": number, - "title": "RESERVED", - "authors": claimants, - })) - - self.emit_table_separator() - self.emit_newline() - - # PEP types key - self.emit_title("PEP Types Key", "type-key") - for type_ in sorted(pep_0_parser.PEP.type_values): - self.output(f" {type_[0]} - {type_} PEP") - self.emit_newline() - - self.emit_newline() - - # PEP status key - self.emit_title("PEP Status Key", "status-key") - for status in sorted(pep_0_parser.PEP.status_values): - # Draft PEPs have no status displayed, Active shares a key with Accepted - if status in ("Active", "Draft"): - continue - if status == "Accepted": - msg = " A - Accepted (Standards Track only) or Active proposal" - else: - msg = " {status[0]} - {status} proposal".format(status=status) - self.output(msg) - self.emit_newline() - - self.emit_newline() - - # PEP owners - self.emit_title("Authors/Owners", "authors") - authors_dict = self.verify_email_addresses(peps) - max_name = max(authors_dict.keys(), key=self.normalized_last_first) - max_name_len = len(max_name.last_first) - self.emit_author_table_separator(max_name_len) - _author_header_fmt = f"{'Name':{max_name_len}} Email Address" - self.output(_author_header_fmt) - self.emit_author_table_separator(max_name_len) - sorted_authors = self.sort_authors(authors_dict) - _author_fmt = "{author.last_first:{max_name_len}} {author_email}" - for author in sorted_authors: - # Use the email from authors_dict instead of the one from 'author' as - # the author instance may have an empty email. - _entry = _author_fmt.format( - author=author, - author_email=authors_dict[author], - max_name_len=max_name_len, - ) - self.output(_entry) - self.emit_author_table_separator(max_name_len) - self.emit_newline() - self.emit_newline() - - # References for introduction footnotes - self.emit_title("References", "references") - self.output(references) - - pep0_string = '\n'.join([str(s) for s in self._output]) - return pep0_string diff --git a/pep_extensions/pep_zero_generator/pep_index_generator.py b/pep_extensions/pep_zero_generator/pep_index_generator.py deleted file mode 100644 index 82abc7eb8e5..00000000000 --- a/pep_extensions/pep_zero_generator/pep_index_generator.py +++ /dev/null @@ -1,71 +0,0 @@ -"""Automatically create PEP 0 (the PEP index) - -This file generates and writes the PEP index to disk, ready for later -processing by Sphinx. Firstly, we parse the individual PEP files, getting the -RFC2822 header, and parsing and then validating that metadata. - -After collecting and validating all the PEP data, the creation of the index -itself is in three steps: - - 1. Output static text. - 2. Format an entry for the PEP. - 3. Output the PEP (both by the category and numerical index). - -We then add the newly created PEP 0 file to two Sphinx environment variables -to allow it to be processed as normal. - -""" -from __future__ import annotations - -import csv -import re -from pathlib import Path -from typing import TYPE_CHECKING, List - -from pep_extensions.pep_zero_generator import pep_0_parser -from pep_extensions.pep_zero_generator import pep_0_writer - -if TYPE_CHECKING: - from sphinx.application import Sphinx - from sphinx.environment import BuildEnvironment - - -def create_pep_zero(_: Sphinx, env: BuildEnvironment, docnames: list): - # Sphinx app object is unneeded by this function - - # Read from root directory - path = Path('.') - - pep_zero_filename = 'pep-0000' - peps: List[pep_0_parser.PEP] = [] - pep_pat = re.compile(r"pep-\d{4}") # Path.match() doesn't support regular expressions - title_length = pep_0_writer.title_length - - # AUTHORS.csv is an exception file for PEP0 name parsing - with open("AUTHORS.csv", "r", encoding="UTF8") as f: - read = csv.DictReader(f, quotechar='"', skipinitialspace=True) - author_exception_data = {} - for line in read: - full_name = line.pop("Full Name").strip() - details = {k.strip(): v.strip() for k, v in line.items()} - author_exception_data[full_name] = details - - for file_path in path.iterdir(): - if not file_path.is_file(): - continue # Skip directories etc. - if file_path.match('pep-0000*'): - continue # Skip pre-existing PEP 0 files - if pep_pat.match(str(file_path)) and file_path.suffix in (".txt", ".rst"): - file_path_absolute = path.joinpath(file_path).absolute() - pep = pep_0_parser.PEP(file_path_absolute, author_exception_data, title_length) - peps.append(pep) - peps.sort(key=lambda pep: pep.number) - - pep_writer = pep_0_writer.PEPZeroWriter() - pep0_text = pep_writer.write_pep0(peps) - Path(f"{pep_zero_filename}.rst").write_text(pep0_text, encoding='UTF-8') - - # Add to files for builder - docnames.insert(1, pep_zero_filename) - # Add to files for writer - env.found_docs.add(pep_zero_filename) diff --git a/pep_extensions/theme/static/css/mq.css b/pep_extensions/theme/static/css/mq.css deleted file mode 100644 index 516242da337..00000000000 --- a/pep_extensions/theme/static/css/mq.css +++ /dev/null @@ -1,2673 +0,0 @@ -@charset "UTF-8"; -.container, -.row, -.pep-list-header, -.pep-index-list li, -.info-key, -.listing-company, -.list-recent-jobs li { - *zoom: 1; -} -.container:after, -.row:after, -.pep-list-header:after, -.pep-index-list li:after, -.info-key:after, -.listing-company:after, -.list-recent-jobs li:after { - content: ""; - display: table; - clear: both; -} -.container, -.row, -.pep-list-header, -.pep-index-list li, -.info-key, -.listing-company, -.list-recent-jobs li { - *zoom: 1; -} -.container:after, -.row:after, -.pep-list-header:after, -.pep-index-list li:after, -.info-key:after, -.listing-company:after, -.list-recent-jobs li:after { - content: ""; - display: table; - clear: both; -} -@media (max-width: 24.9375em) { - .search-field:focus { - width: 9em; - } -} -@media (max-width: 30em) { - body:after { - content: "animatebody"; - display: none; - speak: none; - } - .slideshow { - display: none; - } -} -@media (min-width: 25em) { - body:after { - content: "animatebody"; - display: none; - speak: none; - } - .introduction { - font-size: 1.3125em; - } - .content-wrapper .container { - padding: 1em 1.5em; - } - .shrubbery .give-me-more { - display: block; - } - .widget-title .prompt, - .listing-company .prompt { - display: inline; - } -} -@media (min-width: 30em) { - body:after { - content: "animatebody"; - display: none; - speak: none; - } - .options-bar .breaker { - display: none; - } - .adjust-font-size { - border-left: 1px solid #2d3e4d; - } - .search-the-site { - border-right: 1px solid #070a0c; - } -} -@media (min-width: 32.5em) { - body:after { - content: "animatebody"; - display: none; - speak: none; - } - body { - /*text-rendering: optimizeLegibility;*/ - } - .col-row .column { - float: left; - } - .two-col > .column, - .four-col > .column { - width: 50%; - } - .two-col > .double-col, - .four-col > .double-col { - width: 100%; - } - .two-col > div:nth-of-type(2n + 3), - .four-col > div:nth-of-type(2n + 3) { - clear: left; - } - .meta-navigation, - .main-header, - .main-navigation, - .content-wrapper, - .main-footer { - clear: both; - } - .container { - max-width: 75em; - width: 100%; - margin: 0 auto; - padding: 0; - } - .introduction { - font-size: 1.5em; - } - .success-stories-widget blockquote { - font-size: 1.125em; - padding: 1em 1.4em 1.3em; - } - input[type="submit"], - input[type="reset"], - button, - .button, - a.button { - display: inline-block; - vertical-align: baseline; - width: auto; - } - .search-field:focus { - width: 8em; - } -} -@media (min-width: 39.9375em) and (max-width: 58.75em) { - body:after { - content: "drawer_navigation"; - display: none; - speak: none; - } - .main-navigation { - text-align: center; - overflow: visible; - } - .main-navigation .menu { - margin-bottom: 0; - } - .main-navigation .tier-1 > a, - .main-navigation .tier-2 > a { - display: block; - padding: 0.5em 1.5em 0.4em 1em; - position: relative; - } - .main-navigation .tier-1 { - display: block; - width: 100%; - } - .main-navigation .tier-1 > a { - text-align: center; - } - .main-navigation .tier-2 > a { - text-align: left; - } - .main-navigation .menu { - *zoom: 1; - } - .main-navigation .menu:after { - content: ""; - display: table; - clear: both; - } - .main-navigation .tier-1 { - position: relative; - } - .main-navigation .subnav { - position: absolute; - z-index: 100; - text-align: left; - } - .no-touch .main-navigation .subnav { - min-width: 100%; - display: none; - -moz-transition: all 0s ease; - -o-transition: all 0s ease; - -webkit-transition: all 0s ease; - transition: all 0s ease; - } - .touch .main-navigation .subnav { - top: 120%; - display: none; - opacity: 0; - -moz-transition: opacity 0.25s ease-in-out; - -o-transition: opacity 0.25s ease-in-out; - -webkit-transition: opacity 0.25s ease-in-out; - transition: opacity 0.25s ease-in-out; - -moz-box-shadow: 0 0.25em 0.75em rgba(0, 0, 0, 0.6); - -webkit-box-shadow: 0 0.25em 0.75em rgba(0, 0, 0, 0.6); - box-shadow: 0 0.25em 0.75em rgba(0, 0, 0, 0.6); - } - .touch .main-navigation .subnav:before { - position: absolute; - content: ""; - width: 0; - height: 0; - border-color: transparent; - border-style: solid; - border-width: 0.75em; - top: -1.45em; - display: block; - } - .no-touch .main-navigation .element-1:hover .subnav, - .no-touch .main-navigation .element-1:focus .subnav, - .no-touch .main-navigation .element-2:hover .subnav, - .no-touch .main-navigation .element-2:focus .subnav, - .no-touch .main-navigation .element-3:hover .subnav, - .no-touch .main-navigation .element-3:focus .subnav, - .no-touch .main-navigation .element-4:hover .subnav, - .no-touch .main-navigation .element-4:focus .subnav { - left: 0; - display: initial; - -moz-transition-delay: 0.25s; - -o-transition-delay: 0.25s; - -webkit-transition-delay: 0.25s; - transition-delay: 0.25s; - } - .no-touch .main-navigation .element-5:hover .subnav, - .no-touch .main-navigation .element-5:focus .subnav, - .no-touch .main-navigation .element-6:hover .subnav, - .no-touch .main-navigation .element-6:focus .subnav, - .no-touch .main-navigation .element-7:hover .subnav, - .no-touch .main-navigation .element-7:focus .subnav, - .no-touch .main-navigation .element-8:hover .subnav, - .no-touch .main-navigation .element-8:focus .subnav, - .no-touch .main-navigation .last:hover .subnav, - .no-touch .main-navigation .last:focus .subnav { - right: 0; - display: initial; - -moz-transition-delay: 0.25s; - -o-transition-delay: 0.25s; - -webkit-transition-delay: 0.25s; - transition-delay: 0.25s; - } - .touch .main-navigation .element-1:hover .subnav, - .touch .main-navigation .element-1 .subnav.touched, - .touch .main-navigation .element-2:hover .subnav, - .touch .main-navigation .element-2 .subnav.touched, - .touch .main-navigation .element-3:hover .subnav, - .touch .main-navigation .element-3 .subnav.touched, - .touch .main-navigation .element-4:hover .subnav, - .touch .main-navigation .element-4 .subnav.touched { - display: block; - opacity: 1; - left: 0; - } - .touch .main-navigation .element-1 .subnav:before, - .touch .main-navigation .element-2 .subnav:before, - .touch .main-navigation .element-3 .subnav:before, - .touch .main-navigation .element-4 .subnav:before { - left: 1.5em; - } - .touch .main-navigation .element-5:hover .subnav, - .touch .main-navigation .element-5 .subnav.touched, - .touch .main-navigation .element-6:hover .subnav, - .touch .main-navigation .element-6 .subnav.touched, - .touch .main-navigation .element-7:hover .subnav, - .touch .main-navigation .element-7 .subnav.touched, - .touch .main-navigation .element-8:hover .subnav, - .touch .main-navigation .element-8 .subnav.touched, - .touch .main-navigation .last:hover .subnav, - .touch .main-navigation .last .subnav.touched { - display: block; - opacity: 1; - right: 0; - } - .touch .main-navigation .element-5 .subnav:before, - .touch .main-navigation .element-6 .subnav:before, - .touch .main-navigation .element-7 .subnav:before, - .touch .main-navigation .element-8 .subnav:before, - .touch .main-navigation .last .subnav:before { - left: auto; - right: 1.5em; - } - .main-navigation .tier-2 { - display: block; - min-width: 100%; - } - .main-navigation .tier-2 a { - white-space: nowrap; - } - .no-touch .main-navigation { - display: block; - clear: both; - text-align: center; - -moz-border-radius: 8px 8px 0 0; - -webkit-border-radius: 8px; - border-radius: 8px 8px 0 0; - -moz-box-shadow: 0 0 10px rgba(0, 0, 0, 0.2); - -webkit-box-shadow: 0 0 10px rgba(0, 0, 0, 0.2); - box-shadow: 0 0 10px rgba(0, 0, 0, 0.2); - } - .no-touch .main-navigation .tier-1 { - float: left; - width: 33.333333%; - } - .no-touch .main-navigation .tier-1.element-6:not(.unstacked), - .no-touch .main-navigation .tier-1.element-7:not(.unstacked) { - width: 16.6666665%; - } - .no-touch .main-navigation .tier-1.element-1 { - -moz-border-radius-topleft: 8px; - -webkit-border-top-left-radius: 8px; - border-top-left-radius: 8px; - } - .no-touch .main-navigation .tier-1.element-1 > a { - -moz-border-radius-topleft: 7px; - -webkit-border-top-left-radius: 7px; - border-top-left-radius: 7px; - } - .no-touch .main-navigation .tier-1.element-3 { - -moz-border-radius-topright: 8px; - -webkit-border-top-right-radius: 8px; - border-top-right-radius: 8px; - border-right: 0; - } - .no-touch .main-navigation .tier-1.element-3 > a { - -moz-border-radius-topright: 7px; - -webkit-border-top-right-radius: 7px; - border-top-right-radius: 7px; - border-right: 0; - } - .no-touch .main-navigation .tier-1.element-7 { - border-right: 0; - } - .no-touch .main-navigation .tier-2 { - font-size: 0.875em; - } - .no-touch .main-navigation .tier-2 > a { - border-right: 1px solid rgba(255, 255, 255, 0.8); - } - .no-touch .main-navigation .subnav { - -moz-box-shadow: 0 0.5em 0.5em rgba(0, 0, 0, 0.3); - -webkit-box-shadow: 0 0.5em 0.5em rgba(0, 0, 0, 0.3); - box-shadow: 0 0.5em 0.5em rgba(0, 0, 0, 0.3); - } - .no-touch .default-page .main-navigation { - position: relative; - margin-bottom: -0.0625em; - } -} -@media (min-width: 40em) { - body:after { - content: "drawer_navigation"; - display: none; - speak: none; - } - .touch body, - .touch #touchnav-wrapper { - position: relative; - width: 100%; - } - .touch .default-page .main-header { - position: static; - } - .touch .main-navigation { - display: block; - position: absolute; - top: 0; - left: -260px; - width: 260px; - height: 100%; - overflow: scroll; - text-align: center; - font-size: 1.125em; - } - .touch .main-navigation a { - text-align: center; - padding: 0.65em 1.25em 0.55em; - } - .touch .main-navigation .tier-2 { - font-size: 0.875em; - } - .touch .main-navigation .subnav { - position: static; - display: block; - opacity: 1; - border-top: 0; - -moz-box-shadow: none; - -webkit-box-shadow: none; - box-shadow: none; - } - .touch #touchnav-wrapper { - -moz-transition: -moz-transform 300ms ease; - -o-transition: -o-transform 300ms ease; - -webkit-transition: -webkit-transform 300ms ease; - transition: transform 300ms ease; - -moz-transform: translate3d(0, 0, 0); - -ms-transform: translate3d(0, 0, 0); - -webkit-transform: translate3d(0, 0, 0); - transform: translate3d(0, 0, 0); - -webkit-backface-visibility: hidden; - } - .touch .show-sidemenu #touchnav-wrapper { - -moz-transform: translate3d(260px, 0, 0); - -ms-transform: translate3d(260px, 0, 0); - -webkit-transform: translate3d(260px, 0, 0); - transform: translate3d(260px, 0, 0); - } - .three-col > .column { - width: 33.3333%; - } - .three-col > .double-col { - width: 66.6666%; - } - .three-col > div:nth-of-type(3n + 4) { - clear: left; - } - .meta-navigation { - text-align: left; - } - .meta-navigation .say-no-more { - display: none; - visibility: hidden; - } - .meta-navigation .jump-link { - display: none; - } - .meta-navigation li { - float: left; - width: 16.6666667%; - border-left: 1px solid #273643; - border-right: 1px solid #11171d; - } - .site-headline { - float: left; - } - .options-bar-container { - float: right; - } - .donate-button { - display: inline; - margin: 0 0.5em 0 0; - position: relative; - top: 19px; - } - .options-bar { - float: right; - width: auto; - } - .touch .main-navigation .subnav:before { - border-color: transparent; - } - .search-field { - -moz-transition: width 0.3s ease-in-out; - -o-transition: width 0.3s ease-in-out; - -webkit-transition: width 0.3s ease-in-out; - transition: width 0.3s ease-in-out; - } - .search-field:focus { - width: 6em; - margin-right: 0.5em; - } - .no-touch .search-button { - display: inline; - } - .slide-copy p { - font-size: 1em; - } - .introduction { - padding: 0 1.5em; - } - .call-to-action { - font-size: 1.5em; - } - .fontface .call-to-action { - font-size: 1.725em; - } - .fontface .call-to-action span:before { - font-size: 0.875em; - } - .header-banner { - padding: 1em; - } - .home .header-banner, - .default-page .header-banner { - padding: 0; - } - .about-banner, - .download-for-current-os, - .documentation-banner, - .welcome-to-the-foundation { - padding-left: 8.51064%; - padding-right: 8.51064%; - } - .default-page .main-header { - position: relative; - z-index: 10; - } - .with-supernav .super-navigation { - display: none; - } - .python-navigation { - background-color: #2d618c; - *zoom: 1; - filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#FF3776AB',endColorstr='#FF2D618C'); - background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIzMCUiIHN0b3AtY29sb3I9IiMzNzc2YWIiLz48c3RvcCBvZmZzZXQ9Ijk1JSIgc3RvcC1jb2xvcj0iIzJkNjE4YyIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=="); - background-size: 100%; - background-image: -webkit-gradient( - linear, - 50% 0, - 50% 100%, - color-stop(30%, #3776ab), - color-stop(95%, #2d618c) - ); - background-image: -moz-linear-gradient(#3776ab 30%, #2d618c 95%); - background-image: -webkit-linear-gradient(#3776ab 30%, #2d618c 95%); - background-image: linear-gradient(#3776ab 30%, #2d618c 95%); - border-top: 1px solid #629ccd; - border-bottom: 1px solid #18334b; - } - .python-navigation .tier-1 { - border-top: 1px solid #4f90c6; - border-right: 1px solid #2b5b84; - border-bottom: 1px solid #1e415e; - border-left: 1px solid #4f90c6; - } - .python-navigation .tier-1 > a { - color: #e6e8ea; - background-color: transparent; - border-top: 1px solid transparent; - border-bottom: 1px solid transparent; - letter-spacing: 0.01em; - } - .python-navigation .tier-1 > a:hover, - .python-navigation .tier-1 > a:focus, - .python-navigation .tier-1 > a .tier-1:hover > a { - color: #fff; - background-color: #2d618c; - *zoom: 1; - filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#FF326B9C',endColorstr='#FF2D618C'); - background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiMzMjZiOWMiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iIzJkNjE4YyIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=="); - background-size: 100%; - background-image: -webkit-gradient( - linear, - 50% 0, - 50% 100%, - color-stop(10%, #326b9c), - color-stop(90%, #2d618c) - ); - background-image: -moz-linear-gradient(#326b9c 10%, #2d618c 90%); - background-image: -webkit-linear-gradient(#326b9c 10%, #2d618c 90%); - background-image: linear-gradient(#326b9c 10%, #2d618c 90%); - border-top: 1px solid #3776ab; - border-bottom: 1px solid #2d618c; - } - .python-navigation .subnav { - border-top: 1px solid #18334b; - background-color: #d6e5f2; - *zoom: 1; - filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#FFBBD4E9',endColorstr='#FFD6E5F2'); - background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiNiYmQ0ZTkiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iI2Q2ZTVmMiIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=="); - background-size: 100%; - background-image: -webkit-gradient( - linear, - 50% 0, - 50% 100%, - color-stop(10%, #bbd4e9), - color-stop(90%, #d6e5f2) - ); - background-image: -moz-linear-gradient(#bbd4e9 10%, #d6e5f2 90%); - background-image: -webkit-linear-gradient(#bbd4e9 10%, #d6e5f2 90%); - background-image: linear-gradient(#bbd4e9 10%, #d6e5f2 90%); - -moz-box-shadow: inset 0 0 20px rgba(55, 118, 171, 0.15); - -webkit-box-shadow: inset 0 0 20px rgba(55, 118, 171, 0.15); - box-shadow: inset 0 0 20px rgba(55, 118, 171, 0.15); - } - .touch .python-navigation .subnav:before { - border-color: transparent transparent #bbd4e9 transparent; - } - .python-navigation .tier-2 > a { - color: rgba(51, 51, 51, 0.9); - border-top: 1px solid rgba(55, 118, 171, 0.25); - border-bottom: 1px solid transparent; - } - .python-navigation .tier-2 > a:hover, - .python-navigation .tier-2 > a:focus { - background: rgba(255, 255, 255, 0.35); - color: rgba(34, 34, 34, 0.9); - } - .python-navigation .tier-2:last-child > a { - border-bottom: 1px solid rgba(55, 118, 171, 0.25); - } - .python-navigation .current_item { - color: #fff; - background-color: #244e71; - *zoom: 1; - filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#FF2B5B84',endColorstr='#FF244E71'); - background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiMyYjViODQiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iIzI0NGU3MSIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=="); - background-size: 100%; - background-image: -webkit-gradient( - linear, - 50% 0, - 50% 100%, - color-stop(10%, #2b5b84), - color-stop(90%, #244e71) - ); - background-image: -moz-linear-gradient(#2b5b84 10%, #244e71 90%); - background-image: -webkit-linear-gradient(#2b5b84 10%, #244e71 90%); - background-image: linear-gradient(#2b5b84 10%, #244e71 90%); - } - .python-navigation .super-navigation { - color: #666; - border: 1px solid #89b4d9; - background-color: #d6e5f2; - *zoom: 1; - filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#FFFCFDFE',endColorstr='#FFD6E5F2'); - background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiNmY2ZkZmUiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iI2Q2ZTVmMiIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=="); - background-size: 100%; - background-image: -webkit-gradient( - linear, - 50% 0, - 50% 100%, - color-stop(10%, #fcfdfe), - color-stop(90%, #d6e5f2) - ); - background-image: -moz-linear-gradient(#fcfdfe 10%, #d6e5f2 90%); - background-image: -webkit-linear-gradient(#fcfdfe 10%, #d6e5f2 90%); - background-image: linear-gradient(#fcfdfe 10%, #d6e5f2 90%); - } - .python-navigation .super-navigation a:not(.button) { - color: #3776ab; - } - .python-navigation .super-navigation h4 { - color: #316998; - } - .psf-navigation { - background-color: #646565; - *zoom: 1; - filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#FF78797A',endColorstr='#FF646565'); - background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIzMCUiIHN0b3AtY29sb3I9IiM3ODc5N2EiLz48c3RvcCBvZmZzZXQ9Ijk1JSIgc3RvcC1jb2xvcj0iIzY0NjU2NSIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=="); - background-size: 100%; - background-image: -webkit-gradient( - linear, - 50% 0, - 50% 100%, - color-stop(30%, #78797a), - color-stop(95%, #646565) - ); - background-image: -moz-linear-gradient(#78797a 30%, #646565 95%); - background-image: -webkit-linear-gradient(#78797a 30%, #646565 95%); - background-image: linear-gradient(#78797a 30%, #646565 95%); - border-top: 1px solid #9e9fa0; - border-bottom: 1px solid #39393a; - } - .psf-navigation .tier-1 { - border-top: 1px solid #929393; - border-right: 1px solid #5f6060; - border-bottom: 1px solid #454647; - border-left: 1px solid #929393; - } - .psf-navigation .tier-1 > a { - color: #e6e8ea; - background-color: transparent; - border-top: 1px solid transparent; - border-bottom: 1px solid transparent; - letter-spacing: 0.01em; - } - .psf-navigation .tier-1 > a:hover, - .psf-navigation .tier-1 > a:focus, - .psf-navigation .tier-1 > a .tier-1:hover > a { - color: #fff; - background-color: #646565; - *zoom: 1; - filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#FF6E6F70',endColorstr='#FF646565'); - background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiM2ZTZmNzAiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iIzY0NjU2NSIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=="); - background-size: 100%; - background-image: -webkit-gradient( - linear, - 50% 0, - 50% 100%, - color-stop(10%, #6e6f70), - color-stop(90%, #646565) - ); - background-image: -moz-linear-gradient(#6e6f70 10%, #646565 90%); - background-image: -webkit-linear-gradient(#6e6f70 10%, #646565 90%); - background-image: linear-gradient(#6e6f70 10%, #646565 90%); - border-top: 1px solid #78797a; - border-bottom: 1px solid #646565; - } - .psf-navigation .subnav { - border-top: 1px solid #39393a; - background-color: #ececec; - *zoom: 1; - filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#FFDADADA',endColorstr='#FFECECEC'); - background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiNkYWRhZGEiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iI2VjZWNlYyIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=="); - background-size: 100%; - background-image: -webkit-gradient( - linear, - 50% 0, - 50% 100%, - color-stop(10%, #dadada), - color-stop(90%, #ececec) - ); - background-image: -moz-linear-gradient(#dadada 10%, #ececec 90%); - background-image: -webkit-linear-gradient(#dadada 10%, #ececec 90%); - background-image: linear-gradient(#dadada 10%, #ececec 90%); - -moz-box-shadow: inset 0 0 20px rgba(120, 121, 122, 0.15); - -webkit-box-shadow: inset 0 0 20px rgba(120, 121, 122, 0.15); - box-shadow: inset 0 0 20px rgba(120, 121, 122, 0.15); - } - .touch .psf-navigation .subnav:before { - border-color: transparent transparent #dadada transparent; - } - .psf-navigation .tier-2 > a { - color: rgba(51, 51, 51, 0.9); - border-top: 1px solid rgba(120, 121, 122, 0.25); - border-bottom: 1px solid transparent; - } - .psf-navigation .tier-2 > a:hover, - .psf-navigation .tier-2 > a:focus { - background: rgba(255, 255, 255, 0.35); - color: rgba(34, 34, 34, 0.9); - } - .psf-navigation .tier-2:last-child > a { - border-bottom: 1px solid rgba(120, 121, 122, 0.25); - } - .psf-navigation .current_item { - color: #fff; - background-color: #525353; - *zoom: 1; - filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#FF5F6060',endColorstr='#FF525353'); - background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiM1ZjYwNjAiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iIzUyNTM1MyIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=="); - background-size: 100%; - background-image: -webkit-gradient( - linear, - 50% 0, - 50% 100%, - color-stop(10%, #5f6060), - color-stop(90%, #525353) - ); - background-image: -moz-linear-gradient(#5f6060 10%, #525353 90%); - background-image: -webkit-linear-gradient(#5f6060 10%, #525353 90%); - background-image: linear-gradient(#5f6060 10%, #525353 90%); - } - .psf-navigation .super-navigation { - color: #666; - border: 1px solid #b8b9b9; - background-color: #ececec; - *zoom: 1; - filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#FFFFFFFF',endColorstr='#FFECECEC'); - background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiNmZmZmZmYiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iI2VjZWNlYyIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=="); - background-size: 100%; - background-image: -webkit-gradient( - linear, - 50% 0, - 50% 100%, - color-stop(10%, #fff), - color-stop(90%, #ececec) - ); - background-image: -moz-linear-gradient(#fff 10%, #ececec 90%); - background-image: -webkit-linear-gradient(#fff 10%, #ececec 90%); - background-image: linear-gradient(#fff 10%, #ececec 90%); - } - .psf-navigation .super-navigation a:not(.button) { - color: #78797a; - } - .psf-navigation .super-navigation h4 { - color: #6b6c6d; - } - .docs-navigation { - background-color: #ffc91a; - *zoom: 1; - filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#FFFFD343',endColorstr='#FFFFC91A'); - background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIzMCUiIHN0b3AtY29sb3I9IiNmZmQzNDMiLz48c3RvcCBvZmZzZXQ9Ijk1JSIgc3RvcC1jb2xvcj0iI2ZmYzkxYSIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=="); - background-size: 100%; - background-image: -webkit-gradient( - linear, - 50% 0, - 50% 100%, - color-stop(30%, #ffd343), - color-stop(95%, #ffc91a) - ); - background-image: -moz-linear-gradient(#ffd343 30%, #ffc91a 95%); - background-image: -webkit-linear-gradient(#ffd343 30%, #ffc91a 95%); - background-image: linear-gradient(#ffd343 30%, #ffc91a 95%); - border-top: 1px solid #ffe590; - border-bottom: 1px solid #c39500; - } - .docs-navigation .tier-1 { - border-top: 1px solid #ffdf76; - border-right: 1px solid #ffc710; - border-bottom: 1px solid #dca900; - border-left: 1px solid #ffdf76; - } - .docs-navigation .tier-1 > a { - color: #333; - background-color: transparent; - border-top: 1px solid transparent; - border-bottom: 1px solid transparent; - letter-spacing: 0.01em; - } - .docs-navigation .tier-1 > a:hover, - .docs-navigation .tier-1 > a:focus, - .docs-navigation .tier-1 > a .tier-1:hover > a { - color: #fff; - background-color: #ffc91a; - *zoom: 1; - filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#FFFFCE2F',endColorstr='#FFFFC91A'); - background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiNmZmNlMmYiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iI2ZmYzkxYSIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=="); - background-size: 100%; - background-image: -webkit-gradient( - linear, - 50% 0, - 50% 100%, - color-stop(10%, #ffce2f), - color-stop(90%, #ffc91a) - ); - background-image: -moz-linear-gradient(#ffce2f 10%, #ffc91a 90%); - background-image: -webkit-linear-gradient(#ffce2f 10%, #ffc91a 90%); - background-image: linear-gradient(#ffce2f 10%, #ffc91a 90%); - border-top: 1px solid #ffd343; - border-bottom: 1px solid #ffc91a; - } - .docs-navigation .subnav { - border-top: 1px solid #c39500; - background-color: white; - *zoom: 1; - filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#FFFFFFFF',endColorstr='#FFFFFFFF'); - background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiNmZmZmZmYiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iI2ZmZmZmZiIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=="); - background-size: 100%; - background-image: -webkit-gradient( - linear, - 50% 0, - 50% 100%, - color-stop(10%, #fff), - color-stop(90%, #fff) - ); - background-image: -moz-linear-gradient(#fff 10%, #fff 90%); - background-image: -webkit-linear-gradient(#fff 10%, #fff 90%); - background-image: linear-gradient(#fff 10%, #fff 90%); - -moz-box-shadow: inset 0 0 20px rgba(255, 211, 67, 0.15); - -webkit-box-shadow: inset 0 0 20px rgba(255, 211, 67, 0.15); - box-shadow: inset 0 0 20px rgba(255, 211, 67, 0.15); - } - .touch .docs-navigation .subnav:before { - border-color: transparent transparent white transparent; - } - .docs-navigation .tier-2 > a { - color: rgba(51, 51, 51, 0.9); - border-top: 1px solid rgba(255, 211, 67, 0.25); - border-bottom: 1px solid transparent; - } - .docs-navigation .tier-2 > a:hover, - .docs-navigation .tier-2 > a:focus { - background: rgba(255, 255, 255, 0.35); - color: rgba(34, 34, 34, 0.9); - } - .docs-navigation .tier-2:last-child > a { - border-bottom: 1px solid rgba(255, 211, 67, 0.25); - } - .docs-navigation .current_item { - color: #fff; - background-color: #f6bc00; - *zoom: 1; - filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#FFFFC710',endColorstr='#FFF6BC00'); - background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiNmZmM3MTAiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iI2Y2YmMwMCIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=="); - background-size: 100%; - background-image: -webkit-gradient( - linear, - 50% 0, - 50% 100%, - color-stop(10%, #ffc710), - color-stop(90%, #f6bc00) - ); - background-image: -moz-linear-gradient(#ffc710 10%, #f6bc00 90%); - background-image: -webkit-linear-gradient(#ffc710 10%, #f6bc00 90%); - background-image: linear-gradient(#ffc710 10%, #f6bc00 90%); - } - .docs-navigation .super-navigation { - color: #666; - border: 1px solid #fff1c3; - background-color: white; - *zoom: 1; - filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#FFFFFFFF',endColorstr='#FFFFFFFF'); - background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiNmZmZmZmYiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iI2ZmZmZmZiIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=="); - background-size: 100%; - background-image: -webkit-gradient( - linear, - 50% 0, - 50% 100%, - color-stop(10%, #fff), - color-stop(90%, #fff) - ); - background-image: -moz-linear-gradient(#fff 10%, #fff 90%); - background-image: -webkit-linear-gradient(#fff 10%, #fff 90%); - background-image: linear-gradient(#fff 10%, #fff 90%); - } - .docs-navigation .super-navigation a:not(.button) { - color: #ffd343; - } - .docs-navigation .super-navigation h4 { - color: #ffcd2a; - } - .pypl-navigation { - background-color: #6c9238; - *zoom: 1; - filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#FF82B043',endColorstr='#FF6C9238'); - background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIzMCUiIHN0b3AtY29sb3I9IiM4MmIwNDMiLz48c3RvcCBvZmZzZXQ9Ijk1JSIgc3RvcC1jb2xvcj0iIzZjOTIzOCIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=="); - background-size: 100%; - background-image: -webkit-gradient( - linear, - 50% 0, - 50% 100%, - color-stop(30%, #82b043), - color-stop(95%, #6c9238) - ); - background-image: -moz-linear-gradient(#82b043 30%, #6c9238 95%); - background-image: -webkit-linear-gradient(#82b043 30%, #6c9238 95%); - background-image: linear-gradient(#82b043 30%, #6c9238 95%); - border-top: 1px solid #a6ca75; - border-bottom: 1px solid #3e5420; - } - .pypl-navigation .tier-1 { - border-top: 1px solid #9bc363; - border-right: 1px solid #678b35; - border-bottom: 1px solid #4b6627; - border-left: 1px solid #9bc363; - } - .pypl-navigation .tier-1 > a { - color: #e6e8ea; - background-color: transparent; - border-top: 1px solid transparent; - border-bottom: 1px solid transparent; - letter-spacing: 0.01em; - } - .pypl-navigation .tier-1 > a:hover, - .pypl-navigation .tier-1 > a:focus, - .pypl-navigation .tier-1 > a .tier-1:hover > a { - color: #fff; - background-color: #6c9238; - *zoom: 1; - filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#FF77A13D',endColorstr='#FF6C9238'); - background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiM3N2ExM2QiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iIzZjOTIzOCIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=="); - background-size: 100%; - background-image: -webkit-gradient( - linear, - 50% 0, - 50% 100%, - color-stop(10%, #77a13d), - color-stop(90%, #6c9238) - ); - background-image: -moz-linear-gradient(#77a13d 10%, #6c9238 90%); - background-image: -webkit-linear-gradient(#77a13d 10%, #6c9238 90%); - background-image: linear-gradient(#77a13d 10%, #6c9238 90%); - border-top: 1px solid #82b043; - border-bottom: 1px solid #6c9238; - } - .pypl-navigation .subnav { - border-top: 1px solid #3e5420; - background-color: #eef5e4; - *zoom: 1; - filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#FFDDEBCA',endColorstr='#FFEEF5E4'); - background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiNkZGViY2EiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iI2VlZjVlNCIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=="); - background-size: 100%; - background-image: -webkit-gradient( - linear, - 50% 0, - 50% 100%, - color-stop(10%, #ddebca), - color-stop(90%, #eef5e4) - ); - background-image: -moz-linear-gradient(#ddebca 10%, #eef5e4 90%); - background-image: -webkit-linear-gradient(#ddebca 10%, #eef5e4 90%); - background-image: linear-gradient(#ddebca 10%, #eef5e4 90%); - -moz-box-shadow: inset 0 0 20px rgba(130, 176, 67, 0.15); - -webkit-box-shadow: inset 0 0 20px rgba(130, 176, 67, 0.15); - box-shadow: inset 0 0 20px rgba(130, 176, 67, 0.15); - } - .touch .pypl-navigation .subnav:before { - border-color: transparent transparent #ddebca transparent; - } - .pypl-navigation .tier-2 > a { - color: rgba(51, 51, 51, 0.9); - border-top: 1px solid rgba(130, 176, 67, 0.25); - border-bottom: 1px solid transparent; - } - .pypl-navigation .tier-2 > a:hover, - .pypl-navigation .tier-2 > a:focus { - background: rgba(255, 255, 255, 0.35); - color: rgba(34, 34, 34, 0.9); - } - .pypl-navigation .tier-2:last-child > a { - border-bottom: 1px solid rgba(130, 176, 67, 0.25); - } - .pypl-navigation .current_item { - color: #fff; - background-color: #59792e; - *zoom: 1; - filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#FF678B35',endColorstr='#FF59792E'); - background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiM2NzhiMzUiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iIzU5NzkyZSIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=="); - background-size: 100%; - background-image: -webkit-gradient( - linear, - 50% 0, - 50% 100%, - color-stop(10%, #678b35), - color-stop(90%, #59792e) - ); - background-image: -moz-linear-gradient(#678b35 10%, #59792e 90%); - background-image: -webkit-linear-gradient(#678b35 10%, #59792e 90%); - background-image: linear-gradient(#678b35 10%, #59792e 90%); - } - .pypl-navigation .super-navigation { - color: #666; - border: 1px solid #bed99a; - background-color: #eef5e4; - *zoom: 1; - filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#FFFFFFFF',endColorstr='#FFEEF5E4'); - background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiNmZmZmZmYiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iI2VlZjVlNCIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=="); - background-size: 100%; - background-image: -webkit-gradient( - linear, - 50% 0, - 50% 100%, - color-stop(10%, #fff), - color-stop(90%, #eef5e4) - ); - background-image: -moz-linear-gradient(#fff 10%, #eef5e4 90%); - background-image: -webkit-linear-gradient(#fff 10%, #eef5e4 90%); - background-image: linear-gradient(#fff 10%, #eef5e4 90%); - } - .pypl-navigation .super-navigation a:not(.button) { - color: #82b043; - } - .pypl-navigation .super-navigation h4 { - color: #749e3c; - } - .jobs-navigation { - background-color: #8b5792; - *zoom: 1; - filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#FFA06BA7',endColorstr='#FF8B5792'); - background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIzMCUiIHN0b3AtY29sb3I9IiNhMDZiYTciLz48c3RvcCBvZmZzZXQ9Ijk1JSIgc3RvcC1jb2xvcj0iIzhiNTc5MiIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=="); - background-size: 100%; - background-image: -webkit-gradient( - linear, - 50% 0, - 50% 100%, - color-stop(30%, #a06ba7), - color-stop(95%, #8b5792) - ); - background-image: -moz-linear-gradient(#a06ba7 30%, #8b5792 95%); - background-image: -webkit-linear-gradient(#a06ba7 30%, #8b5792 95%); - background-image: linear-gradient(#a06ba7 30%, #8b5792 95%); - border-top: 1px solid #bf9bc4; - border-bottom: 1px solid #58375c; - } - .jobs-navigation .tier-1 { - border-top: 1px solid #b58bba; - border-right: 1px solid #85538c; - border-bottom: 1px solid #67406c; - border-left: 1px solid #b58bba; - } - .jobs-navigation .tier-1 > a { - color: #e6e8ea; - background-color: transparent; - border-top: 1px solid transparent; - border-bottom: 1px solid transparent; - letter-spacing: 0.01em; - } - .jobs-navigation .tier-1 > a:hover, - .jobs-navigation .tier-1 > a:focus, - .jobs-navigation .tier-1 > a .tier-1:hover > a { - color: #fff; - background-color: #8b5792; - *zoom: 1; - filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#FF985F9F',endColorstr='#FF8B5792'); - background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiM5ODVmOWYiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iIzhiNTc5MiIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=="); - background-size: 100%; - background-image: -webkit-gradient( - linear, - 50% 0, - 50% 100%, - color-stop(10%, #985f9f), - color-stop(90%, #8b5792) - ); - background-image: -moz-linear-gradient(#985f9f 10%, #8b5792 90%); - background-image: -webkit-linear-gradient(#985f9f 10%, #8b5792 90%); - background-image: linear-gradient(#985f9f 10%, #8b5792 90%); - border-top: 1px solid #a06ba7; - border-bottom: 1px solid #8b5792; - } - .jobs-navigation .subnav { - border-top: 1px solid #58375c; - background-color: #fcfbfd; - *zoom: 1; - filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#FFEEE5EF',endColorstr='#FFFCFBFD'); - background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiNlZWU1ZWYiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iI2ZjZmJmZCIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=="); - background-size: 100%; - background-image: -webkit-gradient( - linear, - 50% 0, - 50% 100%, - color-stop(10%, #eee5ef), - color-stop(90%, #fcfbfd) - ); - background-image: -moz-linear-gradient(#eee5ef 10%, #fcfbfd 90%); - background-image: -webkit-linear-gradient(#eee5ef 10%, #fcfbfd 90%); - background-image: linear-gradient(#eee5ef 10%, #fcfbfd 90%); - -moz-box-shadow: inset 0 0 20px rgba(160, 107, 167, 0.15); - -webkit-box-shadow: inset 0 0 20px rgba(160, 107, 167, 0.15); - box-shadow: inset 0 0 20px rgba(160, 107, 167, 0.15); - } - .touch .jobs-navigation .subnav:before { - border-color: transparent transparent #eee5ef transparent; - } - .jobs-navigation .tier-2 > a { - color: rgba(51, 51, 51, 0.9); - border-top: 1px solid rgba(160, 107, 167, 0.25); - border-bottom: 1px solid transparent; - } - .jobs-navigation .tier-2 > a:hover, - .jobs-navigation .tier-2 > a:focus { - background: rgba(255, 255, 255, 0.35); - color: rgba(34, 34, 34, 0.9); - } - .jobs-navigation .tier-2:last-child > a { - border-bottom: 1px solid rgba(160, 107, 167, 0.25); - } - .jobs-navigation .current_item { - color: #fff; - background-color: #764a7c; - *zoom: 1; - filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#FF85538C',endColorstr='#FF764A7C'); - background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiM4NTUzOGMiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iIzc2NGE3YyIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=="); - background-size: 100%; - background-image: -webkit-gradient( - linear, - 50% 0, - 50% 100%, - color-stop(10%, #85538c), - color-stop(90%, #764a7c) - ); - background-image: -moz-linear-gradient(#85538c 10%, #764a7c 90%); - background-image: -webkit-linear-gradient(#85538c 10%, #764a7c 90%); - background-image: linear-gradient(#85538c 10%, #764a7c 90%); - } - .jobs-navigation .super-navigation { - color: #666; - border: 1px solid #d3bbd7; - background-color: #fcfbfd; - *zoom: 1; - filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#FFFFFFFF',endColorstr='#FFFCFBFD'); - background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiNmZmZmZmYiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iI2ZjZmJmZCIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=="); - background-size: 100%; - background-image: -webkit-gradient( - linear, - 50% 0, - 50% 100%, - color-stop(10%, #fff), - color-stop(90%, #fcfbfd) - ); - background-image: -moz-linear-gradient(#fff 10%, #fcfbfd 90%); - background-image: -webkit-linear-gradient(#fff 10%, #fcfbfd 90%); - background-image: linear-gradient(#fff 10%, #fcfbfd 90%); - } - .jobs-navigation .super-navigation a:not(.button) { - color: #a06ba7; - } - .jobs-navigation .super-navigation h4 { - color: #945d9c; - } - .shop-navigation { - background-color: #9e4650; - *zoom: 1; - filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#FFB55863',endColorstr='#FF9E4650'); - background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIzMCUiIHN0b3AtY29sb3I9IiNiNTU4NjMiLz48c3RvcCBvZmZzZXQ9Ijk1JSIgc3RvcC1jb2xvcj0iIzllNDY1MCIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=="); - background-size: 100%; - background-image: -webkit-gradient( - linear, - 50% 0, - 50% 100%, - color-stop(30%, #b55863), - color-stop(95%, #9e4650) - ); - background-image: -moz-linear-gradient(#b55863 30%, #9e4650 95%); - background-image: -webkit-linear-gradient(#b55863 30%, #9e4650 95%); - background-image: linear-gradient(#b55863 30%, #9e4650 95%); - border-top: 1px solid #cc8d95; - border-bottom: 1px solid #622b32; - } - .shop-navigation .tier-1 { - border-top: 1px solid #c57b84; - border-right: 1px solid #97434d; - border-bottom: 1px solid #74333b; - border-left: 1px solid #c57b84; - } - .shop-navigation .tier-1 > a { - color: #e6e8ea; - background-color: transparent; - border-top: 1px solid transparent; - border-bottom: 1px solid transparent; - letter-spacing: 0.01em; - } - .shop-navigation .tier-1 > a:hover, - .shop-navigation .tier-1 > a:focus, - .shop-navigation .tier-1 > a .tier-1:hover > a { - color: #fff; - background-color: #9e4650; - *zoom: 1; - filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#FFAC4C58',endColorstr='#FF9E4650'); - background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiNhYzRjNTgiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iIzllNDY1MCIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=="); - background-size: 100%; - background-image: -webkit-gradient( - linear, - 50% 0, - 50% 100%, - color-stop(10%, #ac4c58), - color-stop(90%, #9e4650) - ); - background-image: -moz-linear-gradient(#ac4c58 10%, #9e4650 90%); - background-image: -webkit-linear-gradient(#ac4c58 10%, #9e4650 90%); - background-image: linear-gradient(#ac4c58 10%, #9e4650 90%); - border-top: 1px solid #b55863; - border-bottom: 1px solid #9e4650; - } - .shop-navigation .subnav { - border-top: 1px solid #622b32; - background-color: #fbf7f8; - *zoom: 1; - filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#FFF1DEE0',endColorstr='#FFFBF7F8'); - background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiNmMWRlZTAiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iI2ZiZjdmOCIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=="); - background-size: 100%; - background-image: -webkit-gradient( - linear, - 50% 0, - 50% 100%, - color-stop(10%, #f1dee0), - color-stop(90%, #fbf7f8) - ); - background-image: -moz-linear-gradient(#f1dee0 10%, #fbf7f8 90%); - background-image: -webkit-linear-gradient(#f1dee0 10%, #fbf7f8 90%); - background-image: linear-gradient(#f1dee0 10%, #fbf7f8 90%); - -moz-box-shadow: inset 0 0 20px rgba(181, 88, 99, 0.15); - -webkit-box-shadow: inset 0 0 20px rgba(181, 88, 99, 0.15); - box-shadow: inset 0 0 20px rgba(181, 88, 99, 0.15); - } - .touch .shop-navigation .subnav:before { - border-color: transparent transparent #f1dee0 transparent; - } - .shop-navigation .tier-2 > a { - color: rgba(51, 51, 51, 0.9); - border-top: 1px solid rgba(181, 88, 99, 0.25); - border-bottom: 1px solid transparent; - } - .shop-navigation .tier-2 > a:hover, - .shop-navigation .tier-2 > a:focus { - background: rgba(255, 255, 255, 0.35); - color: rgba(34, 34, 34, 0.9); - } - .shop-navigation .tier-2:last-child > a { - border-bottom: 1px solid rgba(181, 88, 99, 0.25); - } - .shop-navigation .current_item { - color: #fff; - background-color: #853b44; - *zoom: 1; - filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#FF97434D',endColorstr='#FF853B44'); - background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiM5NzQzNGQiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iIzg1M2I0NCIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=="); - background-size: 100%; - background-image: -webkit-gradient( - linear, - 50% 0, - 50% 100%, - color-stop(10%, #97434d), - color-stop(90%, #853b44) - ); - background-image: -moz-linear-gradient(#97434d 10%, #853b44 90%); - background-image: -webkit-linear-gradient(#97434d 10%, #853b44 90%); - background-image: linear-gradient(#97434d 10%, #853b44 90%); - } - .shop-navigation .super-navigation { - color: #666; - border: 1px solid #dcb0b6; - background-color: #fbf7f8; - *zoom: 1; - filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#FFFFFFFF',endColorstr='#FFFBF7F8'); - background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiNmZmZmZmYiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iI2ZiZjdmOCIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=="); - background-size: 100%; - background-image: -webkit-gradient( - linear, - 50% 0, - 50% 100%, - color-stop(10%, #fff), - color-stop(90%, #fbf7f8) - ); - background-image: -moz-linear-gradient(#fff 10%, #fbf7f8 90%); - background-image: -webkit-linear-gradient(#fff 10%, #fbf7f8 90%); - background-image: linear-gradient(#fff 10%, #fbf7f8 90%); - } - .shop-navigation .super-navigation a:not(.button) { - color: #b55863; - } - .shop-navigation .super-navigation h4 { - color: #a94b56; - } - .default-page .content-wrapper { - padding-top: 2em; - } - .main-content.with-left-sidebar { - width: 65.95745%; - float: right; - margin-right: 0; - #margin-left: -20px; - } - .main-content.with-right-sidebar { - width: 65.95745%; - float: left; - margin-right: 2.12766%; - } - .text { - font-size: 0.9375em; - } - .left-sidebar { - width: 31.91489%; - float: left; - margin-right: 2.12766%; - margin-top: 1em; - } - .right-sidebar { - width: 31.91489%; - float: right; - margin-right: 0; - #margin-left: -20px; - } - .left-sidebar .small-widget, - .left-sidebar .medium-widget, - .left-sidebar .triple-widget, - .right-sidebar .small-widget, - .right-sidebar .medium-widget, - .right-sidebar .triple-widget { - float: none; - width: auto; - margin-right: auto; - #margin-left: auto; - } - .row { - margin-bottom: 1em; - } - .small-widget { - width: 48.93617%; - float: left; - margin-right: 2.12766%; - } - .small-widget:nth-child(2), - .small-widget.last { - margin-right: 0; - } - .triple-widget { - width: 31.91489%; - float: left; - margin-right: 2.12766%; - } - .triple-widget.last { - margin-right: 0; - } - .most-recent-posts { - width: 74.46809%; - float: left; - margin-right: 2.12766%; - } - .pep-widget, - .psf-widget, - .python-needs-you-widget { - padding: 1.5em 1.75em; - clear: both; - } - .pep-list-header, - .pep-index-list li, - .info-key { - margin: 0 -0.5em; - } - .pep-list-header { - display: block; - } - .pep-index-list .label { - display: none; - } - .pep-index-list a { - display: block; - } - .pep-index-list li { - border-bottom: 1px solid #e3e7ec; - margin-bottom: 0; - } - .pep-type, - .pep-num, - .pep-title, - .pep-owner { - float: left; - border-bottom: 0; - } - .pep-type { - width: 15%; - } - .pep-num { - width: 10%; - } - .pep-title { - width: 50%; - } - .pep-owner { - width: 25%; - } - .jobs-intro { - padding-top: 2em; - padding-bottom: 2em; - } - .listing-company-category:before { - content: "Category: "; - color: #666; - } - .listing-job-title:before { - content: "Title: "; - color: #666; - } - .listing-job-type:before { - content: "Looking for: "; - color: #666; - } - .release-number, - .release-date, - .release-download, - .release-enhancements { - -moz-box-orient: vertical; - display: inline-block; - margin-right: -4px; - vertical-align: middle; - } - .release-number { - width: 20%; - } - .release-date { - width: 30%; - } - .release-download { - width: 25%; - } - .release-enhancements { - width: 25%; - } - .release-version, - .release-status, - .release-start, - .release-end, - .release-pep { - -moz-box-orient: vertical; - display: inline-block; - margin-right: -4px; - vertical-align: middle; - } - .release-version { - width: 15%; - } - .release-status { - width: 20%; - } - .release-start { - width: 25%; - } - .release-end { - width: 25%; - } - .release-pep { - width: 15%; - } - .previous-next { - overflow: hidden; - *zoom: 1; - } - .previous-next a { - -moz-box-sizing: border-box; - -webkit-box-sizing: border-box; - box-sizing: border-box; - } - .previous-next .prev-button { - width: 48.93617%; - float: left; - margin-right: 2.12766%; - } - .previous-next .next-button { - width: 48.93617%; - float: right; - margin-right: 0; - #margin-left: -20px; - } - .main-footer .jump-link { - display: none; - } - .sitemap .tier-1 { - float: left; - width: 50%; - } - .sitemap .tier-1:nth-child(odd) { - clear: left; - } - .sitemap .tier-1:nth-child(even) { - border-left: 1px solid #f7f7f8; - } - .sitemap .tier-1.element-7 { - clear: none; - } - .footer-links { - clear: both; - text-align: center; - } - .footer-links li { - display: inline-block; - } -} -@media (min-width: 50em) { - body:after { - content: "drawer_navigation"; - display: none; - speak: none; - } - .site-headline { - margin: 0.25em 0 0.5em; - } - .site-headline a .python-logo { - width: 255.2px; - height: 72.16px; - } - .site-headline a .psf-logo { - width: 293.92px; - height: 72.16px; - } - .donate-button { - top: 33px; - } - .options-bar { - margin: 0.875em 0; - } - .search-field { - background: #fff; - padding: 0.4em 0.5em 0.3em; - margin-right: 0.5em; - width: 11em; - } - .search-field:focus { - width: 13em; - } - .home .header-banner { - margin: 0 2em 0 1em; - } - .slideshow .slides li { - overflow: hidden; - *zoom: 1; - } - .slide-code, - .slide-copy { - float: left; - width: 50%; - min-height: 280px; - } - .slide-code { - position: relative; - line-height: 1.5; - } - .js .launch-shell { - display: block; - } - .flexslide .launch-shell { - display: block; - position: absolute; - top: 1.25em; - right: 52%; - z-index: 50; - } - .flexslide .launch-shell span, - .flexslide .launch-shell a { - display: inline-block; - } - .flexslide .launch-shell .button { - padding-bottom: 0.2em; - } - .flexslide .launch-shell .button .message { - opacity: 0; - position: absolute; - top: -9999px; - right: 2.6em; - white-space: nowrap; - padding: 0.4em 0.75em 0.35em; - color: #999; - background-color: #1f1f1f; - *zoom: 1; - filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#FF333333',endColorstr='#FF1F1F1F'); - background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiMzMzMzMzMiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iIzFmMWYxZiIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=="); - background-size: 100%; - background-image: -webkit-gradient( - linear, - 50% 0, - 50% 100%, - color-stop(10%, #333), - color-stop(90%, #1f1f1f) - ); - background-image: -moz-linear-gradient(#333 10%, #1f1f1f 90%); - background-image: -webkit-linear-gradient(#333 10%, #1f1f1f 90%); - background-image: linear-gradient(#333 10%, #1f1f1f 90%); - border-top: 1px solid #444; - border-right: 1px solid #444; - border-bottom: 1px solid #444; - border-left: 1px solid #444; - -moz-border-radius: 6px; - -webkit-border-radius: 6px; - border-radius: 6px; - -moz-box-shadow: 1px 1px 1px rgba(0, 0, 0, 0.05); - -webkit-box-shadow: 1px 1px 1px rgba(0, 0, 0, 0.05); - box-shadow: 1px 1px 1px rgba(0, 0, 0, 0.05); - -moz-transition: opacity 0.25s ease-in-out, top 0s linear 0.25s; - -o-transition: opacity 0.25s ease-in-out, top 0s linear 0.25s; - -webkit-transition: opacity 0.25s ease-in-out, top 0s linear; - -webkit-transition-delay: 0s, 0.25s; - transition: opacity 0.25s ease-in-out, top 0s linear 0.25s; - } - .flexslide .launch-shell .button:hover .message { - opacity: 1; - top: 0; - -moz-transition: opacity 0.25s ease-in-out, top 0s linear; - -o-transition: opacity 0.25s ease-in-out, top 0s linear; - -webkit-transition: opacity 0.25s ease-in-out, top 0s linear; - transition: opacity 0.25s ease-in-out, top 0s linear; - } - .introduction { - text-align: center; - } - .introduction .breaker { - display: block; - width: 100%; - height: 1px; - font-size: 1px; - line-height: 1px; - } - .main-header .container { - padding-bottom: 0; - } - .header-banner { - padding: 0 0 0 1em; - margin: 0 -1em 0 0; - } - .about-banner, - .download-for-current-os, - .documentation-banner, - .community-banner { - padding-left: 0; - padding-right: 51.06383%; - padding-top: 1em; - } - .about-banner { - background: 120% 0 no-repeat url(../img/landing-about.png?1576869008) - transparent; - min-height: 345px; - padding-bottom: 3.5em; - margin-bottom: -2.5em; - } - .download-for-current-os { - background: 130% 0 no-repeat url(../img/landing-downloads.png?1576869008) - transparent; - min-height: 345px; - padding-bottom: 4em; - margin-bottom: -3em; - } - .documentation-banner { - background: 130% 0 no-repeat url(../img/landing-docs.png?1576869008) - transparent; - padding-bottom: 1em; - } - .community-banner { - text-align: left; - background: 110% 0 no-repeat url(../img/landing-community.png?1576869008) - transparent; - min-height: 345px; - padding-bottom: 2em; - margin-bottom: -1.25em; - } - .welcome-to-the-foundation { - padding-top: 2em; - padding-bottom: 2em; - } - .welcome-message { - text-align: left; - position: absolute; - left: 0; - width: 23.40426%; - margin-top: 0.56875em; - } - .latest-blog-post, - .featured-event, - .jobs-intro { - position: relative; - text-align: left; - min-height: 130px; - } - .latest-blog-post .call-to-action, - .featured-event .call-to-action, - .jobs-intro .call-to-action { - margin-left: 34.04255%; - } - .latest-blog-post .date-posted, - .latest-blog-post .event-date, - .featured-event .date-posted, - .featured-event .event-date, - .jobs-intro .date-posted, - .jobs-intro .event-date { - position: absolute; - left: 0; - width: 31.91489%; - } - .latest-blog-post .date-posted time, - .featured-event .date-posted time, - .jobs-intro .date-posted time { - position: relative; - top: 30px; - } - .latest-blog-post .excerpt, - .featured-event .excerpt, - .jobs-intro .excerpt { - margin-left: 34.04255%; - } - .home .content-wrapper .container { - padding-top: 2.5em; - } - .main-content.with-left-sidebar { - width: 74.46809%; - float: right; - margin-right: 0; - #margin-left: -20px; - } - .main-content.with-right-sidebar { - width: 74.46809%; - float: left; - margin-right: 2.12766%; - } - .left-sidebar { - width: 23.40426%; - float: left; - margin-right: 2.12766%; - } - .right-sidebar { - width: 23.40426%; - float: right; - margin-right: 0; - #margin-left: -20px; - } - .featured-success-story .success-quote:before, - .featured-success-story .success-quote:after { - font-size: 2.375em; - } - .quote-by, - .quote-by-organization { - display: -moz-inline-stack; - display: inline-block; - vertical-align: baseline; - } - .lt-ie8 .quote-by, - .lt-ie8 .quote-by-organization { - vertical-align: auto; - zoom: 1; - display: inline; - } - .quote-by-organization:before { - content: ", "; - margin-left: -0.25em; - } - .activity-feed { - position: absolute; - right: 0; - } - .psf-widget, - .python-needs-you-widget { - min-height: 14em; - position: relative; - } - .psf-widget .python-logo, - .python-needs-you-widget .python-logo { - position: absolute; - top: 0.5em; - right: 1em; - width: 210px; - height: 210px; - background: top left no-repeat url(../img/python-logo-large.png?1576869008) - transparent; - } - .psf-widget .widget-title, - .psf-widget p, - .python-needs-you-widget .widget-title, - .python-needs-you-widget p { - margin-right: 34.04255%; - } - .triple-widget { - width: 31.91489%; - float: left; - margin-right: 2.12766%; - } - .triple-widget.last { - margin-right: 0; - } - .list-recent-events .event-title, - .list-recent-events p, - .list-recent-posts .event-title, - .list-recent-posts p { - margin-left: 25.53191%; - } - .list-recent-events time, - .list-recent-posts time { - position: absolute; - top: 0.3em; - left: 0; - width: 23.40426%; - } - .list-recent-jobs .listing-company-category a, - .list-recent-jobs .listing-job-type a { - white-space: nowrap; - } - .list-recent-jobs .listing-posted { - width: 48.93617%; - float: left; - margin-right: 2.12766%; - margin-right: 0; - } - .list-recent-jobs .listing-company-category { - width: 48.93617%; - float: right; - margin-right: 0; - #margin-left: -20px; - text-align: right; - clear: none; - } - .list-recent-jobs .listing-actions { - clear: both; - overflow: hidden; - *zoom: 1; - padding-top: 0.9375em; - text-align: right; - } - .listing-company .listing-company-name { - width: 57.44681%; - float: left; - margin-right: 2.12766%; - } - .listing-company .listing-company-name a:hover:after, - .listing-company .listing-company-name a:focus:after { - color: #666; - content: " View Details"; - font-size: 0.75em; - } - .listing-company .listing-location { - width: 40.42553%; - float: right; - margin-right: 0; - #margin-left: -20px; - text-align: right; - } - .job-meta { - width: 48.93617%; - float: left; - margin-right: 2.12766%; - margin-bottom: 0; - } - .job-tags { - width: 48.93617%; - float: right; - margin-right: 0; - #margin-left: -20px; - } - .wide-form ul { - margin-left: 24%; - } - .wide-form p { - overflow: hidden; - *zoom: 1; - } - .wide-form p label, - .wide-form p textarea { - display: inline-block; - vertical-align: top; - } - .wide-form p label { - width: 24%; - } - .wide-form p input[type="text"], - .wide-form p input[type="password"], - .wide-form p input[type="search"], - .wide-form p input[type="email"], - .wide-form p input[type="url"], - .wide-form p input[type="tel"] { - width: 75%; - display: inline-block; - vertical-align: top; - } - .wide-form p textarea { - width: 75%; - } - .wide-form p button { - margin-left: 24%; - } - .wide-form p button + button { - margin-left: 0; - } - .jobs-form ul { - margin-top: -3.25em; - *zoom: 1; - } - .jobs-form ul:after { - content: ""; - display: table; - clear: both; - } - .jobs-form ul li { - float: left; - width: 33%; - } - .jobs-form ul.errorlist { - margin-top: 0; - } - .sitemap, - .footer-links, - .copyright { - font-size: 0.875em; - } - .sitemap .tier-1 { - width: 32.97872%; - border-left: 0; - border-right: 0; - } - .sitemap .tier-1:nth-child(odd), - .sitemap .tier-1:nth-child(even) { - clear: none; - border-left: 0; - border-right: 0; - } - .sitemap .tier-1.element-1, - .sitemap .tier-1.element-2, - .sitemap .tier-1.element-4, - .sitemap .tier-1.element-5, - .sitemap .tier-1.element-8 { - border-right: 1px solid #d5d6d8; - } - .sitemap .tier-1.element-2, - .sitemap .tier-1.element-3, - .sitemap .tier-1.element-5, - .sitemap .tier-1.element-6, - .sitemap .tier-1.element-7, - .sitemap .tier-1.element-8, - .sitemap .tier-1.element-9 { - border-left: 1px solid #f7f7f8; - } - .footer-links .say-no-more { - display: inline; - visibility: visible; - } - .flex-slideshow.default-slideshow .caption-wrapper { - position: absolute; - top: 1em; - left: 1em; - bottom: 2em; - width: 33%; - padding: 0.75em; - overflow: hidden; - background: #e6e8ea; - background: rgba(255, 255, 255, 0.75); - } - .flex-control-nav { - padding-bottom: 1.5em; - } -} -@media (min-width: 58.75em) { - body:after { - content: "drawer_navigation load_supernavs"; - display: none; - speak: none; - } - .main-navigation { - text-align: center; - overflow: visible; - } - .main-navigation .menu { - margin-bottom: 0; - } - .main-navigation .tier-1 > a, - .main-navigation .tier-2 > a { - display: block; - padding: 0.5em 1.5em 0.4em 1em; - position: relative; - } - .main-navigation .tier-1 { - display: block; - width: 100%; - } - .main-navigation .tier-1 > a { - text-align: center; - } - .main-navigation .tier-2 > a { - text-align: left; - } - .main-navigation .menu { - *zoom: 1; - } - .main-navigation .menu:after { - content: ""; - display: table; - clear: both; - } - .main-navigation .tier-1 { - position: relative; - } - .main-navigation .subnav { - position: absolute; - z-index: 100; - text-align: left; - } - .no-touch .main-navigation .subnav { - min-width: 100%; - display: none; - -moz-transition: all 0s ease; - -o-transition: all 0s ease; - -webkit-transition: all 0s ease; - transition: all 0s ease; - } - .touch .main-navigation .subnav { - top: 120%; - display: none; - opacity: 0; - -moz-transition: opacity 0.25s ease-in-out; - -o-transition: opacity 0.25s ease-in-out; - -webkit-transition: opacity 0.25s ease-in-out; - transition: opacity 0.25s ease-in-out; - -moz-box-shadow: 0 0.25em 0.75em rgba(0, 0, 0, 0.6); - -webkit-box-shadow: 0 0.25em 0.75em rgba(0, 0, 0, 0.6); - box-shadow: 0 0.25em 0.75em rgba(0, 0, 0, 0.6); - } - .touch .main-navigation .subnav:before { - position: absolute; - content: ""; - width: 0; - height: 0; - border-color: transparent; - border-style: solid; - border-width: 0.75em; - top: -1.45em; - display: block; - } - .no-touch .main-navigation .element-1:hover .subnav, - .no-touch .main-navigation .element-1:focus .subnav, - .no-touch .main-navigation .element-2:hover .subnav, - .no-touch .main-navigation .element-2:focus .subnav, - .no-touch .main-navigation .element-3:hover .subnav, - .no-touch .main-navigation .element-3:focus .subnav, - .no-touch .main-navigation .element-4:hover .subnav, - .no-touch .main-navigation .element-4:focus .subnav { - left: 0; - display: initial; - -moz-transition-delay: 0.25s; - -o-transition-delay: 0.25s; - -webkit-transition-delay: 0.25s; - transition-delay: 0.25s; - } - .no-touch .main-navigation .element-5:hover .subnav, - .no-touch .main-navigation .element-5:focus .subnav, - .no-touch .main-navigation .element-6:hover .subnav, - .no-touch .main-navigation .element-6:focus .subnav, - .no-touch .main-navigation .element-7:hover .subnav, - .no-touch .main-navigation .element-7:focus .subnav, - .no-touch .main-navigation .element-8:hover .subnav, - .no-touch .main-navigation .element-8:focus .subnav, - .no-touch .main-navigation .last:hover .subnav, - .no-touch .main-navigation .last:focus .subnav { - right: 0; - display: initial; - -moz-transition-delay: 0.25s; - -o-transition-delay: 0.25s; - -webkit-transition-delay: 0.25s; - transition-delay: 0.25s; - } - .touch .main-navigation .element-1:hover .subnav, - .touch .main-navigation .element-1 .subnav.touched, - .touch .main-navigation .element-2:hover .subnav, - .touch .main-navigation .element-2 .subnav.touched, - .touch .main-navigation .element-3:hover .subnav, - .touch .main-navigation .element-3 .subnav.touched, - .touch .main-navigation .element-4:hover .subnav, - .touch .main-navigation .element-4 .subnav.touched { - display: block; - opacity: 1; - left: 0; - } - .touch .main-navigation .element-1 .subnav:before, - .touch .main-navigation .element-2 .subnav:before, - .touch .main-navigation .element-3 .subnav:before, - .touch .main-navigation .element-4 .subnav:before { - left: 1.5em; - } - .touch .main-navigation .element-5:hover .subnav, - .touch .main-navigation .element-5 .subnav.touched, - .touch .main-navigation .element-6:hover .subnav, - .touch .main-navigation .element-6 .subnav.touched, - .touch .main-navigation .element-7:hover .subnav, - .touch .main-navigation .element-7 .subnav.touched, - .touch .main-navigation .element-8:hover .subnav, - .touch .main-navigation .element-8 .subnav.touched, - .touch .main-navigation .last:hover .subnav, - .touch .main-navigation .last .subnav.touched { - display: block; - opacity: 1; - right: 0; - } - .touch .main-navigation .element-5 .subnav:before, - .touch .main-navigation .element-6 .subnav:before, - .touch .main-navigation .element-7 .subnav:before, - .touch .main-navigation .element-8 .subnav:before, - .touch .main-navigation .last .subnav:before { - left: auto; - right: 1.5em; - } - .main-navigation .tier-2 { - display: block; - min-width: 100%; - } - .main-navigation .tier-2 a { - white-space: nowrap; - } - .no-touch .main-navigation { - display: block; - text-align: center; - font-size: 1.125em; - -moz-border-radius: 8px; - -webkit-border-radius: 8px; - border-radius: 8px; - -moz-box-shadow: 0 0 10px rgba(0, 0, 0, 0.2); - -webkit-box-shadow: 0 0 10px rgba(0, 0, 0, 0.2); - box-shadow: 0 0 10px rgba(0, 0, 0, 0.2); - } - .no-touch .main-navigation .menu { - text-align: center; - } - .no-touch .main-navigation .tier-1 { - float: none; - border-top: 0; - border-bottom: 0; - width: auto; - margin: 0 -5px 0 0; - display: -moz-inline-stack; - display: inline-block; - vertical-align: baseline; - border-right: 1px solid rgba(0, 0, 0, 0.2); - border-left: 1px solid rgba(255, 255, 255, 0.1); - } - .lt-ie8 .no-touch .main-navigation .tier-1 { - vertical-align: auto; - zoom: 1; - display: inline; - } - .no-touch .main-navigation .tier-1.element-1 { - border-left: 0; - } - .no-touch .main-navigation .tier-1.last { - border-right: 0; - } - .no-touch .main-navigation .tier-1.element-6, - .no-touch .main-navigation .tier-1.element-7 { - width: auto; - } - .no-touch .main-navigation .tier-1 > a { - padding: 0.65em 1.25em 0.55em; - } - .no-touch .main-navigation .tier-2 { - font-size: 0.875em; - } - .no-touch .default-page .main-navigation { - position: relative; - margin-bottom: -1.375em; - } - .four-col > .column { - width: 25%; - } - .four-col > .double-col { - width: 50%; - } - .four-col > div:nth-of-type(2n + 3) { - clear: none; - } - .four-col > div:nth-of-type(4n + 5) { - clear: left; - } - .site-headline a .python-logo { - width: 290px; - height: 82px; - } - .site-headline a .psf-logo { - width: 334px; - height: 82px; - } - .search-field { - width: 14em; - } - .search-field:focus { - width: 18em; - margin-right: 0.5em; - } - .donate-button { - top: 38px; - } - .options-bar { - margin: 1.3125em 0; - } - .with-supernav .subnav { - display: none; - border-right: 1px solid rgba(102, 102, 102, 0.3); - } - .with-supernav .super-navigation { - display: block; - } - .super-navigation { - color: #666; - position: absolute; - top: 0; - width: 28em; - min-height: 100%; - text-align: left; - padding: 1.5em 1.75em; - border-top: 1px solid rgba(255, 255, 255, 0.8); - border-left: 1px solid rgba(255, 255, 255, 0.8); - } - .main-navigation .super-navigation a:not(.button) { - padding: 0; - border: 0; - } - .main-navigation .super-navigation a:not(.button):hover, - .main-navigation .super-navigation a:not(.button):focus { - border: 0; - background: transparent; - } - .main-navigation .super-navigation a:not(.button):hover, - .main-navigation .super-navigation a:not(.button):focus { - color: #1e2933; - } - .super-navigation h2, - .super-navigation h3, - .super-navigation h4, - .super-navigation h5 { - margin-top: 0; - } - #community .super-navigation h4, - #blog .super-navigation h4, - #events .super-navigation h4 { - font-family: Flux, "Source Sans Pro", Arial, sans-serif; - font-weight: 700; - font-size: 1.3125em; - line-height: 1.25em; - margin-bottom: 0; - } - .super-navigation p.date-posted { - color: #666; - font-size: 0.625em !important; - font-style: italic; - } - .super-navigation p.excert { - font-size: 0.625em; - line-height: 1.3em; - } - .super-navigation p.quote-by { - color: #3776ab; - } - .tier-1.element-1 .super-navigation, - .tier-1.element-2 .super-navigation, - .tier-1.element-3 .super-navigation { - left: 100.25%; - } - .tier-1.element-4 .super-navigation, - .tier-1.element-5 .super-navigation, - .tier-1.element-6 .super-navigation, - .tier-1.element-7 .super-navigation { - left: -28em; - } - .super-navigation .menu { - text-align: left; - } - .about-banner, - .download-for-current-os, - .documentation-banner { - padding-left: 0; - padding-right: 42.55319%; - } - .about-banner p:last-child, - .download-for-current-os p:last-child, - .documentation-banner p:last-child { - margin-bottom: 0; - } - .about-banner p, - .documentation-banner p, - .community-banner p { - margin-right: 14.81481%; - } - .about-banner, - .documentation-banner { - background-position: 110% 0; - } - .download-for-current-os { - background-position: 115% 0; - padding-bottom: 6em; - margin-bottom: -3em; - } - .community-banner { - background-position: 100% 0; - } - .featured-success-story .success-quote { - margin-left: 8.51064%; - margin-right: 8.51064%; - } - .main-content.with-left-sidebar { - padding-left: 3.19149%; - padding-right: 3.19149%; - } - .single-event-title { - font-size: 2em; - } - .fontface .single-event-title { - font-size: 2.3em; - } - .fontface .single-event-title span:before { - font-size: 0.875em; - } - .text > p:first-of-type { - color: #666; - font-size: 1.125em; - line-height: 1.6875; - margin-bottom: 1.25em; - } - .small-widget p, - .small-widget li, - .medium-widget p, - .medium-widget li, - .psf-widget p, - .psf-widget li, - .python-needs-you-widget p, - .python-needs-you-widget li, - .documentation-help p, - .documentation-help li { - font-size: 0.9375em; - } - .small-widget { - width: 23.40426%; - float: left; - margin-right: 2.12766%; - } - .small-widget:nth-child(2) { - margin-right: 2.12766%; - } - .medium-widget { - width: 48.93617%; - float: left; - margin-right: 2.12766%; - } - .small-widget.last, - .medium-widget.last { - float: right; - margin-right: 0; - } - .blog-widget li, - .event-widget li, - .most-recent-posts li { - padding-left: 7em; - } - .blog-widget .say-no-more, - .event-widget .say-no-more, - .most-recent-posts .say-no-more { - display: inline; - visibility: visible; - } - .pep-widget, - .psf-widget, - .python-needs-you-widget { - padding: 1.5em 1.75em; - } - .psf-widget .widget-title, - .psf-widget p, - .python-needs-you-widget .widget-title, - .python-needs-you-widget p { - margin-right: 25.53191%; - } - .mapped-events h2 { - margin-top: 0.5em; - } - .tag-wrapper { - display: inline; - } - .welcome-message { - width: 23.40426%; - } - .latest-blog-post .call-to-action, - .featured-event .call-to-action, - .jobs-intro .call-to-action { - margin-left: 25.53191%; - } - .latest-blog-post .date-posted, - .latest-blog-post .event-date, - .featured-event .date-posted, - .featured-event .event-date, - .jobs-intro .date-posted, - .jobs-intro .event-date { - width: 23.40426%; - } - .latest-blog-post .excerpt, - .featured-event .excerpt, - .jobs-intro .excerpt { - margin-left: 25.53191%; - } - .subscription-channels li { - display: -moz-inline-stack; - display: inline-block; - vertical-align: baseline; - width: 30%; - } - .lt-ie8 .subscription-channels li { - vertical-align: auto; - zoom: 1; - display: inline; - } - .pep-widget .widget-title { - position: relative; - padding-right: 6em; - } - .rss-link { - position: absolute; - top: 0; - right: 0; - } - .sitemap a { - text-align: left; - } - .sitemap .tier-1 { - width: 16.6667%; - border: 0; - } - .sitemap .tier-1.element-1, - .sitemap .tier-1.element-2, - .sitemap .tier-1.element-3, - .sitemap .tier-1.element-4, - .sitemap .tier-1.element-5, - .sitemap .tier-1.element-6, - .sitemap .tier-1.element-7, - .sitemap .tier-1.element-8, - .sitemap .tier-1.element-9, - .sitemap .tier-1.element-10 { - border: 0; - } - .sitemap .subnav, - .sitemap .subnav li { - border: 0; - } - .footer-links a { - padding: 0.3em 0.75em; - } - .flex-slideshow.home-slideshow .caption-wrapper { - float: left; - width: 49%; - } - .flex-slideshow.default-slideshow .caption-wrapper { - top: 2em; - left: 2em; - bottom: 3em; - width: 25%; - padding: 1em; - } - .flex-viewport { - padding-bottom: 0.5em; - } - .touch .flex-viewport { - padding-bottom: 1em; - } - .default-slideshow .flex-control-nav { - text-align: right; - } - .home-slideshow .flex-control-nav { - position: absolute; - bottom: 0; - right: 0; - width: 49%; - padding: 0.5em; - text-align: right; - } - .home-slideshow .flex-direction-nav .flex-prev, - .home-slideshow .flex-direction-nav .flex-next { - top: 40%; - font-size: 1.5em; - filter: progid:DXImageTransform.Microsoft.Alpha(enabled=false); - opacity: 1; - } - .home-slideshow .flex-direction-nav .flex-prev { - left: -0.75em; - } - .home-slideshow .flex-direction-nav .flex-next { - right: -0.75em; - } - .touch body, - .touch #touchnav-wrapper { - position: relative; - width: 100%; - } - .touch .default-page .main-header { - position: static; - } - .touch .main-navigation { - display: block; - position: absolute; - top: 0; - left: -260px; - width: 260px; - height: 100%; - overflow: scroll; - text-align: center; - font-size: 1.125em; - } - .touch .main-navigation a { - text-align: center; - padding: 0.65em 1.25em 0.55em; - } - .touch .main-navigation .tier-2 { - font-size: 0.875em; - } - .touch .main-navigation .subnav { - position: static; - display: block; - opacity: 1; - border-top: 0; - -moz-box-shadow: none; - -webkit-box-shadow: none; - box-shadow: none; - } - .touch #touchnav-wrapper { - -moz-transition: -moz-transform 300ms ease; - -o-transition: -o-transform 300ms ease; - -webkit-transition: -webkit-transform 300ms ease; - transition: transform 300ms ease; - -moz-transform: translate3d(0, 0, 0); - -ms-transform: translate3d(0, 0, 0); - -webkit-transform: translate3d(0, 0, 0); - transform: translate3d(0, 0, 0); - -webkit-backface-visibility: hidden; - } - .touch .show-sidemenu #touchnav-wrapper { - -moz-transform: translate3d(260px, 0, 0); - -ms-transform: translate3d(260px, 0, 0); - -webkit-transform: translate3d(260px, 0, 0); - transform: translate3d(260px, 0, 0); - } -} -@media (min-width: 64em) { - body:after { - content: "drawer_navigation load_supernavs"; - display: none; - speak: none; - } - .about-banner { - background-position: 100% 0; - } - .download-for-current-os { - background-position: 105% 0; - } - .download-for-current-os p { - margin-right: 14.81481%; - } - .documentation-banner { - background-position: 110% 0; - min-height: 345px; - } - .documentation-banner .call-to-action { - margin-right: 8.51064%; - } - .documentation-banner p { - margin-right: 0; - } - .community-banner { - padding-left: 0; - padding-right: 51.06383%; - } - .community-banner p { - margin-right: 0; - } - .latest-blog-post .call-to-action, - .featured-event .call-to-action, - .jobs-intro .call-to-action { - margin-left: 25.53191%; - margin-right: 8.51064%; - } - .latest-blog-post .excerpt, - .featured-event .excerpt, - .jobs-intro .excerpt { - margin-left: 25.53191%; - margin-right: 8.51064%; - } - .psf-widget .widget-title, - .psf-widget p { - margin-right: 34.04255%; - } - .mapped-events h2 { - margin-top: 1em; - } - .default-page .main-content.with-left-sidebar { - padding-left: 8.51064%; - padding-right: 8.51064%; - } - .event-description, - .job-description { - padding-left: 8.51064%; - padding-right: 8.51064%; - } -} -@media (min-width: 75em) { - body:after { - content: "drawer_navigation load_supernavs"; - display: none; - speak: none; - } - .about-banner, - .community-banner { - padding-left: 8.51064%; - padding-right: 51.06383%; - } - .about-banner { - background-position: 85% 0; - } - .download-for-current-os { - padding-left: 8.51064%; - padding-right: 42.55319%; - background-position: 95% 0; - padding-bottom: 6em; - margin-bottom: -3em; - } - .download-for-current-os p { - margin-right: 17.3913%; - } - .documentation-banner { - padding-left: 8.51064%; - padding-right: 42.55319%; - background-position: 100% 0; - } - .documentation-banner .call-to-action { - margin-right: 17.3913%; - } - .community-banner { - background-position: 90% 0; - } -} -@-ms-viewport { - width: device-width; -} -@viewport { - width: device-width; -} diff --git a/pep_extensions/theme/static/css/pep.css b/pep_extensions/theme/static/css/pep.css deleted file mode 100644 index 8e3a4dcaef0..00000000000 --- a/pep_extensions/theme/static/css/pep.css +++ /dev/null @@ -1,263 +0,0 @@ -/* - -TODO: PSF callout -TODO: Refs PEP 310 - -Explicitly don't reformat syntax highlighting as per pydotorg as pydotorg doesn't have it - */ - -/* Generic PEP page formatting */ - -.pep-page pre { - padding: .5em; - background: inherit; - border-left: 0; - -webkit-box-shadow: 0 0 0 0; - -moz-box-shadow: 0 0 0 0; - box-shadow: 0 0 0 0; -} -.pep-page pre.literal-block { - background-color: #e6e8ea; - border: 1px solid #ddd; - padding: 1em; - -webkit-box-shadow: 0 0 1em rgba( 0, 0, 0, 0.2 ); - -moz-box-shadow: 0 0 1em rgba( 0, 0, 0, 0.2 ); - box-shadow: 0 0 1em rgba( 0, 0, 0, 0.2 ); -} - -/* PEP Header Blocks*/ - -dl.rfc2822, -dl.footnote { - background-color: #f6f6f6; - display: grid; - grid-template-columns: fit-content(30%) auto; - line-height: 1.875; - width: 100%; - border-collapse: collapse; - border-spacing: 0; - margin: 0; - padding: 0; - border: 0; -} - -dl.rfc2822 { - grid-template-columns: fit-content(30%) auto; -} - -dl.footnote { - grid-template-columns: fit-content(10%) auto; -} -.footnote .label{ - width: inherit; -} - -dl.rfc2822 > dt, -dl.footnote > dt { - width: inherit; - margin: 0; - border: 0; - text-align: left; - vertical-align: top; - padding: .25em .5em .2em; -} - -dl.rfc2822 > dt { - font-weight: 700; - background-color: #f0f0f0; -} - -dl.rfc2822 > dt:after { - content: ":"; -} - -dl.footnote > dt { - font-weight: normal; -} - -dl.rfc2822 > dd, -dl.footnote > dd { - padding: .25em .5em .2em; - border: 0; - border-left: 2px solid #fff; - margin: 0; - text-align: left; - vertical-align: top; -} - -dl.rfc2822 > dd:nth-of-type(even) { - background-color: #f0f0f0; -} - -/* Link formatting */ - -h1:hover > a.headerlink, -h2:hover > a.headerlink, -h3:hover > a.headerlink, -h4:hover > a.headerlink, -h5:hover > a.headerlink, -h6:hover > a.headerlink, -dt:hover > a.headerlink, -caption:hover > a.headerlink, -p.caption:hover > a.headerlink, -div.code-block-caption:hover > a.headerlink { - visibility: visible; -} - -a.headerlink { - visibility: hidden; -} - -a.brackets:before, -span.brackets > a:before{ - content: "["; -} - -a.brackets:after, -span.brackets > a:after { - content: "]"; -} - -/* Header Formatting*/ -/* We need to move all header formatting up a level (e.g. h2=h1, h3=h2 etc, except h1) */ -h2{ - margin-top: 1em; - margin-bottom: .25em; - font-size: 1.75em; - line-height: 1em; - font-weight: 700; -} - -h3 { - font-size: 1.5em; - margin-top: 1.3125em; - margin-bottom: .32813em; -} - -h4 { - font-size: 1.3125em; - margin-top: 1.75em; - font-weight: normal; -} - -/* Code formatting (code literals and Pygments highlighting blocks) */ - -div.highlight > pre { - padding: 1em; -} - -code.literal { - padding: 0; - margin: 0; - border-radius: 0; - box-shadow: none; - background: none; - color: #444; /* Same as body colour */ - display: inline; -} - -/* Sidebar formatting */ - -aside.left-sidebar { - overflow-y: scroll; - position: sticky; - top: 0; - padding-right: 0.5em; - height: 100vh; - scrollbar-width: thin; /* CSS Standards, not *yet* widely supported */ - scrollbar-color: #ccc transparent; -} -/* Chrome/Edge/Safari vendor prefixes */ -aside.left-sidebar::-webkit-scrollbar { - width: 6px; -} -aside.left-sidebar::-webkit-scrollbar-track { - background: transparent; -} -aside.left-sidebar::-webkit-scrollbar-thumb { - background: #ccc; -} - -aside h3 { - margin-top: 0.5em; - margin-bottom: 0; - font-size: 1.2em; -} - -aside > h6 { - text-align: center; - margin: 0; -} - -div.source-link { - margin-top: 0.25em; - font-weight: 700; -} - -form.search > input { - margin: 0; - border-radius: 3px; - text-shadow: none; - box-shadow: none; -} -form.search > input[type="text"] { - width: 85%; - padding: 0 2px; - cursor: text; -} -form.search > input[type="submit"] { - width: 12%; - padding: 0 6px; - border: 1px solid #caccce; - background: #ccc; - text-align: center; - vertical-align: middle; -} - -div.related > nav > ul { - display: flex; - justify-content: space-between; - margin-left: 0; -} - -aside ul { - margin-left: 1em; - line-height: 22px; -} - -/*####################################################################################*/ -/* Styles explicitly just for matching current pydotorg for visual regression testing */ -/*####################################################################################*/ - -dl.footnote { - background-color: inherit; -} - -dl.footnote > dt, -dl.footnote > dd{ - background-color: #f6f6f6; -} - -div#references > dl.footnote > dt, -div#references > dl.footnote > dd { - margin-bottom: 1.3125em; -} - -div#references > dl.footnote > dt:last-of-type, -div#references > dl.footnote > dd:last-of-type { - margin-bottom: 0; -} - -div.highlight > pre { - box-shadow: 0 0 1em rgba( 0, 0, 0, 0.2 ); - border: 1px solid transparent; -} - -code.literal { - font-family: "Courier New", monospace; - font-size: 12.1833px; -} - -div.zero-height{ - line-height: 0; -} \ No newline at end of file diff --git a/pep_extensions/theme/static/css/style.css b/pep_extensions/theme/static/css/style.css deleted file mode 100644 index f16888e1f88..00000000000 --- a/pep_extensions/theme/static/css/style.css +++ /dev/null @@ -1,4501 +0,0 @@ -@charset "UTF-8"; -/*@import url('https://fonts.googleapis.com/css2?family=Source+Sans+Pro:ital,wght@0,400;0,700;1,400&display=swap');*/ -@font-face{ - font-family: "Source Sans Pro"; - src:url("../fonts/SourceSansPro-Regular-webfont.fd0d51605201.woff") format("woff"); - font-weight: normal; - font-style: normal -} -@font-face{ - font-family: "Source Sans Pro"; - src:url("../fonts/SourceSansPro-Bold-webfont.be855452e565.woff") format("woff"); - font-weight: 700; - font-style: normal -} -@font-face{font-family: "Source Sans Pro"; - src:url("../fonts/SourceSansPro-It-webfont.1aa29ac0f190.woff") format("woff"); - font-weight: normal; - font-style: italic -} -@font-face { - font-family: 'Flux'; - src: url('../fonts/Flux-Regular.ttf') format('truetype'); - font-weight: normal; - font-style: normal; -} - -.psf-widget, -.python-needs-you-widget, -.main-header, -.site-base { - background-color: #2b5b84; - *zoom: 1; - filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#FF1E415E',endColorstr='#FF2B5B84'); - background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiMxZTQxNWUiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iIzJiNWI4NCIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=="); - background-size: 100%; - background-image: -webkit-gradient( - linear, - 50% 0, - 50% 100%, - color-stop(10%, #1e415e), - color-stop(90%, #2b5b84) - ); - background-image: -moz-linear-gradient(#1e415e 10%, #2b5b84 90%); - background-image: -webkit-linear-gradient(#1e415e 10%, #2b5b84 90%); - background-image: linear-gradient(#1e415e 10%, #2b5b84 90%); - -moz-box-shadow: inset 0 0 50px rgba(0, 0, 0, 0.03), - inset 0 0 20px rgba(0, 0, 0, 0.03); - -webkit-box-shadow: inset 0 0 50px rgba(0, 0, 0, 0.03), - inset 0 0 20px rgba(0, 0, 0, 0.03); - box-shadow: inset 0 0 50px rgba(0, 0, 0, 0.03), - inset 0 0 20px rgba(0, 0, 0, 0.03); -} -.psf-widget, -.python-needs-you-widget { - margin-bottom: 0.5em; - padding: 1.25em; - *zoom: 1; -} -.psf-widget:after, -.python-needs-you-widget:after { - content: ""; - display: table; - clear: both; -} -.pep-widget, -.most-recent-events .more-by-location, -.more-by-location { - background-color: #d8dbde; - *zoom: 1; - filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#FFE6E8EA',endColorstr='#FFD8DBDE'); - background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiNlNmU4ZWEiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iI2Q4ZGJkZSIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=="); - background-size: 100%; - background-image: -webkit-gradient( - linear, - 50% 0, - 50% 100%, - color-stop(10%, #e6e8ea), - color-stop(90%, #d8dbde) - ); - background-image: -moz-linear-gradient(#e6e8ea 10%, #d8dbde 90%); - background-image: -webkit-linear-gradient(#e6e8ea 10%, #d8dbde 90%); - background-image: linear-gradient(#e6e8ea 10%, #d8dbde 90%); - -moz-box-shadow: inset 0 0 10px rgba(0, 0, 0, 0.01); - -webkit-box-shadow: inset 0 0 10px rgba(0, 0, 0, 0.01); - box-shadow: inset 0 0 10px rgba(0, 0, 0, 0.01); -} -.pep-widget, -.most-recent-events .more-by-location { - border: 1px solid #caccce; - margin-bottom: 0.5em; - padding: 1.25em; - *zoom: 1; -} -.pep-widget:after, -.most-recent-events .more-by-location:after { - content: ""; - display: table; - clear: both; -} -.single-event-date { - background-color: #ffdd6c; - *zoom: 1; - filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#FFFFE89F',endColorstr='#FFFFDD6C'); - background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiNmZmU4OWYiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iI2ZmZGQ2YyIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=="); - background-size: 100%; - background-image: -webkit-gradient( - linear, - 50% 0, - 50% 100%, - color-stop(10%, #ffe89f), - color-stop(90%, #ffdd6c) - ); - background-image: -moz-linear-gradient(#ffe89f 10%, #ffdd6c 90%); - background-image: -webkit-linear-gradient(#ffe89f 10%, #ffdd6c 90%); - background-image: linear-gradient(#ffe89f 10%, #ffdd6c 90%); - -moz-box-shadow: inset 0 0 10px rgba(0, 0, 0, 0.05); - -webkit-box-shadow: inset 0 0 10px rgba(0, 0, 0, 0.05); - box-shadow: inset 0 0 10px rgba(0, 0, 0, 0.05); -} -.single-event-date { - border: 1px solid #ffcc24; - margin-bottom: 0.5em; - padding: 1.25em; - *zoom: 1; -} -.single-event-date:after { - content: ""; - display: table; - clear: both; -} -.psf-widget .button, -.python-needs-you-widget .button, -.donate-button, -.header-banner .button, -.header-banner a.button, -a.delete, -form.deletion-form button[type="submit"], -button[type="submit"], -.search-button, -#dive-into-python .flex-control-paging a, -.text form button, -.text form input[type="submit"], -.sidebar-widget form button, -.sidebar-widget form input[type="submit"], -input[type="submit"], -input[type="reset"], -button, -a.button, -.button { - cursor: pointer; - color: #4d4d4d !important; - font-weight: normal; - margin-bottom: 0.4375em; - padding: 0.4em 0.75em 0.35em; - text-align: left; - white-space: nowrap; - text-shadow: 1px 1px 1px rgba(255, 255, 255, 0.3); - background-color: #ccc; - *zoom: 1; - filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#FFD9D9D9',endColorstr='#FFCCCCCC'); - background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiNkOWQ5ZDkiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iI2NjY2NjYyIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=="); - background-size: 100%; - background-image: -webkit-gradient( - linear, - 50% 0, - 50% 100%, - color-stop(10%, #d9d9d9), - color-stop(90%, #ccc) - ); - background-image: -moz-linear-gradient(#d9d9d9 10%, #ccc 90%); - background-image: -webkit-linear-gradient(#d9d9d9 10%, #ccc 90%); - background-image: linear-gradient(#d9d9d9 10%, #ccc 90%); - border-top: 1px solid #caccce; - border-right: 1px solid #caccce; - border-bottom: 1px solid #999; - border-left: 1px solid #caccce; - -moz-border-radius: 6px; - -webkit-border-radius: 6px; - border-radius: 6px; - -moz-box-shadow: 1px 1px 1px rgba(0, 0, 0, 0.05), - inset 0 0 5px rgba(255, 255, 255, 0.5); - -webkit-box-shadow: 1px 1px 1px rgba(0, 0, 0, 0.05), - inset 0 0 5px rgba(255, 255, 255, 0.5); - box-shadow: 1px 1px 1px rgba(0, 0, 0, 0.05), - inset 0 0 5px rgba(255, 255, 255, 0.5); -} -.donate-button:hover, -a.delete:hover, -form.deletion-form button[type="submit"]:hover, -.search-button:hover, -#dive-into-python .flex-control-paging a:hover, -.text form button:hover, -.text form input[type="submit"]:hover, -.sidebar-widget form button:hover, -.sidebar-widget form input[type="submit"]:hover, -input[type="submit"]:hover, -input[type="reset"]:hover, -button:hover, -.button:hover, -.donate-button:focus, -a.delete:focus, -form.deletion-form button[type="submit"]:focus, -.search-button:focus, -#dive-into-python .flex-control-paging a:focus, -.text form button:focus, -.text form input[type="submit"]:focus, -.sidebar-widget form button:focus, -.sidebar-widget form input[type="submit"]:focus, -input[type="submit"]:focus, -input[type="reset"]:focus, -button:focus, -.button:focus, -.donate-button:active, -a.delete:active, -form.deletion-form button[type="submit"]:active, -.search-button:active, -#dive-into-python .flex-control-paging a:active, -.text form button:active, -.text form input[type="submit"]:active, -.sidebar-widget form button:active, -.sidebar-widget form input[type="submit"]:active, -input[type="submit"]:active, -input[type="reset"]:active, -button:active, -.button:active { - color: #1a1a1a !important; - background-color: #d9d9d9; - *zoom: 1; - filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#FFE6E6E6',endColorstr='#FFD9D9D9'); - background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiNlNmU2ZTYiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iI2Q5ZDlkOSIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=="); - background-size: 100%; - background-image: -webkit-gradient( - linear, - 50% 0, - 50% 100%, - color-stop(10%, #e6e6e6), - color-stop(90%, #d9d9d9) - ); - background-image: -moz-linear-gradient(#e6e6e6 10%, #d9d9d9 90%); - background-image: -webkit-linear-gradient(#e6e6e6 10%, #d9d9d9 90%); - background-image: linear-gradient(#e6e6e6 10%, #d9d9d9 90%); -} -.psf-widget .button, -.python-needs-you-widget .button, -.donate-button, -.header-banner .button, -.header-banner a.button { - background-color: #ffd343; - *zoom: 1; - filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#FFFFDF76',endColorstr='#FFFFD343'); - background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiNmZmRmNzYiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iI2ZmZDM0MyIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=="); - background-size: 100%; - background-image: -webkit-gradient( - linear, - 50% 0, - 50% 100%, - color-stop(10%, #ffdf76), - color-stop(90%, #ffd343) - ); - background-image: -moz-linear-gradient(#ffdf76 10%, #ffd343 90%); - background-image: -webkit-linear-gradient(#ffdf76 10%, #ffd343 90%); - background-image: linear-gradient(#ffdf76 10%, #ffd343 90%); - border-top: 1px solid #dca900; - border-right: 1px solid #dca900; - border-bottom: 1px solid #dca900; - border-left: 1px solid #dca900; -} -.psf-widget .button:hover, -.python-needs-you-widget .button:hover, -.donate-button:hover, -.header-banner .button:hover, -.psf-widget .button:active, -.python-needs-you-widget .button:active, -.donate-button:active, -.header-banner .button:active { - background-color: inherit; - background-color: #ffd343; - *zoom: 1; - filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#FFFFEBA9',endColorstr='#FFFFD343'); - background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiNmZmViYTkiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iI2ZmZDM0MyIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=="); - background-size: 100%; - background-image: -webkit-gradient( - linear, - 50% 0, - 50% 100%, - color-stop(10%, #ffeba9), - color-stop(90%, #ffd343) - ); - background-image: -moz-linear-gradient(#ffeba9 10%, #ffd343 90%); - background-image: -webkit-linear-gradient(#ffeba9 10%, #ffd343 90%); - background-image: linear-gradient(#ffeba9 10%, #ffd343 90%); -} -a.delete, -form.deletion-form button[type="submit"] { - background-color: #b55863; - *zoom: 1; - filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#FFC57B84',endColorstr='#FFB55863'); - background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiNjNTdiODQiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iI2I1NTg2MyIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=="); - background-size: 100%; - background-image: -webkit-gradient( - linear, - 50% 0, - 50% 100%, - color-stop(10%, #c57b84), - color-stop(90%, #b55863) - ); - background-image: -moz-linear-gradient(#c57b84 10%, #b55863 90%); - background-image: -webkit-linear-gradient(#c57b84 10%, #b55863 90%); - background-image: linear-gradient(#c57b84 10%, #b55863 90%); - border-top: 1px solid #74333b; - border-right: 1px solid #74333b; - border-bottom: 1px solid #74333b; - border-left: 1px solid #74333b; - color: #fff !important; -} -a.delete:hover, -form.deletion-form button[type="submit"]:hover, -a.delete:active, -form.deletion-form button[type="submit"]:active { - background-color: inherit; - color: #fff !important; - background-color: #b55863; - *zoom: 1; - filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#FFD49FA5',endColorstr='#FFB55863'); - background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiNkNDlmYTUiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iI2I1NTg2MyIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=="); - background-size: 100%; - background-image: -webkit-gradient( - linear, - 50% 0, - 50% 100%, - color-stop(10%, #d49fa5), - color-stop(90%, #b55863) - ); - background-image: -moz-linear-gradient(#d49fa5 10%, #b55863 90%); - background-image: -webkit-linear-gradient(#d49fa5 10%, #b55863 90%); - background-image: linear-gradient(#d49fa5 10%, #b55863 90%); -} -button[type="submit"], -.search-button, -#dive-into-python .flex-control-paging a, -.text form button, -.text form input[type="submit"], -.sidebar-widget form button, -.sidebar-widget form input[type="submit"] { - color: #e6e8ea !important; - text-shadow: none; - background-color: #2b5b84; - *zoom: 1; - filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#FF3776AB',endColorstr='#FF2B5B84'); - background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiMzNzc2YWIiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iIzJiNWI4NCIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=="); - background-size: 100%; - background-image: -webkit-gradient( - linear, - 50% 0, - 50% 100%, - color-stop(10%, #3776ab), - color-stop(90%, #2b5b84) - ); - background-image: -moz-linear-gradient(#3776ab 10%, #2b5b84 90%); - background-image: -webkit-linear-gradient(#3776ab 10%, #2b5b84 90%); - background-image: linear-gradient(#3776ab 10%, #2b5b84 90%); - border-top: 1px solid #3d83be; - border-right: 1px solid #3776ab; - border-bottom: 1px solid #3776ab; - border-left: 1px solid #3d83be; - -moz-box-shadow: inset 0 0 5px rgba(55, 118, 171, 0.2); - -webkit-box-shadow: inset 0 0 5px rgba(55, 118, 171, 0.2); - box-shadow: inset 0 0 5px rgba(55, 118, 171, 0.2); -} -button[type="submit"]:hover, -.search-button:hover, -#dive-into-python .flex-control-paging a:hover, -.text form button:hover, -.text form input[type="submit"]:hover, -.sidebar-widget form button:hover, -.sidebar-widget form input[type="submit"]:hover, -button[type="submit"]:active, -.search-button:active, -#dive-into-python .flex-control-paging a:active, -.text form button:active, -.text form input[type="submit"]:active, -.sidebar-widget form button:active, -.sidebar-widget form input[type="submit"]:active { - background: inherit; - color: #f2f4f6 !important; - background-color: #244e71; - *zoom: 1; - filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#FF316998',endColorstr='#FF244E71'); - background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiMzMTY5OTgiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iIzI0NGU3MSIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=="); - background-size: 100%; - background-image: -webkit-gradient( - linear, - 50% 0, - 50% 100%, - color-stop(10%, #316998), - color-stop(90%, #244e71) - ); - background-image: -moz-linear-gradient(#316998 10%, #244e71 90%); - background-image: -webkit-linear-gradient(#316998 10%, #244e71 90%); - background-image: linear-gradient(#316998 10%, #244e71 90%); -} -.header-banner a:not(.button), -.header-banner a:not(.readmore), -.text a:not(.button), -.sidebar-widget a:not(.button), -.active-user-list a { - border-bottom: 1px solid #ffdf76; - text-decoration: none; -} -.header-banner a:hover:not(.button), -.header-banner a:hover:not(.readmore), -.text a:hover:not(.button), -.sidebar-widget a:hover:not(.button), -.active-user-list a:hover, -.header-banner a:focus:not(.button), -.header-banner a:focus:not(.readmore), -.text a:focus:not(.button), -.sidebar-widget a:focus:not(.button), -.active-user-list a:focus { - border-bottom-color: #ffd343; -} -.blog-widget li, -.event-widget li, -.most-recent-posts li { - border-top: 1px solid #caccce; - padding-left: 4em; - padding-top: 0.4375em; - padding-bottom: 0.4375em; - position: relative; -} -.blog-widget li time, -.event-widget li time, -.most-recent-posts li time { - position: absolute; - top: 50%; - left: 0; - margin-top: -0.75em; -} -.pagination a { - display: block; - color: #999; - padding: 0.5em 0.75em 0.4em; - border: 1px solid #caccce; - background-color: transparent; -} -form, -.header-banner, -.success-stories-widget .quote-from { - *zoom: 1; -} -form:after, -.header-banner:after, -.success-stories-widget .quote-from:after { - content: ""; - display: table; - clear: both; -} -html, -body, -div, -span, -object, -iframe, -h1, -h2, -h3, -h4, -h5, -h6, -p, -blockquote, -pre, -abbr, -address, -cite, -code, -del, -dfn, -em, -img, -ins, -kbd, -q, -samp, -small, -strong, -sub, -sup, -var, -b, -i, -dl, -dt, -dd, -ol, -ul, -li, -fieldset, -form, -label, -legend, -table, -caption, -tbody, -tfoot, -thead, -tr, -th, -td, -article, -aside, -canvas, -details, -figcaption, -figure, -footer, -header, -hgroup, -menu, -nav, -section, -summary, -time, -mark, -audio, -video { - margin: 0; - padding: 0; - border: 0; - font-size: 100%; - font: inherit; - vertical-align: baseline; -} -article, -aside, -details, -figcaption, -figure, -footer, -header, -hgroup, -menu, -nav, -section, -form { - display: block; -} -blockquote { - quotes: none; -} -blockquote:before, -blockquote:after { - content: ""; - content: none; -} -q { - display: inline; -} -q:before { - content: "“"; -} -q:after { - content: "”"; -} -q q:before { - content: "‘"; -} -q q:after { - content: "’"; -} -ins { - background-color: #ddd; - color: #222; - text-decoration: none; -} -mark { - display: inline-block; - padding: 0 0.25em; - margin: 0 -0.125em; - background-color: #ffb; -} -s, -strike, -del { - text-decoration: line-through; -} -abbr[title], -dfn[title] { - cursor: help; -} -table { - width: 100%; - border-collapse: collapse; - border-spacing: 0; -} -th, -td { - text-align: left; - vertical-align: top; -} -hr { - display: block; - height: 1px; - border: 0; - border-top: 1px solid #caccce; - margin: 1.75em 0; - padding: 0; -} -input, -button, -select { - display: inline-block; - vertical-align: middle; - cursor: pointer; -} -html { - font-size: 100%; - -webkit-text-size-adjust: 100%; - -ms-text-size-adjust: 100%; - overflow-y: scroll; - -webkit-font-smoothing: antialiased; - margin: 0; -} -body { - *font-size: small; - /*text-rendering: optimizeSpeed;*/ -} -select, -input, -textarea, -button { - font: 99%; - -webkit-font-smoothing: antialiased; - margin: 0; -} -h1, -h2, -h3, -h4, -h5, -h6 { - font-weight: normal; -} -ul, -ol { - margin-left: 1.5em; -} -ul { - list-style: square; -} -ol { - list-style: decimal; -} -ol ol { - list-style: upper-alpha; -} -ol ol ol { - list-style: lower-roman; -} -ol ol ol ol { - list-style: lower-alpha; -} -nav ul, -menu ul, -.menu, -form ul, -.errorlist, -.text form label + ul, -.sidebar-widget form label + ul, -.tabs { - margin-left: 0; - list-style: none; - list-style-image: none; -} -small { - font-size: 85%; -} -b, -strong, -th { - font-weight: 700; -} -i, -em, -cite { - font-style: italic; -} -sub, -sup { - font-size: 75%; - line-height: 0; - position: relative; -} -sup { - top: -0.5em; -} -sub { - bottom: -0.25em; -} -pre, -code, -kbd, -samp, -var { - font-family: Consolas, "Lucida Console", "Liberation Mono", "DejaVu Sans Mono", - "Bitstream Vera Sans Mono", "Courier New", monospace, sans-serif; -} -pre { - white-space: pre-wrap; - white-space: -moz-pre-wrap !important; - white-space: -pre-wrap; - white-space: -o-pre-wrap; - word-wrap: break-word; -} -code { - color: #11a611; -} -var { - font-style: italic; -} -textarea { - overflow: auto; - vertical-align: top; - resize: vertical; -} -.ie7 legend { - border: 0; - padding: 0; - white-space: normal; - *margin-left: -7px; -} -input[type="radio"] { - vertical-align: text-bottom; -} -input[type="checkbox"] { - vertical-align: baseline; -} -.ie7 input[type="checkbox"] { - vertical-align: bottom; -} -button, -input[type="button"], -input[type="reset"], -input[type="submit"] { - cursor: pointer; - -webkit-appearance: button; - -moz-appearance: button; -} -.lt-ie8 button, -.lt-ie8 input[type="button"], -.lt-ie8 input[type="reset"], -.lt-ie8 input[type="submit"] { - overflow: visible; -} -button[disabled], -input[disabled] { - cursor: default; -} -input[type="checkbox"], -input[type="radio"] { - padding: 0; - *width: 13px; - *height: 13px; -} -input[type="search"] { - -webkit-appearance: textfield; -} -input[type="search"]::-webkit-search-decoration, -input[type="search"]::-webkit-search-cancel-button { - -webkit-appearance: none; -} -.no-boxshadow input:invalid, -.no-boxshadow textarea:invalid { - background-color: #f0dddd; -} -.ie7 img { - -ms-interpolation-mode: bicubic; -} -abbr.initialism { - speak: spell-out; -} -abbr.truncation { - speak: normal; -} -@-ms-viewport { - width: device-width; -} -canvas { - -ms-touch-action: double-tap-zoom; -} -svg:not(:root) { - overflow: hidden; -} -html { - background-color: #2b5b84; - font: normal 100%/1.625 "Source Sans Pro", Arial, sans-serif; -} -body { - color: #444; - background-color: #fff; -} -body:after { - content: "small"; - display: none; -} -body, -input, -textarea, -select, -button { - color: #444; - font: normal 100%/1.625 "Source Sans Pro", Arial, sans-serif; -} -* { - -moz-box-sizing: border-box; - -webkit-box-sizing: border-box; - box-sizing: border-box; -} -a, -a:active, -a:visited, -a:hover, -a:visited:hover { - color: #3776ab; - text-decoration: none; -} -a:hover, -a:focus { - color: #1e2933; -} -.touch a[href^="tel:"] { - border-bottom: 1px dotted #444; -} -a img { - display: block; - margin: 0 auto; -} -::-moz-selection { - background: #3776ab; - color: #fff; - text-shadow: none; -} -::selection { - background: #3776ab; - color: #fff; - text-shadow: none; -} -a:link { - -webkit-tap-highlight-color: #1e2933; -} -img, -embed, -object, -video { - max-width: 100%; -} -.giga { - font-size: 2.5em; -} -.fontface .giga { - font-size: 2.875em; -} -.fontface .giga span:before { - font-size: 0.875em; -} -.mega { - font-size: 2.25em; -} -.fontface .mega { - font-size: 2.5875em; -} -.fontface .mega span:before { - font-size: 0.875em; -} -.kilo { - font-size: 2em; -} -.fontface .kilo { - font-size: 2.3em; -} -.fontface .kilo span:before { - font-size: 0.875em; -} -h1, -.alpha { - color: #3776ab; - font-weight: 700; - font-family: "Source Sans Pro", Arial, sans-serif; - line-height: 1em; - font-size: 1.75em; - margin-bottom: 0.4375em; -} -h2, -.beta { - color: #999; - font-family: "Source Sans Pro", Arial, sans-serif; - font-size: 1.5em; - margin-top: 1.3125em; - margin-bottom: 0.32813em; -} -h3, -.chi { - color: #222; - font-size: 1.3125em; - margin-top: 1.75em; - margin-bottom: 0.4375em; -} -h4, -.delta { - color: #222; - font-weight: 700; - font-family: "Source Sans Pro", Arial, sans-serif; - font-size: 1.125em; - margin-top: 1.3125em; - margin-bottom: 0.4375em; -} -h5, -.epsilon { - color: #222; - font-weight: 700; - font-family: "Source Sans Pro", Arial, sans-serif; - text-transform: uppercase; - letter-spacing: 0.0625em; - margin-top: 1.75em; -} -h6, -.gamma { - color: #222; - font-weight: 700; - font-family: "Source Sans Pro", Arial, sans-serif; - margin-top: 1.75em; -} -blockquote { - position: relative; - font: italic 1.125em Georgia, serif; - line-height: 2; - padding-top: 1.3125em; - padding-bottom: 1.3125em; - border-top: 3px solid #ffeba9; - border-bottom: 3px solid #ffeba9; - margin-bottom: 1.3125em; -} -blockquote footer { - font: normal 0.77778em "Source Sans Pro", Arial, sans-serif; -} -blockquote em { - font-style: normal; -} -dl { - border-top: 1px solid #e6e8ea; -} -dl dt { - font-weight: 700; - font-family: "Source Sans Pro", Arial, sans-serif; - border-bottom: 1px solid #e6e8ea; -} -dl dd { - padding-left: 1.5em; - border-bottom: 1px solid #caccce; -} -.errorlist { - color: #b55863; - margin-bottom: 0; -} -.errorlist + label { - margin-top: 0; -} -.error-message { - color: #b55863; -} -label { - display: block; - color: #999; - font-weight: bold; - margin-top: 0.875em; - margin-top: 0.21875em; -} -label.active { - color: #3776ab; -} -input, -textarea { - width: 100%; - padding: 0.65em; - border: 1px solid #caccce; - -moz-border-radius: 6px; - -webkit-border-radius: 6px; - border-radius: 6px; -} -input, -textarea, -select { - margin-bottom: 0.875em; -} -input[type="checkbox"], -input[type="radio"] { - width: auto; - border: 0; - margin-right: 0.25em; -} -input[type="radio"] { - margin-bottom: 0.25em; -} -.no-touch input:focus { - -moz-box-shadow: 0 0 10px rgba(0, 0, 0, 0.2); - -webkit-box-shadow: 0 0 10px rgba(0, 0, 0, 0.2); - box-shadow: 0 0 10px rgba(0, 0, 0, 0.2); -} -input[required="required"] { - border-color: #b55863; -} -input[required="required"]:focus { - -moz-box-shadow: 0 0 10px rgba(255, 0, 0, 0.5); - -webkit-box-shadow: 0 0 10px rgba(255, 0, 0, 0.5); - box-shadow: 0 0 10px rgba(255, 0, 0, 0.5); -} -::-webkit-input-placeholder { - color: #999; - font-style: italic; -} -input:-moz-placeholder { - color: #999; - font-style: italic; -} -input[type="submit"], -input[type="reset"], -button, -a.button, -.button { - display: block; -} -input[type="reset"], -button.secondaryAction[type="submit"] { - background-color: #999; - *zoom: 1; - filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#FFB3B3B3',endColorstr='#FF999999'); - background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiNiM2IzYjMiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iIzk5OTk5OSIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=="); - background-size: 100%; - background-image: -webkit-gradient( - linear, - 50% 0, - 50% 100%, - color-stop(10%, #b3b3b3), - color-stop(90%, #999) - ); - background-image: -moz-linear-gradient(#b3b3b3 10%, #999 90%); - background-image: -webkit-linear-gradient(#b3b3b3 10%, #999 90%); - background-image: linear-gradient(#b3b3b3 10%, #999 90%); - border-top: 1px solid #caccce; - border-right: 1px solid #999; - border-bottom: 1px solid gray; - border-left: 1px solid #999; -} -input[type="reset"]:hover, -input[type="reset"]:focus, -input[type="reset"]:active, -button.secondaryAction[type="submit"]:hover, -button.secondaryAction[type="submit"]:focus, -button.secondaryAction[type="submit"]:active { - color: #fff; - background-color: #b3b3b3; - *zoom: 1; - filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#FF999999',endColorstr='#FFB3B3B3'); - background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiM5OTk5OTkiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iI2IzYjNiMyIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=="); - background-size: 100%; - background-image: -webkit-gradient( - linear, - 50% 0, - 50% 100%, - color-stop(10%, #999), - color-stop(90%, #b3b3b3) - ); - background-image: -moz-linear-gradient(#999 10%, #b3b3b3 90%); - background-image: -webkit-linear-gradient(#999 10%, #b3b3b3 90%); - background-image: linear-gradient(#999 10%, #b3b3b3 90%); -} -input[type="image"] { - width: auto; -} -b, -strong { - font-weight: 700; - font-family: "Source Sans Pro", Arial, sans-serif; -} -i, -em { - font-family: "Source Sans Pro", Arial, sans-serif; - font-style: italic; -} -abbr, -dfn { - border-bottom: 1px dotted #3776ab; -} -.col-row { - margin: -1em; - overflow: hidden; - *zoom: 1; -} -.column, -.not-column { - padding-left: 1em; - padding-right: 1em; -} -.column { - padding-bottom: 1.75em; -} -h1.not-column { - padding-left: 0.57143em; - padding-right: 0.57143em; -} -h2.not-column { - padding-left: 0.66667em; - padding-right: 0.66667em; -} -.pre, -.rss-link { - white-space: nowrap; -} -.say-no-more { - display: none; - visibility: hidden; -} -.prompt, -.readmore:before, -.give-me-more a:before { - font-family: Flux, "Source Sans Pro", Arial, sans-serif; - font-size: 120%; - letter-spacing: -0.0625em; -} -.readmore, -.give-me-more a { - white-space: nowrap; -} -.readmore:before, -.give-me-more a:before { - content: ">>>"; - margin-right: 0.25em; -} -.larger { - font-size: 120%; -} -.indent { - padding-left: 2em; -} -.top-bar a:hover, -.top-bar a:focus, -.python .top-bar .python-meta a, -.psf .top-bar .psf-meta a, -.docs .top-bar .docs-meta a, -.pypi .top-bar .pypi-meta a, -.jobs .top-bar .jobs-meta a, -.shop .top-bar .shop-meta a { - color: #fff; - background-color: #1f2a32; - *zoom: 1; - filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#FF13191E',endColorstr='#FF1F2A32'); - background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiMxMzE5MWUiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iIzFmMmEzMiIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=="); - background-size: 100%; - background-image: -webkit-gradient( - linear, - 50% 0, - 50% 100%, - color-stop(10%, #13191e), - color-stop(90%, #1f2a32) - ); - background-image: -moz-linear-gradient(#13191e 10%, #1f2a32 90%); - background-image: -webkit-linear-gradient(#13191e 10%, #1f2a32 90%); - background-image: linear-gradient(#13191e 10%, #1f2a32 90%); -} -.top-bar a:hover:before, -.top-bar a:focus:before, -.python .top-bar .python-meta a:before, -.psf .top-bar .psf-meta a:before, -.docs .top-bar .docs-meta a:before, -.pypi .top-bar .pypi-meta a:before, -.jobs .top-bar .jobs-meta a:before, -.shop .top-bar .shop-meta a:before { - left: 50%; -} -.top-bar { - color: #bbb; - background-color: #1e2933; - border-bottom: 1px solid #1f3b47; -} -.top-bar a { - position: relative; - display: block; - color: #999; - background: transparent; - text-align: center; - padding: 0.5em 0.75em 0.4em; - font-size: 1em; - line-height: 1.75em; -} -.top-bar a:before { - position: absolute; - content: ""; - width: 0; - height: 0; - border-color: transparent; - border-style: solid; - border-width: 0.5em; - border-right-color: transparent; - border-bottom-color: transparent; - border-left-color: transparent; - top: 0; - left: -9999px; - margin-left: -0.25em; -} -.top-bar li { - border-top: 3px solid #3776ab; -} -.top-bar .python-meta, -.top-bar .python-meta a:before { - border-top-color: #3776ab; -} -.top-bar .psf-meta, -.top-bar .psf-meta a:before { - border-top-color: #78797a; -} -.top-bar .docs-meta, -.top-bar .docs-meta a:before { - border-top-color: #ffd343; -} -.top-bar .pypi-meta, -.top-bar .pypi-meta a:before { - border-top-color: #82b043; -} -.top-bar .jobs-meta, -.top-bar .jobs-meta a:before { - border-top-color: #a06ba7; -} -.top-bar .shop-meta, -.top-bar .shop-meta a:before { - border-top-color: #b55863; -} -.meta-navigation { - text-align: center; -} -.meta-navigation .menu, -.meta-navigation form ul, -form .meta-navigation ul, -.meta-navigation .errorlist, -.meta-navigation .text form label + ul, -.text form .meta-navigation label + ul, -.meta-navigation .sidebar-widget form label + ul, -.sidebar-widget form .meta-navigation label + ul { - margin-bottom: 0; -} -.meta-navigation .say-no-more { - display: inline; - visibility: visible; -} -.meta-navigation .jump-link { - background-color: #11171d; -} -.main-header { - border-top: 1px solid #191919; - border-bottom: 1px solid #444; -} -.main-header .container { - text-align: center; - padding: 0.75em 1em; -} -.site-headline { - color: #fff; - margin: 0.15em auto 0.2em; -} -.site-headline a { - display: block; - margin: 0 auto; -} -.site-headline a .python-logo { - width: 217.5px; - height: 61.5px; -} -.site-headline a .psf-logo { - width: 250.5px; - height: 61.5px; -} -.options-bar-container { - float: none; -} -.donate-button { - display: block; - text-align: center; - position: relative; - top: 0; - margin: 1em 0.7em; -} -.options-bar { - width: 100%; - color: #bbb; - margin-bottom: 1.3125em; - border-top: 1px solid #2d3e4d; - border-bottom: 1px solid #070a0c; - background-color: #1e2933; - line-height: 1em; - -moz-border-radius: 6px; - -webkit-border-radius: 6px; - border-radius: 6px; -} -.options-bar form { - padding: 0.35em 0.2em 0.3em; -} -.options-bar .breaker { - display: block; - width: 100%; - height: 1px; - font-size: 1px; - line-height: 1px; - border-top: 1px solid #070a0c; - border-bottom: 1px solid #2d3e4d; -} -.options-bar .subnav { - display: none; -} -#site-map-link, -.jump-to-menu, -.search-the-site, -.icon-search, -.icon-search:before, -input#s, -.adjust-font-size, -.winkwink-nudgenudge, -.account-signin { - display: -moz-inline-stack; - display: inline-block; - vertical-align: middle; -} -.lt-ie8 #site-map-link, -.lt-ie8 .jump-to-menu, -.lt-ie8 .search-the-site, -.lt-ie8 .icon-search, -.lt-ie8 .icon-search:before, -.lt-ie8 input#s, -.lt-ie8 .adjust-font-size, -.lt-ie8 .winkwink-nudgenudge, -.lt-ie8 .account-signin { - vertical-align: auto; - zoom: 1; - display: inline; -} -.touch .search-the-site, -.winkwink-nudgenudge, -.account-signin { - border-left: 1px solid #2d3e4d; -} -.touch #site-map-link, -.jump-to-menu, -.adjust-font-size, -.winkwink-nudgenudge { - border-right: 1px solid #070a0c; -} -#site-map-link { - color: #bbb; -} -#site-map-link:hover, -#site-map-link:focus { - color: #fff; -} -.no-touch #site-map-link { - display: none; -} -.menu-icon { - display: inline-block; - font-size: 1.25em; - margin: -0.125em -0.125em 0 0; -} -.search-the-site { - text-align: left; - padding: 0.35em 0.2em 0.3em; -} -.search-the-site .icon-search:before { - font-size: 1.75em; - margin: 0 0.125em 0 0.25em; -} -.search-the-site .no-touch { - border-left: 0; -} -.search-field { - width: 4.5em; - margin-bottom: 0; - color: #bbb; - background-color: transparent; - border: 0; - margin: 0.125em 0; - padding: 0.4em 0 0.3em; - -moz-border-radius: 0; - -webkit-border-radius: 0; - border-radius: 0; -} -.search-field::-webkit-input-placeholder { - color: #bbb; - font-style: normal; -} -.search-field:-moz-placeholder { - color: #bbb; - font-style: normal; -} -.search-field:focus { - background-color: #fff; - color: #444; - padding: 0.4em 0.5em 0.3em; -} -.search-field:blur { - color: #bbb; -} -.search-button { - margin-right: 0.2em; - margin-bottom: 0; - text-shadow: none; -} -.touch .search-button { - display: none; -} -.no-touch .adjust-font-size { - display: none; -} -.adjust-font-size, -.winkwink-nudgenudge, -.account-signin { - text-align: center; - overflow: visible; -} -.adjust-font-size .menu, -.adjust-font-size form ul, -form .adjust-font-size ul, -.adjust-font-size .errorlist, -.adjust-font-size .text form label + ul, -.text form .adjust-font-size label + ul, -.adjust-font-size .sidebar-widget form label + ul, -.sidebar-widget form .adjust-font-size label + ul, -.winkwink-nudgenudge .menu, -.winkwink-nudgenudge form ul, -form .winkwink-nudgenudge ul, -.winkwink-nudgenudge .errorlist, -.winkwink-nudgenudge .text form label + ul, -.text form .winkwink-nudgenudge label + ul, -.winkwink-nudgenudge .sidebar-widget form label + ul, -.sidebar-widget form .winkwink-nudgenudge label + ul, -.account-signin .menu, -.account-signin form ul, -form .account-signin ul, -.account-signin .errorlist, -.account-signin .text form label + ul, -.text form .account-signin label + ul, -.account-signin .sidebar-widget form label + ul, -.sidebar-widget form .account-signin label + ul { - margin-bottom: 0; -} -.adjust-font-size .tier-1 > a, -.adjust-font-size .tier-2 > a, -.winkwink-nudgenudge .tier-1 > a, -.winkwink-nudgenudge .tier-2 > a, -.account-signin .tier-1 > a, -.account-signin .tier-2 > a { - display: block; - padding: 0.5em 1.5em 0.4em 1em; - position: relative; -} -.adjust-font-size .tier-1, -.winkwink-nudgenudge .tier-1, -.account-signin .tier-1 { - display: block; - width: 100%; -} -.adjust-font-size .tier-1 > a, -.winkwink-nudgenudge .tier-1 > a, -.account-signin .tier-1 > a { - text-align: center; -} -.adjust-font-size .tier-2 > a, -.winkwink-nudgenudge .tier-2 > a, -.account-signin .tier-2 > a { - text-align: left; -} -.adjust-font-size .menu, -.adjust-font-size form ul, -form .adjust-font-size ul, -.adjust-font-size .errorlist, -.adjust-font-size .text form label + ul, -.text form .adjust-font-size label + ul, -.adjust-font-size .sidebar-widget form label + ul, -.sidebar-widget form .adjust-font-size label + ul, -.winkwink-nudgenudge .menu, -.winkwink-nudgenudge form ul, -form .winkwink-nudgenudge ul, -.winkwink-nudgenudge .errorlist, -.winkwink-nudgenudge .text form label + ul, -.text form .winkwink-nudgenudge label + ul, -.winkwink-nudgenudge .sidebar-widget form label + ul, -.sidebar-widget form .winkwink-nudgenudge label + ul, -.account-signin .menu, -.account-signin form ul, -form .account-signin ul, -.account-signin .errorlist, -.account-signin .text form label + ul, -.text form .account-signin label + ul, -.account-signin .sidebar-widget form label + ul, -.sidebar-widget form .account-signin label + ul { - *zoom: 1; -} -.adjust-font-size .menu:after, -.adjust-font-size form ul:after, -form .adjust-font-size ul:after, -.adjust-font-size .errorlist:after, -.adjust-font-size .text form label + ul:after, -.text form .adjust-font-size label + ul:after, -.adjust-font-size .sidebar-widget form label + ul:after, -.sidebar-widget form .adjust-font-size label + ul:after, -.winkwink-nudgenudge .menu:after, -.winkwink-nudgenudge form ul:after, -form .winkwink-nudgenudge ul:after, -.winkwink-nudgenudge .errorlist:after, -.winkwink-nudgenudge .text form label + ul:after, -.text form .winkwink-nudgenudge label + ul:after, -.winkwink-nudgenudge .sidebar-widget form label + ul:after, -.sidebar-widget form .winkwink-nudgenudge label + ul:after, -.account-signin .menu:after, -.account-signin form ul:after, -form .account-signin ul:after, -.account-signin .errorlist:after, -.account-signin .text form label + ul:after, -.text form .account-signin label + ul:after, -.account-signin .sidebar-widget form label + ul:after, -.sidebar-widget form .account-signin label + ul:after { - content: ""; - display: table; - clear: both; -} -.adjust-font-size .tier-1, -.winkwink-nudgenudge .tier-1, -.account-signin .tier-1 { - position: relative; -} -.adjust-font-size .subnav, -.winkwink-nudgenudge .subnav, -.account-signin .subnav { - position: absolute; - z-index: 100; - text-align: left; -} -.no-touch .adjust-font-size .subnav, -.no-touch .winkwink-nudgenudge .subnav, -.no-touch .account-signin .subnav { - min-width: 100%; - display: none; - -moz-transition: all 0s ease; - -o-transition: all 0s ease; - -webkit-transition: all 0s ease; - transition: all 0s ease; -} -.touch .adjust-font-size .subnav, -.touch .winkwink-nudgenudge .subnav, -.touch .account-signin .subnav { - top: 120%; - display: none; - opacity: 0; - -moz-transition: opacity 0.25s ease-in-out; - -o-transition: opacity 0.25s ease-in-out; - -webkit-transition: opacity 0.25s ease-in-out; - transition: opacity 0.25s ease-in-out; - -moz-box-shadow: 0 0.25em 0.75em rgba(0, 0, 0, 0.6); - -webkit-box-shadow: 0 0.25em 0.75em rgba(0, 0, 0, 0.6); - box-shadow: 0 0.25em 0.75em rgba(0, 0, 0, 0.6); -} -.touch .adjust-font-size .subnav:before, -.touch .winkwink-nudgenudge .subnav:before, -.touch .account-signin .subnav:before { - position: absolute; - content: ""; - width: 0; - height: 0; - border-color: transparent; - border-style: solid; - border-width: 0.75em; - top: -1.45em; - display: block; -} -.no-touch .adjust-font-size .element-1:hover .subnav, -.no-touch .adjust-font-size .element-1:focus .subnav, -.no-touch .adjust-font-size .element-2:hover .subnav, -.no-touch .adjust-font-size .element-2:focus .subnav, -.no-touch .adjust-font-size .element-3:hover .subnav, -.no-touch .adjust-font-size .element-3:focus .subnav, -.no-touch .adjust-font-size .element-4:hover .subnav, -.no-touch .adjust-font-size .element-4:focus .subnav, -.no-touch .winkwink-nudgenudge .element-1:hover .subnav, -.no-touch .winkwink-nudgenudge .element-1:focus .subnav, -.no-touch .winkwink-nudgenudge .element-2:hover .subnav, -.no-touch .winkwink-nudgenudge .element-2:focus .subnav, -.no-touch .winkwink-nudgenudge .element-3:hover .subnav, -.no-touch .winkwink-nudgenudge .element-3:focus .subnav, -.no-touch .winkwink-nudgenudge .element-4:hover .subnav, -.no-touch .winkwink-nudgenudge .element-4:focus .subnav, -.no-touch .account-signin .element-1:hover .subnav, -.no-touch .account-signin .element-1:focus .subnav, -.no-touch .account-signin .element-2:hover .subnav, -.no-touch .account-signin .element-2:focus .subnav, -.no-touch .account-signin .element-3:hover .subnav, -.no-touch .account-signin .element-3:focus .subnav, -.no-touch .account-signin .element-4:hover .subnav, -.no-touch .account-signin .element-4:focus .subnav { - left: 0; - display: initial; - -moz-transition-delay: 0.25s; - -o-transition-delay: 0.25s; - -webkit-transition-delay: 0.25s; - transition-delay: 0.25s; -} -.no-touch .adjust-font-size .element-5:hover .subnav, -.no-touch .adjust-font-size .element-5:focus .subnav, -.no-touch .adjust-font-size .element-6:hover .subnav, -.no-touch .adjust-font-size .element-6:focus .subnav, -.no-touch .adjust-font-size .element-7:hover .subnav, -.no-touch .adjust-font-size .element-7:focus .subnav, -.no-touch .adjust-font-size .element-8:hover .subnav, -.no-touch .adjust-font-size .element-8:focus .subnav, -.no-touch .adjust-font-size .last:hover .subnav, -.no-touch .adjust-font-size .last:focus .subnav, -.no-touch .winkwink-nudgenudge .element-5:hover .subnav, -.no-touch .winkwink-nudgenudge .element-5:focus .subnav, -.no-touch .winkwink-nudgenudge .element-6:hover .subnav, -.no-touch .winkwink-nudgenudge .element-6:focus .subnav, -.no-touch .winkwink-nudgenudge .element-7:hover .subnav, -.no-touch .winkwink-nudgenudge .element-7:focus .subnav, -.no-touch .winkwink-nudgenudge .element-8:hover .subnav, -.no-touch .winkwink-nudgenudge .element-8:focus .subnav, -.no-touch .winkwink-nudgenudge .last:hover .subnav, -.no-touch .winkwink-nudgenudge .last:focus .subnav, -.no-touch .account-signin .element-5:hover .subnav, -.no-touch .account-signin .element-5:focus .subnav, -.no-touch .account-signin .element-6:hover .subnav, -.no-touch .account-signin .element-6:focus .subnav, -.no-touch .account-signin .element-7:hover .subnav, -.no-touch .account-signin .element-7:focus .subnav, -.no-touch .account-signin .element-8:hover .subnav, -.no-touch .account-signin .element-8:focus .subnav, -.no-touch .account-signin .last:hover .subnav, -.no-touch .account-signin .last:focus .subnav { - right: 0; - display: initial; - -moz-transition-delay: 0.25s; - -o-transition-delay: 0.25s; - -webkit-transition-delay: 0.25s; - transition-delay: 0.25s; -} -.touch .adjust-font-size .element-1:hover .subnav, -.touch .adjust-font-size .element-1 .subnav.touched, -.touch .adjust-font-size .element-2:hover .subnav, -.touch .adjust-font-size .element-2 .subnav.touched, -.touch .adjust-font-size .element-3:hover .subnav, -.touch .adjust-font-size .element-3 .subnav.touched, -.touch .adjust-font-size .element-4:hover .subnav, -.touch .adjust-font-size .element-4 .subnav.touched, -.touch .winkwink-nudgenudge .element-1:hover .subnav, -.touch .winkwink-nudgenudge .element-1 .subnav.touched, -.touch .winkwink-nudgenudge .element-2:hover .subnav, -.touch .winkwink-nudgenudge .element-2 .subnav.touched, -.touch .winkwink-nudgenudge .element-3:hover .subnav, -.touch .winkwink-nudgenudge .element-3 .subnav.touched, -.touch .winkwink-nudgenudge .element-4:hover .subnav, -.touch .winkwink-nudgenudge .element-4 .subnav.touched, -.touch .account-signin .element-1:hover .subnav, -.touch .account-signin .element-1 .subnav.touched, -.touch .account-signin .element-2:hover .subnav, -.touch .account-signin .element-2 .subnav.touched, -.touch .account-signin .element-3:hover .subnav, -.touch .account-signin .element-3 .subnav.touched, -.touch .account-signin .element-4:hover .subnav, -.touch .account-signin .element-4 .subnav.touched { - display: block; - opacity: 1; - left: 0; -} -.touch .adjust-font-size .element-1 .subnav:before, -.touch .adjust-font-size .element-2 .subnav:before, -.touch .adjust-font-size .element-3 .subnav:before, -.touch .adjust-font-size .element-4 .subnav:before, -.touch .winkwink-nudgenudge .element-1 .subnav:before, -.touch .winkwink-nudgenudge .element-2 .subnav:before, -.touch .winkwink-nudgenudge .element-3 .subnav:before, -.touch .winkwink-nudgenudge .element-4 .subnav:before, -.touch .account-signin .element-1 .subnav:before, -.touch .account-signin .element-2 .subnav:before, -.touch .account-signin .element-3 .subnav:before, -.touch .account-signin .element-4 .subnav:before { - left: 1.5em; -} -.touch .adjust-font-size .element-5:hover .subnav, -.touch .adjust-font-size .element-5 .subnav.touched, -.touch .adjust-font-size .element-6:hover .subnav, -.touch .adjust-font-size .element-6 .subnav.touched, -.touch .adjust-font-size .element-7:hover .subnav, -.touch .adjust-font-size .element-7 .subnav.touched, -.touch .adjust-font-size .element-8:hover .subnav, -.touch .adjust-font-size .element-8 .subnav.touched, -.touch .adjust-font-size .last:hover .subnav, -.touch .adjust-font-size .last .subnav.touched, -.touch .winkwink-nudgenudge .element-5:hover .subnav, -.touch .winkwink-nudgenudge .element-5 .subnav.touched, -.touch .winkwink-nudgenudge .element-6:hover .subnav, -.touch .winkwink-nudgenudge .element-6 .subnav.touched, -.touch .winkwink-nudgenudge .element-7:hover .subnav, -.touch .winkwink-nudgenudge .element-7 .subnav.touched, -.touch .winkwink-nudgenudge .element-8:hover .subnav, -.touch .winkwink-nudgenudge .element-8 .subnav.touched, -.touch .winkwink-nudgenudge .last:hover .subnav, -.touch .winkwink-nudgenudge .last .subnav.touched, -.touch .account-signin .element-5:hover .subnav, -.touch .account-signin .element-5 .subnav.touched, -.touch .account-signin .element-6:hover .subnav, -.touch .account-signin .element-6 .subnav.touched, -.touch .account-signin .element-7:hover .subnav, -.touch .account-signin .element-7 .subnav.touched, -.touch .account-signin .element-8:hover .subnav, -.touch .account-signin .element-8 .subnav.touched, -.touch .account-signin .last:hover .subnav, -.touch .account-signin .last .subnav.touched { - display: block; - opacity: 1; - right: 0; -} -.touch .adjust-font-size .element-5 .subnav:before, -.touch .adjust-font-size .element-6 .subnav:before, -.touch .adjust-font-size .element-7 .subnav:before, -.touch .adjust-font-size .element-8 .subnav:before, -.touch .adjust-font-size .last .subnav:before, -.touch .winkwink-nudgenudge .element-5 .subnav:before, -.touch .winkwink-nudgenudge .element-6 .subnav:before, -.touch .winkwink-nudgenudge .element-7 .subnav:before, -.touch .winkwink-nudgenudge .element-8 .subnav:before, -.touch .winkwink-nudgenudge .last .subnav:before, -.touch .account-signin .element-5 .subnav:before, -.touch .account-signin .element-6 .subnav:before, -.touch .account-signin .element-7 .subnav:before, -.touch .account-signin .element-8 .subnav:before, -.touch .account-signin .last .subnav:before { - left: auto; - right: 1.5em; -} -.adjust-font-size .tier-2, -.winkwink-nudgenudge .tier-2, -.account-signin .tier-2 { - display: block; - min-width: 100%; -} -.adjust-font-size .tier-2 a, -.winkwink-nudgenudge .tier-2 a, -.account-signin .tier-2 a { - white-space: nowrap; -} -.adjust-font-size a, -.winkwink-nudgenudge a, -.account-signin a { - color: #bbb; - background-color: transparent; -} -.adjust-font-size .tier-1, -.winkwink-nudgenudge .tier-1, -.account-signin .tier-1 { - float: none; -} -.adjust-font-size .tier-1:hover > a, -.winkwink-nudgenudge .tier-1:hover > a, -.account-signin .tier-1:hover > a { - color: #555; - background-color: #caccce; -} -.adjust-font-size .subnav, -.winkwink-nudgenudge .subnav, -.account-signin .subnav { - background-color: #caccce; -} -.adjust-font-size .subnav a, -.winkwink-nudgenudge .subnav a, -.account-signin .subnav a { - color: #555; -} -.adjust-font-size .subnav a:hover, -.adjust-font-size .subnav a:focus, -.winkwink-nudgenudge .subnav a:hover, -.winkwink-nudgenudge .subnav a:focus, -.account-signin .subnav a:hover, -.account-signin .subnav a:focus { - color: #e6e8ea; - background-color: #999; -} -.touch .adjust-font-size .subnav a .tier-2, -.touch .winkwink-nudgenudge .subnav a .tier-2, -.touch .account-signin .subnav a .tier-2 { - padding-top: 0.75em; - padding-bottom: 0.6em; -} -.adjust-font-size .subnav .text-reset, -.winkwink-nudgenudge .subnav .text-reset, -.account-signin .subnav .text-reset { - color: #888; -} -.touch .adjust-font-size .subnav, -.touch .winkwink-nudgenudge .subnav, -.touch .account-signin .subnav { - top: 135%; - border: 3px solid #666; -} -.touch .adjust-font-size .subnav:before, -.touch .winkwink-nudgenudge .subnav:before, -.touch .account-signin .subnav:before { - top: -1.6em; - border-color: transparent transparent #666 transparent; -} -.adjust-font-size :hover .subnav, -.winkwink-nudgenudge :hover .subnav, -.account-signin :hover .subnav { - display: block; -} -.account-signin { - display: none; -} -.account-signin-authenticated { - display: inline-block; -} -.psf .account-signin, -.jobs .account-signin { - display: inline-block; -} -#site-map-link, -.adjust-font-size .tier-1 > a, -.winkwink-nudgenudge .tier-1 > a, -.account-signin .tier-1 > a { - padding: 1em 1em 0.875em; -} -.main-navigation { - display: none; - margin-bottom: 1px; -} -.header-banner { - clear: both; - margin: 0 1em; - position: relative; -} -.header-banner img { - display: block; - margin: 0 auto; -} -.header-banner p { - color: #e6e8ea; -} -.header-banner a:not(.button), -.header-banner a:not(.readmore) { - color: #ffd343; -} -.header-banner a:not(.button):hover, -.header-banner a:not(.button):focus, -.header-banner a:not(.readmore):hover, -.header-banner a:not(.readmore):focus { - color: #fff; -} -.home .slideshow { - margin: 0 auto; - max-width: 61.25em; - background: #1e2933; - -moz-box-shadow: inset 0 0 30px rgba(0, 0, 0, 0.6); - -webkit-box-shadow: inset 0 0 30px rgba(0, 0, 0, 0.6); - box-shadow: inset 0 0 30px rgba(0, 0, 0, 0.6); -} -.slide-code, -.slide-copy { - text-align: left; -} -.slide-code { - overflow: auto; - padding: 1.25em 1.5em; -} -.slide-code code { - display: inline-block; - color: #11a611; -} -.slide-code code .comment { - color: #666; -} -.slide-code code .output { - color: #ddd; -} -.js .launch-shell, -.no-js .launch-shell { - display: none; -} -.slide-copy { - background: #1c3b56; - padding: 1.25em 2.5em; -} -.slide-copy h1 { - color: #ffd343; - font-size: 1.3125em; - font-weight: 700; - font-family: "Source Sans Pro", Arial, sans-serif; -} -#dive-into-python .flex-control-paging { - position: absolute; - bottom: 0; - left: 50%; - padding: 0 0 1em; - margin-left: 0; - width: 50%; - max-width: 30.75em; -} -#dive-into-python .flex-control-paging a { - filter: alpha(opacity=70); - opacity: 0.7; -} -#dive-into-python .flex-control-paging a:hover, -#dive-into-python .flex-control-paging a:focus { - filter: progid:DXImageTransform.Microsoft.Alpha(enabled=false); - opacity: 1; -} -#dive-into-python .flex-control-paging .flex-active { - color: #ffd343 !important; - filter: progid:DXImageTransform.Microsoft.Alpha(enabled=false); - opacity: 1; -} -.introduction { - color: #caccce; - font-size: 1.25em; - text-align: left; - padding: 0.25em 0.5em; - margin-top: 0.875em; - margin-bottom: 0.875em; -} -.introduction p { - line-height: 1.4em; - margin-bottom: 0; -} -.introduction a, -.introduction a:link, -.introduction a:visited { - color: #ffd343; - text-decoration: underline; -} -.introduction a:hover, -.introduction a:focus, -.introduction a:link:hover, -.introduction a:link:focus, -.introduction a:visited:hover, -.introduction a:visited:focus { - color: #fff; -} -.introduction .breaker { - display: none; -} -.about-banner, -.download-for-current-os, -.documentation-banner, -.latest-blog-post, -.featured-event, -.jobs-intro { - text-align: left; -} -.call-to-action { - color: #ffd343; - font-size: 1.125em; - line-height: 1.25em; - margin-top: 0.4375em; - margin-bottom: 0.4375em; -} -.call-to-action a { - color: #ffd343; - border-bottom: 2px dotted #3776ab; - line-height: 1.35em; -} -.call-to-action a:hover, -.call-to-action a:focus { - color: #e6e8ea; -} -.content-wrapper { - padding: 0; - background-color: #f9f9f9; - *zoom: 1; - filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#FFFCFCFC',endColorstr='#FFF9F9F9'); - background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiNmY2ZjZmMiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iI2Y5ZjlmOSIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=="); - background-size: 100%; - background-image: -webkit-gradient( - linear, - 50% 0, - 50% 100%, - color-stop(10%, #fcfcfc), - color-stop(90%, #f9f9f9) - ); - background-image: -moz-linear-gradient(#fcfcfc 10%, #f9f9f9 90%); - background-image: -webkit-linear-gradient(#fcfcfc 10%, #f9f9f9 90%); - background-image: linear-gradient(#fcfcfc 10%, #f9f9f9 90%); -} -.content-wrapper .container { - padding: 0.25em; -} -.main-content { - padding-bottom: 1.75em; -} -.main-content > article { - margin-top: 1.3125em; - padding-bottom: 1.75em; -} -.page-title { - color: #666; - word-spacing: 0.15em; - font-size: 2em; -} -.fontface .page-title { - font-size: 2.3em; -} -.fontface .page-title span:before { - font-size: 0.875em; -} -.event-form .page-title { - margin-top: 0 !important; -} -.default-title { - word-spacing: 0.15em; -} -.text { - font-size: 1em; -} -.text .giga, -.text .mega, -.text .kilo { - color: #3776ab; -} -.sidebar-widget { - padding-bottom: 1.3125em; -} -.text h1, -.sidebar-widget h1 { - margin-top: 1em; - margin-bottom: 0.25em; -} -.text .default-title, -.text .page-title, -.sidebar-widget .default-title, -.sidebar-widget .page-title { - margin-top: 1.3125em; - margin-bottom: 0.875em; -} -.text p, -.text pre, -.text ul, -.text ol, -.text dl, -.text blockquote, -.text address, -.text form, -.text table, -.text figure, -.sidebar-widget p, -.sidebar-widget pre, -.sidebar-widget ul, -.sidebar-widget ol, -.sidebar-widget dl, -.sidebar-widget blockquote, -.sidebar-widget address, -.sidebar-widget form, -.sidebar-widget table, -.sidebar-widget figure { - margin-bottom: 1.3125em; - line-height: 1.875; -} -.text p, -.text dd, -.text blockquote, -.text address, -.sidebar-widget p, -.sidebar-widget dd, -.sidebar-widget blockquote, -.sidebar-widget address { - -webkit-hyphens: auto; - -moz-hyphens: auto; - -ms-hyphens: auto; - -o-hyphens: auto; - hyphens: auto; -} -.text p tt, -.text p var, -.text p code, -.text p kbd, -.text p abbr, -.text p acronym, -.text dd tt, -.text dd var, -.text dd code, -.text dd kbd, -.text dd abbr, -.text dd acronym, -.text blockquote tt, -.text blockquote var, -.text blockquote code, -.text blockquote kbd, -.text blockquote abbr, -.text blockquote acronym, -.text address tt, -.text address var, -.text address code, -.text address kbd, -.text address abbr, -.text address acronym, -.sidebar-widget p tt, -.sidebar-widget p var, -.sidebar-widget p code, -.sidebar-widget p kbd, -.sidebar-widget p abbr, -.sidebar-widget p acronym, -.sidebar-widget dd tt, -.sidebar-widget dd var, -.sidebar-widget dd code, -.sidebar-widget dd kbd, -.sidebar-widget dd abbr, -.sidebar-widget dd acronym, -.sidebar-widget blockquote tt, -.sidebar-widget blockquote var, -.sidebar-widget blockquote code, -.sidebar-widget blockquote kbd, -.sidebar-widget blockquote abbr, -.sidebar-widget blockquote acronym, -.sidebar-widget address tt, -.sidebar-widget address var, -.sidebar-widget address code, -.sidebar-widget address kbd, -.sidebar-widget address abbr, -.sidebar-widget address acronym { - -webkit-hyphens: none; - -moz-hyphens: none; - -ms-hyphens: none; - -o-hyphens: none; - hyphens: none; -} -.text li > ul, -.text li > ol, -.sidebar-widget li > ul, -.sidebar-widget li > ol { - margin-bottom: 0; -} -.text li, -.sidebar-widget li { - line-height: 1.65em; - margin: 0.2625em 0; -} -.text blockquote, -.sidebar-widget blockquote { - padding-left: 3em; - padding-right: 1em; -} -.text form, -.sidebar-widget form { - line-height: 1.625em; - margin-bottom: 1.3125em; -} -.text form button, -.text form input[type="submit"], -.sidebar-widget form button, -.sidebar-widget form input[type="submit"] { - font-size: 1.125em; - padding: 0.4em 1em 0.35em; -} -.text a:not(.button), -.sidebar-widget a:not(.button) { - display: inline; -} -.text nav a, -.text .menu a, -.text form ul a, -form .text ul a, -.text .errorlist a, -.text form label + ul a, -.text .sidebar-widget form label + ul a, -.sidebar-widget form .text label + ul a, -.text input[type="submit"], -.text input[type="reset"], -.text input[type="button"], -.text button, -.text .prompt, -.text .readmore:before, -.text .give-me-more a:before, -.give-me-more .text a:before, -.text nav a:hover, -.text .menu a:hover, -.text form ul a:hover, -form .text ul a:hover, -.text .errorlist a:hover, -.text form label + ul a:hover, -.text .sidebar-widget form label + ul a:hover, -.sidebar-widget form .text label + ul a:hover, -.text input[type="submit"]:hover, -.text input[type="reset"]:hover, -.text input[type="button"]:hover, -.text .prompt:hover, -.text .readmore:hover:before, -.text .give-me-more a:hover:before, -.give-me-more .text a:hover:before, -.text nav a:focus, -.text .menu a:focus, -.text form ul a:focus, -form .text ul a:focus, -.text .errorlist a:focus, -.text form label + ul a:focus, -.text .sidebar-widget form label + ul a:focus, -.sidebar-widget form .text label + ul a:focus, -.text input[type="submit"]:focus, -.text input[type="reset"]:focus, -.text input[type="button"]:focus, -.text .prompt:focus, -.text .readmore:focus:before, -.text .give-me-more a:focus:before, -.give-me-more .text a:focus:before, -.sidebar-widget nav a, -.sidebar-widget .menu a, -.sidebar-widget form ul a, -form .sidebar-widget ul a, -.sidebar-widget .errorlist a, -.sidebar-widget .text form label + ul a, -.text form .sidebar-widget label + ul a, -.sidebar-widget form label + ul a, -.sidebar-widget input[type="submit"], -.sidebar-widget input[type="reset"], -.sidebar-widget input[type="button"], -.sidebar-widget button, -.sidebar-widget .prompt, -.sidebar-widget .readmore:before, -.sidebar-widget .give-me-more a:before, -.give-me-more .sidebar-widget a:before, -.sidebar-widget nav a:hover, -.sidebar-widget .menu a:hover, -.sidebar-widget form ul a:hover, -form .sidebar-widget ul a:hover, -.sidebar-widget .errorlist a:hover, -.sidebar-widget .text form label + ul a:hover, -.text form .sidebar-widget label + ul a:hover, -.sidebar-widget form label + ul a:hover, -.sidebar-widget input[type="submit"]:hover, -.sidebar-widget input[type="reset"]:hover, -.sidebar-widget input[type="button"]:hover, -.sidebar-widget .prompt:hover, -.sidebar-widget .readmore:hover:before, -.sidebar-widget .give-me-more a:hover:before, -.give-me-more .sidebar-widget a:hover:before, -.sidebar-widget nav a:focus, -.sidebar-widget .menu a:focus, -.sidebar-widget form ul a:focus, -form .sidebar-widget ul a:focus, -.sidebar-widget .errorlist a:focus, -.sidebar-widget .text form label + ul a:focus, -.text form .sidebar-widget label + ul a:focus, -.sidebar-widget form label + ul a:focus, -.sidebar-widget input[type="submit"]:focus, -.sidebar-widget input[type="reset"]:focus, -.sidebar-widget input[type="button"]:focus, -.sidebar-widget .prompt:focus, -.sidebar-widget .readmore:focus:before, -.sidebar-widget .give-me-more a:focus:before, -.give-me-more .sidebar-widget a:focus:before { - border-bottom: 0; -} -.text figcaption, -.sidebar-widget figcaption { - font-style: italic; - font-size: 0.875em; -} -.text abbr[title], -.text dfn[title], -.sidebar-widget abbr[title], -.sidebar-widget dfn[title] { - border-bottom: 1px dotted #3776ab; -} -.text abbr[title], -.sidebar-widget abbr[title] { - font-size: 0.875em; - text-transform: uppercase; - letter-spacing: 0.125em; -} -.text var, -.sidebar-widget var { - color: #222; - font-size: 104%; - font-weight: 700; -} -.text code, -.text kbd, -.text samp, -.sidebar-widget code, -.sidebar-widget kbd, -.sidebar-widget samp { - display: inline-block; -} -.text code, -.text samp, -.sidebar-widget code, -.sidebar-widget samp { - border: 0; -} -.text samp, -.sidebar-widget samp { - border-bottom: 1px solid #caccce; - background-color: #e6e8ea; - padding: 0.125em 0.375em 0; - margin: 0 0.25em; -} -.text code, -.text kbd, -.sidebar-widget code, -.sidebar-widget kbd { - padding: 0.125em 0.375em 0; - margin: 0 -0.0625em; - background: #e6e8ea; - background: rgba(230, 232, 234, 0.5); - -moz-box-shadow: 0 0 0.5em rgba(0, 0, 0, 0.1) inset; - -webkit-box-shadow: 0 0 0.5em rgba(0, 0, 0, 0.1) inset; - box-shadow: 0 0 0.5em rgba(0, 0, 0, 0.1) inset; - -moz-border-radius: 6px; - -webkit-border-radius: 6px; - border-radius: 6px; -} -.text pre, -.sidebar-widget pre { - padding: 0.5em; - border-left: 5px solid #11a611; - background: #e6e8ea; - -moz-box-shadow: 0 0 0.5em rgba(0, 0, 0, 0.1) inset; - -webkit-box-shadow: 0 0 0.5em rgba(0, 0, 0, 0.1) inset; - box-shadow: 0 0 0.5em rgba(0, 0, 0, 0.1) inset; -} -.text pre code, -.sidebar-widget pre code { - display: block; - padding: 0; - margin: 0; - -moz-box-shadow: 0; - -webkit-box-shadow: 0; - box-shadow: 0; - -moz-border-radius: 0; - -webkit-border-radius: 0; - border-radius: 0; -} -.text s, -.text strike, -.text del, -.sidebar-widget s, -.sidebar-widget strike, -.sidebar-widget del { - color: #999; -} -table caption { - caption-side: top; - color: #444; - font-size: 1.125em; - text-align: left; - margin-bottom: 1.75em; -} -table thead, -table tfoot { - border-bottom: 1px solid #ddd; -} -table tr { - background-color: #f6f6f6; -} -table tr th { - background-color: #f0f0f0; -} -table tr:nth-of-type(even), -table tr.even { - background-color: #f0f0f0; -} -table th, -table td { - padding: 0.25em 0.5em 0.2em; - border-left: 2px solid #fff; -} -table th:first-child, -table td:first-child { - border-left: none; -} -table tfoot { - border-top: 1px solid #ddd; -} -.row-title { - border-top: 5px solid #d4dbe1; - padding: 0.75em 1em 0.5em; -} -.small-widget, -.download-list-widget, -.active-release-list-widget, -.most-recent-events, -.triple-widget, -.most-recent-posts, -.medium-widget, -.sidebar-widget { - border-top: 5px solid #e6e8ea; - padding: 1.25em; -} -.small-widget h4, -.download-list-widget h4, -.active-release-list-widget h4, -.most-recent-events h4, -.triple-widget h4, -.most-recent-posts h4, -.medium-widget h4, -.sidebar-widget h4 { - border-top: 1px solid #e6e8ea; - margin-top: 1.75em; - padding-top: 0.5em; -} -.small-widget p, -.download-list-widget p, -.active-release-list-widget p, -.most-recent-events p, -.triple-widget p, -.most-recent-posts p, -.medium-widget p, -.sidebar-widget p, -.small-widget ul, -.download-list-widget ul, -.active-release-list-widget ul, -.most-recent-events ul, -.triple-widget ul, -.most-recent-posts ul, -.medium-widget ul, -.sidebar-widget ul { - margin-bottom: 0.875em; -} -.small-widget p:last-child, -.download-list-widget p:last-child, -.active-release-list-widget p:last-child, -.most-recent-events p:last-child, -.triple-widget p:last-child, -.most-recent-posts p:last-child, -.medium-widget p:last-child, -.sidebar-widget p:last-child, -.small-widget ul:last-child, -.download-list-widget ul:last-child, -.active-release-list-widget ul:last-child, -.most-recent-events ul:last-child, -.triple-widget ul:last-child, -.most-recent-posts ul:last-child, -.medium-widget ul:last-child, -.sidebar-widget ul:last-child { - margin-bottom: 0; -} -.small-widget li > a, -.download-list-widget li > a, -.active-release-list-widget li > a, -.most-recent-events li > a, -.triple-widget li > a, -.most-recent-posts li > a, -.medium-widget li > a, -.sidebar-widget li > a { - display: inline-block; -} -.widget-title, -.listing-company { - color: #444; - line-height: 1.25em; - margin: 0 0 0.1em; - font-family: Flux, "Source Sans Pro", Arial, sans-serif; - font-size: 1.3125em; -} -.fontface .widget-title, -.fontface .listing-company { - font-size: 1.50938em; -} -.fontface .widget-title span:before, -.fontface .listing-company span:before { - font-size: 0.875em; -} -.widget-title .prompt, -.widget-title .readmore:before, -.widget-title .give-me-more a:before, -.give-me-more .widget-title a:before, -.listing-company .prompt, -.listing-company .readmore:before, -.listing-company .give-me-more a:before, -.give-me-more .listing-company a:before { - display: none; -} -.widget-title > span, -.listing-company > span { - margin-right: 0.25em; -} -.widget-title > span:before, -.listing-company > span:before { - color: #999; -} -.python .small-widget, -.python .download-list-widget, -.python .active-release-list-widget, -.python .most-recent-events, -.python .triple-widget, -.python .most-recent-posts, -.python .medium-widget, -.python .sidebar-widget { - border-top: 4px solid #75a8d3; -} -.psf-home .small-widget, -.psf-home .download-list-widget, -.psf-home .active-release-list-widget, -.psf-home .most-recent-events, -.psf-home .triple-widget, -.psf-home .most-recent-posts, -.psf-home .medium-widget, -.psf-home .sidebar-widget { - border-top: 5px solid #caccce; -} -.docs .small-widget, -.docs .download-list-widget, -.docs .active-release-list-widget, -.docs .most-recent-events, -.docs .triple-widget, -.docs .most-recent-posts, -.docs .medium-widget, -.docs .sidebar-widget { - border-top: 5px solid #ffd343; -} -.pypl .small-widget, -.pypl .download-list-widget, -.pypl .active-release-list-widget, -.pypl .most-recent-events, -.pypl .triple-widget, -.pypl .most-recent-posts, -.pypl .medium-widget, -.pypl .sidebar-widget { - border-top: 5px solid #82b043; -} -.jobs .small-widget, -.jobs .download-list-widget, -.jobs .active-release-list-widget, -.jobs .most-recent-events, -.jobs .triple-widget, -.jobs .most-recent-posts, -.jobs .medium-widget, -.jobs .sidebar-widget { - border-top: 5px solid #c9abcd; -} -.shop .small-widget, -.shop .download-list-widget, -.shop .active-release-list-widget, -.shop .most-recent-events, -.shop .triple-widget, -.shop .most-recent-posts, -.shop .medium-widget, -.shop .sidebar-widget { - border-top: 5px solid #b55863; -} -.python .widget-title > span:before, -.python .listing-company > span:before { - color: #3776ab; -} -.psf .widget-title > span:before, -.psf .listing-company > span:before { - color: #78797a; -} -.docs .widget-title > span:before, -.docs .listing-company > span:before { - color: #ffd343; -} -.pypl .widget-title > span:before, -.pypl .listing-company > span:before { - color: #82b043; -} -.jobs .widget-title > span:before, -.jobs .listing-company > span:before { - color: #a06ba7; -} -.shop .widget-title > span:before, -.shop .listing-company > span:before { - color: #b55863; -} -.download-widget p:last-child a { - white-space: nowrap; -} -.time-posted { - display: block; - font-size: 0.875em; - font-style: italic; - margin-bottom: 0.75em; -} -.blog-name { - display: block; - font-weight: 700; - font-family: "Source Sans Pro", Arial, sans-serif; - letter-spacing: 0.01em; -} -.success-stories-widget blockquote { - color: #666; - background-color: #ffe590; - padding: 0.7em 1em 0.875em; - margin-bottom: 0.4375em; - font-size: 1em; - line-height: 1.75em; - background-color: #ffdf76; - *zoom: 1; - filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#FFFFE590',endColorstr='#FFFFDF76'); - background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiNmZmU1OTAiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iI2ZmZGY3NiIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=="); - background-size: 100%; - background-image: -webkit-gradient( - linear, - 50% 0, - 50% 100%, - color-stop(10%, #ffe590), - color-stop(90%, #ffdf76) - ); - background-image: -moz-linear-gradient(#ffe590 10%, #ffdf76 90%); - background-image: -webkit-linear-gradient(#ffe590 10%, #ffdf76 90%); - background-image: linear-gradient(#ffe590 10%, #ffdf76 90%); - -moz-border-radius: 6px; - -webkit-border-radius: 6px; - border-radius: 6px; -} -.success-stories-widget blockquote:after { - position: absolute; - content: ""; - width: 0; - height: 0; - border-color: transparent; - border-style: solid; - border-width: 1.5em; - left: 20%; - bottom: -2.875em; - border-top-color: #ffdf76; -} -.success-stories-widget blockquote a { - color: #666; -} -.success-stories-widget blockquote a:hover, -.success-stories-widget blockquote a:focus, -.success-stories-widget blockquote a:active { - color: #3776ab; -} -.success-stories-widget .quote-from td { - padding: 0.5em; - vertical-align: middle; -} -.success-stories-widget .quote-from img { - max-height: 5em; -} -.success-stories-widget .quote-from p { - font-size: 0.875em; -} -.applications-widget { - padding-left: 0.75em; -} -.applications-widget ul { - border-top: 1px solid #caccce; -} -.applications-widget li { - padding: 0.5em 0 0.4em; - border-bottom: 1px solid #caccce; -} -.shrubbery { - position: relative; -} -.shrubbery .give-me-more { - color: #caccce; - display: none; - position: absolute; - top: 0.25em; - right: 0.25em; -} -.shrubbery .give-me-more a { - color: #999; -} -.shrubbery .give-me-more a:hover, -.shrubbery .give-me-more a:active { - color: #666; -} -.draft-preview { - color: #b55863; - font-weight: 700; - font-family: "Source Sans Pro", Arial, sans-serif; -} -.pep-widget { - margin-bottom: 1.3125em; -} -.pep-widget .widget-title { - color: #737373; - margin-bottom: 0.35em; - font-size: 1.125em; -} -.fontface .pep-widget .widget-title { - font-size: 1.29375em; -} -.fontface .pep-widget .widget-title span:before { - font-size: 0.875em; -} -.pep-widget .widget-title a { - color: #3776ab; -} -.pep-widget .widget-title a:hover, -.pep-widget .widget-title a:active { - color: #1f3b47; -} -.pep-widget .pep-number { - color: #666; - font-weight: 700; - font-family: "Source Sans Pro", Arial, sans-serif; - display: inline-block; - width: 3em; -} -.pep-list { - border-top: 1px solid #caccce; - line-height: 1.2em; - margin: 0; -} -.pep-list li { - display: block; - line-height: 1.35em; -} -.pep-list li a { - display: block; - color: #3776ab; - background-color: #f2f4f6; - border-bottom: 1px solid #e6eaee; - padding: 0.6em 0.75em 0.5em; -} -.pep-list li a:hover, -.pep-list li a:focus, -.pep-list li a:active { - color: #222; - background-color: #fefefe; -} -.rss-link { - line-height: 1em; -} -.rss-link span:before { - color: #cc9547; -} -.pep-list-header { - font-weight: 700; - font-family: "Source Sans Pro", Arial, sans-serif; - display: none; -} -.pep-index-list { - margin-bottom: 2.625em; -} -.pep-index-list .label { - font-weight: 700; - font-family: "Source Sans Pro", Arial, sans-serif; - display: inline-block; - width: 20%; -} -.pep-index-list li { - background-color: #f2f4f6; - border-bottom: 1px solid #caccce; -} -.pep-index-list a { - display: inline-block; - color: #3776ab; -} -.pep-index-list a:hover, -.pep-index-list a:focus, -.pep-index-list a:active { - color: #222; -} -.pep-type, -.pep-num, -.pep-title, -.pep-owner { - padding: 0.5em 0.5em 0.4em; - border-bottom: 1px solid #e3e7ec; -} -.footnote .label { - width: 4em; -} -.info-key dt, -.info-key dd { - display: block; - float: left; - padding: 0.5em 0.5em 0.4em; -} -.info-key dt { - width: 25%; -} -.info-key dd { - width: 75%; - border-bottom: 1px solid #e6e8ea; -} -.pep-owner-header { - margin: 0 -0.5em; - overflow: hidden; - *zoom: 1; -} -.pep-owner-header .label { - font-weight: 700; - font-family: "Source Sans Pro", Arial, sans-serif; - float: left; - width: 50%; - padding: 0.25em 0.5em 0.2em; -} -.pep-owner-list li { - background-color: #f2f4f6; - border-bottom: 1px solid #caccce; - overflow: hidden; - *zoom: 1; -} -.pep-owner-list li:hover { - background-color: #fefefe; -} -.pep-owner-list .owner-name, -.pep-owner-list .owner-email { - float: left; - width: 50%; - padding: 0.5em 0.5em 0.4em; -} -.featured-success-story { - padding: 1.3125em 0; - background: center -230px no-repeat url(../img/success-glow2.png?1576869008) transparent; -} -.featured-success-story img { - padding: 10px 30px; -} -.featured-success-story .success-quote { - color: #ffd343; - font-size: 1.625em; - line-height: 1.5; - position: static; - text-shadow: 0 0 4px rgba(0, 0, 0, 0.5); -} -.featured-success-story .success-quote:before, -.featured-success-story .success-quote:after { - color: #4f90c6; - font-style: normal; - font-size: 2em; - line-height: 0; - vertical-align: text-bottom; - position: static; -} -.featured-success-story .success-quote:before { - content: "“"; - top: auto; - left: auto; - margin-left: -0.2em; -} -.featured-success-story .success-quote:after { - content: "”"; - bottom: auto; - right: auto; - margin-right: -0.2em; -} -a.activity-feed { - border-bottom: 0; - font-size: 0.75em; -} -a.activity-feed span { - margin-right: 0.25em; -} -p.quote-by { - color: #e6e8ea; - margin-bottom: 0; -} -p.quote-by-organization { - color: #e6e8ea; -} -.newest-success-stories { - padding-top: 1.3125em; -} -.newest-success-stories .widget-title { - position: relative; -} -.story-header { - background-color: #f2f4f6; - margin: -1.3em 0 0; - overflow: hidden; - max-height: 24em; - border-bottom: 3px solid #ffd343; -} -.story-header img { - display: block; - margin: 0 auto; - min-width: 100%; -} -.welcome-message { - font-family: "Source Sans Pro", Arial, sans-serif; - font-size: 1.125em; - color: #ffc710; - margin-top: 0; - margin-bottom: 0.875em; -} -.fontface .welcome-message { - font-size: 1.125em; -} -.latest-blog-post .date-posted, -.latest-blog-post .event-date, -.featured-event .date-posted, -.featured-event .event-date { - color: #a8a8a8; -} -.latest-blog-post p.excerpt, -.featured-event p.excerpt { - max-width: none; -} -.latest-blog-post .readmore, -.featured-event .readmore { - color: #ffd343; -} -.latest-blog-post .readmore:hover, -.latest-blog-post .readmore:focus, -.featured-event .readmore:hover, -.featured-event .readmore:focus { - color: #fff; -} -.most-recent-posts li time { - position: relative; -} -.just-missed { - color: #3776ab; - margin-top: 1.3125em; -} -.list-recent-events, -.list-recent-posts { - border-top: 1px solid #ddd; -} -.list-recent-events li, -.list-recent-posts li { - position: relative; - border-bottom: 1px solid #ddd; - padding: 0 0 0.75em; -} -.list-recent-events li .date-start, -.list-recent-events li .date-end, -.list-recent-events li .single-date, -.list-recent-events li .time-start, -.list-recent-events li .time-end, -.list-recent-events li .year, -.list-recent-posts li .date-start, -.list-recent-posts li .date-end, -.list-recent-posts li .single-date, -.list-recent-posts li .time-start, -.list-recent-posts li .time-end, -.list-recent-posts li .year { - position: relative; - top: 0; -} -.list-recent-events .event-title, -.list-recent-posts .event-title { - font-size: 1.25em; - line-height: 1.3em; - margin-top: 0.4375em; -} -.single-event-date { - margin-top: 0.75em; - margin-bottom: 1.25em; - padding: 0.5em 0.75em; -} -.event-description { - padding: 1.3125em 0; -} -.more-by-location { - margin-bottom: 0; -} -.community-success-stories blockquote { - padding: 0; - color: #666; - line-height: 1.5; -} -.community-success-stories blockquote:before { - content: ""; -} -.python-weekly { - background-color: #f2f4f6; - -moz-border-radius: 0 0 8px 8px; - -webkit-border-radius: 0; - border-radius: 0 0 8px 8px; - padding: 0.75em 1em; -} -.twitter-stream li { - background-color: #f2f4f6; - line-height: 1.3; - padding: 0.5em; - margin-bottom: 0.25em; -} -.twitter-stream li .view-on-twitter { - font-weight: 700; - font-family: "Source Sans Pro", Arial, sans-serif; - font-size: 0.85714em; -} -.twitteruser { - font-weight: 700; - font-family: "Source Sans Pro", Arial, sans-serif; -} -.twittermention { - color: #3776ab; -} -.mapped-events { - border-top: 3px solid #e6e8ea; -} -.mapped-events .medium-widget { - border-top: 0; -} -.tag-wrapper { - display: block; -} -.tag-wrapper .tag { - white-space: nowrap; - color: #666; - font-size: 0.875em; - vertical-align: baseline; - padding: 0.2em 0.4em 0.1em; - background-color: #e6e8ea; - border-top: 1px solid #f2f4f6; - border-bottom: 1px solid #caccce; -} -.tag-wrapper .tag:hover, -.tag-wrapper .tag:focus { - color: #444; - background-color: #d0d4d7; - border-top: 1px solid #dae0e5; - border-bottom: 1px solid #b5b8ba; -} -.git-avatar, -.git-repo { - display: inline-block; - vertical-align: bottom; -} -.git-avatar { - margin-right: 0.5em; -} -.git-repo { - padding-bottom: 0.25em; -} -.list-row-headings { - font-weight: 700; - font-family: "Source Sans Pro", Arial, sans-serif; - padding: 0.5em 0.5em 0.4em 0.75em; - margin-right: 1.25em; -} -.list-row-container { - border: 1px solid #caccce; -} -.list-row-container li { - padding: 0.5em 0.5em 0.4em 0.75em; - margin-right: 0; -} -.list-row-container li:nth-child(odd) { - background-color: #f2f4f6; -} -.pagination, -.previous-next { - display: block; - width: 100%; - text-align: center; - padding-top: 1.3125em; -} -.pagination li { - line-height: 2; - display: -moz-inline-stack; - display: inline-block; - vertical-align: baseline; -} -.lt-ie8 .pagination li { - vertical-align: auto; - zoom: 1; - display: inline; -} -.pagination a:hover, -.pagination a:focus { - color: #333; - background-color: #ffd343; -} -.pagination a.active { - color: #e6e8ea; - background-color: #3776ab; -} -.pagination a.disabled, -.pagination a.disabled:hover, -.pagination a.disabled:focus { - color: #caccce; - background-color: transparent; -} -.pagination .previous a, -.pagination .next a, -.pagination .previous a:hover, -.pagination .next a:hover, -.pagination .previous a:focus, -.pagination .next a:focus { - border: 0; -} -.previous-next .prev-button, -.previous-next .next-button { - display: block; - padding: 0.5em 0.75em 0.4em; - margin-bottom: 0.875em; -} -.previous-next .prev-button:not(.disabled):hover, -.previous-next .prev-button:not(.disabled):focus, -.previous-next .next-button:not(.disabled):hover, -.previous-next .next-button:not(.disabled):focus { - color: #333; - background-color: #ffd343; -} -.previous-next .prev-button-text, -.previous-next .next-button-text { - display: block; - border-bottom: 1px solid #caccce; - padding-bottom: 0.5em; -} -.previous-next .prevnext-description { - display: block; - padding-top: 0.5em; -} -.previous-next .disabled .prev-button-text, -.previous-next .disabled .next-button-text { - color: #caccce; - border-bottom: 0; -} -.previous-next .icon-arrow-right, -.previous-next .icon-arrow-left { - vertical-align: bottom; -} -.single-event .previous-next { - margin-top: 1.3125em; - border-top: 1px solid #caccce; -} -.release-number, -.release-date, -.release-download, -.release-enhancements { - display: block; -} -.release-number { - font-weight: 700; - font-family: "Source Sans Pro", Arial, sans-serif; -} -.release-version, -.release-status, -.release-start, -.release-end, -.release-pep { - display: block; -} -.release-version { - font-weight: 700; - font-family: "Source Sans Pro", Arial, sans-serif; -} -.active-release-list-widget .list-row-headings, -.active-release-list-widget .list-row-container li { - font-size: 0.875em; -} -.active-release-list-widget .list-row-container { - margin-bottom: 0.5em; -} -.download-list-widget .list-row-headings, -.download-list-widget .list-row-container li { - font-size: 0.875em; -} -.download-list-widget .list-row-container { - margin-bottom: 0.5em; -} -.no-touch .download-list-widget .list-row-container { - height: 16.75em; - overflow-y: scroll; -} -.main-content .psf-widget a:not(.button), -.main-content .python-needs-you-widget a:not(.button) { - color: #ffd343; -} -.main-content .psf-widget a:not(.button):hover, -.main-content .psf-widget a:not(.button):focus, -.main-content .python-needs-you-widget a:not(.button):hover, -.main-content .python-needs-you-widget a:not(.button):focus { - color: #fff1c3; -} -.psf-widget .widget-title, -.psf-widget .readmore, -.psf-widget .readmore:before, -.python-needs-you-widget .widget-title, -.python-needs-you-widget .readmore, -.python-needs-you-widget .readmore:before { - color: #ffd343; -} -.psf-widget .widget-title:hover, -.psf-widget .widget-title:focus, -.psf-widget .readmore:hover, -.psf-widget .readmore:focus, -.psf-widget .readmore:before:hover, -.psf-widget .readmore:before:focus, -.python-needs-you-widget .widget-title:hover, -.python-needs-you-widget .widget-title:focus, -.python-needs-you-widget .readmore:hover, -.python-needs-you-widget .readmore:focus, -.python-needs-you-widget .readmore:before:hover, -.python-needs-you-widget .readmore:before:focus { - color: #fff; -} -.psf-widget p, -.python-needs-you-widget p { - color: #caccce; -} -.psf-widget .click-these, -.python-needs-you-widget .click-these { - margin-bottom: 0; -} -.user-feedback { - padding: 0.75em 1em 0.65em; - margin-bottom: 1.3125em; - -moz-border-radius: 6px; - -webkit-border-radius: 6px; - border-radius: 6px; -} -.user-feedback p { - margin-bottom: 0; -} -.user-feedback a { - text-decoration: underline; -} -.user-feedback a:hover, -.user-feedback a:focus { - color: #222; -} -.level-general { - background-color: #e9f1f8; - border: 1px solid #c2d9ec; -} -.level-notice { - background-color: #fff7dc; - border: 2px solid #ffd343; -} -.level-notice span { - color: #dca900; -} -.level-error { - background-color: #ecd4d7; - border: 2px solid #b55863; -} -.level-error span { - color: #b55863; -} -.level-success { - background-color: #d6e7bf; - border: 2px solid #82b043; -} -.level-success span { - color: #82b043; - margin-right: 0.5em; -} -.left-sidebar .sidebar-widget { - margin-bottom: 0.875em; -} -.left-sidebar .twitter-widget { - padding: 0; -} -.left-sidebar .twtr-doc { - padding: 0.75em; -} -.jobs-form p { - padding: 0 0.3125em; -} -.jobs-form .required { - background-color: #f8f0f1; - padding-top: 0.625em; -} -.list-recent-jobs li { - padding: 0.875em 0.5em; -} -.listing-company .listing-new { - display: inline-block; - color: #fff; - background-color: #b55863; - font-size: 0.58333em; - text-transform: uppercase; - letter-spacing: 0.0625em; - padding: 0.45em 0.5em 0; - margin-right: 0.25em; -} -.listing-company .listing-removed { - display: inline-block; - color: #fff; - background-color: #666; - font-size: 0.58333em; - text-transform: uppercase; - letter-spacing: 0.0625em; - padding: 0.45em 0.5em 0; - margin-right: 0.25em; -} -.listing-company .listing-location a { - color: #999; -} -.listing-company .listing-location a:hover, -.listing-company .listing-location a:focus { - color: #3776ab; -} -.listing-company-category, -.listing-job-type, -.listing-posted { - clear: both; - display: block; -} -.listing-company .company-name { - font-size: 125%; -} -.job-post-meta { - clear: both; - border: 1px solid #caccce; - padding: 0.875em 0.5em; - overflow: hidden; - *zoom: 1; -} -.job-post-meta span { - display: block; -} -.job-post-meta .listing-actions { - border-top: 1px solid #caccce; - clear: both; - padding-top: 1.25em; - text-align: right; -} -.job-tags { - margin-bottom: 0; -} -.breadcrumbs { - padding: 0.5em 0; - border-bottom: 1px solid #caccce; -} -.breadcrumbs li { - display: -moz-inline-stack; - display: inline-block; - vertical-align: baseline; -} -.lt-ie8 .breadcrumbs li { - vertical-align: auto; - zoom: 1; - display: inline; -} -.breadcrumbs .prompt, -.breadcrumbs .readmore:before, -.breadcrumbs .give-me-more a:before, -.give-me-more .breadcrumbs a:before { - margin-left: 0.5em; -} -.section-navigation { - border-top: 3px solid #75a8d3; - background-color: #e1ecf5; - padding: 0.875em 0.75em 0.875em; -} -.section-navigation h2:first-child { - margin-top: 0.65625em; -} -.section-navigation h3:first-child { - margin-top: 0.65625em; -} -.section-nav a { - display: block; - padding: 0.3em 0 0.2em; -} -.psf-sidebar-widget { - color: #f2f4f6; - background-color: #3776ab; - *zoom: 1; - filter: progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr='#FF2B5B84',endColorstr='#FF3776AB'); - background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiMyYjViODQiLz48c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iIzM3NzZhYiIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=="); - background-size: 100%; - background-image: -webkit-gradient( - linear, - 50% 0, - 50% 100%, - color-stop(10%, #2b5b84), - color-stop(90%, #3776ab) - ); - background-image: -moz-linear-gradient(#2b5b84 10%, #3776ab 90%); - background-image: -webkit-linear-gradient(#2b5b84 10%, #3776ab 90%); - background-image: linear-gradient(#2b5b84 10%, #3776ab 90%); -} -.psf-sidebar-widget .widget-title { - color: #ffd343; - margin-top: 0.4375em; -} -.psf-sidebar-widget .widget-title a { - color: #ffd343; -} -.psf-sidebar-widget .widget-title a:hover, -.psf-sidebar-widget .widget-title a:focus { - color: #fff; -} -.user-profile-controls { - border-bottom: 1px solid #caccce; - margin-bottom: 2em; -} -.user-profile-controls li { - display: -moz-inline-stack; - display: inline-block; - vertical-align: baseline; - margin-right: 0.75em; -} -.lt-ie8 .user-profile-controls li { - vertical-align: auto; - zoom: 1; - display: inline; -} -.user-profile-controls + .return-link { - margin-top: -1.3125em; -} -.return-link { - padding-bottom: 2.1875em; -} -.active-user-list .user-name, -.active-user-list .user-location, -.active-user-list .user-psfmember-status { - display: inline-block; - vertical-align: top; -} -.active-user-list .user-name { - width: 25%; -} -.active-user-list .user-location { - width: 40%; -} -.active-user-list .user-psfmember-status { - width: 25%; -} -.profile-label { - color: #999; -} -.psf-codeofconduct { - font-size: 0.875em; - padding: 0.5em 1em; - margin-bottom: 1em; - background-color: #fff; - -moz-box-shadow: 0.25em 0.25em 0.75em rgba(0, 0, 0, 0.15); - -webkit-box-shadow: 0.25em 0.25em 0.75em rgba(0, 0, 0, 0.15); - box-shadow: 0.25em 0.25em 0.75em rgba(0, 0, 0, 0.15); -} -.horizontal-menu { - padding-bottom: 1.3125em; -} -.horizontal-menu ul, -.horizontal-menu ol { - list-style: none; - margin-left: 0; -} -.horizontal-menu li { - margin-right: 1em; - display: -moz-inline-stack; - display: inline-block; - vertical-align: baseline; -} -.lt-ie8 .horizontal-menu li { - vertical-align: auto; - zoom: 1; - display: inline; -} -.main-footer .jump-link, -.sitemap a, -.footer-links a { - display: block; - text-align: center; - padding: 0.5em 0.75em 0.4em; -} -.main-footer { - clear: both; - color: #666; - background-color: #e6e8ea; - border-top: 1px solid #d8dbde; -} -.main-footer .container { - padding: 0 0.75em 0.75em; -} -.main-footer a { - color: #666; -} -.main-footer a:hover, -.main-footer a:focus { - color: #444; -} -.main-footer .jump-link { - background-color: #e0e3e5; -} -.main-footer a.jump-link { - margin: 0.75em 0; - border-top: 1px solid #e6e8ea; - border-bottom: 1px solid #dbdee1; -} -.main-footer a.jump-link:hover, -.main-footer a.jump-link:focus { - background-color: #dbdee1; - border-top: 1px solid #e0e3e5; - border-bottom: 1px solid #d5d9dc; -} -.sitemap { - padding-bottom: 0.5em; -} -.sitemap .tier-1 { - margin-bottom: 1.3125em; -} -.sitemap .tier-1 > a { - color: #3776ab; - padding: 0.4em 0.5em 0.3em; - font-weight: 700; - font-family: Flux, "Source Sans Pro", Arial, sans-serif; - font-size: 1.25em; - margin-top: 0.875em; - margin-bottom: 0; -} -.sitemap .tier-1 > a:hover, -.sitemap .tier-1 > a:focus { - color: #222; -} -.sitemap .subnav { - font-size: 1em; - margin-bottom: 0; - border-top: 1px solid #d5d6d8; - border-bottom: 1px solid #f7f7f8; -} -.sitemap .subnav li { - border-top: 1px solid #f7f7f8; - border-bottom: 1px solid #d5d6d8; -} -.sitemap .subnav a:hover, -.sitemap .subnav a:focus { - background-color: #ecedef; -} -.site-base { - border-top: 1px solid #111; -} -.site-base .container { - padding: 1em; -} -.footer-links { - margin-bottom: 0.5em; -} -.footer-links a { - color: #89b4d9; - font-weight: 700; - font-family: Flux, "Source Sans Pro", Arial, sans-serif; - font-size: 1.125em; -} -.fontface .footer-links a { - font-size: 1.29375em; -} -.fontface .footer-links a span:before { - font-size: 0.875em; -} -.footer-links a:hover, -.footer-links a:focus { - color: #fff7dc; - text-shadow: 0 0 5px rgba(255, 211, 67, 0.2); -} -.copyright { - clear: both; - color: #75a8d3; - font-size: 0.75em; - text-align: center; - margin-bottom: 0; -} -.copyright a { - border-bottom: 1px dotted #4f90c6; - color: #75a8d3; -} -.copyright a:hover, -.copyright a:focus { - color: #fff; - text-decoration: none; -} -#python-status-indicator { - border-radius: 99px; - display: inline-block; - height: 12px; - width: 12px; -} -.python-status-indicator-none { - background-color: #008000; -} -.python-status-indicator-minor { - background-color: #ff0; -} -.python-status-indicator-major { - background-color: #ffa500; -} -.python-status-indicator-critical { - background-color: #f00; -} -.python-status-indicator-default { - background-color: #808080; -} -div.note { - background-color: #eee; - border: 1px solid #ccc; - padding: 0.3125em 0.625em; - margin-bottom: 1.5625em; -} -div.note > p { - margin-bottom: 0; -} -p.admonition-title { - font-weight: bold; -} -p.admonition-title:after { - content: ":"; -} -div.warning, -form.deletion-form { - background-color: #ffe4e4; - border: 1px solid #f66; - padding: 0.3125em 0.625em; - margin-bottom: 1.5625em; -} -div.warning > p, -form.deletion-form > p { - margin-bottom: 0; -} -form.deletion-form { - border-radius: 0.625em; - padding: 0.9375em; -} -form.deletion-form button[type="submit"] { - margin-top: 0.625em; -} -form.deletion-form label { - color: #b55863; -} -div.sidebar { - margin: 0 0 0.5em 1em; - border: 1px solid #ddb; - padding: 0.4375em 0.4375em 0 0.4375em; - background-color: #ffe; - width: 40%; - float: right; -} -div.sidebar > p.sidebar-title { - font-size: 1em; - font-weight: bold; - margin-top: 0; -} -div.sidebar > p { - font-size: 0.9375em; - margin-top: 0.625em; - margin-bottom: 0; -} -img.align-right { - float: right; - margin-left: 1.25em; -} -span.highlighted { - background-color: yellow; -} -.text .flex-slideshow ul, -.text .flex-slideshow ol { - margin-bottom: 0; -} -.generatedcontent .text .flex-slideshow ul li:before { - content: ""; - display: none; -} -.loading .flex-slideshow { - opacity: 0; -} -.flex-slideshow { - position: relative; -} -.flex-slideshow .slides { - *zoom: 1; -} -.flex-slideshow .slides:after { - content: ""; - display: table; - clear: both; -} -.flex-slideshow .slides > li { - display: none; - -webkit-backface-visibility: hidden; -} -* html .flex-slideshow .slides { - height: 1%; -} -.no-js .flex-slideshow .slides > li:first-child { - display: block; -} -.flex-slideshow .slide-container { - position: relative; -} -.flex-slideshow .frame-wrapper { - margin-bottom: 0.75em; -} -.flex-slideshow .caption-wrapper h2 { - margin-top: 0; -} -.flex-slideshow .caption-wrapper p { - min-height: 1.75em; -} -.flex-control-nav li, -.flex-direction-nav li { - display: inline-block; -} -.flex-control-nav a, -.flex-direction-nav a { - cursor: pointer; - display: block; -} -.flex-control-nav { - text-align: center; - padding: 0 2.5em; -} -.flex-control-nav a { - font-size: 1em; - line-height: 1em; - color: #888; - margin-left: 0.5em; -} -.flex-control-nav a:hover, -.flex-control-nav a:focus { - color: #444; - background-color: #ccc; - border-color: #bbb; -} -.text .flex-control-nav a { - text-decoration: none; -} -.flex-control-nav .flex-active { - color: #666; - background-color: #fff; -} -.touch .flex-control-nav a { - padding: 0.5em 0.75em; -} -.flex-direction-nav { - height: 0; -} -.touch .flex-direction-nav { - display: none; -} -.flex-direction-nav .flex-prev, -.flex-direction-nav .flex-next { - position: absolute; - bottom: -0.25em; - font-size: 1.25em; - font-weight: bold; - line-height: 1em; - color: #999; -} -.flex-direction-nav .flex-prev:hover, -.flex-direction-nav .flex-prev:focus, -.flex-direction-nav .flex-next:hover, -.flex-direction-nav .flex-next:focus { - filter: progid:DXImageTransform.Microsoft.Alpha(enabled=false); - opacity: 1; -} -.text .flex-direction-nav .flex-prev, -.text .flex-direction-nav .flex-next { - text-decoration: none; -} -.flex-direction-nav .flex-prev { - left: 0; -} -.flex-direction-nav .flex-next { - right: 0; -} -.home-slideshow .flex-direction-nav .flex-prev, -.home-slideshow .flex-direction-nav .flex-next { - top: 33%; - bottom: auto; - filter: alpha(opacity=70); - opacity: 0.7; -} -.home-slideshow .flex-direction-nav .flex-prev:hover, -.home-slideshow .flex-direction-nav .flex-prev:focus, -.home-slideshow .flex-direction-nav .flex-next:hover, -.home-slideshow .flex-direction-nav .flex-next:focus { - filter: progid:DXImageTransform.Microsoft.Alpha(enabled=false); - opacity: 1; -} -.home-slideshow .flex-direction-nav .flex-prev { - left: 0.75em; -} -.home-slideshow .flex-direction-nav .flex-next { - right: 0.75em; -} -.home-slideshow .flex-direction-nav .flex-prev:hover, -.home-slideshow .flex-direction-nav .flex-next:hover { - background-color: #e6e8ea; -} -@media print { - .flex-control-nav, - .flex-direction-nav, - .flex-control-paging { - display: none; - } -} -#nojs, -#oldie-warning { - padding: 0.75em 0.75em 0.65em; - text-align: center; - background-color: #c33; -} -#nojs p, -#oldie-warning p { - color: #e6e6e6; - font-weight: bold; - margin: 0; -} -#nojs a, -#oldie-warning a { - color: #e6e6e6; - text-decoration: underline; -} -#nojs a:hover, -#nojs a:focus, -#oldie-warning a:hover, -#oldie-warning a:focus { - color: #fff; - text-decoration: none; -} -#oldie-warning { - background-color: #ff7; -} -#oldie-warning p { - color: #444; -} -#oldie-warning a { - color: #444; -} -#oldie-warning a:hover, -#oldie-warning a:focus { - color: #000; -} -.js #nojs { - display: none; -} -.ir { - display: block; - text-indent: -9999px; - overflow: hidden; - background-repeat: no-repeat; - text-align: left; - direction: ltr; -} -.hidden { - display: none; - visibility: hidden; -} -.screen-reader-text { - border: 0; - clip: rect(0 0 0 0); - height: 1px; - margin: -1px; - overflow: hidden; - padding: 0; - position: absolute; - width: 1px; -} -.screen-reader-text.focusable:active, -.screen-reader-text.focusable:focus { - clip: auto; - height: auto; - margin: 0; - overflow: visible; - position: static; - width: auto; -} -.invisible { - visibility: hidden; -} -@media print { - *, - *:before, - *:after { - background: transparent !important; - color: #000 !important; - box-shadow: none !important; - text-shadow: none !important; - } - body { - font-size: 10pt; - line-height: 1.67; - } - a, - a:visited { - text-decoration: underline !important; - } - *[role="main"] a[href]:after { - content: " (" attr(href) ")"; - font-size: 75%; - } - *[role="main"] abbr[title]:after { - content: " (" attr(title) ")"; - font-size: 75%; - } - .ir a:after, - a[href^="javascript:"]:after, - a[href^="#"]:after { - content: ""; - } - pre, - blockquote { - border: 1px solid #999; - page-break-inside: avoid; - } - thead { - display: table-header-group; - } - tr, - img { - page-break-inside: avoid; - } - img { - max-width: 100% !important; - } - @page { - margin: 0.5cm; - } - p, - h2, - h3 { - orphans: 3; - widows: 3; - } - h1, - h2, - h3 { - page-break-after: avoid; - } - .do-not-print, - .screen-reader-text, - .invisible, - .jump-to-menu, - .jump-link, - #site-map-link { - display: none; - } - .say-no-more { - display: inline; - visibility: visible; - } - .blog-widget li, - .event-widget li { - padding-left: 6em; - } - .site-headline a { - display: block; - } - .site-headline a .python-logo, - .site-headline a .psf-logo { - display: none; - } - .python .site-headline a:before { - width: 290px; - height: 82px; - content: url(../img/python-logo_print.png?1576869008); - } - .psf .site-headline a:before { - width: 334px; - height: 82px; - content: url(../img/psf-logo_print.png?1576869008); - } -} -.icon-megaphone, -.icon-python-alt, -.icon-pypi, -.icon-news, -.icon-moderate, -.icon-mercurial, -.icon-jobs, -.icon-help, -.icon-download, -.icon-documentation, -.icon-community, -.icon-code, -.icon-close, -.icon-calendar, -.icon-beginner, -.icon-advanced, -.icon-sitemap, -.icon-search, -.icon-search-alt, -.icon-python, -.icon-github, -.icon-get-started, -.icon-feed, -.icon-facebook, -.icon-email, -.icon-arrow-up, -.icon-arrow-right, -.icon-arrow-left, -.icon-arrow-down, -.errorlist:before, -.icon-freenode, -.icon-alert, -.icon-versions, -.icon-twitter, -.icon-thumbs-up, -.icon-thumbs-down, -.icon-text-resize, -.icon-success-stories, -.icon-statistics, -.icon-stack-overflow { - font-family: "Pythonicon"; - speak: none; - font-style: normal; - font-weight: normal; - font-variant: normal; - text-transform: none; - line-height: 1; - margin-right: 0.5em; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; -} -.icon-megaphone span, -.icon-python-alt span, -.icon-pypi span, -.icon-news span, -.icon-moderate span, -.icon-mercurial span, -.icon-jobs span, -.icon-help span, -.icon-download span, -.icon-documentation span, -.icon-community span, -.icon-code span, -.icon-close span, -.icon-calendar span, -.icon-beginner span, -.icon-advanced span, -.icon-sitemap span, -.icon-search span, -.icon-search-alt span, -.icon-python span, -.icon-github span, -.icon-get-started span, -.icon-feed span, -.icon-facebook span, -.icon-email span, -.icon-arrow-up span, -.icon-arrow-right span, -.icon-arrow-left span, -.icon-arrow-down span, -.errorlist:before span, -.icon-freenode span, -.icon-alert span, -.icon-versions span, -.icon-twitter span, -.icon-thumbs-up span, -.icon-thumbs-down span, -.icon-text-resize span, -.icon-success-stories span, -.icon-statistics span, -.icon-stack-overflow span { - display: none; -} -@font-face { - font-family: "Pythonicon"; - src: url(Pythonicon.eot); -} -@font-face { - font-family: "Pythonicon"; - src: url(data:application/x-font-ttf;charset=utf-8;base64,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) - format("truetype"), - url(data:application/font-woff;charset=utf-8;base64,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) - format("woff"); - font-weight: normal; - font-style: normal; -} -.icon-megaphone:before { - content: "\e600"; -} -.icon-python-alt:before { - content: "\e601"; -} -.icon-pypi:before { - content: "\e602"; -} -.icon-news:before { - content: "\e603"; -} -.icon-moderate:before { - content: "\e604"; -} -.icon-mercurial:before { - content: "\e605"; -} -.icon-jobs:before { - content: "\e606"; -} -.icon-help:before { - content: "\3f"; -} -.icon-download:before { - content: "\e609"; -} -.icon-documentation:before { - content: "\e60a"; -} -.icon-community:before { - content: "\e60b"; -} -.icon-code:before { - content: "\e60c"; -} -.icon-close:before { - content: "\58"; -} -.icon-calendar:before { - content: "\e60e"; -} -.icon-beginner:before { - content: "\e60f"; -} -.icon-advanced:before { - content: "\e610"; -} -.icon-sitemap:before { - content: "\e611"; -} -.icon-search-alt:before { - content: "\e612"; -} -.icon-search:before { - content: "\e613"; -} -.icon-python:before { - content: "\e614"; -} -.icon-github:before { - content: "\e615"; -} -.icon-get-started:before { - content: "\e616"; -} -.icon-feed:before { - content: "\e617"; -} -.icon-facebook:before { - content: "\e618"; -} -.icon-email:before { - content: "\e619"; -} -.icon-arrow-up:before { - content: "\e61a"; -} -.icon-arrow-right:before { - content: "\e61b"; -} -.icon-arrow-left:before { - content: "\e61c"; -} -.icon-arrow-down:before, -.errorlist:before { - content: "\e61d"; -} -.icon-freenode:before { - content: "\e61e"; -} -.icon-alert:before { - content: "\e61f"; -} -.icon-versions:before { - content: "\e620"; -} -.icon-twitter:before { - content: "\e621"; -} -.icon-thumbs-up:before { - content: "\e622"; -} -.icon-thumbs-down:before { - content: "\e623"; -} -.icon-text-resize:before { - content: "\e624"; -} -.icon-success-stories:before { - content: "\e625"; -} -.icon-statistics:before { - content: "\e626"; -} -.icon-stack-overflow:before { - content: "\e627"; -} -.no-fontface .icon-megaphone:before, -.no-fontface .icon-python-alt:before, -.no-fontface .icon-pypi:before, -.no-fontface .icon-news:before, -.no-fontface .icon-moderate:before, -.no-fontface .icon-mercurial:before, -.no-fontface .icon-jobs:before, -.no-fontface .icon-help:before, -.no-fontface .icon-download:before, -.no-fontface .icon-documentation:before, -.no-fontface .icon-community:before, -.no-fontface .icon-code:before, -.no-fontface .icon-close:before, -.no-fontface .icon-calendar:before, -.no-fontface .icon-beginner:before, -.no-fontface .icon-advanced:before, -.no-fontface .icon-sitemap:before, -.no-fontface .icon-search:before, -.no-fontface .icon-search-alt:before, -.no-fontface .icon-python:before, -.no-fontface .icon-github:before, -.no-fontface .icon-get-started:before, -.no-fontface .icon-feed:before, -.no-fontface .icon-facebook:before, -.no-fontface .icon-email:before, -.no-fontface .icon-arrow-up:before, -.no-fontface .icon-arrow-right:before, -.no-fontface .icon-arrow-left:before, -.no-fontface .icon-arrow-down:before, -.no-fontface .errorlist:before, -.no-fontface .icon-freenode:before, -.no-fontface .icon-alert:before, -.no-fontface .icon-versions:before, -.no-fontface .icon-twitter:before, -.no-fontface .icon-thumbs-up:before, -.no-fontface .icon-thumbs-down:before, -.no-fontface .icon-text-resize:before, -.no-fontface .icon-success-stories:before, -.no-fontface .icon-statistics:before, -.no-fontface .icon-stack-overflow:before, -.no-svg .icon-megaphone:before, -.no-svg .icon-python-alt:before, -.no-svg .icon-pypi:before, -.no-svg .icon-news:before, -.no-svg .icon-moderate:before, -.no-svg .icon-mercurial:before, -.no-svg .icon-jobs:before, -.no-svg .icon-help:before, -.no-svg .icon-download:before, -.no-svg .icon-documentation:before, -.no-svg .icon-community:before, -.no-svg .icon-code:before, -.no-svg .icon-close:before, -.no-svg .icon-calendar:before, -.no-svg .icon-beginner:before, -.no-svg .icon-advanced:before, -.no-svg .icon-sitemap:before, -.no-svg .icon-search:before, -.no-svg .icon-search-alt:before, -.no-svg .icon-python:before, -.no-svg .icon-github:before, -.no-svg .icon-get-started:before, -.no-svg .icon-feed:before, -.no-svg .icon-facebook:before, -.no-svg .icon-email:before, -.no-svg .icon-arrow-up:before, -.no-svg .icon-arrow-right:before, -.no-svg .icon-arrow-left:before, -.no-svg .icon-arrow-down:before, -.no-svg .errorlist:before, -.no-svg .icon-freenode:before, -.no-svg .icon-alert:before, -.no-svg .icon-versions:before, -.no-svg .icon-twitter:before, -.no-svg .icon-thumbs-up:before, -.no-svg .icon-thumbs-down:before, -.no-svg .icon-text-resize:before, -.no-svg .icon-success-stories:before, -.no-svg .icon-statistics:before, -.no-svg .icon-stack-overflow:before, -.no-generatedcontent .icon-megaphone:before, -.no-generatedcontent .icon-python-alt:before, -.no-generatedcontent .icon-pypi:before, -.no-generatedcontent .icon-news:before, -.no-generatedcontent .icon-moderate:before, -.no-generatedcontent .icon-mercurial:before, -.no-generatedcontent .icon-jobs:before, -.no-generatedcontent .icon-help:before, -.no-generatedcontent .icon-download:before, -.no-generatedcontent .icon-documentation:before, -.no-generatedcontent .icon-community:before, -.no-generatedcontent .icon-code:before, -.no-generatedcontent .icon-close:before, -.no-generatedcontent .icon-calendar:before, -.no-generatedcontent .icon-beginner:before, -.no-generatedcontent .icon-advanced:before, -.no-generatedcontent .icon-sitemap:before, -.no-generatedcontent .icon-search:before, -.no-generatedcontent .icon-search-alt:before, -.no-generatedcontent .icon-python:before, -.no-generatedcontent .icon-github:before, -.no-generatedcontent .icon-get-started:before, -.no-generatedcontent .icon-feed:before, -.no-generatedcontent .icon-facebook:before, -.no-generatedcontent .icon-email:before, -.no-generatedcontent .icon-arrow-up:before, -.no-generatedcontent .icon-arrow-right:before, -.no-generatedcontent .icon-arrow-left:before, -.no-generatedcontent .icon-arrow-down:before, -.no-generatedcontent .errorlist:before, -.no-generatedcontent .icon-freenode:before, -.no-generatedcontent .icon-alert:before, -.no-generatedcontent .icon-versions:before, -.no-generatedcontent .icon-twitter:before, -.no-generatedcontent .icon-thumbs-up:before, -.no-generatedcontent .icon-thumbs-down:before, -.no-generatedcontent .icon-text-resize:before, -.no-generatedcontent .icon-success-stories:before, -.no-generatedcontent .icon-statistics:before, -.no-generatedcontent .icon-stack-overflow:before { - display: none; - margin-right: 0; -} -.no-fontface .icon-megaphone span, -.no-fontface .icon-python-alt span, -.no-fontface .icon-pypi span, -.no-fontface .icon-news span, -.no-fontface .icon-moderate span, -.no-fontface .icon-mercurial span, -.no-fontface .icon-jobs span, -.no-fontface .icon-help span, -.no-fontface .icon-download span, -.no-fontface .icon-documentation span, -.no-fontface .icon-community span, -.no-fontface .icon-code span, -.no-fontface .icon-close span, -.no-fontface .icon-calendar span, -.no-fontface .icon-beginner span, -.no-fontface .icon-advanced span, -.no-fontface .icon-sitemap span, -.no-fontface .icon-search span, -.no-fontface .icon-search-alt span, -.no-fontface .icon-python span, -.no-fontface .icon-github span, -.no-fontface .icon-get-started span, -.no-fontface .icon-feed span, -.no-fontface .icon-facebook span, -.no-fontface .icon-email span, -.no-fontface .icon-arrow-up span, -.no-fontface .icon-arrow-right span, -.no-fontface .icon-arrow-left span, -.no-fontface .icon-arrow-down span, -.no-fontface .errorlist:before span, -.no-fontface .icon-freenode span, -.no-fontface .icon-alert span, -.no-fontface .icon-versions span, -.no-fontface .icon-twitter span, -.no-fontface .icon-thumbs-up span, -.no-fontface .icon-thumbs-down span, -.no-fontface .icon-text-resize span, -.no-fontface .icon-success-stories span, -.no-fontface .icon-statistics span, -.no-fontface .icon-stack-overflow span, -.no-svg .icon-megaphone span, -.no-svg .icon-python-alt span, -.no-svg .icon-pypi span, -.no-svg .icon-news span, -.no-svg .icon-moderate span, -.no-svg .icon-mercurial span, -.no-svg .icon-jobs span, -.no-svg .icon-help span, -.no-svg .icon-download span, -.no-svg .icon-documentation span, -.no-svg .icon-community span, -.no-svg .icon-code span, -.no-svg .icon-close span, -.no-svg .icon-calendar span, -.no-svg .icon-beginner span, -.no-svg .icon-advanced span, -.no-svg .icon-sitemap span, -.no-svg .icon-search span, -.no-svg .icon-search-alt span, -.no-svg .icon-python span, -.no-svg .icon-github span, -.no-svg .icon-get-started span, -.no-svg .icon-feed span, -.no-svg .icon-facebook span, -.no-svg .icon-email span, -.no-svg .icon-arrow-up span, -.no-svg .icon-arrow-right span, -.no-svg .icon-arrow-left span, -.no-svg .icon-arrow-down span, -.no-svg .errorlist:before span, -.no-svg .icon-freenode span, -.no-svg .icon-alert span, -.no-svg .icon-versions span, -.no-svg .icon-twitter span, -.no-svg .icon-thumbs-up span, -.no-svg .icon-thumbs-down span, -.no-svg .icon-text-resize span, -.no-svg .icon-success-stories span, -.no-svg .icon-statistics span, -.no-svg .icon-stack-overflow span, -.no-generatedcontent .icon-megaphone span, -.no-generatedcontent .icon-python-alt span, -.no-generatedcontent .icon-pypi span, -.no-generatedcontent .icon-news span, -.no-generatedcontent .icon-moderate span, -.no-generatedcontent .icon-mercurial span, -.no-generatedcontent .icon-jobs span, -.no-generatedcontent .icon-help span, -.no-generatedcontent .icon-download span, -.no-generatedcontent .icon-documentation span, -.no-generatedcontent .icon-community span, -.no-generatedcontent .icon-code span, -.no-generatedcontent .icon-close span, -.no-generatedcontent .icon-calendar span, -.no-generatedcontent .icon-beginner span, -.no-generatedcontent .icon-advanced span, -.no-generatedcontent .icon-sitemap span, -.no-generatedcontent .icon-search span, -.no-generatedcontent .icon-search-alt span, -.no-generatedcontent .icon-python span, -.no-generatedcontent .icon-github span, -.no-generatedcontent .icon-get-started span, -.no-generatedcontent .icon-feed span, -.no-generatedcontent .icon-facebook span, -.no-generatedcontent .icon-email span, -.no-generatedcontent .icon-arrow-up span, -.no-generatedcontent .icon-arrow-right span, -.no-generatedcontent .icon-arrow-left span, -.no-generatedcontent .icon-arrow-down span, -.no-generatedcontent .errorlist:before span, -.no-generatedcontent .icon-freenode span, -.no-generatedcontent .icon-alert span, -.no-generatedcontent .icon-versions span, -.no-generatedcontent .icon-twitter span, -.no-generatedcontent .icon-thumbs-up span, -.no-generatedcontent .icon-thumbs-down span, -.no-generatedcontent .icon-text-resize span, -.no-generatedcontent .icon-success-stories span, -.no-generatedcontent .icon-statistics span, -.no-generatedcontent .icon-stack-overflow span { - display: inline; -} -.ie8 .icon-megaphone:before, -.ie8 .icon-python-alt:before, -.ie8 .icon-pypi:before, -.ie8 .icon-news:before, -.ie8 .icon-moderate:before, -.ie8 .icon-mercurial:before, -.ie8 .icon-jobs:before, -.ie8 .icon-help:before, -.ie8 .icon-download:before, -.ie8 .icon-documentation:before, -.ie8 .icon-community:before, -.ie8 .icon-code:before, -.ie8 .icon-close:before, -.ie8 .icon-calendar:before, -.ie8 .icon-beginner:before, -.ie8 .icon-advanced:before, -.ie8 .icon-sitemap:before, -.ie8 .icon-search:before, -.ie8 .icon-search-alt:before, -.ie8 .icon-python:before, -.ie8 .icon-github:before, -.ie8 .icon-get-started:before, -.ie8 .icon-feed:before, -.ie8 .icon-facebook:before, -.ie8 .icon-email:before, -.ie8 .icon-arrow-up:before, -.ie8 .icon-arrow-right:before, -.ie8 .icon-arrow-left:before, -.ie8 .icon-arrow-down:before, -.ie8 .errorlist:before, -.ie8 .icon-freenode:before, -.ie8 .icon-alert:before, -.ie8 .icon-versions:before, -.ie8 .icon-twitter:before, -.ie8 .icon-thumbs-up:before, -.ie8 .icon-thumbs-down:before, -.ie8 .icon-text-resize:before, -.ie8 .icon-success-stories:before, -.ie8 .icon-statistics:before, -.ie8 .icon-stack-overflow:before { - display: inline; -} -.ie8 .icon-megaphone span, -.ie8 .icon-python-alt span, -.ie8 .icon-pypi span, -.ie8 .icon-news span, -.ie8 .icon-moderate span, -.ie8 .icon-mercurial span, -.ie8 .icon-jobs span, -.ie8 .icon-help span, -.ie8 .icon-download span, -.ie8 .icon-documentation span, -.ie8 .icon-community span, -.ie8 .icon-code span, -.ie8 .icon-close span, -.ie8 .icon-calendar span, -.ie8 .icon-beginner span, -.ie8 .icon-advanced span, -.ie8 .icon-sitemap span, -.ie8 .icon-search span, -.ie8 .icon-search-alt span, -.ie8 .icon-python span, -.ie8 .icon-github span, -.ie8 .icon-get-started span, -.ie8 .icon-feed span, -.ie8 .icon-facebook span, -.ie8 .icon-email span, -.ie8 .icon-arrow-up span, -.ie8 .icon-arrow-right span, -.ie8 .icon-arrow-left span, -.ie8 .icon-arrow-down span, -.ie8 .errorlist:before span, -.ie8 .icon-freenode span, -.ie8 .icon-alert span, -.ie8 .icon-versions span, -.ie8 .icon-twitter span, -.ie8 .icon-thumbs-up span, -.ie8 .icon-thumbs-down span, -.ie8 .icon-text-resize span, -.ie8 .icon-success-stories span, -.ie8 .icon-statistics span, -.ie8 .icon-stack-overflow span { - display: none; -} - diff --git a/pep_extensions/theme/static/fonts/Flux-Regular.ttf b/pep_extensions/theme/static/fonts/Flux-Regular.ttf deleted file mode 100644 index 948382896ccca33cd14e0d82a3a399f23b4d0e34..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 61832 zcmeFad4OAGy*GZIlbIwlnaRHIdor0MlSwkk>}xw+=?bN#w6xHcvdL=8bwO0TVBre5 zamD4L0tIE$SEcRn0xE(RM0*iL5wQw__v%$t6s|Iv_w#+8bCS$Zpm6Wc_xHz3dFGs) zB+q%yci*0GBqm9c1%Fy3^Yrxb$DMh`$A2bCe>fXg{Yw@to|aP5tRy`@j@Q8@YgVuS z<468>1g|fZr1sw~S%1Rh+1FllHC}JS`{C8=dy40NVq3Q)v46(vZKs{H{k$*P2Yw?- zt&dBR{I1jXTojgms9lQh_Tzo;uJcYmN4x1WRY}sX!FMh^{p^3(_1BBOmy@K9MUwQ` z*}Hdc-|?sXpYFhWetf>N8yB=c)jWaM$K!Q;_c<3`JhLYJOT2zXk~B}BeeP-7+hSuG z%#Ziki|1^=_&iOUd<xDl#^=ND*nZB=o6ddo_mcF?U0BmQ&O7(Qi=Mw@yIGQ+3uAqO z^DfwV-WP8B+&Ple_5ePAfkd!jo=@GlJN?`#rr|$JA<eIGMS8$=?Mrn0-svq*&s{Mm zYi2cD@lr3zbQS;Md-Bg~FH0A-B=G(>HM4vs@t*kmGQaY&bcv+n7wAq{HohmZBm7*$ zzQ?YSTBR2G9(f<GTqTa|XHrr6D}An2+e(L)OC{;faVfkUpW**qRIG$0T=<(T)}UF! z9ASWm-efPy_uvqgWR|AaxPl`;|D!a`c1qLoI;od^U$V*%N-lXy>XlxQ*08cPjG@K* z9`=ybBRzxHRcRQ<A+{Rde^g4db}7idhU3i`|0>zpol=qgLQ1l$B@_D=-g{E=OMj7; zNv}#PfxWE!DclD~_OO)Jv`9tSCAG6TX;^kke%X)tzm0JtUPq*WO!xW`*0%wl`3tUp z0M{SFI38m&=6+l`K8g2!iPt}r+T}i}3Usu~vl!D@(_tLPaWvpFL~RBsBwr=1V=qZ9 zY@Ia8zKHKVf%mS)@h2Gc+K2H|eCILTA9G93%w56u<M?yj?{j#*?_fNN&-@7AJ0iu{ z3LN+0^EO=j9^U(^WRlOq^Zzfr{vlp}3CFckQ2KYkbdA)(J|z|Eu>X`4luJ@tJ`ta3 zm3Cm>BA$OpQ^oOLFy|j|1l4K!alA$9XA$w5uJN%M_ojRP4)YUUPLWRJ*PFgu|Lh}D zir{^;q4D8*7I-80Hx20*bAOP2Ati8p1miiHONBq-pn0&Gv{^n0*Tw*+ronER`!D{z zEa>BQJQIy?C`aYBd@o)T4ha4<ZWKr9=W{PfKb5RFK7#QR{wyl|2?tF>eirl7Yl27f z_?0xqzxM*i;TnEUFtvl`{*3#A?jb46>^aE}x{HCHL+m!t+~=f(2E0i}#-tT&Oq$^E z{fab-&wJE)=qP_s8V1fdZx9|hF5U@zT!e9hG$cEvoZNwX{R^j|p_T;Br?5^M-=F)f zybCnYhqbGCr8$jK*Syz$tnYf@NBNA#jpzL(t~n*U=6s1bo4B2ZU*eJlch~SUKd5~p zuCIfHXazJck-jM1Ce5*4Hp$kr?d)Q93Hzx0ko+^v$2GTV?$O*IwuimpU^p61h6~}r z@S^Z-k!U0tm806IDQb;+qrqr*bZK;3bZ6q>zsYlRm^&=pAl)S0fjKAGI<^gSz87;o zDF3)Vr!DLb`@>;A=fHwFElqRoz?^JuZtmH+Z_Ryk?*6%}=PsQ)e{Sd8>bVtj{k7KF zKhKWMcE5UX)^X(9NA5pz-;sNd%pCdZkuM$j{E@+*f9L0SJoEfBk3RF%Ge3Fev1fkp z%(tJ}|I9Vd{L@dnTK^<qf|dS{{>QYS5M@S2nt(?0e|S^V(yG<z+u98soko+{Vzt>F zPM6!`_4xzAP&g8e#S_U?x+~M2&E<Ovy~R?wuTt$F7#tcN866v+n4E$}Ub1xA@)awO zTeW)4+I8!XKVid(8#kS_`Q$BIPuaFzy6i)jfB4!@e&+KxeBs6~-n9SLTfX$=+i$z$ z&aeEhuYT<tUq5tk=ALKH+p%-^kv;$Njx%4l=!_Tt@t^<m{6GA0*E@gxAOHTu@6LMH z<2N68-)ZOk_Tk_E@a%X0;?zq&_=#^n@S`Vx`t*-~a`&I^d+1lsKl|KEfByO2r+)U! z5A1vYl~?@JN3Oo=V;`43di|$Ab^jy(cJ8C!|G~wN9sZsq9gw8#iUU&HnvGv!>?4~F zu(=N%kQN0FN^O$nl&!e~63d3ei_che7u$vxauydd5u9nV;pw|HiRpD4W1GVJ!uyu( z*cYA-@7})Su9gHp;*FjAHuZ$>lGblL1AmX-7`bbFldpcdbJM0l%+o^i;4Ap}zD=0n zOl1Zf`K6v&e5f_MB7B!7xn|?qjdxwT$amNHqD{U?B)s^p``2u|>;6T)$fiyBl(xQ7 ztoXfWxRo{Qux4!r@9V`Z>o?vt?z>Ccv~M5Hxqf3Ta@VE%_WAbVIh5B2r27|KVA8@1 z<H`j<0&@Toix03%*I+UnVi6x*h(%%%taH;M+`BEiV*SR&SZQQaj$qy`9Rl&mlHAP> zfz|oReK=VujY<V622O{4(tRJSysDJLYmah8x({F5EuAbamC8~``H(DKJnstTh8-g5 zx^W``34G8l^+|c?^PM<vXXi;~*&=nw%Or3?(|^}Uw=pYwUZdAMta-X+u;nu?ueKIj z&uslb>#JI`_9^YFx^=pT^+Ek-+V-{G*#2X~H67)STRQITc&6i}&O3}xnT)3Ins-^u zmX(%EtrhDBtT$MHY;)U&ZJ)FK*8Vj|(dl)5&UKaRfV=EI*?pt?h{x+$<k{`H#B;Of zyPl^#FM99wUE(+UzZ)12d?dIl_+YRW8V|iEbUmcnwn#ei+vt~~PsQ$ux5O`r-yHv4 zqCfG=q&|6S@?FWtQ+oV+N9sS)$EP3fk}|=}7rOUkC$kr2FUoDqot=A8{L8oGugE{# z)84bZXL%uB*r5FTey_QAW$#CO|5&`Mw5xP~`Hu2Sef@oxR{WKvm5VB0s1D-am-^o` zuxc<q<Q<+KK67OE$cv*Fk7>tV953MCk%@aIKRI>Yq8*EOOkcm`8%w{mEW7NE<%28a z75Nn>t+-+((7N&i$8B7dUoEYEWvzehkJkNo{f_l79{-*b)@?9vFrVl>v7i5YY*Wig zi#88#K63IkCqKAF-r~i-;+8YF{BCP}>&C5nlz;oSes1fLQ{t!W*yh~!$?enIFWvsk zsV%2IzvHqUH|)4)$74J9?fk9yw@a)1`{b@?=-=sA>~7zE=@}J}+w|Pa(rxl1pg6Pi zs~M@2$VF=Do-lzPIwdDY5~G4Kjj;h^7lv-jM62{poO}pF-f{?pqmw!<)&US&&p}M4 zdFc?JiLQanSr6V=yb)a9<2#5qT1Ph#wYNwN?;nKu%wC#^V2XAL)(t$Dc2Ik}v;^Zs zjMFjpVqA`K9mal)yD=WZcoO3UjF&OYTPE6GGfB(&Sn4$1g$*jn=NEdbmXbvmP4<;5 zrJ~bi*T#-t9(M)<c4v?U9rwzevrpX-bT~sHrz1%4VLxLb`2j3eC)t!IX{D#ZXn~}+ zrAiJR#vel~4~33nKYQT`>kCidd%ds-BJz7AADHuWVs!rb1CkL(YtIa>GW=`lo{>6m zY{MC#WQK%0d_W4}sKc=XN0V~2;n;@P4jk!y7moCK4~}%*f4I=wT8)`lHP%<6F~)R! zIAXdIh6V>#4(tss32Z;xy6r6A^5DhJRsL;f+Hr2&YujW0_7_9nn!IA_Cg1&^i`+ML z#pIXRMOTnO&`8#~YuEw#Imn-~G(uF;i;EV%_#DpQg5oifI2+`TAz?Y~SQZ`aIOcG4 zD#sv>bUlBVQ&=x3tQTMH1%>qjOTEBSFDR^6rLbO5STCorGVYk<6h`y)9R^n4g&Xd} zkhfs6Hk^1cx-bSXmSJqdI0Him3LU9`KZ);;J+0ux*>ea_B}q<9O&=0xg<e-R&r;Q( z#?_Zfrt%EbQthkig3P7Eb%zTlLFTY)bw;LhXz)ktblFB(wbEBkroPK6rv)R1NV?l; zT_3btHXk>}(qn;$y$}p^_1SFZY{s7Rj&*f2)|DIUup4^1d(JyklMD2<J8hlv@3j7~ zqZC}Wt!<@qduzy1G`U-U*lr9vUHyUFYQNFka-#eheK{5GGS?1j+V$~LvH&&FD!JzV zB;P9E2?_6(val16XKQBwR1F*p!cZD#Yxr3aXHX2dX2RJp&Nwt%0nJtwnyr9lE1=m5 zXtn~Ht$=1LpxMfy>A;*O4l<W=#_^d3KGVQw8u(1()@k4~4Sc3me5QfVG~I%*H;nrY ztM?nm{f2SBVcc&R_Z!CjhH<}P`YK7IY0N#1xu-GrH2=2&e|KRh(r6lUPh&bT4KTcc zFzf`k#W1++v6Jkvlk8D0IOu|dF3dpQkkv;ZfiME4)7c7K^Wf|dq>^2V;c>xZ(Y)MO z9+gYQpzN?4<yeB1m}bGnR-?vYhgVn}#b@&}Q(lg0=#}h`m!lS2ye|?d$845ZIbPet zRxPc4bwFG%tJm2Em*1k*S^W-Iz|x9i?fj+-cq7mmER06NLph%>HyjR+76Kjet+OYx zZMYn!%l_ODzr0$uhtm#MHtuxAaxO<Y<Y4FGQWsrvFlQ`_YhgQ{pXAn@JSo3Z>Vf_7 zgBgHYBN;d_h|@DT6Z|X*{;dEf72u@8{}E<3VC=$Ba8dzIpk}~-Hq2Au{A+`Th;t2L z#??5#mI1~JhsE6EoHt2ZFhUS(!kCsWXa&aHcqhb{)`hcPzO-IUBVif|Ty4g+E<Sk| zuI3;gnI)>tuvA{tH>x4_P7)fO#L>E_5!ejML#(grfVfQIwF|FZ&Ps_rX)28^4yC92 z!13{3UpUB^x4RmMOa&aS0k19SXg4?`t_zo)^|g1V2V!Ps4(0-xHBNS7?N-KEsJu9x z9?gf^?WK6EFJ>{@QU)V4yF+GkG+<rpIkU`s*?zyTknm_)5g5X=tU;{kI<9jJipG%? zO>>%U38@%-W_WHh%gcWRAg5;FENVcuiq`f6Cw}0>55W7u5Psmq51jZ_ocMtgKX8J% zZNwXxyA{wNxduT8AtwHJL8=MDC27an@vO0Ydut2Rw6^DC-T_xUJ!&@D+gn-;Hj{ZI zeUq&e&YZQBg%%}Ki$Y7!><$-gk;HT&Ha@j1n_V_F9>WX%eA>Cq(kp!JD`q4w)~=_u zlSI%%A|M(k<hdTqr-ww)Ln7!Q5%iD<dPoF49^`=J1yYklDHc3K9M9mQWpfUrN2ziN zO)H0x?xROxI$e6iY_b_zGzPoLJerOxPo!Zj$`gHP;c_FkVz~RvrJ+Ts<f0H;dR8V} zvf&W`e-HZrTPc4FO65H>cuAH!@rI05wSfTJuqaZ`hQo)T;1L@HA!4oVsw`3{TSs;f zP1lb1$s$tEwDq&L`WYDt;&UeD4CaR`R@J4dsj4eg(p6nLm+pJ=kmi)&X{Y(OYlh_Q zp`E7%*h?2&FjT7cR;uToJ6P<mK;1F$cNe=3F+77bws8Ggte@7dKa3UYv0@qa3N3@= zBj^QhY48!UI$FV135TvPmMU?^VJ(ZVX4fqK*pENvzjM*Ye0LxkjPDK4{fl&?v;(3x zi5X3pQKQ14jTpL(7@FXq;W`DV1hP`2n%=sV=G5vg)SEiYMqm%Nn!_HDHEz%1HiO>T z=5d;Xc4x?IPY!!A2i;HlmGn0TiGVxO!>KE$htgoh)xII-7!H2^S1VWY&kw-{{(^K0 z5cO?(&=#yip+^nq5vUdPr~y4{K#v;GqXzV-0X=F!k1!3n1+0<U1eUqBk?6^wl}9&` z#8T{AEi{Q1_N^BBMhp8^3;R|J`%nw}Rtx)93;R|J`&JA4Rtx)93;R|J`&JA4R;${# z^Cwa4TP?U;%k5hipq3=t7UoIpd}jz&tuq+3x7CeW{>;+cF18xB8;N%kw1ksFuLF$E zOyji|FVkG+eDysb-1OYb>?Zb2=)W%JJ0NB7!4L+?YawVk--ZCEkP4>|;1mL!LV!~U za0&rVA;2lb`8H%GdtdVs5fW)%%}ZRnJ0P`)J{*u*4oEErp2q>H<xr)T15(R@TY!mh z@9w&eFcF+hLM5~U)p1UwCd}=XWZ_kK0d+5+?giAnfVvk@_X6r(K-~+ddjWMXpza0K zy@0wGQ1=4rUO?TeLVf-u3e>$=C2m7rMYByn=0J%I07V`_jHbQCCAr*m!Rsn4DHN9W zxK<dv*+@L+X*2k8k$BeA_H1_TNIX8WHk&(PGM%10As3#kMp>*f5e^RZhGjY2I}`-! z@Q8G{53%`HDLR8c!U6{tTU4%U&|aYz&Q7Xo*|Ws*d3LTTTd9qTIVgK@72?F*Fvoxj z(zcCnkw%fBn+3Zc1TNW2m<eJPigQ$x>dR|l(2(F!=7JsMa^f5;8*wacwdn(0vAD;Z z_O`XQx&omNgU|14b9z^X{rx@RR*lA%3MDoMn5HvkwfWp0n=KkmxS1<pZq>FKT2dAl z>+p7moauDN9q6+|fH2TtkbM}>Tawn#Aao&Y*SBV|LR5ij5{EGWq&&|1h=NL7Z>UNm z!(u}Bkpf9-@p!Tm8bnvcvjsI!hPsV~^&>HBv=A^j14%D)_I6gQt*w=ix6ftuj*Jev z!Vbpdo<OXcv@>~h<Ee?eJ45-29$#<LtzoQ(X<AH`Ofn+N7DL=@Yw0w*2JI|gHnqiz zL*d1nsy@m^+2;c6>)^RINThQ~A_)u&k=uf2AQ4O+7KvaZJqO3Uiv8DEO*&!`9kB=r z_Jbf92KLiJH6b=GwQw8BfayBOhwO_mc*u^J!vMq9UwegVSFBmH?DpHAeU{zou3b=i zM0VDGEoi6+yj;r;N>S-LVP+e8I93dh1_o6c7$6M{pdbUJfdSIM0BK-=G%$d%NkEb$ zh~YWN!6nPk&99If+zKPkfzL^Nf%MFAde&BGBL}F$3G$r5$C*N?HhjR0ubBY{H_ij3 zn}9RWEScRvXv`AP#T<hgvfXv;T6uWG_N2A2Za8WQ_XHd(%Pi{srqOP-b`(|=J<Ps% zW1p|B8~B^-@s+#08X2OobYpyISrRx(&i#dbNB%4#a#hxKK<X!|!sy41y;y`-v2nR< zi({>E$hJ6STO6`24yh4`Y>TV1Ee_ch=dw+Q@9G2;^MGPrg<>91%ma#fK#_uXc|b7_ zDCW6L%>$|M<N(P5g3wVs9^uxM0J1}%gc7$S;GN@pU8<Dqf|Trnl<b0(?1Gf+f|Trn zl<b0(?1Gf+f|Trnl<b0(?1Gf+f|Trnl<b0(>{6xV{7Dok*@frDZ6GBXcbK(0$PK|z zT5_%xgA?|fMoZE}cumBCTDE;fHdAhIlYMJ5g(W$=EW1mq2ggr#w0CIa4ufM&&OZ`; zs?``N2BYPe)!^%idy96rd_kw%HBru|AcW=k@Nr$4<^5sCrp5wijCCCsn_A=OG`7?} zI&s=mj4^+H!0)LRI8%0zyfK0QE(Kk;!nzamhCmhmwRFQYu|=v8HuBrr^Ko`u?LYrb z9$PWH0}L93p1ct`B+vu$q#vJ=CUFtbG>~WrXI(hsywL@$0v5ue=mJ)|_`d=CU52p< z;|vV4DEe^>aoX<}6w#0G_N(9R$9L%y{h)|`e77Ip?Z<cfIbVqgoP-r<FatS5;tXrp zfTiuiz#0rN874uTlOWDX5a%R_b5d#*!M#ZkC4GvRuv41k3vqy~OPtU&AoNv4Y+QBd zNy6xb5{5nmS<-{Y0kaXDk!d%=9X(ozID=&g;#;B;-x3ht5)j`KfNu%^cOw3tj<FZx za*XRR_G8?Q@esz77%yPFjG+Yn=1-y!-x549ZbQUJ5gT~y+*z+w;RZJ8?3CiGlU^fF z&;^m9o^wB*#TN}bdRFxHEzdhf7rCQOgC{c(jtq2r49@6D&X~K?=#DuYF}JbP9lNsA zp9_U@!A^rW7mMY626nD%$6#!_KN{_yjt%Z`>4Wi<C0t249I3vrH5CsU9g&pHnh4sh z!KBrejyN86RdT^#uHy1mvVlOZ!fjhw^3QqL47(4o9gq$lkOm=h5`sDsppJw}9SKlJ z0@RVf#}c591gIkc>PT>Tp@)<q!+sD*R7GY2=<spWnsL^HGcLP&Kps6Hj~<Xm56Ghj z;OqhY^kAY1iUIe4OnPwJ1CkH34G~GixrCN^xL^j+H3lJ0RG`PP3_4PLHAKsxS>cYu zq$pLmriG#v|Jy1gu@zJ}EBNI5l0&XcxviZ+5_B)_al-*9t{xys&`FZOz7~=o_EVAs zp;#$qX(vh0Yj-*C(OEj2ljVHc9$+lNMFAKXl3;g360mnb5=0>ha*zc5Bnixh4hyJO zmX;wi`W1E^G_gne(+nvckg&qbW<cDmLfniGm;rG!AZ`Z4&49QW5I1vPhRWt4M!*|T zBKL`0AScd+w|EFFCO)CER41`ir(h}a20L)q15zh&V^h5e8<@rhrm=x(Y#?$QB(@Dq zV*}IJz%({6jSWm=1Jl^RG&V4e4NPML)7Vs|nLmlbG&W$_#+k;}>`lyj@xHoiA=l4X zkLqRA4y$KmE6CDH_<#r4M?e7)@|Y2kgz5$yDY6#?Sc9OkAZRQI8Vlm?LC{!GrLiDr z48eHNSP&2seuq%<<g04Ao#2*&AT2<T{7WvBn!|hKzLHl5j~QN3G@0Ta5(RD*Ka;<9 z!OuJpa^i7V7=Md;lfeR)vz4CDDSS@0iBba?wUtNlJ{jV!d6t$l&>iGgQPf|CjY$r= z&h_F05A@%1OTJc%KlK!kwMmEM_3X1)m=2gEQyw}7i){F;lwXKAV3WC4cx6MagZ;tF zcK7w&(bq?MYW}^5pjvUSF$6zcy6i2t41D|B>z;ZlUaQf)(sQq{+vR@)^mEd$XJGcX zKo%(Q?*{z40sn5mzZ>xH2K>7L|85oj-GF~L;7@`)A$4<AKzW`Bq=ZVZjfjQ<{wNV} zln9u<7L`P*C#@218jqX?@uoq%X%KH3#G3~3ra`=E5N{g9n+EZwLA+@YZyLm#2Jxmr zylItq=TD*#uLwGGr>u`ew`$Cj&B0xjKC(h$j(QRZj`Bwf-J>zBt3R7r<qaiI9ZW6m zgT3HL6nz~X2Csn<MC3)^csM=0biAO|`t3<yT-y@pU7YJ0&4mrDMI*Pq_rduzU!41^ z{J8veK=U*<G6ROv0LX;i%{ZInXXJpNhBLqnoUN5wgw(YGBQ|{428`H%5y6kUa8#tO z4HyA~f+J1?M@)kYrh7OqZN@h@<C~lD&CU4cX54)<aJgCi=4O0zGrp<fEkbCD2szUY zqB8PzZ3D@W>YkC-;%qrTLu?&5qP0e_Rv6yGyLJPSZXnVPM7n`UH$LPBBHciw8;EoR zk!~Q;4Me(uNH-Aa1|r=+q+3Pg{7Do<y0Lb*s=CQYB&CpN4YgdMC?8N+55Gf+$il=# z)&{zT-WX+w>XwtSC^>YD$L)1^LE+s}u~L;=bTLaNqhV%$!WLVfA3ke!F2Clik;U)M zwA<TyKXSs-OSe|5TQ6NYu(LZo;L|#7g?KWe*LYWz+}W^|EiG-$`Mup<bEH4!%tjoe zD<a*@;P6}AU3wO3v&gN3W1*qGOsC72Uwzid@L6l}qb0pbKen=Z%B4$}UV2I;5(uo@ zvNauz>9pn+*&S!LaJRcW5(*?bI}%o-(U<nDiib@;N2guSWhuNixf8ag4*pvSc+{#A zui?QfJg6b$!e6Eg2eO|eUmyY_shBQitJ;{R#O|B=)6(j5OMYB?^&O8r@PK@_Yxccz zu!c%ad~Fy$&M)LWz(E4IeRKu~HQT4f8D*6wC~6yo9whM$0&K&H2crvP0Am@(CX6#M z$fl+DwU8f&Frhd*AXSC^QpGID!iZU_n5BwYs+gsUS*n<&idm|d<sfL3^2?+!Xf9Yl z;DIc7APYbkaSks?$j}%kTv$brm1Kdm;h4ZzAXm8)$Q^qZj6xk8kz~rI7=hhP*9!X& zhaedzeZ$`g^k=<{1;f4q5+<SYbgHy26c7BXJz#A!x+B&L8EZ4gs_8vUA53N)fqcXw z@3F@E;_;H*5Xz0D(~u`EtuBkr$A)adnAsBcnC|^ocQqIMo8D$>)3o?fy*`rZ{<*)h zzsi^4;U1#ccng-SNNF!P+l%X7aJCnmEn-i*a8zW17n}{_yUy9o$TwnY2WEoZ0p5+M zyc+@UM!>rf05$^NjevI};N1v#Hv-;`fOjL{-3WL$0^W^)cO&542zWQ5^6vae6yA-1 zcO#s46Gqm}z=!}Oh2wRCfpzv^3kl~c`)l=_Q8u!5JS?-w__p!N$q8?4X{tEYWnnst zKUoa>y3^Uf^6tdgsTWoHFF1LCF^@0nvX)n!+~pY=?(g>MEpC(o%b?f)Vl{a$45^Ux zhXYa=)ZoPkgCd$@m0r*pfr(SA7j)(Yoq0iLUeK8rbmj$}5l|_|Kr&g4Ra*F&7PCdT z<D+t&ftbu7n2g*+N=hN}kMAN(A!MWjaCQLB4#3#~I6DAm2jJ`goE?C(18{Z#&JMuY z0XRDVX9wWy0Gu5voaaxXz*)peN!i&b6sI~kDVrq-StmT{*zm&>TZaR&$t?rH!BW<| z+&Uc2FU~tHh4qv2UN*SpqQSxQHdahde<z!**)6`FWhZr)cC9JmVTM7Jp9V|~($X1F zBV{P)=~@5<o*$4^C^Te`U_D{TkmXACBtpNz3ZpopCV?<a31T<m7-8%b&+KE~1I#S% zVWl4zYp)a`d&GUOhwN#SMvoQ&Yw1z-SMz;Iz>$?V1FVVrQv8#GK6JNXw$=OU4}Evb zdrD6hYY*Z!_)q}+_It?El=S-pQkotHb`5#Yc!g)|IE;ZSz^Ty8A#h;`To?iuhQNg( z(0K^@m4e$4hVR75hcHMplZ)I{caa-GxEX{M7$}U^NqHlYR?&f8;4lk%iGyC^SW_JI z5(mA+K`(L8OC0nP2ff5WFLBUI9P|<gy~IH;anMT~^b%L;W&R`zy@=QocZXwDmqjQ~ z&YGG!Ya$3knvvc7UiTf<(?&<Oj=>g+jGZ#>>&bSz>fFg}T~j@&p#Y2bvf3-z<k)ub z=Y=QtGuGN+H)UP6(yA?8$y3(%JIR&8BNHwCP5uCA>2!iB!5T+EiDH^9b-0sFFX1YA zsbm!yI5s*7lE<d$^thLz=`0aT%u>bQl7)Sx_Qdk#tQ-H=o{-P*)PBZXv-@aW(^%a# zSeJ(4>A*e52<~<i+9rCcTBeud`?HtOciUlCdqF=oDMNIxMrtY5<e(MTE1w$p2dh>s zJP?uOX-bNB9bWD$Ey=p04zu2_?;Q-b$!B_MEBn`#J#FoIS<m#o;#fe1;V*GNgi^&? ziO&SBX(?Yv5F*!pK}27<&`=2!29&t^ggv0qaVSAJ+t|J*^UIboL)T+}V-v;NA7~vv zfg$xm?H}tnd<S6FDy82HR>Vh~-vP0bYk1lBee#*^*{@Qy4QOHRW%)|X(;@AHSF6xM zC!j{y*Mb(1*8mR^{yT6+s#_~{aBa^c-t}i}JkskubSuf{R^f;chV<P2AXz5PD85c- z0E9)O(-0_ptYncV9~%9BY1uD-aDuF_wK~~ct)15Yylf<@QE(x<fr~cj9Ff{3;8S)= z`1c3F+w=?~mW`*vv*2F1Vj#-kRb=z?F3J<gv|w3XFmi}|!Bn3~XILhqH8P^<!?k}Y z4YKo!a?9+i^0{`bu9H?LQ#?{0fgNE-mAV^p2rKgnJL{PBpBkN~@(Ic|v;!+~tbd{n zvTuGIyJgFS4)|#Vx-~)=HUitk(3!e0Y@mcnkW`h~3IP3GRVJ&41E~@O+LNgoQ;7n~ z!?8uXCMS0-ip8gQOib*Yj@N#lpDwsvJ<~mfB|R>8VVW%-+`DaLWZT}s;R{ZxR!_QM zxb~ag)u$EnTUHhdE4So}r>#Z-8<&0GkS~Vl_e(b;IRSh)FaiLJuuTr)Eusw>kd_6e z9I#X<<;g7-2P_o_EENYV6$dO82P_o_EEP(SVlIGAWK}Jg(T6#R4uh%$Its1LppY1$ zZZ172Hzw{2vcybYg>Rt+I9LFtZf3C+QQbyXv152~a5|WrDEK|O(fEfiERS15UG8_n zl<?+9k;2T8$k;U5=gfp{|G{bTLQabzsl-MPNM$@XW#P)WtDr0HMZAUhCB-W399m@g zhYr)zzP*^G9pC4fKrSyEWT|kXhd9wAOgo}eDuANkm0D3izzVBMI}D{AhSCm0X@{Y- z!%*5`DD5zmb{I-K45b~0(hfsuhoQ8?P}*TA?J$&fSXJ8dCsCAk7)C~z8`G^?a)IYX zuHmB$v4!Dl_HbmR5NRDbc`U3_Zg6<xK#MD!a)j?$K*CqbmRKp+I==OSewBtR=WdzM z+k6)NdtZl^55guSTK@8UT5i_l9IJ1UhJ~)T0HajaLlzX#vH?d<%WtODgyAPlD<W?S z)rycSLpCs?i9v9x6dki^MiCg`1kJYZ?_2gzVp34_m+vo+af)WC+E3)Yf~d1Z)F-j2 zUQo6DKe+r4!ryoRGPa);;B#WVHo><x@GS*rIN#bpKQ{2K4SZ_@-`c>pHt;Qla#Y^O zxABC2JgJ{%!FdAb#3OzXSU1UB60eOo9mFdM;rYQj2w^fn)nFY>bP%=vBvc0LlDDBQ zXW*Y9x2~8E<WwuhrxA2)1RWbe$41bx5p-+>9UDQ%M$oYlbZi728$riL(6JG8Yy=$} zLB~dwj^|IJ(6JG8Y*d{>irP?xEt#5BHrvBQp)HAGUX&N31R#Z8)mmG2PH3{*-wzKa z)S1ZkxML}MPv5{8mDmRQR^&=6A|cOEdT4^NzWybdG74>TnULMu>F}FM2A8eFV2V~V zMVrGPwwHqG$$~fHE?9kRpb*blU824=yNWif0xs?N^RJ+Bom8H|pSn$Wlo|_R#W(7| zs3@vriB%JhnB~EHT<n&E^5R}roSmV0tH=}9U^6(R+eLXQ`5UlGfF#NWbOP_4xIz&Q zO4g&$n@~qp<DB*zR^&mF-@;q40%2Al%nF2AfiNo&W(C5mK$sN>vjSmOAj}GcS%EMs z5M~9!tU#DmMcDjF6ogrUFsq2bm4wNPfSRRhvpcI$2JAZnvC-pukwK3wXDipN-YD;> zZ7Z%r&FRqEBKw4=wsq}RwjKLS37&ZFzu>vG@STKZeH2Ji1sseQZsfQ$u)<uLfB*T? znL|B4YLn0R&Au$_Ewk4v_<?=%C(PF&tyXL)vIy(-bq%jj0bGObX}=A2zSM0han`0> zLj{C^>FD14_OkQ(4-ee6<e&a==|5fFeN&qpn*Fm~zQ9w{u;=Jct!?&Nu^!aZ$U&^f zAWdLBZ)}AxwC_YftjQiXFbJortLoC&*h9B}edO_bm*23zIP+s>t^JOTvu^iX%~pH9 z_GN-Afcqea!ys)X5OjJ7o;vno;}NkI$_r3A;sV(zK111IqE=0nSFhuamTw)HzR6bg z2E#owEWs9eYfr~^<SPTV+HJMx8qey6Z?1>*c+I>NB@pfx-hu$4ViVkfQQABbbEVmq z+T9*@W9>%vZj{O_D$f4z64A%-+(puF<llnT67y=BB;*oRXMP5@gmCbYL9~!dUvdoJ z=~}bpD$T{ESAWmvp}Mv;fP$!NBL|c6FRiS~n7Q`iI5S@_D%<FuA>8u^{GK_%<AR5E z;JP;AIvws!k0R>AX%!-c<mv-^r%IO0mNo9Xt}JORrB|<@`PQ*b@}T^$Sg(iR!tYIv zt)Munvq2Ktz*4r7jm_SD_sEZif5bMS#^yN}+f=(*z_w-XgY2cbuj5XgO|^@7UgUwC zR`%k1iy}TU$^OO?@+Xw%RO|O_$oxzO9*oH+4eg0zLhc8!^Vv6%f9YW+)L3ItR31{m zGYZ>FRNtss;21C#<+6t?sxF*CiD_}-#7JUPFs3o6qGK0^67}dp)Pu?z4oFeV+*?;S z4U1|<3Sc>+Xvc&z%7mbT7oUzD7HcA7DytR*WFgbCkZD=Sv@B#=7BVdhnU;l2%R;7Q zA=9#uX<5j$EM!_1GA#?4mW52qsxoc<B#KPSV(qvMB4(%#5*Y#*P-F<qOA$o1F(c{) zoGyxloNw;x9gGCaNhfo4Rl<AC-k3Gg7qF%l<$Qf<&k{@7m+9}%hRf|!X1~3Ixl(<> za4BZ(wuPJ>W>dytu|^8PEsSL|$sy)JO%vgU;_G+I<nyE%6FyoPxFLT__>2d^V5A3h zVz)~ec12jVE5abMFkl{rT@i*|5r$n6hFuZnc10MlG~>IJbZ?cgVHHtw?tbZTg9Vac z211KTlnta$CnN*^H1V!a#fA^q@Bte>V8aJ&_<#)`u;BwXe87ee*zf@xK48NKZ1{i; zAF$yAHhd~J=1-zv!v}2OHo!(}Uek+6!6>EaD2&;|MDQJmp;91};T_lOToM{j<R-HY zcXl%KL5(xi<qCJX+jQ>kcyz+5m)(A+yv1Gnh0Vd_#K@{l;l#-#+tAY4p=T`FKj!lf z6{9F2;_ycuC3MpHs4I*}2WJ3Hr4F6w-2+1PfJ8l@cMs^@gH?J!?;e%jJ)n0FP@&4d zhI%;&_duyT4FYOGKrINU1p&1npcVwwf`D2OPzwTTK|n1Cs09JFAfOfm)PjIoP=(t3 zNffAw47s3TCH+-Ff((`t!s|-aehFn0?ELWBLS{1W?#;XUhlackSHCxy4VcWKo=~hm zm~ePfV{5ub&kdVRvc;S-m}EKDHxUYs6eG-O6!PO0_F4H5tbmv_N2MJk*i?%p4oX#} z2s!vv!$)$%r^*c<;OGM!eSo76a1_|yg`*-je1Id+54l0MPJ-k{Jz~}@J4j-X?4X4> zd6l^ERKX6y2Ac0TEdd*xh;cf`UX05zuEW@maW}?87*ArnfblYhQb06+5(U-`=ZjTs zB3>#Ahnz0#muOB#vJKNLw|gWv(QS9-7Ug2&VShP->L1j=<|5HCyZi<B?3J-hW^!#R zy>7D0V(PcJ68)1t?`S3A1GELa{{qE$FYup{&On_r;2i?I9b68GNP*Y@C}K?b1mH%+ zn+AN!$v;JLQ?ezyaHP181Ls-Fh@n;mAsPZAVMPP+O9;$7O_GobZ;&Xboo*r);));) zOi9-imyAe}mDsy2ai_c7*K3P+*)mgw{8*Qj)n3wA;-ye>z&~to#@*h8t3$p&ZLsNd z+7^o?w7tLk_{px|z}iyxbgz%ecH_6)JxP}<nRnxPc`Y-WlJ7%~aSau73i|~#hJ}$Y zNrjxEG8B|ikNGvMyJl;n1)rt;hD1qDVT1RTuyJpQkw3w!iD)aN<+z@n-5aq3r_<b4 z8Vu^$&YkQ7rQ-Rgx3*?AZNB2Tzgnsxwo5e=0d_09AM{%#-AOf`RScEltGJJ_*G1hY zZOx>ZP8A#w<d~qS%-gA?qAC|&$(h7-Tw0qc5MdU92t;R;omf<<RaQBm3~5t_v?)W{ zlp$@(;D9nXpbQQug9FOofHF9s3=SxR1IpllGB}_N4k)V}Fn<z-1ImzoxXt;ZNJ*{W z;+fHM1!?x?{JVzsL~3-l`J8dPqc@*2Xtk(;X3@zEafqXPJX^Y;fV`=(I6UURg;*u$ zHyC`~k!UsWb&cNSb+iY=p$_EAU9PT)HR;6KMcHJgc2{~+(3^A{n7rKLj916OKINF7 zQYw^RxB>dqC0z*0A<$tE1*!ZYB4mU!(rzx`=ny<DgXH2G&qLCOhoX-fm2D>!v<no_ z-B7FnP9nCYP0kcNR!j&UOIIolENnx&J?xB)`j;(>tjGllQ5*B31l}I8*Y1$N;Ho|9 z_MyteU;6>s1DNa6@+C0i%~Db9%@kE%w3`9-oAp|o=GrjI$We|MSp~kMnRb1kX3GXu zI_$UGeKb0j%B#hh&p!KAs^cC5eNzV{=?naRVaX@%7sgD0f*qFc>rCu=P3~e!y^Ud+ zuPBljItL{&^o_gT?5(-`*Y$bY+6o$-tn(E{k<B3fC!Bp2I5S9#>6S3Cu>ukK(W?23 z1@?-<5)G9*FPD+hfyJv97{WHT<WpVCmOUE3_P}ov56U-qYHJQfKUn*vxbNH_r6+LT zHpxN`2EQ{sIaN@(v`IL*7TA7IEL*cAo7Cxs2jn5w>|I$uvULo7oFw^d_D%5GyJjd3 z3F%B>LBy_rIyy_@Oyo()zHQ_H8*)o|hDPdGxzO07Is*~i9KaHhHBn_5;lZqO5;7ZG zk{uv8agGy|QbO9P)F;PSv1;$?l;vf`0ef1%%-xkKgo6F{$Yj=2NV-|3)F(4XyUwbw zeT80VWJg==T6VG3XKlv@B9}Ro^VPl~o|%0NeUt3caYD)wZ;@sZ^@~*fOO`6}m59tb z>psA1p1M&j%(;d?1}&Wm!BHaMu(0LBg+QNWnZGaQTaro-)5=hd)j=z>huZXQZEe+D z?JFds$%eZVxUj*7#{MMIcR`GX4b7vF$6TR;Z{rC>Ej{@o^eo&1vO{Oufmk~%89OW) zJ7l6A7NK3WWbCkH?A($u0V<7DN8{;54L+5m2spuh6t;^8qR0bk@<4KXAh|t|+#X17 z4<xq-lG_8x?SbU>KyrH^xjm5F9!PEvB)3PE-18?<B)70z$xd|DYotVx09D4T^#LjD zPx@79dC~1FFYoDDQTDk@E5Bs$_r#Jt-nI@p=6!8#v?Zx|i_&kyQ~mKob*g!L68SVf zb^!QrNExOP_6zwmWTgn}h2!HbdNPy&6fhGO4rzHiX6?YNuxu29B&ls7A#D*tS_kqV zuLf6vNpO>Z_Ix*F3Ensn<8+L@7?)#Qhp`{yZj6U8p2T<o<7EuRQk*}D0&UfoIRrwm zNItF=T($y=TwE0abt*HmXqx;Qm{r5rMs!?1gHCifvXi;Qc!;%mLs3h-+o{tzx}vVG zh@<5ZdCV1XLwhDCHxx3fN0N*=ZM9j}r!{uym>ew)`F&%Rq|Edk9f<wNQVe*w5w?p9 zd;vTVUl7L<Ux=Cp0Z-C_bOt>Mn05e8VU^;;p!hH-J`9QvgW`o9ybDLgb`OK%!<^z> z_`aZcx((r>d84)k%kgnMPzDsmSOO0TtStemr`oavs6GKaB!Gtm@Q?r=62L<Oct`*b z3E&|CJS2dJ1n`hh@i2c91rG`ECT;_Jg|xJ&_iD8mHL<=XCU99a^KBHi*%A!L-NJfb z+~ciQ3f5)r{zxqAYj5|$Dyam1#S8`u;0<dem4O9sa0G3$-<69NSG+nwW_&zASqIW- zRrU~QAV{?y!lnh4F3@8XcO$QjcDv@OMoO!*3};3oi}E_N*5K4L6pyj9dmJ4Gy)k5z zTU?gf=eX`l&%MM>We-S$l-V5u$n_%c@D_GY4*_G;lfwzG0ov-N2}&nWZ-pdamxNqH zct+%OlOTg6|EJ`1lR!ImK*43B9UN#S0RkGX3;QZDU{x?6DX<7fJekB$i30H&vb=zJ z4L+v<;x$0L28h=H@fsjr1H@~9cnuJ*0pc}4yatHZ0P$#3BbvO-pF}~t28%~U4a6M^ zLrJ=k?*gAj{I7a#I@E&F&H~zTApRFsQ_0k%Yb1a@7&c~fcsttd20Qu(xM{C{bS&sA z=FK6m*<rC{9Q=ByI2uYW3#_&{^|pY+>@*o#TXZctYo{?83c(t*Te<^!i`Qy%>h%`< zZ!~rVW9a<gbCL}aocj~voy$QU8)hilkAJG&qXS;3ijg!cRqLVC3P5ZiYlu^jvS->r zMV%z$gvCTrOY%&}3!;sD+=xLR7}3yxjG5moTURVDTemKYXv**a3-!Fq`|+OIvt-o3 zra>Lc^<0l4FF~@k;pJ0~RQNo?3Kbp}uWsQ*JjCw}U!B|(g~QE2v>Avt1JPz6+6+XS zfoL-jZ3d#vK(rZ%HUrUSAleK>n}KLE5N%cwJ%17f(PkhTw*jJ2sG&F@++rh#m91Tt zKWoBM?DDRdC<Mw@cCdDNBxMTqL|D;N`+lhc*{SUF`ZN0?dS1TOoWuiPpZe65xz8Ec z0e|fpcBZqoMcA^YxmV<q0mHYOlbB!UK_xG0#mBsy1iSUZt;7E`b>60_^S9;p>Jd;s z;9y^I*S^d~=+6n}+R0))K@i#}u#e4vz3p!=Cqbf1WGARI#r!;lSRY-36_*lC2xylB z8$I{@@oTS~KKI<phdy)DP3-YUUHfmee)CzerXqam&jUtT=?7@a0Xn1I<f=zajg3@~ zI)`)NQLB4GY3I0zP3KA6P_eHIgY!hgKR$@0v?6Hypg%w8&ky?ZgZ})WKR@Wt5Bl?i z{`{anKj_a7`tyVS{GdNS=+6)O^Q-hXe-efML{AOXBlZhTKf1sp20`{AQ3i@cr49m` z<QL!E<Oo|<j)O=&%g1{I!`5YTYnz^X!p*L)Mz8l;5IJTAPwi1wDxvd82isY@(3a0< zOxy|PvIKuVfPS31w~&vq#i|ia$q{_+X%Fjt?l0`JV(mReE|=D`#Tp9&3~&Ld-kaQ9 zs$GIiI*bS%jvg+F0C@*88`OFZ(QVLx=poWqtss*-%ElNvCgIVc+yYc)gDQmpLqy5N za-kJ|qm!{pffdSNMWcUt$X%JT_@h>9)Nhf^k-YErwtURmAAVnDpkuOQpz^+Ozcqqp zZT2-i*Z6ZWk6!OVtl%0~HW{LBJ!|HklCGCYK{$jDNeLTJ2(RBGe-4;fvpgyP**%NM zFSb(6t!G6%W0szgd^PHYMDawF3g8*ZXA96X5_M(qj0Sv?LIjwJHoqf4hRuT`jCLbH z&p?IX2@wqBPs(>6bolZSwAE{VB6nzo&*<zc6#AS---^&B?V)7Wb?w53Da?QFOYz*% zJj4J)FTh{0Gua?QWVBO=_CJ%tpqL(m>qYKA6LOH-5z0mfO0BaqJ;k`i>+zbI(}$yY zVR8D*%<6Hsceb023FSz3Bh^CQCV!8|Ag&^4HdUZ&U<%L{77c6#4L&K<?JgV@i%<j8 zfZAoyh96YA0b~?15@!@zp>T<KC9)HMab1HnVjA@APM*D_&x<oeH$+1V7|<Xrjm2fT zxZboav0Q!xEkMH9wB-o0*|Hq)%)Sb^1n0iM&X+^rigyVMm_o~B0c(L}O3_lJkmL<* zicfJv#zgPnl~1*Tk2!*kXCVWdOCzNxMce2mkPMn7aFU@0VlL5b2>uqiUkK2X?dQ5T zIn?FEu2EMYKFZ473xf1E&tQ~o-O!R5S(yqAS8`^%c7^j4t#4tpK52HgP6Bk)FQFzI z<j0Y4!%jOq3E2psZy8TZPfq(ZokZXDY`LPn(TzrV02f(tE~#;$;l)zypV|kw03|Z% zM4Xn|(9ynkf+$t&P&+!LN&CnEDOX&gpo2oN0fxM-qvT58eD&44H@cz@lir~(4g~f0 zxNdsdEie7!^n1=fgSEHys9~Z@r~kN=a0%iZK%N`bbCi^w|4c+DFk(P&Vg+16Q6!J| zHzNB)3EnjxNZB0NxX|dDK>IG#s%-L%DAG>dhA1aT5nZ%sz*D!OeFEjpDELSBckmig zzy+Uj<LOcT!Jj^bOmRxhuIupdIy^mFvh3l9EqA-Wc9oiIzw$QrpyMZ=uYK)ng^57n z<wn-MknAsDIXmWlCVgIh2@kH5lx(%I`^erCo;C7>IG1sMnX2PS`spD3C=#f_*flgV z1aqhAt=(BWo(-_tZN%@zxj(bd$REcRuhSS}fMh?XxL`p%2f+nphmQxDM@o0`iY5<E zY2UgBnMV&Yj~-+mJ;*%r<QQeoHb7307eT$is7Kod{%;rlDso~2<irLpCwg$V4IFPh z@I=Nq59;w0JL?WbLoSG|#DkocX&<az)$?|csvQ&Aq37+;^LFTYJM_FAdfpB_Z-<_@ zL(kix=k3t*cIbIK^t>H<-mdET`I9JmUPO7goym0=bHIzl?oo*Sqq-O9D)w40L-8|A z3<*y7A|k6CWW2Bm6=>|!Ca1Tf!^A?pBcbGSzt1@mw8D{OMmsqn?cCYughOI5db|6{ z74i2LOd+=kz2kEBwAJcnOIdq+TdY6o^V=+zE{AOFFoa!fjjKEA)fu~7v2w)hb7rj$ zy)|GrJ4|TerPt^!<fyo^3BRr*;tKahtWHbTuQz)vR;S)<A%7(uY-u+eS{+t{vFgB8 zxG}7?MPshOgCW`(VzX?wyc4>@BYmCfi@__x6Fug>Nfdx>K@^?}HmG}&;51Q<K=~|X z*M$?O<c3nWIqCvP^yP$?>QpJp35s%Zic<GcgF`__KFWJh<%S5PQ^1G>KAAH%FeyW% zT<rr2#o5$2iB;<A<pD>Sh0tLt=wP$z22b_K7hatEgQivf9cU>HK6-*0AE^BmCvirt z=|ps$3KJ)2$J{a3VDs2xqpW&i-L=9`YMC|v^lKYBs2v}aPpgd`M4!Z!#Ay`oC!0c4 zx{ysJI_sfv0&E|$E?(33ux~-BbXD1I$<01kMF?pqiD)#@tFlk8yli`a|EV8bx$?48 zalCBh*x9SH*;Qwcjh{uwvmSrLM742f_r5i2t~z~qX!liX)?9h|@L*}vo~fxl8_VU5 zblg<>h{MCwT(*%})m-*Ca@i&9UU4F%3+()X?Ula_y%@po7jz2$gWL%6H7ILJ3C1kW z)d*P@QYN6tBqdHl@~sgPso;E?OF9uVQ6St1kx+d%_g1)F&_!w$H8bS7Qv+Dhm(v9x zQ=ux=Z^`g*NLP1p?Fv7dT5pO*WAgbE5sI?&EGg<j(CI^i?#~)&BgSrwi!rXi_-Bk; zFb-gR7vskmzs7h4gGW#FIB{d7G5RrD$d6Xg_uAdE0Y>}JA@;CkR#d}GyH@l%Q$aJE zC~V65JSnF!P>MQIL0jz?tk1h^S-6X3!tRugUFnL*mO#o`sD=VD$Ru+|rzh^Z_tWJv zvqnRK9HR}b&_Pm}-6x}m7ZfUQiVZZ7dB$O;6wASuQZ6Xj18!U;_`Z7hp5%94e#<TW zS6%h|{{8q{{@s7Z9)2Xo{}NS0&poHn%14kVNI`8aVr?@hXi&KnElrf&&ZxEJ1TXmY zZR)=mL{SV>5redffj(l8RxwDcm@2JekXA7+t@`oMqL1o;a>nJu2=wiUs&7XiUPnMS zBUtzd$YBKfb_Du%1k;Jg`V?rFvJTTE?U011^D*)xoUqVGNZD|{2xp>=X9i#BhYVcE z*$Yd_tEm_=YW1pVmj+G+!fMzCz&@ig^NPz(9T+(EvK5o(uFdDyo;x{t-r8Jl?RlSl zUvlueKr!L8Mf1M*e<D?2MpwvsqJL=jmEhvtL+UYK+5E1>i{G`mq8`sYa)do=j~D#D zo{0SjYbzzpVYlf{uuMOzvCCy@U^~A)&ITIo2lcU985@j1Q*2iHJ$^IA4qpEvs?tDC zloz7vG*Mf{;rzDqLSP?}7jgsFZs6JtT)Tm5v1ff3j*2XB1J`b#QeY@X7(&5I6NV^x z2rI2AG|j`2)u<LBN|f2Auy_4xThwDR`J#4y^u}z=9gVnL5f*Z?S(7(rx5d0BI@+UN z({=nE`U7|kqfRhXuM;E>h3X+~;Fwcl4+hxZ;(La$7K;A`c>K>QeOs8#R5D7H=)$(7 zYGVrY3hR<|tJs$X)xj+_KCi-{jgEY@dsc}B&Tm?{1aF*(aXQ9cjLR{u!`P2;H^xI4 zPhz})@iK-I^qoJ6Vxy70iQ6FBZ$aWt#G}aLuZLd9FHSj%A{a=a!Fc3Z`O11Eke$oJ zgH+NFI0WZD!fuiGV6Mf~s2h)jVFesS{*`<lf&*FI<SSCXQ|#NZ5ge%2)&gBhl{R7r zVk;7xDT{*KA!cFQj$0ZZ>+$(|#^OIaN&e#OVmG_cj~DT=f`8V{*D!?N%=rQvg*sUM zKhTe|VgDd3-fZGDdPDxG$(+HuPn?@(I!MX@)#8FY72}C~A1$69&)JD*Bo~Yf8aR4T z_v+rDzLFzFUbq@kKi%rHSc2^)i!R*5oC#ltC+@aqEbrIr(3#a>Y||W{XK0;~@frhe zQz!K|AieY_=;>R*yKd;|oY2#0fR^;MphwQVX-G-lOq%)*q#-5KkdkRg$uy*78d5S1 zDM_uTX)mw3KZ^V_9yY`ks?y;$(_833L;I>48a+lD9deyCx)Y!il>n^(4e1W5t)*<T zqQ^~G5?%;BZo<QvusRb|unBtH1U+to9ydXco1n){(BmfPaTCC8f*v<PkDH*!P0-^e zRgce~g!H(rsizgM%h8bXRss%+$yRiv`eU*Fq}`hAPbLQv)^-TayZkY`uFVni1!8tB zj&e(67>%X#!;$ECZ!p+99<99yz5P)%sK`0prHt2?DY~7xIFT$KccBia9cKm%uEUj5 zjfM_aQW#u^i+(k{hpq1CS6wx*fB*AWUDdyT|A~)09Q)7T#rR)wkJQ{B(8J~t9*;Zi z?Q;gOuJ{^3M5K`K<gchJ0%%)s3)#U<-T`WAQ2B>_SJW~Zy{Hh^L|TQiNT7VOZvE6@ z6%NCDlBW*MYaQe1SSdQoRCAeCKKV5IRRLnQ*+-T3F<IU|2Hj&?*n2%cKzEr5be9R( z@xav58GSx9OK@fY%11y5_1ehB?<goBZfp!8(*>JH@dOlnLoq(wD$oTL#Hf8gN}AF~ zQ6+wk+WX^g>>ZD3I#4n`yMAF0kmfZQdAE`JuIM*h0|jJg4MNw{@2n|(9cpK}dSf&l zk#C0zdiABF-*-9Y=!Af!XD8Xpsi~1$RxUJ}2vfRMMudc(oh)^+y#Y<07Cb#OUlF+J zj%Z9>2LV8SWmVVSy<M{#<}am=2OStT4A*W7YvJo?Yz|Z|_(>S}Meb9L%aSuF<fO=# zVm~LgLoA5ZQs)MW)z-lT1hIQxFK+9fx9Vq<;BC_5W;~kv>g@anXi@0M0Wt0Ykte8* zmkJC2`@VV-vhaVxS3d+1YUW&c2;dTZ&<<gtDxZ=kpQ=ZMyaZ-1fmwljfGz|C+*Mzn zk{4>(!Rvbc;Ohlme-no=3NTaCCr48NpmQGVZ&&rEdR)jq1bYS^-U?mjhp^8|KNH$4 z4EU2aYqCY(Vogk=Mk%Rkv19g255WZxeg||5R*^kSi4K*n8-3Fh___(cZUJBFA`}CE ziR~OBUVz;cP<}#UVt-h(22v>+P6OGo+@^IAb(<GhwDvm{$iB+0T9~&+;>jBn<JPDe zx3j0J)cp`yxHN9%?TWAll2!jM?*->urL*X_Y}9JvPCTRNCPDOy=d62|jkvb*tc|Kd z(T|OCE3{Qw*mI(Ui@F)&<52CL2tgwI*@u2gtkKkj`YP>v@E<17MD!HztGu~MZU2|Q zjD@Q$PGn>4SESPz`p8bpE!aak$-Lx|w%}HD!$GW_GH(+UEz-iyfrTrgue3RVHsokw z=V)Q)Xkk=nVdrSc;UJlJ%-*Mp??!}GfkBDzT@v_qVU5CvBztd+KY0mHo>7CZ83bQ5 zaH=y1zGe`7&A_nFz_8E2u+PA-&%m(Hz_8E2u+PA-&%m(Hz_8E2u+ON5{rpK3!#)GU zJ_B=UzJV$FMUu&h2otGbomS~2gj|Y=r6}5}8lS(mdQpPjZnEk^tg^n}FSCUmhM2z5 zV#r_GIe;odIqvW9Bw(bP8%FAge(IESim%&zs5_mMoiJndsfHN~Xi*)|r@8)yfj7fr zHzLzW5$+D6!=vcZX0oF|oFKNAI<ZlAKi1Sihn4U1KUDiwQy-n%PZ`=X+f%1CVLL5Y z3-N}?9|+!fy|py9-W_c%<VLc3f1QZqi_q=ZC0+06BUHP*r>OSzQDH)Q-9j)yMK)L0 z$j|^LMuN#v^gPwM&{jtgBSX%GlOg5luqhu5XyXdL87jZw`n~pG6IfLB-V7M}@f*Ss zwV8H9^*l&oO~c)qw{KsX@cjUfWt;fU4T^7fV5O8Mr-Zqx)hIR?IV|GT$+~uHSQQOZ zlrmCiRm7j4;)Y@V{FIyO!1pPbZN<?8ctklo>S1lA7+ei;#|+I<YPF)@e&Pt>*RQC> z<;o^-9Ywb_ASdHDMJ4HRPTM*uD|Sy3Jpq45u~82}EUAVl_O+tNO4VY50eaeU#p+br z>40bO3n5H@)OnA>D`H-;Uzli-=3NRJJhWV~D(my&w?`%HCnLH;4>-|Lisb9j>5cZm zsm7zAEt>hf5Bp&=-m$!HD2mxNbJ!NkOrRmMuL9Cx@&rYf*tbtZYCeQZ^tYA$pdCP> z6FIWIpbQbmCQB+*r?rM9)d&)Rrtq2OBuR7ES8guV$%#^n&k*JCUzqq#osO!2ziJYx z$JzA?GPn$o-5Ro|qqN6~_M=i2Pz?7KJrG3x9TB_3B5K#D{NWwok8XYYNNf3o)`FD{ z6q1&v8b#RRZ(wsbn(2JE$>KKqnkpq?YL}g(7~2av?-1g6?;TFV6u<Bbi!UfLW5*nE zJO~=1NE2C!RC!~BEJ48jr3o?&&_#921pPeU(SK}9D>^}_Kei>pRXk`>XQF1G$p(=^ zHk}CTc>t{m`Z2!w73E9t`b3P=G4^6yj&U8vevG>@9>RDM;{}YDF_e(q{7Dqe-Y82a zZDvDiwXuchC|!8i#rFjsyx~nd@yMk3Y8M?tJD&fCqql-1lB{ovqn|?Te*PFx1ZTfC za4aaQ<A`LoSIQF~^*~C51s@%=w<Kbg_%8TJ^;I(}AHj+he3U^5KZ6i{1|fW5ckaSb z;iC*f_%K8fMkG~RPy@YO3^jJ}hzx3i^AR<F{5x(qKtMr+INp?#y2&nzT=wRO64p}f z)5nCWI<82j=cEaW*-ipiC4s9F{FjpIzmy;wO7LGw@Lx*sUrO*_O7LGw@Lvw%J(78o z0CNm7F9w-6LbxKoW(4AH1ZWxonnr-85x55<$f{8q3~tgpaq=MyLX!vIpQ>xQASs5R zPz;T*3`8g*ud0fmu#8&IL_2`;su0Y>y~#@{j4H+wj1w_V$JmQ;ImUGu`!VjucnIT3 zj2AFo#!!Ud{7Docn8*5&mlL^Hl7DLDUOgK0rr3Ps^%T}sZ;s&CsIuDRvEjN!(Qm?L zCTxFt25{GK6(aHl)K#ou`-r{u^xGrcn?2^*5RUa@{#~esjm__J%ry5uM_c48iGWCh zwiepxe}CFiD_j=30&m*;j$Qp4|A1Zi=5+NM!>{(w$3|BSZOK>Qx5jRTFGjz#D{_@0 zR-;GGGSOUPe&IzI7545eTy#<KA1+>T$tAfDyg$$X0s&-y?UIKP`w2j5SJ}y8=QefI zqF?8s3P`PxOK-8`9PPoU$eEUVa-<Bz_7_e;MM$S2q*D>nsR-#*1a}u9or<b-DndFH zA)To6wK@aspXB?zslOAo1mr5EVU;Tvn&Zk;a+u>{i<%RMRWUWcbHNh4aU#a)7<(}; z$G8q-KgQh{4`Dos@dC!n7>byhKZzoy)b<DT<N?XZeb}mUhR96)XH?Lw2sPd!@{-b3 zo$BVo9;R%!LGAa4dy)ewdwhE5L@b;h?~0b=*4W~mlYU=r)NVynI#0VTXdiNW3)4L= zgDc{^?0V<a+D%z%O4s%w=ZDc-eSJ3(llHnFv{GNX;K)GHp3qa9#n_^;3VN>bzM>j# zd&4XhHEGmYR&*1kDo)W`PR(ai%{OYqn!MJALZ@C605_hPD$x|9*a>~$gg$TrjZWwT zCjjjPpq&7;6M%LC&`to_2|zmmXeR*e1fZP&v{ME2{7Do*i<&ml2b8OE9i`vaSKu;l zTF`QfJJ8kFX}k5`fJfa?SO^dDw*TJnNL54F=cB5_djGMXz~<~-01xi?fAY=XK{lmN zx)1&)n2v(Me$avFGokKZRx2Hd%XQo;3CuJ68c|c)?kRp<>F@ok2;As98l|u}k5zaV z0!LVN<)ea!`u)EwYm_)f4_hRDF<Mjuzc!*FD$DB?jmNCj8?~O$(`pqbV%zjvRId$m zD8EH@wDL|WV{bH?YW^7uH3zgXl!0&?keO9kd46}OC3xdRjMFjpVqA`K9mal)yD=WZ zcoO3UjF&MKnK^$Fg_RpErkZO?=f_T3k3!Jw!$%3GF#SR-zDC8qKL5}C7h+Ri=km}j zRj4pU#C<8kg%}lh8M3d=>y3=Ac)vNa*3=>H>i9!}&o#QlDY3SrHH%~TEyMT8t@692 z#nP4Z8zq!y!V##G4ht3EB6?e8;UgfAByt>C_yJk?2wC_DS@;N9_y}3}2w5mo%z$rG zypyVP=v>_m-l*23)XZYRvv_|A_XJR}(gJxXs&ZTwY)qguKK`#zzbU?L2fyJ?`Fu(# z@Dgu&SJ^<CMABcT{*>6SfdX#Jjx}o-^MyV5tvRQ!lyow^&gb#9L`SC?3-wK>B10aR zHDw>1Vl9@iFCNp#PKV9iVs{&YK@al#?`QwjGuSm|Gj+(aMm7ZtF^AP0>o7*!EX$_R znljj;(YN*JP^P`SY7F^3Z5<K(z^$<(l};F1WkA$`YN2lcne_Xt@8<PgNp#l@iSD{7 zK&Ff*SK~%G)rZP~#d5Gxa<Eczuu^j1z#OcUoNA@yV5Q`^52fNKg?VTP1cl}4T!nTD zFs96-(m%Hz^_?GBQhx*tKLx>~>ewfaIZ~L9)<{)k*xVq(O$BJy0yJv@nzaDUS^zs1 zz>Wp5V*%_~06P}Ijs>t|0qj@+I~Kr>1+Zg5WykrGDC}6kQ{py?X0;iQvFqDApl**l z=EiTl<z8*+v9*6&h&ObupsvUS6IJgt@b`LfHv)QZ2eV0FfcHGE^Zoz7aYo^%W5wA% zG6{|uXT1Dz_TS$M&ORc49=1bT>SMM8QU&;;&I%PkRK%9V{xY$%UQ}^Y%ogtgS8t~i zR2nl^=h+<%dyIT-QJznkWBfEAcMC`&b{!V$qA(PE4#8hV@K+K1RRn((!Cyu2R}uVG z1b-F5Uq$d&5&TsIe-*)BMetV<{8a>h6;=M4KZ(L$!q?&aCBjh0imfBuN--TXzT`El zGkf-AYLmx?G4ch4d^`cqJ}50_5ut;I;1M9h4!o#RZW>UF0%}oUlX@ehaZVM7Q9zJ( zC2=2b4AOH9LT?Pxa}3gR402@*(sN9eo@0=nV_bR;Vh*8qX!lujfeN(|7exhqz?t}= zOcXInLmYdQu0R2IJr)(fYy1eOz~CgFViFjf1O_L8!AW3n5*VBW1}A~RNnmgi7@PzK zCxO99U~m!`oCF3ZRSeFbM8V)Bo&>jP#G;y7Ve-PHH^Qh=)j@krFIEFm*lLOdN`mh@ z#d+XOP`pj)o+)QVHB+auCAD+*k8gnLtvR)uW{ZMn+Kc1{D5u%Lj5H4PQ(9w&U`uun zio%E_hG6vwEVlv6ZQ^&+#(~>$;C39i9S3g50g-Xwc3j2nIB+}8{dXH?9p`h<?-e5# z4LTYEo`yL^sk}#2w3J&OL;=k)NYy-@!L4LS1zI6`r{en*jil@w$r3G&Bu6M>G^J9& z6ewT{6fgw}m;wb%fdZyL0aKuWDNw)^C}0W{Fa-*j0tHNg0;WI#Q=ot;l>+8ZqENsT zo)@<v3aCenoLY3))>1byp7DD_A>2d+lZYEpJ~`yLHt2AKP#76{<QVba*kFaN={$2d zJ9{hypyHqE{j1U<X)XKEjI;u{7TcJHa7L9EVpqom&UlP)0ygJ_YI9D&=9~Z?CSY?; zz~-EQ%{c*^a{>f#2-f6;(sgn%q(TCCp?K0_;HIidhaphV5GZH}XaxmgY{1xsp~R<$ zKtV&|c3LdXiIK#pU`%6dz}SVMe0l{wy@Jb<^>r$0M25uAxl#OjMj8d}h`1w_8ZPD6 zAobA*p6F>Q=x8z4OY5eP(JGaeR)LmQftFU`5mtegR)LmQftFT*mR5n5R)LmQftFT* zmR5n5R)LmQftFT*mR6~>G=CC>mR8|ea2v9>7Vc_zBO1~)?|85^_uqYHL9v+aGjB{! zpRVtYIKI)D_q7`(YSV8(TkQDyHj3J+=El9GQ~n}<l6?~@WEzx)-{B!j6Lnj?I9tLo zP{5gx=}UkC>aOHQwK4tDWiOW<y>+~B-SQUbfqFM{njjLS2BAD^*oa5WU|BK@Ucx@< zHMQcs8`y^ggR~NPby`g)Z;yn0Ki-2h5_+Zr%BX-cDxi!C7F+>kR6rROP(}rmQ2}LC zKp7QKMg^2n0cBJ`85K}QMWu}SlPHuy`+;$r^F;&dB>>72te?!MRkUTAJ6G5u%YVBO z+vZ0XHfB~k+qu-{q^?GH($<Cul0Ts~DmAu;PaZmI-{$0EyJIxFpoOV*mBAJBP!Cgf zf9*e2tt7gcwpuOiMqiwvxpR3zbLU9NA8BrJ8vB*n<1|}WQBeCq?5m)D!|2X;KpMk? zyG0z@4LRgi<&Yb4$PGE<h8%K34!I$R+>k@Gp-BDxpfLa}4&cS1fBH!NP)$Ien#=5i zSm^_p`#=YM0C*q7N}rm`?1NZ=;Q=?AN<qf!qNP#ysL)f0vSy)1IR*VLD7-+>$)HLn zgP@Z^(8(a^WDs;R2s#-AoeY9b20<r-pp!w+$sp)t5OgvKIvE6=41!JuRXUkJi9#oX zST=5hJw2qb2f;9$I!vs2Ye}_v+X*#Upu&7n7pUw!<sBB-`GLh5vGs&k^_i6&DJTkz zBN~15&d9ce%`ID-Hm1bu8&-z2nc?Nh*Xx;_!g_<~>-}!*smJe$!N5CL<gF=}DYBbl zCy}Uk(E*D(Py%JAX+IHFjCr{oL6uz;ug>8}eR3$L$y3iV#E6&5$RPS@uV0!YhD1BE ziB#vp{iS2-=j%b~;Hb(fZ`RY7{guiq+K;KT@BeKW@R9{pny7p7k$_OeMnh^`3Wss% z*g=5uh1nk*69^PKc#nJoOpiFk@w*YO1RfK>Fm)F}Q4TOmKY~GlOp%om{dI&@icjOZ znyv8jZ%{mkBGo-OQY{31vnag7Lva7Ffdw>yZSY9d5VO*c$541hEs(?>76h*#U*8ZS z-{($Q<XB-MuNFSpv9^4MDK7Y92e;L$usZQer|^vdB(i4E4*=(HHCNn-Dj!1fFfR4X zv(FFlZO)><KtJH0=g=gcn*<~$0m(eh7e6f>!a~X%imH+RT7#Ti`7XqesWgF<X%AkL zf!<^}yI?iXx15g!@T{L3&OwyZ)eYw-juj2;RkhHrZaF`DY;-Emy#y)yB#$BL-d-(d z2O?!VmWl{itI}Q=RA|M#e?IEG^~h6m#F=VDn<LI>p9SW;b*YHb++3em)N;z71z-I) zYdLRQDz6mOs}Zwn=6-^BxkeU#q+hy*b`i9IqKGoVgOK1VW2t>B{K{T3;!6=H<@OvE z=XF96cR~?&LJ@aDqjf?NcdGV%Clqlf6ftGG$wORN_uFV#(eMVzpl<3>F^|MhiuqVQ zdr+qz^U|ZZREJbh0!Qd&%swWc0P`Y8U9<Dx1&_iHA|4|4#gYCI(MAw_-Dqg6S$T-& zEDQywD9|CA=7?57YBeTZLs$fz=NIgRqHX3BaL_b$G;Xv7{-7FOKr5?x1)9P6{eoW` zM!55JTL^PGjUK|BPF<+iObLA(6}DLvwpmoQ&7#166wDumZ5D-X7KLqw5>^b#OQ?}s zs@POzIK_|fyYCPa6zg{5j8n&3*fmajuzBfbJ;L7L8R{I#V1N;jX@@`nVrYU&Hv_QD z0(c_;%PauPEC9<a0Lv@@%PauPEC9<a0Lv@@%PauPEC9<a0Lv@@%PgQ;X7eXeEVBUU z7`IVk>6!)p-NLTI?}K1C>CHL|bGb45>ap|}=C!r|6Sz_{8vh^R>L~K<|1Pdz6TTU) zJ_BL9_swu6WbtR;3a&^_Q~jn(*en^rR~hgX)l`BV+Hm5*=)xGlScb6);|vV)c~FVZ z)vOw0e|tTODW3MmrJFv^M-(&vJN789+h%HYgSvZ;nsPVw=>8ABp=H2RTv=-1sO0-@ zGLIJBzIv-}Ri8bdJ7F^2jHTP;aPLsCxn(z$b6xgPe7sv4XMG2x2}pm+YfO-UK1{J| zN|`HiD+{fbg;vW#t7W0pM522aj!M)j3#~?J-2c<txxhzxT?hVt-{>_Oy=J7*=*<Yd zg(Nf@X+}cgWgY?nHUezyU?;{{609+@K{h3^lTFiKNz$}Qx82ZZlBSMvniP|?F@B^e zP2E6VUN&_Xk|r(7#*5mrsp6#I^#-Z`bMN=fLk}!(@~h>;_qubx`<;94x#ygF?m2GG z1#M@G(bs7GrmrQTjwF$a(bqBhI!0f|=<Ar~p)s(J3Ppe4mY8Kyw;v|0=j?QG>?^Zv z=4I3oaXDdxFN;uR1Wp(c;|rWH0w;{X2_taA2%IniCyc-eBXGh9oG=0>jKB#aE+<T{ z#NmVyI3cfD&}RNt<IVbzJDbfimVY?e!Sjb=pF6!ho!ZsX_45U1r@yuDCj8UH>}qG% zAu%42h8;WU&ntVc6{)8K`skoLJD?Ba<2uR_S86d*;8$y$bvqyw^i@o&MZCO2i|a*@ znuPo^c}7aPmoB(#V(NvMdR=1bg_wFFre27t7h>v#n0g_mUd=dKG$E}|5K^l7)RpgL zf3}4rFH@+P-jf?&jJXuQWizElA*3jT6ortY5K<IEib6<H2q_97MIodpgcOC4q7YIP zLW)92Q3xsO5>k344k1M$Bwpi~-Wy4|OXdZ$F*&)@<}D^#YimOGOK!ut|E&lqDI2=V z!_7ArMM*Z62W6imZ%-cP=dY$_!4MA<B32_Wi%+nTVplRE@sMIvi`XZzB1<^R8k?VE zE5{;^D>$y?sEtzM4JpFtEZe4YBN^`3xsjSTLvn9G$+TdAGh??ZpkDDAk)y1t3~&^i ztQ=b;5S+%e<0DI8J@-$CuhjWS8|zH;N+({NY(6zN;(mLRn*k;7+~(&uOL`$c*@bfK zuKt>w=goyD)6+#pl&@`0=0qVA%P&vA*MO6M$o5urt*MTgWJDHu0OTr9vb7jqeU@Ao z*O9-PiI}yYReTU6M&KU4;^*~iZDw@J4n<jc68`CM{0Jj5!ibJAq9crG!}UfvIvhX3 zK!y!6kh>E#NH51^*u5RUR<o4N#KDhc6iWO~<Kya#z;yT2LHt&C17pBZ;5cvsI0>8q z&H)#JtH2FlaXzliAlLY~b~|Tp?c++kV{9r;Ncm&_>XwSUs_4-2;*z3xpt7a1pgg*z zt0WLul2;)4G>WUDS$UcD%PW1wl^y+soqem9NLCF`Z=koZt*5`H<Ic5Bp8oxwhQ8Zs z8g8$sv~4TgwX(YD9wMNMz9w<n9bJV;O_JqEY)G!|AzFa(b(OqFuK$mTP$a&tI>%8$ zlSuk~2pje)<LfHx&uc}CNDqlQ$n|bu3^)oL2TlMdfiu84;39ApxB)l_Pp`ybdC9n% zj<0KhNg{<3Yr-}iL~&?H596-Ygxlr~<-RapTsePHcu7d@v+-hlUjJk9Vtig_<K<%r z=~g;kv`GF(x5kUe;N{})Dls~<m}ZSft80N2JG1d$akbTK?r6X0#BS`Q--+>yme49P zT|2ar?$SKSgWbRwa1=NWoB&P&XMl6SMc^uM18`_1y%L93Qv9ODyQFZQi2qmhuBN(l zyf~up`uQ;9amJA&2U)c*iPZTEvp^P6Q`3SX4fcJ<W>i5>7+Y}Crjoku;tDBqMHAT( zi~3~7X?pa8K_2V|#(<;1ao_}S5;y~#11<trfg6B>`}9g2+$TdYB)kH!ZE8nWS5B$J z|9Cc)TDK=GnaS8GUr+Czxw6N+JtaJEHL>YV*&hdOo$57XMVCFp?%0-n!-mtDH5Fqs zH}-RpHOj%Vv7bvcF5|PPt>!Y`B_XbsF_IF*fAF>nKfE%mW!*}#)^mnVDEj(h@(DZz zKls91=M=DhCP9{_Qj+Q|CbNLZ90TC~bM`2L9C=W!!Iv-?dN7jzVl4GV)YP@$IO$7_ zlRi4htaq|shTeAlNBihc<8`AwZN$A;_hqZBUACIF%Z0~KE5DAp&fw|G)q_0P4U7Rt zf#bjl;3RMcI0sw=t^zjzXAGrR;*248&HF`I3|mZf|1Lb5iWk%C*6w-6*OEn$!L%#q zyT_Z`-Zo8GYCDq1?^u6D_bin#fF{aLsvmhWs*dD1BKg85$Ks5W;>?VF%|6P2Y>}AJ zt#p})`r;Lw%UG3=^b!|CWOea<GkH&C6iZ%Nyt$11^zFpBDWpmr$Wg59$(A{!l1yCl z5(=J$iB>eh057YCG?MPl;!;i!4pw<GTdl^WvR^Y!uDumjC?)QX6OP92x2#VVR)-rx zE8n>$Y+JQ!-nAy&Q=SqG=z*?vEq==iwBELS)UsB->qxBk;oan=iRwTp_L|P2ds-Ur z8;%*dzj@~0>~C9tiN3r--C;c`{%o$l3ET|dBpHolM$zL^E6E#Bk~g?Y@&<<P2GG3$ zC3yo%@&=UT4JgSQ5aC}Ws>%k{sM$}2b7nGNxZ|yn-sl7Wea262(OypCJNdjC7A-)+ zEhcuirTVG#!Q90|Pg;?$Q*6l6wmCCCDa+hBZke`FHDRTS1B1YBU<^1490yJSCxJ7- zIp8926}SO7<1@VyXM8S0{pL0J8Z4(VeVQE!=?(E}+_L#}am`-F$E=y{qasw`#(Os@ z7elqt61Ks~&Vl3_b7qPiPt1Duw~L!YI*)Ftzx<9~qor?I-g8Gqa9x-2NV(1;R4J*0 z8wbMcQe0Bh?5upv`2iB`X8QfbRgKHF>b`wteOp6ao4BJ86*k^PChX$EzfSn0q*?%N zZ4)#!7MOX{dfrp2`TQ=i3JpO|;=lCsugGe{&yee#GQ<o#1j`&knH&Q3LoA97x!x&5 zD3jn_TZQ`7(1KHgOhRTkx67E5yC8VkUAb1w$z2e97X;r0!FNIMT@ZX11TT9rUr@WW zA>yutRVXZzML2!35a&?~Dx1$L6oxjIxzk2EMGf*`H!ubq1&#wJfRn%(;2dxfxC-0= z7DJY1S=p7gwCI(vRala2S8GmWBp~sp1gGrjMjw@(DlTD)rGnIQSz;j4={2psR9lg_ zXV#Qj8{1oJ)-9{*jkXol=G8Cj3<WBJf!yWYy{mWDl=!QAwsb_d)P~FZn^&x{tnT<= zYj<&Rk$uXYN8IDIxBZT)5`TWMsxam&E6(?1<!0AMTO-B6s&Ft`!_Jn9rDc&oMXa-~ zEf6XQmxg+cURy*?yM6Yj(NosQ3Y=J>g=vcwI?NE1czH(0)%-0$cL&_=4$$2Jx;sF3 z2k7nq-5sF219UgPq`UCNGxJ6#x<)4i*a-o4LV#vx$S6n0n$ZaXB82ffnF8Rmt|eMz zMNzc1e36VmDPaaJdQu2Q>?RTrPV3GvF)o^bI4}t82F8G+z;WONa1uBJoC7WbSAiRV zLm26mIQ+`2B<mG8q(oWQSvVhsW4Ur{6HX$EY*}jf(r2na_>ra0EtGG<WSXe1OwBYw zE<AEntXg8*M_X>cz2)W;3*?lTH<v`~5^~=a8D4|!(7NEn+-i_`NfKi?J!XLJ<wfr) zWYlB4qHlxrZIHeV(zijFOAzJ~bo(|)-?AtTb8(|_CGC;2<}LA!i8+b+xtem4HqtoB zH6>U@a=kkln+uYFMw4;4QrtjhZ@Dk_r);9L?m>o=xJk+ITYaf}>f90K9&hfPXM>$M zxGTHZ*|WJ+{YYYFpcxsaxM=*%&B7r%m1_|Ylf1_8-0hj}{!M4}%-yE>qUg6yWX~no zn8c`Wu$qkIG{0HChH+(9<mNNW69vt2xS7it#rwu%)y8YB+PaYSWGb_B;+*{!IrGkx zTTe|tWxdC;=8aXgzU$^+V3cQVLRlZMWzSDOi~%OJ5Fe2Ec-aX)z`k*DyV3*Ha&oP` z%8>i@+UY-ZQm)yS8AcyW<X+32dCdAWHuW;d&?KXf1Z4zH<4+h&2Av|??<|gz;67Ar zb}^b!F4>hZj%3$)az~f<<%ZsKw?C9umXQ@%(-h3i9kCAW{WUv3+I4u8JolFECc4j~ z?gsL>9Mk?Z5^P#5K4Kx1OxPy)**8B_{q(7&jy+{gc{ff&h7(sl9{T3f)gSuEQtPJv zKFV*ght+fTU$B{e-AizQ3<m4ljckc$7Ky{~%%V*xTN0il<5##g6s)n2mxjZofY=Mx z68nF8{@DKt^eHns79EMp?7=X(<3$bl|MB9;rOOhr{|&2?AmL8ze|OE-T?00;|Dz-a zB4+B^!b;-%FD=(0P{k2`Z>TmLEDhHL?fX*0{ufp(Es28zHeP@T$kvJD9!8}0)2|Y< zT~dvRa~)cYW3$0&79vH8AdIH=ys@&2T1(0r%JV|?R&_&7z@L$skzeBTR|Y<llV4a? zT~N^-w#t{37nbK0lm~p-60)6lts>9BFWIt=Ecxk3&7|KW8!l$$rxRHuH9g%zTZZN= za>{!Mt8Tq%z01Bp?GmBhrBp+;I@=W=BOmmoiP*7kPsHAB=bUePwg8|V1L{S4Q2i^v zP0t+>Cq(*y_2Y^cdwTS@48RlqpCvi&(#uJXi2?gF6_zChS$?+uT>Y_q4Dmy<mdF&6 zh<NU(mC1<b#Uf=ED;@D%{4le!S><Dc4U@NQuMvfT|36Vsl9}z%91ER+W@LqmateL+ zzT7fje!ffvl_g$pPEk&1X_40_K`~7m-tDwO-Y@OYQp&B{z}sRb9YCDyY_j4gM8N-R z3W~F`GUl|w`UY*tE08u=RniE5w$liWv;LV+sy|jEw`fN)UbBM>ZotD<c_P}UZEh=k zndy!27WlU0mX#KX#F}VAEqEXyo8ZCfqc190hI*Oakf08tw`oi`T7R-P@}xKNq&J)r zjuMc((IF)|ObJPgO<re{jK@fqP7wb9%pkyOT!0nl09$VY1o00L#6Lg~{{TV!0|fC8 z5X3(~ivk4k4-mvZKoI``LHq+o%FE%T3}^;=febcBG{W4A4Ml_sJQ0)m(4~~71*zxn zG_~Xv6%_k2#6V<7sCNOH3YzXK1*L^4ly&<8q?W+3WUuO0;<qS^2?-qEg4z~?<4kZY zlcxLenkpC<E^S5)al$zkAlr-SUu_v&oLrcg%~vM~Ne?KHu^^2@V>6$$Mxb$*#^(F} z`KUbo`;#Rc8q+u2?_VnmZ$6l)59Ps!^58>x@S!~TP#%0J4?dI!AIgId<-v#Y;6r)v zp*;9d9(*VdK3922uf$Ovd<expj2#BenP%|KhvxZ5rRAB6Wp6>=-*R`+gH;G_zA;Q( zqnXF8e<DAZPqC-U2m6&>Z6J@iQ&y^EVK_@71ZT>)o+BA$laNs+Bgvv{WF)W1ND}FR zq$J2i{vVt^z3Juh&wbc#?|${w?wi+yhd1-iAM(zi!mft3an?KK-QvqBE80His3VB$ z+?li?hdRvG!lay*L*aZ{Q$S_8x;3)&D%(3mg7fo4JfqDMk>w;4ooOd+U1>#~9GSHE z(rNyaHcPXuJ>8$^w!iZoo5S>1c<+Gvl(o+~$F$-DE2c$~<Ha>f5lRz@;=+<xb12jt zTe74Ft5Z|#Q=Hd0_w<prVCo_E%LC+z7CV2VwcW%bF#ca?0^i4m^OuP4IPZAWjC(@V z1#{;SeZnMc%He=v$~h;GP`|!|9?r>ZZNs?x$a<pqfw(R}#8B4pNsJv>EWbu?XijKj z4p&c(r=)4o8F5L?La0bQ2_5Y`J(18L4|W4%z)|2hZ~{09oB_@O7lEt54FK&tn^Bsq z#PcX<iF3nx6vcHTCnhD4i76DOdoxq~wzUl>O>J>6>g<S~@+6zcKhAUJb(O){N4k&( zHP5{6xoJO(^wokyvR2)R5#&kh@=IzQyi5E&<CAktpGl6w5q&nunIYjloJm9<vrl%I zGd}0tJp3@=7}sPWIg=M;Vr`M+beULNGI>!ZYPQ4(i#qwt+MF}3IW9VOqki8o?;CdC zH_ZEndEYSa8|Hn(yl<HI4U1YYdjB5u{ypgZd(iv$fc!lme-C>99#`+*gWkVKs*`US zq3#j4ZV^{TsC$IEN2q&*x<{yc#I1Xry2q(|oVv%Udz`w*se9b5dz`w*sm|n4c%RUw z?8xlZ916A}M_G4BU6GOq-nVHiPcW%U1OVb6!v@^-58*W>Fo`xgwO5Y{u}s{r&Cy#g zJg>G=>1~v`i}Slsx@ISEtE-*G0qPp8s5RRiF*Du2v?2Y{axPb~t**oNJX+tq)L&fR zU0d5-hj&zW{q&d3ou1^K$F18pPk*6rR!RH!LRJ2(>_Am8R4vEq>60lpGI=olXvz&K zQBc#lsy5u;URl-N9}chTtah&}+XwV@p8eUIyRG}V9ZoH_-7X0?2SaW3rJ=g^P_TJP z(4KS08s}Dv6bf3Ub#0UiORgRApW#vE*EtBw=tI$Ib-yLE55ibQuLylNCBNXD-|3l2 z`a7BNs54>`9Cf86HB#2hwVD04vZonv!n;M^_Ry6i#j;AQiz}yFKHzzO@MrInaV>My zn|3!jA_ml7OWRWFhxeJ-@U@zrM4309Z<5SYb|jmbs}V{GKr!NRC)O0%Kj!5a;V3&g z<1Sx}BY4CSJmUIqkbidrW57}1IB)_u37i4W0T+R*zzx8$TBcXx2p(}pPFy=Vvdb3^ zNbYndyAA>@#p0Z-@}y>TV6x6C2@;Np6UVM?cgOdwvO4b=Xz{IQd5!-DHsrRf+R+`m zx1pkLQ&VGab4B(~^Zr$oroZ={%dTwhSz6iD*jzodtf6V`uC|`Mkk9M)_O$O>+hAGc zm2IIwP3P*`9&f<wE6wW(uZq;<_{+pVNzO#;to47<G4tT0Pdd@vSfk2>*?2hSQAmzn z)WbYIJ_V<xGWI2bsLaDfLO;4sjkF@E&qX87q4<j!K-@F2X~;d9_>6!d6QCpvqr;ds ztR6C2kbMz5Z`4nkk$5y%7ql+kUOil1d+*Ms>4`h?zPQzT`CDJh{rcZnmhXG7PQUr1 zva%oXt`=*Xb;)`^^;ftw<7BudSJ?|fR$`w*p>45#yVBZ5(nMl)@$oCLKXs_zH@^Dv z39?I0q%Vo0n9O~b!yOM#WN*31NU}mJGi-;pn74?OCYjw6tA2Cl>g0Z72@mU9xI`Mt zq$(Llvf(wGb2+whlxJ<=q?UYob^h!{cxDEh{MPzg`(uudTJN{S3DfE}PM7m~V0Kf4 zHsVfdzti4;ytS3@OX&KknZx}QGqD(w_CUdp_^ODnt9+c;g2cg5e5?xjpau*U41suU zQ!NaJ9?m8~`1*T#w*T3;R!rZlu;SZen?C+*|J8~YUkIG+Io9(`;N$!Yot7})XV70> z6vr=`d^h6l`VyCtJWS4@SpI|$i07-Us^@d8<)|%E93>`dl%wpASRphlxGx1H7*(qF zoRqViWa`NqNx@4Z5xF@_L|zx6w~nLu<j7H$Q{{e4WTLFb9_{cKk|c@zEv8HB{GN=> z+Xvekr`O!NXGcb|vj_U@{?N_SZB_P?w|29Q(#P7b*?JnB=An=uH}Ud}H?#PM8E<BZ zd}h3vrALE&kqq8?j`e~z&RYeK2|G*@I}SpV-pemhsmrn(IZJm|mZkR+;R1;TKcq;< zIXMMaV)zYaN8^5LFvSnq^+L|b62D{X+@`sX$BxsnYYcY$j5S@^wx+A4>V58tg1Zk# zdeN0s#Oq4@GVncsVY%9ZP?EOp3neY=d6A?dvo*>jx)Cy!@DxHMT5wJ!68+Kr7B+!w z=cD0`w!L}#re%%OYvqfrA{?*1QTgII1mJwG$2EPw*UYU`p3U|bvE6*`d9_(c9@xyw zD``X}JdZdUe4FTgGT>#$wfK(<uOre5PmFJbiL<hfCz~iSB>nG~%I5VsNsZ?#fq!JT z_KS$iGQAjAm^Q?}POhVRzUXt#%phGUJW!-E@iwVWgmG>huwp%yAA1^pDg9QkE=o9+ zZ1GCa%YN8Rbi%@575)bg6<|aURu*L!mf?98E-SRG>8a-IaAQMW@sifn(X)OFsw>_U zsa_V!XWCpA$_rE!d2g04Da!O$E-m_OpeB@;7pe(ted6&aw%mNdifqbXzjL^vd0kgk zd3(dZEN?F?_676n!kJ^mOB#!7>9<<gVwoj0ZvN|26VAEhW<T$oOCX!?I_Jb$v53{F zi<5%Xdek}3R59zCbDpL0?3K=WwraPZcFuEDzCGofGfjIWeUAK>tG0W-;hg(aL58@P zSs7lQ90ts}_yC=9&Joen-#O<V{GPt&oM)&C>rUr9QysM4>zrq)GP}+>&sOiS#fd`d z&rucjtIoNXbCLVxey;kIN3w9sxldJPRI-zNTs@+W(VhdyUHidO7*4bgB_)iTeII`@ z&K{sdSZ$;1A<8|V&-YULLA6&s&YceKtW^j33#Zg{L|=`lBPckBDK|p-4yD$OKXUBw zfwBD);pTlU;YeR!Ed0Q+@V4<o2ObD-+q?h4y^kO02(LYOFsut52_GIgGIIFwkq7zd zM&9rkw$667gWAS8KS&F}<;H`L{Zjjmk+H`P?mes;Wr?3}7*`MTzK3bMXi$gvwj*3m zAbZPhp;4!<4t}3nmqgkhRS)r1QnG_KKcaR5YTx+79S<KH9X~X2q+_Bh)-lREI}V$7 zb{rjj=)go*$AgdTd_>;wHZ(k6L&I)Ekx>ORM|hXCPcYsAbn@5#i*Ns3BZrS17(Wz_ zbVNEk`xpH+iEp_z(i6pIe{z_w6H3?%Oz^dP!RQFRBK`Id_e8(FHErqMb&(c6a3s7p zJaKsMgCh^`J^WC3d~_D+s9VsfN~5y3Q*sY}Jnfot?xVHqp#1~%&|YY8oa>|dFG*X5 z_QGf&arkTp0+K{&m%i<yZzKF-7soEnWOQvNf><3<ayls|<%I&m8cRYMV^D@r$qMc* zJOb68UF}`5`@-w?AK15dY&?AQ=uu6ibaOZ!k9PFNx;i3Vossaa&aOx-ym@_HPiJpD z8tDu_ICA8`*rAcbE7I|(G&7ih@K>ni{JF!%e45%nG4aTX<;!Ip@Cq4k!b|yY<`DdB zzW;7;)1nmOp;m3O;ZnkpeDLFZBoUGfvu+qb+AYB_Dz5ouNa__V%2#2Ut6^n4OvI6; zV5(j<U?XXQPstYEWf(5n!R>O5*)H(c4K5{?R4?3X1tV#ItzoMOl(+^SbsK%R9>>Ft zn7KEB`5}U7Z3VBlt2^Mg!wlD*^v#`&%-yW5+@s!sDd%2RAKr<r@_x0~vRQTd6^t++ zXI14_)o-X@Q-7#FtDeHj^F8$e^;_z7^%M2$XssVacm4<UWAzF3C+gqSPt|qxY4xY- z>*%nj;Gg@{$LQa0(y!;$H`ISq-%{UJuc&`wB>b(qp#HmhmR_Gyze!&1SD6p?tAA1d zM}0{BC#c~eM$SPf;#1JwqjZjNkH_eo$DzP~hBLk!ZucJbq<R90;E&Y%)O*!`R_|BW z)Q?!vzNoIK|D{f=FQ^}?*H|_E-)PcLvqJPg)!(b{s~@P#%!U8R>d`0F@2fAWKU2@4 zb-%3sTzyIXjrwKvRrK-CsjsQ8V43~0<xwADt?BpF@3Ox68TDV(AE2dwRQ<O4uj&PL zR{fRwPWEGm4s>>|?abKl*x_-Z2MZ8YwiK|rvcL&`2KtJB^z&T$8b^$SdnXP-9r8@g z%*em|C%@0-DRcC!=kmmQXymZ`#*~wKg&t)s*vj3nYuW<N{)Dgjs`?p@X`8HXSQmi* zVNF`EGwo*CMRtX~)gHBf#Xe=f?1_1{dUkm3_l$a;_q@*E8yT^T-^uuD#t$<~GoQ+Q zC2LpKSF-QT{^y(ra}MQvEawwB&*YrS`LZ{QzY=dn&NJ2pZ`d32uJP{hKIlE<o$&su z_ha6ty{Elj^Iq`&gLf)7E4M1QF}FMSF4|c?b4jhAnbc<&u#8`0jO0Ptn`fq=%)1#I zjofPjT7fR08;H-mqWU<l00ubUK<Oc1$INwg&&(C|4({iu5Ovp6cbsD%$NrfMls>Ok za=nM^T-89iM#{T&r`LOlx-L`KB%`mG-;{6_<oBi26Po#;D&xAGr&anrr*-RM)EK9y z`WVS8fC0|eQ+^{bNV!eG5Or+ldYIqu;Cd(LyMQ}^ySToa`}a`qJ2>v)-o2b#?98~J z|DB{qi+IACrmEnZSI?XUdjZ<Gn%{bOHpNvLS0d@H=8C8M8=5(-%N6Nzc`B3Axj+%M z3tr<hFRNaTec;o@tJGmyGKpNAsY|^A9$(Q|U&-}qT9OS8f9%w8UH`TpoDT3*O600S z{`GUG9f$+H^pf<Rspk@<u29b;oUvP;BrsP3-wHD-3VH6QrP51Mhf4)+N&Pl{wHmHy zaD5qEPlD@7a6JjGC&Be3xSj;pm%;UAa6JjGC&Bd;U-$-ip3-=}k7FjS6g*s~h4LNO zX`zf)L!Djv{x#ktQg1ya*?&ikLZ_{?vWxR>YK~EBFJ*+fH*(LkNa*yEx`X?}JeL-k z*1SPWUZ*9m(d(~4^@8gr-ef3qk{YKp9ryB!K5AIO^#JEXx)%9{DSjy}>gR5ugY#?j z{59Q1;wXZ<OVlC1HzTK?9yh)8ipIZuk>H_BV_fJ$dM&`O>M1F$X@>@*ys;aQ?~4Qd z(1?sEgZWA4J1^6+%MRw{J1>LzHyo@_IW*DE-8j(4JNuzx`5sf#6n$g*BnKSIJ1+55 za5)7or|4OCyidU`1XsC0J9o|ZNqy!QE2-bbjeOgE)K=$w-z7~|?)No1*ftdQV~uh7 zMhOkL0ua0o$hgu}_6+SHq9U!{#JC#bd^^WsV8_feeCspx>uJ81WdmS0Z@zoxIa=~O zy>uQdpM~1a(i)Wdls>wqS~QlgC9o{tBi|x;snxwIwC3k)1B}9Yz>JEQolyY>;0v=y zh8|(uU(dVKInf2$eTjBoqTT0d_j!jCU2-^)J31z5?<LxM8L7mKXK8^@hTvVOUie<> zo8ioQOv+n@{|RLX{}al%#9L(q2>+9@C~vzAh9<#`ylGOusY&;05x;KWI~#!}=&_kM zwQy{OCYN#E1}vwaI)Mnk?BafuV>kHi;TWTKp|W0%ef&;%o1qTjPgiv7Hc)OO&j-2Q z1PlQ?W_|!Zu7Qs$^xqX)cZL3wx#bEid`(l4aL)@VqeNP1W-1paE+?3c8_heRruDSa zP||tce1SKg1vlrN9yv=3&eDRj;OIO!I!h}q&<dHAWDdKO=#?6W2VF_Qk#G;e(RFb0 z3i!ALKHPCT8y`u2Epw^qE#aV3dM1{+bqioP=o_?1=)%m6HnL?lbM+c#+%E3NX{q5- z=fU-P#_f5&>J43<#ZP`Uz<0=8MHptjMmWEvuUXgSTFT4Q0DO22qoafoz8#tqZZwJ1 zTaDCPhRmCzrQSHBu~*Nxy^PXcq+J=I`}t)rxV?_tDhuJ6v@7|pZTtocGqsVJoiZzF z(`sN3eRm%{YbWkx=(BCe$9K>Cgy%nD?lsgurJrn;^#d?(u83_xEp7=skDU9q^BZ}e zaMg{xV+ZfrNqxKY`(&2h#>mQq;$=pc*+R;^Mj2_(W`1=)vcCtZdo{A=G9+mUmi7@O z_}^fheUuiSl39a0%aFk%+<lU}2Xr~PyP3O<+&#?Qcj~(~|E@yX?xEJtQ^zTEvS%rm zL+Jpe1C$O>I>6I*<oA`7c!Cm#dGF`J^`9c8okCWB79GJBF3g`usdyHF71?-OC382e zUM-vlt)mUCV+*||8b_2qm2jzd)0zR^_)&C|&r{c+BgLxkzCJAyvwFGkH-9R}Z;fSq G|K9<?*H8NZ diff --git a/pep_extensions/theme/static/fonts/SourceSansPro-Bold-webfont.be855452e565.woff b/pep_extensions/theme/static/fonts/SourceSansPro-Bold-webfont.be855452e565.woff deleted file mode 100644 index 58510a7b6bcf54841dbc6a89b2e4a408d90153e7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 26256 zcmY&;b8se4*zFtJ-eki~vaxO3w#|)g+qP}nw(}<0*iJUq&F}l}{p0r3sp;p;IsJ6? z)J%2Hw5yz`C;$ZTT}<NuX#btt!T&e@um1lRK>;NZ005-yo8|q6e1v17uc)Z9%r|%P z9pioj&k!0=E+#A@3IKqDf5-UWAOyhzfQ!k?DSdOl003AD006ts_~zb2Oi4u$0DzbO z)=+<gzU`~+Q%;GF@tgDdj@7@RZ&{e@W@KYv|IICZ=kfo>LT<MpxRHw!Apn5*pXR$w zz%Lj`xHwaLGn;Sj+Y3_voy!ENiLTVl!13FQO#iKc{=YyrvvxQA=GXxMSy=!e`oKfq zEXmx&z!(6~4g1zGe}nb&`T)`VoBZawzGH%K{6aK=R57=4a{J~szuW)zgOzpj%h+4n z8GY*v(7*Fee`6({*v{U@!0kJ);la0$@IQbef&gs|Y)k+EBk*s{cYi<y=>nu+?d=?$ z0086foFGTv+)50LRkXc>$+y=O@7w42jj)rp^Efx4k-o9M{tmzp6OtFQWGZRtz2JS5 z8<Gr*Ef*QGCu=By8xjMO6%zSd1zK@np#R<)1X2W7`5REz2@4AV{O8x#HwFYGX1|0G zzD9MA(*Ewo0`R><qWsUb|JnvKg!%Rx>VprY@=t*tF?^4u49Isc+<?VtzSc<(KS%kV zHXk%$FY|~6CubGc_}5g6_+M0vC@pD9I-Q}x)=S1%A*d%asv~I?M#Cb1RXS!<K;sez z2ttJ=XVoBX9Ex5cC7`&rO|B?Ra3(}rz-#>YJaMhPK5i%I{@c7{pWBst?72;lyS+Vo z??rGMCf?(vvl5}yUDKiq>*{qq+F7LT^)Hgaa5S`qM~?5MP$$7m3pSU1^XK^N78(8* zNOq@^$Dt!m97yaw$DzfOll$jUILFJ3vRQuP{Q4EQR3$`~eSmE0;{N+8*Kp?m?hWtx zNAgoc>*&UH_i5%u=d9YbC*IQH;{IFt^>L5hn`V3Njq~&8+4=3mo9&VGbb7i{%02pf zVv$3LVyx6(Ki|wRvm3d28LDwoHOYXuy#$*ldi<N-3ttV$cbdInG#UpSVGv&W%N4K^ zC0NMV@vSCc5j-`kRuM4BIQujOsxL5aWaw94H$Jx|q;X;R7~GUM$~))<NH4f&zrjim zNQ@s_zrqbBJ7i4br_Bu_JBVz65~GZ)RB=}E2fjJfb)X|5G%x>3=#E?-nA5^>JZPIi z{F1p9kE@j)@>{?f7CPU@gJMLq%E^+xss!4-$F%IYNs$ueZo|aCNiwwLY4ug`W8Ix( zNQa{FHR&{c$ADW<M}>&G4lLXKc#WCfK>Ie>P-MISdvmib@D-7IawJdCs$BS1P)C?k z@2Y4C#IJypB^kM}_P3ME#tg*IoWGdNTLa=SB%}*mZiz1gZt)f>9GSaYgpNsO)HNni z(3te4{hNKX0+#U>#?~N4(dLX$GWcSN4&16i+Lhj<)rICiLyY{|@6$GDZPq@;mVH31 z@C~Nnx2RlP_!=qqn20Ty-YX&}sY+Z}cQ19lk_q(QvaD(?JMGevGTLIby`OIEGB*9E z*^D`WwfZ`w88yP6md{K2!yfJ^7AWhWy=rN#xg1b^=R1V#LtU}hTu2?}TGx0Yfrv$G zR>{$5_gThG?>}@ZjWFu#jaDkV)s4L$&=?8jjPxiYizTm&wp^x@S*y5)zZM+;-M)j| z)2JR&(+16}nFrSQ6C*zS&h{ovR<+anl~pu`rWjT~cGiNheomh$df*iHD&JRXlWwe| zaHFlPcSmVjnOaQNDpH1@Q%=WQ*y>iYu0-Thky%oy-M1%PXu*swo3ioJj>dN0ZrfI) zGIT#q{;DCO6c$eb!OfR!(u7dW)YJ$x$!w+!DuX4e5Dcq8F8H4+`^rFl%J;*FNbAf< zK!X)Ps!yRV3Q292TSGr>Un7!h+Qv4ZQzlluR7m*nTbu`WLMW;>wR)+DkcA>_iL+>h zs2Q=`S-e`vGP?_WTdm(t0Pgvx8$wgS#|<Aq7YeGM=m1Z226qSA4Gj;%&fjQ<-Qh3f zwIABfFLt=UV3#}I_K4v9qc_(Fe<5bS@~jBzI$uz4El5y_swKNOy@yz<+$~%c!2Z}D zz&Jd*@1HnY;(wVjO!8(s5XE}IIE0C!Fk}-k?P|duN~U|IyV1r48$YTYS}FdPGDc9S z2`G_jt}=QIysMisz2+Ub;B<$-lH-3GOPo`D;Z-J*nPYU<eVlM`htZ^}<yX0@=puWP ztjtP!JJjJI&-^vU`xfIQiFHmqhjd6Vr*ubmV$lwJiEOq<Tj}YK{)tmPVa=P)x@cB# z1R0i|Z3>4T{JI{kcM|%v>FMyZ-SS0j+8IqX=EG=bp$6#0)XBAurLv_=j<)y1DCL6y zH(BXd4`TuYDoO7J3r9jiG6&mwN0O-;HYdw-db{7T;ED$tLvDs2N8pep5Ub%lQAO1E z%)^t<^7VJT#5tEqfccM=Qf7K6qDKT(i0TwpLv66L(sSUItOs2dX04Z!S<5=7VL_nU zl=cbeB@-Yv{r-Z5K`b07vYM*AcG02t^XfK9C6J(E_S%0|<-ur3n=u#OC&#%3_es5^ z_Vm0_vCY+Q=DBNaj$7)ONzt}w7LUajwUc-tqsOf?mS+_N2wAJ3Rpoj%jo*lr%i^$Y z8ey&x%SbX9VD0iyPn&YZlPU9K>(l9yIYHww`p7Y<n_wZW1&s%H(3FvrpEuN+tnGzf zF=?TVrNhCgc4SG9mC_8ABWHq;D`APl+LZ@=<&&PPa-%uL122~1Wah|q>-3bNewo;h z6y!=IBQpEh1-Hj`#cFa#h8ZZ~+qf=MEN3D|t=mp4@z*=W8o@6#x?kjRNW?KZ=lqdV z@nAV&&OS5r>XqT*)NQNo#Y3w(Uz23xdIg$E-<xx9)7H^joOXDGnuKv;Cm!VjHhO?A zZGlKdVfw3qkHdD6PsBLuK>=orjnUj{3g3}79l}ghU7e|l@z>tpE7MX_o3-kU0}t*E zv~`mY?z6?ZE!6;P4xwLSH;;9&^&rajk7aXc5*)ugQpDdWm8~kp@LemI?am6gT7ApB zVZIO_9A6zdr{S;?G_9kz?-_GFm%>FKk4vw7z5;G78y}z%Tw>|*@wHNbANsjES#nHf zE@wX1xRKz|p4QCmMom^m#7~JFaT>Q^uZYImi5K^TbU6wdhVj)CYZ<BDP*GihEDM7p z>;z`KG+bkO^Ht|7O8=@~vKZp~;f&Un4=o*edB;Xc9&XKS#<ujdzd$jKz2%^bR|#ZY z(|gB_!qon)JZNvLz3t7OsRL!jThQ*5X4ekJSXv*8_N=y9+poq|vpHT)H?&HQr_2U( ziCSp?Y{iX_=D_V$A6Y++Y-<#Tdl9_iC+CQ)&}xk`T~1V$7XqCr6x0?QxvI%R60eU} z8+e<!vt~aj9238eCz9N(GLrl*dduZGvBY{^UM?sSa&zx<aK&n)z+M=0ln6qpXF|{( ztl3S*&bSU_+ao<0j{9(yOx~y<9P_yH#~E`Q_tn}q7WcOr#4$^&XWyqmNeiQ9@$<LG zPi`qujW;0vWDNDDpX3x6R{f4qIy(mLB$Tnx(iC)ySLZlQ(x`wY|M`*ftisILST`6C zb>kkhb=h%D&R^^SN!P!K7S9AjIiL89r<%&ZNN~3^9;}TegvJq0m*0(kXWybb5^)$u zLPc1sEXb<?gE3C|TTE5RNA}vP?p3!e>E4rtvw9y~j~Yp!otxCEt`0MU>O4O^>!ep8 z2u!}-3oV28;rj%aF{9)TrpXH%of<u-leNQUFx{FDx(+{`KqH^e4Jng+Em+)umO(tr zpLob&-qJ<rSwHWCb92H565Aw*zfK2Le~5gLI_Lmz6FVtU)H-g#?1hy<Yj%joBT%N! z8;9uh3{9DIFQ4xP?_PvPnL;~8mpir{Z`Df^l{hKi<70qLuJBv0mnmtiH=n`*qG3Lx zW*&75<xy+A=vfWb7x)xEe0xn|h104hYI>F$&+%$vjPJ8430{4OVfn(??A5N>LwwE_ zFXYhs4q`>HLPvu8Fgd3B!PxK<mv$0qj+2s0d0*$mQzYkw4<KLC_&r(ufAdtsIfFSP zeTP5yFa|r564c{Har*io5lru2NWYM&2?2nd2`H=ov<C5}z`?$WzCOz-hZKK*1I!>( z&dIou1E`|*_4IU&wDdG}bZqQ3|GOx7`JI!!gNd@fyqnD6=v{)i*_w%>{JuVRoL{5w zfy;Q}6!i2U0McAIy#Jl+n)>PEK#D>lvx6Nl1iVng<N7s027<;7_sfso<T9ky2b^Lr z{)C`~K!Kou;D8{7V1e+4pbB;iW{HqQ!uDzW?&(r~U!5NVbVY)I0Kb5s0A$4iYE8oJ z*Vk9<7s0FE&Gzy2S8pvop0E8$|0mQN{)JE7et!tmBmpxYeXp<hF2%W0S!Eb#lr_Bl zVU#p~0E`aETqSjt^#xv*_9l0i*E?u{-~e%f;T~#&;sRrX!yRmd<OF4f<=Kx6O(187 z$17xr=m=Sf=@Dj%>I!R%%Ohfp><n#<?G=8G?qA*>pHC2ffqtTVgI$z(g?WbhKesU9 z@HUs(TZv{<T3zPj4aJjcHM-5Fm#@yathRqUOg3UJJzcK1M&*+dGTd7Y4Fnz&8>mBK zG~kEf;ZG0sR}YuytJap&vY-r)SN=*_T4wv4+$>wQ+UoVzC+_Z`gp4BL^Loz6yWb-U zNy$0dseJ{7dn=VPNT)NovJTE01@p_O@WTTx=tBQn9Das=ua2G}*Z`k^3&0}?1PIOd z!2+lPQ~-JblYl!w7vQfOP)DItR!abR3jqnte`t-61Bl+39tV0I%qmV;Lpw0$V#FZ` zjMhFd)b4|lCsYW0w1PDMtyClv7zg)@*IzCyDV-&}fSHS{(Qzi7Nopd#!quYtxZDv_ zeAhP6G}DK?2q@wQweS!vDhli;p<!k6IPCE5jqNvOK9v2z?>?(FAtbsen}>PX?#sv* zxXb%B$qf~lVw#boX-32o)aS)yYjML;sNwn{pjXeSjQ|;fzNozUFseN9m2#wQgVVyw zl;LVmM9h~4X>M5^&A*t-S>(YRV+iB$VqJwmR#L?`E^KeWsI#n0!_?zqpL;>gxmG0U zxC4S%r;-y8x?czr{EsG_QA#K%aE+2daOhX4pe%=L10RJvZ$c1*UBbdln?bezp92>9 zvgt*<o+(qM4Xsdm9~7~hExM5eMBavcR?(of7<E{E(D*n7m7e?&N4iLm_N7lIWKw<i z*GoNe&}uGL6gm@|Y@;ZQfShgC?H7~btqSd9k^D|q6&B^wq$43Zv+aEpx!B;{y!xH# zV{hL={!4^NT!aj;{<y!<f4}B6orhHZ!V#?7u{73We&1IB2ms{k3xMPX9PUQ&Qa)^E z>&Wdkn|+dg%$b!Y(@T_K)Q2}R#U5csARNZFfVIdtDq@yVihzbDE*6hJvTsXDRjdg6 zO?)Ijgh!j2nt8>86E9R9Ax;tM@P2z2Kt~s9L?a?8a(*i>#jw8FoMSdCCdfbQdDU%a z#i(ce=&{n6)BJhv=t#Ue`zOS8*i?2WDl6OZkFG6i>K?ROB5Qcos(d0bD7Wj}vGA=3 z#+5Ws|HxP<+AvNTsayi?U-B6_OT{Q*r!K0DY3QWRY3;FcD2y&H!U||CmhQF+R;m!= zAGj;|q#zkVoNzg!0Ie%FX2g$w(QJ@oRT`Hmk90DpO-`FeyuVoW`1pT}Q!a2d*^bs5 z33?sk+Ep!CHaoww#O$|kvC-br)<-tlLu`6$Peh@^k<ElCOD0LqPrM+oybk8+989rT z`oA<NBCA{;O;*7F1Hu`v=IJxui(l$EkB283^45;3D_kP3i>t5k^xE;htBDr0WUyJi zZeY?_TIqDDGg}cL@XgTevlkV{^3nV@q$77=wFNE3E{Gt_Ig-wT!8VRU8OB!`VxmM^ zJtSR*TxA|?{#gV`J4!2fa?Oj{>{H+CpEWp&MIPA=6a#uSM2la<>r{sC2N5yMK(sU7 z+0d$hTgke6`@3=1*v|{Z_R_1L#+JftRSM|R(w6@l^(zn%prjd;6MhVzH+1eJr<m8T z#>t}0pk|?HoW_p?X+BgaK9T0s7v)9F02MjPXiD!9PoH{@m4TFsMvYS@xadsv-g(%C z(rqm^ojZEyCs;duvkY7Mofv^A`!e4QJELX9!)`LzOt+6#EdJvlQu-=G!2gqV&+d6f zK&lU3&TAoW*({J;*J5tBd5|ye#4i2wamVhR&F9r_rxx~9uiq7tX<I4lB?tALEwDJ< zS0m&aPKi{PA5xt0uClGD$$Fsdi$W>V-VycIm>tD+6ykLsA#+Czy7QJChJXbDz1P0Z zbo+Vnrtw_getY+X|B~XF!=vJvS>xmNT9@1g2>9$%vO&;@=Bxcee2TZPW}6678<uN> zZVgeYDEQr~ij3vUOfzpLjDw|eVYUPiN1*S7W!FHKQfp8mA5D^!zz|575J(sqH0q=6 zL|3d;RUNNMTG!Lo)2mI1Y>;|zJKsfyy=j>UK0n9k<rcsA>wxSc;!qBe<H4Sw6h?<H zC7q=&E}fMmJ=D$HTh6Jy`;_!!hcK;cSJ?R+n0@ZjTC>^K;QVw{=*i06=`_x|@EVv~ zll5S@J@0rPTkF<!b^gG#!RliD;XGd63Yz&it);b*U~aLo*?ejIa*8IvjuVcX8s#~p z%8r33djzVD<C-7^!S8`##;r586a}ypr3gFEAhT(J1Q!#9D(*J<m#nrbNLYLT4@-78 zC>^V!X<RET;XGJL{8%BbD7BNEYf*-r!wcHAcaD)+#eR-4UkuA=Upa=5MRf!2=O`Io zCEiDwdPXCBl^!7=()KPwI@Zjn;rzC<?OA<8W7xeHrv%wpjsJ3zK$iUW%cxx|VjPWX z^Or28SXbh+nBqsIp7~efO`_c69r+W&YP`Q*+*p4gP{S>>SKR0BsuNg<HLfc|()D<X z{-^)JY?}mkXBy-B)UMzHTKj#3v>wq-19m}a^dn3PgM<KX-!j-u!(Yfo)cGeyJF2lV ze6pNJRytMCzBa2YIKr5}^dE(0c>ECwOB(ypkv24_t0e!W--6wYvZ@v5$(nH`u;h0` zWR;4f4uzm?`RL133LMknEoWS1s;+?t%7M>A<#)_4?}-USUi2zrQ6&*)lt|+0s5zZH zpX0w67_<$dYBg3|{tZ``(^#dxe++bnRhmq`<{W)4eIm)~5|JYL7FIX<u3!Akc#NrW zLrd>8)gO6O(TaJp)8?IPH(d`&ttGH>&_&>B%XydTDCVkvELZJmv2f9OI(X3=ZiIME z!z+Dl18=Uci3m5GIx$#ID)n-1&Qxf<dD3c{_G*2meNT@iiAa~s5XULgJRy+X3(rm6 zEGdPda67zg)oa&#rs1Gh(qdv3(qc-?zUH|3+5EEIpDTfT-#d7j5cG>Yp2KYRGl9K1 zw%Jv@_6F{5FkSOrUc3{j*NDtlJB_A<o&16sB(oTL>8ijqS-%t>)H(<uI)&?0ZsbFv zcib)_jd(nL9w~q;qGl;uZ+)Y;)3rGN?X<(Ulk@hpz0~Y_o9~Ueur{3Qmo`fkROEv* zVvqpCunOn`$w=Q#A>(nCJ}PvmT)2LDzUY*P=&q4Pr0t6lMI;7aOWtjr=1qBW<B~DF z7V)pZ@~4o4x=rDuTynT3v)TKH(s4<f4~xsu11Nr>)|RN&M2@VXWe19IFr1L-h75Kt z+Z5^4bNztRfNSMyKWcO+Xxs?-He$KWj?}6oElk=R7T4R#awHNftxnUHf832e*UR8q zR^+GqS}(=+4wUxQZSwC#_8iGV|3IAvMTX#a|H?W<|I6l$_TBK@M{S2^)@&Ps4q`yH zQMVJtEsGc33D*tz#fS{r!&UZkM=czTe|44p7i4cB5rs&cGHBAR^$T%hVPfxt9oL-K z4|Lmr0Xcbg2@E`65qSYT-$N*l0l1D^;x^<tK7qS;6q_2CzUOhhYIwe;&9+}&zgGr4 zw6)>1;w?j?QwuBnsQ-{)RA49vswl$oPYAQq0&bP5pvZ#Q0*}x@7|H`+oc-ZV#V|OO zeQd{7t`bOlvdC-PtP_-V46NH_A#0E<ehL+(6>)WRK6z(u3zsCW18pxcF7sLfy;3(T zWw<0i|4r&Gcmu&FF56B((l3mkl}JY>BOq=gW3=vWV3Wl^qbwQpWHsC<!&s4pb6|;) z0-$>lr14bXkP?gr5>cV*;mOHJ_Z>Dn!@+B>eD~g$E8lZ{P(FdBz1<Pa%%BL@0AJ8L zatf#geI`G}<#r`>6>c+S677YP{&Vb~_7bruxgJ^e^@J1U(;(9I=<-HzUoo2K{l)fU zMdLvc)OH!@p^for)W66A%2`-ucpmqK2(oxOS^}{{F`syHa~MjEcDH|YVDZ}TVrez4 zerYT`+N}E+PX4=s`huHNhx2s%VGjR?Z%6S^ywJ}pqCz!ZPzxzR6GbJ;YzcL33{~Pb zH8&pR7IapbPu}i{WZVTV4iED4Ihy}ZUKnw(1CE3Wb%Ug&pFPzZKSi9%I#Mit>fQu@ zh=jOTK^6_s0Ak^|mSh*cP+Nn`{%bYQWXos9(1un@jrZf+I@*_y%ga9SaNFF>wWp({ zy1n!KU*EqJ6DXJ7hGX$mjxMXiJ{ZtD91y)Bct(AQmy10`%qDC5j;KG&kda`;Mun22 zqRyz$m4{J=u|#>Q;PhTj_tT<l=y1aon9Ab6yG`M!r2-z-tI&V%a**fccNy4=RS1TM zkJrtkgPe5#OE+th0)`Hmu!UZckGFy!*B$a)VoUV6Ry@v5Yn5e*`hVGhMGIV2!uy}U z%XyYf4>uk#_hF(h(g1u&Kn<j6<9;VbGD^#$boS;ns5rNsiP5)!LOTS;rC}TS7tcT7 z=BBlJS*SG>|M4dM;;J5C`=BbP0usbpUSGR8PX}=Dzy-u3`rO|vH?+oNy$8+R|3z%_ z0dLp?8+ss2y(4S}*)gV=`>mJ{0;I?aFtTGJ@sYPq(1Zt{<Y(V2HpJ~Ch}`){_#SVv z{Cn?*Bv>6}yY8O}{Xq0cDTaWgNxv|84Ex)(ZD#)<DsY{h=v~;F2@y5S8gue_S6b^0 z6rW$^7)v}nDjd!qhpkQ9iTcAiM>XA(&%;HDQ`b^rs6e4;no(cp0}@8>+{fDih+4vH zv%!}xKv%2dVTV(mpqMR}zKGj9v=|8d;(@FoX^A|F#0(}Y_14WHW2MVNGmFg)5`ns} z$eTPar-*4n;wnFwD<GE^B)3bS#In8jP|<ej8l)wkWxh!xR0*vt<uSdTQ8>fCYQf-f zle~N%I{_587Jc78(a&E&KTod6Pw6LCijIXVp>YkQYz1qdLd9TsR~1a&taakEd~-}m zLU@%sll$qFnzAA?1bkK>NepNhM!w?0AD<m0C`GfU9?!tH>3Cdy@RZis3m9iPo7_zG zhNk4EZN5XRqQkYqqh`x5+)%x>)}^j9>+SHuP+;!{ujBhcNWz3&LL^g%WyevI)3opx z>a)E-YAQt3pe2ZSE4k!wiLhFbwC?+FI@FGNN%|1W_=!jYn&4^O*a1d!3S@3(M0x#u zbCKJzh;Ch&Hs!*pIM&e}BkqxLRIHk?Us3|bo3hCGe$jqEUc`gzPiyIVMI@VBXL>hU znf{G!Wi(!$Qh=3)TW#N^8zBEMIE?4>mvEQaDCCI@5NcudIeebit09uTL#_%3+V66% zakH(`FGO&;xm_((w?SbQs~dGdh=oeE9{yEm(Z;t~76ZC`DsJoz+f+wlGGt2qLDbgU zi)ahQS&(qQ836IvZR)3V?`vi_86(G5Ibe#QNO@#n^h(&{7ntM^G>634CBiUf&r%)# z**AEasDkvMZi|o{M1A;@R~|Lb2g-%xGmTlVJ{nmHLRSNd?~upQjrgjUNT0`3sY8U{ z;Fs%=!0lus65DPD5k1WukGWex4^BP_PEJX>=YVj*{6`^5Zf?;y#&nK8O9hngCR)g5 z0ARu49FfK69D(b7X<U%9<7;ojnCsU3)NC`*XYtViWFl|mtku#+WYnIiK2S7i+ZIV$ z{yoBd)+w)in=66U*cMm4HfxBvd_#Akz&&_lEkDvq@mb!-9-rHQZv0AmgBnSn0V)se zO~gdM3HF1B6zEkp>8?{kP8z=`+fPuDGsQ%5I^)pWeSPuiTH@3q$7tdEr)BE8!`D)+ z_214t947Zy-tLY-0X*}=qf>3xU#1&*JDvT1SNSYBYtZMJm6yypm}ZWD_^CQMNPoy| z3(TWr<S9N%3;L%I<**4a@;+8EW?(vfxic;sp^zz}95Kil*OE!PMa^po5M_c|A;~1^ zDA5EQG^+hoz^yJleu?=_-HmCJ=3v&XN!d^3*$t$J8Jfp-5KCh(fsG7!fdA=`@8Hr` zNn+s9hKAOU|GYomre9<!^97Z!zJRn+(2!ADx~+pS>Pt&NXf+Pspy0{I;~D*H#X76u z>@@a?CJHCQcV4G4|JWifFcOGS9qEK@d)&DAn0vnXm#;I!*KoJV^L(PjiCg+rg710( zAC&Zu4%f1ep3vkKIbz~k7h<)7yVa^#k$~0e0+0)MyYk7w12vv)XMIAP19>Oq;bZ3o zpJtqz1}>4(#)ZSE62u-E0h$_C2x+}%;-ryQC^+?c3YUls14GpRGeY?ug&$j%(3tmh zRo8A2-+DuMLNLd4JRvM{{Crfr&?Swaw<0|%^L-rT==iDMxwX$3jz2-FtysGP&|LpZ zSN7K4qFJ~r>+ucNt*wiIPEXRgVaU2oxK$bIE&^m)0fn0`q5=~6gwcs$E3ZVxR2hqR zlZR?g<uyccPZ6G4S&P;Pe9W&mdKX$W+)_M%=U=>DB2p@kG-XC+?)%`mXN}%=<L$q3 z8AC<S@?(OCX&9U5PA$Xj?)ST##gAC9(GFW}#wv8J{vKAwjS5bgREr@omQ31n1rvU= zREDsra#=PZEK`nQ9MYcx=WE31gLQ(z^HPDZJ|tr@SQ?TS*H>HJ2cDTe<+kfxZcjP5 zcy0Hy_gZ7j4VF7tj^hN|+&-uCA7W!(?0mTXwI5D=aBXz<6ljV@tY_LZ{15zvqv$FP za|x817ERbw*ca87$mh<Fe!@Y-w+`-x&Is$`s_~+CKW$Q7?zHp>D`PIcK<W1hLXR!q zY7+e6Y8iAOJt@6FS6lutIT4H+wn>Xfuwc^~rGX4f2=g123j6sAdE3zL@AcXB7rbqC zG*08$JT8)Na=nY)QC-4$A!zG%au#LJ{X5qUIM-||zvyVU0&VKI%DBx~VW>&(%&=Kn zehs2S`pU_g+jA@42i`chh;E+yteq3vLZnjSb+1~acFOymx5v%*PqmPoB&iGIIN3?w z?G=-z25WGPhtQIzu?}bU=gtVmA=`DIxqL4<QYb*XgOh#@>^%De1r#(SKncFKJ5%3N zdq`@3X7SwWjT30`X~UiEpJvs)@2Zh+|9tvOJ~+$b9PhsF&4ic##wxN3AS(euXNUm- zKgiRcxcWhCk@NklwqG44t8%h^dg8M;R(Kpnu`*i_6VZy>_XAsx%PT@B7BBQ1X6Nwm zQ7RU-4AcwvGi=>1$WD+((1Hf+trhljrC+2yDf^YY&ll~(ll(zKKXASsN^WR|8zoUX zn|SNZ@B02`_pSkr2FbN4;bdJ2xZb$2GOb54g`@eD;=(hClw`!^nmU8zm_iUX952ab zB8Zq=8KA<)=8zRcorfnQ-WqRB%+xe|@Ke6OmK({7eKs_-7C!rUpS<ZZoyifihSapF zmh!|bWaJ+<pCV|ossMOA!y)!%Fx-tS!^^1xO=B$a-N>xBPU%L$q77&V+`U0H1_@MO z89(G=2hR!eWMG#>!hDYg<8wCc%+4IvF=XM<$X50V;s*5R@!bGtY1g8qEss=*B^Jri z@K@K}kkAoymGkW3q!+pQ*W~?pYxDl#sym5<c_*g1PxdH9p2`u>Nwb=>+B9!j!~%j` zCZ1HAp%}xtXX-Qt;-X?=<BTF7^43%^oNH!ZH#7{{Wmol=_$sGkP*T6fl^&d&Uk?OO zqrrpM9T(h@t9&k{#R?^&ekUptgneJNPDaK9kHT|;#|`=YMNDhO*_>zrDwKm%|2K?( zA`@M}5CgdU42s+g+!Zm67ly?=WWU~<xK#X5%>%B>=LPw>>uu*w7wtj|;L2BIgI_i7 zbd>jbXKfy?x0HipXKP=1dwi4m16<*QHgK6)i=!#Sv?-&eYNT-lJyLjI1ad?|Hkm;) zjwu+B1qxoR$CA-2)uqDax!ZTe$Jb)X_PejemDUo$>viefZs&okiN=upW^^#w!FQ0M zB`M9^Z6qR<rZDvZ)U_)?v&gX&4?nUiE%rdiG>Kk8wHg9_4vYSu263s#%+(zeTRcM) z8v_?~9*jO@T@4<Gn(aki)Z1M!$tAf~DLH2jM}BtBAD6ISE~u+B*}zb)`)5~~w>M+E z9X%_=%L)juJu|PaxZQoCil@y@Hph(Eh6RMGCLjgXX$H5(vRP?GEx#G5o17(xb%$ZO z8hl<a#ZeuJm4H#_AzmOU+DVW-e&qHc0zm={un(c;tG$v+jR(s5GseYz_r~O|Ms*~Y z8@MI<0anMx(svFm%3i_rDl3TE{X2ZWAYwmC6WR%*p-N+IqQNv6ySy>M!`Ml)PTb_g zhsq%J%wdsUhD9kx*FBDX(;$UuGPpMZjbvGY(f=2j>i0O8BqgD|gNzwNr?Mejyz?O? zAo{-b9L}N~!^pV1?8}+CkY4w!PHn(@hHJc?@Lalj{sp#~zGgq(M4fyRT(_5XwZutF zsgeegf->AZ(JtA-dx2Y31$vtor9mJ^GFbI;fI;?{2Y@VbK2uV}i;{@Y11So{jgqjz zCfzm4($3&rE-5aP@^u$^c`VDs@NFUR@r%^aE;7;F&6yc~!of0vg@MC2DkO$<N+UJ< z&10JJbd`WcU<sV>8mWRqI8l{<{3TEexN2j4k9SGd8_UIh?CCfk*1Nk#8Wq?lAaVP^ zCFp-$k<VNn+pD3F&4Z22pl)OJFBD8u6io_iFd?n;c7d|RIF3s{#1gd4og~OT0L73N zL``p)WSKU*-QEX+csSQT!k0CbmRMl*FeakQ?GuOwO0*G<;v5e&2W~3RVhlBRM(+KQ z^s`La`}1RbGM@0Xz8;l_vR3DVL&{Rlp7L{5W&TBN_}^>4(AR432lO^323yy)yG}FK zyGnhJkNut9r#D-d-Jq9q-q>}GME~_&ZqnB;Yj73y*-I=L)y`3ZIi`8z3W#m{K`xP( zQ;UH;?S2mx(VHtld~k*Kw=zly+P3|~fFK@Fx;{9N(MUF!d_oDQ_6llJS00JB>HeT~ zv{y`uFMh4omMOFH`kED1(8!$4GMx)@?ys?%#Pep?C&b%Wzt8KxuS_zLNY@1}OGt0c z=x#^*70%T=#+m~4!wOG@CCAG6m(k&nto!=cAI0D;rm)Q);xY5Tp2tZv`7E@KGHlsa zg9(VA%sa;wWi+(d=CzepCy{P&Lk4D3tkXD{yY$;a#d-L&8`R&#Q&TPMy~(jAQ?Zhk zK|MC>d%#>LV$3#;$6&(+uuy%y7zJ<yC`g~Gsw`POHH$C~B7wx0=w<0>aK7o>+ERN$ zADS2(qxAYr+KUo46W~8X(*U8^;E>|T+)6=J8SE)hr7)Z%H9P`>*gMefnJ?*sslm~M z6g@V*b*dYDOO^H4vKFJy9DBO#+ld^*N#m~iM}ez6E=&(=GOC*7eWU-Z*$m~Vs+q>K z{`7Gha9qit99FkB8I8EQ>Rx~1bc%Mn_+8^B+YwJ4L)By2PO$xa4fXXjRqhF|^Gc*w z?V*qzcn}+lDcl3dup0PWWAoE#FM2!4;Atfy4~xs2%9JqW^(}~cV<@KN{qC8=A~zlo z{%nil=Uwu?`=!vdVzXD1?MqX*nlZWxQ)*6w92!ms*>w~@PLMcawWV`p=RA1KB2*e4 z4;fvv*b8HR4V!9f4epa<FOE?t=bN`K5K{Y*#{xFMhcujWJ={woI>`F@^OpTxhvS3G zaF06#o>lJtWnGxv&!ElJ?Th2K%?0$r0!jbg2r_)|qMx|LLWvfg)P7e<6+b6z?=WiM zHiLrudtWAZ0cvzOI9(~%l_b9`P8IFHm`m!;UDq=XNP2UM8D(WTCiaN*5Ou1`K4F8L zl1-Y>@7ES+6^sxPh>Go2$G>X=PTve`qTJ_bt(KZ?nTeEEXLBrZd$kHDxYO5VPMd|B z{uisIV-HS6lp)CTK2zp!@2p6wBM+x25t&e|EDMsFVrcI!)DBFx`>;*aVZX8gsoi-Q z5DHZ7-=$He<ikO2{M3EF3(6skF#X5VV8chXb?s#-i477n1B78Pn`4$Te4p8Ok=~JP z^cRhe20Sy&T4&WvTO+-JvpK%PZ-WG(O^a4o2@MunxkR*gG<i;t7lWp2p<Qm^$TT<9 z=r;smV$uhDg?lKwu(pulxqNj_LigQ~t5rE%Z(4k7UME?P_&6Ps6TM%NkPEH0moYfC z)nuf7gQ`3E;M_xN^fz-EhxuGWvIaA9Db?r~U^xZHKMz2%jcTK6F!sD7t0G(u@-{MH z`mqe@8O5kWHi`QrTE4uJ!O<tf8ni+mZPm{Rn|&WMJlT3*xf0mv%{&}ur(TRtNEF-a zVyAj|U2W+oa294<<FglY3U~o`H`F(C!x#?Rhl;4vDG{9Oyns;K$RHLj+Yf#Sdd~_q z0po@eXj$aXA3W-92l}A;iNDMG)`<0WTcubSp+MXbI_+RhaAXA4r5FQ~@Ht;%yxq(W zwuX^rx9(rLfbNR2DHqxGY4G0S70t1;GgVw)#UGP^RA&NjzZ~yArFUlrgyXuzOWz3? zWvX8>hyep2KG6+%Icybe^;ZJU{s1mRid5WF7YV=GO<J$B5z=S#z14C08U<5w+W4YB zu9QDXgARY3uk`*K0lQClaHa8mF}Y0A|Egvw@6vJpE0kl|#pt9`XS7)>VZ|csSG&9^ zTnCxTA*tCBKQg7nI2*?X>G)7*r=v_0%m!O{+UYDS7f#v2WC?oiMURYUAW<GBe6P69 zS#I8u#v>(uhNXT1!KBfQO%3mFFB9w?9#%)kZJFu8;y-`o)_n)@ayU@1Fu`?I;YdtY z<6LfniZK2A%7YaAL}NszsuS#!aY*E*E@{FKVeh$Wt{8ol%5{<=G2N29)oSiY#>@Ye z$tUGek_=giWWO(=e$xOPQ4LH0iCS49dx|}jr6|C3;3N{(Xz}RE1fj8pvavMLq*Jh0 z<wuFC%{94IfBLd+_g!i-+)<5HdUIaq)zvtYn)e}9r72>SB@-L1#w*6;bMz%xEmn@y z%qG(gMWxMrQ+BUL;V*JFa?8O-&d<S?nVFXKpO=J8=Y5}0Wj$6i!-!=$g{QizoV$h| zGs%$z`k(8=3McvM43fj;&<}Ubnj8V9Dfh_&sT^;gIn2nHOIX(uUNruk)?cER{ksTW z=X<rwWFZ?j7c`JWykz)?Q(4)W<9AL=UVak8o0!dFh??!-CC%tnKRmIUaKqCRg3I-q ze#;JtW3EvqYV-}ds%1x#MRJe8f`n;umztQ)y5?pJSR!Eg0_SfRXXH|0Rzs$kX?tX} z1Z4pTvi$z)H2p-#0rz%-oL&l3l?t5i>1m7l<q8ffMLbF9mQd89H!dcrt749@0Y<{i zlH#TX3W{aK+Peb>FmWt=C<rXV64foyalx6#+;3agyp=ZG*IDaC+5`@ka8a>}oDUyo zejg1+-U?)*!Rcl7pvrsdAe8+FI${-5JLKD?5An;u{z$8#o_xK;(&nq(ZsUE^5RyK` zJ7@c!xFZ|#ftAF+?cy;h!-VNn<_le7qGpY!UnQkelLvdqxgAs*#5{AEv3u@MQ(OkQ zKpsDKa{pn^rD_)J%a$X*qk&T8@0GIeS;DXf{Kb~B?oXaDFgQeKH{R6!xBQDIS)~Tf zh#yjGbfyRcP3xq$ya>FI3DSyZUl<R-^+V^&7?lnQnXH(M<G$?*E%xxGItVXw`PB)_ zVo8=o+A3Yh_X&D+g}1l0nu(;%F=XRk=u`$gNJOCNnWxdDRy-w6+F5Y3n?4A>MDw|9 zDU#LH1H{@osGm6u+bn&+0g4&yn3n+-QM(eUw$}aT2@}L))S1o{+WEsl1&L9JMH?`X zoRUtv`bRZ&mjKw3n;-i!gdn%LFo~FR2AmZU`;=$<FM{ewShXp_-EBN_gUk0@w5zL{ z_3f9L3tB@mU&2G6U9;fj&mOrqw>Ou)O<9JNmcMi0%tXA;HTcsa=6wdJ9HX_|aegp_ z>12L!DwtGYFsKlk(5PP05bc*!BcS|%L=nad$McIq!b;9Pq&U1WP%>MuqdpuP{b@xi z2=(lrK#xDCVBJ818tqlt#Nf`R))yO`D2O#k^Hhf>GlOUh3o+6^RDNI?Xh9rs_Ekmz zJo0I_vzw75B)dHc?%wgto$1HxOt5RKQoKpFm=LyZB<*csRBtJ<K3uXw!Joyw9B6^Z z=?h|eDxKj+?@l>|*UDp(7%JhVcjM(QE(;jM$5P}gL(jok#$-8GnJCp(Y3wE{$@VlX zt~p}338qi*rEwuY`qXXsg%DJYqR2Z!hR;B%MhPdf)v5C!4Q2zWTT~FFD}zS~8K=|3 zZ8*67Z_O(!btrQAqy<vwb0{|axW$e6qP^U;Bj{@JH_^+d0BQEYt4frw^(}B8AsG*` zwc18Wu#(*<deuUm9-16C_YYJaDH>ooK>osR*Yoy5M_D>w6NAuYFfNnSDciv=l2|IM zg`d^3y|bq+uL#ZOo@^ic)Dy?_C$mVqeQgYSNh0wDF{4xHvBkogbEH4&Mq(@M*&}PT zD<+a@M4ab|>9O({hlvg5g^BJ7Z_{9DHNz8y(oECIEI}&T_nUr5uZ|>xp!)E7eVi>f zvxIl5au;2K7MYGRZczaPbaEV3f~*N=NiM1Q&9H;4vZ9ug+&I@kqtfzr9{hr=s&;Th z&!#~goy<u&^FTZC+h)P%<vpCMbbA7pSY<OeBrW-F(^kI<U4p81)!?b%zDy~49mn3E zZO>){WFNq2SZ(oA8|KrXYsumI0O=Y)s6=^6v&GxcOi@9yd3_B(;Z;bqBl~Gi)P)7j zUV9n1X`V)Ja`#Z6XGD5*+X`w_VzRtgE%v_g?<h>Hk#Tj{j5LcZc)5T~(oBo2i|tz4 z;y(?0FtVgK9hOO-6=`~WZYRCI|F+e$rr@sMbk%;|>0xY~Ly`ABUf-K%RjL1g$AsEs zp?J<FAZN<3LDVBmi%i_b)paX%i(=OZ&-wjNAG-`(2{G6sD=MTY;YwThHx@-D35(+t zDdxS~s-mI#Q3Xq;RMj?7PbF}M*0;TQg<Wd{jQa-xpQ>wlcvp3F?jIr_X4${^jEU9v zf9H59mN6N56hYqxK(=AUh9=y2R58N}z=}pEqOPo~q80`XP2yp|BgtUJVI(Y%$NsH9 z;+T4FI?=UjaY>yus~w3ekv2LfG$yBx5xh#VhI$l#?#eN*<|K$ofyRbB&Z&<w2Ev)& zIH3G2Z{LYBIUK|?@u59l__#$W@PGIbUo=aQDabF*`gT6u?60C<<I>XAUTgANROGE= z17crL{Bn_xpYW;7<<obclU<b=#Bz}*<hk47&cM`G<8Kym;W#{Hn$Qj8{4}Z##9JGt z>uPX(KBbDPRr;5<{&N$F1HgOAc!XI0N=#RISbv7EAfsH)38u@`!5!Sx0tXJaK|J?` zgEj0Cv-hWrJ;ElBeZuH0Tm6L{v2FKZe$4<UWlVKhNhijR!ex!-$GQ_aSz@@l;WB@h z!4Jqh8zyD70k~IMA9&e`q?%e!H5+ZTbVVy$TN@kJRoU>W^|px(*}p2!cHEDTQQ20m ztWD&f#eYtTTi2VP<0-zF=0AsXtJhifd*y5{jIC6eW2o62m`zz4Ot}|>N>l46|7dU& z`1{(^;6`c*xj%Tzwv*sSQq4L{XO^QDbTMWrWYs&d?5iliN8-gR4A&<SMQJm-`AgyL zE3WnJP!A_ply~H?j;~dnpa#HD3gW+{kBZ_(mAQ&-wSrSg-ao(Vk{ftc5^cp(piz(g zl)6+th$-!^tlR?A-gq2-99l1z!fN+pk;45Vo&O8C$hdtp+TOwFY5X&h{^nY3z->vW z1}<{~nvHi%zdI6{3Ki|;pAN)O9;I#<Q&ME?IHxr0@1Wt4hr~pZLhgqbrmPEDUaH&e zW&PR`YOdBh+o)@GpB{i|EV;*(oqnGvq>_uTozm{Ne0Q<(?us-N14f4Rk=gXf&>4bU ziWD7kC|FAr0lNEO=TNe2{2z#qDux5RxWyT(!&bgGHdzaLo)?Hz+eBh|cVvsdH|&l! z$Nv6VX?uZ28xg$|55a&N(r-~E)i9W!c-iLIfa`)7h&y7PrZDSTD1r)FuMQmckQUaW z4gnGKV+bRyQ-h~g$!KH;6A8nN0!&O%)9z0+MT;Cr^sxb%M%3Kj8~!XWv$<ZMtk1bU zMd9$Ne_mYe6U0@}Xgwd6hB5uCRLe%fD`P^;bztsdU3Gl6j}t#el-X^!X!3;=e(zA9 z3~uMuu?y-OWDrf(=e99G#SJsyAgEp~FY0!1Prfw&_()KU*hK`Rx?mDsEUs!RN@7Jx z3aPItW;QSHzv5ihpIzZk4y8BVRRkqmBq~XzFEJ`p<H4L_Z#U=R4nwr0ur`YbLK}B; zMx^SmA5E)A;y}5ZIn}UWzg6-)Nfat&eE_q)dQ2>P!~!GI>3Y+jzJjQs9Og6wR$gCT zU7wtme;xHx&c+^PvaC(sZtC{UZh-Kp+53(fc$Frp$g9eCi&Fg_Y?3KSqp4RPKzGnA zsa=v>($ACCBQ6-9YN^teeSw>AR@$-YEbOc1`db|QJiCcMBX%xMW&bB)`60oac_SNw zdOhkxXIy+CHd6XkMm_z4O(Y5fB@s@D9<7pU<cU>A?_mnfF@@Ue=GM$3Gs7cyed)fI zNAA<>su79%hC02a!*eU+YI!3kYBYDVrNip-ti7_;rlxXZs<kwgT7qu=R!aPz{qW|K zdNHS{!J!+F&H=HcA+liSyd?0VnI;7mb5|A;#;_YZn%Q&acQC^bYnKs4TVT;{%C3<o z^<jQISL|%Sk7$uxp7c%mk<I!nc|4bB6Ulz?{;z$IgfzbDiHoc&cjU*bCFe_-JCRG7 z%On@{sq6Xk0<pK>TR6P(Vnw?=nJKmlvhkX3efMdLt7LH|8MnwY0K;V^8uR#nMUgo@ z;ge|qs4edU=yjGQ8+Dp09L?<0EekAO^i_ZD&FRa%otuRaKCvVW#w8^hM<}Ir^>kUT z?CZECPE6onYj*-_pWMKW1bf7EG4^v|JyLO%Zadg!k^{PJswNK%{-DEz!HBM6@l0_C z*<4hh<-O9dEDP@?1oa@<*hc`3JbnzBg4fh@{$DigaeUa`Qe{B80Z6wc_5Dc7Vo_<* zlaWFvGDC|~3v=9{r*E_C;DWo<*wd>k%?6tH`Oe+qBGi!&qt!54Y>VYn^Ha24L{m#u zSx4-()jGCK#@lm`bM2HxH1igh=V(_q605KGqEz<f#&P0IMfvwHMBW#18>#8;zZvN& z2+k^KItn|xTp`l~n1B3UpA`^Wg<_1_0WR@#uQW${xc&m7m;+S$81U}?_4Xnvs!Y9$ zobHlV=SiXtcIRgrjjF9bXsax3be12Dg|xJU_E&-CKh0L7k%o2h5~uM-ob;Bc<}Q^Z zEKI~T3uYISO-!Rw)f%{y$oci$ohtG2=eentr`NI|AW6`AgB`DpKWfWbM|ayt8|)ip z25MY}DSE9@FCg&sL`ZoqO_Cd^hB+wDPD2nQ8u*5~`0VGsJ;<r3hAED3Vcwx%I-*6k zWiXa?jKTQAt5#JJzY;~s5`2l#nzzjpbDsBWs`=D8FF&s!kX)LaW;A+zcJ#)%KLzf> z9*bNAxoT{Xb(f4UR}XCO$Wd{5dF*XX>=rAoUihqmZE^2#6YgMkJ8U>HpsF-SDfSUu z8MMYf^rm*(6Ql`3rab5(%wwpPaAHF@Qe_e`#wq5{MwU6}b{s8<QhGQanA7!PW5g5v z=S(-!8QmLxO(){u>V7smyG$0O^o*|B0M8kGy$x0y_Gz5QnSC8@pSrUXb5AxOs~!hW zFR6}LhEiYF)3YaO(2n4=I7p6n07#97klm4JrQ~Vqv(Q(#Da>i`YbIvKA1wua%t`^z z5UmovX;Pc9+HE&ugF|mO!Ei{4m!%R1nLviiHEYyy-syj?u(E#cx6-plC5?;v2F{Kl z@DAWf{0u)+X|e~ert3C;!Rt>R-4MR?`!>Wb^vUdd29xfAXvV6*mhK>Md#;^EXLJP> z$a5o*nutrlV4DnMC{<WUB?q=B8yt3!xFTZD(!)d9lKpV;Qo&S`B)u>nbg}aql#7g` zKTP7lE<V{Ab1B)J8pgg;eXkK1M}gkM0W|7@gDM6va2G~9HpJNRgGx3_^)rEv4r}uN zo5P<73-Tu$SL2napv5v?so#gHza{&9P))S>cf0jzBDwob^#N_aMhEzC^NFML)Lfgf zDX*mXSDj>v9I5N8=kfi`E86AHHZSTX6r|B)_o61HOO>WGv2xlDGzC)^aZ_Za-}Qc5 zmTMv3f#Y`8Bv;|N@(4M6ZP(+E<Uv)UiEDJve%SVQ4Q5=s&hW+@X}Rv`ho$3Fbod<h zY4vnd=6MO6rU*H@pc(L^;I4}9mG0H2%TC+e^|`f$g*AF5H?56Eu?->O#f^<pIV-!_ znT9@mV-WiLP3ci`mlu(Kh7oRd?1v<OOa`2+l=$gfzw+#*T*ng<fFVUF8lMX^A=irf z#A%<JEO<Z&cJ)@tR_>Zff|c}$ZKAZ}-Ra`{#bS}thNI>i$!&fYd9d?4?><#ts0X{> z6wc=9%(5|nH-6^ir77vR!d)GlN`bJH3tVP6u_QCYSUDyx)xKk(XhPS+)T#b7u@8`1 zQ2LKG9BGx#uXf9?*KECv`S;tpgufeU);R|7{}N>?aeX(JJ@kiDQm<^%Rt8VBr%L^1 z7_Y>#6f;h5`|eE)JTIb5tHn8v3>O4Onh4L~mp8utgj-7sPKYWrO<NnFq18FZ7Z~Ix z4Z}}2NCq_3p~r?OsgicHDVK=PAD2e^gsTTNhn&gyO+Df!o@X2{$#^<rNeGv2EpmB# zuQq%hW<J&OTG`X436ZVL=<$%FW<S{9^ThJhy-Pjt>As@{uwZ2(Yy<_TXTV)OvS3}s z@w4_yQ-&aHh--888@2<vc|LDdXh}(0nnoG=Ckvcb+{pH?O-{LLgWRIX#@;=~gZFAm z!x@VKLeBbnN;9CY-ad7<ie#Et<zdeZu}{OE2{z3|kF!4aQ`46$v^F`<=ph$mtP5#d zs*0ZcZ&cMFCyY(u5*d@Yv&B`Qmvr-q$|v+0Ys!)EBC;j=<f^R59NG%uq|((z2OsM; zSj~&?7K&8VFV9o*s}K3DLyoJJb)nf=#HqpQ%#elOAFeMi8Z%e73O6>NW!gtr1&^!{ z-Z3PdqXyOCO3zWCvR(R)z~|nHAN49lfebV27VW$j3q?ak;*7E;1Hwnwq*Or2ky`G0 zC8^GgbE#KPVyWYq)|2KZd&Kjok1E!PQ@$pQmqi%!52GW(m?}?Y5fU5dVpbTg-a&_L zAjbsPUi?E%Nxth#xiZ!=$Pqha8rY>0)M0|ob<xCw^gKH)F?~7_y_w4q^m+5R^B7m- z&pSok(DxyU!#1D;EP0<*RT-DGb|{h+0X}c1^~;^fz@|<p;wA9qH9z+!yFIdJek#C4 zofnm>?*9bMB{JGc6gDOgW|Ez>Lp$}c9MXi53^<-v2gMFaw~!=WQpFyY0B|5~?E@m? z6R-CE36dnqZ)#^xYiDQYo}#_(zH!MokIrkcaX!FdX)fi}GpGV9v`hQ^h))$Mj)5ao zGp<<5PbUHS3xM@Rkjh`r2}Q}+JA~`NdX~ai+QS%I0G=A{{_wa!lX|HO=S59gs_!L@ zIw)Q_ZL!*%em!py#Ofy>)2<vqry>@aWBZL2VO4s+w>O-K#1qM|seA2rmESI4b67T$ z5OF{H=;8i;tGUh4u>l0*cYNcgn{foo@g+pl!cV4BPqzPQ2gUQqo5ebBLLiY8&!_wd z>b-fBY=A{h2I!si-O(JWxHU(LnHP^A$i*~j;|E?8%QQe)sCVt>cu`DwVW((?cExb2 z*H2Y8fS0sU7K<sscVfzH1XnDC^@WbIJCrre{K<jgDESa=(DeJ7KSCQcIoW*wDE9FC z`q3iIZUc*yZlV?m<);pKg#BLSTqXEf3GNz~nt<{Xil;otoQk;4m2~v3kO#zQd>lvC zpcvJ}Qg=mhrFV_9)TGM<{8*1tf>NQcEIJD(Q5Nc6kPS`QO$H2|qX{5jb+L4<9_@{# zYA4{wwKc%h3AOliLKQGInH_~t35R$BPW`C}NA99EF0vY*i0An(Y<sM(SA{b4q3}Is z4U2DM4Jjy!Bw~q?)=*ETS;i91x^>Mx@oBH^O4i;pjhe_8zBi=}Y$UNWfn5Ot>sqnm z$cryJ%x(Ox`E%m6^9dTx)+NpNteU&5DLD5_i#H5k8bg4wH({-S^#s@-yOv9NIM()- zD#D;;nQj$EbjaFiE37^@2u#qRiMGrdS;3Gonl{mAw7S60`tMZ}Xukc{Y_BW`DeaUk z@X&H)5X=;ZE#S27XR;6p`J8;Ng04DedOD_db|j3%h+VQRja}Wl`~JuN-(FsT_Gm## zQ*U?Ais?N+Ur4)Tw;farAw4e239N6^xP_im5B3fj=)8bT=ce6|?cDT6Sp^rd%WT*5 z&P^K$`NP7P-J4M|W%r-%zNv-NxaH478?#-U|8LMBxRW8%*fgx`CsY3Yy_;wdcl<ez zh<q9fxWb!hka9F+a#2`M0cs?V56KWZHMgLn{!LPK<h_S2i%Q0%rMEYaC0Tm*13dxo zB%4RmQ<R|xr=i(&D;!fiaJ<3%=xPHapBUi;T8n55Dvwrrz(A1Vw9gpZuE(T$s`Ih- z#+`-r{_WDr_J$V<8@!2|$=|ttQ&$)M3~k8k%{Az2IH2>if_vzeT*Z^*jH|^a>@cDM zTgw^MfyIQZ@uv(B9foQh7OWdF86`X{MY8I_BvYAd(7=l_^|(fFioolBS9W>10M&?v zPHtV@+Pb<oySTlrjZ?n*)hUhHMP7NVt?jY4p-uV<g=YFXw@y<PtW)NSz;FN2=ykfX z>y&7G+QItFZ8>k<O#KZT^*3l|xg+O}2f?RI8;MnN;i^Nj>MNvSnzU%+3)lcjf_Yni zy;@m{*>Re1$exV6VU0Qq+<89e2qq*~pIEc{WN&Ad3&Ci(DjKZ{N3%z_Yxa^Qv%3~A z9?G;~3kSwWqvIoWb*vBk0>>FUXpfASdw^y8fe#}ac%70R`Qa3?m)D-{<@I4tf+EMV z^$OHGweXqNTGraja<BwrKrXkw&}?Hb{0MIFFL+Z4zfyQl<H>;5#=C}I)wXW@GvUnZ zgV}yxQm4Je2l;yKRodIrr8Usr>kwAqWZH1ytfz}|NF>*)huDL~)hNoK(_b<=+$X05 z?1F@CDZ=?Lg|s5t=qtN*hqe#&c>$p)KZ0g3S$%W2_Twi?R-D-3+q0tSigtEn&o)`H ze|KRMbp}?VWAKv@>CyYrgik=H*<d%?KC6>j`W&6qn18cyw5n)SM>X1jysqkDJDK_q z|CZ%7DE$Aw=>dC?PtU8n$<$A>^q|5WL64hj|15eupMxH+P7iCix``rc9rCH-s7+X8 zUNVBR-d;A>0BAcvX$x|zZ%-YT)fUCo0+3i=ER(UkEvbq{Qe@0>P$e6sEwUEsWzd8N zwoq8GDX748(?U31qgLvVc?%lSXn-H%{Gd#8i(<Ny{RcYY5*)Y_z<12|+`)8ZN~E32 zW{kLEA2^nrS~9U-flwj@#2Mhn2guajA5S4skgDr*SVK3@VIkn^TYo3!;jz7Z^mkI+ z0N=U&A3#1nAW`JM{-yklbMT!TbzE|X?!j2-cd}9;n_jDmeSL#GF_>6NTFBr49Gi87 zMBco#*t{shzPq<KLo(QSa3cA~seQy<UXXVM#S~RsEa&2kQQ2dc8x(D30GYISD2lC& zgAV$Jtap&&*iMx<(V)F57y+TvL2FJo9W<2L&8$rX0yEDebjy~JXxA*dcWle9&qHGM z7c2%q=OAORtDpP6KKsaS)H}S~#>;8mW-)-P;)`Pd5DlFtMtjETU_@F??2e`EwC>mL z!>Ne&%v40h&e~y3R@zU_sWv+uNr%H?3a|>E*1WhANj6hrJdue$RRSfmZaY~?8c7e1 zme5v^+IpNWQBQbH<LCd_$~Uqp6a0Mbr#NUr+y9h4ml*rU0cXiv7%S^+d3GCs6c%f_ z;+fP+2%RV9y(&d9no+;GySz&8E>Ag}wCl(uzr@?TMWtcZ4WBZIL24U_?KW-Z!cFk( z=En1foq))81{%E2!IQ?FfqMVgt>`&;#`0{J!~n>&m2(1C`HEh_>&kSc7n-tlrUhW? z3Yba|^#a)fj?Izq$}b7L-RyKw@KNZJvsNwJoQ`MpHVx`-@C-gWb*nCQG4bbNL#9zZ zpJrbk%_BSMgJX5l7wet$K&{zdSj4);X^<9M>TjYsk6zRZw`{6^3S5e-x9qIvCxLO{ zM)KOlm7;~Abo(-N7n`y@?rxyl&1%szJ??Iu*8zDy@Y+$JH@mxN6=bn*4DvH-=QeCN zA0bt5UR+{c^pCe<y<sXUsT}un>(~$LDCWj-kLc?t&#a@`gkFeZi>GD%Y~VR@>WKh2 zC*$cFORP9%kws--jd#FfiN3}#uF>iC7iZRpC5YAKW32I}b8)-X^3sa-M)X;>OOL@( zfhP~%a@o@|hh&(~EuAyyYd@gx;W+N^#@Iy!@N!(OFk$mkX1TDXgLXF-Fk!KIZgU5# z#DKYmbst34Dl_ARgp-wd2h|wma?0$Z6$JrTN~nlXbuq?{o5>hCB`)jUjOK=cYWT7Y z2grlq;b2z&CRRK_wf(R;BhNo#+8^tUE(&iOdO-J=bBZ;J!`O-q)EcsiSp#;|5fhCn zT1e7D{1#%ekU3b!zm-&xs%NzGB>aqaPCG|>;dSI$&{p_MJGYHQFs3SStvB|GP2xt1 zdcs)aLQ929f!jvpcEH3cnS?W{$4Yx1F!$oHGQH~&fQ!UM)7T+-P%`?9QJ@^Il-XjV zY{VH{DZ;t*w7x^|g;|+a%4}r=s;7`@I$?{}@8GkF2sliBLbZY(rfPkB4QU~+Q(M>f z^)1oT+6RX={qV&gIo!N>{jQ%h|ILP-Qdl`a{K(hEdse=&R~tgsey5NBWN{B4ZT|i6 zFOnY|>zIl5ht3oL9Z>))zJIK#0-mu7qrG~E3`@|1dm*z$+io#mzzwQl<cxt|k*P2K zX{<p5;<7*g=jmc)<0(njsiK2B$Dj*g`bfIS4-l!3MVR4lnO@DO&5sr3H`7))7Hxr1 zJR6i<9vT@(^4w#R=hju~ND>bsYQMPHyyR9?0)VG_lhJtq=nQ~gx%y^Gk<jwE>ITJ8 z9Lu<vK=z<4pyKe2SioQzg?hA&fet38suX7%BDcZo6y1f`foKkbh#QMT^|Zz`<tQny zA9HcJKu8A3k6h*f&<(AiBXl%B=3;-75A3P`PiGFm-Z(*D-aUHifSY>w1*}cmqYoY! zG#O}Q<JPkW08pE5nm@qrCR6@=(+~pTFclJ>-mhb;K9l83dDEeA7z<&;Ski)<jieee zmqq36vFv0PW45jdJ)n5G8}q4NS)aYqPihbFcA}kq@4%j`D_89ilmDc(zx(?ka^>{g zPS*2gcw1DsJGuWurvTGKYLR$Z85dOzc-dNd**jrR@1!>{KqqC;W~zdXu7EcyqIBm= z=o>B|W&-?^iaTkrN2!uihQe|B0rQr@)|*OXh7XE3_D{yiDU+*EZ&RC?$zyogT?=Tv zdNMX?;sk*e8)M;;yzbfuN6)v;O0;&jCXS}I{r&v8-;Ph7@zBB<Pc=>M>Jcu!HFWIp z_VshemnFu3@k`5RY<}%qznMXj9n+KdENy8$d4J=qAOB#ek;y;p;}?%}9<GopLtUQh z<PVPM<Y$vo_1id<<U09Lw+A@dcj;yK97r3iE?*&@TDyy;5I8lM-_I|YN<XWg-yL!T zG`&qv|2|TcKDTk~zJ4*Tofu-x{rT$)!upopdQw68EhZI&MolVs307BJQkGd>Y5nMN z1;XbZR}ds2;kF|S0{g)%k3F}5e@`z77_r7;u*Z+)ud!^z8ksZ1W@*!#n&@k+(s5p9 z4?}d7zM^8b%0bCr7+@85BNtlnSqlx4xSQeK+wA48BY!$_e39khnPYFKfy0%)@PfXj z+4T;<daJow?wS1cj?Y^!2CTib%GS$jL<%wTUJ}>q67?C#Y6RF3k<^+TJ8;%<B##|6 zlpTeY)fsjKOGA_$<43aN&d(I<F`)5n81qx-vadG0P*?}v<5IxJzPQ(T3l{O~AD=yY z{o`F-L(fts8S;2k%2jbuZeKo^Lit=Oi7K^mbSjl`VBhYFD!xn~o>GR<r@Xst1gUGF zvq`DOPiuf*b$XQ|EF7(wsjvhY5p=08EI_Z8u^c^28(nMUL8mls0%cxkB=agii+MR) z=w?jIMa{=%-@4YR)HvQxnKsn6stt_f&Aj_EEp#2)iHsAL<mz2@9vTf<9xAutVR}4^ zq)ebio-`VL7Zoqy+n}!upaM=Wpv8U6zY=O<l#O~$A<IOnXVgd;%PxlHL2F5fD$}4V zWk6VTJJzWa#)Gl;6$QQe{O#NFQ5QZJbxqK;jLpYutLM-AyT6+^zmxKD@r0^yG#akD znURgJEL--<vZ1#qBlmSA5*>-GeiAi<#8q%LTpc&SX8kM0akYxw=Y{tBJ6WY%G?u>8 zQ*L$Cr0-<s_D)F=&{w@fKeRE*Ra*GX?)f6KepS5ZOE{~iYvrj{1J0i+E*BzqvU-A) z8}9%B?5hH=RV^yT+_szwgwc6Z@4SO%D^*co@hq#Xn(g%?c^LCg^0T=edS49=bjYal z>L@W((J3B1#6iYepI)@%q4S4d>0ZD4@JajderfG@I#<uz^Xgkq9(jZ6_qntEqM%*j z$CHj7Gv<&$f4X!ta`U<EM7wf!X5GApW*lC&W5>^*@9CJ*Toc**)&g2XG(&5k^Ik$2 zi_DC9`Mfz08^>;WQw+;4rMV8DYfx~y*<|y)ObBQ6-F`OA$V>=7dQQx|&1EbRa_@nQ zqsGO2GuWJ$1u4M_MU)Xbg9U7ui&p8}G=-%IX9Tk;EdE^ObYXT1OCg=YQpoA$HO9hQ zPGRxiW(o_19k-gqGC;!n&;Ml1X)J~#+KJ)c9DQKKItpPOb3ey4nUY&flPT4w$qd3e zf^>uaqvK={U)*}6jD>=WG3LsU|3;xj{#uH_7rALIrLdMDTT4)13s~IZ>{^QHT8eQk zSWjUrW^3_{v6kR%){?~#x7wKgH$HmvpB9@J&m41agr^vMp!;Lc*EB$9Jyihe9~`}^ za#&RfTUCjU9HPn{aSSFYRWa%fxU)kT@lcJUx1UmssH93+drE0E!-G=FgHq%Hx&^dg z-%`S=wk7OQ!3Hh0s-~X$0gmcB@ExN|H9K#X+>+Z#Ze9i%*_3-d2E*1-XR-Bp%C9Tz z#Z4j|)GgugnxhZ!-^`gs@E<ROB05ZKSWVc4%knt<h}_T^i6J*l4Eag;<$sw&YH^I% zr}Om@EZ_?+hhHuK!S4*>{RZJXm#0a1=s2lmWwM!X<!`(LzdGPMN92b1&(00Gb%DcJ z|B*i(KEBAjxGMAQFT9ZXe&NO;`2OXz2gkwrQ6JN(S2i}i2B0U+4M~~Q3a0S}MTa$4 zfP}drCw;@M$3C*9moztI0=wiuQ!il&g<Do-FXLryv(fX;zM4YQLbKi^wOwpe#gM*l zpOzra*_T*51%9tbyut+lL(k!8(Vtpk#A!^-*N#v#LPxFBW;`5ULMt86Z5=dQ><-q4 z_mW@|tp$4ZVoJi1Ng%kD*qZL)>T|bJp?x>i5fQ8fc3@ZeO`PoE@NO!4U^GJS0dj56 zhStPN?flFSo0qQL(MzgkenLFj^>>bFSBPt6=j;W1>x!-=<kTsxW5@S4uUiqXf4TMB zPp|9ME@=-9X>Snu-14=3&o!2JuELokbj}f;^-AuCc~g?J(?*<z%NX2u$MFU!v=viQ zeCQ+u<LL@rrB!98A?1xis@6v#sRlP2rR)pPo+L~j1&hmA^2j-AmWw}slFQB6Bb=bI z>&4t;mrc%P?Tvkfb^h(rQg{-GdxdLj0375EdogU!;QovaHAFz(nLK_~kAlmY$uB<a zFfF8QVS3)kqfdT8(JLUVZ`32F%{IYdr&`)4k39nhPcuK(9GH1HB5>Up!(hbUgNb}U zGY}@9R(Bq)Bd639jy0twpiikun+1=T%AHYGe4lGxjo?Omc+<?97A&zJb8rn=r90XA z^vYZiXRVnt0|JHYfWTr(ubw9=)ak`Ey<6vPq5P8BW_QX0i)Yh0MRZQ`SS;4H(3os~ z1YPFE=7*cd;Iu*24PKVpIr>po1;Lm3flhx}hW<)8`aaN7actqEg=*|(Etpvi=qI6? zE>BMpRp`r$VCVod+E(nNr~u({xO|!Qxlt9A-C}(=9e_eI#!A;am$fzQ3@{%Ujzio# z){+M^=V179cF~5sHM_YIuqu!1tM+GBT@0&sMU|?!>Htk$9-||cNoJfiz4-_o18s}a z1d%@B8kS8Pve5~l<CnddCdTMFO<fF{1(wn%lGSn?A`o_|p(>gm@{i35KI@U?WHsM_ zXPNQ1-lRE8=fO7Ct2u%dL)4ue{#fS&Z^-C;fotNn3Revn>cxobMA{2vqWvd&7aX<( z73d8q9=ypUc9UAHXvFjoD|W+Wic2zO2~EPl@Y?Q8-~RTdZu*<AKYdzzX=7*S#!jK0 zK2Z5PVTc%_dd_IEeowm64C)Hx!c+R3tPs2F2g?~@Fs49u={X~Z&R{FLC!AX9$bA}+ zQ&wM?`7SAuj{D2_FRa%a@62QZBUCjiU4&fT{I|0o=~)hp-u77M(w^m{(n;!So4OzF zh~C$=#7X^_Sr2!v*mCl!_D<WPjuo3Ov?WPzq)%HizHfDVlHwRTM+fwT%z05u++vcB zZ>;2pKa-eovBZqqtH+I<p8C(4s)L@(=*c?IBh(r-UI*3i|4urwr|G5%KoRPRj3kt4 zF>VyC0lcI4Eodzoi`L)>TGNu-!zKeDwcgL9HsgAXrg$@rSeloNN%IRYpuS}^4^V4S z#XWfos*&h$9H+Z0r7@~uvrC}SN;&|*9i{F@ZdL5AY&h8xwXc9ag|~>!NR`03r{n0& zvRYb+$Hg^hcb0{zHNWjz$7%{6z3%0+a!umYX&ANsq0v3#Je$`8d*_9{8*^e$QIy?n z@-rv)p!L4x)SfC7p|M8y7<zMZL}$?DX4H<HK{v+uIhB`Vw;ezS9Id};1f4$T*R9X_ z)u;T97(hpA&C55u`de*a?P7Cw0G-LJ{cO`*HiGUu+wv#Sp*%4@4gep^xbaB+Xij1o zR3whccclVE>5jZOF2(Oy#ZZHl%08@nB3@R-po#!cl`3}gug~6stYqY5<d$3VcH642 zqH%hL1zyM69MPzY%H(|ik^?kr+(_$_{n>eYc=u9QjFof10a84%w8`qk`|p?xS*R$X zsbT|Q@R%55DI1-YVH2^Y(q^H*u?35ku9>WKY8kb}<4LYQxm=J!ahcYttRP8Yv1TCq zw02$^TB4nvOnzEd_v$~BPX1}~WxaHg-=(z)t*>R{SjHI!iCVew+*5kDSs<=TI_SVV z6o&zKL}KYmhc`DSfo@qYI|F79JM^#_1$V6q9IBTEljQX~%BiDal~Z<FPr#`XB1pHN zRW>{1l#6DQl}f;59E~)nm}nju%$pRyDUfNZFcZl~?|3Wfp%%~a6TNF*KYYqD{F1b` zr*rj!J%<keXwAvv+Q+1>tG}nGpAWL=C7Q-mDi^mLOc7E>R%xH~^$}~|AsV|B^t|%{ zI%l;Mt90@+&uD8(;#lRT1Y)%2iVeRX^w=GGfsPbKa4=X%-zYY-8Y~B`7LjSZ(j%)b zFC7HR<k~K$OaYo~EOw<VMJ4sOo1V{)s+qkhn|+unJ<^mZoE@3fHprv$?1URKY!jB# z_(Ki7H?<JYw)?Un_yTQ-r4v)wcsJajjL{j=F@7fQz`paMVY{%A+LZ)H$FauKMuymp zEKrWEB?TiIJuU1iZU*3Pg54KyLf9kR%Kzkjr~mi;?QUT;Kab7CA9L0~-k%8(vitSd z^|kIcIzR8<iTksEx0Fwl)8Y!yS+LiR46e@3%%VA-l!$fSoM>fb@%Sx#mEY){l)1HR z^-@B@(+(J&)4DpFy5|UoNMzI6u04F)^p>tC*j{YrPm*gQ*44y0{Wjy7>+omvj+7LS zT^Ss&m*3~zM$<hB=ZR)+qbZ4-4-lhc`Zqf7?Rr2vC$zImeRJa)?d&GJmbM!hI{$z1 zTK?Nz>+KPj0-X>16An`Tm2qvzK}^)@&I!%~E+3nZ*kr2TZVf;1;^+d-Tg3YPLB%_C z6+fEMRnqMkPcD$Edkz>2rhTLHOWhBQ+=kVo_k_ni5zf&)DdXCaQ|L7_X3-kt^0E1a zjZ--EqlA6nD!~t2{tWHNNYznNKgPCIO-kIFwWL404(<HNJzYDJ>y&nFw{VW`@&8A( z`~R0|fBV*?6OfT1eyNb)tT+q6LT3S(*(?Avil~i>i;<2J(I0T~GN(r(8FXpu``+@t z9T)rfz^WH^J+`vHA5Q&_8<$KSWR4y)$kYSN!FXJsGoadiu~`1SclBwZnVap3G)kB* z&~Lp<gKX&ln?_JJ>h`-;V?5h24?9BV@%ofJeh+({xg~Gws7KTZbGc>Y678?|aRl2E zvXgnxW5`Y3(MRs&&Dvo)WeNQK$N7Js?atT#J~^`O{zQI@J)7-oh={dZHMfmRg>}E4 zcDT^s5vIjS4DGuZ$E+8=HpS4I+w@4Yfz7=0)43@AAi^}i*HV)*_%ri-@IDb3efFbZ znX74;Xc*3Ri1y=_V;Qc()0xl$?LsiuD-sT)W!09nBcXa?GMq?Gs?5xPGU04AHs6jm zcbO_GBQ;BSe#z=63B7e>!=BD>bUYd$`?b4y@_lV*{m&P+?cRRwi1x=?a^MNGtI73K z>xH46FLbV6zO81wYx^a#<oQ>~$M3+IGV>S3CUHL4{UG-orx>HES&mcNPpy4HET%tK zh?KpVOiaJedUguSSogomOiRelJ)wt?b=cELBlaPxg#kc3E_u*e;PbQ8x9XwJE@uR+ zWOsO2R3w2n*a^!-j+c@66oR*;NrnaZzu#--BdNpW#D$sT%{49Wz2-MBUboonH|z(D z7bPdPD8Kf=h7AXXdyibv21whLBTSAE<o!kX3!EYjQzyb-hAj9)aWVF!>=BQ09ynDY z?!U5oRVbx#dQS+Il*O|*tSE`53#tAYG!~X*W?fc%p1W6IgdVe|;2A3+X|OaDbk^X_ zr%MfVjDL`g>&Kj(4?P{cf14UA1(p<-6tYZlN#@2EX|vZ?6l6sdW8MCO%fGh(-V0;y zgPD6_@K58d2Ig#=L27TlEe1I|;^qT9&KEFTq4)17=ho|Y@F*iJqMRzCQ>2Qp1?Lub z^$2}lzIfRPeHyp*W>$|LYgzs0yWt1P8}UDC!RyI{gjcFcen-1<^NO`-?j8U)ZlD~P z8pWehgliGM&vEd0KYtJ&jokh0bI`y4Ag1B{SvP<F{{So+oYDXQc-muNWME)m<S6p? zHjs(uxB1E-&%po!XY4)p!s!1q{xPsGWmjcjWZ+<60*L|uAruO|c-muNWME)d{d)sQ zUiv@d{{i-;3_uYS@CpE__y@@Vc-n1~Pe@cz7{!nGeeX^yX%WUyp->Sq#Po<E9uh*3 z)KoTw3=+d&gAH!XC-jfPc0<H0WRfCcXp<zih!Ba01dTRrBam=0iwX%hQq-p4b-vpe zlQ{6>-2eBy^Ud`um;!(1DbO}UeTgS>5_JjDOLBG@89$Fhri{8-z$7Vo)9BNAjup)` z2B_oa1$J=k6qz7L$N{pCq)9(HPx8%u<GQzbhr^pge<H+?)Z%aQf%iW~!8fQ%k?l0< zeh2%5^gtidj!s#jcA;)NICq9zMM0LF=4F+0mw0Z3z(0-q62)uw7X97Eb_wD&Ig8`` zj#+vRsp_LFKvJSME5|S>_fYX(BTLQkj;wiwfaASVL&an;V#4@=l-NFj3iGMRB#GR5 zZRfl+_g9hfwqm#3!8Q6%+6>RwiCvOH(tCzJ-rHmL;Cb`@?tj^bxJgQ6KS}BumurNE z1q!BtZf}V>X^za^o5fN3?li0PsyP}QRybBuKg=zsd9y#v@w)kifcr=7brkJeQe}UR znQ88uU>D*~S_@Z)7EC!_;kgf~%jBcq!>pTi*ob})HK(;`#ns{mru=s1rnzr|C9W1- z|6?-oSJvVRwLuo;2ESpw4jT#Ge<AB?(F$wfYDTr+QLqzSqn;xCCSSa}Kw>YjuI2*Y z$UAcIFZfIyp<d*izJn&rcfgk2yBH%ig>Pz%sMgFIoJ+jNBi(EA7$T#3E`6r_%h=-m z1pIBxQxGI($UK5S#)#DFc-muNV2FXj1q|01cQF|;-C)jO?qFWUe1`cKiw#QwOCQS~ zmT#;stZl3}*xcA=u)SjsV{hVM<0#<Rz$wJ3#Tmev!Fhvg0@oRCBkl_BZQP%DG<YWQ zoZ@-GE5#eYTgH2aPl_*#Zxufue**s{0VV+_fd)Y-!6?Bgf`<gZ2<ZqV3DpSA5ZWdz zBU~lCPeewfO5}v-6wzB^GGaMm3&bvnTZy-bpOes$=#e-l=^!~z@`;p))CQ?f(t6S{ z($}Ov$z;eZ0>WpqUb1K8T;$ftU6C)7-=N^3uukEXqKKlA;swP|N;XP8N)MESl#7%P zD1T6qQ3+6KQaPi_r8+}ROYMhxj`}+F4;mI4vo!fMr)YlAiqcx7^-9}9dztnH?O!@t zIxRYHbW?Qq=}GC;>HX1f(%)jBV^Cpm%uvd3is20-DWh4&T*fuVUrgFeHB8T#6`9>L zcQRjLA!M<|;+`dkrG@1*D-Np$t83PJ)_pb{HWO^l**e)yvwdUdW_QY7z&_9ZiG!2F z1xF9ZBF8m2;3>x!PHav}PIgX3PAi=5IomkTa{lI`<Wd8Kb6obg>~VE*J>YuIEz0eZ z+atG60P|d(2LJ#7009610O|lg00jUy00aO60096302TlM0RRDC00RI4c-n=LJx;?w z5QU#fK+tdmv;_qPSYU(zrGf%PDufYz>^Q-~u^|aT;Utu_G@OGIa2~#0uPvoQtMR^_ zd2jwKX;UM06m+*Fy<;^Fw8N{$Yj8e1?r2+|9(T2;Z;#hC*RRJL+70?1|ELT~eaR@& zp^mWq7Du294OJ;o29CAVj69hp+(tJll@gum*?k8tHdN?z1;^-4xyE`VGIOttJA=FM z%oyb>@6=Zqkkc}6@m0FS3V3fs6ZTLMo&TdTt?I#5n$dyP872yu>zLDn8@C>Ndh}S4 zJ9XSe8w+*nq7$k-k<W5Qcnh*7Y$();voo?rI$!Cn>8$SSpzZ6PTDj}EnaD8Vz<I{# zO4oO@O+%d}-#IEf?^Uab^+K&2?v#k#_VtR|{*&+zmHk++c-n2yM@*A(7{~GNQwoK$ z_ZIga@B6l8xLau5d*D_SD0P4q>z)x6a71I`P2;+#ae*ru^`Hj#h$HI3vpXKts}|qC zH=pFmC(m<u^5lnwzxCTsHUFzm;T9}JU?q|$Y(x`-omk?CCxJwgNG63;(nu$ROtQ!( zhg|Z=rvn9aq!XR#LRY%cogVb07rp62U;5FX0chwLIB?>kkRpmHVIYGT%n*h$jN!QP zP)ZqIe2icuqZrK?#xjoaOkg6Dn9LNWGL7k!GlQATVm5P_%RJ_@fC{m2oCdaYgM)lv z2YcDYAx?5aB539v+c+RriDZvN(a3Gyi;csa;wL}&#WBuspEl02kVWjHl801rj|V*E z5s!Jo$8dTtc*b+i;paR1dCf~+QNw4x(!^o{EMXZ-spSZDtYA4o>It!uRjdxDyoPnG zWj!0&z*Ua2nN4hAD_{7=HO_N^>%8HuL`#g=C061jUJ@ixk|bGDBvsNRofcZT%oXl% zkxSfVC#NNYo7|F2$zr!;OOE79p5)s?wE<0YYsxZHkD+uZUCNSn4NcROy3$ZOluo5f zS*R>h7AybVbDQewuCCjw1O8C3s<NWK##|XbQ<u-`4F&7k2e10W=P~~XYbYH`=N~m9 znhF2_c-q^+_`h`nV=sgE29AJ;jf{+aksICEv?CNZ2t;~s5D5Y@8X{#kuxZCcFl=B^ zaNWSH?XrPQ!F3Z$E0Z>u!wTfExk5SYAep%k4&w$6sCrHX*If)8_5T@|v^O%ll>tS# Tfa*9W!MKqdM6>~LGbsK50n#l& diff --git a/pep_extensions/theme/static/fonts/SourceSansPro-It-webfont.1aa29ac0f190.woff b/pep_extensions/theme/static/fonts/SourceSansPro-It-webfont.1aa29ac0f190.woff deleted file mode 100644 index 3cd960220baf812a5d77980d8d16cf1fa109d96b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 27964 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 X4I${(0;g{ZACz@E>xgJm*nnTY3!-@G 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 AB>(^b diff --git a/pep_extensions/theme/static/fonts/SourceSansPro-Regular-webfont.fd0d51605201.woff b/pep_extensions/theme/static/fonts/SourceSansPro-Regular-webfont.fd0d51605201.woff deleted file mode 100644 index 6732daada5bc1ca4a36c5cc2a61ced6738533742..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 26392 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 diff --git a/pep_extensions/theme/static/js/doctools.js b/pep_extensions/theme/static/js/doctools.js deleted file mode 100644 index d714cba0de2..00000000000 --- a/pep_extensions/theme/static/js/doctools.js +++ /dev/null @@ -1,137 +0,0 @@ -/* - * doctools.js - * ~~~~~~~~~~~ - * - * Sphinx JavaScript utilities for all documentation. - * - * :copyright: Copyright 2007-2020 by the Sphinx team, see AUTHORS. - * :license: BSD, see LICENSE for details. - * - */ - -/** - * Footnote fixer - */ -document.querySelectorAll("span.brackets").forEach(el => { - if (!el.children.length) { - el.innerText = "[" + el.innerText + "]" - } -}) - -/** - * select a different prefix for underscore - */ - -const ready = (callback) => { - if (document.readyState !== "loading") callback(); - else document.addEventListener("DOMContentLoaded", callback); -} - -const removeElements = (elms) => {for (let el of elms) { el.remove() }} - -/** - * highlight a given string on a node by wrapping it in - * span elements with the given class name. - */ -const highlightText = function(text, className, curNode) { - function highlight(node, addItems) { - if (node.nodeType === 3) { // Text node - const val = node.nodeValue; - const parent = node.parentNode - const pos = val.toLowerCase().indexOf(text); - if (pos >= 0 - && !parent.classList.contains(className) - && !parent.classList.contains("nohighlight") - ) { - let span; - const closestNode = node.parentNode.closest("body, svg, foreignObject"); - const isInSVG = closestNode && closestNode.matches("svg") - if (isInSVG) { - span = document.createElementNS("http://www.w3.org/2000/svg", "tspan"); - } else { - span = document.createElement("span"); - span.classList.add(className); - } - - span.appendChild(document.createTextNode(val.substr(pos, text.length))); - parent.insertBefore(span, parent.insertBefore( - document.createTextNode(val.substr(pos + text.length)), - node.nextSibling)); - node.nodeValue = val.substr(0, pos); - if (isInSVG) { - const rect = document.createElementNS("http://www.w3.org/2000/svg", "rect"); - const bbox = parent.getBBox(); - rect.x.baseVal.value = bbox.x; - rect.y.baseVal.value = bbox.y; - rect.width.baseVal.value = bbox.width; - rect.height.baseVal.value = bbox.height; - rect.setAttribute('class', className); - addItems.push({ - "parent": node.parentNode, - "target": rect}); - } - } - } - else if (node.matches("button, select, textarea")) { - node.childNodes.forEach(el => highlight(el, addItems)); - } - else if (node.nodeType === 1) - { - node.childNodes.forEach(el => highlight(el, addItems)); - } - } - let addItems = []; - // const content = document.querySelector('[role="main"]'); - highlight(curNode, addItems) - for (let i = 0; i < addItems.length; ++i) { - addItems[i].parent.insertAdjacentHTML("beforebegin", addItems[i].target) - } - return curNode; -}; - -/** - * Small JavaScript module for the documentation. - */ -const Documentation = { - init : function() { - this.highlightSearchWords(); - }, - - gettext : string => string, - - /** - * highlight the search words provided in the urle in the text - */ - highlightSearchWords : function() { - const urlParams = new URLSearchParams(window.location.search); - const terms = urlParams.get("highlight") ? urlParams.get("highlight").split(/\s+/) : []; - if (terms.length) { - window.setTimeout(() => { - terms.forEach(term => highlightText(term.toLowerCase(), 'highlighted', document.querySelector("body"))) - }, 10); - let hideMatches = document.createElement("p") - let hideMatchesLink = document.createElement("a") - hideMatches.classList.add("highlight-link") - hideMatchesLink.href = "javascript:Documentation.hideSearchWords()" - hideMatchesLink.innerText = _('Hide Search Matches') - hideMatchesLink.style.fontStyle = "italic" - hideMatches.appendChild(hideMatchesLink) - document.getElementById("searchbox").appendChild(hideMatches) - } - }, - - /** - * helper function to hide the search marks again - */ - hideSearchWords : function() { - removeElements(document.querySelectorAll("#searchbox .highlight-link")) - document.querySelectorAll("span.highlighted").forEach(el => el.classList.remove("highlighted")) - }, -}; - -// quick alias for translations -_ = Documentation.gettext; - -ready(() => { - Documentation.init(); -}); \ No newline at end of file diff --git a/pep_extensions/theme/static/js/searchtools.js b/pep_extensions/theme/static/js/searchtools.js deleted file mode 100644 index 04007380c99..00000000000 --- a/pep_extensions/theme/static/js/searchtools.js +++ /dev/null @@ -1,530 +0,0 @@ -/* - * searchtools.js - * ~~~~~~~~~~~~~~~~ - * - * Sphinx JavaScript utilities for the full-text search. - * - * :copyright: Copyright 2007-2020 by the Sphinx team, see AUTHORS. - * :license: BSD, see LICENSE for details. - * - */ - - -/** - * Simple result scoring code. - */ -const Scorer = { - // Implement the following function to further tweak the score for each result - // The function takes a result array [filename, title, anchor, descr, score] - // and returns the new score. - /* - score: function(result) { - return result[4]; - }, - */ - - // query matches the full name of an object - objNameMatch: 11, - // or matches in the last dotted part of the object name - objPartialMatch: 6, - // Additive scores depending on the priority of the object - objPrio: {0: 15, // used to be importantResults - 1: 5, // used to be objectResults - 2: -5}, // used to be unimportantResults - // Used when the priority is not in the mapping. - objPrioDefault: 0, - - // query found in title - title: 15, - partialTitle: 7, - // query found in terms - term: 5, - partialTerm: 2 -}; - - -if (!splitQuery) { - function splitQuery(query) { - return query.split(/\s+/); - } -} - - -const removeChildren = (elm) => { - while (elm.lastChild) { - elm.removeChild(elm.lastChild); - } -} -/** - * Search Module - */ -const Search = { - - _index: null, - _queued_query: null, - _pulse_status: -1, - - htmlToText: function (htmlString) { - const htmlElement = document.createElement('span'); - htmlElement.innerHTML = htmlString; - removeElements(htmlElement.getElementsByClassName('headerlink')); - const docContent = htmlElement.querySelector('[role="main"]'); - if (docContent === undefined) { - console.warn("Content block not found. Sphinx search tries to obtain it " + - "via '[role=main]'. Could you check your theme or template."); - return ""; - } - return docContent.textContent || docContent.innerText; - }, - - init: function () { - const urlParams = new URLSearchParams(window.location.search); - const query = urlParams.get("q"); - if (query) { - document.querySelector('input[name="q"]').value = query; - this.performSearch(query); - } - }, - - setIndex: function (index) { - let q; - this._index = index; - if ((q = this._queued_query) !== null) { - this._queued_query = null; - Search.query(q); - } - }, - - hasIndex: function () { - return this._index !== null; - }, - - deferQuery: function (query) { - this._queued_query = query; - }, - - stopPulse: function () { - this._pulse_status = 0; - }, - - startPulse: function () { - if (this._pulse_status >= 0) - return; - - function pulse() { - let i; - Search._pulse_status = (Search._pulse_status + 1) % 4; - let dotString = ''; - for (i = 0; i < Search._pulse_status; i++) - dotString += '.'; - Search.dots.innerText = dotString; - if (Search._pulse_status > -1) - window.setTimeout(pulse, 500); - } - - pulse(); - }, - - /** - * perform a search for something (or wait until index is loaded) - */ - performSearch: function (query) { - const dotsSpan = document.createElement("span"); - const searchText = document.createElement("h2"); - searchText.textContent = _('Searching'); - const searchSummary = document.createElement("p"); - searchSummary.classList.add("search-summary") - searchSummary.innerText = "" - const searchList = document.createElement("ul"); - searchList.classList.add("search") - - // create the required interface elements - this.out = document.getElementById("search-results"); - this.title = this.out.appendChild(searchText); - this.dots = this.title.appendChild(dotsSpan) - this.status = this.out.appendChild(searchSummary); - this.output = this.out.appendChild(searchList); - - document.getElementById("search-progress").innerText = _('Preparing search...') - this.startPulse(); - - // index already loaded, the browser was quick! - if (this.hasIndex()) - this.query(query); - else - this.deferQuery(query); - }, - - /** - * execute search (requires search index to be loaded) - */ - query: function (query) { - let i; - - // stem the searchterms and add them to the correct list - const stemmer = new Stemmer(); - const searchterms = []; - const excluded = []; - const hlterms = []; - const tmp = splitQuery(query); - const objectterms = []; - for (i = 0; i < tmp.length; i++) { - if (tmp[i] !== "") { - objectterms.push(tmp[i].toLowerCase()); - } - - // stopwords array is from language_data.js - if (stopwords.indexOf(tmp[i].toLowerCase()) !== -1 || tmp[i].match(/^\d+$/) || - tmp[i] === "") { - // skip this "word" - continue; - } - // stem the word - let word = stemmer.stemWord(tmp[i].toLowerCase()); - // prevent stemmer from cutting word smaller than two chars - if (word.length < 3 && tmp[i].length >= 3) { - word = tmp[i]; - } - let toAppend; - // select the correct list - if (word[0] === '-') { - toAppend = excluded; - word = word.substr(1); - } else { - toAppend = searchterms; - hlterms.push(tmp[i].toLowerCase()); - } - // only add if not already in the list - if (!toAppend.includes(word)) - toAppend.push(word); - } - const highlightstring = '?highlight=' + encodeURIComponent(hlterms.join(" ")); - - // console.debug('SEARCH: searching for:'); - // console.info('required: ', searchterms); - // console.info('excluded: ', excluded); - - // prepare search - const terms = this._index.terms; - const titleterms = this._index.titleterms; - - // array of [filename, title, anchor, descr, score] - let results = []; - removeChildren(document.getElementById("search-progress")) - - // lookup as object - for (i = 0; i < objectterms.length; i++) { - const others = [].concat(objectterms.slice(0, i), - objectterms.slice(i + 1, objectterms.length)); - results = results.concat(this.performObjectSearch(objectterms[i], others)); - } - - // lookup as search terms in fulltext - results = results.concat(this.performTermsSearch(searchterms, excluded, terms, titleterms)); - - // let the scorer override scores with a custom scoring function - if (Scorer.score) { - for (i = 0; i < results.length; i++) - results[i][4] = Scorer.score(results[i]); - } - - // now sort the results by score (in opposite order of appearance, since the - // display function below uses pop() to retrieve items) and then - // alphabetically - results.sort(function (a, b) { - let left = a[4]; - let right = b[4]; - if (left > right) { - return 1; - } else if (left < right) { - return -1; - } else { - // same score: sort alphabetically - left = a[1].toLowerCase(); - right = b[1].toLowerCase(); - return (left > right) ? -1 : ((left < right) ? 1 : 0); - } - }); - - // for debugging - //Search.lastresults = results.slice(); // a copy - //console.info('search results:', Search.lastresults); - - const resultCount = results.length - - function displayNextItem() { - const doc_builder = DOCUMENTATION_OPTIONS.BUILDER - const docUrlRoot = DOCUMENTATION_OPTIONS.URL_ROOT - const docFileSuffix = DOCUMENTATION_OPTIONS.FILE_SUFFIX - const docLinkSuffix = DOCUMENTATION_OPTIONS.LINK_SUFFIX - const docHasSource = DOCUMENTATION_OPTIONS.HAS_SOURCE - - // results left, load the summary and display it - // this is intended to be dynamic (don't sub resultsCount) - if (results.length) { - const item = results.pop(); - - let listItem = document.createElement("li") - let requestUrl = ""; - let linkUrl = ""; - if (doc_builder === 'dirhtml') { - // dirhtml builder - let dirname = item[0] + '/'; - if (dirname.match(/\/index\/$/)) { - dirname = dirname.substring(0, dirname.length - 6); - } else if (dirname === 'index/') { - dirname = ''; - } - requestUrl = docUrlRoot + dirname; - linkUrl = requestUrl; - - } else { - // normal html builders - requestUrl = docUrlRoot + item[0] + docFileSuffix; - linkUrl = item[0] + docLinkSuffix; - } - let linkEl = document.createElement("a") - linkEl.href = linkUrl + highlightstring + item[2] - linkEl.innerHTML = item[1] - listItem.appendChild(linkEl) - if (item[3]) { - let spanEl = document.createElement("span") - spanEl.innerText = " (" + item[3] + ')' - listItem.appendChild(spanEl) - Search.output.appendChild(listItem); - setTimeout(() => displayNextItem(), 5) - } else if (docHasSource) { - fetch(requestUrl) - .then(responseData => responseData.text()) - .then(data => { - if (data !== '' && data !== undefined) { - listItem.appendChild(Search.makeSearchSummary(data, searchterms, hlterms)); - } - Search.output.appendChild(listItem); - setTimeout(() => displayNextItem(), 5) - }) - } else { - // no source available, just display title - Search.output.appendChild(listItem); - setTimeout(() => displayNextItem(), 5) - } - } - // search finished, update title and status message - else { - Search.stopPulse(); - Search.title.innerText = _('Search Results'); - if (!resultCount) - Search.status.innerText = _('Your search did not match any documents. Please make sure that all words are spelled correctly and that you\'ve selected enough categories.'); - else - Search.status.innerText = _('Search finished, found %s page(s) matching the search query.').replace('%s', resultCount); - } - } - displayNextItem(); - }, - - /** - * search for object names - */ - performObjectSearch: function (object, otherterms) { - const filenames = this._index.filenames; - const docnames = this._index.docnames; - const objects = this._index.objects; - const objnames = this._index.objnames; - const titles = this._index.titles; - - let i; - const results = []; - - for (let prefix in objects) { - for (let name in objects[prefix]) { - const fullname = (prefix ? prefix + '.' : '') + name; - const fullnameLower = fullname.toLowerCase(); - if (fullnameLower.indexOf(object) > -1) { - let score = 0; - const parts = fullnameLower.split('.'); - // check for different match types: exact matches of full name or - // "last name" (i.e. last dotted part) - if (fullnameLower == object || parts[parts.length - 1] == object) { - score += Scorer.objNameMatch; - // matches in last name - } else if (parts[parts.length - 1].indexOf(object) > -1) { - score += Scorer.objPartialMatch; - } - const match = objects[prefix][name]; - const objname = objnames[match[1]][2]; - const title = titles[match[0]]; - // If more than one term searched for, we require other words to be - // found in the name/title/description - if (otherterms.length > 0) { - const haystack = (prefix + ' ' + name + ' ' + - objname + ' ' + title).toLowerCase(); - let allfound = true; - for (i = 0; i < otherterms.length; i++) { - if (haystack.indexOf(otherterms[i]) == -1) { - allfound = false; - break; - } - } - if (!allfound) { - continue; - } - } - const descr = objname + _(', in ') + title; - - let anchor = match[3]; - if (anchor === '') - anchor = fullname; - else if (anchor == '-') - anchor = objnames[match[1]][1] + '-' + fullname; - // add custom score for some objects according to scorer - if (Scorer.objPrio.hasOwnProperty(match[2])) { - score += Scorer.objPrio[match[2]]; - } else { - score += Scorer.objPrioDefault; - } - results.push([docnames[match[0]], fullname, '#' + anchor, descr, score, filenames[match[0]]]); - } - } - } - - return results; - }, - - /** - * search for full-text terms in the index - */ - performTermsSearch: function (searchterms, excluded, terms, titleterms) { - const docnames = this._index.docnames; - const filenames = this._index.filenames; - const titles = this._index.titles; - - let i, j, file; - const fileMap = {}; - const scoreMap = {}; - const results = []; - - // perform the search on the required terms - for (i = 0; i < searchterms.length; i++) { - const word = searchterms[i]; - let files = []; - const _o = [ - {files: terms[word], score: Scorer.term}, - {files: titleterms[word], score: Scorer.title} - ]; - // add support for partial matches - if (word.length > 2) { - let w; - for (w in terms) { - if (w.match(word) && !terms[word]) { - _o.push({files: terms[w], score: Scorer.partialTerm}) - } - } - for (w in titleterms) { - if (w.match(word) && !titleterms[word]) { - _o.push({files: titleterms[w], score: Scorer.partialTitle}) - } - } - } - - // no match but word was a required one - if (_o.every(o => o.files === undefined)) { - break; - } - // found search word in contents - _o.forEach(o => { - let _files = o.files; - if (_files === undefined) - return - - if (_files.length === undefined) - _files = [_files]; - files = files.concat(_files); - - // set score for the word in each file to Scorer.term - for (j = 0; j < _files.length; j++) { - file = _files[j]; - if (!(file in scoreMap)) - scoreMap[file] = {}; - scoreMap[file][word] = o.score; - } - }); - - // create the mapping - for (j = 0; j < files.length; j++) { - file = files[j]; - if (file in fileMap && fileMap[file].indexOf(word) === -1) - fileMap[file].push(word); - else - fileMap[file] = [word]; - } - } - - // now check if the files don't contain excluded terms - for (file in fileMap) { - let valid = true; - - // check if all requirements are matched - const filteredTermCount = // as search terms with length < 3 are discarded: ignore - searchterms.filter(function (term) { - return term.length > 2 - }).length; - if ( - fileMap[file].length != searchterms.length && - fileMap[file].length != filteredTermCount - ) continue; - - // ensure that none of the excluded terms is in the search result - for (i = 0; i < excluded.length; i++) { - if (terms[excluded[i]] === file || - titleterms[excluded[i]] === file || - (terms[excluded[i]] || []).includes(file) || - (titleterms[excluded[i]] || []).includes(file)) { - valid = false; - break; - } - } - - // if we have still a valid result we can add it to the result list - if (valid) { - // select one (max) score for the file. - // for better ranking, we should calculate ranking by using words statistics like basic tf-idf... - const score = Math.max(...fileMap[file].map(w => scoreMap[file][w])) - results.push([docnames[file], titles[file], '', null, score, filenames[file]]); - } - } - return results; - }, - - /** - * helper function to return a node containing the - * search summary for a given text. keywords is a list - * of stemmed words, hlwords is the list of normal, unstemmed - * words. the first one is used to find the occurrence, the - * latter for highlighting it. - */ - makeSearchSummary: function (htmlText, keywords, hlwords) { - const text = Search.htmlToText(htmlText); - const textLower = text.toLowerCase(); - let start = 0; - keywords.forEach(keyword => { - const i = textLower.indexOf(keyword.toLowerCase()); - if (i > -1) - start = i; - }) - start = Math.max(start - 120, 0); - const excerpt = ((start > 0) ? '...' : '') + - text.substr(start, 240).trim() + - ((start + 240 - text.length) ? '...' : ''); - let contextEl = document.createElement("div") - contextEl.classList.add("context") - contextEl.innerText = excerpt - hlwords.forEach(hlword => { - contextEl = highlightText(hlword, 'highlighted', contextEl); - }) - return contextEl; - } -}; - -ready(() => { - Search.init(); -}); diff --git a/pep_extensions/theme/static/py.png b/pep_extensions/theme/static/py.png deleted file mode 100644 index 93e4a02c3d321c545898a2ebb8873c26dd8a9e5b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 695 zcmV;o0!aOdP)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV00001b5ch_0Itp) z=>Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2iOD~ z5jY_RGbdgE00K8jL_t(I%Vm>KNL4`;hrfH@vv+$Uln|xSCTLTOHmzE;5FTwpDtJ)a zz)exE-2_34AR^i+ZCXeh7m*-F5k*FrmbSHs%rX_!{PXUec{69`w(#D(>Vd<+%=bIz zH_V)XUD5sE?K5ebbKaSDu}#Dnq^Y!3`tis9>wSO*T+WBP3wS3NNBU~*PAtw^yjZ+< zQ5yK0z%d{y@_Pz6YdL>s7$<f+t<8@+fNGI119U%pf7@GoT&xO=P6mx?ltsrSXAI%K zN<B?|&R2lajslk-eR%D}cBNjxdjg<TZh=Y_f)Y;b4u|PneZkvUi*DSnoO*XJ^xk!C zSv5OtXPJkn%~8N2387O_8GQrjEa#vvh<xGRY3jAp@tdh9eFMu=wHl&85<;)qfsXPH zv9;*N+UWfF@YDI}S8IR(DPZQtY9|l2N-s`<OF$BU{beyt?Zrk;ENXpuXkwsuaO3B# zE3MIqOQBQIe^_Gj?uf#R)<6(Ck=fk(pUIcc<6pf!ZB>6Y^hI$}5GUX?Ns>+iCUiRP z7h|*&%kQa?wQA%pYzqpaf*4?WM!x_ygY0K@07rplx^QhGhnE)r4wbx0x11<&3V?63 z=F8ch)p6iQ88E;iumPmSZif%JIwIgKh$T3)*ab8ImGLVf;IoYtVAb11Z&@wm>96=S z)!B<I0N=AU*)t1`jrF?K@n>&hojbAPoik&f)Lp;=N!HK;X~5oyfJ49$pbcorTyADv dm$H!t;2#0MumAjv0Ga>*002ovPDHLkV1gIiH5UK? diff --git a/pep_extensions/theme/templates/breadcrumbs.html b/pep_extensions/theme/templates/breadcrumbs.html deleted file mode 100644 index 4336d2d00d8..00000000000 --- a/pep_extensions/theme/templates/breadcrumbs.html +++ /dev/null @@ -1,8 +0,0 @@ -<ul class="breadcrumbs menu" role="directory" aria-label="breadcrumbs navigation"> - {% block breadcrumbs %} - <li><a href="{{ theme_root_url }}" title="The Python Programming Language">Python</a><span class="prompt">>>></span></li> - <li><a href="{{ theme_root_url }}dev/">Python Developer's Guide</a><span class="prompt">>>></span></li> - <li><a href="{{ pathto("pep-0000") }}">PEP Index</a><span class="prompt">>>></span></li> - <li>{{ title }}</li> - {% endblock %} -</ul> \ No newline at end of file diff --git a/pep_extensions/theme/templates/customsidebar.html b/pep_extensions/theme/templates/customsidebar.html deleted file mode 100644 index 220a7b64b5e..00000000000 --- a/pep_extensions/theme/templates/customsidebar.html +++ /dev/null @@ -1,47 +0,0 @@ -<h6>Python Enhancement Proposals</h6> - - -{# Search box #} -{%- if pagename != "search" and builder != "singlehtml" %} - <div id="searchbox" class="inline-search" style="display: none" role="search"> - <form class="search" action="{{ pathto('search') }}" method="get"> - <label for="q" style="position:absolute;width:1px;height:1px;overflow: hidden"> - {{ _('Quick search') }} - </label> - <input type="text" placeholder="{{ _('Quick search') }}" name="q" id="q" /> - <input type="submit" value="{{ _('Go') }}" enterkeyhint="go"/> - </form> - </div> - <script>document.getElementById("searchbox").style.display = 'block';</script> -{%- endif %} - -{# Source link #} -{%- if show_source and has_source and sourcename %} - <div class="source-link" role="note" aria-label="source link"> - <a href="https://github.com/python/peps/blob/master/{{sourcename}}">{{_('Page Source (GitHub)')}}</a> - </div> -{%- endif %} - -{# Navigation #} -{%- if title|pep_id|e and title|pep_id|e != "PEP 0000" %} -<div class="related" role="navigation" aria-label="related navigation"> - <h3>{{ _('Quick Navigation') }}</h3> - <nav> - <ul> - {%- if prev %} - <li class=""><a href="{{ prev.link|e }}">{{ prev.title|pep_id|striptags|e }}</a></li> - {%- endif %} - <li class=""><a title="PEP 0" href="{{ pathto('pep-0000') }}">PEP Index</a></li> - {%- if next %} - <li class=""><a href="{{ next.link|e }}">{{ next.title|pep_id|striptags|e }}</a></li> - {%- endif %} - </ul> - </nav> -</div> -{%- endif %} - -{# Table of Contents #} -{%- if display_toc %} -<h3>{{ _('Contents') }}</h3> -{{ toc }} -{%- endif %} \ No newline at end of file diff --git a/pep_extensions/theme/templates/layout.html b/pep_extensions/theme/templates/layout.html deleted file mode 100644 index b019b23102a..00000000000 --- a/pep_extensions/theme/templates/layout.html +++ /dev/null @@ -1,57 +0,0 @@ -{% extends "basic/layout.html" %} - -{% set html_tag = '<html lang="en-GB" class="fontface">' %} -{%- if not embedded %} - {%- set titlesuffix = " | "|safe + docstitle|e %} -{%- else %} - {%- set titlesuffix = "" %} -{%- endif %} - - -{%- block css %} - <link href="{{ pathto('_static/css/style.css', 1) }}" rel="stylesheet"> - <link href="{{ pathto('_static/css/mq.css', 1) }}" rel="stylesheet"> - <link href="{{ pathto('_static/css/pep.css', 1) }}" rel="stylesheet"> - <link rel="stylesheet" href="{{ pathto('_static/pygments.css', 1) }}" type="text/css" /> -{%- endblock %} - -{%- block body_tag %}<body class="python pages pep-page">{% endblock %} -{%- block header %}<header style="height: 219px; background-color: #2b5b84;"></header>{% endblock %} -{%- block relbar1 %}{% endblock %} -{%- block relbar2 %}{% endblock %} -{%- block sidebar2 %}{% endblock %} -{%- block content %} - <div id="touchnav-wrapper"> - <div id="content" class="content-wrapper"> - {%- block document %} - <div class="container"> - {%- if render_sidebar %} - <section class="main-content with-left-sidebar"> - {%- endif %} - {% include "breadcrumbs.html" %} - <article class="text" role="main"> - {% block body %} {% endblock %} - </article> - {%- if render_sidebar %} - </section> - <aside class="left-sidebar" role="navigation"> - {%- if logo %} - <p class="logo"><a href="{{ pathto(master_doc)|e }}"> - <img class="logo" src="{{ pathto('_static/' + logo, 1)|e }}" alt="Logo"/> - </a></p> - {%- endif %} - {% include "customsidebar.html" %} - </aside> - {%- endif %} - </div> - {%- endblock %} - <div class="clearer"></div> - </div> - </div> -{%- endblock %} -{%- block footer %} -<footer> - <div style="height: 553.5px; background-color: #e6e8ea; border-top: 1px solid #d8dbde;"></div> - <div style="height: 103.05px; background-color: #2b5b84;"></div> -</footer> -{%- endblock %} \ No newline at end of file diff --git a/pep_extensions/theme/templates/search.html b/pep_extensions/theme/templates/search.html deleted file mode 100644 index 6187d6d02e4..00000000000 --- a/pep_extensions/theme/templates/search.html +++ /dev/null @@ -1,41 +0,0 @@ -{% extends "basic/search.html" %} -{%- block scripts %} - {{ super() }} - <script src="{{ pathto('_static/searchtools.js', 1) }}"></script> -{%- endblock %} -{% block body %} - <h1 id="search-documentation">{{ _('Search') }}</h1> - <div id="fallback" class="admonition warning"> - <script>document.getElementById("fallback").style.display = "none";</script> - <p> - {% trans %}Please activate JavaScript to enable the search - functionality.{% endtrans %} - </p> - </div> - <p> - {% trans %}Searching for multiple words only shows matches that contain - all words.{% endtrans %} - </p> - <form action="" method="get"> - <input type="text" name="q" aria-labelledby="search-documentation" value="" /> - <input type="submit" value="{{ _('search') }}" /> - <span id="search-progress" style="padding-left: 10px"></span> - </form> - {% if search_performed %} - <h2>{{ _('Search Results') }}</h2> - {% if not search_results %} - <p>{{ _('Your search did not match any documents. Please make sure that all words are spelled correctly and that you\'ve selected enough categories.') }}</p> - {% endif %} - {% endif %} - <div id="search-results"> - {% if search_results %} - <ul> - {% for href, caption, context in search_results %} - <li><a href="{{ pathto(item.href) }}">{{ caption }}</a> - <div class="context">{{ context|e }}</div> - </li> - {% endfor %} - </ul> - {% endif %} - </div> -{% endblock %} \ No newline at end of file diff --git a/pep_extensions/theme/theme.conf b/pep_extensions/theme/theme.conf deleted file mode 100644 index 8a5ba9581bf..00000000000 --- a/pep_extensions/theme/theme.conf +++ /dev/null @@ -1,7 +0,0 @@ -[theme] -inherit = basic -pygments_style = sphinx -pygments_dark_style = monokai - -[options] -root_url = https://www.python.org/ \ No newline at end of file From 08f55d7c2564c31591412d57958d722fd40e3785 Mon Sep 17 00:00:00 2001 From: Adam Turner <9087854+AA-Turner@users.noreply.github.com> Date: Sun, 16 Aug 2020 12:57:16 +0100 Subject: [PATCH 108/108] Change html_title to lowercase (per @pradyunsg) Co-authored-by: Pradyun Gedam <3275593+pradyunsg@users.noreply.github.com> --- conf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conf.py b/conf.py index 5011d01de83..03b20cfb582 100644 --- a/conf.py +++ b/conf.py @@ -43,4 +43,4 @@ html_math_renderer = "math2html" html_show_copyright = False html_show_sphinx = False -html_title = "PEPs.Python.org" +html_title = "peps.python.org"