jsii-pacmak 1.62.0 → 1.63.2

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.
package/jest.config.mjs CHANGED
@@ -2,4 +2,5 @@ import { overriddenConfig } from '../../jest.config.mjs';
2
2
 
3
3
  export default overriddenConfig({
4
4
  coveragePathIgnorePatterns: ['/node_modules/', '<rootDir>/test'],
5
+ watchPathIgnorePatterns: ['.*\\.tsx?$'],
5
6
  });
@@ -103,9 +103,12 @@ class GoTypeRef {
103
103
  ret.push(...this.typeMap.value.dependencies);
104
104
  break;
105
105
  case 'union':
106
- for (const t of this.typeMap.value) {
107
- ret.push(...t.dependencies);
108
- }
106
+ // Unions ultimately result in `interface{}` being rendered, so no import is needed. We
107
+ // hence ignore them entirely here for now. In the future, we may want to inject specific
108
+ // runtime type checks around use of unions, which may result in imports being useful.
109
+ // for (const t of this.typeMap.value) {
110
+ // ret.push(...t.dependencies);
111
+ // }
109
112
  break;
110
113
  case 'void':
111
114
  case 'primitive':
@@ -1,4 +1,4 @@
1
- import { Assembly, OptionalValue, TypeReference } from '@jsii/spec';
1
+ import { Assembly, OptionalValue, TypeReference, Type } from '@jsii/spec';
2
2
  export interface TypeName {
3
3
  pythonType(context: NamingContext): string;
4
4
  requiredImports(context: NamingContext): PythonImports;
@@ -17,6 +17,8 @@ export interface PythonImports {
17
17
  export interface NamingContext {
18
18
  /** The assembly in which the PythonType is expressed. */
19
19
  readonly assembly: Assembly;
20
+ /** A resolver to obtain complete information about a type. */
21
+ readonly typeResolver: (fqn: string) => Type;
20
22
  /** The submodule of the assembly in which the PythonType is expressed (could be the module root) */
21
23
  readonly submodule: string;
22
24
  /**
@@ -68,4 +70,14 @@ export declare function toPythonFqn(fqn: string, rootAssm: Assembly): {
68
70
  packageName: string;
69
71
  pythonFqn: string;
70
72
  };
73
+ /**
74
+ * Computes the nesting-qualified name of a type.
75
+ *
76
+ * @param fqn the fully qualified jsii name of the type.
77
+ * @param rootAssm the root assembly for the project.
78
+ *
79
+ * @returns the nesting-qualified python type name (the name of the class,
80
+ * qualified with all nesting parent classes).
81
+ */
82
+ export declare function toPythonFullName(fqn: string, rootAssm: Assembly): string;
71
83
  //# sourceMappingURL=type-name.d.ts.map
@@ -12,7 +12,7 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
12
12
  };
13
13
  var _Dict_element, _List_element, _Optional_wrapped, _Primitive_pythonType, _Union_options, _UserType_fqn;
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
- exports.toPythonFqn = exports.mergePythonImports = exports.toPackageName = exports.toTypeName = void 0;
15
+ exports.toPythonFullName = exports.toPythonFqn = exports.mergePythonImports = exports.toPackageName = exports.toTypeName = void 0;
16
16
  const spec_1 = require("@jsii/spec");
17
17
  const codemaker_1 = require("codemaker");
18
18
  const crypto_1 = require("crypto");
@@ -193,11 +193,18 @@ class UserType {
193
193
  }
194
194
  return { [requiredImport.sourcePackage]: new Set([requiredImport.item]) };
195
195
  }
196
- resolve({ assembly, emittedTypes, submodule, surroundingTypeFqns, typeAnnotation = true, }) {
196
+ resolve({ assembly, emittedTypes, submodule, surroundingTypeFqns, typeAnnotation = true, parameterType, typeResolver, }) {
197
197
  const { assemblyName, packageName, pythonFqn } = toPythonFqn(__classPrivateFieldGet(this, _UserType_fqn, "f"), assembly);
198
+ // If this is a type annotation for a parameter, allow dicts to be passed where structs are expected.
199
+ const type = typeResolver(__classPrivateFieldGet(this, _UserType_fqn, "f"));
200
+ const isStruct = (0, spec_1.isInterfaceType)(type) && !!type.datatype;
201
+ const wrapType = typeAnnotation && parameterType && isStruct
202
+ ? (pyType) => `typing.Union[${pyType}, typing.Dict[str, typing.Any]]`
203
+ : (pyType) => pyType;
198
204
  if (assemblyName !== assembly.name) {
199
205
  return {
200
- pythonType: pythonFqn,
206
+ // If it's a struct, then we allow passing as a dict, too...
207
+ pythonType: wrapType(pythonFqn),
201
208
  requiredImport: {
202
209
  sourcePackage: packageName,
203
210
  item: '',
@@ -219,7 +226,7 @@ class UserType {
219
226
  (!emittedTypes.has(__classPrivateFieldGet(this, _UserType_fqn, "f")) || nestingParent != null)) {
220
227
  // Possibly a forward reference, outputting the stringifierd python FQN
221
228
  return {
222
- pythonType: JSON.stringify(pythonFqn.substring(submodulePythonName.length + 1)),
229
+ pythonType: wrapType(JSON.stringify(pythonFqn.substring(submodulePythonName.length + 1))),
223
230
  };
224
231
  }
225
232
  if (!typeAnnotation && nestingParent) {
@@ -230,7 +237,7 @@ class UserType {
230
237
  }
231
238
  // We'll just make a module-qualified reference at this point.
232
239
  return {
233
- pythonType: pythonFqn.substring(submodulePythonName.length + 1),
240
+ pythonType: wrapType(pythonFqn.substring(submodulePythonName.length + 1)),
234
241
  };
235
242
  }
236
243
  const [toImport, ...nested] = pythonFqn
@@ -262,6 +269,20 @@ function toPythonFqn(fqn, rootAssm) {
262
269
  return { assemblyName, packageName, pythonFqn: fqnParts.join('.') };
263
270
  }
264
271
  exports.toPythonFqn = toPythonFqn;
272
+ /**
273
+ * Computes the nesting-qualified name of a type.
274
+ *
275
+ * @param fqn the fully qualified jsii name of the type.
276
+ * @param rootAssm the root assembly for the project.
277
+ *
278
+ * @returns the nesting-qualified python type name (the name of the class,
279
+ * qualified with all nesting parent classes).
280
+ */
281
+ function toPythonFullName(fqn, rootAssm) {
282
+ const { packageName, pythonFqn } = toPythonFqn(fqn, rootAssm);
283
+ return pythonFqn.slice(packageName.length + 1);
284
+ }
285
+ exports.toPythonFullName = toPythonFullName;
265
286
  /**
266
287
  * Computes the python relative import path from `fromModule` to `toModule`.
267
288
  *
@@ -442,6 +442,10 @@ class BaseMethod {
442
442
  arguments: documentableArgs,
443
443
  documentableItem: `method-${this.pythonName}`,
444
444
  });
445
+ if ((this.shouldEmitBody || forceEmitBody) &&
446
+ (!renderAbstract || !this.abstract)) {
447
+ emitParameterTypeChecks(code, pythonParams.slice(1), `${(0, type_name_1.toPythonFullName)(this.parent.fqn, context.assembly)}.${this.pythonName}`);
448
+ }
445
449
  this.emitBody(code, context, renderAbstract, forceEmitBody, liftedPropNames, pythonParams[0], returnType);
446
450
  code.closeBlock();
447
451
  }
@@ -573,6 +577,7 @@ class BaseProperty {
573
577
  this.generator.emitDocString(code, this.apiLocation, this.docs, {
574
578
  documentableItem: `prop-${this.pythonName}`,
575
579
  });
580
+ // NOTE: No parameters to validate here, this is a getter...
576
581
  if ((this.shouldEmitBody || forceEmitBody) &&
577
582
  (!renderAbstract || !this.abstract)) {
578
583
  code.line(`return typing.cast(${pythonType}, jsii.${this.jsiiGetMethod}(${this.implicitParameter}, "${this.jsName}"))`);
@@ -590,6 +595,11 @@ class BaseProperty {
590
595
  openSignature(code, 'def', this.pythonName, [this.implicitParameter, `value: ${pythonType}`], false, 'None');
591
596
  if ((this.shouldEmitBody || forceEmitBody) &&
592
597
  (!renderAbstract || !this.abstract)) {
598
+ emitParameterTypeChecks(code, [`value: ${pythonType}`],
599
+ // In order to get a property accessor, we must resort to getting the
600
+ // attribute on the type, instead of the value (where the getter would
601
+ // be implicitly invoked for us...)
602
+ `getattr(${(0, type_name_1.toPythonFullName)(this.parent.fqn, context.assembly)}, ${JSON.stringify(this.pythonName)}).fset`);
593
603
  code.line(`jsii.${this.jsiiSetMethod}(${this.implicitParameter}, "${this.jsName}", value)`);
594
604
  }
595
605
  else {
@@ -724,7 +734,7 @@ class Struct extends BasePythonClassType {
724
734
  : [implicitParameter];
725
735
  openSignature(code, 'def', '__init__', constructorArguments, false, 'None');
726
736
  this.emitConstructorDocstring(code);
727
- // Re-type struct arguments that were passed as "dict"
737
+ // Re-type struct arguments that were passed as "dict". Do this before validating argument types...
728
738
  for (const member of members.filter((m) => m.isStruct(this.generator))) {
729
739
  // Note that "None" is NOT an instance of dict (that's convenient!)
730
740
  const typeName = (0, type_name_1.toTypeName)(member.type.type).pythonType({
@@ -735,6 +745,7 @@ class Struct extends BasePythonClassType {
735
745
  code.line(`${member.pythonName} = ${typeName}(**${member.pythonName})`);
736
746
  code.closeBlock();
737
747
  }
748
+ emitParameterTypeChecks(code, kwargs, `${(0, type_name_1.toPythonFullName)(this.spec.fqn, context.assembly)}.__init__`);
738
749
  // Required properties, those will always be put into the dict
739
750
  assignDictionary(code, `${implicitParameter}._values: typing.Dict[str, typing.Any]`, members
740
751
  .filter((m) => !m.optional)
@@ -763,6 +774,7 @@ class Struct extends BasePythonClassType {
763
774
  code.line('@builtins.property');
764
775
  openSignature(code, 'def', member.pythonName, ['self'], true, pythonType);
765
776
  member.emitDocString(code);
777
+ // NOTE: No parameter to validate here, this is a getter.
766
778
  code.line(`result = self._values.get(${JSON.stringify(member.pythonName)})`);
767
779
  if (!member.optional) {
768
780
  // Add an assertion to maye MyPY happy!
@@ -1099,6 +1111,8 @@ class PythonModule {
1099
1111
  code.line('import jsii');
1100
1112
  code.line('import publication');
1101
1113
  code.line('import typing_extensions');
1114
+ code.line();
1115
+ code.line('from typeguard import check_type');
1102
1116
  // Determine if we need to write out the kernel load line.
1103
1117
  if (this.loadAssembly) {
1104
1118
  this.emitDependencyImports(code);
@@ -1376,6 +1390,7 @@ class Package {
1376
1390
  install_requires: [
1377
1391
  `jsii${(0, version_utils_1.toPythonVersionRange)(`^${jsiiVersionSimple}`)}`,
1378
1392
  'publication>=0.0.3',
1393
+ 'typeguard~=2.13.3',
1379
1394
  ]
1380
1395
  .concat(dependencies)
1381
1396
  .sort(),
@@ -1709,6 +1724,7 @@ class PythonGenerator extends generator_1.Generator {
1709
1724
  emittedTypes: new Set(),
1710
1725
  resolver,
1711
1726
  submodule: assm.name,
1727
+ typeResolver: (fqn) => resolver.dereference(fqn),
1712
1728
  });
1713
1729
  }
1714
1730
  /**
@@ -1762,7 +1778,8 @@ class PythonGenerator extends generator_1.Generator {
1762
1778
  }
1763
1779
  onStaticMethod(cls, method) {
1764
1780
  const { parameters = [] } = method;
1765
- this.getPythonType(cls.fqn).addMember(new StaticMethod(this, toPythonMethodName(method.name), method.name, parameters, method.returns, method.docs, true, // Always static
1781
+ const klass = this.getPythonType(cls.fqn);
1782
+ klass.addMember(new StaticMethod(this, toPythonMethodName(method.name), method.name, parameters, method.returns, method.docs, true, // Always static
1766
1783
  {
1767
1784
  abstract: method.abstract,
1768
1785
  liftedProp: this.getliftedProp(method),
@@ -1770,7 +1787,8 @@ class PythonGenerator extends generator_1.Generator {
1770
1787
  }));
1771
1788
  }
1772
1789
  onStaticProperty(cls, prop) {
1773
- this.getPythonType(cls.fqn).addMember(new StaticProperty(this, toPythonPropertyName(prop.name, prop.const), prop.name, prop, prop.docs, {
1790
+ const klass = this.getPythonType(cls.fqn);
1791
+ klass.addMember(new StaticProperty(this, toPythonPropertyName(prop.name, prop.const), prop.name, prop, prop.docs, {
1774
1792
  abstract: prop.abstract,
1775
1793
  immutable: prop.immutable,
1776
1794
  isStatic: prop.static,
@@ -1779,15 +1797,16 @@ class PythonGenerator extends generator_1.Generator {
1779
1797
  }
1780
1798
  onMethod(cls, method) {
1781
1799
  const { parameters = [] } = method;
1800
+ const klass = this.getPythonType(cls.fqn);
1782
1801
  if (method.async) {
1783
- this.getPythonType(cls.fqn).addMember(new AsyncMethod(this, toPythonMethodName(method.name, method.protected), method.name, parameters, method.returns, method.docs, !!method.static, {
1802
+ klass.addMember(new AsyncMethod(this, toPythonMethodName(method.name, method.protected), method.name, parameters, method.returns, method.docs, !!method.static, {
1784
1803
  abstract: method.abstract,
1785
1804
  liftedProp: this.getliftedProp(method),
1786
1805
  parent: cls,
1787
1806
  }));
1788
1807
  }
1789
1808
  else {
1790
- this.getPythonType(cls.fqn).addMember(new Method(this, toPythonMethodName(method.name, method.protected), method.name, parameters, method.returns, method.docs, !!method.static, {
1809
+ klass.addMember(new Method(this, toPythonMethodName(method.name, method.protected), method.name, parameters, method.returns, method.docs, !!method.static, {
1791
1810
  abstract: method.abstract,
1792
1811
  liftedProp: this.getliftedProp(method),
1793
1812
  parent: cls,
@@ -1795,7 +1814,8 @@ class PythonGenerator extends generator_1.Generator {
1795
1814
  }
1796
1815
  }
1797
1816
  onProperty(cls, prop) {
1798
- this.getPythonType(cls.fqn).addMember(new Property(this, toPythonPropertyName(prop.name, prop.const, prop.protected), prop.name, prop, prop.docs, {
1817
+ const klass = this.getPythonType(cls.fqn);
1818
+ klass.addMember(new Property(this, toPythonPropertyName(prop.name, prop.const, prop.protected), prop.name, prop, prop.docs, {
1799
1819
  abstract: prop.abstract,
1800
1820
  immutable: prop.immutable,
1801
1821
  isStatic: prop.static,
@@ -1820,17 +1840,19 @@ class PythonGenerator extends generator_1.Generator {
1820
1840
  }
1821
1841
  onInterfaceMethod(ifc, method) {
1822
1842
  const { parameters = [] } = method;
1823
- this.getPythonType(ifc.fqn).addMember(new InterfaceMethod(this, toPythonMethodName(method.name, method.protected), method.name, parameters, method.returns, method.docs, !!method.static, { liftedProp: this.getliftedProp(method), parent: ifc }));
1843
+ const klass = this.getPythonType(ifc.fqn);
1844
+ klass.addMember(new InterfaceMethod(this, toPythonMethodName(method.name, method.protected), method.name, parameters, method.returns, method.docs, !!method.static, { liftedProp: this.getliftedProp(method), parent: ifc }));
1824
1845
  }
1825
1846
  onInterfaceProperty(ifc, prop) {
1826
1847
  let ifaceProperty;
1848
+ const klass = this.getPythonType(ifc.fqn);
1827
1849
  if (ifc.datatype) {
1828
1850
  ifaceProperty = new StructField(this, prop, ifc);
1829
1851
  }
1830
1852
  else {
1831
1853
  ifaceProperty = new InterfaceProperty(this, toPythonPropertyName(prop.name, prop.const, prop.protected), prop.name, prop, prop.docs, { immutable: prop.immutable, isStatic: prop.static, parent: ifc });
1832
1854
  }
1833
- this.getPythonType(ifc.fqn).addMember(ifaceProperty);
1855
+ klass.addMember(ifaceProperty);
1834
1856
  }
1835
1857
  onBeginEnum(enm) {
1836
1858
  this.addPythonType(new Enum(this, (0, util_2.toPythonIdentifier)(enm.name), enm, enm.fqn, {}, enm.docs));
@@ -1988,6 +2010,50 @@ function openSignature(code, keyword, name, params, trailingComma = false, retur
1988
2010
  code.unindent(false);
1989
2011
  code.openBlock(`)${suffix}`);
1990
2012
  }
2013
+ /**
2014
+ * Emits runtime type checking code for parameters.
2015
+ *
2016
+ * @param code the CodeMaker to use for emitting code.
2017
+ * @param params the parameter signatures to be type-checked.
2018
+ * @param typedEntity the type-annotated entity.
2019
+ */
2020
+ function emitParameterTypeChecks(code, params, typedEntity) {
2021
+ const paramInfo = params.map((param) => {
2022
+ const [name] = param.split(/\s*[:=]\s*/, 1);
2023
+ if (name === '*') {
2024
+ return { kwargsMark: true };
2025
+ }
2026
+ else if (name.startsWith('*')) {
2027
+ return { name: name.slice(1), is_rest: true };
2028
+ }
2029
+ return { name };
2030
+ });
2031
+ const typesVar = slugifyAsNeeded('type_hints', paramInfo
2032
+ .filter((param) => param.name != null)
2033
+ .map((param) => param.name.split(/\s*:\s*/)[0]));
2034
+ let openedBlock = false;
2035
+ for (const { is_rest, kwargsMark, name } of paramInfo) {
2036
+ if (kwargsMark) {
2037
+ // This is the keyword-args separator, we won't check keyword arguments here because the kwargs will be rolled
2038
+ // up into a struct instance, and that struct's constructor will be checking again...
2039
+ break;
2040
+ }
2041
+ if (!openedBlock) {
2042
+ code.openBlock('if __debug__');
2043
+ code.line(`${typesVar} = typing.get_type_hints(${typedEntity})`);
2044
+ openedBlock = true;
2045
+ }
2046
+ let expectedType = `${typesVar}[${JSON.stringify(name)}]`;
2047
+ if (is_rest) {
2048
+ // This is a vararg, so the value will appear as a tuple.
2049
+ expectedType = `typing.Tuple[${expectedType}, ...]`;
2050
+ }
2051
+ code.line(`check_type(argname=${JSON.stringify(`argument ${name}`)}, value=${name}, expected_type=${expectedType})`);
2052
+ }
2053
+ if (openedBlock) {
2054
+ code.closeBlock();
2055
+ }
2056
+ }
1991
2057
  function assignCallResult(code, variable, funct, params) {
1992
2058
  const prefix = `${variable} = ${funct}(`;
1993
2059
  const suffix = ')';
package/lib/version.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  /** The short version number for this JSII compiler (e.g: `X.Y.Z`) */
2
- export declare const VERSION = "1.62.0";
2
+ export declare const VERSION = "1.63.2";
3
3
  /** The qualified version number for this JSII compiler (e.g: `X.Y.Z (build #######)`) */
4
- export declare const VERSION_DESC = "1.62.0 (build 293ac17)";
4
+ export declare const VERSION_DESC = "1.63.2 (build a8a8833)";
5
5
  //# sourceMappingURL=version.d.ts.map
package/lib/version.js CHANGED
@@ -1,9 +1,9 @@
1
1
  "use strict";
2
- // Generated at 2022-07-12T18:04:59Z by generate.sh
2
+ // Generated at 2022-07-29T15:35:51Z by generate.sh
3
3
  Object.defineProperty(exports, "__esModule", { value: true });
4
4
  exports.VERSION_DESC = exports.VERSION = void 0;
5
5
  /** The short version number for this JSII compiler (e.g: `X.Y.Z`) */
6
- exports.VERSION = '1.62.0';
6
+ exports.VERSION = '1.63.2';
7
7
  /** The qualified version number for this JSII compiler (e.g: `X.Y.Z (build #######)`) */
8
- exports.VERSION_DESC = '1.62.0 (build 293ac17)';
8
+ exports.VERSION_DESC = '1.63.2 (build a8a8833)';
9
9
  //# sourceMappingURL=version.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jsii-pacmak",
3
- "version": "1.62.0",
3
+ "version": "1.63.2",
4
4
  "description": "A code generation framework for jsii backend languages",
5
5
  "license": "Apache-2.0",
6
6
  "author": {
@@ -37,31 +37,31 @@
37
37
  "package": "package-js"
38
38
  },
39
39
  "dependencies": {
40
- "@jsii/check-node": "1.62.0",
41
- "@jsii/spec": "^1.62.0",
40
+ "@jsii/check-node": "1.63.2",
41
+ "@jsii/spec": "^1.63.2",
42
42
  "clone": "^2.1.2",
43
- "codemaker": "^1.62.0",
43
+ "codemaker": "^1.63.2",
44
44
  "commonmark": "^0.30.0",
45
45
  "escape-string-regexp": "^4.0.0",
46
46
  "fs-extra": "^10.1.0",
47
- "jsii-reflect": "^1.62.0",
48
- "jsii-rosetta": "^1.62.0",
47
+ "jsii-reflect": "^1.63.2",
48
+ "jsii-rosetta": "^1.63.2",
49
49
  "semver": "^7.3.7",
50
50
  "spdx-license-list": "^6.6.0",
51
51
  "xmlbuilder": "^15.1.1",
52
52
  "yargs": "^16.2.0"
53
53
  },
54
54
  "devDependencies": {
55
- "@jsii/dotnet-runtime": "^1.62.0",
56
- "@jsii/java-runtime": "^1.62.0",
57
- "@jsii/go-runtime": "^1.62.0",
58
- "@scope/jsii-calc-lib": "^1.62.0",
55
+ "@jsii/dotnet-runtime": "^1.63.2",
56
+ "@jsii/java-runtime": "^1.63.2",
57
+ "@jsii/go-runtime": "^1.63.2",
58
+ "@scope/jsii-calc-lib": "^1.63.2",
59
59
  "@types/clone": "^2.1.1",
60
60
  "@types/commonmark": "^0.27.5",
61
61
  "@types/fs-extra": "^9.0.13",
62
62
  "@types/semver": "^7.3.10",
63
- "jsii": "^1.62.0",
64
- "jsii-build-tools": "^1.62.0",
63
+ "jsii": "^1.63.2",
64
+ "jsii-build-tools": "^1.63.2",
65
65
  "jsii-calc": "^3.20.120"
66
66
  },
67
67
  "keywords": [