dissect.cstruct 5.0.dev8__tar.gz → 5.0.dev10__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) hide show
  1. {dissect_cstruct-5.0.dev8 → dissect_cstruct-5.0.dev10}/PKG-INFO +1 -1
  2. {dissect_cstruct-5.0.dev8 → dissect_cstruct-5.0.dev10}/dissect/cstruct/bitbuffer.py +6 -6
  3. {dissect_cstruct-5.0.dev8 → dissect_cstruct-5.0.dev10}/dissect/cstruct/compiler.py +28 -28
  4. {dissect_cstruct-5.0.dev8 → dissect_cstruct-5.0.dev10}/dissect/cstruct/cstruct.py +60 -28
  5. {dissect_cstruct-5.0.dev8 → dissect_cstruct-5.0.dev10}/dissect/cstruct/tools/stubgen.py +5 -5
  6. {dissect_cstruct-5.0.dev8 → dissect_cstruct-5.0.dev10}/dissect/cstruct/types/base.py +121 -38
  7. {dissect_cstruct-5.0.dev8 → dissect_cstruct-5.0.dev10}/dissect/cstruct/types/char.py +5 -5
  8. {dissect_cstruct-5.0.dev8 → dissect_cstruct-5.0.dev10}/dissect/cstruct/types/enum.py +15 -15
  9. {dissect_cstruct-5.0.dev8 → dissect_cstruct-5.0.dev10}/dissect/cstruct/types/int.py +4 -4
  10. {dissect_cstruct-5.0.dev8 → dissect_cstruct-5.0.dev10}/dissect/cstruct/types/packed.py +26 -15
  11. {dissect_cstruct-5.0.dev8 → dissect_cstruct-5.0.dev10}/dissect/cstruct/types/pointer.py +24 -24
  12. {dissect_cstruct-5.0.dev8 → dissect_cstruct-5.0.dev10}/dissect/cstruct/types/structure.py +72 -51
  13. {dissect_cstruct-5.0.dev8 → dissect_cstruct-5.0.dev10}/dissect/cstruct/types/void.py +1 -1
  14. {dissect_cstruct-5.0.dev8 → dissect_cstruct-5.0.dev10}/dissect/cstruct/types/wchar.py +5 -5
  15. {dissect_cstruct-5.0.dev8 → dissect_cstruct-5.0.dev10}/dissect/cstruct/util.py +12 -4
  16. {dissect_cstruct-5.0.dev8 → dissect_cstruct-5.0.dev10}/dissect.cstruct.egg-info/PKG-INFO +1 -1
  17. {dissect_cstruct-5.0.dev8 → dissect_cstruct-5.0.dev10}/dissect.cstruct.egg-info/scm_file_list.json +51 -51
  18. dissect_cstruct-5.0.dev10/dissect.cstruct.egg-info/scm_version.json +8 -0
  19. {dissect_cstruct-5.0.dev8 → dissect_cstruct-5.0.dev10}/tests/test_align.py +13 -13
  20. {dissect_cstruct-5.0.dev8 → dissect_cstruct-5.0.dev10}/tests/test_basic.py +85 -13
  21. {dissect_cstruct-5.0.dev8 → dissect_cstruct-5.0.dev10}/tests/test_benchmark.py +179 -0
  22. {dissect_cstruct-5.0.dev8 → dissect_cstruct-5.0.dev10}/tests/test_compiler.py +12 -18
  23. {dissect_cstruct-5.0.dev8 → dissect_cstruct-5.0.dev10}/tests/test_parser.py +34 -34
  24. {dissect_cstruct-5.0.dev8 → dissect_cstruct-5.0.dev10}/tests/test_types_base.py +4 -4
  25. {dissect_cstruct-5.0.dev8 → dissect_cstruct-5.0.dev10}/tests/test_types_custom.py +15 -14
  26. {dissect_cstruct-5.0.dev8 → dissect_cstruct-5.0.dev10}/tests/test_types_enum.py +4 -4
  27. {dissect_cstruct-5.0.dev8 → dissect_cstruct-5.0.dev10}/tests/test_types_flag.py +4 -4
  28. {dissect_cstruct-5.0.dev8 → dissect_cstruct-5.0.dev10}/tests/test_types_pointer.py +2 -2
  29. {dissect_cstruct-5.0.dev8 → dissect_cstruct-5.0.dev10}/tests/test_types_structure.py +21 -21
  30. {dissect_cstruct-5.0.dev8 → dissect_cstruct-5.0.dev10}/tests/test_types_union.py +12 -12
  31. {dissect_cstruct-5.0.dev8 → dissect_cstruct-5.0.dev10}/tox.ini +2 -0
  32. dissect_cstruct-5.0.dev8/dissect.cstruct.egg-info/scm_version.json +0 -8
  33. {dissect_cstruct-5.0.dev8 → dissect_cstruct-5.0.dev10}/.git-blame-ignore-revs +0 -0
  34. {dissect_cstruct-5.0.dev8 → dissect_cstruct-5.0.dev10}/.gitattributes +0 -0
  35. {dissect_cstruct-5.0.dev8 → dissect_cstruct-5.0.dev10}/CHANGELOG.md +0 -0
  36. {dissect_cstruct-5.0.dev8 → dissect_cstruct-5.0.dev10}/COPYRIGHT +0 -0
  37. {dissect_cstruct-5.0.dev8 → dissect_cstruct-5.0.dev10}/LICENSE +0 -0
  38. {dissect_cstruct-5.0.dev8 → dissect_cstruct-5.0.dev10}/MANIFEST.in +0 -0
  39. {dissect_cstruct-5.0.dev8 → dissect_cstruct-5.0.dev10}/README.md +0 -0
  40. {dissect_cstruct-5.0.dev8 → dissect_cstruct-5.0.dev10}/dissect/cstruct/__init__.py +0 -0
  41. {dissect_cstruct-5.0.dev8 → dissect_cstruct-5.0.dev10}/dissect/cstruct/exception.py +0 -0
  42. {dissect_cstruct-5.0.dev8 → dissect_cstruct-5.0.dev10}/dissect/cstruct/expression.py +0 -0
  43. {dissect_cstruct-5.0.dev8 → dissect_cstruct-5.0.dev10}/dissect/cstruct/lexer.py +0 -0
  44. {dissect_cstruct-5.0.dev8 → dissect_cstruct-5.0.dev10}/dissect/cstruct/parser.py +0 -0
  45. {dissect_cstruct-5.0.dev8 → dissect_cstruct-5.0.dev10}/dissect/cstruct/tools/__init__.py +0 -0
  46. {dissect_cstruct-5.0.dev8 → dissect_cstruct-5.0.dev10}/dissect/cstruct/types/__init__.py +0 -0
  47. {dissect_cstruct-5.0.dev8 → dissect_cstruct-5.0.dev10}/dissect/cstruct/types/flag.py +0 -0
  48. {dissect_cstruct-5.0.dev8 → dissect_cstruct-5.0.dev10}/dissect/cstruct/types/leb128.py +0 -0
  49. {dissect_cstruct-5.0.dev8 → dissect_cstruct-5.0.dev10}/dissect.cstruct.egg-info/SOURCES.txt +0 -0
  50. {dissect_cstruct-5.0.dev8 → dissect_cstruct-5.0.dev10}/dissect.cstruct.egg-info/dependency_links.txt +0 -0
  51. {dissect_cstruct-5.0.dev8 → dissect_cstruct-5.0.dev10}/dissect.cstruct.egg-info/entry_points.txt +0 -0
  52. {dissect_cstruct-5.0.dev8 → dissect_cstruct-5.0.dev10}/dissect.cstruct.egg-info/requires.txt +0 -0
  53. {dissect_cstruct-5.0.dev8 → dissect_cstruct-5.0.dev10}/dissect.cstruct.egg-info/top_level.txt +0 -0
  54. {dissect_cstruct-5.0.dev8 → dissect_cstruct-5.0.dev10}/examples/disk.py +0 -0
  55. {dissect_cstruct-5.0.dev8 → dissect_cstruct-5.0.dev10}/examples/mirai.py +0 -0
  56. {dissect_cstruct-5.0.dev8 → dissect_cstruct-5.0.dev10}/examples/pe.py +0 -0
  57. {dissect_cstruct-5.0.dev8 → dissect_cstruct-5.0.dev10}/examples/protobuf.py +0 -0
  58. {dissect_cstruct-5.0.dev8 → dissect_cstruct-5.0.dev10}/examples/secdesc.py +0 -0
  59. {dissect_cstruct-5.0.dev8 → dissect_cstruct-5.0.dev10}/pyproject.toml +0 -0
  60. {dissect_cstruct-5.0.dev8 → dissect_cstruct-5.0.dev10}/setup.cfg +0 -0
  61. {dissect_cstruct-5.0.dev8 → dissect_cstruct-5.0.dev10}/tests/__init__.py +0 -0
  62. {dissect_cstruct-5.0.dev8 → dissect_cstruct-5.0.dev10}/tests/_data/testdef.txt +0 -0
  63. {dissect_cstruct-5.0.dev8 → dissect_cstruct-5.0.dev10}/tests/_docs/Makefile +0 -0
  64. {dissect_cstruct-5.0.dev8 → dissect_cstruct-5.0.dev10}/tests/_docs/__init__.py +0 -0
  65. {dissect_cstruct-5.0.dev8 → dissect_cstruct-5.0.dev10}/tests/_docs/conf.py +0 -0
  66. {dissect_cstruct-5.0.dev8 → dissect_cstruct-5.0.dev10}/tests/_docs/index.rst +0 -0
  67. {dissect_cstruct-5.0.dev8 → dissect_cstruct-5.0.dev10}/tests/conftest.py +0 -0
  68. {dissect_cstruct-5.0.dev8 → dissect_cstruct-5.0.dev10}/tests/test_annotations.py +0 -0
  69. {dissect_cstruct-5.0.dev8 → dissect_cstruct-5.0.dev10}/tests/test_bitbuffer.py +0 -0
  70. {dissect_cstruct-5.0.dev8 → dissect_cstruct-5.0.dev10}/tests/test_bitfield.py +0 -0
  71. {dissect_cstruct-5.0.dev8 → dissect_cstruct-5.0.dev10}/tests/test_ctypes.py +0 -0
  72. {dissect_cstruct-5.0.dev8 → dissect_cstruct-5.0.dev10}/tests/test_expression.py +0 -0
  73. {dissect_cstruct-5.0.dev8 → dissect_cstruct-5.0.dev10}/tests/test_lexer.py +0 -0
  74. {dissect_cstruct-5.0.dev8 → dissect_cstruct-5.0.dev10}/tests/test_tools_stubgen.py +0 -0
  75. {dissect_cstruct-5.0.dev8 → dissect_cstruct-5.0.dev10}/tests/test_types_char.py +0 -0
  76. {dissect_cstruct-5.0.dev8 → dissect_cstruct-5.0.dev10}/tests/test_types_int.py +0 -0
  77. {dissect_cstruct-5.0.dev8 → dissect_cstruct-5.0.dev10}/tests/test_types_leb128.py +0 -0
  78. {dissect_cstruct-5.0.dev8 → dissect_cstruct-5.0.dev10}/tests/test_types_packed.py +0 -0
  79. {dissect_cstruct-5.0.dev8 → dissect_cstruct-5.0.dev10}/tests/test_types_void.py +0 -0
  80. {dissect_cstruct-5.0.dev8 → dissect_cstruct-5.0.dev10}/tests/test_types_wchar.py +0 -0
  81. {dissect_cstruct-5.0.dev8 → dissect_cstruct-5.0.dev10}/tests/test_utils.py +0 -0
  82. {dissect_cstruct-5.0.dev8 → dissect_cstruct-5.0.dev10}/tests/utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dissect.cstruct
3
- Version: 5.0.dev8
3
+ Version: 5.0.dev10
4
4
  Summary: A Dissect module implementing a parser for C-like structures: structure parsing in Python made easy
5
5
  Author-email: Dissect Team <dissect@fox-it.com>
6
6
  License-Expression: Apache-2.0
@@ -19,11 +19,11 @@ class BitBuffer:
19
19
 
20
20
  def read(self, field_type: type[BaseType], bits: int) -> int:
21
21
  if self._remaining == 0 or self._type != field_type:
22
- if field_type.size is None:
22
+ if field_type.__size__ is None:
23
23
  raise ValueError("Reading variable-length fields is unsupported")
24
24
 
25
25
  self._type = field_type
26
- self._remaining = field_type.size * 8
26
+ self._remaining = field_type.__size__ * 8
27
27
  self._buffer = field_type._read(self.stream, endian=self.endian)
28
28
 
29
29
  if isinstance(self._buffer, bytes):
@@ -51,17 +51,17 @@ class BitBuffer:
51
51
  if self._type:
52
52
  self.flush()
53
53
 
54
- if field_type.size is None:
54
+ if field_type.__size__ is None:
55
55
  raise ValueError("Writing variable-length fields is unsupported")
56
56
 
57
- self._remaining = field_type.size * 8
57
+ self._remaining = field_type.__size__ * 8
58
58
  self._type = field_type
59
59
 
60
- if self._type is None or self._type.size is None:
60
+ if self._type is None or self._type.__size__ is None:
61
61
  raise ValueError("Invalid state")
62
62
 
63
63
  if self.endian == "<":
64
- self._buffer |= data << (self._type.size * 8 - self._remaining)
64
+ self._buffer |= data << (self._type.__size__ * 8 - self._remaining)
65
65
  else:
66
66
  self._buffer |= data << (self._remaining - bits)
67
67
 
@@ -58,7 +58,7 @@ python_compile = compile
58
58
 
59
59
 
60
60
  def compile(structure: type[Structure]) -> type[Structure]:
61
- return Compiler(structure.cs).compile(structure)
61
+ return Compiler(structure.__cs__).compile(structure)
62
62
 
63
63
 
64
64
  class Compiler:
@@ -163,7 +163,7 @@ class _ReadSourceGenerator:
163
163
  field_type = field.type
164
164
 
165
165
  if isinstance(field_type, EnumMetaType):
166
- field_type = field_type.type
166
+ field_type = field_type.__type__
167
167
 
168
168
  if not issubclass(field_type, SUPPORTED_TYPES):
169
169
  raise TypeError(f"Unsupported type for compiler: {field_type}")
@@ -188,7 +188,7 @@ class _ReadSourceGenerator:
188
188
 
189
189
  # Array of structures and multi-dimensional arrays
190
190
  elif issubclass(field_type, (Array, CharArray, WcharArray)) and (
191
- issubclass(field_type.type, Structure) or issubclass(field_type.type, BaseArray) or is_dynamic
191
+ issubclass(field_type.__type__, Structure) or issubclass(field_type.__type__, BaseArray) or is_dynamic
192
192
  ):
193
193
  yield from flush()
194
194
  yield from align_to_field(field)
@@ -222,22 +222,22 @@ class _ReadSourceGenerator:
222
222
  yield from flush()
223
223
 
224
224
  if self.align:
225
- yield f"stream.seek(-stream.tell() & (cls.alignment - 1), {io.SEEK_CUR})"
225
+ yield f"stream.seek(-stream.tell() & (cls.__alignment__ - 1), {io.SEEK_CUR})"
226
226
 
227
227
  def _generate_structure(self, field: Field) -> Iterator[str]:
228
228
  template = f"""
229
- {"_s = stream.tell()" if field.type.dynamic else ""}
229
+ {"_s = stream.tell()" if field.type.__dynamic__ else ""}
230
230
  r["{field._name}"] = {self._map_field(field)}._read(stream, context=r, endian=endian)
231
- {f's["{field._name}"] = stream.tell() - _s' if field.type.dynamic else ""}
231
+ {f's["{field._name}"] = stream.tell() - _s' if field.type.__dynamic__ else ""}
232
232
  """
233
233
 
234
234
  yield dedent(template)
235
235
 
236
236
  def _generate_array(self, field: Field) -> Iterator[str]:
237
237
  template = f"""
238
- {"_s = stream.tell()" if field.type.dynamic else ""}
238
+ {"_s = stream.tell()" if field.type.__dynamic__ else ""}
239
239
  r["{field._name}"] = {self._map_field(field)}._read(stream, context=r, endian=endian)
240
- {f's["{field._name}"] = stream.tell() - _s' if field.type.dynamic else ""}
240
+ {f's["{field._name}"] = stream.tell() - _s' if field.type.__dynamic__ else ""}
241
241
  """
242
242
 
243
243
  yield dedent(template)
@@ -247,12 +247,12 @@ class _ReadSourceGenerator:
247
247
  read_type = "_t"
248
248
  field_type = field.type
249
249
  if issubclass(field_type, (Enum, Flag)):
250
- read_type += ".type"
251
- field_type = field_type.type
250
+ read_type += ".__type__"
251
+ field_type = field_type.__type__
252
252
 
253
253
  if issubclass(field_type, Char):
254
- field_type = field_type.cs.uint8
255
- lookup = "cls.cs.uint8"
254
+ field_type = field_type.__cs__.uint8
255
+ lookup = "cls.__cs__.uint8"
256
256
 
257
257
  template = f"""
258
258
  _t = {lookup}
@@ -277,17 +277,17 @@ class _ReadSourceGenerator:
277
277
  read_type = _get_read_type(self.cs, field_type)
278
278
 
279
279
  if issubclass(field_type, (Array, CharArray, WcharArray)):
280
- count = field_type.num_entries
281
- read_type = _get_read_type(self.cs, field_type.type)
280
+ count = field_type.__num_entries__
281
+ read_type = _get_read_type(self.cs, field_type.__type__)
282
282
 
283
283
  if issubclass(read_type, (Char, Wchar, Int)):
284
- count *= read_type.size
284
+ count *= read_type.__size__
285
285
  getter = f"buf[{size}:{size + count}]"
286
286
  else:
287
287
  getter = f"data[{slice_index}:{slice_index + count}]"
288
288
  slice_index += count
289
289
  elif issubclass(read_type, (Char, Wchar, Int)):
290
- getter = f"buf[{size}:{size + read_type.size}]"
290
+ getter = f"buf[{size}:{size + read_type.__size__}]"
291
291
  else:
292
292
  getter = f"data[{slice_index}]"
293
293
  slice_index += 1
@@ -302,13 +302,13 @@ class _ReadSourceGenerator:
302
302
  # Create the final reading code
303
303
  if issubclass(field_type, Array):
304
304
  reads.append(f"_t = {self._map_field(field)}")
305
- reads.append("_et = _t.type")
305
+ reads.append("_et = _t.__type__")
306
306
 
307
- if issubclass(field_type.type, Int):
307
+ if issubclass(field_type.__type__, Int):
308
308
  reads.append(f"_b = {getter}")
309
- item_parser = parser_template.format(type="_et", getter=f"_b[i:i + {field_type.type.size}]")
310
- list_comp = f"[{item_parser} for i in range(0, {count}, {field_type.type.size})]"
311
- elif issubclass(field_type.type, Pointer):
309
+ item_parser = parser_template.format(type="_et", getter=f"_b[i:i + {field_type.__type__.__size__}]")
310
+ list_comp = f"[{item_parser} for i in range(0, {count}, {field_type.__type__.__size__})]"
311
+ elif issubclass(field_type.__type__, Pointer):
312
312
  item_parser = "_et.__new__(_et, e, stream, context=r, endian=endian)"
313
313
  list_comp = f"[{item_parser} for e in {getter}]"
314
314
  else:
@@ -327,7 +327,7 @@ class _ReadSourceGenerator:
327
327
  reads.append(f'r["{field._name}"] = {parser}')
328
328
  reads.append("") # Generates a newline in the resulting code
329
329
 
330
- size += field_type.size
330
+ size += field_type.__size__
331
331
 
332
332
  fmt = _optimize_struct_fmt(info)
333
333
  if fmt == "x" or (len(fmt) == 2 and fmt[1] == "x"):
@@ -370,19 +370,19 @@ def _generate_struct_info(cs: cstruct, fields: list[Field], align: bool = False)
370
370
 
371
371
  # Array of more complex types are handled elsewhere
372
372
  if issubclass(read_type, (Array, CharArray, WcharArray)):
373
- count = read_type.num_entries
374
- read_type = _get_read_type(cs, read_type.type)
373
+ count = read_type.__num_entries__
374
+ read_type = _get_read_type(cs, read_type.__type__)
375
375
 
376
376
  # Take the pack char for Packed
377
377
  if issubclass(read_type, Packed):
378
- yield field, count, read_type.packchar
378
+ yield field, count, read_type.__fmt__
379
379
 
380
380
  # Other types are byte based
381
381
  # We don't actually unpack anything here but slice directly out of the buffer
382
382
  elif issubclass(read_type, (Char, Wchar, Int)):
383
- yield field, count * read_type.size, "x"
383
+ yield field, count * read_type.__size__, "x"
384
384
 
385
- size = count * read_type.size
385
+ size = count * read_type.__size__
386
386
  imaginary_offset += size
387
387
  if current_offset is not None:
388
388
  current_offset += size
@@ -416,7 +416,7 @@ def _optimize_struct_fmt(info: Iterator[tuple[Field, int, str]]) -> str:
416
416
 
417
417
  def _get_read_type(cs: cstruct, type_: type[BaseType]) -> type[BaseType]:
418
418
  if issubclass(type_, (Enum, Flag)):
419
- type_ = type_.type
419
+ type_ = type_.__type__
420
420
 
421
421
  if issubclass(type_, Pointer):
422
422
  type_ = cs.pointer
@@ -206,7 +206,28 @@ class cstruct:
206
206
  if load:
207
207
  self.load(load)
208
208
 
209
- def __getattr__(self, attr: str) -> Any:
209
+ def __getattr__(
210
+ self, attr: str
211
+ ) -> (
212
+ type[
213
+ LEB128
214
+ | BaseType
215
+ | Char
216
+ | Enum
217
+ | Flag
218
+ | Int
219
+ | Packed[int]
220
+ | Packed[float]
221
+ | Pointer
222
+ | Structure
223
+ | Union
224
+ | Void
225
+ | Wchar
226
+ ]
227
+ | int
228
+ | str
229
+ | bytes
230
+ ):
210
231
  try:
211
232
  return self.consts[attr]
212
233
  except KeyError:
@@ -227,7 +248,7 @@ class cstruct:
227
248
  # Update types to point to the new cstruct instance
228
249
  for name, type_ in self.types.items():
229
250
  new_type = copy.copy(type_)
230
- new_type.cs = cs
251
+ new_type.__cs__ = cs
231
252
  cs.add_type(name, new_type, replace=True)
232
253
 
233
254
  for name, value in self.consts.items():
@@ -288,8 +309,10 @@ class cstruct:
288
309
  """
289
310
  # In cstruct 5.0 we changed the function signature of _read and _write
290
311
  # Check if the function signature is compatible, and warn if not
291
- for type_to_check in (type_, type_.ArrayType):
292
- type_name = type_.__name__ + (f".{type_.ArrayType.__name__}" if type_to_check is type_.ArrayType else "")
312
+ for type_to_check in (type_, type_.__ArrayType__):
313
+ type_name = type_.__name__ + (
314
+ f".{type_.__ArrayType__.__name__}" if type_to_check is type_.__ArrayType__ else ""
315
+ )
293
316
 
294
317
  for method in ("_read", "_read_array", "_read_0", "_write", "_write_array", "_write_0"):
295
318
  if not hasattr(type_to_check, method):
@@ -481,10 +504,10 @@ class cstruct:
481
504
  attrs = attrs or {}
482
505
  attrs.update(
483
506
  {
484
- "cs": self,
485
- "size": size,
486
- "dynamic": size is None,
487
- "alignment": alignment or size,
507
+ "__cs__": self,
508
+ "__size__": size,
509
+ "__dynamic__": size is None,
510
+ "__alignment__": alignment or size,
488
511
  }
489
512
  )
490
513
  return types.new_class(name, bases, {}, lambda ns: ns.update(attrs))
@@ -494,37 +517,37 @@ class cstruct:
494
517
  if num_entries is None:
495
518
  null_terminated = True
496
519
  size = None
497
- elif isinstance(num_entries, Expression) or type_.dynamic:
520
+ elif isinstance(num_entries, Expression) or type_.__dynamic__:
498
521
  size = None
499
522
  else:
500
- if type_.size is None:
523
+ if type_.__size__ is None:
501
524
  raise ValueError(f"Cannot create array of dynamic type: {type_.__name__}")
502
- size = num_entries * type_.size
525
+ size = num_entries * type_.__size__
503
526
 
504
527
  name = f"{type_.__name__}[]" if null_terminated else f"{type_.__name__}[{num_entries}]"
505
528
 
506
- bases = (type_.ArrayType,)
529
+ bases = (type_.__ArrayType__,)
507
530
 
508
531
  attrs = {
509
- "type": type_,
510
- "num_entries": num_entries,
511
- "null_terminated": null_terminated,
532
+ "__type__": type_,
533
+ "__num_entries__": num_entries,
534
+ "__null_terminated__": null_terminated,
512
535
  }
513
536
 
514
- return cast("type[Array]", self._make_type(name, bases, size, alignment=type_.alignment, attrs=attrs))
537
+ return cast("type[Array]", self._make_type(name, bases, size, alignment=type_.__alignment__, attrs=attrs))
515
538
 
516
539
  def _make_int_type(self, name: str, size: int, signed: bool, *, alignment: int | None = None) -> type[Int]:
517
540
  return cast("type[Int]", self._make_type(name, (Int,), size, alignment=alignment, attrs={"signed": signed}))
518
541
 
519
- def _make_packed_type(self, name: str, packchar: str, base: type, *, alignment: int | None = None) -> type[Packed]:
542
+ def _make_packed_type(self, name: str, fmt: str, base: type, *, alignment: int | None = None) -> type[Packed]:
520
543
  return cast(
521
544
  "type[Packed]",
522
545
  self._make_type(
523
546
  name,
524
547
  (base, Packed),
525
- struct.calcsize(packchar),
548
+ struct.calcsize(fmt),
526
549
  alignment=alignment,
527
- attrs={"packchar": packchar},
550
+ attrs={"__fmt__": fmt},
528
551
  ),
529
552
  )
530
553
 
@@ -538,9 +561,9 @@ class cstruct:
538
561
  return self._make_type(
539
562
  f"{target.__name__}*",
540
563
  (Pointer,),
541
- self.pointer.size,
542
- alignment=self.pointer.alignment,
543
- attrs={"type": target},
564
+ self.pointer.__size__,
565
+ alignment=self.pointer.__alignment__,
566
+ attrs={"__type__": target},
544
567
  )
545
568
 
546
569
  def _make_struct(
@@ -557,7 +580,7 @@ class cstruct:
557
580
  (base,),
558
581
  None,
559
582
  attrs={
560
- "fields": fields,
583
+ "__members__": fields,
561
584
  "__align__": align,
562
585
  "__anonymous__": anonymous,
563
586
  },
@@ -568,6 +591,15 @@ class cstruct:
568
591
  ) -> type[Structure]:
569
592
  return self._make_struct(name, fields, align=align, anonymous=anonymous, base=Union)
570
593
 
594
+ @property
595
+ def typedefs(self) -> dict[str, type[BaseType]]:
596
+ warnings.warn(
597
+ "The 'typedefs' property is deprecated, use 'types' instead.",
598
+ DeprecationWarning,
599
+ stacklevel=2,
600
+ )
601
+ return self.types
602
+
571
603
  if TYPE_CHECKING:
572
604
  # ruff: noqa: PYI042
573
605
  _int = int
@@ -749,8 +781,8 @@ def ctypes_type(type_: type[BaseType]) -> Any:
749
781
  "d": _ctypes.c_double,
750
782
  }
751
783
 
752
- if issubclass(type_, Packed) and type_.packchar in mapping:
753
- return mapping[type_.packchar]
784
+ if issubclass(type_, Packed) and type_.__fmt__ in mapping:
785
+ return mapping[type_.__fmt__]
754
786
 
755
787
  if issubclass(type_, Char):
756
788
  return _ctypes.c_char
@@ -759,11 +791,11 @@ def ctypes_type(type_: type[BaseType]) -> Any:
759
791
  return _ctypes.c_wchar
760
792
 
761
793
  if issubclass(type_, BaseArray):
762
- subtype = ctypes_type(type_.type)
763
- return subtype * type_.num_entries
794
+ subtype = ctypes_type(type_.__type__)
795
+ return subtype * type_.__num_entries__
764
796
 
765
797
  if issubclass(type_, Pointer):
766
- subtype = ctypes_type(type_.type)
798
+ subtype = ctypes_type(type_.__type__)
767
799
  return _ctypes.POINTER(subtype)
768
800
 
769
801
  if issubclass(type_, Structure):
@@ -121,9 +121,9 @@ def generate_typehint(
121
121
  if issubclass(type_, types.WcharArray):
122
122
  return f"{module_prefix}WcharArray"
123
123
  if issubclass(type_, types.Pointer):
124
- return f"{module_prefix}Pointer[{generate_typehint(type_.type, prefix, module_prefix)}]"
124
+ return f"{module_prefix}Pointer[{generate_typehint(type_.__type__, prefix, module_prefix)}]"
125
125
  if issubclass(type_, types.Array):
126
- return f"{module_prefix}Array[{generate_typehint(type_.type, prefix, module_prefix)}]"
126
+ return f"{module_prefix}Array[{generate_typehint(type_.__type__, prefix, module_prefix)}]"
127
127
  return f"{prefix}{type_.__name__}"
128
128
 
129
129
 
@@ -159,15 +159,15 @@ def generate_structure_stub(
159
159
  indent = " " * 4
160
160
 
161
161
  args = ["self"]
162
- for field_name, field in structure.fields.items():
162
+ for field_name, field in structure.__members__.items():
163
163
  inlined = False
164
164
 
165
165
  # If it's a structure and not globally defined, add an inline stub for it
166
166
  nested_type = field.type
167
167
  while issubclass(nested_type, types.BaseArray):
168
- nested_type = nested_type.type
168
+ nested_type = nested_type.__type__
169
169
 
170
- if issubclass(nested_type, types.Structure) and nested_type.__name__ not in structure.cs.types:
170
+ if issubclass(nested_type, types.Structure) and nested_type.__name__ not in structure.__cs__.types:
171
171
  inlined = True
172
172
  inline_stub = generate_structure_stub(nested_type, cs_prefix=cs_prefix, module_prefix=module_prefix)
173
173