Skip to content

Commit 7b6e4fa

Browse files
Add package orderers documentation (#1737)
Signed-off-by: Bryce Gattis <[email protected]> Signed-off-by: Jean-Christophe Morin <[email protected]> Co-authored-by: Jean-Christophe Morin <[email protected]>
1 parent 2c5ef7a commit 7b6e4fa

File tree

3 files changed

+244
-82
lines changed

3 files changed

+244
-82
lines changed

docs/source/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ Welcome to rez's documentation!
3232
caching
3333
pip
3434
plugins
35+
package_orderers
3536

3637
.. toctree::
3738
:maxdepth: 2

docs/source/package_orderers.rst

Lines changed: 243 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,243 @@
1+
================
2+
Package Orderers
3+
================
4+
5+
Rez's default :ref:`version <versions-concept>` resolution algorithm will always sort by the latest alphanumeric
6+
version. However, package orderers allow you to customize this functionality globally,
7+
or at a per package level.
8+
9+
This can be used to ensure that specific version have priority over others.
10+
Higher versions can still be accessed if explicitly requested.
11+
12+
Configuration
13+
=============
14+
15+
Package orderers can be configured in the ``rezconfig.py`` via the :data:`package_orderers` setting.
16+
17+
Types
18+
=====
19+
20+
These are the available built-in orderers.
21+
22+
sorted
23+
------
24+
25+
This is the default orderer that sorts based on the package's :attr:`version` attribute.
26+
27+
You can optionally explicitly request this orderer like this:
28+
29+
.. code-block:: python
30+
31+
package_orderers = [
32+
{
33+
"type": "sorted", # Required
34+
"descending": True, # Required
35+
"packages": ["python"] # Optional, if not supplied, orderer applies to all packages
36+
}
37+
]
38+
39+
version_split
40+
-------------
41+
42+
This orderer orders all package versions less than or equal to a given version first, then sorts by the default
43+
sorted order.
44+
45+
For example, given the versions [5, 4, 3, 2, 1], an orderer initialized with version=3 would give the
46+
order [3, 2, 1, 5, 4].
47+
48+
.. code-block:: python
49+
50+
package_orderers = [
51+
{
52+
"type": "version_split",
53+
"first_version": "2.7.16"
54+
}
55+
]
56+
57+
58+
A common use case is to ease migration from python-2 to python-3:
59+
60+
.. code-block:: python
61+
62+
package_orderers = [
63+
{
64+
"type": "per_family",
65+
"orderers": [
66+
{
67+
"packages": ["python"],
68+
"type": "version_split",
69+
"first_version": "2.7.16"
70+
}
71+
]
72+
}
73+
]
74+
75+
This will ensure that for the "python" package, versions equals or lower than "2.7.16" will have priority.
76+
Considering the following versions: "2.7.4", "2.7.16", "3.7.4":
77+
78+
.. table::
79+
:align: left
80+
81+
==================== =============
82+
Example Result
83+
==================== =============
84+
rez-env python python-2.7.16
85+
rez-env python-3 python-3.7.4
86+
==================== =============
87+
88+
Package orderers will also apply to variants of packages.
89+
Consider a package "pipeline-1.0" which has the following variants:
90+
``[["python-2.7.4", "python-2.7.16", "python-3.7.4"]]``
91+
92+
.. table::
93+
:align: left
94+
95+
============================= ==========================
96+
Example Result
97+
============================= ==========================
98+
rez-env pipeline pipeline-1.0 python-2.7.16
99+
rez-env pipeline python-3 pipeline-1.0 python-3.7.4
100+
============================= ==========================
101+
102+
103+
per_family
104+
----------
105+
106+
This orderer allows you to define different orderers to different package families.
107+
108+
.. code-block:: python
109+
110+
package_orderers = [
111+
{
112+
"type": "per_family",
113+
"orderers": [
114+
{
115+
"packages": ["python"],
116+
"type": "version_split",
117+
"first_version": "2.7.16"
118+
}
119+
]
120+
}
121+
]
122+
123+
124+
soft_timestamp
125+
--------------
126+
127+
This orderer takes in a given time ``T`` and returns packages released before ``T``, in descending order, followed by
128+
those released after.
129+
130+
If ``rank`` is non-zero, version changes at that rank and above are allowed over the timestamp.
131+
132+
A timestamp can be generated with python:
133+
134+
.. code-block:: text
135+
136+
$ python -c "import datetime, time; print(int(time.mktime(datetime.date(2019, 9, 9).timetuple())))"
137+
1568001600
138+
139+
The following example will prefer package released before 2019-09-09.
140+
141+
.. code-block:: python
142+
143+
package_orderers = [
144+
{
145+
"type": "soft_timestamp",
146+
"timestamp": 1568001600, # 2019-09-09
147+
"rank": 3
148+
}
149+
]
150+
151+
The rank can be used to allow some versions released after the timestamp to still be considered.
152+
When using semantic versionnng, a value of 3 is the most common.
153+
This will let version with a different patch number to be accepted.
154+
155+
Considering a package "foo" with the following versions:
156+
157+
- "1.0.0" was released at 2019-09-07
158+
- "2.0.0" was released at 2019-09-08
159+
- "2.0.1" was released at 2019-09-10
160+
- "2.1.0" was released at 2019-09-11
161+
- "3.0.0" was released at 2019-09-12
162+
163+
the following talbes shows the effect of rank:
164+
165+
.. table::
166+
:align: left
167+
168+
=========== ========== ==== =========
169+
Example Timestamp Rank Result
170+
=========== ========== ==== =========
171+
rez-env foo 2019-09-09 0 foo-2.0.0
172+
rez-env foo 2019-09-09 3 foo-2.0.1
173+
rez-env foo 2019-09-09 2 foo-2.1.0
174+
rez-env foo 2019-09-09 1 foo-3.0.0
175+
=========== ========== ==== =========
176+
177+
178+
no_order
179+
--------
180+
181+
An orderer that does not change the order - a no op.
182+
183+
This orderer is useful in cases where you want to apply some default orderer
184+
to a set of packages, but may want to explicitly NOT reorder a particular
185+
package. You would use a :class:`rez.package_order.NullPackageOrder` in a :class:`rez.package_order.PerFamilyOrder` to do this.
186+
187+
188+
Custom orderers
189+
===============
190+
191+
It is possible to create custom orderers using the API. This can be achieved
192+
by subclassing :class:`rez.package_order.PackageOrder` and implementing some mandatory
193+
methods. Once that's done, you need to register the orderer using :func:`rez.package_order.register_orderer`.
194+
195+
.. note::
196+
197+
Implementing a custom orderer should only be done if absolutely necessary.
198+
It could make your environment behave in very special ways and more importantly
199+
in non expected ways from a user perspective. It can also make it harder to share
200+
the set of affected packages to others.
201+
202+
203+
.. code-block:: python
204+
:caption: rezconfig.py
205+
206+
from rez.version import Version
207+
from rez.package_order import PackageOrder, register_orderer
208+
209+
210+
class MyOrderer(PackageOrder):
211+
name = "my_orderer"
212+
213+
def __init__(self, custom_arg: str, **kwargs):
214+
super().__init__(self, **kwargs)
215+
self.custom_arg = custom_arg
216+
217+
def sort_key_implementation(self, package_name: str, version: Version):
218+
pass
219+
220+
def __str__(self):
221+
pass
222+
223+
def __eq__(self, other):
224+
pass
225+
226+
def to_pod(self, other):
227+
pass
228+
229+
@classmethod
230+
def from_pod(cls, data):
231+
pass
232+
233+
234+
register_orderer(MyOrderer)
235+
236+
package_orderers = [
237+
{
238+
"type": "my_orderer",
239+
"custom_arg": "value here"
240+
}
241+
]
242+
243+
For more details, please see :gh-rez:`src/rez/package_order.py`.

src/rez/rezconfig.py

Lines changed: 0 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -430,88 +430,6 @@
430430
# This will affect the order of version resolution.
431431
# This can be used to ensure that specific version have priority over others.
432432
# Higher versions can still be accessed if explicitly requested.
433-
#
434-
# A common use case is to ease migration from python-2 to python-3:
435-
#
436-
# .. code-block:: python
437-
#
438-
# package_orderers = [
439-
# {
440-
# "type": "per_family",
441-
# "orderers": [
442-
# {
443-
# "packages": ["python"],
444-
# "type": "version_split",
445-
# "first_version": "2.7.16"
446-
# }
447-
# ]
448-
# }
449-
# ]
450-
#
451-
# This will ensure that for the "python" package, versions equals or lower than "2.7.16" will have priority.
452-
# Considering the following versions: "2.7.4", "2.7.16", "3.7.4":
453-
#
454-
# ==================== =============
455-
# Example Result
456-
# ==================== =============
457-
# rez-env python python-2.7.16
458-
# rez-env python-3 python-3.7.4
459-
# ==================== =============
460-
#
461-
#
462-
# Package orderers will also apply to variants of packages.
463-
# Consider a package "pipeline-1.0" which has the following variants:
464-
# ``[["python-2.7.4", "python-2.7.16", "python-3.7.4"]]``
465-
#
466-
# ============================= ==========================
467-
# Example Result
468-
# ============================= ==========================
469-
# rez-env pipeline pipeline-1.0 python-2.7.16
470-
# rez-env pipeline python-3 pipeline-1.0 python-3.7.4
471-
# ============================= ==========================
472-
#
473-
#
474-
# Here's another example, using another orderer: "soft_timestamp".
475-
# This orderer will prefer packages released before a provided timestamp.
476-
# The following example will prefer package released before 2019-09-09.
477-
#
478-
# .. code-block:: python
479-
#
480-
# package_orderers = [
481-
# {
482-
# "type": "soft_timestamp",
483-
# "timestamp": 1568001600, # 2019-09-09
484-
# "rank": 3
485-
# }
486-
# ]
487-
#
488-
# A timestamp can be generated with python:
489-
#
490-
# .. code-block:: text
491-
#
492-
# $ python -c "import datetime, time; print(int(time.mktime(datetime.date(2019, 9, 9).timetuple())))"
493-
# 1568001600
494-
#
495-
# The rank can be used to allow some versions released after the timestamp to still be considered.
496-
# When using semantic versionnng, a value of 3 is the most common.
497-
# This will let version with a different patch number to be accepted.
498-
#
499-
# Considering a package "foo" with the following versions:
500-
#
501-
# - "1.0.0" was released at 2019-09-07
502-
# - "2.0.0" was released at 2019-09-08
503-
# - "2.0.1" was released at 2019-09-10
504-
# - "2.1.0" was released at 2019-09-11
505-
# - "3.0.0" was released at 2019-09-12
506-
#
507-
# =========== ========== ==== =========
508-
# Example Timestamp Rank Result
509-
# =========== ========== ==== =========
510-
# rez-env foo 2019-09-09 0 foo-2.0.0
511-
# rez-env foo 2019-09-09 3 foo-2.0.1
512-
# rez-env foo 2019-09-09 2 foo-2.1.0
513-
# rez-env foo 2019-09-09 1 foo-3.0.0
514-
# =========== ========== ==== =========
515433
package_orderers = None
516434

517435
# If True, unversioned packages are allowed. Solve times are slightly better if

0 commit comments

Comments
 (0)