Skip to content

Commit c2ae21d

Browse files
committed
Add omittable_distros support for configs
1 parent 7d9f656 commit c2ae21d

File tree

14 files changed

+384
-5
lines changed

14 files changed

+384
-5
lines changed

README.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1286,6 +1286,32 @@ the `-r`/`--requirement` option.
12861286
Users can see the optional distros in the dump output with verbosity level of 1
12871287
or higher. `hab dump - -v`
12881288

1289+
### Omittable Distros
1290+
1291+
The `omittable_distros` key in [config](#config) definitions are used to specify distros
1292+
that are not required to use this hab configuration. This can be used to make it
1293+
so not all hosts need to have a dcc installed. For example a producer likely will
1294+
never need to open houdini but does need access to external tools. You would need
1295+
to install Houdini(or create a empty .hab.json distro) so hab doesn't raise an
1296+
`InvalidRequirementError` when it can't find Houdini.
1297+
1298+
```json5
1299+
"distros": [
1300+
"houdini20.0==20.0.688",
1301+
"SideFXLabs20.0==20.0.506",
1302+
"python_tools"
1303+
],
1304+
"omittable_distros": [
1305+
"houdini20.0",
1306+
"SideFXLabs20.0"
1307+
]
1308+
```
1309+
This will make it so `houdini20.0` and `SideFXLabs20.0` will be loaded if found,
1310+
but if not they will be ignored. `python_tools` will always need to be installed.
1311+
1312+
Note: `omittable_distros` is a list of distro names. It does not accept specifier
1313+
arguments like `==20.0.688`.
1314+
12891315
### Platform specific code
12901316

12911317
Hab works on windows, linux and osx(needs tested). To make it easier to handle

hab/parsers/config.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,8 +129,19 @@ def load(self, filename):
129129
data = super().load(filename)
130130
self._alias_mods = data.get("alias_mods", NotSet)
131131
self.inherits = data.get("inherits", NotSet)
132+
if self.omittable_distros is NotSet:
133+
self.omittable_distros = data.get("omittable_distros", NotSet)
132134
return data
133135

136+
@hab_property(verbosity=3, process_order=50)
137+
def omittable_distros(self):
138+
"""A collection of distro names that are ignored if required by distros."""
139+
return self.frozen_data.get("omittable_distros", NotSet)
140+
141+
@omittable_distros.setter
142+
def omittable_distros(self, value):
143+
self.frozen_data["omittable_distros"] = value
144+
134145
@hab_property(verbosity=1, group=0)
135146
def uri(self):
136147
# Mark uri as a HabProperty so it is included in _properties

hab/parsers/flat_config.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,9 @@ def versions(self):
223223
self._alias_mods = {}
224224
self.frozen_data["versions"] = versions
225225

226-
reqs = self.resolver.resolve_requirements(distros)
226+
reqs = self.resolver.resolve_requirements(
227+
distros, omittable=self.omittable_distros
228+
)
227229
for req in reqs.values():
228230
version = self.resolver.find_distro(req)
229231
versions.append(version)

hab/resolver.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -356,18 +356,23 @@ def resolve(self, uri, forced_requirements=None):
356356
if forced_requirements is not None:
357357
self.forced_requirements = current
358358

359-
def resolve_requirements(self, requirements):
359+
def resolve_requirements(self, requirements, omittable=None):
360360
"""Recursively solve the provided requirements into a final list of requirements.
361361
362362
Args:
363363
requirements (list): The requirements to resolve.
364+
omittable (list, optional): A list of distro names that are not required.
365+
If a suitable distro can not be found, normally an `InvalidRequirementError`
366+
is raised. If that distro name is in this list a warning is logged instead.
364367
365368
Raises:
366369
MaxRedirectError: Redirect limit reached, unable to resolve the requested
367370
requirements.
368371
"""
369372

370-
solver = Solver(requirements, self, forced=self.forced_requirements)
373+
solver = Solver(
374+
requirements, self, forced=self.forced_requirements, omittable=omittable
375+
)
371376
return solver.resolve()
372377

373378
def uri_validate(self, uri):

hab/solvers.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,18 @@ class Solver(object):
1818
forced (dict, optional): Forces this distro requirement replacing any resolved
1919
requirements. Using this may lead to configuring your environment
2020
incorrectly, use with caution.
21+
omittable (list, optional): A list of distro names that are not required.
22+
If a suitable distro can not be found, normally an `InvalidRequirementError`
23+
is raised. If that distro name is in this list a warning is logged instead.
2124
2225
Attributes:
2326
invalid (dict, optional): If a recursive requirement makes a already resolved
2427
version invalid, that version is added to this list as an exclusive exclude.
2528
"""
2629

27-
def __init__(self, requirements, resolver, forced=None):
30+
def __init__(self, requirements, resolver, forced=None, omittable=None):
2831
self.forced = forced if forced else {}
32+
self.omittable = omittable if omittable else []
2933
self.invalid = {}
3034
self.max_redirects = 2
3135
self.requirements = requirements
@@ -126,6 +130,10 @@ def _resolve(
126130
logger.warning(f"Forced Requirement: {req}")
127131
reported.add(name)
128132

133+
if name in self.omittable and name not in self.resolver.distros:
134+
logger.warning(f"Skipping missing omitted requirement: {req}")
135+
continue
136+
129137
# Update the requirement to match all current requirements
130138
req = self.append_requirement(resolved, req)
131139
if name in self.invalid:

tests/site_omit/README.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
This is a isolated site configuration specifically for testing omittable_distros.
2+
This allows for custom configuration of the default config without affecting other tests.
3+
4+
* The [default](configs/default.json) config defines `omittable_distros` that can be
5+
inherited by other distros. It lists two distros that do not exist for this site.
6+
* [omittable/defined](omittable/defined.json) defines `omittable_distros` replacing it with a modified
7+
list of distros to omit for this URI and its children.
8+
* [omittable/inherited](omittable/inherited.json) does not define the `omittable_distros` and inherits
9+
from its parents which aren't defined so it finally inherits the value defined
10+
in the `default` config.
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
{
2+
"name": "default",
3+
"context": [],
4+
"inherits": false,
5+
"distros": {
6+
"maya2020": [
7+
"the_dcc_plugin_a",
8+
"the_dcc_plugin_b",
9+
"the_dcc_plugin_c"
10+
],
11+
"houdini19.5": [
12+
"the_dcc_plugin_d"
13+
]
14+
},
15+
"omittable_distros": [
16+
"missing_dcc",
17+
"non-existent-distro",
18+
"the_dcc_plugin_b"
19+
]
20+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
{
2+
"name": "defined",
3+
"context": ["omittable"],
4+
"description": "This config defines omittable_distros and will ignore the default.",
5+
"inherits": true,
6+
"distros": {
7+
"maya2020": [
8+
"the_dcc_plugin_a",
9+
"the_dcc_plugin_b",
10+
"the_dcc_plugin_c"
11+
],
12+
"houdini19.5": [
13+
"the_dcc_plugin_d"
14+
],
15+
"missing_dcc": [
16+
"the_dcc_plugin_d",
17+
"non-existent-distro"
18+
]
19+
},
20+
"omittable_distros": [
21+
"houdini19.5",
22+
"missing_dcc",
23+
"non-existent-distro"
24+
]
25+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{
2+
"name": "inherited",
3+
"context": ["omittable"],
4+
"description": "This config doesn't define omittable_distros and will inherit from default.",
5+
"inherits": true,
6+
"distros": {
7+
"maya2020": [
8+
"the_dcc_plugin_a",
9+
"the_dcc_plugin_b"
10+
],
11+
"missing_dcc": [
12+
"the_dcc_plugin_d",
13+
"non-existent-distro"
14+
]
15+
}
16+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
{
2+
"name": "invalid",
3+
"context": ["omittable"],
4+
"description": "This config doesn't mark the distro missing_dcc as omittable_distros and will cause an InvalidRequirementError.",
5+
"inherits": true,
6+
"distros": {
7+
"maya2020": [
8+
"the_dcc_plugin_a",
9+
"the_dcc_plugin_b",
10+
"the_dcc_plugin_c"
11+
],
12+
"houdini19.5": [
13+
"the_dcc_plugin_d"
14+
],
15+
"missing_dcc": [
16+
"the_dcc_plugin_d",
17+
"non-existent-distro"
18+
]
19+
},
20+
"omittable_distros": [
21+
"houdini19.5",
22+
"non-existent-distro"
23+
]
24+
}

0 commit comments

Comments
 (0)