#
# CDDL HEADER START
#
# The contents of this file are subject to the terms of the
# Common Development and Distribution License (the "License").
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
# See the License for the specific language governing permissions
# and limitations under the License.
#
# When distributing Covered Code, include this CDDL HEADER in each
# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
# If applicable, add the following below this CDDL HEADER, with the
# fields enclosed by brackets "[]" replaced with your own identifying
# information: Portions Copyright [yyyy] [name of copyright owner]
#
# CDDL HEADER END
#
#
#
import calendar
import datetime
import time
import weakref
"""Base exception class for all version errors."""
"""Used to indicate that the specified DotSequence is not valid."""
"""A DotSequence is the typical "x.y.z" string used in software
versioning. We define the "major release" value and the "minor release"
value as the first two numbers in the sequence."""
#
# We employ the Flyweight design pattern for dotsequences, since they
# are used immutably, are highly repetitive (0.5.11 over and over) and,
# for what they contain, are relatively expensive memory-wise.
#
# Do this first; if the string is zero chars or non-numeric
# chars, this will throw.
raise ValueError("Negative number")
raise ValueError("Zero padded number")
return x
if ds is None:
return ds
# Was I already initialized? See __new__ above.
return
try:
except ValueError:
raise IllegalDotSequence(dotstring)
raise IllegalDotSequence("Empty DotSequence")
"""Return true if self is a "subsequence" of other, meaning that
other and self have identical components, up to the length of
self's sequence."""
return False
if a != b:
return False
return True
""" Test if DotSequences have the same major number """
""" Test if DotSequences have the same major and minor num """
"""A subclass of DotSequence with (much) weaker rules about its format.
This is intended to accept user input with wildcard characters."""
#
# We employ the Flyweight design pattern for dotsequences, since they
# are used immutably, are highly repetitive (0.5.11 over and over) and,
# for what they contain, are relatively expensive memory-wise.
#
# Do this first; if the string is zero chars or non-numeric
# chars (other than "*"), an exception will be raised.
if elem == "*":
return elem
None)
if ds is not None:
return ds
return ds
try:
except ValueError:
raise IllegalDotSequence(dotstring)
raise IllegalDotSequence("Empty MatchingDotSequence")
return True
try:
other[i])):
return True
except IndexError:
other[i]):
return True
other[-1]):
return True
return False
return False
try:
other[i])):
return False
except IndexError:
other[i]):
return False
other[-1]):
return False
return True
"""Return true if self is a "subsequence" of other, meaning that
other and self have identical components, up to the length of
self's sequence or self or other is '*'."""
return True
return False
if a != b:
return False
return True
"""Test if DotSequences have the same major number, or major
is '*'."""
""" Test if DotSequences have the same major and minor num."""
"""Used to indicate that the specified version string is not valid."""
"""Version format is release[,build_release]-branch:datetime, which we
decompose into three DotSequences and a date string. Time
representation is in the ISO8601-compliant form "YYYYMMDDTHHMMSSZ",
referring to the UTC time associated with the version. The release and
branch DotSequences are interpreted normally, where v1 < v2 implies that
v2 is a later release or branch. The build_release DotSequence records
the system on which the package binaries were constructed."""
# XXX If illegally formatted, raise exception.
if not version_string:
raise IllegalVersion("Version cannot be empty")
#
# Locate and extract the time, branch, and build strings,
# if specified. Error checking happens in the second half of
# the routine. In the event that a given part of the input is
# signalled but empty (for example: '0.3-' or '0.3-3.0:',
# we'll produce an empty (but not None) string for that portion.
#
# Locate and extract the time string, if specified.
if timeidx != -1:
else:
timeidx = None
timestr = None
# Locate and extract the branch string, if specified.
if branchidx != -1:
else:
branch = None
# Locate and extract the build string, if specified.
if buildidx != -1:
else:
build = None
if buildidx == 0:
raise IllegalVersion("Versions must have a release value")
#
# Error checking and conversion from strings to objects
# begins here.
#
try:
if branch is not None:
else:
if build is not None:
else:
if build_string is None:
build_string = "5.11"
except IllegalDotSequence as e:
#
# In 99% of the cases in which we use date and time, it's solely
# for comparison. Since the ISO date string lexicographically
# collates in date order, we just hold onto the string-
# converting it to anything else is expensive.
#
if timestr is not None:
raise IllegalVersion("Time must be ISO8601 format.")
try:
dateint % 100,
timeint // 10000,
timeint % 100)
except ValueError:
raise IllegalVersion("Time must be ISO8601 format.")
else:
"""Returns the serialized state of this object in a format
that that can be easily stored using JSON, pickle, etc."""
"""Allocate a new object using previously serialized state
obtained via getstate()."""
return outstr
if include_build:
else:
return outstr
branch_str = ""
return None
return True
return False
return True
return False
return True
return False
"""Returns True if 'self' comes before 'other', and vice versa.
If exactly one of the release values of the versions is None,
then that version is less than the other. The same applies to
the branch and timestamp components.
"""
return False
return True
return False
return True
return False
return True
return False
return True
return False
return True
return False
"""Returns True if 'self' comes after 'other', and vice versa.
If exactly one of the release values of the versions is None,
then that version is less than the other. The same applies to
the branch and timestamp components.
"""
return True
return True
return False
return True
return False
return True
return False
return True
return False
return True
return False
# If a timestamp is present, it's enough to hash on, and is
# nicely unique. If not, use release and branch, which are
# not very unique.
else:
"""Evaluate true if self is a successor version to other.
The loosest constraint is CONSTRAINT_NONE (None is treated
equivalently, which is a simple test for self > other. As we
proceed through the policies we get stricter, depending on the
selected constraint.
Slightly less loose is CONSTRAINT_AUTO. In this case, if any of
the release, branch, or timestamp components is None, it acts as
a "don't care" value -- a versioned component always succeeds
None.
For CONSTRAINT_RELEASE, self is a successor to other if all of
the components of other's release match, and there are later
components of self's version. The branch and datetime
components are ignored.
For CONSTRAINT_RELEASE_MAJOR and CONSTRAINT_RELEASE_MINOR, other
is effectively truncated to [other[0]] and [other[0], other[1]]
prior to being treated as for CONSTRAINT_RELEASE.
Similarly for CONSTRAINT_BRANCH, the release fields of other and
self are expected to be identical, and then the branches are
compared as releases were for the CONSTRAINT_RELEASE* policies.
"""
if constraint == CONSTRAINT_AUTO and \
return False
return False
return False
return False
return False
return False
return True
elif constraint == CONSTRAINT_AUTO:
return False
return False
return False
return False
return False
return False
return True
if constraint == CONSTRAINT_RELEASE:
if constraint == CONSTRAINT_BRANCH:
raise ValueError("constraint has unknown value")
"""Takes an assumed valid version string and splits it into
its components as a tuple of the form ((release, build_release,
branch, timestr), short_ver)."""
# Locate and extract the time string.
if timeidx != -1:
else:
timeidx = None
timestr = None
# Locate and extract the branch string.
if branchidx != -1:
else:
branch = None
# Locate and extract the build string.
if buildidx != -1:
else:
build = None
build_release = ""
if build is not None:
if branch is not None:
else:
"""An alternative for Version with (much) weaker rules about its format.
This is intended to accept user input with globbing characters."""
raise IllegalVersion("Version cannot be empty")
if version_string == "latest":
# Treat special "latest" syntax as equivalent to '*' for
# version comparison purposes.
version_string = "*"
else:
if not build_release:
#
# Error checking and conversion from strings to objects
# begins here.
#
try:
#
# Every component of the version (after the first) is
# optional, if not provided, assume "*" (wildcard).
#
('release', (release,)),
if not val:
continue
if attr != 'timestr':
break
except IllegalDotSequence as e:
if build_release is not None:
if branch is not None:
if timestr is not None:
# Store the re-constructed input value for use as a string
# representation of this object.
if self.match_latest:
return "latest"
return self.__original
return "*"
return True
return False
return True
return False
return True
return False
"""Returns True if 'self' comes before 'other', and vice versa.
If exactly one of the release values of the versions is None or
"*", then that version is less than the other. The same applies
to the branch and timestamp components.
"""
return False
return True
return True
return False
return True
return True
return False
return True
return True
return False
return True
"""Returns True if 'self' comes after 'other', and vice versa.
If exactly one of the release values of the versions is None or
"*", then that version is less than the other. The same applies
to the branch and timestamp components.
"""
return True
return False
return True
return False
return False
return True
return False
return False
return True
return False
return False
# If a timestamp is present, it's enough to hash on, and is
# nicely unique. If not, use release and branch, which are
# not very unique.
else: