PinInPy 1.0.1__cp313-cp313-win32.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.
@@ -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
+ [![Upload Python Package](https://github.com/KagiamamaHIna/PinInPy/actions/workflows/python-publish.yml/badge.svg)](https://github.com/KagiamamaHIna/PinInPy/actions/workflows/python-publish.yml)
33
+ ![PyPI version](https://img.shields.io/pypi/v/PinInPy)
34
+ ![PyPI - Python Version](https://img.shields.io/pypi/pyversions/PinInPy)
35
+ ![PyPI - License](https://img.shields.io/pypi/l/PinInPy)
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=V80_ymd2yLk2UpRLJQuHndwvhQI-kTOTD1ooBW1I6-k,177664
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=BLWkcoBBaeCx8jVONI8U_yio93Axp7qMoW-QbdfeAIY,102
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,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: scikit-build-core 0.11.6
3
+ Root-Is-Purelib: false
4
+ Tag: cp313-cp313-win32
5
+
@@ -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.