obstruct 0.2.14__tar.gz → 0.3.0__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.
- {obstruct-0.2.14 → obstruct-0.3.0}/.idea/workspace.xml +42 -3
- {obstruct-0.2.14 → obstruct-0.3.0}/PKG-INFO +1 -1
- obstruct-0.3.0/src/obstruct/__version__.py +1 -0
- {obstruct-0.2.14 → obstruct-0.3.0}/src/obstruct/aot/base.py +5 -2
- {obstruct-0.2.14 → obstruct-0.3.0}/src/obstruct/aot/unpack.py +62 -35
- {obstruct-0.2.14 → obstruct-0.3.0}/src/obstruct/struct_type.py +7 -0
- {obstruct-0.2.14 → obstruct-0.3.0}/test/test_speed.py +32 -29
- obstruct-0.2.14/src/obstruct/__version__.py +0 -1
- {obstruct-0.2.14 → obstruct-0.3.0}/.idea/.gitignore +0 -0
- {obstruct-0.2.14 → obstruct-0.3.0}/.idea/inspectionProfiles/Project_Default.xml +0 -0
- {obstruct-0.2.14 → obstruct-0.3.0}/.idea/inspectionProfiles/profiles_settings.xml +0 -0
- {obstruct-0.2.14 → obstruct-0.3.0}/.idea/misc.xml +0 -0
- {obstruct-0.2.14 → obstruct-0.3.0}/.idea/modules.xml +0 -0
- {obstruct-0.2.14 → obstruct-0.3.0}/.idea/obstruct.iml +0 -0
- {obstruct-0.2.14 → obstruct-0.3.0}/.idea/vcs.xml +0 -0
- {obstruct-0.2.14 → obstruct-0.3.0}/README.md +0 -0
- {obstruct-0.2.14 → obstruct-0.3.0}/pyproject.toml +0 -0
- {obstruct-0.2.14 → obstruct-0.3.0}/src/obstruct/__init__.py +0 -0
- {obstruct-0.2.14 → obstruct-0.3.0}/src/obstruct/aot/__init__.py +0 -0
- {obstruct-0.2.14 → obstruct-0.3.0}/src/obstruct/aot/aot.py +0 -0
- {obstruct-0.2.14 → obstruct-0.3.0}/src/obstruct/aot/pack.py +0 -0
- {obstruct-0.2.14 → obstruct-0.3.0}/src/obstruct/metadata_marks.py +0 -0
- {obstruct-0.2.14 → obstruct-0.3.0}/src/obstruct/methods.py +0 -0
- {obstruct-0.2.14 → obstruct-0.3.0}/src/obstruct/types/__init__.py +0 -0
- {obstruct-0.2.14 → obstruct-0.3.0}/src/obstruct/types/base.py +0 -0
- {obstruct-0.2.14 → obstruct-0.3.0}/src/obstruct/types/types.py +0 -0
- {obstruct-0.2.14 → obstruct-0.3.0}/src/obstruct/types/types.pyi +0 -0
- {obstruct-0.2.14 → obstruct-0.3.0}/test/test.py +0 -0
- {obstruct-0.2.14 → obstruct-0.3.0}/uv.lock +0 -0
|
@@ -4,7 +4,11 @@
|
|
|
4
4
|
<option name="autoReloadType" value="SELECTIVE" />
|
|
5
5
|
</component>
|
|
6
6
|
<component name="ChangeListManager">
|
|
7
|
-
<list default="true" id="b482b6b4-48ce-4be1-bf3c-a72ec254fa35" name="更改" comment="
|
|
7
|
+
<list default="true" id="b482b6b4-48ce-4be1-bf3c-a72ec254fa35" name="更改" comment="fix: 更新版本号至 0.2.15,修复延迟加载不会应用到类属性的问题">
|
|
8
|
+
<change beforePath="$PROJECT_DIR$/src/obstruct/aot/base.py" beforeDir="false" afterPath="$PROJECT_DIR$/src/obstruct/aot/base.py" afterDir="false" />
|
|
9
|
+
<change beforePath="$PROJECT_DIR$/src/obstruct/aot/unpack.py" beforeDir="false" afterPath="$PROJECT_DIR$/src/obstruct/aot/unpack.py" afterDir="false" />
|
|
10
|
+
<change beforePath="$PROJECT_DIR$/test/test_speed.py" beforeDir="false" afterPath="$PROJECT_DIR$/test/test_speed.py" afterDir="false" />
|
|
11
|
+
</list>
|
|
8
12
|
<option name="SHOW_DIALOG" value="false" />
|
|
9
13
|
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
|
10
14
|
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
|
|
@@ -252,7 +256,39 @@
|
|
|
252
256
|
<option name="project" value="LOCAL" />
|
|
253
257
|
<updated>1786969506672</updated>
|
|
254
258
|
</task>
|
|
255
|
-
<
|
|
259
|
+
<task id="LOCAL-00016" summary="fix: 更新版本号至 0.2.13,修复类变量识别错误的问题">
|
|
260
|
+
<option name="closed" value="true" />
|
|
261
|
+
<created>1786969885468</created>
|
|
262
|
+
<option name="number" value="00016" />
|
|
263
|
+
<option name="presentableId" value="LOCAL-00016" />
|
|
264
|
+
<option name="project" value="LOCAL" />
|
|
265
|
+
<updated>1786969885469</updated>
|
|
266
|
+
</task>
|
|
267
|
+
<task id="LOCAL-00017" summary="fix: 更新版本号至 0.2.13,修复类变量识别错误的问题">
|
|
268
|
+
<option name="closed" value="true" />
|
|
269
|
+
<created>1786969895079</created>
|
|
270
|
+
<option name="number" value="00017" />
|
|
271
|
+
<option name="presentableId" value="LOCAL-00017" />
|
|
272
|
+
<option name="project" value="LOCAL" />
|
|
273
|
+
<updated>1786969895079</updated>
|
|
274
|
+
</task>
|
|
275
|
+
<task id="LOCAL-00018" summary="fix: 更新版本号至 0.2.14,修复 __cendian__ 类变量识别错误的问题">
|
|
276
|
+
<option name="closed" value="true" />
|
|
277
|
+
<created>1786969988797</created>
|
|
278
|
+
<option name="number" value="00018" />
|
|
279
|
+
<option name="presentableId" value="LOCAL-00018" />
|
|
280
|
+
<option name="project" value="LOCAL" />
|
|
281
|
+
<updated>1786969988797</updated>
|
|
282
|
+
</task>
|
|
283
|
+
<task id="LOCAL-00019" summary="fix: 更新版本号至 0.2.15,修复延迟加载不会应用到类属性的问题">
|
|
284
|
+
<option name="closed" value="true" />
|
|
285
|
+
<created>1786971691114</created>
|
|
286
|
+
<option name="number" value="00019" />
|
|
287
|
+
<option name="presentableId" value="LOCAL-00019" />
|
|
288
|
+
<option name="project" value="LOCAL" />
|
|
289
|
+
<updated>1786971691114</updated>
|
|
290
|
+
</task>
|
|
291
|
+
<option name="localTasksCounter" value="20" />
|
|
256
292
|
<servers />
|
|
257
293
|
</component>
|
|
258
294
|
<component name="TypeScriptGeneratedFilesManager">
|
|
@@ -285,6 +321,9 @@
|
|
|
285
321
|
<MESSAGE value="feat: 更新版本号(跳过一次版本号更改),添加 NOT_A_FIELD 标记控制一个字段是否该被当作二进制字段解析" />
|
|
286
322
|
<MESSAGE value="feat: 更新版本号,添加一些更加清晰明确的类型别名" />
|
|
287
323
|
<MESSAGE value="chore: 更新项目信息和 README 文档" />
|
|
288
|
-
<
|
|
324
|
+
<MESSAGE value="fix: 更新版本号至 0.2.13,修复类变量识别错误的问题" />
|
|
325
|
+
<MESSAGE value="fix: 更新版本号至 0.2.14,修复 __cendian__ 类变量识别错误的问题" />
|
|
326
|
+
<MESSAGE value="fix: 更新版本号至 0.2.15,修复延迟加载不会应用到类属性的问题" />
|
|
327
|
+
<option name="LAST_COMMIT_MESSAGE" value="fix: 更新版本号至 0.2.15,修复延迟加载不会应用到类属性的问题" />
|
|
289
328
|
</component>
|
|
290
329
|
</project>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
version = "0.3.0"
|
|
@@ -5,6 +5,8 @@ import itertools
|
|
|
5
5
|
import typing
|
|
6
6
|
from typing import Any
|
|
7
7
|
|
|
8
|
+
if typing.TYPE_CHECKING:
|
|
9
|
+
from obstruct import Struct
|
|
8
10
|
|
|
9
11
|
|
|
10
12
|
class _objective_node_operator:
|
|
@@ -121,8 +123,9 @@ def unique_name_generator():
|
|
|
121
123
|
itertools.combinations(available_characters, cnt))
|
|
122
124
|
|
|
123
125
|
|
|
124
|
-
def is_struct(tp):
|
|
125
|
-
|
|
126
|
+
def is_struct(tp) -> typing.TypeIs[type[Struct]]:
|
|
127
|
+
from obstruct.struct_type import Struct
|
|
128
|
+
return isinstance(tp, type) and issubclass(tp, Struct)
|
|
126
129
|
|
|
127
130
|
|
|
128
131
|
def is_array(tp):
|
|
@@ -7,10 +7,14 @@ import typing
|
|
|
7
7
|
from .base import unique_name_generator, is_struct, is_array, get_array_ctype, function_def, for_stmt, get_array_length
|
|
8
8
|
|
|
9
9
|
if typing.TYPE_CHECKING:
|
|
10
|
-
from
|
|
10
|
+
from obstruct.struct_type import Struct
|
|
11
11
|
|
|
12
12
|
|
|
13
|
-
def
|
|
13
|
+
def batch_add_code(objs, code: str):
|
|
14
|
+
for obj in objs:
|
|
15
|
+
obj.add_code(code)
|
|
16
|
+
|
|
17
|
+
def create_unpack_methods(cls: type[Struct]):
|
|
14
18
|
from ..methods import get_ctype
|
|
15
19
|
|
|
16
20
|
with (
|
|
@@ -52,58 +56,74 @@ def create_unpack_methods(cls: type[struct_type.Struct]):
|
|
|
52
56
|
iter_update.add_node(iter_update_inner.node)
|
|
53
57
|
|
|
54
58
|
array_fields = []
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
59
|
+
post_inits = []
|
|
60
|
+
|
|
61
|
+
def walk(
|
|
62
|
+
struct_type: type[Struct],
|
|
63
|
+
absolute_xpath: tuple[str, ...],
|
|
64
|
+
current_xname: str = 'self',
|
|
65
|
+
parent_xname=None,
|
|
66
|
+
current_type_name='cls',
|
|
67
|
+
offset=0
|
|
68
|
+
):
|
|
69
|
+
name = current_xname
|
|
70
|
+
|
|
71
|
+
if len(absolute_xpath) > 1: # 在处理内嵌的结构体
|
|
72
|
+
current_field_name = absolute_xpath[-1]
|
|
73
|
+
update_add_code(f"{name} = {parent_xname}.{current_field_name}")
|
|
74
|
+
unpack_add_code(f"{parent_xname}.{current_field_name} = {name} = __new__({current_type_name})") # 组合赋值
|
|
64
75
|
else:
|
|
65
|
-
unpack_add_code(f"{name} = __new__({
|
|
76
|
+
unpack_add_code(f"{name} = __new__({current_type_name})") # 不需要临时变量存储根对象
|
|
66
77
|
# update 在这里不需要创建新对象
|
|
67
78
|
|
|
79
|
+
fields = struct_type.__cfields__
|
|
80
|
+
|
|
68
81
|
for field in fields: # 遍历字段
|
|
69
82
|
field_xpath = f'{name}.{field.name}'
|
|
70
83
|
|
|
71
|
-
# ctype = get_ctype(field.type)
|
|
72
|
-
# print(f"当前字段:{field_xpath},类型:{field.type} '{ctype}',偏移量:{offset}+{struct.calcsize(ctype)}")
|
|
73
|
-
|
|
74
84
|
if is_struct(field.type): # 是个内嵌的结构体
|
|
75
85
|
if field.type not in inner_classes: # 如果这个内嵌的结构体类型不在已知的结构体中(没有分配类名称)
|
|
76
86
|
type_name = next(ung) # 生成一个唯一的类名
|
|
77
|
-
inner_classes[field.type] = type_name
|
|
87
|
+
inner_classes[field.type] = type_name
|
|
78
88
|
else:
|
|
79
89
|
type_name = inner_classes[field.type] # 如果在,那么提取
|
|
80
90
|
|
|
81
|
-
|
|
91
|
+
field_xname = next(ung)
|
|
92
|
+
walk(
|
|
93
|
+
field.type,
|
|
94
|
+
absolute_xpath + (field.name,),
|
|
95
|
+
field_xname,
|
|
96
|
+
name,
|
|
97
|
+
type_name,
|
|
98
|
+
offset
|
|
99
|
+
)
|
|
82
100
|
offset += field.type.__cstruct__.size
|
|
83
101
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
102
|
+
post_inits.append(field_xname)
|
|
103
|
+
|
|
104
|
+
elif is_array(field.type): # 如果是一个数组类型
|
|
105
|
+
dtype = get_array_ctype(field.type) # 获取内容数据类型
|
|
106
|
+
nbytes = get_array_length(field.type) * struct.calcsize(dtype) # 计算数组实际大小
|
|
107
|
+
array_fields.append((next(ung), field_xpath, dtype, offset, nbytes)) # 记录这个数组
|
|
108
|
+
offset += nbytes # 增加当前偏移量
|
|
109
|
+
|
|
110
|
+
else: # 不是特殊的类型,正常处理(添加 assign 目标,并增加偏移量)
|
|
90
111
|
assigns.append(field_xpath)
|
|
91
112
|
offset += struct.calcsize(get_ctype(field.type))
|
|
92
113
|
|
|
93
|
-
walk(cls
|
|
114
|
+
walk(cls, ('A',))
|
|
94
115
|
|
|
95
|
-
|
|
116
|
+
assigns_expr = ', '.join(assigns)
|
|
117
|
+
assign_code = f"{assigns_expr} = _unpack(buffer)" # 生成普通的 unpack, update 用的赋值语句
|
|
96
118
|
# {assigns} = _unpack(buffer)
|
|
97
119
|
unpack.add_code(assign_code)
|
|
98
120
|
update.add_code(assign_code)
|
|
99
121
|
|
|
100
|
-
assign_code =
|
|
101
|
-
# {assigns} = values
|
|
122
|
+
assign_code = f"{assigns_expr} = values" # 生成 iter_xxx 的赋值语句
|
|
102
123
|
iter_unpack_inner.add_code(assign_code)
|
|
103
124
|
iter_update_inner.add_code(assign_code)
|
|
104
125
|
|
|
105
|
-
assign_code =
|
|
106
|
-
# {assigns} = _unpack_from(buffer, offset)
|
|
126
|
+
assign_code = f"{assigns_expr} = _unpack_from(buffer, offset)" # 生成 xxx_from 的赋值语句
|
|
107
127
|
unpack_from.add_code(assign_code)
|
|
108
128
|
update_from.add_code(assign_code)
|
|
109
129
|
|
|
@@ -145,6 +165,13 @@ def create_unpack_methods(cls: type[struct_type.Struct]):
|
|
|
145
165
|
if array_fields:
|
|
146
166
|
unpack.insert_code(0, 'buffer = memoryview(buffer)')
|
|
147
167
|
|
|
168
|
+
|
|
169
|
+
for init in post_inits:
|
|
170
|
+
batch_add_code(
|
|
171
|
+
[unpack, update, unpack_from, update_from, iter_unpack_inner, iter_update_inner],
|
|
172
|
+
f"{init}.__post_unpack__()"
|
|
173
|
+
)
|
|
174
|
+
|
|
148
175
|
unpack.add_return('self')
|
|
149
176
|
update.add_return('self')
|
|
150
177
|
unpack_from.add_return('self')
|
|
@@ -156,12 +183,12 @@ def create_unpack_methods(cls: type[struct_type.Struct]):
|
|
|
156
183
|
for n, *_ in array_fields:
|
|
157
184
|
iter_update_inner.add_code(f'{n}.clear()')
|
|
158
185
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
186
|
+
print(unpack.generate_code())
|
|
187
|
+
print(update.generate_code())
|
|
188
|
+
print(unpack_from.generate_code())
|
|
189
|
+
print(update_from.generate_code())
|
|
190
|
+
print(iter_unpack.generate_code())
|
|
191
|
+
print(iter_update.generate_code())
|
|
165
192
|
|
|
166
193
|
globals = {
|
|
167
194
|
v: k for k, v in inner_classes.items() # 翻转字典
|
|
@@ -81,6 +81,13 @@ class StructMeta(type):
|
|
|
81
81
|
create_unpack_methods(cls)
|
|
82
82
|
)
|
|
83
83
|
|
|
84
|
+
def __getattr__(self, item):
|
|
85
|
+
if item in self.__struct_methods__:
|
|
86
|
+
self.__compile_struct__()
|
|
87
|
+
return getattr(self, item)
|
|
88
|
+
|
|
89
|
+
raise AttributeError(item)
|
|
90
|
+
|
|
84
91
|
|
|
85
92
|
endian_mapping = {
|
|
86
93
|
'little': '<',
|
|
@@ -21,6 +21,9 @@ class MyStruct(obs.Struct):
|
|
|
21
21
|
k: obs.unsigned_char
|
|
22
22
|
l: obs.long_long
|
|
23
23
|
|
|
24
|
+
def __post_unpack__(self):
|
|
25
|
+
...
|
|
26
|
+
|
|
24
27
|
|
|
25
28
|
@dataclasses.dataclass()
|
|
26
29
|
class AnotherStruct(obs.Struct):
|
|
@@ -36,15 +39,15 @@ print('MyStruct size', MyStruct.__cstruct__.size)
|
|
|
36
39
|
print('AnotherStruct size', AnotherStruct.__cstruct__.size)
|
|
37
40
|
|
|
38
41
|
|
|
39
|
-
data = MyStruct(
|
|
40
|
-
|
|
41
|
-
)
|
|
42
|
-
|
|
43
|
-
packed_data = data.pack()
|
|
42
|
+
# data = MyStruct(
|
|
43
|
+
# 1,2,1.0,4,5,6,7,8,9,b'8',1,2
|
|
44
|
+
# )
|
|
45
|
+
#
|
|
46
|
+
# packed_data = data.pack()
|
|
44
47
|
|
|
45
48
|
|
|
46
|
-
complex_data = AnotherStruct(data, array('i', [100]*100), data)
|
|
47
|
-
packed_complex_data = complex_data.pack()
|
|
49
|
+
# complex_data = AnotherStruct(data, array('i', [100]*100), data)
|
|
50
|
+
# packed_complex_data = complex_data.pack()
|
|
48
51
|
|
|
49
52
|
|
|
50
53
|
def test_timeit(name, code):
|
|
@@ -71,31 +74,31 @@ def test_timeit(name, code):
|
|
|
71
74
|
print(f'Average: {sum(res)/(len(res))/NUMBER:.3f} ns per step', '\n\n')
|
|
72
75
|
|
|
73
76
|
|
|
74
|
-
print("\n\nMyStruct:", MyStruct.__cstruct__.size)
|
|
77
|
+
# print("\n\nMyStruct:", MyStruct.__cstruct__.size)
|
|
75
78
|
print("AnotherStruct:", AnotherStruct.__cstruct__.size, '\n\n')
|
|
76
79
|
|
|
77
80
|
NUMBER = 10000
|
|
78
81
|
REPEAT = 128
|
|
79
82
|
SORT = 32
|
|
80
83
|
|
|
81
|
-
test_timeit(
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
)
|
|
85
|
-
|
|
86
|
-
test_timeit(
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
)
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
test_timeit(
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
)
|
|
97
|
-
|
|
98
|
-
test_timeit(
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
)
|
|
84
|
+
# test_timeit(
|
|
85
|
+
# name='Pack',
|
|
86
|
+
# code="""data.pack()""",
|
|
87
|
+
# )
|
|
88
|
+
#
|
|
89
|
+
# test_timeit(
|
|
90
|
+
# name='Unpack',
|
|
91
|
+
# code="""MyStruct.unpack(packed_data)""",
|
|
92
|
+
# )
|
|
93
|
+
#
|
|
94
|
+
#
|
|
95
|
+
#
|
|
96
|
+
# test_timeit(
|
|
97
|
+
# name='Complex Pack',
|
|
98
|
+
# code="""complex_data.pack()""",
|
|
99
|
+
# )
|
|
100
|
+
#
|
|
101
|
+
# test_timeit(
|
|
102
|
+
# name='Complex Unpack',
|
|
103
|
+
# code="""AnotherStruct.unpack(packed_complex_data)""",
|
|
104
|
+
# )
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
version = "0.2.14"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|