Skip to content

Commit

Permalink
fix: dependencies of dependencies (#1200)
Browse files Browse the repository at this point in the history
  • Loading branch information
antazoey authored Jan 5, 2023
1 parent d70d5de commit ddd298b
Show file tree
Hide file tree
Showing 11 changed files with 242 additions and 96 deletions.
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@
"web3[tester]==6.0.0b7",
# ** Dependencies maintained by ApeWorX **
"eip712>=0.1.4,<0.2",
"ethpm-types>=0.3.12,<0.4",
"ethpm-types>=0.3.15,<0.4",
"evm-trace>=0.1.0a14",
],
entry_points={
Expand Down
86 changes: 60 additions & 26 deletions src/ape/api/projects.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import yaml
from ethpm_types import Checksum, ContractType, PackageManifest, Source
from ethpm_types.manifest import PackageName
from ethpm_types.utils import compute_checksum
from ethpm_types.utils import AnyUrl, compute_checksum
from packaging.version import InvalidVersion, Version
from pydantic import ValidationError

Expand Down Expand Up @@ -190,6 +190,13 @@ def version_id(self) -> str:
Most often, this is either a version number or a branch name.
"""

@property
@abstractmethod
def uri(self) -> AnyUrl:
"""
The URI to use when listing in a PackageManifest.
"""

@cached_property
def _base_cache_path(self) -> Path:
version_id = self.version_id
Expand Down Expand Up @@ -293,35 +300,62 @@ def _get_compiled_manifest(self) -> PackageManifest:
source_path.touch()
source_path.write_text(content)

# Handle dependencies and import remappings indicated in the manifest file
# Handle import remapping entries indicated in the manifest file
target_config_file = project.path / project.config_file_name
packages_used = set()
config_data: Dict[str, Any] = {}
for compiler in [x for x in manifest.compilers or [] if x.settings]:
name = compiler.name.lower()
compiler_data = config_data.get(name, {})
compiler_data = {}
settings = compiler.settings or {}
new_remappings: List[str] = []
if "remappings" in settings:
existing_remappings = compiler_data.get("remappings", [])
new_remappings = list(set([*settings["remappings"], *existing_remappings]))

cleaned_remappings = []
for remapping in new_remappings:
remapping_list = []
for remapping in settings.get("remappings") or []:
parts = remapping.split("=")
key = parts[0]
link = parts[1]
if link.startswith(f".cache{os.path.sep}"):
link = os.path.sep.join(link.split(f".cache{os.path.sep}"))[1:]

new_entry = f"{parts[0]}={link}"
cleaned_remappings.append(new_entry)
packages_used.add(link)
new_entry = f"{key}={link}"
remapping_list.append(new_entry)

if cleaned_remappings:
compiler_data["import_remapping"] = cleaned_remappings
if remapping_list:
compiler_data["import_remapping"] = remapping_list

if compiler_data:
config_data[name] = compiler_data

# Handle dependencies indicated in the manifest file
dependencies_config: List[Dict] = []
dependencies = manifest.dependencies or {}
dependencies_used = {
p: d for p, d in dependencies.items() if any(p.lower() in x for x in packages_used)
}
for package_name, uri in dependencies_used.items():
if "://" not in str(uri) and hasattr(uri, "scheme"):
uri_str = f"{uri.scheme}://{uri}"
else:
uri_str = str(uri)

dependency = {"name": str(package_name)}
if uri_str.startswith("https://"):
# Assume GitHub dependency
version = uri_str.split("/")[-1]
dependency["github"] = uri_str.replace(f"/releases/tag/{version}", "")
dependency["github"] = dependency["github"].replace("https://github.com/", "")
dependency["version"] = version

elif uri_str.startswith("file://"):
dependency["local"] = uri_str.replace("file://", "")

dependencies_config.append(dependency)

if dependencies_config:
config_data["dependencies"] = dependencies_config

if config_data:
target_config_file.unlink(missing_ok=True)
with open(target_config_file, "w+") as cf:
yaml.safe_dump(config_data, cf)

Expand All @@ -338,21 +372,21 @@ def _extract_local_manifest(self, project_path: Path) -> PackageManifest:
if cached_manifest:
return cached_manifest

project = self._get_project(project_path)

with self.config_manager.using_project(project.path):
# Load dependencies of dependencies before loading dependencies.
self.project_manager._load_dependencies()
compiler_data = self.project_manager._get_compiler_data(compile_if_needed=False)

sources = self._get_sources(project)

# NOTE: Dependencies are not compiled here. Instead, the sources are packaged
# for later usage via imports. For legacy reasons, many dependency-esque projects
# are not meant to compile on their own.
project_manifest = project._create_manifest(
sources, project.contracts_folder, {}, name=project.name, version=project.version
)

with self.config_manager.using_project(project_path):
project = self._get_project(project_path)
sources = self._get_sources(project)
dependencies = self.project_manager._extract_manifest_dependencies()
project_manifest = project._create_manifest(
sources, project.contracts_folder, {}, name=project.name, version=project.version
)
compiler_data = self.project_manager._get_compiler_data(compile_if_needed=False)

if dependencies:
project_manifest.dependencies = dependencies
if compiler_data:
project_manifest.compilers = compiler_data

Expand Down
17 changes: 17 additions & 0 deletions src/ape/managers/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -275,18 +275,35 @@ def using_project(
initial_project_folder = self.PROJECT_FOLDER
initial_contracts_folder = self.contracts_folder

if (
initial_project_folder == project_folder
and initial_contracts_folder == contracts_folder
):
# Already in project
yield self.project_manager
return

self.PROJECT_FOLDER = project_folder
self.contracts_folder = contracts_folder
self.project_manager.path = project_folder
os.chdir(project_folder)
clean_config = False

try:
# Process and reload the project's configuration
clean_config = self.project_manager.local_project.process_config_file()
self.load(force_reload=True)
yield self.project_manager

finally:
temp_project_path = self.project_manager.path
self.PROJECT_FOLDER = initial_project_folder
self.contracts_folder = initial_contracts_folder
self.project_manager.path = initial_project_folder

if initial_project_folder.is_dir():
os.chdir(initial_project_folder)

config_file = temp_project_path / CONFIG_FILE_NAME
if clean_config and config_file.is_file():
config_file.unlink()
20 changes: 18 additions & 2 deletions src/ape/managers/project/dependency.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
from typing import Dict, Optional, Type

from ethpm_types import PackageManifest
from pydantic import root_validator
from ethpm_types.utils import AnyUrl
from pydantic import FileUrl, HttpUrl, root_validator

from ape.api import DependencyAPI
from ape.api.projects import _load_manifest_from_file
Expand Down Expand Up @@ -77,6 +78,16 @@ def version_id(self) -> str:
latest_release = github_client.get_release(self.github, "latest")
return latest_release.tag_name

@property
def uri(self) -> AnyUrl:
_uri = f"https://github.com/{self.github.strip('/')}"
if self.version and not self.version.startswith("v"):
_uri = f"{_uri}/releases/tag/v{self.version}"
elif self.version:
_uri = f"{_uri}/releases/tag/{self.version}"

return HttpUrl(_uri, scheme="https")

def __repr__(self):
return f"<{self.__class__.__name__} github={self.github}>"

Expand Down Expand Up @@ -137,7 +148,7 @@ def validate_contracts_folder(cls, value):

@property
def path(self) -> Path:
given_path = Path(self.local).absolute()
given_path = Path(self.local).resolve().absolute()
if not given_path.is_dir():
raise ProjectError(f"No project exists at path '{given_path}'.")

Expand All @@ -147,6 +158,11 @@ def path(self) -> Path:
def version_id(self) -> str:
return self.version

@property
def uri(self) -> AnyUrl:
path = self._target_manifest_cache_file.resolve().absolute()
return FileUrl(f"file://{path}", scheme="file")

def extract_manifest(self) -> PackageManifest:
if self._target_manifest_cache_file.is_file():
manifest = _load_manifest_from_file(self._target_manifest_cache_file)
Expand Down
Loading

0 comments on commit ddd298b

Please sign in to comment.