Skip to content

Commit a80df52

Browse files
feat: CLI requires the package name and fails if not provided
1 parent 25f5bb8 commit a80df52

4 files changed

Lines changed: 44 additions & 10 deletions

File tree

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

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,6 @@ public void setNamespacePrefix(String namespacePrefix) {
186186
return result;
187187
}
188188

189-
//todo: manage defining project name when there are multiple namespaces - currently it will just use the first one it encounters, but this may not be ideal
190189
@Override
191190
public Map<String, ? extends CharSequence> afterAllGenerate(
192191
ResourceSet set,
@@ -201,9 +200,22 @@ public void setNamespacePrefix(String namespacePrefix) {
201200
result.putAll(generateInits(subfolders));
202201
result.putAll(processDAG(nameSpace, context, cleanVersion));
203202
}
204-
String resolvedProjectName = (projectName != null && !projectName.isBlank())
205-
? projectName
206-
: "python-" + contexts.keySet().stream().findFirst().map(ns -> ns.split("\\.")[0]).orElse("unknown");
203+
String resolvedProjectName;
204+
if (projectName != null && !projectName.isBlank()) {
205+
resolvedProjectName = projectName;
206+
} else {
207+
String derivedNamespace = contexts.entrySet().stream()
208+
.max(Comparator.comparingInt(e -> e.getValue().getSubfolders().size()))
209+
.map(Map.Entry::getKey)
210+
.orElse("unknown");
211+
resolvedProjectName = "python-" + derivedNamespace;
212+
if (contexts.size() > 1) {
213+
LOGGER.warn(
214+
"Multiple top-level namespaces found: {}. Defaulting pyproject.toml project name to '{}' "
215+
+ "(largest namespace by file count). Set an explicit project name via setProjectName() to suppress this warning.",
216+
contexts.keySet(), resolvedProjectName);
217+
}
218+
}
207219
result.put(PYPROJECT_TOML, PythonCodeGeneratorUtil.createToml(resolvedProjectName, cleanVersion));
208220
return result;
209221
}

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

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,8 @@
5656
* process</li>
5757
* <li><b>-t, --tgt &lt;target-dir&gt;</b>: Target directory for generated
5858
* Python code (defaults to <code>./python</code> if not specified)</li>
59-
* <li><b>-p, --project-name &lt;projectName&gt;</b>: Override the
60-
* <code>pyproject.toml</code> project name (default:
61-
* <code>python-&lt;first-namespace-segment&gt;</code>)</li>
59+
* <li><b>-p, --project-name &lt;projectName&gt;</b>: The
60+
* <code>pyproject.toml</code> project name (required)</li>
6261
* <li><b>-x, --namespace-prefix &lt;prefix&gt;</b>: Prepend a prefix segment
6362
* to every generated namespace (e.g. {@code finos} turns {@code cdm.x.y} into
6463
* {@code finos.cdm.x.y})</li>
@@ -119,7 +118,7 @@ public int execute(String[] args) {
119118
Option failOnWarningsOpt = Option.builder("w").longOpt("fail-on-warnings")
120119
.desc("Treat validation warnings as errors").build();
121120
Option projectNameOpt = Option.builder("p").longOpt("project-name").argName("projectName")
122-
.desc("Override the pyproject.toml project name (default: python-<first-namespace-segment>)")
121+
.desc("The pyproject.toml project name (required)")
123122
.hasArg().build();
124123
Option namespacePrefixOpt = Option.builder("x").longOpt("namespace-prefix").argName("namespacePrefix")
125124
.desc("Prepend a prefix segment to every namespace (e.g. 'finos' turns 'cdm.x.y' into 'finos.cdm.x.y')")
@@ -162,6 +161,12 @@ public int execute(String[] args) {
162161
}
163162
}
164163

164+
if (projectName == null || projectName.isBlank()) {
165+
System.err.println("Project name (-p / --project-name) is required.");
166+
printUsage(options);
167+
return 1;
168+
}
169+
165170
if (cmd.hasOption("s")) {
166171
String srcDir = cmd.getOptionValue("s");
167172
return translateFromSourceDir(

src/test/java/com/regnosys/rosetta/generator/python/PythonCodeGeneratorCLITest.java

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,17 @@ void testInvalidSourceFileReturnsError() {
4949
assertEquals(1, exitCode, "Should return 1 when source file does not exist");
5050
}
5151

52+
@Test
53+
void testMissingProjectNameReturnsError() throws IOException {
54+
Path validFile = createValidRosettaFile(tempDir);
55+
PythonCodeGeneratorCLI cli = new PythonCodeGeneratorCLI();
56+
int exitCode = cli.execute(new String[] {
57+
"-f", validFile.toString(),
58+
"-t", tempDir.resolve("python").toString()
59+
});
60+
assertEquals(1, exitCode, "Should return 1 when -p is not provided");
61+
}
62+
5263
@Test
5364
void testValidationErrorsFailByDefault() throws IOException {
5465
Path validFile = createValidRosettaFile(tempDir); // Use valid file, let MockValidator inject error
@@ -57,7 +68,8 @@ void testValidationErrorsFailByDefault() throws IOException {
5768

5869
int exitCode = cli.execute(new String[] {
5970
"-f", validFile.toString(),
60-
"-t", tempDir.resolve("python").toString()
71+
"-t", tempDir.resolve("python").toString(),
72+
"-p", "test-project"
6173
});
6274

6375
assertEquals(1, exitCode, "Should return 1 (fail) when validation errors occur by default");
@@ -72,6 +84,7 @@ void testAllowErrorsPasses() throws IOException {
7284
int exitCode = cli.execute(new String[] {
7385
"-f", validFile.toString(),
7486
"-t", tempDir.resolve("python").toString(),
87+
"-p", "test-project",
7588
"-e"
7689
});
7790

@@ -87,6 +100,7 @@ void testWarningsFailWithFlag() throws IOException {
87100
int exitCode = cli.execute(new String[] {
88101
"-f", validFile.toString(),
89102
"-t", tempDir.resolve("python").toString(),
103+
"-p", "test-project",
90104
"-w" // --fail-on-warnings
91105
});
92106

@@ -123,6 +137,7 @@ void testDevVersionFormatIsAcceptedAndConverted() throws IOException {
123137
int exitCode = cli.execute(new String[] {
124138
"-f", validFile.toString(),
125139
"-t", outputDir.toString(),
140+
"-p", "test-project",
126141
"-v", "1.2.3-dev.4"
127142
});
128143

@@ -143,6 +158,7 @@ void testDevVersionWithZeroPatchIsAccepted() throws IOException {
143158
int exitCode = cli.execute(new String[] {
144159
"-f", validFile.toString(),
145160
"-t", outputDir.toString(),
161+
"-p", "test-project",
146162
"-v", "1.2.3-dev.0"
147163
});
148164

@@ -168,6 +184,7 @@ void testValidVersionAppearsInToml() throws IOException {
168184
int exitCode = cli.execute(new String[] {
169185
"-f", validFile.toString(),
170186
"-t", outputDir.toString(),
187+
"-p", "test-project",
171188
"-v", "2.5.1"
172189
});
173190

test/cdm_tests/cdm_setup/build_cdm.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ CDM_SOURCE_PATH="$MY_PATH/../rosetta"
4646
PYTHON_TARGET_PATH=$PROJECT_ROOT_PATH/target/python-cdm
4747
PYTHON_SETUP_PATH="$MY_PATH/../../python_setup"
4848
JAR_PATH="$PROJECT_ROOT_PATH/target/python-0.0.0.main-SNAPSHOT.jar"
49-
CDM_PROJECT_NAME="finos_cdm"
49+
CDM_PROJECT_NAME="finos-cdm"
5050
cd ${MY_PATH} || error
5151

5252
# Parse command-line arguments for --skip-cdm

0 commit comments

Comments
 (0)