python-negar 1.2.13__tar.gz → 1.3__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.
@@ -1,3 +1,12 @@
1
+ 1.3 - 2025-01-01
2
+ -- Enhanced the handling of immutable words to achieve greater accuracy in results.
3
+
4
+ 1.2.15 - 2024-12-31
5
+ -- Fixed issue #24 and added several new immutable words.
6
+
7
+ 1.2.14 - 2024-12-30
8
+ -- Fixed issue with prefix spacing in cases like "mi + space + ZWNJ + <word>".
9
+
1
10
  1.2.13 - 2024-12-26
2
11
  -- Fixed issue with quotes after a dot where no space was allowed in between.
3
12
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: python-negar
3
- Version: 1.2.13
3
+ Version: 1.3
4
4
  Summary: Negar is a spell corrector and Persian text editor
5
5
  Home-page: http://github.com/shahinism/python-negar
6
6
  Author: Shahin Azad
@@ -13,7 +13,7 @@ Classifier: Environment :: Console
13
13
  Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
14
14
  Classifier: Programming Language :: Python
15
15
  Classifier: Programming Language :: Python :: 3
16
- Requires-Python: >=3.6
16
+ Requires-Python: >=3.8
17
17
  Description-Content-Type: text/markdown
18
18
  License-File: LICENSE
19
19
  License-File: AUTHORS
@@ -1,7 +1,7 @@
1
1
  import platform
2
2
  from pathlib import Path
3
3
 
4
- __version__ = "1.2.13"
4
+ __version__ = "1.3"
5
5
 
6
6
  DATAFILE = Path(__file__).parent.absolute() / "data/immutable.words"
7
7
  APPDATA = "AppData/Roaming/" if platform.system() == "Windows" else "."
@@ -92,15 +92,18 @@
92
92
  الشان
93
93
  الکتر
94
94
  الکترومتر
95
+ الکترومتری
95
96
  الکتری
96
97
  الماس‌نشان
97
98
  المان
98
99
  الها
99
100
  ام‌ابیها
101
+ ام‌ابیها
100
102
  امفی‌تآتر
101
103
  امنیتتان
102
104
  امها
103
105
  انتها
106
+ انتهایی
104
107
  انرژی‌درمان
105
108
  انسان‌دوستان
106
109
  انسان‌دوستان
@@ -196,8 +199,11 @@
196
199
  بنگستان
197
200
  بنها
198
201
  بها
202
+ بهائیت
199
203
  بهارستان
200
204
  بهارستان
205
+ بهایی
206
+ بهاییت
201
207
  بهبها
202
208
  بهتان
203
209
  بهتان
@@ -205,6 +211,7 @@
205
211
  بهتری
206
212
  بهترین
207
213
  بهترین
214
+ به‌تنهایی
208
215
  بهمان
209
216
  بوتان
210
217
  بودنتان
@@ -254,6 +261,7 @@
254
261
  بیازمایید
255
262
  بیاسایند
256
263
  بی‌اشتها
264
+ بی‌اشتهایی
257
265
  بیافتد
258
266
  بیافرید
259
267
  بیافریند
@@ -324,9 +332,11 @@
324
332
  بیایی
325
333
  بیایید
326
334
  بیاییم
335
+ بیاییم
327
336
  بیبسکو
328
337
  بیبل
329
338
  بی‌بها
339
+ بی‌بهایی
330
340
  بیت
331
341
  بیت‌التکمه‌ها
332
342
  بیت‌الحکمه
@@ -379,6 +389,7 @@
379
389
  بیدارتر
380
390
  بیدارترین
381
391
  بیدار‌دل
392
+ بیداردل
382
393
  بیدارشان
383
394
  بیدارشدگی
384
395
  بیدارگری
@@ -464,11 +475,14 @@
464
475
  بیست‌میلیونی
465
476
  بیستمین
466
477
  بیست‌و‌پنجم
478
+ بیست‌وپنجم
467
479
  بیست‌و‌چهار‌ساعته
480
+ بیست‌وچهارساعته
468
481
  بیست‌ودوم
469
482
  بیست‌وسوم
470
483
  بیستون
471
484
  بیست‌و‌هفتم
485
+ بیست‌وهفتم
472
486
  بیست‌ویکم
473
487
  بیسرنامه
474
488
  بیسکای
@@ -540,6 +554,7 @@
540
554
  بیکار
541
555
  بیکاران
542
556
  بیکار‌شده
557
+ بیکارشده
543
558
  بیکارگی
544
559
  بیکارند
545
560
  بیکاره
@@ -659,6 +674,7 @@
659
674
  بین
660
675
  بینا
661
676
  بینا‌بینی
677
+ بینابینی
662
678
  بینات
663
679
  بیناتری
664
680
  بینارداغ
@@ -852,7 +868,9 @@
852
868
  تفتان
853
869
  تکلیفتان
854
870
  تک‌و‌تنها
871
+ تک‌وتنها
855
872
  تک‌و‌تنهایی
873
+ تک‌وتنهایی
856
874
  تلاشتان
857
875
  تلویزیون‌تان
858
876
  تماستان
@@ -864,6 +882,7 @@
864
882
  تنها
865
883
  تنهای
866
884
  تنهایی
885
+ تنهایی
867
886
  تنوره‌کشان
868
887
  تهیدستان
869
888
  توتستان
@@ -1039,6 +1058,7 @@
1039
1058
  سینمادوستان
1040
1059
  سینما‌دوستان
1041
1060
  شاعر‌صفتان
1061
+ شاعرصفتان
1042
1062
  شانگها
1043
1063
  شبستان
1044
1064
  شبستر
@@ -1055,6 +1075,7 @@
1055
1075
  شورستان
1056
1076
  شوشتر
1057
1077
  شوشتری
1078
+ شیخ‌بهایی
1058
1079
  شیربها
1059
1080
  صربستان
1060
1081
  صفرکیلومتر
@@ -1150,10 +1171,12 @@
1150
1171
  کودکستان
1151
1172
  کوهستان
1152
1173
  کیلومتر
1174
+ کیلومتری
1153
1175
  کیها
1154
1176
  گالوانومتر
1155
1177
  گانگستر
1156
1178
  گران‌بها
1179
+ گران‌بهایی
1157
1180
  گرجستان
1158
1181
  گردافشان
1159
1182
  گرده‌افشان
@@ -1180,6 +1203,8 @@
1180
1203
  لیموعمان
1181
1204
  ماتریس
1182
1205
  متان
1206
+ متر
1207
+ متری
1183
1208
  متشابها
1184
1209
  متکلمان
1185
1210
  متها
@@ -1333,7 +1358,7 @@
1333
1358
  میخی
1334
1359
  مید
1335
1360
  میداس
1336
- مید‌استار
1361
+ میداستار
1337
1362
  میدان
1338
1363
  میدانا
1339
1364
  میدان‌چای
@@ -1383,7 +1408,7 @@
1383
1408
  میرباقری
1384
1409
  میرپنج
1385
1410
  میرجاوه
1386
- میر‌جلیل
1411
+ میرجلیل
1387
1412
  میرحاجی
1388
1413
  میرحسین
1389
1414
  میرحسینی
@@ -1397,14 +1422,15 @@
1397
1422
  میرر
1398
1423
  میرزا
1399
1424
  میرزاآقابیک
1400
- میرزا‌ابوطالبی
1425
+ میرزاابوطالبی
1401
1426
  میرزابی
1402
1427
  میرزابیگی
1403
- میرزا‌ده
1428
+ میرزاده
1404
1429
  میرزا‌سالاری‌ها
1430
+ میرزاسالاری‌ها
1405
1431
  میرزاغفور
1406
1432
  میرزاغوثی
1407
- میرزا‌نظری
1433
+ میرزانظری
1408
1434
  میرزای
1409
1435
  میرزایی
1410
1436
  میرزمانی
@@ -1626,6 +1652,7 @@
1626
1652
  میلیارددلاری
1627
1653
  میلیاردر
1628
1654
  میلیارد‌ریالی
1655
+ میلیاردریالی
1629
1656
  میلیاردم
1630
1657
  میلیاردمین
1631
1658
  میلیاردها
@@ -1757,6 +1784,7 @@
1757
1784
  میهنه
1758
1785
  میهنی
1759
1786
  میهو‌ی
1787
+ میهوی
1760
1788
  میوت
1761
1789
  میور
1762
1790
  میوسن
@@ -1809,9 +1837,10 @@
1809
1837
  نهاد
1810
1838
  نهالستان
1811
1839
  نهایت
1840
+ نهایی
1812
1841
  نه‌تنها
1813
1842
  نوبها
1814
- نو‌دولتان
1843
+ نودولتان
1815
1844
  نورافشان
1816
1845
  نوع‌دوستان
1817
1846
  نونها
@@ -1822,6 +1851,7 @@
1822
1851
  نیشتر
1823
1852
  نیم‌بها
1824
1853
  نیمه‌نها
1854
+ نیمه‌نهایی
1825
1855
  هزاردستان
1826
1856
  هستان
1827
1857
  هشتر
@@ -57,7 +57,7 @@ class PersianEditor:
57
57
  self.cleanup()
58
58
 
59
59
  def cleanup(self):
60
- self._handle_urls(State.save)
60
+ self.__handle_urls__(State.save)
61
61
  # fix punctuation spaces at first
62
62
  # : ; , ! ? and their Persian counterparts should have one space after and no space before
63
63
  # An exception is triple dots, which should be handled first
@@ -77,10 +77,12 @@ class PersianEditor:
77
77
  self.char_validator() if self._fix_misc_non_persian_chars else None
78
78
  self.fix_arabic_numbers() if self._fix_arabic_numbers else None
79
79
  self.fix_english_numbers() if self._fix_english_numbers else None
80
+ self.__handle_immutable_words__(State.save)
80
81
  self.fix_prefix_spacing() if self._fix_prefix_spacing else None
81
82
  self.fix_prefix_separate() if self._fix_prefix_separate else None
82
83
  self.fix_suffix_spacing() if self._fix_suffix_spacing else None
83
84
  self.fix_suffix_separate() if self._fix_suffix_separate else None
85
+ self.__handle_immutable_words__(State.restore)
84
86
  self.fix_spacing_for_braces_and_quotes() \
85
87
  if self._fix_spacing_for_braces_and_quotes else None
86
88
  self.cleanup_redundant_zwnj()
@@ -92,7 +94,7 @@ class PersianEditor:
92
94
  )
93
95
  if self._trim_leading_trailing_whitespaces:
94
96
  self.text = "\n".join([line.strip() for line in self.text.split("\n")])
95
- self._handle_urls(State.restore)
97
+ self.__handle_urls__(State.restore)
96
98
  return self.text
97
99
 
98
100
  def __repr__(self):
@@ -100,7 +102,7 @@ class PersianEditor:
100
102
 
101
103
  __str__ = __repr__
102
104
 
103
- def _handle_urls(self, state):
105
+ def __handle_urls__(self, state):
104
106
  """Remove URLs and putting them back at the end of the process."""
105
107
  if state == State.save:
106
108
  self.urls = list(set(re.findall(URLREGX, self.text, re.M | re.I | re.X)))
@@ -111,6 +113,19 @@ class PersianEditor:
111
113
  for i, url in enumerate(self.urls):
112
114
  self.text = re.sub(f"__URL__#{i}__", url, self.text)
113
115
 
116
+ def __handle_immutable_words__(self, state):
117
+ """Remove URLs and putting them back at the end of the process."""
118
+ if state == State.save:
119
+ self.immutable_words = {}
120
+ words = self.text.split()
121
+ for i, word in enumerate(words):
122
+ if (word:=word.strip()) in ImmutableWords.get():
123
+ self.immutable_words[i] = word
124
+ self.text = regex.sub(rf"\b{word}\b", rf"__IMM__#{i}__", self.text)
125
+ if state == State.restore:
126
+ for imm_key, imm_word in self.immutable_words.items():
127
+ self.text = re.sub(f"__IMM__#{imm_key}__", imm_word, self.text)
128
+
114
129
  def fix_dashes(self):
115
130
  """Replace double and triple dashes with `ndash` and `mdash`, respectively."""
116
131
  self.text = re.sub(r"-{3}", r"—", self.text)
@@ -178,9 +193,9 @@ class PersianEditor:
178
193
 
179
194
  def fix_prefix_spacing(self):
180
195
  """Put ZWNJ between a word and its prefix (mi* nemi* bi* na*)."""
181
- self.text = re.sub(r"\b(بی|نا)‌*(\s+)(?!(می)\b)", r"\1‌", self.text)
196
+ self.text = re.sub(r"\b(بی|نا)([\s|‌]+)(?!(می)\b)", r"\1‌", self.text)
182
197
  # the following case is for the mi(n.) and nemi(n.)
183
- self.text = re.sub(rf"\b(ن?می)‌*(\s+)(?!(.|{self._prepositions})\b)", r"\1‌", self.text)
198
+ self.text = re.sub(rf"\b(ن?می)([\s|‌]+)(?!(.|{self._prepositions})\b)", r"\1‌", self.text)
184
199
 
185
200
  def fix_prefix_separate(self):
186
201
  """Put ZWNJ between a word and its prefix (mi* nemi* bi*)."""
@@ -193,22 +208,8 @@ class PersianEditor:
193
208
  """,
194
209
  re.VERBOSE,
195
210
  ) # \b for words like سهمیه
196
-
197
- # Replace backslashes with a temporary placeholder
198
- text = self.text.replace("\\", "PN__BACKSLASH__PN")
199
- wlist = text.split(" ")
200
- for word in wlist:
201
- regx_iter = regx.finditer(word)
202
- for p in regx_iter:
203
- # Checks that the prefix (mi* nemi* bi*) is part a a word or not, like میلاد.
204
- if p.group() not in ImmutableWords.get():
205
- text = re.sub(
206
- re.escape(p.group()),
207
- p.group(1) + "\u200c" + p.group(2),
208
- text,
209
- )
210
- # Restore the original backslashes
211
- self.text = text.replace("PN__BACKSLASH__PN", "\\")
211
+ # Checks that the prefix (mi*, nemi*, and bi*) is part a a word or not, like میلاد.
212
+ self.__immutability_check__(regx)
212
213
 
213
214
  def fix_suffix_spacing(self):
214
215
  """Put ZWNJ between a word and its suffix (*ha[ye] *tar[in])."""
@@ -256,19 +257,22 @@ class PersianEditor:
256
257
  )\b""",
257
258
  re.VERBOSE,
258
259
  )
260
+ # Checks that the suffix (tar*, haye*) is part of a word or not, like بهتر.
261
+ self.__immutability_check__(regx)
262
+
263
+ def __immutability_check__(self, regx: re.Pattern):
259
264
  # Replace backslashes with a temporary placeholder
260
265
  text = self.text.replace("\\", "PN__BACKSLASH__PN")
261
- wlist = text.split(" ")
266
+ wlist = text.split()
262
267
  for word in wlist:
263
268
  regx_iter = regx.finditer(word)
264
269
  for p in regx_iter:
265
- # Checks that the suffix (tar* haye*) is part of a word or not, like بهتر.
266
- if p.group() not in ImmutableWords.get():
267
- text = re.sub(
268
- re.escape(p.group()),
269
- p.group(1) + "\u200c" + p.group(2),
270
- text,
271
- )
270
+ # if p.group() not in ImmutableWords.get():
271
+ text = re.sub(
272
+ rf"\b{re.escape(p.group())}\b",
273
+ p.group(1) + "\u200c" + p.group(2),
274
+ text,
275
+ )
272
276
  # Restore the original backslashes
273
277
  self.text = text.replace("PN__BACKSLASH__PN", "\\")
274
278
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: python-negar
3
- Version: 1.2.13
3
+ Version: 1.3
4
4
  Summary: Negar is a spell corrector and Persian text editor
5
5
  Home-page: http://github.com/shahinism/python-negar
6
6
  Author: Shahin Azad
@@ -13,7 +13,7 @@ Classifier: Environment :: Console
13
13
  Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
14
14
  Classifier: Programming Language :: Python
15
15
  Classifier: Programming Language :: Python :: 3
16
- Requires-Python: >=3.6
16
+ Requires-Python: >=3.8
17
17
  Description-Content-Type: text/markdown
18
18
  License-File: LICENSE
19
19
  License-File: AUTHORS
@@ -33,7 +33,7 @@ setup(
33
33
  },
34
34
  long_description_content_type="text/markdown",
35
35
  long_description=open("README.md", encoding="utf8").read(),
36
- python_requires=">=3.6",
36
+ python_requires=">=3.8",
37
37
  classifiers=[
38
38
  "Environment :: Console",
39
39
  "License :: OSI Approved :: GNU General Public License v3 (GPLv3)",
@@ -93,6 +93,16 @@ class Test(unittest.TestCase):
93
93
  self.input_ = r"در پیشوند کلمات با نیم‌فاصله نظیر ' می شود '، ' میشود '، ' بی شک '، ' بیشک ' , ' خانه اش '، ' وظیفه شناس ' ، ' کمک تان ' و یا ' نمیرود '"
94
94
  self.output_ = "در پیشوند کلمات با نیم‌فاصله نظیر «می‌شود»، «می‌شود»، «بی‌شک»، «بی‌شک»، «خانه‌اش»، «وظیفه‌شناس»، «کمک‌تان» و یا «نمی‌رود»"
95
95
 
96
+ @_assertEqual("Fix Prefix ZWNJ II")
97
+ def test_fix_prefix_ZWNJ_ii(self):
98
+ self.input_ = r"می‌ شود"
99
+ self.output_ = "می‌شود"
100
+
101
+ @_assertEqual("Fix Prefix ZWNJ III")
102
+ def test_fix_prefix_ZWNJ_iii(self):
103
+ self.input_ = r"می ‌شود"
104
+ self.output_ = "می‌شود"
105
+
96
106
  @_assertEqual("Fix Suffix ZWNJ I")
97
107
  def test_fix_suffix_ZWNJ_I(self):
98
108
  self.input_ = r"در پسوند کلمات با نیم‌فاصله نظیر کتابها، خوشترین -- و البته امکان عدم تنظیم (در صورت انتخاب کاربر)"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes