Introducing the magical "jsii" that runs programs written in TypeScript with Python etc.

First of all, if you write from the conclusion, you can do something like the figure below.

image.png

This is an example of executing the program written in TypeScript displayed on the upper side from the Python program on the lower side.

It uses a library called jsii to convert ** TypeScript programs into Python-executable libraries **. As the official documentation says the magic happens, it's a magical technique.

jsii can be used in languages such as Java in addition to Python, but in this article, a program written in TypeScript will be executed in Python.

Let's actually do it.

Execution environment of this paper

Try using jsii

You can use jsii roughly in the following flow.

  1. Write the program in TypeScript
  2. Build packages in other languages using jsii
  3. Install and use from other languages

TypeScript program description

As a sample, write an appropriate FizzBuzz program in lib / index.ts with TypeScript.

lib/index.ts


export class MyClass {
  fizzBuzz(arg: number): string {
    if (arg % (3 * 5) === 0) {
      return 'FizzBuzz';
    } else if (arg % 3 === 0) {
      return 'Fizz';
    } else if (arg % 5 === 0) {
      return 'Buzz';
    }
    return arg.toString();
  }
}

If you want to check the operation by executing it normally as TypeScript, execute it by your favorite method such as $ npx ts-node lib / index.ts.

Description of package.json

jsii uses the information of package.json at build time to register the meta information for the library of each language. Therefore, jsii cannot be operated unless package.json is written" properly "to some extent.

The following is a setting example.

package.json


{
  "name": "jsii-example",
  "version": "1.0.0",
  "main": "lib/index.js",
  "types": "lib/index.d.ts",
  "author": "your_name",
  "repository": {
    "url": "https://example.com",
    "type": "Git"
  },
  "license": "MIT",
  "jsii": {
    "outdir": "dist",
    "targets": {
      "python": {
        "distName": "your_name.jsii_example",
        "module": "your_name.jsii_example"
      }
    }
  },
  "devDependencies": {
    "jsii": "^0.20.6",
    "jsii-pacmak": "^0.20.6"
  }
}

As mentioned above, the parts that are usually omitted such as repository and ʻauthorare required when using jsii. Also,main and typesmust be specified in the same directory aslib / index.ts`.

In addition, as a jsii-specific setting, describe the information for each language package in the place called jsii. This time, in order to build the Python package, the module name information is described as python in targets.

Build with jsii

Install the packages required to run the jsii build.

$ npm install --save-dev jsii jsii-pacmak
$ echo "jsii
wheel
publication" > requirements.txt
$ pip install --require requirements.txt

After the above installation is completed, build with the jsii command and package with the jsii-pacmak command.

$ npx jsii
$ npx jsii-pacmak

It is successful if your_name.jsii_example-1.0.0.tar.gz is created in the dist / python directory.

Run from python

Install the package file you just created as a Python library.

$ pip install dist/python/your_name.jsii_example-1.0.0.tar.gz

Import this library and write a Python program that calls the fizzBuzz function.

python.py


import your_name.jsii_example

obj = your_name.jsii_example.MyClass()

print(obj.fizz_buzz(2))
print(obj.fizz_buzz(3))
print(obj.fizz_buzz(5))
print(obj.fizz_buzz(15))

It's finally time to run.

$ python python.py 
2
Fizz
Buzz
FizzBuzz

I was able to call code written in TypeScript from Python!

Use jsii with Docker

Since the execution environment construction described so far requires installation of multiple languages, it is a little troublesome, so this time we have prepared a Dockerfile that can prepare Python and Node.js necessary for executing jsii together.

FROM python:3.7.5-slim

ENV DIR /app
WORKDIR $DIR
RUN apt update && apt install -y nodejs npm

# setup python
COPY requirements.txt $DIR
RUN pip install --requirement requirements.txt

# setup node
COPY package.json $DIR
RUN npm install

# main: lib/index.ts
COPY lib/ $DIR/lib

After preparing the above package.json, requirements.txt, lib / index.ts, use it as follows.

$ mkdir dist
$ docker build --tag jsii-example .
$ docker run --rm --volume $(pwd)/dist:/app/dist jsii-example /bin/bash -c 'npx jsii && npx jsii-pacmak'

It is successful if the package file is generated under dist /.

How jsii works

The mechanism of jsii is explained in the jsii documentation. jsii/runtime-architecture.md at master · aws/jsii

When the host code such as Python reaches the place where jsii is used, it seems that the child process of node is started, the program is executed, and the result is received by Python. If you look in the / tmp directory on your host, you'll find evidence of a temporary npm install of the program.

The documentation also states that ** performance is sacrificed ** because processing that originally ends in Python also depends on communication with Node.js. It is difficult for jsii to operate in applications that require performance such as production environments, and it is expected to be used in development and build tools.

Example of using jsii

jsii is an OSS developed by AWS. As an actual usage example, jsii is used in AWS CDK, which is an Infrastructure as Code tool provided by AWS. Like jsii, aws-cdk allows you to write infrastructure configurations in TypeScript, Python, .NET, and Java.

Quoted from Frequently Asked Questions about AWS Cloud Development

AWS builds the business logic of the AWS Construct library package in TypeScript and provides mappings to each supported programming language. This ensures that AWS CDK constructs behave consistently across different languages and can provide a comprehensive set of construct packages available in all languages. All code created in the AWS CDK project is native to your preferred programming language. The JavaScript runtime is a detailed implementation of your programming experience. You can find the jsii project at https://github.com/aws/jsii.

Tips --There are restrictions on TypeScript that can be executed with jsii --To give an easy-to-understand example, if you try to use reserved words in other languages in TypeScript, they may not work properly. --Other restrictions are described in the documentation. - jsii/typescript-restrictions.md at master · aws/jsii --Not compatible with Python 3.8 --This article runs on Python 3.7.5. When using 3.8.0, an error occurs at the time of writing this article and the library made with jsii cannot be executed. --There is also an issue - Python 3.8.0: ImportError: cannot import name '_Union' from 'typing' · Issue #913 · aws/jsii --Ruby support is under development --Although it is not clearly stated in the document, if you read the History and the source code, you will find some descriptions that seem to be compatible with Ruby. --If you specify ruby in targets in package.json, jsii works properly and a package-like file is generated indist / ruby /, but TypeScript source code is used as it is. Programs to include just seems to be running and gem generation is implemented Is not ... --There is an issue regarding Ruby support - Ruby support · Issue #144 · aws/jsii

Summary

Using jsii, I was able to execute a program written in TypeScript within the Python source code. Although it is still under development and has many restrictions, it has a certain future because it is actually used in AWS CDK. If you want to use a tool created with one code base from multiple languages, I think this jsii is an option.

The program used this time is also posted on GitHub. If you are interested, please have a look. https://github.com/s2terminal/jsii-example

Recommended Posts

Introducing the magical "jsii" that runs programs written in TypeScript with Python etc.
Convert files written in python etc. to pdf with syntax highlighting
Stress Test with Locust written in Python
Display Python 3 in the browser with MAMP
[Python] Get the files in a folder with Python
Load the network modeled with Rhinoceros in Python ②
The one that displays the progress bar in Python
Formulas that appear in Doing Math with Python
Load the network modeled with Rhinoceros in Python ①
The story that fits in with pip installation
Introducing the book "Creating a profitable AI with Python" that allows you to learn machine learning in the shortest course
[Python] Leave only the elements that start with a specific character string in the array
A note that runs an external program in Python and parses the resulting line
[Python] Get the numbers in the graph image with OCR
Use Cursur that closes automatically with sqlite3 in Python
Crawl the URL contained in the twitter tweet with python
Convert the image in .zip to PDF with Python
Get the result in dict format with Python psycopg2
Write letters in the card illustration with OpenCV python
Find the part that is 575 from Wikipedia in Python
A memo that I touched the Datastore with python
Modules that may go through the shell in Python
Try scraping the data of COVID-19 in Tokyo with Python
Let's create a script that registers with Ideone.com in Python.
Use a macro that runs when saving python with vscode
The story that `while queue` did not work in python
[CleanArchitecture with Python] Part2: Frameworks & Drivers Layer: Introducing the Web
[Homology] Count the number of holes in data with Python
The story that Python stopped working with VS Code (Windows 10)
Treat the Interface class like that with Python type annotations
About netaddr that operates IP address, CIDR, etc. in Python
If you think that the person you put in with pip doesn't work → Maybe you are using python3?
I bought and analyzed the year-end jumbo lottery with Python that can be executed in Colaboratory
A story that didn't work when I tried to log in with the Python requests module
The story of creating a bot that displays active members in a specific channel of slack with python