Skip to content

Commit

Permalink
blurb: replace spaces with underscores in news directory (#499)
Browse files Browse the repository at this point in the history
Co-authored-by: Hugo van Kemenade <hugovk@users.noreply.github.com>
Co-authored-by: C.A.M. Gerlach <CAM.Gerlach@Gerlach.CAM>
Co-authored-by: Larry Hastings <larry@hastings.org>
Co-authored-by: Éric <merwok@netwok.org>
  • Loading branch information
5 people committed Mar 6, 2024
1 parent 67b7836 commit ae19036
Show file tree
Hide file tree
Showing 2 changed files with 102 additions and 31 deletions.
48 changes: 39 additions & 9 deletions blurb/blurb.py
Expand Up @@ -38,7 +38,6 @@
## Licensed to the Python Software Foundation under a contributor agreement.
##


# TODO
#
# automatic git adds and removes
Expand Down Expand Up @@ -110,19 +109,46 @@
sections.append(section.strip())


_sanitize_section = {
"C API": "C_API",
"Core and Builtins": "Core_and_Builtins",
"Tools/Demos": "Tools-Demos",
}


def sanitize_section(section):
"""
Cleans up a section string, making it viable as a directory name.
Clean up a section string, making it viable as a directory name.
"""
return _sanitize_section.get(section, section)


def sanitize_section_legacy(section):
"""
Clean up a section string, making it viable as a directory name (allow spaces).
"""
return section.replace("/", "-")


_unsanitize_section = {
"C_API": "C API",
"Core_and_Builtins": "Core and Builtins",
"Tools-Demos": "Tools/Demos",
}


def unsanitize_section(section):
return _unsanitize_section.get(section, section)

def next_filename_unsanitize_sections(filename):
s = filename
for key, value in _unsanitize_section.items():
for separator in "/\\":
key = f"{separator}{key}{separator}"
value = f"{separator}{value}{separator}"
filename = filename.replace(key, value)
return filename


def textwrap_body(body, *, subsequent_indent=''):
"""
Expand Down Expand Up @@ -300,14 +326,18 @@ def glob_blurbs(version):
wildcard = base + ".rst"
filenames.extend(glob.glob(wildcard))
else:
for section in sections:
wildcard = os.path.join(base, sanitize_section(section), "*.rst")
sanitized_sections = (
{sanitize_section(section) for section in sections} |
{sanitize_section_legacy(section) for section in sections}
)
for section in sanitized_sections:
wildcard = os.path.join(base, section, "*.rst")
entries = glob.glob(wildcard)
entries.sort(reverse=True)
deletables = [x for x in entries if x.endswith("/README.rst")]
for filename in deletables:
entries.remove(filename)
filenames.extend(entries)
filenames.sort(reverse=True, key=next_filename_unsanitize_sections)
return filenames


Expand Down Expand Up @@ -537,8 +567,8 @@ def save(self, path):
@staticmethod
def _parse_next_filename(filename):
"""
Parses a "next" filename into its equivalent blurb metadata.
Returns a dict.
Parses a "next" filename into its equivalent blurb metadata.
Returns a dict.
"""
components = filename.split(os.sep)
section, filename = components[-2:]
Expand All @@ -552,7 +582,7 @@ def _parse_next_filename(filename):
metadata = {"date": fields[0], "nonce": fields[-2], "section": section}

for field in fields[1:-2]:
for name in ("gh-issue","bpo"):
for name in ("gh-issue", "bpo"):
_, got, value = field.partition(name + "-")
if got:
metadata[name] = value.strip()
Expand Down Expand Up @@ -589,7 +619,7 @@ def _extract_next_filename(self):
metadata, body = self[-1]
metadata['section'] = sanitize_section(metadata['section'])
metadata['root'] = root
if int(metadata["gh-issue"]) > 0 :
if int(metadata["gh-issue"]) > 0:
path = "{root}/Misc/NEWS.d/next/{section}/{date}.gh-issue-{gh-issue}.{nonce}.rst".format_map(metadata)
elif int(metadata["bpo"]) > 0:
# assume it's a GH issue number
Expand Down
85 changes: 63 additions & 22 deletions blurb/tests/test_blurb.py
Expand Up @@ -5,31 +5,31 @@


UNCHANGED_SECTIONS = (
"C API",
"Core and Builtins",
"Library",
)


@pytest.mark.parametrize("section", UNCHANGED_SECTIONS)
def test_sanitize_section_no_change(section: str) -> None:
def test_sanitize_section_no_change(section):
sanitized = blurb.sanitize_section(section)
assert sanitized == section


@pytest.mark.parametrize(
"section, expected",
(
("C API", "C_API"),
("Core and Builtins", "Core_and_Builtins"),
("Tools/Demos", "Tools-Demos"),
),
)
def test_sanitize_section_changed(section: str, expected: str) -> None:
def test_sanitize_section_changed(section, expected):
sanitized = blurb.sanitize_section(section)
assert sanitized == expected


@pytest.mark.parametrize("section", UNCHANGED_SECTIONS)
def test_unsanitize_section_no_change(section: str) -> None:
def test_unsanitize_section_no_change(section):
unsanitized = blurb.unsanitize_section(section)
assert unsanitized == section

Expand All @@ -40,12 +40,12 @@ def test_unsanitize_section_no_change(section: str) -> None:
("Tools-Demos", "Tools/Demos"),
),
)
def test_unsanitize_section_changed(section: str, expected: str) -> None:
def test_unsanitize_section_changed(section, expected):
unsanitized = blurb.unsanitize_section(section)
assert unsanitized == expected


def test_glob_blurbs_next(fs: FakeFilesystem) -> None:
def test_glob_blurbs_next(fs):
# Arrange
fake_news_entries = (
"Misc/NEWS.d/next/Library/2022-04-11-18-34-33.gh-issue-11111.pC7gnM.rst",
Expand All @@ -69,28 +69,71 @@ def test_glob_blurbs_next(fs: FakeFilesystem) -> None:
assert set(filenames) == set(fake_news_entries)


def test_glob_blurbs_sort_order(fs):
"""
It shouldn't make a difference to sorting whether
section names have spaces or underscores.
"""
# Arrange
fake_news_entries = (
"Misc/NEWS.d/next/Core and Builtins/2023-07-23-12-01-00.gh-issue-33331.Pf_BI1.rst",
"Misc/NEWS.d/next/Core_and_Builtins/2023-07-23-12-02-00.gh-issue-33332.Pf_BI2.rst",
"Misc/NEWS.d/next/Core and Builtins/2023-07-23-12-03-00.gh-issue-33333.Pf_BI3.rst",
"Misc/NEWS.d/next/Core_and_Builtins/2023-07-23-12-04-00.gh-issue-33334.Pf_BI4.rst",
)
# As fake_news_entries, but reverse sorted by *filename* only
expected = [
"Misc/NEWS.d/next/Core_and_Builtins/2023-07-23-12-04-00.gh-issue-33334.Pf_BI4.rst",
"Misc/NEWS.d/next/Core and Builtins/2023-07-23-12-03-00.gh-issue-33333.Pf_BI3.rst",
"Misc/NEWS.d/next/Core_and_Builtins/2023-07-23-12-02-00.gh-issue-33332.Pf_BI2.rst",
"Misc/NEWS.d/next/Core and Builtins/2023-07-23-12-01-00.gh-issue-33331.Pf_BI1.rst",
]
fake_readmes = (
"Misc/NEWS.d/next/Library/README.rst",
"Misc/NEWS.d/next/Core and Builtins/README.rst",
"Misc/NEWS.d/next/Tools-Demos/README.rst",
"Misc/NEWS.d/next/C API/README.rst",
)
for fn in fake_news_entries + fake_readmes:
fs.create_file(fn)

# Act
filenames = blurb.glob_blurbs("next")

# Assert
assert filenames == expected


@pytest.mark.parametrize(
"news_entry, expected_section",
(
(
"Misc/NEWS.d/next/Library/2022-04-11-18-34-33.gh-issue-55555.pC7gnM.rst",
"Misc/NEWS.d/next/Library/2022-04-11-18-34-33.gh-issue-33333.pC7gnM.rst",
"Library",
),
(
"Misc/NEWS.d/next/Core and Builtins/2023-03-17-12-09-45.gh-issue-33333.Pf_BI7.rst",
"Misc/NEWS.d/next/Core_and_Builtins/2023-03-17-12-09-45.gh-issue-44444.Pf_BI7.rst",
"Core and Builtins",
),
(
"Misc/NEWS.d/next/Core and Builtins/2023-03-17-12-09-45.gh-issue-55555.Pf_BI7.rst",
"Core and Builtins",
),
(
"Misc/NEWS.d/next/Tools-Demos/2023-03-21-01-27-07.gh-issue-44444.2F1Byz.rst",
"Misc/NEWS.d/next/Tools-Demos/2023-03-21-01-27-07.gh-issue-66666.2F1Byz.rst",
"Tools/Demos",
),
(
"Misc/NEWS.d/next/C API/2023-03-27-22-09-07.gh-issue-66666.3SN8Bs.rst",
"Misc/NEWS.d/next/C_API/2023-03-27-22-09-07.gh-issue-77777.3SN8Bs.rst",
"C API",
),
(
"Misc/NEWS.d/next/C API/2023-03-27-22-09-07.gh-issue-88888.3SN8Bs.rst",
"C API",
),
),
)
def test_load_next(news_entry: str, expected_section: str, fs: FakeFilesystem) -> None:
def test_load_next(news_entry, expected_section, fs):
# Arrange
fs.create_file(news_entry, contents="testing")
blurbs = blurb.Blurbs()
Expand All @@ -107,26 +150,24 @@ def test_load_next(news_entry: str, expected_section: str, fs: FakeFilesystem) -
"news_entry, expected_path",
(
(
"Misc/NEWS.d/next/Library/2022-04-11-18-34-33.gh-issue-55555.pC7gnM.rst",
"root/Misc/NEWS.d/next/Library/2022-04-11-18-34-33.gh-issue-55555.pC7gnM.rst",
"Misc/NEWS.d/next/Library/2022-04-11-18-34-33.gh-issue-33333.pC7gnM.rst",
"root/Misc/NEWS.d/next/Library/2022-04-11-18-34-33.gh-issue-33333.pC7gnM.rst",
),
(
"Misc/NEWS.d/next/Core and Builtins/2023-03-17-12-09-45.gh-issue-33333.Pf_BI7.rst",
"root/Misc/NEWS.d/next/Core and Builtins/2023-03-17-12-09-45.gh-issue-33333.Pf_BI7.rst",
"Misc/NEWS.d/next/Core and Builtins/2023-03-17-12-09-45.gh-issue-44444.Pf_BI7.rst",
"root/Misc/NEWS.d/next/Core_and_Builtins/2023-03-17-12-09-45.gh-issue-44444.Pf_BI7.rst",
),
(
"Misc/NEWS.d/next/Tools-Demos/2023-03-21-01-27-07.gh-issue-44444.2F1Byz.rst",
"root/Misc/NEWS.d/next/Tools-Demos/2023-03-21-01-27-07.gh-issue-44444.2F1Byz.rst",
"Misc/NEWS.d/next/Tools-Demos/2023-03-21-01-27-07.gh-issue-55555.2F1Byz.rst",
"root/Misc/NEWS.d/next/Tools-Demos/2023-03-21-01-27-07.gh-issue-55555.2F1Byz.rst",
),
(
"Misc/NEWS.d/next/C API/2023-03-27-22-09-07.gh-issue-66666.3SN8Bs.rst",
"root/Misc/NEWS.d/next/C API/2023-03-27-22-09-07.gh-issue-66666.3SN8Bs.rst",
"root/Misc/NEWS.d/next/C_API/2023-03-27-22-09-07.gh-issue-66666.3SN8Bs.rst",
),
),
)
def test_extract_next_filename(
news_entry: str, expected_path: str, fs: FakeFilesystem
) -> None:
def test_extract_next_filename(news_entry, expected_path, fs):
# Arrange
fs.create_file(news_entry, contents="testing")
blurb.root = "root"
Expand Down

0 comments on commit ae19036

Please sign in to comment.