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

Add imports to __init__.py #44

Merged
merged 3 commits into from
Nov 20, 2023
Merged
Show file tree
Hide file tree
Changes from all 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
27 changes: 20 additions & 7 deletions pypechain/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@
from web3.exceptions import NoABIFunctionsFound

from pypechain.render.main import render_files
from pypechain.utilities.file import write_string_to_file
from pypechain.utilities.format import apply_black_formatting
from pypechain.utilities.templates import get_jinja_env


def main(argv: Sequence[str] | None = None) -> None:
Expand All @@ -32,7 +35,7 @@ def main(argv: Sequence[str] | None = None) -> None:
setup_directory(output_dir)

# List to store all JSON ABI files to be processed
json_files_to_process = []
json_files_to_process: list[Path] = []

# Check if provided path is a directory or file
if os.path.isdir(abi_file_path):
Expand All @@ -42,16 +45,31 @@ def main(argv: Sequence[str] | None = None) -> None:
# Otherwise, add the single file to the list
json_files_to_process.append(Path(abi_file_path))

file_names: list[str] = []

# Now process all gathered files
for json_file in json_files_to_process:
try:
render_files(str(json_file), output_dir, line_length)
rendered_file_names = render_files(str(json_file), output_dir, line_length)
file_names.extend(rendered_file_names)
except NoABIFunctionsFound:
print(f"No ABI Functions found in {json_file}, skipping...")
except BaseException as err:
print(f"Error creating types for {json_file}")
raise err

# Finally, render the __init__.py file
render_init_file(output_dir, file_names, line_length)


def render_init_file(output_dir: str, file_names: list[str], line_length):
"""Creates an __init__.py file that imports all other files."""
env = get_jinja_env()
init_template = env.get_template("init.py.jinja2")
init_code = init_template.render(file_names=file_names)
formatted_init_code = apply_black_formatting(init_code, line_length)
write_string_to_file(f"{output_dir}/__init__.py", formatted_init_code)


def gather_json_files(directory: str) -> list:
"""Gathers all JSON files in the specified directory and its subdirectories."""
Expand All @@ -68,11 +86,6 @@ def setup_directory(directory: str) -> None:
# Create the directory
os.makedirs(directory)

# Create an empty __init__.py file in the directory
init_file_path = os.path.join(directory, "__init__.py")
with open(init_file_path, "a", encoding="utf-8"):
pass


class Args(NamedTuple):
"""Command line arguments for pypechain."""
Expand Down
20 changes: 13 additions & 7 deletions pypechain/render/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,13 @@
import os
from pathlib import Path


from pypechain.render.contract import render_contract_file
from pypechain.render.types import render_types_file
from pypechain.utilities.file import write_string_to_file
from pypechain.utilities.format import apply_black_formatting


def render_files(abi_file_path: str, output_dir: str, line_length: int) -> None:
def render_files(abi_file_path: str, output_dir: str, line_length: int) -> list[str]:
"""Processes a single JSON file to generate class and types files."""

# get names
Expand All @@ -22,12 +21,19 @@ def render_files(abi_file_path: str, output_dir: str, line_length: int) -> None:

# render the code
rendered_contract_code = render_contract_file(contract_name, file_path)
# TODO: if there are no types generated, then this should return None
rendered_types_code = render_types_file(contract_name, file_path)

# Format the generated code using Black
file_names: list[str] = []
# Format the generated code using Black and rite the code to file
formatted_contract_code = apply_black_formatting(rendered_contract_code, line_length)
formatted_types_code = apply_black_formatting(rendered_types_code, line_length)

# Write the code to file
write_string_to_file(f"{contract_path}Contract.py", formatted_contract_code)
write_string_to_file(f"{contract_path}Types.py", formatted_types_code)
file_names.append(f"{contract_name}Contract")

# TODO: write tests for this conditional write.
if rendered_types_code:
formatted_types_code = apply_black_formatting(rendered_types_code, line_length)
write_string_to_file(f"{contract_path}Types.py", formatted_types_code)
file_names.append(f"{contract_name}Types")

return file_names
8 changes: 7 additions & 1 deletion pypechain/render/types.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
"""Functions to render Python types from an abi usng a jinja2 template."""
from __future__ import annotations

from dataclasses import asdict
from pathlib import Path

from pypechain.utilities.abi import get_events_for_abi, get_structs_for_abi, load_abi_from_file
from pypechain.utilities.templates import get_jinja_env


def render_types_file(contract_name: str, abi_file_path: Path) -> str:
def render_types_file(contract_name: str, abi_file_path: Path) -> str | None:
"""Returns the serialized code of the types file to be generated.

Arguments
Expand All @@ -33,8 +35,12 @@ def render_types_file(contract_name: str, abi_file_path: Path) -> str:
structs = [asdict(struct) for struct in structs_list]
events = [asdict(event) for event in get_events_for_abi(abi)]
has_events = bool(events)
has_structs = bool(structs)
has_event_params = any(len(event["inputs"]) > 0 for event in events)

if not has_events and not has_structs:
return None

return types_template.render(
contract_name=contract_name,
structs=structs,
Expand Down
5 changes: 5 additions & 0 deletions pypechain/templates/init.py.jinja2
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
"""Export all types from generated files."""

{% for name in file_names -%}
from .{{name}} import *
{% endfor %}