Skip to content

Commit

Permalink
Fix compatibility with docutils 0.21.x (#779)
Browse files Browse the repository at this point in the history
* Ensure the rst- prefix on all css classes generated in docutils nodes.

* Use python 3.13. alpha 5 version because of issue msgpack/msgpack-python#593
  • Loading branch information
tristanlatr committed Apr 19, 2024
1 parent fe29bb7 commit 8da9fb6
Show file tree
Hide file tree
Showing 9 changed files with 65 additions and 51 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/unit.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:

strategy:
matrix:
python-version: [pypy-3.7, 3.7, 3.8, 3.9, '3.10', 3.11, '3.12', '3.13-dev']
python-version: [pypy-3.7, 3.7, 3.8, 3.9, '3.10', 3.11, '3.12', '3.13.0-alpha.5']
os: [ubuntu-20.04]
include:
- os: windows-latest
Expand Down
2 changes: 2 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,8 @@ This is the last major release to support Python 3.7.
order of class members and module/package members, the supported values are "alphabetical" or "source".
The default behavior is to sort all members alphabetically.
* Make sure the line number coming from ast analysis has precedence over the line of a ``ivar`` field.
* Ensure that all docutils generated css classes have the ``rst-`` prefix, the base theme have been updated accordingly.
* Fix compatibility issue with docutils 0.21.x

pydoctor 23.9.1
^^^^^^^^^^^^^^^
Expand Down
24 changes: 18 additions & 6 deletions pydoctor/node2stan.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"""
from __future__ import annotations

from itertools import chain
import re
import optparse
from typing import Any, Callable, ClassVar, Iterable, List, Optional, Union, TYPE_CHECKING
Expand Down Expand Up @@ -148,6 +149,11 @@ def starttag(self, node: nodes.Node, tagname: str, suffix: str = '\n', **attribu
- hrefs not starting with C{'#'} are given target='_top'
- all headings (C{<hM{n}>}) are given the css class C{'heading'}
"""

to_list_names = {'name':'names',
'id':'ids',
'class':'classes'}

# Get the list of all attribute dictionaries we need to munge.
attr_dicts = [attributes]
if isinstance(node, nodes.Node):
Expand All @@ -158,15 +164,21 @@ def starttag(self, node: nodes.Node, tagname: str, suffix: str = '\n', **attribu
# iterate through attributes one at a time because some
# versions of docutils don't case-normalize attributes.
for attr_dict in attr_dicts:
for key, val in tuple(attr_dict.items()):
# Prefix all CSS classes with "rst-"; and prefix all
# Prefix all CSS classes with "rst-"; and prefix all
# names with "rst-" to avoid conflicts.
done = set()
for key, val in tuple(attr_dict.items()):
if key.lower() in ('class', 'id', 'name'):
if not val.startswith('rst-'):
attr_dict[key] = f'rst-{val}'
elif key.lower() in ('classes', 'ids', 'names'):
list_key = to_list_names[key.lower()]
attr_dict[list_key] = [f'rst-{cls}' if not cls.startswith('rst-')
else cls for cls in sorted(chain(val.split(),
attr_dict.get(list_key, ())))]
del attr_dict[key]
done.add(list_key)
for key, val in tuple(attr_dict.items()):
if key.lower() in ('classes', 'ids', 'names') and key.lower() not in done:
attr_dict[key] = [f'rst-{cls}' if not cls.startswith('rst-')
else cls for cls in val]
else cls for cls in sorted(val)]
elif key.lower() == 'href':
if attr_dict[key][:1]=='#':
href = attr_dict[key][1:]
Expand Down
4 changes: 2 additions & 2 deletions pydoctor/test/epydoc/test_epytext.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,8 @@ def test_literal_braces() -> None:
This test makes sure that braces are getting rendered as desired.
"""
assert epytext2html("{1:{2:3}}") == '{1:{2:3}}'
assert epytext2html("C{{1:{2:3}}}") == '<tt class="rst-docutils literal"><span class="pre">{1:{2:3}}</span></tt>'
assert epytext2html("{1:C{{2:3}}}") == '{1:<tt class="rst-docutils literal">{2:3}</tt>}'
assert epytext2html("C{{1:{2:3}}}") == '<tt class="rst-docutils rst-literal"><span class="pre">{1:{2:3}}</span></tt>'
assert epytext2html("{1:C{{2:3}}}") == '{1:<tt class="rst-docutils rst-literal">{2:3}</tt>}'
assert epytext2html("{{{}{}}{}}") == '{{{}{}}{}}'
assert epytext2html("{{E{lb}E{lb}E{lb}}}") == '{{{{{}}'

Expand Down
32 changes: 16 additions & 16 deletions pydoctor/test/epydoc/test_epytext2html.py
Original file line number Diff line number Diff line change
Expand Up @@ -225,9 +225,9 @@ def test_epytext_inline() -> None:
expected = '''
<p> <em> <strong> Inline markup </strong> may be nested; and it may span </em> multiple lines.</p>
<ul class="rst-simple"> <li> <em> Italicized text </em> </li> <li> <strong> Bold-faced text </strong> </li>
<li> <tt class="rst-docutils literal"> Source code </tt> </li>
<li> Math: <span class="rst-math rst-formula"> <i> m </i> * <i> x </i> + <i> b </i> </span> </li></ul>
<p> Without the capital letter, matching braces are not interpreted as markup: <tt class="rst-docutils literal">
<li> <tt class="rst-docutils rst-literal"> Source code </tt> </li>
<li> Math: <span class="rst-formula rst-math"> <i> m </i> * <i> x </i> + <i> b </i> </span> </li></ul>
<p> Without the capital letter, matching braces are not interpreted as markup: <tt class="rst-docutils rst-literal">
<span class="pre"> my_dict={1:2, </span> 3:4} </tt> .</p>
'''
assert epytext2html(doc) == squash(expected)
Expand All @@ -246,11 +246,11 @@ def test_epytext_url() -> None:
'''
expected = '''
<ul class="rst-simple">
<li><a class="rst-reference external" href="http://www.python.org" target="_top">www.python.org</a></li>
<li><a class="rst-reference external" href="http://www.python.org" target="_top">http://www.python.org</a></li>
<li><a class="rst-reference external" href="http://epydoc.sourceforge.net" target="_top">The epydoc homepage</a></li>
<li><a class="rst-reference external" href="http://www.python.org" target="_top">The<strong><em>Python</em></strong>homepage</a></li>
<li><a class="rst-reference external" href="mailto:edloper@gradient.cis.upenn.edu" target="_top">Edward Loper</a></li></ul>'''
<li><a class="rst-external rst-reference" href="http://www.python.org" target="_top">www.python.org</a></li>
<li><a class="rst-external rst-reference" href="http://www.python.org" target="_top">http://www.python.org</a></li>
<li><a class="rst-external rst-reference" href="http://epydoc.sourceforge.net" target="_top">The epydoc homepage</a></li>
<li><a class="rst-external rst-reference" href="http://www.python.org" target="_top">The<strong><em>Python</em></strong>homepage</a></li>
<li><a class="rst-external rst-reference" href="mailto:edloper@gradient.cis.upenn.edu" target="_top">Edward Loper</a></li></ul>'''

assert epytext2html(doc) == squash(expected)

Expand Down Expand Up @@ -286,7 +286,7 @@ def test_nested_markup() -> None:
It becomes a little bit complicated with U{B{custom} links <https://google.ca>}
'''
expected = '''
It becomes a little bit complicated with<a class="rst-reference external" href="https://google.ca" target="_top"><strong>custom</strong>links</a>
It becomes a little bit complicated with<a class="rst-external rst-reference" href="https://google.ca" target="_top"><strong>custom</strong>links</a>
'''

assert epytext2html(doc) == squash(expected)
Expand Down Expand Up @@ -335,42 +335,42 @@ def test_get_toc() -> None:
expected_html="""
<li>
<p class="rst-first">
<a class="rst-reference internal" href="#rst-titles" id="rst-toc-entry-1">
<a class="rst-internal rst-reference" href="#rst-titles" id="rst-toc-entry-1">
Titles
</a>
</p>
<ul class="rst-simple">
<li>
<a class="rst-reference internal" href="#rst-level-2" id="rst-toc-entry-2">
<a class="rst-internal rst-reference" href="#rst-level-2" id="rst-toc-entry-2">
Level 2
</a>
<ul>
<li>
<a class="rst-reference internal" href="#rst-level-3" id="rst-toc-entry-3">
<a class="rst-internal rst-reference" href="#rst-level-3" id="rst-toc-entry-3">
Level 3
</a>
</li>
</ul>
</li>
<li>
<a class="rst-reference internal" href="#rst-level-22" id="rst-toc-entry-4">
<a class="rst-internal rst-reference" href="#rst-level-22" id="rst-toc-entry-4">
Level 2.2
</a>
</li>
<li>
<a class="rst-reference internal" href="#rst-level-22-1" id="rst-toc-entry-5">
<a class="rst-internal rst-reference" href="#rst-level-22-1" id="rst-toc-entry-5">
Level 22
</a>
</li>
</ul>
</li>
<li>
<a class="rst-reference internal" href="#rst-lists" id="rst-toc-entry-6">
<a class="rst-internal rst-reference" href="#rst-lists" id="rst-toc-entry-6">
Lists
</a>
</li>
<li>
<a class="rst-reference internal" href="#rst-other" id="rst-toc-entry-7">
<a class="rst-internal rst-reference" href="#rst-other" id="rst-toc-entry-7">
Other
</a>
</li>
Expand Down
34 changes: 17 additions & 17 deletions pydoctor/test/epydoc/test_restructuredtext.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,16 +114,16 @@ def test_rst_xref_implicit_target() -> None:

def test_rst_directive_adnomitions() -> None:
expected_html_multiline="""
<div class="rst-admonition {}">
<p class="rst-first rst-admonition-title">{}</p>
<div class="rst-admonition rst-{}">
<p class="rst-admonition-title rst-first">{}</p>
<p>this is the first line</p>
<p class="rst-last">and this is the second line</p>
</div>
"""

expected_html_single_line = """
<div class="rst-admonition {}">
<p class="rst-first rst-admonition-title">{}</p>
<div class="rst-admonition rst-{}">
<p class="rst-admonition-title rst-first">{}</p>
<p class="rst-last">this is a single line</p>
</div>
"""
Expand Down Expand Up @@ -177,7 +177,7 @@ def test_rst_directive_versionadded() -> None:
"""
html = rst2html(".. versionadded:: 0.6")
expected_html="""<div class="rst-versionadded">
<span class="rst-versionmodified rst-added">New in version 0.6.</span></div>
<span class="rst-added rst-versionmodified">New in version 0.6.</span></div>
"""
assert html==expected_html, html

Expand All @@ -189,7 +189,7 @@ def test_rst_directive_versionchanged() -> None:
html = rst2html(""".. versionchanged:: 0.7
Add extras""")
expected_html="""<div class="rst-versionchanged">
<span class="rst-versionmodified rst-changed">Changed in version 0.7: </span><span>Add extras</span></div>
<span class="rst-changed rst-versionmodified">Changed in version 0.7: </span><span>Add extras</span></div>
"""
assert html==expected_html, html

Expand All @@ -201,16 +201,16 @@ def test_rst_directive_deprecated() -> None:
html = rst2html(""".. deprecated:: 0.2
For security reasons""")
expected_html="""<div class="rst-deprecated">
<span class="rst-versionmodified rst-deprecated">Deprecated since version 0.2: </span><span>For security reasons</span></div>
<span class="rst-deprecated rst-versionmodified">Deprecated since version 0.2: </span><span>For security reasons</span></div>
"""
assert html==expected_html, html

def test_rst_directive_seealso() -> None:

html = rst2html(".. seealso:: Hey")
expected_html = """
<div class="rst-admonition seealso">
<p class="rst-first rst-admonition-title">See Also</p>
<div class="rst-admonition rst-seealso">
<p class="rst-admonition-title rst-first">See Also</p>
<p class="rst-last">Hey</p>
</div>"""
assert prettify(html).strip() == prettify(expected_html).strip(), html
Expand Down Expand Up @@ -297,23 +297,23 @@ def test_get_toc() -> None:
expected_html="""
<li>
<p class="rst-first">
<a class="rst-reference internal" href="#rst-titles" id="rst-toc-entry-1">
<a class="rst-internal rst-reference" href="#rst-titles" id="rst-toc-entry-1">
Titles
</a>
</p>
<ul class="rst-simple">
<li>
<a class="rst-reference internal" href="#rst-level-2" id="rst-toc-entry-2">
<a class="rst-internal rst-reference" href="#rst-level-2" id="rst-toc-entry-2">
Level 2
</a>
<ul>
<li>
<a class="rst-reference internal" href="#rst-level-3" id="rst-toc-entry-3">
<a class="rst-internal rst-reference" href="#rst-level-3" id="rst-toc-entry-3">
Level 3
</a>
<ul>
<li>
<a class="rst-reference internal" href="#rst-level-4" id="rst-toc-entry-4">
<a class="rst-internal rst-reference" href="#rst-level-4" id="rst-toc-entry-4">
Level 4
</a>
</li>
Expand All @@ -322,24 +322,24 @@ def test_get_toc() -> None:
</ul>
</li>
<li>
<a class="rst-reference internal" href="#rst-level-2-2" id="rst-toc-entry-5">
<a class="rst-internal rst-reference" href="#rst-level-2-2" id="rst-toc-entry-5">
Level 2.2
</a>
</li>
<li>
<a class="rst-reference internal" href="#rst-level-22" id="rst-toc-entry-6">
<a class="rst-internal rst-reference" href="#rst-level-22" id="rst-toc-entry-6">
Level 22
</a>
</li>
</ul>
</li>
<li>
<a class="rst-reference internal" href="#rst-lists" id="rst-toc-entry-7">
<a class="rst-internal rst-reference" href="#rst-lists" id="rst-toc-entry-7">
Lists
</a>
</li>
<li>
<a class="rst-reference internal" href="#rst-other" id="rst-toc-entry-8">
<a class="rst-internal rst-reference" href="#rst-other" id="rst-toc-entry-8">
Other
</a>
</li>
Expand Down
4 changes: 2 additions & 2 deletions pydoctor/test/test_epydoc2stan.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,12 +89,12 @@ def test_html_empty_module() -> None:
mod = fromText('''
"""C{thing}"""
''', modname='module')
assert docstring2html(mod) == '<div>\n<p>\n<tt class="rst-docutils literal">thing</tt>\n</p>\n</div>'
assert docstring2html(mod) == '<div>\n<p>\n<tt class="rst-docutils rst-literal">thing</tt>\n</p>\n</div>'

mod = fromText('''
"""My C{thing}."""
''', modname='module')
assert docstring2html(mod) == '<div>\n<p>My <tt class="rst-docutils literal">thing</tt>.</p>\n</div>'
assert docstring2html(mod) == '<div>\n<p>My <tt class="rst-docutils rst-literal">thing</tt>.</p>\n</div>'

mod = fromText('''
"""
Expand Down
2 changes: 1 addition & 1 deletion pydoctor/test/test_type_fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,7 @@ def process(typestr: str) -> str:
assert process("'hello'[str]") == "<span class=\"literal\">'hello'</span>[<code>str]</code>"
assert process('"hello"[str]') == "<span class=\"literal\">\"hello\"</span>[<code>str]</code>"
assert process('`hello`[str]') == "<code>hello</code>[<code>str]</code>"
assert process('`hello <https://github.com>`_[str]') == """<a class="rst-reference external" href="https://github.com" target="_top">hello</a>[<code>str]</code>"""
assert process('`hello <https://github.com>`_[str]') == """<a class="rst-external rst-reference" href="https://github.com" target="_top">hello</a>[<code>str]</code>"""
assert process('**hello**[str]') == "<strong>hello</strong>[<code>str]</code>"
assert process('["hello" or str, default: 2]') == """[<span class="literal">"hello"</span> or <code>str</code>, <em>default</em>: <span class="literal">2</span>]"""

Expand Down
12 changes: 6 additions & 6 deletions pydoctor/themes/base/apidocs.css
Original file line number Diff line number Diff line change
Expand Up @@ -409,7 +409,7 @@ table .private {
- 'functionHeader' is used for lines like `def func():` and `var =`
*/
code, .literal, .pre, #childList > div .functionHeader,
code, .rst-literal, .pre, #childList > div .functionHeader,
#splitTables > table tr td:nth-child(2), .fieldArg {
font-family: Menlo, Monaco, Consolas, "Courier New", monospace;
}
Expand Down Expand Up @@ -452,7 +452,7 @@ blockquote {
This defines the code style, it's black on light gray.
It also overwrite the default values inherited from bootstrap min
*/
code, .literal {
code, .rst-literal {
padding:2px 4px;
background-color: #f4f4f4;
border-radius:4px
Expand Down Expand Up @@ -579,20 +579,20 @@ div.rst-admonition {
border-radius: 4px;
}

div.warning, div.attention, div.danger, div.error, div.caution {
div.rst-warning, div.rst-attention, div.rst-danger, div.rst-error, div.rst-caution {
background-color: #ffcf9cb0;
border: 1px solid #ffbbaa;
}

div.danger p.rst-admonition-title, div.error p.rst-admonition-title, div.caution p.rst-admonition-title {
div.rst-danger p.rst-admonition-title, div.rst-error p.rst-admonition-title, div.rst-caution p.rst-admonition-title {
color: #b94a48;
}

div.tip p.rst-admonition-title, div.hint p.rst-admonition-title, div.important p.rst-admonition-title{
div.rst-tip p.rst-admonition-title, div.rst-hint p.rst-admonition-title, div.rst-important p.rst-admonition-title{
color: #3a87ad;
}

div.tip, div.hint, div.important {
div.rst-tip, div.rst-hint, div.rst-important {
background-color: #d9edf7;
border-color: #bce8f1;
}
Expand Down

0 comments on commit 8da9fb6

Please sign in to comment.