obstruct 0.2.1__tar.gz → 0.2.2__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 (34) hide show
  1. {obstruct-0.2.1 → obstruct-0.2.2}/.idea/Hydrogenlib-Objective-Struct.iml +1 -1
  2. obstruct-0.2.2/.idea/misc.xml +4 -0
  3. obstruct-0.2.2/.idea/vcs.xml +6 -0
  4. obstruct-0.2.2/.idea/workspace.xml +170 -0
  5. obstruct-0.2.2/PKG-INFO +76 -0
  6. obstruct-0.2.2/README.md +62 -0
  7. obstruct-0.2.2/src/obstruct/__version__.py +1 -0
  8. {obstruct-0.2.1 → obstruct-0.2.2}/src/obstruct/aot/base.py +1 -5
  9. {obstruct-0.2.1 → obstruct-0.2.2}/src/obstruct/aot/unpack.py +1 -1
  10. {obstruct-0.2.1 → obstruct-0.2.2}/src/obstruct/decorator.py +2 -9
  11. {obstruct-0.2.1 → obstruct-0.2.2}/src/obstruct/methods.py +4 -6
  12. obstruct-0.2.2/src/obstruct/types/types.pyi +33 -0
  13. obstruct-0.2.2/test/test.py +28 -0
  14. obstruct-0.2.2/test/test_speed.py +59 -0
  15. {obstruct-0.2.1 → obstruct-0.2.2}/uv.lock +14 -14
  16. obstruct-0.2.1/.hydro-ignore +0 -0
  17. obstruct-0.2.1/.idea/workspace.xml +0 -4
  18. obstruct-0.2.1/PKG-INFO +0 -12
  19. obstruct-0.2.1/README.md +0 -0
  20. obstruct-0.2.1/src/obstruct/__version__.py +0 -1
  21. obstruct-0.2.1/src/obstruct/types/types.pyi +0 -67
  22. {obstruct-0.2.1 → obstruct-0.2.2}/.idea/.gitignore +0 -0
  23. {obstruct-0.2.1 → obstruct-0.2.2}/.idea/inspectionProfiles/Project_Default.xml +0 -0
  24. {obstruct-0.2.1 → obstruct-0.2.2}/.idea/inspectionProfiles/profiles_settings.xml +0 -0
  25. {obstruct-0.2.1 → obstruct-0.2.2}/.idea/modules.xml +0 -0
  26. {obstruct-0.2.1 → obstruct-0.2.2}/pyproject.toml +0 -0
  27. {obstruct-0.2.1 → obstruct-0.2.2}/src/obstruct/__init__.py +0 -0
  28. {obstruct-0.2.1 → obstruct-0.2.2}/src/obstruct/aot/__init__.py +0 -0
  29. {obstruct-0.2.1 → obstruct-0.2.2}/src/obstruct/aot/aot.py +0 -0
  30. {obstruct-0.2.1 → obstruct-0.2.2}/src/obstruct/aot/pack.py +0 -0
  31. {obstruct-0.2.1 → obstruct-0.2.2}/src/obstruct/struct_type.py +0 -0
  32. {obstruct-0.2.1 → obstruct-0.2.2}/src/obstruct/types/__init__.py +0 -0
  33. {obstruct-0.2.1 → obstruct-0.2.2}/src/obstruct/types/base.py +0 -0
  34. {obstruct-0.2.1 → obstruct-0.2.2}/src/obstruct/types/types.py +0 -0
@@ -5,7 +5,7 @@
5
5
  <sourceFolder url="file://$MODULE_DIR$/src" />
6
6
  <excludeFolder url="file://$MODULE_DIR$/.venv" />
7
7
  </content>
8
- <orderEntry type="inheritedJdk" />
8
+ <orderEntry type="jdk" jdkName="E:\.projects\obstruct\.venv" jdkType="Python SDK" />
9
9
  <orderEntry type="sourceFolder" forTests="false" />
10
10
  </component>
11
11
  <component name="PackageRequirementsSettings" />
@@ -0,0 +1,4 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <project version="4">
3
+ <component name="ProjectRootManager" version="2" project-jdk-name="E:\.projects\obstruct\.venv" project-jdk-type="Python SDK" />
4
+ </project>
@@ -0,0 +1,6 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <project version="4">
3
+ <component name="VcsDirectoryMappings">
4
+ <mapping directory="$PROJECT_DIR$" vcs="Git" />
5
+ </component>
6
+ </project>
@@ -0,0 +1,170 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <project version="4">
3
+ <component name="AutoImportSettings">
4
+ <option name="autoReloadType" value="SELECTIVE" />
5
+ </component>
6
+ <component name="ChangeListManager">
7
+ <list default="true" id="b482b6b4-48ce-4be1-bf3c-a72ec254fa35" name="更改" comment="initial commit">
8
+ <change beforePath="$PROJECT_DIR$/README.md" beforeDir="false" afterPath="$PROJECT_DIR$/README.md" afterDir="false" />
9
+ <change beforePath="$PROJECT_DIR$/src/obstruct/aot/base.py" beforeDir="false" afterPath="$PROJECT_DIR$/src/obstruct/aot/base.py" afterDir="false" />
10
+ <change beforePath="$PROJECT_DIR$/src/obstruct/aot/unpack.py" beforeDir="false" afterPath="$PROJECT_DIR$/src/obstruct/aot/unpack.py" afterDir="false" />
11
+ <change beforePath="$PROJECT_DIR$/src/obstruct/decorator.py" beforeDir="false" afterPath="$PROJECT_DIR$/src/obstruct/decorator.py" afterDir="false" />
12
+ <change beforePath="$PROJECT_DIR$/src/obstruct/methods.py" beforeDir="false" afterPath="$PROJECT_DIR$/src/obstruct/methods.py" afterDir="false" />
13
+ <change beforePath="$PROJECT_DIR$/uv.lock" beforeDir="false" afterPath="$PROJECT_DIR$/uv.lock" afterDir="false" />
14
+ </list>
15
+ <option name="SHOW_DIALOG" value="false" />
16
+ <option name="HIGHLIGHT_CONFLICTS" value="true" />
17
+ <option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
18
+ <option name="LAST_RESOLUTION" value="IGNORE" />
19
+ </component>
20
+ <component name="FileTemplateManagerImpl">
21
+ <option name="RECENT_TEMPLATES">
22
+ <list>
23
+ <option value="Python Script" />
24
+ </list>
25
+ </option>
26
+ </component>
27
+ <component name="Git.Settings">
28
+ <option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
29
+ </component>
30
+ <component name="GitHubPullRequestSearchHistory"><![CDATA[{
31
+ "lastFilter": {
32
+ "state": "OPEN",
33
+ "assignee": "LittleNightSong"
34
+ }
35
+ }]]></component>
36
+ <component name="GithubPullRequestsUISettings"><![CDATA[{
37
+ "selectedUrlAndAccountId": {
38
+ "url": "https://github.com/LittleNightSong/obstruct.git",
39
+ "accountId": "c74c50b1-2437-429b-b395-d763b566b8a2"
40
+ }
41
+ }]]></component>
42
+ <component name="ProjectColorInfo"><![CDATA[{
43
+ "associatedIndex": 3,
44
+ "fromUser": false
45
+ }]]></component>
46
+ <component name="ProjectId" id="3HzAgHvw3X1T2NidzBlYQSHnZow" />
47
+ <component name="ProjectViewState">
48
+ <option name="hideEmptyMiddlePackages" value="true" />
49
+ <option name="showLibraryContents" value="true" />
50
+ </component>
51
+ <component name="PropertiesComponent"><![CDATA[{
52
+ "keyToString": {
53
+ "ModuleVcsDetector.initialDetectionPerformed": "true",
54
+ "Python.test.executor": "Run",
55
+ "Python.test_speed.executor": "Run",
56
+ "RunOnceActivity.ShowReadmeOnStart": "true",
57
+ "RunOnceActivity.typescript.service.memoryLimit.init": "true",
58
+ "codeWithMe.voiceChat.enabledByDefault": "false",
59
+ "git-widget-placeholder": "main",
60
+ "last_opened_file_path": "E:/.projects/obstruct",
61
+ "node.js.detected.package.eslint": "true",
62
+ "node.js.detected.package.jshint": "true",
63
+ "node.js.detected.package.tslint": "true",
64
+ "node.js.selected.package.eslint": "(autodetect)",
65
+ "node.js.selected.package.jshint": "",
66
+ "node.js.selected.package.tslint": "(autodetect)",
67
+ "nodejs_package_manager_path": "npm"
68
+ }
69
+ }]]></component>
70
+ <component name="RunManager" selected="Python.test_speed">
71
+ <configuration name="test" type="PythonConfigurationType" factoryName="Python" temporary="true" nameIsGenerated="true">
72
+ <module name="Hydrogenlib-Objective-Struct" />
73
+ <option name="ENV_FILES" value="" />
74
+ <option name="INTERPRETER_OPTIONS" value="" />
75
+ <option name="PARENT_ENVS" value="true" />
76
+ <envs>
77
+ <env name="PYTHONUNBUFFERED" value="1" />
78
+ </envs>
79
+ <option name="SDK_HOME" value="" />
80
+ <option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/test" />
81
+ <option name="IS_MODULE_SDK" value="true" />
82
+ <option name="ADD_CONTENT_ROOTS" value="true" />
83
+ <option name="ADD_SOURCE_ROOTS" value="true" />
84
+ <option name="DEBUG_JUST_MY_CODE" value="false" />
85
+ <option name="RUN_TOOL" value="" />
86
+ <option name="SCRIPT_NAME" value="$PROJECT_DIR$/test/test.py" />
87
+ <option name="PARAMETERS" value="" />
88
+ <option name="SHOW_COMMAND_LINE" value="false" />
89
+ <option name="EMULATE_TERMINAL" value="false" />
90
+ <option name="MODULE_MODE" value="false" />
91
+ <option name="REDIRECT_INPUT" value="false" />
92
+ <option name="INPUT_FILE" value="" />
93
+ <method v="2" />
94
+ </configuration>
95
+ <configuration name="test_speed" type="PythonConfigurationType" factoryName="Python" temporary="true" nameIsGenerated="true">
96
+ <module name="Hydrogenlib-Objective-Struct" />
97
+ <option name="ENV_FILES" value="" />
98
+ <option name="INTERPRETER_OPTIONS" value="" />
99
+ <option name="PARENT_ENVS" value="true" />
100
+ <envs>
101
+ <env name="PYTHONUNBUFFERED" value="1" />
102
+ </envs>
103
+ <option name="SDK_HOME" value="" />
104
+ <option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/test" />
105
+ <option name="IS_MODULE_SDK" value="true" />
106
+ <option name="ADD_CONTENT_ROOTS" value="true" />
107
+ <option name="ADD_SOURCE_ROOTS" value="true" />
108
+ <option name="DEBUG_JUST_MY_CODE" value="false" />
109
+ <option name="RUN_TOOL" value="" />
110
+ <option name="SCRIPT_NAME" value="$PROJECT_DIR$/test/test_speed.py" />
111
+ <option name="PARAMETERS" value="" />
112
+ <option name="SHOW_COMMAND_LINE" value="false" />
113
+ <option name="EMULATE_TERMINAL" value="false" />
114
+ <option name="MODULE_MODE" value="false" />
115
+ <option name="REDIRECT_INPUT" value="false" />
116
+ <option name="INPUT_FILE" value="" />
117
+ <method v="2" />
118
+ </configuration>
119
+ <recent_temporary>
120
+ <list>
121
+ <item itemvalue="Python.test_speed" />
122
+ <item itemvalue="Python.test" />
123
+ </list>
124
+ </recent_temporary>
125
+ </component>
126
+ <component name="SharedIndexes">
127
+ <attachedChunks>
128
+ <set>
129
+ <option value="bundled-python-sdk-821f704e66d9-5bd6d13a2a75-com.jetbrains.pycharm.pro.sharedIndexes.bundled-PY-262.9437.214" />
130
+ </set>
131
+ </attachedChunks>
132
+ </component>
133
+ <component name="TaskManager">
134
+ <task active="true" id="Default" summary="默认任务">
135
+ <changelist id="b482b6b4-48ce-4be1-bf3c-a72ec254fa35" name="更改" comment="" />
136
+ <created>1786860632989</created>
137
+ <option name="number" value="Default" />
138
+ <option name="presentableId" value="Default" />
139
+ <updated>1786860632989</updated>
140
+ </task>
141
+ <task id="LOCAL-00001" summary="initial commit">
142
+ <option name="closed" value="true" />
143
+ <created>1786865208583</created>
144
+ <option name="number" value="00001" />
145
+ <option name="presentableId" value="LOCAL-00001" />
146
+ <option name="project" value="LOCAL" />
147
+ <updated>1786865208583</updated>
148
+ </task>
149
+ <option name="localTasksCounter" value="2" />
150
+ <servers />
151
+ </component>
152
+ <component name="TypeScriptGeneratedFilesManager">
153
+ <option name="version" value="3" />
154
+ </component>
155
+ <component name="Vcs.Log.Tabs.Properties">
156
+ <option name="TAB_STATES">
157
+ <map>
158
+ <entry key="MAIN">
159
+ <value>
160
+ <State />
161
+ </value>
162
+ </entry>
163
+ </map>
164
+ </option>
165
+ </component>
166
+ <component name="VcsManagerConfiguration">
167
+ <MESSAGE value="initial commit" />
168
+ <option name="LAST_COMMIT_MESSAGE" value="initial commit" />
169
+ </component>
170
+ </project>
@@ -0,0 +1,76 @@
1
+ Metadata-Version: 2.5
2
+ Name: obstruct
3
+ Version: 0.2.2
4
+ Author-email: LittleNightSong <LittleNightSongYO@outlook.com>
5
+ Classifier: Development Status :: 3 - Alpha
6
+ Classifier: Programming Language :: Python
7
+ Classifier: Programming Language :: Python :: 3.11
8
+ Classifier: Programming Language :: Python :: 3.12
9
+ Classifier: Programming Language :: Python :: 3.13
10
+ Classifier: Programming Language :: Python :: Implementation :: CPython
11
+ Classifier: Programming Language :: Python :: Implementation :: PyPy
12
+ Requires-Python: >=3.12
13
+ Description-Content-Type: text/markdown
14
+
15
+ _来自已弃坑的 `Hydrogenlib`,重拾起当初的决心_
16
+
17
+
18
+ >[!TIP]
19
+ > 这个项目来自 [`HydrogenLib`](https://github.com/LittleNightSong/HydrogenLib)的 `Objective-Struct` 模块,脱离大项目的版本
20
+ >
21
+ > 同时,`HydrogenLib`中的 `Objective-Struct` 不再会更新
22
+
23
+
24
+ # OBStruct
25
+ _一个简单、纯粹、极速的二进制解析库_
26
+
27
+ ## 亮点
28
+ - 基于类型注解的字段声明方式
29
+ - 支持 `struct` 标准库中的所有格式,并额外支持 array 类型
30
+ - 基于 AOT 的加速
31
+ - 完整的操作支持(打包、解包、流式处理)
32
+
33
+ ## 安装
34
+ ```commandline
35
+ pip install obstruct
36
+ ```
37
+ 如果使用 `uv` 等包管理器,则按照工具的方法安装即可
38
+
39
+
40
+ ## 用法
41
+
42
+ 首先声明一个 `Struct` 类型,它是一个 `dataclass`,也是一个 `struct`
43
+
44
+ ```python
45
+ import obstruct as obs
46
+ from dataclasses import dataclass
47
+
48
+ @obs.struct()
49
+ @dataclass()
50
+ class MyStruct(obs.Struct):
51
+ a: int
52
+ b: float
53
+ c: obs.long
54
+ d: obs.unsigned_short
55
+
56
+
57
+ if __name__ == '__main__':
58
+ data = MyStruct(a=0, b=2.0, c=10000, d=14545)
59
+
60
+ packed_data = data.pack()
61
+ print(packed_data)
62
+
63
+ restored = MyStruct.unpack(packed_data)
64
+ print(restored)
65
+
66
+ print(data == restored)
67
+
68
+ ```
69
+
70
+ 在上述示例中,你可能发现 `data != restored`,这是浮点数的精度限制导致的
71
+ 一般来说,我们不建议使用浮点数类型
72
+
73
+ ## 计划
74
+ - 展平装饰器,目前的 API 较为繁琐,需要简化为唯一的 `Struct` 基类
75
+ - 继续优化性能
76
+ - 通过存根文件强制表明类型似乎变得不再有效了
@@ -0,0 +1,62 @@
1
+ _来自已弃坑的 `Hydrogenlib`,重拾起当初的决心_
2
+
3
+
4
+ >[!TIP]
5
+ > 这个项目来自 [`HydrogenLib`](https://github.com/LittleNightSong/HydrogenLib)的 `Objective-Struct` 模块,脱离大项目的版本
6
+ >
7
+ > 同时,`HydrogenLib`中的 `Objective-Struct` 不再会更新
8
+
9
+
10
+ # OBStruct
11
+ _一个简单、纯粹、极速的二进制解析库_
12
+
13
+ ## 亮点
14
+ - 基于类型注解的字段声明方式
15
+ - 支持 `struct` 标准库中的所有格式,并额外支持 array 类型
16
+ - 基于 AOT 的加速
17
+ - 完整的操作支持(打包、解包、流式处理)
18
+
19
+ ## 安装
20
+ ```commandline
21
+ pip install obstruct
22
+ ```
23
+ 如果使用 `uv` 等包管理器,则按照工具的方法安装即可
24
+
25
+
26
+ ## 用法
27
+
28
+ 首先声明一个 `Struct` 类型,它是一个 `dataclass`,也是一个 `struct`
29
+
30
+ ```python
31
+ import obstruct as obs
32
+ from dataclasses import dataclass
33
+
34
+ @obs.struct()
35
+ @dataclass()
36
+ class MyStruct(obs.Struct):
37
+ a: int
38
+ b: float
39
+ c: obs.long
40
+ d: obs.unsigned_short
41
+
42
+
43
+ if __name__ == '__main__':
44
+ data = MyStruct(a=0, b=2.0, c=10000, d=14545)
45
+
46
+ packed_data = data.pack()
47
+ print(packed_data)
48
+
49
+ restored = MyStruct.unpack(packed_data)
50
+ print(restored)
51
+
52
+ print(data == restored)
53
+
54
+ ```
55
+
56
+ 在上述示例中,你可能发现 `data != restored`,这是浮点数的精度限制导致的
57
+ 一般来说,我们不建议使用浮点数类型
58
+
59
+ ## 计划
60
+ - 展平装饰器,目前的 API 较为繁琐,需要简化为唯一的 `Struct` 基类
61
+ - 继续优化性能
62
+ - 通过存根文件强制表明类型似乎变得不再有效了
@@ -0,0 +1 @@
1
+ version = "0.2.2"
@@ -5,9 +5,6 @@ import itertools
5
5
  import typing
6
6
  from typing import Any
7
7
 
8
- import typing_inspection.typing_objects
9
-
10
- from _hydrogenlib_core.typefunc import enhanced_generator
11
8
  from obstruct.methods import get_ctype
12
9
 
13
10
 
@@ -113,7 +110,6 @@ available_characters = tuple(
113
110
  )
114
111
 
115
112
 
116
- @enhanced_generator(history=True)
117
113
  def unique_name_generator():
118
114
  cnt = 0
119
115
  while True:
@@ -127,7 +123,7 @@ def is_struct(tp):
127
123
 
128
124
 
129
125
  def is_array(tp):
130
- if typing_inspection.typing_objects.is_annotated(typing.get_origin(tp)):
126
+ if typing.get_origin(tp) is typing.Annotated:
131
127
  return True
132
128
  return False
133
129
 
@@ -112,7 +112,7 @@ def create_unpack_methods(cls: type[struct_type.Struct]):
112
112
  # print(unpack_from.generate_code())
113
113
  # print(update_from.generate_code())
114
114
  # print(iter_unpack.generate_code())
115
- print(iter_update.generate_code())
115
+ # print(iter_update.generate_code())
116
116
 
117
117
  globals = {
118
118
  v: k for k, v in inner_classes.items() # 翻转字典
@@ -9,24 +9,17 @@ endian_control_characters = tuple('<@=!>')
9
9
 
10
10
 
11
11
  def struct(maybe_cls=None, *, endian='@'):
12
- def decorator[T](cls: T) -> type[struct_type.Struct]:
12
+ def decorator[T](cls: T) -> T:
13
13
  import struct
14
-
15
- # module = sys.modules[cls.__module__]
16
-
17
14
  fields = dataclasses.fields(cls)
18
- # namesp = module.__dict__
19
- # print(namesp)
20
15
  real_annotations = typing.get_type_hints(cls)
21
- # print(cls, real_annotations)
22
16
 
23
17
  for field in fields:
24
- print(cls, field.name, repr(field.type))
18
+ # print(cls, field.name, repr(field.type))
25
19
  if isinstance(field.type, str):
26
20
  field.type = real_annotations[field.name]
27
21
 
28
22
  cls.__ctype__ = to_format_string([field.type for field in fields])
29
- # print(cls.__ctype__)
30
23
  cls.__cfields__ = tuple(fields) # type: tuple[dataclasses.Field, ...]
31
24
  cls.__cstruct__ = struct.Struct(endian + cls.__ctype__) # 构造 Struct 类型
32
25
  cls.__cendian__ = endian
@@ -1,8 +1,6 @@
1
1
  import struct
2
2
  from collections.abc import Buffer
3
- from typing import Any, Sequence, Iterator, get_args, get_origin
4
-
5
- from typing_inspection.typing_objects import is_annotated
3
+ from typing import Any, Sequence, Iterator, get_args, get_origin, Annotated, cast
6
4
 
7
5
  from .struct_type import CType
8
6
 
@@ -13,14 +11,14 @@ mapping = {
13
11
  CTypesFields = Sequence[str | CType | type] | Iterator[str | CType | type]
14
12
 
15
13
 
16
- def get_ctype(tp):
14
+ def get_ctype(tp) -> str:
17
15
  if isinstance(tp, str):
18
16
  return tp
19
17
  elif _ := getattr(tp, '__ctype__', None):
20
- return _
18
+ return cast(str, _)
21
19
  elif _ := mapping.get(tp):
22
20
  return _
23
- elif is_annotated(get_origin(tp)):
21
+ elif get_origin(tp) is Annotated:
24
22
  # 目前需要 Annotated 的类型只有 array
25
23
  tp_args = get_args(tp)
26
24
  dtype = get_args(tp_args[0])[0]
@@ -0,0 +1,33 @@
1
+ import sys
2
+
3
+
4
+ def pad(size: int) -> type: ...
5
+
6
+
7
+ char = bytes
8
+ signed_char = int
9
+ unsigned_char = int
10
+ long = int
11
+ unsigned_long = int
12
+ short = int
13
+ unsigned_short = int
14
+ unsigned_int = int
15
+ long_long = int
16
+ unsigned_long_long = int
17
+ double = float
18
+ short_float = float
19
+ size_t = int
20
+ ssize_t = int
21
+
22
+
23
+ def string(length: int) -> type[bytes]: ...
24
+
25
+
26
+ def pascal_string(length: int) -> type[bytes]: ...
27
+
28
+
29
+ pointer = int
30
+
31
+ if sys.version_info >= (3, 14, 0):
32
+ float_complex = complex
33
+ double_complex = complex
@@ -0,0 +1,28 @@
1
+ import dataclasses
2
+
3
+ import obstruct as obs
4
+ from obstruct import Struct
5
+
6
+
7
+ @obs.struct()
8
+ @dataclasses.dataclass(slots=True)
9
+ class MyStruct(Struct):
10
+ a: int
11
+ b: int
12
+ c: float
13
+ d: obs.double_complex
14
+
15
+
16
+
17
+ if __name__ == '__main__':
18
+ data = MyStruct(15, 20, 1.2, 8 + 7j)
19
+ print(data)
20
+
21
+ packed_data = data.pack()
22
+
23
+ print(packed_data)
24
+
25
+ restored = MyStruct.unpack(packed_data)
26
+ print(restored)
27
+
28
+ print(data == restored)
@@ -0,0 +1,59 @@
1
+ import dataclasses
2
+ import time
3
+
4
+ import obstruct as obs
5
+
6
+
7
+ @obs.struct()
8
+ @dataclasses.dataclass(slots=True)
9
+ class MyStruct(obs.Struct):
10
+ a: int
11
+ b: int
12
+ c: float
13
+ d: int
14
+ e: obs.short
15
+ f: obs.unsigned_short
16
+ g: obs.long
17
+ h: obs.unsigned_long
18
+ i: obs.unsigned_long
19
+ j: obs.char
20
+ k: obs.unsigned_char
21
+ l: obs.long_long
22
+
23
+
24
+
25
+ data = MyStruct(
26
+ 1,2,1.0,4,5,6,7,8,9,b'8',1,2
27
+ )
28
+
29
+
30
+ packed_data = data.pack()
31
+
32
+
33
+ def test_timeit(name, code):
34
+ import timeit
35
+
36
+ print("Test: ", name)
37
+ res = timeit.timeit(
38
+ code,
39
+ number=NUMBER,
40
+ timer=time.perf_counter_ns,
41
+ globals=globals()
42
+ )
43
+ print(f'{NUMBER} steps finished in {res:.3f} ns')
44
+ print(f'Average: {res/NUMBER:.3f} ns per step', '\n\n')
45
+
46
+
47
+ NUMBER = 10000
48
+
49
+ test_timeit(
50
+ name='Pack',
51
+ code="""data.pack()""",
52
+ )
53
+
54
+ test_timeit(
55
+ name='Unpack',
56
+ code="""MyStruct.unpack(packed_data)""",
57
+ )
58
+
59
+
@@ -303,20 +303,6 @@ wheels = [
303
303
  { url = "https://mirrors.aliyun.com/pypi/packages/9b/43/832f631d32e4f1211caa2ba368317739fe71f0b8530e4c9d15dc454bac2a/httpx2_jsfetch-1.0-py3-none-any.whl", hash = "sha256:cb916b707601e69a07721aabc8f3f6659be3a6893bc1ff5c6f9e02241df2da32" },
304
304
  ]
305
305
 
306
- [[package]]
307
- name = "hydrogenlib-objective-struct"
308
- source = { editable = "." }
309
-
310
- [package.dev-dependencies]
311
- dev = [
312
- { name = "hatch" },
313
- ]
314
-
315
- [package.metadata]
316
-
317
- [package.metadata.requires-dev]
318
- dev = [{ name = "hatch", specifier = ">=1.18.0" }]
319
-
320
306
  [[package]]
321
307
  name = "hyperlink"
322
308
  version = "21.0.0"
@@ -427,6 +413,20 @@ wheels = [
427
413
  { url = "https://mirrors.aliyun.com/pypi/packages/e8/3d/1087453384dbde46a8c7f9356eead2c58be8a7bf156bca40243377c85715/more_itertools-11.1.0-py3-none-any.whl", hash = "sha256:4b65538ae22f6fed0ce4874efd317463a7489796a0939fa66824dd542125a192" },
428
414
  ]
429
415
 
416
+ [[package]]
417
+ name = "obstruct"
418
+ source = { editable = "." }
419
+
420
+ [package.dev-dependencies]
421
+ dev = [
422
+ { name = "hatch" },
423
+ ]
424
+
425
+ [package.metadata]
426
+
427
+ [package.metadata.requires-dev]
428
+ dev = [{ name = "hatch", specifier = ">=1.18.0" }]
429
+
430
430
  [[package]]
431
431
  name = "packaging"
432
432
  version = "26.3"
File without changes
@@ -1,4 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <project version="4">
3
- <component name="PropertiesComponent">{}</component>
4
- </project>
obstruct-0.2.1/PKG-INFO DELETED
@@ -1,12 +0,0 @@
1
- Metadata-Version: 2.5
2
- Name: obstruct
3
- Version: 0.2.1
4
- Author-email: LittleNightSong <LittleNightSongYO@outlook.com>
5
- Classifier: Development Status :: 3 - Alpha
6
- Classifier: Programming Language :: Python
7
- Classifier: Programming Language :: Python :: 3.11
8
- Classifier: Programming Language :: Python :: 3.12
9
- Classifier: Programming Language :: Python :: 3.13
10
- Classifier: Programming Language :: Python :: Implementation :: CPython
11
- Classifier: Programming Language :: Python :: Implementation :: PyPy
12
- Requires-Python: >=3.12
obstruct-0.2.1/README.md DELETED
File without changes
@@ -1 +0,0 @@
1
- version = "0.2.1"
@@ -1,67 +0,0 @@
1
- import sys
2
- from typing import Literal, Sequence
3
-
4
-
5
- class _ctype:
6
- __ctype__: str
7
-
8
-
9
- def pad(size: int) -> type: ...
10
-
11
-
12
- class char(bytes, _ctype): ...
13
-
14
-
15
- class signed_char(int, _ctype): ...
16
-
17
-
18
- class unsigned_char(int, _ctype): ...
19
-
20
-
21
- class long(int, _ctype): ...
22
-
23
-
24
- class unsigned_long(int, _ctype): ...
25
-
26
-
27
- class short(int, _ctype): ...
28
-
29
-
30
- class unsigned_short(int, _ctype): ...
31
-
32
-
33
- class unsigned_int(int, _ctype): ...
34
-
35
-
36
- class long_long(int, _ctype): ...
37
-
38
-
39
- class unsigned_long_long(int, _ctype): ...
40
-
41
-
42
- class double(float, _ctype): ...
43
-
44
-
45
- class short_float(float, _ctype): ...
46
-
47
-
48
- class size_t(int, _ctype): ...
49
-
50
-
51
- class ssize_t(int, _ctype): ...
52
-
53
-
54
- def string(length: int) -> type[bytes]: ...
55
-
56
-
57
- def pascal_string(length: int) -> type[bytes]: ...
58
-
59
-
60
- class pointer(int, _ctype): ...
61
-
62
-
63
- if sys.version_info >= (3, 14, 0):
64
- class float_complex(complex, _ctype): ...
65
-
66
-
67
- class double_complex(complex, _ctype): ...
File without changes
File without changes
File without changes