PinInPy 1.0.1__cp310-cp310-win_amd64.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.
- PinInPy/PinIn4Cpp/LICENSE +21 -0
- PinInPy/PinIn4Cpp/licenses/PinIn.txt +21 -0
- PinInPy/PinIn4Cpp/licenses/pinyin-data.txt +21 -0
- PinInPy/__init__.py +379 -0
- PinInPy/_pinin4cpp_cffi.pyd +0 -0
- pininpy-1.0.1.dist-info/METADATA +90 -0
- pininpy-1.0.1.dist-info/RECORD +9 -0
- pininpy-1.0.1.dist-info/WHEEL +5 -0
- pininpy-1.0.1.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 KagiyamaHina
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2019 Juntong Liu
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2016 mozillazg
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
PinInPy/__init__.py
ADDED
|
@@ -0,0 +1,379 @@
|
|
|
1
|
+
from ._pinin4cpp_cffi import lib,ffi
|
|
2
|
+
from enum import IntEnum
|
|
3
|
+
import cffi
|
|
4
|
+
|
|
5
|
+
_pffi = ffi
|
|
6
|
+
|
|
7
|
+
ffi = cffi.FFI()
|
|
8
|
+
|
|
9
|
+
__version__ = "1.0.1"
|
|
10
|
+
__all__ = ["PinIn", "TreeSearcher", "Logic", "Keyboard", "PinInConfig", "DeserializeException", "PinInInitException", "TreeSearcherInitException"]
|
|
11
|
+
|
|
12
|
+
def _create_pinin(handle):
|
|
13
|
+
if handle == ffi.NULL:
|
|
14
|
+
return None
|
|
15
|
+
return ffi.gc(handle,lib.PinInCpp_PinIn_Free)
|
|
16
|
+
|
|
17
|
+
def _create_tree_searcher(handle):
|
|
18
|
+
if handle == ffi.NULL:
|
|
19
|
+
return None
|
|
20
|
+
return ffi.gc(handle,lib.PinInCpp_TreeSearcher_Free)
|
|
21
|
+
|
|
22
|
+
class Logic(IntEnum):
|
|
23
|
+
'''匹配逻辑,传递给TreeSearcher用的'''
|
|
24
|
+
BEGIN = lib.PinInCpp_BEGIN
|
|
25
|
+
'''前缀匹配:必须从字符串开头开始匹配'''
|
|
26
|
+
CONTAIN = lib.PinInCpp_CONTAIN
|
|
27
|
+
'''部分匹配:匹配字符串中的任意位置字串'''
|
|
28
|
+
EQUAL = lib.PinInCpp_EQUAL
|
|
29
|
+
'''完全匹配:字面意思'''
|
|
30
|
+
|
|
31
|
+
class Keyboard(IntEnum):
|
|
32
|
+
'''不能自定义的预设键位枚举'''
|
|
33
|
+
NULLKeyboard = lib.PinInCpp_NULLKeyboard
|
|
34
|
+
'''代表不改变Keyboard,特殊的枚举量'''
|
|
35
|
+
QUANPIN = lib.PinInCpp_QUANPIN
|
|
36
|
+
'''基础的全拼方案 PinIn类的默认方案'''
|
|
37
|
+
DAQIAN = lib.PinInCpp_DAQIAN
|
|
38
|
+
'''注音(大千)输入法方案'''
|
|
39
|
+
XIAOHE = lib.PinInCpp_XIAOHE
|
|
40
|
+
'''小鹤双拼方案'''
|
|
41
|
+
ZIRANMA = lib.PinInCpp_ZIRANMA
|
|
42
|
+
'''自然码双拼方案'''
|
|
43
|
+
SOUGOU = lib.PinInCpp_SOUGOU
|
|
44
|
+
'''搜狗双拼方案'''
|
|
45
|
+
ZHINENG_ABC = lib.PinInCpp_ZHINENG_ABC
|
|
46
|
+
'''智能ABC双拼方案'''
|
|
47
|
+
GUOBIAO = lib.PinInCpp_GUOBIAO
|
|
48
|
+
'''国标双拼方案'''
|
|
49
|
+
MICROSOFT = lib.PinInCpp_MICROSOFT
|
|
50
|
+
'''微软双拼方案'''
|
|
51
|
+
PINYINPP = lib.PinInCpp_PINYINPP
|
|
52
|
+
'''拼音加加双拼方案'''
|
|
53
|
+
ZIGUANG = lib.PinInCpp_ZIGUANG
|
|
54
|
+
'''紫光双拼方案'''
|
|
55
|
+
|
|
56
|
+
class PinInConfig:
|
|
57
|
+
'''配置PinIn的匹配逻辑,一定要调用commit方法,不然设置是不会生效的'''
|
|
58
|
+
__pinin:PinIn
|
|
59
|
+
'''PinInConfig所属的PinIn对象'''
|
|
60
|
+
keyboard:Keyboard
|
|
61
|
+
'''键位枚举'''
|
|
62
|
+
fZh2Z:bool
|
|
63
|
+
'''zh -> z模糊音'''
|
|
64
|
+
fSh2S:bool
|
|
65
|
+
'''sh -> s模糊音'''
|
|
66
|
+
fCh2C:bool
|
|
67
|
+
'''ch -> c模糊音'''
|
|
68
|
+
fAng2An:bool
|
|
69
|
+
'''ang -> an模糊音'''
|
|
70
|
+
fIng2In:bool
|
|
71
|
+
'''ing -> in模糊音'''
|
|
72
|
+
fEng2En:bool
|
|
73
|
+
'''eng -> en模糊音'''
|
|
74
|
+
fU2V:bool
|
|
75
|
+
'''u -> v模糊音'''
|
|
76
|
+
fFirstChar:bool
|
|
77
|
+
'''实际上是强制把首字母加入到匹配列表,但是全拼匹配有序列匹配的逻辑,所以实际上一定程度上有首字母匹配,但是开启这个可以把一些更加不严格的拼音搜索匹配到。比如:toding == 铜锭,只会在这个生效的时候有用'''
|
|
78
|
+
def __init__(self, pinin:PinIn):
|
|
79
|
+
self.__pinin = pinin
|
|
80
|
+
rawCfg = lib.PinInCpp_PinIn_GetConfig(pinin.cdata)
|
|
81
|
+
self.keyboard = rawCfg.keyboard
|
|
82
|
+
self.fZh2Z = rawCfg.fZh2Z != bytes([0])
|
|
83
|
+
self.fSh2S = rawCfg.fSh2S != bytes([0])
|
|
84
|
+
self.fCh2C = rawCfg.fCh2C != bytes([0])
|
|
85
|
+
self.fAng2An = rawCfg.fAng2An != bytes([0])
|
|
86
|
+
self.fIng2In = rawCfg.fIng2In != bytes([0])
|
|
87
|
+
self.fEng2En = rawCfg.fEng2En != bytes([0])
|
|
88
|
+
self.fU2V = rawCfg.fU2V != bytes([0])
|
|
89
|
+
self.fFirstChar = rawCfg.fFirstChar != bytes([0])
|
|
90
|
+
def set_keyboard(self, keyboard:Keyboard):
|
|
91
|
+
'''
|
|
92
|
+
设置 keyboard 字段为输入参数
|
|
93
|
+
'''
|
|
94
|
+
self.keyboard = keyboard
|
|
95
|
+
return self
|
|
96
|
+
def set_fZh2Z(self, enable:bool):
|
|
97
|
+
'''
|
|
98
|
+
设置 fZh2Z 字段为输入参数
|
|
99
|
+
'''
|
|
100
|
+
self.fZh2Z = enable
|
|
101
|
+
return self
|
|
102
|
+
def set_fSh2S(self, enable:bool):
|
|
103
|
+
'''
|
|
104
|
+
设置 fSh2S 字段为输入参数
|
|
105
|
+
'''
|
|
106
|
+
self.fSh2S = enable
|
|
107
|
+
return self
|
|
108
|
+
def set_fCh2C(self, enable:bool):
|
|
109
|
+
'''
|
|
110
|
+
设置 fCh2C 字段为输入参数
|
|
111
|
+
'''
|
|
112
|
+
self.fCh2C = enable
|
|
113
|
+
return self
|
|
114
|
+
def set_fAng2An(self, enable:bool):
|
|
115
|
+
'''
|
|
116
|
+
设置 fAng2An 字段为输入参数
|
|
117
|
+
'''
|
|
118
|
+
self.fAng2An = enable
|
|
119
|
+
return self
|
|
120
|
+
def set_fIng2In(self, enable:bool):
|
|
121
|
+
'''
|
|
122
|
+
设置 fIng2In 字段为输入参数
|
|
123
|
+
'''
|
|
124
|
+
self.fIng2In = enable
|
|
125
|
+
return self
|
|
126
|
+
def set_fEng2En(self, enable:bool):
|
|
127
|
+
'''
|
|
128
|
+
设置 fEng2En 字段为输入参数
|
|
129
|
+
'''
|
|
130
|
+
self.fEng2En = enable
|
|
131
|
+
return self
|
|
132
|
+
def set_fU2V(self, enable:bool):
|
|
133
|
+
'''
|
|
134
|
+
设置 fU2V 字段为输入参数
|
|
135
|
+
'''
|
|
136
|
+
self.fU2V = enable
|
|
137
|
+
return self
|
|
138
|
+
def set_fFirstChar(self, enable:bool):
|
|
139
|
+
'''
|
|
140
|
+
设置 fFirstChar 字段为输入参数
|
|
141
|
+
'''
|
|
142
|
+
self.fFirstChar = enable
|
|
143
|
+
return self
|
|
144
|
+
|
|
145
|
+
def commit(self):
|
|
146
|
+
'''
|
|
147
|
+
提交所更改的配置以生效
|
|
148
|
+
'''
|
|
149
|
+
rawCfg = lib.PinInCpp_PinIn_GetConfig(self.__pinin.cdata)
|
|
150
|
+
rawCfg.keyboard = self.keyboard
|
|
151
|
+
rawCfg.fZh2Z = bytes([self.fZh2Z and 1 or 0])
|
|
152
|
+
rawCfg.fSh2S = bytes([self.fSh2S and 1 or 0])
|
|
153
|
+
rawCfg.fCh2C = bytes([self.fCh2C and 1 or 0])
|
|
154
|
+
rawCfg.fAng2An = bytes([self.fAng2An and 1 or 0])
|
|
155
|
+
rawCfg.fIng2In = bytes([self.fIng2In and 1 or 0])
|
|
156
|
+
rawCfg.fEng2En = bytes([self.fEng2En and 1 or 0])
|
|
157
|
+
rawCfg.fU2V = bytes([self.fU2V and 1 or 0])
|
|
158
|
+
rawCfg.fFirstChar = bytes([self.fFirstChar and 1 or 0])
|
|
159
|
+
lib.PinInCpp_PinIn_ConfigCommit(self.__pinin.cdata, rawCfg)
|
|
160
|
+
pass
|
|
161
|
+
|
|
162
|
+
class DeserializeException(Exception):
|
|
163
|
+
'''PinIn4Cpp反序列化时出现的错误'''
|
|
164
|
+
message = "Normal?"
|
|
165
|
+
code = "PinInCpp_DeserNormal"
|
|
166
|
+
def __init__(self, code):
|
|
167
|
+
if code == lib.PinInCpp_FileNotOpen:
|
|
168
|
+
self.code = "PinInCpp_FileNotOpen"
|
|
169
|
+
self.message = "File not successfully opened"
|
|
170
|
+
elif code == lib.PinInCpp_DeserBinaryVersionInvalidException:
|
|
171
|
+
self.code = "PinInCpp_DeserBinaryVersionInvalidException"
|
|
172
|
+
self.message = "Invalid binary file version"
|
|
173
|
+
elif code == lib.PinInCpp_DeserOutOfRange:
|
|
174
|
+
self.code = "PinInCpp_DeserOutOfRange"
|
|
175
|
+
self.message = "out-of-range exceptions"
|
|
176
|
+
elif code == lib.PinInCpp_DeserBadAlloc:
|
|
177
|
+
self.code = "PinInCpp_DeserBadAlloc"
|
|
178
|
+
self.message = "bad allocation"
|
|
179
|
+
|
|
180
|
+
def __str__(self):
|
|
181
|
+
return f"{self.code}: {self.message}"
|
|
182
|
+
|
|
183
|
+
class PinInInitException(Exception):
|
|
184
|
+
'''PinIn初始化失败异常'''
|
|
185
|
+
filename = None
|
|
186
|
+
def __init__(self, filename):
|
|
187
|
+
self.filename = filename
|
|
188
|
+
pass
|
|
189
|
+
def __str__(self):
|
|
190
|
+
return f"PinInInitException: Please check if the {self.filename} file is valid"
|
|
191
|
+
|
|
192
|
+
class TreeSearcherInitException(Exception):
|
|
193
|
+
'''TreeSearcher初始化失败异常'''
|
|
194
|
+
filename = None
|
|
195
|
+
def __init__(self, filename):
|
|
196
|
+
self.filename = filename
|
|
197
|
+
pass
|
|
198
|
+
def __str__(self):
|
|
199
|
+
return f"TreeSearcherInitException: Please check if the {self.filename} file is valid. Or check the PinIn object."
|
|
200
|
+
|
|
201
|
+
class PinIn:
|
|
202
|
+
'''拼音的配置类'''
|
|
203
|
+
cdata = None
|
|
204
|
+
def __init__(self, path:str):
|
|
205
|
+
self.cdata = _create_pinin(lib.PinInCpp_PinIn_New(path.encode("utf-8")))
|
|
206
|
+
if self.cdata == None:
|
|
207
|
+
raise PinInInitException(path)
|
|
208
|
+
|
|
209
|
+
@staticmethod
|
|
210
|
+
def deserialize(path:str, keyboard:Keyboard = Keyboard.NULLKeyboard)->PinIn:
|
|
211
|
+
'''
|
|
212
|
+
反序列化指定路径上的文件返回PinIn对象,keyboard为NULLKeyboard的时候加载默认的全拼
|
|
213
|
+
'''
|
|
214
|
+
pinin_getter = _pffi.new("PinInCpp_PinIn[1]")
|
|
215
|
+
deser_error = lib.PinInCpp_PinIn_Deserialize(path.encode("utf-8"),keyboard,pinin_getter)
|
|
216
|
+
if deser_error != lib.PinInCpp_DeserNormal:
|
|
217
|
+
raise DeserializeException(deser_error)
|
|
218
|
+
result = PinIn.__new__(PinIn)
|
|
219
|
+
result.cdata = _create_pinin(pinin_getter[0])
|
|
220
|
+
return result
|
|
221
|
+
|
|
222
|
+
def serialize(self, path:str)->bool:
|
|
223
|
+
'''序列化PinIn类到指定的路径上'''
|
|
224
|
+
return lib.PinInCpp_PinIn_Serialize(self.cdata, path.encode("utf-8")) != 0
|
|
225
|
+
|
|
226
|
+
def get_config(self)->PinInConfig:
|
|
227
|
+
'''获取config对象以配置PinIn'''
|
|
228
|
+
return PinInConfig(self)
|
|
229
|
+
|
|
230
|
+
def is_empty(self)->bool:
|
|
231
|
+
'''判断PinIn是否为空,其实一般来讲没什么用'''
|
|
232
|
+
return lib.PinInCpp_PinIn_Empty(self.cdata) != 0
|
|
233
|
+
|
|
234
|
+
def pre_cache_string(self, input_str:str):
|
|
235
|
+
'''缓存输入的字符串中的汉字字符'''
|
|
236
|
+
lib.PinInCpp_PinIn_PreCacheString(self.cdata, input_str.encode("utf-8"))
|
|
237
|
+
|
|
238
|
+
def pre_null_pinyin_id_cache(self):
|
|
239
|
+
'''将空拼音id的字符也缓存进去'''
|
|
240
|
+
lib.PinInCpp_PinIn_PreNullPinyinIdCache(self.cdata)
|
|
241
|
+
|
|
242
|
+
def is_char_cache_enabled(self)->bool:
|
|
243
|
+
'''判断是否开启字符缓存'''
|
|
244
|
+
return lib.PinInCpp_PinIn_IsCharCacheEnabled(self.cdata) != 0
|
|
245
|
+
|
|
246
|
+
def set_char_cache(self, enable:bool):
|
|
247
|
+
'''
|
|
248
|
+
设置是否开启字符串缓存
|
|
249
|
+
|
|
250
|
+
警告!!!关闭后可能会导致严重性能下降,而字符本身并不是内存占用大头
|
|
251
|
+
'''
|
|
252
|
+
lib.PinInCpp_PinIn_SetCharCache(self.cdata, enable and 1 or 0)
|
|
253
|
+
|
|
254
|
+
|
|
255
|
+
class TreeSearcher:
|
|
256
|
+
'''用于搜索的搜索树'''
|
|
257
|
+
cdata = None
|
|
258
|
+
def __init__(self, logic:Logic, PathOrPinIn:str|PinIn):
|
|
259
|
+
temp_handle = None
|
|
260
|
+
if type(PathOrPinIn) == str:
|
|
261
|
+
temp_handle = lib.PinInCpp_TreeSearcher_NewPath(logic, PathOrPinIn.encode("utf-8"))
|
|
262
|
+
else:
|
|
263
|
+
temp_handle = lib.PinInCpp_TreeSearcher_NewPinIn(logic, PathOrPinIn.cdata)
|
|
264
|
+
self.cdata = _create_tree_searcher(temp_handle)
|
|
265
|
+
if self.cdata == None:
|
|
266
|
+
raise TreeSearcherInitException(PathOrPinIn)
|
|
267
|
+
|
|
268
|
+
@staticmethod
|
|
269
|
+
def deserialize(path:str, pinin:PinIn)->TreeSearcher:
|
|
270
|
+
'''
|
|
271
|
+
反序列化指定路径上的文件返回TreeSearcher对象,必须提供PinIn上下文
|
|
272
|
+
'''
|
|
273
|
+
tree_getter = _pffi.new("PinInCpp_TreeSearcher[1]")
|
|
274
|
+
deser_error = lib.PinInCpp_TreeSearcher_Deserialize(path.encode("utf-8"),pinin.cdata,tree_getter)
|
|
275
|
+
if deser_error != lib.PinInCpp_DeserNormal:
|
|
276
|
+
raise DeserializeException(deser_error)
|
|
277
|
+
result = TreeSearcher.__new__(TreeSearcher)
|
|
278
|
+
result.cdata = _create_tree_searcher(tree_getter[0])
|
|
279
|
+
return result
|
|
280
|
+
|
|
281
|
+
|
|
282
|
+
def get_pinin(self):
|
|
283
|
+
'''获取这个搜索树的PinIn上下文'''
|
|
284
|
+
empty_pinin = PinIn.__new__(PinIn)
|
|
285
|
+
empty_pinin.cdata = _create_pinin(lib.PinInCpp_TreeSearcher_GetPinIn(self.cdata))
|
|
286
|
+
if empty_pinin.cdata == None:
|
|
287
|
+
raise Exception("PinIn: nullptr error")
|
|
288
|
+
return empty_pinin
|
|
289
|
+
|
|
290
|
+
def serialize(self, path:str)->bool:
|
|
291
|
+
'''序列化TreeSearcher类到指定的路径上'''
|
|
292
|
+
return lib.PinInCpp_TreeSearcher_Serialize(self.cdata, path.encode("utf-8")) != 0
|
|
293
|
+
|
|
294
|
+
def put_string(self, item:str) -> int:
|
|
295
|
+
'''
|
|
296
|
+
放入待搜索项
|
|
297
|
+
|
|
298
|
+
:param self: self
|
|
299
|
+
:param item: 待搜索项
|
|
300
|
+
:type item: str
|
|
301
|
+
:return: TreeSearcher内部的字符串id
|
|
302
|
+
:rtype: int
|
|
303
|
+
'''
|
|
304
|
+
return lib.PinInCpp_TreeSearcher_PutString(self.cdata, item.encode("utf-8"))
|
|
305
|
+
|
|
306
|
+
def execute_search(self, search_str:str)->list[str]:
|
|
307
|
+
'''执行搜索并返回字符串数组'''
|
|
308
|
+
resultData = lib.PinInCpp_TreeSearcher_ExecuteSearch(self.cdata, search_str.encode("utf-8"))
|
|
309
|
+
resultData = ffi.gc(resultData, lib.PinInCpp_SearchResult_Free)
|
|
310
|
+
|
|
311
|
+
bufSize = -1
|
|
312
|
+
buf = None
|
|
313
|
+
|
|
314
|
+
result = []
|
|
315
|
+
resultSize = resultData.size
|
|
316
|
+
|
|
317
|
+
if resultSize == 0:
|
|
318
|
+
return result
|
|
319
|
+
id_list = ffi.unpack(resultData.ids, resultSize)
|
|
320
|
+
|
|
321
|
+
for id in id_list:
|
|
322
|
+
size = lib.PinInCpp_TreeSearcher_GetStrSizeById(self.cdata, id) + 1
|
|
323
|
+
|
|
324
|
+
if size > bufSize:
|
|
325
|
+
bufSize = size * 2
|
|
326
|
+
buf = ffi.new("char[]", bufSize)
|
|
327
|
+
lib.PinInCpp_TreeSearcher_PutToCharBuf(self.cdata, id, buf, bufSize)
|
|
328
|
+
result.append(ffi.string(buf).decode("utf-8"))
|
|
329
|
+
|
|
330
|
+
return result
|
|
331
|
+
|
|
332
|
+
def execute_search_get_ids(self, search_str:str)->list[int]:
|
|
333
|
+
'''执行搜索并返回字符串id数组'''
|
|
334
|
+
resultData = lib.PinInCpp_TreeSearcher_ExecuteSearch(self.cdata, search_str.encode("utf-8"))
|
|
335
|
+
resultData = ffi.gc(resultData, lib.PinInCpp_SearchResult_Free)
|
|
336
|
+
|
|
337
|
+
result = []
|
|
338
|
+
resultSize = resultData.size
|
|
339
|
+
|
|
340
|
+
if resultSize == 0:
|
|
341
|
+
return result
|
|
342
|
+
|
|
343
|
+
result = ffi.unpack(resultData.ids, resultSize)
|
|
344
|
+
return result
|
|
345
|
+
|
|
346
|
+
def get_str_by_id(self, id:int)->str:
|
|
347
|
+
'''根据字符串id返回字符串'''
|
|
348
|
+
cid = ffi.cast("size_t", id)
|
|
349
|
+
size = lib.PinInCpp_TreeSearcher_GetStrSizeById(self.cdata, cid) + 1
|
|
350
|
+
buf = ffi.new("char[]", size)
|
|
351
|
+
lib.PinInCpp_TreeSearcher_PutToCharBuf(self.cdata, cid, buf, size)
|
|
352
|
+
return ffi.string(buf).decode("utf-8")
|
|
353
|
+
|
|
354
|
+
def get_str_list_by_ids(self, ids:list[int])->list[str]:
|
|
355
|
+
'''根据字符串id数组返回字符串数组'''
|
|
356
|
+
result = []
|
|
357
|
+
bufSize = -1
|
|
358
|
+
buf = None
|
|
359
|
+
for id in ids:
|
|
360
|
+
cid = ffi.cast("size_t", id)
|
|
361
|
+
size = lib.PinInCpp_TreeSearcher_GetStrSizeById(self.cdata, cid) + 1
|
|
362
|
+
if size > bufSize:
|
|
363
|
+
bufSize = size * 2
|
|
364
|
+
buf = ffi.new("char[]", bufSize)
|
|
365
|
+
lib.PinInCpp_TreeSearcher_PutToCharBuf(self.cdata, cid, buf, bufSize)
|
|
366
|
+
result.append(ffi.string(buf).decode("utf-8"))
|
|
367
|
+
return result
|
|
368
|
+
|
|
369
|
+
def str_pool_reserve(self, newcapacity:int):
|
|
370
|
+
'''扩容TreeSearcher内部的字符串池的大小,通常不需要手动调用'''
|
|
371
|
+
lib.PinInCpp_TreeSearcher_StrPoolReserve(self.cdata, ffi.cast("size_t", newcapacity))
|
|
372
|
+
|
|
373
|
+
def refresh(self):
|
|
374
|
+
'''强制PinIn提交的配置现在就要刷新'''
|
|
375
|
+
lib.PinInCpp_TreeSearcher_Refresh(self.cdata)
|
|
376
|
+
|
|
377
|
+
def shrink_to_fit(self):
|
|
378
|
+
'''减少TreeSearcher中多余分配的内存,可以收缩内存占用'''
|
|
379
|
+
lib.PinInCpp_TreeSearcher_ShrinkToFit(self.cdata)
|
|
Binary file
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
|
+
Name: PinInPy
|
|
3
|
+
Version: 1.0.1
|
|
4
|
+
Summary: Python library for Pinyin searching
|
|
5
|
+
Keywords: PinIn,pinyin match,pinyin,cffi
|
|
6
|
+
Author-Email: SajoYukimi <kagiyamahino@gmail.com>
|
|
7
|
+
License: MIT
|
|
8
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
9
|
+
Classifier: Intended Audience :: Developers
|
|
10
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
11
|
+
Classifier: Operating System :: MacOS :: MacOS X
|
|
12
|
+
Classifier: Operating System :: Microsoft :: Windows
|
|
13
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
21
|
+
Classifier: Programming Language :: C++
|
|
22
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
23
|
+
Classifier: Natural Language :: Chinese (Simplified)
|
|
24
|
+
Classifier: Natural Language :: Chinese (Traditional)
|
|
25
|
+
Project-URL: Homepage, https://github.com/KagiamamaHIna/PinInPy
|
|
26
|
+
Project-URL: Bug Tracker, https://github.com/KagiamamaHIna/PinInPy/issues
|
|
27
|
+
Project-URL: Source, https://github.com/KagiamamaHIna/PinInPy
|
|
28
|
+
Requires-Python: >=3.9
|
|
29
|
+
Requires-Dist: cffi
|
|
30
|
+
Description-Content-Type: text/markdown
|
|
31
|
+
|
|
32
|
+
[](https://github.com/KagiamamaHIna/PinInPy/actions/workflows/python-publish.yml)
|
|
33
|
+

|
|
34
|
+

|
|
35
|
+

|
|
36
|
+
|
|
37
|
+
# PinIn Python
|
|
38
|
+
基于[PinIn4Cpp](https://github.com/KagiamamaHIna/PinIn4Cpp)的Python封装,提供C++的性能的同时用python的方式使用PinIn4Cpp
|
|
39
|
+
|
|
40
|
+
## 特性
|
|
41
|
+
完全基于PinIn4Cpp的C API,因此相比C++版本功能略有减少
|
|
42
|
+
- 提供Pythonic的封装,而不必调用原始的C API
|
|
43
|
+
- 高效的构建和即时搜索性能
|
|
44
|
+
- 可配置的预设键位方案和模糊音方案
|
|
45
|
+
|
|
46
|
+
## 安装
|
|
47
|
+
```
|
|
48
|
+
pip install PinInPy
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## 示例
|
|
52
|
+
**注意**:拼音字典文件(pinyin.txt),需要自行准备,也可以从[pinyin-data](https://github.com/mozillazg/pinyin-data)中下载直接使用
|
|
53
|
+
|
|
54
|
+
```python
|
|
55
|
+
import PinInPy
|
|
56
|
+
# BEGIN是前缀匹配,也就是根据字符串开头开始匹配
|
|
57
|
+
tree = PinInPy.TreeSearcher(PinInPy.Logic.BEGIN, "pinyin.txt")
|
|
58
|
+
tree.put_string("佐城雪美")
|
|
59
|
+
tree.put_string("游佐梢")
|
|
60
|
+
tree.put_string("市原仁奈")
|
|
61
|
+
|
|
62
|
+
print(tree.execute_search("zcxm"))#根据zcxm搜索 打印: ["佐城雪美"]
|
|
63
|
+
print(tree.execute_search("zchenxm"))#测试无模糊音时 打印: []
|
|
64
|
+
|
|
65
|
+
pinin = tree.get_pinin()# 获取PinIn对象,可以用于配置依赖PinIn对象的TreeSearcher
|
|
66
|
+
pinin.get_config().set_fEng2En(True).commit()# 设置eng -> en的模糊音
|
|
67
|
+
# 这时候en == eng
|
|
68
|
+
print(tree.execute_search("zchenxm"))# 打印: ["佐城雪美"]
|
|
69
|
+
|
|
70
|
+
pinin.get_config().set_keyboard(PinInPy.Keyboard.MICROSOFT).commit()# 设置键位为微软双拼
|
|
71
|
+
# y b(ou) z o(uo) u(sh) k(ao) == you zuo shao
|
|
72
|
+
print(tree.execute_search("ybzouk"))# 打印: ["游佐梢"]
|
|
73
|
+
|
|
74
|
+
# 可以根据已有的PinIn对象去构造新的搜索树,PinIn上的配置是会被共享的 CONTAIN是部分匹配,部分匹配则是可以从任意位置开始匹配
|
|
75
|
+
# 通常部分匹配的性能更差
|
|
76
|
+
tree2 = PinInPy.TreeSearcher(PinInPy.Logic.CONTAIN, pinin)
|
|
77
|
+
tree2.put_string("佐城雪美")
|
|
78
|
+
tree2.put_string("游佐梢")
|
|
79
|
+
tree2.put_string("市原仁奈")
|
|
80
|
+
tree2.put_string("serika")
|
|
81
|
+
# r f(en) n l(ai) == ren nai
|
|
82
|
+
print(tree2.execute_search("rfnl"))# 因为是部分匹配,所以后面会被匹配仁奈 打印: ["市原仁奈"]
|
|
83
|
+
# 注意! 双拼是成对匹配的,如果只有奇数个拼音音素输入则不会匹配任何中文
|
|
84
|
+
print(tree2.execute_search("r"))# 打印: ["serika"]
|
|
85
|
+
```
|
|
86
|
+
## 注意事项
|
|
87
|
+
不包含PinIn4Cpp中的ParallelSearch,拼音格式化功能,Keyboard自定义(只能使用预设),从内存中加载字典文件,从内存中加载二进制序列化文件的功能
|
|
88
|
+
PinIn类也不暴露拼音获取功能
|
|
89
|
+
|
|
90
|
+
理论上是平台无关的,但是GitHub Actions只构建了Linux,Windows,MacOS的Wheel包,如果你的目标平台不是其中之一的话可以自行尝试下载源代码,配置CMake,配置C/C++编译器,用```pip install .```安装
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
PinInPy/__init__.py,sha256=FaYenZm4bC2XHG0LzPKAtqtISoq6PIZ-OqJ9bdAdLQ4,14278
|
|
2
|
+
PinInPy/_pinin4cpp_cffi.pyd,sha256=xlUwlaz8wlYm12-dxXTlJq2_oWFb0Z2Zpi1fU_cbbAY,220160
|
|
3
|
+
PinInPy/PinIn4Cpp/LICENSE,sha256=3nH_RsSCl3ylLvmncdaquvWk_m6FKwdOrXltntBMm2o,1090
|
|
4
|
+
PinInPy/PinIn4Cpp/licenses/PinIn.txt,sha256=U2Zk_x4Aw_kS6nvEhpFhWC-4041zTHknxNfekGNM6zA,1089
|
|
5
|
+
PinInPy/PinIn4Cpp/licenses/pinyin-data.txt,sha256=fvkvCf6oBIyBajaZTo3DGpHWwh6dI6S3QRIohG5hjto,1097
|
|
6
|
+
pininpy-1.0.1.dist-info/METADATA,sha256=0mijrs7pLXcus-cBS-skpPnuwkGEMUhS3kGaNBooajk,4394
|
|
7
|
+
pininpy-1.0.1.dist-info/WHEEL,sha256=hrGeChGtn46HBGmzasO9QQDSLelRN-tUarBSv4gFcsI,106
|
|
8
|
+
pininpy-1.0.1.dist-info/licenses/LICENSE,sha256=3nH_RsSCl3ylLvmncdaquvWk_m6FKwdOrXltntBMm2o,1090
|
|
9
|
+
pininpy-1.0.1.dist-info/RECORD,,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 KagiyamaHina
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|