Skip to content

Commit a595e71

Browse files
committed
Make NuGet version tests pass
Signed-off-by: Philippe Ombredanne <pombredanne@nexb.com>
1 parent b575744 commit a595e71

3 files changed

Lines changed: 217 additions & 122 deletions

File tree

src/univers/nuget.py

Lines changed: 95 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,10 @@
1+
# SPDX-License-Identifier: Apache-2.0
2+
# Nuget version utility originally from:
3+
# https://raw.githubusercontent.com/google/osv/f5647ad2f746685b08debfba0293e442f2fb9945/lib/osv/nuget.py
14
# Copyright 2022 Google LLC
5+
# modified by nexB and others for integration in the Univers library
26
#
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.
7+
# Visit https://aboutcode.org and https://github.com/nexB/univers for support and download.
148

159
import functools
1610
import re
@@ -129,8 +123,13 @@ def normalize(version):
129123

130124

131125
def _extract_revision(str_version):
132-
"""Extract revision (4th component) from version number (if any)."""
126+
"""
127+
Extract revision from ``str_version`` and return a tuple of:
128+
(dotted version string without revision, revision integer).
129+
The revision is the 4th numeric dotted component of a NuGet version.
130+
"""
133131
# e.g. '1.0.0.0-prerelease'
132+
# note: each match group contains its leading dot.
134133
pattern = re.compile(r"^(\d+)(\.\d+)(\.\d+)(\.\d+)(.*)")
135134
match = pattern.match(str_version)
136135
if not match:
@@ -142,15 +141,20 @@ def _extract_revision(str_version):
142141
)
143142

144143

144+
class InvalidNuGetVersion(Exception):
145+
pass
146+
147+
145148
@functools.total_ordering
146149
class Version:
147150
"""NuGet version."""
148151

149-
def __init__(self, base_semver, revision):
152+
def __init__(self, base_semver, revision=0):
150153
self._base_semver = base_semver
151154
if self._base_semver.prerelease:
152155
self._base_semver = self._base_semver.replace(prerelease=base_semver.prerelease.lower())
153-
self._revision = revision
156+
self._revision = revision or 0
157+
self._original_version = None
154158

155159
def __eq__(self, other):
156160
return self._base_semver == other._base_semver and self._revision == other._revision
@@ -166,6 +170,82 @@ def __lt__(self, other):
166170

167171
@classmethod
168172
def from_string(cls, str_version):
173+
if not str_version:
174+
return
175+
176+
str_version = str_version.strip()
177+
if " " in str_version:
178+
raise InvalidNuGetVersion(f"version cannot contain spaces: {str_version}")
179+
180+
if not any(c.isdigit() for c in str_version):
181+
raise InvalidNuGetVersion(f"version does not contain any digit: {str_version}")
182+
183+
original = str_version
169184
str_version = coerce(str_version)
170185
str_version, revision = _extract_revision(str_version)
171-
return Version(parse(str_version), revision)
186+
vers = Version(base_semver=parse(str_version), revision=revision)
187+
vers._original_version = original
188+
return vers
189+
190+
def __repr__(self):
191+
return f"Version<{self.to_string()}>"
192+
193+
def to_string(self, with_empty_revision=False, include_prerelease=True, include_build=True):
194+
major = self.major or "0"
195+
minor = self.minor or "0"
196+
patch = self.patch or "0"
197+
198+
if with_empty_revision:
199+
revision = self.revision and f".{self.revision}" or ".0"
200+
else:
201+
revision = self.revision and f".{self.revision}" or ""
202+
203+
if include_prerelease:
204+
prerelease = self.prerelease and f"-{self.prerelease}" or ""
205+
else:
206+
prerelease = ""
207+
if include_build:
208+
build = self.build and f"+{self.build}" or ""
209+
else:
210+
build = ""
211+
212+
return f"{major}.{minor}.{patch}{revision}{prerelease}{build}"
213+
214+
def __str__(self):
215+
return self.to_string(
216+
with_empty_revision=False, include_prerelease=True, include_build=True
217+
)
218+
219+
@property
220+
def base_version(self):
221+
"""
222+
Return the base version dotted string composed of the four numerical
223+
segments including revision and ignoring prerelease and build.
224+
"""
225+
return self.to_string(
226+
with_empty_revision=True, include_prerelease=False, include_build=False
227+
)
228+
229+
@property
230+
def major(self):
231+
return self._base_semver.major
232+
233+
@property
234+
def minor(self):
235+
return self._base_semver.minor
236+
237+
@property
238+
def patch(self):
239+
return self._base_semver.patch
240+
241+
@property
242+
def revision(self):
243+
return self._revision
244+
245+
@property
246+
def prerelease(self):
247+
return self._base_semver.prerelease and self._base_semver.prerelease or ""
248+
249+
@property
250+
def build(self):
251+
return self._base_semver.build and self._base_semver.build or ""

src/univers/nuget.py.ABOUT

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
about_resource: nuget.py
22
package_url: pkg:github/google/osv@0.0.14#lib/osv/nuget.py
3-
copyright: Copyright 2022 Google LLC
3+
copyright: Copyright 2022 Google LLC and others
44
download_url: https://raw.githubusercontent.com/google/osv/f5647ad2f746685b08debfba0293e442f2fb9945/lib/osv/nuget.py
55
license_expression: apache-2.0
66
homepage_url: https://github.com/google/osv/

0 commit comments

Comments
 (0)