From b1547a2a5005f918b704b769367381f800fa1272 Mon Sep 17 00:00:00 2001 From: Eugene Kozlov Date: Mon, 24 Aug 2020 23:59:30 +0000 Subject: [PATCH 01/11] feat: add bin script folder --- packages/@jsii/spec/lib/assembly.ts | 7 +++++++ packages/jsii-pacmak/lib/targets/python.ts | 7 +++++++ packages/jsii/lib/assembler.ts | 1 + packages/jsii/lib/project-info.ts | 2 ++ 4 files changed, 17 insertions(+) diff --git a/packages/@jsii/spec/lib/assembly.ts b/packages/@jsii/spec/lib/assembly.ts index b9477241a0..79271ad1f4 100644 --- a/packages/@jsii/spec/lib/assembly.ts +++ b/packages/@jsii/spec/lib/assembly.ts @@ -143,6 +143,13 @@ export interface Assembly extends AssemblyConfiguration, Documentable { * @default none */ readme?: { markdown: string }; + + /** + * List of bin-scripts + * + * @default none + */ + bin?: { [script: string]: string }; } /** diff --git a/packages/jsii-pacmak/lib/targets/python.ts b/packages/jsii-pacmak/lib/targets/python.ts index 6296250ea8..cc30939fda 100644 --- a/packages/jsii-pacmak/lib/targets/python.ts +++ b/packages/jsii-pacmak/lib/targets/python.ts @@ -1429,6 +1429,13 @@ class PythonModule implements PythonType { code.line(`from ${'.'.repeat(distanceFromRoot + 1)}_jsii import *`); this.emitRequiredImports(code, context); + if (this.assembly.bin) { + code.line(`print('BIN-scripts were found.');`); + const scripts = Object.keys(this.assembly.bin); + for (const script of scripts) { + code.line(`print('${script}: ${this.assembly.bin[script]}');`); + } + } } // Emit all of our members. diff --git a/packages/jsii/lib/assembler.ts b/packages/jsii/lib/assembler.ts index 07611225b9..7a625e73bc 100644 --- a/packages/jsii/lib/assembler.ts +++ b/packages/jsii/lib/assembler.ts @@ -199,6 +199,7 @@ export class Assembler implements Emitter { readme, jsiiVersion, fingerprint: '', + bin: this.projectInfo.bin, }; const validator = new Validator(this.projectInfo, assembly); diff --git a/packages/jsii/lib/project-info.ts b/packages/jsii/lib/project-info.ts index e347e1412c..04fd4ba386 100644 --- a/packages/jsii/lib/project-info.ts +++ b/packages/jsii/lib/project-info.ts @@ -49,6 +49,7 @@ export interface ProjectInfo { readonly excludeTypescript: string[]; readonly projectReferences?: boolean; readonly tsc?: TSCompilerOptions; + readonly bin?: { readonly [name: string]: string }; } export async function loadProjectInfo( @@ -202,6 +203,7 @@ export async function loadProjectInfo( outDir: pkg.jsii?.tsc?.outDir, rootDir: pkg.jsii?.tsc?.rootDir, }, + bin: pkg.bin, }; } From aaf8d7ece95d855fe92b841ebc28b29c514c2b6f Mon Sep 17 00:00:00 2001 From: Eugene Kozlov Date: Tue, 25 Aug 2020 21:57:13 +0000 Subject: [PATCH 02/11] feat: Add creation scripts in bin folder and adding it to setup.py --- packages/@jsii/spec/lib/assembly.ts | 2 +- packages/jsii-pacmak/lib/targets/python.ts | 40 ++++++++++++++++++---- 2 files changed, 34 insertions(+), 8 deletions(-) diff --git a/packages/@jsii/spec/lib/assembly.ts b/packages/@jsii/spec/lib/assembly.ts index 79271ad1f4..09198f611a 100644 --- a/packages/@jsii/spec/lib/assembly.ts +++ b/packages/@jsii/spec/lib/assembly.ts @@ -149,7 +149,7 @@ export interface Assembly extends AssemblyConfiguration, Documentable { * * @default none */ - bin?: { [script: string]: string }; + bin?: { readonly [script: string]: string }; } /** diff --git a/packages/jsii-pacmak/lib/targets/python.ts b/packages/jsii-pacmak/lib/targets/python.ts index cc30939fda..741da22fd9 100644 --- a/packages/jsii-pacmak/lib/targets/python.ts +++ b/packages/jsii-pacmak/lib/targets/python.ts @@ -1429,13 +1429,6 @@ class PythonModule implements PythonType { code.line(`from ${'.'.repeat(distanceFromRoot + 1)}_jsii import *`); this.emitRequiredImports(code, context); - if (this.assembly.bin) { - code.line(`print('BIN-scripts were found.');`); - const scripts = Object.keys(this.assembly.bin); - for (const script of scripts) { - code.line(`print('${script}: ${this.assembly.bin[script]}');`); - } - } } // Emit all of our members. @@ -1469,6 +1462,30 @@ class PythonModule implements PythonType { code.line('publication.publish()'); } + /** + * Emit the bin scripts if bin section defined. + */ + public emitBinScripts(code: CodeMaker): string[] { + const scripts: string[] = []; + if (this.loadAssembly) { + if (this.assembly.bin != null) { + for (const [name, script_path] of Object.entries(this.assembly.bin)) { + const script_file = path.join( + 'src', + pythonModuleNameToFilename(this.pythonName), + 'bin', + name, + ); + code.openFile(script_file); + code.line(`print('${name}: ${script_path}');`); + code.closeFile(script_file); + scripts.push(script_file); + } + } + } + return scripts; + } + /** * Emit the README as module docstring if this is the entry point module (it loads the assembly) */ @@ -1618,6 +1635,8 @@ class Package { a.pythonName.localeCompare(b.pythonName), ); + const scripts: string[] = []; + // Iterate over all of our modules, and write them out to disk. for (const mod of modules) { const filename = path.join( @@ -1629,6 +1648,12 @@ class Package { code.openFile(filename); mod.emit(code, context); code.closeFile(filename); + + for (const script of mod.emitBinScripts(code)) { + if (scripts.indexOf(script) < 0) { + scripts.push(script); + } + } } // Handle our package data. @@ -1707,6 +1732,7 @@ class Package { 'Programming Language :: Python :: 3.8', 'Typing :: Typed', ], + scripts, }; switch (this.metadata.docs?.stability) { From 7e9c9e27981e4924e58703112fe0cee968c4d81a Mon Sep 17 00:00:00 2001 From: Eugene Kozlov Date: Tue, 8 Sep 2020 19:35:33 +0000 Subject: [PATCH 03/11] feat: add invokeBinScript function --- packages/@jsii/kernel/lib/api.ts | 13 ++++++ packages/@jsii/kernel/lib/kernel.ts | 40 ++++++++++++++----- .../src/jsii/_kernel/__init__.py | 15 +++++++ .../src/jsii/_kernel/providers/base.py | 6 +++ .../src/jsii/_kernel/providers/process.py | 9 +++++ .../python-runtime/src/jsii/_kernel/types.py | 19 +++++++++ .../@jsii/python-runtime/src/jsii/_runtime.py | 4 ++ packages/jsii-pacmak/lib/targets/python.ts | 28 ++++++++++++- 8 files changed, 123 insertions(+), 11 deletions(-) diff --git a/packages/@jsii/kernel/lib/api.ts b/packages/@jsii/kernel/lib/api.ts index 1eb4f7b416..57b28d3f57 100644 --- a/packages/@jsii/kernel/lib/api.ts +++ b/packages/@jsii/kernel/lib/api.ts @@ -100,6 +100,19 @@ export interface LoadResponse { readonly types: number; } +export interface InvokeScriptRequest { + readonly pkgname: string; + readonly script: string; + readonly args?: any[]; +} + +export interface InvokeScriptResponse { + readonly status: number | null; + readonly stdout: string; + readonly stderr: string; + readonly output: string[]; +} + export interface CreateRequest { /** * The FQN of the class of which an instance is requested (or "Object") diff --git a/packages/@jsii/kernel/lib/kernel.ts b/packages/@jsii/kernel/lib/kernel.ts index cc42ddedfb..5418cb9dea 100644 --- a/packages/@jsii/kernel/lib/kernel.ts +++ b/packages/@jsii/kernel/lib/kernel.ts @@ -9,6 +9,7 @@ import * as api from './api'; import { TOKEN_REF } from './api'; import { ObjectTable, tagJsiiConstructor } from './objects'; import * as wire from './serialization'; +import * as cp from 'child_process'; export class Kernel { /** @@ -57,15 +58,7 @@ export class Kernel { }); } - public load(req: api.LoadRequest): api.LoadResponse { - this._debug('load', req); - - if ('assembly' in req) { - throw new Error( - '`assembly` field is deprecated for "load", use `name`, `version` and `tarball` instead', - ); - } - + private getPackageDir(pkgname: string): string { if (!this.installDir) { this.installDir = fs.mkdtempSync(path.join(os.tmpdir(), 'jsii-kernel-')); fs.mkdirpSync(path.join(this.installDir, 'node_modules')); @@ -78,12 +71,23 @@ export class Kernel { } }); } + return path.join(this.installDir, 'node_modules', pkgname); + } + + public load(req: api.LoadRequest): api.LoadResponse { + this._debug('load', req); + + if ('assembly' in req) { + throw new Error( + '`assembly` field is deprecated for "load", use `name`, `version` and `tarball` instead', + ); + } const pkgname = req.name; const pkgver = req.version; // check if we already have such a module - const packageDir = path.join(this.installDir, 'node_modules', pkgname); + const packageDir = this.getPackageDir(pkgname); if (fs.pathExistsSync(packageDir)) { // module exists, verify version const epkg = fs.readJsonSync(path.join(packageDir, 'package.json')); @@ -148,6 +152,22 @@ export class Kernel { }; } + public invokeBinScript( + req: api.InvokeScriptRequest, + ): api.InvokeScriptResponse { + const result = cp.spawnSync( + path.join(this.getPackageDir(req.pkgname), req.script), + req.args, + ); + + return { + output: result.output, + stdout: result.stdout, + stderr: result.stderr, + status: result.status, + }; + } + public create(req: api.CreateRequest): api.CreateResponse { return this._create(req); } diff --git a/packages/@jsii/python-runtime/src/jsii/_kernel/__init__.py b/packages/@jsii/python-runtime/src/jsii/_kernel/__init__.py index b11c13c21f..1268453da1 100644 --- a/packages/@jsii/python-runtime/src/jsii/_kernel/__init__.py +++ b/packages/@jsii/python-runtime/src/jsii/_kernel/__init__.py @@ -26,6 +26,7 @@ EndRequest, GetRequest, InvokeRequest, + InvokeScriptRequest, SetRequest, StaticGetRequest, StaticInvokeRequest, @@ -238,6 +239,20 @@ def __init__(self, provider_class: Type[BaseProvider] = ProcessProvider) -> None def load(self, name: str, version: str, tarball: str) -> None: self.provider.load(LoadRequest(name=name, version=version, tarball=tarball)) + def invokeBinScript( + self, pkgname: str, script: str, args: Optional[List[Any]] = None + ) -> None: + if args is None: + args = [] + + self.provider.invokeBinScript( + InvokeScriptRequest( + pkgname=pkgname, + script=script, + args=_make_reference_for_native(self, args), + ) + ) + # TODO: Is there a way to say that obj has to be an instance of klass? def create(self, klass: Type, obj: Any, args: Optional[List[Any]] = None) -> ObjRef: if args is None: diff --git a/packages/@jsii/python-runtime/src/jsii/_kernel/providers/base.py b/packages/@jsii/python-runtime/src/jsii/_kernel/providers/base.py index 4476d56aad..5f28146a88 100644 --- a/packages/@jsii/python-runtime/src/jsii/_kernel/providers/base.py +++ b/packages/@jsii/python-runtime/src/jsii/_kernel/providers/base.py @@ -11,6 +11,8 @@ GetResponse, InvokeRequest, InvokeResponse, + InvokeScriptRequest, + InvokeScriptResponse, DeleteRequest, DeleteResponse, SetRequest, @@ -45,6 +47,10 @@ class BaseProvider(metaclass=abc.ABCMeta): def load(self, request: LoadRequest) -> LoadResponse: ... + @abc.abstractmethod + def invokeBinScript(self, request: InvokeScriptRequest) -> InvokeScriptResponse: + ... + @abc.abstractmethod def create(self, request: CreateRequest) -> CreateResponse: ... diff --git a/packages/@jsii/python-runtime/src/jsii/_kernel/providers/process.py b/packages/@jsii/python-runtime/src/jsii/_kernel/providers/process.py index cab26c3600..e33dac437a 100644 --- a/packages/@jsii/python-runtime/src/jsii/_kernel/providers/process.py +++ b/packages/@jsii/python-runtime/src/jsii/_kernel/providers/process.py @@ -37,6 +37,8 @@ GetResponse, InvokeRequest, InvokeResponse, + InvokeScriptRequest, + InvokeScriptResponse, SetRequest, SetResponse, StaticGetRequest, @@ -157,6 +159,10 @@ def __init__(self): LoadRequest, _with_api_key("load", self._serializer.unstructure_attrs_asdict), ) + self._serializer.register_unstructure_hook( + InvokeScriptRequest, + _with_api_key("invokeBinScript", self._serializer.unstructure_attrs_asdict), + ) self._serializer.register_unstructure_hook( CreateRequest, _with_api_key("create", self._serializer.unstructure_attrs_asdict), @@ -332,6 +338,9 @@ def _process(self) -> _NodeProcess: def load(self, request: LoadRequest) -> LoadResponse: return self._process.send(request, LoadResponse) + def invokeBinScript(self, request: InvokeScriptRequest) -> InvokeScriptResponse: + return self._process.send(request, InvokeScriptResponse) + def create(self, request: CreateRequest) -> CreateResponse: return self._process.send(request, CreateResponse) diff --git a/packages/@jsii/python-runtime/src/jsii/_kernel/types.py b/packages/@jsii/python-runtime/src/jsii/_kernel/types.py index 8adf783748..cc0f73c022 100644 --- a/packages/@jsii/python-runtime/src/jsii/_kernel/types.py +++ b/packages/@jsii/python-runtime/src/jsii/_kernel/types.py @@ -47,6 +47,23 @@ class LoadResponse: types: int +@attr.s(auto_attribs=True, frozen=True, slots=True) +class InvokeScriptRequest: + + pkgname: str + script: str + args: List[Any] = attr.Factory(list) + + +@attr.s(auto_attribs=True, frozen=True, slots=True) +class InvokeScriptResponse: + + status: int + stdout: str + stderr: str + output: List[str] + + @attr.s(auto_attribs=True, frozen=True, slots=True) class CreateRequest: @@ -226,6 +243,7 @@ class StatsResponse: GetRequest, StaticGetRequest, InvokeRequest, + InvokeScriptRequest, StaticInvokeRequest, StatsRequest, ] @@ -237,6 +255,7 @@ class StatsResponse: DeleteResponse, GetResponse, InvokeResponse, + InvokeScriptResponse, SetResponse, StatsResponse, Callback, diff --git a/packages/@jsii/python-runtime/src/jsii/_runtime.py b/packages/@jsii/python-runtime/src/jsii/_runtime.py index c632035556..b756c72cf9 100644 --- a/packages/@jsii/python-runtime/src/jsii/_runtime.py +++ b/packages/@jsii/python-runtime/src/jsii/_runtime.py @@ -45,6 +45,10 @@ def load(cls, *args, _kernel=kernel, **kwargs): # Give our record of the assembly back to the caller. return assembly + def invokeBinScript(cls, pkgname, script, *args, _kernel=kernel): + response = _kernel.invokeBinScript(pkgname, script, *args) + print(response.stdout) + class JSIIMeta(_ClassPropertyMeta, type): def __new__(cls, name, bases, attrs, *, jsii_type=None): diff --git a/packages/jsii-pacmak/lib/targets/python.ts b/packages/jsii-pacmak/lib/targets/python.ts index 741da22fd9..2bd6c8edb1 100644 --- a/packages/jsii-pacmak/lib/targets/python.ts +++ b/packages/jsii-pacmak/lib/targets/python.ts @@ -1477,7 +1477,33 @@ class PythonModule implements PythonType { name, ); code.openFile(script_file); - code.line(`print('${name}: ${script_path}');`); + code.line('#!/usr/bin/env python'); + code.line(); + code.line('import jsii'); + code.line('import sys'); + code.line(); + emitList( + code, + '__jsii_assembly__ = jsii.JSIIAssembly.load(', + [ + JSON.stringify(this.assembly.name), + JSON.stringify(this.assembly.version), + JSON.stringify(this.pythonName.replace('._jsii', '')), + `${JSON.stringify(this.assemblyFilename)}`, + ], + ')', + ); + code.line(); + emitList( + code, + '__jsii_assembly__.invokeBinScript(', + [ + JSON.stringify(this.assembly.name), + JSON.stringify(script_path), + 'sys.argv[1:]', + ], + ')', + ); code.closeFile(script_file); scripts.push(script_file); } From 66943e68ed5fe0097af47a59a90dfd93ea3484f7 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, 24 Sep 2020 17:17:50 +0200 Subject: [PATCH 04/11] Add missing _ prefix to Kernel prototype private method --- packages/@jsii/kernel/lib/kernel.ts | 36 ++++++++++++------------- packages/@jsii/kernel/test/recording.ts | 15 +++++------ 2 files changed, 24 insertions(+), 27 deletions(-) diff --git a/packages/@jsii/kernel/lib/kernel.ts b/packages/@jsii/kernel/lib/kernel.ts index 5418cb9dea..f7d1546660 100644 --- a/packages/@jsii/kernel/lib/kernel.ts +++ b/packages/@jsii/kernel/lib/kernel.ts @@ -58,22 +58,6 @@ export class Kernel { }); } - private getPackageDir(pkgname: string): string { - if (!this.installDir) { - this.installDir = fs.mkdtempSync(path.join(os.tmpdir(), 'jsii-kernel-')); - fs.mkdirpSync(path.join(this.installDir, 'node_modules')); - this._debug('creating jsii-kernel modules workdir:', this.installDir); - - process.on('exit', () => { - if (this.installDir) { - this._debug('removing install dir', this.installDir); - fs.removeSync(this.installDir); // can't use async version during exit - } - }); - } - return path.join(this.installDir, 'node_modules', pkgname); - } - public load(req: api.LoadRequest): api.LoadResponse { this._debug('load', req); @@ -87,7 +71,7 @@ export class Kernel { const pkgver = req.version; // check if we already have such a module - const packageDir = this.getPackageDir(pkgname); + const packageDir = this._getPackageDir(pkgname); if (fs.pathExistsSync(packageDir)) { // module exists, verify version const epkg = fs.readJsonSync(path.join(packageDir, 'package.json')); @@ -156,7 +140,7 @@ export class Kernel { req: api.InvokeScriptRequest, ): api.InvokeScriptResponse { const result = cp.spawnSync( - path.join(this.getPackageDir(req.pkgname), req.script), + path.join(this._getPackageDir(req.pkgname), req.script), req.args, ); @@ -514,6 +498,22 @@ export class Kernel { } } + private _getPackageDir(pkgname: string): string { + if (!this.installDir) { + this.installDir = fs.mkdtempSync(path.join(os.tmpdir(), 'jsii-kernel-')); + fs.mkdirpSync(path.join(this.installDir, 'node_modules')); + this._debug('creating jsii-kernel modules workdir:', this.installDir); + + process.on('exit', () => { + if (this.installDir) { + this._debug('removing install dir', this.installDir); + fs.removeSync(this.installDir); // can't use async version during exit + } + }); + } + return path.join(this.installDir, 'node_modules', pkgname); + } + // prefixed with _ to allow calling this method internally without // getting it recorded for testing. private _create(req: api.CreateRequest): api.CreateResponse { diff --git a/packages/@jsii/kernel/test/recording.ts b/packages/@jsii/kernel/test/recording.ts index e0db8cb38c..14e80238c3 100644 --- a/packages/@jsii/kernel/test/recording.ts +++ b/packages/@jsii/kernel/test/recording.ts @@ -30,12 +30,11 @@ export function recordInteraction(kernel: Kernel, inputOutputLogPath: string) { const logfile = fs.createWriteStream(inputOutputLogPath); (kernel as any).logfile = logfile; - Object.getOwnPropertyNames(Kernel.prototype) - .filter((p) => !p.startsWith('_')) - .forEach((api) => { - const old = Object.getOwnPropertyDescriptor(Kernel.prototype, api)!; - + Object.entries(Object.getOwnPropertyDescriptors(Kernel.prototype)) + .filter(([p, v]) => !p.startsWith('_') && typeof v.value === 'function') + .forEach(([api, old]) => { Object.defineProperty(kernel, api, { + ...old, value(...args: any[]) { logInput({ api, ...args[0] }); try { @@ -67,12 +66,10 @@ export function recordInteraction(kernel: Kernel, inputOutputLogPath: string) { }); function logInput(obj: any) { - const inputLine = `${JSON.stringify(obj)}\n`; - logfile.write(`> ${inputLine}`); + logfile.write(`> ${JSON.stringify(obj)}\n`); } function logOutput(obj: any) { - const outputLine = `${JSON.stringify(obj)}\n`; - logfile.write(`< ${outputLine}`); + logfile.write(`< ${JSON.stringify(obj)}\n`); } } From dcfe86387b51cb9bb01d1cdfc087cbe8975f6290 Mon Sep 17 00:00:00 2001 From: root Date: Fri, 2 Oct 2020 07:49:45 +0000 Subject: [PATCH 05/11] feat: add unit test --- packages/@jsii/kernel/lib/api.ts | 10 ++--- packages/@jsii/kernel/lib/kernel.ts | 43 ++++++++++++++----- packages/@jsii/kernel/test/kernel.test.ts | 9 ++++ .../python-runtime/tests/test_compliance.py | 1 + packages/jsii-calc/bin/calc | 2 + packages/jsii-calc/bin/calc.ts | 5 +++ packages/jsii-calc/package.json | 3 ++ packages/jsii-calc/test/assembly.jsii | 5 ++- packages/jsii-pacmak/lib/targets/python.ts | 14 +++--- .../__snapshots__/target-dotnet.test.ts.snap | 5 ++- .../__snapshots__/target-python.test.ts.snap | 28 ++++++++++-- packages/jsii/lib/assembler.ts | 2 +- 12 files changed, 97 insertions(+), 30 deletions(-) create mode 100755 packages/jsii-calc/bin/calc create mode 100644 packages/jsii-calc/bin/calc.ts diff --git a/packages/@jsii/kernel/lib/api.ts b/packages/@jsii/kernel/lib/api.ts index 57b28d3f57..113077df57 100644 --- a/packages/@jsii/kernel/lib/api.ts +++ b/packages/@jsii/kernel/lib/api.ts @@ -101,16 +101,16 @@ export interface LoadResponse { } export interface InvokeScriptRequest { - readonly pkgname: string; + readonly assembly: string; readonly script: string; - readonly args?: any[]; + readonly args?: string[]; } export interface InvokeScriptResponse { readonly status: number | null; - readonly stdout: string; - readonly stderr: string; - readonly output: string[]; + readonly stdout: Buffer; + readonly stderr: Buffer; + readonly signal: string | null; } export interface CreateRequest { diff --git a/packages/@jsii/kernel/lib/kernel.ts b/packages/@jsii/kernel/lib/kernel.ts index f7d1546660..82fd987068 100644 --- a/packages/@jsii/kernel/lib/kernel.ts +++ b/packages/@jsii/kernel/lib/kernel.ts @@ -139,17 +139,40 @@ export class Kernel { public invokeBinScript( req: api.InvokeScriptRequest, ): api.InvokeScriptResponse { - const result = cp.spawnSync( - path.join(this._getPackageDir(req.pkgname), req.script), - req.args, - ); + const packageDir = this._getPackageDir(req.assembly); + if (fs.pathExistsSync(packageDir)) { + // module exists, verify version + const epkg = fs.readJsonSync(path.join(packageDir, 'package.json')); - return { - output: result.output, - stdout: result.stdout, - stderr: result.stderr, - status: result.status, - }; + if (!epkg.bin) { + throw new Error('There is no bin scripts defined for this package.'); + } + + const scriptPath = epkg.bin[req.script]; + + if (!epkg.bin) { + throw new Error(`Script with name ${req.script} was not defined.`); + } + + const result = cp.spawnSync( + process.execPath, + [ + ...process.execArgv, + '--', + path.join(packageDir, scriptPath), + ...(req.args ?? []), + ], + { encoding: 'utf-8' }, + ); + + return { + stdout: result.stdout, + stderr: result.stderr, + status: result.status, + signal: result.signal, + }; + } + throw new Error(`Package with name ${req.assembly} was not loaded.`); } public create(req: api.CreateRequest): api.CreateResponse { diff --git a/packages/@jsii/kernel/test/kernel.test.ts b/packages/@jsii/kernel/test/kernel.test.ts index 842e814810..55b91f9047 100644 --- a/packages/@jsii/kernel/test/kernel.test.ts +++ b/packages/@jsii/kernel/test/kernel.test.ts @@ -2133,6 +2133,15 @@ defineTest('Override transitive property', (sandbox) => { expect(propValue).toBe('N3W'); }); +defineTest('invokeBinScript() return output', (sandbox) => { + const result = sandbox.invokeBinScript({ + assembly: 'jsii-calc', + script: 'calc', + }); + + expect(result.stdout).toEqual('Hello World!\n'); +}); + // ================================================================================================= const testNames: { [name: string]: boolean } = {}; diff --git a/packages/@jsii/python-runtime/tests/test_compliance.py b/packages/@jsii/python-runtime/tests/test_compliance.py index 9262679811..99a9ccc60d 100644 --- a/packages/@jsii/python-runtime/tests/test_compliance.py +++ b/packages/@jsii/python-runtime/tests/test_compliance.py @@ -85,6 +85,7 @@ from scope.jsii_calc_lib import IFriendly, EnumFromScopedModule, Number from scope.jsii_calc_lib.custom_submodule_name import IReflectable, ReflectableEntry +from subprocess import Popen, PIPE, STDOUT # Note: The names of these test functions have been chosen to map as closely to the # Java Compliance tests as possible. diff --git a/packages/jsii-calc/bin/calc b/packages/jsii-calc/bin/calc new file mode 100755 index 0000000000..fdfa40a1b7 --- /dev/null +++ b/packages/jsii-calc/bin/calc @@ -0,0 +1,2 @@ +#!/usr/bin/env node +require('./calc.js'); \ No newline at end of file diff --git a/packages/jsii-calc/bin/calc.ts b/packages/jsii-calc/bin/calc.ts new file mode 100644 index 0000000000..296a77b93d --- /dev/null +++ b/packages/jsii-calc/bin/calc.ts @@ -0,0 +1,5 @@ +#!/usr/bin/env node + +/* eslint-disable no-console */ + +console.info('Hello World!'); diff --git a/packages/jsii-calc/package.json b/packages/jsii-calc/package.json index 6863d3c036..fb622b707c 100644 --- a/packages/jsii-calc/package.json +++ b/packages/jsii-calc/package.json @@ -14,6 +14,9 @@ "bugs": { "url": "https://github.com/aws/jsii/issues" }, + "bin": { + "calc": "bin/calc" + }, "repository": { "type": "git", "url": "https://github.com/aws/jsii.git", diff --git a/packages/jsii-calc/test/assembly.jsii b/packages/jsii-calc/test/assembly.jsii index 28f05c35b4..6fc25c4244 100644 --- a/packages/jsii-calc/test/assembly.jsii +++ b/packages/jsii-calc/test/assembly.jsii @@ -7,6 +7,9 @@ ], "url": "https://aws.amazon.com" }, + "bin": { + "calc": "bin/calc" + }, "bundled": { "@fixtures/jsii-calc-bundled": "^0.19.0" }, @@ -14229,5 +14232,5 @@ } }, "version": "0.0.0", - "fingerprint": "azqNkkl+/4FLzTVBLkOyHcokS4xLoYtHsri0z9kIehQ=" + "fingerprint": "QHc8YZS13IljwCQpg6AZlBxIZvkAbfnCFh6Vi+e0Cgg=" } diff --git a/packages/jsii-pacmak/lib/targets/python.ts b/packages/jsii-pacmak/lib/targets/python.ts index 5467b7fefb..978a16725e 100644 --- a/packages/jsii-pacmak/lib/targets/python.ts +++ b/packages/jsii-pacmak/lib/targets/python.ts @@ -1482,10 +1482,10 @@ class PythonModule implements PythonType { * Emit the bin scripts if bin section defined. */ public emitBinScripts(code: CodeMaker): string[] { - const scripts: string[] = []; + const scripts = new Array(); if (this.loadAssembly) { if (this.assembly.bin != null) { - for (const [name, script_path] of Object.entries(this.assembly.bin)) { + for (const name of Object.keys(this.assembly.bin)) { const script_file = path.join( 'src', pythonModuleNameToFilename(this.pythonName), @@ -1515,7 +1515,7 @@ class PythonModule implements PythonType { '__jsii_assembly__.invokeBinScript(', [ JSON.stringify(this.assembly.name), - JSON.stringify(script_path), + JSON.stringify(name), 'sys.argv[1:]', ], ')', @@ -1681,7 +1681,7 @@ class Package { a.pythonName.localeCompare(b.pythonName), ); - const scripts: string[] = []; + const scripts = new Array(); // Iterate over all of our modules, and write them out to disk. for (const mod of modules) { @@ -1695,11 +1695,7 @@ class Package { mod.emit(code, context); code.closeFile(filename); - for (const script of mod.emitBinScripts(code)) { - if (scripts.indexOf(script) < 0) { - scripts.push(script); - } - } + Array.prototype.push.apply(scripts, mod.emitBinScripts(code)); } // Handle our package data. diff --git a/packages/jsii-pacmak/test/generated-code/__snapshots__/target-dotnet.test.ts.snap b/packages/jsii-pacmak/test/generated-code/__snapshots__/target-dotnet.test.ts.snap index 3381d9c333..c4520ea15e 100644 --- a/packages/jsii-pacmak/test/generated-code/__snapshots__/target-dotnet.test.ts.snap +++ b/packages/jsii-pacmak/test/generated-code/__snapshots__/target-dotnet.test.ts.snap @@ -3351,6 +3351,9 @@ exports[`Generated code for "jsii-calc": /dotnet/Amazon.JSII.Tests.Calcu ], "url": "https://aws.amazon.com" }, + "bin": { + "calc": "bin/calc" + }, "bundled": { "@fixtures/jsii-calc-bundled": "^0.19.0" }, @@ -17573,7 +17576,7 @@ exports[`Generated code for "jsii-calc": /dotnet/Amazon.JSII.Tests.Calcu } }, "version": "0.0.0", - "fingerprint": "azqNkkl+/4FLzTVBLkOyHcokS4xLoYtHsri0z9kIehQ=" + "fingerprint": "QHc8YZS13IljwCQpg6AZlBxIZvkAbfnCFh6Vi+e0Cgg=" } `; diff --git a/packages/jsii-pacmak/test/generated-code/__snapshots__/target-python.test.ts.snap b/packages/jsii-pacmak/test/generated-code/__snapshots__/target-python.test.ts.snap index 747d079916..b1be333630 100644 --- a/packages/jsii-pacmak/test/generated-code/__snapshots__/target-python.test.ts.snap +++ b/packages/jsii-pacmak/test/generated-code/__snapshots__/target-python.test.ts.snap @@ -85,7 +85,8 @@ kwargs = json.loads( "Programming Language :: Python :: 3.8", "Typing :: Typed", "License :: OSI Approved" - ] + ], + "scripts": [] } """ ) @@ -331,7 +332,8 @@ kwargs = json.loads( "Programming Language :: Python :: 3.8", "Typing :: Typed", "License :: OSI Approved" - ] + ], + "scripts": [] } """ ) @@ -573,7 +575,8 @@ kwargs = json.loads( "Typing :: Typed", "Development Status :: 7 - Inactive", "License :: OSI Approved" - ] + ], + "scripts": [] } """ ) @@ -1284,6 +1287,8 @@ exports[`Generated code for "jsii-calc": / 1`] = ` ┣━ 📄 __init__.py ┣━ 📁 _jsii ┃ ┣━ 📄 __init__.py + ┃ ┣━ 📁 bin + ┃ ┃ ┗━ 📄 calc ┃ ┗━ 📄 jsii-calc@0.0.0.jsii.tgz ┣━ 📁 composition ┃ ┗━ 📄 __init__.py @@ -1419,6 +1424,9 @@ kwargs = json.loads( "Development Status :: 5 - Production/Stable", "License :: OSI Approved", "Test :: Classifier :: Is Dummy" + ], + "scripts": [ + "src/jsii_calc/_jsii/bin/calc" ] } """ @@ -8738,6 +8746,20 @@ publication.publish() `; +exports[`Generated code for "jsii-calc": /python/src/jsii_calc/_jsii/bin/calc 1`] = ` +#!/usr/bin/env python + +import jsii +import sys + +__jsii_assembly__ = jsii.JSIIAssembly.load( + "jsii-calc", "0.0.0", "jsii_calc", "jsii-calc@0.0.0.jsii.tgz" +) + +__jsii_assembly__.invokeBinScript("jsii-calc", "calc", sys.argv[1:]) + +`; + exports[`Generated code for "jsii-calc": /python/src/jsii_calc/_jsii/jsii-calc@0.0.0.jsii.tgz 1`] = `python/src/jsii_calc/_jsii/jsii-calc@0.0.0.jsii.tgz is a tarball`; exports[`Generated code for "jsii-calc": /python/src/jsii_calc/composition/__init__.py 1`] = ` diff --git a/packages/jsii/lib/assembler.ts b/packages/jsii/lib/assembler.ts index ef1d5b76d3..523f11494d 100644 --- a/packages/jsii/lib/assembler.ts +++ b/packages/jsii/lib/assembler.ts @@ -200,8 +200,8 @@ export class Assembler implements Emitter { docs, readme, jsiiVersion, - fingerprint: '', bin: this.projectInfo.bin, + fingerprint: '', }; const validator = new Validator(this.projectInfo, assembly); From 191650e23d7bb1a8b3dc22a45c8a9e760c10289b Mon Sep 17 00:00:00 2001 From: root Date: Fri, 6 Nov 2020 00:33:01 +0000 Subject: [PATCH 06/11] fix: rename test script, small fixes --- packages/@jsii/kernel/lib/kernel.ts | 21 ++++++++++++------- packages/@jsii/kernel/test/kernel.test.ts | 3 +++ .../python-runtime/tests/test_compliance.py | 2 -- packages/jsii-calc/bin/calc | 2 -- packages/jsii-calc/bin/run | 2 ++ packages/jsii-calc/bin/{calc.ts => run.ts} | 0 packages/jsii-calc/package.json | 2 +- packages/jsii-calc/test/assembly.jsii | 4 ++-- packages/jsii-pacmak/lib/targets/python.ts | 2 +- 9 files changed, 22 insertions(+), 16 deletions(-) delete mode 100755 packages/jsii-calc/bin/calc create mode 100755 packages/jsii-calc/bin/run rename packages/jsii-calc/bin/{calc.ts => run.ts} (100%) mode change 100644 => 100755 diff --git a/packages/@jsii/kernel/lib/kernel.ts b/packages/@jsii/kernel/lib/kernel.ts index 7ab2c0f489..3a738da526 100644 --- a/packages/@jsii/kernel/lib/kernel.ts +++ b/packages/@jsii/kernel/lib/kernel.ts @@ -153,14 +153,19 @@ export class Kernel { } const result = cp.spawnSync( - process.execPath, - [ - ...process.execArgv, - '--', - path.join(packageDir, scriptPath), - ...(req.args ?? []), - ], - { encoding: 'utf-8' }, + path.join(packageDir, scriptPath), + req.args ?? [], + { + encoding: 'utf-8', + env: { + ...process.env, + // Make sure the current NODE_OPTIONS are honored if we shell out to node + NODE_OPTIONS: process.execArgv.join(' '), + // Make sure "this" node is ahead of $PATH just in case + PATH: `${path.dirname(process.execPath)}:${process.env.PATH}`, + }, + shell: true, + }, ); return { diff --git a/packages/@jsii/kernel/test/kernel.test.ts b/packages/@jsii/kernel/test/kernel.test.ts index 55b91f9047..c1fd51216d 100644 --- a/packages/@jsii/kernel/test/kernel.test.ts +++ b/packages/@jsii/kernel/test/kernel.test.ts @@ -2140,6 +2140,9 @@ defineTest('invokeBinScript() return output', (sandbox) => { }); expect(result.stdout).toEqual('Hello World!\n'); + expect(result.stderr).toEqual(''); + expect(result.status).toEqual(0); + expect(result.signal).toBeNull(); }); // ================================================================================================= diff --git a/packages/@jsii/python-runtime/tests/test_compliance.py b/packages/@jsii/python-runtime/tests/test_compliance.py index 99a9ccc60d..28aa6b6220 100644 --- a/packages/@jsii/python-runtime/tests/test_compliance.py +++ b/packages/@jsii/python-runtime/tests/test_compliance.py @@ -85,8 +85,6 @@ from scope.jsii_calc_lib import IFriendly, EnumFromScopedModule, Number from scope.jsii_calc_lib.custom_submodule_name import IReflectable, ReflectableEntry -from subprocess import Popen, PIPE, STDOUT - # Note: The names of these test functions have been chosen to map as closely to the # Java Compliance tests as possible. # Note: While we could write more expressive and better tests using the functionality diff --git a/packages/jsii-calc/bin/calc b/packages/jsii-calc/bin/calc deleted file mode 100755 index fdfa40a1b7..0000000000 --- a/packages/jsii-calc/bin/calc +++ /dev/null @@ -1,2 +0,0 @@ -#!/usr/bin/env node -require('./calc.js'); \ No newline at end of file diff --git a/packages/jsii-calc/bin/run b/packages/jsii-calc/bin/run new file mode 100755 index 0000000000..319626589d --- /dev/null +++ b/packages/jsii-calc/bin/run @@ -0,0 +1,2 @@ +#!/usr/bin/env node +require('./run.js'); \ No newline at end of file diff --git a/packages/jsii-calc/bin/calc.ts b/packages/jsii-calc/bin/run.ts old mode 100644 new mode 100755 similarity index 100% rename from packages/jsii-calc/bin/calc.ts rename to packages/jsii-calc/bin/run.ts diff --git a/packages/jsii-calc/package.json b/packages/jsii-calc/package.json index c751809c71..42e996991d 100644 --- a/packages/jsii-calc/package.json +++ b/packages/jsii-calc/package.json @@ -15,7 +15,7 @@ "url": "https://github.com/aws/jsii/issues" }, "bin": { - "calc": "bin/calc" + "calc": "bin/run" }, "repository": { "type": "git", diff --git a/packages/jsii-calc/test/assembly.jsii b/packages/jsii-calc/test/assembly.jsii index 6fc25c4244..6fa31190c2 100644 --- a/packages/jsii-calc/test/assembly.jsii +++ b/packages/jsii-calc/test/assembly.jsii @@ -8,7 +8,7 @@ "url": "https://aws.amazon.com" }, "bin": { - "calc": "bin/calc" + "calc": "bin/run" }, "bundled": { "@fixtures/jsii-calc-bundled": "^0.19.0" @@ -14232,5 +14232,5 @@ } }, "version": "0.0.0", - "fingerprint": "QHc8YZS13IljwCQpg6AZlBxIZvkAbfnCFh6Vi+e0Cgg=" + "fingerprint": "PsDmaHKd+MyoFC39pwTAIqvsyQeBHe7VCf6CtDe7TbY=" } diff --git a/packages/jsii-pacmak/lib/targets/python.ts b/packages/jsii-pacmak/lib/targets/python.ts index 0ab08ed070..2af57be105 100644 --- a/packages/jsii-pacmak/lib/targets/python.ts +++ b/packages/jsii-pacmak/lib/targets/python.ts @@ -1695,7 +1695,7 @@ class Package { mod.emit(code, context); code.closeFile(filename); - Array.prototype.push.apply(scripts, mod.emitBinScripts(code)); + scripts.push(...mod.emitBinScripts(code)); } // Handle our package data. From 375147b5a4fffd9e0d4ffe73f33bde61be853ca7 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: Fri, 6 Nov 2020 09:45:38 +0100 Subject: [PATCH 07/11] fix snapshots --- .../generated-code/__snapshots__/target-dotnet.test.ts.snap | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/jsii-pacmak/test/generated-code/__snapshots__/target-dotnet.test.ts.snap b/packages/jsii-pacmak/test/generated-code/__snapshots__/target-dotnet.test.ts.snap index 2e4711e95b..93a124a10c 100644 --- a/packages/jsii-pacmak/test/generated-code/__snapshots__/target-dotnet.test.ts.snap +++ b/packages/jsii-pacmak/test/generated-code/__snapshots__/target-dotnet.test.ts.snap @@ -3352,7 +3352,7 @@ exports[`Generated code for "jsii-calc": /dotnet/Amazon.JSII.Tests.Calcu "url": "https://aws.amazon.com" }, "bin": { - "calc": "bin/calc" + "calc": "bin/run" }, "bundled": { "@fixtures/jsii-calc-bundled": "^0.19.0" @@ -17576,7 +17576,7 @@ exports[`Generated code for "jsii-calc": /dotnet/Amazon.JSII.Tests.Calcu } }, "version": "0.0.0", - "fingerprint": "QHc8YZS13IljwCQpg6AZlBxIZvkAbfnCFh6Vi+e0Cgg=" + "fingerprint": "PsDmaHKd+MyoFC39pwTAIqvsyQeBHe7VCf6CtDe7TbY=" } `; From 122b17e3f73c1a02f46a6dd4a15b18425e657aa5 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, 11 Nov 2020 11:12:56 +0100 Subject: [PATCH 08/11] fix linter offense --- packages/@jsii/kernel/lib/kernel.ts | 2 +- packages/@jsii/kernel/test/kernel.test.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/@jsii/kernel/lib/kernel.ts b/packages/@jsii/kernel/lib/kernel.ts index 7286c35821..9d5caf0070 100644 --- a/packages/@jsii/kernel/lib/kernel.ts +++ b/packages/@jsii/kernel/lib/kernel.ts @@ -1,4 +1,5 @@ import * as spec from '@jsii/spec'; +import * as cp from 'child_process'; import * as fs from 'fs-extra'; import * as os from 'os'; import * as path from 'path'; @@ -9,7 +10,6 @@ import * as api from './api'; import { TOKEN_REF } from './api'; import { ObjectTable, tagJsiiConstructor } from './objects'; import * as wire from './serialization'; -import * as cp from 'child_process'; export class Kernel { /** diff --git a/packages/@jsii/kernel/test/kernel.test.ts b/packages/@jsii/kernel/test/kernel.test.ts index 5793d32e4d..343c0d1a82 100644 --- a/packages/@jsii/kernel/test/kernel.test.ts +++ b/packages/@jsii/kernel/test/kernel.test.ts @@ -2216,7 +2216,7 @@ async function preparePackage(module: string, useCache = true) { }); const stdout = new Array(); child.stdout.on('data', (chunk) => stdout.push(Buffer.from(chunk))); - child.once('exit', (code, signal) => { + child.once('close', (code, signal) => { if (code === 0) { return ok(); } From 26b3a5b871da0253ea2c2e1d3f57d62a9471f718 Mon Sep 17 00:00:00 2001 From: Eugene Kozlov Date: Fri, 27 Nov 2020 17:38:11 +0000 Subject: [PATCH 09/11] Add cmd wrapper for Windows --- packages/jsii-calc/bin/run | 2 +- packages/jsii-calc/bin/run.cmd | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 packages/jsii-calc/bin/run.cmd diff --git a/packages/jsii-calc/bin/run b/packages/jsii-calc/bin/run index 319626589d..ea7dde785e 100755 --- a/packages/jsii-calc/bin/run +++ b/packages/jsii-calc/bin/run @@ -1,2 +1,2 @@ #!/usr/bin/env node -require('./run.js'); \ No newline at end of file +require('./run.js'); diff --git a/packages/jsii-calc/bin/run.cmd b/packages/jsii-calc/bin/run.cmd new file mode 100644 index 0000000000..8c083b0bff --- /dev/null +++ b/packages/jsii-calc/bin/run.cmd @@ -0,0 +1,2 @@ +@echo off +node "%~dp0\run" %* From 1d7ced42b97ed131b4bc99103600d8bc616f4114 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, 30 Nov 2020 10:15:52 +0100 Subject: [PATCH 10/11] fix test expectations --- packages/jsii-calc/test/assembly.jsii | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/jsii-calc/test/assembly.jsii b/packages/jsii-calc/test/assembly.jsii index c1947ca7e3..03e458ddc0 100644 --- a/packages/jsii-calc/test/assembly.jsii +++ b/packages/jsii-calc/test/assembly.jsii @@ -14345,5 +14345,5 @@ } }, "version": "0.0.0", - "fingerprint": "55ZmA4GbUYPUmTXM2oFDEND8/Yk2Vzw1FThRWEOigAM=" + "fingerprint": "XfCnzPEGbEJR6hhBX8zWyFzWJP2wH9ztW2ZcW6Wdb+4=" } From f42d16087138cf61ed87337b8e028a78ca7bb5ed Mon Sep 17 00:00:00 2001 From: root Date: Mon, 30 Nov 2020 19:41:47 +0000 Subject: [PATCH 11/11] Fix Windows tests --- packages/jsii-pacmak/lib/targets/python.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/jsii-pacmak/lib/targets/python.ts b/packages/jsii-pacmak/lib/targets/python.ts index 37f6aa0815..0e8c730e95 100644 --- a/packages/jsii-pacmak/lib/targets/python.ts +++ b/packages/jsii-pacmak/lib/targets/python.ts @@ -1525,7 +1525,7 @@ class PythonModule implements PythonType { ')', ); code.closeFile(script_file); - scripts.push(script_file); + scripts.push(script_file.replace(/\\/g, '/')); } } }