| Server IP : 172.67.201.108 / Your IP : 216.73.216.55 Web Server : Apache/2.4.68 (Amazon Linux) OpenSSL/3.5.7 System : Linux ip-172-31-69-123.ec2.internal 6.1.177-224.371.amzn2023.x86_64 #1 SMP PREEMPT_DYNAMIC Mon Jul 27 20:28:29 UTC 2026 x86_64 User : ec2-user ( 1000) PHP Version : 8.4.24 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : OFF | Sudo : ON | Pkexec : ON Directory : /lib/python3.9/site-packages/elementpath/regex/ |
Upload File : |
#
# Copyright (c), 2016-2020, SISSA (International School for Advanced Studies).
# All rights reserved.
# This file is distributed under the terms of the MIT License.
# See the file 'LICENSE' in the root directory of the present
# distribution, or http://opensource.org/licenses/MIT.
#
# @author Davide Brunato <[email protected]>
#
"""
This module defines Unicode code points helper functions.
"""
from sys import maxunicode
from typing import Iterable, Iterator, Optional, Set, Tuple, Union
CHARACTER_CLASS_ESCAPED: Set[int] = {ord(c) for c in r'-|.^?*+{}()[]\\'}
"""Code Points of escaped chars in a character class."""
CodePoint = Union[int, Tuple[int, int]]
def code_point_order(cp: CodePoint) -> int:
"""Ordering function for code points."""
return cp if isinstance(cp, int) else cp[0]
def code_point_reverse_order(cp: CodePoint) -> int:
"""Reverse ordering function for code points."""
return cp if isinstance(cp, int) else cp[1] - 1
def iter_code_points(code_points: Iterable[CodePoint], reverse=False) -> Iterator[CodePoint]:
"""
Iterates a code points sequence. Three ore more consecutive
code points are merged in a range.
:param code_points: an iterable with code points and code point ranges.
:param reverse: if `True` reverses the order of the sequence.
:return: yields code points or code point ranges.
"""
start_cp = end_cp = 0
if reverse:
code_points = sorted(code_points, key=code_point_reverse_order, reverse=True)
else:
code_points = sorted(code_points, key=code_point_order)
for cp in code_points:
if isinstance(cp, int):
cp = cp, cp + 1
if not end_cp:
start_cp, end_cp = cp
continue
elif reverse:
if start_cp <= cp[1]:
start_cp = min(start_cp, cp[0])
continue
elif end_cp >= cp[0]:
end_cp = max(end_cp, cp[1])
continue
if end_cp > start_cp + 1:
yield start_cp, end_cp
else:
yield start_cp
start_cp, end_cp = cp
else:
if end_cp:
if end_cp > start_cp + 1:
yield start_cp, end_cp
else:
yield start_cp
def get_code_point_range(cp: CodePoint) -> Optional[CodePoint]:
"""
Returns a code point range.
:param cp: a single code point or a code point range.
:return: a code point range or `None` if the argument is not a \
code point or a code point range.
"""
if isinstance(cp, int):
if 0 <= cp <= maxunicode:
return cp, cp + 1
else:
try:
if isinstance(cp[0], int) and isinstance(cp[1], int):
if 0 <= cp[0] < cp[1] <= maxunicode + 1:
return cp
except (IndexError, TypeError):
pass
return None
def code_point_repr(cp: CodePoint) -> str:
"""
Returns the string representation of a code point.
:param cp: an integer or a tuple with at least two integers. \
Values must be in interval [0, sys.maxunicode].
"""
if isinstance(cp, int):
if cp in CHARACTER_CLASS_ESCAPED:
return r'\%s' % chr(cp)
return chr(cp)
if cp[0] in CHARACTER_CLASS_ESCAPED:
start_char = r'\%s' % chr(cp[0])
else:
start_char = chr(cp[0])
end_cp = cp[1] - 1 # Character ranges include the right bound
if end_cp in CHARACTER_CLASS_ESCAPED:
end_char = r'\%s' % chr(end_cp)
else:
end_char = chr(end_cp)
if end_cp > cp[0] + 1:
return '%s-%s' % (start_char, end_char)
else:
return start_char + end_char