datalad_container/containers_list.py
"""List known container environments of a dataset"""
__docformat__ = 'restructuredtext'
import logging
import os.path as op
import datalad.support.ansi_colors as ac
from datalad.coreapi import subdatasets
from datalad.distribution.dataset import (
Dataset,
EnsureDataset,
datasetmethod,
require_dataset,
)
from datalad.interface.base import (
Interface,
build_doc,
eval_results,
)
from datalad.interface.common_opts import recursion_flag
from datalad.interface.results import get_status_dict
from datalad.interface.utils import default_result_renderer
from datalad.support.constraints import EnsureNone
from datalad.support.param import Parameter
from datalad.ui import ui
from datalad_container.utils import get_container_configuration
lgr = logging.getLogger("datalad.containers.containers_list")
@build_doc
# all commands must be derived from Interface
class ContainersList(Interface):
# first docstring line is used a short description in the cmdline help
# the rest is put in the verbose help and manpage
"""List containers known to a dataset
"""
result_renderer = 'tailored'
# parameters of the command, must be exhaustive
_params_ = dict(
dataset=Parameter(
args=("-d", "--dataset"),
doc="""specify the dataset to query. If no dataset is given, an
attempt is made to identify the dataset based on the current
working directory""",
constraints=EnsureDataset() | EnsureNone()),
contains=Parameter(
args=('--contains',),
metavar='PATH',
action='append',
doc="""when operating recursively, restrict the reported containers
to those from subdatasets that contain the given path (i.e. the
subdatasets that are reported by :command:`datalad subdatasets
--contains=PATH`). Top-level containers are always reported."""),
recursive=recursion_flag,
)
@staticmethod
@datasetmethod(name='containers_list')
@eval_results
def __call__(dataset=None, recursive=False, contains=None):
ds = require_dataset(dataset, check_installed=True,
purpose='list containers')
refds = ds.path
if recursive:
for sub in ds.subdatasets(
contains=contains,
on_failure='ignore',
return_type='generator',
result_renderer='disabled'):
subds = Dataset(sub['path'])
if subds.is_installed():
for c in subds.containers_list(recursive=recursive,
return_type='generator',
on_failure='ignore',
result_filter=None,
result_renderer=None,
result_xfm=None):
c['name'] = sub['gitmodule_name'] + '/' + c['name']
c['refds'] = refds
yield c
# all info is in the dataset config!
containers = get_container_configuration(ds)
for k, v in containers.items():
if 'image' not in v:
# there is no container location configured
continue
res = get_status_dict(
status='ok',
action='containers',
name=k,
type='file',
path=op.join(ds.path, v.pop('image')),
refds=refds,
parentds=ds.path,
# TODO
#state='absent' if ... else 'present'
**v)
yield res
@staticmethod
def custom_result_renderer(res, **kwargs):
if res["action"] != "containers":
default_result_renderer(res)
else:
ui.message(
"{name} -> {path}"
.format(name=ac.color_word(res["name"], ac.MAGENTA),
path=op.relpath(res["path"], res["refds"])))