Skip to content
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
26 changes: 26 additions & 0 deletions natrix/ast_tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,32 @@ def parse_file(file_path):
return ast


def parse_source(source_code):
"""
Parse Vyper source code directly without requiring a file path.

Args:
source_code: The Vyper source code as a string

Returns:
The parsed AST with metadata
"""
import tempfile

# Create a temporary file to hold the source code
with tempfile.NamedTemporaryFile(mode="w", suffix=".vy", delete=False) as temp_file:
temp_file.write(source_code)
temp_file_path = temp_file.name

try:
# Parse the temporary file
result = parse_file(temp_file_path)
return result
finally:
# Clean up the temporary file
os.unlink(temp_file_path)


class VyperASTVisitor:
def visit(self, node: Node):
ast_type = node.ast_type
Expand Down
36 changes: 35 additions & 1 deletion tests/test_ast_tools.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import subprocess
import re

from natrix.ast_tools import VYPER_VERSION, vyper_compile, parse_file
from natrix.ast_tools import VYPER_VERSION, vyper_compile, parse_file, parse_source


def test_vyper_compile_integration():
Expand Down Expand Up @@ -48,3 +48,37 @@ def test_modules_compilation():
result = vyper_compile(test_file, "annotated_ast")
assert isinstance(result, dict)
assert "ast" in result


def test_parse_source():
# Simple Vyper contract source code
source_code = """
# A simple counter contract
counter: uint256

@external
def increment():
self.counter += 1

@external
@view
def get_counter() -> uint256:
return self.counter
"""

result = parse_source(source_code)

# Check the result structure
assert isinstance(result, dict)
assert "ast" in result
assert "ast_type" in result["ast"]
assert result["ast"]["ast_type"] == "Module"
assert "metadata" in result
assert isinstance(result["metadata"], dict)
assert "function_info" in result["metadata"]

# Check that we have our two functions
functions = result["metadata"]["function_info"]
function_names = [name.split()[0] for name in functions.keys()]
assert "increment" in function_names
assert "get_counter" in function_names
Loading