Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sphinx's html_last_updated_fmt should be set to a format string, not literal #53

Closed
paravoid opened this issue Mar 9, 2023 · 3 comments · Fixed by #54
Closed

Sphinx's html_last_updated_fmt should be set to a format string, not literal #53

paravoid opened this issue Mar 9, 2023 · 3 comments · Fixed by #54

Comments

@paravoid
Copy link
Contributor

paravoid commented Mar 9, 2023

I'm the Debian maintainer for tox. I recently uploaded pyproject-api to Debian, as a dependency of tox 4 (which is now in Debian experimental).

The reproducible builds folks filed a bug report, Debian bug #1032057 whereas they reported that the pyproject-api package cannot be built reproducibly -- that is, building it twice in the same environment yields a different output.

The cause seems to be the Sphinx documentation, and this line from docs/conf.py:

html_title, html_last_updated_fmt = "pyproject-api docs", datetime.now().isoformat()

datetime.now() is the culprit. Chris Lamb proposed a patch to use SOURCE_DATE_EPOCH.

However, while investigating this and after looking at the Sphinx documentation, I saw that html_last_updated_fmt, as the name hints, is supposed to be the format string, not the actual date. A literal date works as a format because anything that's not percent-encoded is passed on unmodified. So I think that's just a happy accident.

I checked the Sphinx source code, and it looks like the string is used in prepare_writing() from builders/html/init.py, which in turn passes it on as an argument to format_date() from util/i18n.py. It looks like format_date() has support for SOURCE_DATE_EPOCH already.

So from what I can tell, a much simpler patch would be to just set html_last_updated_fmt = "%Y-%m-%dT%H:%M:%S.%f" for the equivalent ISO 8601 string -- or even something with less resolution. No need to fiddle with the datetime module, or SOURCE_DATE_EPOCH at all.

Let me know what you think -especially with regards to accuracy/resolution- and I can prepare a PR. Or free to take care of it directly since it's a one-liner :)

Note that tox itself seems to be suffering from the same issue, so if you fix it directly, you may want to patch it in both projects.

@gaborbernat
Copy link
Member

PR welcome 👍

@paravoid
Copy link
Contributor Author

@gaborbernat thanks for the quick response!

Before I submit the PR, what is your desired accuracy here?

  • The equivalent to what you have today would be %Y-%m-%dT%H:%M:%S.%f
  • It may be enough to have just %Y-%m-%d %H:%M?
  • According to the Sphinx docs, "The empty string is equivalent to '%b %d, %Y' (or a locale-dependent equivalent).", so that's also an option.

@gaborbernat
Copy link
Member

What we have today please.

paravoid added a commit to paravoid/pyproject-api that referenced this issue Mar 10, 2023
According to the Sphinx documentation and source code,
html_last_updated_fmt is supposed to be a strftime()-like format string,
not a literal string with a date.

Instead of datetime.now().isoformat, set this to the equivalent format
string (sans microseconds, as Sphinx does not support %f).

This is a no-op generally. However, unlike our implementation here,
Sphinx's date generation obeys SOURCE_DATE_EPOCH, which means that the
builds will now be able to be built reproducibly.

Fixes tox-dev#53

Signed-off-by: Faidon Liambotis <paravoid@debian.org>
paravoid added a commit to paravoid/pyproject-api that referenced this issue Mar 10, 2023
According to the Sphinx documentation and source code,
html_last_updated_fmt is supposed to be a strftime()-like format string,
not a literal string with a date.

Instead of datetime.now().isoformat, set this to the equivalent format
string (sans microseconds, as Sphinx does not support %f).

This is a no-op generally. However, unlike our implementation here,
Sphinx's date generation obeys SOURCE_DATE_EPOCH, which means that the
builds will now be able to be built reproducibly.

Fixes tox-dev#53

Signed-off-by: Faidon Liambotis <paravoid@debian.org>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants