Skip to content

Commit 47ad9bf

Browse files
authored
Implement __slots__ (#30)
* Fix #25 * Bump version * Force unbuffered * Review feedback * Add missing __slots__
1 parent d965cca commit 47ad9bf

13 files changed

Lines changed: 173 additions & 9 deletions

File tree

.github/workflows/build.yaml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ jobs:
3232
run: pip install emake
3333
- name: Run lint
3434
run: emake lint
35+
env:
36+
PYTHONUNBUFFERED: "1"
3537

3638
test-image:
3739
name: Generate test ext4 image
@@ -49,6 +51,8 @@ jobs:
4951
run: |
5052
set -e
5153
./_test_image.sh
54+
env:
55+
PYTHONUNBUFFERED: "1"
5256
- uses: actions/upload-artifact@v6
5357
with:
5458
name: test.ext4
@@ -88,6 +92,8 @@ jobs:
8892
- name: Run tests
8993
shell: bash
9094
run: emake test
95+
env:
96+
PYTHONUNBUFFERED: "1"
9197

9298
fuzz:
9399
name: Fuzz
@@ -112,6 +118,8 @@ jobs:
112118
- name: Run test
113119
shell: bash
114120
run: make fuzz
121+
env:
122+
PYTHONUNBUFFERED: "1"
115123

116124
build-sdist:
117125
name: Build sdist
@@ -125,6 +133,8 @@ jobs:
125133
- *install-emake
126134
- name: Building sdist
127135
run: emake build --sdist
136+
env:
137+
PYTHONUNBUFFERED: "1"
128138
- uses: actions/upload-artifact@v6
129139
with:
130140
name: pip-sdist
@@ -148,6 +158,8 @@ jobs:
148158
path: .
149159
- name: Test wheel
150160
run: emake test --wheel
161+
env:
162+
PYTHONUNBUFFERED: "1"
151163
- uses: actions/upload-artifact@v6
152164
with:
153165
name: pip-wheel-none-any
@@ -188,6 +200,8 @@ jobs:
188200
--arch ${{ matrix.arch }} \
189201
--libc ${{ matrix.libc }} \
190202
--python ${{ matrix.python }}
203+
env:
204+
PYTHONUNBUFFERED: "1"
191205
- name: Download test.ext4
192206
uses: actions/download-artifact@v8
193207
with:
@@ -200,6 +214,8 @@ jobs:
200214
--arch ${{ matrix.arch }} \
201215
--libc ${{ matrix.libc }} \
202216
--python ${{ matrix.python }}
217+
env:
218+
PYTHONUNBUFFERED: "1"
203219
- uses: actions/upload-artifact@v6
204220
with:
205221
name: pip-wheel-${{ matrix.python }}-${{ matrix.arch }}-${{ matrix.libc }}

ext4/block.py

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
import errno
22
import io
33
import os
4-
from typing import TYPE_CHECKING
4+
from typing import (
5+
TYPE_CHECKING,
6+
final,
7+
)
58

69
from ._compat import override
710

@@ -11,7 +14,13 @@
1114
from .volume import Volume
1215

1316

17+
@final
1418
class BlockIOBlocks:
19+
__slots__ = (
20+
"_null_block",
21+
"blockio",
22+
)
23+
1524
def __init__(self, blockio: "BlockIO") -> None:
1625
self.blockio: BlockIO = blockio
1726
self._null_block: bytearray = bytearray(self.block_size)
@@ -41,7 +50,14 @@ def __getitem__(self, ee_block: int) -> bytearray | bytes:
4150
return self._null_block
4251

4352

53+
@final
4454
class BlockIO(io.RawIOBase):
55+
__slots__ = (
56+
"blocks",
57+
"cursor",
58+
"inode",
59+
)
60+
4561
def __init__(self, inode: "Inode") -> None:
4662
super().__init__()
4763
self.inode: Inode = inode

ext4/blockdescriptor.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121

2222
@final
2323
class BlockDescriptor(Ext4Struct):
24+
__slots__ = ("bg_no",)
25+
2426
_pack_ = 1
2527
# _anonymous_ = ("bg_reserved",)
2628
_fields_ = [

ext4/directory.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@
2828

2929

3030
class DirectoryEntryStruct(Ext4Struct):
31+
__slots__: tuple[str, ...] = ("directory",)
32+
3133
def __init__(self, directory: "Directory", offset: int) -> None:
3234
self.directory: Directory = directory
3335
super().__init__(directory.volume, offset)
@@ -39,6 +41,7 @@ def read_from_volume(self) -> None:
3941

4042

4143
class DirectoryEntryBase(DirectoryEntryStruct):
44+
__slots__: tuple[str, ...] = ()
4245
@property
4346
def name_bytes(self) -> bytes:
4447
return bytes(self.name)[: self.name_len] # pyright: ignore[reportAny]
@@ -55,6 +58,7 @@ def is_fake_entry(self) -> bool:
5558

5659
@final
5760
class DirectoryEntry(DirectoryEntryBase):
61+
__slots__ = ()
5862
_pack_ = 1
5963
# _anonymous_ = ("l_i_reserved",)
6064
_fields_ = [
@@ -67,6 +71,7 @@ class DirectoryEntry(DirectoryEntryBase):
6771

6872
@final
6973
class DirectoryEntry2(DirectoryEntryBase):
74+
__slots__ = ()
7075
_pack_ = 1
7176
# _anonymous_ = ("l_i_reserved",)
7277
_fields_ = [
@@ -85,6 +90,7 @@ def is_fake_entry(self) -> bool:
8590

8691
@final
8792
class DirectoryEntryTail(DirectoryEntryStruct):
93+
__slots__ = ()
8894
_pack_ = 1
8995
# _anonymous_ = ("det_reserved_zero1", "det_reserved_zero2",)
9096
_fields_ = [
@@ -107,6 +113,7 @@ def expected_magic(self) -> int:
107113

108114
@final
109115
class DirectoryEntryHash(DirectoryEntryStruct):
116+
__slots__ = ()
110117
_pack_ = 1
111118
# _anonymous_ = ("det_reserved_zero1", "det_reserved_zero2",)
112119
_fields_ = [

ext4/extent.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,13 @@
2020
from .volume import Volume
2121

2222

23+
@final
2324
class ExtentBlocks:
25+
__slots__: tuple[str, ...] = (
26+
"_null_block",
27+
"extent",
28+
)
29+
2430
def __init__(self, extent: "Extent") -> None:
2531
self.extent: Extent = extent
2632
self._null_block: bytearray = bytearray(self.block_size)
@@ -74,6 +80,13 @@ def __len__(self) -> int:
7480

7581
@final
7682
class ExtentHeader(Ext4Struct):
83+
__slots__ = (
84+
"extents",
85+
"indices",
86+
"tail",
87+
"tree",
88+
)
89+
7790
_pack_ = 1
7891
# _anonymous_ = ()
7992
_fields_ = [
@@ -153,6 +166,11 @@ def checksum(self) -> int | None:
153166

154167
@final
155168
class ExtentIndex(Ext4Struct):
169+
__slots__ = (
170+
"ei_no",
171+
"header",
172+
)
173+
156174
_pack_ = 1
157175
# _anonymous_ = ("ei_unused",)
158176
_fields_ = [
@@ -184,6 +202,12 @@ def inode(self) -> "Inode":
184202

185203
@final
186204
class Extent(Ext4Struct):
205+
__slots__ = (
206+
"blocks",
207+
"ee_no",
208+
"header",
209+
)
210+
187211
_pack_ = 1
188212
# _anonymous_ = ("ei_unused",)
189213
_fields_ = [
@@ -231,6 +255,8 @@ def read(self) -> bytes:
231255

232256
@final
233257
class ExtentTail(Ext4Struct):
258+
__slots__ = ("header",)
259+
234260
_pack_ = 1
235261
_fields_ = [
236262
("et_checksum", c_uint32),
@@ -250,6 +276,11 @@ def inode(self) -> "Inode":
250276

251277

252278
class ExtentTree:
279+
__slots__: tuple[str, ...] = (
280+
"headers",
281+
"inode",
282+
)
283+
253284
def __init__(self, inode: "Inode") -> None:
254285
self.inode: Inode = inode
255286
self.headers: list[ExtentHeader] = []

ext4/htree.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@
3131

3232

3333
class LittleEndianStructureWithVolume(LittleEndianStructure):
34+
__slots__: tuple[str, ...] = ("_volume",)
35+
3436
def __init__(self) -> None:
3537
super().__init__()
3638
self._volume: Volume | None = None
@@ -47,6 +49,8 @@ def volume(self, volume: "Volume") -> None:
4749

4850
@final
4951
class DotDirectoryEntry2(LittleEndianStructureWithVolume):
52+
__slots__ = ()
53+
5054
_pack_ = 1
5155
# _anonymous_ = ()
5256
_fields_ = [
@@ -76,6 +80,7 @@ def verify(self) -> None:
7680

7781
@final
7882
class DXRootInfo(LittleEndianStructure):
83+
__slots__ = ()
7984
_pack_ = 1
8085
# _anonymous_ = ("reserved_zero")
8186
_fields_ = [
@@ -88,6 +93,8 @@ class DXRootInfo(LittleEndianStructure):
8893

8994

9095
class DXBase(Ext4Struct):
96+
__slots__: tuple[str, ...] = ("directory",)
97+
9198
def __init__(self, directory: "Directory", offset: int) -> None:
9299
self.directory: Directory = directory
93100
super().__init__(directory.volume, offset)
@@ -102,6 +109,11 @@ def read_from_volume(self) -> None:
102109

103110
@final
104111
class DXEntry(DXBase):
112+
__slots__ = (
113+
"index",
114+
"parent",
115+
)
116+
105117
_pack_ = 1
106118
# _anonymous_ = ("")
107119
_fields_ = [
@@ -119,6 +131,8 @@ def __init__(self, parent: "DXEntriesBase", index: int) -> None:
119131

120132

121133
class DXEntriesBase(DXBase):
134+
__slots__: tuple[str, ...] = ()
135+
122136
@override
123137
def read_from_volume(self) -> None:
124138
super().read_from_volume()
@@ -141,6 +155,8 @@ def info_length(self) -> int:
141155

142156
@final
143157
class DXRoot(DXEntriesBase):
158+
__slots__ = ()
159+
144160
_pack_ = 1
145161
# _anonymous_ = ("")
146162
_fields_ = [
@@ -159,6 +175,7 @@ def __init__(self, inode: "Directory") -> None:
159175

160176
@final
161177
class DXFake(LittleEndianStructure):
178+
__slots__ = ()
162179
_pack_ = 1
163180
# _anonymous_ = ("")
164181
_fields_ = [
@@ -178,6 +195,8 @@ def magic(self) -> int:
178195

179196
@final
180197
class DXNode(DXEntriesBase):
198+
__slots__ = ()
199+
181200
_pack_ = 1
182201
# _anonymous_ = ("")
183202
_fields_ = [
@@ -196,6 +215,8 @@ def __init__(self, directory: "Directory", offset: int) -> None:
196215

197216
@final
198217
class DXTail(DXBase):
218+
__slots__ = ("parent",)
219+
199220
_pack_ = 1
200221
# _anonymous_ = ("dt_reserved")
201222
_fields_ = [

0 commit comments

Comments
 (0)