optimize instantiation and comparison of versions (#29429)

Re-work the checks and comparisons around commit versions, when no
commit version is involved the overhead is now in the noise, where one
is the overhead is now constant rather than linear.
This commit is contained in:
Tom Scogland 2022-03-15 11:53:28 -07:00 committed by GitHub
parent 1250fac467
commit 94794d061a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -48,7 +48,7 @@
VALID_VERSION = re.compile(r'^[A-Za-z0-9_.-]+$') VALID_VERSION = re.compile(r'^[A-Za-z0-9_.-]+$')
# regex for a commit version # regex for a commit version
COMMIT_VERSION = re.compile(r'^[a-z0-9]{40}$') COMMIT_VERSION = re.compile(r'^[a-f0-9]{40}$')
# regex for version segments # regex for version segments
SEGMENT_REGEX = re.compile(r'(?:(?P<num>[0-9]+)|(?P<str>[a-zA-Z]+))(?P<sep>[_.-]*)') SEGMENT_REGEX = re.compile(r'(?:(?P<num>[0-9]+)|(?P<str>[a-zA-Z]+))(?P<sep>[_.-]*)')
@ -167,7 +167,14 @@ def __gt__(self, other):
class Version(object): class Version(object):
"""Class to represent versions""" """Class to represent versions"""
__slots__ = ['version', 'separators', 'string', 'is_commit', 'commit_lookup'] __slots__ = [
"version",
"separators",
"string",
"commit_lookup",
"is_commit",
"commit_version",
]
def __init__(self, string): def __init__(self, string):
if not isinstance(string, str): if not isinstance(string, str):
@ -182,7 +189,7 @@ def __init__(self, string):
# An object that can lookup git commits to compare them to versions # An object that can lookup git commits to compare them to versions
self.commit_lookup = None self.commit_lookup = None
self.commit_version = None
segments = SEGMENT_REGEX.findall(string) segments = SEGMENT_REGEX.findall(string)
self.version = tuple( self.version = tuple(
int(m[0]) if m[0] else VersionStrComponent(m[1]) for m in segments int(m[0]) if m[0] else VersionStrComponent(m[1]) for m in segments
@ -195,6 +202,8 @@ def _cmp(self, other_lookups=None):
commit_lookup = self.commit_lookup or other_lookups commit_lookup = self.commit_lookup or other_lookups
if self.is_commit and commit_lookup: if self.is_commit and commit_lookup:
if self.commit_version is not None:
return self.commit_version
commit_info = commit_lookup.get(self.string) commit_info = commit_lookup.get(self.string)
if commit_info: if commit_info:
prev_version, distance = commit_info prev_version, distance = commit_info
@ -203,7 +212,8 @@ def _cmp(self, other_lookups=None):
# If commit is exactly a known version, no distance suffix # If commit is exactly a known version, no distance suffix
prev_tuple = Version(prev_version).version if prev_version else () prev_tuple = Version(prev_version).version if prev_version else ()
dist_suffix = (VersionStrComponent(''), distance) if distance else () dist_suffix = (VersionStrComponent(''), distance) if distance else ()
return prev_tuple + dist_suffix self.commit_version = prev_tuple + dist_suffix
return self.commit_version
return self.version return self.version