Beispiel #1
0
 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)
Beispiel #2
0
 def visit_reference(node: nodes.reference) -> None:
     """Mask email addresses if present."""
     node.replace_self(peps.mask_email(node))
Beispiel #3
0
 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', 'pep-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)
Beispiel #4
0
    def apply(self) -> None:
        if not Path(self.document["source"]).match("pep-*"):
            return  # not a PEP file, exit early

        if not len(self.document):
            raise PEPParsingError("Document tree is empty.")

        header = self.document[0]
        if not isinstance(
                header,
                nodes.field_list) or "rfc2822" not in header["classes"]:
            raise PEPParsingError(
                "Document does not begin with an RFC-2822 header; it is not a PEP."
            )

        # PEP number should be the first field
        pep_field = header[0]
        if pep_field[0].astext().lower() != "pep":
            raise PEPParsingError(
                "Document does not contain an RFC-2822 'PEP' header!")

        # Extract PEP number
        value = pep_field[1].astext()
        try:
            pep = int(value)
        except ValueError:
            raise PEPParsingError(
                f"'PEP' header must contain an integer. '{value}' is invalid!")

        # Special processing for PEP 0.
        if 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 PEPParsingError("No title!")

        fields_to_remove = []
        for field in header:
            name = field[0].astext().lower()
            body = field[1]
            if len(body) == 0:
                # body is empty
                continue
            elif len(body) > 1:
                msg = f"PEP header field body contains multiple elements:\n{field.pformat(level=1)}"
                raise PEPParsingError(msg)
            elif not isinstance(body[0], nodes.paragraph):  # len(body) == 1
                msg = f"PEP header field body may only contain a single paragraph:\n{field.pformat(level=1)}"
                raise PEPParsingError(msg)

            para = body[0]
            if name in {"author", "bdfl-delegate", "pep-delegate", "sponsor"}:
                # mask emails
                for node in para:
                    if isinstance(node, nodes.reference):
                        pep_num = pep if name == "discussions-to" else -1
                        node.replace_self(peps.mask_email(node, pep_num))
            elif name in {"replaces", "superseded-by", "requires"}:
                # replace PEP numbers with normalised list of links to PEPs
                new_body = []
                space = nodes.Text(" ")
                for ref_pep in re.split(r",?\s+", body.astext()):
                    new_body.append(
                        nodes.reference(
                            ref_pep,
                            ref_pep,
                            refuri=(self.document.settings.pep_base_url +
                                    pep_url.format(int(ref_pep)))))
                    new_body.append(space)
                para[:] = new_body[:-1]  # drop trailing space
            elif name in {"last-modified", "content-type", "version"}:
                # Mark unneeded fields
                fields_to_remove.append(field)

        # Remove unneeded fields
        for field in fields_to_remove:
            field.parent.remove(field)