Skip to content

Commit

Permalink
perf: improve performance of project.get_contract() (ApeWorX#2166)
Browse files Browse the repository at this point in the history
  • Loading branch information
antazoey authored Jul 2, 2024
1 parent d58c75a commit 9481f4e
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 12 deletions.
17 changes: 5 additions & 12 deletions src/ape/managers/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -2276,16 +2276,6 @@ def in_tempdir(self) -> bool:

return in_tempdir(self.path)

@property
def manifest(self) -> PackageManifest:
# Reloads to handle changes from other ongoing sessions.
# If don't need a reload, use `._manifest` instead.
if self.manifest_path.is_file():
reloaded = PackageManifest.model_validate_json(self.manifest_path.read_text())
self._manifest = reloaded

return self._manifest

@property
def meta(self) -> PackageMeta:
"""
Expand Down Expand Up @@ -2375,11 +2365,14 @@ def load_manifest(self) -> PackageManifest:
return PackageManifest()

try:
return _load_manifest(self.manifest_path)
manifest = _load_manifest(self.manifest_path)
except Exception as err:
logger.error(f"__local__.json manifest corrupted! Re-building.\nFull error: {err}.")
self.manifest_path.unlink(missing_ok=True)
return PackageManifest()
manifest = PackageManifest()

self._manifest = manifest
return manifest

def get_contract(self, name: str) -> Any:
if name in dir(self):
Expand Down
11 changes: 11 additions & 0 deletions tests/functional/test_project.py
Original file line number Diff line number Diff line change
Expand Up @@ -540,6 +540,17 @@ def test_get_contract(project_with_contracts):
assert isinstance(actual, ContractContainer)
assert actual.contract_type.name == "Other"

# Ensure manifest is only loaded once by none-ing out the path.
# Otherwise, this can be a MAJOR performance hit.
manifest_path = project_with_contracts.manifest_path
project_with_contracts.manifest_path = None
try:
actual = project_with_contracts.get_contract("Other")
assert isinstance(actual, ContractContainer)
assert actual.contract_type.name == "Other"
finally:
project_with_contracts.manifest_path = manifest_path


def test_get_contract_not_exists(project):
actual = project.get_contract("this is not a contract")
Expand Down
5 changes: 5 additions & 0 deletions tests/integration/cli/test_compile.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,11 @@ def test_compile(ape_cli, runner, integ_project, clean_cache):
cmd = ("compile", "--project", f"{integ_project.path}")
result = runner.invoke(ape_cli, cmd, catch_exceptions=False)
assert result.exit_code == 0, result.output

# We have to load the manifest again because normally we are not referencing
# the manifest in the same process as `ape compile`.
integ_project.load_manifest()

assert integ_project.manifest.contract_types

# First time it compiles, it compiles the files with registered compilers successfully.
Expand Down

0 comments on commit 9481f4e

Please sign in to comment.