Skip to content

Commit

Permalink
feat: add invokeBinScript function
Browse files Browse the repository at this point in the history
  • Loading branch information
kozlove-aws authored and root committed Sep 11, 2020
1 parent aaf8d7e commit 7e9c9e2
Show file tree
Hide file tree
Showing 8 changed files with 123 additions and 11 deletions.
13 changes: 13 additions & 0 deletions packages/@jsii/kernel/lib/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down
40 changes: 30 additions & 10 deletions packages/@jsii/kernel/lib/kernel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
/**
Expand Down Expand Up @@ -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'));
Expand All @@ -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'));
Expand Down Expand Up @@ -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);
}
Expand Down
15 changes: 15 additions & 0 deletions packages/@jsii/python-runtime/src/jsii/_kernel/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
EndRequest,
GetRequest,
InvokeRequest,
InvokeScriptRequest,
SetRequest,
StaticGetRequest,
StaticInvokeRequest,
Expand Down Expand Up @@ -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:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
GetResponse,
InvokeRequest,
InvokeResponse,
InvokeScriptRequest,
InvokeScriptResponse,
DeleteRequest,
DeleteResponse,
SetRequest,
Expand Down Expand Up @@ -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:
...
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@
GetResponse,
InvokeRequest,
InvokeResponse,
InvokeScriptRequest,
InvokeScriptResponse,
SetRequest,
SetResponse,
StaticGetRequest,
Expand Down Expand Up @@ -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),
Expand Down Expand Up @@ -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)

Expand Down
19 changes: 19 additions & 0 deletions packages/@jsii/python-runtime/src/jsii/_kernel/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:

Expand Down Expand Up @@ -226,6 +243,7 @@ class StatsResponse:
GetRequest,
StaticGetRequest,
InvokeRequest,
InvokeScriptRequest,
StaticInvokeRequest,
StatsRequest,
]
Expand All @@ -237,6 +255,7 @@ class StatsResponse:
DeleteResponse,
GetResponse,
InvokeResponse,
InvokeScriptResponse,
SetResponse,
StatsResponse,
Callback,
Expand Down
4 changes: 4 additions & 0 deletions packages/@jsii/python-runtime/src/jsii/_runtime.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down
28 changes: 27 additions & 1 deletion packages/jsii-pacmak/lib/targets/python.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down

0 comments on commit 7e9c9e2

Please sign in to comment.