-
Notifications
You must be signed in to change notification settings - Fork 4
Description
Bug Report
There are two issues:
1. Title: Partial Object Construction (Stepwise Initialization)
Problem Description:
Rosetta functions often populate an output object through multiple set operations. Pydantic's default constructor (used by the legacy _get_rune_object) enforces validation of all required fields immediately. If the object is missing other required fields during the first set operation, Pydantic throws a ValidationError. Additionally, _get_rune_object fails with a KeyError because it cannot resolve classes from the generated _bundle module's namespace.
Note: Invalid Rune is not supported
As with all aspects of the generator, this functionality only applies to valid Rune models. If a model is invalid, it will be discarded before generation. For example, the following is invalid Rune and would be skipped:
type IncompleteObject:
value1 int (1..1)
value2 int (1..1)
func TestIncompleteObjectReturn:
inputs:
value1 int (1..1)
output:
result IncompleteObject (1..1)
set result:
IncompleteObject {
value1: value1
}
Steps to Reproduce:
- Define a Rosetta type with multiple required fields.
- Define a Rosetta function that sets these fields one by one.
- Call the function in Python.
Example Rune code: IncompleteObjects.rosetta
type A:
a1 int (1..1)
a2 int (1..1)
func CreateA:
inputs:
a1 int (1..1)
output:
a A (1..1)
set a->a1: a1
set a->a2: a1 * 2
Test Case:
- Python:
test/python_unit_tests/features/language/test_incomplete_objects.py - Rosetta:
test/python_unit_tests/features/language/IncompleteObjects.rosetta
Other Tests (currently disabled/skipped):
Rune: FunctionTest.rosetta
Python Unit Tests: test_functions_object_creation.py
- def test_create_incomplete_object_succeeds_in_python():
- def test_complex_type_inputs():
Expected Result:
The object should be constructed successfully in steps, with validation deferred until the object is fully populated or explicitly validated.
Actual Result:
The below generated Python produces two errors:
- KeyError:
_get_rune_objectcannot find the model class in therune.runtime.utilsnamespace. - ValidationError: If the class is found, Pydantic fails immediately on the first
setbecause required fields are stillNone.
@replaceable
@validate_call
def rosetta_dsl_test_language_IncompleteObjects_functions_CreateA(a1: int) -> rosetta_dsl_test_language_IncompleteObjects_A:
"""
Parameters
----------
a1 : int
Returns
-------
a : rosetta_dsl.test.language.IncompleteObjects.A
"""
self = inspect.currentframe()
a = _get_rune_object('rosetta_dsl_test_language_IncompleteObjects_A', 'a1', rune_resolve_attr(self, "a1"))
a = set_rune_attr(rune_resolve_attr(self, 'a'), 'a2', (rune_resolve_attr(self, "a1") * 2))
return aAdditional Context:
Partial fix implemented in PythonFunctionGenerator.java by switching to model_construct(), but full removal of _get_rune_object is still pending.
2. Title: Fragile Object Building (Direct Constructors)
The generator relies on a magic _get_rune_object helper which bypasses IDE checks and is hard to debug. This helper attempts to resolve model classes from the global namespace, which is fragile and leads to isolation issues when multiple bundles are present.
Steps to Reproduce:
- Define a Rosetta function that creator a new object (e.g., using
set). - Observe the generated code calling
_get_rune_object.
Example Rune code: (See JUnit Test testComplexSetConstructors)
type ObservationIdentifier:
observable Observable (1..1)
observationDate date (1..1)
func ResolveObservation:
inputs: date date (1..1)
output: identifiers ObservationIdentifier (1..1)
set identifiers -> observationDate:
date
Test Case:
- JUnit:
PythonFunctionTypeTest.testComplexSetConstructors(Disabled)
Expected Result:
The generator should emit direct Python constructor calls (e.g., MyClass(attr=val)) or standard Pydantic methods, providing full IDE support and transparency.
Actual Result:
Generated code uses _get_rune_object(base_model, attribute, value), which is opaque to static analysis.
In some cases, when the generator uses _get_rune_object when it encounters the need to create a new object. This function does not perform as expected, it bypasses IDE checks and is hard to debug.
Proposed Solution:
Refactor PythonFunctionGenerator to use direct Python constructor calls (e.g., MyClass(attr=val)).