-
-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathpatterns.py
More file actions
82 lines (55 loc) · 2.41 KB
/
Copy pathpatterns.py
File metadata and controls
82 lines (55 loc) · 2.41 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
import re
from typing import Optional
from modules.utilities import first
REGEX_MATCH_ALL = r"<all_urls>"
REGEX_MATCH_SCHEME = r"\*|https?"
REGEXGROUP_MATCH_SCHEME = r"scheme"
REGEX_MATCH_HOST = r"(\*\.)*[^\/\*]+|\*"
REGEXGROUP_MATCH_HOST = r"host"
REGEX_MATCH_PATH = r"\/.*"
REGEXGROUP_MATCH_PATH = r"path"
MATCH_PATTERN_ALL_NORMALIZED = "*://*/*"
# Outer parentheses necessary to enclose `|`:
REGEX_MATCH_PATTERN = re.compile(
r"^(?:" + REGEX_MATCH_ALL + r"|"
+ r"(?P<" + REGEXGROUP_MATCH_SCHEME + r">" + REGEX_MATCH_SCHEME + r"):\/\/"
+ r"(?P<" + REGEXGROUP_MATCH_HOST + r">" + REGEX_MATCH_HOST + r")"
+ r"(?P<" + REGEXGROUP_MATCH_PATH + r">" + REGEX_MATCH_PATH + r")"
+ r")$"
)
REGEX_INCLUDE_REGULAR = r"^(.+)$"
REGEX_INCLUDE_REGEX = r"^\/(.+)\/$"
REGEX_INCLUDE_PATTERN = re.compile(
REGEX_INCLUDE_REGEX + "|" + REGEX_INCLUDE_REGULAR
)
def normalizeMatchPattern(pattern: str) -> str:
return MATCH_PATTERN_ALL_NORMALIZED if pattern == REGEX_MATCH_ALL else pattern
def isMatchPattern(pattern: str) -> bool:
return REGEX_MATCH_PATTERN.match(pattern) is not None
def isIncludePattern(pattern: str) -> bool:
return REGEX_INCLUDE_PATTERN.match(pattern) is not None
def isIncludePattern_regex(pattern: str) -> bool:
return re.compile(REGEX_INCLUDE_REGEX).match(pattern) is not None
def withoutSurroundingSlashes(s: str) -> str:
return first(re.subn(re.compile(r"^\/|\/$"), "", s))
def regexFromIncludePattern(pattern: str) -> re.Pattern: # raises re.error
return (
re.compile(withoutSurroundingSlashes(pattern), re.IGNORECASE)
if isIncludePattern_regex(pattern)
else re.compile(r"^" + regexify(pattern) + r"$", re.IGNORECASE)
)
def regexify(segment: str) -> str:
return re.escape(segment).replace(r"\*", ".*")
# Returns None if the pattern is invalid:
def extractGroup(group: str, matchPattern: str) -> Optional[str]:
try:
match: Optional[re.Match] = REGEX_MATCH_PATTERN.search(normalizeMatchPattern(matchPattern))
return None if match is None else match.group(group)
except:
return None
def schemeIn(matchPattern: str) -> Optional[str]:
return extractGroup(REGEXGROUP_MATCH_SCHEME, matchPattern)
def hostIn(matchPattern: str) -> Optional[str]:
return extractGroup(REGEXGROUP_MATCH_HOST, matchPattern)
def pathIn(matchPattern: str) -> Optional[str]:
return extractGroup(REGEXGROUP_MATCH_PATH, matchPattern)