Allow combinatorial projections in views#9679
Conversation
210de14 to
030f312
Compare
0a4f958 to
c612d4f
Compare
scheibelp
left a comment
There was a problem hiding this comment.
Overall, I think the primary change that needs to be made here is that there are members of YamlFilesystemView which should no longer be accessible given the fact that the view no longer has a single root (namely .root and .extensions_layout). Those should be replaced with functions that take a Spec as a parameter.
Let me know if this is unclear or seems off-target.
| try: | ||
| with open(filename, "r") as f: | ||
| return spack.spec.Spec.from_yaml(f) | ||
| except IOError: |
There was a problem hiding this comment.
IOError includes errors like "file not found" as well as permission errors. This appears to have been consolidated from existing logic so that's not necessarily your choice, but IMO it's worthwhile to get more specific about the error.
It may also be worth creating a more generic utility function that, given a file name, opens it and applies a function to the result.
There was a problem hiding this comment.
You're correct that this was already extant code, but I disagree that it's a misuse of IOError. We want a no-exception method for getting specs from files, so that the calling code can determine whether not getting a spec is an error or not.
There was a problem hiding this comment.
I actually agree with Peter that this should be more specific -- why does it have to squash the IOError? Doing that means the calling code knows a lot less about what happened.
In this case, there is actually likely to be something wrong if from_yaml() fails, because the calling code got the name from os.listdir(), so you know the file should really exist. If it is corrupt or unreadable, the user likely wants to know, at least with a warning.
Note that from_yaml() can take a filename, so you don't need the open call here. would just inline this function and have the calling code determine what is worth catching...
| """ | ||
| raise NotImplementedError | ||
|
|
||
| def get_projection_for_spec(self, spec): |
There was a problem hiding this comment.
I think this is fine but that any user of YamlFilesystemView that originally wanted to access view.root would now want to use this function. Therefore I think view.root should be replaced with view._root (i.e. that is now a private and internal detail of the view). Currently I don't think all build system implementations (e.g. Python and Aspell) are consistent with the other changes in this PR but making this change would help with that.
There was a problem hiding this comment.
It seems that the check in the AspellDictPackage class is still a correct use of the view root to check whether the view is being used for an extension or externally.
I've updated the PythonPackage build system to use the new syntax to get its location within the view. Since python packages are always extensions and extensions are linked into combinatorial views using non-combinatorial sub-views, it doesn't actually make a difference, but I think relying on that would be too fragile.
There was a problem hiding this comment.
I want to eliminate the possibility of getting it wrong by forcing the usage that is always correct. Basically I don't want future developers to have to reason like this (although I agree with your points).
There was a problem hiding this comment.
I'm still not convinced that root shouldn't be something you're allowed to ask a view. But I don't think removing it will harm any of the current cases, so I'll make the change and we can always change it back later if necessary.
|
@scheibelp comments addressed. |
…xed existing tests
…r normal projection
…in projections.yaml
a34132f to
978f2f4
Compare
|
@scheibelp ping |
scheibelp
left a comment
There was a problem hiding this comment.
I have a few minor requests related to clarity/documentation.
I will continue reviewing this tomorrow morning.
|
@scheibelp comments addressed |
2236e98 to
7ad8e1f
Compare
8aebf6a to
eff30d9
Compare
scheibelp
left a comment
There was a problem hiding this comment.
I have a few requests/questions about the tests.
| old_path = spack.repo.path | ||
| repo_dirs = [spack.paths.packages_path, spack.paths.mock_packages_path] | ||
| path = RepoPath(*repo_dirs) | ||
| sys.meta_path.append(path) |
There was a problem hiding this comment.
Could this use repo.swap. Although there is minimal duplication, it's useful to minimize the number of unique manipulations of sys.meta_path.
There was a problem hiding this comment.
I'm a little bit worried that repo.swap doesn't restore sys.meta_path properly, but that's a separate scope of work than this PR and this PR should use the logic there. We can fix it separately if there's an issue.
If the path added by repo.swap is already in sys.meta_path, won't repo.swap accidentally change it from its current location to the end of sys.meta_path (because list.remove removes the first instance in the list, not the last)? If so, we can fix this by either caching sys.meta_path the same way we cache repo.path or by reversing the list, removing the item, and reversing it again.
There was a problem hiding this comment.
If the path added by repo.swap is already in sys.meta_path, won't repo.swap accidentally change it from its current location to the end of sys.meta_path (because list.remove removes the first instance in the list, not the last)?
I think you're right. Generally I think this just hasn't happened yet - the same Repo/RepoPath is not added multiple times. I think it's worth sorting out in a separate PR. Generally I assume that it should be disallowed to add it multiple times (raise an exception).
There was a problem hiding this comment.
Testing could be a reason to add the same one multiple times, but if we need that there's other ways to ensure we don't mess up the ordering.
|
Thanks! |
Allow views to specify projections more complicated than merging every package into a shared prefix. This will allow sites to configure a view for the way they want to present packages to their users.
From the new documentation for views:
The default projection into a view is to link every package into the
root of the view. This can be changed through the
projections.yamlfile in the view. The projection configuration file for a view located
at
/my/viewis stored in/my/view/.spack/projections.yaml.When creating a view, the projection configuration file can also be
specified from the command line using the
--projection-fileoptionto the
spack viewcommand.The projections configuration file is a mapping of partial specs to
spec format strings, as shown in the example below.
The entries in the projections configuration file must all be either
specs or the keyword
all. ~~For each spec, the projection used willbe the first non-
allentry that the spec satisfies, or the projection for theallentry if one exists and the spec satisfies no other entriesand the keyword. Given the example above, any spec satisfyingallissatisfied by any spec
[email protected]will be linked into/my/view/zlib-1.2.8/, any specsatisfying
[email protected]+mpi %[email protected] ^[email protected]will be linkedinto
/my/view/hdf5-1.8.10/mvapich2-2.2-gcc-4.9.3, and any specsatisfying
[email protected]~mpi %[email protected]will be linked into/my/view/hdf5-1.8.10/gcc-4.9.3.If the keyword
alldoes not appear in the projectionsconfiguration file, any spec that does not satisfy any entry in the
file will be linked into the root of the view as in a single-prefix
view.
Any entries that appear below the keywordallin theprojections configuration file will not be used, as all specs will use
the projection under
allbefore reaching those entries.