From db6db64366f48eb6372be9ad9dec248c8a40a871 Mon Sep 17 00:00:00 2001 From: amin Date: Thu, 4 Nov 2021 23:43:20 +0330 Subject: [PATCH 1/4] Reverse reshaping added --- arabic_reshaper/__init__.py | 4 +- arabic_reshaper/arabic_reshaper.py | 29 +++++++++++++ arabic_reshaper/tests/test_002_reshaping.py | 46 ++++++++++++++------- setup.py | 2 +- 4 files changed, 62 insertions(+), 19 deletions(-) diff --git a/arabic_reshaper/__init__.py b/arabic_reshaper/__init__.py index 89ea012..667b3ce 100644 --- a/arabic_reshaper/__init__.py +++ b/arabic_reshaper/__init__.py @@ -1,6 +1,6 @@ import os -from .arabic_reshaper import reshape, default_reshaper, ArabicReshaper +from .arabic_reshaper import reshape, default_reshaper, ArabicReshaper, reverse_reshape from .reshaper_config import (config_for_true_type_font, ENABLE_NO_LIGATURES, ENABLE_SENTENCES_LIGATURES, @@ -9,4 +9,4 @@ ENABLE_ALL_LIGATURES) -__version__ = '2.1.3' +__version__ = '2.2.3' diff --git a/arabic_reshaper/arabic_reshaper.py b/arabic_reshaper/arabic_reshaper.py index 4721a6a..6c4fdb0 100644 --- a/arabic_reshaper/arabic_reshaper.py +++ b/arabic_reshaper/arabic_reshaper.py @@ -238,6 +238,35 @@ def reshape(self, text): return ''.join(result) + def _reversed_letters(self): + reversed_letters = {} + for k, v in self.letters.items(): + [reversed_letters.update({char_: k}) for char_ in v if char_] + + return reversed_letters + + def reverse_reshape(self, text): + result = [] + reversed_letters = self._reversed_letters() + + for char_ in text: + if char_ in self.letters.keys(): + result.append(char_) + continue + + # a = [k for k, v in self.letters.items() if char_ in v] + # + # if not a: + # result.append(char_) + # continue + # + # result.append(a[0]) + + result.append(reversed_letters.get(char_, char_)) + + return "".join(result) + default_reshaper = ArabicReshaper() reshape = default_reshaper.reshape +reverse_reshape = default_reshaper.reverse_reshape diff --git a/arabic_reshaper/tests/test_002_reshaping.py b/arabic_reshaper/tests/test_002_reshaping.py index 9ad865b..a52a6ef 100644 --- a/arabic_reshaper/tests/test_002_reshaping.py +++ b/arabic_reshaper/tests/test_002_reshaping.py @@ -20,31 +20,45 @@ def t(): test.assertEqual(case[1], test.reshaper.reshape(case[0])) t() +def _reverse_reshaping_test(test): + for i, case in enumerate(test.cases): + def t(): test.assertEqual(case[2], test.reshaper.reverse_reshape(case[1])) + if hasattr(test, 'subTest'): + with test.subTest(i=i, case=case[0]): + t() + else: + print('running test case %d' % i, file=sys.stderr) + t() + + class TestDefaultReshaping(unittest.TestCase): def setUp(self): self.reshaper = arabic_reshaper.default_reshaper self.cases = ( - ('السلام عليكم', 'ﺍﻟﺴﻼﻡ ﻋﻠﻴﻜﻢ'), - ('السَلَاْمٌ عَلَيْكُمْ', 'ﺍﻟﺴﻼﻡ ﻋﻠﻴﻜﻢ'), - ('اللغة العربية هي أكثر اللغات', 'ﺍﻟﻠﻐﺔ ﺍﻟﻌﺮﺑﻴﺔ ﻫﻲ ﺃﻛﺜﺮ ﺍﻟﻠﻐﺎﺕ'), - ('تحدثاً ونطقاً ضمن مجموعة', 'ﺗﺤﺪﺛﺎ ﻭﻧﻄﻘﺎ ﺿﻤﻦ ﻣﺠﻤﻮﻋﺔ'), - ('اللغات السامية', 'ﺍﻟﻠﻐﺎﺕ ﺍﻟﺴﺎﻣﻴﺔ'), - ('العربية لغة رسمية في', 'ﺍﻟﻌﺮﺑﻴﺔ ﻟﻐﺔ ﺭﺳﻤﻴﺔ ﻓﻲ'), - ('كل دول الوطن العربي', 'ﻛﻞ ﺩﻭﻝ ﺍﻟﻮﻃﻦ ﺍﻟﻌﺮﺑﻲ'), - ('إضافة إلى كونها لغة', 'ﺇﺿﺎﻓﺔ ﺇﻟﻰ ﻛﻮﻧﻬﺎ ﻟﻐﺔ'), - ('رسمية في تشاد وإريتريا', 'ﺭﺳﻤﻴﺔ ﻓﻲ ﺗﺸﺎﺩ ﻭﺇﺭﻳﺘﺮﻳﺎ'), - ('وإسرائيل. وهي إحدى اللغات', 'ﻭﺇﺳﺮﺍﺋﻴﻞ. ﻭﻫﻲ ﺇﺣﺪﻯ ﺍﻟﻠﻐﺎﺕ'), - ('الرسمية الست في منظمة', 'ﺍﻟﺮﺳﻤﻴﺔ ﺍﻟﺴﺖ ﻓﻲ ﻣﻨﻈﻤﺔ'), - ('الأمم المتحدة، ويُحتفل', 'ﺍﻷﻣﻢ ﺍﻟﻤﺘﺤﺪﺓ، ﻭﻳﺤﺘﻔﻞ'), - ('باليوم العالمي للغة العربية', 'ﺑﺎﻟﻴﻮﻡ ﺍﻟﻌﺎﻟﻤﻲ ﻟﻠﻐﺔ ﺍﻟﻌﺮﺑﻴﺔ'), - ('في 18 ديسمبر كذكرى اعتماد', 'ﻓﻲ 18 ﺩﻳﺴﻤﺒﺮ ﻛﺬﻛﺮﻯ ﺍﻋﺘﻤﺎﺩ'), - ('العربية بين لغات العمل في', 'ﺍﻟﻌﺮﺑﻴﺔ ﺑﻴﻦ ﻟﻐﺎﺕ ﺍﻟﻌﻤﻞ ﻓﻲ'), - ('الأمم المتحدة.', 'ﺍﻷﻣﻢ ﺍﻟﻤﺘﺤﺪﺓ.'), + ('السلام عليكم', 'ﺍﻟﺴﻼﻡ ﻋﻠﻴﻜﻢ', 'السﻼم عليكم'), + ('السَلَاْمٌ عَلَيْكُمْ', 'ﺍﻟﺴﻼﻡ ﻋﻠﻴﻜﻢ', 'السﻼم عليكم'), + ('اللغة العربية هي أكثر اللغات', 'ﺍﻟﻠﻐﺔ ﺍﻟﻌﺮﺑﻴﺔ ﻫﻲ ﺃﻛﺜﺮ ﺍﻟﻠﻐﺎﺕ', 'اللغة العربية هي أكثر اللغات'), + ('تحدثاً ونطقاً ضمن مجموعة', 'ﺗﺤﺪﺛﺎ ﻭﻧﻄﻘﺎ ﺿﻤﻦ ﻣﺠﻤﻮﻋﺔ', 'تحدثا ونطقا ضمن مجموعة'), + ('اللغات السامية', 'ﺍﻟﻠﻐﺎﺕ ﺍﻟﺴﺎﻣﻴﺔ', 'اللغات السامية'), + ('العربية لغة رسمية في', 'ﺍﻟﻌﺮﺑﻴﺔ ﻟﻐﺔ ﺭﺳﻤﻴﺔ ﻓﻲ', 'العربية لغة رسمية في'), + ('كل دول الوطن العربي', 'ﻛﻞ ﺩﻭﻝ ﺍﻟﻮﻃﻦ ﺍﻟﻌﺮﺑﻲ', 'كل دول الوطن العربي'), + ('إضافة إلى كونها لغة', 'ﺇﺿﺎﻓﺔ ﺇﻟﻰ ﻛﻮﻧﻬﺎ ﻟﻐﺔ', 'إضافة إلى كونها لغة'), + ('رسمية في تشاد وإريتريا', 'ﺭﺳﻤﻴﺔ ﻓﻲ ﺗﺸﺎﺩ ﻭﺇﺭﻳﺘﺮﻳﺎ', 'رسمية في تشاد وإريتريا'), + ('وإسرائيل. وهي إحدى اللغات', 'ﻭﺇﺳﺮﺍﺋﻴﻞ. ﻭﻫﻲ ﺇﺣﺪﻯ ﺍﻟﻠﻐﺎﺕ', 'وإسرائيل. وهي إحدى اللغات'), + ('الرسمية الست في منظمة', 'ﺍﻟﺮﺳﻤﻴﺔ ﺍﻟﺴﺖ ﻓﻲ ﻣﻨﻈﻤﺔ', 'الرسمية الست في منظمة'), + ('الأمم المتحدة، ويُحتفل', 'ﺍﻷﻣﻢ ﺍﻟﻤﺘﺤﺪﺓ، ﻭﻳﺤﺘﻔﻞ', 'اﻷمم المتحدة، ويحتفل'), + ('باليوم العالمي للغة العربية', 'ﺑﺎﻟﻴﻮﻡ ﺍﻟﻌﺎﻟﻤﻲ ﻟﻠﻐﺔ ﺍﻟﻌﺮﺑﻴﺔ', 'باليوم العالمي للغة العربية'), + ('في 18 ديسمبر كذكرى اعتماد', 'ﻓﻲ 18 ﺩﻳﺴﻤﺒﺮ ﻛﺬﻛﺮﻯ ﺍﻋﺘﻤﺎﺩ', 'في 18 ديسمبر كذكرى اعتماد'), + ('العربية بين لغات العمل في', 'ﺍﻟﻌﺮﺑﻴﺔ ﺑﻴﻦ ﻟﻐﺎﺕ ﺍﻟﻌﻤﻞ ﻓﻲ', 'العربية بين لغات العمل في'), + ('الأمم المتحدة.', 'ﺍﻷﻣﻢ ﺍﻟﻤﺘﺤﺪﺓ.', 'اﻷمم المتحدة.'), ) def test_reshaping(self): _reshaping_test(self) + def test_reverse_reshaping(self): + _reverse_reshaping_test(self) + class TestZWJReshaping(unittest.TestCase): def setUp(self): diff --git a/setup.py b/setup.py index b9ce8f3..3ef1a1c 100755 --- a/setup.py +++ b/setup.py @@ -14,7 +14,7 @@ " applications that don't support Arabic"), long_description=long_description, long_description_content_type="text/markdown", - version='2.1.3', + version='2.2.3', platforms="ALL", license="MIT", packages=['arabic_reshaper'], From 1a02cdbd9123927638266912a8e99c010c678185 Mon Sep 17 00:00:00 2001 From: amin Date: Fri, 12 Nov 2021 22:02:17 +0330 Subject: [PATCH 2/4] Tests fixed --- arabic_reshaper/arabic_reshaper.py | 98 +++++++++++-- arabic_reshaper/letters.py | 12 ++ arabic_reshaper/tests/test_002_reshaping.py | 153 ++++++++++++-------- 3 files changed, 191 insertions(+), 72 deletions(-) diff --git a/arabic_reshaper/arabic_reshaper.py b/arabic_reshaper/arabic_reshaper.py index 6c4fdb0..263307d 100644 --- a/arabic_reshaper/arabic_reshaper.py +++ b/arabic_reshaper/arabic_reshaper.py @@ -15,7 +15,7 @@ from .ligatures import LIGATURES from .reshaper_config import auto_config -from .letters import (UNSHAPED, ISOLATED, TATWEEL, ZWJ, LETTERS_ARABIC, +from .letters import (UNSHAPED, ISOLATED, TATWEEL, ZWJ, LETTERS_ARABIC, SPECIAL_LETTERS, LETTERS_ARABIC_V2, LETTERS_KURDISH, FINAL, INITIAL, MEDIAL, connects_with_letters_before_and_after, connects_with_letter_before, connects_with_letter_after) @@ -152,8 +152,8 @@ def reshape(self, text): previous_letter[LETTER], self.letters): output.append((letter, isolated_form)) elif (previous_letter[FORM] == FINAL and not - connects_with_letters_before_and_after( - previous_letter[LETTER], self.letters + connects_with_letters_before_and_after( + previous_letter[LETTER], self.letters )): output.append((letter, isolated_form)) elif previous_letter[FORM] == isolated_form: @@ -239,29 +239,103 @@ def reshape(self, text): return ''.join(result) def _reversed_letters(self): + """ + Declared letters are for reshaping by default. This if for reversing declared letters and preparing them + for reverse reshaping + For example assume that we have a declared letter like: '\u0626': ('\uFE89', '\uFE8B', '\uFE8C', '\uFE8A') + We need to reverse it and change it to a dict like: { + '\uFE89': '\u0626', + '\uFE8B': '\u0626', + '\uFE8C': '\u0626', + '\uFE8A': '\u0626', + } + Now with this reversed letter dict, we can change char '\uFE89' to '\u0626' in text easily + """ reversed_letters = {} + + # example for k: '\u0626' + # example for v: ('\uFE89', '\uFE8B', '\uFE8C', '\uFE8A'). so v is a tuple for k, v in self.letters.items(): + # Add char_ and its normal form as a dict, if char_ was not null [reversed_letters.update({char_: k}) for char_ in v if char_] return reversed_letters - def reverse_reshape(self, text): + def _reversed_ligatures(self): + """ + Declared ligatures are for reshaping by default. This if for reversing declared ligatures and preparing them + for reverse reshaping + For example assume that we have a declared ligatures like: ('ARABIC LIGATURE SAD WITH HAH', ( + '\u0635\u062D', ('\uFC20', '\uFCB1', '', ''), + )), + We need to reverse it and change it to a dict like: { + '\uFC20': '\u0635\u062D', + '\uFCB1': '\u0635\u062D', + } + Now with this reversed ligatures dict, we can change char '\uFC20' to '\u0635\u062D' in text easily + Actually first element of declared ligature would be ignored + """ + original_text = 0 + reshaped_text = 1 + + reversed_ligatures = {} + + # title example: 'ARABIC LIGATURE SAD WITH HAH' + # ligature example: ('\u0635\u062D', ('\uFC20', '\uFCB1', '', '')) + for title, ligature in LIGATURES: + [reversed_ligatures.update({char_: ligature[original_text]}) for + char_ in ligature[reshaped_text] if char_] + + return reversed_ligatures + + def reverse_reshape(self, text: str) -> str: + """ + This is for reshaping from a reshaped text to original one + It iterates over each char of text + First checks if that char exists in original chars list. If that's so, + it means that char has not changed during reshape process and is equal to it's original shape. So that + would be appended to result without change + Second, checks if char is in SPECIAL_LETTERS. these letters are those which have generated during reshaping + process, and need to get replaced with their two chars + Third, checks if char is in ligatures. If that's so, would replace with original text + And finally, if any of mentioned conditions didn't meet, would try to find original shape of char, in + reversed_letters + """ + text_list = list(text) result = [] reversed_letters = self._reversed_letters() + reversed_ligatures = self._reversed_ligatures() - for char_ in text: + for index, char_ in enumerate(text_list): + # Checking if char_ is in original shape letters list and has not changed during reshape if char_ in self.letters.keys(): result.append(char_) continue - # a = [k for k, v in self.letters.items() if char_ in v] - # - # if not a: - # result.append(char_) - # continue - # - # result.append(a[0]) + # Checking if char_ is a special character + if char_ in SPECIAL_LETTERS.keys(): + next_char = text_list[index+1] + next_next_char = text_list[index+2] + + # Checking if two following chars are harakat. in that case, first harakat should be placed in middle + # of special chars + if HARAKAT_RE.match(next_char) and HARAKAT_RE.match(next_next_char): + result.append(next_char.join(list(SPECIAL_LETTERS.get(char_)))) + + # Omitting first harakat + text_list[index+1] = '' + + else: + result.append("".join(list(SPECIAL_LETTERS.get(char_)))) + + continue + + # Checking if char_ is in ligatures + if char_ in reversed_ligatures: + result.append(reversed_ligatures[char_]) + continue + # If couldn't find char is letters, append char itself result.append(reversed_letters.get(char_, char_)) return "".join(result) diff --git a/arabic_reshaper/letters.py b/arabic_reshaper/letters.py index e0ebd71..c570596 100644 --- a/arabic_reshaper/letters.py +++ b/arabic_reshaper/letters.py @@ -508,6 +508,18 @@ ZWJ: (ZWJ, ZWJ, ZWJ, ZWJ), } +# Special letters are like lam with alef with hamza. for reverse reshaping, we need this to reverse from reshaped +# lam with alef to regular one +SPECIAL_LETTERS = { + # lam alef + '\ufefc': ('\u0644', '\u0627'), + # lam with alef with hamza + '\ufef7': ('\u0644', '\u0623'), + # lam with alef with mad + '\ufef5': ('\u0644', '\u0622'), +} + + def connects_with_letter_before(letter,LETTERS): if letter not in LETTERS: return False diff --git a/arabic_reshaper/tests/test_002_reshaping.py b/arabic_reshaper/tests/test_002_reshaping.py index a52a6ef..2c949aa 100644 --- a/arabic_reshaper/tests/test_002_reshaping.py +++ b/arabic_reshaper/tests/test_002_reshaping.py @@ -35,8 +35,8 @@ class TestDefaultReshaping(unittest.TestCase): def setUp(self): self.reshaper = arabic_reshaper.default_reshaper self.cases = ( - ('السلام عليكم', 'ﺍﻟﺴﻼﻡ ﻋﻠﻴﻜﻢ', 'السﻼم عليكم'), - ('السَلَاْمٌ عَلَيْكُمْ', 'ﺍﻟﺴﻼﻡ ﻋﻠﻴﻜﻢ', 'السﻼم عليكم'), + ('السلام عليكم', 'ﺍﻟﺴﻼﻡ ﻋﻠﻴﻜﻢ', 'السلام عليكم'), + ('السَلَاْمٌ عَلَيْكُمْ', 'ﺍﻟﺴﻼﻡ ﻋﻠﻴﻜﻢ', 'السلام عليكم'), ('اللغة العربية هي أكثر اللغات', 'ﺍﻟﻠﻐﺔ ﺍﻟﻌﺮﺑﻴﺔ ﻫﻲ ﺃﻛﺜﺮ ﺍﻟﻠﻐﺎﺕ', 'اللغة العربية هي أكثر اللغات'), ('تحدثاً ونطقاً ضمن مجموعة', 'ﺗﺤﺪﺛﺎ ﻭﻧﻄﻘﺎ ﺿﻤﻦ ﻣﺠﻤﻮﻋﺔ', 'تحدثا ونطقا ضمن مجموعة'), ('اللغات السامية', 'ﺍﻟﻠﻐﺎﺕ ﺍﻟﺴﺎﻣﻴﺔ', 'اللغات السامية'), @@ -46,11 +46,12 @@ def setUp(self): ('رسمية في تشاد وإريتريا', 'ﺭﺳﻤﻴﺔ ﻓﻲ ﺗﺸﺎﺩ ﻭﺇﺭﻳﺘﺮﻳﺎ', 'رسمية في تشاد وإريتريا'), ('وإسرائيل. وهي إحدى اللغات', 'ﻭﺇﺳﺮﺍﺋﻴﻞ. ﻭﻫﻲ ﺇﺣﺪﻯ ﺍﻟﻠﻐﺎﺕ', 'وإسرائيل. وهي إحدى اللغات'), ('الرسمية الست في منظمة', 'ﺍﻟﺮﺳﻤﻴﺔ ﺍﻟﺴﺖ ﻓﻲ ﻣﻨﻈﻤﺔ', 'الرسمية الست في منظمة'), - ('الأمم المتحدة، ويُحتفل', 'ﺍﻷﻣﻢ ﺍﻟﻤﺘﺤﺪﺓ، ﻭﻳﺤﺘﻔﻞ', 'اﻷمم المتحدة، ويحتفل'), + ('الأمم المتحدة، ويُحتفل', 'ﺍﻷﻣﻢ ﺍﻟﻤﺘﺤﺪﺓ، ﻭﻳﺤﺘﻔﻞ', 'الأمم المتحدة، ويحتفل'), ('باليوم العالمي للغة العربية', 'ﺑﺎﻟﻴﻮﻡ ﺍﻟﻌﺎﻟﻤﻲ ﻟﻠﻐﺔ ﺍﻟﻌﺮﺑﻴﺔ', 'باليوم العالمي للغة العربية'), ('في 18 ديسمبر كذكرى اعتماد', 'ﻓﻲ 18 ﺩﻳﺴﻤﺒﺮ ﻛﺬﻛﺮﻯ ﺍﻋﺘﻤﺎﺩ', 'في 18 ديسمبر كذكرى اعتماد'), ('العربية بين لغات العمل في', 'ﺍﻟﻌﺮﺑﻴﺔ ﺑﻴﻦ ﻟﻐﺎﺕ ﺍﻟﻌﻤﻞ ﻓﻲ', 'العربية بين لغات العمل في'), - ('الأمم المتحدة.', 'ﺍﻷﻣﻢ ﺍﻟﻤﺘﺤﺪﺓ.', 'اﻷمم المتحدة.'), + ('الأمم المتحدة.', 'ﺍﻷﻣﻢ ﺍﻟﻤﺘﺤﺪﺓ.', 'الأمم المتحدة.'), + ('الآمم المتحدة.', 'ﺍﻵﻣﻢ ﺍﻟﻤﺘﺤﺪﺓ.', 'الآمم المتحدة.'), ) def test_reshaping(self): @@ -142,26 +143,29 @@ def setUp(self): 'delete_harakat': False }) self.cases = ( - ('السَلَاْمٌ عَلَيْكُمْ', 'ﺍﻟﺴَﻼَْﻡٌ ﻋَﻠَﻴْﻜُﻢْ'), - ('اللغة العربية هي أكثر اللغات', 'ﺍﻟﻠﻐﺔ ﺍﻟﻌﺮﺑﻴﺔ ﻫﻲ ﺃﻛﺜﺮ ﺍﻟﻠﻐﺎﺕ'), - ('تحدثاً ونطقاً ضمن مجموعة', 'ﺗﺤﺪﺛﺎً ﻭﻧﻄﻘﺎً ﺿﻤﻦ ﻣﺠﻤﻮﻋﺔ'), - ('اللغات السامية', 'ﺍﻟﻠﻐﺎﺕ ﺍﻟﺴﺎﻣﻴﺔ'), - ('العربية لغة رسمية في', 'ﺍﻟﻌﺮﺑﻴﺔ ﻟﻐﺔ ﺭﺳﻤﻴﺔ ﻓﻲ'), - ('كل دول الوطن العربي', 'ﻛﻞ ﺩﻭﻝ ﺍﻟﻮﻃﻦ ﺍﻟﻌﺮﺑﻲ'), - ('إضافة إلى كونها لغة', 'ﺇﺿﺎﻓﺔ ﺇﻟﻰ ﻛﻮﻧﻬﺎ ﻟﻐﺔ'), - ('رسمية في تشاد وإريتريا', 'ﺭﺳﻤﻴﺔ ﻓﻲ ﺗﺸﺎﺩ ﻭﺇﺭﻳﺘﺮﻳﺎ'), - ('وإسرائيل. وهي إحدى اللغات', 'ﻭﺇﺳﺮﺍﺋﻴﻞ. ﻭﻫﻲ ﺇﺣﺪﻯ ﺍﻟﻠﻐﺎﺕ'), - ('الرسمية الست في منظمة', 'ﺍﻟﺮﺳﻤﻴﺔ ﺍﻟﺴﺖ ﻓﻲ ﻣﻨﻈﻤﺔ'), - ('الأمم المتحدة، ويُحتفل', 'ﺍﻷﻣﻢ ﺍﻟﻤﺘﺤﺪﺓ، ﻭﻳُﺤﺘﻔﻞ'), - ('باليوم العالمي للغة العربية', 'ﺑﺎﻟﻴﻮﻡ ﺍﻟﻌﺎﻟﻤﻲ ﻟﻠﻐﺔ ﺍﻟﻌﺮﺑﻴﺔ'), - ('في 18 ديسمبر كذكرى اعتماد', 'ﻓﻲ 18 ﺩﻳﺴﻤﺒﺮ ﻛﺬﻛﺮﻯ ﺍﻋﺘﻤﺎﺩ'), - ('العربية بين لغات العمل في', 'ﺍﻟﻌﺮﺑﻴﺔ ﺑﻴﻦ ﻟﻐﺎﺕ ﺍﻟﻌﻤﻞ ﻓﻲ'), - ('الأمم المتحدة.', 'ﺍﻷﻣﻢ ﺍﻟﻤﺘﺤﺪﺓ.'), + ('السَلَاْمٌ عَلَيْكُمْ', 'ﺍﻟﺴَﻼَْﻡٌ ﻋَﻠَﻴْﻜُﻢْ', 'السَلَاْمٌ عَلَيْكُمْ'), + ('اللغة العربية هي أكثر اللغات', 'ﺍﻟﻠﻐﺔ ﺍﻟﻌﺮﺑﻴﺔ ﻫﻲ ﺃﻛﺜﺮ ﺍﻟﻠﻐﺎﺕ', 'اللغة العربية هي أكثر اللغات'), + ('تحدثاً ونطقاً ضمن مجموعة', 'ﺗﺤﺪﺛﺎً ﻭﻧﻄﻘﺎً ﺿﻤﻦ ﻣﺠﻤﻮﻋﺔ', 'تحدثاً ونطقاً ضمن مجموعة'), + ('اللغات السامية', 'ﺍﻟﻠﻐﺎﺕ ﺍﻟﺴﺎﻣﻴﺔ', 'اللغات السامية'), + ('العربية لغة رسمية في', 'ﺍﻟﻌﺮﺑﻴﺔ ﻟﻐﺔ ﺭﺳﻤﻴﺔ ﻓﻲ', 'العربية لغة رسمية في'), + ('كل دول الوطن العربي', 'ﻛﻞ ﺩﻭﻝ ﺍﻟﻮﻃﻦ ﺍﻟﻌﺮﺑﻲ', 'كل دول الوطن العربي'), + ('إضافة إلى كونها لغة', 'ﺇﺿﺎﻓﺔ ﺇﻟﻰ ﻛﻮﻧﻬﺎ ﻟﻐﺔ', 'إضافة إلى كونها لغة'), + ('رسمية في تشاد وإريتريا', 'ﺭﺳﻤﻴﺔ ﻓﻲ ﺗﺸﺎﺩ ﻭﺇﺭﻳﺘﺮﻳﺎ', 'رسمية في تشاد وإريتريا'), + ('وإسرائيل. وهي إحدى اللغات', 'ﻭﺇﺳﺮﺍﺋﻴﻞ. ﻭﻫﻲ ﺇﺣﺪﻯ ﺍﻟﻠﻐﺎﺕ', 'وإسرائيل. وهي إحدى اللغات'), + ('الرسمية الست في منظمة', 'ﺍﻟﺮﺳﻤﻴﺔ ﺍﻟﺴﺖ ﻓﻲ ﻣﻨﻈﻤﺔ', 'الرسمية الست في منظمة'), + ('الأمم المتحدة، ويُحتفل', 'ﺍﻷﻣﻢ ﺍﻟﻤﺘﺤﺪﺓ، ﻭﻳُﺤﺘﻔﻞ', 'الأمم المتحدة، ويُحتفل'), + ('باليوم العالمي للغة العربية', 'ﺑﺎﻟﻴﻮﻡ ﺍﻟﻌﺎﻟﻤﻲ ﻟﻠﻐﺔ ﺍﻟﻌﺮﺑﻴﺔ', 'باليوم العالمي للغة العربية'), + ('في 18 ديسمبر كذكرى اعتماد', 'ﻓﻲ 18 ﺩﻳﺴﻤﺒﺮ ﻛﺬﻛﺮﻯ ﺍﻋﺘﻤﺎﺩ', 'في 18 ديسمبر كذكرى اعتماد'), + ('العربية بين لغات العمل في', 'ﺍﻟﻌﺮﺑﻴﺔ ﺑﻴﻦ ﻟﻐﺎﺕ ﺍﻟﻌﻤﻞ ﻓﻲ', 'العربية بين لغات العمل في'), + ('الأمم المتحدة.', 'ﺍﻷﻣﻢ ﺍﻟﻤﺘﺤﺪﺓ.', 'الأمم المتحدة.'), ) def test_reshaping(self): _reshaping_test(self) + def test_reverse_reshaping(self): + _reverse_reshaping_test(self) + class TestReshapingWithHarakatWithoutLigatures(unittest.TestCase): def setUp(self): @@ -170,26 +174,29 @@ def setUp(self): 'support_ligatures': False }) self.cases = ( - ('السَلَاْمٌ عَلَيْكُمْ', 'ﺍﻟﺴَﻠَﺎْﻡٌ ﻋَﻠَﻴْﻜُﻢْ'), - ('اللغة العربية هي أكثر اللغات', 'ﺍﻟﻠﻐﺔ ﺍﻟﻌﺮﺑﻴﺔ ﻫﻲ ﺃﻛﺜﺮ ﺍﻟﻠﻐﺎﺕ'), - ('تحدثاً ونطقاً ضمن مجموعة', 'ﺗﺤﺪﺛﺎً ﻭﻧﻄﻘﺎً ﺿﻤﻦ ﻣﺠﻤﻮﻋﺔ'), - ('اللغات السامية', 'ﺍﻟﻠﻐﺎﺕ ﺍﻟﺴﺎﻣﻴﺔ'), - ('العربية لغة رسمية في', 'ﺍﻟﻌﺮﺑﻴﺔ ﻟﻐﺔ ﺭﺳﻤﻴﺔ ﻓﻲ'), - ('كل دول الوطن العربي', 'ﻛﻞ ﺩﻭﻝ ﺍﻟﻮﻃﻦ ﺍﻟﻌﺮﺑﻲ'), - ('إضافة إلى كونها لغة', 'ﺇﺿﺎﻓﺔ ﺇﻟﻰ ﻛﻮﻧﻬﺎ ﻟﻐﺔ'), - ('رسمية في تشاد وإريتريا', 'ﺭﺳﻤﻴﺔ ﻓﻲ ﺗﺸﺎﺩ ﻭﺇﺭﻳﺘﺮﻳﺎ'), - ('وإسرائيل. وهي إحدى اللغات', 'ﻭﺇﺳﺮﺍﺋﻴﻞ. ﻭﻫﻲ ﺇﺣﺪﻯ ﺍﻟﻠﻐﺎﺕ'), - ('الرسمية الست في منظمة', 'ﺍﻟﺮﺳﻤﻴﺔ ﺍﻟﺴﺖ ﻓﻲ ﻣﻨﻈﻤﺔ'), - ('الأمم المتحدة، ويُحتفل', 'ﺍﻟﺄﻣﻢ ﺍﻟﻤﺘﺤﺪﺓ، ﻭﻳُﺤﺘﻔﻞ'), - ('باليوم العالمي للغة العربية', 'ﺑﺎﻟﻴﻮﻡ ﺍﻟﻌﺎﻟﻤﻲ ﻟﻠﻐﺔ ﺍﻟﻌﺮﺑﻴﺔ'), - ('في 18 ديسمبر كذكرى اعتماد', 'ﻓﻲ 18 ﺩﻳﺴﻤﺒﺮ ﻛﺬﻛﺮﻯ ﺍﻋﺘﻤﺎﺩ'), - ('العربية بين لغات العمل في', 'ﺍﻟﻌﺮﺑﻴﺔ ﺑﻴﻦ ﻟﻐﺎﺕ ﺍﻟﻌﻤﻞ ﻓﻲ'), - ('الأمم المتحدة.', 'ﺍﻟﺄﻣﻢ ﺍﻟﻤﺘﺤﺪﺓ.'), + ('السَلَاْمٌ عَلَيْكُمْ', 'ﺍﻟﺴَﻠَﺎْﻡٌ ﻋَﻠَﻴْﻜُﻢْ', 'السَلَاْمٌ عَلَيْكُمْ'), + ('اللغة العربية هي أكثر اللغات', 'ﺍﻟﻠﻐﺔ ﺍﻟﻌﺮﺑﻴﺔ ﻫﻲ ﺃﻛﺜﺮ ﺍﻟﻠﻐﺎﺕ', 'اللغة العربية هي أكثر اللغات'), + ('تحدثاً ونطقاً ضمن مجموعة', 'ﺗﺤﺪﺛﺎً ﻭﻧﻄﻘﺎً ﺿﻤﻦ ﻣﺠﻤﻮﻋﺔ', 'تحدثاً ونطقاً ضمن مجموعة'), + ('اللغات السامية', 'ﺍﻟﻠﻐﺎﺕ ﺍﻟﺴﺎﻣﻴﺔ', 'اللغات السامية'), + ('العربية لغة رسمية في', 'ﺍﻟﻌﺮﺑﻴﺔ ﻟﻐﺔ ﺭﺳﻤﻴﺔ ﻓﻲ', 'العربية لغة رسمية في'), + ('كل دول الوطن العربي', 'ﻛﻞ ﺩﻭﻝ ﺍﻟﻮﻃﻦ ﺍﻟﻌﺮﺑﻲ', 'كل دول الوطن العربي'), + ('إضافة إلى كونها لغة', 'ﺇﺿﺎﻓﺔ ﺇﻟﻰ ﻛﻮﻧﻬﺎ ﻟﻐﺔ', 'إضافة إلى كونها لغة'), + ('رسمية في تشاد وإريتريا', 'ﺭﺳﻤﻴﺔ ﻓﻲ ﺗﺸﺎﺩ ﻭﺇﺭﻳﺘﺮﻳﺎ', 'رسمية في تشاد وإريتريا'), + ('وإسرائيل. وهي إحدى اللغات', 'ﻭﺇﺳﺮﺍﺋﻴﻞ. ﻭﻫﻲ ﺇﺣﺪﻯ ﺍﻟﻠﻐﺎﺕ', 'وإسرائيل. وهي إحدى اللغات'), + ('الرسمية الست في منظمة', 'ﺍﻟﺮﺳﻤﻴﺔ ﺍﻟﺴﺖ ﻓﻲ ﻣﻨﻈﻤﺔ', 'الرسمية الست في منظمة'), + ('الأمم المتحدة، ويُحتفل', 'ﺍﻟﺄﻣﻢ ﺍﻟﻤﺘﺤﺪﺓ، ﻭﻳُﺤﺘﻔﻞ', 'الأمم المتحدة، ويُحتفل'), + ('باليوم العالمي للغة العربية', 'ﺑﺎﻟﻴﻮﻡ ﺍﻟﻌﺎﻟﻤﻲ ﻟﻠﻐﺔ ﺍﻟﻌﺮﺑﻴﺔ', 'باليوم العالمي للغة العربية'), + ('في 18 ديسمبر كذكرى اعتماد', 'ﻓﻲ 18 ﺩﻳﺴﻤﺒﺮ ﻛﺬﻛﺮﻯ ﺍﻋﺘﻤﺎﺩ', 'في 18 ديسمبر كذكرى اعتماد'), + ('العربية بين لغات العمل في', 'ﺍﻟﻌﺮﺑﻴﺔ ﺑﻴﻦ ﻟﻐﺎﺕ ﺍﻟﻌﻤﻞ ﻓﻲ', 'العربية بين لغات العمل في'), + ('الأمم المتحدة.', 'ﺍﻟﺄﻣﻢ ﺍﻟﻤﺘﺤﺪﺓ.', 'الأمم المتحدة.'), ) def test_reshaping(self): _reshaping_test(self) + def test_reverse_reshaping(self): + _reverse_reshaping_test(self) + class TestReshapingWithShiftedHarakatWithoutLigatures(unittest.TestCase): def setUp(self): @@ -231,36 +238,62 @@ def setUp(self): 'وَأْتُونِي مُسْلِمِينَ ﴿٣١﴾', 'ﺇﻧﻪ ﻣﻦ ﺳﻠﻴﻤﺎﻥ ﻭﺇﻧﻪ ﷽ ﴿٣٠﴾ ' - 'ﺃﻻ ﺗﻌﻠﻮﺍ ﻋﻠﻲ ﻭﺃﺗﻮﻧﻲ ﻣﺴﻠﻤﻴﻦ ﴿٣١﴾'), - - ('فَذَكِّرْ إِنَّمَا أَنتَ' - ' مُذَكِّرٌ ﴿٢١﴾ لَّسْتَ' - ' عَلَيْهِم بِمُصَيْطِرٍ ﴿٢٢﴾' - ' إِلَّا مَن تَوَلَّىٰ' - ' وَكَفَرَ ﴿٢٣﴾ فَيُعَذِّبُهُ' - ' اللَّـهُ الْعَذَابَ' - ' الْأَكْبَرَ ﴿٢٤﴾', - - 'ﻓﺬﻛﺮ ﺇﻧﻤﺎ ﺃﻧﺖ' - ' ﻣﺬﻛﺮ ﴿٢١﴾ ﻟﺴﺖ' - ' ﻋﻠﻴﻬﻢ ﺑﻤﺼﻴﻄﺮ ﴿٢٢﴾' - ' ﺇﻻ ﻣﻦ ﺗﻮﻟﻰ' - ' ﻭﻛﻔﺮ ﴿٢٣﴾ ﻓﻴﻌﺬﺑﻪ' - ' ﷲ ﺍﻟﻌﺬﺍﺏ' - ' ﺍﻷﻛﺒﺮ ﴿٢٤﴾'), - - ('محمد رسول الله صلى الله عليه وسلم', - 'ﷴ ﷶ ﷲ ﷺ'), - - ('الله جل جلاله', - 'ﷲ ﷻ'), - - ('محمد رسول الله عليه صلى الله وسلم', - 'ﷴ ﷶ ﷲ ﷷ ﷹ ﷲ ﷸ'), + 'ﺃﻻ ﺗﻌﻠﻮﺍ ﻋﻠﻲ ﻭﺃﺗﻮﻧﻲ ﻣﺴﻠﻤﻴﻦ ﴿٣١﴾', + + 'إنه من سليمان وإنه بسم الله الرحمن الرحيم ﴿٣٠﴾ ' + 'ألا تعلوا علي وأتوني مسلمين ﴿٣١﴾' + ), + ( + 'فَذَكِّرْ إِنَّمَا أَنتَ' + ' مُذَكِّرٌ ﴿٢١﴾ لَّسْتَ' + ' عَلَيْهِم بِمُصَيْطِرٍ ﴿٢٢﴾' + ' إِلَّا مَن تَوَلَّىٰ' + ' وَكَفَرَ ﴿٢٣﴾ فَيُعَذِّبُهُ' + ' اللَّـهُ الْعَذَابَ' + ' الْأَكْبَرَ ﴿٢٤﴾', + + 'ﻓﺬﻛﺮ ﺇﻧﻤﺎ ﺃﻧﺖ' + ' ﻣﺬﻛﺮ ﴿٢١﴾ ﻟﺴﺖ' + ' ﻋﻠﻴﻬﻢ ﺑﻤﺼﻴﻄﺮ ﴿٢٢﴾' + ' ﺇﻻ ﻣﻦ ﺗﻮﻟﻰ' + ' ﻭﻛﻔﺮ ﴿٢٣﴾ ﻓﻴﻌﺬﺑﻪ' + ' ﷲ ﺍﻟﻌﺬﺍﺏ' + ' ﺍﻷﻛﺒﺮ ﴿٢٤﴾', + + 'فذكر إنما أنت' + ' مذكر ﴿٢١﴾ لست' + ' عليهم بمصيطر ﴿٢٢﴾' + ' إلا من تولى' + ' وكفر ﴿٢٣﴾ فيعذبه' + ' الله العذاب' + ' الأكبر ﴿٢٤﴾', + ), + + ( + 'محمد رسول الله صلى الله عليه وسلم', + 'ﷴ ﷶ ﷲ ﷺ', + 'محمد رسول الله صلى الله عليه وسلم', + ), + + ( + 'الله جل جلاله', + 'ﷲ ﷻ', + 'الله جل جلاله', + ), + + ( + 'محمد رسول الله عليه صلى الله وسلم', + 'ﷴ ﷶ ﷲ ﷷ ﷹ ﷲ ﷸ', + 'محمد رسول الله عليه صلى الله وسلم', + ), ) def test_reshaping(self): _reshaping_test(self) + def test_reverse_reshaping(self): + _reverse_reshaping_test(self) + + if __name__ == '__main__': unittest.main() From d5e3034281e2e2bddb82f7295cc71631aec9ae46 Mon Sep 17 00:00:00 2001 From: amin Date: Sat, 13 Nov 2021 20:43:57 +0330 Subject: [PATCH 3/4] Unreshape tests separated --- arabic_reshaper/__init__.py | 2 +- arabic_reshaper/arabic_reshaper.py | 4 +- arabic_reshaper/tests/test_002_reshaping.py | 191 +++++++----------- arabic_reshaper/tests/test_004_unreshaping.py | 169 ++++++++++++++++ 4 files changed, 244 insertions(+), 122 deletions(-) create mode 100644 arabic_reshaper/tests/test_004_unreshaping.py diff --git a/arabic_reshaper/__init__.py b/arabic_reshaper/__init__.py index 667b3ce..fc861c2 100644 --- a/arabic_reshaper/__init__.py +++ b/arabic_reshaper/__init__.py @@ -1,6 +1,6 @@ import os -from .arabic_reshaper import reshape, default_reshaper, ArabicReshaper, reverse_reshape +from .arabic_reshaper import reshape, default_reshaper, ArabicReshaper, unreshape from .reshaper_config import (config_for_true_type_font, ENABLE_NO_LIGATURES, ENABLE_SENTENCES_LIGATURES, diff --git a/arabic_reshaper/arabic_reshaper.py b/arabic_reshaper/arabic_reshaper.py index 263307d..c3d3609 100644 --- a/arabic_reshaper/arabic_reshaper.py +++ b/arabic_reshaper/arabic_reshaper.py @@ -288,7 +288,7 @@ def _reversed_ligatures(self): return reversed_ligatures - def reverse_reshape(self, text: str) -> str: + def unreshape(self, text: str) -> str: """ This is for reshaping from a reshaped text to original one It iterates over each char of text @@ -343,4 +343,4 @@ def reverse_reshape(self, text: str) -> str: default_reshaper = ArabicReshaper() reshape = default_reshaper.reshape -reverse_reshape = default_reshaper.reverse_reshape +unreshape = default_reshaper.unreshape diff --git a/arabic_reshaper/tests/test_002_reshaping.py b/arabic_reshaper/tests/test_002_reshaping.py index 2c949aa..9ad865b 100644 --- a/arabic_reshaper/tests/test_002_reshaping.py +++ b/arabic_reshaper/tests/test_002_reshaping.py @@ -20,46 +20,31 @@ def t(): test.assertEqual(case[1], test.reshaper.reshape(case[0])) t() -def _reverse_reshaping_test(test): - for i, case in enumerate(test.cases): - def t(): test.assertEqual(case[2], test.reshaper.reverse_reshape(case[1])) - if hasattr(test, 'subTest'): - with test.subTest(i=i, case=case[0]): - t() - else: - print('running test case %d' % i, file=sys.stderr) - t() - - class TestDefaultReshaping(unittest.TestCase): def setUp(self): self.reshaper = arabic_reshaper.default_reshaper self.cases = ( - ('السلام عليكم', 'ﺍﻟﺴﻼﻡ ﻋﻠﻴﻜﻢ', 'السلام عليكم'), - ('السَلَاْمٌ عَلَيْكُمْ', 'ﺍﻟﺴﻼﻡ ﻋﻠﻴﻜﻢ', 'السلام عليكم'), - ('اللغة العربية هي أكثر اللغات', 'ﺍﻟﻠﻐﺔ ﺍﻟﻌﺮﺑﻴﺔ ﻫﻲ ﺃﻛﺜﺮ ﺍﻟﻠﻐﺎﺕ', 'اللغة العربية هي أكثر اللغات'), - ('تحدثاً ونطقاً ضمن مجموعة', 'ﺗﺤﺪﺛﺎ ﻭﻧﻄﻘﺎ ﺿﻤﻦ ﻣﺠﻤﻮﻋﺔ', 'تحدثا ونطقا ضمن مجموعة'), - ('اللغات السامية', 'ﺍﻟﻠﻐﺎﺕ ﺍﻟﺴﺎﻣﻴﺔ', 'اللغات السامية'), - ('العربية لغة رسمية في', 'ﺍﻟﻌﺮﺑﻴﺔ ﻟﻐﺔ ﺭﺳﻤﻴﺔ ﻓﻲ', 'العربية لغة رسمية في'), - ('كل دول الوطن العربي', 'ﻛﻞ ﺩﻭﻝ ﺍﻟﻮﻃﻦ ﺍﻟﻌﺮﺑﻲ', 'كل دول الوطن العربي'), - ('إضافة إلى كونها لغة', 'ﺇﺿﺎﻓﺔ ﺇﻟﻰ ﻛﻮﻧﻬﺎ ﻟﻐﺔ', 'إضافة إلى كونها لغة'), - ('رسمية في تشاد وإريتريا', 'ﺭﺳﻤﻴﺔ ﻓﻲ ﺗﺸﺎﺩ ﻭﺇﺭﻳﺘﺮﻳﺎ', 'رسمية في تشاد وإريتريا'), - ('وإسرائيل. وهي إحدى اللغات', 'ﻭﺇﺳﺮﺍﺋﻴﻞ. ﻭﻫﻲ ﺇﺣﺪﻯ ﺍﻟﻠﻐﺎﺕ', 'وإسرائيل. وهي إحدى اللغات'), - ('الرسمية الست في منظمة', 'ﺍﻟﺮﺳﻤﻴﺔ ﺍﻟﺴﺖ ﻓﻲ ﻣﻨﻈﻤﺔ', 'الرسمية الست في منظمة'), - ('الأمم المتحدة، ويُحتفل', 'ﺍﻷﻣﻢ ﺍﻟﻤﺘﺤﺪﺓ، ﻭﻳﺤﺘﻔﻞ', 'الأمم المتحدة، ويحتفل'), - ('باليوم العالمي للغة العربية', 'ﺑﺎﻟﻴﻮﻡ ﺍﻟﻌﺎﻟﻤﻲ ﻟﻠﻐﺔ ﺍﻟﻌﺮﺑﻴﺔ', 'باليوم العالمي للغة العربية'), - ('في 18 ديسمبر كذكرى اعتماد', 'ﻓﻲ 18 ﺩﻳﺴﻤﺒﺮ ﻛﺬﻛﺮﻯ ﺍﻋﺘﻤﺎﺩ', 'في 18 ديسمبر كذكرى اعتماد'), - ('العربية بين لغات العمل في', 'ﺍﻟﻌﺮﺑﻴﺔ ﺑﻴﻦ ﻟﻐﺎﺕ ﺍﻟﻌﻤﻞ ﻓﻲ', 'العربية بين لغات العمل في'), - ('الأمم المتحدة.', 'ﺍﻷﻣﻢ ﺍﻟﻤﺘﺤﺪﺓ.', 'الأمم المتحدة.'), - ('الآمم المتحدة.', 'ﺍﻵﻣﻢ ﺍﻟﻤﺘﺤﺪﺓ.', 'الآمم المتحدة.'), + ('السلام عليكم', 'ﺍﻟﺴﻼﻡ ﻋﻠﻴﻜﻢ'), + ('السَلَاْمٌ عَلَيْكُمْ', 'ﺍﻟﺴﻼﻡ ﻋﻠﻴﻜﻢ'), + ('اللغة العربية هي أكثر اللغات', 'ﺍﻟﻠﻐﺔ ﺍﻟﻌﺮﺑﻴﺔ ﻫﻲ ﺃﻛﺜﺮ ﺍﻟﻠﻐﺎﺕ'), + ('تحدثاً ونطقاً ضمن مجموعة', 'ﺗﺤﺪﺛﺎ ﻭﻧﻄﻘﺎ ﺿﻤﻦ ﻣﺠﻤﻮﻋﺔ'), + ('اللغات السامية', 'ﺍﻟﻠﻐﺎﺕ ﺍﻟﺴﺎﻣﻴﺔ'), + ('العربية لغة رسمية في', 'ﺍﻟﻌﺮﺑﻴﺔ ﻟﻐﺔ ﺭﺳﻤﻴﺔ ﻓﻲ'), + ('كل دول الوطن العربي', 'ﻛﻞ ﺩﻭﻝ ﺍﻟﻮﻃﻦ ﺍﻟﻌﺮﺑﻲ'), + ('إضافة إلى كونها لغة', 'ﺇﺿﺎﻓﺔ ﺇﻟﻰ ﻛﻮﻧﻬﺎ ﻟﻐﺔ'), + ('رسمية في تشاد وإريتريا', 'ﺭﺳﻤﻴﺔ ﻓﻲ ﺗﺸﺎﺩ ﻭﺇﺭﻳﺘﺮﻳﺎ'), + ('وإسرائيل. وهي إحدى اللغات', 'ﻭﺇﺳﺮﺍﺋﻴﻞ. ﻭﻫﻲ ﺇﺣﺪﻯ ﺍﻟﻠﻐﺎﺕ'), + ('الرسمية الست في منظمة', 'ﺍﻟﺮﺳﻤﻴﺔ ﺍﻟﺴﺖ ﻓﻲ ﻣﻨﻈﻤﺔ'), + ('الأمم المتحدة، ويُحتفل', 'ﺍﻷﻣﻢ ﺍﻟﻤﺘﺤﺪﺓ، ﻭﻳﺤﺘﻔﻞ'), + ('باليوم العالمي للغة العربية', 'ﺑﺎﻟﻴﻮﻡ ﺍﻟﻌﺎﻟﻤﻲ ﻟﻠﻐﺔ ﺍﻟﻌﺮﺑﻴﺔ'), + ('في 18 ديسمبر كذكرى اعتماد', 'ﻓﻲ 18 ﺩﻳﺴﻤﺒﺮ ﻛﺬﻛﺮﻯ ﺍﻋﺘﻤﺎﺩ'), + ('العربية بين لغات العمل في', 'ﺍﻟﻌﺮﺑﻴﺔ ﺑﻴﻦ ﻟﻐﺎﺕ ﺍﻟﻌﻤﻞ ﻓﻲ'), + ('الأمم المتحدة.', 'ﺍﻷﻣﻢ ﺍﻟﻤﺘﺤﺪﺓ.'), ) def test_reshaping(self): _reshaping_test(self) - def test_reverse_reshaping(self): - _reverse_reshaping_test(self) - class TestZWJReshaping(unittest.TestCase): def setUp(self): @@ -143,29 +128,26 @@ def setUp(self): 'delete_harakat': False }) self.cases = ( - ('السَلَاْمٌ عَلَيْكُمْ', 'ﺍﻟﺴَﻼَْﻡٌ ﻋَﻠَﻴْﻜُﻢْ', 'السَلَاْمٌ عَلَيْكُمْ'), - ('اللغة العربية هي أكثر اللغات', 'ﺍﻟﻠﻐﺔ ﺍﻟﻌﺮﺑﻴﺔ ﻫﻲ ﺃﻛﺜﺮ ﺍﻟﻠﻐﺎﺕ', 'اللغة العربية هي أكثر اللغات'), - ('تحدثاً ونطقاً ضمن مجموعة', 'ﺗﺤﺪﺛﺎً ﻭﻧﻄﻘﺎً ﺿﻤﻦ ﻣﺠﻤﻮﻋﺔ', 'تحدثاً ونطقاً ضمن مجموعة'), - ('اللغات السامية', 'ﺍﻟﻠﻐﺎﺕ ﺍﻟﺴﺎﻣﻴﺔ', 'اللغات السامية'), - ('العربية لغة رسمية في', 'ﺍﻟﻌﺮﺑﻴﺔ ﻟﻐﺔ ﺭﺳﻤﻴﺔ ﻓﻲ', 'العربية لغة رسمية في'), - ('كل دول الوطن العربي', 'ﻛﻞ ﺩﻭﻝ ﺍﻟﻮﻃﻦ ﺍﻟﻌﺮﺑﻲ', 'كل دول الوطن العربي'), - ('إضافة إلى كونها لغة', 'ﺇﺿﺎﻓﺔ ﺇﻟﻰ ﻛﻮﻧﻬﺎ ﻟﻐﺔ', 'إضافة إلى كونها لغة'), - ('رسمية في تشاد وإريتريا', 'ﺭﺳﻤﻴﺔ ﻓﻲ ﺗﺸﺎﺩ ﻭﺇﺭﻳﺘﺮﻳﺎ', 'رسمية في تشاد وإريتريا'), - ('وإسرائيل. وهي إحدى اللغات', 'ﻭﺇﺳﺮﺍﺋﻴﻞ. ﻭﻫﻲ ﺇﺣﺪﻯ ﺍﻟﻠﻐﺎﺕ', 'وإسرائيل. وهي إحدى اللغات'), - ('الرسمية الست في منظمة', 'ﺍﻟﺮﺳﻤﻴﺔ ﺍﻟﺴﺖ ﻓﻲ ﻣﻨﻈﻤﺔ', 'الرسمية الست في منظمة'), - ('الأمم المتحدة، ويُحتفل', 'ﺍﻷﻣﻢ ﺍﻟﻤﺘﺤﺪﺓ، ﻭﻳُﺤﺘﻔﻞ', 'الأمم المتحدة، ويُحتفل'), - ('باليوم العالمي للغة العربية', 'ﺑﺎﻟﻴﻮﻡ ﺍﻟﻌﺎﻟﻤﻲ ﻟﻠﻐﺔ ﺍﻟﻌﺮﺑﻴﺔ', 'باليوم العالمي للغة العربية'), - ('في 18 ديسمبر كذكرى اعتماد', 'ﻓﻲ 18 ﺩﻳﺴﻤﺒﺮ ﻛﺬﻛﺮﻯ ﺍﻋﺘﻤﺎﺩ', 'في 18 ديسمبر كذكرى اعتماد'), - ('العربية بين لغات العمل في', 'ﺍﻟﻌﺮﺑﻴﺔ ﺑﻴﻦ ﻟﻐﺎﺕ ﺍﻟﻌﻤﻞ ﻓﻲ', 'العربية بين لغات العمل في'), - ('الأمم المتحدة.', 'ﺍﻷﻣﻢ ﺍﻟﻤﺘﺤﺪﺓ.', 'الأمم المتحدة.'), + ('السَلَاْمٌ عَلَيْكُمْ', 'ﺍﻟﺴَﻼَْﻡٌ ﻋَﻠَﻴْﻜُﻢْ'), + ('اللغة العربية هي أكثر اللغات', 'ﺍﻟﻠﻐﺔ ﺍﻟﻌﺮﺑﻴﺔ ﻫﻲ ﺃﻛﺜﺮ ﺍﻟﻠﻐﺎﺕ'), + ('تحدثاً ونطقاً ضمن مجموعة', 'ﺗﺤﺪﺛﺎً ﻭﻧﻄﻘﺎً ﺿﻤﻦ ﻣﺠﻤﻮﻋﺔ'), + ('اللغات السامية', 'ﺍﻟﻠﻐﺎﺕ ﺍﻟﺴﺎﻣﻴﺔ'), + ('العربية لغة رسمية في', 'ﺍﻟﻌﺮﺑﻴﺔ ﻟﻐﺔ ﺭﺳﻤﻴﺔ ﻓﻲ'), + ('كل دول الوطن العربي', 'ﻛﻞ ﺩﻭﻝ ﺍﻟﻮﻃﻦ ﺍﻟﻌﺮﺑﻲ'), + ('إضافة إلى كونها لغة', 'ﺇﺿﺎﻓﺔ ﺇﻟﻰ ﻛﻮﻧﻬﺎ ﻟﻐﺔ'), + ('رسمية في تشاد وإريتريا', 'ﺭﺳﻤﻴﺔ ﻓﻲ ﺗﺸﺎﺩ ﻭﺇﺭﻳﺘﺮﻳﺎ'), + ('وإسرائيل. وهي إحدى اللغات', 'ﻭﺇﺳﺮﺍﺋﻴﻞ. ﻭﻫﻲ ﺇﺣﺪﻯ ﺍﻟﻠﻐﺎﺕ'), + ('الرسمية الست في منظمة', 'ﺍﻟﺮﺳﻤﻴﺔ ﺍﻟﺴﺖ ﻓﻲ ﻣﻨﻈﻤﺔ'), + ('الأمم المتحدة، ويُحتفل', 'ﺍﻷﻣﻢ ﺍﻟﻤﺘﺤﺪﺓ، ﻭﻳُﺤﺘﻔﻞ'), + ('باليوم العالمي للغة العربية', 'ﺑﺎﻟﻴﻮﻡ ﺍﻟﻌﺎﻟﻤﻲ ﻟﻠﻐﺔ ﺍﻟﻌﺮﺑﻴﺔ'), + ('في 18 ديسمبر كذكرى اعتماد', 'ﻓﻲ 18 ﺩﻳﺴﻤﺒﺮ ﻛﺬﻛﺮﻯ ﺍﻋﺘﻤﺎﺩ'), + ('العربية بين لغات العمل في', 'ﺍﻟﻌﺮﺑﻴﺔ ﺑﻴﻦ ﻟﻐﺎﺕ ﺍﻟﻌﻤﻞ ﻓﻲ'), + ('الأمم المتحدة.', 'ﺍﻷﻣﻢ ﺍﻟﻤﺘﺤﺪﺓ.'), ) def test_reshaping(self): _reshaping_test(self) - def test_reverse_reshaping(self): - _reverse_reshaping_test(self) - class TestReshapingWithHarakatWithoutLigatures(unittest.TestCase): def setUp(self): @@ -174,29 +156,26 @@ def setUp(self): 'support_ligatures': False }) self.cases = ( - ('السَلَاْمٌ عَلَيْكُمْ', 'ﺍﻟﺴَﻠَﺎْﻡٌ ﻋَﻠَﻴْﻜُﻢْ', 'السَلَاْمٌ عَلَيْكُمْ'), - ('اللغة العربية هي أكثر اللغات', 'ﺍﻟﻠﻐﺔ ﺍﻟﻌﺮﺑﻴﺔ ﻫﻲ ﺃﻛﺜﺮ ﺍﻟﻠﻐﺎﺕ', 'اللغة العربية هي أكثر اللغات'), - ('تحدثاً ونطقاً ضمن مجموعة', 'ﺗﺤﺪﺛﺎً ﻭﻧﻄﻘﺎً ﺿﻤﻦ ﻣﺠﻤﻮﻋﺔ', 'تحدثاً ونطقاً ضمن مجموعة'), - ('اللغات السامية', 'ﺍﻟﻠﻐﺎﺕ ﺍﻟﺴﺎﻣﻴﺔ', 'اللغات السامية'), - ('العربية لغة رسمية في', 'ﺍﻟﻌﺮﺑﻴﺔ ﻟﻐﺔ ﺭﺳﻤﻴﺔ ﻓﻲ', 'العربية لغة رسمية في'), - ('كل دول الوطن العربي', 'ﻛﻞ ﺩﻭﻝ ﺍﻟﻮﻃﻦ ﺍﻟﻌﺮﺑﻲ', 'كل دول الوطن العربي'), - ('إضافة إلى كونها لغة', 'ﺇﺿﺎﻓﺔ ﺇﻟﻰ ﻛﻮﻧﻬﺎ ﻟﻐﺔ', 'إضافة إلى كونها لغة'), - ('رسمية في تشاد وإريتريا', 'ﺭﺳﻤﻴﺔ ﻓﻲ ﺗﺸﺎﺩ ﻭﺇﺭﻳﺘﺮﻳﺎ', 'رسمية في تشاد وإريتريا'), - ('وإسرائيل. وهي إحدى اللغات', 'ﻭﺇﺳﺮﺍﺋﻴﻞ. ﻭﻫﻲ ﺇﺣﺪﻯ ﺍﻟﻠﻐﺎﺕ', 'وإسرائيل. وهي إحدى اللغات'), - ('الرسمية الست في منظمة', 'ﺍﻟﺮﺳﻤﻴﺔ ﺍﻟﺴﺖ ﻓﻲ ﻣﻨﻈﻤﺔ', 'الرسمية الست في منظمة'), - ('الأمم المتحدة، ويُحتفل', 'ﺍﻟﺄﻣﻢ ﺍﻟﻤﺘﺤﺪﺓ، ﻭﻳُﺤﺘﻔﻞ', 'الأمم المتحدة، ويُحتفل'), - ('باليوم العالمي للغة العربية', 'ﺑﺎﻟﻴﻮﻡ ﺍﻟﻌﺎﻟﻤﻲ ﻟﻠﻐﺔ ﺍﻟﻌﺮﺑﻴﺔ', 'باليوم العالمي للغة العربية'), - ('في 18 ديسمبر كذكرى اعتماد', 'ﻓﻲ 18 ﺩﻳﺴﻤﺒﺮ ﻛﺬﻛﺮﻯ ﺍﻋﺘﻤﺎﺩ', 'في 18 ديسمبر كذكرى اعتماد'), - ('العربية بين لغات العمل في', 'ﺍﻟﻌﺮﺑﻴﺔ ﺑﻴﻦ ﻟﻐﺎﺕ ﺍﻟﻌﻤﻞ ﻓﻲ', 'العربية بين لغات العمل في'), - ('الأمم المتحدة.', 'ﺍﻟﺄﻣﻢ ﺍﻟﻤﺘﺤﺪﺓ.', 'الأمم المتحدة.'), + ('السَلَاْمٌ عَلَيْكُمْ', 'ﺍﻟﺴَﻠَﺎْﻡٌ ﻋَﻠَﻴْﻜُﻢْ'), + ('اللغة العربية هي أكثر اللغات', 'ﺍﻟﻠﻐﺔ ﺍﻟﻌﺮﺑﻴﺔ ﻫﻲ ﺃﻛﺜﺮ ﺍﻟﻠﻐﺎﺕ'), + ('تحدثاً ونطقاً ضمن مجموعة', 'ﺗﺤﺪﺛﺎً ﻭﻧﻄﻘﺎً ﺿﻤﻦ ﻣﺠﻤﻮﻋﺔ'), + ('اللغات السامية', 'ﺍﻟﻠﻐﺎﺕ ﺍﻟﺴﺎﻣﻴﺔ'), + ('العربية لغة رسمية في', 'ﺍﻟﻌﺮﺑﻴﺔ ﻟﻐﺔ ﺭﺳﻤﻴﺔ ﻓﻲ'), + ('كل دول الوطن العربي', 'ﻛﻞ ﺩﻭﻝ ﺍﻟﻮﻃﻦ ﺍﻟﻌﺮﺑﻲ'), + ('إضافة إلى كونها لغة', 'ﺇﺿﺎﻓﺔ ﺇﻟﻰ ﻛﻮﻧﻬﺎ ﻟﻐﺔ'), + ('رسمية في تشاد وإريتريا', 'ﺭﺳﻤﻴﺔ ﻓﻲ ﺗﺸﺎﺩ ﻭﺇﺭﻳﺘﺮﻳﺎ'), + ('وإسرائيل. وهي إحدى اللغات', 'ﻭﺇﺳﺮﺍﺋﻴﻞ. ﻭﻫﻲ ﺇﺣﺪﻯ ﺍﻟﻠﻐﺎﺕ'), + ('الرسمية الست في منظمة', 'ﺍﻟﺮﺳﻤﻴﺔ ﺍﻟﺴﺖ ﻓﻲ ﻣﻨﻈﻤﺔ'), + ('الأمم المتحدة، ويُحتفل', 'ﺍﻟﺄﻣﻢ ﺍﻟﻤﺘﺤﺪﺓ، ﻭﻳُﺤﺘﻔﻞ'), + ('باليوم العالمي للغة العربية', 'ﺑﺎﻟﻴﻮﻡ ﺍﻟﻌﺎﻟﻤﻲ ﻟﻠﻐﺔ ﺍﻟﻌﺮﺑﻴﺔ'), + ('في 18 ديسمبر كذكرى اعتماد', 'ﻓﻲ 18 ﺩﻳﺴﻤﺒﺮ ﻛﺬﻛﺮﻯ ﺍﻋﺘﻤﺎﺩ'), + ('العربية بين لغات العمل في', 'ﺍﻟﻌﺮﺑﻴﺔ ﺑﻴﻦ ﻟﻐﺎﺕ ﺍﻟﻌﻤﻞ ﻓﻲ'), + ('الأمم المتحدة.', 'ﺍﻟﺄﻣﻢ ﺍﻟﻤﺘﺤﺪﺓ.'), ) def test_reshaping(self): _reshaping_test(self) - def test_reverse_reshaping(self): - _reverse_reshaping_test(self) - class TestReshapingWithShiftedHarakatWithoutLigatures(unittest.TestCase): def setUp(self): @@ -238,62 +217,36 @@ def setUp(self): 'وَأْتُونِي مُسْلِمِينَ ﴿٣١﴾', 'ﺇﻧﻪ ﻣﻦ ﺳﻠﻴﻤﺎﻥ ﻭﺇﻧﻪ ﷽ ﴿٣٠﴾ ' - 'ﺃﻻ ﺗﻌﻠﻮﺍ ﻋﻠﻲ ﻭﺃﺗﻮﻧﻲ ﻣﺴﻠﻤﻴﻦ ﴿٣١﴾', - - 'إنه من سليمان وإنه بسم الله الرحمن الرحيم ﴿٣٠﴾ ' - 'ألا تعلوا علي وأتوني مسلمين ﴿٣١﴾' - ), - ( - 'فَذَكِّرْ إِنَّمَا أَنتَ' - ' مُذَكِّرٌ ﴿٢١﴾ لَّسْتَ' - ' عَلَيْهِم بِمُصَيْطِرٍ ﴿٢٢﴾' - ' إِلَّا مَن تَوَلَّىٰ' - ' وَكَفَرَ ﴿٢٣﴾ فَيُعَذِّبُهُ' - ' اللَّـهُ الْعَذَابَ' - ' الْأَكْبَرَ ﴿٢٤﴾', - - 'ﻓﺬﻛﺮ ﺇﻧﻤﺎ ﺃﻧﺖ' - ' ﻣﺬﻛﺮ ﴿٢١﴾ ﻟﺴﺖ' - ' ﻋﻠﻴﻬﻢ ﺑﻤﺼﻴﻄﺮ ﴿٢٢﴾' - ' ﺇﻻ ﻣﻦ ﺗﻮﻟﻰ' - ' ﻭﻛﻔﺮ ﴿٢٣﴾ ﻓﻴﻌﺬﺑﻪ' - ' ﷲ ﺍﻟﻌﺬﺍﺏ' - ' ﺍﻷﻛﺒﺮ ﴿٢٤﴾', - - 'فذكر إنما أنت' - ' مذكر ﴿٢١﴾ لست' - ' عليهم بمصيطر ﴿٢٢﴾' - ' إلا من تولى' - ' وكفر ﴿٢٣﴾ فيعذبه' - ' الله العذاب' - ' الأكبر ﴿٢٤﴾', - ), - - ( - 'محمد رسول الله صلى الله عليه وسلم', - 'ﷴ ﷶ ﷲ ﷺ', - 'محمد رسول الله صلى الله عليه وسلم', - ), - - ( - 'الله جل جلاله', - 'ﷲ ﷻ', - 'الله جل جلاله', - ), - - ( - 'محمد رسول الله عليه صلى الله وسلم', - 'ﷴ ﷶ ﷲ ﷷ ﷹ ﷲ ﷸ', - 'محمد رسول الله عليه صلى الله وسلم', - ), + 'ﺃﻻ ﺗﻌﻠﻮﺍ ﻋﻠﻲ ﻭﺃﺗﻮﻧﻲ ﻣﺴﻠﻤﻴﻦ ﴿٣١﴾'), + + ('فَذَكِّرْ إِنَّمَا أَنتَ' + ' مُذَكِّرٌ ﴿٢١﴾ لَّسْتَ' + ' عَلَيْهِم بِمُصَيْطِرٍ ﴿٢٢﴾' + ' إِلَّا مَن تَوَلَّىٰ' + ' وَكَفَرَ ﴿٢٣﴾ فَيُعَذِّبُهُ' + ' اللَّـهُ الْعَذَابَ' + ' الْأَكْبَرَ ﴿٢٤﴾', + + 'ﻓﺬﻛﺮ ﺇﻧﻤﺎ ﺃﻧﺖ' + ' ﻣﺬﻛﺮ ﴿٢١﴾ ﻟﺴﺖ' + ' ﻋﻠﻴﻬﻢ ﺑﻤﺼﻴﻄﺮ ﴿٢٢﴾' + ' ﺇﻻ ﻣﻦ ﺗﻮﻟﻰ' + ' ﻭﻛﻔﺮ ﴿٢٣﴾ ﻓﻴﻌﺬﺑﻪ' + ' ﷲ ﺍﻟﻌﺬﺍﺏ' + ' ﺍﻷﻛﺒﺮ ﴿٢٤﴾'), + + ('محمد رسول الله صلى الله عليه وسلم', + 'ﷴ ﷶ ﷲ ﷺ'), + + ('الله جل جلاله', + 'ﷲ ﷻ'), + + ('محمد رسول الله عليه صلى الله وسلم', + 'ﷴ ﷶ ﷲ ﷷ ﷹ ﷲ ﷸ'), ) def test_reshaping(self): _reshaping_test(self) - def test_reverse_reshaping(self): - _reverse_reshaping_test(self) - - if __name__ == '__main__': unittest.main() diff --git a/arabic_reshaper/tests/test_004_unreshaping.py b/arabic_reshaper/tests/test_004_unreshaping.py new file mode 100644 index 0000000..f84b462 --- /dev/null +++ b/arabic_reshaper/tests/test_004_unreshaping.py @@ -0,0 +1,169 @@ +from __future__ import unicode_literals +from __future__ import print_function + +import unittest +import sys +import arabic_reshaper + + +def _unreshaping_test(test): + for i, case in enumerate(test.cases): + def t(): test.assertEqual(case[1], test.reshaper.unreshape(case[0])) + if hasattr(test, 'subTest'): + with test.subTest(i=i, case=case[0]): + t() + else: + print('running test case %d' % i, file=sys.stderr) + t() + + +class TestDefaultUnreshaping(unittest.TestCase): + def setUp(self): + self.reshaper = arabic_reshaper.default_reshaper + self.cases = ( + # Reshaped text, Unreshaped text + ('ﺍﻟﺴﻼﻡ ﻋﻠﻴﻜﻢ', 'السلام عليكم'), + ('ﺍﻟﻠﻐﺔ ﺍﻟﻌﺮﺑﻴﺔ ﻫﻲ ﺃﻛﺜﺮ ﺍﻟﻠﻐﺎﺕ', 'اللغة العربية هي أكثر اللغات'), + ('ﺗﺤﺪﺛﺎ ﻭﻧﻄﻘﺎ ﺿﻤﻦ ﻣﺠﻤﻮﻋﺔ', 'تحدثا ونطقا ضمن مجموعة'), + ('ﺍﻟﻠﻐﺎﺕ ﺍﻟﺴﺎﻣﻴﺔ', 'اللغات السامية'), + ('ﺍﻟﻌﺮﺑﻴﺔ ﻟﻐﺔ ﺭﺳﻤﻴﺔ ﻓﻲ', 'العربية لغة رسمية في'), + ('ﻛﻞ ﺩﻭﻝ ﺍﻟﻮﻃﻦ ﺍﻟﻌﺮﺑﻲ', 'كل دول الوطن العربي'), + ('ﺇﺿﺎﻓﺔ ﺇﻟﻰ ﻛﻮﻧﻬﺎ ﻟﻐﺔ', 'إضافة إلى كونها لغة'), + ('ﺭﺳﻤﻴﺔ ﻓﻲ ﺗﺸﺎﺩ ﻭﺇﺭﻳﺘﺮﻳﺎ', 'رسمية في تشاد وإريتريا'), + ('ﻭﺇﺳﺮﺍﺋﻴﻞ. ﻭﻫﻲ ﺇﺣﺪﻯ ﺍﻟﻠﻐﺎﺕ', 'وإسرائيل. وهي إحدى اللغات'), + ('ﺍﻟﺮﺳﻤﻴﺔ ﺍﻟﺴﺖ ﻓﻲ ﻣﻨﻈﻤﺔ', 'الرسمية الست في منظمة'), + ('ﺍﻷﻣﻢ ﺍﻟﻤﺘﺤﺪﺓ، ﻭﻳﺤﺘﻔﻞ', 'الأمم المتحدة، ويحتفل'), + ('ﺑﺎﻟﻴﻮﻡ ﺍﻟﻌﺎﻟﻤﻲ ﻟﻠﻐﺔ ﺍﻟﻌﺮﺑﻴﺔ', 'باليوم العالمي للغة العربية'), + ('ﻓﻲ 18 ﺩﻳﺴﻤﺒﺮ ﻛﺬﻛﺮﻯ ﺍﻋﺘﻤﺎﺩ', 'في 18 ديسمبر كذكرى اعتماد'), + ('ﺍﻟﻌﺮﺑﻴﺔ ﺑﻴﻦ ﻟﻐﺎﺕ ﺍﻟﻌﻤﻞ ﻓﻲ', 'العربية بين لغات العمل في'), + ('ﺍﻷﻣﻢ ﺍﻟﻤﺘﺤﺪﺓ.', 'الأمم المتحدة.'), + ('ﺍﻵﻣﻢ ﺍﻟﻤﺘﺤﺪﺓ.', 'الآمم المتحدة.'), + ('ﺍﺳﻢ ﻣﻦ amin ﺍﺳﺖ', 'اسم من amin است'), + ) + + def test_unreshaping(self): + _unreshaping_test(self) + + +class TestUnreshapingWithHarakat(unittest.TestCase): + def setUp(self): + self.reshaper = arabic_reshaper.ArabicReshaper({ + 'delete_harakat': False + }) + self.cases = ( + # Reshaped text, Unreshaped text + ('ﺍﻟﺴَﻼَْﻡٌ ﻋَﻠَﻴْﻜُﻢْ', 'السَلَاْمٌ عَلَيْكُمْ'), + ('ﺍﻟﻠﻐﺔ ﺍﻟﻌﺮﺑﻴﺔ ﻫﻲ ﺃﻛﺜﺮ ﺍﻟﻠﻐﺎﺕ', 'اللغة العربية هي أكثر اللغات'), + ('ﺗﺤﺪﺛﺎً ﻭﻧﻄﻘﺎً ﺿﻤﻦ ﻣﺠﻤﻮﻋﺔ', 'تحدثاً ونطقاً ضمن مجموعة'), + ('ﺍﻟﻠﻐﺎﺕ ﺍﻟﺴﺎﻣﻴﺔ', 'اللغات السامية'), + ('ﺍﻟﻌﺮﺑﻴﺔ ﻟﻐﺔ ﺭﺳﻤﻴﺔ ﻓﻲ', 'العربية لغة رسمية في'), + ('ﻛﻞ ﺩﻭﻝ ﺍﻟﻮﻃﻦ ﺍﻟﻌﺮﺑﻲ', 'كل دول الوطن العربي'), + ('ﺇﺿﺎﻓﺔ ﺇﻟﻰ ﻛﻮﻧﻬﺎ ﻟﻐﺔ', 'إضافة إلى كونها لغة'), + ('ﺭﺳﻤﻴﺔ ﻓﻲ ﺗﺸﺎﺩ ﻭﺇﺭﻳﺘﺮﻳﺎ', 'رسمية في تشاد وإريتريا'), + ('ﻭﺇﺳﺮﺍﺋﻴﻞ. ﻭﻫﻲ ﺇﺣﺪﻯ ﺍﻟﻠﻐﺎﺕ', 'وإسرائيل. وهي إحدى اللغات'), + ('ﺍﻟﺮﺳﻤﻴﺔ ﺍﻟﺴﺖ ﻓﻲ ﻣﻨﻈﻤﺔ', 'الرسمية الست في منظمة'), + ('ﺍﻷﻣﻢ ﺍﻟﻤﺘﺤﺪﺓ، ﻭﻳُﺤﺘﻔﻞ', 'الأمم المتحدة، ويُحتفل'), + ('ﺑﺎﻟﻴﻮﻡ ﺍﻟﻌﺎﻟﻤﻲ ﻟﻠﻐﺔ ﺍﻟﻌﺮﺑﻴﺔ', 'باليوم العالمي للغة العربية'), + ('ﻓﻲ 18 ﺩﻳﺴﻤﺒﺮ ﻛﺬﻛﺮﻯ ﺍﻋﺘﻤﺎﺩ', 'في 18 ديسمبر كذكرى اعتماد'), + ('ﺍﻟﻌﺮﺑﻴﺔ ﺑﻴﻦ ﻟﻐﺎﺕ ﺍﻟﻌﻤﻞ ﻓﻲ', 'العربية بين لغات العمل في'), + ('ﺍﻷﻣﻢ ﺍﻟﻤﺘﺤﺪﺓ.', 'الأمم المتحدة.'), + ) + + def test_unreshaping(self): + _unreshaping_test(self) + + +class TestUnreshapingWithHarakatWithoutLigatures(unittest.TestCase): + def setUp(self): + self.reshaper = arabic_reshaper.ArabicReshaper({ + 'delete_harakat': False, + 'support_ligatures': False + }) + self.cases = ( + # Reshaped text, Unreshaped text + ('ﺍﻟﺴَﻠَﺎْﻡٌ ﻋَﻠَﻴْﻜُﻢْ', 'السَلَاْمٌ عَلَيْكُمْ'), + ('ﺍﻟﻠﻐﺔ ﺍﻟﻌﺮﺑﻴﺔ ﻫﻲ ﺃﻛﺜﺮ ﺍﻟﻠﻐﺎﺕ', 'اللغة العربية هي أكثر اللغات'), + ('ﺗﺤﺪﺛﺎً ﻭﻧﻄﻘﺎً ﺿﻤﻦ ﻣﺠﻤﻮﻋﺔ', 'تحدثاً ونطقاً ضمن مجموعة'), + ('ﺍﻟﻠﻐﺎﺕ ﺍﻟﺴﺎﻣﻴﺔ', 'اللغات السامية'), + ('ﺍﻟﻌﺮﺑﻴﺔ ﻟﻐﺔ ﺭﺳﻤﻴﺔ ﻓﻲ', 'العربية لغة رسمية في'), + ('ﻛﻞ ﺩﻭﻝ ﺍﻟﻮﻃﻦ ﺍﻟﻌﺮﺑﻲ', 'كل دول الوطن العربي'), + ('ﺇﺿﺎﻓﺔ ﺇﻟﻰ ﻛﻮﻧﻬﺎ ﻟﻐﺔ', 'إضافة إلى كونها لغة'), + ('ﺭﺳﻤﻴﺔ ﻓﻲ ﺗﺸﺎﺩ ﻭﺇﺭﻳﺘﺮﻳﺎ', 'رسمية في تشاد وإريتريا'), + ('ﻭﺇﺳﺮﺍﺋﻴﻞ. ﻭﻫﻲ ﺇﺣﺪﻯ ﺍﻟﻠﻐﺎﺕ', 'وإسرائيل. وهي إحدى اللغات'), + ('ﺍﻟﺮﺳﻤﻴﺔ ﺍﻟﺴﺖ ﻓﻲ ﻣﻨﻈﻤﺔ', 'الرسمية الست في منظمة'), + ('ﺍﻟﺄﻣﻢ ﺍﻟﻤﺘﺤﺪﺓ، ﻭﻳُﺤﺘﻔﻞ', 'الأمم المتحدة، ويُحتفل'), + ('ﺑﺎﻟﻴﻮﻡ ﺍﻟﻌﺎﻟﻤﻲ ﻟﻠﻐﺔ ﺍﻟﻌﺮﺑﻴﺔ', 'باليوم العالمي للغة العربية'), + ('ﻓﻲ 18 ﺩﻳﺴﻤﺒﺮ ﻛﺬﻛﺮﻯ ﺍﻋﺘﻤﺎﺩ', 'في 18 ديسمبر كذكرى اعتماد'), + ('ﺍﻟﻌﺮﺑﻴﺔ ﺑﻴﻦ ﻟﻐﺎﺕ ﺍﻟﻌﻤﻞ ﻓﻲ', 'العربية بين لغات العمل في'), + ('ﺍﻟﺄﻣﻢ ﺍﻟﻤﺘﺤﺪﺓ.', 'الأمم المتحدة.'), + ) + + def test_unreshaping(self): + _unreshaping_test(self) + + +class TestUnreshapingLigatures(unittest.TestCase): + def setUp(self): + self.reshaper = arabic_reshaper.ArabicReshaper({ + 'delete_tatweel': True, + 'ARABIC LIGATURE BISMILLAH AR-RAHMAN AR-RAHEEM': True, + 'ARABIC LIGATURE JALLAJALALOUHOU': True, + 'ARABIC LIGATURE SALLALLAHOU ALAYHE WASALLAM': True, + 'ARABIC LIGATURE ALLAH ': True, + 'ARABIC LIGATURE AKBAR': True, + 'ARABIC LIGATURE ALAYHE': True, + 'ARABIC LIGATURE MOHAMMAD': True, + 'ARABIC LIGATURE RASOUL': True, + 'ARABIC LIGATURE SALAM': True, + 'ARABIC LIGATURE SALLA': True, + 'ARABIC LIGATURE WASALLAM': True, + }) + self.cases = ( + # Reshaped text, Unreshaped text + ( + 'ﺇﻧﻪ ﻣﻦ ﺳﻠﻴﻤﺎﻥ ﻭﺇﻧﻪ ﷽ ﴿٣٠﴾ ' + 'ﺃﻻ ﺗﻌﻠﻮﺍ ﻋﻠﻲ ﻭﺃﺗﻮﻧﻲ ﻣﺴﻠﻤﻴﻦ ﴿٣١﴾', + + 'إنه من سليمان وإنه بسم الله الرحمن الرحيم ﴿٣٠﴾ ' + 'ألا تعلوا علي وأتوني مسلمين ﴿٣١﴾' + ), + ( + 'ﻓﺬﻛﺮ ﺇﻧﻤﺎ ﺃﻧﺖ' + ' ﻣﺬﻛﺮ ﴿٢١﴾ ﻟﺴﺖ' + ' ﻋﻠﻴﻬﻢ ﺑﻤﺼﻴﻄﺮ ﴿٢٢﴾' + ' ﺇﻻ ﻣﻦ ﺗﻮﻟﻰ' + ' ﻭﻛﻔﺮ ﴿٢٣﴾ ﻓﻴﻌﺬﺑﻪ' + ' ﷲ ﺍﻟﻌﺬﺍﺏ' + ' ﺍﻷﻛﺒﺮ ﴿٢٤﴾', + + 'فذكر إنما أنت' + ' مذكر ﴿٢١﴾ لست' + ' عليهم بمصيطر ﴿٢٢﴾' + ' إلا من تولى' + ' وكفر ﴿٢٣﴾ فيعذبه' + ' الله العذاب' + ' الأكبر ﴿٢٤﴾', + ), + + ( + 'ﷴ ﷶ ﷲ ﷺ', + 'محمد رسول الله صلى الله عليه وسلم', + ), + + ( + 'ﷲ ﷻ', + 'الله جل جلاله', + ), + + ( + 'ﷴ ﷶ ﷲ ﷷ ﷹ ﷲ ﷸ', + 'محمد رسول الله عليه صلى الله وسلم', + ), + ) + + def test_unreshaping(self): + _unreshaping_test(self) + + +if __name__ == '__main__': + unittest.main() From e00df3304d4ac6373844b038605e0d83a377dd8f Mon Sep 17 00:00:00 2001 From: amin Date: Thu, 18 Nov 2021 18:35:03 +0330 Subject: [PATCH 4/4] Version fixed --- arabic_reshaper/__init__.py | 6 ++---- arabic_reshaper/__version__.py | 2 +- arabic_reshaper/arabic_reshaper.py | 32 +++++++++++++++--------------- setup.py | 2 +- 4 files changed, 20 insertions(+), 22 deletions(-) diff --git a/arabic_reshaper/__init__.py b/arabic_reshaper/__init__.py index fc861c2..f06d58b 100644 --- a/arabic_reshaper/__init__.py +++ b/arabic_reshaper/__init__.py @@ -1,6 +1,4 @@ -import os - -from .arabic_reshaper import reshape, default_reshaper, ArabicReshaper, unreshape +from .arabic_reshaper import reshape, unreshape, default_reshaper, ArabicReshaper from .reshaper_config import (config_for_true_type_font, ENABLE_NO_LIGATURES, ENABLE_SENTENCES_LIGATURES, @@ -9,4 +7,4 @@ ENABLE_ALL_LIGATURES) -__version__ = '2.2.3' +__version__ = '2.2.0' diff --git a/arabic_reshaper/__version__.py b/arabic_reshaper/__version__.py index f811561..04188a1 100644 --- a/arabic_reshaper/__version__.py +++ b/arabic_reshaper/__version__.py @@ -1 +1 @@ -__version__ = '2.1.2' +__version__ = '2.2.0' diff --git a/arabic_reshaper/arabic_reshaper.py b/arabic_reshaper/arabic_reshaper.py index c3d3609..ff9632c 100644 --- a/arabic_reshaper/arabic_reshaper.py +++ b/arabic_reshaper/arabic_reshaper.py @@ -238,7 +238,7 @@ def reshape(self, text): return ''.join(result) - def _reversed_letters(self): + def _reversed_letters(self) -> dict: """ Declared letters are for reshaping by default. This if for reversing declared letters and preparing them for reverse reshaping @@ -255,13 +255,13 @@ def _reversed_letters(self): # example for k: '\u0626' # example for v: ('\uFE89', '\uFE8B', '\uFE8C', '\uFE8A'). so v is a tuple - for k, v in self.letters.items(): - # Add char_ and its normal form as a dict, if char_ was not null - [reversed_letters.update({char_: k}) for char_ in v if char_] + for original_form, reshaped_form in self.letters.items(): + # Add char and its normal form as a dict, if char was not null (there is cases that char is null) + [reversed_letters.update({char: original_form}) for char in reshaped_form if char] return reversed_letters - def _reversed_ligatures(self): + def _reversed_ligatures(self) -> dict: """ Declared ligatures are for reshaping by default. This if for reversing declared ligatures and preparing them for reverse reshaping @@ -283,8 +283,8 @@ def _reversed_ligatures(self): # title example: 'ARABIC LIGATURE SAD WITH HAH' # ligature example: ('\u0635\u062D', ('\uFC20', '\uFCB1', '', '')) for title, ligature in LIGATURES: - [reversed_ligatures.update({char_: ligature[original_text]}) for - char_ in ligature[reshaped_text] if char_] + [reversed_ligatures.update({char: ligature[original_text]}) for + char in ligature[reshaped_text] if char] return reversed_ligatures @@ -306,37 +306,37 @@ def unreshape(self, text: str) -> str: reversed_letters = self._reversed_letters() reversed_ligatures = self._reversed_ligatures() - for index, char_ in enumerate(text_list): + for index, char in enumerate(text_list): # Checking if char_ is in original shape letters list and has not changed during reshape - if char_ in self.letters.keys(): - result.append(char_) + if char in self.letters.keys(): + result.append(char) continue # Checking if char_ is a special character - if char_ in SPECIAL_LETTERS.keys(): + if char in SPECIAL_LETTERS.keys(): next_char = text_list[index+1] next_next_char = text_list[index+2] # Checking if two following chars are harakat. in that case, first harakat should be placed in middle # of special chars if HARAKAT_RE.match(next_char) and HARAKAT_RE.match(next_next_char): - result.append(next_char.join(list(SPECIAL_LETTERS.get(char_)))) + result.append(next_char.join(list(SPECIAL_LETTERS.get(char)))) # Omitting first harakat text_list[index+1] = '' else: - result.append("".join(list(SPECIAL_LETTERS.get(char_)))) + result.append("".join(list(SPECIAL_LETTERS.get(char)))) continue # Checking if char_ is in ligatures - if char_ in reversed_ligatures: - result.append(reversed_ligatures[char_]) + if char in reversed_ligatures: + result.append(reversed_ligatures[char]) continue # If couldn't find char is letters, append char itself - result.append(reversed_letters.get(char_, char_)) + result.append(reversed_letters.get(char, char)) return "".join(result) diff --git a/setup.py b/setup.py index 3ef1a1c..fbee068 100755 --- a/setup.py +++ b/setup.py @@ -14,7 +14,7 @@ " applications that don't support Arabic"), long_description=long_description, long_description_content_type="text/markdown", - version='2.2.3', + version='2.2.0', platforms="ALL", license="MIT", packages=['arabic_reshaper'],