rez.version#

Implements everything needed to manipulate versions and requirements.

There are three class types: VersionToken, Version and VersionRange. A Version is a set of zero or more VersionTokens, separate by .s or -s (eg 1.2-3). A VersionToken is a string containing alphanumerics, and default implemenations NumericToken and AlphanumericVersionToken are supplied. You can implement your own if you want stricter tokens or different sorting behaviour.

A VersionRange is a set of one or more contiguous version ranges. For example, 3+<5 contains any version >=3 but less than 5. Version ranges can be used to define dependency requirements between objects. They can be OR’d together, AND’d and inverted.

The empty version '', and empty version range '', are also handled. The empty version is used to denote unversioned objects. The empty version range, also known as the ‘any’ range, is used to refer to any version of an object.

Requirements and list of requirements are represented by Requirement and RequirementList respectively.

class rez.version.Version#

Bases: _Comparable

A Version is a sequence of zero or more version tokens, separated by either a dot . or hyphen - delimiters. Note that separators only affect Version objects cosmetically. In other words, the version 1.0.0 is equivalent to 1-0-0.

The empty version '' is the smallest possible version, and can be used to represent an unversioned resource.

inf = Version('[INF]')#
__init__(ver_str='', make_token=<class 'rez.version._version.AlphanumericVersionToken'>)#
Parameters:
  • ver_str (str) – Version string.

  • make_token (Callable[[str], None]) – Callable that creates a VersionToken subclass from a string.

copy()#

Returns a copy of the version.

Return type:

Version

trim(len_)#

Return a copy of the version, possibly with less tokens.

Parameters:

len (int) – New version length. If >= current length, an unchanged copy of the version is returned.

Return type:

Version

next()#
property major#

Semantic versioning major version.

Returns:

A VersionToken or a subclass of a VersionToken.

Return type:

VersionToken

property minor#

Semantic versioning minor version.

Returns:

A VersionToken or a subclass of a VersionToken.

Return type:

VersionToken

property patch#

Semantic versioning patch version.

Returns:

A VersionToken or a subclass of a VersionToken.

Return type:

VersionToken

as_tuple()#

Convert to a tuple of strings.

Example

>>> print Version("1.2.12").as_tuple()
('1', '2', '12')
Return type:

tuple[str]

class rez.version.VersionRange#

Bases: _Comparable

A version range is a set of one or more contiguous ranges of versions. For example, “3.0 or greater, but less than 4” is a contiguous range that contains versions such as 3.0, 3.1.0, 3.99 etc. Version ranges behave something like sets. They can be intersected, added and subtracted, but can also be inverted. You can test to see if a Version is contained within a VersionRange.

A VersionRange 3 (for example) is the superset of any version 3[.X.X...]. The version 3 itself is also within this range, and is smaller than 3.0. Any version with common leading tokens, but with a larger token count, is the larger version of the two.

VersionRange objects have a flexible syntax that let you describe any combination of contiguous ranges, including inclusive and exclusive upper and lower bounds. This is best explained by example (those listed on the same line are equivalent):

  • 3: ‘superset’ syntax, contains 3, 3.0, 3.1.4 etc;

  • 2+, >=2: inclusive lower bound syntax, contains 2, 2.1, 5.0.0 etc;

  • >2: exclusive lower bound;

  • <5: exclusive upper bound;

  • <=5: inclusive upper bound;

  • ==2: a range that contains only the exact single version 2.

  • 1+<5, >=1<5: inclusive lower, exclusive upper. The most common form of a ‘bounded’ version range (ie, one with a lower and upper bound);

  • >1<5: exclusive lower, exclusive upper;

  • >1<=5: exclusive lower, inclusive upper;

  • 1+<=5, 1..5: inclusive lower, inclusive upper;

  • <=4,>2, <4,>2, <4,>=2: Reverse pip syntax (note comma)

To help with readability, bounded ranges can also have their bounds separated with a comma, eg >=2,<=6. The comma is purely cosmetic and is dropped in the string representation.

To describe more than one contiguous range, seperate ranges with the or | symbol. For example, the version range 4|6+ contains versions such as 4, 4.0, 4.3.1, 6, 6.1, 10.0.0, but does not contain any version 5[.X.X...X]. If you provide multiple ranges that overlap, they will be automatically optimised. For example, the version range 3+<6|4+<8 becomes 3+<8.

Note that the empty string version range represents the superset of all possible versions. This is called the “any” range. The empty version can also be used as an upper or lower bound, leading to some odd but perfectly valid version range syntax. For example, > is a valid range - read like >'', it means any version greater than the empty version.

__init__(range_str='', make_token=<class 'rez.version._version.AlphanumericVersionToken'>, invalid_bound_error=True)#
Parameters:
  • range_str (str) – Range string, such as “3”, “3+<4.5”, “2|6+”. The range will be optimised, so the string representation of this instance may not match range_str. For example, “3+<6|4+<8” == “3+<8”.

  • make_token (Type[VersionToken]) – Version token class to use.

  • invalid_bound_error (bool) – If True, raise an exception if an impossible range is given, such as ‘3+<2’.

is_any()#
Returns:

True if this is the “any” range, ie the empty string range that contains all versions.

Return type:

bool

lower_bounded()#
Returns:

True if the range has a lower bound (that is not the empty version).

Return type:

bool

upper_bounded()#
Returns:

True if the range has an upper bound.

Return type:

bool

bounded()#
Returns:

True if the range has a lower and upper bound.

Return type:

bool

issuperset(range)#
Returns:

True if the VersionRange is contained within this range.

Return type:

bool

issubset(range)#
Returns:

True if we are contained within the version range.

Return type:

bool

union(other)#

OR together version ranges.

Calculates the union of this range with one or more other ranges.

Parameters:

other (VersionRange or list[VersionRange]) – Version range object(s) to OR with.

Returns:

Range object representing the union.

Return type:

VersionRange

intersection(other)#

AND together version ranges.

Calculates the intersection of this range with one or more other ranges.

Parameters:

other (VersionRange or list[VersionRange]) – Version range object(s) to AND with.

Returns:

New VersionRange object representing the intersection, or None if no ranges intersect.

Return type:

Optional[VersionRange]

inverse()#

Calculate the inverse of the range.

Returns:

New VersionRange object representing the inverse of this range, or None if there is no inverse (ie, this range is the any range).

Return type:

Optional[VersionRange]

intersects(other)#

Determine if we intersect with another range.

Parameters:

other (VersionRange) – Version range object.

Returns:

True if the ranges intersect, False otherwise.

Return type:

bool

split()#

Split into separate contiguous ranges.

Returns:

A list of VersionRange objects. For example, the range 3|5+ will be split into ["3", "5+"].

Return type:

list[VersionRange]

classmethod as_span(lower_version=None, upper_version=None, lower_inclusive=True, upper_inclusive=True)#

Create a range from lower_version..upper_version.

Parameters:
  • lower_version (Version) – Version object representing lower bound of the range.

  • upper_version (Version) – Version object representing upper bound of the range.

  • lower_inclusive (bool) – Include lower_version into the span.

  • upper_inclusive (bool) – Include upper_inclusive into the span.

Return type:

VersionRange

classmethod from_version(version, op=None)#

Create a range from a version.

Parameters:
  • version (Version) – This is used as the upper/lower bound of the range.

  • op (Optional[str]) – Operation as a string. One of: gt, >, gte, >=, lt, <, lte, <=, eq, ==. If None, a bounded range will be created that contains the version superset.

Return type:

VersionRange

classmethod from_versions(versions)#

Create a range from a list of versions.

This method creates a range that contains only the given versions and no other. Typically the range looks like (for eg) ==3|==4|==5.1.

Parameters:

versions (list[Version]) – List of Version objects.

Return type:

VersionRange

to_versions()#

Returns exact version ranges as Version objects, or None if there are no exact version ranges present.

Return type:

Optional[list[Version]]

contains_version(version)#

Returns True if version is contained in this range.

Return type:

bool

iter_intersect_test(iterable, key=None, descending=False)#

Performs containment tests on a sorted list of versions.

This is more optimal than performing separate containment tests on a list of sorted versions.

Parameters:
  • iterable – An ordered sequence of versioned objects. If the list is not sorted by version, behaviour is undefined.

  • key (Callable[Any]) – Function that returns a Version given an object from iterable. If None, the identity function is used.

  • descending (bool) – Set to True if iterable is in descending version order.

Returns:

An iterator that returns (bool, object) tuples, where ‘object’ is the original object in iterable, and the bool indicates whether that version is contained in this range.

Return type:

Iterator[tuple[bool, Any]]

iter_intersecting(iterable, key=None, descending=False)#

Like :meth:iter_intersect_test`, but returns intersections only.

Returns:

An iterator that returns items from iterable that intersect.

iter_non_intersecting(iterable, key=None, descending=False)#

Like iter_intersect_test(), but returns non-intersections only.

Returns:

An iterator that returns items from iterable that don’t intersect.

span()#

Return a contiguous range that is a superset of this range.

Returns:

A range object representing the span of this range. For example, the span of 2+<4|6+<8 would be 2+<8.

Return type:

VersionRange

visit_versions(func)#

Visit each version in the range, and apply a function to each.

This is for advanced usage only.

If func returns a Version, this call will change the versions in place.

It is possible to change versions in a way that is nonsensical - for example setting an upper bound to a smaller version than the lower bound. Use at your own risk.

Parameters:

func (Callable[[Version], Optional[Version]]) – Takes a version, and is applied to every version in the range. If func returns a Version, it will replace the existing version, updating this VersionRange instance in place.

Return type:

None

class rez.version.Requirement#

Bases: _Common

Defines a requirement for an object. For example, foo-5+ means that you require any version of foo, version 5 or greater. An unversioned requirement can also be used (foo), this means you require any version of foo. You can drop the hyphen between object name and version range if the version range starts with a non-alphanumeric character - eg foo<2.

There are two different prefixes that can be applied to a requirement:

  • !: The conflict requirement. This means that you require this version range of an object NOT to be present. To conflict with all versions of an object, use “!foo”.

  • ~: This is known as a “weak reference”, and means, “I do not require this object, but if present, it must be within this range.” It is equivalent to the conflict of the inverse of the given version range.

There is one subtle case to be aware of. ~foo is a requirement that has no effect. It means “I do not require foo, but if foo is present, it can be any version.” This statement is still valid, but will produce a Requirement object with a None range.

Examples of valid requirement strings:

  • foo-1.0

  • foo@1.0

  • foo#1.0

  • foo-1+

  • foo-1+<4.3

  • foo<3

  • foo==1.0.1

sep_regex = re.compile('[-@#=<>]')#
__init__(s, invalid_bound_error=True)#
Parameters:
  • s (str) – Requirement string

  • invalid_bound_error (bool) – If True, raise VersionError if an impossible range is given, such as 3+<2.

classmethod construct(name, range=None)#

Create a requirement directly from an object name and VersionRange.

Parameters:
  • name (str) – Object name string.

  • range (Optional[VersionRange]) – If None, an unversioned requirement is created.

property name#

Name of the required object.

Return type:

str

property range#

Version range of the requirement.

Return type:

VersionRange

property conflict#

True if the requirement is a conflict requirement, eg “!foo”, “~foo-1”.

Return type:

bool

property weak#

True if the requirement is weak, eg “~foo”.

Note

Note that weak requirements are also conflict requirements, but not necessarily the other way around.

Return type:

bool

safe_str()#

Return a string representation that is safe for the current filesystem, and guarantees that no two different Requirement objects will encode to the same value.

Return type:

str

conflicts_with(other)#

Returns True if this requirement conflicts with another Requirement or VersionedObject.

Return type:

bool

merged(other)#

Merge two requirements.

Two requirements can be in conflict and if so, this function returns None. For example, requests for foo-4 and foo-6 are in conflict, since both cannot be satisfied with a single version of foo.

Some example successful requirements merges are:

  • foo-3+ and !foo-5+ == foo-3+<5

  • foo-1 and foo-1.5 == foo-1.5

  • !foo-2 and !foo-5 == !foo-2|5

Returns:

the merged result of two requirements.

Return type:

Requirement

class rez.version.RequirementList#

Bases: _Common

A list of requirements.

This class takes a Requirement list and reduces it to the equivalent optimal form, merging any requirements for common objects. Order of objects is retained.

__init__(requirements)#
Parameters:

requirements (list[Requirement]) – List of requirements.

property requirements#

Returns optimised list of requirements, or None if there are conflicts.

Return type:

list[Requirement]

property conflict#

Get the requirement conflict, if any.

Returns:

None if there is no conflict, otherwise a 2-tuple containing the conflicting requirement objects.

Return type:

Optional[tuple[Requirement]]

property names#

Set of names of requirements, not including conflict requirements.

Return type:

set[str]

property conflict_names#

Set of conflict requirement names.

Return type:

set[str]

get(name)#

Returns the requirement for the given object, or None.

Parameters:

name (str) – requirement to get.

Return type:

Requirement

class rez.version.VersionedObject#

Bases: _Common

Definition of a versioned object, eg foo-1.0.

foo is also a valid object definiton. When there is no version part, we are defining an unversioned object.

Note

Note that -, @ or # can be used as the seperator between object name and version, however this is purely cosmetic. foo-1 is the same as foo@1.

sep_regex_str = '[-@#]'#
sep_regex = re.compile('[-@#]')#
__init__(s)#
Parameters:

s (str) –

classmethod construct(name, version=None)#

Create a VersionedObject directly from an object name and version.

Parameters:
property name#

Name of the object.

Return type:

str

property version#

Version of the object.

Return type:

Version

as_exact_requirement()#

Get the versioned object, as an exact requirement string.

Returns:

Equivalent requirement string, eg maya==2016.1

Return type:

str

class rez.version.VersionToken#

Bases: _Comparable

Token within a version number.

A version token is that part of a version number that appears between a delimiter, typically . or -. For example, the version number 2.3.07b contains the tokens 2, 3 and 07b respectively.

Version tokens are only allowed to contain alphanumerics (any case) and underscores.

__init__(token)#
Parameters:

token (str) – Token string, eg “rc02”

less_than(other)#

Compare to another VersionToken.

Parameters:

other (VersionToken) – The VersionToken object to compare against.

Returns:

True if this token is less than other, False otherwise.

Return type:

bool

next()#

Returns the next largest token.

class rez.version.NumericToken#

Bases: VersionToken

Numeric version token.

Version token supporting numbers only. Padding is ignored.

__init__(token)#
Parameters:

token (str) – Token string, eg “rc02”

less_than(other)#

Compare to another VersionToken.

Parameters:

other (VersionToken) – The VersionToken object to compare against.

Returns:

True if this token is less than other, False otherwise.

Return type:

bool

next()#

Returns the next largest token.

class rez.version.AlphanumericVersionToken#

Bases: VersionToken

Alphanumeric version token.

These tokens compare as follows:

  • each token is split into alpha and numeric groups (subtokens);

  • the resulting subtoken list is compared.

  • alpha comparison is case-sensitive, numeric comparison is padding-sensitive.

Subtokens compare as follows:

  • alphas come before numbers;

  • alphas are compared alphabetically (_, then A-Z, then a-z);

  • numbers are compared numerically. If numbers are equivalent but zero-padded differently, they are then compared alphabetically. Thus 01 < 1.

Some example comparisons that equate to true:

  • 3 < 4

  • 01 < 1

  • beta < 1

  • alpha3 < alpha4

  • alpha < alpha3

  • gamma33 < 33gamma

numeric_regex = re.compile('[0-9]+')#
regex = re.compile('[a-zA-Z0-9_]+\\Z')#
__init__(token)#
Parameters:

token (str) – Token string, eg “rc02”

less_than(other)#

Compare to another VersionToken.

Parameters:

other (VersionToken) – The VersionToken object to compare against.

Returns:

True if this token is less than other, False otherwise.

Return type:

bool

next()#

Returns the next largest token.

rez.version.reverse_sort_key(comparable)#

Key that gives reverse sort order on versions and version ranges.

Example

>>> Version("1.0") < Version("2.0")
True
>>> reverse_sort_key(Version("1.0")) < reverse_sort_key(Version("2.0"))
False
Parameters:

comparable (Version or VersionRange) – Object to wrap.

Returns:

Wrapper object that reverses comparisons.

Return type:

_ReversedComparable

exception rez.version.ParseException#

Bases: Exception

__init__(*args, **kwargs)#
__new__(**kwargs)#
add_note()#

Exception.add_note(note) – add a note to the exception

args#
with_traceback()#

Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.

exception rez.version.VersionError#

Bases: Exception

__init__(*args, **kwargs)#
__new__(**kwargs)#
add_note()#

Exception.add_note(note) – add a note to the exception

args#
with_traceback()#

Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.