Skip to content

Instantly share code, notes, and snippets.

@scbedd
Last active April 21, 2023 22:53
Show Gist options
  • Save scbedd/be33c0a4d8979866f1d23ef3a0744f10 to your computer and use it in GitHub Desktop.
Save scbedd/be33c0a4d8979866f1d23ef3a0744f10 to your computer and use it in GitHub Desktop.
Discarded Code - Sorting Spec Lists
# After writing this code, I realized that these inputs do not need to be sorted to meet my purposes for `scripts/analyze_deps.py`.
# As a result, I have removed this code from the code base, but am emplacing it here so that I can retrieve it later.
# pip install packaging
from typing import List
import re
from packaging.version import Version, parse
class SortableSpecifierSet:
def trim_spec(self, spec):
"""
Expected inputs
">= 2.7.8"
"<= 0.16.3a123"
"!= 1.0.0"
"!= 1.1"
Should return the bare version value.
"""
matcher = re.compile(r"[\<\>\=\!\~][\<\>\=]?[\=]?")
return matcher.sub('', spec, 1).strip()
def _get_sort_value(self, spec):
"""
Returns the lowest valued member of the spec.
This is primarily used to sort SpecifierSets in ascending order, from most restrictive to least.
"""
# "<2.0.0, != 1.1.2, == 1.1.3" -> ["<2.0.0", "!=1.1.2", "1.1.3"]
# ">=1.1.3, <2.0.0" -> [">=1.1.3", "<2.0.0"]
# "<2.0.0,>=1.1.3" -> ["<2.0.0", ">=1.1.3"]
return str(sorted([Version(self.trim_spec(lower_spec)) for lower_spec in spec.split(",")])[0])
def __init__(self, full_spec):
self.full_spec = full_spec
self.sort_spec = Version(self._get_sort_value(full_spec))
def __lt__(self, obj):
return (self.sort_spec < obj)
def __gt__(self, obj):
return (self.sort_spec > obj)
def __le__(self, obj):
return (self.sort_spec <= obj)
def __ge__(self, obj):
return (self.sort_spec >= obj)
def __eq__(self, obj):
return (self.sort_spec == obj)
def __repr__(self):
return str((self.full_spec))
def sort_spec_list(specs: List[str]) -> List[SortableSpecifierSet]:
"""
Sorts a given set of specifiers, each unit of which being sorted by the lowest version included in the speclist.
EG:
['!=0.6.2', '>=0.6.2,>=0.6.1,!=0.6.3,!=0.6.4']
-> ['>=0.6.2,>=0.6.1,!=0.6.3,!=0.6.4', '!=0.6.2']
0.6.1 being the lowers of second specifier in list.
"""
if specs:
inputs = [SortableSpecifierSet(spec) for spec in specs if spec]
return sorted(inputs)
else:
return []
def test_spec_list_scenarios_ascending():
scenarios = [
['>=0.7.1', '>=0.6.21', '>=0.6.18', '>=0.6.10', '<2.0.0,>=0.6.17'],
['>=0.7.1', '!=0.6.1', '!=0.8.3', '>=0.6.10', '>=0.6.17,<2.0.0'],
['!=0.7.7', '!=0.7.6', '>=0.16.1,!=0.16.3,!=0.16.4'],
# we should never encounter this in the wild but better to test for it here
# (multiple conflicting valid > specs)
['!=0.7.7', '>=0.6.2,>=0.6.1,!=0.6.2,!=0.6.2'],
# this case is another diabolical one. forcing us to internally sort the possible return versions
['!=0.6.2', '>=0.6.2,>=0.6.1,!=0.6.3,!=0.6.4'],
['!=0.7.7', '~=1.1', '>=0.16.1']
]
success_results = [
['>=0.6.10', '<2.0.0,>=0.6.17', '>=0.6.18', '>=0.6.21', '>=0.7.1'],
['!=0.6.1', '>=0.6.10', '>=0.6.17,<2.0.0', '>=0.7.1', '!=0.8.3'],
['!=0.7.6', '!=0.7.7','>=0.16.1,!=0.16.3,!=0.16.4'],
['>=0.6.2,>=0.6.1,!=0.6.2,!=0.6.2', '!=0.7.7'],
['>=0.6.2,>=0.6.1,!=0.6.3,!=0.6.4', '!=0.6.2'],
['!=0.7.7', '>=0.16.1', '~=1.1']
]
for index, scenario in enumerate(scenarios):
result = [spec.full_spec for spec in sort_spec_list(scenario)]
assert(result == success_results[index])
if __name__ == "__main__":
test_spec_list_scenarios_ascending()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment