From 7de99960923abc75a6ea7330c92eeff867cde2d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=91=A8=F0=9F=8F=BC=E2=80=8D=F0=9F=92=BB=20Romain=20M?= =?UTF-8?q?arcadier-Muller?= Date: Mon, 19 Oct 2020 17:22:31 +0200 Subject: [PATCH 01/16] feat(pacmak): prerelease identifier support When an NPM package built with `jsii` is tagged with a version that includes a prerelease identifier (e.g: `1.2.3-alpha.1`), automatically represent this as a pre-release version in generated packages, too. For most currently supported languages, this simply means forwarding the version untouched, however for Python, prerelease identifiers need to be mapped into one of the supported tokens in PyPI (`.dev#`, `.a#`, `.b#` or `.rc#`). Fixes #2114 --- packages/jsii-pacmak/lib/targets/dotnet.ts | 3 +- .../lib/targets/dotnet/filegenerator.ts | 4 +- packages/jsii-pacmak/lib/targets/java.ts | 15 +-- packages/jsii-pacmak/lib/targets/js.ts | 13 ++- packages/jsii-pacmak/lib/targets/python.ts | 4 +- .../jsii-pacmak/lib/targets/version-utils.ts | 104 +++++++++++++++++- .../test/targets/version-utils.test.ts | 53 +++++++++ 7 files changed, 175 insertions(+), 21 deletions(-) diff --git a/packages/jsii-pacmak/lib/targets/dotnet.ts b/packages/jsii-pacmak/lib/targets/dotnet.ts index 45b022fbc9..a4bbbb3db0 100644 --- a/packages/jsii-pacmak/lib/targets/dotnet.ts +++ b/packages/jsii-pacmak/lib/targets/dotnet.ts @@ -13,6 +13,7 @@ import { shell, Scratch, setExtend, filterAsync } from '../util'; import { DotNetGenerator } from './dotnet/dotnetgenerator'; import { TargetBuilder, BuildOptions } from '../builder'; import { JsiiModule } from '../packaging'; +import { toReleaseVersion } from './version-utils'; export const TARGET_FRAMEWORK = 'netcoreapp3.1'; @@ -274,7 +275,7 @@ export default class Dotnet extends Target { assm: spec.Assembly, ): { [language: string]: PackageInfo } { const packageId = assm.targets!.dotnet!.packageId; - const version = assm.version; + const version = toReleaseVersion(assm.version, 'dotnet'); const packageInfo: PackageInfo = { repository: 'Nuget', url: `https://www.nuget.org/packages/${packageId}/${version}`, diff --git a/packages/jsii-pacmak/lib/targets/dotnet/filegenerator.ts b/packages/jsii-pacmak/lib/targets/dotnet/filegenerator.ts index 14e68a680a..88789671f5 100644 --- a/packages/jsii-pacmak/lib/targets/dotnet/filegenerator.ts +++ b/packages/jsii-pacmak/lib/targets/dotnet/filegenerator.ts @@ -5,7 +5,7 @@ import * as xmlbuilder from 'xmlbuilder'; import { DotNetNameUtils } from './nameutils'; import * as logging from '../../logging'; import { TARGET_FRAMEWORK } from '../dotnet'; -import { toNuGetVersionRange } from '../version-utils'; +import { toNuGetVersionRange, toReleaseVersion } from '../version-utils'; // Represents a dependency in the dependency tree. export class DotNetDependency { @@ -182,6 +182,6 @@ export class FileGenerator { // suffix is guaranteed to start with a leading `-` return `${assembly.version}${suffix}`; } - return assembly.version; + return toReleaseVersion(assembly.version, 'dotnet'); } } diff --git a/packages/jsii-pacmak/lib/targets/java.ts b/packages/jsii-pacmak/lib/targets/java.ts index fd96e469ea..82ea326ada 100644 --- a/packages/jsii-pacmak/lib/targets/java.ts +++ b/packages/jsii-pacmak/lib/targets/java.ts @@ -23,7 +23,7 @@ import { shell, Scratch, slugify, setExtend } from '../util'; import { TargetBuilder, BuildOptions } from '../builder'; import { JsiiModule } from '../packaging'; import { VERSION, VERSION_DESC } from '../version'; -import { toMavenVersionRange } from './version-utils'; +import { toMavenVersionRange, toReleaseVersion } from './version-utils'; import { INCOMPLETE_DISCLAIMER_COMPILING, INCOMPLETE_DISCLAIMER_NONCOMPILING, @@ -366,6 +366,7 @@ export default class Java extends Target { ): { [language: string]: PackageInfo } { const groupId = assm.targets!.java!.maven.groupId; const artifactId = assm.targets!.java!.maven.artifactId; + const releaseVersion = toReleaseVersion(assm.version, 'java'); const url = `https://repo1.maven.org/maven2/${groupId.replace( /\./g, '/', @@ -379,12 +380,12 @@ export default class Java extends Target { language: 'xml', code: xmlbuilder .create({ - dependency: { groupId, artifactId, version: assm.version }, + dependency: { groupId, artifactId, version: releaseVersion }, }) .end({ pretty: true }) .replace(/<\?\s*xml(\s[^>]+)?>\s*/m, ''), }, - 'Apache Buildr': `'${groupId}:${artifactId}:jar:${assm.version}'`, + 'Apache Buildr': `'${groupId}:${artifactId}:jar:${releaseVersion}'`, 'Apache Ivy': { language: 'xml', code: xmlbuilder @@ -392,14 +393,14 @@ export default class Java extends Target { dependency: { '@groupId': groupId, '@name': artifactId, - '@rev': assm.version, + '@rev': releaseVersion, }, }) .end({ pretty: true }) .replace(/<\?\s*xml(\s[^>]+)?>\s*/m, ''), }, - 'Groovy Grape': `@Grapes(\n@Grab(group='${groupId}', module='${artifactId}', version='${assm.version}')\n)`, - 'Gradle / Grails': `compile '${groupId}:${artifactId}:${assm.version}'`, + 'Groovy Grape': `@Grapes(\n@Grab(group='${groupId}', module='${artifactId}', version='${releaseVersion}')\n)`, + 'Gradle / Grails': `compile '${groupId}:${artifactId}:${releaseVersion}'`, }, }, }; @@ -1088,7 +1089,7 @@ class JavaGenerator extends Generator { */ function makeVersion(version: string, suffix?: string): string { if (!suffix) { - return version; + return toReleaseVersion(version, 'java'); } if (!suffix.startsWith('-') && !suffix.startsWith('.')) { throw new Error( diff --git a/packages/jsii-pacmak/lib/targets/js.ts b/packages/jsii-pacmak/lib/targets/js.ts index db5740dd6f..a0e788bda3 100644 --- a/packages/jsii-pacmak/lib/targets/js.ts +++ b/packages/jsii-pacmak/lib/targets/js.ts @@ -1,6 +1,7 @@ import * as spec from '@jsii/spec'; import { Generator } from '../generator'; import { PackageInfo, Target } from '../target'; +import { toReleaseVersion } from './version-utils'; export default class JavaScript extends Target { public static toPackageInfos( @@ -8,7 +9,10 @@ export default class JavaScript extends Target { ): { [language: string]: PackageInfo } { const packageInfo: PackageInfo = { repository: 'NPM', - url: `https://www.npmjs.com/package/${assm.name}/v/${assm.version}`, + url: `https://www.npmjs.com/package/${assm.name}/v/${toReleaseVersion( + assm.version, + 'js', + )}`, usage: { 'package.json': { language: 'js', @@ -16,11 +20,14 @@ export default class JavaScript extends Target { }, npm: { language: 'console', - code: `$ npm i ${assm.name}@${assm.version}`, + code: `$ npm i ${assm.name}@${toReleaseVersion(assm.version, 'js')}`, }, yarn: { language: 'console', - code: `$ yarn add ${assm.name}@${assm.version}`, + code: `$ yarn add ${assm.name}@${toReleaseVersion( + assm.version, + 'js', + )}`, }, }, }; diff --git a/packages/jsii-pacmak/lib/targets/python.ts b/packages/jsii-pacmak/lib/targets/python.ts index d33588d760..13ae992384 100644 --- a/packages/jsii-pacmak/lib/targets/python.ts +++ b/packages/jsii-pacmak/lib/targets/python.ts @@ -14,7 +14,7 @@ import { Rosetta, typeScriptSnippetFromSource, } from 'jsii-rosetta'; -import { toPythonVersionRange } from './version-utils'; +import { toPythonVersionRange, toReleaseVersion } from './version-utils'; import { INCOMPLETE_DISCLAIMER_COMPILING, INCOMPLETE_DISCLAIMER_NONCOMPILING, @@ -2160,7 +2160,7 @@ class PythonGenerator extends Generator { this.package = new Package( this, assm.targets!.python!.distName, - assm.version, + toReleaseVersion(assm.version, 'python'), assm, ); diff --git a/packages/jsii-pacmak/lib/targets/version-utils.ts b/packages/jsii-pacmak/lib/targets/version-utils.ts index 61a527487c..ffa1aafabb 100644 --- a/packages/jsii-pacmak/lib/targets/version-utils.ts +++ b/packages/jsii-pacmak/lib/targets/version-utils.ts @@ -1,4 +1,7 @@ -import { Comparator, Range } from 'semver'; +import { Comparator, Range, parse } from 'semver'; +import { inspect } from 'util'; +import type { TargetName } from '.'; +import { info } from '../logging'; /** * Converts a SemVer range expression to a Maven version range expression. @@ -12,7 +15,10 @@ export function toMavenVersionRange( semverRange: string, suffix?: string, ): string { - return toBracketNotation(semverRange, suffix, { semver: false }); + return toBracketNotation(semverRange, suffix, { + semver: false, + target: 'java', + }); } /** @@ -23,7 +29,10 @@ export function toMavenVersionRange( * @see https://docs.microsoft.com/en-us/nuget/concepts/package-versioning#version-ranges-and-wildcards */ export function toNuGetVersionRange(semverRange: string): string { - return toBracketNotation(semverRange, undefined, { semver: false }); + return toBracketNotation(semverRange, undefined, { + semver: false, + target: 'dotnet', + }); } /** @@ -38,7 +47,10 @@ export function toPythonVersionRange(semverRange: string): string { .map((set) => set .map((comp) => { - const versionId = comp.semver.raw?.replace(/-0$/, '') ?? '0.0.0'; + const versionId = toReleaseVersion( + comp.semver.raw?.replace(/-0$/, '') ?? '0.0.0', + 'python', + ); switch (comp.operator) { case '': // With ^0.0.0, somehow we get a left entry with an empty operator and value, we'll fix this up @@ -55,10 +67,90 @@ export function toPythonVersionRange(semverRange: string): string { .join(', '); } +/** + * Converts an original version number from the NPM convention to the target + * language's convention for expressing the same. For versions that do not + * include a prerelease identifier, this always returns the assembly version + * unmodified. + * + * @param assemblyVersion the assembly version being released + * @param target the target language for which the verison is destined + * + * @returns the version that should be serialized + */ +export function toReleaseVersion( + assemblyVersion: string, + target: TargetName, +): string { + const version = parse(assemblyVersion, { includePrerelease: true }); + if (version == null) { + throw new Error( + `Unable to parse the provided assembly version: "${assemblyVersion}"`, + ); + } + if (version.prerelease.length === 0) { + return assemblyVersion; + } + switch (target) { + case 'python': + // Python supports a limited set of identifiers... And we have a mapping table... + // https://packaging.python.org/guides/distributing-packages-using-setuptools/#pre-release-versioning + const [label, sequence, ...rest] = version.prerelease; + if (rest.length > 0) { + info( + `Unable to map prerelease identifier (in: ${assemblyVersion}) components to python: ${inspect( + version.prerelease, + )}`, + ); + break; + } + if (!Number.isInteger(sequence)) { + info( + `Unable to map prerelease identifier (in: ${assemblyVersion}) to python, as sequence ${inspect( + sequence, + )} is not an integer`, + ); + break; + } + switch (label) { + case 'dev': + return `${version.major}.${version.minor}.${version.patch}.dev${sequence}`; + case 'alpha': + return `${version.major}.${version.minor}.${version.patch}.a${sequence}`; + case 'beta': + return `${version.major}.${version.minor}.${version.patch}.b${sequence}`; + case 'rc': + return `${version.major}.${version.minor}.${version.patch}.rc${sequence}`; + default: + info( + `Unable to map prerelease identifier (in: ${assemblyVersion}) to python, as label ${inspect( + label, + )} is not mapped (only "dev", "alpha", "beta" and "rc" are)`, + ); + } + break; + case 'dotnet': + case 'java': + case 'js': + // Not touching - the NPM version number should be usable as-is + break; + default: + info( + `Unknown target ${inspect( + target, + )} for ${assemblyVersion}. Returning version as-is.`, + ); + } + return assemblyVersion; +} + function toBracketNotation( semverRange: string, suffix?: string, - { semver = true }: { semver?: boolean } = {}, + { + semver = true, + target = 'js', + }: { semver?: boolean; target?: TargetName } = {}, ): string { if (semverRange === '*') { semverRange = '>=0.0.0'; @@ -137,6 +229,6 @@ function toBracketNotation( if (trimDashZero) { str = str.replace(/-0$/, ''); } - return suffix ? `${str}${suffix}` : str; + return suffix ? `${str}${suffix}` : toReleaseVersion(str, target); } } diff --git a/packages/jsii-pacmak/test/targets/version-utils.test.ts b/packages/jsii-pacmak/test/targets/version-utils.test.ts index 13a73cee2a..1e32eed071 100644 --- a/packages/jsii-pacmak/test/targets/version-utils.test.ts +++ b/packages/jsii-pacmak/test/targets/version-utils.test.ts @@ -1,7 +1,9 @@ +import { TargetName } from '../../lib/targets'; import { toMavenVersionRange, toNuGetVersionRange, toPythonVersionRange, + toReleaseVersion, } from '../../lib/targets/version-utils'; const examples: Record< @@ -102,3 +104,54 @@ describe(toPythonVersionRange, () => { expect(toPythonVersionRange(semver)).toEqual(python)); } }); + +describe(toReleaseVersion, () => { + type Expectations = { readonly [K in TargetName]: string }; + const examples: Record = { + '1.2.3': { + dotnet: '1.2.3', + go: '1.2.3', + java: '1.2.3', + js: '1.2.3', + python: '1.2.3', + }, + '1.2.3-pre': { + dotnet: '1.2.3-pre', + go: '1.2.3-pre', + java: '1.2.3-pre', + js: '1.2.3-pre', + python: '1.2.3-pre', + }, + '1.2.3-alpha.1337': { + dotnet: '1.2.3-alpha.1337', + go: '1.2.3-alpha.1337', + java: '1.2.3-alpha.1337', + js: '1.2.3-alpha.1337', + python: '1.2.3.a1337', + }, + '1.2.3-beta.42': { + dotnet: '1.2.3-beta.42', + go: '1.2.3-beta.42', + java: '1.2.3-beta.42', + js: '1.2.3-beta.42', + python: '1.2.3.b42', + }, + '1.2.3-rc.9': { + dotnet: '1.2.3-rc.9', + go: '1.2.3-rc.9', + java: '1.2.3-rc.9', + js: '1.2.3-rc.9', + python: '1.2.3.rc9', + }, + }; + + for (const [version, targets] of Object.entries(examples)) { + test(`"${version}" translations`, () => { + for (const [target, targetVersion] of Object.entries(targets)) { + expect(toReleaseVersion(version, target as TargetName)).toBe( + targetVersion, + ); + } + }); + } +}); From bacaddf9bda6c8c1384ba981c6f1ecdc315ee236 Mon Sep 17 00:00:00 2001 From: Romain Marcadier Date: Thu, 22 Oct 2020 09:59:59 +0200 Subject: [PATCH 02/16] Update packages/jsii-pacmak/lib/targets/version-utils.ts Co-authored-by: Niranjan Jayakar --- packages/jsii-pacmak/lib/targets/version-utils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/jsii-pacmak/lib/targets/version-utils.ts b/packages/jsii-pacmak/lib/targets/version-utils.ts index ffa1aafabb..16d0bb8868 100644 --- a/packages/jsii-pacmak/lib/targets/version-utils.ts +++ b/packages/jsii-pacmak/lib/targets/version-utils.ts @@ -74,7 +74,7 @@ export function toPythonVersionRange(semverRange: string): string { * unmodified. * * @param assemblyVersion the assembly version being released - * @param target the target language for which the verison is destined + * @param target the target language for which the version is destined * * @returns the version that should be serialized */ From 0216e7ffd9fd398ff3e95677e50b010cefd79a61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=91=A8=F0=9F=8F=BC=E2=80=8D=F0=9F=92=BB=20Romain=20M?= =?UTF-8?q?arcadier-Muller?= Date: Thu, 22 Oct 2020 10:30:22 +0200 Subject: [PATCH 03/16] add comment on toBracketNotation --- packages/jsii-pacmak/lib/targets/version-utils.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/packages/jsii-pacmak/lib/targets/version-utils.ts b/packages/jsii-pacmak/lib/targets/version-utils.ts index 7b17cfba89..0930cd570e 100644 --- a/packages/jsii-pacmak/lib/targets/version-utils.ts +++ b/packages/jsii-pacmak/lib/targets/version-utils.ts @@ -136,6 +136,17 @@ export function toReleaseVersion( return assemblyVersion; } +/** + * Converts a semantic version range to the kind of bracket notation used by + * Maven and NuGet. For example, this turns `^1.2.3` into `[1.2.3,2.0.0)`. + * + * @param semverRange The semantic version range to be converted. + * @param suffix A version suffix to apply to versions in the resulting expression. + * @param semver Whether the target supports full semantic versioning (including + * `-0` as the lowest possible prerelease identifier) + * + * @returns a bracket-notation version range. + */ function toBracketNotation( semverRange: string, suffix?: string, From 059274f9fb01e8dcd1739f1222e34f5e41787a15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=91=A8=F0=9F=8F=BC=E2=80=8D=F0=9F=92=BB=20Romain=20M?= =?UTF-8?q?arcadier-Muller?= Date: Thu, 22 Oct 2020 10:32:11 +0200 Subject: [PATCH 04/16] fix linter violations --- packages/jsii-pacmak/lib/targets/dotnet.ts | 1 + packages/jsii-pacmak/lib/targets/dotnet/filegenerator.ts | 2 +- packages/jsii-pacmak/lib/targets/js.ts | 1 + packages/jsii-pacmak/test/generated-code/target-dotnet.test.ts | 2 +- packages/jsii-pacmak/test/generated-code/target-go.test.ts | 2 +- packages/jsii-pacmak/test/generated-code/target-java.test.ts | 2 +- packages/jsii-pacmak/test/generated-code/target-python.test.ts | 2 +- 7 files changed, 7 insertions(+), 5 deletions(-) diff --git a/packages/jsii-pacmak/lib/targets/dotnet.ts b/packages/jsii-pacmak/lib/targets/dotnet.ts index 4c406601fa..17ab004215 100644 --- a/packages/jsii-pacmak/lib/targets/dotnet.ts +++ b/packages/jsii-pacmak/lib/targets/dotnet.ts @@ -15,6 +15,7 @@ import { import { shell, Scratch, setExtend, filterAsync } from '../util'; import { DotNetGenerator } from './dotnet/dotnetgenerator'; import { toReleaseVersion } from './version-utils'; + import { TargetName } from '.'; export const TARGET_FRAMEWORK = 'netcoreapp3.1'; diff --git a/packages/jsii-pacmak/lib/targets/dotnet/filegenerator.ts b/packages/jsii-pacmak/lib/targets/dotnet/filegenerator.ts index e17a3fae82..9055f67b40 100644 --- a/packages/jsii-pacmak/lib/targets/dotnet/filegenerator.ts +++ b/packages/jsii-pacmak/lib/targets/dotnet/filegenerator.ts @@ -3,11 +3,11 @@ import { CodeMaker } from 'codemaker'; import * as path from 'path'; import * as xmlbuilder from 'xmlbuilder'; +import { TargetName } from '..'; import * as logging from '../../logging'; import { TARGET_FRAMEWORK } from '../dotnet'; import { toNuGetVersionRange, toReleaseVersion } from '../version-utils'; import { DotNetNameUtils } from './nameutils'; -import { TargetName } from '..'; // Represents a dependency in the dependency tree. export class DotNetDependency { diff --git a/packages/jsii-pacmak/lib/targets/js.ts b/packages/jsii-pacmak/lib/targets/js.ts index 62ed66bbfe..82897d56af 100644 --- a/packages/jsii-pacmak/lib/targets/js.ts +++ b/packages/jsii-pacmak/lib/targets/js.ts @@ -3,6 +3,7 @@ import * as spec from '@jsii/spec'; import { Generator } from '../generator'; import { PackageInfo, Target } from '../target'; import { toReleaseVersion } from './version-utils'; + import { TargetName } from '.'; export default class JavaScript extends Target { diff --git a/packages/jsii-pacmak/test/generated-code/target-dotnet.test.ts b/packages/jsii-pacmak/test/generated-code/target-dotnet.test.ts index e6c8e5e11b..b741819970 100644 --- a/packages/jsii-pacmak/test/generated-code/target-dotnet.test.ts +++ b/packages/jsii-pacmak/test/generated-code/target-dotnet.test.ts @@ -1,4 +1,4 @@ -import { verifyGeneratedCodeFor } from './harness'; import { TargetName } from '../../lib/targets'; +import { verifyGeneratedCodeFor } from './harness'; verifyGeneratedCodeFor(TargetName.DOTNET); diff --git a/packages/jsii-pacmak/test/generated-code/target-go.test.ts b/packages/jsii-pacmak/test/generated-code/target-go.test.ts index 19c55cfbc1..c987a8dbfa 100644 --- a/packages/jsii-pacmak/test/generated-code/target-go.test.ts +++ b/packages/jsii-pacmak/test/generated-code/target-go.test.ts @@ -1,4 +1,4 @@ -import { verifyGeneratedCodeFor } from './harness'; import { TargetName } from '../../lib/targets'; +import { verifyGeneratedCodeFor } from './harness'; verifyGeneratedCodeFor(TargetName.GO); diff --git a/packages/jsii-pacmak/test/generated-code/target-java.test.ts b/packages/jsii-pacmak/test/generated-code/target-java.test.ts index 8714cdbc44..922a2f6d33 100644 --- a/packages/jsii-pacmak/test/generated-code/target-java.test.ts +++ b/packages/jsii-pacmak/test/generated-code/target-java.test.ts @@ -1,4 +1,4 @@ -import { verifyGeneratedCodeFor } from './harness'; import { TargetName } from '../../lib/targets'; +import { verifyGeneratedCodeFor } from './harness'; verifyGeneratedCodeFor(TargetName.JAVA); diff --git a/packages/jsii-pacmak/test/generated-code/target-python.test.ts b/packages/jsii-pacmak/test/generated-code/target-python.test.ts index e57acf499c..9d35bc728d 100644 --- a/packages/jsii-pacmak/test/generated-code/target-python.test.ts +++ b/packages/jsii-pacmak/test/generated-code/target-python.test.ts @@ -1,4 +1,4 @@ -import { verifyGeneratedCodeFor } from './harness'; import { TargetName } from '../../lib/targets'; +import { verifyGeneratedCodeFor } from './harness'; verifyGeneratedCodeFor(TargetName.PYTHON, 120_000); From 1941a4361d586fa76a80cea9a6241c650075fc0b Mon Sep 17 00:00:00 2001 From: Romain Marcadier Date: Thu, 22 Oct 2020 11:03:45 +0200 Subject: [PATCH 05/16] Update all-targets-tested.test.ts --- .../jsii-pacmak/test/generated-code/all-targets-tested.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/jsii-pacmak/test/generated-code/all-targets-tested.test.ts b/packages/jsii-pacmak/test/generated-code/all-targets-tested.test.ts index 86625657ed..2cc9732828 100644 --- a/packages/jsii-pacmak/test/generated-code/all-targets-tested.test.ts +++ b/packages/jsii-pacmak/test/generated-code/all-targets-tested.test.ts @@ -26,8 +26,8 @@ describe('target is tested', () => { ).resolves.toMatch( new RegExp( [ - "import \\{ verifyGeneratedCodeFor \\} from '\\./harness';", "import \\{ TargetName \\} from '\\.\\./\\.\\./lib/targets';", + "import \\{ verifyGeneratedCodeFor \\} from '\\./harness';", '', `verifyGeneratedCodeFor\\(TargetName.${key}(?:, [0-9_]+)?\\);`, ].join('\\n'), From f3dc6599562d2897a1bcd49a4c3f17f05317b0e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=91=A8=F0=9F=8F=BC=E2=80=8D=F0=9F=92=BB=20Romain=20M?= =?UTF-8?q?arcadier-Muller?= Date: Thu, 22 Oct 2020 15:10:45 +0200 Subject: [PATCH 06/16] fixup tests --- .../jsii-pacmak/lib/targets/version-utils.ts | 2 +- .../test/targets/version-utils.test.ts | 18 ++++++++++++------ 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/packages/jsii-pacmak/lib/targets/version-utils.ts b/packages/jsii-pacmak/lib/targets/version-utils.ts index 0930cd570e..1144e84322 100644 --- a/packages/jsii-pacmak/lib/targets/version-utils.ts +++ b/packages/jsii-pacmak/lib/targets/version-utils.ts @@ -96,7 +96,7 @@ export function toReleaseVersion( // Python supports a limited set of identifiers... And we have a mapping table... // https://packaging.python.org/guides/distributing-packages-using-setuptools/#pre-release-versioning const [label, sequence, ...rest] = version.prerelease; - if (rest.length > 0) { + if (rest.length > 0 || sequence == null) { throw new Error( `Unable to map prerelease identifier (in: ${assemblyVersion}) components to python: ${inspect( version.prerelease, diff --git a/packages/jsii-pacmak/test/targets/version-utils.test.ts b/packages/jsii-pacmak/test/targets/version-utils.test.ts index 1e32eed071..df5b11b442 100644 --- a/packages/jsii-pacmak/test/targets/version-utils.test.ts +++ b/packages/jsii-pacmak/test/targets/version-utils.test.ts @@ -106,7 +106,7 @@ describe(toPythonVersionRange, () => { }); describe(toReleaseVersion, () => { - type Expectations = { readonly [K in TargetName]: string }; + type Expectations = { readonly [K in TargetName]: string | RegExp }; const examples: Record = { '1.2.3': { dotnet: '1.2.3', @@ -120,7 +120,7 @@ describe(toReleaseVersion, () => { go: '1.2.3-pre', java: '1.2.3-pre', js: '1.2.3-pre', - python: '1.2.3-pre', + python: /Unable to map prerelease identifier \(in: 1\.2\.3-pre\) components to python: \[ 'pre' \]/, }, '1.2.3-alpha.1337': { dotnet: '1.2.3-alpha.1337', @@ -147,10 +147,16 @@ describe(toReleaseVersion, () => { for (const [version, targets] of Object.entries(examples)) { test(`"${version}" translations`, () => { - for (const [target, targetVersion] of Object.entries(targets)) { - expect(toReleaseVersion(version, target as TargetName)).toBe( - targetVersion, - ); + for (const [target, expectedResult] of Object.entries(targets)) { + if (typeof expectedResult === 'string') { + expect(toReleaseVersion(version, target as TargetName)).toBe( + expectedResult, + ); + } else { + expect(() => toReleaseVersion(version, target as TargetName)).toThrow( + expectedResult, + ); + } } }); } From 033d7778fa131d00685c5649806c154aeb80f64c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=91=A8=F0=9F=8F=BC=E2=80=8D=F0=9F=92=BB=20Romain=20M?= =?UTF-8?q?arcadier-Muller?= Date: Thu, 22 Oct 2020 17:22:28 +0200 Subject: [PATCH 07/16] add support for .pr####.# identifiers --- .../jsii-pacmak/lib/targets/version-utils.ts | 17 +++++++++++------ .../test/targets/version-utils.test.ts | 7 +++++++ 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/packages/jsii-pacmak/lib/targets/version-utils.ts b/packages/jsii-pacmak/lib/targets/version-utils.ts index 1144e84322..3cb10e082a 100644 --- a/packages/jsii-pacmak/lib/targets/version-utils.ts +++ b/packages/jsii-pacmak/lib/targets/version-utils.ts @@ -100,7 +100,7 @@ export function toReleaseVersion( throw new Error( `Unable to map prerelease identifier (in: ${assemblyVersion}) components to python: ${inspect( version.prerelease, - )}`, + )}. The format should be 'X.Y.Z-label.sequence', where sequence is a positive integer, and label is "pr####", "dev", "pre", "alpha", beta", or "rc"`, ); } if (!Number.isInteger(sequence)) { @@ -110,21 +110,26 @@ export function toReleaseVersion( )} is not an integer`, ); } + const baseVersion = `${version.major}.${version.minor}.${version.patch}`; switch (label) { case 'dev': case 'pre': - return `${version.major}.${version.minor}.${version.patch}.dev${sequence}`; + return `${baseVersion}.dev${sequence}`; case 'alpha': - return `${version.major}.${version.minor}.${version.patch}.a${sequence}`; + return `${baseVersion}.a${sequence}`; case 'beta': - return `${version.major}.${version.minor}.${version.patch}.b${sequence}`; + return `${baseVersion}.b${sequence}`; case 'rc': - return `${version.major}.${version.minor}.${version.patch}.rc${sequence}`; + return `${baseVersion}.rc${sequence}`; default: + // We emit `-pr${pull_request_id}.0` + if (typeof label === 'string' && /^pr\d+$/.test(label)) { + return `${baseVersion}.post${label.substr(2)}.dev${sequence}`; + } throw new Error( `Unable to map prerelease identifier (in: ${assemblyVersion}) to python, as label ${inspect( label, - )} is not mapped (only "dev", "pre", "alpha", "beta" and "rc" are)`, + )} is not mapped (only "pr####", "dev", "pre", "alpha", "beta" and "rc" are)`, ); } case TargetName.DOTNET: diff --git a/packages/jsii-pacmak/test/targets/version-utils.test.ts b/packages/jsii-pacmak/test/targets/version-utils.test.ts index df5b11b442..f6037d09e0 100644 --- a/packages/jsii-pacmak/test/targets/version-utils.test.ts +++ b/packages/jsii-pacmak/test/targets/version-utils.test.ts @@ -143,6 +143,13 @@ describe(toReleaseVersion, () => { js: '1.2.3-rc.9', python: '1.2.3.rc9', }, + '1.2.3-pr4567.8': { + dotnet: '1.2.3-pr4567.8', + go: '1.2.3-pr4567.8', + java: '1.2.3-pr4567.8', + js: '1.2.3-pr4567.8', + python: '1.2.3.post4567.dev8', + }, }; for (const [version, targets] of Object.entries(examples)) { From 874ed3dc82bfbaa71056e82a50075ad2d6674468 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=91=A8=F0=9F=8F=BC=E2=80=8D=F0=9F=92=BB=20Romain=20M?= =?UTF-8?q?arcadier-Muller?= Date: Tue, 27 Oct 2020 12:49:53 +0100 Subject: [PATCH 08/16] add tests --- packages/jsii-pacmak/lib/index.ts | 4 +- packages/jsii-pacmak/lib/packaging.ts | 14 +- packages/jsii-pacmak/lib/targets/java.ts | 3 +- .../prerelease-identifiers.test.ts.snap | 2830 +++++++++++++++++ .../test/generated-code/harness.ts | 4 +- .../prerelease-identifiers.test.ts | 160 + 6 files changed, 3004 insertions(+), 11 deletions(-) create mode 100644 packages/jsii-pacmak/test/generated-code/__snapshots__/prerelease-identifiers.test.ts.snap create mode 100644 packages/jsii-pacmak/test/generated-code/prerelease-identifiers.test.ts diff --git a/packages/jsii-pacmak/lib/index.ts b/packages/jsii-pacmak/lib/index.ts index 9608d531a5..49a1eaa485 100644 --- a/packages/jsii-pacmak/lib/index.ts +++ b/packages/jsii-pacmak/lib/index.ts @@ -1,3 +1,4 @@ +import { TypeSystem } from 'jsii-reflect'; import { Rosetta } from 'jsii-rosetta'; import * as logging from './logging'; @@ -61,9 +62,10 @@ export async function pacmak({ await timers.recordAsync('load jsii', () => { logging.info('Loading jsii assemblies and translations'); + const system = new TypeSystem(); return Promise.all( modulesToPackage.map(async (m) => { - await m.load(); + await m.load(system); return rosetta.addAssembly(m.assembly.spec, m.moduleDirectory); }), ); diff --git a/packages/jsii-pacmak/lib/packaging.ts b/packages/jsii-pacmak/lib/packaging.ts index 41f11bd1eb..162ba2c03c 100644 --- a/packages/jsii-pacmak/lib/packaging.ts +++ b/packages/jsii-pacmak/lib/packaging.ts @@ -1,12 +1,10 @@ -import * as reflect from 'jsii-reflect'; +import type { Assembly, TypeSystem } from 'jsii-reflect'; import * as os from 'os'; import * as path from 'path'; import * as logging from '../lib/logging'; import { Scratch, shell } from './util'; -const SHARED_TS = new reflect.TypeSystem(); - export interface JsiiModuleOptions { /** * Name of the module @@ -41,7 +39,7 @@ export class JsiiModule { public outputDirectory: string; private _tarball?: Scratch; - public _assembly?: reflect.Assembly; + public _assembly?: Assembly; public constructor(options: JsiiModuleOptions) { this.name = options.name; @@ -87,11 +85,13 @@ export class JsiiModule { return this._tarball.object; } - public async load() { - this._assembly = await SHARED_TS.loadModule(this.moduleDirectory); + public async load(system: TypeSystem) { + return system + .loadModule(this.moduleDirectory) + .then((assembly) => (this._assembly = assembly)); } - public get assembly(): reflect.Assembly { + public get assembly(): Assembly { if (!this._assembly) { throw new Error('Assembly not available yet, call load() first'); } diff --git a/packages/jsii-pacmak/lib/targets/java.ts b/packages/jsii-pacmak/lib/targets/java.ts index a12a2a2487..b764dfc433 100644 --- a/packages/jsii-pacmak/lib/targets/java.ts +++ b/packages/jsii-pacmak/lib/targets/java.ts @@ -2750,7 +2750,8 @@ class JavaGenerator extends Generator { const { packageName, typeName } = this.toNativeName( this.assembly, - this.assembly.types![fqn], + // It's okay for this parameter to be `undefined` (there is an overload for that): + this.assembly.types?.[fqn]!, ); const className = typeName && binaryName ? typeName.replace('.', '$') : typeName; diff --git a/packages/jsii-pacmak/test/generated-code/__snapshots__/prerelease-identifiers.test.ts.snap b/packages/jsii-pacmak/test/generated-code/__snapshots__/prerelease-identifiers.test.ts.snap new file mode 100644 index 0000000000..959135d8a4 --- /dev/null +++ b/packages/jsii-pacmak/test/generated-code/__snapshots__/prerelease-identifiers.test.ts.snap @@ -0,0 +1,2830 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`foo@0.0.0-pr1234.0: / 1`] = ` + + ┣━ 📁 dotnet + ┃ ┗━ 📁 Com.Acme.Foo + ┃ ┣━ 📄 AssemblyInfo.cs + ┃ ┣━ 📁 Com + ┃ ┃ ┗━ 📁 Acme + ┃ ┃ ┗━ 📁 Foo + ┃ ┃ ┗━ 📁 Internal + ┃ ┃ ┗━ 📁 DependencyResolution + ┃ ┃ ┗━ 📄 Anchor.cs + ┃ ┣━ 📄 Com.Acme.Foo.csproj + ┃ ┗━ 📄 foo-0.0.0-pr1234.0.tgz + ┣━ 📁 go + ┃ ┗━ 📁 foo + ┃ ┣━ 📄 foo.go + ┃ ┗━ 📁 jsii + ┃ ┣━ 📄 jsii.go + ┃ ┗━ 📄 tarball.embedded.go + ┣━ 📁 java + ┃ ┣━ 📄 pom.xml + ┃ ┗━ 📁 src + ┃ ┗━ 📁 main + ┃ ┣━ 📁 java + ┃ ┃ ┗━ 📁 com + ┃ ┃ ┗━ 📁 acme + ┃ ┃ ┗━ 📁 foo + ┃ ┃ ┗━ 📄 $Module.java + ┃ ┗━ 📁 resources + ┃ ┗━ 📁 com + ┃ ┗━ 📁 acme + ┃ ┗━ 📁 foo + ┃ ┣━ 📄 $Module.txt + ┃ ┗━ 📄 foo@0.0.0-pr1234.0.jsii.tgz + ┣━ 📁 js + ┃ ┗━ 📄 foo@0.0.0-pr1234.0.jsii.tgz + ┗━ 📁 python + ┣━ 📄 MANIFEST.in + ┣━ 📄 pyproject.toml + ┣━ 📄 README.md + ┣━ 📄 setup.py + ┗━ 📁 src + ┗━ 📁 foo + ┗━ 📁 _jsii + ┣━ 📄 __init__.py + ┗━ 📄 foo@0.0.0-pr1234.0.jsii.tgz +`; + +exports[`foo@0.0.0-pr1234.0: /dotnet/Com.Acme.Foo/AssemblyInfo.cs 1`] = ` +using Amazon.JSII.Runtime.Deputy; + +[assembly: JsiiAssembly("foo", "0.0.0-pr1234.0", "foo-0.0.0-pr1234.0.tgz")] + +`; + +exports[`foo@0.0.0-pr1234.0: /dotnet/Com.Acme.Foo/Com.Acme.Foo.csproj 1`] = ` + + + + Test assembly: foo + Com.Acme.Foo + UNLICENSED + 0.0.0-pr1234.0 + + Test + en-US + https://test.nope/foo + foo.nope.git + git + + true + true + true + true + enable + snupkg + netcoreapp3.1 + + + + + + + + + 0612,0618 + + + + +`; + +exports[`foo@0.0.0-pr1234.0: /dotnet/Com.Acme.Foo/Com/Acme/Foo/Internal/DependencyResolution/Anchor.cs 1`] = ` +#pragma warning disable CS0672,CS0809,CS1591 + +namespace Com.Acme.Foo.Internal.DependencyResolution +{ + public sealed class Anchor + { + public Anchor() + { + } + } +} + +`; + +exports[`foo@0.0.0-pr1234.0: /dotnet/Com.Acme.Foo/foo-0.0.0-pr1234.0.tgz 1`] = `dotnet/Com.Acme.Foo/foo-0.0.0-pr1234.0.tgz is a tarball`; + +exports[`foo@0.0.0-pr1234.0: /go/foo/foo.go 1`] = ` +// Test assembly: foo +package foo + +import ( +) + + +`; + +exports[`foo@0.0.0-pr1234.0: /go/foo/jsii/jsii.go 1`] = ` +package jsii + +import ( + rt "github.com/aws-cdk/jsii/jsii-experimental" + "sync" +) + +var once sync.Once + +// Initialize performs the necessary work for the enclosing +// module to be loaded in the jsii kernel. +func Initialize() { + once.Do(func(){ + // Load this library into the kernel + rt.Load("foo", "0.0.0-pr1234.0", tarball) + }) +} + +`; + +exports[`foo@0.0.0-pr1234.0: /go/foo/jsii/tarball.embedded.go 1`] = `go/foo/jsii/tarball.embedded.go embeds a tarball`; + +exports[`foo@0.0.0-pr1234.0: /java/pom.xml 1`] = ` + + + 4.0.0 + \${project.groupId}:\${project.artifactId} + Test assembly: foo + https://test.nope/foo + + + + Test + + test + + + + + scm:git:foo.nope.git + foo.nope.git + + com.acme + foo + 0.0.0-pr1234.0 + jar + + UTF-8 + + + + software.amazon.jsii + jsii-runtime + [0.0.0,0.0.1) + + + org.jetbrains + annotations + [16.0.3,20.0.0) + + + + javax.annotation + javax.annotation-api + [1.3.2,1.4.0) + compile + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.1 + + 1.8 + 1.8 + + + + org.apache.maven.plugins + maven-jar-plugin + 3.2.0 + + + true + + true + true + + + + + + org.apache.maven.plugins + maven-source-plugin + 3.2.1 + + + attach-sources + + jar + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 3.1.1 + + + attach-javadocs + + jar + + + + + false + protected + + **/$Module.java + + -J-XX:+TieredCompilation + -J-XX:TieredStopAtLevel=1 + + + + org.apache.maven.plugins + maven-enforcer-plugin + 3.0.0-M3 + + + enforce-maven + + enforce + + + + + 3.6 + + + + + + + + org.codehaus.mojo + versions-maven-plugin + 2.7 + + false + + + + + + +`; + +exports[`foo@0.0.0-pr1234.0: /java/src/main/java/com/acme/foo/$Module.java 1`] = ` +package com.acme.foo; + +import java.io.BufferedReader; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.IOException; +import java.io.Reader; +import java.io.UncheckedIOException; + +import java.nio.charset.StandardCharsets; + +import java.util.HashMap; +import java.util.Map; + +import software.amazon.jsii.JsiiModule; + +@software.amazon.jsii.Internal +public final class $Module extends JsiiModule { + private static final Map MODULE_TYPES = load(); + + private static Map load() { + final Map result = new HashMap<>(); + final ClassLoader cl = $Module.class.getClassLoader(); + try (final InputStream is = cl.getResourceAsStream("com/acme/foo/$Module.txt"); + final Reader rd = new InputStreamReader(is, StandardCharsets.UTF_8); + final BufferedReader br = new BufferedReader(rd)) { + br.lines() + .filter(line -> !line.trim().isEmpty()) + .forEach(line -> { + final String[] parts = line.split("=", 2); + final String fqn = parts[0]; + final String className = parts[1]; + result.put(fqn, className); + }); + } + catch (final IOException exception) { + throw new UncheckedIOException(exception); + } + return result; + } + + private final Map> cache = new HashMap<>(); + + public $Module() { + super("foo", "0.0.0-pr1234.0", $Module.class, "foo@0.0.0-pr1234.0.jsii.tgz"); + } + + @Override + protected Class resolveClass(final String fqn) throws ClassNotFoundException { + if (!MODULE_TYPES.containsKey(fqn)) { + throw new ClassNotFoundException("Unknown JSII type: " + fqn); + } + String className = MODULE_TYPES.get(fqn); + if (!this.cache.containsKey(className)) { + this.cache.put(className, this.findClass(className)); + } + return this.cache.get(className); + } + + private Class findClass(final String binaryName) { + try { + return Class.forName(binaryName); + } + catch (final ClassNotFoundException exception) { + throw new RuntimeException(exception); + } + } +} + +`; + +exports[`foo@0.0.0-pr1234.0: /java/src/main/resources/com/acme/foo/$Module.txt 1`] = ``; + +exports[`foo@0.0.0-pr1234.0: /java/src/main/resources/com/acme/foo/foo@0.0.0-pr1234.0.jsii.tgz 1`] = `java/src/main/resources/com/acme/foo/foo@0.0.0-pr1234.0.jsii.tgz is a tarball`; + +exports[`foo@0.0.0-pr1234.0: /js/foo@0.0.0-pr1234.0.jsii.tgz 1`] = `js/foo@0.0.0-pr1234.0.jsii.tgz is a tarball`; + +exports[`foo@0.0.0-pr1234.0: /python/MANIFEST.in 1`] = ` +include pyproject.toml + +`; + +exports[`foo@0.0.0-pr1234.0: /python/README.md 1`] = ` + + +`; + +exports[`foo@0.0.0-pr1234.0: /python/pyproject.toml 1`] = ` +[build-system] +requires = ["setuptools~=49.3", "wheel~=0.34"] +build-backend = "setuptools.build_meta" + +`; + +exports[`foo@0.0.0-pr1234.0: /python/setup.py 1`] = ` +import json +import setuptools + +kwargs = json.loads( + """ +{ + "name": "foo", + "version": "0.0.0.post1234.dev0", + "description": "Test assembly: foo", + "license": "UNLICENSED", + "url": "https://test.nope/foo", + "long_description_content_type": "text/markdown", + "author": "Test", + "bdist_wheel": { + "universal": true + }, + "project_urls": { + "Source": "foo.nope.git" + }, + "package_dir": { + "": "src" + }, + "packages": [ + "foo._jsii" + ], + "package_data": { + "foo._jsii": [ + "foo@0.0.0-pr1234.0.jsii.tgz" + ] + }, + "python_requires": ">=3.6", + "install_requires": [ + "jsii>=1337.42.1337, <1338.0.0", + "publication>=0.0.3" + ], + "classifiers": [ + "Intended Audience :: Developers", + "Operating System :: OS Independent", + "Programming Language :: JavaScript", + "Programming Language :: Python :: 3 :: Only", + "Programming Language :: Python :: 3.6", + "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", + "Typing :: Typed" + ] +} +""" +) + +with open("README.md", encoding="utf8") as fp: + kwargs["long_description"] = fp.read() + + +setuptools.setup(**kwargs) + +`; + +exports[`foo@0.0.0-pr1234.0: /python/src/foo/_jsii/__init__.py 1`] = ` +import abc +import builtins +import datetime +import enum +import typing + +import jsii +import publication +import typing_extensions + +__jsii_assembly__ = jsii.JSIIAssembly.load( + "foo", "0.0.0-pr1234.0", __name__[0:-6], "foo@0.0.0-pr1234.0.jsii.tgz" +) + +__all__ = [ + "__jsii_assembly__", +] + +publication.publish() + +`; + +exports[`foo@0.0.0-pr1234.0: /python/src/foo/_jsii/foo@0.0.0-pr1234.0.jsii.tgz 1`] = `python/src/foo/_jsii/foo@0.0.0-pr1234.0.jsii.tgz is a tarball`; + +exports[`foo@1.2.3 depends on bar@^0.0.0-pr1234.0: / 1`] = ` + + ┣━ 📁 dotnet + ┃ ┗━ 📁 Com.Acme.Foo + ┃ ┣━ 📄 AssemblyInfo.cs + ┃ ┣━ 📁 Com + ┃ ┃ ┗━ 📁 Acme + ┃ ┃ ┗━ 📁 Foo + ┃ ┃ ┗━ 📁 Internal + ┃ ┃ ┗━ 📁 DependencyResolution + ┃ ┃ ┗━ 📄 Anchor.cs + ┃ ┣━ 📄 Com.Acme.Foo.csproj + ┃ ┗━ 📄 foo-1.2.3.tgz + ┣━ 📁 go + ┃ ┗━ 📁 foo + ┃ ┣━ 📄 foo.go + ┃ ┗━ 📁 jsii + ┃ ┣━ 📄 jsii.go + ┃ ┗━ 📄 tarball.embedded.go + ┣━ 📁 java + ┃ ┣━ 📄 pom.xml + ┃ ┗━ 📁 src + ┃ ┗━ 📁 main + ┃ ┣━ 📁 java + ┃ ┃ ┗━ 📁 com + ┃ ┃ ┗━ 📁 acme + ┃ ┃ ┗━ 📁 foo + ┃ ┃ ┗━ 📄 $Module.java + ┃ ┗━ 📁 resources + ┃ ┗━ 📁 com + ┃ ┗━ 📁 acme + ┃ ┗━ 📁 foo + ┃ ┣━ 📄 $Module.txt + ┃ ┗━ 📄 foo@1.2.3.jsii.tgz + ┣━ 📁 js + ┃ ┗━ 📄 foo@1.2.3.jsii.tgz + ┗━ 📁 python + ┣━ 📄 MANIFEST.in + ┣━ 📄 pyproject.toml + ┣━ 📄 README.md + ┣━ 📄 setup.py + ┗━ 📁 src + ┗━ 📁 foo + ┗━ 📁 _jsii + ┣━ 📄 __init__.py + ┗━ 📄 foo@1.2.3.jsii.tgz +`; + +exports[`foo@1.2.3 depends on bar@^0.0.0-pr1234.0: /dotnet/Com.Acme.Foo/AssemblyInfo.cs 1`] = ` +using Amazon.JSII.Runtime.Deputy; + +[assembly: JsiiAssembly("foo", "1.2.3", "foo-1.2.3.tgz")] + +`; + +exports[`foo@1.2.3 depends on bar@^0.0.0-pr1234.0: /dotnet/Com.Acme.Foo/Com.Acme.Foo.csproj 1`] = ` + + + + Test assembly: foo + Com.Acme.Foo + UNLICENSED + 1.2.3 + + Test + en-US + https://test.nope/foo + foo.nope.git + git + + true + true + true + true + enable + snupkg + netcoreapp3.1 + + + + + + + + + + 0612,0618 + + + + +`; + +exports[`foo@1.2.3 depends on bar@^0.0.0-pr1234.0: /dotnet/Com.Acme.Foo/Com/Acme/Foo/Internal/DependencyResolution/Anchor.cs 1`] = ` +#pragma warning disable CS0672,CS0809,CS1591 + +namespace Com.Acme.Foo.Internal.DependencyResolution +{ + public sealed class Anchor + { + public Anchor() + { + new Com.Acme.Bar.Internal.DependencyResolution.Anchor(); + } + } +} + +`; + +exports[`foo@1.2.3 depends on bar@^0.0.0-pr1234.0: /dotnet/Com.Acme.Foo/foo-1.2.3.tgz 1`] = `dotnet/Com.Acme.Foo/foo-1.2.3.tgz is a tarball`; + +exports[`foo@1.2.3 depends on bar@^0.0.0-pr1234.0: /go/foo/foo.go 1`] = ` +// Test assembly: foo +package foo + +import ( +) + + +`; + +exports[`foo@1.2.3 depends on bar@^0.0.0-pr1234.0: /go/foo/jsii/jsii.go 1`] = ` +package jsii + +import ( + rt "github.com/aws-cdk/jsii/jsii-experimental" + "sync" + // Initialization endpoints of dependencies + bar "/bar/jsii" +) + +var once sync.Once + +// Initialize performs the necessary work for the enclosing +// module to be loaded in the jsii kernel. +func Initialize() { + once.Do(func(){ + // Ensure all dependencies are initialized + bar.Initialize() + + // Load this library into the kernel + rt.Load("foo", "1.2.3", tarball) + }) +} + +`; + +exports[`foo@1.2.3 depends on bar@^0.0.0-pr1234.0: /go/foo/jsii/tarball.embedded.go 1`] = `go/foo/jsii/tarball.embedded.go embeds a tarball`; + +exports[`foo@1.2.3 depends on bar@^0.0.0-pr1234.0: /java/pom.xml 1`] = ` + + + 4.0.0 + \${project.groupId}:\${project.artifactId} + Test assembly: foo + https://test.nope/foo + + + + Test + + test + + + + + scm:git:foo.nope.git + foo.nope.git + + com.acme + foo + 1.2.3 + jar + + UTF-8 + + + + com.acme + bar + [0.0.0-pr1234.0,0.0.1) + + + software.amazon.jsii + jsii-runtime + [0.0.0,0.0.1) + + + org.jetbrains + annotations + [16.0.3,20.0.0) + + + + javax.annotation + javax.annotation-api + [1.3.2,1.4.0) + compile + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.1 + + 1.8 + 1.8 + + + + org.apache.maven.plugins + maven-jar-plugin + 3.2.0 + + + true + + true + true + + + + + + org.apache.maven.plugins + maven-source-plugin + 3.2.1 + + + attach-sources + + jar + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 3.1.1 + + + attach-javadocs + + jar + + + + + false + protected + + **/$Module.java + + -J-XX:+TieredCompilation + -J-XX:TieredStopAtLevel=1 + + + + org.apache.maven.plugins + maven-enforcer-plugin + 3.0.0-M3 + + + enforce-maven + + enforce + + + + + 3.6 + + + + + + + + org.codehaus.mojo + versions-maven-plugin + 2.7 + + false + + + + + + +`; + +exports[`foo@1.2.3 depends on bar@^0.0.0-pr1234.0: /java/src/main/java/com/acme/foo/$Module.java 1`] = ` +package com.acme.foo; + +import static java.util.Arrays.asList; + +import java.io.BufferedReader; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.IOException; +import java.io.Reader; +import java.io.UncheckedIOException; + +import java.nio.charset.StandardCharsets; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import software.amazon.jsii.JsiiModule; + +@software.amazon.jsii.Internal +public final class $Module extends JsiiModule { + private static final Map MODULE_TYPES = load(); + + private static Map load() { + final Map result = new HashMap<>(); + final ClassLoader cl = $Module.class.getClassLoader(); + try (final InputStream is = cl.getResourceAsStream("com/acme/foo/$Module.txt"); + final Reader rd = new InputStreamReader(is, StandardCharsets.UTF_8); + final BufferedReader br = new BufferedReader(rd)) { + br.lines() + .filter(line -> !line.trim().isEmpty()) + .forEach(line -> { + final String[] parts = line.split("=", 2); + final String fqn = parts[0]; + final String className = parts[1]; + result.put(fqn, className); + }); + } + catch (final IOException exception) { + throw new UncheckedIOException(exception); + } + return result; + } + + private final Map> cache = new HashMap<>(); + + public $Module() { + super("foo", "1.2.3", $Module.class, "foo@1.2.3.jsii.tgz"); + } + + @Override + public List> getDependencies() { + return asList(com.acme.bar.$Module.class); + } + + @Override + protected Class resolveClass(final String fqn) throws ClassNotFoundException { + if (!MODULE_TYPES.containsKey(fqn)) { + throw new ClassNotFoundException("Unknown JSII type: " + fqn); + } + String className = MODULE_TYPES.get(fqn); + if (!this.cache.containsKey(className)) { + this.cache.put(className, this.findClass(className)); + } + return this.cache.get(className); + } + + private Class findClass(final String binaryName) { + try { + return Class.forName(binaryName); + } + catch (final ClassNotFoundException exception) { + throw new RuntimeException(exception); + } + } +} + +`; + +exports[`foo@1.2.3 depends on bar@^0.0.0-pr1234.0: /java/src/main/resources/com/acme/foo/$Module.txt 1`] = ``; + +exports[`foo@1.2.3 depends on bar@^0.0.0-pr1234.0: /java/src/main/resources/com/acme/foo/foo@1.2.3.jsii.tgz 1`] = `java/src/main/resources/com/acme/foo/foo@1.2.3.jsii.tgz is a tarball`; + +exports[`foo@1.2.3 depends on bar@^0.0.0-pr1234.0: /js/foo@1.2.3.jsii.tgz 1`] = `js/foo@1.2.3.jsii.tgz is a tarball`; + +exports[`foo@1.2.3 depends on bar@^0.0.0-pr1234.0: /python/MANIFEST.in 1`] = ` +include pyproject.toml + +`; + +exports[`foo@1.2.3 depends on bar@^0.0.0-pr1234.0: /python/README.md 1`] = ` + + +`; + +exports[`foo@1.2.3 depends on bar@^0.0.0-pr1234.0: /python/pyproject.toml 1`] = ` +[build-system] +requires = ["setuptools~=49.3", "wheel~=0.34"] +build-backend = "setuptools.build_meta" + +`; + +exports[`foo@1.2.3 depends on bar@^0.0.0-pr1234.0: /python/setup.py 1`] = ` +import json +import setuptools + +kwargs = json.loads( + """ +{ + "name": "foo", + "version": "1.2.3", + "description": "Test assembly: foo", + "license": "UNLICENSED", + "url": "https://test.nope/foo", + "long_description_content_type": "text/markdown", + "author": "Test", + "bdist_wheel": { + "universal": true + }, + "project_urls": { + "Source": "foo.nope.git" + }, + "package_dir": { + "": "src" + }, + "packages": [ + "foo._jsii" + ], + "package_data": { + "foo._jsii": [ + "foo@1.2.3.jsii.tgz" + ] + }, + "python_requires": ">=3.6", + "install_requires": [ + "bar>=0.0.0.post1234.dev0, <0.0.1", + "jsii>=1337.42.1337, <1338.0.0", + "publication>=0.0.3" + ], + "classifiers": [ + "Intended Audience :: Developers", + "Operating System :: OS Independent", + "Programming Language :: JavaScript", + "Programming Language :: Python :: 3 :: Only", + "Programming Language :: Python :: 3.6", + "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", + "Typing :: Typed" + ] +} +""" +) + +with open("README.md", encoding="utf8") as fp: + kwargs["long_description"] = fp.read() + + +setuptools.setup(**kwargs) + +`; + +exports[`foo@1.2.3 depends on bar@^0.0.0-pr1234.0: /python/src/foo/_jsii/__init__.py 1`] = ` +import abc +import builtins +import datetime +import enum +import typing + +import jsii +import publication +import typing_extensions + +import bar._jsii + +__jsii_assembly__ = jsii.JSIIAssembly.load( + "foo", "1.2.3", __name__[0:-6], "foo@1.2.3.jsii.tgz" +) + +__all__ = [ + "__jsii_assembly__", +] + +publication.publish() + +`; + +exports[`foo@1.2.3 depends on bar@^0.0.0-pr1234.0: /python/src/foo/_jsii/foo@1.2.3.jsii.tgz 1`] = `python/src/foo/_jsii/foo@1.2.3.jsii.tgz is a tarball`; + +exports[`foo@1.2.3 depends on bar@^2.0.0-rc.42: / 1`] = ` + + ┣━ 📁 dotnet + ┃ ┗━ 📁 Com.Acme.Foo + ┃ ┣━ 📄 AssemblyInfo.cs + ┃ ┣━ 📁 Com + ┃ ┃ ┗━ 📁 Acme + ┃ ┃ ┗━ 📁 Foo + ┃ ┃ ┗━ 📁 Internal + ┃ ┃ ┗━ 📁 DependencyResolution + ┃ ┃ ┗━ 📄 Anchor.cs + ┃ ┣━ 📄 Com.Acme.Foo.csproj + ┃ ┗━ 📄 foo-1.2.3.tgz + ┣━ 📁 go + ┃ ┗━ 📁 foo + ┃ ┣━ 📄 foo.go + ┃ ┗━ 📁 jsii + ┃ ┣━ 📄 jsii.go + ┃ ┗━ 📄 tarball.embedded.go + ┣━ 📁 java + ┃ ┣━ 📄 pom.xml + ┃ ┗━ 📁 src + ┃ ┗━ 📁 main + ┃ ┣━ 📁 java + ┃ ┃ ┗━ 📁 com + ┃ ┃ ┗━ 📁 acme + ┃ ┃ ┗━ 📁 foo + ┃ ┃ ┗━ 📄 $Module.java + ┃ ┗━ 📁 resources + ┃ ┗━ 📁 com + ┃ ┗━ 📁 acme + ┃ ┗━ 📁 foo + ┃ ┣━ 📄 $Module.txt + ┃ ┗━ 📄 foo@1.2.3.jsii.tgz + ┣━ 📁 js + ┃ ┗━ 📄 foo@1.2.3.jsii.tgz + ┗━ 📁 python + ┣━ 📄 MANIFEST.in + ┣━ 📄 pyproject.toml + ┣━ 📄 README.md + ┣━ 📄 setup.py + ┗━ 📁 src + ┗━ 📁 foo + ┗━ 📁 _jsii + ┣━ 📄 __init__.py + ┗━ 📄 foo@1.2.3.jsii.tgz +`; + +exports[`foo@1.2.3 depends on bar@^2.0.0-rc.42: /dotnet/Com.Acme.Foo/AssemblyInfo.cs 1`] = ` +using Amazon.JSII.Runtime.Deputy; + +[assembly: JsiiAssembly("foo", "1.2.3", "foo-1.2.3.tgz")] + +`; + +exports[`foo@1.2.3 depends on bar@^2.0.0-rc.42: /dotnet/Com.Acme.Foo/Com.Acme.Foo.csproj 1`] = ` + + + + Test assembly: foo + Com.Acme.Foo + UNLICENSED + 1.2.3 + + Test + en-US + https://test.nope/foo + foo.nope.git + git + + true + true + true + true + enable + snupkg + netcoreapp3.1 + + + + + + + + + + 0612,0618 + + + + +`; + +exports[`foo@1.2.3 depends on bar@^2.0.0-rc.42: /dotnet/Com.Acme.Foo/Com/Acme/Foo/Internal/DependencyResolution/Anchor.cs 1`] = ` +#pragma warning disable CS0672,CS0809,CS1591 + +namespace Com.Acme.Foo.Internal.DependencyResolution +{ + public sealed class Anchor + { + public Anchor() + { + new Com.Acme.Bar.Internal.DependencyResolution.Anchor(); + } + } +} + +`; + +exports[`foo@1.2.3 depends on bar@^2.0.0-rc.42: /dotnet/Com.Acme.Foo/foo-1.2.3.tgz 1`] = `dotnet/Com.Acme.Foo/foo-1.2.3.tgz is a tarball`; + +exports[`foo@1.2.3 depends on bar@^2.0.0-rc.42: /go/foo/foo.go 1`] = ` +// Test assembly: foo +package foo + +import ( +) + + +`; + +exports[`foo@1.2.3 depends on bar@^2.0.0-rc.42: /go/foo/jsii/jsii.go 1`] = ` +package jsii + +import ( + rt "github.com/aws-cdk/jsii/jsii-experimental" + "sync" + // Initialization endpoints of dependencies + bar "/bar/jsii" +) + +var once sync.Once + +// Initialize performs the necessary work for the enclosing +// module to be loaded in the jsii kernel. +func Initialize() { + once.Do(func(){ + // Ensure all dependencies are initialized + bar.Initialize() + + // Load this library into the kernel + rt.Load("foo", "1.2.3", tarball) + }) +} + +`; + +exports[`foo@1.2.3 depends on bar@^2.0.0-rc.42: /go/foo/jsii/tarball.embedded.go 1`] = `go/foo/jsii/tarball.embedded.go embeds a tarball`; + +exports[`foo@1.2.3 depends on bar@^2.0.0-rc.42: /java/pom.xml 1`] = ` + + + 4.0.0 + \${project.groupId}:\${project.artifactId} + Test assembly: foo + https://test.nope/foo + + + + Test + + test + + + + + scm:git:foo.nope.git + foo.nope.git + + com.acme + foo + 1.2.3 + jar + + UTF-8 + + + + com.acme + bar + [2.0.0-rc.42,3.0.0) + + + software.amazon.jsii + jsii-runtime + [0.0.0,0.0.1) + + + org.jetbrains + annotations + [16.0.3,20.0.0) + + + + javax.annotation + javax.annotation-api + [1.3.2,1.4.0) + compile + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.1 + + 1.8 + 1.8 + + + + org.apache.maven.plugins + maven-jar-plugin + 3.2.0 + + + true + + true + true + + + + + + org.apache.maven.plugins + maven-source-plugin + 3.2.1 + + + attach-sources + + jar + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 3.1.1 + + + attach-javadocs + + jar + + + + + false + protected + + **/$Module.java + + -J-XX:+TieredCompilation + -J-XX:TieredStopAtLevel=1 + + + + org.apache.maven.plugins + maven-enforcer-plugin + 3.0.0-M3 + + + enforce-maven + + enforce + + + + + 3.6 + + + + + + + + org.codehaus.mojo + versions-maven-plugin + 2.7 + + false + + + + + + +`; + +exports[`foo@1.2.3 depends on bar@^2.0.0-rc.42: /java/src/main/java/com/acme/foo/$Module.java 1`] = ` +package com.acme.foo; + +import static java.util.Arrays.asList; + +import java.io.BufferedReader; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.IOException; +import java.io.Reader; +import java.io.UncheckedIOException; + +import java.nio.charset.StandardCharsets; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import software.amazon.jsii.JsiiModule; + +@software.amazon.jsii.Internal +public final class $Module extends JsiiModule { + private static final Map MODULE_TYPES = load(); + + private static Map load() { + final Map result = new HashMap<>(); + final ClassLoader cl = $Module.class.getClassLoader(); + try (final InputStream is = cl.getResourceAsStream("com/acme/foo/$Module.txt"); + final Reader rd = new InputStreamReader(is, StandardCharsets.UTF_8); + final BufferedReader br = new BufferedReader(rd)) { + br.lines() + .filter(line -> !line.trim().isEmpty()) + .forEach(line -> { + final String[] parts = line.split("=", 2); + final String fqn = parts[0]; + final String className = parts[1]; + result.put(fqn, className); + }); + } + catch (final IOException exception) { + throw new UncheckedIOException(exception); + } + return result; + } + + private final Map> cache = new HashMap<>(); + + public $Module() { + super("foo", "1.2.3", $Module.class, "foo@1.2.3.jsii.tgz"); + } + + @Override + public List> getDependencies() { + return asList(com.acme.bar.$Module.class); + } + + @Override + protected Class resolveClass(final String fqn) throws ClassNotFoundException { + if (!MODULE_TYPES.containsKey(fqn)) { + throw new ClassNotFoundException("Unknown JSII type: " + fqn); + } + String className = MODULE_TYPES.get(fqn); + if (!this.cache.containsKey(className)) { + this.cache.put(className, this.findClass(className)); + } + return this.cache.get(className); + } + + private Class findClass(final String binaryName) { + try { + return Class.forName(binaryName); + } + catch (final ClassNotFoundException exception) { + throw new RuntimeException(exception); + } + } +} + +`; + +exports[`foo@1.2.3 depends on bar@^2.0.0-rc.42: /java/src/main/resources/com/acme/foo/$Module.txt 1`] = ``; + +exports[`foo@1.2.3 depends on bar@^2.0.0-rc.42: /java/src/main/resources/com/acme/foo/foo@1.2.3.jsii.tgz 1`] = `java/src/main/resources/com/acme/foo/foo@1.2.3.jsii.tgz is a tarball`; + +exports[`foo@1.2.3 depends on bar@^2.0.0-rc.42: /js/foo@1.2.3.jsii.tgz 1`] = `js/foo@1.2.3.jsii.tgz is a tarball`; + +exports[`foo@1.2.3 depends on bar@^2.0.0-rc.42: /python/MANIFEST.in 1`] = ` +include pyproject.toml + +`; + +exports[`foo@1.2.3 depends on bar@^2.0.0-rc.42: /python/README.md 1`] = ` + + +`; + +exports[`foo@1.2.3 depends on bar@^2.0.0-rc.42: /python/pyproject.toml 1`] = ` +[build-system] +requires = ["setuptools~=49.3", "wheel~=0.34"] +build-backend = "setuptools.build_meta" + +`; + +exports[`foo@1.2.3 depends on bar@^2.0.0-rc.42: /python/setup.py 1`] = ` +import json +import setuptools + +kwargs = json.loads( + """ +{ + "name": "foo", + "version": "1.2.3", + "description": "Test assembly: foo", + "license": "UNLICENSED", + "url": "https://test.nope/foo", + "long_description_content_type": "text/markdown", + "author": "Test", + "bdist_wheel": { + "universal": true + }, + "project_urls": { + "Source": "foo.nope.git" + }, + "package_dir": { + "": "src" + }, + "packages": [ + "foo._jsii" + ], + "package_data": { + "foo._jsii": [ + "foo@1.2.3.jsii.tgz" + ] + }, + "python_requires": ">=3.6", + "install_requires": [ + "bar>=2.0.0.rc42, <3.0.0", + "jsii>=1337.42.1337, <1338.0.0", + "publication>=0.0.3" + ], + "classifiers": [ + "Intended Audience :: Developers", + "Operating System :: OS Independent", + "Programming Language :: JavaScript", + "Programming Language :: Python :: 3 :: Only", + "Programming Language :: Python :: 3.6", + "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", + "Typing :: Typed" + ] +} +""" +) + +with open("README.md", encoding="utf8") as fp: + kwargs["long_description"] = fp.read() + + +setuptools.setup(**kwargs) + +`; + +exports[`foo@1.2.3 depends on bar@^2.0.0-rc.42: /python/src/foo/_jsii/__init__.py 1`] = ` +import abc +import builtins +import datetime +import enum +import typing + +import jsii +import publication +import typing_extensions + +import bar._jsii + +__jsii_assembly__ = jsii.JSIIAssembly.load( + "foo", "1.2.3", __name__[0:-6], "foo@1.2.3.jsii.tgz" +) + +__all__ = [ + "__jsii_assembly__", +] + +publication.publish() + +`; + +exports[`foo@1.2.3 depends on bar@^2.0.0-rc.42: /python/src/foo/_jsii/foo@1.2.3.jsii.tgz 1`] = `python/src/foo/_jsii/foo@1.2.3.jsii.tgz is a tarball`; + +exports[`foo@1.2.3 depends on bar@^4.5.6-pre.1337: / 1`] = ` + + ┣━ 📁 dotnet + ┃ ┗━ 📁 Com.Acme.Foo + ┃ ┣━ 📄 AssemblyInfo.cs + ┃ ┣━ 📁 Com + ┃ ┃ ┗━ 📁 Acme + ┃ ┃ ┗━ 📁 Foo + ┃ ┃ ┗━ 📁 Internal + ┃ ┃ ┗━ 📁 DependencyResolution + ┃ ┃ ┗━ 📄 Anchor.cs + ┃ ┣━ 📄 Com.Acme.Foo.csproj + ┃ ┗━ 📄 foo-1.2.3.tgz + ┣━ 📁 go + ┃ ┗━ 📁 foo + ┃ ┣━ 📄 foo.go + ┃ ┗━ 📁 jsii + ┃ ┣━ 📄 jsii.go + ┃ ┗━ 📄 tarball.embedded.go + ┣━ 📁 java + ┃ ┣━ 📄 pom.xml + ┃ ┗━ 📁 src + ┃ ┗━ 📁 main + ┃ ┣━ 📁 java + ┃ ┃ ┗━ 📁 com + ┃ ┃ ┗━ 📁 acme + ┃ ┃ ┗━ 📁 foo + ┃ ┃ ┗━ 📄 $Module.java + ┃ ┗━ 📁 resources + ┃ ┗━ 📁 com + ┃ ┗━ 📁 acme + ┃ ┗━ 📁 foo + ┃ ┣━ 📄 $Module.txt + ┃ ┗━ 📄 foo@1.2.3.jsii.tgz + ┣━ 📁 js + ┃ ┗━ 📄 foo@1.2.3.jsii.tgz + ┗━ 📁 python + ┣━ 📄 MANIFEST.in + ┣━ 📄 pyproject.toml + ┣━ 📄 README.md + ┣━ 📄 setup.py + ┗━ 📁 src + ┗━ 📁 foo + ┗━ 📁 _jsii + ┣━ 📄 __init__.py + ┗━ 📄 foo@1.2.3.jsii.tgz +`; + +exports[`foo@1.2.3 depends on bar@^4.5.6-pre.1337: /dotnet/Com.Acme.Foo/AssemblyInfo.cs 1`] = ` +using Amazon.JSII.Runtime.Deputy; + +[assembly: JsiiAssembly("foo", "1.2.3", "foo-1.2.3.tgz")] + +`; + +exports[`foo@1.2.3 depends on bar@^4.5.6-pre.1337: /dotnet/Com.Acme.Foo/Com.Acme.Foo.csproj 1`] = ` + + + + Test assembly: foo + Com.Acme.Foo + UNLICENSED + 1.2.3 + + Test + en-US + https://test.nope/foo + foo.nope.git + git + + true + true + true + true + enable + snupkg + netcoreapp3.1 + + + + + + + + + + 0612,0618 + + + + +`; + +exports[`foo@1.2.3 depends on bar@^4.5.6-pre.1337: /dotnet/Com.Acme.Foo/Com/Acme/Foo/Internal/DependencyResolution/Anchor.cs 1`] = ` +#pragma warning disable CS0672,CS0809,CS1591 + +namespace Com.Acme.Foo.Internal.DependencyResolution +{ + public sealed class Anchor + { + public Anchor() + { + new Com.Acme.Bar.Internal.DependencyResolution.Anchor(); + } + } +} + +`; + +exports[`foo@1.2.3 depends on bar@^4.5.6-pre.1337: /dotnet/Com.Acme.Foo/foo-1.2.3.tgz 1`] = `dotnet/Com.Acme.Foo/foo-1.2.3.tgz is a tarball`; + +exports[`foo@1.2.3 depends on bar@^4.5.6-pre.1337: /go/foo/foo.go 1`] = ` +// Test assembly: foo +package foo + +import ( +) + + +`; + +exports[`foo@1.2.3 depends on bar@^4.5.6-pre.1337: /go/foo/jsii/jsii.go 1`] = ` +package jsii + +import ( + rt "github.com/aws-cdk/jsii/jsii-experimental" + "sync" + // Initialization endpoints of dependencies + bar "/bar/jsii" +) + +var once sync.Once + +// Initialize performs the necessary work for the enclosing +// module to be loaded in the jsii kernel. +func Initialize() { + once.Do(func(){ + // Ensure all dependencies are initialized + bar.Initialize() + + // Load this library into the kernel + rt.Load("foo", "1.2.3", tarball) + }) +} + +`; + +exports[`foo@1.2.3 depends on bar@^4.5.6-pre.1337: /go/foo/jsii/tarball.embedded.go 1`] = `go/foo/jsii/tarball.embedded.go embeds a tarball`; + +exports[`foo@1.2.3 depends on bar@^4.5.6-pre.1337: /java/pom.xml 1`] = ` + + + 4.0.0 + \${project.groupId}:\${project.artifactId} + Test assembly: foo + https://test.nope/foo + + + + Test + + test + + + + + scm:git:foo.nope.git + foo.nope.git + + com.acme + foo + 1.2.3 + jar + + UTF-8 + + + + com.acme + bar + [4.5.6-pre.1337,5.0.0) + + + software.amazon.jsii + jsii-runtime + [0.0.0,0.0.1) + + + org.jetbrains + annotations + [16.0.3,20.0.0) + + + + javax.annotation + javax.annotation-api + [1.3.2,1.4.0) + compile + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.1 + + 1.8 + 1.8 + + + + org.apache.maven.plugins + maven-jar-plugin + 3.2.0 + + + true + + true + true + + + + + + org.apache.maven.plugins + maven-source-plugin + 3.2.1 + + + attach-sources + + jar + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 3.1.1 + + + attach-javadocs + + jar + + + + + false + protected + + **/$Module.java + + -J-XX:+TieredCompilation + -J-XX:TieredStopAtLevel=1 + + + + org.apache.maven.plugins + maven-enforcer-plugin + 3.0.0-M3 + + + enforce-maven + + enforce + + + + + 3.6 + + + + + + + + org.codehaus.mojo + versions-maven-plugin + 2.7 + + false + + + + + + +`; + +exports[`foo@1.2.3 depends on bar@^4.5.6-pre.1337: /java/src/main/java/com/acme/foo/$Module.java 1`] = ` +package com.acme.foo; + +import static java.util.Arrays.asList; + +import java.io.BufferedReader; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.IOException; +import java.io.Reader; +import java.io.UncheckedIOException; + +import java.nio.charset.StandardCharsets; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import software.amazon.jsii.JsiiModule; + +@software.amazon.jsii.Internal +public final class $Module extends JsiiModule { + private static final Map MODULE_TYPES = load(); + + private static Map load() { + final Map result = new HashMap<>(); + final ClassLoader cl = $Module.class.getClassLoader(); + try (final InputStream is = cl.getResourceAsStream("com/acme/foo/$Module.txt"); + final Reader rd = new InputStreamReader(is, StandardCharsets.UTF_8); + final BufferedReader br = new BufferedReader(rd)) { + br.lines() + .filter(line -> !line.trim().isEmpty()) + .forEach(line -> { + final String[] parts = line.split("=", 2); + final String fqn = parts[0]; + final String className = parts[1]; + result.put(fqn, className); + }); + } + catch (final IOException exception) { + throw new UncheckedIOException(exception); + } + return result; + } + + private final Map> cache = new HashMap<>(); + + public $Module() { + super("foo", "1.2.3", $Module.class, "foo@1.2.3.jsii.tgz"); + } + + @Override + public List> getDependencies() { + return asList(com.acme.bar.$Module.class); + } + + @Override + protected Class resolveClass(final String fqn) throws ClassNotFoundException { + if (!MODULE_TYPES.containsKey(fqn)) { + throw new ClassNotFoundException("Unknown JSII type: " + fqn); + } + String className = MODULE_TYPES.get(fqn); + if (!this.cache.containsKey(className)) { + this.cache.put(className, this.findClass(className)); + } + return this.cache.get(className); + } + + private Class findClass(final String binaryName) { + try { + return Class.forName(binaryName); + } + catch (final ClassNotFoundException exception) { + throw new RuntimeException(exception); + } + } +} + +`; + +exports[`foo@1.2.3 depends on bar@^4.5.6-pre.1337: /java/src/main/resources/com/acme/foo/$Module.txt 1`] = ``; + +exports[`foo@1.2.3 depends on bar@^4.5.6-pre.1337: /java/src/main/resources/com/acme/foo/foo@1.2.3.jsii.tgz 1`] = `java/src/main/resources/com/acme/foo/foo@1.2.3.jsii.tgz is a tarball`; + +exports[`foo@1.2.3 depends on bar@^4.5.6-pre.1337: /js/foo@1.2.3.jsii.tgz 1`] = `js/foo@1.2.3.jsii.tgz is a tarball`; + +exports[`foo@1.2.3 depends on bar@^4.5.6-pre.1337: /python/MANIFEST.in 1`] = ` +include pyproject.toml + +`; + +exports[`foo@1.2.3 depends on bar@^4.5.6-pre.1337: /python/README.md 1`] = ` + + +`; + +exports[`foo@1.2.3 depends on bar@^4.5.6-pre.1337: /python/pyproject.toml 1`] = ` +[build-system] +requires = ["setuptools~=49.3", "wheel~=0.34"] +build-backend = "setuptools.build_meta" + +`; + +exports[`foo@1.2.3 depends on bar@^4.5.6-pre.1337: /python/setup.py 1`] = ` +import json +import setuptools + +kwargs = json.loads( + """ +{ + "name": "foo", + "version": "1.2.3", + "description": "Test assembly: foo", + "license": "UNLICENSED", + "url": "https://test.nope/foo", + "long_description_content_type": "text/markdown", + "author": "Test", + "bdist_wheel": { + "universal": true + }, + "project_urls": { + "Source": "foo.nope.git" + }, + "package_dir": { + "": "src" + }, + "packages": [ + "foo._jsii" + ], + "package_data": { + "foo._jsii": [ + "foo@1.2.3.jsii.tgz" + ] + }, + "python_requires": ">=3.6", + "install_requires": [ + "bar>=4.5.6.dev1337, <5.0.0", + "jsii>=1337.42.1337, <1338.0.0", + "publication>=0.0.3" + ], + "classifiers": [ + "Intended Audience :: Developers", + "Operating System :: OS Independent", + "Programming Language :: JavaScript", + "Programming Language :: Python :: 3 :: Only", + "Programming Language :: Python :: 3.6", + "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", + "Typing :: Typed" + ] +} +""" +) + +with open("README.md", encoding="utf8") as fp: + kwargs["long_description"] = fp.read() + + +setuptools.setup(**kwargs) + +`; + +exports[`foo@1.2.3 depends on bar@^4.5.6-pre.1337: /python/src/foo/_jsii/__init__.py 1`] = ` +import abc +import builtins +import datetime +import enum +import typing + +import jsii +import publication +import typing_extensions + +import bar._jsii + +__jsii_assembly__ = jsii.JSIIAssembly.load( + "foo", "1.2.3", __name__[0:-6], "foo@1.2.3.jsii.tgz" +) + +__all__ = [ + "__jsii_assembly__", +] + +publication.publish() + +`; + +exports[`foo@1.2.3 depends on bar@^4.5.6-pre.1337: /python/src/foo/_jsii/foo@1.2.3.jsii.tgz 1`] = `python/src/foo/_jsii/foo@1.2.3.jsii.tgz is a tarball`; + +exports[`foo@2.0.0-rc.42: / 1`] = ` + + ┣━ 📁 dotnet + ┃ ┗━ 📁 Com.Acme.Foo + ┃ ┣━ 📄 AssemblyInfo.cs + ┃ ┣━ 📁 Com + ┃ ┃ ┗━ 📁 Acme + ┃ ┃ ┗━ 📁 Foo + ┃ ┃ ┗━ 📁 Internal + ┃ ┃ ┗━ 📁 DependencyResolution + ┃ ┃ ┗━ 📄 Anchor.cs + ┃ ┣━ 📄 Com.Acme.Foo.csproj + ┃ ┗━ 📄 foo-2.0.0-rc.42.tgz + ┣━ 📁 go + ┃ ┗━ 📁 foo + ┃ ┣━ 📄 foo.go + ┃ ┗━ 📁 jsii + ┃ ┣━ 📄 jsii.go + ┃ ┗━ 📄 tarball.embedded.go + ┣━ 📁 java + ┃ ┣━ 📄 pom.xml + ┃ ┗━ 📁 src + ┃ ┗━ 📁 main + ┃ ┣━ 📁 java + ┃ ┃ ┗━ 📁 com + ┃ ┃ ┗━ 📁 acme + ┃ ┃ ┗━ 📁 foo + ┃ ┃ ┗━ 📄 $Module.java + ┃ ┗━ 📁 resources + ┃ ┗━ 📁 com + ┃ ┗━ 📁 acme + ┃ ┗━ 📁 foo + ┃ ┣━ 📄 $Module.txt + ┃ ┗━ 📄 foo@2.0.0-rc.42.jsii.tgz + ┣━ 📁 js + ┃ ┗━ 📄 foo@2.0.0-rc.42.jsii.tgz + ┗━ 📁 python + ┣━ 📄 MANIFEST.in + ┣━ 📄 pyproject.toml + ┣━ 📄 README.md + ┣━ 📄 setup.py + ┗━ 📁 src + ┗━ 📁 foo + ┗━ 📁 _jsii + ┣━ 📄 __init__.py + ┗━ 📄 foo@2.0.0-rc.42.jsii.tgz +`; + +exports[`foo@2.0.0-rc.42: /dotnet/Com.Acme.Foo/AssemblyInfo.cs 1`] = ` +using Amazon.JSII.Runtime.Deputy; + +[assembly: JsiiAssembly("foo", "2.0.0-rc.42", "foo-2.0.0-rc.42.tgz")] + +`; + +exports[`foo@2.0.0-rc.42: /dotnet/Com.Acme.Foo/Com.Acme.Foo.csproj 1`] = ` + + + + Test assembly: foo + Com.Acme.Foo + UNLICENSED + 2.0.0-rc.42 + + Test + en-US + https://test.nope/foo + foo.nope.git + git + + true + true + true + true + enable + snupkg + netcoreapp3.1 + + + + + + + + + 0612,0618 + + + + +`; + +exports[`foo@2.0.0-rc.42: /dotnet/Com.Acme.Foo/Com/Acme/Foo/Internal/DependencyResolution/Anchor.cs 1`] = ` +#pragma warning disable CS0672,CS0809,CS1591 + +namespace Com.Acme.Foo.Internal.DependencyResolution +{ + public sealed class Anchor + { + public Anchor() + { + } + } +} + +`; + +exports[`foo@2.0.0-rc.42: /dotnet/Com.Acme.Foo/foo-2.0.0-rc.42.tgz 1`] = `dotnet/Com.Acme.Foo/foo-2.0.0-rc.42.tgz is a tarball`; + +exports[`foo@2.0.0-rc.42: /go/foo/foo.go 1`] = ` +// Test assembly: foo +package foo + +import ( +) + + +`; + +exports[`foo@2.0.0-rc.42: /go/foo/jsii/jsii.go 1`] = ` +package jsii + +import ( + rt "github.com/aws-cdk/jsii/jsii-experimental" + "sync" +) + +var once sync.Once + +// Initialize performs the necessary work for the enclosing +// module to be loaded in the jsii kernel. +func Initialize() { + once.Do(func(){ + // Load this library into the kernel + rt.Load("foo", "2.0.0-rc.42", tarball) + }) +} + +`; + +exports[`foo@2.0.0-rc.42: /go/foo/jsii/tarball.embedded.go 1`] = `go/foo/jsii/tarball.embedded.go embeds a tarball`; + +exports[`foo@2.0.0-rc.42: /java/pom.xml 1`] = ` + + + 4.0.0 + \${project.groupId}:\${project.artifactId} + Test assembly: foo + https://test.nope/foo + + + + Test + + test + + + + + scm:git:foo.nope.git + foo.nope.git + + com.acme + foo + 2.0.0-rc.42 + jar + + UTF-8 + + + + software.amazon.jsii + jsii-runtime + [0.0.0,0.0.1) + + + org.jetbrains + annotations + [16.0.3,20.0.0) + + + + javax.annotation + javax.annotation-api + [1.3.2,1.4.0) + compile + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.1 + + 1.8 + 1.8 + + + + org.apache.maven.plugins + maven-jar-plugin + 3.2.0 + + + true + + true + true + + + + + + org.apache.maven.plugins + maven-source-plugin + 3.2.1 + + + attach-sources + + jar + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 3.1.1 + + + attach-javadocs + + jar + + + + + false + protected + + **/$Module.java + + -J-XX:+TieredCompilation + -J-XX:TieredStopAtLevel=1 + + + + org.apache.maven.plugins + maven-enforcer-plugin + 3.0.0-M3 + + + enforce-maven + + enforce + + + + + 3.6 + + + + + + + + org.codehaus.mojo + versions-maven-plugin + 2.7 + + false + + + + + + +`; + +exports[`foo@2.0.0-rc.42: /java/src/main/java/com/acme/foo/$Module.java 1`] = ` +package com.acme.foo; + +import java.io.BufferedReader; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.IOException; +import java.io.Reader; +import java.io.UncheckedIOException; + +import java.nio.charset.StandardCharsets; + +import java.util.HashMap; +import java.util.Map; + +import software.amazon.jsii.JsiiModule; + +@software.amazon.jsii.Internal +public final class $Module extends JsiiModule { + private static final Map MODULE_TYPES = load(); + + private static Map load() { + final Map result = new HashMap<>(); + final ClassLoader cl = $Module.class.getClassLoader(); + try (final InputStream is = cl.getResourceAsStream("com/acme/foo/$Module.txt"); + final Reader rd = new InputStreamReader(is, StandardCharsets.UTF_8); + final BufferedReader br = new BufferedReader(rd)) { + br.lines() + .filter(line -> !line.trim().isEmpty()) + .forEach(line -> { + final String[] parts = line.split("=", 2); + final String fqn = parts[0]; + final String className = parts[1]; + result.put(fqn, className); + }); + } + catch (final IOException exception) { + throw new UncheckedIOException(exception); + } + return result; + } + + private final Map> cache = new HashMap<>(); + + public $Module() { + super("foo", "2.0.0-rc.42", $Module.class, "foo@2.0.0-rc.42.jsii.tgz"); + } + + @Override + protected Class resolveClass(final String fqn) throws ClassNotFoundException { + if (!MODULE_TYPES.containsKey(fqn)) { + throw new ClassNotFoundException("Unknown JSII type: " + fqn); + } + String className = MODULE_TYPES.get(fqn); + if (!this.cache.containsKey(className)) { + this.cache.put(className, this.findClass(className)); + } + return this.cache.get(className); + } + + private Class findClass(final String binaryName) { + try { + return Class.forName(binaryName); + } + catch (final ClassNotFoundException exception) { + throw new RuntimeException(exception); + } + } +} + +`; + +exports[`foo@2.0.0-rc.42: /java/src/main/resources/com/acme/foo/$Module.txt 1`] = ``; + +exports[`foo@2.0.0-rc.42: /java/src/main/resources/com/acme/foo/foo@2.0.0-rc.42.jsii.tgz 1`] = `java/src/main/resources/com/acme/foo/foo@2.0.0-rc.42.jsii.tgz is a tarball`; + +exports[`foo@2.0.0-rc.42: /js/foo@2.0.0-rc.42.jsii.tgz 1`] = `js/foo@2.0.0-rc.42.jsii.tgz is a tarball`; + +exports[`foo@2.0.0-rc.42: /python/MANIFEST.in 1`] = ` +include pyproject.toml + +`; + +exports[`foo@2.0.0-rc.42: /python/README.md 1`] = ` + + +`; + +exports[`foo@2.0.0-rc.42: /python/pyproject.toml 1`] = ` +[build-system] +requires = ["setuptools~=49.3", "wheel~=0.34"] +build-backend = "setuptools.build_meta" + +`; + +exports[`foo@2.0.0-rc.42: /python/setup.py 1`] = ` +import json +import setuptools + +kwargs = json.loads( + """ +{ + "name": "foo", + "version": "2.0.0.rc42", + "description": "Test assembly: foo", + "license": "UNLICENSED", + "url": "https://test.nope/foo", + "long_description_content_type": "text/markdown", + "author": "Test", + "bdist_wheel": { + "universal": true + }, + "project_urls": { + "Source": "foo.nope.git" + }, + "package_dir": { + "": "src" + }, + "packages": [ + "foo._jsii" + ], + "package_data": { + "foo._jsii": [ + "foo@2.0.0-rc.42.jsii.tgz" + ] + }, + "python_requires": ">=3.6", + "install_requires": [ + "jsii>=1337.42.1337, <1338.0.0", + "publication>=0.0.3" + ], + "classifiers": [ + "Intended Audience :: Developers", + "Operating System :: OS Independent", + "Programming Language :: JavaScript", + "Programming Language :: Python :: 3 :: Only", + "Programming Language :: Python :: 3.6", + "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", + "Typing :: Typed" + ] +} +""" +) + +with open("README.md", encoding="utf8") as fp: + kwargs["long_description"] = fp.read() + + +setuptools.setup(**kwargs) + +`; + +exports[`foo@2.0.0-rc.42: /python/src/foo/_jsii/__init__.py 1`] = ` +import abc +import builtins +import datetime +import enum +import typing + +import jsii +import publication +import typing_extensions + +__jsii_assembly__ = jsii.JSIIAssembly.load( + "foo", "2.0.0-rc.42", __name__[0:-6], "foo@2.0.0-rc.42.jsii.tgz" +) + +__all__ = [ + "__jsii_assembly__", +] + +publication.publish() + +`; + +exports[`foo@2.0.0-rc.42: /python/src/foo/_jsii/foo@2.0.0-rc.42.jsii.tgz 1`] = `python/src/foo/_jsii/foo@2.0.0-rc.42.jsii.tgz is a tarball`; + +exports[`foo@4.5.6-pre.1337: / 1`] = ` + + ┣━ 📁 dotnet + ┃ ┗━ 📁 Com.Acme.Foo + ┃ ┣━ 📄 AssemblyInfo.cs + ┃ ┣━ 📁 Com + ┃ ┃ ┗━ 📁 Acme + ┃ ┃ ┗━ 📁 Foo + ┃ ┃ ┗━ 📁 Internal + ┃ ┃ ┗━ 📁 DependencyResolution + ┃ ┃ ┗━ 📄 Anchor.cs + ┃ ┣━ 📄 Com.Acme.Foo.csproj + ┃ ┗━ 📄 foo-4.5.6-pre.1337.tgz + ┣━ 📁 go + ┃ ┗━ 📁 foo + ┃ ┣━ 📄 foo.go + ┃ ┗━ 📁 jsii + ┃ ┣━ 📄 jsii.go + ┃ ┗━ 📄 tarball.embedded.go + ┣━ 📁 java + ┃ ┣━ 📄 pom.xml + ┃ ┗━ 📁 src + ┃ ┗━ 📁 main + ┃ ┣━ 📁 java + ┃ ┃ ┗━ 📁 com + ┃ ┃ ┗━ 📁 acme + ┃ ┃ ┗━ 📁 foo + ┃ ┃ ┗━ 📄 $Module.java + ┃ ┗━ 📁 resources + ┃ ┗━ 📁 com + ┃ ┗━ 📁 acme + ┃ ┗━ 📁 foo + ┃ ┣━ 📄 $Module.txt + ┃ ┗━ 📄 foo@4.5.6-pre.1337.jsii.tgz + ┣━ 📁 js + ┃ ┗━ 📄 foo@4.5.6-pre.1337.jsii.tgz + ┗━ 📁 python + ┣━ 📄 MANIFEST.in + ┣━ 📄 pyproject.toml + ┣━ 📄 README.md + ┣━ 📄 setup.py + ┗━ 📁 src + ┗━ 📁 foo + ┗━ 📁 _jsii + ┣━ 📄 __init__.py + ┗━ 📄 foo@4.5.6-pre.1337.jsii.tgz +`; + +exports[`foo@4.5.6-pre.1337: /dotnet/Com.Acme.Foo/AssemblyInfo.cs 1`] = ` +using Amazon.JSII.Runtime.Deputy; + +[assembly: JsiiAssembly("foo", "4.5.6-pre.1337", "foo-4.5.6-pre.1337.tgz")] + +`; + +exports[`foo@4.5.6-pre.1337: /dotnet/Com.Acme.Foo/Com.Acme.Foo.csproj 1`] = ` + + + + Test assembly: foo + Com.Acme.Foo + UNLICENSED + 4.5.6-pre.1337 + + Test + en-US + https://test.nope/foo + foo.nope.git + git + + true + true + true + true + enable + snupkg + netcoreapp3.1 + + + + + + + + + 0612,0618 + + + + +`; + +exports[`foo@4.5.6-pre.1337: /dotnet/Com.Acme.Foo/Com/Acme/Foo/Internal/DependencyResolution/Anchor.cs 1`] = ` +#pragma warning disable CS0672,CS0809,CS1591 + +namespace Com.Acme.Foo.Internal.DependencyResolution +{ + public sealed class Anchor + { + public Anchor() + { + } + } +} + +`; + +exports[`foo@4.5.6-pre.1337: /dotnet/Com.Acme.Foo/foo-4.5.6-pre.1337.tgz 1`] = `dotnet/Com.Acme.Foo/foo-4.5.6-pre.1337.tgz is a tarball`; + +exports[`foo@4.5.6-pre.1337: /go/foo/foo.go 1`] = ` +// Test assembly: foo +package foo + +import ( +) + + +`; + +exports[`foo@4.5.6-pre.1337: /go/foo/jsii/jsii.go 1`] = ` +package jsii + +import ( + rt "github.com/aws-cdk/jsii/jsii-experimental" + "sync" +) + +var once sync.Once + +// Initialize performs the necessary work for the enclosing +// module to be loaded in the jsii kernel. +func Initialize() { + once.Do(func(){ + // Load this library into the kernel + rt.Load("foo", "4.5.6-pre.1337", tarball) + }) +} + +`; + +exports[`foo@4.5.6-pre.1337: /go/foo/jsii/tarball.embedded.go 1`] = `go/foo/jsii/tarball.embedded.go embeds a tarball`; + +exports[`foo@4.5.6-pre.1337: /java/pom.xml 1`] = ` + + + 4.0.0 + \${project.groupId}:\${project.artifactId} + Test assembly: foo + https://test.nope/foo + + + + Test + + test + + + + + scm:git:foo.nope.git + foo.nope.git + + com.acme + foo + 4.5.6-pre.1337 + jar + + UTF-8 + + + + software.amazon.jsii + jsii-runtime + [0.0.0,0.0.1) + + + org.jetbrains + annotations + [16.0.3,20.0.0) + + + + javax.annotation + javax.annotation-api + [1.3.2,1.4.0) + compile + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.1 + + 1.8 + 1.8 + + + + org.apache.maven.plugins + maven-jar-plugin + 3.2.0 + + + true + + true + true + + + + + + org.apache.maven.plugins + maven-source-plugin + 3.2.1 + + + attach-sources + + jar + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 3.1.1 + + + attach-javadocs + + jar + + + + + false + protected + + **/$Module.java + + -J-XX:+TieredCompilation + -J-XX:TieredStopAtLevel=1 + + + + org.apache.maven.plugins + maven-enforcer-plugin + 3.0.0-M3 + + + enforce-maven + + enforce + + + + + 3.6 + + + + + + + + org.codehaus.mojo + versions-maven-plugin + 2.7 + + false + + + + + + +`; + +exports[`foo@4.5.6-pre.1337: /java/src/main/java/com/acme/foo/$Module.java 1`] = ` +package com.acme.foo; + +import java.io.BufferedReader; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.IOException; +import java.io.Reader; +import java.io.UncheckedIOException; + +import java.nio.charset.StandardCharsets; + +import java.util.HashMap; +import java.util.Map; + +import software.amazon.jsii.JsiiModule; + +@software.amazon.jsii.Internal +public final class $Module extends JsiiModule { + private static final Map MODULE_TYPES = load(); + + private static Map load() { + final Map result = new HashMap<>(); + final ClassLoader cl = $Module.class.getClassLoader(); + try (final InputStream is = cl.getResourceAsStream("com/acme/foo/$Module.txt"); + final Reader rd = new InputStreamReader(is, StandardCharsets.UTF_8); + final BufferedReader br = new BufferedReader(rd)) { + br.lines() + .filter(line -> !line.trim().isEmpty()) + .forEach(line -> { + final String[] parts = line.split("=", 2); + final String fqn = parts[0]; + final String className = parts[1]; + result.put(fqn, className); + }); + } + catch (final IOException exception) { + throw new UncheckedIOException(exception); + } + return result; + } + + private final Map> cache = new HashMap<>(); + + public $Module() { + super("foo", "4.5.6-pre.1337", $Module.class, "foo@4.5.6-pre.1337.jsii.tgz"); + } + + @Override + protected Class resolveClass(final String fqn) throws ClassNotFoundException { + if (!MODULE_TYPES.containsKey(fqn)) { + throw new ClassNotFoundException("Unknown JSII type: " + fqn); + } + String className = MODULE_TYPES.get(fqn); + if (!this.cache.containsKey(className)) { + this.cache.put(className, this.findClass(className)); + } + return this.cache.get(className); + } + + private Class findClass(final String binaryName) { + try { + return Class.forName(binaryName); + } + catch (final ClassNotFoundException exception) { + throw new RuntimeException(exception); + } + } +} + +`; + +exports[`foo@4.5.6-pre.1337: /java/src/main/resources/com/acme/foo/$Module.txt 1`] = ``; + +exports[`foo@4.5.6-pre.1337: /java/src/main/resources/com/acme/foo/foo@4.5.6-pre.1337.jsii.tgz 1`] = `java/src/main/resources/com/acme/foo/foo@4.5.6-pre.1337.jsii.tgz is a tarball`; + +exports[`foo@4.5.6-pre.1337: /js/foo@4.5.6-pre.1337.jsii.tgz 1`] = `js/foo@4.5.6-pre.1337.jsii.tgz is a tarball`; + +exports[`foo@4.5.6-pre.1337: /python/MANIFEST.in 1`] = ` +include pyproject.toml + +`; + +exports[`foo@4.5.6-pre.1337: /python/README.md 1`] = ` + + +`; + +exports[`foo@4.5.6-pre.1337: /python/pyproject.toml 1`] = ` +[build-system] +requires = ["setuptools~=49.3", "wheel~=0.34"] +build-backend = "setuptools.build_meta" + +`; + +exports[`foo@4.5.6-pre.1337: /python/setup.py 1`] = ` +import json +import setuptools + +kwargs = json.loads( + """ +{ + "name": "foo", + "version": "4.5.6.dev1337", + "description": "Test assembly: foo", + "license": "UNLICENSED", + "url": "https://test.nope/foo", + "long_description_content_type": "text/markdown", + "author": "Test", + "bdist_wheel": { + "universal": true + }, + "project_urls": { + "Source": "foo.nope.git" + }, + "package_dir": { + "": "src" + }, + "packages": [ + "foo._jsii" + ], + "package_data": { + "foo._jsii": [ + "foo@4.5.6-pre.1337.jsii.tgz" + ] + }, + "python_requires": ">=3.6", + "install_requires": [ + "jsii>=1337.42.1337, <1338.0.0", + "publication>=0.0.3" + ], + "classifiers": [ + "Intended Audience :: Developers", + "Operating System :: OS Independent", + "Programming Language :: JavaScript", + "Programming Language :: Python :: 3 :: Only", + "Programming Language :: Python :: 3.6", + "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", + "Typing :: Typed" + ] +} +""" +) + +with open("README.md", encoding="utf8") as fp: + kwargs["long_description"] = fp.read() + + +setuptools.setup(**kwargs) + +`; + +exports[`foo@4.5.6-pre.1337: /python/src/foo/_jsii/__init__.py 1`] = ` +import abc +import builtins +import datetime +import enum +import typing + +import jsii +import publication +import typing_extensions + +__jsii_assembly__ = jsii.JSIIAssembly.load( + "foo", "4.5.6-pre.1337", __name__[0:-6], "foo@4.5.6-pre.1337.jsii.tgz" +) + +__all__ = [ + "__jsii_assembly__", +] + +publication.publish() + +`; + +exports[`foo@4.5.6-pre.1337: /python/src/foo/_jsii/foo@4.5.6-pre.1337.jsii.tgz 1`] = `python/src/foo/_jsii/foo@4.5.6-pre.1337.jsii.tgz is a tarball`; diff --git a/packages/jsii-pacmak/test/generated-code/harness.ts b/packages/jsii-pacmak/test/generated-code/harness.ts index fc92a9a7c9..ab092136e5 100644 --- a/packages/jsii-pacmak/test/generated-code/harness.ts +++ b/packages/jsii-pacmak/test/generated-code/harness.ts @@ -9,7 +9,7 @@ import { shell } from '../../lib/util'; const FILE = Symbol('file'); const MISSING = Symbol('missing'); const TARBALL = Symbol('tarball'); -const TREE = Symbol('tree'); +export const TREE = Symbol('tree'); // Custom serializers so we can see the source without escape sequences expect.addSnapshotSerializer({ @@ -75,7 +75,7 @@ export function verifyGeneratedCodeFor( } } -function checkTree( +export function checkTree( file: string, root: string = file, ): TreeStructure | undefined { diff --git a/packages/jsii-pacmak/test/generated-code/prerelease-identifiers.test.ts b/packages/jsii-pacmak/test/generated-code/prerelease-identifiers.test.ts new file mode 100644 index 0000000000..7b6224cdc7 --- /dev/null +++ b/packages/jsii-pacmak/test/generated-code/prerelease-identifiers.test.ts @@ -0,0 +1,160 @@ +import { Assembly, SchemaVersion, SPEC_FILE_NAME } from '@jsii/spec'; +import { toPascalCase } from 'codemaker'; +import * as fs from 'fs-extra'; +import { tmpdir } from 'os'; +import { join } from 'path'; + +import { pacmak } from '../../lib'; +import { checkTree, TREE } from './harness'; + +for (const prerelease of ['4.5.6-pre.1337', '0.0.0-pr1234.0', '2.0.0-rc.42']) { + test(`foo@1.2.3 depends on bar@^${prerelease}`, async () => { + const outDir = await fs.mkdtemp( + join(tmpdir(), 'jsii-pacmak.prerelease-identifiers.test.output.'), + ); + + try { + await mockSourceDirectory('1.2.3', { bar: `^${prerelease}` }, (source) => + pacmak({ + codeOnly: true, + force: true, + fingerprint: false, + inputDirectories: [source], + outputDirectory: outDir, + }), + ); + + expect({ [TREE]: checkTree(outDir) }).toMatchSnapshot('/'); + } finally { + await fs.remove(outDir); + } + }); + + test(`foo@${prerelease}`, async () => { + const outDir = await fs.mkdtemp( + join(tmpdir(), 'jsii-pacmak.prerelease-identifiers.test.output.'), + ); + + try { + await mockSourceDirectory(prerelease, undefined, (source) => + pacmak({ + codeOnly: true, + force: true, + fingerprint: false, + inputDirectories: [source], + outputDirectory: outDir, + }), + ); + + expect({ [TREE]: checkTree(outDir) }).toMatchSnapshot('/'); + } finally { + await fs.remove(outDir); + } + }); +} + +//#region Test Helpers + +async function mockSourceDirectory( + version: string, + dependencies: { readonly [name: string]: string } | undefined, + cb: (source: string) => Promise, +): Promise { + const dir = await fs.mkdtemp( + join(tmpdir(), 'jsii-pacmak.prerelease-identifiers.test.input.'), + ); + try { + const assembly = mockAssembly('foo', version, dependencies); + await fs.writeJson(join(dir, SPEC_FILE_NAME), assembly, { spaces: 2 }); + await fs.writeJson( + join(dir, 'package.json'), + { + jsii: { + outdir: 'dist', + targets: assembly.targets, + }, + license: assembly.license, + name: assembly.name, + peerDependencies: assembly.dependencies, + version: assembly.version, + }, + { spaces: 2 }, + ); + + /* eslint-disable no-await-in-loop */ + for (const [name, version] of Object.entries(assembly.dependencies ?? {})) { + const pkgDir = join(dir, 'node_modules', name); + await fs.mkdirp(pkgDir); + const assembly = mockAssembly(name, version.replace(/^[^\d]/, '')); + await fs.writeJson(join(pkgDir, SPEC_FILE_NAME), assembly, { spaces: 2 }); + await fs.writeJson( + join(pkgDir, 'package.json'), + { + jsii: { + outdir: 'dist', + targets: assembly.targets, + }, + license: assembly.license, + name: assembly.name, + version: assembly.version, + }, + { spaces: 2 }, + ); + } + /* eslint-enable no-await-in-loop */ + + return await cb(dir); + } finally { + await fs.remove(dir); + } +} + +function mockAssembly( + name: string, + version: string, + dependencies?: { readonly [name: string]: string }, +): Assembly { + return { + author: { name: 'Test', roles: ['test'] }, + dependencies, + dependencyClosure: + dependencies && + Object.keys(dependencies).reduce( + (closure, name) => ({ + ...closure, + [name]: { targets: targetsOf(name) }, + }), + {}, + ), + description: `Test assembly: ${name}`, + fingerprint: '', + homepage: `https://test.nope/${name}`, + jsiiVersion: '1337.42.1337', + license: 'UNLICENSED', + name, + repository: { type: 'git', url: `${name}.nope.git` }, + schema: SchemaVersion.LATEST, + targets: targetsOf(name), + version, + }; + + function targetsOf(name: string): Assembly['targets'] { + return { + dotnet: { + namespace: `Com.Acme.${toPascalCase(name)}`, + packageId: `Com.Acme.${toPascalCase(name)}`, + }, + go: {}, + java: { + maven: { groupId: 'com.acme', artifactId: name }, + package: `com.acme.${name}`, + }, + python: { + distName: name, + module: name, + }, + }; + } +} + +//#endregion From b1ff0c59d7e6c9c4c8683ec05172012ca52d6fc6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=91=A8=F0=9F=8F=BC=E2=80=8D=F0=9F=92=BB=20Romain=20M?= =?UTF-8?q?arcadier-Muller?= Date: Tue, 27 Oct 2020 13:01:38 +0100 Subject: [PATCH 09/16] document Python pre-version translation --- docs/configuration.md | 337 ++++++++++++++++++++---------------------- 1 file changed, 164 insertions(+), 173 deletions(-) diff --git a/docs/configuration.md b/docs/configuration.md index c956a3ad9e..a8b425b22d 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -1,8 +1,7 @@ # Configuration -The configuration for `jsii` is recorded in the `package.json` file, which is -the standard package manifest for NPM packages. This document describes the -constraints and extensions `jsii` adds to the [package.json schema]. +The configuration for `jsii` is recorded in the `package.json` file, which is the standard package manifest for NPM +packages. This document describes the constraints and extensions `jsii` adds to the [package.json schema]. [package.json schema]: https://docs.npmjs.com/files/package.json @@ -12,30 +11,28 @@ Use [jsii-config](../packages/jsii-config) to aid in configuring a new jsii modu ## Additional Requirements & Extensions -In order to be able to generate valid packages for all the supported target -package managers, certain fields that are optional in the standard -[package.json schema] are required by `jsii`. +In order to be able to generate valid packages for all the supported target package managers, certain fields that are +optional in the standard [package.json schema] are required by `jsii`. -For example, Maven Central requires packages to carry [sufficient metadata], -such as *developer information* and *license*, in order to be valid for -publishing. +For example, Maven Central requires packages to carry [sufficient metadata], such as _developer information_ and +_license_, in order to be valid for publishing. -Field | Required | Extensions -------------|----------|-------------------------------------------------------- -`author` | Required | `author.organization` -`license` | Required | -`main` | Required | -`repository`| Required | -`stability` | | The field itself is an extension -`types` | Required | +| Field | Required | Extensions | +| ------------ | -------- | -------------------------------- | +| `author` | Required | `author.organization` | +| `license` | Required | +| `main` | Required | +| `repository` | Required | +| `stability` | | The field itself is an extension | +| `types` | Required | [sufficient metadata]: https://central.sonatype.org/pages/requirements.html#sufficient-metadata ### Attribution & Licensing -* The [`author`][npm-author] field must be set. Although the string form - (`"The Octocat (https://github.com/octocat)"`) works, - it is recommended to set the value using the `object` format: +- The [`author`][npm-author] field must be set. Although the string form + (`"The Octocat (https://github.com/octocat)"`) works, it is recommended to set the value using + the `object` format: ```js { // ... @@ -48,22 +45,20 @@ Field | Required | Extensions // ... } ``` - The `organization` field is an extension from the [package.json schema] that - can be used to signal the `author` field refers to an `organization` and not - and individual person. -* The [`license`][npm-license] field must be set to a valid [SPDX license id]. - If you do not intend to release your package for third-party consumption, - `UNLICENSED` (not to be confused with `Unlicense`) is a valid option. + The `organization` field is an extension from the [package.json schema] that can be used to signal the `author` field + refers to an `organization` and not and individual person. +- The [`license`][npm-license] field must be set to a valid [SPDX license id]. If you do not intend to release your + package for third-party consumption, `UNLICENSED` (not to be confused with `Unlicense`) is a valid option. [npm-author]: https://docs.npmjs.com/files/package.json#people-fields-author-contributors [npm-license]: https://docs.npmjs.com/files/package.json#license -[SPDX license id]: https://spdx.org/licenses/ +[spdx license id]: https://spdx.org/licenses/ ### Source Control Information -The [`repository`][npm-repository] field must be set to the URL of the -source-control system (such as a `git` repository) for the package. The -recommended way to provide the value is using the `object` representation: +The [`repository`][npm-repository] field must be set to the URL of the source-control system (such as a `git` +repository) for the package. The recommended way to provide the value is using the `object` representation: + ```js { "repository": { @@ -78,100 +73,91 @@ recommended way to provide the value is using the `object` representation: ### Library Entry Point -Both the [`main`][npm-main] field must be set to the `.js` file that acts as the -entry point of your library (what node's `require('library-name')` will load). -Additionally, `TypeScript`'s [`types`][ts-types] field must be set to the -`.d.ts` file corresponding to the `main` file. The assembly emitted by `jsii` -will only represent types that are exported from the `types` file. +Both the [`main`][npm-main] field must be set to the `.js` file that acts as the entry point of your library (what +node's `require('library-name')` will load). Additionally, `TypeScript`'s [`types`][ts-types] field must be set to the +`.d.ts` file corresponding to the `main` file. The assembly emitted by `jsii` will only represent types that are +exported from the `types` file. [npm-main]: https://docs.npmjs.com/files/package.json#main -[ts-types]: https://www.typescriptlang.org/docs/handbook/declaration-files/publishing.html#including-declarations-in-your-npm-package +[ts-types]: + https://www.typescriptlang.org/docs/handbook/declaration-files/publishing.html#including-declarations-in-your-npm-package ### Package-level API Stability -The [`.jsii` assembly document](./assembly.md) allows representing API stability -levels on individual API elements. The default value set for API elements for -which a stability declaration is not found can be configured using the -`stability` field of the `package.json` file. It can be set to one of the -following values: `experimental`, `stable`, `deprecated` and `external`. While -the exact semantic value of those fields is defined by the package maintainer, -the generic interpretation for those on packages is: - -* `experimental` - the package is not yet ready for production usage, as it is - still in the early stages of its development. -* `stable` - the package is ready for production and its APIs should be - expected to adhere to [semantic versioning]. -* `deprecated` - the package should no longer be used and may no longer be - maintained. It is a good practice to set the `deprecated` field in - `package.json` with an explanation of how consumers of the package should - update their dependencies. -* `external` - the package includes APIs that are derived from external - artifacts, and the owners of those artifacts control their stability. - +The [`.jsii` assembly document](./assembly.md) allows representing API stability levels on individual API elements. The +default value set for API elements for which a stability declaration is not found can be configured using the +`stability` field of the `package.json` file. It can be set to one of the following values: `experimental`, `stable`, +`deprecated` and `external`. While the exact semantic value of those fields is defined by the package maintainer, the +generic interpretation for those on packages is: + +- `experimental` - the package is not yet ready for production usage, as it is still in the early stages of its + development. +- `stable` - the package is ready for production and its APIs should be expected to adhere to [semantic versioning]. +- `deprecated` - the package should no longer be used and may no longer be maintained. It is a good practice to set the + `deprecated` field in `package.json` with an explanation of how consumers of the package should update their + dependencies. +- `external` - the package includes APIs that are derived from external artifacts, and the owners of those artifacts + control their stability. ## The `jsii` section -In order to configure the behavior of `jsii`, the `package.json` file must -include a `jsii` section that can contain the following entries: +In order to configure the behavior of `jsii`, the `package.json` file must include a `jsii` section that can contain the +following entries: -Field | Type | Required | Default --------------------|------------|----------|------------------------------------ -`excludeTypescript`|`string[]` | | *none* -`metadata` |`object` | | *none* -`projectReferences`|`boolean` | | `true` -`targets` |`object` | Required | -`tsc` |`object` | | `{ outDir: '.', rootDir: '.' }` -`versionFormat` |`short|full`| | `full` +| Field | Type | Required | Default | +| ------------------- | ---------- | -------- | ------------------------------- | +| `excludeTypescript` | `string[]` | | _none_ | +| `metadata` | `object` | | _none_ | +| `projectReferences` | `boolean` | | `true` | +| `targets` | `object` | Required | +| `tsc` | `object` | | `{ outDir: '.', rootDir: '.' }` | +| `versionFormat` | `short | full` | | `full` | ### `excludeTypescript` -By default, `jsii` will include _all_ `*.ts` files (except `.d.ts` files) in the -`TypeScript` compiler input. This can be problematic for example when the -package's build or test procedure generates `.ts` files that cannot be compiled -with `jsii`'s compiler settings. +By default, `jsii` will include _all_ `*.ts` files (except `.d.ts` files) in the `TypeScript` compiler input. This can +be problematic for example when the package's build or test procedure generates `.ts` files that cannot be compiled with +`jsii`'s compiler settings. -The `excludeTypescript` configuration accepts a list of glob patterns. Files -matching any of those patterns will be excluded from the `TypeScript` compiler -input. +The `excludeTypescript` configuration accepts a list of glob patterns. Files matching any of those patterns will be +excluded from the `TypeScript` compiler input. ### `metadata` -The `metadata` section can be used to record additional metadata as key-value -pairs that will be recorded as-is into the `.jsii` assembly file. That metadata -can later be inspected using [`jsii-reflect`](../packages/jsii-reflect) -utilities, for example. +The `metadata` section can be used to record additional metadata as key-value pairs that will be recorded as-is into the +`.jsii` assembly file. That metadata can later be inspected using [`jsii-reflect`](../packages/jsii-reflect) utilities, +for example. ### `targets` -The `targets` section is where `jsii` packages define which target languages -they support. This provides the package generators with the additional -information they require in order to name generated artifacts. Configuration is -provided as a mapping from target name to a configuration object. +The `targets` section is where `jsii` packages define which target languages they support. This provides the package +generators with the additional information they require in order to name generated artifacts. Configuration is provided +as a mapping from target name to a configuration object. #### Configuring `Python` The `python` target requires two configuration entries: -* `module` - the name of the generated **Python** module, which will be used by - users in `import` directives. -* `distName` - the [PyPI] distribution name for the package. -* `classifiers` - a list of [trove classifiers] to declare on the package. It is - the user's responsibility to specify *valid* values (the authoritative list of - valid [trove classifiers] is mastered in the [pypa/trove-classifiers] package). - * Some classifiers are automatically included (and should not be added to the - `classifiers` property) based on relevant configuration from the - `package.json` file: - * `Development Status :: ` is determined based on the package's `stability` - * `License ::` is determined based on the package's `license` - * `Operating System :: OS Independent` is always set - * `Typing :: Typed` is always set - * Additionally, the following `Programming Language ::` classifiers are - already set (more could be added by the user if relevant): - * `Programming Language :: Python :: 3 :: Only` - * `Programming Language :: Python :: 3.6` - * `Programming Language :: Python :: 3.7` - * `Programming Language :: Python :: 3.8` + +- `module` - the name of the generated **Python** module, which will be used by users in `import` directives. +- `distName` - the [PyPI] distribution name for the package. +- `classifiers` - a list of [trove classifiers] to declare on the package. It is the user's responsibility to specify + _valid_ values (the authoritative list of valid [trove classifiers] is mastered in the [pypa/trove-classifiers] + package). + - Some classifiers are automatically included (and should not be added to the `classifiers` property) based on + relevant configuration from the `package.json` file: + - `Development Status :: ` is determined based on the package's `stability` + - `License ::` is determined based on the package's `license` + - `Operating System :: OS Independent` is always set + - `Typing :: Typed` is always set + - Additionally, the following `Programming Language ::` classifiers are already set (more could be added by the user + if relevant): + - `Programming Language :: Python :: 3 :: Only` + - `Programming Language :: Python :: 3.6` + - `Programming Language :: Python :: 3.7` + - `Programming Language :: Python :: 3.8` Example: + ```js { "jsii": { @@ -194,21 +180,40 @@ Example: The resulting package can be published to [PyPI]. -[PyPI]: https://pypi.org/ +[pypi]: https://pypi.org/ [trove classifiers]: https://www.python.org/dev/peps/pep-0301/#distutils-trove-classification [pypa/trove-classifiers]: https://github.com/pypa/trove-classifiers +##### Prerelease Versions + +The original `npm` package may feature a version number that includes a [SemVer 2.0][semver]-compliant prerelease +identifer (e.g: `1.2.3-pre.4`). Python packages distributed to [PyPI] must however use a different format to express +prerelease versions, as specified in [PEP-440]. In order to generate valid packages, only certain prerelease identifiers +are accepted by `jsii-pacmak`, and are translated according to the following table: + +| Source Version (`npm`) | Python Version ([PEP-440]) | Notes | +| ---------------------- | -------------------------- | -------------------------------------- | +| `X.Y.Z.dev.N` | `X.Y.Z.devN` | Development, iteration `N`. | +| `X.Y.Z.pre.N` | `X.Y.Z.devN` | Development, iteration `N` | +| `X.Y.Z.alpha.N` | `X.Y.Z.aN` | Alpha release, iteration `N` | +| `X.Y.Z.beta.N` | `X.Y.Z.bN` | Beta release, iteration `N` | +| `X.Y.Z.rc.N` | `X.Y.Z.rcN` | Release candidate, iteration `N` | +| `X.Y.Z.prN.M` | `X.Y.Z.postN.devM` | Post-release number `N`, iteration `M` | + +[semver]: https://semver.org/spec/v2.0.0.html +[pep-440]: https://www.python.org/dev/peps/pep-0440/#pre-releases + #### Configuring `Java` The `java` target requires the following configuration: -* `maven` - the `groupId` and `artifactId` for the **Maven** package. - + Optionally a `versionSuffix` can be provided that will be appended at the - end of the **Maven** package's `version` field. The suffix must start with - a `.` or a `-`. -* `package` - the root **Java** package name under which the types will be - declared. + +- `maven` - the `groupId` and `artifactId` for the **Maven** package. + - Optionally a `versionSuffix` can be provided that will be appended at the end of the **Maven** package's `version` + field. The suffix must start with a `.` or a `-`. +- `package` - the root **Java** package name under which the types will be declared. Example: + ```js { "jsii": { @@ -226,30 +231,28 @@ Example: } ``` -The resulting artifact is a **Maven** package that can be deployed to -[Maven Central] using the `deploy-staged-repository` command of the -[nexus-staging-maven-plugin]. +The resulting artifact is a **Maven** package that can be deployed to [Maven Central] using the +`deploy-staged-repository` command of the [nexus-staging-maven-plugin]. -[Maven Centra]: https://search.maven.org +[maven centra]: https://search.maven.org [nexus-staging-maven-plugin]: https://mvnrepository.com/artifact/org.sonatype.plugins/nexus-staging-maven-plugin #### Configuring `.NET` The `dotnet` target requires the following configuration: -* `namespace` - the root namespace under which types will be declared. -* `packageId` - the identified of the package in the NuGet registry. -* `iconUrl` - the URL of the icon to be shown in the [NuGet Gallery][NuGet]. It - should be at least 64x64 pixels and a transparent background is recommended. - See the [.NET documentation] for more information. -* `versionSuffix` - an optional suffix that will be appended at the end of the - NuGet package's `version` field. The suffix must start with a `-`. -* `signAssembly` - whether the assembly should be strong-name signed. Defaults - to `false` when not specified. -* `assemblyOriginatorKeyFile`- the path to the strong-name signing key to be - used. When not specified or if the file referred to does not exist, the - assembly will not be strong-name signed. + +- `namespace` - the root namespace under which types will be declared. +- `packageId` - the identified of the package in the NuGet registry. +- `iconUrl` - the URL of the icon to be shown in the [NuGet Gallery][nuget]. It should be at least 64x64 pixels and a + transparent background is recommended. See the [.NET documentation] for more information. +- `versionSuffix` - an optional suffix that will be appended at the end of the NuGet package's `version` field. The + suffix must start with a `-`. +- `signAssembly` - whether the assembly should be strong-name signed. Defaults to `false` when not specified. +- `assemblyOriginatorKeyFile`- the path to the strong-name signing key to be used. When not specified or if the file + referred to does not exist, the assembly will not be strong-name signed. Example: + ```js { "jsii": { @@ -267,21 +270,19 @@ Example: } ``` -The resulting artifact is a NuGet package that can be published to [NuGet] using -the standard [`nuget push`][nuget-push] command. +The resulting artifact is a NuGet package that can be published to [NuGet] using the standard [`nuget push`][nuget-push] +command. -[NuGet]: https://www.nuget.org +[nuget]: https://www.nuget.org [nuget-push]: https://docs.microsoft.com/fr-fr/nuget/nuget-org/publish-a-package -[.NET documentation]: https://docs.microsoft.com/en-us/dotnet/core/tools/csproj#packageiconurl +[.net documentation]: https://docs.microsoft.com/en-us/dotnet/core/tools/csproj#packageiconurl #### Configuring `GoLang` - **Experimental** -The `go` target is currently unstable and not suitable for production use. To -enable go package generation, add the `go` key with an empty object to the jsii -targets configuration. +The `go` target is currently unstable and not suitable for production use. To enable go package generation, add the `go` +key with an empty object to the jsii targets configuration. -This will add generated go package code to your specified `outDir` for testing -and experimentation. +This will add generated go package code to your specified `outDir` for testing and experimentation. ```js { @@ -298,69 +299,59 @@ and experimentation. ### `tsc` -In order to the generated `javascript` can be properly loaded by the `jsii` -runtimes, `jsii` generates a [`tsconfig.json`] file with fixed settings at the -beginning of the compilation pass. Certain configuration options can however -be set by the maintainers in order to better suit their development workflow -or processes. Those configuration are set in the `jsii.tsc` section of the -`package.json` file, but use the same name as [`tsconfig.json`]: - -* `outDir` - path to the directory when artifacts generated by the `TypeScript` - compiler will be placed. - * This influences the location of `.d.ts` and `.js` files, but will not affect - the location of the `.jsii` file, which will _always_ be placed at the - package's root. -* `rootDir` - specifies the root directory that contains all of the `.ts` source - files. This is used in conjunction with `outDir`, to control the directory - structure that gets generated. - -Refer to the [TypeScript compiler options reference][ts-options] for more -information about those options. +In order to the generated `javascript` can be properly loaded by the `jsii` runtimes, `jsii` generates a +[`tsconfig.json`] file with fixed settings at the beginning of the compilation pass. Certain configuration options can +however be set by the maintainers in order to better suit their development workflow or processes. Those configuration +are set in the `jsii.tsc` section of the `package.json` file, but use the same name as [`tsconfig.json`]: + +- `outDir` - path to the directory when artifacts generated by the `TypeScript` compiler will be placed. + - This influences the location of `.d.ts` and `.js` files, but will not affect the location of the `.jsii` file, which + will _always_ be placed at the package's root. +- `rootDir` - specifies the root directory that contains all of the `.ts` source files. This is used in conjunction with + `outDir`, to control the directory structure that gets generated. + +Refer to the [TypeScript compiler options reference][ts-options] for more information about those options. [`tsconfig.json`]: https://www.typescriptlang.org/docs/handbook/tsconfig-json.html [ts-options]: https://www.typescriptlang.org/docs/handbook/compiler-options.html ### `versionFormat` -Determines the format of the `jsii` toolchain version string that will be -included in the `.jsii` assembly file's `jsiiVersion` attribute. +Determines the format of the `jsii` toolchain version string that will be included in the `.jsii` assembly file's +`jsiiVersion` attribute. -* `full` (the default) - a version number including a commit hash will be used - * For example: `0.14.3 (build 1b1062d)` -* `short` - only the version number of `jsii` will be used - * For example: `0.14.3` +- `full` (the default) - a version number including a commit hash will be used + - For example: `0.14.3 (build 1b1062d)` +- `short` - only the version number of `jsii` will be used + - For example: `0.14.3` -This option is primarily useful for developing regression tests when developing -`jsii` itself, as using the `short` format reduces volatility in the assemblies -generated by development versions of `jsii`. Users of `jsii` are advised to -leave the default setting, as having full version information can be essential -when trying to troubleshoot assembly generation problems. +This option is primarily useful for developing regression tests when developing `jsii` itself, as using the `short` +format reduces volatility in the assemblies generated by development versions of `jsii`. Users of `jsii` are advised to +leave the default setting, as having full version information can be essential when trying to troubleshoot assembly +generation problems. ## Dependency considerations -Like any node library, `jsii` packages can declare runtime dependencies using -the [`dependencies`][npm-reps] section of `package.json`. +Like any node library, `jsii` packages can declare runtime dependencies using the [`dependencies`][npm-reps] section of +`package.json`. [npm-deps]: https://docs.npmjs.com/files/package.json#dependencies ### Dependencies that are `jsii` modules -Node modules are conventionally versioned using [semantic versioning], but that -is not true of all package managers that `jsii` is able to target. Additionally, -only one version of the `jsii` runtime and kernel can be used within a given -application. In order to avoid version resolution surprises at run-time, `jsii` -requires duplicating `jsii` modules declarations from [`dependencies`][npm-deps] -into the [`peerDependencies`][npm-peer-deps] section. +Node modules are conventionally versioned using [semantic versioning], but that is not true of all package managers that +`jsii` is able to target. Additionally, only one version of the `jsii` runtime and kernel can be used within a given +application. In order to avoid version resolution surprises at run-time, `jsii` requires duplicating `jsii` modules +declarations from [`dependencies`][npm-deps] into the [`peerDependencies`][npm-peer-deps] section. [npm-peer-deps]: https://docs.npmjs.com/files/package.json#peerdependencies [semantic versioning]: https://semver.org ### Dependencies that are not `jsii` modules -The `jsii` runtimes in non-**javascript** languages do not use `npm install`, -and as a consequence cannot rely on `npm install` bringing in a package's -dependencies. As a consequence, dependencies that are not themselves `jsii` -modules, __must__ also be referenced in the [`bundledDependencies`][npm-bundled] -section, so that they are bundled within the NPM package. +The `jsii` runtimes in non-**javascript** languages do not use `npm install`, and as a consequence cannot rely on +`npm install` bringing in a package's dependencies. As a consequence, dependencies that are not themselves `jsii` +modules, **must** also be referenced in the [`bundledDependencies`][npm-bundled] section, so that they are bundled +within the NPM package. [npm-bundled]: https://docs.npmjs.com/files/package.json#bundleddependencies From f623d7e03e694b209289a61ea29272980c0f55d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=91=A8=F0=9F=8F=BC=E2=80=8D=F0=9F=92=BB=20Romain=20M?= =?UTF-8?q?arcadier-Muller?= Date: Tue, 27 Oct 2020 13:06:52 +0100 Subject: [PATCH 10/16] fix linter offense --- packages/jsii-pacmak/lib/targets/java.ts | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/packages/jsii-pacmak/lib/targets/java.ts b/packages/jsii-pacmak/lib/targets/java.ts index b764dfc433..6d53e807a7 100644 --- a/packages/jsii-pacmak/lib/targets/java.ts +++ b/packages/jsii-pacmak/lib/targets/java.ts @@ -2748,11 +2748,10 @@ class JavaGenerator extends Generator { return this.getNativeName(depMod, name.join('.'), mod); } - const { packageName, typeName } = this.toNativeName( - this.assembly, - // It's okay for this parameter to be `undefined` (there is an overload for that): - this.assembly.types?.[fqn]!, - ); + const { packageName, typeName } = + fqn === this.assembly.name + ? this.toNativeName(this.assembly) + : this.toNativeName(this.assembly, this.assembly.types![fqn]); const className = typeName && binaryName ? typeName.replace('.', '$') : typeName; return `${packageName}${className ? `.${className}` : ''}`; @@ -2773,7 +2772,9 @@ class JavaGenerator extends Generator { return `${javaPackage}${tail ? `.${tail}` : ''}`; } - private toNativeName(assm: spec.Assembly): { packageName: string }; + private toNativeName( + assm: spec.Assembly, + ): { packageName: string; typeName: undefined }; private toNativeName( assm: spec.Assembly, type: spec.Type, From eafcaf06e46789929886cfa33fc0bd2c6bbd4820 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=91=A8=F0=9F=8F=BC=E2=80=8D=F0=9F=92=BB=20Romain=20M?= =?UTF-8?q?arcadier-Muller?= Date: Tue, 27 Oct 2020 14:07:22 +0100 Subject: [PATCH 11/16] stop using mock-fs, it apparently has unstable compatibility with jest (who also replaces 'fs' for it's own needs) --- packages/jsii-pacmak/package.json | 2 - packages/jsii-pacmak/test/npm-modules.test.ts | 107 ++++++++++-------- 2 files changed, 61 insertions(+), 48 deletions(-) diff --git a/packages/jsii-pacmak/package.json b/packages/jsii-pacmak/package.json index 8dbc1ea270..3748e2de3b 100644 --- a/packages/jsii-pacmak/package.json +++ b/packages/jsii-pacmak/package.json @@ -58,7 +58,6 @@ "@types/commonmark": "^0.27.4", "@types/fs-extra": "^8.1.1", "@types/jest": "^26.0.15", - "@types/mock-fs": "^4.13.0", "@types/node": "^10.17.42", "@types/semver": "^7.3.4", "@types/yargs": "^15.0.9", @@ -66,7 +65,6 @@ "jest": "^26.6.1", "jsii-build-tools": "^0.0.0", "jsii-calc": "^0.0.0", - "mock-fs": "^4.13.0", "prettier": "^2.1.2", "ts-jest": "^26.4.2", "typescript": "~3.9.7" diff --git a/packages/jsii-pacmak/test/npm-modules.test.ts b/packages/jsii-pacmak/test/npm-modules.test.ts index a60d51af26..7cbccc227b 100644 --- a/packages/jsii-pacmak/test/npm-modules.test.ts +++ b/packages/jsii-pacmak/test/npm-modules.test.ts @@ -1,68 +1,83 @@ -import * as mockfs from 'mock-fs'; +import { mkdirp, mkdtemp, remove, writeJson } from 'fs-extra'; +import { tmpdir } from 'os'; +import { join } from 'path'; import { findJsiiModules } from '../lib/npm-modules'; describe(findJsiiModules, () => { - afterEach((done) => { - mockfs.restore(); - done(); - }); + let workDir = tmpdir(); + + beforeEach(() => + mkdtemp(join(tmpdir(), 'jsii-pacmak.npm-modules.test.')).then((dir) => { + workDir = dir; + }), + ); - // Increase the timeout - those are crazy slow on CI/CI for some reason. - jest.setTimeout(30_000); + afterEach(async () => { + // Be extra cautious to avoid deleting this we shouldn't delete... + if (workDir !== tmpdir()) { + await remove(workDir); + } + }); test('is sorted topologically', async () => { - mockfs({ - '/packageA/package.json': JSON.stringify({ - name: 'packageA', - jsii: { - outdir: 'dist', - targets: { - python: {}, - }, + await mkdirp(join(workDir, 'packageA')); + await writeJson(join(workDir, 'packageA', 'package.json'), { + name: 'packageA', + jsii: { + outdir: 'dist', + targets: { + python: {}, }, - dependencies: { - packageB: '*', - }, - }), - '/packageB/package.json': JSON.stringify({ - name: 'packageB', - jsii: { - outdir: 'dist', - targets: { - python: {}, - }, + }, + dependencies: { + packageB: '*', + }, + }); + await mkdirp(join(workDir, 'packageB')); + await writeJson(join(workDir, 'packageB', 'package.json'), { + name: 'packageB', + jsii: { + outdir: 'dist', + targets: { + python: {}, }, - }), + }, }); - const mods = await findJsiiModules(['/packageA', '/packageB'], false); + const mods = await findJsiiModules( + [join(workDir, 'packageA'), join(workDir, 'packageB')], + false, + ); expect(mods.map((m) => m.name)).toEqual(['packageB', 'packageA']); }); test('without deps loads packages in given order', async () => { - mockfs({ - '/packageA/package.json': JSON.stringify({ - name: 'packageA', - jsii: { - outdir: 'dist', - targets: { - python: {}, - }, + await mkdirp(join(workDir, 'packageA')); + await writeJson(join(workDir, 'packageA', 'package.json'), { + name: 'packageA', + jsii: { + outdir: 'dist', + targets: { + python: {}, }, - }), - '/packageB/package.json': JSON.stringify({ - name: 'packageB', - jsii: { - outdir: 'dist', - targets: { - python: {}, - }, + }, + }); + await mkdirp(join(workDir, 'packageB')); + await writeJson(join(workDir, 'packageB', 'package.json'), { + name: 'packageB', + jsii: { + outdir: 'dist', + targets: { + python: {}, }, - }), + }, }); - const mods = await findJsiiModules(['/packageA', '/packageB'], false); + const mods = await findJsiiModules( + [join(workDir, 'packageA'), join(workDir, 'packageB')], + false, + ); expect(mods.map((m) => m.name)).toEqual(['packageA', 'packageB']); }); }); From 650e93171626fa72c3bc2b9fc4779bc7e0acb2ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=91=A8=F0=9F=8F=BC=E2=80=8D=F0=9F=92=BB=20Romain=20M?= =?UTF-8?q?arcadier-Muller?= Date: Wed, 28 Oct 2020 13:17:22 +0100 Subject: [PATCH 12/16] pr feedback from @nija-at --- docs/configuration.md | 16 +++++++------- packages/jsii-pacmak/lib/targets/js.ts | 22 ++++++++----------- .../jsii-pacmak/lib/targets/version-utils.ts | 15 ++++++++----- .../test/targets/version-utils.test.ts | 9 +++++++- 4 files changed, 35 insertions(+), 27 deletions(-) diff --git a/docs/configuration.md b/docs/configuration.md index a8b425b22d..ee13b409bb 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -191,14 +191,14 @@ identifer (e.g: `1.2.3-pre.4`). Python packages distributed to [PyPI] must howev prerelease versions, as specified in [PEP-440]. In order to generate valid packages, only certain prerelease identifiers are accepted by `jsii-pacmak`, and are translated according to the following table: -| Source Version (`npm`) | Python Version ([PEP-440]) | Notes | -| ---------------------- | -------------------------- | -------------------------------------- | -| `X.Y.Z.dev.N` | `X.Y.Z.devN` | Development, iteration `N`. | -| `X.Y.Z.pre.N` | `X.Y.Z.devN` | Development, iteration `N` | -| `X.Y.Z.alpha.N` | `X.Y.Z.aN` | Alpha release, iteration `N` | -| `X.Y.Z.beta.N` | `X.Y.Z.bN` | Beta release, iteration `N` | -| `X.Y.Z.rc.N` | `X.Y.Z.rcN` | Release candidate, iteration `N` | -| `X.Y.Z.prN.M` | `X.Y.Z.postN.devM` | Post-release number `N`, iteration `M` | +| Source Version (`npm`) | Python Version ([PEP-440]) | Notes | +| ---------------------- | -------------------------- | -------------------------------- | +| `X.Y.Z.dev.N` | `X.Y.Z.devN` | Development, iteration `N`. | +| `X.Y.Z.prN.0` | `X.Y.Z.devM` | Development, iteration `N` | +| `X.Y.Z.pre.N` | `X.Y.Z.devN` | Development, iteration `N` | +| `X.Y.Z.alpha.N` | `X.Y.Z.aN` | Alpha release, iteration `N` | +| `X.Y.Z.beta.N` | `X.Y.Z.bN` | Beta release, iteration `N` | +| `X.Y.Z.rc.N` | `X.Y.Z.rcN` | Release candidate, iteration `N` | [semver]: https://semver.org/spec/v2.0.0.html [pep-440]: https://www.python.org/dev/peps/pep-0440/#pre-releases diff --git a/packages/jsii-pacmak/lib/targets/js.ts b/packages/jsii-pacmak/lib/targets/js.ts index 82897d56af..3de5d49d0c 100644 --- a/packages/jsii-pacmak/lib/targets/js.ts +++ b/packages/jsii-pacmak/lib/targets/js.ts @@ -10,30 +10,26 @@ export default class JavaScript extends Target { public static toPackageInfos( assm: spec.Assembly, ): { [language: string]: PackageInfo } { + const releaseVersion = toReleaseVersion( + assm.version, + TargetName.JAVASCRIPT, + ); + const packageInfo: PackageInfo = { repository: 'NPM', - url: `https://www.npmjs.com/package/${assm.name}/v/${toReleaseVersion( - assm.version, - TargetName.JAVASCRIPT, - )}`, + url: `https://www.npmjs.com/package/${assm.name}/v/${releaseVersion}`, usage: { 'package.json': { language: 'js', - code: JSON.stringify({ [assm.name]: `^${assm.version}` }, null, 2), + code: JSON.stringify({ [assm.name]: `^${releaseVersion}` }, null, 2), }, npm: { language: 'console', - code: `$ npm i ${assm.name}@${toReleaseVersion( - assm.version, - TargetName.JAVASCRIPT, - )}`, + code: `$ npm i ${assm.name}@${releaseVersion}`, }, yarn: { language: 'console', - code: `$ yarn add ${assm.name}@${toReleaseVersion( - assm.version, - TargetName.JAVASCRIPT, - )}`, + code: `$ yarn add ${assm.name}@${releaseVersion}`, }, }, }; diff --git a/packages/jsii-pacmak/lib/targets/version-utils.ts b/packages/jsii-pacmak/lib/targets/version-utils.ts index 3cb10e082a..e902b4b55c 100644 --- a/packages/jsii-pacmak/lib/targets/version-utils.ts +++ b/packages/jsii-pacmak/lib/targets/version-utils.ts @@ -100,7 +100,7 @@ export function toReleaseVersion( throw new Error( `Unable to map prerelease identifier (in: ${assemblyVersion}) components to python: ${inspect( version.prerelease, - )}. The format should be 'X.Y.Z-label.sequence', where sequence is a positive integer, and label is "pr####", "dev", "pre", "alpha", beta", or "rc"`, + )}. The format should be 'X.Y.Z-label.sequence', where sequence is a positive integer, and label is "pr####.0", "dev", "pre", "alpha", beta", or "rc"`, ); } if (!Number.isInteger(sequence)) { @@ -111,6 +111,7 @@ export function toReleaseVersion( ); } const baseVersion = `${version.major}.${version.minor}.${version.patch}`; + // See PEP 440: https://www.python.org/dev/peps/pep-0440/#pre-releases switch (label) { case 'dev': case 'pre': @@ -123,13 +124,17 @@ export function toReleaseVersion( return `${baseVersion}.rc${sequence}`; default: // We emit `-pr${pull_request_id}.0` - if (typeof label === 'string' && /^pr\d+$/.test(label)) { - return `${baseVersion}.post${label.substr(2)}.dev${sequence}`; + if ( + typeof label === 'string' && + /^pr\d+$/.test(label) && + sequence === 0 + ) { + return `${baseVersion}.dev${label.substr(2)}`; } throw new Error( - `Unable to map prerelease identifier (in: ${assemblyVersion}) to python, as label ${inspect( + `Unable to map prerelease identifier (in: ${assemblyVersion}) to python, as label ${inspect( label, - )} is not mapped (only "pr####", "dev", "pre", "alpha", "beta" and "rc" are)`, + )} is not mapped (only "pr####.0", "dev", "pre", "alpha", "beta" and "rc" are)`, ); } case TargetName.DOTNET: diff --git a/packages/jsii-pacmak/test/targets/version-utils.test.ts b/packages/jsii-pacmak/test/targets/version-utils.test.ts index f6037d09e0..1594eee6cb 100644 --- a/packages/jsii-pacmak/test/targets/version-utils.test.ts +++ b/packages/jsii-pacmak/test/targets/version-utils.test.ts @@ -148,7 +148,14 @@ describe(toReleaseVersion, () => { go: '1.2.3-pr4567.8', java: '1.2.3-pr4567.8', js: '1.2.3-pr4567.8', - python: '1.2.3.post4567.dev8', + python: /Unable to map prerelease identifier \(in: 1\.2\.3-pr4567\.8\) to python, as label 'pr4567' is not mapped/, + }, + '1.2.3-pr4567.0': { + dotnet: '1.2.3-pr4567.0', + go: '1.2.3-pr4567.0', + java: '1.2.3-pr4567.0', + js: '1.2.3-pr4567.0', + python: '1.2.3.dev4567', }, }; From 929b709e557dc280349685adc64fa16cb44240f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=91=A8=F0=9F=8F=BC=E2=80=8D=F0=9F=92=BB=20Romain=20M?= =?UTF-8?q?arcadier-Muller?= Date: Wed, 28 Oct 2020 13:46:03 +0100 Subject: [PATCH 13/16] fixup test expectations I had forgotten to touch --- .../__snapshots__/prerelease-identifiers.test.ts.snap | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/jsii-pacmak/test/generated-code/__snapshots__/prerelease-identifiers.test.ts.snap b/packages/jsii-pacmak/test/generated-code/__snapshots__/prerelease-identifiers.test.ts.snap index 959135d8a4..d2fcf9098a 100644 --- a/packages/jsii-pacmak/test/generated-code/__snapshots__/prerelease-identifiers.test.ts.snap +++ b/packages/jsii-pacmak/test/generated-code/__snapshots__/prerelease-identifiers.test.ts.snap @@ -385,7 +385,7 @@ kwargs = json.loads( """ { "name": "foo", - "version": "0.0.0.post1234.dev0", + "version": "0.0.0.dev1234", "description": "Test assembly: foo", "license": "UNLICENSED", "url": "https://test.nope/foo", @@ -890,7 +890,7 @@ kwargs = json.loads( }, "python_requires": ">=3.6", "install_requires": [ - "bar>=0.0.0.post1234.dev0, <0.0.1", + "bar>=0.0.0.dev1234, <0.0.1", "jsii>=1337.42.1337, <1338.0.0", "publication>=0.0.3" ], From d5398d661613887fca7cc39f9d29fedf27d4719d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=91=A8=F0=9F=8F=BC=E2=80=8D=F0=9F=92=BB=20Romain=20M?= =?UTF-8?q?arcadier-Muller?= Date: Wed, 28 Oct 2020 16:09:13 +0100 Subject: [PATCH 14/16] pull .prN mapping --- docs/configuration.md | 1 - .../jsii-pacmak/lib/targets/version-utils.ts | 12 +- .../prerelease-identifiers.test.ts.snap | 943 ------------------ .../prerelease-identifiers.test.ts | 2 +- .../test/targets/version-utils.test.ts | 14 - 5 files changed, 3 insertions(+), 969 deletions(-) diff --git a/docs/configuration.md b/docs/configuration.md index ee13b409bb..c6cb330b3a 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -194,7 +194,6 @@ are accepted by `jsii-pacmak`, and are translated according to the following tab | Source Version (`npm`) | Python Version ([PEP-440]) | Notes | | ---------------------- | -------------------------- | -------------------------------- | | `X.Y.Z.dev.N` | `X.Y.Z.devN` | Development, iteration `N`. | -| `X.Y.Z.prN.0` | `X.Y.Z.devM` | Development, iteration `N` | | `X.Y.Z.pre.N` | `X.Y.Z.devN` | Development, iteration `N` | | `X.Y.Z.alpha.N` | `X.Y.Z.aN` | Alpha release, iteration `N` | | `X.Y.Z.beta.N` | `X.Y.Z.bN` | Beta release, iteration `N` | diff --git a/packages/jsii-pacmak/lib/targets/version-utils.ts b/packages/jsii-pacmak/lib/targets/version-utils.ts index e902b4b55c..ff38328fb6 100644 --- a/packages/jsii-pacmak/lib/targets/version-utils.ts +++ b/packages/jsii-pacmak/lib/targets/version-utils.ts @@ -100,7 +100,7 @@ export function toReleaseVersion( throw new Error( `Unable to map prerelease identifier (in: ${assemblyVersion}) components to python: ${inspect( version.prerelease, - )}. The format should be 'X.Y.Z-label.sequence', where sequence is a positive integer, and label is "pr####.0", "dev", "pre", "alpha", beta", or "rc"`, + )}. The format should be 'X.Y.Z-label.sequence', where sequence is a positive integer, and label is "dev", "pre", "alpha", beta", or "rc"`, ); } if (!Number.isInteger(sequence)) { @@ -123,18 +123,10 @@ export function toReleaseVersion( case 'rc': return `${baseVersion}.rc${sequence}`; default: - // We emit `-pr${pull_request_id}.0` - if ( - typeof label === 'string' && - /^pr\d+$/.test(label) && - sequence === 0 - ) { - return `${baseVersion}.dev${label.substr(2)}`; - } throw new Error( `Unable to map prerelease identifier (in: ${assemblyVersion}) to python, as label ${inspect( label, - )} is not mapped (only "pr####.0", "dev", "pre", "alpha", "beta" and "rc" are)`, + )} is not mapped (only "dev", "pre", "alpha", "beta" and "rc" are)`, ); } case TargetName.DOTNET: diff --git a/packages/jsii-pacmak/test/generated-code/__snapshots__/prerelease-identifiers.test.ts.snap b/packages/jsii-pacmak/test/generated-code/__snapshots__/prerelease-identifiers.test.ts.snap index d2fcf9098a..f1764d09b9 100644 --- a/packages/jsii-pacmak/test/generated-code/__snapshots__/prerelease-identifiers.test.ts.snap +++ b/packages/jsii-pacmak/test/generated-code/__snapshots__/prerelease-identifiers.test.ts.snap @@ -1,948 +1,5 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`foo@0.0.0-pr1234.0: / 1`] = ` - - ┣━ 📁 dotnet - ┃ ┗━ 📁 Com.Acme.Foo - ┃ ┣━ 📄 AssemblyInfo.cs - ┃ ┣━ 📁 Com - ┃ ┃ ┗━ 📁 Acme - ┃ ┃ ┗━ 📁 Foo - ┃ ┃ ┗━ 📁 Internal - ┃ ┃ ┗━ 📁 DependencyResolution - ┃ ┃ ┗━ 📄 Anchor.cs - ┃ ┣━ 📄 Com.Acme.Foo.csproj - ┃ ┗━ 📄 foo-0.0.0-pr1234.0.tgz - ┣━ 📁 go - ┃ ┗━ 📁 foo - ┃ ┣━ 📄 foo.go - ┃ ┗━ 📁 jsii - ┃ ┣━ 📄 jsii.go - ┃ ┗━ 📄 tarball.embedded.go - ┣━ 📁 java - ┃ ┣━ 📄 pom.xml - ┃ ┗━ 📁 src - ┃ ┗━ 📁 main - ┃ ┣━ 📁 java - ┃ ┃ ┗━ 📁 com - ┃ ┃ ┗━ 📁 acme - ┃ ┃ ┗━ 📁 foo - ┃ ┃ ┗━ 📄 $Module.java - ┃ ┗━ 📁 resources - ┃ ┗━ 📁 com - ┃ ┗━ 📁 acme - ┃ ┗━ 📁 foo - ┃ ┣━ 📄 $Module.txt - ┃ ┗━ 📄 foo@0.0.0-pr1234.0.jsii.tgz - ┣━ 📁 js - ┃ ┗━ 📄 foo@0.0.0-pr1234.0.jsii.tgz - ┗━ 📁 python - ┣━ 📄 MANIFEST.in - ┣━ 📄 pyproject.toml - ┣━ 📄 README.md - ┣━ 📄 setup.py - ┗━ 📁 src - ┗━ 📁 foo - ┗━ 📁 _jsii - ┣━ 📄 __init__.py - ┗━ 📄 foo@0.0.0-pr1234.0.jsii.tgz -`; - -exports[`foo@0.0.0-pr1234.0: /dotnet/Com.Acme.Foo/AssemblyInfo.cs 1`] = ` -using Amazon.JSII.Runtime.Deputy; - -[assembly: JsiiAssembly("foo", "0.0.0-pr1234.0", "foo-0.0.0-pr1234.0.tgz")] - -`; - -exports[`foo@0.0.0-pr1234.0: /dotnet/Com.Acme.Foo/Com.Acme.Foo.csproj 1`] = ` - - - - Test assembly: foo - Com.Acme.Foo - UNLICENSED - 0.0.0-pr1234.0 - - Test - en-US - https://test.nope/foo - foo.nope.git - git - - true - true - true - true - enable - snupkg - netcoreapp3.1 - - - - - - - - - 0612,0618 - - - - -`; - -exports[`foo@0.0.0-pr1234.0: /dotnet/Com.Acme.Foo/Com/Acme/Foo/Internal/DependencyResolution/Anchor.cs 1`] = ` -#pragma warning disable CS0672,CS0809,CS1591 - -namespace Com.Acme.Foo.Internal.DependencyResolution -{ - public sealed class Anchor - { - public Anchor() - { - } - } -} - -`; - -exports[`foo@0.0.0-pr1234.0: /dotnet/Com.Acme.Foo/foo-0.0.0-pr1234.0.tgz 1`] = `dotnet/Com.Acme.Foo/foo-0.0.0-pr1234.0.tgz is a tarball`; - -exports[`foo@0.0.0-pr1234.0: /go/foo/foo.go 1`] = ` -// Test assembly: foo -package foo - -import ( -) - - -`; - -exports[`foo@0.0.0-pr1234.0: /go/foo/jsii/jsii.go 1`] = ` -package jsii - -import ( - rt "github.com/aws-cdk/jsii/jsii-experimental" - "sync" -) - -var once sync.Once - -// Initialize performs the necessary work for the enclosing -// module to be loaded in the jsii kernel. -func Initialize() { - once.Do(func(){ - // Load this library into the kernel - rt.Load("foo", "0.0.0-pr1234.0", tarball) - }) -} - -`; - -exports[`foo@0.0.0-pr1234.0: /go/foo/jsii/tarball.embedded.go 1`] = `go/foo/jsii/tarball.embedded.go embeds a tarball`; - -exports[`foo@0.0.0-pr1234.0: /java/pom.xml 1`] = ` - - - 4.0.0 - \${project.groupId}:\${project.artifactId} - Test assembly: foo - https://test.nope/foo - - - - Test - - test - - - - - scm:git:foo.nope.git - foo.nope.git - - com.acme - foo - 0.0.0-pr1234.0 - jar - - UTF-8 - - - - software.amazon.jsii - jsii-runtime - [0.0.0,0.0.1) - - - org.jetbrains - annotations - [16.0.3,20.0.0) - - - - javax.annotation - javax.annotation-api - [1.3.2,1.4.0) - compile - - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.8.1 - - 1.8 - 1.8 - - - - org.apache.maven.plugins - maven-jar-plugin - 3.2.0 - - - true - - true - true - - - - - - org.apache.maven.plugins - maven-source-plugin - 3.2.1 - - - attach-sources - - jar - - - - - - org.apache.maven.plugins - maven-javadoc-plugin - 3.1.1 - - - attach-javadocs - - jar - - - - - false - protected - - **/$Module.java - - -J-XX:+TieredCompilation - -J-XX:TieredStopAtLevel=1 - - - - org.apache.maven.plugins - maven-enforcer-plugin - 3.0.0-M3 - - - enforce-maven - - enforce - - - - - 3.6 - - - - - - - - org.codehaus.mojo - versions-maven-plugin - 2.7 - - false - - - - - - -`; - -exports[`foo@0.0.0-pr1234.0: /java/src/main/java/com/acme/foo/$Module.java 1`] = ` -package com.acme.foo; - -import java.io.BufferedReader; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.IOException; -import java.io.Reader; -import java.io.UncheckedIOException; - -import java.nio.charset.StandardCharsets; - -import java.util.HashMap; -import java.util.Map; - -import software.amazon.jsii.JsiiModule; - -@software.amazon.jsii.Internal -public final class $Module extends JsiiModule { - private static final Map MODULE_TYPES = load(); - - private static Map load() { - final Map result = new HashMap<>(); - final ClassLoader cl = $Module.class.getClassLoader(); - try (final InputStream is = cl.getResourceAsStream("com/acme/foo/$Module.txt"); - final Reader rd = new InputStreamReader(is, StandardCharsets.UTF_8); - final BufferedReader br = new BufferedReader(rd)) { - br.lines() - .filter(line -> !line.trim().isEmpty()) - .forEach(line -> { - final String[] parts = line.split("=", 2); - final String fqn = parts[0]; - final String className = parts[1]; - result.put(fqn, className); - }); - } - catch (final IOException exception) { - throw new UncheckedIOException(exception); - } - return result; - } - - private final Map> cache = new HashMap<>(); - - public $Module() { - super("foo", "0.0.0-pr1234.0", $Module.class, "foo@0.0.0-pr1234.0.jsii.tgz"); - } - - @Override - protected Class resolveClass(final String fqn) throws ClassNotFoundException { - if (!MODULE_TYPES.containsKey(fqn)) { - throw new ClassNotFoundException("Unknown JSII type: " + fqn); - } - String className = MODULE_TYPES.get(fqn); - if (!this.cache.containsKey(className)) { - this.cache.put(className, this.findClass(className)); - } - return this.cache.get(className); - } - - private Class findClass(final String binaryName) { - try { - return Class.forName(binaryName); - } - catch (final ClassNotFoundException exception) { - throw new RuntimeException(exception); - } - } -} - -`; - -exports[`foo@0.0.0-pr1234.0: /java/src/main/resources/com/acme/foo/$Module.txt 1`] = ``; - -exports[`foo@0.0.0-pr1234.0: /java/src/main/resources/com/acme/foo/foo@0.0.0-pr1234.0.jsii.tgz 1`] = `java/src/main/resources/com/acme/foo/foo@0.0.0-pr1234.0.jsii.tgz is a tarball`; - -exports[`foo@0.0.0-pr1234.0: /js/foo@0.0.0-pr1234.0.jsii.tgz 1`] = `js/foo@0.0.0-pr1234.0.jsii.tgz is a tarball`; - -exports[`foo@0.0.0-pr1234.0: /python/MANIFEST.in 1`] = ` -include pyproject.toml - -`; - -exports[`foo@0.0.0-pr1234.0: /python/README.md 1`] = ` - - -`; - -exports[`foo@0.0.0-pr1234.0: /python/pyproject.toml 1`] = ` -[build-system] -requires = ["setuptools~=49.3", "wheel~=0.34"] -build-backend = "setuptools.build_meta" - -`; - -exports[`foo@0.0.0-pr1234.0: /python/setup.py 1`] = ` -import json -import setuptools - -kwargs = json.loads( - """ -{ - "name": "foo", - "version": "0.0.0.dev1234", - "description": "Test assembly: foo", - "license": "UNLICENSED", - "url": "https://test.nope/foo", - "long_description_content_type": "text/markdown", - "author": "Test", - "bdist_wheel": { - "universal": true - }, - "project_urls": { - "Source": "foo.nope.git" - }, - "package_dir": { - "": "src" - }, - "packages": [ - "foo._jsii" - ], - "package_data": { - "foo._jsii": [ - "foo@0.0.0-pr1234.0.jsii.tgz" - ] - }, - "python_requires": ">=3.6", - "install_requires": [ - "jsii>=1337.42.1337, <1338.0.0", - "publication>=0.0.3" - ], - "classifiers": [ - "Intended Audience :: Developers", - "Operating System :: OS Independent", - "Programming Language :: JavaScript", - "Programming Language :: Python :: 3 :: Only", - "Programming Language :: Python :: 3.6", - "Programming Language :: Python :: 3.7", - "Programming Language :: Python :: 3.8", - "Typing :: Typed" - ] -} -""" -) - -with open("README.md", encoding="utf8") as fp: - kwargs["long_description"] = fp.read() - - -setuptools.setup(**kwargs) - -`; - -exports[`foo@0.0.0-pr1234.0: /python/src/foo/_jsii/__init__.py 1`] = ` -import abc -import builtins -import datetime -import enum -import typing - -import jsii -import publication -import typing_extensions - -__jsii_assembly__ = jsii.JSIIAssembly.load( - "foo", "0.0.0-pr1234.0", __name__[0:-6], "foo@0.0.0-pr1234.0.jsii.tgz" -) - -__all__ = [ - "__jsii_assembly__", -] - -publication.publish() - -`; - -exports[`foo@0.0.0-pr1234.0: /python/src/foo/_jsii/foo@0.0.0-pr1234.0.jsii.tgz 1`] = `python/src/foo/_jsii/foo@0.0.0-pr1234.0.jsii.tgz is a tarball`; - -exports[`foo@1.2.3 depends on bar@^0.0.0-pr1234.0: / 1`] = ` - - ┣━ 📁 dotnet - ┃ ┗━ 📁 Com.Acme.Foo - ┃ ┣━ 📄 AssemblyInfo.cs - ┃ ┣━ 📁 Com - ┃ ┃ ┗━ 📁 Acme - ┃ ┃ ┗━ 📁 Foo - ┃ ┃ ┗━ 📁 Internal - ┃ ┃ ┗━ 📁 DependencyResolution - ┃ ┃ ┗━ 📄 Anchor.cs - ┃ ┣━ 📄 Com.Acme.Foo.csproj - ┃ ┗━ 📄 foo-1.2.3.tgz - ┣━ 📁 go - ┃ ┗━ 📁 foo - ┃ ┣━ 📄 foo.go - ┃ ┗━ 📁 jsii - ┃ ┣━ 📄 jsii.go - ┃ ┗━ 📄 tarball.embedded.go - ┣━ 📁 java - ┃ ┣━ 📄 pom.xml - ┃ ┗━ 📁 src - ┃ ┗━ 📁 main - ┃ ┣━ 📁 java - ┃ ┃ ┗━ 📁 com - ┃ ┃ ┗━ 📁 acme - ┃ ┃ ┗━ 📁 foo - ┃ ┃ ┗━ 📄 $Module.java - ┃ ┗━ 📁 resources - ┃ ┗━ 📁 com - ┃ ┗━ 📁 acme - ┃ ┗━ 📁 foo - ┃ ┣━ 📄 $Module.txt - ┃ ┗━ 📄 foo@1.2.3.jsii.tgz - ┣━ 📁 js - ┃ ┗━ 📄 foo@1.2.3.jsii.tgz - ┗━ 📁 python - ┣━ 📄 MANIFEST.in - ┣━ 📄 pyproject.toml - ┣━ 📄 README.md - ┣━ 📄 setup.py - ┗━ 📁 src - ┗━ 📁 foo - ┗━ 📁 _jsii - ┣━ 📄 __init__.py - ┗━ 📄 foo@1.2.3.jsii.tgz -`; - -exports[`foo@1.2.3 depends on bar@^0.0.0-pr1234.0: /dotnet/Com.Acme.Foo/AssemblyInfo.cs 1`] = ` -using Amazon.JSII.Runtime.Deputy; - -[assembly: JsiiAssembly("foo", "1.2.3", "foo-1.2.3.tgz")] - -`; - -exports[`foo@1.2.3 depends on bar@^0.0.0-pr1234.0: /dotnet/Com.Acme.Foo/Com.Acme.Foo.csproj 1`] = ` - - - - Test assembly: foo - Com.Acme.Foo - UNLICENSED - 1.2.3 - - Test - en-US - https://test.nope/foo - foo.nope.git - git - - true - true - true - true - enable - snupkg - netcoreapp3.1 - - - - - - - - - - 0612,0618 - - - - -`; - -exports[`foo@1.2.3 depends on bar@^0.0.0-pr1234.0: /dotnet/Com.Acme.Foo/Com/Acme/Foo/Internal/DependencyResolution/Anchor.cs 1`] = ` -#pragma warning disable CS0672,CS0809,CS1591 - -namespace Com.Acme.Foo.Internal.DependencyResolution -{ - public sealed class Anchor - { - public Anchor() - { - new Com.Acme.Bar.Internal.DependencyResolution.Anchor(); - } - } -} - -`; - -exports[`foo@1.2.3 depends on bar@^0.0.0-pr1234.0: /dotnet/Com.Acme.Foo/foo-1.2.3.tgz 1`] = `dotnet/Com.Acme.Foo/foo-1.2.3.tgz is a tarball`; - -exports[`foo@1.2.3 depends on bar@^0.0.0-pr1234.0: /go/foo/foo.go 1`] = ` -// Test assembly: foo -package foo - -import ( -) - - -`; - -exports[`foo@1.2.3 depends on bar@^0.0.0-pr1234.0: /go/foo/jsii/jsii.go 1`] = ` -package jsii - -import ( - rt "github.com/aws-cdk/jsii/jsii-experimental" - "sync" - // Initialization endpoints of dependencies - bar "/bar/jsii" -) - -var once sync.Once - -// Initialize performs the necessary work for the enclosing -// module to be loaded in the jsii kernel. -func Initialize() { - once.Do(func(){ - // Ensure all dependencies are initialized - bar.Initialize() - - // Load this library into the kernel - rt.Load("foo", "1.2.3", tarball) - }) -} - -`; - -exports[`foo@1.2.3 depends on bar@^0.0.0-pr1234.0: /go/foo/jsii/tarball.embedded.go 1`] = `go/foo/jsii/tarball.embedded.go embeds a tarball`; - -exports[`foo@1.2.3 depends on bar@^0.0.0-pr1234.0: /java/pom.xml 1`] = ` - - - 4.0.0 - \${project.groupId}:\${project.artifactId} - Test assembly: foo - https://test.nope/foo - - - - Test - - test - - - - - scm:git:foo.nope.git - foo.nope.git - - com.acme - foo - 1.2.3 - jar - - UTF-8 - - - - com.acme - bar - [0.0.0-pr1234.0,0.0.1) - - - software.amazon.jsii - jsii-runtime - [0.0.0,0.0.1) - - - org.jetbrains - annotations - [16.0.3,20.0.0) - - - - javax.annotation - javax.annotation-api - [1.3.2,1.4.0) - compile - - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.8.1 - - 1.8 - 1.8 - - - - org.apache.maven.plugins - maven-jar-plugin - 3.2.0 - - - true - - true - true - - - - - - org.apache.maven.plugins - maven-source-plugin - 3.2.1 - - - attach-sources - - jar - - - - - - org.apache.maven.plugins - maven-javadoc-plugin - 3.1.1 - - - attach-javadocs - - jar - - - - - false - protected - - **/$Module.java - - -J-XX:+TieredCompilation - -J-XX:TieredStopAtLevel=1 - - - - org.apache.maven.plugins - maven-enforcer-plugin - 3.0.0-M3 - - - enforce-maven - - enforce - - - - - 3.6 - - - - - - - - org.codehaus.mojo - versions-maven-plugin - 2.7 - - false - - - - - - -`; - -exports[`foo@1.2.3 depends on bar@^0.0.0-pr1234.0: /java/src/main/java/com/acme/foo/$Module.java 1`] = ` -package com.acme.foo; - -import static java.util.Arrays.asList; - -import java.io.BufferedReader; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.IOException; -import java.io.Reader; -import java.io.UncheckedIOException; - -import java.nio.charset.StandardCharsets; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import software.amazon.jsii.JsiiModule; - -@software.amazon.jsii.Internal -public final class $Module extends JsiiModule { - private static final Map MODULE_TYPES = load(); - - private static Map load() { - final Map result = new HashMap<>(); - final ClassLoader cl = $Module.class.getClassLoader(); - try (final InputStream is = cl.getResourceAsStream("com/acme/foo/$Module.txt"); - final Reader rd = new InputStreamReader(is, StandardCharsets.UTF_8); - final BufferedReader br = new BufferedReader(rd)) { - br.lines() - .filter(line -> !line.trim().isEmpty()) - .forEach(line -> { - final String[] parts = line.split("=", 2); - final String fqn = parts[0]; - final String className = parts[1]; - result.put(fqn, className); - }); - } - catch (final IOException exception) { - throw new UncheckedIOException(exception); - } - return result; - } - - private final Map> cache = new HashMap<>(); - - public $Module() { - super("foo", "1.2.3", $Module.class, "foo@1.2.3.jsii.tgz"); - } - - @Override - public List> getDependencies() { - return asList(com.acme.bar.$Module.class); - } - - @Override - protected Class resolveClass(final String fqn) throws ClassNotFoundException { - if (!MODULE_TYPES.containsKey(fqn)) { - throw new ClassNotFoundException("Unknown JSII type: " + fqn); - } - String className = MODULE_TYPES.get(fqn); - if (!this.cache.containsKey(className)) { - this.cache.put(className, this.findClass(className)); - } - return this.cache.get(className); - } - - private Class findClass(final String binaryName) { - try { - return Class.forName(binaryName); - } - catch (final ClassNotFoundException exception) { - throw new RuntimeException(exception); - } - } -} - -`; - -exports[`foo@1.2.3 depends on bar@^0.0.0-pr1234.0: /java/src/main/resources/com/acme/foo/$Module.txt 1`] = ``; - -exports[`foo@1.2.3 depends on bar@^0.0.0-pr1234.0: /java/src/main/resources/com/acme/foo/foo@1.2.3.jsii.tgz 1`] = `java/src/main/resources/com/acme/foo/foo@1.2.3.jsii.tgz is a tarball`; - -exports[`foo@1.2.3 depends on bar@^0.0.0-pr1234.0: /js/foo@1.2.3.jsii.tgz 1`] = `js/foo@1.2.3.jsii.tgz is a tarball`; - -exports[`foo@1.2.3 depends on bar@^0.0.0-pr1234.0: /python/MANIFEST.in 1`] = ` -include pyproject.toml - -`; - -exports[`foo@1.2.3 depends on bar@^0.0.0-pr1234.0: /python/README.md 1`] = ` - - -`; - -exports[`foo@1.2.3 depends on bar@^0.0.0-pr1234.0: /python/pyproject.toml 1`] = ` -[build-system] -requires = ["setuptools~=49.3", "wheel~=0.34"] -build-backend = "setuptools.build_meta" - -`; - -exports[`foo@1.2.3 depends on bar@^0.0.0-pr1234.0: /python/setup.py 1`] = ` -import json -import setuptools - -kwargs = json.loads( - """ -{ - "name": "foo", - "version": "1.2.3", - "description": "Test assembly: foo", - "license": "UNLICENSED", - "url": "https://test.nope/foo", - "long_description_content_type": "text/markdown", - "author": "Test", - "bdist_wheel": { - "universal": true - }, - "project_urls": { - "Source": "foo.nope.git" - }, - "package_dir": { - "": "src" - }, - "packages": [ - "foo._jsii" - ], - "package_data": { - "foo._jsii": [ - "foo@1.2.3.jsii.tgz" - ] - }, - "python_requires": ">=3.6", - "install_requires": [ - "bar>=0.0.0.dev1234, <0.0.1", - "jsii>=1337.42.1337, <1338.0.0", - "publication>=0.0.3" - ], - "classifiers": [ - "Intended Audience :: Developers", - "Operating System :: OS Independent", - "Programming Language :: JavaScript", - "Programming Language :: Python :: 3 :: Only", - "Programming Language :: Python :: 3.6", - "Programming Language :: Python :: 3.7", - "Programming Language :: Python :: 3.8", - "Typing :: Typed" - ] -} -""" -) - -with open("README.md", encoding="utf8") as fp: - kwargs["long_description"] = fp.read() - - -setuptools.setup(**kwargs) - -`; - -exports[`foo@1.2.3 depends on bar@^0.0.0-pr1234.0: /python/src/foo/_jsii/__init__.py 1`] = ` -import abc -import builtins -import datetime -import enum -import typing - -import jsii -import publication -import typing_extensions - -import bar._jsii - -__jsii_assembly__ = jsii.JSIIAssembly.load( - "foo", "1.2.3", __name__[0:-6], "foo@1.2.3.jsii.tgz" -) - -__all__ = [ - "__jsii_assembly__", -] - -publication.publish() - -`; - -exports[`foo@1.2.3 depends on bar@^0.0.0-pr1234.0: /python/src/foo/_jsii/foo@1.2.3.jsii.tgz 1`] = `python/src/foo/_jsii/foo@1.2.3.jsii.tgz is a tarball`; - exports[`foo@1.2.3 depends on bar@^2.0.0-rc.42: / 1`] = ` ┣━ 📁 dotnet diff --git a/packages/jsii-pacmak/test/generated-code/prerelease-identifiers.test.ts b/packages/jsii-pacmak/test/generated-code/prerelease-identifiers.test.ts index 7b6224cdc7..a65ae3d7eb 100644 --- a/packages/jsii-pacmak/test/generated-code/prerelease-identifiers.test.ts +++ b/packages/jsii-pacmak/test/generated-code/prerelease-identifiers.test.ts @@ -7,7 +7,7 @@ import { join } from 'path'; import { pacmak } from '../../lib'; import { checkTree, TREE } from './harness'; -for (const prerelease of ['4.5.6-pre.1337', '0.0.0-pr1234.0', '2.0.0-rc.42']) { +for (const prerelease of ['4.5.6-pre.1337', '2.0.0-rc.42']) { test(`foo@1.2.3 depends on bar@^${prerelease}`, async () => { const outDir = await fs.mkdtemp( join(tmpdir(), 'jsii-pacmak.prerelease-identifiers.test.output.'), diff --git a/packages/jsii-pacmak/test/targets/version-utils.test.ts b/packages/jsii-pacmak/test/targets/version-utils.test.ts index 1594eee6cb..df5b11b442 100644 --- a/packages/jsii-pacmak/test/targets/version-utils.test.ts +++ b/packages/jsii-pacmak/test/targets/version-utils.test.ts @@ -143,20 +143,6 @@ describe(toReleaseVersion, () => { js: '1.2.3-rc.9', python: '1.2.3.rc9', }, - '1.2.3-pr4567.8': { - dotnet: '1.2.3-pr4567.8', - go: '1.2.3-pr4567.8', - java: '1.2.3-pr4567.8', - js: '1.2.3-pr4567.8', - python: /Unable to map prerelease identifier \(in: 1\.2\.3-pr4567\.8\) to python, as label 'pr4567' is not mapped/, - }, - '1.2.3-pr4567.0': { - dotnet: '1.2.3-pr4567.0', - go: '1.2.3-pr4567.0', - java: '1.2.3-pr4567.0', - js: '1.2.3-pr4567.0', - python: '1.2.3.dev4567', - }, }; for (const [version, targets] of Object.entries(examples)) { From e45088cc96b7188d1c3384097f31c2f2b9cfa1fc Mon Sep 17 00:00:00 2001 From: Niranjan Jayakar Date: Wed, 28 Oct 2020 16:20:42 +0000 Subject: [PATCH 15/16] Update docs/configuration.md --- docs/configuration.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/configuration.md b/docs/configuration.md index c6cb330b3a..3d15652290 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -233,7 +233,7 @@ Example: The resulting artifact is a **Maven** package that can be deployed to [Maven Central] using the `deploy-staged-repository` command of the [nexus-staging-maven-plugin]. -[maven centra]: https://search.maven.org +[maven central]: https://search.maven.org [nexus-staging-maven-plugin]: https://mvnrepository.com/artifact/org.sonatype.plugins/nexus-staging-maven-plugin #### Configuring `.NET` From 7bdf1a042529adbbdd5a8a11a461f690c9b02a74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=91=A8=F0=9F=8F=BC=E2=80=8D=F0=9F=92=BB=20Romain=20M?= =?UTF-8?q?arcadier-Muller?= Date: Wed, 28 Oct 2020 17:44:29 +0100 Subject: [PATCH 16/16] make integration test work again (hopefully) --- .github/workflows/main.yml | 4 ++-- packages/jsii-pacmak/lib/targets/version-utils.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 53d8262ca7..df4c6f607b 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -163,14 +163,14 @@ jobs: run: |- npx standard-version \ --compareUrlFormat='{{host}}/{{owner}}/{{repository}}/compare/{{previousTag}}...${{ github.sha }}' \ - --prerelease=pr${{ github.event.pull_request.number }} \ + --prerelease=dev.${{ github.event.pull_request.number }} \ --skip.commit - name: Standard Version (Nightly) if: github.event_name == 'push' run: |- npx standard-version \ --compareUrlFormat='{{host}}/{{owner}}/{{repository}}/compare/{{previousTag}}...${{ github.sha }}' \ - --prerelease=nightly.$(date -u +'%Y%m%d') \ + --prerelease=dev.$(date -u +'%Y%m%d') \ --skip.commit # Now we'll be preparing a release package (with the "real" version) - name: Run "align-version.sh" diff --git a/packages/jsii-pacmak/lib/targets/version-utils.ts b/packages/jsii-pacmak/lib/targets/version-utils.ts index ff38328fb6..55b41e6dec 100644 --- a/packages/jsii-pacmak/lib/targets/version-utils.ts +++ b/packages/jsii-pacmak/lib/targets/version-utils.ts @@ -96,7 +96,7 @@ export function toReleaseVersion( // Python supports a limited set of identifiers... And we have a mapping table... // https://packaging.python.org/guides/distributing-packages-using-setuptools/#pre-release-versioning const [label, sequence, ...rest] = version.prerelease; - if (rest.length > 0 || sequence == null) { + if (rest.filter((elt) => elt !== 0).length > 0 || sequence == null) { throw new Error( `Unable to map prerelease identifier (in: ${assemblyVersion}) components to python: ${inspect( version.prerelease,