{"record":{"id":"f2d4f0a91f42450e","repo":"python/cpython","slug":"markupbase-parserbase-must-be-subclassed","errorCode":null,"errorMessage":"_markupbase.ParserBase must be subclassed","messagePattern":"_markupbase\\.ParserBase must be subclassed","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"Lib/_markupbase.py","lineNumber":29,"sourceCode":"_declstringlit_match = re.compile(r'(\\'[^\\']*\\'|\"[^\"]*\")\\s*').match\n_commentclose = re.compile(r'--\\s*>')\n_markedsectionclose = re.compile(r']\\s*]\\s*>')\n\n# An analysis of the MS-Word extensions is available at\n# http://web.archive.org/web/20060321153828/http://www.planetpublish.com/xmlarena/xap/Thursday/WordtoXML.pdf\n\n_msmarkedsectionclose = re.compile(r']\\s*>')\n\ndel re\n\n\nclass ParserBase:\n    \"\"\"Parser base class which provides some common support methods used\n    by the SGML/HTML and XHTML parsers.\"\"\"\n\n    def __init__(self):\n        if self.__class__ is ParserBase:\n            raise RuntimeError(\n                \"_markupbase.ParserBase must be subclassed\")\n\n    def reset(self):\n        self.lineno = 1\n        self.offset = 0\n\n    def getpos(self):\n        \"\"\"Return current line number and offset.\"\"\"\n        return self.lineno, self.offset\n\n    # Internal -- update line number and offset.  This should be\n    # called for each piece of data exactly once, in order -- in other\n    # words the concatenation of all the input strings to this\n    # function should be exactly the entire input.\n    def updatepos(self, i, j):\n        if i >= j:\n            return j\n        rawdata = self.rawdata","sourceCodeStart":11,"sourceCodeEnd":47,"githubUrl":"https://github.com/python/cpython/blob/bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6/Lib/_markupbase.py#L11-L47","documentation":"RuntimeError raised by _markupbase.ParserBase.__init__ (Lib/_markupbase.py) when ParserBase itself is instantiated. The class only supplies shared position/declaration-scanning machinery for SGML/HTML/XHTML parsers (html.parser.HTMLParser, html.parser.HTMLParserBase use cases); it has no document handlers, so direct instantiation is blocked.","triggerScenarios":"Calling _markupbase.ParserBase() directly. Reached when someone imports the private module to reuse its regex scanning helpers, or a metaclass/copy path (e.g. copy.copy then __init__ re-run on the base) instantiates the base class.","commonSituations":"Developers reaching for _markupbase to parse fragments; inheriting from the wrong class in a custom parser; copy/deepcopy or pickle round-trips that reconstruct objects through the base __init__.","solutions":["Subclass ParserBase (adding at least goahead/handlers, or better: subclass html.parser.HTMLParser which composes it) — instantiation of the subclass is allowed.","Use html.parser.HTMLParser for real HTML parsing needs; _markupbase is an implementation detail.","If you only need position tracking (lineno/offset), copy the small getpos/updatepos pattern instead of instantiating the base.","For copy/pickle paths, ensure reconstruction targets the concrete subclass, not ParserBase."],"exampleFix":"# before\nimport _markupbase\np = _markupbase.ParserBase()  # RuntimeError: must be subclassed\n\n# after\nfrom html.parser import HTMLParser\n\nclass MyParser(HTMLParser):\n    pass\n\np = MyParser()  # fine","handlingStrategy":"type-guard","validationCode":"import _markupbase\n\ndef instantiable(cls) -> bool:\n    return cls is not _markupbase.ParserBase","typeGuard":"import _markupbase\n\ndef is_concrete_parser_class(cls) -> bool:\n    \"\"\"True when cls can be instantiated (not the abstract ParserBase itself).\"\"\"\n    return isinstance(cls, type) and issubclass(cls, _markupbase.ParserBase) and cls is not _markupbase.ParserBase","tryCatchPattern":"try:\n    p = _markupbase.ParserBase()\nexcept RuntimeError as e:\n    if 'must be subclassed' in str(e):\n        class MiniParser(_markupbase.ParserBase):\n            pass\n        p = MiniParser()\n    else:\n        raise","preventionTips":["Subclass html.parser.HTMLParser for real work; never instantiate ParserBase.","Avoid importing private stdlib modules (_markupbase) — they are not a stable API.","When copy/pickling parser objects, rebuild via the concrete subclass."],"tags":["markup","html-parser","cpython-internals","developer-error"],"backgroundTag":null,"analyzedSha":"bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6","analyzedAt":"2026-08-14T22:01:13.976Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}