feat: Android-pyApi v1.0 - 全面翻译 Android SDK API 为 Python
52 个模块覆盖 Android + Java + org.json 标准库
This commit is contained in:
commit
bfe27fdc08
104 files changed
+58750
No files matched your search
@@ -0,0 +1,287 @@
|
||||
"""
|
||||
Java regex standard library APIs implemented in Python.
|
||||
java.util.regex package - Pattern, Matcher, MatchResult, PatternSyntaxException.
|
||||
"""
|
||||
|
||||
from .._core import Stub
|
||||
from .io import IOException
|
||||
from .lang import RuntimeException
|
||||
import re as _re
|
||||
|
||||
IllegalArgumentException = type("IllegalArgumentException", (RuntimeException,), {})
|
||||
IllegalStateException = type("IllegalStateException", (RuntimeException,), {})
|
||||
|
||||
__all__ = [
|
||||
"Pattern", "Matcher", "MatchResult", "PatternSyntaxException",
|
||||
]
|
||||
|
||||
|
||||
# ============================================================
|
||||
# PatternSyntaxException
|
||||
# ============================================================
|
||||
|
||||
class PatternSyntaxException(IllegalArgumentException):
|
||||
def __init__(self, desc, regex, index):
|
||||
super().__init__(f"{desc}: {regex} at index {index}")
|
||||
self._desc = desc
|
||||
self._regex = regex
|
||||
self._index = index
|
||||
|
||||
def getDescription(self):
|
||||
return self._desc
|
||||
|
||||
def getPattern(self):
|
||||
return self._regex
|
||||
|
||||
def getIndex(self):
|
||||
return self._index
|
||||
|
||||
def getMessage(self):
|
||||
return f"{self._desc} near index {self._index}: {self._regex}"
|
||||
|
||||
|
||||
# ============================================================
|
||||
# MatchResult
|
||||
# ============================================================
|
||||
|
||||
class MatchResult(Stub):
|
||||
def start(self, group=None):
|
||||
raise NotImplementedError
|
||||
|
||||
def end(self, group=None):
|
||||
raise NotImplementedError
|
||||
|
||||
def group(self, group=None):
|
||||
raise NotImplementedError
|
||||
|
||||
def groupCount(self):
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
# ============================================================
|
||||
# Matcher
|
||||
# ============================================================
|
||||
|
||||
class Matcher(MatchResult):
|
||||
def __init__(self, pattern, input_str):
|
||||
super().__init__()
|
||||
self._pattern = pattern
|
||||
self._input = input_str
|
||||
self._re_pattern = pattern._pattern
|
||||
self._match = None
|
||||
self._region_start = 0
|
||||
self._region_end = len(input_str)
|
||||
self._transparent_bounds = False
|
||||
self._anchoring_bounds = True
|
||||
self._last_match = None
|
||||
|
||||
def matches(self):
|
||||
self._match = self._re_pattern.fullmatch(self._input, self._region_start, self._region_end)
|
||||
self._last_match = self._match
|
||||
return self._match is not None
|
||||
|
||||
def find(self, start=None):
|
||||
if start is not None:
|
||||
self._match = self._re_pattern.search(self._input, start, self._region_end)
|
||||
else:
|
||||
if self._match is None:
|
||||
self._match = self._re_pattern.search(self._input, self._region_start, self._region_end)
|
||||
else:
|
||||
pos = self._match.end()
|
||||
self._match = self._re_pattern.search(self._input, pos, self._region_end)
|
||||
if self._match:
|
||||
self._last_match = self._match
|
||||
return self._match is not None
|
||||
|
||||
def lookingAt(self):
|
||||
self._match = self._re_pattern.match(self._input, self._region_start, self._region_end)
|
||||
self._last_match = self._match
|
||||
return self._match is not None
|
||||
|
||||
def start(self, group=0):
|
||||
if self._match is None:
|
||||
raise IllegalStateException("No match available")
|
||||
if group == 0:
|
||||
return self._match.start()
|
||||
return self._match.start(group)
|
||||
|
||||
def end(self, group=0):
|
||||
if self._match is None:
|
||||
raise IllegalStateException("No match available")
|
||||
if group == 0:
|
||||
return self._match.end()
|
||||
return self._match.end(group)
|
||||
|
||||
def group(self, group=0):
|
||||
if self._match is None:
|
||||
raise IllegalStateException("No match available")
|
||||
if isinstance(group, str):
|
||||
return self._match.group(group)
|
||||
return self._match.group(group)
|
||||
|
||||
def groupCount(self):
|
||||
return self._re_pattern.groups
|
||||
|
||||
def replaceAll(self, replacement):
|
||||
return self._re_pattern.sub(replacement, self._input)
|
||||
|
||||
def replaceFirst(self, replacement):
|
||||
return self._re_pattern.sub(replacement, self._input, count=1)
|
||||
|
||||
def appendReplacement(self, sb, replacement):
|
||||
if self._match is None:
|
||||
raise IllegalStateException("No match available")
|
||||
self._append_pos = getattr(self, '_append_pos', 0)
|
||||
sb.append(self._input[self._append_pos:self._match.start()])
|
||||
sb.append(self._re_pattern.sub(replacement, self._match.group(), count=1))
|
||||
self._append_pos = self._match.end()
|
||||
return self
|
||||
|
||||
def appendTail(self, sb):
|
||||
self._append_pos = getattr(self, '_append_pos', 0)
|
||||
sb.append(self._input[self._append_pos:])
|
||||
return sb
|
||||
|
||||
def reset(self, input_str=None):
|
||||
if input_str is not None:
|
||||
self._input = input_str
|
||||
self._region_end = len(input_str)
|
||||
self._match = None
|
||||
self._last_match = None
|
||||
return self
|
||||
|
||||
def region(self, start, end):
|
||||
self._region_start = start
|
||||
self._region_end = end
|
||||
return self
|
||||
|
||||
def regionStart(self):
|
||||
return self._region_start
|
||||
|
||||
def regionEnd(self):
|
||||
return self._region_end
|
||||
|
||||
def hasTransparentBounds(self):
|
||||
return self._transparent_bounds
|
||||
|
||||
def hasAnchoringBounds(self):
|
||||
return self._anchoring_bounds
|
||||
|
||||
def useAnchoringBounds(self, value):
|
||||
self._anchoring_bounds = value
|
||||
return self
|
||||
|
||||
def useTransparentBounds(self, value):
|
||||
self._transparent_bounds = value
|
||||
return self
|
||||
|
||||
def hitEnd(self):
|
||||
return self._match is not None and self._match.end() >= self._region_end
|
||||
|
||||
def requireEnd(self):
|
||||
return self._match is not None and not self.hitEnd()
|
||||
|
||||
def toMatchResult(self):
|
||||
result = Matcher(self._pattern, self._input)
|
||||
result._match = self._match
|
||||
result._last_match = self._last_match
|
||||
return result
|
||||
|
||||
def pattern(self):
|
||||
return self._pattern
|
||||
|
||||
def toString(self):
|
||||
return f"Matcher[pattern={self._pattern.pattern()}]"
|
||||
|
||||
def namedGroups(self):
|
||||
return self._re_pattern.groupindex
|
||||
|
||||
|
||||
class IllegalStateException(RuntimeException):
|
||||
pass
|
||||
|
||||
|
||||
# ============================================================
|
||||
# Pattern
|
||||
# ============================================================
|
||||
|
||||
class Pattern(Stub):
|
||||
CANON_EQ = 128
|
||||
CASE_INSENSITIVE = 2
|
||||
COMMENTS = 4
|
||||
DOTALL = 32
|
||||
LITERAL = 16
|
||||
MULTILINE = 8
|
||||
UNICODE_CASE = 64
|
||||
UNICODE_CHARACTER_CLASS = 256
|
||||
UNIX_LINES = 1
|
||||
|
||||
_re_flags_map = {
|
||||
0: 0, # default
|
||||
2: _re.IGNORECASE,
|
||||
8: _re.MULTILINE,
|
||||
32: _re.DOTALL,
|
||||
64: _re.UNICODE,
|
||||
4: _re.VERBOSE,
|
||||
}
|
||||
|
||||
def __init__(self, regex, flags=0):
|
||||
super().__init__()
|
||||
self._regex = str(regex)
|
||||
self._flags = flags
|
||||
re_flags = 0
|
||||
for java_flag, py_flag in self._re_flags_map.items():
|
||||
if flags & java_flag:
|
||||
re_flags |= py_flag
|
||||
try:
|
||||
self._pattern = _re.compile(self._regex, re_flags)
|
||||
except _re.error as e:
|
||||
raise PatternSyntaxException(str(e), self._regex, e.pos if hasattr(e, 'pos') else 0)
|
||||
|
||||
@staticmethod
|
||||
def compile(regex, flags=0):
|
||||
return Pattern(regex, flags)
|
||||
|
||||
def matcher(self, input_str):
|
||||
return Matcher(self, input_str)
|
||||
|
||||
def split(self, input_str, limit=0):
|
||||
if limit <= 0:
|
||||
parts = self._pattern.split(str(input_str))
|
||||
if limit == 0:
|
||||
while parts and parts[-1] == "":
|
||||
parts.pop()
|
||||
else:
|
||||
parts = self._pattern.split(str(input_str), maxsplit=limit - 1)
|
||||
while len(parts) < limit:
|
||||
parts.append("")
|
||||
return parts
|
||||
|
||||
def splitAsStream(self, input_str):
|
||||
return iter(self.split(input_str))
|
||||
|
||||
@staticmethod
|
||||
def matches(regex, input_str):
|
||||
return bool(_re.fullmatch(regex, str(input_str)))
|
||||
|
||||
@staticmethod
|
||||
def quote(s):
|
||||
return _re.escape(str(s))
|
||||
|
||||
def flags(self):
|
||||
return self._flags
|
||||
|
||||
def pattern(self):
|
||||
return self._regex
|
||||
|
||||
def toString(self):
|
||||
return self._regex
|
||||
|
||||
def predicate(self):
|
||||
return lambda s: bool(self._pattern.fullmatch(str(s)))
|
||||
|
||||
def asPredicate(self):
|
||||
return self.predicate()
|
||||
|
||||
def asMatchPredicate(self):
|
||||
return lambda s: bool(self._pattern.fullmatch(str(s)))
|
||||
Reference in new issue
Block a user