|
12 | 12 | import hashlib
|
13 | 13 | import pkg_resources # part of setuptools
|
14 | 14 | import functools
|
| 15 | +import string |
15 | 16 |
|
16 | 17 | import rdflib
|
17 | 18 | from typing import (Union, Any, AnyStr, cast, Callable, Dict, Sequence, Text,
|
|
31 | 32 | from .builder import adjustFileObjs, adjustDirObjs
|
32 | 33 | from .stdfsaccess import StdFsAccess
|
33 | 34 | from .pack import pack
|
| 35 | +from .utils import get_feature |
| 36 | +try: |
| 37 | + from galaxy.tools.deps.requirements import ToolRequirement |
| 38 | + from galaxy.tools import deps |
| 39 | +except ImportError: |
| 40 | + ToolRequirement = None # type: ignore |
| 41 | + deps = None |
34 | 42 |
|
35 | 43 | _logger = logging.getLogger("cwltool")
|
36 | 44 |
|
@@ -144,6 +152,15 @@ def arg_parser(): # type: () -> argparse.ArgumentParser
|
144 | 152 | exgroup.add_argument("--quiet", action="store_true", help="Only print warnings and errors.")
|
145 | 153 | exgroup.add_argument("--debug", action="store_true", help="Print even more logging")
|
146 | 154 |
|
| 155 | + # help="Dependency resolver configuration file describing how to adapt 'SoftwareRequirement' packages to current system." |
| 156 | + parser.add_argument("--beta-dependency-resolvers-configuration", default=None, help=argparse.SUPPRESS) |
| 157 | + # help="Defaut root directory used by dependency resolvers configuration." |
| 158 | + parser.add_argument("--beta-dependencies-directory", default=None, help=argparse.SUPPRESS) |
| 159 | + # help="Use biocontainers for tools without an explicitly annotated Docker container." |
| 160 | + parser.add_argument("--beta-use-biocontainers", default=None, help=argparse.SUPPRESS, action="store_true") |
| 161 | + # help="Short cut to use Conda to resolve 'SoftwareRequirement' packages." |
| 162 | + parser.add_argument("--beta-conda-dependencies", default=None, help=argparse.SUPPRESS, action="store_true") |
| 163 | + |
147 | 164 | parser.add_argument("--tool-help", action="store_true", help="Print command line help for tool")
|
148 | 165 |
|
149 | 166 | parser.add_argument("--relative-deps", choices=['primary', 'cwd'],
|
@@ -634,8 +651,20 @@ def main(argsl=None,
|
634 | 651 | stdout.write(json.dumps(processobj, indent=4))
|
635 | 652 | return 0
|
636 | 653 |
|
| 654 | + conf_file = getattr(args, "beta_dependency_resolvers_configuration", None) # Text |
| 655 | + use_conda_dependencies = getattr(args, "beta_conda_dependencies", None) # Text |
| 656 | + |
| 657 | + make_tool_kwds = vars(args) |
| 658 | + |
| 659 | + build_job_script = None # type: Callable[[Any, List[str]], Text] |
| 660 | + if conf_file or use_conda_dependencies: |
| 661 | + dependencies_configuration = DependenciesConfigruation(args) # type: DependenciesConfigruation |
| 662 | + make_tool_kwds["build_job_script"] = dependencies_configuration.build_job_script |
| 663 | + |
| 664 | + make_tool_kwds["find_default_container"] = functools.partial(find_default_container, args) |
| 665 | + |
637 | 666 | tool = make_tool(document_loader, avsc_names, metadata, uri,
|
638 |
| - makeTool, vars(args)) |
| 667 | + makeTool, make_tool_kwds) |
639 | 668 |
|
640 | 669 | if args.print_rdf:
|
641 | 670 | printrdf(tool, document_loader.ctx, args.rdf_serializer, stdout)
|
@@ -748,5 +777,100 @@ def locToPath(p):
|
748 | 777 | _logger.removeHandler(stderr_handler)
|
749 | 778 | _logger.addHandler(defaultStreamHandler)
|
750 | 779 |
|
| 780 | + |
| 781 | +COMMAND_WITH_DEPENDENCIES_TEMPLATE = string.Template("""#!/bin/bash |
| 782 | +$handle_dependencies |
| 783 | +python "run_job.py" "job.json" |
| 784 | +""") |
| 785 | + |
| 786 | + |
| 787 | +def find_default_container(args, builder): |
| 788 | + if args.default_container: |
| 789 | + return args.default_container |
| 790 | + elif args.beta_use_biocontainers: |
| 791 | + try: |
| 792 | + from galaxy.tools.deps.containers import ContainerRegistry, AppInfo, ToolInfo, DOCKER_CONTAINER_TYPE |
| 793 | + except ImportError: |
| 794 | + raise Exception("galaxy-lib not found") |
| 795 | + |
| 796 | + app_info = AppInfo( |
| 797 | + involucro_auto_init=True, |
| 798 | + enable_beta_mulled_containers=True, |
| 799 | + ) # type: AppInfo |
| 800 | + container_registry = ContainerRegistry(app_info) # type: ContainerRegistry |
| 801 | + requirements = _get_dependencies(builder) |
| 802 | + tool_info = ToolInfo(requirements=requirements) # type: ToolInfo |
| 803 | + container_description = container_registry.find_best_container_description([DOCKER_CONTAINER_TYPE], tool_info) |
| 804 | + print container_description |
| 805 | + if container_description: |
| 806 | + return container_description.identifier |
| 807 | + |
| 808 | + return None |
| 809 | + |
| 810 | + |
| 811 | +class DependenciesConfigruation(object): |
| 812 | + |
| 813 | + def __init__(self, args): |
| 814 | + # type: (argparse.Namespace) -> None |
| 815 | + conf_file = getattr(args, "beta_dependency_resolvers_configuration", None) |
| 816 | + tool_dependency_dir = getattr(args, "beta_dependencies_directory", None) |
| 817 | + conda_dependencies = getattr(args, "beta_conda_dependencies", None) |
| 818 | + if conf_file is not None and os.path.exists(conf_file): |
| 819 | + self.use_tool_dependencies = True |
| 820 | + if not tool_dependency_dir: |
| 821 | + tool_dependency_dir = os.path.abspath(os.path.dirname(conf_file)) |
| 822 | + self.tool_dependency_dir = tool_dependency_dir |
| 823 | + self.dependency_resolvers_config_file = conf_file |
| 824 | + elif conda_dependencies: |
| 825 | + if not tool_dependency_dir: |
| 826 | + tool_dependency_dir = os.path.abspath("./cwltool_deps") |
| 827 | + self.tool_dependency_dir = tool_dependency_dir |
| 828 | + self.use_tool_dependencies = True |
| 829 | + self.dependency_resolvers_config_file = None |
| 830 | + else: |
| 831 | + self.use_tool_dependencies = False |
| 832 | + |
| 833 | + @property |
| 834 | + def config_dict(self): |
| 835 | + return { |
| 836 | + 'conda_auto_install': True, |
| 837 | + 'conda_auto_init': True, |
| 838 | + } |
| 839 | + |
| 840 | + def build_job_script(self, builder, command): |
| 841 | + # type: (Any, List[str]) -> Text |
| 842 | + if deps is None: |
| 843 | + raise Exception("galaxy-lib not found") |
| 844 | + tool_dependency_manager = deps.build_dependency_manager(self) # type: deps.DependencyManager |
| 845 | + dependencies = _get_dependencies(builder) |
| 846 | + handle_dependencies = "" # str |
| 847 | + if dependencies: |
| 848 | + handle_dependencies = "\n".join(tool_dependency_manager.dependency_shell_commands(dependencies, job_directory=builder.tmpdir)) |
| 849 | + |
| 850 | + template_kwds = dict(handle_dependencies=handle_dependencies) # type: Dict[str, str] |
| 851 | + job_script = COMMAND_WITH_DEPENDENCIES_TEMPLATE.substitute(template_kwds) |
| 852 | + return job_script |
| 853 | + |
| 854 | + |
| 855 | +def _get_dependencies(builder): |
| 856 | + # type: (Any) -> List[ToolRequirement] |
| 857 | + (software_requirement, _) = get_feature(builder, "SoftwareRequirement") |
| 858 | + dependencies = [] # type: List[ToolRequirement] |
| 859 | + if software_requirement and software_requirement.get("packages"): |
| 860 | + packages = software_requirement.get("packages") |
| 861 | + for package in packages: |
| 862 | + version = package.get("version", None) |
| 863 | + if isinstance(version, list): |
| 864 | + if version: |
| 865 | + version = version[0] |
| 866 | + else: |
| 867 | + version = None |
| 868 | + dependencies.append(ToolRequirement.from_dict(dict( |
| 869 | + name=package["package"].split("#")[-1], |
| 870 | + version=version, |
| 871 | + type="package", |
| 872 | + ))) |
| 873 | + return dependencies |
| 874 | + |
751 | 875 | if __name__ == "__main__":
|
752 | 876 | sys.exit(main(sys.argv[1:]))
|
0 commit comments