-
Notifications
You must be signed in to change notification settings - Fork 1
Use AUGUR_SEARCH_PATHS in resolve_config_path() #78
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -5,23 +5,20 @@ workflow configs. | |
| import os | ||
| import sys | ||
| import yaml | ||
| from augur.config import resolve_filepath | ||
| from collections.abc import Callable | ||
| from typing import Optional | ||
| from textwrap import dedent, indent | ||
|
|
||
|
|
||
| # Set search paths for Augur | ||
| # Set search paths | ||
| if "AUGUR_SEARCH_PATHS" in os.environ: | ||
| print(dedent(f"""\ | ||
| Using existing search paths in AUGUR_SEARCH_PATHS: | ||
|
|
||
| {os.environ["AUGUR_SEARCH_PATHS"]!r} | ||
| """), file=sys.stderr) | ||
| else: | ||
| # Note that this differs from the search paths used in | ||
| # resolve_config_path(). | ||
| # This is the preferred default moving forwards, and the plan is to | ||
| # eventually update resolve_config_path() to use AUGUR_SEARCH_PATHS. | ||
| search_paths = [ | ||
| # User analysis directory | ||
| Path.cwd(), | ||
|
|
@@ -44,29 +41,37 @@ else: | |
| repo_root, | ||
| ]) | ||
|
|
||
| search_paths = [path.resolve() for path in search_paths if path.is_dir()] | ||
| seen = set() | ||
| normalized_search_paths = [] | ||
| for path in search_paths: | ||
| # Skip paths that are not directories | ||
| if not path.is_dir(): | ||
| continue | ||
|
|
||
| os.environ["AUGUR_SEARCH_PATHS"] = ":".join(map(str, search_paths)) | ||
| # Resolve to absolute paths | ||
| resolved = path.resolve() | ||
|
|
||
| # Skip duplicate paths (e.g. often the CWD == workflow.basedir) | ||
| if resolved in seen: | ||
| continue | ||
|
|
||
| seen.add(resolved) | ||
| normalized_search_paths.append(resolved) | ||
|
|
||
| os.environ["AUGUR_SEARCH_PATHS"] = ":".join(map(str, normalized_search_paths)) | ||
|
|
||
|
|
||
| class InvalidConfigError(Exception): | ||
| pass | ||
|
|
||
|
|
||
| def resolve_config_path(path: str, defaults_dir: Optional[str] = None) -> Callable: | ||
| def resolve_config_path(path: str) -> Callable: | ||
| """ | ||
| Resolve a relative *path* given in a configuration value. Will always try to | ||
| resolve *path* after expanding wildcards with Snakemake's `expand` functionality. | ||
|
|
||
| Returns the path for the first existing file, checked in the following order: | ||
| 1. relative to the analysis directory or workdir, usually given by ``--directory`` (``-d``) | ||
| 2. relative to *defaults_dir* if it's provided | ||
| 3. relative to the workflow's ``defaults/`` directory if *defaults_dir* is _not_ provided | ||
|
|
||
| This behaviour allows a default configuration value to point to a default | ||
| auxiliary file while also letting the file used be overridden either by | ||
| setting an alternate file path in the configuration or by creating a file | ||
| with the conventional name in the workflow's analysis directory. | ||
| Returns the path for the first existing file found relative to directories | ||
| defined by the AUGUR_SEARCH_PATHS environment variable. | ||
|
Comment on lines
+73
to
+74
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Reviewing this prompted me to catch up on how Small thing to note here that we should be wary to not use |
||
| """ | ||
| global workflow | ||
|
|
||
|
|
@@ -88,31 +93,26 @@ def resolve_config_path(path: str, defaults_dir: Optional[str] = None) -> Callab | |
| and that the rule actually uses the wildcard name. | ||
| """.lstrip("\n").rstrip()).format(path=repr(path), available_wildcards=available_wildcards), " " * 4)) | ||
|
|
||
| if os.path.exists(expanded_path): | ||
| return expanded_path | ||
|
|
||
| if defaults_dir: | ||
| defaults_path = os.path.join(defaults_dir, expanded_path) | ||
| else: | ||
| # Special-case defaults/… for backwards compatibility with older | ||
| # configs. We could achieve the same behaviour with a symlink | ||
| # (defaults/defaults → .) but that seems less clear. | ||
| if path.startswith("defaults/"): | ||
| defaults_path = os.path.join(workflow.basedir, expanded_path) | ||
| else: | ||
| defaults_path = os.path.join(workflow.basedir, "defaults", expanded_path) | ||
|
|
||
| if os.path.exists(defaults_path): | ||
| return defaults_path | ||
|
|
||
| raise InvalidConfigError(indent(dedent(f"""\ | ||
| Unable to resolve the config-provided path {path!r}, | ||
| expanded to {expanded_path!r} after filling in wildcards. | ||
| The workflow does not include the default file {defaults_path!r}. | ||
|
|
||
| Hint: Check that the file {expanded_path!r} exists in your analysis | ||
| directory or remove the config param to use the workflow defaults. | ||
| """), " " * 4)) | ||
| search_paths = [Path(p) for p in os.environ["AUGUR_SEARCH_PATHS"].split(":")] | ||
| try: | ||
| return str(resolve_filepath(Path(expanded_path), search_paths)) | ||
| except Exception as error: | ||
| raise InvalidConfigError( | ||
| indent( | ||
| dedent(f""" | ||
| Unable to resolve the config-provided path {path!r}, | ||
| expanded to {expanded_path!r} after filling in wildcards. | ||
|
|
||
| """) | ||
| + str(error) | ||
| + dedent(f""" | ||
|
|
||
| Hint: Check that the file {expanded_path!r} exists in your analysis | ||
| directory or remove the config param to use the workflow defaults. | ||
| """), | ||
| " " * 4, | ||
| ) | ||
| ) | ||
|
|
||
| return _resolve_config_path | ||
|
|
||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.