Skip to content

Commit 4e0af4b

Browse files
committed
fix scriptlines handling
1 parent dc342b4 commit 4e0af4b

File tree

2 files changed

+31
-27
lines changed

2 files changed

+31
-27
lines changed

src/attr/_make.py

Lines changed: 24 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -752,7 +752,7 @@ def __init__(
752752

753753
# tuples of script, globs, hook
754754
self._script_snippets: list[
755-
tuple[str, dict, Callable[[dict, dict], typing.Any]]
755+
tuple[list[str], dict, Callable[[dict, dict], typing.Any]]
756756
] = []
757757
self._repr_added = False
758758

@@ -770,7 +770,9 @@ def __repr__(self):
770770

771771
def _eval_snippets(self) -> None:
772772
"""Evaluate any registered snippets in one go."""
773-
script_lines = [snippet[0] for snippet in self._script_snippets]
773+
script_lines = [
774+
line for tup in self._script_snippets for line in tup[0]
775+
]
774776
script = "\n".join(script_lines)
775777
globs = {}
776778
for _, snippet_globs, _ in self._script_snippets:
@@ -1565,7 +1567,7 @@ def _generate_unique_filename(cls: type, func_name: str) -> str:
15651567

15661568
def _make_hash_script(
15671569
cls: type, attrs: list[Attribute], frozen: bool, cache_hash: bool
1568-
) -> tuple[str, dict]:
1570+
) -> tuple[list[str], dict]:
15691571
attrs = tuple(
15701572
a for a in attrs if a.hash is True or (a.hash is None and a.eq is True)
15711573
)
@@ -1631,8 +1633,7 @@ def append_hash_computation_lines(prefix, indent):
16311633
else:
16321634
append_hash_computation_lines("return ", tab)
16331635

1634-
script = "\n".join(method_lines)
1635-
return script, globs
1636+
return method_lines, globs
16361637

16371638

16381639
def _add_hash(cls: type, attrs: list[Attribute]):
@@ -1643,7 +1644,9 @@ def _add_hash(cls: type, attrs: list[Attribute]):
16431644
cls, attrs, frozen=False, cache_hash=False
16441645
)
16451646
_compile_and_eval(
1646-
script, globs, filename=_generate_unique_filename(cls, "__hash__")
1647+
"\n".join(script),
1648+
globs,
1649+
filename=_generate_unique_filename(cls, "__hash__"),
16471650
)
16481651
cls.__hash__ = globs["__hash__"]
16491652
return cls
@@ -1661,7 +1664,7 @@ def __ne__(self, other):
16611664
return not result
16621665

16631666

1664-
def _make_eq_script(attrs: list) -> tuple[str, dict]:
1667+
def _make_eq_script(attrs: list) -> tuple[list[str], dict]:
16651668
"""
16661669
Create __eq__ method for *cls* with *attrs*.
16671670
"""
@@ -1693,9 +1696,7 @@ def _make_eq_script(attrs: list) -> tuple[str, dict]:
16931696
else:
16941697
lines.append(" return True")
16951698

1696-
script = "\n".join(lines)
1697-
1698-
return script, globs
1699+
return lines, globs
16991700

17001701

17011702
def _make_order(cls, attrs):
@@ -1763,15 +1764,17 @@ def _add_eq(cls, attrs=None):
17631764

17641765
script, globs = _make_eq_script(attrs)
17651766
_compile_and_eval(
1766-
script, globs, filename=_generate_unique_filename(cls, "__eq__")
1767+
"\n".join(script),
1768+
globs,
1769+
filename=_generate_unique_filename(cls, "__eq__"),
17671770
)
17681771
cls.__eq__ = globs["__eq__"]
17691772
cls.__ne__ = __ne__
17701773

17711774
return cls
17721775

17731776

1774-
def _make_repr_script(attrs, ns) -> tuple[str, dict]:
1777+
def _make_repr_script(attrs, ns) -> tuple[list[str], dict]:
17751778
"""Create the source and globs for a __repr__ and return it."""
17761779
# Figure out which attributes to include, and which function to use to
17771780
# format them. The a.repr value can be either bool or a custom
@@ -1823,7 +1826,7 @@ def _make_repr_script(attrs, ns) -> tuple[str, dict]:
18231826
" already_repring.remove(id(self))",
18241827
]
18251828

1826-
return "\n".join(lines), globs
1829+
return lines, globs
18271830

18281831

18291832
def _add_repr(cls, ns=None, attrs=None):
@@ -1835,7 +1838,9 @@ def _add_repr(cls, ns=None, attrs=None):
18351838

18361839
script, globs = _make_repr_script(attrs, ns)
18371840
_compile_and_eval(
1838-
script, globs, filename=_generate_unique_filename(cls, "__repr__")
1841+
"\n".join(script),
1842+
globs,
1843+
filename=_generate_unique_filename(cls, "__repr__"),
18391844
)
18401845
cls.__repr__ = globs["__repr__"]
18411846
return cls
@@ -1955,7 +1960,7 @@ def _make_init_script(
19551960
is_exc,
19561961
cls_on_setattr,
19571962
attrs_init,
1958-
) -> tuple[str, dict, dict]:
1963+
) -> tuple[list[str], dict, dict]:
19591964
has_cls_on_setattr = (
19601965
cls_on_setattr is not None and cls_on_setattr is not setters.NO_OP
19611966
)
@@ -2112,7 +2117,7 @@ def _attrs_to_init_script(
21122117
needs_cached_setattr: bool,
21132118
has_cls_on_setattr: bool,
21142119
method_name: str,
2115-
) -> tuple[str, dict, dict]:
2120+
) -> tuple[list[str], dict, dict]:
21162121
"""
21172122
Return a script of an initializer for *attrs*, a dict of globals, and
21182123
annotations for the initializer.
@@ -2349,11 +2354,10 @@ def _attrs_to_init_script(
23492354
lines[0] = f"self.__attrs_pre_init__({pre_init_args})"
23502355

23512356
# Python <3.12 doesn't allow backslashes in f-strings.
2352-
NL = "\n "
2357+
lines = [f" {line}" for line in lines] if lines else [" pass"]
2358+
lines = [f"def {method_name}(self, {args}):", *lines]
23532359
return (
2354-
f"""def {method_name}(self, {args}):
2355-
{NL.join(lines) if lines else "pass"}
2356-
""",
2360+
lines,
23572361
names_for_globals,
23582362
annotations,
23592363
)

tests/test_dunders.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ def _add_init(cls, frozen):
104104
cls_on_setattr=None,
105105
attrs_init=False,
106106
)
107-
_compile_and_eval(script, globs, filename="__init__")
107+
_compile_and_eval("\n".join(script), globs, filename="__init__")
108108
cls.__init__ = globs["__init__"]
109109
cls.__init__.__annotations__ = annots
110110
return cls
@@ -1018,25 +1018,25 @@ def test_filenames(self):
10181018
)
10191019
assert (
10201020
CopyC.__init__.__code__.co_filename
1021-
== "<attrs generated methods tests.test_dunders.C-1>"
1021+
== "<attrs generated methods tests.test_dunders.C>"
10221022
)
10231023
assert (
10241024
CopyC.__eq__.__code__.co_filename
1025-
== "<attrs generated methods tests.test_dunders.C-1>"
1025+
== "<attrs generated methods tests.test_dunders.C>"
10261026
)
10271027
assert (
10281028
CopyC.__hash__.__code__.co_filename
1029-
== "<attrs generated methods tests.test_dunders.C-1>"
1029+
== "<attrs generated methods tests.test_dunders.C>"
10301030
)
10311031
assert (
10321032
C.__init__.__code__.co_filename
1033-
== "<attrs generated methods tests.test_dunders.C-2>"
1033+
== "<attrs generated methods tests.test_dunders.C-1>"
10341034
)
10351035
assert (
10361036
C.__eq__.__code__.co_filename
1037-
== "<attrs generated methods tests.test_dunders.C-2>"
1037+
== "<attrs generated methods tests.test_dunders.C-1>"
10381038
)
10391039
assert (
10401040
C.__hash__.__code__.co_filename
1041-
== "<attrs generated methods tests.test_dunders.C-2>"
1041+
== "<attrs generated methods tests.test_dunders.C-1>"
10421042
)

0 commit comments

Comments
 (0)