python / python/cpython

Add flush() to HTMLParser to fill gap after implementation change

Ouverte
#157,003 1 commentaire 0 réactions 1 personne assignée Voir sur GitHub

@serhiy-storchaka y travaille déjà.

Depuis le 5/9/2026.

3.16 stdlib type-feature
Langage dominant
Python
Étoiles
77.2k
Forks
35.9k
Métriques de merge des PR
Métriques de PR en attente

Description

Feature or enhancement

Proposal:

With recent changes it isn't clear when the the parser actually does the parsing/processing anymore on the data given to feed().

Changes were made in #153030 , (seen in 3.14.7), which leave this gap in the HTMLParser.

Propose adding a flush method as seen below ( I reset the parse threshold to 1 which differs from my proposal on discuss, seems appropriate?):

class PrototypeHTMLParser(HTMLParser):

    def flush(self):
        """
        Process all data fed insofar as it contains complete elements any remaining data remains buffered.
        """
        if self._pending:
            self.rawdata += ''.join(self._pending)
            self._pending.clear()
            self._pending_len = 0
            self._parse_threshold = 1
        # Perform incremental parsing but its not EOF.
        self.goahead(0)
Example
from html.parser import HTMLParser


class FlushableHTMLParser(HTMLParser):
    """
    Parser with flush implemented.

    This would be meant to be added to the existing HTMLParser.
    """
    def flush(self):
        if self._pending:
            self.rawdata += ''.join(self._pending)
            self._pending.clear()
            self._pending_len = 0
            self._parse_threshold = 1
        self.goahead(0)


class DemoHTMLParser(FlushableHTMLParser):

    def handle_starttag(self, tag, attrs):
        print (f'Found starttag {tag=} {len(attrs)=}')

    def handle_endtag(self, tag):
        print (f'Found endtag {tag=}')


def parse(html_str_parts: list[str]):
    parser = DemoHTMLParser()
    for part in html_str_parts:
        print (f'Feed {len(part)}')
        parser.feed(part)
    print ('')
    print ('Calling flush()')
    parser.flush()
    print ('Calling close()')
    parser.close()


def demo_attrs(attrs_len):
    print (f'\nDemo with {attrs_len=}')
    print ('='*20)
    attrs = [f" a{i}='1'" for i in range(attrs_len)]
    parse(["<div", *attrs, ">", "content", "</div>"])


if __name__ == '__main__':
    for attrs_len in (2, 8):
        demo_attrs(attrs_len)

Demo with attrs_len=2
====================
Feed 4
Feed 7
Feed 7
Feed 1
Feed 7
Found starttag tag='div' len(attrs)=2
Feed 6
Found endtag tag='div'

Calling flush()
Calling close()

Demo with attrs_len=8
====================
Feed 4
Feed 7
Feed 7
Feed 7
Feed 7
Feed 7
Feed 7
Feed 7
Feed 7
Feed 1
Feed 7
Feed 6

Calling flush()
Found starttag tag='div' len(attrs)=8
Found endtag tag='div'
Calling close()
Other Doc Changes

I think the feed() doc string also needs a cleanup to match these changes. Should that also be part of this issue?

Handling EOF

There is a related issue about how can a stdlib user determine what should be done when close() is called and data is discarded. Specifically from the living spec, eof-in-tag error case. I'm going to link it but include the text here as well:

This error occurs if the parser encounters the end of the input stream in a start tag or an end tag (e.g., <div id=). Such a tag is ignored.

Should I start that in discuss in the same thread as before or make another issue about that? Maybe it is beyond the scope of the python stdlib parser? It seems like a hard problem but it kind of makes the parser into partial solution in certain use cases.

Has this already been discussed elsewhere?

I have already discussed this feature proposal on Discourse

Links to previous discussion of this feature:

https://discuss.python.org/t/proposal-add-new-method-to-htmlparser-flush-self-str/108855

Linked PRs
  • gh-157012

Guide de contribution

Ouvrir le guide de contribution

Par où commencer

  1. Lisez l'issue en entier, puis le guide de contribution du projet.
  2. Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
  3. Forkez le dépôt et travaillez sur une branche.
  4. Ouvrez une pull request qui référence le numéro de l'issue.

Évaluation

Cette issue n'a pas encore été évaluée.

Recevez les nouvelles issues par e-mail

Un résumé court des issues GitHub adaptées aux débutants.