Skip to content

Commit

Permalink
fix: issues with remapping and dependency detection in foundry projec…
Browse files Browse the repository at this point in the history
…ts (#2117)
  • Loading branch information
antazoey authored Jun 6, 2024
1 parent c257109 commit a3e26ab
Show file tree
Hide file tree
Showing 5 changed files with 336 additions and 180 deletions.
91 changes: 66 additions & 25 deletions src/ape/managers/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -626,7 +626,6 @@ def install(
config_override = {**(self.api.config_override or {}), **(config_override or {})}
project = None
did_fetch = False

if self._installation is not None and use_cache:
if config_override:
self._installation.reconfigure(**config_override)
Expand Down Expand Up @@ -732,7 +731,7 @@ def compile(
Args:
use_cache (bool): Set to ``False`` to force a re-compile.
config_override (Optional[dict]): Optionall override the configuration,
config_override (Optional[dict]): Optionally override the configuration,
which may be needed for compiling.
Returns:
Expand Down Expand Up @@ -797,10 +796,15 @@ def _unpack(self, path: Path, tracked: set[str]) -> Iterator["Dependency"]:
yield unpacked_dep


def _get_cache_suffix(package_id: str, version: str, suffix: str = "") -> Path:
def _get_cache_versions_suffix(package_id) -> Path:
package_id_name = package_id.replace("/", "_")
return Path(package_id_name)


def _get_cache_suffix(package_id: str, version: str, suffix: str = "") -> Path:
package_id_path = _get_cache_versions_suffix(package_id)
version_name = f"{version.replace('.', '_').replace('/', '_')}{suffix}"
return Path(package_id_name) / version_name
return package_id_path / version_name


class PackagesCache(ManagerAccessMixin):
Expand Down Expand Up @@ -831,6 +835,12 @@ def manifests_folder(self) -> Path:
def installed_package_names(self) -> set[str]:
return {x.name for x in self.projects_folder.iterdir()}

def get_project_versions_path(self, package_id: str) -> Path:
"""
The path to all the versions (projects) of a dependency.
"""
return self.projects_folder / _get_cache_versions_suffix(package_id)

def get_project_path(self, package_id: str, version: str) -> Path:
"""
Path to the dir of the cached project.
Expand Down Expand Up @@ -989,12 +999,8 @@ def __getitem__(self, name: str) -> DependencyVersionMap:
if versions := {d.version: d.project for d in self._get_specified(name=name)}:
result.extend(versions)

# Add other dependencies of the same package (different versions)
# that are also installed.
for dependency in self.installed:
if dependency.name != name:
continue

# Add remaining installed versions.
for dependency in self.get_versions(name):
if dependency.version not in result:
result[dependency.version] = dependency.project

Expand Down Expand Up @@ -1199,13 +1205,32 @@ def get_versions(self, name: str) -> Iterator[Dependency]:
versions_yielded.add(dependency.version)

# Yield any remaining installed.
using_package_id = False
for dependency in self.installed:
if dependency.name == name:
if dependency.version in versions_yielded:
continue
if dependency.package_id != name:
continue

using_package_id = True
if dependency.version in versions_yielded:
continue

yield dependency
versions_yielded.add(dependency.version)
yield dependency
versions_yielded.add(dependency.version)

if using_package_id:
# Done.
return

# Never yield. Check if using short-name.
for dependency in self.installed:
if dependency.name != name:
continue

elif dependency.version in versions_yielded:
continue

yield dependency
versions_yielded.add(dependency.version)

def _create_dependency(self, api: DependencyAPI) -> Dependency:
if api in self._cache:
Expand Down Expand Up @@ -1337,15 +1362,15 @@ def install(self, **dependency: Any) -> Union[Dependency, list[Dependency]]:
use_cache: bool = dependency.pop("use_cache", False)
if dependency:
return self.install_dependency(dependency, use_cache=use_cache)
else:
# Install all project's.
result: list[Dependency] = []

# Log the errors as they happen but don't crash the full install.
for dep in self._get_specified():
result.append(dep)
# Install all project's.
result: list[Dependency] = []

return result
# Log the errors as they happen but don't crash the full install.
for dep in self._get_specified(use_cache=use_cache):
result.append(dep)

return result

def install_dependency(
self,
Expand Down Expand Up @@ -2057,6 +2082,13 @@ def project_api(self) -> ProjectAPI:
The 'type' of project this is, such as an Ape project
or a Brownie project (or something else).
"""
default_project = self._get_ape_project_api()

# If an ape-config.yaml file, exists stop now.
if default_project and default_project.config_file.is_file():
return default_project

# ape-config.yaml does no exist. Check for another ProjectAPI type.
project_classes: list[type[ProjectAPI]] = [
t[1] for t in list(self.plugin_manager.projects) # type: ignore
]
Expand All @@ -2065,12 +2097,21 @@ def project_api(self) -> ProjectAPI:
if instance := api.attempt_validate(path=self.path):
return instance

# Try 'ApeProject' last, in case there was a more specific one earlier.
if instance := ApeProject.attempt_validate(path=self.path):
return instance
# If no other APIs worked but we have a default Ape project, use that!
# It should work in most cases (hopefully!).
if default_project:
return default_project

# For some reason we were just not able to create a project here.
# I am not sure this is even possible.
raise ProjectError(f"'{self.path.name}' is not recognized as a project.")

def _get_ape_project_api(self) -> Optional[ApeProject]:
if instance := ApeProject.attempt_validate(path=self.path):
return cast(ApeProject, instance)

return None

@property
def name(self) -> str:
if name := self.config.get("name"):
Expand Down
13 changes: 11 additions & 2 deletions src/ape_pm/_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from ape.exceptions import ProjectError
from ape.logging import logger
from ape.managers.project import Dependency
from ape_pm import LocalDependency


@click.group()
Expand All @@ -29,7 +30,7 @@ def _list(cli_ctx, list_all):
packages = []
dependencies = [*list(pm.dependencies.specified)]
if list_all:
dependencies = list(set([*dependencies, *pm.dependencies.installed]))
dependencies = list({*dependencies, *pm.dependencies.installed})

for dependency in dependencies:
try:
Expand All @@ -38,8 +39,16 @@ def _list(cli_ctx, list_all):
# Project may not even be installed right.
is_compiled = False

# For local dependencies, use the short name.
# This is mostly because it looks nicer than very long paths.
name = (
dependency.name
if isinstance(dependency.api, LocalDependency)
else dependency.package_id
)

item = {
"name": dependency.name,
"name": name,
"version": dependency.version,
"compiled": is_compiled,
}
Expand Down
Loading

0 comments on commit a3e26ab

Please sign in to comment.