Skip to content

Commit 2a384a1

Browse files
derek73claude
andcommitted
Modernize string formatting to f-strings and improve readability
- Convert all .format() and % formatting to f-strings across codebase - Update ruff config to remove UP031/UP032 ignores (Python 2 legacy) - Add noqa comments to dynamic template .format() calls (can't convert to f-strings) - Use SimpleNamespace for dot notation access in test_variations.py - Refactor __repr__ method for improved readability - All 1182 tests pass, ruff checks pass Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
1 parent d410403 commit 2a384a1

6 files changed

Lines changed: 32 additions & 36 deletions

File tree

docs/conf.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@
5050

5151
# General information about the project.
5252
project = 'Nameparser'
53-
copyright = '{:%Y}, Derek Gulbranson'.format(date.today())
53+
copyright = f'{date.today():%Y}, Derek Gulbranson'
5454

5555
# The version info for the project you're documenting, acts as replacement for
5656
# |version| and |release|, also used in various other places throughout the

nameparser/config/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ def __call__(self) -> Set[str]:
7575
return self.elements
7676

7777
def __repr__(self) -> str:
78-
return "SetManager({})".format(self.elements) # used for docs
78+
return f"SetManager({self.elements})" # used for docs
7979

8080
def __iter__(self) -> Iterator[str]:
8181
return iter(self.elements)

nameparser/parser.py

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@ def __next__(self) -> str:
194194
def __str__(self) -> str:
195195
if self.string_format is not None:
196196
# string_format = "{title} {first} {middle} {last} {suffix} ({nickname})"
197-
_s = self.string_format.format(**self.as_dict())
197+
_s = self.string_format.format(**self.as_dict()) # noqa: UP032
198198
# remove trailing punctuation from missing nicknames
199199
_s = _s.replace(str(self.C.empty_attribute_default), '').replace(" ()", "").replace(" ''", "").replace(' ""', "")
200200
_s = self.C.regexes.space_before_comma.sub(',', _s)
@@ -206,18 +206,18 @@ def __hash__(self) -> int:
206206

207207
def __repr__(self) -> str:
208208
if self.unparsable:
209-
_string = "<%(class)s : [ Unparsable ] >" % {'class': self.__class__.__name__, }
209+
_string = f"<{self.__class__.__name__} : [ Unparsable ] >"
210210
else:
211-
_string = "<%(class)s : [\n\ttitle: %(title)r \n\tfirst: %(first)r \n\tmiddle: %(middle)r \n\tlast: %(last)r \n\tsuffix: %(suffix)r\n\tnickname: %(nickname)r\n\tmaiden: %(maiden)r\n]>" % {
212-
'class': self.__class__.__name__,
213-
'title': self.title or '',
214-
'first': self.first or '',
215-
'middle': self.middle or '',
216-
'last': self.last or '',
217-
'suffix': self.suffix or '',
218-
'nickname': self.nickname or '',
219-
'maiden': self.maiden or '',
220-
}
211+
attrs = (
212+
f"\ttitle: {self.title or ''!r} \n"
213+
f"\tfirst: {self.first or ''!r} \n"
214+
f"\tmiddle: {self.middle or ''!r} \n"
215+
f"\tlast: {self.last or ''!r} \n"
216+
f"\tsuffix: {self.suffix or ''!r}\n"
217+
f"\tnickname: {self.nickname or ''!r}\n"
218+
f"\tmaiden: {self.maiden or ''!r}"
219+
)
220+
_string = f"<{self.__class__.__name__} : [\n{attrs}\n]>"
221221
return _string
222222

223223
def as_dict(self, include_empty: bool = True) -> dict[str, str]:
@@ -320,7 +320,7 @@ def initials(self) -> str:
320320
if len(last_initials_list) else ""
321321
}
322322

323-
_s = self.initials_format.format(**initials_dict)
323+
_s = self.initials_format.format(**initials_dict) # noqa: UP032
324324
return self.collapse_whitespace(_s) or self.C.empty_attribute_default
325325

326326
@property
@@ -552,7 +552,7 @@ def _set_list(self, attr: str, value: str | list[str] | None) -> None:
552552
else:
553553
raise TypeError(
554554
"Can only assign strings, lists or None to name attributes."
555-
" Got {}".format(type(value)))
555+
f" Got {type(value)}")
556556
setattr(self, attr+"_list", self.parse_pieces(val))
557557

558558
# Parse helpers
@@ -1163,7 +1163,7 @@ def parse_pieces(self, parts: Iterable[str], additional_parts_count: int = 0) ->
11631163
for part in parts:
11641164
if not isinstance(part, (str, bytes)):
11651165
raise TypeError("Name parts must be strings. "
1166-
" Got {}".format(type(part)))
1166+
f" Got {type(part)}")
11671167
output += [x.strip(' ,') for x in part.split(' ')]
11681168

11691169
# If part contains periods, check if it's multiple titles or suffixes

pyproject.toml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,4 @@ extend-select = [
7171
]
7272
ignore = [
7373
"E74", # ambiguous-{variable,class,function}-name (I have trouble believing that these are real rules)
74-
"UP031", # printf-string-formatting (the code already uses % formatting)
75-
"UP032", # f-string (the code already uses str.format)
7674
]

tests/base.py

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,7 @@ def m(self, actual: T, expected: T, hn: HumanName) -> None:
1818
"""assertEqual with a better message and awareness of hn.C.empty_attribute_default"""
1919
expected_ = expected or hn.C.empty_attribute_default
2020
try:
21-
assert actual == expected_, "'%s' != '%s' for '%s'\n%r" % (
22-
actual,
23-
expected,
24-
hn.original,
25-
hn,
26-
)
21+
assert actual == expected_, f"{actual!r} != {expected!r} for {hn.original!r}\n{hn!r}"
2722
except UnicodeDecodeError:
2823
assert actual == expected_, f"actual={actual!r} != expected={expected_!r}"
2924

tests/test_variations.py

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
from tests.base import HumanNameTestBase
44

5+
from types import SimpleNamespace
6+
57

68
TEST_NAMES = (
79
"John Doe",
@@ -199,18 +201,19 @@ def test_variations_of_TEST_NAMES(self) -> None:
199201
for name in self.TEST_NAMES:
200202
hn = HumanName(name)
201203
if len(hn.suffix_list) > 1:
202-
hn = HumanName("{title} {first} {middle} {last} {suffix}".format(**hn.as_dict()).split(',')[0])
204+
d = SimpleNamespace(**hn.as_dict())
205+
hn = HumanName(f"{d.title} {d.first} {d.middle} {d.last} {d.suffix}".split(',')[0])
203206
hn.C.empty_attribute_default = '' # format strings below require empty string
204-
hn_dict = hn.as_dict()
205-
nocomma = HumanName("{title} {first} {middle} {last} {suffix}".format(**hn_dict))
206-
lastnamecomma = HumanName("{last}, {title} {first} {middle} {suffix}".format(**hn_dict))
207-
if hn.suffix:
208-
suffixcomma = HumanName("{title} {first} {middle} {last}, {suffix}".format(**hn_dict))
209-
if hn.nickname:
210-
nocomma = HumanName("{title} {first} {middle} {last} {suffix} ({nickname})".format(**hn_dict))
211-
lastnamecomma = HumanName("{last}, {title} {first} {middle} {suffix} ({nickname})".format(**hn_dict))
212-
if hn.suffix:
213-
suffixcomma = HumanName("{title} {first} {middle} {last}, {suffix} ({nickname})".format(**hn_dict))
207+
d = SimpleNamespace(**hn.as_dict())
208+
nocomma = HumanName(f"{d.title} {d.first} {d.middle} {d.last} {d.suffix}")
209+
lastnamecomma = HumanName(f"{d.last}, {d.title} {d.first} {d.middle} {d.suffix}")
210+
if d.suffix:
211+
suffixcomma = HumanName(f"{d.title} {d.first} {d.middle} {d.last}, {d.suffix}")
212+
if d.nickname:
213+
nocomma = HumanName(f"{d.title} {d.first} {d.middle} {d.last} {d.suffix} ({d.nickname})")
214+
lastnamecomma = HumanName(f"{d.last}, {d.title} {d.first} {d.middle} {d.suffix} ({d.nickname})")
215+
if d.suffix:
216+
suffixcomma = HumanName(f"{d.title} {d.first} {d.middle} {d.last}, {d.suffix} ({d.nickname})")
214217
for attr in hn._members:
215218
self.m(getattr(hn, attr), getattr(nocomma, attr), hn)
216219
self.m(getattr(hn, attr), getattr(lastnamecomma, attr), hn)

0 commit comments

Comments
 (0)