Beispiel #1
0
def resolve_path(path, ds=None):
    """Resolve a path specification (against a Dataset location)

    Any explicit path (absolute or relative) is returned as an absolute path.
    In case of an explicit relative path, the current working directory is
    used as a reference. Any non-explicit relative path is resolved against
    as dataset location, i.e. considered relative to the location of the
    dataset. If no dataset is provided, the current working directory is
    used.

    Returns
    -------
    Absolute path
    """
    # first make sure it's actually a valid path:
    from datalad.support.network import PathRI
    if not isinstance(RI(path), PathRI):
        raise ValueError("%s is not a valid path" % path)

    path = expandpath(path, force_absolute=False)
    if is_explicit_path(path):
        # normalize path consistently between two (explicit and implicit) cases
        return dlabspath(path, norm=True)

    # no dataset given, use CWD as reference
    # note: abspath would disregard symlink in CWD
    top_path = getpwd() \
        if ds is None else ds.path if isinstance(ds, Dataset) else ds
    return normpath(opj(top_path, path))
Beispiel #2
0
def resolve_path(path, ds=None):
    """Resolve a path specification (against a Dataset location)

    Any explicit path (absolute or relative) is returned as an absolute path.
    In case of an explicit relative path, the current working directory is
    used as a reference. Any non-explicit relative path is resolved against
    as dataset location, i.e. considered relative to the location of the
    dataset. If no dataset is provided, the current working directory is
    used.

    Returns
    -------
    Absolute path
    """
    # first make sure it's actually a valid path:
    from datalad.support.network import PathRI
    if not isinstance(RI(path), PathRI):
        raise ValueError("%s is not a valid path" % path)

    path = expandpath(path, force_absolute=False)
    if is_explicit_path(path):
        # normalize path consistently between two (explicit and implicit) cases
        return dlabspath(path, norm=True)

    # no dataset given, use CWD as reference
    # note: abspath would disregard symlink in CWD
    top_path = getpwd() \
        if ds is None else ds.path if isinstance(ds, Dataset) else ds
    return normpath(opj(top_path, path))
Beispiel #3
0
    def get_containing_subdataset(self, path, recursion_limit=None):
        """Get the (sub-)dataset containing `path`

        Note: The "mount point" of a subdataset is classified as belonging to
        that respective subdataset.

        WARNING: This function is rather expensive, because it queries for all
        subdatasets recursively, and repeatedly -- which can take a substantial
        amount of time for datasets with many (sub-)subdatasets.  In Many cases
        the `subdatasets` command can be used with its `contains` parameter to
        achieve the desired result in a less expensive way.

        Parameters
        ----------
        path : str
          Path to determine the containing (sub-)dataset for
        recursion_limit: int or None
          limit the subdatasets to take into account to the given number of
          hierarchy levels

        Returns
        -------
        Dataset
        """

        if recursion_limit is not None and (recursion_limit < 1):
            lgr.warning("recursion limit < 1 (%s) always results in self.",
                        recursion_limit)
            return self

        if is_explicit_path(path):
            path = resolve_path(path, self)
            if not path.startswith(self.path):
                raise PathOutsideRepositoryError(file_=path, repo=self)
            path = relpath(path, self.path)

        candidates = []
        # TODO: this one would follow all the sub-datasets, which might
        # be inefficient if e.g. there is lots of other sub-datasets already
        # installed but under another sub-dataset.  There is a TODO 'pattern'
        # option which we could use I guess eventually
        for subds in self.subdatasets(
                recursive=True,
                #pattern=
                recursion_limit=recursion_limit,
                result_xfm='relpaths'):
            common = commonprefix((with_pathsep(subds), with_pathsep(path)))
            if common.endswith(sep) and common == with_pathsep(subds):
                candidates.append(common)
        if candidates:
            return Dataset(path=opj(self.path, max(candidates, key=len)))
        return self
Beispiel #4
0
    def get_containing_subdataset(self, path, recursion_limit=None):
        """Get the (sub-)dataset containing `path`

        Note: The "mount point" of a subdataset is classified as belonging to
        that respective subdataset.

        Parameters
        ----------
        path : str
          Path to determine the containing (sub-)dataset for
        recursion_limit: int or None
          limit the subdatasets to take into account to the given number of
          hierarchy levels

        Returns
        -------
        Dataset
        """

        if recursion_limit is not None and (recursion_limit < 1):
            lgr.warning("recursion limit < 1 (%s) always results in self.",
                        recursion_limit)
            return self

        if is_explicit_path(path):
            path = resolve_path(path, self)
            if not path.startswith(self.path):
                raise PathOutsideRepositoryError(file_=path, repo=self)
            path = relpath(path, self.path)

        candidates = []
        # TODO: this one would follow all the sub-datasets, which might
        # be inefficient if e.g. there is lots of other sub-datasets already
        # installed but under another sub-dataset.  There is a TODO 'pattern'
        # option which we could use I guess eventually
        for subds in self.get_subdatasets(
                recursive=True,
                #pattern=
                recursion_limit=recursion_limit,
                absolute=False):
            common = commonprefix((with_pathsep(subds), with_pathsep(path)))
            if common.endswith(sep) and common == with_pathsep(subds):
                candidates.append(common)
        if candidates:
            return Dataset(path=opj(self.path, max(candidates, key=len)))
        return self
Beispiel #5
0
    def get_containing_subdataset(self, path, recursion_limit=None):
        """Get the (sub-)dataset containing `path`

        Note: The "mount point" of a subdataset is classified as belonging to
        that respective subdataset.

        Parameters
        ----------
        path : str
          Path to determine the containing (sub-)dataset for
        recursion_limit: int or None
          limit the subdatasets to take into account to the given number of
          hierarchy levels

        Returns
        -------
        Dataset
        """

        if recursion_limit is not None and (recursion_limit < 1):
            lgr.warning("recursion limit < 1 (%s) always results in self.",
                        recursion_limit)
            return self

        if is_explicit_path(path):
            path = resolve_path(path, self)
            if not path.startswith(self.path):
                raise PathOutsideRepositoryError(file_=path, repo=self)
            path = relpath(path, self.path)

        candidates = []
        # TODO: this one would follow all the sub-datasets, which might
        # be inefficient if e.g. there is lots of other sub-datasets already
        # installed but under another sub-dataset.  There is a TODO 'pattern'
        # option which we could use I guess eventually
        for subds in self.get_subdatasets(recursive=True,
                                          #pattern=
                                          recursion_limit=recursion_limit,
                                          absolute=False):
            common = commonprefix((with_pathsep(subds), with_pathsep(path)))
            if common.endswith(sep) and common == with_pathsep(subds):
                candidates.append(common)
        if candidates:
            return Dataset(path=opj(self.path, max(candidates, key=len)))
        return self
Beispiel #6
0
def resolve_path(path, ds=None):
    """Resolve a path specification (against a Dataset location)

    Any explicit path (absolute or relative) is returned as an absolute path.
    In case of an explicit relative path, the current working directory is
    used as a reference. Any non-explicit relative path is resolved against
    as dataset location, i.e. considered relative to the location of the
    dataset. If no dataset is provided, the current working directory is
    used.

    Returns
    -------
    Absolute path
    """
    path = expandpath(path, force_absolute=False)
    # TODO: normpath?!
    if is_explicit_path(path):
        return abspath(path)
    # no dataset given, use CWD as reference
    # note: abspath would disregard symlink in CWD
    top_path = getpwd() \
        if ds is None else ds.path if isinstance(ds, Dataset) else ds
    return normpath(opj(top_path, path))
Beispiel #7
0
def get_containing_subdataset(ds, path):
    """Given a base dataset and a relative path get containing subdataset

    Parameters
    ----------
    ds : Dataset
      Reference or base dataset
    path : str
      Path relative to the reference dataset

    Returns
    -------
    Dataset
    """

    if is_explicit_path(path) and not path.startswith(ds.path):
        raise ValueError("path {0} not in dataset.".format(path))

    for subds in ds.get_dataset_handles():
        common = os.path.commonprefix((_with_sep(subds), _with_sep(path)))
        if common.endswith(sep) and common == _with_sep(subds):
            return Dataset(path=opj(ds.path, common))
    return ds
Beispiel #8
0
def resolve_path(path, ds=None):
    """Resolve a path specification (against a Dataset location)

    Any explicit path (absolute or relative) is returned as an absolute path.
    In case of an explicit relative path, the current working directory is
    used as a reference. Any non-explicit relative path is resolved against
    as dataset location, i.e. considered relative to the location of the
    dataset. If no dataset is provided, the current working directory is
    used.

    Returns
    -------
    Absolute path
    """
    path = expandpath(path, force_absolute=False)
    # TODO: normpath?!
    if is_explicit_path(path):
        return abspath(path)
    # no dataset given, use CWD as reference
    # note: abspath would disregard symlink in CWD
    top_path = getpwd() \
        if ds is None else ds.path if isinstance(ds, Dataset) else ds
    return normpath(opj(top_path, path))
Beispiel #9
0
def resolve_path(path, ds=None):
    """Resolve a path specification (against a Dataset location)

    Any explicit path (absolute or relative) is return as an absolute path.
    In case of an explicit relative path, the current working directory is
    used as a reference. Any non-explicit relative path is resolved against
    as dataset location, i.e. considered relative to the location of the
    dataset. If no dataset is provided, the current working directory is
    used.

    Returns
    -------
    Absolute path
    """
    path = expandpath(path, force_absolute=False)
    if is_explicit_path(path):
        return abspath(path)
    if ds is None:
        # no dataset given, use CWD as reference
        # TODO: Check whether we should use PWD instead of CWD here. Is it done
        # by abspath?
        return abspath(path)
    else:
        return normpath(opj(ds.path, path))
Beispiel #10
0
def resolve_path(path, ds=None):
    """Resolve a path specification (against a Dataset location)

    Any explicit path (absolute or relative) is return as an absolute path.
    In case of an explicit relative path, the current working directory is
    used as a reference. Any non-explicit relative path is resolved against
    as dataset location, i.e. considered relative to the location of the
    dataset. If no dataset is provided, the current working directory is
    used.

    Returns
    -------
    Absolute path
    """
    path = expandpath(path, force_absolute=False)
    if is_explicit_path(path):
        return abspath(path)
    if ds is None:
        # no dataset given, use CWD as reference
        # TODO: Check whether we should use PWD instead of CWD here. Is it done
        # by abspath?
        return abspath(path)
    else:
        return normpath(opj(ds.path, path))
Beispiel #11
0
def test_is_explicit_path():
    # by default expanded paths are absolute, hence explicit
    assert_true(is_explicit_path(expandpath('~')))
    assert_false(is_explicit_path("here"))