summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorTodd Gamblin <tgamblin@llnl.gov>2023-12-14 04:08:08 -0800
committerGitHub <noreply@github.com>2023-12-14 05:08:08 -0700
commit0dc3fc2d2165e4023b7c6cbb531a19a583ea4bae (patch)
treee419cfa27c60a8d51cc775daf205f8016d1ccbe2 /lib
parenta972314fa6eb8ca15ba0535f13c833c5c1adebf7 (diff)
downloadspack-0dc3fc2d2165e4023b7c6cbb531a19a583ea4bae.tar.gz
spack-0dc3fc2d2165e4023b7c6cbb531a19a583ea4bae.tar.bz2
spack-0dc3fc2d2165e4023b7c6cbb531a19a583ea4bae.tar.xz
spack-0dc3fc2d2165e4023b7c6cbb531a19a583ea4bae.zip
spec parser: precompile quoting-related regular expressions (#41657)
This adds a small (~5%) performance improvement to Spec parsing. Co-authored-by: Massimiliano Culpo <massimiliano.culpo@gmail.com>
Diffstat (limited to 'lib')
-rw-r--r--lib/spack/spack/cmd/__init__.py2
-rw-r--r--lib/spack/spack/parser.py14
2 files changed, 8 insertions, 8 deletions
diff --git a/lib/spack/spack/cmd/__init__.py b/lib/spack/spack/cmd/__init__.py
index cb4083ed8f..58c4de3469 100644
--- a/lib/spack/spack/cmd/__init__.py
+++ b/lib/spack/spack/cmd/__init__.py
@@ -154,7 +154,7 @@ def quote_kvp(string: str) -> str:
or ``name==``, and we assume the rest of the argument is the value. This covers the
common cases of passign flags, e.g., ``cflags="-O2 -g"`` on the command line.
"""
- match = re.match(spack.parser.SPLIT_KVP, string)
+ match = spack.parser.SPLIT_KVP.match(string)
if not match:
return string
diff --git a/lib/spack/spack/parser.py b/lib/spack/spack/parser.py
index 63c139b9f0..0369416faf 100644
--- a/lib/spack/spack/parser.py
+++ b/lib/spack/spack/parser.py
@@ -100,7 +100,7 @@ else:
VALUE = r"(?:[a-zA-Z_0-9\-+\*.,:=\~\/\\]+)"
#: Variant/flag values that match this can be left unquoted in Spack output
-NO_QUOTES_NEEDED = r"^[a-zA-Z0-9,/_.-]+$"
+NO_QUOTES_NEEDED = re.compile(r"^[a-zA-Z0-9,/_.-]+$")
#: Quoted values can be *anything* in between quotes, including escaped quotes.
QUOTED_VALUE = r"(?:'(?:[^']|(?<=\\)')*'|\"(?:[^\"]|(?<=\\)\")*\")"
@@ -110,15 +110,15 @@ VERSION_RANGE = rf"(?:(?:{VERSION})?:(?:{VERSION}(?!\s*=))?)"
VERSION_LIST = rf"(?:{VERSION_RANGE}|{VERSION})(?:\s*,\s*(?:{VERSION_RANGE}|{VERSION}))*"
#: Regex with groups to use for splitting (optionally propagated) key-value pairs
-SPLIT_KVP = rf"^({NAME})(==?)(.*)$"
+SPLIT_KVP = re.compile(rf"^({NAME})(==?)(.*)$")
#: Regex to strip quotes. Group 2 will be the unquoted string.
-STRIP_QUOTES = r"^(['\"])(.*)\1$"
+STRIP_QUOTES = re.compile(r"^(['\"])(.*)\1$")
def strip_quotes_and_unescape(string: str) -> str:
"""Remove surrounding single or double quotes from string, if present."""
- match = re.match(STRIP_QUOTES, string)
+ match = STRIP_QUOTES.match(string)
if not match:
return string
@@ -140,7 +140,7 @@ def quote_if_needed(value: str) -> str:
``"``, and control codes.
"""
- if re.match(spack.parser.NO_QUOTES_NEEDED, value):
+ if NO_QUOTES_NEEDED.match(value):
return value
return json.dumps(value) if "'" in value else f"'{value}'"
@@ -456,14 +456,14 @@ class SpecNodeParser:
)
elif self.ctx.accept(TokenType.KEY_VALUE_PAIR):
- match = re.match(SPLIT_KVP, self.ctx.current_token.value)
+ match = SPLIT_KVP.match(self.ctx.current_token.value)
assert match, "SPLIT_KVP and KEY_VALUE_PAIR do not agree."
name, delim, value = match.groups()
initial_spec._add_flag(name, strip_quotes_and_unescape(value), propagate=False)
elif self.ctx.accept(TokenType.PROPAGATED_KEY_VALUE_PAIR):
- match = re.match(SPLIT_KVP, self.ctx.current_token.value)
+ match = SPLIT_KVP.match(self.ctx.current_token.value)
assert match, "SPLIT_KVP and PROPAGATED_KEY_VALUE_PAIR do not agree."
name, delim, value = match.groups()