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

Fix SOURCE_DATE_EPOCH for multi-line copyright values #11516

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGES
Expand Up @@ -21,6 +21,9 @@ Features added
Bugs fixed
----------

* #11514: Fix ``SOURCE_DATE_EPOCH`` in multi-line copyright footer.
Patch by Bénédikt Tran.

Testing
-------

Expand Down
10 changes: 9 additions & 1 deletion sphinx/config.py
Expand Up @@ -429,7 +429,15 @@ def correct_copyright_year(app: Sphinx, config: Config) -> None:
for k in ('copyright', 'epub_copyright'):
if k in config:
replace = r'\g<1>%s' % format_date('%Y', language='en')
config[k] = copyright_year_re.sub(replace, config[k])
value: str | list[str] | tuple[str, ...] = config[k]
if isinstance(value, str):
config[k] = copyright_year_re.sub(replace, value)
else:
items = (copyright_year_re.sub(replace, x) for x in value)
if isinstance(value, list):
config[k] = list(items)
else:
config[k] = tuple(items)


def check_confval_types(app: Sphinx | None, config: Config) -> None:
Expand Down
45 changes: 30 additions & 15 deletions tests/test_config.py
@@ -1,5 +1,7 @@
"""Test the sphinx.config.Config class."""

import os
import textwrap
from unittest import mock

import pytest
Expand All @@ -8,6 +10,7 @@
from sphinx.config import ENUM, Config, check_confval_types
from sphinx.errors import ConfigError, ExtensionError, VersionRequirementError
from sphinx.testing.path import path
from sphinx.util.i18n import format_date


@pytest.mark.sphinx(testroot='config', confoverrides={
Expand Down Expand Up @@ -445,22 +448,34 @@ def test_conf_py_nitpick_ignore_list(tempdir):


@pytest.mark.sphinx(testroot='copyright-multiline')
def test_multi_line_copyright(app, status, warning):
def test_multi_line_copyright(app):
app.builder.build_all()

content = (app.outdir / 'index.html').read_text(encoding='utf-8')

assert ' &#169; Copyright 2006-2009, Alice.<br/>' in content
assert ' &#169; Copyright 2010-2013, Bob.<br/>' in content
assert ' &#169; Copyright 2014-2017, Charlie.<br/>' in content
assert ' &#169; Copyright 2018-2021, David.<br/>' in content
assert ' &#169; Copyright 2022-2025, Eve.' in content

lines = (
' &#169; Copyright 2006-2009, Alice.<br/>\n \n'
' &#169; Copyright 2010-2013, Bob.<br/>\n \n'
' &#169; Copyright 2014-2017, Charlie.<br/>\n \n'
' &#169; Copyright 2018-2021, David.<br/>\n \n'
' &#169; Copyright 2022-2025, Eve.\n \n'
)
assert lines in content
if os.getenv('SOURCE_DATE_EPOCH') is None:
copyright_footer = (
' &#169; Copyright 2006-2009, Alice.<br/>\n',
' &#169; Copyright 2010-2013, Bob.<br/>\n',
' &#169; Copyright 2014-2017, Charlie.<br/>\n',
' &#169; Copyright 2018-2021, David.<br/>\n',
' &#169; Copyright 2022-2025, Eve.',
)
else:
source_date_year = format_date('%Y', language='en')
copyright_footer = (
f' &#169; Copyright 2006-{source_date_year}, Alice.<br/>\n',
f' &#169; Copyright 2010-{source_date_year}, Bob.<br/>\n',
f' &#169; Copyright 2014-{source_date_year}, Charlie.<br/>\n',
f' &#169; Copyright 2018-{source_date_year}, David.<br/>\n',
f' &#169; Copyright 2022-{source_date_year}, Eve.',
)

# check the copyright footer line by line (empty lines ignored)
for line in copyright_footer:
assert line in content

# check the raw copyright footer block (empty lines included)
expect = '\n'.join(copyright_footer)
expect = textwrap.indent(expect, ' ', lambda _: True)
assert expect in content