Coverage for centralnicreseller/apiconnector/idnaprocessor.py: 85%

27 statements  

« prev     ^ index     » next       coverage.py v7.16.2, created at 2026-10-19 19:53 +0000

1import idna 

2import re 

3 

4 

5class IDNAProcessor: 

6 NON_TRANSITIONAL_TLDS = re.compile( 

7 r"\.(?:art|be|ca|de|swiss|fr|pm|re|tf|wf|yt)\.?$", re.IGNORECASE 

8 ) 

9 

10 @staticmethod 

11 def is_transitional_processing(domain_name: str) -> bool: 

12 """ 

13 Returns True when the domain name should use transitional processing, which 

14 is every TLD except those in NON_TRANSITIONAL_TLDS (matched case-insensitively 

15 at the end of the name). Those keep the deviation characters (ß, ς, ZWJ, 

16 ZWNJ) instead of mapping them. 

17 """ 

18 return not bool(IDNAProcessor.NON_TRANSITIONAL_TLDS.search(domain_name)) 

19 

20 @staticmethod 

21 def to_ascii(domain_name, use_transitional=None): 

22 if use_transitional is None: 

23 use_transitional = IDNAProcessor.is_transitional_processing(domain_name) 

24 try: 

25 if use_transitional: 

26 domain_name = idna.uts46_remap(domain_name, transitional=True) 

27 return idna.encode(domain_name).decode("ascii") 

28 except idna.IDNAError as e: 

29 raise ValueError(f"Unable to translate {domain_name} to ASCII: {e}") 

30 

31 @staticmethod 

32 def to_unicode(domain_name, use_transitional=None): 

33 if use_transitional is None: 

34 use_transitional = IDNAProcessor.is_transitional_processing(domain_name) 

35 try: 

36 if use_transitional: 

37 return idna.decode(domain_name, uts46=True) 

38 else: 

39 return idna.decode(domain_name) 

40 except idna.IDNAError as e: 

41 raise ValueError(f"Unable to translate {domain_name} to Unicode: {e}") 

idnaconverter_py.html">« prev     ^ index     » next       coverage.py v7.16.2, created at 2026-10-19 19:53 +0000