reproto 0.1.1__py3-none-any.whl → 0.1.2__py3-none-any.whl
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.
- .git/COMMIT_EDITMSG +30 -1
- .git/index +0 -0
- .git/logs/HEAD +1 -0
- .git/logs/refs/heads/iyue +1 -0
- .git/logs/refs/remotes/gitlab/iyue +1 -0
- .git/logs/refs/remotes/origin/iyue +1 -0
- .git/objects/03/3fab23ccc74b707a31f6f37dc5df42c100aac0 +0 -0
- .git/objects/07/b71df33935c14ddf99e3480c04eca4685028bc +0 -0
- .git/objects/0b/e20ea749c6ae1075ae98f9426e00b0a4a235af +0 -0
- .git/objects/13/5f50fea51c72f977f48d06a7584aba0f61e260 +0 -0
- .git/objects/1b/97584ebada3e93d7a2cfa4a1aae0b79c414d20 +0 -0
- .git/objects/1b/f0c1ad9586578e8332d061f7648dcb041ec063 +0 -0
- .git/objects/1e/46816d16e7c9db7575f1964403c3daa105be5c +0 -0
- .git/objects/27/24208ca2442e8ab9b453d0eb230fa41243b270 +0 -0
- .git/objects/2d/2b812ca27c477f9e1b2c2706a5eb795ffcf8eb +0 -0
- .git/objects/3f/b8830f516342a0ae1cb7c34b65016827cb9570 +4 -0
- .git/objects/41/f40c22247de377be99e30784229f3f128508a2 +0 -0
- .git/objects/48/cb11e75518a53be14146018214110986fade67 +0 -0
- .git/objects/4f/c6dc41f9c0a1a8e0eedd3ba49c43d78d0dbaba +0 -0
- .git/objects/59/4c23f158ccbd0a4288f9ea046d06160195afbf +0 -0
- .git/objects/5b/d4d87753b79e9157817f0c2e6964a731052854 +0 -0
- .git/objects/65/0189fe083bd711e45d463b229a72be619abad2 +0 -0
- .git/objects/66/663db35bfec8ef5f1a5b1c840fde1bb62a0eb8 +0 -0
- .git/objects/8a/0ed0ed8886fbc823e8d2258fa6d18699e94e25 +0 -0
- .git/objects/8d/d857b3d0ab3f5cd2e9173d532ef86e30df8eda +0 -0
- .git/objects/9e/23448ac58f907d9d123c32bdccedbb3d6741b5 +0 -0
- .git/objects/a0/d192999af7e2cbfa6a9ccd04d720a04e5a06d5 +0 -0
- .git/objects/a9/cc7923c34a4c97c5711d6309672f41d46c612a +0 -0
- .git/objects/af/c9cc15629847447063e86a82b8b56abb4fc08f +0 -0
- .git/objects/b1/db1c131cf32916028342c0037ce8eb57a8eb26 +0 -0
- .git/objects/b2/8334b94392b8af397a05ed702690fa6c9ab1ca +0 -0
- .git/objects/b8/7c89dcfce9e244ff5ef6a4bd394de12e8c8092 +0 -0
- .git/objects/d9/3bd435c8c7ad4efb83dff04d5450fabb9e3faf +0 -0
- .git/objects/e3/27755808d88c7ae5c06c229cf18bd0519646df +0 -0
- .git/objects/e5/83e7c40be934d16a1fa2e973487b395d930f42 +0 -0
- .git/objects/ed/1ae867d5e63195845afc58d88c38ecbdea97df +0 -0
- .git/objects/ef/f44e5099da27f7fb1ef14bb34902ccf4250b89 +0 -0
- .git/objects/f5/1be495b96272fa2e47f30071aed35ac1f0dd2c +0 -0
- .git/objects/fd/0bc07dc3c95e6168ab6d367d9eca139ac1e539 +0 -0
- .git/refs/heads/iyue +1 -1
- .git/refs/remotes/gitlab/iyue +1 -1
- .git/refs/remotes/origin/iyue +1 -1
- .gitignore +2 -1
- core/info_decoder.py +507 -6
- core/reconstructor.py +135 -6
- generation/proto_generator.py +51 -11
- include/google/protobuf/any.proto +162 -0
- include/google/protobuf/api.proto +207 -0
- include/google/protobuf/compiler/plugin.proto +180 -0
- include/google/protobuf/cpp_features.proto +67 -0
- include/google/protobuf/descriptor.proto +1417 -0
- include/google/protobuf/duration.proto +115 -0
- include/google/protobuf/empty.proto +51 -0
- include/google/protobuf/field_mask.proto +245 -0
- include/google/protobuf/go_features.proto +80 -0
- include/google/protobuf/java_features.proto +130 -0
- include/google/protobuf/source_context.proto +48 -0
- include/google/protobuf/struct.proto +95 -0
- include/google/protobuf/timestamp.proto +144 -0
- include/google/protobuf/type.proto +193 -0
- include/google/protobuf/wrappers.proto +157 -0
- parsing/java_parser.py +295 -12
- pyproject.toml +1 -1
- {reproto-0.1.1.dist-info → reproto-0.1.2.dist-info}/METADATA +1 -1
- {reproto-0.1.1.dist-info → reproto-0.1.2.dist-info}/RECORD +69 -20
- utils/builtin_proto.py +262 -0
- utils/type_utils.py +39 -6
- {reproto-0.1.1.dist-info → reproto-0.1.2.dist-info}/WHEEL +0 -0
- {reproto-0.1.1.dist-info → reproto-0.1.2.dist-info}/entry_points.txt +0 -0
utils/builtin_proto.py
ADDED
@@ -0,0 +1,262 @@
|
|
1
|
+
"""
|
2
|
+
Google Protobuf 内置类型管理模块
|
3
|
+
处理内置proto文件的检测、拷贝和导入语句生成
|
4
|
+
"""
|
5
|
+
|
6
|
+
import os
|
7
|
+
import shutil
|
8
|
+
from pathlib import Path
|
9
|
+
from typing import Dict, Set, Optional
|
10
|
+
from utils.logger import logger
|
11
|
+
|
12
|
+
|
13
|
+
def find_include_directory() -> Optional[Path]:
|
14
|
+
"""
|
15
|
+
查找include目录,支持开发环境和安装包环境
|
16
|
+
|
17
|
+
Returns:
|
18
|
+
include目录的路径,如果找不到则返回None
|
19
|
+
"""
|
20
|
+
# 尝试多个可能的位置
|
21
|
+
possible_locations = [
|
22
|
+
# 1. 相对于当前文件的位置(开发环境)
|
23
|
+
Path(__file__).parent.parent / "include",
|
24
|
+
|
25
|
+
# 2. 相对于包安装位置(安装包环境)
|
26
|
+
Path(__file__).parent.parent.parent / "include",
|
27
|
+
|
28
|
+
# 3. 在site-packages中的位置
|
29
|
+
Path(__file__).parent / "include",
|
30
|
+
|
31
|
+
# 4. 使用pkg_resources查找(如果可用)
|
32
|
+
]
|
33
|
+
|
34
|
+
# 尝试使用pkg_resources(推荐方式)
|
35
|
+
try:
|
36
|
+
import pkg_resources
|
37
|
+
try:
|
38
|
+
include_path = Path(pkg_resources.resource_filename('reproto', 'include'))
|
39
|
+
if include_path.exists():
|
40
|
+
possible_locations.insert(0, include_path)
|
41
|
+
except (pkg_resources.DistributionNotFound, FileNotFoundError):
|
42
|
+
pass
|
43
|
+
except ImportError:
|
44
|
+
pass
|
45
|
+
|
46
|
+
# 尝试使用importlib.resources(Python 3.9+推荐方式)
|
47
|
+
try:
|
48
|
+
import importlib.resources as resources
|
49
|
+
try:
|
50
|
+
# 对于Python 3.9+
|
51
|
+
if hasattr(resources, 'files'):
|
52
|
+
include_ref = resources.files('reproto') / 'include'
|
53
|
+
if include_ref.is_dir():
|
54
|
+
possible_locations.insert(0, Path(str(include_ref)))
|
55
|
+
except Exception:
|
56
|
+
pass
|
57
|
+
except ImportError:
|
58
|
+
pass
|
59
|
+
|
60
|
+
# 按优先级检查每个位置
|
61
|
+
for location in possible_locations:
|
62
|
+
if location.exists() and location.is_dir():
|
63
|
+
# 验证这确实是包含proto文件的include目录
|
64
|
+
wrappers_file = location / "google" / "protobuf" / "wrappers.proto"
|
65
|
+
if wrappers_file.exists():
|
66
|
+
logger.debug(f"找到include目录: {location}")
|
67
|
+
return location
|
68
|
+
|
69
|
+
logger.error("无法找到include目录")
|
70
|
+
return None
|
71
|
+
|
72
|
+
|
73
|
+
class BuiltinProtoManager:
|
74
|
+
"""Google Protobuf 内置proto文件管理器"""
|
75
|
+
|
76
|
+
# 内置类型到proto文件的映射
|
77
|
+
_BUILTIN_TYPE_TO_FILE = {
|
78
|
+
# Wrapper types - 都在 wrappers.proto 中
|
79
|
+
'google.protobuf.BoolValue': 'google/protobuf/wrappers.proto',
|
80
|
+
'google.protobuf.Int32Value': 'google/protobuf/wrappers.proto',
|
81
|
+
'google.protobuf.Int64Value': 'google/protobuf/wrappers.proto',
|
82
|
+
'google.protobuf.UInt32Value': 'google/protobuf/wrappers.proto',
|
83
|
+
'google.protobuf.UInt64Value': 'google/protobuf/wrappers.proto',
|
84
|
+
'google.protobuf.FloatValue': 'google/protobuf/wrappers.proto',
|
85
|
+
'google.protobuf.DoubleValue': 'google/protobuf/wrappers.proto',
|
86
|
+
'google.protobuf.StringValue': 'google/protobuf/wrappers.proto',
|
87
|
+
'google.protobuf.BytesValue': 'google/protobuf/wrappers.proto',
|
88
|
+
|
89
|
+
# Well-known types
|
90
|
+
'google.protobuf.Any': 'google/protobuf/any.proto',
|
91
|
+
'google.protobuf.Timestamp': 'google/protobuf/timestamp.proto',
|
92
|
+
'google.protobuf.Duration': 'google/protobuf/duration.proto',
|
93
|
+
'google.protobuf.Empty': 'google/protobuf/empty.proto',
|
94
|
+
'google.protobuf.Struct': 'google/protobuf/struct.proto',
|
95
|
+
'google.protobuf.Value': 'google/protobuf/struct.proto',
|
96
|
+
'google.protobuf.ListValue': 'google/protobuf/struct.proto',
|
97
|
+
'google.protobuf.NullValue': 'google/protobuf/struct.proto',
|
98
|
+
'google.protobuf.FieldMask': 'google/protobuf/field_mask.proto',
|
99
|
+
|
100
|
+
# API types
|
101
|
+
'google.protobuf.Api': 'google/protobuf/api.proto',
|
102
|
+
'google.protobuf.Method': 'google/protobuf/api.proto',
|
103
|
+
'google.protobuf.Mixin': 'google/protobuf/api.proto',
|
104
|
+
|
105
|
+
# Type definitions
|
106
|
+
'google.protobuf.Type': 'google/protobuf/type.proto',
|
107
|
+
'google.protobuf.Field': 'google/protobuf/type.proto',
|
108
|
+
'google.protobuf.Enum': 'google/protobuf/type.proto',
|
109
|
+
'google.protobuf.EnumValue': 'google/protobuf/type.proto',
|
110
|
+
'google.protobuf.Option': 'google/protobuf/type.proto',
|
111
|
+
'google.protobuf.Syntax': 'google/protobuf/type.proto',
|
112
|
+
|
113
|
+
# Source context
|
114
|
+
'google.protobuf.SourceContext': 'google/protobuf/source_context.proto',
|
115
|
+
}
|
116
|
+
|
117
|
+
def __init__(self, include_dir: str, output_dir: str):
|
118
|
+
"""
|
119
|
+
初始化内置proto管理器
|
120
|
+
|
121
|
+
Args:
|
122
|
+
include_dir: include目录路径
|
123
|
+
output_dir: 输出目录路径
|
124
|
+
"""
|
125
|
+
self.include_dir = Path(include_dir)
|
126
|
+
self.output_dir = Path(output_dir)
|
127
|
+
self._copied_files: Set[str] = set()
|
128
|
+
|
129
|
+
def is_builtin_type(self, proto_type: str) -> bool:
|
130
|
+
"""
|
131
|
+
检查是否为内置类型
|
132
|
+
|
133
|
+
Args:
|
134
|
+
proto_type: proto类型名称
|
135
|
+
|
136
|
+
Returns:
|
137
|
+
是否为内置类型
|
138
|
+
"""
|
139
|
+
return proto_type in self._BUILTIN_TYPE_TO_FILE
|
140
|
+
|
141
|
+
def get_import_path(self, proto_type: str) -> Optional[str]:
|
142
|
+
"""
|
143
|
+
获取内置类型的导入路径
|
144
|
+
|
145
|
+
Args:
|
146
|
+
proto_type: proto类型名称
|
147
|
+
|
148
|
+
Returns:
|
149
|
+
导入路径,如果不是内置类型则返回None
|
150
|
+
"""
|
151
|
+
return self._BUILTIN_TYPE_TO_FILE.get(proto_type)
|
152
|
+
|
153
|
+
def ensure_builtin_proto_file(self, proto_type: str) -> bool:
|
154
|
+
"""
|
155
|
+
确保内置proto文件存在于输出目录中
|
156
|
+
|
157
|
+
Args:
|
158
|
+
proto_type: proto类型名称
|
159
|
+
|
160
|
+
Returns:
|
161
|
+
是否成功处理
|
162
|
+
"""
|
163
|
+
if not self.is_builtin_type(proto_type):
|
164
|
+
return False
|
165
|
+
|
166
|
+
import_path = self.get_import_path(proto_type)
|
167
|
+
if not import_path:
|
168
|
+
return False
|
169
|
+
|
170
|
+
# 如果已经拷贝过,直接返回
|
171
|
+
if import_path in self._copied_files:
|
172
|
+
return True
|
173
|
+
|
174
|
+
# 源文件路径
|
175
|
+
source_file = self.include_dir / import_path
|
176
|
+
if not source_file.exists():
|
177
|
+
logger.error(f"内置proto文件不存在: {source_file}")
|
178
|
+
return False
|
179
|
+
|
180
|
+
# 目标文件路径
|
181
|
+
target_file = self.output_dir / import_path
|
182
|
+
|
183
|
+
# 创建目标目录
|
184
|
+
target_file.parent.mkdir(parents=True, exist_ok=True)
|
185
|
+
|
186
|
+
try:
|
187
|
+
# 拷贝文件
|
188
|
+
shutil.copy2(source_file, target_file)
|
189
|
+
self._copied_files.add(import_path)
|
190
|
+
logger.info(f"📄 拷贝内置proto文件: {import_path}")
|
191
|
+
return True
|
192
|
+
except Exception as e:
|
193
|
+
logger.error(f"拷贝内置proto文件失败: {source_file} -> {target_file}, 错误: {e}")
|
194
|
+
return False
|
195
|
+
|
196
|
+
def process_dependencies(self, dependencies: Set[str]) -> Dict[str, str]:
|
197
|
+
"""
|
198
|
+
处理依赖列表,返回需要的导入语句映射
|
199
|
+
|
200
|
+
Args:
|
201
|
+
dependencies: 依赖类型集合
|
202
|
+
|
203
|
+
Returns:
|
204
|
+
类型名到导入路径的映射
|
205
|
+
"""
|
206
|
+
imports = {}
|
207
|
+
|
208
|
+
for dep_type in dependencies:
|
209
|
+
if self.is_builtin_type(dep_type):
|
210
|
+
import_path = self.get_import_path(dep_type)
|
211
|
+
if import_path and self.ensure_builtin_proto_file(dep_type):
|
212
|
+
imports[dep_type] = import_path
|
213
|
+
|
214
|
+
return imports
|
215
|
+
|
216
|
+
def get_copied_files(self) -> Set[str]:
|
217
|
+
"""
|
218
|
+
获取已拷贝的文件列表
|
219
|
+
|
220
|
+
Returns:
|
221
|
+
已拷贝文件路径的集合
|
222
|
+
"""
|
223
|
+
return self._copied_files.copy()
|
224
|
+
|
225
|
+
|
226
|
+
# 全局实例(在需要时初始化)
|
227
|
+
_builtin_manager: Optional[BuiltinProtoManager] = None
|
228
|
+
|
229
|
+
|
230
|
+
def get_builtin_manager(include_dir: str = None, output_dir: str = None) -> BuiltinProtoManager:
|
231
|
+
"""
|
232
|
+
获取全局内置proto管理器实例
|
233
|
+
|
234
|
+
Args:
|
235
|
+
include_dir: include目录路径(可选,如果不提供会自动查找)
|
236
|
+
output_dir: 输出目录路径(首次调用时必需)
|
237
|
+
|
238
|
+
Returns:
|
239
|
+
BuiltinProtoManager实例
|
240
|
+
"""
|
241
|
+
global _builtin_manager
|
242
|
+
|
243
|
+
if _builtin_manager is None:
|
244
|
+
if output_dir is None:
|
245
|
+
raise ValueError("首次调用get_builtin_manager时必须提供output_dir")
|
246
|
+
|
247
|
+
# 如果没有提供include_dir,自动查找
|
248
|
+
if include_dir is None:
|
249
|
+
include_path = find_include_directory()
|
250
|
+
if include_path is None:
|
251
|
+
raise ValueError("无法找到include目录,请手动指定include_dir参数")
|
252
|
+
include_dir = str(include_path)
|
253
|
+
|
254
|
+
_builtin_manager = BuiltinProtoManager(include_dir, output_dir)
|
255
|
+
|
256
|
+
return _builtin_manager
|
257
|
+
|
258
|
+
|
259
|
+
def reset_builtin_manager():
|
260
|
+
"""重置全局内置proto管理器(主要用于测试)"""
|
261
|
+
global _builtin_manager
|
262
|
+
_builtin_manager = None
|
utils/type_utils.py
CHANGED
@@ -169,9 +169,17 @@ class TypeMapper:
|
|
169
169
|
"""获取类型所需的导入语句"""
|
170
170
|
imports = []
|
171
171
|
if cls.is_well_known_type(proto_type):
|
172
|
-
#
|
173
|
-
|
174
|
-
|
172
|
+
# 使用内置proto管理器获取正确的导入路径
|
173
|
+
try:
|
174
|
+
from utils.builtin_proto import get_builtin_manager
|
175
|
+
builtin_manager = get_builtin_manager()
|
176
|
+
import_path = builtin_manager.get_import_path(proto_type)
|
177
|
+
if import_path:
|
178
|
+
imports.append(import_path)
|
179
|
+
except (ImportError, ValueError):
|
180
|
+
# 如果内置管理器不可用,使用旧逻辑作为后备
|
181
|
+
type_name = proto_type.split('.')[-1].lower()
|
182
|
+
imports.append(f"google/protobuf/{type_name}.proto")
|
175
183
|
return imports
|
176
184
|
|
177
185
|
@classmethod
|
@@ -227,7 +235,7 @@ class NamingConverter:
|
|
227
235
|
@staticmethod
|
228
236
|
def to_snake_case(camel_str: str) -> str:
|
229
237
|
"""
|
230
|
-
将CamelCase转换为snake_case
|
238
|
+
将CamelCase转换为snake_case,同时处理$符号
|
231
239
|
|
232
240
|
Args:
|
233
241
|
camel_str: 驼峰命名字符串
|
@@ -238,11 +246,18 @@ class NamingConverter:
|
|
238
246
|
if not camel_str:
|
239
247
|
return camel_str
|
240
248
|
|
249
|
+
# 首先处理$符号:将$替换为_,处理内部类和匿名类
|
250
|
+
s0 = camel_str.replace('$', '_')
|
251
|
+
|
241
252
|
# 处理连续大写字母:XMLParser -> XML_Parser
|
242
|
-
s1 = re.sub('(.)([A-Z][a-z]+)', r'\1_\2',
|
253
|
+
s1 = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', s0)
|
243
254
|
# 处理小写字母后跟大写字母:userId -> user_Id
|
244
255
|
s2 = re.sub('([a-z0-9])([A-Z])', r'\1_\2', s1)
|
245
|
-
|
256
|
+
|
257
|
+
# 清理多余的下划线:将连续的下划线替换为单个下划线
|
258
|
+
s3 = re.sub('_+', '_', s2)
|
259
|
+
|
260
|
+
return s3.lower()
|
246
261
|
|
247
262
|
@staticmethod
|
248
263
|
def to_pascal_case(snake_str: str) -> str:
|
@@ -281,6 +296,24 @@ class NamingConverter:
|
|
281
296
|
|
282
297
|
# 第一个单词保持小写,其余单词首字母大写
|
283
298
|
return components[0].lower() + ''.join(word.capitalize() for word in components[1:] if word)
|
299
|
+
|
300
|
+
@staticmethod
|
301
|
+
def clean_proto_name(name: str) -> str:
|
302
|
+
"""
|
303
|
+
清理proto名称中的$符号,用于消息和枚举名称
|
304
|
+
|
305
|
+
Args:
|
306
|
+
name: 原始名称(可能包含$符号)
|
307
|
+
|
308
|
+
Returns:
|
309
|
+
清理后的名称
|
310
|
+
"""
|
311
|
+
if not name:
|
312
|
+
return name
|
313
|
+
|
314
|
+
# 将$替换为空字符串,这样Models$Device变成ModelsDevice
|
315
|
+
# 这符合proto命名规范,避免语法错误
|
316
|
+
return name.replace('$', '')
|
284
317
|
|
285
318
|
|
286
319
|
class FieldNameProcessor:
|
File without changes
|
File without changes
|