From a1a07bd1ad801ba172200e5cc85ea4850fd8603e Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
<41898282+github-actions[bot]@users.noreply.github.com>
Date: Wed, 7 Jan 2026 15:59:43 +0000
Subject: [PATCH 01/25] fix(deps): replace xtext.version with
org.eclipse.xtext:xtend-maven-plugin
---
pom.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/pom.xml b/pom.xml
index 3c0f1136..31e0f7e4 100644
--- a/pom.xml
+++ b/pom.xml
@@ -83,7 +83,7 @@
9.75.0
- 2.38.0
+ 2.41.0
6.0.0
2.0.17
From ebd7fd12903faf9dc84feaeee4f1ecca9f98b1a8 Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
<41898282+github-actions[bot]@users.noreply.github.com>
Date: Wed, 7 Jan 2026 16:00:03 +0000
Subject: [PATCH 02/25] chore(deps): update dependency
org.apache.maven.plugins:maven-resources-plugin to v3.4.0
---
pom.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/pom.xml b/pom.xml
index 3c0f1136..723daf9b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -105,7 +105,7 @@
3.1.1
1.6.13
3.2.8
- 3.3.1
+ 3.4.0
build/common-domain-model/rosetta-source/src/main/rosetta
target/python-cdm
From 394400db920a4ba52571ba7b6eb7c03cb3ab9795 Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
<41898282+github-actions[bot]@users.noreply.github.com>
Date: Wed, 7 Jan 2026 16:00:18 +0000
Subject: [PATCH 03/25] fix(deps): update dependency
org.apache.commons:commons-lang3 to v3.20.0
---
pom.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/pom.xml b/pom.xml
index 3c0f1136..82c2e6b2 100644
--- a/pom.xml
+++ b/pom.xml
@@ -71,7 +71,7 @@
[21,22)
21
- 3.19.0
+ 3.20.0
1.11.0
2.21.0
33.3.1-jre
From afe186856ea400214fc110f254b7ef05d6b9db8c Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
<41898282+github-actions[bot]@users.noreply.github.com>
Date: Wed, 7 Jan 2026 16:00:22 +0000
Subject: [PATCH 04/25] fix(deps): update dependency
org.apache.commons:commons-text to v1.15.0
---
pom.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/pom.xml b/pom.xml
index 3c0f1136..83d92b7b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -72,7 +72,7 @@
21
3.19.0
- 1.11.0
+ 1.15.0
2.21.0
33.3.1-jre
From 3d20728a37dac27a37b6bd4e45c8e3d0df60a1ba Mon Sep 17 00:00:00 2001
From: dschwartznyc
Date: Thu, 22 Jan 2026 18:20:14 -0500
Subject: [PATCH 05/25] chore: remove renovate.yml
---
.github/workflows/renovate.yml | 38 ----------------------------------
1 file changed, 38 deletions(-)
delete mode 100644 .github/workflows/renovate.yml
diff --git a/.github/workflows/renovate.yml b/.github/workflows/renovate.yml
deleted file mode 100644
index 205db572..00000000
--- a/.github/workflows/renovate.yml
+++ /dev/null
@@ -1,38 +0,0 @@
-# .github/workflows/renovate.yml
-# This workflow runs Renovate Bot on a schedule or on demand.
-# It uses the configuration file located at .github/renovate.json
-
-name: Renovate
-
-on:
- # Allows you to run this workflow manually from the Actions tab
- workflow_dispatch:
- # Runs the workflow on a schedule (e.g., every day at 2 AM)
- schedule:
- - cron: '0 2 * * *'
- push:
- paths:
- - .github/renovate.json
- - .github/workflows/renovate.yml
-
-jobs:
- renovate:
- runs-on: ubuntu-latest
- # 👇 Expanded permissions so Renovate can do everything it needs
- permissions:
- contents: write # push branches, update files
- pull-requests: write # open/update PRs
- issues: write # create/update Dependency Dashboard issue
- security-events: read # read Dependabot vulnerability alerts
- steps:
- # Checks out the repository under $GITHUB_WORKSPACE
- - uses: actions/checkout@v6
-
- # Runs the Renovate GitHub Action
- - name: Renovate
- uses: renovatebot/github-action@v44.2.5
- with:
- token: ${{ secrets.GITHUB_TOKEN }} # required to create PRs/issues
- configurationFile: .github/renovate.json
- env:
- RENOVATE_REPOSITORIES: ${{ github.repository }} # scan current repo
\ No newline at end of file
From c16fa9c6dd844a529e23864a10a158555074bb16 Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
<41898282+github-actions[bot]@users.noreply.github.com>
Date: Mon, 26 Jan 2026 02:57:34 +0000
Subject: [PATCH 06/25] fix(deps): update logback monorepo to v1.5.26
---
pom.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/pom.xml b/pom.xml
index 45bf49c8..3efcdcb1 100644
--- a/pom.xml
+++ b/pom.xml
@@ -87,7 +87,7 @@
6.0.0
2.0.17
- 1.5.21
+ 1.5.26
6.0.1
From 341c03424ed39064f0fbe4426bddf4e120c9fb6a Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Mon, 26 Jan 2026 16:21:37 +0000
Subject: [PATCH 07/25] fix(deps): update dependency org.junit:junit-bom to
v6.0.2
---
pom.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/pom.xml b/pom.xml
index 45bf49c8..de9bc6af 100644
--- a/pom.xml
+++ b/pom.xml
@@ -90,7 +90,7 @@
1.5.21
- 6.0.1
+ 6.0.2
3.0
From cb65b65923ac89d48cc6c59b8668c17f372e9b52 Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Thu, 5 Feb 2026 14:56:54 +0000
Subject: [PATCH 08/25] fix(deps): update rosetta.dsl.version to v9.76.1
---
pom.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/pom.xml b/pom.xml
index de9bc6af..3d732cb3 100644
--- a/pom.xml
+++ b/pom.xml
@@ -81,7 +81,7 @@
s01.oss.sonatype.org
20
- 9.75.3
+ 9.76.1
2.38.0
6.0.0
From dc9e25207e686ed88782aecf9c57689ed7af1ac6 Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Fri, 6 Feb 2026 21:44:32 +0000
Subject: [PATCH 09/25] chore(deps): update dependency
org.apache.maven.plugins:maven-compiler-plugin to v3.15.0
---
pom.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/pom.xml b/pom.xml
index 3d732cb3..a050f154 100644
--- a/pom.xml
+++ b/pom.xml
@@ -97,7 +97,7 @@
3.6.2
3.6.0
3.5.0
- 3.14.1
+ 3.15.0
3.5.4
3.1.1
3.1.4
From 4248283244a00722e96ee2b940ac011dcca216a3 Mon Sep 17 00:00:00 2001
From: dschwartznyc
Date: Sun, 8 Feb 2026 15:17:47 -0500
Subject: [PATCH 10/25] feat: Refactor CLI to return exit codes and add options
for validation error/warning handling, accompanied by new unit tests.
---
.../python/PythonCodeGeneratorCLI.java | 73 ++++++---
.../python/PythonCodeGeneratorCLITest.java | 146 ++++++++++++++++++
2 files changed, 195 insertions(+), 24 deletions(-)
create mode 100644 src/test/java/com/regnosys/rosetta/generator/python/PythonCodeGeneratorCLITest.java
diff --git a/src/main/java/com/regnosys/rosetta/generator/python/PythonCodeGeneratorCLI.java b/src/main/java/com/regnosys/rosetta/generator/python/PythonCodeGeneratorCLI.java
index 71604890..d98f4b21 100644
--- a/src/main/java/com/regnosys/rosetta/generator/python/PythonCodeGeneratorCLI.java
+++ b/src/main/java/com/regnosys/rosetta/generator/python/PythonCodeGeneratorCLI.java
@@ -79,6 +79,10 @@ public class PythonCodeGeneratorCLI {
private static final Logger LOGGER = LoggerFactory.getLogger(PythonCodeGeneratorCLI.class);
public static void main(String[] args) {
+ System.exit(new PythonCodeGeneratorCLI().execute(args));
+ }
+
+ public int execute(String[] args) {
System.out.println("***** Running PythonCodeGeneratorCLI v2 *****");
Options options = new Options();
Option help = new Option("h", "Print usage");
@@ -88,33 +92,44 @@ public static void main(String[] args) {
.build();
Option tgtDirOpt = Option.builder("t").longOpt("tgt").argName("tgtDir")
.desc("Target Python directory (default: ./python)").hasArg().build();
+ Option allowErrorsOpt = Option.builder("e").longOpt("allow-errors")
+ .desc("Continue generation even if validation errors occur").build();
+ Option failOnWarningsOpt = Option.builder("w").longOpt("fail-on-warnings")
+ .desc("Treat validation warnings as errors").build();
options.addOption(help);
options.addOption(srcDirOpt);
options.addOption(srcFileOpt);
options.addOption(tgtDirOpt);
+ options.addOption(allowErrorsOpt);
+ options.addOption(failOnWarningsOpt);
CommandLineParser parser = new DefaultParser();
try {
CommandLine cmd = parser.parse(options, args);
if (cmd.hasOption("h")) {
printUsage(options);
- return;
+ return 0;
}
String tgtDir = cmd.getOptionValue("t", "./python");
+ boolean allowErrors = cmd.hasOption("e");
+ boolean failOnWarnings = cmd.hasOption("w");
+
if (cmd.hasOption("s")) {
String srcDir = cmd.getOptionValue("s");
- translateFromSourceDir(srcDir, tgtDir);
+ return translateFromSourceDir(srcDir, tgtDir, allowErrors, failOnWarnings);
} else if (cmd.hasOption("f")) {
String srcFile = cmd.getOptionValue("f");
- translateFromSourceFile(srcFile, tgtDir);
+ return translateFromSourceFile(srcFile, tgtDir, allowErrors, failOnWarnings);
} else {
System.err.println("Either a source directory (-s) or source file (-f) must be specified.");
printUsage(options);
+ return 1;
}
} catch (ParseException e) {
System.err.println("Failed to parse command line arguments: " + e.getMessage());
printUsage(options);
+ return 1;
}
}
@@ -123,53 +138,59 @@ private static void printUsage(Options options) {
formatter.printHelp("PythonCodeGeneratorCLI", options, true);
}
- private static void translateFromSourceDir(String srcDir, String tgtDir) {
+ protected int translateFromSourceDir(String srcDir, String tgtDir, boolean allowErrors, boolean failOnWarnings) {
// Find all .rosetta files in a directory
Path srcDirPath = Paths.get(srcDir);
if (!Files.exists(srcDirPath)) {
LOGGER.error("Source directory does not exist: {}", srcDir);
- System.exit(1);
+ return 1;
}
if (!Files.isDirectory(srcDirPath)) {
LOGGER.error("Source directory is not a directory: {}", srcDir);
- System.exit(1);
+ return 1;
}
try {
List rosettaFiles = Files.walk(srcDirPath)
.filter(Files::isRegularFile)
.filter(f -> f.getFileName().toString().endsWith(".rosetta"))
.collect(Collectors.toList());
- processRosettaFiles(rosettaFiles, tgtDir);
+ return processRosettaFiles(rosettaFiles, tgtDir, allowErrors, failOnWarnings);
} catch (IOException e) {
LOGGER.error("Failed to process source directory: {}", srcDir, e);
+ return 1;
}
}
- private static void translateFromSourceFile(String srcFile, String tgtDir) {
+ protected int translateFromSourceFile(String srcFile, String tgtDir, boolean allowErrors, boolean failOnWarnings) {
Path srcFilePath = Paths.get(srcFile);
if (!Files.exists(srcFilePath)) {
LOGGER.error("Source file does not exist: {}", srcFile);
- System.exit(1);
+ return 1;
}
if (Files.isDirectory(srcFilePath)) {
LOGGER.error("Source file is a directory: {}", srcFile);
- System.exit(1);
+ return 1;
}
if (!srcFilePath.toString().endsWith(".rosetta")) {
LOGGER.error("Source file does not end with .rosetta: {}", srcFile);
- System.exit(1);
+ return 1;
}
List rosettaFiles = List.of(srcFilePath);
- processRosettaFiles(rosettaFiles, tgtDir);
+ return processRosettaFiles(rosettaFiles, tgtDir, allowErrors, failOnWarnings);
+ }
+
+ protected IResourceValidator getValidator(Injector injector) {
+ return injector.getInstance(IResourceValidator.class);
}
// Common processing function
- private static void processRosettaFiles(List rosettaFiles, String tgtDir) {
+ protected int processRosettaFiles(List rosettaFiles, String tgtDir, boolean allowErrors,
+ boolean failOnWarnings) {
LOGGER.info("Processing {} .rosetta files, writing to: {}", rosettaFiles.size(), tgtDir);
if (rosettaFiles.isEmpty()) {
System.err.println("No .rosetta files found to process.");
- System.exit(1);
+ return 1;
}
Injector injector = new PythonRosettaStandaloneSetup().createInjectorAndDoEMFRegistration();
@@ -188,13 +209,13 @@ private static void processRosettaFiles(List rosettaFiles, String tgtDir)
List models = modelLoader.getRosettaModels(resources);
if (models.isEmpty()) {
LOGGER.error("No valid Rosetta models found.");
- System.exit(1);
+ return 1;
}
String version = models.getFirst().getVersion();
LOGGER.info("Processing {} models, version: {}", models.size(), version);
- IResourceValidator validator = injector.getInstance(IResourceValidator.class);
+ IResourceValidator validator = getValidator(injector);
Map generatedPython = new HashMap<>();
List validModels = new ArrayList<>();
@@ -235,6 +256,9 @@ private static void processRosettaFiles(List rosettaFiles, String tgtDir)
case WARNING:
LOGGER.warn("Validation WARNING in {} (Line {}): {}", model.getName(),
issue.getLineNumber(), issue.getMessage());
+ if (failOnWarnings) {
+ hasErrors = true;
+ }
break;
default:
break;
@@ -246,24 +270,23 @@ private static void processRosettaFiles(List rosettaFiles, String tgtDir)
continue;
}
- if (hasErrors) {
- LOGGER.error("Skipping model {} due to validation errors.", model.getName());
+ if (hasErrors && !allowErrors) {
+ LOGGER.error("Skipping model {} due to validation errors (allowErrors=false).", model.getName());
} else {
+ if (hasErrors) {
+ LOGGER.warn("Proceeding with model {} despite validation errors (allowErrors=true).",
+ model.getName());
+ }
validModels.add(model);
}
}
if (validModels.isEmpty()) {
LOGGER.error("No valid models found after validation. Exiting.");
- System.exit(1);
+ return 1;
}
// Use validModels for generation
- // Re-determine version based on valid models? Or keep original version?
- // Assuming version is consistent across all loaded models or derived from the
- // first one.
- // The original code took version from models.getFirst().getVersion();
-
LOGGER.info("Proceeding with generation for {} valid models.", validModels.size());
pythonCodeGenerator.beforeAllGenerate(resourceSet, validModels, version);
@@ -276,6 +299,7 @@ private static void processRosettaFiles(List rosettaFiles, String tgtDir)
generatedPython.putAll(pythonCodeGenerator.afterAllGenerate(resourceSet, models, version));
writePythonFiles(generatedPython, tgtDir);
+ return 0;
}
private static void writePythonFiles(Map generatedPython, String tgtDir) {
@@ -356,4 +380,5 @@ public Injector createInjector() {
return Guice.createInjector(new PythonRosettaRuntimeModule());
}
}
+
}
\ No newline at end of file
diff --git a/src/test/java/com/regnosys/rosetta/generator/python/PythonCodeGeneratorCLITest.java b/src/test/java/com/regnosys/rosetta/generator/python/PythonCodeGeneratorCLITest.java
new file mode 100644
index 00000000..7366ee3a
--- /dev/null
+++ b/src/test/java/com/regnosys/rosetta/generator/python/PythonCodeGeneratorCLITest.java
@@ -0,0 +1,146 @@
+package com.regnosys.rosetta.generator.python;
+
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import org.eclipse.emf.ecore.util.EcoreUtil;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+class PythonCodeGeneratorCLITest {
+
+ @TempDir
+ Path tempDir;
+
+ @Test
+ void testMissingArgsReturnsError() {
+ PythonCodeGeneratorCLI cli = new PythonCodeGeneratorCLI();
+ int exitCode = cli.execute(new String[] {});
+ assertEquals(1, exitCode, "Should return 1 when no args provided");
+ }
+
+ @Test
+ void testHelpReturnsSuccess() {
+ PythonCodeGeneratorCLI cli = new PythonCodeGeneratorCLI();
+ int exitCode = cli.execute(new String[] { "-h" });
+ assertEquals(0, exitCode, "Should return 0 when help is requested");
+ }
+
+ @Test
+ void testInvalidSourceFileReturnsError() {
+ PythonCodeGeneratorCLI cli = new PythonCodeGeneratorCLI();
+ int exitCode = cli.execute(new String[] { "-f", "non_existent_file.rosetta" });
+ assertEquals(1, exitCode, "Should return 1 when source file does not exist");
+ }
+
+ @Test
+ void testValidationErrorsFailByDefault() throws IOException {
+ Path validFile = createValidRosettaFile(tempDir); // Use valid file, let MockValidator inject error
+ TestCLI cli = new TestCLI();
+ cli.mockValidator.setReturnError(true);
+
+ int exitCode = cli.execute(new String[] {
+ "-f", validFile.toString(),
+ "-t", tempDir.resolve("python").toString()
+ });
+
+ assertEquals(1, exitCode, "Should return 1 (fail) when validation errors occur by default");
+ }
+
+ @Test
+ void testAllowErrorsPasses() throws IOException {
+ Path validFile = createValidRosettaFile(tempDir);
+ TestCLI cli = new TestCLI();
+ cli.mockValidator.setReturnError(true);
+
+ int exitCode = cli.execute(new String[] {
+ "-f", validFile.toString(),
+ "-t", tempDir.resolve("python").toString(),
+ "-e"
+ });
+
+ assertEquals(0, exitCode, "Should return 0 (success) when validation errors occur but --allow-errors is set");
+ }
+
+ @Test
+ void testWarningsFailWithFlag() throws IOException {
+ Path validFile = createValidRosettaFile(tempDir);
+ TestCLI cli = new TestCLI();
+ cli.mockValidator.setReturnWarning(true);
+
+ int exitCode = cli.execute(new String[] {
+ "-f", validFile.toString(),
+ "-t", tempDir.resolve("python").toString(),
+ "-w" // --fail-on-warnings
+ });
+
+ assertEquals(1, exitCode, "Should return 1 (fail) when warnings occur and --fail-on-warnings is set");
+ }
+
+ private Path createValidRosettaFile(Path dir) throws IOException {
+ Path file = dir.resolve("valid.rosetta");
+ String content = "namespace test.model\nversion \"1.0.0\"\ntype Foo:\n attr string (1..1)\n";
+ Files.writeString(file, content);
+ return file;
+ }
+
+ // --- Mocks ---
+
+ static class TestCLI extends PythonCodeGeneratorCLI {
+ MockValidator mockValidator = new MockValidator();
+
+ @Override
+ protected org.eclipse.xtext.validation.IResourceValidator getValidator(com.google.inject.Injector injector) {
+ return mockValidator;
+ }
+ }
+
+ static class MockValidator implements org.eclipse.xtext.validation.IResourceValidator {
+ private boolean returnError = false;
+ private boolean returnWarning = false;
+
+ public void setReturnError(boolean returnError) {
+ this.returnError = returnError;
+ }
+
+ public void setReturnWarning(boolean returnWarning) {
+ this.returnWarning = returnWarning;
+ }
+
+ @Override
+ public java.util.List validate(
+ org.eclipse.emf.ecore.resource.Resource resource,
+ org.eclipse.xtext.validation.CheckMode mode, org.eclipse.xtext.util.CancelIndicator indicator) {
+ java.util.List issues = new java.util.ArrayList<>();
+
+ org.eclipse.emf.common.util.URI uri = null;
+ if (!resource.getContents().isEmpty()) {
+ org.eclipse.emf.ecore.EObject root = resource.getContents().get(0);
+ uri = EcoreUtil.getURI(root);
+ } else {
+ uri = org.eclipse.emf.common.util.URI.createURI("dummy#//");
+ }
+
+ if (returnError) {
+ issues.add(createIssue(org.eclipse.xtext.diagnostics.Severity.ERROR, "Mock Error", uri));
+ }
+ if (returnWarning) {
+ issues.add(createIssue(org.eclipse.xtext.diagnostics.Severity.WARNING, "Mock Warning", uri));
+ }
+ return issues;
+ }
+
+ private org.eclipse.xtext.validation.Issue createIssue(org.eclipse.xtext.diagnostics.Severity severity,
+ String message, org.eclipse.emf.common.util.URI uri) {
+ org.eclipse.xtext.validation.Issue.IssueImpl issue = new org.eclipse.xtext.validation.Issue.IssueImpl();
+ issue.setSeverity(severity);
+ issue.setMessage(message);
+ issue.setLineNumber(1);
+ issue.setUriToProblem(uri);
+ return issue;
+ }
+ }
+}
From ef951cf49f9a98942f2c4f78025d4140b82a73ba Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Wed, 18 Feb 2026 19:31:51 +0000
Subject: [PATCH 11/25] fix(deps): update rosetta.dsl.version to v9.76.2
---
pom.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/pom.xml b/pom.xml
index a050f154..26fe3778 100644
--- a/pom.xml
+++ b/pom.xml
@@ -81,7 +81,7 @@
s01.oss.sonatype.org
20
- 9.76.1
+ 9.76.2
2.38.0
6.0.0
From 086081be8047cf2c5ab762704a4f05f5d3fe4d45 Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Thu, 19 Feb 2026 10:01:33 +0000
Subject: [PATCH 12/25] fix(deps): update rosetta.dsl.version to v9.77.0
---
pom.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/pom.xml b/pom.xml
index 26fe3778..8fa7cd46 100644
--- a/pom.xml
+++ b/pom.xml
@@ -81,7 +81,7 @@
s01.oss.sonatype.org
20
- 9.76.2
+ 9.77.0
2.38.0
6.0.0
From aa89132544b7566b8e99c1378bef37c8a9145735 Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Thu, 19 Feb 2026 15:15:37 +0000
Subject: [PATCH 13/25] fix(deps): update dependency org.jetbrains:annotations
to v26.1.0
---
pom.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/pom.xml b/pom.xml
index 8fa7cd46..fbde9371 100644
--- a/pom.xml
+++ b/pom.xml
@@ -294,7 +294,7 @@
org.jetbrains
annotations
- 26.0.2-1
+ 26.1.0
compile
From edd05ba5b6ccee502fa103967151967016d69244 Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Thu, 19 Feb 2026 21:17:25 +0000
Subject: [PATCH 14/25] fix(deps): update dependency org.junit:junit-bom to
v6.0.3
---
pom.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/pom.xml b/pom.xml
index fbde9371..07771065 100644
--- a/pom.xml
+++ b/pom.xml
@@ -90,7 +90,7 @@
1.5.21
- 6.0.2
+ 6.0.3
3.0
From 712ec5be2379d663573de334dfbcfe0e8f697e95 Mon Sep 17 00:00:00 2001
From: dschwartznyc
Date: Thu, 19 Feb 2026 18:08:01 -0500
Subject: [PATCH 15/25] fix: updated JUnit and Python Unit tests to not use
Functions since those features have not been implemented yet
---
.../python/PythonCodeGeneratorCLITest.java | 13 +
.../RosettaOnlyExistsExpressionTest.java | 3 +
.../expressions/RosettaShortcutTest.java | 2 +
.../PythonFunctionAccumulationTest.java | 2 +
.../functions/PythonFunctionAliasTest.java | 2 +
.../functions/PythonFunctionBasicTest.java | 2 +
.../PythonFunctionConditionTest.java | 2 +
.../PythonFunctionControlFlowTest.java | 2 +
.../functions/PythonFunctionOrderTest.java | 2 +
.../functions/PythonFunctionTypeTest.java | 2 +
.../rule/PythonDataRuleGeneratorTest.java | 3 +
.../features/TestEnumUsage.rosetta | 14 +-
.../features/collections/Collections.rosetta | 43 ++--
.../collections/ListExtensions.rosetta | 72 +++---
.../collections/test_list_extensions.py | 62 ++---
.../collections/test_list_operators.py | 16 +-
.../expressions/ConditionalExpression.rosetta | 28 +-
.../features/expressions/SwitchOp.rosetta | 17 +-
.../expressions/TypeConversion.rosetta | 24 +-
.../test_conditional_expression.py | 18 +-
.../features/expressions/test_switch_op.py | 10 +-
.../expressions/test_type_conversion.py | 24 +-
.../features/functions/AddOperation.rosetta | 17 --
.../features/functions/FunctionTest.rosetta | 240 ------------------
.../features/functions/OrderTest.rosetta | 15 --
.../features/functions/test_functions_abs.py | 42 ---
.../functions/test_functions_add_operation.py | 20 --
.../functions/test_functions_alias.py | 25 --
.../functions/test_functions_arithmetic.py | 12 -
.../features/functions/test_functions_call.py | 6 -
.../functions/test_functions_conditions.py | 24 --
.../functions/test_functions_metadata.py | 13 -
.../test_functions_object_creation.py | 86 -------
.../functions/test_functions_order.py | 19 --
.../functions/test_local_conditions.py | 51 ----
.../features/language/test_enum_usage.py | 9 +-
.../model_structure/Inheritance.rosetta | 9 +-
.../model_structure/test_inheritance.py | 9 +-
.../features/operators/ComparisonOp.rosetta | 46 +---
.../operators/ComplexBooleanLogic.rosetta | 30 +--
.../operators/test_comparison_operators.py | 50 ++--
.../operators/test_complex_boolean_logic.py | 33 ++-
.../features/robustness/NullHandling.rosetta | 24 +-
.../features/robustness/test_null_handling.py | 19 +-
44 files changed, 266 insertions(+), 896 deletions(-)
delete mode 100644 test/python_unit_tests/features/functions/AddOperation.rosetta
delete mode 100644 test/python_unit_tests/features/functions/FunctionTest.rosetta
delete mode 100644 test/python_unit_tests/features/functions/OrderTest.rosetta
delete mode 100644 test/python_unit_tests/features/functions/test_functions_abs.py
delete mode 100644 test/python_unit_tests/features/functions/test_functions_add_operation.py
delete mode 100644 test/python_unit_tests/features/functions/test_functions_alias.py
delete mode 100644 test/python_unit_tests/features/functions/test_functions_arithmetic.py
delete mode 100644 test/python_unit_tests/features/functions/test_functions_call.py
delete mode 100644 test/python_unit_tests/features/functions/test_functions_conditions.py
delete mode 100644 test/python_unit_tests/features/functions/test_functions_metadata.py
delete mode 100644 test/python_unit_tests/features/functions/test_functions_object_creation.py
delete mode 100644 test/python_unit_tests/features/functions/test_functions_order.py
delete mode 100644 test/python_unit_tests/features/functions/test_local_conditions.py
diff --git a/src/test/java/com/regnosys/rosetta/generator/python/PythonCodeGeneratorCLITest.java b/src/test/java/com/regnosys/rosetta/generator/python/PythonCodeGeneratorCLITest.java
index 7366ee3a..5ff024a9 100644
--- a/src/test/java/com/regnosys/rosetta/generator/python/PythonCodeGeneratorCLITest.java
+++ b/src/test/java/com/regnosys/rosetta/generator/python/PythonCodeGeneratorCLITest.java
@@ -1,5 +1,7 @@
package com.regnosys.rosetta.generator.python;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
@@ -15,6 +17,17 @@ class PythonCodeGeneratorCLITest {
@TempDir
Path tempDir;
+ @BeforeAll
+ static void setup() {
+ System.out.println(
+ ">>> Starting PythonCodeGeneratorCLITest. Expected error and warning logs may follow as part of validation testing.");
+ }
+
+ @AfterAll
+ static void tearDown() {
+ System.out.println(">>> Finished PythonCodeGeneratorCLITest.");
+ }
+
@Test
void testMissingArgsReturnsError() {
PythonCodeGeneratorCLI cli = new PythonCodeGeneratorCLI();
diff --git a/src/test/java/com/regnosys/rosetta/generator/python/expressions/RosettaOnlyExistsExpressionTest.java b/src/test/java/com/regnosys/rosetta/generator/python/expressions/RosettaOnlyExistsExpressionTest.java
index 3c0923e1..4f0278f8 100644
--- a/src/test/java/com/regnosys/rosetta/generator/python/expressions/RosettaOnlyExistsExpressionTest.java
+++ b/src/test/java/com/regnosys/rosetta/generator/python/expressions/RosettaOnlyExistsExpressionTest.java
@@ -2,6 +2,7 @@
import org.eclipse.xtext.testing.InjectWith;
import org.eclipse.xtext.testing.extensions.InjectionExtension;
+import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
@@ -10,6 +11,7 @@
import jakarta.inject.Inject;
+@Disabled("Functions are being phased out in tests.")
@ExtendWith(InjectionExtension.class)
@InjectWith(RosettaInjectorProvider.class)
public class RosettaOnlyExistsExpressionTest {
@@ -18,6 +20,7 @@ public class RosettaOnlyExistsExpressionTest {
private PythonGeneratorTestUtils testUtils;
@Test
+ @Disabled("Functions are being phased out in tests.")
public void testOnlyExistsSinglePath() {
testUtils.assertBundleContainsExpectedString("""
type A:
diff --git a/src/test/java/com/regnosys/rosetta/generator/python/expressions/RosettaShortcutTest.java b/src/test/java/com/regnosys/rosetta/generator/python/expressions/RosettaShortcutTest.java
index 2aa79516..b6d9eba8 100644
--- a/src/test/java/com/regnosys/rosetta/generator/python/expressions/RosettaShortcutTest.java
+++ b/src/test/java/com/regnosys/rosetta/generator/python/expressions/RosettaShortcutTest.java
@@ -2,6 +2,7 @@
import org.eclipse.xtext.testing.InjectWith;
import org.eclipse.xtext.testing.extensions.InjectionExtension;
+import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
@@ -10,6 +11,7 @@
import jakarta.inject.Inject;
+@Disabled("Functions are being phased out in tests.")
@ExtendWith(InjectionExtension.class)
@InjectWith(RosettaInjectorProvider.class)
public class RosettaShortcutTest {
diff --git a/src/test/java/com/regnosys/rosetta/generator/python/functions/PythonFunctionAccumulationTest.java b/src/test/java/com/regnosys/rosetta/generator/python/functions/PythonFunctionAccumulationTest.java
index ddb95a87..9f3cc568 100644
--- a/src/test/java/com/regnosys/rosetta/generator/python/functions/PythonFunctionAccumulationTest.java
+++ b/src/test/java/com/regnosys/rosetta/generator/python/functions/PythonFunctionAccumulationTest.java
@@ -4,11 +4,13 @@
import com.regnosys.rosetta.tests.RosettaInjectorProvider;
import org.eclipse.xtext.testing.InjectWith;
import org.eclipse.xtext.testing.extensions.InjectionExtension;
+import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import jakarta.inject.Inject;
import java.util.Map;
+@Disabled("Functions are being phased out in tests.")
@ExtendWith(InjectionExtension.class)
@InjectWith(RosettaInjectorProvider.class)
public class PythonFunctionAccumulationTest {
diff --git a/src/test/java/com/regnosys/rosetta/generator/python/functions/PythonFunctionAliasTest.java b/src/test/java/com/regnosys/rosetta/generator/python/functions/PythonFunctionAliasTest.java
index cd74b7da..636312ba 100644
--- a/src/test/java/com/regnosys/rosetta/generator/python/functions/PythonFunctionAliasTest.java
+++ b/src/test/java/com/regnosys/rosetta/generator/python/functions/PythonFunctionAliasTest.java
@@ -4,11 +4,13 @@
import com.regnosys.rosetta.tests.RosettaInjectorProvider;
import org.eclipse.xtext.testing.InjectWith;
import org.eclipse.xtext.testing.extensions.InjectionExtension;
+import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import jakarta.inject.Inject;
import java.util.Map;
+@Disabled("Functions are being phased out in tests.")
@ExtendWith(InjectionExtension.class)
@InjectWith(RosettaInjectorProvider.class)
public class PythonFunctionAliasTest {
diff --git a/src/test/java/com/regnosys/rosetta/generator/python/functions/PythonFunctionBasicTest.java b/src/test/java/com/regnosys/rosetta/generator/python/functions/PythonFunctionBasicTest.java
index af6302c6..7a67d1cd 100644
--- a/src/test/java/com/regnosys/rosetta/generator/python/functions/PythonFunctionBasicTest.java
+++ b/src/test/java/com/regnosys/rosetta/generator/python/functions/PythonFunctionBasicTest.java
@@ -4,11 +4,13 @@
import com.regnosys.rosetta.tests.RosettaInjectorProvider;
import org.eclipse.xtext.testing.InjectWith;
import org.eclipse.xtext.testing.extensions.InjectionExtension;
+import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import jakarta.inject.Inject;
import java.util.Map;
+@Disabled("Functions are being phased out in tests.")
@ExtendWith(InjectionExtension.class)
@InjectWith(RosettaInjectorProvider.class)
public class PythonFunctionBasicTest {
diff --git a/src/test/java/com/regnosys/rosetta/generator/python/functions/PythonFunctionConditionTest.java b/src/test/java/com/regnosys/rosetta/generator/python/functions/PythonFunctionConditionTest.java
index a1dcef35..8b78aeaa 100644
--- a/src/test/java/com/regnosys/rosetta/generator/python/functions/PythonFunctionConditionTest.java
+++ b/src/test/java/com/regnosys/rosetta/generator/python/functions/PythonFunctionConditionTest.java
@@ -4,11 +4,13 @@
import com.regnosys.rosetta.tests.RosettaInjectorProvider;
import org.eclipse.xtext.testing.InjectWith;
import org.eclipse.xtext.testing.extensions.InjectionExtension;
+import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import jakarta.inject.Inject;
import java.util.Map;
+@Disabled("Functions are being phased out in tests.")
@ExtendWith(InjectionExtension.class)
@InjectWith(RosettaInjectorProvider.class)
public class PythonFunctionConditionTest {
diff --git a/src/test/java/com/regnosys/rosetta/generator/python/functions/PythonFunctionControlFlowTest.java b/src/test/java/com/regnosys/rosetta/generator/python/functions/PythonFunctionControlFlowTest.java
index efe25c77..1ca81c50 100644
--- a/src/test/java/com/regnosys/rosetta/generator/python/functions/PythonFunctionControlFlowTest.java
+++ b/src/test/java/com/regnosys/rosetta/generator/python/functions/PythonFunctionControlFlowTest.java
@@ -4,11 +4,13 @@
import com.regnosys.rosetta.tests.RosettaInjectorProvider;
import org.eclipse.xtext.testing.InjectWith;
import org.eclipse.xtext.testing.extensions.InjectionExtension;
+import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import jakarta.inject.Inject;
import java.util.Map;
+@Disabled("Functions are being phased out in tests.")
@ExtendWith(InjectionExtension.class)
@InjectWith(RosettaInjectorProvider.class)
public class PythonFunctionControlFlowTest {
diff --git a/src/test/java/com/regnosys/rosetta/generator/python/functions/PythonFunctionOrderTest.java b/src/test/java/com/regnosys/rosetta/generator/python/functions/PythonFunctionOrderTest.java
index c6a6c2b7..1142e216 100644
--- a/src/test/java/com/regnosys/rosetta/generator/python/functions/PythonFunctionOrderTest.java
+++ b/src/test/java/com/regnosys/rosetta/generator/python/functions/PythonFunctionOrderTest.java
@@ -4,6 +4,7 @@
import com.regnosys.rosetta.tests.RosettaInjectorProvider;
import org.eclipse.xtext.testing.InjectWith;
import org.eclipse.xtext.testing.extensions.InjectionExtension;
+import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import jakarta.inject.Inject;
@@ -11,6 +12,7 @@
import static org.junit.jupiter.api.Assertions.assertTrue;
import org.junit.jupiter.api.Disabled;
+@Disabled("Functions are being phased out in tests.")
@ExtendWith(InjectionExtension.class)
@InjectWith(RosettaInjectorProvider.class)
public class PythonFunctionOrderTest {
diff --git a/src/test/java/com/regnosys/rosetta/generator/python/functions/PythonFunctionTypeTest.java b/src/test/java/com/regnosys/rosetta/generator/python/functions/PythonFunctionTypeTest.java
index 28c74b93..c8f0111a 100644
--- a/src/test/java/com/regnosys/rosetta/generator/python/functions/PythonFunctionTypeTest.java
+++ b/src/test/java/com/regnosys/rosetta/generator/python/functions/PythonFunctionTypeTest.java
@@ -5,11 +5,13 @@
import org.eclipse.xtext.testing.InjectWith;
import org.eclipse.xtext.testing.extensions.InjectionExtension;
import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import jakarta.inject.Inject;
import java.util.Map;
+@Disabled("Functions are being phased out in tests.")
@ExtendWith(InjectionExtension.class)
@InjectWith(RosettaInjectorProvider.class)
public class PythonFunctionTypeTest {
diff --git a/src/test/java/com/regnosys/rosetta/generator/python/rule/PythonDataRuleGeneratorTest.java b/src/test/java/com/regnosys/rosetta/generator/python/rule/PythonDataRuleGeneratorTest.java
index 0cb5c25e..1d9358f9 100644
--- a/src/test/java/com/regnosys/rosetta/generator/python/rule/PythonDataRuleGeneratorTest.java
+++ b/src/test/java/com/regnosys/rosetta/generator/python/rule/PythonDataRuleGeneratorTest.java
@@ -5,6 +5,7 @@
import com.regnosys.rosetta.generator.python.PythonGeneratorTestUtils;
import org.eclipse.xtext.testing.InjectWith;
import org.eclipse.xtext.testing.extensions.InjectionExtension;
+import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
@@ -226,6 +227,7 @@ class com_rosetta_test_model_QuotePrice(BaseDataClass):
}
@Test
+ @Disabled("Functions are being phased out in tests.")
public void dataRuleWithDoIfAndFunction() {
String pythonString = testUtils.generatePythonFromString(
"""
@@ -263,6 +265,7 @@ def _else_fn0():
}
@Test
+ @Disabled("Functions are being phased out in tests.")
public void dataRuleWithDoIfAndFunctionAndElse() {
String pythonString = testUtils.generatePythonFromString(
"""
diff --git a/test/python_unit_tests/features/TestEnumUsage.rosetta b/test/python_unit_tests/features/TestEnumUsage.rosetta
index 572a7693..daead854 100644
--- a/test/python_unit_tests/features/TestEnumUsage.rosetta
+++ b/test/python_unit_tests/features/TestEnumUsage.rosetta
@@ -8,12 +8,10 @@ enum TrafficLight:
type TrafficLightType:
val TrafficLight(1..1)
-func CheckLight:
- inputs:
- color TrafficLight(1..1)
- output:
- res string(1..1)
- set res:
- if color = TrafficLight -> Red
+type CheckLightTest:
+ color TrafficLight(1..1)
+ target string(1..1)
+ condition TestCond:
+ (if color = TrafficLight -> Red
then "Stop"
- else "Go"
+ else "Go") = target
diff --git a/test/python_unit_tests/features/collections/Collections.rosetta b/test/python_unit_tests/features/collections/Collections.rosetta
index 319586ac..35aaa174 100644
--- a/test/python_unit_tests/features/collections/Collections.rosetta
+++ b/test/python_unit_tests/features/collections/Collections.rosetta
@@ -54,15 +54,23 @@ type SortTest:
then True
else False
-func JoinTestFunction: <"Test join operation">
- inputs:
- field1 string (1..1)
- field2 string (1..1)
- delimiter string (1..1)
- output:
- result string (1..1)
- set result:
- [field1, field2] join delimiter
+type JoinTest:
+ field1 string (1..1)
+ field2 string (1..1)
+ delimiter string (1..1)
+ target string (1..1)
+ condition TestCond:
+ if ([field1, field2] join delimiter) = target
+ then True
+ else False
+
+type FlattenTest:
+ fc FlattenContainer (1..*)
+ target int (0..*)
+ condition TestCond:
+ if (fc extract items then extract items then flatten) all = target
+ then True
+ else False
type FilterItem:
fi int (1..1)
@@ -81,23 +89,12 @@ type FlattenBar:
type FlattenFoo:
bars FlattenBar (0..*)
condition TestCondFoo:
- [1, 2, 3] = (bars
- extract numbers
- then flatten)
+ if [1, 2, 3] all = (bars extract numbers then flatten)
+ then True
+ else False
type FlattenItem:
items int (1..*)
type FlattenContainer:
items FlattenItem (1..*)
-
-func FlattenTestFunction: <"Test flatten operation">
- inputs:
- fc FlattenContainer (1..*) <"Test value">
- output:
- result int (1..*)
- set result:
- fc
- extract items
- then extract items
- then flatten
diff --git a/test/python_unit_tests/features/collections/ListExtensions.rosetta b/test/python_unit_tests/features/collections/ListExtensions.rosetta
index a3edab1c..cd67e9a5 100644
--- a/test/python_unit_tests/features/collections/ListExtensions.rosetta
+++ b/test/python_unit_tests/features/collections/ListExtensions.rosetta
@@ -1,49 +1,37 @@
namespace rosetta_dsl.test.semantic.collections.extensions : <"generate Python unit tests from Rosetta.">
-func ListFirst:
- inputs:
- items int(0..*)
- output:
- res int(0..1)
- set res:
- items first
+type ListFirstTest:
+ items int (0..*)
+ target int (0..1)
+ condition TestCond:
+ items first = target
-func ListLast:
- inputs:
- items int(0..*)
- output:
- res int(0..1)
- set res:
- items last
+type ListLastTest:
+ items int (0..*)
+ target int (0..1)
+ condition TestCond:
+ items last = target
-func ListDistinct:
- inputs:
- items int(0..*)
- output:
- res int(0..*)
- set res:
- items distinct
+type ListDistinctTest:
+ items int (0..*)
+ target int (0..*)
+ condition TestCond:
+ (items distinct) all = (target distinct)
-func ListSum:
- inputs:
- items int(0..*)
- output:
- res int(1..1)
- set res:
- items sum
+type ListSumTest:
+ items int (0..*)
+ target int (1..1)
+ condition TestCond:
+ items sum = target
-func ListOnlyElement:
- inputs:
- items int(0..*)
- output:
- res int(0..1)
- set res:
- items only-element
+type ListOnlyElementTest:
+ items int (0..*)
+ target int (0..1)
+ condition TestCond:
+ items only-element = target
-func ListReverse:
- inputs:
- items int(0..*)
- output:
- res int(0..*)
- set res:
- items reverse
+type ListReverseTest:
+ items int (0..*)
+ target int (0..*)
+ condition TestCond:
+ (items reverse) all = target
diff --git a/test/python_unit_tests/features/collections/test_list_extensions.py b/test/python_unit_tests/features/collections/test_list_extensions.py
index b226bba9..47435b1f 100644
--- a/test/python_unit_tests/features/collections/test_list_extensions.py
+++ b/test/python_unit_tests/features/collections/test_list_extensions.py
@@ -1,71 +1,61 @@
"""List extensions unit tests"""
-from rosetta_dsl.test.semantic.collections.extensions.functions.ListFirst import (
- ListFirst,
+import pytest
+from rosetta_dsl.test.semantic.collections.extensions.ListFirstTest import (
+ ListFirstTest,
)
-from rosetta_dsl.test.semantic.collections.extensions.functions.ListLast import ListLast
-from rosetta_dsl.test.semantic.collections.extensions.functions.ListDistinct import (
- ListDistinct,
+from rosetta_dsl.test.semantic.collections.extensions.ListLastTest import ListLastTest
+from rosetta_dsl.test.semantic.collections.extensions.ListDistinctTest import (
+ ListDistinctTest,
)
-from rosetta_dsl.test.semantic.collections.extensions.functions.ListSum import ListSum
-from rosetta_dsl.test.semantic.collections.extensions.functions.ListOnlyElement import (
- ListOnlyElement,
+from rosetta_dsl.test.semantic.collections.extensions.ListSumTest import ListSumTest
+from rosetta_dsl.test.semantic.collections.extensions.ListOnlyElementTest import (
+ ListOnlyElementTest,
)
-from rosetta_dsl.test.semantic.collections.extensions.functions.ListReverse import (
- ListReverse,
+from rosetta_dsl.test.semantic.collections.extensions.ListReverseTest import (
+ ListReverseTest,
)
def test_list_first():
"""Test 'first' list operator."""
- assert ListFirst(items=[1, 2, 3]) == 1
+ ListFirstTest(items=[1, 2, 3], target=1).validate_model()
# Current implementation raises IndexError for empty list
- try:
- ListFirst(items=[])
- except IndexError:
- pass
+ with pytest.raises(Exception):
+ ListFirstTest(items=[], target=None).validate_model()
def test_list_last():
"""Test 'last' list operator."""
- assert ListLast(items=[1, 2, 3]) == 3
+ ListLastTest(items=[1, 2, 3], target=3).validate_model()
# Current implementation raises IndexError for empty list
- try:
- ListLast(items=[])
- except IndexError:
- pass
+ with pytest.raises(Exception):
+ ListLastTest(items=[], target=None).validate_model()
def test_list_distinct():
"""Test 'distinct' list operator."""
- res = ListDistinct(items=[1, 2, 2, 3])
- # distinct works
- assert len(res) == 3
- assert 1 in res
+ ListDistinctTest(items=[1, 2, 2, 3], target=[1, 2, 3]).validate_model()
def test_list_sum():
"""Test 'sum' list operator."""
- assert ListSum(items=[1, 2, 3]) == 6
- assert ListSum(items=[]) == 0
+ ListSumTest(items=[1, 2, 3], target=6).validate_model()
+ ListSumTest(items=[], target=0).validate_model()
def test_list_only_element():
"""Test 'only-element' list operator."""
- assert ListOnlyElement(items=[1]) == 1
+ ListOnlyElementTest(items=[1], target=1).validate_model()
# Returns None if multiple elements exist
- assert ListOnlyElement(items=[1, 2]) is None
+ ListOnlyElementTest(items=[1, 2], target=None).validate_model()
- # Returns None or raises IndexError if empty?
- try:
- val = ListOnlyElement(items=[])
- assert val is None
- except IndexError:
- pass
+ # Returns None if empty
+ ListOnlyElementTest(items=[], target=None).validate_model()
def test_list_reverse():
"""Test 'reverse' list operator."""
- assert ListReverse(items=[1, 2, 3]) == [3, 2, 1]
- assert ListReverse(items=[]) == []
+ ListReverseTest(items=[1, 2, 3], target=[3, 2, 1]).validate_model()
+ ListReverseTest(items=[], target=[]).validate_model()
diff --git a/test/python_unit_tests/features/collections/test_list_operators.py b/test/python_unit_tests/features/collections/test_list_operators.py
index 30c8967e..eea3168d 100644
--- a/test/python_unit_tests/features/collections/test_list_operators.py
+++ b/test/python_unit_tests/features/collections/test_list_operators.py
@@ -10,14 +10,10 @@
from rosetta_dsl.test.semantic.collections.MaxTest import MaxTest
from rosetta_dsl.test.semantic.collections.LastTest import LastTest
from rosetta_dsl.test.semantic.collections.SortTest import SortTest
-from rosetta_dsl.test.semantic.collections.functions.JoinTestFunction import (
- JoinTestFunction,
-)
+from rosetta_dsl.test.semantic.collections.JoinTest import JoinTest
from rosetta_dsl.test.semantic.collections.FlattenItem import FlattenItem
from rosetta_dsl.test.semantic.collections.FlattenContainer import FlattenContainer
-from rosetta_dsl.test.semantic.collections.functions.FlattenTestFunction import (
- FlattenTestFunction,
-)
+from rosetta_dsl.test.semantic.collections.FlattenTest import FlattenTest
from rosetta_dsl.test.semantic.collections.FlattenBar import FlattenBar
from rosetta_dsl.test.semantic.collections.FlattenFoo import FlattenFoo
from rosetta_dsl.test.semantic.collections.FilterItem import FilterItem
@@ -78,8 +74,7 @@ def test_sort_passes():
def test_join_passes():
"""join tests passes"""
- join_test = JoinTestFunction(field1="a", field2="b", delimiter="")
- assert join_test == "ab"
+ JoinTest(field1="a", field2="b", delimiter="", target="ab").validate_model()
def test_flatten_passes():
@@ -88,8 +83,9 @@ def test_flatten_passes():
flatten_container = FlattenContainer(
items=[flatten_item, flatten_item, flatten_item]
)
- result = FlattenTestFunction(fc=[flatten_container])
- assert result == [1, 2, 3, 1, 2, 3, 1, 2, 3]
+ FlattenTest(
+ fc=[flatten_container], target=[1, 2, 3, 1, 2, 3, 1, 2, 3]
+ ).validate_model()
def test_flatten_foo_passes():
diff --git a/test/python_unit_tests/features/expressions/ConditionalExpression.rosetta b/test/python_unit_tests/features/expressions/ConditionalExpression.rosetta
index 21745471..ef1b933c 100644
--- a/test/python_unit_tests/features/expressions/ConditionalExpression.rosetta
+++ b/test/python_unit_tests/features/expressions/ConditionalExpression.rosetta
@@ -1,23 +1,19 @@
namespace rosetta_dsl.test.semantic.expressions.conditional : <"generate Python unit tests from Rosetta.">
-func ConditionalValue:
- inputs:
- param int(1..1)
- output:
- res string(1..1)
- set res:
- if param > 10
+type ConditionalValueTest:
+ param int(1..1)
+ target string(1..1)
+ condition TestCond:
+ (if param > 10
then "High"
- else "Low"
+ else "Low") = target
-func ConditionalNested:
- inputs:
- param int(1..1)
- output:
- res string(1..1)
- set res:
- if param > 10
+type ConditionalNestedTest:
+ param int(1..1)
+ target string(1..1)
+ condition TestCond:
+ (if param > 10
then "High"
else if param > 5
then "Medium"
- else "Low"
+ else "Low") = target
diff --git a/test/python_unit_tests/features/expressions/SwitchOp.rosetta b/test/python_unit_tests/features/expressions/SwitchOp.rosetta
index c3109fb7..f8a2cd0b 100644
--- a/test/python_unit_tests/features/expressions/SwitchOp.rosetta
+++ b/test/python_unit_tests/features/expressions/SwitchOp.rosetta
@@ -1,13 +1,12 @@
namespace rosetta_dsl.test.semantic.expressions.switch_op
-func SwitchTest: <"Test switch operation">
- inputs:
- x int (1..1)
- output:
- res string (1..1)
-
- set res:
- x switch
+type SwitchTest: <"Test switch operation">
+ x int (1..1)
+ target string (1..1)
+ condition TestCond:
+ if (x switch
1 then "One",
2 then "Two",
- default "Other"
+ default "Other") = target
+ then True
+ else False
diff --git a/test/python_unit_tests/features/expressions/TypeConversion.rosetta b/test/python_unit_tests/features/expressions/TypeConversion.rosetta
index 924df359..ac5eb41a 100644
--- a/test/python_unit_tests/features/expressions/TypeConversion.rosetta
+++ b/test/python_unit_tests/features/expressions/TypeConversion.rosetta
@@ -1,17 +1,13 @@
namespace rosetta_dsl.test.semantic.expressions.type_conversion : <"generate Python unit tests from Rosetta.">
-func StringToInt:
- inputs:
- s string(1..1)
- output:
- res int(1..1)
- set res:
- s to-int
+type StringToIntTest:
+ s string(1..1)
+ target int(1..1)
+ condition TestCond:
+ (s to-int) = target
-func IntToString:
- inputs:
- i int(1..1)
- output:
- res string(1..1)
- set res:
- i to-string
+type IntToStringTest:
+ i int(1..1)
+ target string(1..1)
+ condition TestCond:
+ (i to-string) = target
diff --git a/test/python_unit_tests/features/expressions/test_conditional_expression.py b/test/python_unit_tests/features/expressions/test_conditional_expression.py
index 1edd6dcc..15e00431 100644
--- a/test/python_unit_tests/features/expressions/test_conditional_expression.py
+++ b/test/python_unit_tests/features/expressions/test_conditional_expression.py
@@ -1,24 +1,24 @@
"""Conditional expression unit tests"""
-from rosetta_dsl.test.semantic.expressions.conditional.functions.ConditionalValue import (
- ConditionalValue,
+from rosetta_dsl.test.semantic.expressions.conditional.ConditionalValueTest import (
+ ConditionalValueTest,
)
-from rosetta_dsl.test.semantic.expressions.conditional.functions.ConditionalNested import (
- ConditionalNested,
+from rosetta_dsl.test.semantic.expressions.conditional.ConditionalNestedTest import (
+ ConditionalNestedTest,
)
def test_conditional_value():
"""Test simple if-then-else expression."""
- assert ConditionalValue(param=20) == "High"
- assert ConditionalValue(param=5) == "Low"
+ ConditionalValueTest(param=20, target="High").validate_model()
+ ConditionalValueTest(param=5, target="Low").validate_model()
def test_conditional_nested():
"""Test nested if-then-else expression."""
- assert ConditionalNested(param=20) == "High"
- assert ConditionalNested(param=8) == "Medium"
- assert ConditionalNested(param=2) == "Low"
+ ConditionalNestedTest(param=20, target="High").validate_model()
+ ConditionalNestedTest(param=8, target="Medium").validate_model()
+ ConditionalNestedTest(param=2, target="Low").validate_model()
if __name__ == "__main__":
diff --git a/test/python_unit_tests/features/expressions/test_switch_op.py b/test/python_unit_tests/features/expressions/test_switch_op.py
index 85156700..c5eb14ae 100644
--- a/test/python_unit_tests/features/expressions/test_switch_op.py
+++ b/test/python_unit_tests/features/expressions/test_switch_op.py
@@ -1,18 +1,16 @@
"""Switch expression unit tests"""
-from rosetta_dsl.test.semantic.expressions.switch_op.functions.SwitchTest import (
- SwitchTest,
-)
+from rosetta_dsl.test.semantic.expressions.switch_op.SwitchTest import SwitchTest
def test_switch_op():
"""Test switch operation."""
# Test valid cases
- assert SwitchTest(x=1) == "One"
- assert SwitchTest(x=2) == "Two"
+ SwitchTest(x=1, target="One").validate_model()
+ SwitchTest(x=2, target="Two").validate_model()
# Test default case
- assert SwitchTest(x=3) == "Other"
+ SwitchTest(x=3, target="Other").validate_model()
if __name__ == "__main__":
diff --git a/test/python_unit_tests/features/expressions/test_type_conversion.py b/test/python_unit_tests/features/expressions/test_type_conversion.py
index 2a708126..50a4c85c 100644
--- a/test/python_unit_tests/features/expressions/test_type_conversion.py
+++ b/test/python_unit_tests/features/expressions/test_type_conversion.py
@@ -1,26 +1,18 @@
"""Type conversion unit tests"""
-import pytest
-from rosetta_dsl.test.semantic.expressions.type_conversion.functions.StringToInt import (
- StringToInt,
+from rosetta_dsl.test.semantic.expressions.type_conversion.StringToIntTest import (
+ StringToIntTest,
)
-from rosetta_dsl.test.semantic.expressions.type_conversion.functions.IntToString import (
- IntToString,
+from rosetta_dsl.test.semantic.expressions.type_conversion.IntToStringTest import (
+ IntToStringTest,
)
def test_string_to_int():
- """Test string to integer conversion."""
- assert StringToInt(s="123") == 123
- with pytest.raises(Exception): # ValueError or similar
- StringToInt(s="abc")
+ """Test 'to-int' conversion."""
+ StringToIntTest(s="123", target=123).validate_model()
def test_int_to_string():
- """Test integer to string conversion."""
- assert IntToString(i=456) == "456"
-
-
-if __name__ == "__main__":
- test_string_to_int()
- test_int_to_string()
+ """Test 'to-string' conversion."""
+ IntToStringTest(i=456, target="456").validate_model()
diff --git a/test/python_unit_tests/features/functions/AddOperation.rosetta b/test/python_unit_tests/features/functions/AddOperation.rosetta
deleted file mode 100644
index a64dddb8..00000000
--- a/test/python_unit_tests/features/functions/AddOperation.rosetta
+++ /dev/null
@@ -1,17 +0,0 @@
-namespace rosetta_dsl.test.functions.add_operation : <"generate Python unit tests from Rosetta.">
-
-type UnitType:
- currency string (0..1)
-
-type Quantity:
- value number (0..1)
- unit UnitType (0..1)
-
-func FilterQuantity:
- inputs:
- quantities Quantity (0..*)
- unit UnitType (1..1)
- output:
- filteredQuantities Quantity (0..*)
-
- add filteredQuantities: quantities filter item -> unit = unit
diff --git a/test/python_unit_tests/features/functions/FunctionTest.rosetta b/test/python_unit_tests/features/functions/FunctionTest.rosetta
deleted file mode 100644
index ac9f0936..00000000
--- a/test/python_unit_tests/features/functions/FunctionTest.rosetta
+++ /dev/null
@@ -1,240 +0,0 @@
-namespace rosetta_dsl.test.functions : <"generate Python unit tests from Rosetta.">
-
-func TestAbsNumber: <"Returns the absolute value of a number. If the argument is not negative, the argument is returned. If the argument is negative, the negation of the argument is returned.">
- inputs:
- arg number (1..1)
- output:
- result number (1..1)
- set result: if arg < 0 then -1 * arg else arg
-
-type AInput: <"A type">
- a number (1..1)
-
-func TestAbsInputType: <"Returns the absolute value of a number. If the argument is not negative, the argument is returned. If the argument is negative, the negation of the argument is returned.">
- inputs:
- arg AInput (1..1)
- output:
- result number (1..1)
- set result: if arg -> a < 0 then -1 * arg -> a else arg -> a
-
-type AOutput: <"A type">
- a number (1..1)
-
-func TestAbsOutputType: <"Returns the absolute value of a number. If the argument is not negative, the argument is returned. If the argument is negative, the negation of the argument is returned.">
- inputs:
- arg number (1..1)
- output:
- result AOutput (1..1)
- set result:
- AOutput {
- a: if arg < 0 then arg * -1 else arg
- }
-
-enum ArithmeticOperationEnum: <"An arithmetic operator that can be passed to a function">
- Add <"Addition">
- Subtract <"Subtraction">
- Multiply <"Multiplication">
- Divide <"Division">
- Max <"Max of 2 values">
- Min <"Min of 2 values">
-
-func ArithmeticOperation:
- inputs:
- n1 number (1..1)
- op ArithmeticOperationEnum (1..1)
- n2 number (1..1)
- output:
- result number (1..1)
-
- set result:
- if op = ArithmeticOperationEnum -> Add then
- n1 + n2
- else if op = ArithmeticOperationEnum -> Subtract then
- n1 - n2
- else if op = ArithmeticOperationEnum -> Multiply then
- n1 * n2
- else if op = ArithmeticOperationEnum -> Divide then
- n1 / n2
- else if op = ArithmeticOperationEnum -> Max then
- [n1, n2] max
- else if op = ArithmeticOperationEnum -> Min then
- [n1, n2] min
-
-func TestAlias:
- inputs:
- inp1 number(1..1)
- inp2 number(1..1)
- output:
- result number(1..1)
- alias Alias:
- if inp1 < inp2 then inp1 else inp2
-
- set result:
- Alias
-
-type ComplexTypeA:
- valueA number(1..1)
-
-type ComplexTypeB:
- valueB number(1..1)
-
-type ComplexTypeC:
- valueA number(1..1)
- valueB number(1..1)
-
-func TestComplexTypeInputs:
- inputs:
- a ComplexTypeA (1..1)
- b ComplexTypeB (1..1)
- output:
- c ComplexTypeC (1..1)
- set c->valueA:
- a->valueA
- set c->valueB:
- b->valueB
-
-type A:
- valueA number(1..1)
-
-type B:
- valueB number(1..1)
-
-type C:
- valueC number(1..1)
-
-func TestAliasWithBaseModelInputs:
- inputs:
- a A (1..1)
- b B (1..1)
- output:
- c C (1..1)
- alias Alias1:
- a->valueA
- alias Alias2:
- b->valueB
-set c:
- C {
- valueC: Alias1 * Alias2
- }
-func MinMaxWithSimpleCondition:
- inputs:
- in1 number (1..1)
- in2 number (1..1)
- direction string (1..1)
- output:
- result number (1..1)
- condition Directiom:
- direction = "min" or direction = "max"
- set result:
- if direction = "min" then
- [in1, in2] min
- else if direction = "max" then
- [in1, in2] max
-
-func MinMaxWithPostCondition:
- inputs:
- in1 number (1..1)
- in2 number (1..1)
- direction string (1..1)
- output:
- result number (1..1)
- set result:
- if direction = "min" then
- [in1, in2] min
- else if direction = "max" then
- [in1, in2] max
- post-condition Directiom:
- direction = "min" or direction = "max"
-
-func BaseFunction:
- inputs:
- value number (1..1)
- output:
- result number (1..1)
- set result:
- value * 2
-
-func MainFunction:
- inputs:
- value number (1..1)
- output:
- result number (1..1)
- set result:
- BaseFunction(value)
-
-type KeyEntity:
- [metadata key]
- value int (1..1)
-
-type RefEntity:
- ke KeyEntity (1..1)
- [metadata reference]
-
-func MetadataFunction:
- inputs:
- ref RefEntity (1..1)
- output:
- result int (1..1)
- set result:
- ref->ke->value
-
-type BaseObject:
- value1 int (1..1)
- value2 int (1..1)
-
-type BaseObjectWithBaseClassFields:
- value1 int (1..1)
- value2 int (1..1)
- strict boolean (1..1)
-
-func TestSimpleObjectAssignment:
- inputs:
- baseObject BaseObject (1..1)
- output:
- result BaseObject (1..1)
- set result:
- baseObject
-
-func TestObjectCreationFromFields:
- inputs:
- baseObject BaseObject (1..1)
- output:
- result BaseObject (1..1)
- set result:
- BaseObject {
- value1: baseObject->value1,
- value2: baseObject->value2
- }
-
-type ContainerObject:
- baseObject BaseObject (1..1)
- value3 int (1..1)
-
-func TestContainerObjectCreation:
- inputs:
- value1 int (1..1)
- value2 int (1..1)
- value3 int (1..1)
- output:
- result ContainerObject (1..1)
- set result:
- ContainerObject {
- baseObject: BaseObject {
- value1: value1,
- value2: value2
- },
- value3: value3
- }
-
-func TestContainerObjectCreationFromBaseObject:
- inputs:
- baseObject BaseObject (1..1)
- value3 int (1..1)
- output:
- result ContainerObject (1..1)
- set result:
- ContainerObject {
- baseObject: baseObject,
- value3: value3
- }
-
\ No newline at end of file
diff --git a/test/python_unit_tests/features/functions/OrderTest.rosetta b/test/python_unit_tests/features/functions/OrderTest.rosetta
deleted file mode 100644
index 29d66b4d..00000000
--- a/test/python_unit_tests/features/functions/OrderTest.rosetta
+++ /dev/null
@@ -1,15 +0,0 @@
-namespace rosetta_dsl.test.functions.order
-
-type ClassB:
- attr ClassA (1..1)
-
-func MyFunc:
- inputs:
- arg ClassB (1..1)
- output:
- out ClassA (1..1)
- set out:
- arg->attr
-
-type ClassA:
- val string (1..1)
diff --git a/test/python_unit_tests/features/functions/test_functions_abs.py b/test/python_unit_tests/features/functions/test_functions_abs.py
deleted file mode 100644
index 6c724884..00000000
--- a/test/python_unit_tests/features/functions/test_functions_abs.py
+++ /dev/null
@@ -1,42 +0,0 @@
-from rosetta_dsl.test.functions.functions.TestAbsNumber import TestAbsNumber
-from rosetta_dsl.test.functions.AInput import AInput
-from rosetta_dsl.test.functions.functions.TestAbsInputType import TestAbsInputType
-from rosetta_dsl.test.functions.functions.TestAbsOutputType import TestAbsOutputType
-
-
-def test_abs_positive():
- """Test abs positive"""
- result = TestAbsNumber(arg=5)
- assert result == 5
-
-
-def test_abs_negative():
- """Test abs negative"""
- result = TestAbsNumber(arg=-5)
- assert result == 5
-
-
-def test_abs_input_type_positive():
- """Test abs type positive"""
- a = AInput(a=5)
- result = TestAbsInputType(arg=a)
- assert result == 5
-
-
-def test_abs_input_type_negative():
- """Test abs type negative"""
- a = AInput(a=-5)
- result = TestAbsInputType(arg=a)
- assert result == 5
-
-
-def test_abs_output_type_positive():
- """Test abs output type positive"""
- result = TestAbsOutputType(arg=5)
- assert result.a == 5
-
-
-def test_abs_output_type_negative():
- """Test abs output type negative"""
- result = TestAbsOutputType(arg=-5)
- assert result.a == 5
diff --git a/test/python_unit_tests/features/functions/test_functions_add_operation.py b/test/python_unit_tests/features/functions/test_functions_add_operation.py
deleted file mode 100644
index bd4737a3..00000000
--- a/test/python_unit_tests/features/functions/test_functions_add_operation.py
+++ /dev/null
@@ -1,20 +0,0 @@
-from rosetta_dsl.test.functions.add_operation.UnitType import UnitType
-from rosetta_dsl.test.functions.add_operation.Quantity import Quantity
-from rosetta_dsl.test.functions.add_operation.functions.FilterQuantity import (
- FilterQuantity,
-)
-
-
-def test_add_operation():
- """Test add operation"""
- fx_eur = UnitType(currency="EUR")
- fx_jpy = UnitType(currency="JPY")
- fx_usd = UnitType(currency="USD")
- list_of_quantities = [
- Quantity(unit=fx_eur),
- Quantity(unit=fx_jpy),
- Quantity(unit=fx_usd),
- ]
- fq = FilterQuantity(quantities=list_of_quantities, unit=fx_jpy)
- assert len(fq) == 1
- assert fq[0].unit.currency == "JPY"
diff --git a/test/python_unit_tests/features/functions/test_functions_alias.py b/test/python_unit_tests/features/functions/test_functions_alias.py
deleted file mode 100644
index 47eef5c1..00000000
--- a/test/python_unit_tests/features/functions/test_functions_alias.py
+++ /dev/null
@@ -1,25 +0,0 @@
-"""
-Unit tests for functions.
-"""
-
-from rosetta_dsl.test.functions.functions.TestAlias import TestAlias
-from rosetta_dsl.test.functions.functions.TestAliasWithBaseModelInputs import (
- TestAliasWithBaseModelInputs,
-)
-from rosetta_dsl.test.functions.A import A
-from rosetta_dsl.test.functions.B import B
-
-
-def test_alias():
- """Test alias"""
- assert TestAlias(inp1=5, inp2=10) == 5
- assert TestAlias(inp1=10, inp2=5) == 5
-
-
-def test_alias_with_base_model_inputs():
- """Test alias with base model inputs"""
- a = A(valueA=5)
- b = B(valueB=10)
- c = TestAliasWithBaseModelInputs(a=a, b=b)
- print(c)
- assert c.valueC == 50
diff --git a/test/python_unit_tests/features/functions/test_functions_arithmetic.py b/test/python_unit_tests/features/functions/test_functions_arithmetic.py
deleted file mode 100644
index 73a3ef18..00000000
--- a/test/python_unit_tests/features/functions/test_functions_arithmetic.py
+++ /dev/null
@@ -1,12 +0,0 @@
-from rosetta_dsl.test.functions.functions.ArithmeticOperation import ArithmeticOperation
-from rosetta_dsl.test.functions.ArithmeticOperationEnum import ArithmeticOperationEnum
-
-
-def test_arithmetic_operation():
- """Test arithmetic operation"""
- assert ArithmeticOperation(n1=5, op=ArithmeticOperationEnum.ADD, n2=10) == 15
- assert ArithmeticOperation(n1=5, op=ArithmeticOperationEnum.SUBTRACT, n2=10) == -5
- assert ArithmeticOperation(n1=5, op=ArithmeticOperationEnum.MULTIPLY, n2=10) == 50
- assert ArithmeticOperation(n1=5, op=ArithmeticOperationEnum.DIVIDE, n2=10) == 0.5
- assert ArithmeticOperation(n1=5, op=ArithmeticOperationEnum.MAX, n2=10) == 10
- assert ArithmeticOperation(n1=5, op=ArithmeticOperationEnum.MIN, n2=10) == 5
diff --git a/test/python_unit_tests/features/functions/test_functions_call.py b/test/python_unit_tests/features/functions/test_functions_call.py
deleted file mode 100644
index 0506d67b..00000000
--- a/test/python_unit_tests/features/functions/test_functions_call.py
+++ /dev/null
@@ -1,6 +0,0 @@
-from rosetta_dsl.test.functions.functions.MainFunction import MainFunction
-
-
-def test_function_with_function_call():
- """Test function with function call"""
- assert MainFunction(value=5) == 10
diff --git a/test/python_unit_tests/features/functions/test_functions_conditions.py b/test/python_unit_tests/features/functions/test_functions_conditions.py
deleted file mode 100644
index 5ce0bb49..00000000
--- a/test/python_unit_tests/features/functions/test_functions_conditions.py
+++ /dev/null
@@ -1,24 +0,0 @@
-import pytest
-from rune.runtime.conditions import ConditionViolationError
-from rosetta_dsl.test.functions.functions.MinMaxWithSimpleCondition import (
- MinMaxWithSimpleCondition,
-)
-from rosetta_dsl.test.functions.functions.MinMaxWithPostCondition import (
- MinMaxWithPostCondition,
-)
-
-
-def test_min_max_simple_conditions():
- """Test min max simple conditions"""
- assert MinMaxWithSimpleCondition(in1=5, in2=10, direction="min") == 5
- assert MinMaxWithSimpleCondition(in1=5, in2=10, direction="max") == 10
- with pytest.raises(ConditionViolationError):
- MinMaxWithSimpleCondition(in1=5, in2=-10, direction="none")
-
-
-def test_min_max_post_conditions():
- """Test min max post conditions"""
- assert MinMaxWithPostCondition(in1=5, in2=10, direction="min") == 5
- assert MinMaxWithPostCondition(in1=5, in2=10, direction="max") == 10
- with pytest.raises(ConditionViolationError):
- MinMaxWithPostCondition(in1=5, in2=-10, direction="none")
diff --git a/test/python_unit_tests/features/functions/test_functions_metadata.py b/test/python_unit_tests/features/functions/test_functions_metadata.py
deleted file mode 100644
index 86a50cfb..00000000
--- a/test/python_unit_tests/features/functions/test_functions_metadata.py
+++ /dev/null
@@ -1,13 +0,0 @@
-from rune.runtime.metadata import Reference
-from rosetta_dsl.test.functions.KeyEntity import KeyEntity
-from rosetta_dsl.test.functions.RefEntity import RefEntity
-from rosetta_dsl.test.functions.functions.MetadataFunction import MetadataFunction
-
-
-def test_metadata_function():
- """Test metadata function"""
- key_entity = KeyEntity(value=5)
- key_entity.set_meta(key_external="key-123")
- key_entity.validate_model()
- ref_entity = RefEntity(ke=Reference(target=key_entity, ext_key="key-123"))
- assert MetadataFunction(ref=ref_entity) == 5
diff --git a/test/python_unit_tests/features/functions/test_functions_object_creation.py b/test/python_unit_tests/features/functions/test_functions_object_creation.py
deleted file mode 100644
index 2da08f75..00000000
--- a/test/python_unit_tests/features/functions/test_functions_object_creation.py
+++ /dev/null
@@ -1,86 +0,0 @@
-"""test functions incomplete object return"""
-
-import pytest
-
-from rosetta_dsl.test.functions.BaseObject import BaseObject
-from rosetta_dsl.test.functions.BaseObjectWithBaseClassFields import (
- BaseObjectWithBaseClassFields,
-)
-
-from rosetta_dsl.test.functions.functions.TestSimpleObjectAssignment import (
- TestSimpleObjectAssignment,
-)
-from rosetta_dsl.test.functions.functions.TestObjectCreationFromFields import (
- TestObjectCreationFromFields,
-)
-from rosetta_dsl.test.functions.functions.TestContainerObjectCreation import (
- TestContainerObjectCreation,
-)
-from rosetta_dsl.test.functions.functions.TestContainerObjectCreationFromBaseObject import (
- TestContainerObjectCreationFromBaseObject,
-)
-
-from rosetta_dsl.test.functions.functions.TestComplexTypeInputs import (
- TestComplexTypeInputs,
-)
-from rosetta_dsl.test.functions.ComplexTypeA import ComplexTypeA
-from rosetta_dsl.test.functions.ComplexTypeB import ComplexTypeB
-
-
-def test_simple_object_assignment():
- """Test incomplete object return.
- The Rosetta function returns an IncompleteObject with a missing required field (value2),
- so this is expected to raise a validation exception.
- """
- base_object = BaseObject(value1=5, value2=10)
- result = TestSimpleObjectAssignment(baseObject=base_object)
- assert result == base_object
-
-
-def test_object_creation_from_fields():
- """Test incomplete object return.
- The Rosetta function returns an IncompleteObject with a missing required field (value2),
- so this is expected to raise a validation exception.
- """
- base_object = BaseObject(value1=5, value2=10)
- result = TestObjectCreationFromFields(baseObject=base_object)
- assert result == base_object
-
-
-def test_container_object_creation():
- """Test incomplete object return.
- The Rosetta function returns an IncompleteObject with a missing required field (value2),
- so this is expected to raise a validation exception.
- """
- TestContainerObjectCreation(value1=5, value2=10, value3=20)
-
-
-def test_container_object_creation_from_base_object():
- """Test creation of a container object from a base object."""
- base_object = BaseObject(value1=5, value2=10)
- TestContainerObjectCreationFromBaseObject(baseObject=base_object, value3=20)
-
-
-@pytest.mark.skip(reason="Fails due to Pydantic validation of partial objects")
-def test_create_incomplete_object_succeeds_in_python():
- """Test incomplete object return by setting strict=False in the function definition.
- This test is expected to pass.
- """
- BaseObjectWithBaseClassFields(value1=5, strict=False)
-
-
-@pytest.mark.skip(reason="Fails due to Pydantic validation of partial objects")
-def test_create_incomplete_object_succeeds():
- """Test incomplete object return by setting strict=False in the function definition.
- This test is expected to pass.
- """
- TestCreateIncompleteObjectSucceeds(value1=5)
-
-
-@pytest.mark.skip(reason="Fails due to Pydantic validation of partial objects")
-def test_complex_type_inputs():
- """Test complex type inputs."""
- complex_type_a = ComplexTypeA(valueA=5)
- complex_type_b = ComplexTypeB(valueB=10)
- result = TestComplexTypeInputs(a=complex_type_a, b=complex_type_b)
- assert result.valueA == 5 and result.valueB == 10
diff --git a/test/python_unit_tests/features/functions/test_functions_order.py b/test/python_unit_tests/features/functions/test_functions_order.py
deleted file mode 100644
index eb2c36e1..00000000
--- a/test/python_unit_tests/features/functions/test_functions_order.py
+++ /dev/null
@@ -1,19 +0,0 @@
-"""
-Test that the generator generates the correct order of classes and functions.
-"""
-
-from rosetta_dsl.test.functions.order.ClassA import ClassA
-from rosetta_dsl.test.functions.order.ClassB import ClassB
-from rosetta_dsl.test.functions.order.functions.MyFunc import MyFunc
-
-
-def test_function_order():
- """
- Test that the generator generates the correct order of classes and functions.
- """
- # If the ordering is wrong, the import of MyFunc will fail during decorator execution
- # with a NameError because ClassB depends on ClassA, and MyFunc depends on both.
- a = ClassA(val="hello")
- b = ClassB(attr=a)
- result = MyFunc(b)
- assert result.val == "hello"
diff --git a/test/python_unit_tests/features/functions/test_local_conditions.py b/test/python_unit_tests/features/functions/test_local_conditions.py
deleted file mode 100644
index 940205dc..00000000
--- a/test/python_unit_tests/features/functions/test_local_conditions.py
+++ /dev/null
@@ -1,51 +0,0 @@
-'''Tests of the local registration of conditions'''
-import inspect
-import pytest
-from rune.runtime.conditions import rune_local_condition
-from rune.runtime.conditions import rune_execute_local_conditions
-from rune.runtime.conditions import ConditionViolationError
-
-
-def test_pre_post_conditions():
- '''Tests the registration of functions in two different registries'''
- _pre_registry = {}
- _post_registry = {}
- self = inspect.currentframe()
-
- # A local PRE condition
- @rune_local_condition(_pre_registry)
- def some_local_condition():
- print(f'Pre {self}')
- return True
-
- # A local POST condition
- @rune_local_condition(_post_registry)
- def some_local_post_condition():
- print(f'Post {self}')
- return True
-
- # Check all PRE conditions
- rune_execute_local_conditions(_pre_registry, 'Pre-condition')
-
- print('Some Code....')
-
- # Check all POST conditions
- rune_execute_local_conditions(_post_registry, 'Post-condition')
-
-
-def test_raise_local_cond():
- '''checks if exception is raised and it is of the correct type'''
- _registry = {}
- @rune_local_condition(_registry)
- def some_failing_local_post_condition():
- return False
-
- with pytest.raises(ConditionViolationError):
- rune_execute_local_conditions(_registry, 'condition')
-
-
-if __name__ == '__main__':
- test_pre_post_conditions()
- test_raise_local_cond()
-
-# EOF
diff --git a/test/python_unit_tests/features/language/test_enum_usage.py b/test/python_unit_tests/features/language/test_enum_usage.py
index 03db9fb1..417c3d7e 100644
--- a/test/python_unit_tests/features/language/test_enum_usage.py
+++ b/test/python_unit_tests/features/language/test_enum_usage.py
@@ -1,7 +1,7 @@
"""Enum usage unit tests"""
from rosetta_dsl.test.semantic.test_enum_usage.TrafficLight import TrafficLight
-from rosetta_dsl.test.semantic.test_enum_usage.functions.CheckLight import CheckLight
+from rosetta_dsl.test.semantic.test_enum_usage.CheckLightTest import CheckLightTest
def test_enum_values():
@@ -12,7 +12,6 @@ def test_enum_values():
def test_enum_function():
- """Test passing enum as function input."""
- # Function should handle enum correctly
- assert CheckLight(color=TrafficLight.RED) == "Stop"
- assert CheckLight(color=TrafficLight.GREEN) == "Go"
+ """Test passing enum as input."""
+ CheckLightTest(color=TrafficLight.RED, target="Stop").validate_model()
+ CheckLightTest(color=TrafficLight.GREEN, target="Go").validate_model()
diff --git a/test/python_unit_tests/features/model_structure/Inheritance.rosetta b/test/python_unit_tests/features/model_structure/Inheritance.rosetta
index 4a2dec9d..7081c88e 100644
--- a/test/python_unit_tests/features/model_structure/Inheritance.rosetta
+++ b/test/python_unit_tests/features/model_structure/Inheritance.rosetta
@@ -6,7 +6,8 @@ type Super:
type Sub extends Super:
subAttr int (1..1)
-func ProcessSuper:
- inputs: s Super(1..1)
- output: res string(1..1)
- set res: s -> superAttr
+type InheritanceTest:
+ s Super (1..1)
+ target string (1..1)
+ condition TestCond:
+ s -> superAttr = target
diff --git a/test/python_unit_tests/features/model_structure/test_inheritance.py b/test/python_unit_tests/features/model_structure/test_inheritance.py
index 8cd00042..e5216feb 100644
--- a/test/python_unit_tests/features/model_structure/test_inheritance.py
+++ b/test/python_unit_tests/features/model_structure/test_inheritance.py
@@ -2,8 +2,8 @@
import pytest
from rosetta_dsl.test.semantic.model_structure.inheritance.Sub import Sub
-from rosetta_dsl.test.semantic.model_structure.inheritance.functions.ProcessSuper import (
- ProcessSuper,
+from rosetta_dsl.test.semantic.model_structure.inheritance.InheritanceTest import (
+ InheritanceTest,
)
@@ -20,10 +20,9 @@ def test_inheritance_structure():
def test_polymorphism():
- """Test passing Sub to a function expecting Super"""
+ """Test passing Sub to a field expecting Super"""
sub = Sub(superAttr="hello", subAttr=20)
- result = ProcessSuper(s=sub)
- assert result == "hello"
+ InheritanceTest(s=sub, target="hello").validate_model()
if __name__ == "__main__":
diff --git a/test/python_unit_tests/features/operators/ComparisonOp.rosetta b/test/python_unit_tests/features/operators/ComparisonOp.rosetta
index 27cdd8c6..145ee6b5 100644
--- a/test/python_unit_tests/features/operators/ComparisonOp.rosetta
+++ b/test/python_unit_tests/features/operators/ComparisonOp.rosetta
@@ -1,37 +1,13 @@
namespace rosetta_dsl.test.semantic.comparison_op : <"generate Python unit tests from Rosetta.">
-func LessThan:
- inputs:
- a int(1..1)
- b int(1..1)
- output:
- res boolean(1..1)
- set res:
- a < b
-
-func LessThanOrEqual:
- inputs:
- a int(1..1)
- b int(1..1)
- output:
- res boolean(1..1)
- set res:
- a <= b
-
-func GreaterThan:
- inputs:
- a int(1..1)
- b int(1..1)
- output:
- res boolean(1..1)
- set res:
- a > b
-
-func GreaterThanOrEqual:
- inputs:
- a int(1..1)
- b int(1..1)
- output:
- res boolean(1..1)
- set res:
- a >= b
+type ComparisonTest:
+ a int(1..1)
+ b int(1..1)
+ op string(1..1)
+ target boolean(1..1)
+ condition TestCond:
+ if op = "LT" then (a < b) = target
+ else if op = "LE" then (a <= b) = target
+ else if op = "GT" then (a > b) = target
+ else if op = "GE" then (a >= b) = target
+ else False
diff --git a/test/python_unit_tests/features/operators/ComplexBooleanLogic.rosetta b/test/python_unit_tests/features/operators/ComplexBooleanLogic.rosetta
index 410fabf2..6b1c7c72 100644
--- a/test/python_unit_tests/features/operators/ComplexBooleanLogic.rosetta
+++ b/test/python_unit_tests/features/operators/ComplexBooleanLogic.rosetta
@@ -1,18 +1,18 @@
namespace rosetta_dsl.test.semantic.operators.complex_boolean_logic : <"generate Python unit tests from Rosetta.">
-func NotOp: <"Tests negation by equality">
- inputs:
- b boolean(1..1)
- output:
- res boolean(1..1)
- set res:
- b = False
+type NotOpTest:
+ a boolean(1..1)
+ target boolean(1..1)
+ condition TestCond:
+ if (a = False) = target
+ then True
+ else False
-func ComplexLogic: <"Tests complex boolean expression with negation by equality">
- inputs:
- a boolean(1..1)
- b boolean(1..1)
- output:
- res boolean(1..1)
- set res:
- (a or b) and (a = False)
+type ComplexLogicTest:
+ a boolean(1..1)
+ b boolean(1..1)
+ target boolean(1..1)
+ condition TestCond:
+ if ((a or b) and (a = False)) = target
+ then True
+ else False
diff --git a/test/python_unit_tests/features/operators/test_comparison_operators.py b/test/python_unit_tests/features/operators/test_comparison_operators.py
index 1177ed12..0ab495c2 100644
--- a/test/python_unit_tests/features/operators/test_comparison_operators.py
+++ b/test/python_unit_tests/features/operators/test_comparison_operators.py
@@ -1,45 +1,31 @@
-"""Comparison operator unit tests"""
+"""Comparison operators unit tests"""
-from rosetta_dsl.test.semantic.comparison_op.functions.LessThan import LessThan
-from rosetta_dsl.test.semantic.comparison_op.functions.LessThanOrEqual import (
- LessThanOrEqual,
-)
-from rosetta_dsl.test.semantic.comparison_op.functions.GreaterThan import GreaterThan
-from rosetta_dsl.test.semantic.comparison_op.functions.GreaterThanOrEqual import (
- GreaterThanOrEqual,
-)
+from rosetta_dsl.test.semantic.comparison_op.ComparisonTest import ComparisonTest
def test_less_than():
- """Test < operator"""
- assert LessThan(a=1, b=2) is True
- assert LessThan(a=2, b=1) is False
- assert LessThan(a=1, b=1) is False
+ """Test '<' operator."""
+ ComparisonTest(a=5, b=10, op="LT", target=True).validate_model()
+ ComparisonTest(a=10, b=5, op="LT", target=False).validate_model()
+ ComparisonTest(a=5, b=5, op="LT", target=False).validate_model()
def test_less_than_or_equal():
- """Test <= operator"""
- assert LessThanOrEqual(a=1, b=2) is True
- assert LessThanOrEqual(a=2, b=1) is False
- assert LessThanOrEqual(a=1, b=1) is True
+ """Test '<=' operator."""
+ ComparisonTest(a=5, b=10, op="LE", target=True).validate_model()
+ ComparisonTest(a=5, b=5, op="LE", target=True).validate_model()
+ ComparisonTest(a=10, b=5, op="LE", target=False).validate_model()
def test_greater_than():
- """Test > operator"""
- assert GreaterThan(a=2, b=1) is True
- assert GreaterThan(a=1, b=2) is False
- assert GreaterThan(a=1, b=1) is False
+ """Test '>' operator."""
+ ComparisonTest(a=10, b=5, op="GT", target=True).validate_model()
+ ComparisonTest(a=5, b=10, op="GT", target=False).validate_model()
+ ComparisonTest(a=5, b=5, op="GT", target=False).validate_model()
def test_greater_than_or_equal():
- """Test >= operator"""
- assert GreaterThanOrEqual(a=2, b=1) is True
- assert GreaterThanOrEqual(a=1, b=2) is False
- assert GreaterThanOrEqual(a=1, b=1) is True
-
-
-if __name__ == "__main__":
- test_less_than()
- test_less_than_or_equal()
- test_greater_than()
- test_greater_than_or_equal()
+ """Test '>=' operator."""
+ ComparisonTest(a=10, b=5, op="GE", target=True).validate_model()
+ ComparisonTest(a=5, b=5, op="GE", target=True).validate_model()
+ ComparisonTest(a=5, b=10, op="GE", target=False).validate_model()
diff --git a/test/python_unit_tests/features/operators/test_complex_boolean_logic.py b/test/python_unit_tests/features/operators/test_complex_boolean_logic.py
index b59cc637..198a531e 100644
--- a/test/python_unit_tests/features/operators/test_complex_boolean_logic.py
+++ b/test/python_unit_tests/features/operators/test_complex_boolean_logic.py
@@ -1,28 +1,25 @@
"""Complex boolean logic unit tests"""
-from rosetta_dsl.test.semantic.operators.complex_boolean_logic.functions.NotOp import (
- NotOp,
+from rosetta_dsl.test.semantic.operators.complex_boolean_logic.NotOpTest import (
+ NotOpTest,
)
-from rosetta_dsl.test.semantic.operators.complex_boolean_logic.functions.ComplexLogic import (
- ComplexLogic,
+from rosetta_dsl.test.semantic.operators.complex_boolean_logic.ComplexLogicTest import (
+ ComplexLogicTest,
)
def test_not_op():
- """Test logical negation via equality"""
- assert NotOp(b=True) is False
- assert NotOp(b=False) is True
+ """Test negation by equality."""
+ NotOpTest(a=True, target=False).validate_model()
+ NotOpTest(a=False, target=True).validate_model()
def test_complex_logic():
- """Test logic: (a or b) and (not a)"""
- # effectively: (not a) and b
- assert ComplexLogic(a=True, b=True) is False # (T or T) and F -> F
- assert ComplexLogic(a=True, b=False) is False # (T or F) and F -> F
- assert ComplexLogic(a=False, b=True) is True # (F or T) and T -> T
- assert ComplexLogic(a=False, b=False) is False # (F or F) and T -> F
-
-
-if __name__ == "__main__":
- test_not_op()
- test_complex_logic()
+ """Test complex boolean expression with negation by equality."""
+ # (a or b) and (not a)
+ # T, T -> (T or T) and F -> T and F -> F
+ ComplexLogicTest(a=True, b=True, target=False).validate_model()
+ # F, T -> (F or T) and T -> T and T -> T
+ ComplexLogicTest(a=False, b=True, target=True).validate_model()
+ # F, F -> (F or F) and T -> F and T -> F
+ ComplexLogicTest(a=False, b=False, target=False).validate_model()
diff --git a/test/python_unit_tests/features/robustness/NullHandling.rosetta b/test/python_unit_tests/features/robustness/NullHandling.rosetta
index 5e31cc1e..d1e2120a 100644
--- a/test/python_unit_tests/features/robustness/NullHandling.rosetta
+++ b/test/python_unit_tests/features/robustness/NullHandling.rosetta
@@ -1,17 +1,13 @@
namespace rosetta_dsl.test.semantic.robustness.null_handling : <"generate Python unit tests from Rosetta.">
-func IsAbsent:
- inputs:
- val string(0..1)
- output:
- res boolean(1..1)
- set res:
- val is absent
+type IsAbsentTest:
+ val string(0..1)
+ target boolean(1..1)
+ condition TestCond:
+ (val is absent) = target
-func IsAbsentList:
- inputs:
- list int(0..*)
- output:
- res boolean(1..1)
- set res:
- list is absent
+type IsAbsentListTest:
+ items int (0..*)
+ target boolean(1..1)
+ condition TestCond:
+ (items is absent) = target
diff --git a/test/python_unit_tests/features/robustness/test_null_handling.py b/test/python_unit_tests/features/robustness/test_null_handling.py
index 67b57029..f45f638e 100644
--- a/test/python_unit_tests/features/robustness/test_null_handling.py
+++ b/test/python_unit_tests/features/robustness/test_null_handling.py
@@ -1,22 +1,23 @@
"""Null handling unit tests"""
-from rosetta_dsl.test.semantic.robustness.null_handling.functions.IsAbsent import (
- IsAbsent,
+from rosetta_dsl.test.semantic.robustness.null_handling.IsAbsentTest import (
+ IsAbsentTest,
)
-from rosetta_dsl.test.semantic.robustness.null_handling.functions.IsAbsentList import (
- IsAbsentList,
+from rosetta_dsl.test.semantic.robustness.null_handling.IsAbsentListTest import (
+ IsAbsentListTest,
)
def test_is_absent():
"""Test 'is absent' check on scalar value."""
- assert IsAbsent(val=None) is True
- assert IsAbsent(val="foo") is False
+ IsAbsentTest(val=None, target=True).validate_model()
+ IsAbsentTest(val="foo", target=False).validate_model()
def test_is_absent_list():
"""Test 'is absent' check on list of values."""
- assert IsAbsentList(list=[]) is True
+ # Renamed field from 'list' to 'items' to avoid name collision with built-in list type
+ IsAbsentListTest(items=[], target=True).validate_model()
# If list is explicit None?
- assert IsAbsentList(list=None) is True
- assert IsAbsentList(list=[1]) is False
+ IsAbsentListTest(items=None, target=True).validate_model()
+ IsAbsentListTest(items=[1], target=False).validate_model()
From 2c88ac7ff1ed9a4c84b2452cad0f194375834fc5 Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Mon, 23 Feb 2026 19:26:46 +0000
Subject: [PATCH 16/25] fix(deps): update logback monorepo to v1.5.32
---
pom.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/pom.xml b/pom.xml
index e963a5dc..0869a824 100644
--- a/pom.xml
+++ b/pom.xml
@@ -87,7 +87,7 @@
6.0.0
2.0.17
- 1.5.26
+ 1.5.32
6.0.3
From 79a22adc16ffb45becbe436c1ec3392e49b9da40 Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Tue, 10 Mar 2026 17:55:30 +0000
Subject: [PATCH 17/25] fix(deps): update rosetta.dsl.version to v9.77.1
---
pom.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/pom.xml b/pom.xml
index 0869a824..a3444769 100644
--- a/pom.xml
+++ b/pom.xml
@@ -81,7 +81,7 @@
s01.oss.sonatype.org
20
- 9.77.0
+ 9.77.1
2.38.0
6.0.0
From 9d7665fd73b5cbabe674551f5bb76ab69d76dbab Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Wed, 11 Mar 2026 14:00:51 +0000
Subject: [PATCH 18/25] chore(deps): update dependency
org.apache.maven.plugins:maven-shade-plugin to v3.6.2
---
pom.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/pom.xml b/pom.xml
index a3444769..e8421925 100644
--- a/pom.xml
+++ b/pom.xml
@@ -424,7 +424,7 @@
org.apache.maven.plugins
maven-shade-plugin
- 3.6.1
+ 3.6.2
true
From ebbe0517748465310035bc309b4a92668d3f7d21 Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Wed, 11 Mar 2026 14:04:00 +0000
Subject: [PATCH 19/25] chore(deps): update dependency
org.apache.maven.plugins:maven-surefire-plugin to v3.5.5
---
pom.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/pom.xml b/pom.xml
index e8421925..34e36175 100644
--- a/pom.xml
+++ b/pom.xml
@@ -98,7 +98,7 @@
3.6.0
3.5.0
3.15.0
- 3.5.4
+ 3.5.5
3.1.1
3.1.4
2.8.2
From 62c9ddc8467f5d19177a0a32e0e8487e4946b521 Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Wed, 11 Mar 2026 14:08:30 +0000
Subject: [PATCH 20/25] chore(deps): update actions/upload-artifact action to
v7
---
.github/workflows/release.yml | 2 +-
.github/workflows/scan-cve.yml | 2 +-
.github/workflows/scan-license.yml | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index d54728d3..1c9b8bf1 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -183,7 +183,7 @@ jobs:
- name: In dry run - upload build outputs as workflow artifacts
if: ${{ github.event.inputs.dry_run == 'true' }}
- uses: actions/upload-artifact@v6
+ uses: actions/upload-artifact@v7
with:
name: dry-run-${{ needs.prepare-release.outputs.tag_name }}
path: |
diff --git a/.github/workflows/scan-cve.yml b/.github/workflows/scan-cve.yml
index f751959f..1a4e8025 100644
--- a/.github/workflows/scan-cve.yml
+++ b/.github/workflows/scan-cve.yml
@@ -53,7 +53,7 @@ jobs:
--out ./reports
- name: Upload Test results
if: ${{ always() }}
- uses: actions/upload-artifact@v6
+ uses: actions/upload-artifact@v7
with:
name: Depcheck report
path: ${{github.workspace}}/reports
diff --git a/.github/workflows/scan-license.yml b/.github/workflows/scan-license.yml
index 95485680..2e9ef5f5 100644
--- a/.github/workflows/scan-license.yml
+++ b/.github/workflows/scan-license.yml
@@ -82,7 +82,7 @@ jobs:
if [ $LINES_FOUND -gt 1 ]; then echo $LICENSE_REPORT ; exit -1; fi
working-directory: .
- name: Upload license XML reports
- uses: actions/upload-artifact@v6
+ uses: actions/upload-artifact@v7
with:
name: license-xml-report
path: './**/${{ env.REPORT_PATH }}'
From 74d59961bd0b9dba83eabf409764f3873bdaa8b0 Mon Sep 17 00:00:00 2001
From: dschwartznyc
Date: Fri, 27 Mar 2026 18:22:55 -0400
Subject: [PATCH 21/25] feat: update to use the PyPI version of the runtime
---
.../python/util/PythonCodeGeneratorUtil.java | 2 +-
test/python_setup/setup_python_env.sh | 19 -------------------
2 files changed, 1 insertion(+), 20 deletions(-)
diff --git a/src/main/java/com/regnosys/rosetta/generator/python/util/PythonCodeGeneratorUtil.java b/src/main/java/com/regnosys/rosetta/generator/python/util/PythonCodeGeneratorUtil.java
index dc7258d1..0e966f43 100644
--- a/src/main/java/com/regnosys/rosetta/generator/python/util/PythonCodeGeneratorUtil.java
+++ b/src/main/java/com/regnosys/rosetta/generator/python/util/PythonCodeGeneratorUtil.java
@@ -106,7 +106,7 @@ public static String createPYProjectTomlFile(String namespace, String version) {
requires-python = ">= 3.11"
dependencies = [
"pydantic>=2.10.3",
- "rune.runtime>=1.0.0,<1.1.0"
+ "rune.runtime>=1.0.0,<2.0.0"
]
[tool.setuptools.packages.find]
where = ["src"]""".formatted(namespace, version).stripIndent();
diff --git a/test/python_setup/setup_python_env.sh b/test/python_setup/setup_python_env.sh
index 81ab2473..7c3be670 100755
--- a/test/python_setup/setup_python_env.sh
+++ b/test/python_setup/setup_python_env.sh
@@ -61,25 +61,6 @@ if [ -n "$RUNE_RUNTIME_FILE" ]; then
echo "Error: Local file $RUNE_RUNTIME_FILE not found."
error
fi
-else
- # --- Remote Repository Logic ---
- echo "No local source provided. Pulling from repo..."
- RUNTIMEURL="https://api.github.com/repos/finos/rune-python-runtime/releases/latest"
-
- release_data=$(curl -s $RUNTIMEURL)
- download_url=$(echo "$release_data" | grep '"browser_download_url":' | head -n 1 | sed -E 's/.*"([^"]+)".*/\1/')
-
- if command -v wget &>/dev/null; then
- wget "$download_url"
- elif command -v curl &>/dev/null; then
- curl -LO "$download_url"
- else
- echo "Neither wget nor curl is installed."
- error
- fi
-
- ${PYEXE} -m pip install rune_runtime*-py3-*.whl --force-reinstall || error
- rm rune_runtime*-py3-*.whl
fi
deactivate
From f7d7910149b0dcd93ca8af94484404ad930f8567 Mon Sep 17 00:00:00 2001
From: dschwartznyc
Date: Mon, 30 Mar 2026 15:56:49 -0400
Subject: [PATCH 22/25] feat: add project name override for pyproject.toml
generation
---
.../generator/python/PythonCodeGenerator.java | 18 ++++++++++-
.../python/PythonCodeGeneratorCLI.java | 30 +++++++++++++++----
.../python/util/PythonCodeGeneratorUtil.java | 11 +++++--
3 files changed, 51 insertions(+), 8 deletions(-)
diff --git a/src/main/java/com/regnosys/rosetta/generator/python/PythonCodeGenerator.java b/src/main/java/com/regnosys/rosetta/generator/python/PythonCodeGenerator.java
index f54af1ca..97eb92f9 100644
--- a/src/main/java/com/regnosys/rosetta/generator/python/PythonCodeGenerator.java
+++ b/src/main/java/com/regnosys/rosetta/generator/python/PythonCodeGenerator.java
@@ -97,11 +97,27 @@ public class PythonCodeGenerator extends AbstractExternalGenerator {
private Map contexts = null;
+ /**
+ * Optional override for the pyproject.toml project name.
+ * When null, the name is derived from the namespace as "python-<first-segment>".
+ */
+ private String projectName = null;
+
public PythonCodeGenerator() {
super(PYTHON);
contexts = new HashMap<>();
}
+ /**
+ * Overrides the pyproject.toml project name. When not set (or set to null),
+ * the name is derived from the namespace as "python-<first-segment>".
+ *
+ * @param projectName the project name, or null for default behaviour
+ */
+ public void setProjectName(String projectName) {
+ this.projectName = projectName;
+ }
+
@Override
public Map beforeAllGenerate(ResourceSet set,
Collection extends RosettaModel> models, String version) {
@@ -180,7 +196,7 @@ private Map processDAG(String nameSpace, PythonCodeGenerat
Set enumImports = context.getEnumImports();
if (nameSpaceObjects != null && !nameSpaceObjects.isEmpty() && dependencyDAG != null && enumImports != null) {
- result.put(PYPROJECT_TOML, PythonCodeGeneratorUtil.createPYProjectTomlFile(nameSpace, cleanVersion));
+ result.put(PYPROJECT_TOML, PythonCodeGeneratorUtil.createPYProjectTomlFile(nameSpace, cleanVersion, projectName));
PythonCodeWriter bundleWriter = new PythonCodeWriter();
TopologicalOrderIterator topologicalOrderIterator = new TopologicalOrderIterator<>(
dependencyDAG);
diff --git a/src/main/java/com/regnosys/rosetta/generator/python/PythonCodeGeneratorCLI.java b/src/main/java/com/regnosys/rosetta/generator/python/PythonCodeGeneratorCLI.java
index d98f4b21..689ba54a 100644
--- a/src/main/java/com/regnosys/rosetta/generator/python/PythonCodeGeneratorCLI.java
+++ b/src/main/java/com/regnosys/rosetta/generator/python/PythonCodeGeneratorCLI.java
@@ -96,6 +96,9 @@ public int execute(String[] args) {
.desc("Continue generation even if validation errors occur").build();
Option failOnWarningsOpt = Option.builder("w").longOpt("fail-on-warnings")
.desc("Treat validation warnings as errors").build();
+ Option projectNameOpt = Option.builder("n").longOpt("project-name").argName("projectName")
+ .desc("Override the pyproject.toml project name (default: python-)")
+ .hasArg().build();
options.addOption(help);
options.addOption(srcDirOpt);
@@ -103,6 +106,7 @@ public int execute(String[] args) {
options.addOption(tgtDirOpt);
options.addOption(allowErrorsOpt);
options.addOption(failOnWarningsOpt);
+ options.addOption(projectNameOpt);
CommandLineParser parser = new DefaultParser();
try {
@@ -114,13 +118,14 @@ public int execute(String[] args) {
String tgtDir = cmd.getOptionValue("t", "./python");
boolean allowErrors = cmd.hasOption("e");
boolean failOnWarnings = cmd.hasOption("w");
+ String projectName = cmd.getOptionValue("n");
if (cmd.hasOption("s")) {
String srcDir = cmd.getOptionValue("s");
- return translateFromSourceDir(srcDir, tgtDir, allowErrors, failOnWarnings);
+ return translateFromSourceDir(srcDir, tgtDir, allowErrors, failOnWarnings, projectName);
} else if (cmd.hasOption("f")) {
String srcFile = cmd.getOptionValue("f");
- return translateFromSourceFile(srcFile, tgtDir, allowErrors, failOnWarnings);
+ return translateFromSourceFile(srcFile, tgtDir, allowErrors, failOnWarnings, projectName);
} else {
System.err.println("Either a source directory (-s) or source file (-f) must be specified.");
printUsage(options);
@@ -139,7 +144,11 @@ private static void printUsage(Options options) {
}
protected int translateFromSourceDir(String srcDir, String tgtDir, boolean allowErrors, boolean failOnWarnings) {
- // Find all .rosetta files in a directory
+ return translateFromSourceDir(srcDir, tgtDir, allowErrors, failOnWarnings, null);
+ }
+
+ protected int translateFromSourceDir(String srcDir, String tgtDir, boolean allowErrors, boolean failOnWarnings,
+ String projectName) {
Path srcDirPath = Paths.get(srcDir);
if (!Files.exists(srcDirPath)) {
LOGGER.error("Source directory does not exist: {}", srcDir);
@@ -154,7 +163,7 @@ protected int translateFromSourceDir(String srcDir, String tgtDir, boolean allow
.filter(Files::isRegularFile)
.filter(f -> f.getFileName().toString().endsWith(".rosetta"))
.collect(Collectors.toList());
- return processRosettaFiles(rosettaFiles, tgtDir, allowErrors, failOnWarnings);
+ return processRosettaFiles(rosettaFiles, tgtDir, allowErrors, failOnWarnings, projectName);
} catch (IOException e) {
LOGGER.error("Failed to process source directory: {}", srcDir, e);
return 1;
@@ -162,6 +171,11 @@ protected int translateFromSourceDir(String srcDir, String tgtDir, boolean allow
}
protected int translateFromSourceFile(String srcFile, String tgtDir, boolean allowErrors, boolean failOnWarnings) {
+ return translateFromSourceFile(srcFile, tgtDir, allowErrors, failOnWarnings, null);
+ }
+
+ protected int translateFromSourceFile(String srcFile, String tgtDir, boolean allowErrors, boolean failOnWarnings,
+ String projectName) {
Path srcFilePath = Paths.get(srcFile);
if (!Files.exists(srcFilePath)) {
LOGGER.error("Source file does not exist: {}", srcFile);
@@ -176,7 +190,7 @@ protected int translateFromSourceFile(String srcFile, String tgtDir, boolean all
return 1;
}
List rosettaFiles = List.of(srcFilePath);
- return processRosettaFiles(rosettaFiles, tgtDir, allowErrors, failOnWarnings);
+ return processRosettaFiles(rosettaFiles, tgtDir, allowErrors, failOnWarnings, projectName);
}
protected IResourceValidator getValidator(Injector injector) {
@@ -186,6 +200,11 @@ protected IResourceValidator getValidator(Injector injector) {
// Common processing function
protected int processRosettaFiles(List rosettaFiles, String tgtDir, boolean allowErrors,
boolean failOnWarnings) {
+ return processRosettaFiles(rosettaFiles, tgtDir, allowErrors, failOnWarnings, null);
+ }
+
+ protected int processRosettaFiles(List rosettaFiles, String tgtDir, boolean allowErrors,
+ boolean failOnWarnings, String projectName) {
LOGGER.info("Processing {} .rosetta files, writing to: {}", rosettaFiles.size(), tgtDir);
if (rosettaFiles.isEmpty()) {
@@ -204,6 +223,7 @@ protected int processRosettaFiles(List rosettaFiles, String tgtDir, boolea
.forEach(resources::add);
PythonCodeGenerator pythonCodeGenerator = injector.getInstance(PythonCodeGenerator.class);
+ pythonCodeGenerator.setProjectName(projectName);
PythonModelLoader modelLoader = injector.getInstance(PythonModelLoader.class);
List models = modelLoader.getRosettaModels(resources);
diff --git a/src/main/java/com/regnosys/rosetta/generator/python/util/PythonCodeGeneratorUtil.java b/src/main/java/com/regnosys/rosetta/generator/python/util/PythonCodeGeneratorUtil.java
index 0e966f43..3abb4349 100644
--- a/src/main/java/com/regnosys/rosetta/generator/python/util/PythonCodeGeneratorUtil.java
+++ b/src/main/java/com/regnosys/rosetta/generator/python/util/PythonCodeGeneratorUtil.java
@@ -95,13 +95,20 @@ public static String getNamespace(RosettaModel rm) {
}
public static String createPYProjectTomlFile(String namespace, String version) {
+ return createPYProjectTomlFile(namespace, version, null);
+ }
+
+ public static String createPYProjectTomlFile(String namespace, String version, String projectName) {
+ String name = (projectName != null && !projectName.isBlank())
+ ? projectName
+ : "python-" + namespace.split("\\.")[0];
return """
[build-system]
requires = ["setuptools>=62.0"]
build-backend = "setuptools.build_meta"
[project]
- name = "python-%s"
+ name = "%s"
version = "%s"
requires-python = ">= 3.11"
dependencies = [
@@ -109,7 +116,7 @@ public static String createPYProjectTomlFile(String namespace, String version) {
"rune.runtime>=1.0.0,<2.0.0"
]
[tool.setuptools.packages.find]
- where = ["src"]""".formatted(namespace, version).stripIndent();
+ where = ["src"]""".formatted(name, version).stripIndent();
}
public static String cleanVersion(String version) {
From d958efc466a983e6c1d8dcd46c4aa94d4d9ad3a3 Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Tue, 31 Mar 2026 15:05:40 +0000
Subject: [PATCH 23/25] chore(deps): update dependency
org.apache.maven.plugins:maven-resources-plugin to v3.5.0
---
pom.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/pom.xml b/pom.xml
index 7f4d41eb..8afc9ddf 100644
--- a/pom.xml
+++ b/pom.xml
@@ -105,7 +105,7 @@
3.1.1
1.6.13
3.2.8
- 3.4.0
+ 3.5.0
build/common-domain-model/rosetta-source/src/main/rosetta
target/python-cdm
From d45a2acd61b999305500ae4da952931397fac0b4 Mon Sep 17 00:00:00 2001
From: dschwartznyc
Date: Tue, 31 Mar 2026 11:08:58 -0400
Subject: [PATCH 24/25] Update Apache Commons Lang version to 3.20.0
---
pom.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/pom.xml b/pom.xml
index ea34a8a7..4c02d168 100644
--- a/pom.xml
+++ b/pom.xml
@@ -71,7 +71,7 @@
[21,22)
21
- 3.19.0
+ 3.20.0
1.15.0
2.21.0
33.3.1-jre
From 825664778a7ad89593b8562fc7f70d332cb4be5d Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Tue, 31 Mar 2026 15:19:04 +0000
Subject: [PATCH 25/25] chore(config): migrate config .github/renovate.json
---
.github/renovate.json | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/.github/renovate.json b/.github/renovate.json
index eff022d8..bc14dbe8 100644
--- a/.github/renovate.json
+++ b/.github/renovate.json
@@ -62,7 +62,6 @@
],
"prCreation": "immediate",
"prPriority": 100,
- "stabilityDays": 0,
"minimumReleaseAge": "0 days",
"schedule": [
"at any time"
@@ -87,4 +86,4 @@
"dependencyDashboardApproval": true
}
]
-}
\ No newline at end of file
+}