Skip to content

Commit b2bbffc

Browse files
Ruff cleanup: enforce PLW2901 (no loop/context var overwrite)
1 parent 3b5c85f commit b2bbffc

File tree

13 files changed

+80
-75
lines changed

13 files changed

+80
-75
lines changed

pypdf/_cmap.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -460,11 +460,11 @@ def build_font_width_map(
460460
# will consider width of char as avg(width)
461461
m = 0
462462
cpt = 0
463-
for xx in w:
464-
xx = xx.get_object()
465-
if xx > 0:
466-
m += xx
467-
cpt += 1
463+
for xx in w:
464+
xx_val = xx.get_object()
465+
if xx_val > 0:
466+
m += xx_val
467+
cpt += 1
468468
font_width_map["default"] = m / max(1, cpt)
469469
st = cast(int, ft["/FirstChar"])
470470
en = cast(int, ft["/LastChar"])

pypdf/_doc_common.py

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -391,8 +391,8 @@ def recursive_call(
391391
return top, -1
392392
return None, mi + ma
393393
for idx, kid in enumerate(cast(ArrayObject, node["/Kids"])):
394-
kid = cast(DictionaryObject, kid.get_object())
395-
n, i = recursive_call(kid, mi)
394+
kid_obj = cast(DictionaryObject, kid.get_object())
395+
n, i = recursive_call(kid_obj, mi)
396396
if n is not None: # page has just been found ...
397397
if i < 0: # ... just below!
398398
return node, idx
@@ -612,8 +612,8 @@ def _build_field(
612612
states: list[str] = []
613613
retval[key][NameObject("/_States_")] = ArrayObject(states)
614614
for k in obj.get(FA.Kids, {}):
615-
k = k.get_object()
616-
for s in list(k["/AP"]["/N"].keys()):
615+
k_obj = k.get_object()
616+
for s in list(k_obj["/AP"]["/N"].keys()):
617617
if s not in states:
618618
states.append(s)
619619
retval[key][NameObject("/_States_")] = ArrayObject(states)
@@ -641,8 +641,8 @@ def _check_kids(
641641
if PagesAttributes.KIDS in tree:
642642
# recurse down the tree
643643
for kid in tree[PagesAttributes.KIDS]: # type: ignore
644-
kid = kid.get_object()
645-
self.get_fields(kid, retval, fileobj, stack)
644+
kid_obj = kid.get_object()
645+
self.get_fields(kid_obj, retval, fileobj, stack)
646646

647647
def _write_field(self, fileobj: Any, field: Any, field_attributes: Any) -> None:
648648
field_attributes_tuple = FA.attributes()
@@ -771,16 +771,16 @@ def _get_inherited(obj: DictionaryObject, key: str) -> Any:
771771
else:
772772
kids = field.get("/Kids", ())
773773
for k in kids:
774-
k = k.get_object()
775-
if (k.get("/Subtype", "") == "/Widget") and ("/T" not in k):
774+
k_obj = k.get_object()
775+
if (k_obj.get("/Subtype", "") == "/Widget") and ("/T" not in k_obj):
776776
# Kid that is just a widget, not a field:
777-
if "/P" in k:
778-
ret += [k["/P"].get_object()]
777+
if "/P" in k_obj:
778+
ret += [k_obj["/P"].get_object()]
779779
else:
780780
ret += [
781781
p
782782
for p in self.pages
783-
if k.indirect_reference in p.get("/Annots", "")
783+
if k_obj.indirect_reference in p.get("/Annots", "")
784784
]
785785
return [
786786
x
@@ -1317,9 +1317,9 @@ def xfa(self) -> Optional[dict[str, Any]]:
13171317
i = iter(fields)
13181318
for f in i:
13191319
tag = f
1320-
f = next(i)
1321-
if isinstance(f, IndirectObject):
1322-
field = cast(Optional[EncodedStreamObject], f.get_object())
1320+
f_val = next(i)
1321+
if isinstance(f_val, IndirectObject):
1322+
field = cast(Optional[EncodedStreamObject], f_val.get_object())
13231323
if field:
13241324
es = zlib.decompress(field._data)
13251325
retval[tag] = es

pypdf/_page.py

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -740,14 +740,14 @@ def _get_inline_images(self) -> dict[str, ImageFile]:
740740
if k in {"/Length", "/L"}: # no length is expected
741741
continue
742742
if isinstance(v, list):
743-
v = ArrayObject(
743+
translated_v = ArrayObject(
744744
[self._translate_value_inline_image(k, x) for x in v]
745745
)
746746
else:
747-
v = self._translate_value_inline_image(k, v)
748-
k = NameObject(_INLINE_IMAGE_KEY_MAPPING[k])
749-
if k not in init:
750-
init[k] = v
747+
translated_v = self._translate_value_inline_image(k, v)
748+
mapped_k = NameObject(_INLINE_IMAGE_KEY_MAPPING[k])
749+
if mapped_k not in init:
750+
init[mapped_k] = translated_v
751751
ii["object"] = EncodedStreamObject.initialize_from_dictionary(init)
752752
extension, byte_stream, img = _xobj_to_image(ii["object"])
753753
files[f"~{num}~"] = ImageFile(
@@ -1231,13 +1231,13 @@ def _merge_page_writer(
12311231
else:
12321232
trsf = Transformation(ctm)
12331233
for a in cast(ArrayObject, page2[PG.ANNOTS]):
1234-
a = a.get_object()
1235-
aa = a.clone(
1234+
a_obj = a.get_object()
1235+
aa = a_obj.clone(
12361236
pdf,
12371237
ignore_fields=("/P", "/StructParent", "/Parent"),
12381238
force_duplicate=True,
12391239
)
1240-
r = cast(ArrayObject, a["/Rect"])
1240+
r = cast(ArrayObject, a_obj["/Rect"])
12411241
pt1 = trsf.apply_on((r[0], r[1]), True)
12421242
pt2 = trsf.apply_on((r[2], r[3]), True)
12431243
aa[NameObject("/Rect")] = ArrayObject(
@@ -1248,8 +1248,8 @@ def _merge_page_writer(
12481248
max(pt1[1], pt2[1]),
12491249
)
12501250
)
1251-
if "/QuadPoints" in a:
1252-
q = cast(ArrayObject, a["/QuadPoints"])
1251+
if "/QuadPoints" in a_obj:
1252+
q = cast(ArrayObject, a_obj["/QuadPoints"])
12531253
aa[NameObject("/QuadPoints")] = ArrayObject(
12541254
trsf.apply_on((q[0], q[1]), True)
12551255
+ trsf.apply_on((q[2], q[3]), True)

pypdf/_text_extraction/_layout_mode/_fixed_width_page.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -191,8 +191,10 @@ def recurs_to_target_op(
191191
elif op == b"TD":
192192
text_state_mgr.set_state_param(b"TL", -operands[1])
193193
elif op == b"T*":
194-
operands = [0, -text_state_mgr.TL]
195-
text_state_mgr.add_tm(operands)
194+
operands_for_tm = [0, -text_state_mgr.TL]
195+
else:
196+
operands_for_tm = operands
197+
text_state_mgr.add_tm(operands_for_tm)
196198
elif op == b"Tf":
197199
text_state_mgr.set_font(fonts[operands[0]], operands[1])
198200
else: # handle Tc, Tw, Tz, TL, and Ts operators

pypdf/_text_extraction/_layout_mode/_font.py

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,10 @@ def __post_init__(self) -> None:
6464
for d_font_idx, d_font in enumerate(
6565
self.font_dictionary["/DescendantFonts"]
6666
):
67-
while isinstance(d_font, IndirectObject):
68-
d_font = d_font.get_object()
69-
self.font_dictionary["/DescendantFonts"][d_font_idx] = d_font
67+
d_font_val = d_font
68+
while isinstance(d_font_val, IndirectObject):
69+
d_font_val = d_font_val.get_object()
70+
self.font_dictionary["/DescendantFonts"][d_font_idx] = d_font_val
7071
ord_map = {
7172
ord(_target): _surrogate
7273
for _target, _surrogate in self.char_map.items()
@@ -80,18 +81,18 @@ def __post_init__(self) -> None:
8081
skip_count = 0
8182
_w = d_font.get("/W", [])
8283
for idx, w_entry in enumerate(_w):
83-
w_entry = w_entry.get_object()
84+
w_val = w_entry.get_object()
8485
if skip_count:
8586
skip_count -= 1
8687
continue
87-
if not isinstance(w_entry, (int, float)): # pragma: no cover
88+
if not isinstance(w_val, (int, float)): # pragma: no cover
8889
# We should never get here due to skip_count above. Add a
8990
# warning and or use reader's "strict" to force an ex???
9091
continue
9192
# check for format (1): `int [int int int int ...]`
9293
w_next_entry = _w[idx + 1].get_object()
9394
if isinstance(w_next_entry, Sequence):
94-
start_idx, width_list = w_entry, w_next_entry
95+
start_idx, width_list = w_val, w_next_entry
9596
self.width_map.update(
9697
{
9798
ord_map[_cidx]: _width
@@ -112,7 +113,7 @@ def __post_init__(self) -> None:
112113
_w[idx + 2].get_object(), (int, float)
113114
):
114115
start_idx, stop_idx, const_width = (
115-
w_entry,
116+
w_val,
116117
w_next_entry,
117118
_w[idx + 2].get_object(),
118119
)

pypdf/_writer.py

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -979,13 +979,13 @@ def update_page_form_field_values(
979979
logger_warning("No fields to update on this page", __name__)
980980
return
981981
for annotation in page[PG.ANNOTS]: # type: ignore
982-
annotation = cast(DictionaryObject, annotation.get_object())
983-
if annotation.get("/Subtype", "") != "/Widget":
982+
annotation_obj = cast(DictionaryObject, annotation.get_object())
983+
if annotation_obj.get("/Subtype", "") != "/Widget":
984984
continue
985-
if "/FT" in annotation and "/T" in annotation:
986-
parent_annotation = annotation
985+
if "/FT" in annotation_obj and "/T" in annotation_obj:
986+
parent_annotation = annotation_obj
987987
else:
988-
parent_annotation = annotation.get(
988+
parent_annotation = annotation_obj.get(
989989
PG.PARENT, DictionaryObject()
990990
).get_object()
991991

@@ -1098,17 +1098,17 @@ def reattach_fields(
10981098
annotations = cast(ArrayObject, page["/Annots"])
10991099
for idx, annotation in enumerate(annotations):
11001100
is_indirect = isinstance(annotation, IndirectObject)
1101-
annotation = cast(DictionaryObject, annotation.get_object())
1102-
if annotation.get("/Subtype", "") == "/Widget" and "/FT" in annotation:
1101+
annotation_obj = cast(DictionaryObject, annotation.get_object())
1102+
if annotation_obj.get("/Subtype", "") == "/Widget" and "/FT" in annotation_obj:
11031103
if (
1104-
"indirect_reference" in annotation.__dict__
1105-
and annotation.indirect_reference in fields
1104+
"indirect_reference" in annotation_obj.__dict__
1105+
and annotation_obj.indirect_reference in fields
11061106
):
11071107
continue
11081108
if not is_indirect:
1109-
annotations[idx] = self._add_object(annotation)
1110-
fields.append(annotation.indirect_reference)
1111-
lst.append(annotation)
1109+
annotations[idx] = self._add_object(annotation_obj)
1110+
fields.append(annotation_obj.indirect_reference)
1111+
lst.append(annotation_obj)
11121112
return lst
11131113

11141114
def clone_reader_document_root(self, reader: PdfReader) -> None:
@@ -1469,8 +1469,10 @@ def _write_pdf_structure(self, stream: StreamType) -> tuple[list[int], list[int]
14691469
object_positions.append(stream.tell())
14701470
stream.write(f"{idnum} 0 obj\n".encode())
14711471
if self._encryption and obj != self._encrypt_entry:
1472-
obj = self._encryption.encrypt_object(obj, idnum, 0)
1473-
obj.write_to_stream(stream)
1472+
obj_to_write = self._encryption.encrypt_object(obj, idnum, 0)
1473+
else:
1474+
obj_to_write = obj
1475+
obj_to_write.write_to_stream(stream)
14741476
stream.write(b"\nendobj\n")
14751477
else:
14761478
object_positions.append(-1)
@@ -1560,8 +1562,10 @@ def add_metadata(self, infos: dict[str, Any]) -> None:
15601562
infos = cast(DictionaryObject, infos.get_object())
15611563
for key, value in list(infos.items()):
15621564
if isinstance(value, PdfObject):
1563-
value = value.get_object()
1564-
args[NameObject(key)] = create_string_object(str(value))
1565+
value_obj = value.get_object()
1566+
else:
1567+
value_obj = value
1568+
args[NameObject(key)] = create_string_object(str(value_obj))
15651569
if self._info is None:
15661570
self._info = DictionaryObject()
15671571
self._info.update(args)

pypdf/filters.py

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -760,27 +760,26 @@ def decode_stream_data(stream: Any) -> bytes:
760760
if not data:
761761
return data
762762
for filter_name, params in zip(filters, decode_parms):
763-
if isinstance(params, NullObject):
764-
params = {}
763+
params_obj = {} if isinstance(params, NullObject) else params
765764
if filter_name in (FT.ASCII_HEX_DECODE, FTA.AHx):
766765
data = ASCIIHexDecode.decode(data)
767766
elif filter_name in (FT.ASCII_85_DECODE, FTA.A85):
768767
data = ASCII85Decode.decode(data)
769768
elif filter_name in (FT.LZW_DECODE, FTA.LZW):
770-
data = LZWDecode.decode(data, params)
769+
data = LZWDecode.decode(data, params_obj)
771770
elif filter_name in (FT.FLATE_DECODE, FTA.FL):
772-
data = FlateDecode.decode(data, params)
771+
data = FlateDecode.decode(data, params_obj)
773772
elif filter_name in (FT.RUN_LENGTH_DECODE, FTA.RL):
774773
data = RunLengthDecode.decode(data)
775774
elif filter_name == FT.CCITT_FAX_DECODE:
776775
height = stream.get(IA.HEIGHT, ())
777-
data = CCITTFaxDecode.decode(data, params, height)
776+
data = CCITTFaxDecode.decode(data, params_obj, height)
778777
elif filter_name == FT.DCT_DECODE:
779778
data = DCTDecode.decode(data)
780779
elif filter_name == FT.JPX_DECODE:
781780
data = JPXDecode.decode(data)
782781
elif filter_name == FT.JBIG2_DECODE:
783-
data = JBIG2Decode.decode(data, params)
782+
data = JBIG2Decode.decode(data, params_obj)
784783
elif filter_name == "/Crypt":
785784
if "/Name" in params or "/Type" in params:
786785
raise NotImplementedError(

pypdf/generic/_files.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -394,8 +394,8 @@ def _load(cls, catalog: DictionaryObject) -> Generator[EmbeddedFile]:
394394
for kid in cast(ArrayObject, container["/Kids"].get_object()):
395395
# There might be further (nested) kids here.
396396
# Wait for an example before evaluating an implementation.
397-
kid = kid.get_object()
398-
if "/Names" in kid:
399-
yield from cls._load_from_names(cast(ArrayObject, kid["/Names"]))
397+
kid_obj = kid.get_object()
398+
if "/Names" in kid_obj:
399+
yield from cls._load_from_names(cast(ArrayObject, kid_obj["/Names"]))
400400
if "/Names" in container:
401401
yield from cls._load_from_names(cast(ArrayObject, container["/Names"]))

pyproject.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,6 @@ ignore = [
173173
"PERF203", # `try`-`except` within a loop incurs performance overhead
174174
"PGH003", # Use specific rule codes when ignoring type issues
175175
"PLW1510", # `subprocess.run` without explicit `check` argument
176-
"PLW2901", # `with` statement variable `img` overwritten by assignment target
177176
"PT011", # `pytest.raises(ValueError)` is too broad, set the `match`
178177
"PT012", # `pytest.raises()` block should contain a single simple statement
179178
"PT014", # Ruff bug: Duplicate of test case at index 1 in `@pytest_mark.parametrize`

tests/scripts/test_make_release.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,11 +41,11 @@ def test_strip_header(data, expected):
4141
def test_get_git_commits_since_tag():
4242
make_release = pytest.importorskip("make_release")
4343

44-
with open(COMMITS__VERSION_4_0_1, mode="rb") as commits, mock.patch(
45-
"urllib.request.urlopen", side_effect=lambda _: commits
44+
with open(COMMITS__VERSION_4_0_1, mode="rb") as commits_fh, mock.patch(
45+
"urllib.request.urlopen", side_effect=lambda _: commits_fh
4646
), mock.patch("subprocess.check_output", return_value=GIT_LOG__VERSION_4_0_1):
47-
commits = make_release.get_git_commits_since_tag("4.0.1")
48-
assert commits == [
47+
commits_list = make_release.get_git_commits_since_tag("4.0.1")
48+
assert commits_list == [
4949
make_release.Change(
5050
commit_hash="b7bfd0d7eddfd0865a94cc9e7027df6596242cf7",
5151
prefix="BUG",

0 commit comments

Comments
 (0)