Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deploying by a contract name [1/2] — refactor feature dependencies #565

Merged
merged 21 commits into from
Aug 4, 2022
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 7 additions & 6 deletions protostar/commands/build/build_command.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
from logging import Logger
from typing import List, Optional

from protostar.cli import ActivityIndicator
from protostar.cli.command import Command
from protostar.commands.build.project_compiler import ProjectCompiler
from protostar.cli import ActivityIndicator, Command
from protostar.compiler import ProjectCompiler, ProjectCompilerConfig
from protostar.utils import log_color_provider


Expand Down Expand Up @@ -53,10 +52,12 @@ async def run(self, args):
log_color_provider.colorize("GRAY", "Building projects' contracts")
):
try:
self._project_compiler.compile(
self._project_compiler.compile_project(
output_dir=args.output,
relative_cairo_path=args.cairo_path,
disable_hint_validation=args.disable_hint_validation,
config=ProjectCompilerConfig(
hint_validation_disabled=args.disable_hint_validation,
relative_cairo_path=args.cairo_path,
),
)
except BaseException as exc:
self._logger.error("Build failed")
Expand Down
5 changes: 0 additions & 5 deletions protostar/commands/build/build_exceptions.py

This file was deleted.

141 changes: 0 additions & 141 deletions protostar/commands/build/project_compiler.py

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ def save_protostar_toml(self, project_root: Path, libs_path: Path) -> None:
self.protostar_toml_writer.save(
path=project_root / "protostar.toml",
protostar_config=ProtostarConfigSection.get_default(self.version_manager),
protostar_project=ProtostarProjectSection(libs_path=libs_path),
protostar_project=ProtostarProjectSection(libs_relative_path=libs_path),
protostar_contracts=ProtostarContractsSection.get_default(),
)

Expand Down
3 changes: 2 additions & 1 deletion protostar/commands/install/install_command.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,8 @@ def install(
alias: Optional[str] = None,
) -> None:
project_section = self._project_section_loader.load()
libs_path = self._project_root_path / project_section.libs_path
libs_path = self._project_root_path / project_section.libs_relative_path

if package_name:
package_info = extract_info_from_repo_id(package_name)

Expand Down
2 changes: 1 addition & 1 deletion protostar/commands/remove/remove_command.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ def remove(self, internal_dependency_reference: str):
package_name = retrieve_real_package_name(
internal_dependency_reference,
self._project_root_path,
project_section.libs_path,
project_section.libs_relative_path,
)

self._logger.info(
Expand Down
8 changes: 0 additions & 8 deletions protostar/commands/test/expected_event.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import os
from collections import deque
from dataclasses import dataclass
from enum import Enum
from pathlib import Path
from typing import List, Optional, Tuple, Union

from starkware.starknet.business_logic.execution.objects import Event
Expand All @@ -12,12 +10,6 @@
from protostar.commands.test.test_suite import TestSuite


def collect_immediate_subdirectories(root_dir: Path) -> List[str]:
assert root_dir.is_dir(), f"{root_dir} is supposed to be a directory!"
(root, dirs, _) = next(os.walk(str(root_dir.resolve())))
return [str(Path(root, directory).resolve()) for directory in dirs]


@dataclass
class ExpectedEvent:
name: str
Expand Down
14 changes: 7 additions & 7 deletions protostar/commands/test/test_command.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from logging import getLogger
from pathlib import Path
from typing import TYPE_CHECKING, List, Optional
from typing import List, Optional

from protostar.cli.activity_indicator import ActivityIndicator
from protostar.cli.command import Command
Expand All @@ -13,6 +13,7 @@
from protostar.commands.test.testing_live_logger import TestingLiveLogger
from protostar.commands.test.testing_seed import TestingSeed
from protostar.commands.test.testing_summary import TestingSummary
from protostar.compiler import ProjectCairoPathBuilder
from protostar.utils.compiler.pass_managers import (
StarknetPassManagerFactory,
TestCollectorPassManagerFactory,
Expand All @@ -21,21 +22,18 @@
from protostar.utils.protostar_directory import ProtostarDirectory
from protostar.utils.starknet_compilation import CompilerConfig, StarknetCompiler

if TYPE_CHECKING:
from protostar.commands.build.project_compiler import ProjectCompiler


class TestCommand(Command):
def __init__(
self,
project_root_path: Path,
protostar_directory: ProtostarDirectory,
project_compiler: "ProjectCompiler",
project_cairo_path_builder: ProjectCairoPathBuilder,
) -> None:
super().__init__()
self._project_root_path = project_root_path
self._protostar_directory = protostar_directory
self._project_compiler = project_compiler
self._project_cairo_path_builder = project_cairo_path_builder

@property
def name(self) -> str:
Expand Down Expand Up @@ -164,7 +162,9 @@ async def test(
str(path)
for path in [
self._protostar_directory.protostar_test_only_cairo_packages_path,
*self._project_compiler.build_cairo_path(cairo_path or []),
*self._project_cairo_path_builder.build_project_cairo_path_list(
cairo_path or []
),
]
]
factory = (
Expand Down
10 changes: 6 additions & 4 deletions protostar/commands/update/update_command.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,19 +71,21 @@ def update(self, package: Optional[str]) -> None:

if package:
package = retrieve_real_package_name(
package, self._project_root_path, project_section.libs_path
package, self._project_root_path, project_section.libs_relative_path
)
try:
update_package(
package, self._project_root_path, project_section.libs_path
package, self._project_root_path, project_section.libs_relative_path
)
except PackageAlreadyUpToDateException as err:
self._logger.info(err.message)
else:
for package_name in listdir(project_section.libs_path):
for package_name in listdir(project_section.libs_relative_path):
try:
update_package(
package_name, self._project_root_path, project_section.libs_path
package_name,
self._project_root_path,
project_section.libs_relative_path,
)
except PackageAlreadyUpToDateException:
continue
7 changes: 7 additions & 0 deletions protostar/compiler/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
from .project_compiler import (
CompilationException,
ProjectCairoPathBuilder,
ProjectCompiler,
ProjectCompilerConfig,
SourceFileNotFoundException,
)
40 changes: 40 additions & 0 deletions protostar/compiler/compiled_contract_writer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import json
from pathlib import Path
from typing import Any

from starkware.starknet.services.api.contract_class import ContractClass


class CompiledContractWriter:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this could be a plain function

Copy link
Contributor Author

@kasperski95 kasperski95 Aug 3, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this case, it could. Something feels off when mixing paradigms.

It's easier to find a file that contains a class rather than a list of functions. Naming files in the same way as the main exported function is confusing because a function and a filename use the same casing, and that makes importing/patching confusing.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can still define single public module function, and name the module the same way. That's what I have seen in the wild.

Something feels off when mixing paradigms.

To me, using classes too much in Python/JS is mixing paradigms.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can still define single public module function, and name the module the same way. That's what I have seen in the wild.

I did it when I used the functional paradigm. Auto import functionality confused the function with the module, if they were named in the same way. Also, I couldn't patch the function, if it was imported from the __init__.py (barrel file) from the same reason.

To me, using classes too much in Python/JS is mixing paradigms.

Functional programming is more common in Python, but it doesn't mean that this is the proper tool for the job.

  • Object-Oriented Programming is the tool best suited for defining how we cross architectural boundaries with polymorphism and plugins
  • Functional programming is the tool we use to push data to the boundaries of our applications
  • and Structured programming is the tool we use to write algorithms

https://khalilstemmler.com/articles/software-design-architecture/full-stack-software-design/

def __init__(self, contract: ContractClass, contract_name: str) -> None:
self._contract = contract
self._contract_name = contract_name

def save(self, output_dir: Path) -> None:
self.save_compiled_contract(output_dir)
self.save_compiled_contract_abi(output_dir)

def save_compiled_contract(self, output_dir: Path) -> None:
self._create_output_dir(output_dir)
serialized_contract = self._contract.Schema().dump(self._contract)
self._save_as_json(data=serialized_contract, path=output_dir)

def save_compiled_contract_abi(self, output_dir: Path) -> None:
if not self._contract.abi:
return
self._create_output_dir(output_dir)
self._save_as_json(data=self._contract.abi, path=output_dir)

@staticmethod
def _create_output_dir(output_dir: Path):
output_dir.mkdir(parents=True, exist_ok=True)

@staticmethod
def _save_as_json(data: Any, path: Path):
with open(
path,
mode="w",
encoding="utf-8",
) as output_abi_file:
json.dump(data, output_abi_file, indent=4, sort_keys=True)
output_abi_file.write("\n")
44 changes: 44 additions & 0 deletions protostar/compiler/project_cairo_path_builder.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import os
from pathlib import Path
from typing import List, Optional

from protostar.protostar_toml.protostar_project_section import ProtostarProjectSection


class ProjectCairoPathBuilder:
def __init__(
self,
project_root_path: Path,
project_section_loader: ProtostarProjectSection.Loader,
) -> None:
self._project_root_path = project_root_path
self._project_section_loader = project_section_loader

def build_project_cairo_path_list(
self, relative_cairo_path_list: List[Path]
) -> List[Path]:
"""NOTE: This function uses `list` suffix to mitigate confusion and
remain consistency with StarkNet's `cairo_path`."""

return [
*relative_cairo_path_list,
self._project_root_path,
*self._build_libs_cairo_path_list(),
]

def _build_libs_cairo_path_list(self) -> List[Path]:
libs_path = self._get_libs_path()
if libs_path is None:
return []
return [libs_path, *self._build_packages_cairo_path_list()]

def _build_packages_cairo_path_list(self) -> List[Path]:
libs_path = self._get_libs_path()
if libs_path is None:
return []
(root, dirs, _) = next(os.walk(str(libs_path.resolve())))
return [Path(root, directory).resolve() for directory in dirs]

def _get_libs_path(self) -> Optional[Path]:
project_section = self._project_section_loader.load()
return project_section.get_libs_path(self._project_root_path)
Loading