supriya-project / uqbar

Tools for building documentation with Sphinx, Graphviz and LaTeX
https://supriya-project.github.io/uqbar
MIT License
13 stars 7 forks source link

Sphinx: ERROR: Content block expected for the "container" directive; none found. #87

Open trevorbaca opened 1 year ago

trevorbaca commented 1 year ago

Sometime after January 14 (Abjad 3.15) and yesterday, Sphinx started to issue an ERROR/WARNING pair for every .. container:: example directive that's followed by explanatory text (rather than by example Python code).

So Sphinx errors on this (explanatory text immediately after container directive):

        ..  container:: example

            Gets slice open at right:

            >>> items = [0, 1, 2, 3, 4, 5]
            >>> tuple_ = abjad.CyclicTuple(items=items)
            >>> tuple_[2:]
            (2, 3, 4, 5)

But Sphinx is happy with this (explanatory text hoisted outside of container directive):

        Gets slice open at right:

        ..  container:: example

            >>> items = [0, 1, 2, 3, 4, 5]
            >>> tuple_ = abjad.CyclicTuple(items=items)
            >>> tuple_[2:]
            (2, 3, 4, 5)

Are you seeing anything similar? Is there any chance this has to do with uqbar? It's possible the problem could be Sphinx itself, or black. But I can't figure it out.

It seems like these same errors should be occurring when building uqbar's own docs, at ...

https://github.com/josiah-wolf-oberholtzer/uqbar/blob/42b24f7917d2b2078e44cf184d9e45adf5d091d5/uqbar/book/console.py#L86

https://github.com/josiah-wolf-oberholtzer/uqbar/blob/42b24f7917d2b2078e44cf184d9e45adf5d091d5/uqbar/book/console.py#L104

https://github.com/josiah-wolf-oberholtzer/uqbar/blob/42b24f7917d2b2078e44cf184d9e45adf5d091d5/uqbar/book/console.py#L122

... for example.

For reference, Sphinx's error output on Abjad's API looks like this:

/Users/trevor/abjad/abjad/bind.py:docstring of abjad.bind.annotate:1: ERROR: Content block expected for the "container" directive; none found.
/Users/trevor/abjad/abjad/bind.py:docstring of abjad.bind.annotate:1: WARNING: Explicit markup ends without a blank line; unexpected unindent.
/Users/trevor/abjad/abjad/bind.py:docstring of abjad.bind.Wrapper.__copy__:1: ERROR: Content block expected for the "container" directive; none found.
/Users/trevor/abjad/abjad/bind.py:docstring of abjad.bind.Wrapper.__copy__:1: WARNING: Explicit markup ends without a blank line; unexpected unindent.
/Users/trevor/abjad/abjad/cyclictuple.py:docstring of abjad.cyclictuple.CyclicTuple.__getitem__:1: ERROR: Content block expected for the "container" directive; none found.
/Users/trevor/abjad/abjad/cyclictuple.py:docstring of abjad.cyclictuple.CyclicTuple.__getitem__:1: WARNING: Explicit markup ends without a blank line; unexpected unindent.
/Users/trevor/abjad/abjad/duration.py:docstring of abjad.duration.Duration.__ne__:6: ERROR: Content block expected for the "container" directive; none found.
/Users/trevor/abjad/abjad/duration.py:docstring of abjad.duration.Duration.__ne__:7: WARNING: Explicit markup ends without a blank line; unexpected unindent.
/Users/trevor/abjad/abjad/duration.py:docstring of abjad.duration.Duration.to_clock_string:1: ERROR: Content block expected for the "container" directive; none found.
/Users/trevor/abjad/abjad/duration.py:docstring of abjad.duration.Duration.to_clock_string:1: WARNING: Explicit markup ends without a blank line; unexpected unindent.
/Users/trevor/abjad/abjad/duration.py:docstring of abjad.duration.Duration.from_lilypond_duration_string:1: ERROR: Content block expected for the "container" directive; none found.
/Users/trevor/abjad/abjad/duration.py:docstring of abjad.duration.Duration.from_lilypond_duration_string:1: WARNING: Explicit markup ends without a blank line; unexpected unindent.
/Users/trevor/abjad/abjad/duration.py:docstring of abjad.duration.Duration.is_token:1: ERROR: Content block expected for the "container" directive; none found.
/Users/trevor/abjad/abjad/duration.py:docstring of abjad.duration.Duration.is_token:1: WARNING: Explicit markup ends without a blank line; unexpected unindent.
/Users/trevor/abjad/abjad/duration.py:docstring of abjad.duration.Offset.__eq__:1: ERROR: Content block expected for the "container" directive; none found.
/Users/trevor/abjad/abjad/duration.py:docstring of abjad.duration.Offset.__eq__:1: WARNING: Explicit markup ends without a blank line; unexpected unindent.
/Users/trevor/abjad/abjad/duration.py:docstring of abjad.duration.Offset.__ge__:1: ERROR: Content block expected for the "container" directive; none found.
/Users/trevor/abjad/abjad/duration.py:docstring of abjad.duration.Offset.__ge__:1: WARNING: Explicit markup ends without a blank line; unexpected unindent.
/Users/trevor/abjad/abjad/duration.py:docstring of abjad.duration.Offset.__gt__:1: ERROR: Content block expected for the "container" directive; none found.
/Users/trevor/abjad/abjad/duration.py:docstring of abjad.duration.Offset.__gt__:1: WARNING: Explicit markup ends without a blank line; unexpected unindent.
/Users/trevor/abjad/abjad/duration.py:docstring of abjad.duration.Offset.__le__:1: ERROR: Content block expected for the "container" directive; none found.
/Users/trevor/abjad/abjad/duration.py:docstring of abjad.duration.Offset.__le__:1: WARNING: Explicit markup ends without a blank line; unexpected unindent.
/Users/trevor/abjad/abjad/duration.py:docstring of abjad.duration.Offset.__lt__:1: ERROR: Content block expected for the "container" directive; none found.
/Users/trevor/abjad/abjad/duration.py:docstring of abjad.duration.Offset.__lt__:1: WARNING: Explicit markup ends without a blank line; unexpected unindent.
/Users/trevor/abjad/abjad/duration.py:docstring of abjad.duration.Duration.__ne__:6: ERROR: Content block expected for the "container" directive; none found.
/Users/trevor/abjad/abjad/duration.py:docstring of abjad.duration.Duration.__ne__:7: WARNING: Explicit markup ends without a blank line; unexpected unindent.
/Users/trevor/abjad/abjad/duration.py:docstring of abjad.duration.Duration.to_clock_string:1: ERROR: Content block expected for the "container" directive; none found.
/Users/trevor/abjad/abjad/duration.py:docstring of abjad.duration.Duration.to_clock_string:1: WARNING: Explicit markup ends without a blank line; unexpected unindent.
/Users/trevor/abjad/abjad/duration.py:docstring of abjad.duration.Duration.from_lilypond_duration_string:1: ERROR: Content block expected for the "container" directive; none found.
/Users/trevor/abjad/abjad/duration.py:docstring of abjad.duration.Duration.from_lilypond_duration_string:1: WARNING: Explicit markup ends without a blank line; unexpected unindent.
/Users/trevor/abjad/abjad/duration.py:docstring of abjad.duration.Duration.is_token:1: ERROR: Content block expected for the "container" directive; none found.
/Users/trevor/abjad/abjad/duration.py:docstring of abjad.duration.Duration.is_token:1: WARNING: Explicit markup ends without a blank line; unexpected unindent.
/Users/trevor/abjad/abjad/get.py:docstring of abjad.get.contents:1: ERROR: Content block expected for the "container" directive; none found.
/Users/trevor/abjad/abjad/get.py:docstring of abjad.get.contents:1: WARNING: Explicit markup ends without a blank line; unexpected unindent.
/Users/trevor/abjad/abjad/get.py:docstring of abjad.get.descendants:1: ERROR: Content block expected for the "container" directive; none found.
/Users/trevor/abjad/abjad/get.py:docstring of abjad.get.descendants:1: WARNING: Explicit markup ends without a blank line; unexpected unindent.
/Users/trevor/abjad/abjad/get.py:docstring of abjad.get.duration:1: ERROR: Content block expected for the "container" directive; none found.
/Users/trevor/abjad/abjad/get.py:docstring of abjad.get.duration:1: WARNING: Explicit markup ends without a blank line; unexpected unindent.
/Users/trevor/abjad/abjad/get.py:docstring of abjad.get.effective:1: ERROR: Content block expected for the "container" directive; none found.
/Users/trevor/abjad/abjad/get.py:docstring of abjad.get.effective:1: WARNING: Explicit markup ends without a blank line; unexpected unindent.
/Users/trevor/abjad/abjad/get.py:docstring of abjad.get.effective_staff:1: ERROR: Content block expected for the "container" directive; none found.
/Users/trevor/abjad/abjad/get.py:docstring of abjad.get.effective_staff:1: WARNING: Explicit markup ends without a blank line; unexpected unindent.
/Users/trevor/abjad/abjad/get.py:docstring of abjad.get.grace:2: ERROR: Content block expected for the "container" directive; none found.
/Users/trevor/abjad/abjad/get.py:docstring of abjad.get.grace:3: WARNING: Explicit markup ends without a blank line; unexpected unindent.
/Users/trevor/abjad/abjad/get.py:docstring of abjad.get.has_effective_indicator:1: ERROR: Content block expected for the "container" directive; none found.
/Users/trevor/abjad/abjad/get.py:docstring of abjad.get.has_effective_indicator:1: WARNING: Explicit markup ends without a blank line; unexpected unindent.
/Users/trevor/abjad/abjad/get.py:docstring of abjad.get.has_indicator:1: ERROR: Content block expected for the "container" directive; none found.
/Users/trevor/abjad/abjad/get.py:docstring of abjad.get.has_indicator:1: WARNING: Explicit markup ends without a blank line; unexpected unindent.
/Users/trevor/abjad/abjad/get.py:docstring of abjad.get.indicator:1: ERROR: Content block expected for the "container" directive; none found.
/Users/trevor/abjad/abjad/get.py:docstring of abjad.get.indicator:1: WARNING: Explicit markup ends without a blank line; unexpected unindent.
/Users/trevor/abjad/abjad/get.py:docstring of abjad.get.indicators:1: ERROR: Content block expected for the "container" directive; none found.
/Users/trevor/abjad/abjad/get.py:docstring of abjad.get.indicators:1: WARNING: Explicit markup ends without a blank line; unexpected unindent.
/Users/trevor/abjad/abjad/get.py:docstring of abjad.get.lineage:1: ERROR: Content block expected for the "container" directive; none found.
/Users/trevor/abjad/abjad/get.py:docstring of abjad.get.lineage:1: WARNING: Explicit markup ends without a blank line; unexpected unindent.
/Users/trevor/abjad/abjad/get.py:docstring of abjad.get.logical_tie:1: ERROR: Content block expected for the "container" directive; none found.
/Users/trevor/abjad/abjad/get.py:docstring of abjad.get.logical_tie:1: WARNING: Explicit markup ends without a blank line; unexpected unindent.
< ... snip ... >
/Users/trevor/abjad/abjad/timespan.py:docstring of abjad.timespan.Timespan.__contains__:1: ERROR: Content block expected for the "container" directive; none found.
/Users/trevor/abjad/abjad/timespan.py:docstring of abjad.timespan.Timespan.__contains__:1: WARNING: Explicit markup ends without a blank line; unexpected unindent.
/Users/trevor/abjad/abjad/timespan.py:docstring of abjad.timespan.Timespan.__lt__:9: WARNING: Explicit markup ends without a blank line; unexpected unindent.
/Users/trevor/abjad/abjad/timespan.py:docstring of abjad.timespan.Timespan.reflect:1: ERROR: Content block expected for the "container" directive; none found.
/Users/trevor/abjad/abjad/timespan.py:docstring of abjad.timespan.Timespan.reflect:1: WARNING: Explicit markup ends without a blank line; unexpected unindent.
/Users/trevor/abjad/abjad/timespan.py:docstring of abjad.timespan.Timespan.stretch:1: ERROR: Content block expected for the "container" directive; none found.
/Users/trevor/abjad/abjad/timespan.py:docstring of abjad.timespan.Timespan.stretch:1: WARNING: Explicit markup ends without a blank line; unexpected unindent.
/Users/trevor/abjad/abjad/timespan.py:docstring of abjad.timespan.TimespanList.__and__:1: ERROR: Content block expected for the "container" directive; none found.
/Users/trevor/abjad/abjad/timespan.py:docstring of abjad.timespan.TimespanList.__and__:1: WARNING: Explicit markup ends without a blank line; unexpected unindent.
/Users/trevor/abjad/abjad/timespan.py:docstring of abjad.timespan.TimespanList.__invert__:1: ERROR: Content block expected for the "container" directive; none found.
/Users/trevor/abjad/abjad/timespan.py:docstring of abjad.timespan.TimespanList.__invert__:1: WARNING: Explicit markup ends without a blank line; unexpected unindent.
/Users/trevor/abjad/abjad/timespan.py:docstring of abjad.timespan.TimespanList.__sub__:1: ERROR: Content block expected for the "container" directive; none found.
/Users/trevor/abjad/abjad/timespan.py:docstring of abjad.timespan.TimespanList.__sub__:1: WARNING: Explicit markup ends without a blank line; unexpected unindent.
/Users/trevor/abjad/abjad/timespan.py:docstring of abjad.timespan.TimespanList.clip_timespan_durations:1: ERROR: Content block expected for the "container" directive; none found.
/Users/trevor/abjad/abjad/timespan.py:docstring of abjad.timespan.TimespanList.clip_timespan_durations:1: WARNING: Explicit markup ends without a blank line; unexpected unindent.
/Users/trevor/abjad/abjad/timespan.py:docstring of abjad.timespan.TimespanList.compute_logical_and:1: ERROR: Content block expected for the "container" directive; none found.
/Users/trevor/abjad/abjad/timespan.py:docstring of abjad.timespan.TimespanList.compute_logical_and:1: WARNING: Explicit markup ends without a blank line; unexpected unindent.
/Users/trevor/abjad/abjad/timespan.py:docstring of abjad.timespan.TimespanList.compute_logical_or:1: ERROR: Content block expected for the "container" directive; none found.
/Users/trevor/abjad/abjad/timespan.py:docstring of abjad.timespan.TimespanList.compute_logical_or:1: WARNING: Explicit markup ends without a blank line; unexpected unindent.
/Users/trevor/abjad/abjad/timespan.py:docstring of abjad.timespan.TimespanList.compute_logical_xor:1: ERROR: Content block expected for the "container" directive; none found.
/Users/trevor/abjad/abjad/timespan.py:docstring of abjad.timespan.TimespanList.compute_logical_xor:1: WARNING: Explicit markup ends without a blank line; unexpected unindent.
/Users/trevor/abjad/abjad/timespan.py:docstring of abjad.timespan.TimespanList.compute_overlap_factor:1: ERROR: Content block expected for the "container" directive; none found.
/Users/trevor/abjad/abjad/timespan.py:docstring of abjad.timespan.TimespanList.compute_overlap_factor:1: WARNING: Explicit markup ends without a blank line; unexpected unindent.
/Users/trevor/abjad/abjad/timespan.py:docstring of abjad.timespan.TimespanList.compute_overlap_factor_mapping:1: ERROR: Content block expected for the "container" directive; none found.
/Users/trevor/abjad/abjad/timespan.py:docstring of abjad.timespan.TimespanList.compute_overlap_factor_mapping:1: WARNING: Explicit markup ends without a blank line; unexpected unindent.
/Users/trevor/abjad/abjad/timespan.py:docstring of abjad.timespan.TimespanList.explode:1: ERROR: Content block expected for the "container" directive; none found.
/Users/trevor/abjad/abjad/timespan.py:docstring of abjad.timespan.TimespanList.explode:1: WARNING: Explicit markup ends without a blank line; unexpected unindent.
/Users/trevor/abjad/abjad/timespan.py:docstring of abjad.timespan.TimespanList.get_timespans_that_satisfy_time_relation:1: ERROR: Content block expected for the "container" directive; none found.
/Users/trevor/abjad/abjad/timespan.py:docstring of abjad.timespan.TimespanList.get_timespans_that_satisfy_time_relation:1: WARNING: Explicit markup ends without a blank line; unexpected unindent.
/Users/trevor/abjad/abjad/timespan.py:docstring of abjad.timespan.TimespanList.partition:1: ERROR: Content block expected for the "container" directive; none found.
/Users/trevor/abjad/abjad/timespan.py:docstring of abjad.timespan.TimespanList.partition:1: WARNING: Explicit markup ends without a blank line; unexpected unindent.
/Users/trevor/abjad/abjad/timespan.py:docstring of abjad.timespan.TimespanList.reflect:1: ERROR: Content block expected for the "container" directive; none found.
/Users/trevor/abjad/abjad/timespan.py:docstring of abjad.timespan.TimespanList.reflect:1: WARNING: Explicit markup ends without a blank line; unexpected unindent.
/Users/trevor/abjad/abjad/timespan.py:docstring of abjad.timespan.TimespanList.remove_degenerate_timespans:1: ERROR: Content block expected for the "container" directive; none found.
/Users/trevor/abjad/abjad/timespan.py:docstring of abjad.timespan.TimespanList.remove_degenerate_timespans:1: WARNING: Explicit markup ends without a blank line; unexpected unindent.
/Users/trevor/abjad/abjad/timespan.py:docstring of abjad.timespan.TimespanList.repeat_to_stop_offset:1: ERROR: Content block expected for the "container" directive; none found.
/Users/trevor/abjad/abjad/timespan.py:docstring of abjad.timespan.TimespanList.repeat_to_stop_offset:1: WARNING: Explicit markup ends without a blank line; unexpected unindent.
/Users/trevor/abjad/abjad/timespan.py:docstring of abjad.timespan.TimespanList.rotate:1: ERROR: Content block expected for the "container" directive; none found.
/Users/trevor/abjad/abjad/timespan.py:docstring of abjad.timespan.TimespanList.rotate:1: WARNING: Explicit markup ends without a blank line; unexpected unindent.
/Users/trevor/abjad/abjad/timespan.py:docstring of abjad.timespan.TimespanList.round_offsets:1: ERROR: Content block expected for the "container" directive; none found.
/Users/trevor/abjad/abjad/timespan.py:docstring of abjad.timespan.TimespanList.round_offsets:1: WARNING: Explicit markup ends without a blank line; unexpected unindent.
/Users/trevor/abjad/abjad/timespan.py:docstring of abjad.timespan.TimespanList.scale:1: ERROR: Content block expected for the "container" directive; none found.
/Users/trevor/abjad/abjad/timespan.py:docstring of abjad.timespan.TimespanList.scale:1: WARNING: Explicit markup ends without a blank line; unexpected unindent.
/Users/trevor/abjad/abjad/timespan.py:docstring of abjad.timespan.TimespanList.split_at_offset:1: ERROR: Content block expected for the "container" directive; none found.
/Users/trevor/abjad/abjad/timespan.py:docstring of abjad.timespan.TimespanList.split_at_offset:1: WARNING: Explicit markup ends without a blank line; unexpected unindent.
/Users/trevor/abjad/abjad/timespan.py:docstring of abjad.timespan.TimespanList.split_at_offsets:1: ERROR: Content block expected for the "container" directive; none found.
/Users/trevor/abjad/abjad/timespan.py:docstring of abjad.timespan.TimespanList.split_at_offsets:1: WARNING: Explicit markup ends without a blank line; unexpected unindent.
/Users/trevor/abjad/abjad/timespan.py:docstring of abjad.timespan.TimespanList.stretch:1: ERROR: Content block expected for the "container" directive; none found.
/Users/trevor/abjad/abjad/timespan.py:docstring of abjad.timespan.TimespanList.stretch:1: WARNING: Explicit markup ends without a blank line; unexpected unindent.
/Users/trevor/abjad/abjad/timespan.py:docstring of abjad.timespan.TimespanList.translate:1: ERROR: Content block expected for the "container" directive; none found.
/Users/trevor/abjad/abjad/timespan.py:docstring of abjad.timespan.TimespanList.translate:1: WARNING: Explicit markup ends without a blank line; unexpected unindent.
/Users/trevor/abjad/abjad/timespan.py:docstring of abjad.timespan.TimespanList.translate_offsets:1: ERROR: Content block expected for the "container" directive; none found.
/Users/trevor/abjad/abjad/timespan.py:docstring of abjad.timespan.TimespanList.translate_offsets:1: WARNING: Explicit markup ends without a blank line; unexpected unindent.
/Users/trevor/abjad/abjad/tweaks.py:docstring of abjad.tweaks.bundle:1: ERROR: Content block expected for the "container" directive; none found.
/Users/trevor/abjad/abjad/tweaks.py:docstring of abjad.tweaks.bundle:1: WARNING: Explicit markup ends without a blank line; unexpected unindent.
/Users/trevor/abjad/abjad/wf.py:docstring of abjad.wf.check_beamed_long_notes:1: ERROR: Content block expected for the "container" directive; none found.
/Users/trevor/abjad/abjad/wf.py:docstring of abjad.wf.check_beamed_long_notes:1: WARNING: Explicit markup ends without a blank line; unexpected unindent.
/Users/trevor/abjad/abjad/wf.py:docstring of abjad.wf.check_out_of_range_pitches:1: ERROR: Content block expected for the "container" directive; none found.
/Users/trevor/abjad/abjad/wf.py:docstring of abjad.wf.check_out_of_range_pitches:1: WARNING: Explicit markup ends without a blank line; unexpected unindent.
/Users/trevor/abjad/abjad/wf.py:docstring of abjad.wf.check_overlapping_text_spanners:1: ERROR: Content block expected for the "container" directive; none found.
/Users/trevor/abjad/abjad/wf.py:docstring of abjad.wf.check_overlapping_text_spanners:1: WARNING: Explicit markup ends without a blank line; unexpected unindent.
/Users/trevor/abjad/abjad/wf.py:docstring of abjad.wf.check_unmatched_stop_text_spans:1: ERROR: Content block expected for the "container" directive; none found.
/Users/trevor/abjad/abjad/wf.py:docstring of abjad.wf.check_unmatched_stop_text_spans:1: WARNING: Explicit markup ends without a blank line; unexpected unindent.
/Users/trevor/abjad/abjad/wf.py:docstring of abjad.wf.check_unterminated_hairpins:1: ERROR: Content block expected for the "container" directive; none found.
/Users/trevor/abjad/abjad/wf.py:docstring of abjad.wf.check_unterminated_hairpins:1: WARNING: Explicit markup ends without a blank line; unexpected unindent.
/Users/trevor/abjad/abjad/wf.py:docstring of abjad.wf.check_unterminated_text_spanners:1: ERROR: Content block expected for the "container" directive; none found.
/Users/trevor/abjad/abjad/wf.py:docstring of abjad.wf.check_unterminated_text_spanners:1: WARNING: Explicit markup ends without a blank line; unexpected unindent.
josiah-wolf-oberholtzer commented 1 year ago

container is a built-in directive in docutils, so this probably isn't related to uqbar. But I'll look into it.

What version of Sphinx are you on now? sphinx-build --version will spit it out. I'm on 5.3.0.

I am using the .. container:: example directive over in supriya: https://github.com/josiah-wolf-oberholtzer/supriya/blob/e00e3886a2546ac5443d793ad26ef75cd2654da0/supriya/ugens/bases.py#L267-L295

... and I haven't had trouble. One difference is I'm using the :: code block directive in front of every code block. That's also the case inside the .. container directives in uqbar's own docs. I haven't tested to see if that matters though.

trevorbaca commented 1 year ago

I stayed on Sphinx 5.3.0, too. Uqbar's constraint of <6 and >=5.3.0 made it clear to do. Thanks for that!

I noticed uqbar is using the naked :: directive, too, so I tested it in Abjad, but appears not to make a difference in Abjad's builds.

A strange clue is that it's only the first container directive in a docstring that raises this error; nonfirst container directives in a docstring continue to interpret just fine.

Once upon a time I had to temporarily change something in uqbar's call to black_format() for something or other. So I thought it might have been a problem that I (yesterday) upgraded from black 22.1.0 to 23.1.0 at the same moment that I upgraded from uqbar 0.6.8 to 0.6.9. But downgrading to black 22.1.0 doesn't change anything (same with uqbar 0.6.8). Which is odd. I'm surprised that I haven't been able to downgrade dependencies back to something that gives me a clean build, especially since I build Abjad's 3.15 docs only a month ago. Le sigh.

josiah-wolf-oberholtzer commented 1 year ago

Interesting. Definitely not seeing anything weird over here.

What branch of Abjad are you building the docs on? I can try to reproduce when I have some free time.

trevorbaca commented 1 year ago

Cool. You can build on main, though I just merged in a manual workaround for all the docstrings in question. The workaround's ugly tho (strange to not be able to start a container with explanatory text), so if you do find something that'd be awesome.

To reproduce, just type "foo:" inside any container directive, and see if Sphinx complains.

Hmm, actually, I guess if you go try that and the error isn't reproducible, then I suppose it's just something to do with the config of my venv. Lemme know if it's even reproducible on your machine.