@contractkit/plugin-python 0.11.5 → 0.11.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -5,9 +5,9 @@ $ tsup src/index.ts --format esm --sourcemap --dts && tsc --emitDeclarationOnly
5
5
  CLI tsup v8.5.1
6
6
  CLI Target: esnext
7
7
  ESM Build start
8
- ESM dist/index.js 42.68 KB
9
- ESM dist/index.js.map 90.20 KB
10
- ESM ⚡️ Build success in 183ms
8
+ ESM dist/index.js 43.30 KB
9
+ ESM dist/index.js.map 92.85 KB
10
+ ESM ⚡️ Build success in 274ms
11
11
  DTS Build start
12
- DTS ⚡️ Build success in 4903ms
12
+ DTS ⚡️ Build success in 4814ms
13
13
  DTS dist/index.d.ts 1.10 KB
@@ -3,22 +3,22 @@ $ vitest run --coverage
3
3
   RUN  v4.1.5 /home/runner/work/ContractKit/ContractKit/packages/plugin-python
4
4
  Coverage enabled with v8
5
5
 
6
- ✓ tests/codegen-client.test.ts (27 tests) 127ms
7
- ✓ tests/codegen-models.test.ts (32 tests) 150ms
6
+ ✓ tests/codegen-client.test.ts (30 tests) 70ms
7
+ ✓ tests/codegen-models.test.ts (36 tests) 177ms
8
8
 
9
9
   Test Files  2 passed (2)
10
-  Tests  59 passed (59)
11
-  Start at  19:14:39
12
-  Duration  5.03s (transform 2.04s, setup 0ms, import 6.39s, tests 278ms, environment 0ms)
10
+  Tests  66 passed (66)
11
+  Start at  17:06:40
12
+  Duration  5.70s (transform 2.27s, setup 0ms, import 7.55s, tests 246ms, environment 0ms)
13
13
 
14
14
   % Coverage report from v8
15
15
  -------------------|---------|----------|---------|---------|-------------------
16
16
  File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
17
17
  -------------------|---------|----------|---------|---------|-------------------
18
- All files | 82.67 | 76.92 | 85.71 | 84.75 |
19
- src | 82.36 | 77.14 | 83.33 | 84.2 |
20
- ...gen-client.ts | 82.6 | 77.92 | 86.48 | 83.33 | ...87-507,540-541
21
- ...gen-models.ts | 82.04 | 75.97 | 79.31 | 85.32 | ...33,347-349,353
18
+ All files | 83.57 | 78.28 | 86.31 | 85.13 |
19
+ src | 83.33 | 78.6 | 84.28 | 84.61 |
20
+ ...gen-client.ts | 83.18 | 78.96 | 87.17 | 83.56 | ...02-522,555-556
21
+ ...gen-models.ts | 83.53 | 78.06 | 80.64 | 85.97 | ...59,373-375,379
22
22
  tests | 86.66 | 74.19 | 92 | 92.1 |
23
23
  helpers.ts | 86.66 | 74.19 | 92 | 92.1 | 137-141,167
24
24
  -------------------|---------|----------|---------|---------|-------------------
package/CHANGELOG.md CHANGED
@@ -1,5 +1,20 @@
1
1
  # @contractkit/contractkit-plugin-python
2
2
 
3
+ ## 0.11.7
4
+
5
+ ### Patch Changes
6
+
7
+ - 2bf01f1: Split multi-line descriptions across `#` comment lines and escape `"""` in generated method docstrings so ordinary multi-line doc comments can no longer produce invalid Python. Render the `interval` scalar as `str` and throw on an unmapped scalar type instead of falling back to `Any`.
8
+ - Updated dependencies [2bf01f1]
9
+ - @contractkit/core@0.23.0
10
+
11
+ ## 0.11.6
12
+
13
+ ### Patch Changes
14
+
15
+ - Updated dependencies [0d3b8e2]
16
+ - @contractkit/core@0.22.0
17
+
3
18
  ## 0.11.5
4
19
 
5
20
  ### Patch Changes
@@ -1 +1 @@
1
- {"version":3,"file":"codegen-client.d.ts","sourceRoot":"","sources":["../src/codegen-client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAqF,MAAM,mBAAmB,CAAC;AAMvI,MAAM,WAAW,oBAAoB;IACjC,0EAA0E;IAC1E,gBAAgB,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACvC,0FAA0F;IAC1F,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,kDAAkD;IAClD,eAAe,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC9B;;;;OAIG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,UAAU,EAAE,eAAe,UAAQ,GAAG,OAAO,CAOtF;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,UAAU,EAAE,IAAI,GAAE,oBAAyB,GAAG,MAAM,CA0G9F;AA4XD,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE1D;AAED,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAQ3D;AAED,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAG7D;AAmCD,eAAO,MAAM,cAAc,wuGAqF1B,CAAC"}
1
+ {"version":3,"file":"codegen-client.d.ts","sourceRoot":"","sources":["../src/codegen-client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAqF,MAAM,mBAAmB,CAAC;AAMvI,MAAM,WAAW,oBAAoB;IACjC,0EAA0E;IAC1E,gBAAgB,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACvC,0FAA0F;IAC1F,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,kDAAkD;IAClD,eAAe,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC9B;;;;OAIG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,UAAU,EAAE,eAAe,UAAQ,GAAG,OAAO,CAOtF;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,UAAU,EAAE,IAAI,GAAE,oBAAyB,GAAG,MAAM,CA0G9F;AA2YD,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE1D;AAED,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAQ3D;AAED,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAG7D;AAmCD,eAAO,MAAM,cAAc,wuGAqF1B,CAAC"}
@@ -11,6 +11,15 @@ export interface ModelCodegenOptions {
11
11
  * Generate Pydantic v2 model classes from a ContractRootNode.
12
12
  */
13
13
  export declare function generatePydanticModels(root: ContractRootNode, opts?: ModelCodegenOptions): string;
14
+ /**
15
+ * Render a ContractKit type node as its Python type annotation (Pydantic v2 conventions).
16
+ *
17
+ * @param modelsWithInput - Model names that have a distinct `Input` variant; a `ref` to one of
18
+ * these renders as `<Name>Input` when `forInput` is set.
19
+ * @param forInput - When true, request-side refs use their `Input` variant.
20
+ * @throws {Error} Via the scalar renderer, if a scalar name has no Python mapping (guards against
21
+ * a scalar being added to core without updating this plugin).
22
+ */
14
23
  export declare function renderPyType(type: ContractTypeNode, modelsWithInput?: Set<string>, forInput?: boolean): string;
15
24
  /** Convert a field name to a valid Python identifier in snake_case. */
16
25
  export declare function toPythonFieldName(name: string): string;
@@ -1 +1 @@
1
- {"version":3,"file":"codegen-models.d.ts","sourceRoot":"","sources":["../src/codegen-models.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAwB,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAKlG,MAAM,WAAW,mBAAmB;IAChC,wEAAwE;IACxE,gBAAgB,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACvC,6DAA6D;IAC7D,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,+DAA+D;IAC/D,eAAe,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CACjC;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,gBAAgB,EAAE,IAAI,GAAE,mBAAwB,GAAG,MAAM,CAwDrG;AAsGD,wBAAgB,YAAY,CAAC,IAAI,EAAE,gBAAgB,EAAE,eAAe,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,EAAE,QAAQ,UAAQ,GAAG,MAAM,CAkC5G;AAyCD,uEAAuE;AACvE,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAUtD;AA0JD,kHAAkH;AAClH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAQ3D"}
1
+ {"version":3,"file":"codegen-models.d.ts","sourceRoot":"","sources":["../src/codegen-models.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAwB,gBAAgB,EAAkB,MAAM,mBAAmB,CAAC;AAKlH,MAAM,WAAW,mBAAmB;IAChC,wEAAwE;IACxE,gBAAgB,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACvC,6DAA6D;IAC7D,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,+DAA+D;IAC/D,eAAe,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CACjC;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,gBAAgB,EAAE,IAAI,GAAE,mBAAwB,GAAG,MAAM,CAwDrG;AAsGD;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,gBAAgB,EAAE,eAAe,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,EAAE,QAAQ,UAAQ,GAAG,MAAM,CAkC5G;AA6CD,uEAAuE;AACvE,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAUtD;AAuKD,kHAAkH;AAClH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAQ3D"}
package/dist/index.js CHANGED
@@ -221,6 +221,8 @@ function renderScalar(name) {
221
221
  return "datetime";
222
222
  case "duration":
223
223
  return "timedelta";
224
+ case "interval":
225
+ return "str";
224
226
  case "uuid":
225
227
  return "UUID";
226
228
  case "null":
@@ -231,8 +233,10 @@ function renderScalar(name) {
231
233
  case "json":
232
234
  case "object":
233
235
  return "Any";
234
- default:
235
- return "Any";
236
+ default: {
237
+ const _exhaustive = name;
238
+ throw new Error(`plugin-python: unmapped scalar '${String(_exhaustive)}' \u2014 add a case`);
239
+ }
236
240
  }
237
241
  }
238
242
  __name(renderScalar, "renderScalar");
@@ -244,6 +248,10 @@ function toPythonFieldName(name) {
244
248
  return result;
245
249
  }
246
250
  __name(toPythonFieldName, "toPythonFieldName");
251
+ function commentLines(text, indent) {
252
+ return text.split("\n").map((line) => `${indent}# ${line}`);
253
+ }
254
+ __name(commentLines, "commentLines");
247
255
  function generateModel(model, allModelsWithInput, imports) {
248
256
  if (model.type) {
249
257
  return generateTypeAlias(model, allModelsWithInput, imports);
@@ -257,7 +265,7 @@ function generateModel(model, allModelsWithInput, imports) {
257
265
  __name(generateModel, "generateModel");
258
266
  function generateTypeAlias(model, allModelsWithInput, _) {
259
267
  const lines = [];
260
- if (model.description) lines.push(`# ${model.description}`);
268
+ if (model.description) lines.push(...commentLines(model.description, ""));
261
269
  if (model.deprecated) lines.push("# @deprecated");
262
270
  lines.push(`${model.name} = ${renderPyType(model.type, allModelsWithInput)}`);
263
271
  if (allModelsWithInput.has(model.name)) {
@@ -268,7 +276,7 @@ function generateTypeAlias(model, allModelsWithInput, _) {
268
276
  __name(generateTypeAlias, "generateTypeAlias");
269
277
  function generateSimpleModel(model, allModelsWithInput, imports) {
270
278
  const lines = [];
271
- if (model.description) lines.push(`# ${model.description}`);
279
+ if (model.description) lines.push(...commentLines(model.description, ""));
272
280
  if (model.deprecated) lines.push("# @deprecated");
273
281
  const baseList = model.bases && model.bases.length > 0 ? model.bases.join(", ") : "BaseModel";
274
282
  lines.push(`class ${model.name}(${baseList}):`);
@@ -290,7 +298,7 @@ __name(generateSimpleModel, "generateSimpleModel");
290
298
  function generateSplitModel(model, allModelsWithInput, imports) {
291
299
  const lines = [];
292
300
  const readFields = model.fields.filter((f) => f.visibility !== "writeonly");
293
- if (model.description) lines.push(`# ${model.description}`);
301
+ if (model.description) lines.push(...commentLines(model.description, ""));
294
302
  if (model.deprecated) lines.push("# @deprecated");
295
303
  const readBaseList = model.bases && model.bases.length > 0 ? model.bases.join(", ") : "BaseModel";
296
304
  lines.push(`class ${model.name}(${readBaseList}):`);
@@ -350,7 +358,7 @@ function renderField(field, allModelsWithInput, imports, forInput) {
350
358
  fieldAnnotations.push(`default=${def}`);
351
359
  }
352
360
  if (field.deprecated) lines.push(` # @deprecated`);
353
- if (field.description) lines.push(` # ${field.description}`);
361
+ if (field.description) lines.push(...commentLines(field.description, " "));
354
362
  let rhs;
355
363
  if (fieldAnnotations.length > 0) {
356
364
  imports.add("pydantic", "Field");
@@ -511,8 +519,8 @@ function generateMethod(route, op, opts) {
511
519
  if (op.name || desc) {
512
520
  lines.push(` async def ${methodName}(${selfParam}${paramStr}) -> ${returnType}:`);
513
521
  lines.push(` """`);
514
- if (op.name) lines.push(` ${op.name}`);
515
- if (desc) lines.push(` ${desc}`);
522
+ if (op.name) lines.push(...docstringLines(op.name, " "));
523
+ if (desc) lines.push(...docstringLines(desc, " "));
516
524
  lines.push(` """`);
517
525
  } else {
518
526
  lines.push(` async def ${methodName}(${selfParam}${paramStr}) -> ${returnType}:`);
@@ -596,6 +604,14 @@ function buildHeadersDictLines(headers, typeName) {
596
604
  return lines;
597
605
  }
598
606
  __name(buildHeadersDictLines, "buildHeadersDictLines");
607
+ function docstringLines(text, indent) {
608
+ return text.split("\n").map((line) => {
609
+ let safe = line.replace(/"/g, '\\"');
610
+ if (/\\$/.test(safe)) safe += " ";
611
+ return `${indent}${safe}`;
612
+ });
613
+ }
614
+ __name(docstringLines, "docstringLines");
599
615
  function snakeToPascal(s) {
600
616
  return s.split("_").filter(Boolean).map((p) => p.charAt(0).toUpperCase() + p.slice(1)).join("");
601
617
  }