doc: Defer parsing version_txt to fix an obscure bug

Defer parsing the version read from version.txt until it's about
to be used, in order to fix an obscure bug involving indirect
pkg_resources.

When pkg_resources are imported, they override packaging with their own
pkg_resources.extern.packaging.  Depending on the system, this could
either wrap the vendored pkg_resources._vendor.packaging or system
packaging.  For some reason, in the latter case the Version objects
created prior to the wrapping are incompatible with the objects created
afterwards.  This causes the doc build to fail with:

```
Exception occurred:
  File "/tmp/polybar/build/doc/conf.py", line 249, in run
    if directive_version > version_txt:
TypeError: '>' not supported between instances of 'Version' and 'Version'
```

This happens because apparently pkg_resources are imported indirectly
somewhere between conf.py processing and running VersionDirective.
Deferring version parsing until the latter guarantees that both objects
are constructed at the same point in program flow and therefore use
the same packaging package.
This commit is contained in:
Michał Górny 2022-01-31 00:29:01 +01:00 committed by Patrick Ziegler
parent 69a2bf211a
commit a33e8de922

View File

@ -26,7 +26,9 @@ def get_version(root_path):
with open(path, "r") as f:
for line in f.readlines():
if not line.startswith("#"):
return packaging.version.parse(line)
# NB: we can't parse it yet since sphinx could import
# pkg_resources later on and it could patch packaging.version
return line
raise RuntimeError("No version found in {}".format(path))
@ -245,8 +247,9 @@ if packaging.version.parse(sphinx.__version__) >= packaging.version.parse("1.8.5
"""
def run(self) -> List[Node]:
directive_version = packaging.version.parse(self.arguments[0])
parsed_version_txt = packaging.version.parse(version_txt)
if directive_version > version_txt:
if directive_version > parsed_version_txt:
self.arguments[0] += " (unreleased)"
return super().run()