Skip to content

Commit ae8d0a8

Browse files
committed
dependency updates
1 parent d907217 commit ae8d0a8

File tree

12 files changed

+103
-63
lines changed

12 files changed

+103
-63
lines changed

README.md

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,25 @@ The following features have not been implemented yet. PRs or notifications for d
2929

3030
You can install this package from PyPI
3131

32-
Install command assuming an active virtual environment:
32+
For example, using [`uv`](https://docs.astral.sh/uv/)
33+
34+
Setting up virtual environment:
35+
36+
```sh
37+
uv venv
38+
```
39+
40+
Regular install:
3341

3442
```sh
35-
pip install cfdp-py
43+
uv pip install -e .
3644
```
3745

46+
Interactive install with testing support:
47+
48+
```sh
49+
uv pip install -e ".[test]"
50+
```
3851

3952
# Examples
4053

@@ -47,14 +60,13 @@ If you want to run the tests, it is recommended to install `pytest` and `coverag
4760
first. You also have to install the package with the optional `test` feature:
4861

4962
```sh
50-
pip install coverage pytest
51-
pip install cfdp-py[test]
63+
uv pip install -e ".[test]"
5264
```
5365

5466
Running tests regularly:
5567

5668
```sh
57-
pytest .
69+
pytest
5870
```
5971

6072
Running tests with coverage:
@@ -91,11 +103,11 @@ make doctest
91103
Linting:
92104

93105
```sh
94-
ruff check .
106+
ruff check
95107
```
96108

97109
Formatting:
98110

99111
```sh
100-
ruff format .
112+
ruff format
101113
```

docs/conf.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@
6464
intersphinx_mapping = {
6565
"python": ("https://docs.python.org/3", None),
6666
"spacepackets": ("https://spacepackets.readthedocs.io/en/latest/", None),
67-
"crcmod": ("https://crcmod.sourceforge.net/", None),
67+
"fastcrc": ("https://fastcrc.readthedocs.io/en/latest/", None),
6868
}
6969

7070
# -- Options for HTML output -------------------------------------------------
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
11
cfdp @ git+https://gitlab.com/librecube/lib/python-cfdp.git
2+
# Install local cfdp-py interactively
3+
-e ../..

justfile

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# Run with `just all`
2-
all: fmt check test
2+
all: fmt check coverage
3+
4+
setup:
5+
uv venv
6+
7+
install:
8+
uv pip install -e ".[test]"
39

410
fmt:
511
ruff format
@@ -9,3 +15,7 @@ check:
915

1016
test:
1117
pytest
18+
19+
coverage:
20+
coverage run -m pytest
21+
coverage report

pyproject.toml

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,16 @@ classifiers = [
2727
"Topic :: Scientific/Engineering"
2828
]
2929
dependencies = [
30-
"spacepackets>=0.26.0, <=0.28",
31-
"crcmod~=1.7",
30+
"spacepackets>=0.30,<0.32",
31+
"fastcrc~=0.3",
3232
"deprecation~=2.1",
3333
]
3434

3535
[project.optional-dependencies]
3636
test = [
37-
"pyfakefs~=5.2"
37+
"pyfakefs~=5.2",
38+
"pytest",
39+
"coverage"
3840
]
3941
lint = ["ruff"]
4042

src/cfdppy/filestore.py

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,11 @@
77
import os
88
import platform
99
import shutil
10+
import struct
1011
import subprocess
1112
from typing import TYPE_CHECKING, BinaryIO
1213

13-
from crcmod.predefined import PredefinedCrc
14+
import fastcrc
1415
from spacepackets.cfdp.defs import NULL_CHECKSUM_U32, ChecksumType
1516
from spacepackets.cfdp.tlv import FilestoreResponseStatusCode
1617

@@ -351,9 +352,12 @@ def checksum_type_to_crcmod_str(self, checksum_type: ChecksumType) -> str | None
351352
return "crc32c"
352353
raise ChecksumNotImplemented(checksum_type)
353354

355+
"""
356+
354357
def _generate_crc_calculator(self, checksum_type: ChecksumType) -> PredefinedCrc:
355358
self._verify_checksum(checksum_type)
356359
return PredefinedCrc(self.checksum_type_to_crcmod_str(checksum_type))
360+
"""
357361

358362
def calculate_checksum(
359363
self,
@@ -370,16 +374,26 @@ def calculate_checksum(
370374
return calc_modular_checksum(file_path)
371375
if segment_len == 0:
372376
raise ValueError("segment length can not be 0")
373-
crc_obj = self._generate_crc_calculator(checksum_type)
377+
func = None
378+
if checksum_type == ChecksumType.CRC_32:
379+
func = fastcrc.crc32.iso_hdlc
380+
elif checksum_type == ChecksumType.CRC_32C:
381+
func = fastcrc.crc32.iscsi
382+
else:
383+
raise ChecksumNotImplemented(checksum_type)
384+
current = func(b"")
374385
current_offset = 0
375386
# Calculate the file CRC
376387
with open(file_path, "rb") as file:
377388
while current_offset < size_to_verify:
378389
read_len = min(segment_len, size_to_verify - current_offset)
379390
if read_len > 0:
380-
crc_obj.update(self.read_from_opened_file(file, current_offset, read_len))
391+
current = func(
392+
self.read_from_opened_file(file, current_offset, read_len), current
393+
)
381394
current_offset += read_len
382-
return crc_obj.digest()
395+
assert current is not None
396+
return struct.pack("!I", current)
383397

384398

385399
HostFilestore = NativeFilestore

src/cfdppy/restricted_filestore.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,12 +133,14 @@ def calculate_checksum(
133133

134134
def verify_checksum(
135135
self,
136-
checksum: bytes,
136+
checksum: int | bytes,
137137
checksum_type: ChecksumType,
138138
file_path: Path,
139139
size_to_verify: int,
140140
segment_len: int = 4096,
141141
) -> bool:
142+
if isinstance(checksum, int):
143+
checksum = checksum.to_bytes(4, "big")
142144
"""Verify checksum of file."""
143145
return super().verify_checksum(
144146
checksum=checksum,

tests/test_dest_handler.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,7 @@ def _insert_file_segment(
224224
)
225225
return fsm_res
226226

227-
def _generic_insert_eof_pdu(self, file_size: int, checksum: bytes) -> FsmResult:
227+
def _generic_insert_eof_pdu(self, file_size: int, checksum: int | bytes) -> FsmResult:
228228
eof_pdu = EofPdu(file_size=file_size, file_checksum=checksum, pdu_conf=self.src_pdu_conf)
229229
fsm_res = self.dest_handler.state_machine(eof_pdu)
230230
if self.expected_mode == TransmissionMode.UNACKNOWLEDGED:

tests/test_dest_handler_acked.py

Lines changed: 28 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import struct
22
import time
33

4+
import fastcrc
45
from spacepackets.cfdp import (
56
NULL_CHECKSUM_U32,
67
ConditionCode,
@@ -18,7 +19,6 @@
1819
FinishedPdu,
1920
TransactionStatus,
2021
)
21-
from spacepackets.crc import mkPredefinedCrcFun
2222

2323
from cfdppy.defs import CfdpState
2424
from cfdppy.handler.dest import FsmResult, TransactionStep
@@ -45,12 +45,12 @@ def test_acked_small_file_transfer(self):
4545
file_content = b"Hello World!"
4646
with open(self.src_file_path, "wb") as of:
4747
of.write(file_content)
48-
crc32_func = mkPredefinedCrcFun("crc32")
49-
crc32 = struct.pack("!I", crc32_func(file_content))
48+
crc32 = fastcrc.crc32.iso_hdlc(file_content)
49+
crc32_bytes = struct.pack("!I", crc32)
5050
# Basic acknowledged empty file transfer.
5151
self._generic_regular_transfer_init(len(file_content))
5252
self._insert_file_segment(file_content, 0)
53-
fsm_res = self._generic_insert_eof_pdu(len(file_content), crc32)
53+
fsm_res = self._generic_insert_eof_pdu(len(file_content), crc32_bytes)
5454
self._generic_eof_recv_indication_check(fsm_res)
5555
self._generic_verify_eof_ack_packet(fsm_res, TransactionStep.WAITING_FOR_FINISHED_ACK)
5656
finished_pdu = self._generic_no_error_finished_pdu_check_acked(fsm_res)
@@ -99,11 +99,11 @@ def test_deferred_missing_file_segment_handling(self):
9999
file_content = b"Hello World!"
100100
with open(self.src_file_path, "wb") as of:
101101
of.write(file_content)
102-
crc32_func = mkPredefinedCrcFun("crc32")
103-
crc32 = struct.pack("!I", crc32_func(file_content))
102+
crc32 = fastcrc.crc32.iso_hdlc(file_content)
103+
crc32_bytes = struct.pack("!I", crc32)
104104
self._generic_regular_transfer_init(len(file_content))
105105
self._insert_file_segment(file_content[0:5], 0)
106-
fsm_res = self._generic_insert_eof_pdu(len(file_content), crc32)
106+
fsm_res = self._generic_insert_eof_pdu(len(file_content), crc32_bytes)
107107
self._generic_eof_recv_indication_check(fsm_res)
108108
self._generic_verify_eof_ack_packet(fsm_res, TransactionStep.WAITING_FOR_MISSING_DATA)
109109
self._state_checker(fsm_res, 1, CfdpState.BUSY, TransactionStep.WAITING_FOR_MISSING_DATA)
@@ -126,8 +126,8 @@ def test_immediate_missing_file_seg_handling_0(self):
126126
file_content = b"Hello World!"
127127
with open(self.src_file_path, "wb") as of:
128128
of.write(file_content)
129-
crc32_func = mkPredefinedCrcFun("crc32")
130-
crc32 = struct.pack("!I", crc32_func(file_content))
129+
crc32 = fastcrc.crc32.iso_hdlc(file_content)
130+
crc32_bytes = struct.pack("!I", crc32)
131131
self._generic_regular_transfer_init(len(file_content))
132132
# A middle segment is missing now, with the expected lost segment tuple to be (3, 6). The
133133
# lost segment is immediately supplied.
@@ -137,7 +137,7 @@ def test_immediate_missing_file_seg_handling_0(self):
137137
# Insert the missing file content.
138138
self._insert_file_segment(file_content[3:6], 3, expected_progress=12)
139139
# All lost segments were delivered, regular transfer finish.
140-
fsm_res = self._generic_insert_eof_pdu(len(file_content), crc32)
140+
fsm_res = self._generic_insert_eof_pdu(len(file_content), crc32_bytes)
141141
self._generic_eof_recv_indication_check(fsm_res)
142142
self._generic_verify_eof_ack_packet(fsm_res, TransactionStep.WAITING_FOR_FINISHED_ACK)
143143
finished_pdu = self._generic_no_error_finished_pdu_check_acked(fsm_res)
@@ -148,8 +148,8 @@ def test_immediate_missing_file_seg_handling_1(self):
148148
file_content = b"Hello World!"
149149
with open(self.src_file_path, "wb") as of:
150150
of.write(file_content)
151-
crc32_func = mkPredefinedCrcFun("crc32")
152-
crc32 = struct.pack("!I", crc32_func(file_content))
151+
crc32 = fastcrc.crc32.iso_hdlc(file_content)
152+
crc32_bytes = struct.pack("!I", crc32)
153153
self._generic_regular_transfer_init(len(file_content))
154154
# Simulate the second segment being lost, with more than one segment following after that.
155155
self._insert_file_segment(file_content[0:2], 0)
@@ -160,7 +160,7 @@ def test_immediate_missing_file_seg_handling_1(self):
160160
# Now insert the missing segment.
161161
self._insert_file_segment(file_content[2:4], 2, expected_progress=12)
162162
# All lost segments were delivered, regular transfer finish.
163-
fsm_res = self._generic_insert_eof_pdu(len(file_content), crc32)
163+
fsm_res = self._generic_insert_eof_pdu(len(file_content), crc32_bytes)
164164
self._generic_eof_recv_indication_check(fsm_res)
165165
self._generic_verify_eof_ack_packet(fsm_res, TransactionStep.WAITING_FOR_FINISHED_ACK)
166166
finished_pdu = self._generic_no_error_finished_pdu_check_acked(fsm_res)
@@ -171,8 +171,8 @@ def test_immediate_multi_missing_segment_handling(self):
171171
file_content = b"Hello World!"
172172
with open(self.src_file_path, "wb") as of:
173173
of.write(file_content)
174-
crc32_func = mkPredefinedCrcFun("crc32")
175-
crc32 = struct.pack("!I", crc32_func(file_content))
174+
crc32 = fastcrc.crc32.iso_hdlc(file_content)
175+
crc32_bytes = struct.pack("!I", crc32)
176176
self._generic_regular_transfer_init(len(file_content))
177177
self._insert_file_segment(file_content[0:2], 0)
178178
self._insert_file_segment(file_content[4:6], 4, 1)
@@ -187,7 +187,7 @@ def test_immediate_multi_missing_segment_handling(self):
187187
self._insert_file_segment(file_content[2:4], 2, expected_progress=12)
188188
self._insert_file_segment(file_content[6:8], 6, expected_progress=12)
189189
# All lost segments were delivered, regular transfer finish.
190-
fsm_res = self._generic_insert_eof_pdu(len(file_content), crc32)
190+
fsm_res = self._generic_insert_eof_pdu(len(file_content), crc32_bytes)
191191
self._generic_eof_recv_indication_check(fsm_res)
192192
self._generic_verify_eof_ack_packet(fsm_res, TransactionStep.WAITING_FOR_FINISHED_ACK)
193193
finished_pdu = self._generic_no_error_finished_pdu_check_acked(fsm_res)
@@ -198,8 +198,8 @@ def test_immediate_missing_segment_also_rerequested_after_eof(self):
198198
file_content = b"Hello World!"
199199
with open(self.src_file_path, "wb") as of:
200200
of.write(file_content)
201-
crc32_func = mkPredefinedCrcFun("crc32")
202-
crc32 = struct.pack("!I", crc32_func(file_content))
201+
crc32 = fastcrc.crc32.iso_hdlc(file_content)
202+
crc32_bytes = struct.pack("!I", crc32)
203203
self._generic_regular_transfer_init(len(file_content))
204204
# Missing middle segment
205205
self._insert_file_segment(file_content[0:2], 0)
@@ -208,7 +208,7 @@ def test_immediate_missing_segment_also_rerequested_after_eof(self):
208208
self._generic_verify_missing_segment_requested(0, len(file_content), [(2, 6)])
209209

210210
# All lost segments were delivered, regular transfer finish.
211-
fsm_res = self._generic_insert_eof_pdu(len(file_content), crc32)
211+
fsm_res = self._generic_insert_eof_pdu(len(file_content), crc32_bytes)
212212
self._generic_eof_recv_indication_check(fsm_res)
213213
self._generic_verify_eof_ack_packet(fsm_res, TransactionStep.WAITING_FOR_MISSING_DATA)
214214
self._state_checker(fsm_res, 1, CfdpState.BUSY, TransactionStep.WAITING_FOR_MISSING_DATA)
@@ -230,8 +230,8 @@ def test_multi_segment_missing_deferred_handling(self):
230230
file_content = b"Hello World!"
231231
with open(self.src_file_path, "wb") as of:
232232
of.write(file_content)
233-
crc32_func = mkPredefinedCrcFun("crc32")
234-
crc32 = struct.pack("!I", crc32_func(file_content))
233+
crc32 = fastcrc.crc32.iso_hdlc(file_content)
234+
crc32_bytes = struct.pack("!I", crc32)
235235
self._generic_regular_transfer_init(len(file_content))
236236
self._insert_file_segment(file_content[0:2], 0)
237237
self._insert_file_segment(file_content[4:6], 4, 1)
@@ -242,7 +242,7 @@ def test_multi_segment_missing_deferred_handling(self):
242242
self._insert_file_segment(file_content[8:], 8, 1)
243243
self._generic_verify_missing_segment_requested(0, len(file_content), [(6, 8)])
244244

245-
fsm_res = self._generic_insert_eof_pdu(len(file_content), crc32)
245+
fsm_res = self._generic_insert_eof_pdu(len(file_content), crc32_bytes)
246246
self._generic_eof_recv_indication_check(fsm_res)
247247
self._generic_verify_eof_ack_packet(fsm_res, TransactionStep.WAITING_FOR_MISSING_DATA)
248248
self._state_checker(fsm_res, 1, CfdpState.BUSY, TransactionStep.WAITING_FOR_MISSING_DATA)
@@ -274,8 +274,8 @@ def test_missing_metadata_pdu(self):
274274
file_content = b"Hello World!"
275275
with open(self.src_file_path, "wb") as of:
276276
of.write(file_content)
277-
crc32_func = mkPredefinedCrcFun("crc32")
278-
crc32 = struct.pack("!I", crc32_func(file_content))
277+
crc32 = fastcrc.crc32.iso_hdlc(file_content)
278+
crc32_bytes = struct.pack("!I", crc32)
279279
self._insert_file_segment(
280280
file_content[0:2],
281281
0,
@@ -308,7 +308,7 @@ def test_missing_metadata_pdu(self):
308308
2,
309309
)
310310
# All lost segments were delivered, regular transfer finish.
311-
fsm_res = self._generic_insert_eof_pdu(len(file_content), crc32)
311+
fsm_res = self._generic_insert_eof_pdu(len(file_content), crc32_bytes)
312312
self._generic_eof_recv_indication_check(fsm_res)
313313
self._generic_verify_eof_ack_packet(fsm_res, TransactionStep.WAITING_FOR_FINISHED_ACK)
314314
finished_pdu = self._generic_no_error_finished_pdu_check_acked(fsm_res)
@@ -337,8 +337,8 @@ def test_metadata_eof_only_missing_metadata(self):
337337
def _generic_deferred_lost_segment_handling_with_timeout(self, file_content: bytes):
338338
with open(self.src_file_path, "wb") as of:
339339
of.write(file_content)
340-
crc32_func = mkPredefinedCrcFun("crc32")
341-
crc32 = struct.pack("!I", crc32_func(file_content))
340+
crc32 = fastcrc.crc32.iso_hdlc(file_content)
341+
crc32_bytes = struct.pack("!I", crc32)
342342
self._generic_regular_transfer_init(len(file_content))
343343
self._insert_file_segment(file_content[0:2], 0)
344344
self._insert_file_segment(file_content[4:6], 4, 1)
@@ -350,7 +350,7 @@ def _generic_deferred_lost_segment_handling_with_timeout(self, file_content: byt
350350
self._generic_verify_missing_segment_requested(0, len(file_content), [(6, 8)])
351351

352352
# This should trigger deferred EOF handling.
353-
fsm_res = self._generic_insert_eof_pdu(len(file_content), crc32)
353+
fsm_res = self._generic_insert_eof_pdu(len(file_content), crc32_bytes)
354354
self._generic_eof_recv_indication_check(fsm_res)
355355
self._generic_verify_eof_ack_packet(fsm_res, TransactionStep.WAITING_FOR_MISSING_DATA)
356356
self._state_checker(fsm_res, 1, CfdpState.BUSY, TransactionStep.WAITING_FOR_MISSING_DATA)

0 commit comments

Comments
 (0)