#1005338 Fails on non breaking space

Package:
pydoctor
Source:
pydoctor
Submitter:
Guido Günther
Date:
2022-03-23 05:33:02 UTC
Severity:
normal
Tags:
#1005338#5
Date:
2022-02-11 14:56:20 UTC
From:
To:
Hi,
I *think* since the switch to python3.9 pydoctor fails to build gbp's
API docs:

make apidocs
pydoctor -v --config=.pydoctor.cfg
adding directory /var/scratch/src/git-buildpackage/git-buildpackage/gbp
adding directory /var/scratch/src/git-buildpackage/git-buildpackage/tests/doctests
processing ['gbp.scripts.create_remote_repo']
processing ['gbp.scripts.create_remote_repo', 'gbp.deb.changelog']
processing ['gbp.scripts.create_remote_repo', 'gbp.deb.changelog', 'gbp.command_wrappers']
processing ['gbp.scripts.create_remote_repo', 'gbp.config']
processing ['gbp.scripts.create_remote_repo', 'gbp.config', 'gbp.errors']
…
Package 'gbp.rpm'
ZopeInterfaceModule 'gbp.rpm.changelog'
ZopeInterfaceClass 'gbp.rpm.changelog.ChangelogError'
ZopeInterfaceClass 'gbp.rpm.changelog._ChangelogHeader'
ZopeInterfaceClass 'gbp.rpm.changelog._ChangelogEntry'
Traceback (most recent call last):
  File "/usr/lib/python3.9/xml/sax/expatreader.py", line 217, in feed
    self._parser.Parse(data, isFinal)
xml.parsers.expat.ExpatError: undefined entity: line 1, column 46

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/twisted/web/_flatten.py", line 321, in _flattenTree
    element = next(stack[-1])
  File "/usr/lib/python3/dist-packages/twisted/web/_flatten.py", line 237, in _flattenElement
    result = renderMethod(request, rootClone)
  File "/usr/lib/python3/dist-packages/pydoctor/templatewriter/pages/functionchild.py", line 73, in functionBody
    return self.docgetter.get(self.ob)
  File "/usr/lib/python3/dist-packages/pydoctor/templatewriter/pages/__init__.py", line 71, in get
    return epydoc2stan.format_docstring(ob)
  File "/usr/lib/python3/dist-packages/pydoctor/epydoc2stan.py", line 744, in format_docstring
    fh.handle(Field.from_epydoc(field, source))
  File "/usr/lib/python3/dist-packages/pydoctor/epydoc2stan.py", line 600, in handle
    m(field)
  File "/usr/lib/python3/dist-packages/pydoctor/epydoc2stan.py", line 529, in handle_type
    self.types[name] = field.format()
  File "/usr/lib/python3/dist-packages/pydoctor/epydoc2stan.py", line 353, in format
    return self.body.to_stan(_EpydocLinker(self.source))
  File "/usr/lib/python3/dist-packages/pydoctor/epydoc/markup/__init__.py", line 134, in to_stan
    self._stan = Tag('', children=node2stan.node2stan(self.to_node(), docstring_linker).children)
  File "/usr/lib/python3/dist-packages/pydoctor/node2stan.py", line 42, in node2stan
    return html2stan(''.join(html))
  File "/usr/lib/python3/dist-packages/pydoctor/stanutils.py", line 30, in html2stan
    stan = XMLString(b'<div>%s</div>' % html).load()[0]
  File "/usr/lib/python3/dist-packages/twisted/web/template.py", line 402, in __init__
    self._loadedTemplate = _flatsaxParse(NativeStringIO(s))
  File "/usr/lib/python3/dist-packages/twisted/web/template.py", line 356, in _flatsaxParse
    parser.parse(fl)
  File "/usr/lib/python3.9/xml/sax/expatreader.py", line 111, in parse
    xmlreader.IncrementalParser.parse(self, source)
  File "/usr/lib/python3.9/xml/sax/xmlreader.py", line 125, in parse
    self.feed(buffer)
  File "/usr/lib/python3.9/xml/sax/expatreader.py", line 221, in feed
    self._err_handler.fatalError(exc)
  File "/usr/lib/python3.9/xml/sax/handler.py", line 38, in fatalError
    raise exception
xml.sax._exceptions.SAXParseException: <unknown>:1:46: undefined entity

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/bin/pydoctor", line 33, in <module>
    sys.exit(load_entry_point('pydoctor==21.12.1', 'console_scripts', 'pydoctor')())
  File "/usr/lib/python3/dist-packages/pydoctor/driver.py", line 482, in main
    writer.writeIndividualFiles(subjects)
  File "/usr/lib/python3/dist-packages/pydoctor/templatewriter/writer.py", line 81, in writeIndividualFiles
    self._writeDocsFor(ob)
  File "/usr/lib/python3/dist-packages/pydoctor/templatewriter/writer.py", line 103, in _writeDocsFor
    self._writeDocsFor(o)
  File "/usr/lib/python3/dist-packages/pydoctor/templatewriter/writer.py", line 103, in _writeDocsFor
    self._writeDocsFor(o)
  File "/usr/lib/python3/dist-packages/pydoctor/templatewriter/writer.py", line 103, in _writeDocsFor
    self._writeDocsFor(o)
  File "/usr/lib/python3/dist-packages/pydoctor/templatewriter/writer.py", line 101, in _writeDocsFor
    self._writeDocsForOne(ob, fobj)
  File "/usr/lib/python3/dist-packages/pydoctor/templatewriter/writer.py", line 123, in _writeDocsForOne
    flattenToFile(fobj, page)
  File "/usr/lib/python3/dist-packages/pydoctor/templatewriter/writer.py", line 31, in flattenToFile
    raise err
twisted.web.error.FlattenerError: Exception while flattening:
  <pydoctor.templatewriter.pages.ZopeInterfaceClassPage object at 0x7f3024199490>
  Tag <>
  [[Tag('html', children=['\n', '  ', '\n', '\n', '  ', Tag('', children=['Head']), '\n', '\n', '  ', Tag('body', children=['\n', '\n', '    ', Tag('div'), '\n', '\n', '    ', Tag('', children=['Nav']), '\n', '\n', '    ', Tag('div', attributes=OrderedDict([('class', 'container')])), '\n', '\n', '    ', Tag('div', attributes=OrderedDict([('class', 'container')]), children=['\n', '\n', '      ', Tag('div', attributes=OrderedDict([('class', 'page-header')]), children=['\n', '        ', slot('heading'), '\n', '        ', Tag('div', attributes=OrderedDict([('id', 'showPrivate')]), children=['\n', '          ', Tag('button', attributes=OrderedDict([('class', 'btn btn-link'), ('onclick', 'togglePrivate()')]), children=['Toggle Private API']), '\n', '        ']), '\n', '      ']), '\n', '\n', '      ', Tag('div', attributes=OrderedDict([('class', 'categoryHeader')]), children=['\n', '        ', slot('category'), '\n', '      ']), '\n', '\n', '      ', Tag('div', attributes=OrderedDict([('class', 'extrasDocstring')]), children=['\n', '        ', slot('extras'), '\n', '        ', Tag('p', children=[Tag('a', children=['View In Hierarchy'])]), '\n', '      ']), '\n', '\n', '      ', Tag('div', attributes=OrderedDict([('class', 'moduleDocstring')]), children=['\n', '        ', slot('docstring'), '\n', '      ']), '\n', '\n', '      ', Tag('div', attributes=OrderedDict([('id', 'splitTables')]), children=['\n', '        ', slot('mainTable'), '\n', '        ', Tag('', children=['\n', '          ', Tag('p', attributes=OrderedDict([('class', 'inheritedFrom')]), children=['\n', '            Inherited from ', slot('baseName'), ':', '\n', '          ']), '\n', '          ', slot('baseTable'), '\n', '          ']), '\n', '\n', '          ', slot('packageInitTable'), '\n', '      ']), '\n', '\n', '      ', Tag('div', attributes=OrderedDict([('id', 'childList')]), children=['\n', '\n', '        ', slot('childlist'), '\n', '\n', '      ']), '\n', '    ']), '\n', '\n', '    ', Tag('footer'), '\n', '\n', '    ', Tag('script', attributes=OrderedDict([('src', 'pydoctor.js'), ('type', 'text/javascript')])), '\n', '\n', '  ']), '\n'])]]
  [Tag('html', children=['\n', '  ', '\n', '\n', '  ', Tag('', children=['Head']), '\n', '\n', '  ', Tag('body', children=['\n', '\n', '    ', Tag('div'), '\n', '\n', '    ', Tag('', children=['Nav']), '\n', '\n', '    ', Tag('div', attributes=OrderedDict([('class', 'container')])), '\n', '\n', '    ', Tag('div', attributes=OrderedDict([('class', 'container')]), children=['\n', '\n', '      ', Tag('div', attributes=OrderedDict([('class', 'page-header')]), children=['\n', '        ', slot('heading'), '\n', '        ', Tag('div', attributes=OrderedDict([('id', 'showPrivate')]), children=['\n', '          ', Tag('button', attributes=OrderedDict([('class', 'btn btn-link'), ('onclick', 'togglePrivate()')]), children=['Toggle Private API']), '\n', '        ']), '\n', '      ']), '\n', '\n', '      ', Tag('div', attributes=OrderedDict([('class', 'categoryHeader')]), children=['\n', '        ', slot('category'), '\n', '      ']), '\n', '\n', '      ', Tag('div', attributes=OrderedDict([('class', 'extrasDocstring')]), children=['\n', '        ', slot('extras'), '\n', '        ', Tag('p', children=[Tag('a', children=['View In Hierarchy'])]), '\n', '      ']), '\n', '\n', '      ', Tag('div', attributes=OrderedDict([('class', 'moduleDocstring')]), children=['\n', '        ', slot('docstring'), '\n', '      ']), '\n', '\n', '      ', Tag('div', attributes=OrderedDict([('id', 'splitTables')]), children=['\n', '        ', slot('mainTable'), '\n', '        ', Tag('', children=['\n', '          ', Tag('p', attributes=OrderedDict([('class', 'inheritedFrom')]), children=['\n', '            Inherited from ', slot('baseName'), ':', '\n', '          ']), '\n', '          ', slot('baseTable'), '\n', '          ']), '\n', '\n', '          ', slot('packageInitTable'), '\n', '      ']), '\n', '\n', '      ', Tag('div', attributes=OrderedDict([('id', 'childList')]), children=['\n', '\n', '        ', slot('childlist'), '\n', '\n', '      ']), '\n', '    ']), '\n', '\n', '    ', Tag('footer'), '\n', '\n', '    ', Tag('script', attributes=OrderedDict([('src', 'pydoctor.js'), ('type', 'text/javascript')])), '\n', '\n', '  ']), '\n'])]
  Tag <html>
  ['\n', '  ', '\n', '\n', '  ', Tag('', children=['Head']), '\n', '\n', '  ', Tag('body', children=['\n', '\n', '    ', Tag('div'), '\n', '\n', '    ', Tag('', children=['Nav']), '\n', '\n', '    ', Tag('div', attributes=OrderedDict([('class', 'container')])), '\n', '\n', '    ', Tag('div', attributes=OrderedDict([('class', 'container')]), children=['\n', '\n', '      ', Tag('div', attributes=OrderedDict([('class', 'page-header')]), children=['\n', '        ', slot('heading'), '\n', '        ', Tag('div', attributes=OrderedDict([('id', 'showPrivate')]), children=['\n', '          ', Tag('button', attributes=OrderedDict([('class', 'btn btn-link'), ('onclick', 'togglePrivate()')]), children=['Toggle Private API']), '\n', '        ']), '\n', '      ']), '\n', '\n', '      ', Tag('div', attributes=OrderedDict([('class', 'categoryHeader')]), children=['\n', '        ', slot('category'), '\n', '      ']), '\n', '\n', '      ', Tag('div', attributes=OrderedDict([('class', 'extrasDocstring')]), children=['\n', '        ', slot('extras'), '\n', '        ', Tag('p', children=[Tag('a', children=['View In Hierarchy'])]), '\n', '      ']), '\n', '\n', '      ', Tag('div', attributes=OrderedDict([('class', 'moduleDocstring')]), children=['\n', '        ', slot('docstring'), '\n', '      ']), '\n', '\n', '      ', Tag('div', attributes=OrderedDict([('id', 'splitTables')]), children=['\n', '        ', slot('mainTable'), '\n', '        ', Tag('', children=['\n', '          ', Tag('p', attributes=OrderedDict([('class', 'inheritedFrom')]), children=['\n', '            Inherited from ', slot('baseName'), ':', '\n', '          ']), '\n', '          ', slot('baseTable'), '\n', '          ']), '\n', '\n', '          ', slot('packageInitTable'), '\n', '      ']), '\n', '\n', '      ', Tag('div', attributes=OrderedDict([('id', 'childList')]), children=['\n', '\n', '        ', slot('childlist'), '\n', '\n', '      ']), '\n', '    ']), '\n', '\n', '    ', Tag('footer'), '\n', '\n', '    ', Tag('script', attributes=OrderedDict([('src', 'pydoctor.js'), ('type', 'text/javascript')])), '\n', '\n', '  ']), '\n']
  Tag <body>
  ['\n', '\n', '    ', Tag('div'), '\n', '\n', '    ', Tag('', children=['Nav']), '\n', '\n', '    ', Tag('div', attributes=OrderedDict([('class', 'container')])), '\n', '\n', '    ', Tag('div', attributes=OrderedDict([('class', 'container')]), children=['\n', '\n', '      ', Tag('div', attributes=OrderedDict([('class', 'page-header')]), children=['\n', '        ', slot('heading'), '\n', '        ', Tag('div', attributes=OrderedDict([('id', 'showPrivate')]), children=['\n', '          ', Tag('button', attributes=OrderedDict([('class', 'btn btn-link'), ('onclick', 'togglePrivate()')]), children=['Toggle Private API']), '\n', '        ']), '\n', '      ']), '\n', '\n', '      ', Tag('div', attributes=OrderedDict([('class', 'categoryHeader')]), children=['\n', '        ', slot('category'), '\n', '      ']), '\n', '\n', '      ', Tag('div', attributes=OrderedDict([('class', 'extrasDocstring')]), children=['\n', '        ', slot('extras'), '\n', '        ', Tag('p', children=[Tag('a', children=['View In Hierarchy'])]), '\n', '      ']), '\n', '\n', '      ', Tag('div', attributes=OrderedDict([('class', 'moduleDocstring')]), children=['\n', '        ', slot('docstring'), '\n', '      ']), '\n', '\n', '      ', Tag('div', attributes=OrderedDict([('id', 'splitTables')]), children=['\n', '        ', slot('mainTable'), '\n', '        ', Tag('', children=['\n', '          ', Tag('p', attributes=OrderedDict([('class', 'inheritedFrom')]), children=['\n', '            Inherited from ', slot('baseName'), ':', '\n', '          ']), '\n', '          ', slot('baseTable'), '\n', '          ']), '\n', '\n', '          ', slot('packageInitTable'), '\n', '      ']), '\n', '\n', '      ', Tag('div', attributes=OrderedDict([('id', 'childList')]), children=['\n', '\n', '        ', slot('childlist'), '\n', '\n', '      ']), '\n', '    ']), '\n', '\n', '    ', Tag('footer'), '\n', '\n', '    ', Tag('script', attributes=OrderedDict([('src', 'pydoctor.js'), ('type', 'text/javascript')])), '\n', '\n', '  ']
  Tag <div>
  ['\n', '\n', '      ', Tag('div', attributes=OrderedDict([('class', 'page-header')]), children=['\n', '        ', slot('heading'), '\n', '        ', Tag('div', attributes=OrderedDict([('id', 'showPrivate')]), children=['\n', '          ', Tag('button', attributes=OrderedDict([('class', 'btn btn-link'), ('onclick', 'togglePrivate()')]), children=['Toggle Private API']), '\n', '        ']), '\n', '      ']), '\n', '\n', '      ', Tag('div', attributes=OrderedDict([('class', 'categoryHeader')]), children=['\n', '        ', slot('category'), '\n', '      ']), '\n', '\n', '      ', Tag('div', attributes=OrderedDict([('class', 'extrasDocstring')]), children=['\n', '        ', slot('extras'), '\n', '        ', Tag('p', children=[Tag('a', children=['View In Hierarchy'])]), '\n', '      ']), '\n', '\n', '      ', Tag('div', attributes=OrderedDict([('class', 'moduleDocstring')]), children=['\n', '        ', slot('docstring'), '\n', '      ']), '\n', '\n', '      ', Tag('div', attributes=OrderedDict([('id', 'splitTables')]), children=['\n', '        ', slot('mainTable'), '\n', '        ', Tag('', children=['\n', '          ', Tag('p', attributes=OrderedDict([('class', 'inheritedFrom')]), children=['\n', '            Inherited from ', slot('baseName'), ':', '\n', '          ']), '\n', '          ', slot('baseTable'), '\n', '          ']), '\n', '\n', '          ', slot('packageInitTable'), '\n', '      ']), '\n', '\n', '      ', Tag('div', attributes=OrderedDict([('id', 'childList')]), children=['\n', '\n', '        ', slot('childlist'), '\n', '\n', '      ']), '\n', '    ']
  Tag <div>
  ['\n', '\n', '        ', slot('childlist'), '\n', '\n', '      ']
  slot('childlist')
  [<pydoctor.templatewriter.pages.functionchild.FunctionChild object at 0x7f30236ec7f0>, <pydoctor.templatewriter.pages.functionchild.FunctionChild object at 0x7f30236ec280>, <pydoctor.templatewriter.pages.attributechild.AttributeChild object at 0x7f30236ecf70>, <pydoctor.templatewriter.pages.attributechild.AttributeChild object at 0x7f30236ec310>, <pydoctor.templatewriter.pages.attributechild.AttributeChild object at 0x7f30236eca90>]
  <pydoctor.templatewriter.pages.functionchild.FunctionChild object at 0x7f30236ec7f0>
  [Tag('div', attributes=OrderedDict([('class', Tag(''))]), children=['\n', '  ', '\n', '  ', '\n', '  ', Tag('a', attributes=OrderedDict([('name', Tag(''))]), children=['\n', '    ', '\n', '  ']), '\n', '  ', Tag('a', attributes=OrderedDict([('name', Tag(''))]), children=['\n', '    ', '\n', '  ']), '\n', '  ', Tag('div', attributes=OrderedDict([('class', 'functionHeader')]), children=['\n', '    ', Tag(''), '\n', '    ', Tag('', children=['\n', '      def functionName():', '\n', '    ']), '\n', '    ', Tag('a', attributes=OrderedDict([('class', 'sourceLink'), ('href', Tag('', children=[slot('sourceHref')]))]), children=['\n', '      ', '\n', '      (source)', '\n', '    ']), '\n', '  ']), '\n', '  ', Tag('div', attributes=OrderedDict([('class', 'docstring functionBody')]), children=['\n', '    ', Tag(''), '\n', '    ', Tag(''), '\n', '    ', Tag('', children=['\n', '      Docstring.', '\n', '    ']), '\n', '  ']), '\n'])]
  Tag <div>
  ['\n', '  ', '\n', '  ', '\n', '  ', Tag('a', attributes=OrderedDict([('name', Tag(''))]), children=['\n', '    ', '\n', '  ']), '\n', '  ', Tag('a', attributes=OrderedDict([('name', Tag(''))]), children=['\n', '    ', '\n', '  ']), '\n', '  ', Tag('div', attributes=OrderedDict([('class', 'functionHeader')]), children=['\n', '    ', Tag(''), '\n', '    ', Tag('', children=['\n', '      def functionName():', '\n', '    ']), '\n', '    ', Tag('a', attributes=OrderedDict([('class', 'sourceLink'), ('href', Tag('', children=[slot('sourceHref')]))]), children=['\n', '      ', '\n', '      (source)', '\n', '    ']), '\n', '  ']), '\n', '  ', Tag('div', attributes=OrderedDict([('class', 'docstring functionBody')]), children=['\n', '    ', Tag(''), '\n', '    ', Tag(''), '\n', '    ', Tag('', children=['\n', '      Docstring.', '\n', '    ']), '\n', '  ']), '\n']
  Tag <div>
  ['\n', '    ', Tag(''), '\n', '    ', Tag(''), '\n', '    ', Tag('', children=['\n', '      Docstring.', '\n', '    ']), '\n', '  ']
  Tag <>
  File "/usr/lib/python3/dist-packages/twisted/web/_flatten.py", line 321, in _flattenTree
    element = next(stack[-1])
  File "/usr/lib/python3/dist-packages/twisted/web/_flatten.py", line 237, in _flattenElement
    result = renderMethod(request, rootClone)
  File "/usr/lib/python3/dist-packages/pydoctor/templatewriter/pages/functionchild.py", line 73, in functionBody
    return self.docgetter.get(self.ob)
  File "/usr/lib/python3/dist-packages/pydoctor/templatewriter/pages/__init__.py", line 71, in get
    return epydoc2stan.format_docstring(ob)
  File "/usr/lib/python3/dist-packages/pydoctor/epydoc2stan.py", line 744, in format_docstring
    fh.handle(Field.from_epydoc(field, source))
  File "/usr/lib/python3/dist-packages/pydoctor/epydoc2stan.py", line 600, in handle
    m(field)
  File "/usr/lib/python3/dist-packages/pydoctor/epydoc2stan.py", line 529, in handle_type
    self.types[name] = field.format()
  File "/usr/lib/python3/dist-packages/pydoctor/epydoc2stan.py", line 353, in format
    return self.body.to_stan(_EpydocLinker(self.source))
  File "/usr/lib/python3/dist-packages/pydoctor/epydoc/markup/__init__.py", line 134, in to_stan
    self._stan = Tag('', children=node2stan.node2stan(self.to_node(), docstring_linker).children)
  File "/usr/lib/python3/dist-packages/pydoctor/node2stan.py", line 42, in node2stan
    return html2stan(''.join(html))
  File "/usr/lib/python3/dist-packages/pydoctor/stanutils.py", line 30, in html2stan
    stan = XMLString(b'<div>%s</div>' % html).load()[0]
  File "/usr/lib/python3/dist-packages/twisted/web/template.py", line 402, in __init__
    self._loadedTemplate = _flatsaxParse(NativeStringIO(s))
  File "/usr/lib/python3/dist-packages/twisted/web/template.py", line 356, in _flatsaxParse
    parser.parse(fl)
  File "/usr/lib/python3.9/xml/sax/expatreader.py", line 111, in parse
    xmlreader.IncrementalParser.parse(self, source)
  File "/usr/lib/python3.9/xml/sax/xmlreader.py", line 125, in parse
    self.feed(buffer)
  File "/usr/lib/python3.9/xml/sax/expatreader.py", line 221, in feed
    self._err_handler.fatalError(exc)
  File "/usr/lib/python3.9/xml/sax/handler.py", line 38, in fatalError
    raise exception
SAXParseException: <unknown>:1:46: undefined entity

make: *** [Makefile:30: apidocs] Error 1

See e.g. https://salsa.debian.org/agx/git-buildpackage/-/jobs/2455952

I'd appreciate any hints to debug this further. My poor man's `print()`
approach didn't go very far. (Excluding the gbp.rpm module from the doc
build lets it pass)
Cheers,
 -- Guido