Skip to content

Adopt Ruff #62

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

Merged
merged 1 commit into from
Aug 13, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions .ruff.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
target-version = "py39"

[format]
preview = true
quote-style = "single"
docstring-code-format = true

[lint]
preview = true
select = [
"I", # isort
]
ignore = [
"E501", # Ignore line length errors (we use auto-formatting)
]
2 changes: 1 addition & 1 deletion src/blurb/__main__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"""Run blurb using ``python3 -m blurb``."""
from blurb._cli import main

from blurb._cli import main

if __name__ == '__main__':
main()
16 changes: 9 additions & 7 deletions src/blurb/_add.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import tempfile

from blurb._blurb_file import BlurbError, Blurbs
from blurb._cli import subcommand,error,prompt
from blurb._cli import error, prompt, subcommand
from blurb._git import flush_git_add_files, git_add_files
from blurb._template import sections, template

Expand Down Expand Up @@ -43,11 +43,11 @@ def add(*, issue: str | None = None, section: str | None = None):
spaces in names can be substituted for underscores:

{sections}
"""
""" # fmt: skip

handle, tmp_path = tempfile.mkstemp('.rst')
os.close(handle)
atexit.register(lambda : os.unlink(tmp_path))
atexit.register(lambda: os.unlink(tmp_path))

text = _blurb_template_text(issue=issue, section=section)
with open(tmp_path, 'w', encoding='utf-8') as file:
Expand All @@ -72,6 +72,8 @@ def add(*, issue: str | None = None, section: str | None = None):
git_add_files.append(path)
flush_git_add_files()
print('Ready for commit.')


add.__doc__ = add.__doc__.format(sections='\n'.join(f'* {s}' for s in sections))


Expand Down Expand Up @@ -178,13 +180,13 @@ def _extract_section_name(section: str | None, /) -> str | None:

if not matches:
section_list = '\n'.join(f'* {s}' for s in sections)
raise SystemExit(f'Invalid section name: {section!r}\n\n'
f'Valid names are:\n\n{section_list}')
raise SystemExit(
f'Invalid section name: {section!r}\n\nValid names are:\n\n{section_list}'
)

if len(matches) > 1:
multiple_matches = ', '.join(f'* {m}' for m in sorted(matches))
raise SystemExit(f'More than one match for {section!r}:\n\n'
f'{multiple_matches}')
raise SystemExit(f'More than one match for {section!r}:\n\n{multiple_matches}')

return matches[0]

Expand Down
33 changes: 24 additions & 9 deletions src/blurb/_blurb_file.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,13 @@ class BlurbError(RuntimeError):


class Blurbs(list):
def parse(self, text: str, *, metadata: dict[str, str] | None = None,
filename: str = 'input') -> None:
def parse(
self,
text: str,
*,
metadata: dict[str, str] | None = None,
filename: str = 'input',
) -> None:
"""Parses a string.

Appends a list of blurb ENTRIES to self, as tuples: (metadata, body)
Expand Down Expand Up @@ -147,13 +152,17 @@ def finish_entry() -> None:
throw(f'Invalid {issue_keys[key]} number: {value!r}')

if key == 'gh-issue' and int(value) < lowest_possible_gh_issue_number:
throw(f'Invalid gh-issue number: {value!r} (must be >= {lowest_possible_gh_issue_number})')
throw(
f'Invalid gh-issue number: {value!r} (must be >= {lowest_possible_gh_issue_number})'
)

if key == 'section':
if no_changes:
continue
if value not in sections:
throw(f'Invalid section {value!r}! You must use one of the predefined sections.')
throw(
f'Invalid section {value!r}! You must use one of the predefined sections.'
)

if 'gh-issue' not in metadata and 'bpo' not in metadata:
throw("'gh-issue:' or 'bpo:' must be specified in the metadata!")
Expand Down Expand Up @@ -232,7 +241,9 @@ def _parse_next_filename(filename: str) -> dict[str, str]:
assert section in sections, f'Unknown section {section}'

fields = [x.strip() for x in filename.split('.')]
assert len(fields) >= 4, f"Can't parse 'next' filename! filename {filename!r} fields {fields}"
assert len(fields) >= 4, (
f"Can't parse 'next' filename! filename {filename!r} fields {fields}"
)
assert fields[-1] == 'rst'

metadata = {'date': fields[0], 'nonce': fields[-2], 'section': section}
Expand Down Expand Up @@ -263,7 +274,7 @@ def ensure_metadata(self) -> None:
('bpo', '0'),
('date', sortable_datetime()),
('nonce', generate_nonce(body)),
):
):
if name not in metadata:
metadata[name] = default

Expand All @@ -274,10 +285,14 @@ def _extract_next_filename(self) -> str:
metadata['section'] = sanitize_section(metadata['section'])
metadata['root'] = root
if int(metadata['gh-issue']) > 0:
path = '{root}/Misc/NEWS.d/next/{section}/{date}.gh-issue-{gh-issue}.{nonce}.rst'.format_map(metadata)
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
path = '{root}/Misc/NEWS.d/next/{section}/{date}.bpo-{bpo}.{nonce}.rst'.format_map(metadata)
path = '{root}/Misc/NEWS.d/next/{section}/{date}.bpo-{bpo}.{nonce}.rst'.format_map(
metadata
)
for name in ('root', 'section', 'date', 'gh-issue', 'bpo', 'nonce'):
del metadata[name]
return path
Expand All @@ -294,4 +309,4 @@ def save_next(self) -> str:


def sortable_datetime() -> str:
return time.strftime("%Y-%m-%d-%H-%M-%S", time.localtime())
return time.strftime('%Y-%m-%d-%H-%M-%S', time.localtime())
22 changes: 13 additions & 9 deletions src/blurb/_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ def prompt(prompt: str, /) -> str:


def require_ok(prompt: str, /) -> str:
prompt = f"[{prompt}> "
prompt = f'[{prompt}> '
while True:
s = input(prompt).strip()
if s == 'ok':
Expand Down Expand Up @@ -88,7 +88,7 @@ def help(subcommand: str | None = None) -> None:
options.append(f' [-{short_option}|--{name} {metavar}]')
elif p.kind == inspect.Parameter.POSITIONAL_OR_KEYWORD:
positionals.append(' ')
has_default = (p.default != inspect._empty)
has_default = p.default != inspect._empty
if has_default:
positionals.append('[')
nesting += 1
Expand Down Expand Up @@ -146,7 +146,6 @@ def _blurb_help() -> None:


def main() -> None:

args = sys.argv[1:]

if not args:
Expand All @@ -165,6 +164,7 @@ def main() -> None:
raise SystemExit(fn(*args))

import blurb._merge

blurb._merge.original_dir = os.getcwd()
try:
chdir_to_repo_root()
Expand All @@ -177,8 +177,7 @@ def main() -> None:
kwargs = {}
for name, p in inspect.signature(fn).parameters.items():
if p.kind == inspect.Parameter.KEYWORD_ONLY:
if (p.default is not None
and not isinstance(p.default, (bool, str))):
if p.default is not None and not isinstance(p.default, (bool, str)):
raise SystemExit(
'blurb command-line processing cannot handle '
f'options of type {type(p.default).__qualname__}'
Expand Down Expand Up @@ -262,7 +261,9 @@ def handle_option(s, dict):
if total != 1:
middle += 's'

print(f'Error: Wrong number of arguments!\n\nblurb {subcommand} {middle},\nand you specified {how_many}.')
print(
f'Error: Wrong number of arguments!\n\nblurb {subcommand} {middle},\nand you specified {how_many}.'
)
print()
print('usage: ', end='')
help(subcommand)
Expand Down Expand Up @@ -293,11 +294,13 @@ def test_first_line(filename, test):
return False
return True

if not (test_first_line('README', readme_re)
or test_first_line('README.rst', readme_re)):
if not (
test_first_line('README', readme_re)
or test_first_line('README.rst', readme_re)
):
continue

if not test_first_line('LICENSE', 'A. HISTORY OF THE SOFTWARE'.__eq__):
if not test_first_line('LICENSE', 'A. HISTORY OF THE SOFTWARE'.__eq__):
continue
if not os.path.exists('Include/Python.h'):
continue
Expand All @@ -307,5 +310,6 @@ def test_first_line(filename, test):
break

import blurb._blurb_file

blurb._blurb_file.root = path
return path
6 changes: 4 additions & 2 deletions src/blurb/_merge.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,14 @@ def write_news(output: str, *, versions: list[str]) -> None:
def prnt(msg: str = '', /):
buff.append(msg)

prnt("""
prnt(
"""
+++++++++++
Python News
+++++++++++

""".strip())
""".strip()
)

for version in versions:
filenames = glob_blurbs(version)
Expand Down
6 changes: 4 additions & 2 deletions src/blurb/_populate.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import os

from blurb._cli import subcommand
from blurb._git import git_add_files, flush_git_add_files
from blurb._git import flush_git_add_files, git_add_files
from blurb._template import sanitize_section, sections


Expand All @@ -17,7 +17,9 @@ def populate() -> None:
os.makedirs(dir_path, exist_ok=True)
readme_path = f'NEWS.d/next/{dir_name}/README.rst'
with open(readme_path, 'w', encoding='utf-8') as readme:
readme.write(f'Put news entry ``blurb`` files for the *{section}* section in this directory.\n')
readme.write(
f'Put news entry ``blurb`` files for the *{section}* section in this directory.\n'
)
git_add_files.append(dir_path)
git_add_files.append(readme_path)
flush_git_add_files()
20 changes: 16 additions & 4 deletions src/blurb/_release.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,12 @@
import blurb._blurb_file
from blurb._blurb_file import Blurbs
from blurb._cli import error, subcommand
from blurb._git import (flush_git_add_files, flush_git_rm_files,
git_rm_files, git_add_files)
from blurb._git import (
flush_git_add_files,
flush_git_rm_files,
git_add_files,
git_rm_files,
)
from blurb._utils.globs import glob_blurbs
from blurb._utils.text import generate_nonce

Expand All @@ -25,7 +29,9 @@ def release(version: str) -> None:

existing_filenames = glob_blurbs(version)
if existing_filenames:
error("Sorry, can't handle appending 'next' files to an existing version (yet).")
error(
"Sorry, can't handle appending 'next' files to an existing version (yet)."
)

output = f'Misc/NEWS.d/{version}.rst'
filenames = glob_blurbs('next')
Expand All @@ -35,7 +41,13 @@ def release(version: str) -> None:
if not filenames:
print(f'No blurbs found. Setting {version} as having no changes.')
body = f'There were no new changes in version {version}.\n'
metadata = {'no changes': 'True', 'gh-issue': '0', 'section': 'Library', 'date': date, 'nonce': generate_nonce(body)}
metadata = {
'no changes': 'True',
'gh-issue': '0',
'section': 'Library',
'date': date,
'nonce': generate_nonce(body),
}
blurbs.append((metadata, body))
else:
count = len(filenames)
Expand Down
2 changes: 1 addition & 1 deletion src/blurb/_template.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@
'C_API': 'C API',
'Core_and_Builtins': 'Core and Builtins',
'Tools-Demos': 'Tools/Demos',
}
}


def sanitize_section(section: str, /) -> str:
Expand Down
6 changes: 4 additions & 2 deletions src/blurb/_utils/globs.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@
import os

from blurb._template import (
next_filename_unsanitize_sections, sanitize_section,
sanitize_section_legacy, sections,
next_filename_unsanitize_sections,
sanitize_section,
sanitize_section_legacy,
sections,
)


Expand Down
10 changes: 7 additions & 3 deletions src/blurb/_utils/text.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ def textwrap_body(body: str | Iterable[str], *, subsequent_indent: str = '') ->
indents = itertools.chain(
itertools.repeat(initial, 1),
itertools.repeat(subsequent),
)
)
lines = [indent + line for indent, line in zip(indents, lines)]
paragraph = '\n'.join(lines)
paragraphs2.append(paragraph)
Expand Down Expand Up @@ -88,8 +88,12 @@ def textwrap_body(body: str | Iterable[str], *, subsequent_indent: str = '') ->
# twice, so it's stable, and this means occasionally it'll
# convert two spaces to one space, no big deal.

paragraph = '\n'.join(textwrap.wrap(paragraph.strip(), width=76, **kwargs)).rstrip()
paragraph = '\n'.join(textwrap.wrap(paragraph.strip(), width=76, **kwargs)).rstrip()
paragraph = '\n'.join(
textwrap.wrap(paragraph.strip(), width=76, **kwargs)
).rstrip()
paragraph = '\n'.join(
textwrap.wrap(paragraph.strip(), width=76, **kwargs)
).rstrip()
paragraphs2.append(paragraph)
# don't reflow literal code blocks (I hope)
dont_reflow = paragraph.endswith('::')
Expand Down
4 changes: 2 additions & 2 deletions src/blurb/blurb.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@


def error(*a):
s = " ".join(str(x) for x in a)
sys.exit("Error: " + s)
s = ' '.join(str(x) for x in a)
sys.exit('Error: ' + s)


if __name__ == '__main__':
Expand Down
Loading