arabcheck 0.1.0__py3-none-any.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.
arabcheck/__init__.py ADDED
@@ -0,0 +1,5 @@
1
+ """ArabCheck — Lightweight Arabic text toolkit."""
2
+ from .core import ArabCheck
3
+
4
+ __version__ = "0.2.0"
5
+ __all__ = ["ArabCheck", "__version__"]
arabcheck/__main__.py ADDED
@@ -0,0 +1,5 @@
1
+ import sys
2
+ from .cli import main
3
+
4
+ if __name__ == "__main__":
5
+ sys.exit(main())
arabcheck/cli.py ADDED
@@ -0,0 +1,59 @@
1
+ """واجهة سطر الأوامر."""
2
+ from __future__ import annotations
3
+ import argparse
4
+ import json
5
+ import sys
6
+ from pathlib import Path
7
+ from . import __version__
8
+ from .core import ArabCheck
9
+
10
+
11
+ def read_input(args, parser):
12
+ if args.file:
13
+ try:
14
+ return args.file.read_text(encoding="utf-8")
15
+ except FileNotFoundError:
16
+ parser.error(f"الملف غير موجود: {args.file}")
17
+ if args.text:
18
+ return args.text
19
+ if not sys.stdin.isatty():
20
+ return sys.stdin.read()
21
+ parser.error("لازم تمرّر نصاً، أو --file، أو stdin.")
22
+ return ""
23
+
24
+
25
+ def build_parser():
26
+ p = argparse.ArgumentParser(prog="arabcheck", description="ArabCheck — تنظيف وفحص النصوص العربية.")
27
+ p.add_argument("text", nargs="?", help="النص")
28
+ p.add_argument("-f", "--file", type=Path, help="قراءة من ملف")
29
+ p.add_argument("-c", "--clean", action="store_true")
30
+ p.add_argument("-n", "--normalize", action="store_true")
31
+ p.add_argument("-a", "--audit", action="store_true")
32
+ p.add_argument("-j", "--json", action="store_true")
33
+ p.add_argument("-q", "--quiet", action="store_true")
34
+ p.add_argument("-V", "--version", action="version", version=f"%(prog)s {__version__}")
35
+ return p
36
+
37
+
38
+ def main(argv=None) -> int:
39
+ parser = build_parser()
40
+ args = parser.parse_args(argv)
41
+ text = read_input(args, parser)
42
+ checker = ArabCheck()
43
+ result = checker.process(text, clean=args.clean, normalize=args.normalize, audit=args.audit)
44
+ if args.json:
45
+ payload = {**result, "meta": {
46
+ "cleaned": args.clean, "normalized": args.normalize,
47
+ "audited": args.audit, "version": __version__,
48
+ }}
49
+ print(json.dumps(payload, ensure_ascii=False, indent=2))
50
+ else:
51
+ if not args.quiet:
52
+ print(result["result"])
53
+ for issue in result["issues"]:
54
+ print(f"⚠️ {issue['message']}", file=sys.stderr)
55
+ return 1 if result["issues"] else 0
56
+
57
+
58
+ if __name__ == "__main__":
59
+ sys.exit(main())
arabcheck/core.py ADDED
@@ -0,0 +1,49 @@
1
+ """النواة الرئيسية لـ ArabCheck."""
2
+ from __future__ import annotations
3
+ from .patterns import Patterns
4
+
5
+
6
+ class ArabCheck:
7
+ def __init__(self) -> None:
8
+ self.patterns = Patterns()
9
+
10
+ def strip_tashkeel(self, text: str) -> str:
11
+ return self.patterns.TASHKEEL.sub("", text)
12
+
13
+ def strip_tatweel(self, text: str) -> str:
14
+ return self.patterns.TATWEEL.sub("", text)
15
+
16
+ def clean_text(self, text: str) -> str:
17
+ text = self.strip_tashkeel(text)
18
+ text = self.strip_tatweel(text)
19
+ return self.patterns.WHITESPACE.sub(" ", text).strip()
20
+
21
+ def normalize(self, text: str, *, taa_marbuta: bool = False) -> str:
22
+ text = self.patterns.ALIF_VARIANTS.sub("ا", text)
23
+ text = self.patterns.YAA_VARIANTS.sub("ي", text)
24
+ text = self.patterns.HAMZA_WAW.sub("و", text)
25
+ text = self.patterns.HAMZA_YAA.sub("ي", text)
26
+ if taa_marbuta:
27
+ text = self.patterns.TAA_MARBUTA.sub("ه", text)
28
+ return text
29
+
30
+ def audit(self, text: str) -> list:
31
+ issues = []
32
+ for i, word in enumerate(text.split(), start=1):
33
+ if self.patterns.HAMZAT_QAT.match(word):
34
+ issues.append({
35
+ "type": "hamzat_qat",
36
+ "word": word,
37
+ "position": i,
38
+ "message": f"احتمال خطأ: '{word}' تبدأ بـ 'ال' + همزة قطع.",
39
+ })
40
+ return issues
41
+
42
+ def process(self, text, *, clean=False, normalize=False, audit=False):
43
+ issues = self.audit(text) if audit else []
44
+ result = text
45
+ if normalize:
46
+ result = self.normalize(result)
47
+ if clean:
48
+ result = self.clean_text(result)
49
+ return {"input": text, "result": result, "issues": issues}
arabcheck/patterns.py ADDED
@@ -0,0 +1,27 @@
1
+ """أنماط regex المجمّعة مسبقاً."""
2
+ from __future__ import annotations
3
+
4
+ import re
5
+
6
+
7
+ class Patterns:
8
+ """أنماط regex لأداء أفضل (compiled once)."""
9
+
10
+ # التشكيل: حركات + علامات قرآنية + ألف خنجرية
11
+ TASHKEEL = re.compile(
12
+ "[\u0610-\u061A\u064B-\u065F\u0670"
13
+ "\u06D6-\u06DC\u06DF-\u06E8\u06EA-\u06ED]"
14
+ )
15
+
16
+ TATWEEL = re.compile("\u0640")
17
+ WHITESPACE = re.compile(r"\s+")
18
+
19
+ # همزة قطع بعد "ال" التعريف
20
+ HAMZAT_QAT = re.compile(r"^ال[أإآ]")
21
+
22
+ # للتوحيد — كل واحد منفصل عشان يبقى واضح
23
+ ALIF_VARIANTS = re.compile(r"[إأآٱ]")
24
+ YAA_VARIANTS = re.compile(r"[ىي]")
25
+ TAA_MARBUTA = re.compile(r"ة")
26
+ HAMZA_WAW = re.compile(r"ؤ")
27
+ HAMZA_YAA = re.compile(r"ئ")
@@ -0,0 +1,247 @@
1
+ Metadata-Version: 2.4
2
+ Name: arabcheck
3
+ Version: 0.1.0
4
+ Summary: Lightweight toolkit and CLI for cleaning, normalizing, and auditing Arabic text.
5
+ Author-email: Mohamed Kamal Salih Mahmod <102423366+MOHAMEDKAMALSALLIH@users.noreply.github.com>
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/MOHAMEDKAMALSALLIH/arabcheck
8
+ Project-URL: Repository, https://github.com/MOHAMEDKAMALSALLIH/arabcheck
9
+ Project-URL: Issues, https://github.com/MOHAMEDKAMALSALLIH/arabcheck/issues
10
+ Project-URL: Changelog, https://github.com/MOHAMEDKAMALSALLIH/arabcheck/blob/main/CHANGELOG.md
11
+ Project-URL: Releases, https://github.com/MOHAMEDKAMALSALLIH/arabcheck/releases
12
+ Keywords: arabic,nlp,text-cleaning,tashkeel
13
+ Classifier: Development Status :: 3 - Alpha
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Natural Language :: Arabic
16
+ Classifier: Programming Language :: Python :: 3
17
+ Requires-Python: >=3.8
18
+ Description-Content-Type: text/markdown
19
+ License-File: LICENSE
20
+ Provides-Extra: dev
21
+ Requires-Dist: pytest>=7; extra == "dev"
22
+ Dynamic: license-file
23
+
24
+ # ArabCheck 🔍
25
+
26
+ > A lightweight, open-source toolkit and CLI for cleaning, normalizing, and auditing Arabic text for AI and NLP workflows.
27
+
28
+ ![Python](https://img.shields.io/badge/python-3.8%2B-blue)
29
+ ![License](https://img.shields.io/badge/license-MIT-green)
30
+ ![Status](https://img.shields.io/badge/status-alpha-orange)
31
+
32
+ ---
33
+
34
+ ## Why ArabCheck?
35
+
36
+ Arabic text data often contains noise that breaks NLP pipelines:
37
+
38
+ - **Unicode variants** — `أ` / `إ` / `آ` / `ا` / `ٱ` all represent alif
39
+ - **Diacritics (Tashkeel)** — fatha, damma, shadda, tanween
40
+ - **Tatweel (Kashida)** — decorative stretching characters `ـــــ`
41
+ - **Quranic marks** and extra whitespace
42
+
43
+ ArabCheck makes cleaning and auditing this data a one-liner — with full transparency and configurable operations.
44
+
45
+ ---
46
+
47
+ ## Features
48
+
49
+ - 🕌 **Tashkeel removal** — Harakat + Quranic marks
50
+ - 🔤 **Character normalization** — Alif, Yaa, Hamza, Taa Marbuta
51
+ - 〰️ **Tatweel removal** — Kashida stretching characters
52
+ - 🧹 **Text cleaning** — Whitespace normalization
53
+ - 🔍 **Grammar audit** — Detect common hamzat qat/wasl errors
54
+ - 📂 **File + stdin support**
55
+ - 🤖 **JSON output** for CI/CD pipelines
56
+ - 🧩 **Extensible** — easy to add new rules
57
+
58
+ ---
59
+
60
+ ## Install
61
+
62
+ ```bash
63
+ git clone https://github.com/MOHAMEDKAMALSALLIH/arabcheck.git
64
+ cd arabcheck
65
+ pip install -e .
66
+ ```
67
+
68
+ Requirements: Python 3.8+ — no external dependencies.
69
+
70
+ ---
71
+
72
+ Quick Start
73
+
74
+ ```bash
75
+ arabcheck "النَّصُّ العَرَبِيُّ لِلتَّجْرِبَة" --clean
76
+ ```
77
+
78
+ Input:
79
+
80
+ ```
81
+ النَّصُّ العَرَبِيُّ لِلتَّجْرِبَة
82
+ ```
83
+
84
+ Output:
85
+
86
+ ```
87
+ النص العربي للتجربة
88
+ ```
89
+
90
+ ---
91
+
92
+ Usage Examples
93
+
94
+ 1. Clean text
95
+
96
+ ```bash
97
+ arabcheck "العَرَبِيَّةُ ـــ لُغَةٌ جَمِيلَةٌ" --clean
98
+ # → العربية لغة جميلة
99
+ ```
100
+
101
+ 2. Normalize characters
102
+
103
+ ```bash
104
+ arabcheck "أحمد إبراهيم آمن" --normalize
105
+ # → احمد ابراهيم امن
106
+ ```
107
+
108
+ ⚠️ Warning: Normalization loses linguistic information. Use it for search, indexing, or NLP pipelines only.
109
+
110
+ 3. Audit text
111
+
112
+ ```bash
113
+ arabcheck "الأمر بالأمر" --audit
114
+ # ⚠️ احتمال خطأ: 'الأمر' تبدأ بـ 'ال' + همزة قطع.
115
+ ```
116
+
117
+ 4. JSON output (for automation)
118
+
119
+ ```bash
120
+ arabcheck "النَّصُّ" --clean --json
121
+ ```
122
+
123
+ ```json
124
+ {
125
+ "input": "النَّصُّ",
126
+ "result": "النص",
127
+ "issues": [],
128
+ "meta": {
129
+ "cleaned": true,
130
+ "normalized": false,
131
+ "audited": false,
132
+ "version": "0.1.0"
133
+ }
134
+ }
135
+ ```
136
+
137
+ 5. Read from file
138
+
139
+ ```bash
140
+ arabcheck --file dataset.txt --clean
141
+ ```
142
+
143
+ 6. From stdin
144
+
145
+ ```bash
146
+ cat article.txt | arabcheck --clean
147
+ ```
148
+
149
+ ---
150
+
151
+ CLI Reference
152
+
153
+ ```
154
+ usage: arabcheck [-h] [-f FILE] [-c] [-n] [-a] [-j] [-q] [-V] [text]
155
+
156
+ positional arguments:
157
+ text Text to process
158
+
159
+ options:
160
+ -h, --help Show help
161
+ -f, --file FILE Read text from file
162
+ -c, --clean Remove tashkeel, tatweel and extra whitespace
163
+ -n, --normalize Normalize letters (alif, yaa, etc.)
164
+ -a, --audit Audit common spelling issues
165
+ -j, --json Output as JSON
166
+ -q, --quiet Suppress text output
167
+ -V, --version Show version
168
+ ```
169
+
170
+ Exit Codes
171
+
172
+ Code Meaning
173
+ 0 Success, no issues
174
+ 1 Issues found (with --audit)
175
+ 2 Input error
176
+
177
+ ---
178
+
179
+ Use as a Library
180
+
181
+ ```python
182
+ from arabcheck import ArabCheck
183
+
184
+ checker = ArabCheck()
185
+
186
+ # Clean
187
+ text = checker.clean_text("النَّصُّ العَرَبِيُّ ـــ")
188
+ print(text) # → النص العربي
189
+
190
+ # Normalize
191
+ print(checker.normalize("أحمد إبراهيم"))
192
+ # → احمد ابراهيم
193
+
194
+ # Audit
195
+ issues = checker.audit("الأمر بالأمر")
196
+ for issue in issues:
197
+ print(issue["message"])
198
+ ```
199
+
200
+ ---
201
+
202
+ Testing
203
+
204
+ ```bash
205
+ pip install -e ".[dev]"
206
+ pytest
207
+ ```
208
+
209
+ ---
210
+
211
+ Roadmap
212
+
213
+ ☑ Tashkeel & Tatweel removal
214
+ ☑ Character normalization
215
+ ☑ File + stdin support
216
+ ☑ JSON output
217
+ ☑ Exit codes for CI/CD
218
+ ☑ Grammar audit (hamzat qat/wasl)
219
+ ☐ Extended audit rules
220
+ ☐ Dataset loading (CSV, JSONL)
221
+ ☐ Duplicate detection
222
+ ☐ Text quality statistics
223
+ ☐ Publish on PyPI
224
+
225
+ ---
226
+
227
+ Contributing
228
+
229
+ Contributions, issues, and feature requests are welcome! See CONTRIBUTING.md for guidelines.
230
+
231
+ ---
232
+
233
+ Releases
234
+
235
+ See Releases for version history.
236
+
237
+ ---
238
+
239
+ License
240
+
241
+ MIT — see LICENSE for details.
242
+
243
+ ---
244
+
245
+ <p align="center">
246
+ Made with ❤️ for the Arabic NLP community
247
+ </p>
@@ -0,0 +1,11 @@
1
+ arabcheck/__init__.py,sha256=k3WJRkPK83D3GeDH8_Fz1CLXDoRJ9Jplj82xWqKkTNc,143
2
+ arabcheck/__main__.py,sha256=R8toRIEpaunLvLRpFhTKF4x0aBUmBLoqHo0IrF4wuTw,82
3
+ arabcheck/cli.py,sha256=E-LY4gFpBzIaEeC2CnktrKlj06Yj1fYqPxmvqI-zqVA,2066
4
+ arabcheck/core.py,sha256=Z5IRDPqd-1rdsjCa3JiBACa125XNDVE6kz4p0rq1zA0,1804
5
+ arabcheck/patterns.py,sha256=BAEsf17cMsST8FiGx1WvjsPUVJwJH846rrUX6dcmFDg,833
6
+ arabcheck-0.1.0.dist-info/licenses/LICENSE,sha256=Z0UBEKMkWFJy26jZ6lmBo47o-s7PD0_qbM0sdxWUsws,1077
7
+ arabcheck-0.1.0.dist-info/METADATA,sha256=3n3-gTHf9lYiYZ7CJZEb1QS2KaLM9jMl4EjJO6Nsmk0,5423
8
+ arabcheck-0.1.0.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
9
+ arabcheck-0.1.0.dist-info/entry_points.txt,sha256=SubV1UOG9_4s0SYJiqhB5BS08pMtM7em-hVXQ8hN9b4,49
10
+ arabcheck-0.1.0.dist-info/top_level.txt,sha256=Eve9P2VpSSbULW8YxBF42OiN9OxkSXk5ntiJA45tEqA,10
11
+ arabcheck-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (84.0.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ arabcheck = arabcheck.cli:main
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Mohamed Kamal Sallih
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 @@
1
+ arabcheck