Skip to content

Commit

Permalink
Refactor which_package & which_prefix
Browse files Browse the repository at this point in the history
  • Loading branch information
kenodegard committed Oct 18, 2023
1 parent d480c32 commit bada3b1
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 53 deletions.
50 changes: 21 additions & 29 deletions conda_build/conda_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
import os
from functools import partial
from importlib import import_module # noqa: F401
from pathlib import Path
from typing import Iterable

from conda import __version__ as CONDA_VERSION # noqa: F401
from conda.auxlib.packaging import ( # noqa: F401
Expand Down Expand Up @@ -125,46 +127,36 @@ class SignatureError(Exception):
pass


@deprecated("3.28.0", "4.0.0")
def which_package(path):
"""
Given the path (of a (presumably) conda installed file) iterate over
the conda packages the file came from. Usually the iteration yields
only one package.
"""
from os.path import abspath, join
@deprecated(
"3.28.0",
"4.0.0",
addendum="Use `conda_build.inspect_pkg.which_package` instead.",
)
def which_package(path: str | os.PathLike | Path) -> Iterable[PackageRecord]:
from .inspect_pkg import which_package

path = abspath(path)
prefix = which_prefix(path)
if prefix is None:
raise RuntimeError("could not determine conda prefix from: %s" % path)
for dist in linked(prefix):
meta = is_linked(prefix, dist)
if any(abspath(join(prefix, f)) == path for f in meta["files"]):
yield dist
return which_package(path, which_prefix(path))


@deprecated("3.28.0", "4.0.0")
def which_prefix(path):
def which_prefix(path: str | os.PathLike | Path) -> Path:
"""
Given the path (to a (presumably) conda installed file) return the
environment prefix in which the file in located
"""
from os.path import abspath, dirname, isdir, join
from conda.gateways.disk.test import is_conda_environment

prefix = abspath(path)
iteration = 0
while iteration < 20:
if isdir(join(prefix, "conda-meta")):
# we found it, so let's return it
break
if prefix == dirname(prefix):
prefix = Path(path)
for _ in range(20):
if is_conda_environment(prefix):
return prefix
elif prefix == (parent := prefix.parent):
# we cannot chop off any more directories, so we didn't find it
prefix = None
break
prefix = dirname(prefix)
iteration += 1
return prefix
else:
prefix = parent

raise RuntimeError("could not determine conda prefix from: %s" % path)


@deprecated("3.28.0", "4.0.0")
Expand Down
45 changes: 27 additions & 18 deletions conda_build/inspect_pkg.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# Copyright (C) 2014 Anaconda, Inc
# SPDX-License-Identifier: BSD-3-Clause
from __future__ import annotations

import json
import os
import re
Expand All @@ -9,7 +11,12 @@
from functools import lru_cache
from itertools import groupby
from operator import itemgetter
from os.path import abspath, basename, dirname, exists, join, normcase
from os.path import abspath, basename, dirname, exists, join
from pathlib import Path
from typing import Iterable

from conda.models.dist import Dist
from conda.models.records import PackageRecord

from conda_build.conda_interface import (
display_actions,
Expand All @@ -34,32 +41,35 @@
rm_rf,
)

from .deprecations import deprecated


@deprecated("3.28.0", "4.0.0")
@lru_cache(maxsize=None)
def dist_files(prefix, dist):
def dist_files(prefix: str | os.PathLike | Path, dist: Dist) -> set[str]:
meta = is_linked(prefix, dist)
return set(meta["files"]) if meta else set()


def which_package(in_prefix_path, prefix, avoid_canonical_channel_name=False):
@deprecated.argument("3.28.0", "4.0.0", "avoid_canonical_channel_name")
def which_package(
path: str | os.PathLike | Path,
prefix: str | os.PathLike | Path,
) -> Iterable[PackageRecord]:
"""
given the path of a conda installed file iterate over
Given the path (of a (presumably) conda installed file) iterate over
the conda packages the file came from. Usually the iteration yields
only one package.
"""
norm_ipp = normcase(in_prefix_path.replace(os.sep, "/"))
from conda_build.utils import linked_data_no_multichannels
from conda.core.prefix_data import PrefixData

if avoid_canonical_channel_name:
fn = linked_data_no_multichannels
else:
fn = linked_data
for dist in fn(prefix):
# dfiles = set(dist.get('files', []))
dfiles = dist_files(prefix, dist)
# TODO :: This is completely wrong when the env is on a case-sensitive FS!
if any(norm_ipp == normcase(w) for w in dfiles):
yield dist
prefix = Path(prefix)
for prec in PrefixData(prefix).iter_records():
for file in prec["files"]:
# historically, path was relative to prefix just to be safe we append to prefix
# (pathlib correctly handles this even if path is absolute)
if (prefix / file).samefile(prefix / path):
yield prec


def print_object_info(info, key):
Expand Down Expand Up @@ -278,8 +288,7 @@ def inspect_linkages(
else path
)
if path.startswith(prefix):
in_prefix_path = re.sub("^" + prefix + "/", "", path)
deps = list(which_package(in_prefix_path, prefix))
deps = list(which_package(path, prefix))
if len(deps) > 1:
deps_str = [str(dep) for dep in deps]
get_logger(__name__).warn(
Expand Down
8 changes: 2 additions & 6 deletions conda_build/post.py
Original file line number Diff line number Diff line change
Expand Up @@ -926,9 +926,7 @@ def _map_file_to_package(
if not len(owners):
if any(rp == normpath(w) for w in files):
owners.append(pkg_vendored_dist)
new_pkgs = list(
which_package(rp, prefix, avoid_canonical_channel_name=True)
)
new_pkgs = list(which_package(rp, prefix))
# Cannot filter here as this means the DSO (eg libomp.dylib) will not be found in any package
# [owners.append(new_pkg) for new_pkg in new_pkgs if new_pkg not in owners
# and not any([fnmatch(new_pkg.name, i) for i in ignore_for_statics])]
Expand Down Expand Up @@ -1125,9 +1123,7 @@ def _lookup_in_prefix_packages(
in_prefix_dso = normpath(needed_dso)
n_dso_p = "Needed DSO {}".format(in_prefix_dso.replace("\\", "/"))
and_also = " (and also in this package)" if in_prefix_dso in files else ""
pkgs = list(
which_package(in_prefix_dso, run_prefix, avoid_canonical_channel_name=True)
)
pkgs = list(which_package(in_prefix_dso, run_prefix))
in_pkgs_in_run_reqs = [pkg for pkg in pkgs if pkg.quad[0] in requirements_run]
# TODO :: metadata build/inherit_child_run_exports (for vc, mro-base-impl).
for pkg in in_pkgs_in_run_reqs:
Expand Down

0 comments on commit bada3b1

Please sign in to comment.