Skip to content

Commit 435230c

Browse files
refactor: Reorganize project structure by moving documentation and generator/test files into dedicated subdirectories.
1 parent d6952a9 commit 435230c

8 files changed

Lines changed: 74 additions & 41 deletions

File tree

README.md

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
# Rune Python Generator
77

8-
The Rune Python Generator creates Python code from [Rune](https://github.com/finos/rune-dsl). It fully supports the Rune type syntax and has comprehensive [expression coverage](./EXPRESSION_SUPPORT.md), though function generation is not yet fully implemented.
8+
The Rune Python Generator creates Python code from [Rune](https://github.com/finos/rune-dsl). It fully supports the Rune type syntax and has comprehensive [expression coverage](./docs/EXPRESSION_SUPPORT.md), though function generation is not yet fully implemented.
99

1010
The generated code requires the [RunePythonRuntime](https://github.com/finos/rune-python-runtime) library and Python 3.11+.
1111

@@ -28,21 +28,19 @@ The Renovate bot automatically handles DSL updates by creating a pull request. M
2828
## Repository Organization
2929

3030
- `README.md` - this file, for documentation purposes
31-
- `BUILDANDTEST.md` - instructions on building and testing the repo
3231
- `RELEASE.md` - information about the current release
3332
- `src/main` - Java/Xtend code to generate Python from Rune
3433
- `src/test` - Java/Xtend code to run JUnit tests on the code generation process
35-
- `build` - configuration scripts to setup and tear down the Python unit testing environment
36-
- `build/build_cdm.sh` - used to create a Python package using CDM Rune definitions
37-
- `test` - Python unit tests and scripts to run the tests
34+
- `docs/BUILD_AND_TEST.md` - instructions on building and testing the repo
35+
- `test` - Python unit tests of the generated code
3836

3937
## Development setup
4038

4139
### For developers
4240

4341
This guide is meant for everyone who wants to contribute to the Rune Python Generator and needs to get things up and running.
4442

45-
Detailed build and testing instructions can be found in [BUILDANDTEST.md](./BUILDANDTEST.md)
43+
Detailed build and testing instructions can be found in [docs/BUILD_AND_TEST.md](./docs/BUILD_AND_TEST.md)
4644

4745
Troubleshooting: If you run into issues, please open an [issue](https://github.com/finos/rune-python-generator/issues). This helps us improve the guide for everyone.
4846

@@ -61,7 +59,7 @@ To build the project, run `mvn clean package`.
6159

6260
#### UNIT Testing
6361

64-
Building the project using Maven will run JUNIT-based unit tests. All tests should pass. To run the Python unit tests follow the instructions in [BUILDANDTEST.md](./BUILDANDTEST.md)
62+
Building the project using Maven will run JUNIT-based unit tests. All tests should pass. To run the Python unit tests follow the instructions in [docs/BUILD_AND_TEST.md](./docs/BUILD_AND_TEST.md)
6563

6664
### 2. Setting things up in Eclipse
6765

File renamed without changes.
Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,4 +65,25 @@
6565
| RosettaNumberLiteral || Decimal numeric literal value |[RosettaExpression.xcore#L73](https://github.com/finos/rune-dsl/blob/38dd20e8f3f8145588de7a9586972c84caa23951/rosetta-lang/model/RosettaExpression.xcore#L73) |
6666
| RosettaOnlyElement || Unary list operation asserting the only element |[RosettaExpression.xcore#L300](https://github.com/finos/rune-dsl/blob/38dd20e8f3f8145588de7a9586972c84caa23951/rosetta-lang/model/RosettaExpression.xcore#L300) |
6767
| RosettaOnlyExistsExpression || Checks that only the listed expressions exist |[RosettaExpression.xcore#L247](https://github.com/finos/rune-dsl/blob/38dd20e8f3f8145588de7a9586972c84caa23951/rosetta-lang/model/RosettaExpression.xcore#L247) |
68-
| RosettaReference || Abstract base for reference expressions |[RosettaExpression.xcore#L123](https://github.com/finos/rune-dsl/blob/38dd20e8f3f8145588de7a9586972c84caa23951/rosetta-lang/model/RosettaExpression.xcore#L123) |
68+
| RosettaReference || Abstract base for reference expressions |[RosettaExpression.xcore#L123](https://github.com/finos/rune-dsl/blob/38dd20e8f3f8145588de7a9586972c84caa23951/rosetta-lang/model/RosettaExpression.xcore#L123) |
69+
70+
## Proposed Changes to ExpressionGeneration
71+
72+
The following changes are proposed to enhance the `ExpressionGeneration` functionality and address identified gaps:
73+
74+
1. **Direct Function Calling Support**: Implement support for `RosettaCallableWithArgs` to allow direct execution of other Rosetta functions within an expression.
75+
2. **Date/Time & Math Standards**: Create explicit tests and potentially refine implementation for `ToDate`, `ToDateTime`, `Min`, `Max`, `Sort`, and `Reverse` operations to ensure full compatibility with Python's standard library.
76+
3. **List Operations**: Add comprehensive tests for `JoinOperation` and `ReverseOperation`.
77+
4. **Refined Existence Logic**: Investigate and correctly implement/test the `single exists` and `multiple exists` operators if present in the Rosetta DSL, ensuring they map correctly to Python logic (possibly extending `rune_attr_exists` or `rune_count`).
78+
5. **Clean up `RosettaExistsExpressionTest`**: Enable the disabled tests, add assertions, and migrate relevant test cases to the main test suite if they represent core functionality.
79+
80+
## Evaluation of Current Testing
81+
82+
### PythonExpressionGeneratorTest
83+
- **Coverage**: Strong coverage for arithmetic, boolean logic, basic list operations (`count`, `flatten`), `if-then-else`, and `switch`.
84+
- **Gaps**: Missing specific tests for `To*` conversions (Date/Time), `Min/Max/Sort`, and nested function calls.
85+
86+
### RosettaExistsExpressionTest
87+
- **Status**: Currently disabled (`@Disabled`) and non-functional (no assertions).
88+
- **Analysis**: Contains valuable DSL examples for complex `exists` logic (`only exists`, `single exists`, `multiple exists` combined with `or`/`and`).
89+
- **Plan**: Migrate valid DSL cases to `PythonExpressionGeneratorTest`. Specifically, the complex boolean logic combinations should be asserted against expected Python output to verify that `rune_attr_exists` interacts correctly with Python's `and`/`or` operators. The `single/multiple` exists concepts need to be verified against the `PythonExpressionGenerator` implementation (or lack thereof) to decide if they are supported features or need implementation.

src/main/java/com/regnosys/rosetta/generator/python/PythonCodeGenerator.java

Lines changed: 45 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
package com.regnosys.rosetta.generator.python;
22
// TODO: collect imports as a set rather than an array
3+
34
// TODO: re-engineer type generation to use an object that has the features carried throughout the generation (imports, etc.)
45
// TODO: function support
56
// TODO: review and consolidate unit tests
67
// TODO: review migrating choice alias processor to PythonModelObjectGenerator
78

8-
99
import jakarta.inject.Inject;
1010
import com.regnosys.rosetta.generator.external.AbstractExternalGenerator;
1111
import com.regnosys.rosetta.generator.python.enums.PythonEnumGenerator;
12-
import com.regnosys.rosetta.generator.python.func.PythonFunctionGenerator;
12+
import com.regnosys.rosetta.generator.python.functions.PythonFunctionGenerator;
1313
import com.regnosys.rosetta.generator.python.object.PythonModelObjectGenerator;
1414
import com.regnosys.rosetta.generator.python.util.PythonCodeGeneratorUtil;
1515

@@ -28,38 +28,49 @@
2828
import java.util.stream.Collectors;
2929

3030
/**
31-
* PythonCodeGenerator is an external generator for the Rosetta DSL that produces Python code
32-
* from Rosetta model definitions. It supports the generation of Python classes, enums, and functions
31+
* PythonCodeGenerator is an external generator for the Rosetta DSL that
32+
* produces Python code
33+
* from Rosetta model definitions. It supports the generation of Python classes,
34+
* enums, and functions
3335
* based on the structure and semantics of the input Rosetta models.
3436
* <p>
35-
* This generator is designed to be used as part of the Rosetta code generation pipeline and is
36-
* typically invoked by the Rosetta build tools or CLI. It processes Rosetta models and outputs
37-
* Python source files, including project metadata such as <code>pyproject.toml</code>.
37+
* This generator is designed to be used as part of the Rosetta code generation
38+
* pipeline and is
39+
* typically invoked by the Rosetta build tools or CLI. It processes Rosetta
40+
* models and outputs
41+
* Python source files, including project metadata such as
42+
* <code>pyproject.toml</code>.
3843
* </p>
3944
*
4045
* <h2>Features</h2>
4146
* <ul>
42-
* <li>Generates Python classes from Rosetta Data types</li>
43-
* <li>Generates Python enums from Rosetta enumerations</li>
44-
* <li>Generates Python functions from Rosetta function definitions</li>
45-
* <li>Handles Rosetta model namespaces and organizes output into appropriate Python packages</li>
46-
* <li>Produces project files for Python packaging (e.g., <code>pyproject.toml</code>)</li>
47+
* <li>Generates Python classes from Rosetta Data types</li>
48+
* <li>Generates Python enums from Rosetta enumerations</li>
49+
* <li>Generates Python functions from Rosetta function definitions</li>
50+
* <li>Handles Rosetta model namespaces and organizes output into appropriate
51+
* Python packages</li>
52+
* <li>Produces project files for Python packaging (e.g.,
53+
* <code>pyproject.toml</code>)</li>
4754
* </ul>
4855
*
4956
* <h2>Usage</h2>
5057
* <p>
51-
* Typically, this class is not used directly, but is invoked by the Rosetta code generation
52-
* infrastructure. It can be integrated into build pipelines or called from a CLI tool.
58+
* Typically, this class is not used directly, but is invoked by the Rosetta
59+
* code generation
60+
* infrastructure. It can be integrated into build pipelines or called from a
61+
* CLI tool.
5362
* </p>
5463
*
5564
* <h2>Thread Safety</h2>
5665
* <p>
57-
* This class is not thread-safe and should be used in a single-threaded context.
66+
* This class is not thread-safe and should be used in a single-threaded
67+
* context.
5868
* </p>
5969
*
6070
* <h2>Extensibility</h2>
6171
* <p>
62-
* The generator is designed to be extensible. Additional features or customizations can be
72+
* The generator is designed to be extensible. Additional features or
73+
* customizations can be
6374
* implemented by extending this class or its collaborators.
6475
* </p>
6576
*
@@ -73,20 +84,23 @@ public class PythonCodeGenerator extends AbstractExternalGenerator {
7384

7485
private static final Logger LOGGER = LoggerFactory.getLogger(PythonCodeGenerator.class);
7586

76-
@Inject private PythonModelObjectGenerator pojoGenerator;
77-
@Inject private PythonFunctionGenerator funcGenerator;
78-
@Inject private PythonEnumGenerator enumGenerator;
79-
87+
@Inject
88+
private PythonModelObjectGenerator pojoGenerator;
89+
@Inject
90+
private PythonFunctionGenerator funcGenerator;
91+
@Inject
92+
private PythonEnumGenerator enumGenerator;
93+
8094
private List<String> subfolders;
8195
private Map<String, Map<String, CharSequence>> objects = null; // Python code for types by namespace, by type name
8296

83-
8497
public PythonCodeGenerator() {
8598
super("python");
8699
}
87100

88101
@Override
89-
public Map<String, ? extends CharSequence> beforeAllGenerate(ResourceSet set, Collection<? extends RosettaModel> models, String version) {
102+
public Map<String, ? extends CharSequence> beforeAllGenerate(ResourceSet set,
103+
Collection<? extends RosettaModel> models, String version) {
90104
subfolders = new ArrayList<>();
91105
pojoGenerator.beforeAllGenerate();
92106
objects = new HashMap<>();
@@ -113,9 +127,9 @@ public PythonCodeGenerator() {
113127
.map(Function.class::cast).collect(Collectors.toList());
114128

115129
if (!rosettaClasses.isEmpty() ||
116-
!metaDataItems.isEmpty() ||
117-
!rosettaEnums.isEmpty() ||
118-
!rosettaFunctions.isEmpty()) {
130+
!metaDataItems.isEmpty() ||
131+
!rosettaEnums.isEmpty() ||
132+
!rosettaFunctions.isEmpty()) {
119133
addSubfolder(model.getName());
120134
if (!rosettaFunctions.isEmpty()) {
121135
addSubfolder(model.getName() + ".functions");
@@ -127,8 +141,8 @@ public PythonCodeGenerator() {
127141
String namespace = PythonCodeGeneratorUtil.getNamespace(model);
128142
Map<String, CharSequence> currentObject = objects.get(namespace);
129143
if (currentObject == null) {
130-
currentObject = new HashMap<String, CharSequence>();
131-
objects.put(namespace, currentObject);
144+
currentObject = new HashMap<String, CharSequence>();
145+
objects.put(namespace, currentObject);
132146
}
133147
currentObject.putAll(pojoGenerator.generate(rosettaClasses, cleanVersion));
134148
result.putAll(enumGenerator.generate(rosettaEnums, cleanVersion));
@@ -139,9 +153,9 @@ public PythonCodeGenerator() {
139153

140154
@Override
141155
public Map<String, ? extends CharSequence> afterAllGenerate(
142-
ResourceSet set,
143-
Collection<? extends RosettaModel> models,
144-
String version) {
156+
ResourceSet set,
157+
Collection<? extends RosettaModel> models,
158+
String version) {
145159
String cleanVersion = cleanVersion(version);
146160
Map<String, CharSequence> result = new HashMap<>();
147161

@@ -153,7 +167,7 @@ public PythonCodeGenerator() {
153167
Map<String, CharSequence> currentObject = objects.get(namespace);
154168
if (currentObject != null && !currentObject.isEmpty()) {
155169
result.put("pyproject.toml", PythonCodeGeneratorUtil.createPYProjectTomlFile(namespace, cleanVersion));
156-
result.putAll (pojoGenerator.afterAllGenerate(namespace, currentObject));
170+
result.putAll(pojoGenerator.afterAllGenerate(namespace, currentObject));
157171
}
158172
}
159173
return result;

src/main/java/com/regnosys/rosetta/generator/python/func/FunctionDependencyProvider.xtend renamed to src/main/java/com/regnosys/rosetta/generator/python/functions/FunctionDependencyProvider.xtend

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package com.regnosys.rosetta.generator.python.func;
1+
package com.regnosys.rosetta.generator.python.functions;
22

33
import jakarta.inject.Inject
44
import com.regnosys.rosetta.rosetta.RosettaEnumValueReference

src/main/java/com/regnosys/rosetta/generator/python/func/PythonFunctionGenerator.xtend renamed to src/main/java/com/regnosys/rosetta/generator/python/functions/PythonFunctionGenerator.xtend

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package com.regnosys.rosetta.generator.python.func
1+
package com.regnosys.rosetta.generator.python.functions
22

33
import jakarta.inject.Inject
44
import com.regnosys.rosetta.generator.python.expressions.PythonExpressionGenerator

src/test/java/com/regnosys/rosetta/generator/python/expression/PythonExpressionGeneratorTest.xtend renamed to src/test/java/com/regnosys/rosetta/generator/python/expressions/PythonExpressionGeneratorTest.xtend

File renamed without changes.

src/test/java/com/regnosys/rosetta/generator/python/expression/RosettaExistsExpressionTest.xtend renamed to src/test/java/com/regnosys/rosetta/generator/python/expressions/RosettaExistsExpressionTest.xtend

File renamed without changes.

0 commit comments

Comments
 (0)