Skip to content

Commit 3d1dcd9

Browse files
committed
Ensure files are never leaked
Running tests warns that file descriptors are leaked and never closed. Ensure that all files are explicitly closed (using a context decorator whenever possible).
1 parent e1880b1 commit 3d1dcd9

File tree

3 files changed

+26
-16
lines changed

3 files changed

+26
-16
lines changed

django_afip/models.py

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -486,8 +486,11 @@ def certificate_object(self) -> X509 | None:
486486

487487
if not self.certificate:
488488
return None
489-
self.certificate.seek(0)
490-
return load_certificate(FILETYPE_PEM, self.certificate.read())
489+
if not self.certificate.closed:
490+
self.certificate.seek(0)
491+
return load_certificate(FILETYPE_PEM, self.certificate.read())
492+
with self.certificate.storage.open(self.certificate.name, "rb") as f:
493+
return load_certificate(FILETYPE_PEM, f.read())
491494

492495
def get_certificate_expiration(self) -> datetime | None:
493496
"""Return the certificate expiration from the current certificate
@@ -541,13 +544,14 @@ def generate_csr(self, basename: str = "djangoafip") -> BinaryIO:
541544
systems.
542545
"""
543546
csr = BytesIO()
544-
crypto.create_csr(
545-
self.key.file,
546-
self.name,
547-
f"{basename}{int(datetime.now().timestamp())}",
548-
f"CUIT {self.cuit}",
549-
csr,
550-
)
547+
with self.key.file.open("rb") as key_file:
548+
crypto.create_csr(
549+
key_file,
550+
self.name,
551+
f"{basename}{int(datetime.now().timestamp())}",
552+
f"CUIT {self.cuit}",
553+
csr,
554+
)
551555
csr.seek(0)
552556
return csr
553557

@@ -1658,6 +1662,7 @@ def save_pdf(
16581662
if save_model:
16591663
self.save()
16601664

1665+
16611666
class ReceiptEntry(models.Model):
16621667
"""An entry in a receipt.
16631668
@@ -1712,12 +1717,12 @@ class Meta:
17121717
constraints = (
17131718
CheckConstraint(
17141719
condition=Q(discount__gte=Decimal("0.0")),
1715-
name="discount_positive_value"
1720+
name="discount_positive_value",
17161721
),
17171722
CheckConstraint(
17181723
condition=Q(discount__lte=F("quantity") * F("unit_price")),
17191724
name="discount_less_than_total",
1720-
)
1725+
),
17211726
)
17221727

17231728
def __str__(self) -> str:

tests/test_admin.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,8 @@ def test_without_key(admin_client: Client) -> None:
9999
assertMessages(response, [Message(messages.SUCCESS, "Key generated successfully.")])
100100

101101
taxpayer.refresh_from_db()
102-
assert "-----BEGIN PRIVATE KEY-----" in taxpayer.key.file.read().decode()
102+
with taxpayer.key.file.open("rb") as f:
103+
assert "-----BEGIN PRIVATE KEY-----" in f.read().decode()
103104

104105

105106
def test_with_key(admin_client: Client) -> None:
@@ -119,7 +120,8 @@ def test_with_key(admin_client: Client) -> None:
119120
)
120121

121122
taxpayer.refresh_from_db()
122-
assert taxpayer.key.file.read().decode() == "Blah"
123+
with taxpayer.key.file.open("rb") as f:
124+
assert f.read().decode() == "Blah"
123125

124126

125127
def test_admin_taxpayer_request_generation_with_csr(admin_client: Client) -> None:

tests/test_taxpayer.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ def test_key_generation() -> None:
1515
taxpayer = factories.TaxPayerFactory.build(key=None)
1616
taxpayer.generate_key()
1717

18-
key = taxpayer.key.file.read().decode()
18+
with taxpayer.key.file.open("rb") as f:
19+
key = f.read().decode()
1920
assert key.splitlines()[0] == "-----BEGIN PRIVATE KEY-----"
2021
assert key.splitlines()[-1] == "-----END PRIVATE KEY-----"
2122

@@ -28,7 +29,8 @@ def test_dont_overwrite_keys() -> None:
2829
taxpayer = factories.TaxPayerFactory.build(key=FileField(data=text))
2930

3031
taxpayer.generate_key()
31-
key = taxpayer.key.read()
32+
with taxpayer.key.file.open("rb") as f:
33+
key = f.read()
3234

3335
assert text == key
3436

@@ -39,7 +41,8 @@ def test_overwrite_keys_force() -> None:
3941
taxpayer = factories.TaxPayerFactory.build(key__data=text)
4042

4143
taxpayer.generate_key(force=True)
42-
key = taxpayer.key.file.read().decode()
44+
with taxpayer.key.file.open("rb") as f:
45+
key = f.read().decode()
4346

4447
assert text != key
4548
assert key.splitlines()[0] == "-----BEGIN PRIVATE KEY-----"

0 commit comments

Comments
 (0)