1# Copyright 2024 The Bazel Authors. All rights reserved. 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# http://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14 15"A semver version parser" 16 17def _key(version): 18 return ( 19 version.major, 20 version.minor or 0, 21 version.patch or 0, 22 # non pre-release versions are higher 23 version.pre_release == "", 24 # then we compare each element of the pre_release tag separately 25 tuple([ 26 ( 27 i if not i.isdigit() else "", 28 # digit values take precedence 29 int(i) if i.isdigit() else 0, 30 ) 31 for i in version.pre_release.split(".") 32 ]) if version.pre_release else None, 33 # And build info is just alphabetic 34 version.build, 35 ) 36 37def _to_dict(self): 38 return { 39 "build": self.build, 40 "major": self.major, 41 "minor": self.minor, 42 "patch": self.patch, 43 "pre_release": self.pre_release, 44 } 45 46def semver(version): 47 """Parse the semver version and return the values as a struct. 48 49 Args: 50 version: {type}`str` the version string. 51 52 Returns: 53 A {type}`struct` with `major`, `minor`, `patch` and `build` attributes. 54 """ 55 56 # Implement the https://semver.org/ spec 57 major, _, tail = version.partition(".") 58 minor, _, tail = tail.partition(".") 59 patch, _, build = tail.partition("+") 60 patch, _, pre_release = patch.partition("-") 61 62 # buildifier: disable=uninitialized 63 self = struct( 64 major = int(major), 65 minor = int(minor) if minor.isdigit() else None, 66 # NOTE: this is called `micro` in the Python interpreter versioning scheme 67 patch = int(patch) if patch.isdigit() else None, 68 pre_release = pre_release, 69 build = build, 70 # buildifier: disable=uninitialized 71 key = lambda: _key(self), 72 str = lambda: version, 73 to_dict = lambda: _to_dict(self), 74 ) 75 return self 76