python-negar 1.2.9__tar.gz → 1.2.12__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.
Files changed (21) hide show
  1. {python-negar-1.2.9 → python_negar-1.2.12}/Changelog.txt +28 -22
  2. {python-negar-1.2.9 → python_negar-1.2.12}/MANIFEST.in +1 -1
  3. {python-negar-1.2.9 → python_negar-1.2.12}/PKG-INFO +3 -10
  4. {python-negar-1.2.9 → python_negar-1.2.12}/README.md +1 -1
  5. {python-negar-1.2.9 → python_negar-1.2.12}/negar/constants.py +3 -3
  6. {python-negar-1.2.9 → python_negar-1.2.12}/negar/virastar.py +65 -43
  7. {python-negar-1.2.9 → python_negar-1.2.12}/python_negar.egg-info/PKG-INFO +3 -10
  8. {python-negar-1.2.9 → python_negar-1.2.12}/python_negar.egg-info/SOURCES.txt +3 -3
  9. {python-negar-1.2.9 → python_negar-1.2.12}/python_negar.egg-info/entry_points.txt +0 -1
  10. {python-negar-1.2.9 → python_negar-1.2.12}/setup.py +1 -6
  11. python_negar-1.2.12/tests/test_unittest.py +126 -0
  12. python-negar-1.2.9/negar/data/__init__.py +0 -0
  13. {python-negar-1.2.9 → python_negar-1.2.12}/AUTHORS +0 -0
  14. {python-negar-1.2.9 → python_negar-1.2.12}/LICENSE +0 -0
  15. {python-negar-1.2.9 → python_negar-1.2.12}/negar/__init__.py +0 -0
  16. /python-negar-1.2.9/negar/data/untouchable.dat → /python_negar-1.2.12/negar/data/immutable.words +0 -0
  17. {python-negar-1.2.9 → python_negar-1.2.12}/negar/gui.py +0 -0
  18. {python-negar-1.2.9 → python_negar-1.2.12}/python_negar.egg-info/dependency_links.txt +0 -0
  19. {python-negar-1.2.9 → python_negar-1.2.12}/python_negar.egg-info/requires.txt +0 -0
  20. {python-negar-1.2.9 → python_negar-1.2.12}/python_negar.egg-info/top_level.txt +0 -0
  21. {python-negar-1.2.9 → python_negar-1.2.12}/setup.cfg +0 -0
@@ -1,6 +1,13 @@
1
+ 1.2.12 - 2024-12-23
2
+ -- Fix critical issue with naming `immutable.words`
3
+
4
+ 1.2.11 - 2024-12-23
5
+ -- Typo Fix
6
+ -- Renamed `untouchable.dat` to `immutable.words`
7
+
1
8
  1.2.9 - 2024-05-07
2
- -- Fix subtle issue with untoucahle words which stick to nonliteral symbols like Parantheses
3
- -- new test for untoucahle words
9
+ -- Fix subtle issue with immutable words which stick to non-literal symbols like Parentheses
10
+ -- new test for immutable words
4
11
 
5
12
  1.2.8 - 2023-09-21
6
13
  -- Fix subtle issue with triple dots at the end of sentence followed by another [?!.]
@@ -9,13 +16,13 @@
9
16
  -- Remove dot from saving directory under Windows OS.
10
17
 
11
18
  1.2.6 - 2023-08-07
12
- -- Better location for saving user defined untouchable data under Windows OS.
19
+ -- Better location for saving user defined immutable data under Windows OS.
13
20
 
14
21
  1.2.5 - 2023-07-14
15
22
  -- Fix issues with texts that include backslashes as part of their context, such as LaTeX source code.
16
23
 
17
24
  1.2.4 - 2023-06-15
18
- -- Fix the issue with multiple ! and ? and extra space after parantheses at the end of line
25
+ -- Fix the issue with multiple ! and ? and extra space after parentheses at the end of line
19
26
 
20
27
  1.2.2 - 2023-06-13
21
28
  -- Fix the issue with the triple dots that was caused by the previous update
@@ -28,7 +35,7 @@
28
35
 
29
36
  1.1.17 - 2022-12-21
30
37
  -- Fix the issue with می and نمی when they come as nouns, not prefixes.
31
- -- Several new untouchable words: تنهای/تنهایی/تک‌وتنهایی
38
+ -- Several new immutable words: تنهای/تنهایی/تک‌وتنهایی
32
39
 
33
40
  1.1.16 - 2022-09-11
34
41
  -- Fix issues with the following بهمان ,مهاجمان
@@ -55,7 +62,7 @@
55
62
  -- Update in compliance with `negar-gui` ver 0.2
56
63
 
57
64
  1.1.8 - 2012-05-03
58
- -- minor issue with untouchable words
65
+ -- minor issue with immutable words
59
66
  -- remove `disutils` as it's deprecated now
60
67
 
61
68
  1.1.7 - 2012-04-21
@@ -82,7 +89,7 @@
82
89
 
83
90
  1.1.1 - 2022-04-08
84
91
  -- Fixed an issue with `^mi*haye$` with using regex module
85
- -- Suport for new suffix شناس/شناسی
92
+ -- Support for new suffix شناس/شناسی
86
93
 
87
94
  1.1 - 2022-04-07
88
95
  -- Downgraded to PyQt5 for better support in Windows.
@@ -123,7 +130,7 @@
123
130
 
124
131
  0.9.6 - 2022-04-02
125
132
  -- Fixed issue #21, suffix اش
126
- -- Untouchable words updated
133
+ -- Immutable words updated
127
134
 
128
135
  0.9.5 - 2022-04-01
129
136
  -- New options for trimming leading/trailing whitespaces
@@ -145,11 +152,11 @@
145
152
  -- Revision of functions' names and their docstrings and comments to fix issue #14
146
153
 
147
154
  0.8.9 - 2022-03-29
148
- -- Supprot of import button via QFileDialog
155
+ -- Support of import button via QFileDialog
149
156
 
150
157
  0.8.8 - 2022-03-29
151
158
  -- constants.py would encompass some constants variables like __version__
152
- -- Untouchable words update
159
+ -- Immutable words update
153
160
 
154
161
  0.8.7 - 2022-03-29
155
162
  -- Fixed issue #4, users just add their own words to their private file-system
@@ -168,16 +175,16 @@
168
175
 
169
176
  0.8.2 - 2022-03-27
170
177
  -- copy button redesign
171
- -- Untouchable words revision
178
+ -- Immutable words revision
172
179
 
173
180
  0.8.1 - 2022-03-27
174
181
  -- Auto Stretch of headers in QTableView
175
182
  -- No header name for QTableView
176
183
 
177
184
  0.8.0 - 2022-03-26
178
- -- Extra Class for untouchable words
179
- -- Shows untouchable words in config tab via QTableView
180
- -- Untouchable words update
185
+ -- Extra Class for immutable words
186
+ -- Shows immutable words in config tab via QTableView
187
+ -- Immutable words update
181
188
  -- Right alignment for data in QTableView
182
189
 
183
190
  0.7.4 - 2022-03-25
@@ -185,7 +192,7 @@
185
192
  -- Fixed issue with relative import (https://stackoverflow.com/questions/16981921)
186
193
 
187
194
  0.7.3 - 2022-03-25
188
- -- Untouchable words update
195
+ -- Immutable words update
189
196
  -- Fixed issue with import
190
197
 
191
198
  0.7.2 - 2022-03-24
@@ -204,32 +211,32 @@
204
211
  0.6.8 - 2022-03-21
205
212
  -- os replaced by Pathlib
206
213
  -- Fixed some hot-keys in `Config` tab
207
- -- fixed the issue with 'می' at the begaining of the line
214
+ -- fixed the issue with 'می' at the beginning of the line
208
215
 
209
216
  0.6.7 - 2022-03-20
210
217
  -- auto focus on input field
211
218
 
212
219
  0.6.6 - 2022-03-19
213
220
  -- Fixed issue with words that contain 'ها' in the middle or at the end, like 'مهاباد' and 'دانشکده ها'
214
- -- Untouchable words list update as well as redundancy removed
221
+ -- Immutable words list update as well as redundancy removed
215
222
  -- Removing unwanted extra zwmjs
216
223
  -- Negar logo for better desktop switching
217
224
 
218
225
  0.6.5 - 2022-03-18
219
226
  -- Font Size Slider relocate to the bottom
220
227
  -- Fixed issue with words that contain 'می' in the middle like 'سهمیه'
221
- -- Tremendous addition of words start with 'می' into untouchable words
228
+ -- Tremendous addition of words start with 'می' into immutable words
222
229
 
223
230
  0.6.4 - 2022-03-18
224
231
  -- Font Size Slider
225
232
 
226
233
  0.6.3 - 2022-03-18
227
234
  -- Fixed issue with some words like سهمیه
228
- -- untouchable list update
235
+ -- Immutable list update
229
236
  -- Fixed issue with relative import in Python3
230
237
 
231
238
  0.6.2 - 2022-03-17
232
- -- Fixed 17: Some addition to Untouchable words
239
+ -- Fixed 17: Some addition to immutable words
233
240
  -- Revision in compliance with Python3.10 and PyQt6
234
241
  -- Fixed issue with setup
235
242
 
@@ -249,5 +256,4 @@
249
256
  -- Some command line improvements.
250
257
  -- More options added to command-line version
251
258
 
252
- 0.2 - 2012-08-05 Initial release.
253
-
259
+ 0.2 - 2012-08-05 Initial release.
@@ -2,5 +2,5 @@ include README.md
2
2
  include AUTHORS
3
3
  include *.txt
4
4
  include negar/logo.png
5
- include negar/data/*.dat
5
+ include negar/data/*.words
6
6
  recursive-include docs *.txt
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: python-negar
3
- Version: 1.2.9
3
+ Version: 1.2.12
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
@@ -9,20 +9,15 @@ Maintainer: Javad Razavian, Alireza Savand
9
9
  Maintainer-email: javadr@gmail.com, alireza.savand@gmail.com
10
10
  License: GPL
11
11
  Keywords: spellcheck Persian editor
12
- Platform: UNKNOWN
13
12
  Classifier: Environment :: Console
14
13
  Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
15
14
  Classifier: Programming Language :: Python
16
15
  Classifier: Programming Language :: Python :: 3
17
- Classifier: Programming Language :: Python :: 3.6
18
- Classifier: Programming Language :: Python :: 3.7
19
- Classifier: Programming Language :: Python :: 3.8
20
- Classifier: Programming Language :: Python :: 3.9
21
- Classifier: Programming Language :: Python :: 3.10
22
16
  Requires-Python: >=3.6
23
17
  Description-Content-Type: text/markdown
24
18
  License-File: LICENSE
25
19
  License-File: AUTHORS
20
+ Requires-Dist: regex
26
21
 
27
22
  Negar
28
23
  ==========
@@ -114,7 +109,7 @@ result:
114
109
  * جایگزینی
115
110
  + خط تیره‌های پیاپی نظیر (–) و (—) با معادل‌های استانداردشان
116
111
  + سه نقطه‌ی پیاپی (…) با کاراکتر استانداردش در زبان فارسی
117
- + علایمی نظیر کتیشن فارسی با گیومه؛ «نگار»
112
+ + علایمی نظیر کوتیشن فارسی با گیومه؛ «نگار»
118
113
  + اعداد عربی «۱۲۳۴۵۶۷۸۹۰» و انگلیسی «۱۲۳۴۵۶۷۸۹۰» با معادل فارسی
119
114
  + کاراکترهای غیر فارسی نظیر «، ؛ ٪یهک» با معادل‌های فارسی
120
115
 
@@ -177,5 +172,3 @@ Both of them are available on PyPI.
177
172
  <a href="https://github.com/shahinism/python-negar/graphs/contributors">
178
173
  <img src="https://contrib.rocks/image?repo=shahinism/python-negar" />
179
174
  </a>
180
-
181
-
@@ -88,7 +88,7 @@ result:
88
88
  * جایگزینی
89
89
  + خط تیره‌های پیاپی نظیر (–) و (—) با معادل‌های استانداردشان
90
90
  + سه نقطه‌ی پیاپی (…) با کاراکتر استانداردش در زبان فارسی
91
- + علایمی نظیر کتیشن فارسی با گیومه؛ «نگار»
91
+ + علایمی نظیر کوتیشن فارسی با گیومه؛ «نگار»
92
92
  + اعداد عربی «۱۲۳۴۵۶۷۸۹۰» و انگلیسی «۱۲۳۴۵۶۷۸۹۰» با معادل فارسی
93
93
  + کاراکترهای غیر فارسی نظیر «، ؛ ٪یهک» با معادل‌های فارسی
94
94
 
@@ -1,9 +1,9 @@
1
1
  import platform
2
2
  from pathlib import Path
3
3
 
4
- __version__ = "1.2.9"
4
+ __version__ = "1.2.12"
5
5
 
6
- DATAFILE = Path(__file__).parent.absolute() / "data/untouchable.dat"
6
+ DATAFILE = Path(__file__).parent.absolute() / "data/immutable.words"
7
7
  APPDATA = "AppData/Roaming/" if platform.system() == "Windows" else "."
8
8
  USERFILE = Path.home() / f"{APPDATA}python-negar"
9
9
 
@@ -11,7 +11,7 @@ INFO = f"""قابلیت های ویراستار ' نگار ' -- نسخه {__ver
11
11
  * جایگزینی
12
12
  ╛═ خط تیره های پیاپی نظیر (--) و (---) با معادل های استاندارد شان
13
13
  ╛═ سه نقطه ی پیاپی (...) با کاراکتر استانداردش در زبان فارسی
14
- ╛═ علایمی نظیر کتیشن فارسی با گیومه ؛ 'نگار'
14
+ ╛═ علایمی نظیر کوتیشن فارسی با گیومه ؛ 'نگار'
15
15
  ╛═ اعداد عربی '١٢٣٤٥٦٧٨٩٠' و انگلیسی '1234567890' با معادل فارسی
16
16
  ╛═ کاراکتر های غیر فارسی نظیر ',;%يةك' با معادل های فارسی
17
17
  * تنظیم فاصله
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env python
2
+ # ruff: noqa: T201
2
3
 
3
4
  import enum
4
5
  import re
@@ -7,26 +8,30 @@ from pathlib import Path
7
8
 
8
9
  import regex
9
10
 
10
- sys.path.append(Path(__file__).parent.parent.as_posix()) # https://stackoverflow.com/questions/16981921
11
- from negar.constants import DATAFILE, INFO, URLREGX, USERFILE # noqa: E402
11
+ sys.path.append(
12
+ Path(__file__).parent.parent.as_posix()
13
+ ) # https://stackoverflow.com/questions/16981921
14
+ from negar.constants import DATAFILE, INFO, URLREGX, USERFILE # noqa: E402
12
15
 
13
16
 
14
17
  class State(enum.Enum):
15
18
  save = 1
16
19
  restore = 2
17
20
 
21
+
18
22
  class PersianEditor:
19
- """Persian Text Editor for some sanitiztion task called Virastary in Persian."""
23
+ """Persian Text Editor for some sanitization task called Virastary in Persian."""
20
24
 
21
25
  def __init__(self, text, *args):
22
26
  # Check to see if `arg` exists in `args` or not
23
- parse_args = lambda arg: arg not in args # noqa: E731
24
- self._prepositions = \
25
- "از|در|به|با|بر|برای|بی|درباره|تا|را|جز|بدون|چون|مانند|مثل" \
26
- "|زیر|روی|همراه|مگر|الا|اندر|زی|برت|الا|زی|چو|سوای|پایین" \
27
+ parse_args = lambda arg: arg not in args # noqa: E731
28
+ self._prepositions = (
29
+ "از|در|به|با|بر|برای|بی|درباره|تا|را|جز|بدون|چون|مانند|مثل"
30
+ "|زیر|روی|همراه|مگر|الا|اندر|زی|برت|الا|زی|چو|سوای|پایین"
27
31
  "|پشت|پهلوی|پس|پیش|بالای|بیرون|درون|توی|غیر|کنار|مقابل|بهر"
32
+ )
28
33
  self.text = text
29
- self._cleanup_zwnj = False
34
+ self._cleanup_zwnj = False
30
35
  # checking for undesired options
31
36
  self._aggresive = parse_args("aggresive")
32
37
  self._fix_hamzeh = parse_args("fix-hamzeh")
@@ -48,7 +53,7 @@ class PersianEditor:
48
53
  self._fix_spacing_for_braces_and_quotes = parse_args("fix-spacing-bq")
49
54
  self._trim_leading_trailing_whitespaces = parse_args("trim-lt-whitespaces")
50
55
 
51
- UnTouchable() # to generate the untouchable words
56
+ ImmutableWords() # to generate the immutable words
52
57
  self.cleanup()
53
58
 
54
59
  def cleanup(self):
@@ -56,8 +61,8 @@ class PersianEditor:
56
61
  # fix punctuation spaces at first
57
62
  # : ; , ! ? and their Persian counterparts should have one space after and no space before
58
63
  # An exception is triple dots, which should be handled first
59
- self.fix_three_dots() if self._fix_three_dots else None
60
- self.aggressive() if self._aggresive else None
64
+ self.fix_three_dots() if self._fix_three_dots else None
65
+ self.aggressive() if self._aggresive else None
61
66
  self.text = re.sub(
62
67
  r"[ ‌ ]*([…:;,؛،.؟!]{1})[ ‌ ]*",
63
68
  r"\1 ",
@@ -79,12 +84,14 @@ class PersianEditor:
79
84
  self.fix_spacing_for_braces_and_quotes() \
80
85
  if self._fix_spacing_for_braces_and_quotes else None
81
86
  self.cleanup_redundant_zwnj()
82
- self.cleanup_spacing() if self._cleanup_spacing else None
87
+ self.cleanup_spacing() if self._cleanup_spacing else None
83
88
  self.text = re.sub(
84
89
  r"…([.؟!])",
85
90
  r"… \1",
86
91
  self.text,
87
92
  )
93
+ if self._trim_leading_trailing_whitespaces:
94
+ self.text = "\n".join([line.strip() for line in self.text.split("\n")])
88
95
  self._handle_urls(State.restore)
89
96
  return self.text
90
97
 
@@ -96,7 +103,7 @@ class PersianEditor:
96
103
  def _handle_urls(self, state):
97
104
  """Remove URLs and putting them back at the end of the process."""
98
105
  if state == State.save:
99
- self.urls = list(set(re.findall(URLREGX, self.text, re.M|re.I|re.X)))
106
+ self.urls = list(set(re.findall(URLREGX, self.text, re.M | re.I | re.X)))
100
107
  self.urls.sort(key=lambda x: len(x), reverse=True)
101
108
  for i, url in enumerate(self.urls):
102
109
  self.text = regex.sub(rf"{re.escape(url)}", rf"__URL__#{i}__", self.text)
@@ -123,9 +130,9 @@ class PersianEditor:
123
130
  --the last one is achievable if hamzeh_with_yeh set.
124
131
  """
125
132
  if self._hamzeh_with_yeh:
126
- self.text = re.sub(r"(\S)(ه[\s]+[یي])(\b)",r"\1ه‌ی\3",self.text)
133
+ self.text = re.sub(r"(\S)(ه[\s]+[یي])(\b)", r"\1ه‌ی\3", self.text)
127
134
  else:
128
- self.text = re.sub(r"(\S)(ه[\s]+[یي])(\b)",r"\1هٔ\3", self.text)
135
+ self.text = re.sub(r"(\S)(ه[\s]+[یي])(\b)", r"\1هٔ\3", self.text)
129
136
 
130
137
  def cleanup_zwnj(self):
131
138
  """Remove unnecessary ZWNJ that are succeeded/preceded by a space."""
@@ -138,7 +145,7 @@ class PersianEditor:
138
145
 
139
146
  def char_validator(self):
140
147
  """Replace invalid characters with valid ones."""
141
- bad_chars = ",;%يةك"
148
+ bad_chars = ",;%يةك"
142
149
  good_chars = "،؛٪یهک"
143
150
  self.text = self.char_translator(bad_chars, good_chars, self.text)
144
151
 
@@ -165,25 +172,27 @@ class PersianEditor:
165
172
  # Avoids to change English numbers in strings like 'Text12', 'Text_12', or 'A4'
166
173
  self.text = re.sub(
167
174
  r"[۰-۹]+[a-zA-Z_]{1,}[۰-۹]+|[a-zA-Z_]{1,}[۰-۹]+|[۰-۹]+[a-zA-Z_]{1,}",
168
- lambda m:
169
- self.char_translator(persian_numbers, english_numbers, m.group()),
175
+ lambda m: self.char_translator(persian_numbers, english_numbers, m.group()),
170
176
  self.text,
171
177
  )
172
178
 
173
179
  def fix_prefix_spacing(self):
174
180
  """Put ZWNJ between a word and its prefix (mi* nemi* bi* na*)."""
175
- self.text = re.sub(r"\b(بی|نا)‌*(\s+)(?!(می)\b)",r"\1‌", self.text)
176
- # the following case is for the mi(n.) and nami(n.)
177
- self.text = re.sub(rf"\b(ن?می)‌*(\s+)(?!(.|{self._prepositions})\b)",r"\1‌", self.text)
181
+ self.text = re.sub(r"\b(بی|نا)‌*(\s+)(?!(می)\b)", r"\1‌", self.text)
182
+ # 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)
178
184
 
179
185
  def fix_prefix_separate(self):
180
186
  """Put ZWNJ between a word and its prefix (mi* nemi* bi*)."""
181
187
  # regx = re.compile(r"\b(بی|ن?می)‌*([^\[\]\(\)\s]+)") # \b for words like سهمیه
182
- regx = regex.compile(r"""
188
+ regx = regex.compile(
189
+ r"""
183
190
  \b(بی|ن?می)‌*
184
191
  ([^\[\]\(\)\s]+)
185
192
  (?<!های|هایی|ها|شناس|شناسی|گذار|گذاری)\b
186
- """, re.VERBOSE) # \b for words like سهمیه
193
+ """,
194
+ re.VERBOSE,
195
+ ) # \b for words like سهمیه
187
196
 
188
197
  # Replace backslashes with a temporary placeholder
189
198
  text = self.text.replace("\\", "PN__BACKSLASH__PN")
@@ -192,10 +201,10 @@ class PersianEditor:
192
201
  regx_iter = regx.finditer(word)
193
202
  for p in regx_iter:
194
203
  # Checks that the prefix (mi* nemi* bi*) is part a a word or not, like میلاد.
195
- if p.group() not in UnTouchable.words:
204
+ if p.group() not in ImmutableWords.get():
196
205
  text = re.sub(
197
- re.escape( p.group() ),
198
- p.group(1) + "\u200c" + p.group(2) ,
206
+ re.escape(p.group()),
207
+ p.group(1) + "\u200c" + p.group(2),
199
208
  text,
200
209
  )
201
210
  # Restore the original backslashes
@@ -213,7 +222,8 @@ class PersianEditor:
213
222
  |شناس(ی)?
214
223
  |گذار(ی)?|گزار(ی)?
215
224
  |مند|ور|پور
216
- )\b""", re.VERBOSE,
225
+ )\b""",
226
+ re.VERBOSE,
217
227
  )
218
228
  self.text = re.sub(regx, r"‌\1", self.text)
219
229
 
@@ -227,10 +237,14 @@ class PersianEditor:
227
237
 
228
238
  def fix_suffix_separate(self):
229
239
  """Put ZWNJ between a word with its suffix (haye, ...)."""
230
- exag = r"""
240
+ exag = (
241
+ r"""
231
242
  تر(ی(ن)?)?|
232
243
  [تمش]ان|
233
- ها(ی(ی|ت|م|ش|تان|شان)?)?|""" if self._exaggerating_zwnj else ""
244
+ ها(ی(ی|ت|م|ش|تان|شان)?)?|"""
245
+ if self._exaggerating_zwnj
246
+ else ""
247
+ )
234
248
  regx = re.compile(
235
249
  rf"""\b(\S+?) # not-greedy fetch to handle some case like هایشان instead شان
236
250
  ({exag}
@@ -239,7 +253,8 @@ class PersianEditor:
239
253
  # ها(ی(ی|ت|م|ش|تان|شان)?)?|
240
254
  شناس(ی)?|
241
255
  گذار(ی)?|گزار(ی)?
242
- )\b""", re.VERBOSE,
256
+ )\b""",
257
+ re.VERBOSE,
243
258
  )
244
259
  # Replace backslashes with a temporary placeholder
245
260
  text = self.text.replace("\\", "PN__BACKSLASH__PN")
@@ -248,9 +263,9 @@ class PersianEditor:
248
263
  regx_iter = regx.finditer(word)
249
264
  for p in regx_iter:
250
265
  # Checks that the suffix (tar* haye*) is part of a word or not, like بهتر.
251
- if p.group() not in UnTouchable.words:
266
+ if p.group() not in ImmutableWords.get():
252
267
  text = re.sub(
253
- re.escape( p.group() ),
268
+ re.escape(p.group()),
254
269
  p.group(1) + "\u200c" + p.group(2),
255
270
  text,
256
271
  )
@@ -269,9 +284,12 @@ class PersianEditor:
269
284
  def fix_spacing_for_braces_and_quotes(self):
270
285
  """Fix the braces and quotes spacing problems."""
271
286
  # ()[]{}""«» should have one space before and no space after (inside)
272
- for begin, end in zip(["\(","\[","\{",'"',"«"], ["\)","\]","\}",'"',"»"]):
273
- self.text = re.sub(rf"[ ‌]*({begin})\s*([^{end}]+?)\s*?({end})[ ‌]*",
274
- r" \1\2\3 ", self.text )
287
+ for begin, end in zip(["\(", "\[", "\{", '"', "«"], ["\)", "\]", "\}", '"', "»"]):
288
+ self.text = re.sub(
289
+ rf"[ ‌]*({begin})\s*([^{end}]+?)\s*?({end})[ ‌]*", r" \1\2\3 ", self.text
290
+ )
291
+ # self.text = re.sub(rf"^[ ‌]*(.*)[ ‌]*$",
292
+ # r"\1", self.text, flags=re.MULTILINE)
275
293
  # # : ; , ! ? and their Persian counterparts should have one space after and no space before
276
294
  self.text = re.sub(
277
295
  r"[ ‌ ]*([:;,؛،.؟!]{1})[ ‌ ]*",
@@ -314,8 +332,8 @@ class PersianEditor:
314
332
  return newstring
315
333
 
316
334
 
317
- class UnTouchable:
318
- words = set() # a set storing all untouchable words
335
+ class ImmutableWords:
336
+ words = set() # a set storing all immutable words
319
337
 
320
338
  @classmethod
321
339
  def __init__(cls):
@@ -328,31 +346,35 @@ class UnTouchable:
328
346
 
329
347
  @classmethod
330
348
  def add(cls, word_list):
331
- with (USERFILE/"untouchable.dat").open("a", encoding="utf8") as f:
349
+ with (USERFILE / "immutable.words").open("a", encoding="utf8") as f:
332
350
  for word in word_list:
333
351
  if word not in cls.words:
334
- f.write(word+"\n")
352
+ f.write(word + "\n")
335
353
  cls.words.add(word)
336
354
 
337
355
  @classmethod
338
356
  def generate(cls):
339
- """Make a list from untoucahle words.
357
+ """Make a list from immutable words.
340
358
 
341
- A Unicode list from 'data/untouchable.dat' and '~/.python-negar/untouchable.dat'
359
+ A Unicode list from 'data/immutable.words' and '~/.python-negar/immutable.words'
342
360
  containing such words like 'بهتر' or 'میلاد' won't receive any modifications.
343
361
  """
344
362
  with DATAFILE.open(encoding="utf8") as f:
345
363
  for line in f:
346
364
  cls.words.add(line.strip())
347
365
  try:
348
- with (USERFILE/"untouchable.dat").open(encoding="utf8") as f:
366
+ # for compatibility with previous versions, since immutable.words was untouchable.dat before ver 1.2.10
367
+ if (USERFILE / "untouchable.dat").exists():
368
+ (USERFILE / "untouchable.dat").rename(USERFILE / "immutable.words")
369
+ with (USERFILE / "immutable.words").open(encoding="utf8") as f:
349
370
  for line in f:
350
371
  cls.words.add(line.strip())
351
372
  except FileNotFoundError:
352
373
  pass
353
374
 
375
+
354
376
  if __name__ == "__main__":
355
- print( "I'm a module. If you'd like the GUI, use ``negar'' instead. ;-)")
377
+ print("I'm a module. If you'd like the GUI, use ``negar'' instead. ;-)")
356
378
 
357
379
  print(f"""\nUsage:
358
380
  from virastar import PersianEditor
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: python-negar
3
- Version: 1.2.9
3
+ Version: 1.2.12
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
@@ -9,20 +9,15 @@ Maintainer: Javad Razavian, Alireza Savand
9
9
  Maintainer-email: javadr@gmail.com, alireza.savand@gmail.com
10
10
  License: GPL
11
11
  Keywords: spellcheck Persian editor
12
- Platform: UNKNOWN
13
12
  Classifier: Environment :: Console
14
13
  Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
15
14
  Classifier: Programming Language :: Python
16
15
  Classifier: Programming Language :: Python :: 3
17
- Classifier: Programming Language :: Python :: 3.6
18
- Classifier: Programming Language :: Python :: 3.7
19
- Classifier: Programming Language :: Python :: 3.8
20
- Classifier: Programming Language :: Python :: 3.9
21
- Classifier: Programming Language :: Python :: 3.10
22
16
  Requires-Python: >=3.6
23
17
  Description-Content-Type: text/markdown
24
18
  License-File: LICENSE
25
19
  License-File: AUTHORS
20
+ Requires-Dist: regex
26
21
 
27
22
  Negar
28
23
  ==========
@@ -114,7 +109,7 @@ result:
114
109
  * جایگزینی
115
110
  + خط تیره‌های پیاپی نظیر (–) و (—) با معادل‌های استانداردشان
116
111
  + سه نقطه‌ی پیاپی (…) با کاراکتر استانداردش در زبان فارسی
117
- + علایمی نظیر کتیشن فارسی با گیومه؛ «نگار»
112
+ + علایمی نظیر کوتیشن فارسی با گیومه؛ «نگار»
118
113
  + اعداد عربی «۱۲۳۴۵۶۷۸۹۰» و انگلیسی «۱۲۳۴۵۶۷۸۹۰» با معادل فارسی
119
114
  + کاراکترهای غیر فارسی نظیر «، ؛ ٪یهک» با معادل‌های فارسی
120
115
 
@@ -177,5 +172,3 @@ Both of them are available on PyPI.
177
172
  <a href="https://github.com/shahinism/python-negar/graphs/contributors">
178
173
  <img src="https://contrib.rocks/image?repo=shahinism/python-negar" />
179
174
  </a>
180
-
181
-
@@ -8,11 +8,11 @@ negar/__init__.py
8
8
  negar/constants.py
9
9
  negar/gui.py
10
10
  negar/virastar.py
11
- negar/data/__init__.py
12
- negar/data/untouchable.dat
11
+ negar/data/immutable.words
13
12
  python_negar.egg-info/PKG-INFO
14
13
  python_negar.egg-info/SOURCES.txt
15
14
  python_negar.egg-info/dependency_links.txt
16
15
  python_negar.egg-info/entry_points.txt
17
16
  python_negar.egg-info/requires.txt
18
- python_negar.egg-info/top_level.txt
17
+ python_negar.egg-info/top_level.txt
18
+ tests/test_unittest.py
@@ -1,3 +1,2 @@
1
1
  [console_scripts]
2
2
  negar = negar.gui:main
3
-
@@ -21,7 +21,7 @@ setup(
21
21
  "regex",
22
22
  ],
23
23
  package_dir={"negar": "negar"},
24
- package_data={"negar/data": ["data/*.dat"]},
24
+ package_data={"negar/data": ["data/*.words"]},
25
25
  description="Negar is a spell corrector and Persian text editor",
26
26
  license="GPL",
27
27
  keywords="spellcheck Persian editor",
@@ -39,11 +39,6 @@ setup(
39
39
  "License :: OSI Approved :: GNU General Public License v3 (GPLv3)",
40
40
  "Programming Language :: Python",
41
41
  "Programming Language :: Python :: 3",
42
- "Programming Language :: Python :: 3.6",
43
- "Programming Language :: Python :: 3.7",
44
- "Programming Language :: Python :: 3.8",
45
- "Programming Language :: Python :: 3.9",
46
- "Programming Language :: Python :: 3.10",
47
42
  ],
48
43
 
49
44
  )
@@ -0,0 +1,126 @@
1
+ import unittest
2
+ import functools
3
+ from negar.virastar import PersianEditor
4
+
5
+
6
+ class Test(unittest.TestCase):
7
+ def _assertEqual(message=""):
8
+ def decorator(func):
9
+ @functools.wraps(func)
10
+ def wrapper(self, *args, **kwargs):
11
+ func(self, *args, **kwargs)
12
+ return self.assertEqual(f"{PersianEditor(self.input_)}", self.output_, message)
13
+ return wrapper
14
+ return decorator
15
+
16
+ # @unittest.skip("")
17
+ @_assertEqual("Trim Leading Trailing Whitespaces")
18
+ def test_trim_leading_trailing_whitespaces(self):
19
+ self.input_ = "فضا های خالی بیش از حد"
20
+ self.output_ = "فضاهای خالی بیش از حد"
21
+
22
+ @_assertEqual("Fix Hamzeh")
23
+ def test_fix_hamzeh(self):
24
+ self.input_ = "کلماتی که با 'ی' پسوند همراه هستند مانند 'همه ی ' -- و البته امکان جایگزینی آن با حمزه 'ء' ( در صورت انتخاب کاربر )" # noqa: E501
25
+ self.output_ = "کلماتی که با «ی» پسوند همراه هستند مانند «همه‌ی» – و البته امکان جایگزینی آن با حمزه «ء» (در صورت انتخاب کاربر)" # noqa: E501
26
+
27
+ @_assertEqual("Numbers as a Version -- Triple Dots")
28
+ def test_versioning_numbers_triple(self):
29
+ """There is no space between dots of version number!."""
30
+ self.input_ = "نسخه 1.2.4"
31
+ self.output_ = "نسخه ۱.۲.۴"
32
+
33
+ @_assertEqual("Numbers as a Version -- Double Dots")
34
+ def test_versioning_numbers_double(self):
35
+ """There is no space between dots of version number!."""
36
+ self.input_ = "نسخه 1.2"
37
+ self.output_ = "نسخه ۱.۲"
38
+
39
+ @_assertEqual("Consecutive Dashes")
40
+ def test_consecutive_dashes(self):
41
+ self.input_ = "خط تیره های پیاپی نظیر (--) و (---) با معادل های استاندارد شان"
42
+ self.output_ = "خط تیره‌های پیاپی نظیر (–) و (—) با معادل‌های استانداردشان"
43
+
44
+ @_assertEqual("Triple Dots I")
45
+ def test_triple_dots_i(self):
46
+ self.input_ = "سه نقطه ی پیاپی (...) با کاراکتر استانداردش در زبان فارسی"
47
+ self.output_ = "سه نقطه‌ی پیاپی (…) با کاراکتر استانداردش در زبان فارسی"
48
+
49
+ @_assertEqual("Triple Dots II")
50
+ def test_triple_dots_ii(self):
51
+ self.input_ = "پرتره ، طبیعت و غیره یا پرتره ، طبیعت و .... ؟"
52
+ self.output_ = "پرتره، طبیعت و غیره یا پرتره، طبیعت و… ؟"
53
+
54
+ @_assertEqual("Persian Quotations")
55
+ def test_persian_quotations(self):
56
+ self.input_ = "علایمی نظیر کتیشن فارسی با گیومه ؛ 'نگار'"
57
+ self.output_ = "علایمی نظیر کتیشن فارسی با گیومه؛ «نگار»"
58
+
59
+ @_assertEqual("Persian Numbers")
60
+ def test_persian_numbers(self):
61
+ self.input_ = "اعداد عربی '١٢٣٤٥٦٧٨٩٠' و انگلیسی '1234567890' با معادل فارسی"
62
+ self.output_ = "اعداد عربی «۱۲۳۴۵۶۷۸۹۰» و انگلیسی «۱۲۳۴۵۶۷۸۹۰» با معادل فارسی"
63
+
64
+ @_assertEqual("Non-Persian Characters")
65
+ def test_non_persian_characters(self):
66
+ self.input_ = "کاراکتر های غیر فارسی نظیر ',;%يةك' با معادل های فارسی"
67
+ self.output_ = "کاراکترهای غیر فارسی نظیر «، ؛ ٪یهک» با معادل‌های فارسی"
68
+
69
+ @_assertEqual("Persian-Yeh as a Kasreh")
70
+ def test_persian_yeh_as_a_kasreh(self):
71
+ self.input_ = "کلماتی که با 'ی' پسوند همراه هستند مانند 'همه ی ' -- و البته امکان جایگزینی آن با حمزه 'ء' ( در صورت انتخاب کاربر )"
72
+ self.output_ = "کلماتی که با «ی» پسوند همراه هستند مانند «همه‌ی» – و البته امکان جایگزینی آن با حمزه «ء» (در صورت انتخاب کاربر)"
73
+
74
+ @_assertEqual("Fix Parantheses")
75
+ def test_fix_parantheses(self):
76
+ self.input_ = "پرانتز ها یا دیگر علایم ؛ ( نگار )"
77
+ self.output_ = "پرانتزها یا دیگر علایم؛ (نگار)"
78
+
79
+ @_assertEqual("Fix Punctuations")
80
+ def test_fix_punctuation(self):
81
+ self.input_ = "علائم نقطه‌گذاری ؛ بدون فاصله از قبل و با یک فاصله از بعد به استثنای اعداد اعشاری/نسخه نرم‌افزاری مانند 12.4/1.2.4"
82
+ self.output_ = "علائم نقطه‌گذاری؛ بدون فاصله از قبل و با یک فاصله از بعد به استثنای اعداد اعشاری/نسخه نرم‌افزاری مانند ۱۲.۴/۱.۲.۴"
83
+
84
+ @_assertEqual("Fix Prefix ZWNJ")
85
+ def test_fix_prefix_ZWNJ(self):
86
+ self.input_ = r"در پیشوند کلمات با نیم‌فاصله نظیر ' می شود '، ' میشود '، ' بی شک '، ' بیشک ' , ' خانه اش '، ' وظیفه شناس ' ، ' کمک تان ' و یا ' نمیرود '"
87
+ self.output_ = "در پیشوند کلمات با نیم‌فاصله نظیر «می‌شود»، «می‌شود»، «بی‌شک»، «بی‌شک»، «خانه‌اش»، «وظیفه‌شناس»، «کمک‌تان» و یا «نمی‌رود»"
88
+
89
+ @_assertEqual("Fix Suffix ZWNJ I")
90
+ def test_fix_suffix_ZWNJ_I(self):
91
+ self.input_ = r"در پسوند کلمات با نیم‌فاصله نظیر کتابها، خوشترین -- و البته امکان عدم تنظیم (در صورت انتخاب کاربر)"
92
+ self.output_ = "در پسوند کلمات با نیم‌فاصله نظیر کتاب‌ها، خوش‌ترین – و البته امکان عدم تنظیم (در صورت انتخاب کاربر)"
93
+
94
+ @_assertEqual("Fix Redundant Glyphs")
95
+ def test_cleanup_redundant_glyphs(self):
96
+ self.input_ = "استفاده ی بیش از یک علامت ؟؟؟؟ یا !!!"
97
+ self.output_ = "استفاده‌ی بیش از یک علامت؟ یا!"
98
+
99
+ @_assertEqual("Cleanup Kashidas")
100
+ def test_cleanup_kashidas(self):
101
+ self.input_ = "کشیـــــــــدگـــــــــــــــــی در کــــــــــــلمــــات"
102
+ self.output_ = "کشیدگی در کلمات"
103
+
104
+ @_assertEqual("Cleanup Extra Spaces")
105
+ def test_cleanup_extra_spaces(self):
106
+ self.input_ = "فضا های خالی بیش از حد"
107
+ self.output_ = "فضاهای خالی بیش از حد"
108
+
109
+ @_assertEqual("Immutable Words I")
110
+ def test_immutable_words_i(self):
111
+ self.input_ = "تنها ترین خدمتگزار (تنها ترین خدمتگزار)"
112
+ self.output_ = "تنهاترین خدمتگزار (تنهاترین خدمتگزار)"
113
+
114
+ @_assertEqual("Immutable Words II")
115
+ def test_immutable_words_ii(self):
116
+ self.input_ = "تنها ترین خدمتگزار (تنها ترین خدمتگزار)"
117
+ self.output_ = "تنهاترین خدمتگزار (تنهاترین خدمتگزار)"
118
+
119
+ @_assertEqual("Fix Suffix ZWNJ II")
120
+ def test_fix_suffix_ZWNJ_II(self):
121
+ self.input_ = "بیستم ماه میلادی"
122
+ self.output_ = "بیستم ماه میلادی"
123
+
124
+
125
+ if __name__ == "__main__":
126
+ unittest.main()
File without changes
File without changes
File without changes
File without changes
File without changes