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

blurb: replace spaces with underscores in news directory #499

Merged
merged 17 commits into from
Mar 6, 2024
Merged
Show file tree
Hide file tree
Changes from 13 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
15 changes: 15 additions & 0 deletions .coveragerc
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# .coveragerc to control coverage.py

[report]
# Regexes for lines to exclude from consideration
exclude_lines =
# Have to re-enable the standard pragma:
pragma: no cover

# Don't complain if non-runnable code isn't run:
if __name__ == .__main__.:
def main

[run]
omit =
**/blurb/__main__.py
19 changes: 16 additions & 3 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,42 @@ name: Tests

on: [push, pull_request, workflow_dispatch]

env:
FORCE_COLOR: 1

jobs:
build_ubuntu:
strategy:
fail-fast: false
matrix:
python-version: ["3.7", "3.8", "3.9", "3.10", "3.11", "3.12-dev"]
python-version: ["3.7", "3.8", "3.9", "3.10", "3.11", "3.12"]
name: ${{ matrix.python-version }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}
allow-prereleases: true
cache: pip
cache-dependency-path: ".github/workflows/tests.yml"
- name: setup
run: |
python --version
python -m pip install --upgrade pip
python -m pip install --upgrade flit
python -m pip install --upgrade pytest pytest-cov pyfakefs
- name: install
run: |
cd blurb
flit install
python -m pip install -e .
- name: test
run: |
blurb test
- name: pytest
run: |
python -I -m pytest --cov blurb
- name: Upload coverage
uses: codecov/codecov-action@v3
with:
flags: ${{ matrix.python-version }}
name: Python ${{ matrix.python-version }}
109 changes: 32 additions & 77 deletions blurb/blurb.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@
## Licensed to the Python Software Foundation under a contributor agreement.
##


# TODO
#
# automatic git adds and removes
Expand All @@ -51,7 +50,6 @@
import io
import inspect
import itertools
import math
import os
from pathlib import Path
import re
Expand Down Expand Up @@ -113,17 +111,37 @@

def sanitize_section(section):
"""
Cleans up a section string, making it viable as a directory name.
Cleans up a section string, making it viable as a directory name.
hugovk marked this conversation as resolved.
Show resolved Hide resolved
"""
return section.replace("/", "-").replace(" ", "_")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To make things more explicit/readable, this could use a dict similar to the one used below for unsanitize_section.
If new sections that require sanitation are added in the future the function won't work, but it will serve as a reminder to update both dicts.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated.



def sanitize_section_legacy(section):
"""
Cleans up a section string, making it viable as a directory name (allow spaces).
hugovk marked this conversation as resolved.
Show resolved Hide resolved
"""
return section.replace("/", "-")


_unsanitize_section = {
"C_API": "C API",
"Core_and_Builtins": "Core and Builtins",
hugovk marked this conversation as resolved.
Show resolved Hide resolved
"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 @@ -249,40 +267,6 @@ def safe_mkdir(path):
os.makedirs(path)


def which(cmd, path="PATH"):
"""Find cmd on PATH."""
if os.path.exists(cmd):
return cmd
if cmd[0] == '/':
return None
for segment in os.getenv(path).split(":"):
program = os.path.normpath(os.path.join(segment, cmd))
if os.path.exists(program):
return program
return None


def strip_whitespace_lines(lines):
# strip from head
while lines:
if lines[0]:
break
lines.pop(0)

# strip from tail
while lines:
if lines[-1]:
return
lines.pop()


def longest_line(lines):
longest = 0
for line in lines:
longest = max(longest, len(line))
return longest


def version_key(element):
fields = list(element.split("."))
if len(fields) == 1:
Expand Down Expand Up @@ -335,14 +319,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 @@ -560,8 +548,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 @@ -575,7 +563,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 @@ -612,7 +600,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 All @@ -632,31 +620,6 @@ def save_next(self):
blurb.save(filename)
return filename

def save_split_next(self):
"""
Save out blurbs created from "blurb split".
They don't have dates, so we have to get creative.
"""
filenames = []
# the "date" MUST have a leading zero.
# this ensures these files sort after all
# newly created blurbs.
width = int(math.ceil(math.log(len(self), 10))) + 1
i = 1
blurb = Blurbs()
while self:
metadata, body = self.pop()
metadata['date'] = str(i).rjust(width, '0')
if 'release date' in metadata:
del metadata['release date']
blurb.append((metadata, body))
filename = blurb._extract_next_filename()
blurb.save(filename)
blurb.clear()
filenames.append(filename)
i += 1
return filenames


tests_run = 0

Expand Down Expand Up @@ -694,13 +657,6 @@ def filename_test(self, filename):
b.load(filename)



def run(s):
process = subprocess.run(s.split(), capture_output=True)
process.check_returncode()
return process.stdout.decode('ascii')


readme_re = re.compile(r"This is \w+ version \d+\.\d+").match

def chdir_to_repo_root():
Expand Down Expand Up @@ -993,7 +949,6 @@ def release(version):
metadata = {"no changes": "True", "gh-issue": "0", "section": "Library", "date": date, "nonce": nonceify(body)}
blurbs.append((metadata, body))
else:
no_changes = None
count = len(filenames)
print(f'Merging {count} blurbs to "{output}".')

Expand Down