2727 class Test(Enum):
2828 A = ...
2929 B = ...
30+
3031 """ ,
3132 id = "enum" ,
3233 ),
@@ -41,6 +42,7 @@ class Test(Enum):
4142 class Test(Enum):
4243 A = ...
4344 B = ...
45+
4446 """ ,
4547 id = "enum int8" ,
4648 ),
@@ -55,6 +57,7 @@ class Test(Enum):
5557 class Test(Flag):
5658 A = ...
5759 B = ...
60+
5861 """ ,
5962 id = "flag" ,
6063 ),
@@ -63,7 +66,9 @@ class Test(Flag):
6366def test_generate_enum_stub (cs : cstruct , cdef : str , expected : str ) -> None :
6467 cs .load (cdef )
6568
66- assert stubgen .generate_enum_stub (cs .Test ) == textwrap .dedent (expected ).strip ()
69+ # We don't want to strip all trailing whitespace in case it's part of the intended expected output
70+ # So just remove one newline from the final """ block
71+ assert stubgen .generate_enum_stub (cs .Test ) == textwrap .dedent (expected ).lstrip ()[:- 1 ]
6772
6873
6974@pytest .mark .parametrize (
@@ -86,6 +91,7 @@ class Test(Structure):
8691 def __init__(self, a: uint8 | None = ..., b: uint8 | None = ..., c: uint16 | None = ...): ...
8792 @overload
8893 def __init__(self, fh: bytes | memoryview | bytearray | BinaryIO, /): ...
94+
8995 """ ,
9096 id = "basic" ,
9197 ),
@@ -106,6 +112,7 @@ class Test(Structure):
106112 def __init__(self, a: Array[uint8] | None = ..., b: CharArray | None = ..., c: WcharArray | None = ...): ...
107113 @overload
108114 def __init__(self, fh: bytes | memoryview | bytearray | BinaryIO, /): ...
115+
109116 """ , # noqa: E501
110117 id = "array" ,
111118 ),
@@ -124,6 +131,7 @@ class Test(Structure):
124131 def __init__(self, a: Pointer[uint8] | None = ..., b: Array[Pointer[uint8]] | None = ...): ...
125132 @overload
126133 def __init__(self, fh: bytes | memoryview | bytearray | BinaryIO, /): ...
134+
127135 """ ,
128136 id = "pointer" ,
129137 ),
@@ -144,6 +152,7 @@ class Test(Structure):
144152 def __init__(self, a: uint8 | None = ..., b: uint8 | None = ...): ...
145153 @overload
146154 def __init__(self, fh: bytes | memoryview | bytearray | BinaryIO, /): ...
155+
147156 """ ,
148157 id = "anonymous nested" ,
149158 ),
@@ -165,11 +174,13 @@ class __anonymous_0__(Union):
165174 def __init__(self, a: uint8 | None = ..., b: uint8 | None = ...): ...
166175 @overload
167176 def __init__(self, fh: bytes | memoryview | bytearray | BinaryIO, /): ...
177+
168178 x: __anonymous_0__
169179 @overload
170180 def __init__(self, x: __anonymous_0__ | None = ...): ...
171181 @overload
172182 def __init__(self, fh: bytes | memoryview | bytearray | BinaryIO, /): ...
183+
173184 """ ,
174185 id = "named nested" ,
175186 ),
@@ -191,11 +202,13 @@ class __anonymous_0__(Structure):
191202 def __init__(self, a: uint8 | None = ..., b: uint8 | None = ...): ...
192203 @overload
193204 def __init__(self, fh: bytes | memoryview | bytearray | BinaryIO, /): ...
205+
194206 x: Array[__anonymous_0__]
195207 @overload
196208 def __init__(self, x: Array[__anonymous_0__] | None = ...): ...
197209 @overload
198210 def __init__(self, fh: bytes | memoryview | bytearray | BinaryIO, /): ...
211+
199212 """ ,
200213 id = "named nested array" ,
201214 ),
@@ -204,7 +217,9 @@ def __init__(self, fh: bytes | memoryview | bytearray | BinaryIO, /): ...
204217def test_generate_structure_stub (cs : cstruct , cdef : str , expected : str ) -> None :
205218 cs .load (cdef )
206219
207- assert stubgen .generate_structure_stub (cs .Test ) == textwrap .dedent (expected ).strip ()
220+ # We don't want to strip all trailing whitespace in case it's part of the intended expected output
221+ # So just remove one newline from the final """ block
222+ assert stubgen .generate_structure_stub (cs .Test ) == textwrap .dedent (expected ).lstrip ()[:- 1 ]
208223
209224
210225@pytest .mark .parametrize (
@@ -225,10 +240,11 @@ def test_generate_structure_stub(cs: cstruct, cdef: str, expected: str) -> None:
225240 """ ,
226241 """
227242 class cstruct(cstruct):
228- TEST: int = ...
243+ TEST: Literal[1] = ...
229244 class TestEnum(Enum):
230245 A = ...
231246 B = ...
247+
232248 class TestStruct(Structure):
233249 a: cstruct.uint8
234250 @overload
@@ -253,16 +269,64 @@ class Test(Structure):
253269 def __init__(self, a: cstruct.uint8 | None = ...): ...
254270 @overload
255271 def __init__(self, fh: bytes | memoryview | bytearray | BinaryIO, /): ...
272+
256273 _test: TypeAlias = Test
257274 """ ,
258275 id = "alias stub" ,
259276 ),
277+ pytest .param (
278+ """
279+ typedef __u16 __fs16;
280+ typedef __u32 __fs32;
281+ typedef __u64 __fs64;
282+
283+ struct Test {
284+ __fs16 a;
285+ __fs32 b;
286+ __fs64 c;
287+ };
288+ """ ,
289+ """
290+ class cstruct(cstruct):
291+ __fs16: TypeAlias = cstruct.uint16
292+ __fs32: TypeAlias = cstruct.uint32
293+ __fs64: TypeAlias = cstruct.uint64
294+ class Test(Structure):
295+ a: cstruct.uint16
296+ b: cstruct.uint32
297+ c: cstruct.uint64
298+ @overload
299+ def __init__(self, a: cstruct.uint16 | None = ..., b: cstruct.uint32 | None = ..., c: cstruct.uint64 | None = ...): ...
300+ @overload
301+ def __init__(self, fh: bytes | memoryview | bytearray | BinaryIO, /): ...
302+
303+ """ , # noqa: E501
304+ id = "typedef stub" ,
305+ ),
306+ pytest .param (
307+ """
308+ #define INT 1
309+ #define FLOAT 2.0
310+ #define STRING "hello"
311+ #define BYTES b'c'
312+ """ ,
313+ """
314+ class cstruct(cstruct):
315+ INT: Literal[1] = ...
316+ FLOAT: Literal[2.0] = ...
317+ STRING: Literal['hello'] = ...
318+ BYTES: Literal[b'c'] = ...
319+ """ ,
320+ id = "define literals" ,
321+ ),
260322 ],
261323)
262324def test_generate_cstruct_stub (cs : cstruct , cdef : str , expected : str ) -> None :
263325 cs .load (cdef )
264326
265- assert stubgen .generate_cstruct_stub (cs ) == textwrap .dedent (expected ).strip ()
327+ # We don't want to strip all trailing whitespace in case it's part of the intended expected output
328+ # So just remove one newline from the final """ block
329+ assert stubgen .generate_cstruct_stub (cs ) == textwrap .dedent (expected ).lstrip ()[:- 1 ]
266330
267331
268332def test_generate_cstruct_stub_empty (cs : cstruct ) -> None :
@@ -292,9 +356,10 @@ def test_generate_file_stub(tmp_path: Path, monkeypatch: pytest.MonkeyPatch, cap
292356
293357 expected = """
294358 # Generated by cstruct-stubgen
295- from typing import BinaryIO, overload
359+ from typing import BinaryIO, Literal, overload
296360
297361 import dissect.cstruct as __cs__
362+ from typing_extensions import TypeAlias
298363
299364 class _c_structure(__cs__.cstruct):
300365 class Test(__cs__.Structure):
@@ -304,7 +369,9 @@ class Test(__cs__.Structure):
304369 def __init__(self, a: _c_structure.uint32 | None = ..., b: _c_structure.uint32 | None = ...): ...
305370 @overload
306371 def __init__(self, fh: bytes | memoryview | bytearray | BinaryIO, /): ...
307- c_structure: _c_structure
372+
373+ # Technically `c_structure` is an instance of `_c_structure`, but then we can't use it in type hints
374+ c_structure: TypeAlias = _c_structure
308375 """
309376
310377 assert stubgen .generate_file_stub (test_file , tmp_path ) == textwrap .dedent (expected ).lstrip ()
0 commit comments