python-negar 1.2.15__tar.gz → 1.4__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,9 @@
1
+ 1.4 - 2025-01-05
2
+ -- Added a new feature to ignore text after #> as a comment trigger.
3
+
4
+ 1.3 - 2025-01-01
5
+ -- Enhanced the handling of immutable words to achieve greater accuracy in results.
6
+
1
7
  1.2.15 - 2024-12-31
2
8
  -- Fixed issue #24 and added several new immutable words.
3
9
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: python-negar
3
- Version: 1.2.15
3
+ Version: 1.4
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
@@ -42,7 +42,7 @@ Installation
42
42
 
43
43
  ## Git
44
44
 
45
- You can get latest stable changes from github server:
45
+ You can get the latest stable changes from the GitHub server:
46
46
 
47
47
  $ git clone https://github.com/shahinism/python-negar.git
48
48
  $ cd python-negar
@@ -62,11 +62,11 @@ Get the latest tarball & install:
62
62
 
63
63
  ### Windows
64
64
 
65
- Download latest zip archive.
65
+ Download the latest zip archive.
66
66
 
67
67
  https://github.com/shahinism/python-negar/archive/master.zip
68
68
 
69
- Decompress it, and run the following command in root directory of `python-negar`
69
+ Decompress it, and run the following command in the root directory of `python-negar`
70
70
 
71
71
  $ python setup.py install
72
72
 
@@ -85,7 +85,7 @@ Calling by default options:
85
85
  * جایگزینی
86
86
  + خط تیره های پیاپی نظیر (--) و (---) با معادل های استاندارد شان
87
87
  + سه نقطه ی پیاپی (...) با کاراکتر استانداردش در زبان فارسی
88
- + علایمی نظیر کتیشن فارسی با گیومه ؛ 'نگار'
88
+ + علایمی نظیر کوتیشن فارسی با گیومه ؛ 'نگار'
89
89
  + اعداد عربی '١٢٣٤٥٦٧٨٩٠' و انگلیسی '1234567890' با معادل فارسی
90
90
  + کاراکتر های غیر فارسی نظیر ',;%يةك' با معادل های فارسی
91
91
 
@@ -21,7 +21,7 @@ Installation
21
21
 
22
22
  ## Git
23
23
 
24
- You can get latest stable changes from github server:
24
+ You can get the latest stable changes from the GitHub server:
25
25
 
26
26
  $ git clone https://github.com/shahinism/python-negar.git
27
27
  $ cd python-negar
@@ -41,11 +41,11 @@ Get the latest tarball & install:
41
41
 
42
42
  ### Windows
43
43
 
44
- Download latest zip archive.
44
+ Download the latest zip archive.
45
45
 
46
46
  https://github.com/shahinism/python-negar/archive/master.zip
47
47
 
48
- Decompress it, and run the following command in root directory of `python-negar`
48
+ Decompress it, and run the following command in the root directory of `python-negar`
49
49
 
50
50
  $ python setup.py install
51
51
 
@@ -64,7 +64,7 @@ Calling by default options:
64
64
  * جایگزینی
65
65
  + خط تیره های پیاپی نظیر (--) و (---) با معادل های استاندارد شان
66
66
  + سه نقطه ی پیاپی (...) با کاراکتر استانداردش در زبان فارسی
67
- + علایمی نظیر کتیشن فارسی با گیومه ؛ 'نگار'
67
+ + علایمی نظیر کوتیشن فارسی با گیومه ؛ 'نگار'
68
68
  + اعداد عربی '١٢٣٤٥٦٧٨٩٠' و انگلیسی '1234567890' با معادل فارسی
69
69
  + کاراکتر های غیر فارسی نظیر ',;%يةك' با معادل های فارسی
70
70
 
@@ -1,7 +1,7 @@
1
1
  import platform
2
2
  from pathlib import Path
3
3
 
4
- __version__ = "1.2.15"
4
+ __version__ = "1.4"
5
5
 
6
6
  DATAFILE = Path(__file__).parent.absolute() / "data/immutable.words"
7
7
  APPDATA = "AppData/Roaming/" if platform.system() == "Windows" else "."
@@ -92,6 +92,7 @@
92
92
  الشان
93
93
  الکتر
94
94
  الکترومتر
95
+ الکترومتری
95
96
  الکتری
96
97
  الماس‌نشان
97
98
  المان
@@ -331,6 +332,7 @@
331
332
  بیایی
332
333
  بیایید
333
334
  بیاییم
335
+ بیاییم
334
336
  بیبسکو
335
337
  بیبل
336
338
  بی‌بها
@@ -1169,6 +1171,7 @@
1169
1171
  کودکستان
1170
1172
  کوهستان
1171
1173
  کیلومتر
1174
+ کیلومتری
1172
1175
  کیها
1173
1176
  گالوانومتر
1174
1177
  گانگستر
@@ -1200,6 +1203,8 @@
1200
1203
  لیموعمان
1201
1204
  ماتریس
1202
1205
  متان
1206
+ متر
1207
+ متری
1203
1208
  متشابها
1204
1209
  متکلمان
1205
1210
  متها
@@ -57,7 +57,8 @@ class PersianEditor:
57
57
  self.cleanup()
58
58
 
59
59
  def cleanup(self):
60
- self._handle_urls(State.save)
60
+ self.__handle_comments__(State.save)
61
+ self.__handle_urls__(State.save)
61
62
  # fix punctuation spaces at first
62
63
  # : ; , ! ? and their Persian counterparts should have one space after and no space before
63
64
  # An exception is triple dots, which should be handled first
@@ -77,10 +78,12 @@ class PersianEditor:
77
78
  self.char_validator() if self._fix_misc_non_persian_chars else None
78
79
  self.fix_arabic_numbers() if self._fix_arabic_numbers else None
79
80
  self.fix_english_numbers() if self._fix_english_numbers else None
81
+ self.__handle_immutable_words__(State.save)
80
82
  self.fix_prefix_spacing() if self._fix_prefix_spacing else None
81
83
  self.fix_prefix_separate() if self._fix_prefix_separate else None
82
84
  self.fix_suffix_spacing() if self._fix_suffix_spacing else None
83
85
  self.fix_suffix_separate() if self._fix_suffix_separate else None
86
+ self.__handle_immutable_words__(State.restore)
84
87
  self.fix_spacing_for_braces_and_quotes() \
85
88
  if self._fix_spacing_for_braces_and_quotes else None
86
89
  self.cleanup_redundant_zwnj()
@@ -92,7 +95,8 @@ class PersianEditor:
92
95
  )
93
96
  if self._trim_leading_trailing_whitespaces:
94
97
  self.text = "\n".join([line.strip() for line in self.text.split("\n")])
95
- self._handle_urls(State.restore)
98
+ self.__handle_urls__(State.restore)
99
+ self.__handle_comments__(State.restore)
96
100
  return self.text
97
101
 
98
102
  def __repr__(self):
@@ -100,8 +104,19 @@ class PersianEditor:
100
104
 
101
105
  __str__ = __repr__
102
106
 
103
- def _handle_urls(self, state):
104
- """Remove URLs and putting them back at the end of the process."""
107
+ def __handle_comments__(self, state):
108
+ """Extract comments, process the content, and reinsert the comments at the end."""
109
+ if state == State.save:
110
+ self.comments = list(set(re.findall(r"#>.*$", self.text, re.I | re.M)))
111
+ self.comments.sort(key=lambda x: len(x), reverse=True)
112
+ for i, comment in enumerate(self.comments):
113
+ self.text = regex.sub(rf"{re.escape(comment)}", rf"__COMMENT__#{i}__", self.text)
114
+ if state == State.restore:
115
+ for i, comment in enumerate(self.comments):
116
+ self.text = re.sub(f"__COMMENT__#{i}__", comment, self.text)
117
+
118
+ def __handle_urls__(self, state):
119
+ """Remove URLs temporarily and reinsert them at the end of the process."""
105
120
  if state == State.save:
106
121
  self.urls = list(set(re.findall(URLREGX, self.text, re.M | re.I | re.X)))
107
122
  self.urls.sort(key=lambda x: len(x), reverse=True)
@@ -111,6 +126,19 @@ class PersianEditor:
111
126
  for i, url in enumerate(self.urls):
112
127
  self.text = re.sub(f"__URL__#{i}__", url, self.text)
113
128
 
129
+ def __handle_immutable_words__(self, state):
130
+ """Remove immutable words temporarily and reapply them at the end of the process."""
131
+ if state == State.save:
132
+ self.immutable_words = {}
133
+ words = self.text.split()
134
+ for i, word in enumerate(words):
135
+ if (word := word.strip()) in ImmutableWords.get():
136
+ self.immutable_words[i] = word
137
+ self.text = regex.sub(rf"\b{word}\b", rf"__IMM__#{i}__", self.text)
138
+ if state == State.restore:
139
+ for imm_key, imm_word in self.immutable_words.items():
140
+ self.text = re.sub(f"__IMM__#{imm_key}__", imm_word, self.text)
141
+
114
142
  def fix_dashes(self):
115
143
  """Replace double and triple dashes with `ndash` and `mdash`, respectively."""
116
144
  self.text = re.sub(r"-{3}", r"—", self.text)
@@ -193,24 +221,8 @@ class PersianEditor:
193
221
  """,
194
222
  re.VERBOSE,
195
223
  ) # \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
- if word.strip() in ImmutableWords.get():
202
- continue
203
- regx_iter = regx.finditer(word)
204
- for p in regx_iter:
205
- # Checks that the prefix (mi* nemi* bi*) is part a a word or not, like میلاد.
206
- if p.group() not in ImmutableWords.get():
207
- text = re.sub(
208
- re.escape(p.group()),
209
- p.group(1) + "\u200c" + p.group(2),
210
- text,
211
- )
212
- # Restore the original backslashes
213
- self.text = text.replace("PN__BACKSLASH__PN", "\\")
224
+ # Checks that the prefix (mi*, nemi*, and bi*) is part a a word or not, like میلاد.
225
+ self.__immutability_check__(regx)
214
226
 
215
227
  def fix_suffix_spacing(self):
216
228
  """Put ZWNJ between a word and its suffix (*ha[ye] *tar[in])."""
@@ -258,21 +270,22 @@ class PersianEditor:
258
270
  )\b""",
259
271
  re.VERBOSE,
260
272
  )
273
+ # Checks that the suffix (tar*, haye*) is part of a word or not, like بهتر.
274
+ self.__immutability_check__(regx)
275
+
276
+ def __immutability_check__(self, regx: re.Pattern):
261
277
  # Replace backslashes with a temporary placeholder
262
278
  text = self.text.replace("\\", "PN__BACKSLASH__PN")
263
279
  wlist = text.split()
264
280
  for word in wlist:
265
- if word.strip() in ImmutableWords.get():
266
- continue
267
281
  regx_iter = regx.finditer(word)
268
282
  for p in regx_iter:
269
- # Checks that the suffix (tar* haye*) is part of a word or not, like بهتر.
270
- if p.group() not in ImmutableWords.get():
271
- text = re.sub(
272
- re.escape(p.group()),
273
- p.group(1) + "\u200c" + p.group(2),
274
- text,
275
- )
283
+ # if p.group() not in ImmutableWords.get():
284
+ text = re.sub(
285
+ rf"\b{re.escape(p.group())}\b",
286
+ p.group(1) + "\u200c" + p.group(2),
287
+ text,
288
+ )
276
289
  # Restore the original backslashes
277
290
  self.text = text.replace("PN__BACKSLASH__PN", "\\")
278
291
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: python-negar
3
- Version: 1.2.15
3
+ Version: 1.4
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
@@ -42,7 +42,7 @@ Installation
42
42
 
43
43
  ## Git
44
44
 
45
- You can get latest stable changes from github server:
45
+ You can get the latest stable changes from the GitHub server:
46
46
 
47
47
  $ git clone https://github.com/shahinism/python-negar.git
48
48
  $ cd python-negar
@@ -62,11 +62,11 @@ Get the latest tarball & install:
62
62
 
63
63
  ### Windows
64
64
 
65
- Download latest zip archive.
65
+ Download the latest zip archive.
66
66
 
67
67
  https://github.com/shahinism/python-negar/archive/master.zip
68
68
 
69
- Decompress it, and run the following command in root directory of `python-negar`
69
+ Decompress it, and run the following command in the root directory of `python-negar`
70
70
 
71
71
  $ python setup.py install
72
72
 
@@ -85,7 +85,7 @@ Calling by default options:
85
85
  * جایگزینی
86
86
  + خط تیره های پیاپی نظیر (--) و (---) با معادل های استاندارد شان
87
87
  + سه نقطه ی پیاپی (...) با کاراکتر استانداردش در زبان فارسی
88
- + علایمی نظیر کتیشن فارسی با گیومه ؛ 'نگار'
88
+ + علایمی نظیر کوتیشن فارسی با گیومه ؛ 'نگار'
89
89
  + اعداد عربی '١٢٣٤٥٦٧٨٩٠' و انگلیسی '1234567890' با معادل فارسی
90
90
  + کاراکتر های غیر فارسی نظیر ',;%يةك' با معادل های فارسی
91
91
 
@@ -33,12 +33,11 @@ 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)",
40
40
  "Programming Language :: Python",
41
41
  "Programming Language :: Python :: 3",
42
42
  ],
43
-
44
43
  )
@@ -11,7 +11,9 @@ class Test(unittest.TestCase):
11
11
  def wrapper(self, *args, **kwargs):
12
12
  func(self, *args, **kwargs)
13
13
  return self.assertEqual(f"{PersianEditor(self.input_)}", self.output_, message)
14
+
14
15
  return wrapper
16
+
15
17
  return decorator
16
18
 
17
19
  # @unittest.skip("")
@@ -22,8 +24,8 @@ class Test(unittest.TestCase):
22
24
 
23
25
  @_assertEqual("Fix Hamzeh")
24
26
  def test_fix_hamzeh(self):
25
- self.input_ = "کلماتی که با 'ی' پسوند همراه هستند مانند 'همه ی ' -- و البته امکان جایگزینی آن با حمزه 'ء' ( در صورت انتخاب کاربر )" # noqa: E501
26
- self.output_ = "کلماتی که با «ی» پسوند همراه هستند مانند «همه‌ی» – و البته امکان جایگزینی آن با حمزه «ء» (در صورت انتخاب کاربر)" # noqa: E501
27
+ self.input_ = "کلماتی که با 'ی' پسوند همراه هستند مانند 'همه ی ' -- و البته امکان جایگزینی آن با حمزه 'ء' ( در صورت انتخاب کاربر )" # noqa: E501
28
+ self.output_ = "کلماتی که با «ی» پسوند همراه هستند مانند «همه‌ی» – و البته امکان جایگزینی آن با حمزه «ء» (در صورت انتخاب کاربر)" # noqa: E501
27
29
 
28
30
  @_assertEqual("Numbers as a Version -- Triple Dots")
29
31
  def test_versioning_numbers_triple(self):
@@ -61,7 +63,6 @@ class Test(unittest.TestCase):
61
63
  def test_persian_quotations_ii(self):
62
64
  self.input_ = "«تاثیر نسبی داشته است. »"
63
65
  self.output_ = "«تاثیر نسبی داشته است.»"
64
-
65
66
 
66
67
  @_assertEqual("Persian Numbers")
67
68
  def test_persian_numbers(self):
@@ -102,7 +103,7 @@ class Test(unittest.TestCase):
102
103
  def test_fix_prefix_ZWNJ_iii(self):
103
104
  self.input_ = r"می ‌شود"
104
105
  self.output_ = "می‌شود"
105
-
106
+
106
107
  @_assertEqual("Fix Suffix ZWNJ I")
107
108
  def test_fix_suffix_ZWNJ_I(self):
108
109
  self.input_ = r"در پسوند کلمات با نیم‌فاصله نظیر کتابها، خوشترین -- و البته امکان عدم تنظیم (در صورت انتخاب کاربر)"
@@ -127,7 +128,7 @@ class Test(unittest.TestCase):
127
128
  def test_immutable_words_i(self):
128
129
  self.input_ = "تنها ترین خدمتگزار (تنها ترین خدمتگزار)"
129
130
  self.output_ = "تنهاترین خدمتگزار (تنهاترین خدمتگزار)"
130
-
131
+
131
132
  @_assertEqual("Immutable Words II")
132
133
  def test_immutable_words_ii(self):
133
134
  self.input_ = "تنها ترین خدمتگزار (تنها ترین خدمتگزار)"
@@ -138,6 +139,11 @@ class Test(unittest.TestCase):
138
139
  self.input_ = "بیستم ماه میلادی"
139
140
  self.output_ = "بیستم ماه میلادی"
140
141
 
142
+ @_assertEqual("Ignote Comment")
143
+ def test_ignore_comment(self):
144
+ self.input_ = "کشیـــــــــده شده اند #> می نویسد .... "
145
+ self.output_ = "کشیده شده‌اند #> می نویسد .... "
146
+
141
147
 
142
148
  if __name__ == "__main__":
143
149
  unittest.main()
File without changes
File without changes
File without changes
File without changes
File without changes