Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit b8dba09

Browse files
authored
Fix: KeyError 'filename'. (#386)
By dropping the `f()` function (and dropping Python 3.5 compatibility), as the real `f-string` do not have the issue with non-locals. closes #299, #300
1 parent 96735b6 commit b8dba09

File tree

2 files changed

+46
-72
lines changed

2 files changed

+46
-72
lines changed

blurb/blurb.py

+40-69
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,6 @@
4646
import atexit
4747
import base64
4848
import builtins
49-
from collections import OrderedDict
5049
import glob
5150
import hashlib
5251
import io
@@ -63,9 +62,7 @@
6362
import tempfile
6463
import textwrap
6564
import time
66-
import types
6765
import unittest
68-
import uuid
6966

7067

7168
#
@@ -114,32 +111,6 @@
114111
sections.append(section.strip())
115112

116113

117-
def f(s):
118-
"""
119-
Basic support for 3.6's f-strings, in 3.5!
120-
121-
Formats "s" using appropriate globals and locals
122-
dictionaries. This f-string:
123-
f"hello a is {a}"
124-
simply becomes
125-
f("hello a is {a}")
126-
In other words, just throw parentheses around the
127-
string, and you're done!
128-
129-
Implemented internally using str.format_map().
130-
This means it doesn't support expressions:
131-
f("two minus three is {2-3}")
132-
And it doesn't support function calls:
133-
f("how many elements? {len(my_list)}")
134-
But most other f-string features work.
135-
"""
136-
frame = sys._getframe(1)
137-
d = dict(builtins.__dict__)
138-
d.update(frame.f_globals)
139-
d.update(frame.f_locals)
140-
return s.format_map(d)
141-
142-
143114
def sanitize_section(section):
144115
"""
145116
Cleans up a section string, making it viable as a directory name.
@@ -252,10 +223,10 @@ def sortable_datetime():
252223

253224

254225
def prompt(prompt):
255-
return input(f("[{prompt}> "))
226+
return input(f"[{prompt}> ")
256227

257228
def require_ok(prompt):
258-
prompt = f("[{prompt}> ")
229+
prompt = f"[{prompt}> "
259230
while True:
260231
s = input(prompt).strip()
261232
if s == 'ok':
@@ -485,7 +456,7 @@ def parse(self, text, *, metadata=None, filename="input"):
485456
line_number = None
486457

487458
def throw(s):
488-
raise BlurbError(f("Error in {filename}:{line_number}:\n{s}"))
459+
raise BlurbError(f"Error in {filename}:{line_number}:\n{s}")
489460

490461
def finish_entry():
491462
nonlocal body
@@ -565,7 +536,7 @@ def __str__(self):
565536
add_separator = True
566537
if metadata:
567538
for name, value in sorted(metadata.items()):
568-
add(f(".. {name}: {value}\n"))
539+
add(f".. {name}: {value}\n")
569540
add("\n")
570541
add(textwrap_body(body))
571542
return "".join(output)
@@ -587,10 +558,10 @@ def _parse_next_filename(filename):
587558
components = filename.split(os.sep)
588559
section, filename = components[-2:]
589560
section = unsanitize_section(section)
590-
assert section in sections, f("Unknown section {section}")
561+
assert section in sections, f"Unknown section {section}"
591562

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

596567
metadata = {"date": fields[0], "nonce": fields[-2], "section": section}
@@ -779,7 +750,7 @@ def subcommand(fn):
779750
def get_subcommand(subcommand):
780751
fn = subcommands.get(subcommand)
781752
if not fn:
782-
error(f("Unknown subcommand: {subcommand}\nRun 'blurb help' for help."))
753+
error(f"Unknown subcommand: {subcommand}\nRun 'blurb help' for help.")
783754
return fn
784755

785756

@@ -841,19 +812,19 @@ def help(subcommand=None):
841812
for name, p in inspect.signature(fn).parameters.items():
842813
if p.kind == inspect.Parameter.KEYWORD_ONLY:
843814
short_option = name[0]
844-
options.append(f(" [-{short_option}|--{name}]"))
815+
options.append(f" [-{short_option}|--{name}]")
845816
elif p.kind == inspect.Parameter.POSITIONAL_OR_KEYWORD:
846817
positionals.append(" ")
847818
has_default = (p.default != inspect._empty)
848819
if has_default:
849820
positionals.append("[")
850821
nesting += 1
851-
positionals.append(f("<{name}>"))
822+
positionals.append(f"<{name}>")
852823
positionals.append("]" * nesting)
853824

854825

855826
parameters = "".join(options + positionals)
856-
print(f("blurb {subcommand}{parameters}"))
827+
print(f"blurb {subcommand}{parameters}")
857828
print()
858829
print(doc)
859830
sys.exit(0)
@@ -944,7 +915,7 @@ def init_tmp_with_template():
944915
else:
945916
args = list(shlex.split(editor))
946917
if not shutil.which(args[0]):
947-
sys.exit(f("Invalid GIT_EDITOR / EDITOR value: {editor}"))
918+
sys.exit(f"Invalid GIT_EDITOR / EDITOR value: {editor}")
948919
args.append(tmp_path)
949920

950921
while True:
@@ -964,7 +935,7 @@ def init_tmp_with_template():
964935

965936
if failure:
966937
print()
967-
print(f("Error: {failure}"))
938+
print(f"Error: {failure}")
968939
print()
969940
try:
970941
prompt("Hit return to retry (or Ctrl-C to abort)")
@@ -998,20 +969,20 @@ def release(version):
998969
if existing_filenames:
999970
error("Sorry, can't handle appending 'next' files to an existing version (yet).")
1000971

1001-
output = f("Misc/NEWS.d/{version}.rst")
972+
output = f"Misc/NEWS.d/{version}.rst"
1002973
filenames = glob_blurbs("next")
1003974
blurbs = Blurbs()
1004975
date = current_date()
1005976

1006977
if not filenames:
1007-
print(f("No blurbs found. Setting {version} as having no changes."))
1008-
body = f("There were no new changes in version {version}.\n")
978+
print(f"No blurbs found. Setting {version} as having no changes.")
979+
body = f"There were no new changes in version {version}.\n"
1009980
metadata = {"no changes": "True", "bpo": "0", "section": "Library", "date": date, "nonce": nonceify(body)}
1010981
blurbs.append((metadata, body))
1011982
else:
1012983
no_changes = None
1013984
count = len(filenames)
1014-
print(f('Merging {count} blurbs to "{output}".'))
985+
print(f'Merging {count} blurbs to "{output}".')
1015986

1016987
for filename in filenames:
1017988
if not filename.endswith(".rst"):
@@ -1028,14 +999,14 @@ def release(version):
1028999
flush_git_add_files()
10291000

10301001
how_many = len(filenames)
1031-
print(f("Removing {how_many} 'next' files from git."))
1002+
print(f"Removing {how_many} 'next' files from git.")
10321003
git_rm_files.extend(filenames)
10331004
flush_git_rm_files()
10341005

10351006
# sanity check: ensuring that saving/reloading the merged blurb file works.
10361007
blurbs2 = Blurbs()
10371008
blurbs2.load(output)
1038-
assert blurbs2 == blurbs, f("Reloading {output} isn't reproducible?!")
1009+
assert blurbs2 == blurbs, f"Reloading {output} isn't reproducible?!"
10391010

10401011
print()
10411012
print("Ready for commit.")
@@ -1110,7 +1081,7 @@ def print(*a, sep=" "):
11101081
metadata, body = blurbs[0]
11111082
release_date = metadata["release date"]
11121083

1113-
print(f("*Release date: {release_date}*"))
1084+
print(f"*Release date: {release_date}*")
11141085
print()
11151086

11161087
if "no changes" in metadata:
@@ -1191,11 +1162,11 @@ def populate():
11911162

11921163
for section in sections:
11931164
dir_name = sanitize_section(section)
1194-
dir_path = f("NEWS.d/next/{dir_name}")
1165+
dir_path = f"NEWS.d/next/{dir_name}"
11951166
safe_mkdir(dir_path)
1196-
readme_path = f("NEWS.d/next/{dir_name}/README.rst")
1167+
readme_path = f"NEWS.d/next/{dir_name}/README.rst"
11971168
with open(readme_path, "wt", encoding="utf-8") as readme:
1198-
readme.write(f("Put news entry ``blurb`` files for the *{section}* section in this directory.\n"))
1169+
readme.write(f"Put news entry ``blurb`` files for the *{section}* section in this directory.\n")
11991170
git_add_files.append(dir_path)
12001171
git_add_files.append(readme_path)
12011172
flush_git_add_files()
@@ -1216,7 +1187,7 @@ def export():
12161187
# """
12171188
# Test function for blurb command-line processing.
12181189
# """
1219-
# print(f("arg: boolean {boolean} option {option}"))
1190+
# print(f"arg: boolean {boolean} option {option}")
12201191

12211192

12221193
@subcommand
@@ -1301,7 +1272,7 @@ def flush_blurb():
13011272
fields.append(field)
13021273
see_also = ", ".join(fields)
13031274
# print("see_also: ", repr(see_also))
1304-
accumulator.append(f("(See also: {see_also})"))
1275+
accumulator.append(f"(See also: {see_also})")
13051276
see_also = None
13061277
if not accumulator:
13071278
return
@@ -1347,8 +1318,8 @@ def flush_version():
13471318
if version is None:
13481319
assert not blurbs, "version should only be None initially, we shouldn't have blurbs yet"
13491320
return
1350-
assert blurbs, f("No blurbs defined when flushing version {version}!")
1351-
output = f("NEWS.d/{version}.rst")
1321+
assert blurbs, f"No blurbs defined when flushing version {version}!"
1322+
output = f"NEWS.d/{version}.rst"
13521323

13531324
if released:
13541325
# saving merged blurb file for version, e.g. Misc/NEWS.d/3.7.0a1.rst
@@ -1466,11 +1437,11 @@ def flush_version():
14661437
elif line.startswith("- Issue #9516: Issue #9516: avoid errors in sysconfig when MACOSX_DEPLOYMENT_TARGET"):
14671438
line = "- Issue #9516 and Issue #9516: avoid errors in sysconfig when MACOSX_DEPLOYMENT_TARGET"
14681439
elif line.title().startswith(("- Request #", "- Bug #", "- Patch #", "- Patches #")):
1469-
# print(f("FIXING LINE {line_number}: {line!r}"))
1440+
# print(f"FIXING LINE {line_number}: {line!r}")
14701441
line = "- Issue #" + line.partition('#')[2]
1471-
# print(f("FIXED LINE {line_number}: {line!r}"))
1442+
# print(f"FIXED LINE {line_number}: {line!r}")
14721443
# else:
1473-
# print(f("NOT FIXING LINE {line_number}: {line!r}"))
1444+
# print(f"NOT FIXING LINE {line_number}: {line!r}")
14741445

14751446

14761447
# 4. determine the actual content of the line
@@ -1535,7 +1506,7 @@ def flush_version():
15351506
line = line[4:]
15361507
parse_bpo = True
15371508
else:
1538-
# print(f("[[{line_number:8} no bpo]] {line}"))
1509+
# print(f"[[{line_number:8} no bpo]] {line}")
15391510
parse_bpo = False
15401511
if parse_bpo:
15411512
# GAAAH
@@ -1575,9 +1546,9 @@ def flush_version():
15751546
try:
15761547
int(bpo) # this will throw if it's not a legal int
15771548
except ValueError:
1578-
sys.exit(f("Couldn't convert bpo number to int on line {line_number}! {bpo!r}"))
1549+
sys.exit(f"Couldn't convert bpo number to int on line {line_number}! {bpo!r}")
15791550
if see_also == "partially":
1580-
sys.exit(f("What the hell on line {line_number}! {bpo!r}"))
1551+
sys.exit(f"What the hell on line {line_number}! {bpo!r}")
15811552

15821553
# 4.6.1 continuation of blurb
15831554
elif line.startswith(" "):
@@ -1586,7 +1557,7 @@ def flush_version():
15861557
elif line.startswith(" * "):
15871558
line = line[3:]
15881559
elif line:
1589-
sys.exit(f("Didn't recognize line {line_number}! {line!r}"))
1560+
sys.exit(f"Didn't recognize line {line_number}! {line!r}")
15901561
# only add blank lines if we have an initial line in the accumulator
15911562
if line or accumulator:
15921563
accumulator.append(line)
@@ -1598,7 +1569,7 @@ def flush_version():
15981569
git_rm_files.append("NEWS")
15991570
flush_git_rm_files()
16001571

1601-
print(f("Wrote {blurb_count} news items across {version_count} versions."))
1572+
print(f"Wrote {blurb_count} news items across {version_count} versions.")
16021573
print()
16031574
print("Ready for commit.")
16041575

@@ -1647,10 +1618,10 @@ def main():
16471618
def handle_option(s, dict):
16481619
name = dict.get(s, None)
16491620
if not name:
1650-
sys.exit(f('blurb: Unknown option for {subcommand}: "{s}"'))
1621+
sys.exit(f'blurb: Unknown option for {subcommand}: "{s}"')
16511622
kwargs[name] = not kwargs[name]
16521623

1653-
# print(f("short_options {short_options} long_options {long_options}"))
1624+
# print(f"short_options {short_options} long_options {long_options}")
16541625
for a in args:
16551626
if done_with_options:
16561627
filtered_args.append(a)
@@ -1684,7 +1655,7 @@ def handle_option(s, dict):
16841655
# whoops, must be a real type error, reraise
16851656
raise e
16861657

1687-
how_many = f("{specified} argument")
1658+
how_many = f"{specified} argument"
16881659
if specified != 1:
16891660
how_many += "s"
16901661

@@ -1695,12 +1666,12 @@ def handle_option(s, dict):
16951666
middle = "requires"
16961667
else:
16971668
plural = "" if required == 1 else "s"
1698-
middle = f("requires at least {required} argument{plural} and at most")
1699-
middle += f(" {total} argument")
1669+
middle = f"requires at least {required} argument{plural} and at most"
1670+
middle += f" {total} argument"
17001671
if total != 1:
17011672
middle += "s"
17021673

1703-
print(f('Error: Wrong number of arguments!\n\nblurb {subcommand} {middle},\nand you specified {how_many}.'))
1674+
print(f'Error: Wrong number of arguments!\n\nblurb {subcommand} {middle},\nand you specified {how_many}.')
17041675
print()
17051676
print("usage: ", end="")
17061677
help(subcommand)

blurb/pyproject.toml

+6-3
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,13 @@ author-email = "[email protected]"
99
maintainer = "Python Core Developers"
1010
maintainer-email = "[email protected]"
1111
home-page = "https://github.com/python/core-workflow/tree/master/blurb"
12-
requires-python = ">=3.5"
12+
requires-python = ">=3.6"
1313
description-file = "README.rst"
14-
classifiers = [ "Intended Audience :: Developers", "License :: OSI Approved :: BSD License", "Programming Language :: Python :: 3 :: Only",]
15-
14+
classifiers = [
15+
"Intended Audience :: Developers",
16+
"License :: OSI Approved :: BSD License",
17+
"Programming Language :: Python :: 3 :: Only"
18+
]
1619

1720
[tool.flit.scripts]
1821
blurb = "blurb:main"

0 commit comments

Comments
 (0)