nodely >>> putMORE Node.js into Python

  • Embed node_modules/ in Python environments
  • require_node_modules in setup.py
  • Run installed Node.js tools from Python

Setup

Use pip to install the latest release from PyPI:

pip install nodely

And don't forget to install Node.js ;)

Embed node_modules/ in Python environments


In [1]:
import nodely

Many great tools are written with JavaScript in Node.js. It makes sense to use them in Python instead of reinventing the wheel. nodely provides an API for managing local node_modules/ in Python environments and running the installed Node.js tools from Python

If the root directory of the current Python environment is:


In [2]:
import sys

sys.prefix


Out[2]:
'C:\\Users\\Zimmermann\\Miniconda3\\envs\\nodely'

Then nodely will create:


In [3]:
nodely.NODE_MODULES_DIR


Out[3]:
Path('C:\\Users\\Zimmermann\\Miniconda3\\envs\\nodely\\node_modules')

Please don't modify the above constant, except you exactly know what you are doing ;)

Let's say you want to use the CoffeeScript compiler... Just install the Node.js package:


In [4]:
nodely.install('coffee-script')

It provides the coffee executable. If you want to know its absolute path:


In [5]:
nodely.which('coffee')


Out[5]:
Path('C:\\Users\\Zimmermann\\Miniconda3\\envs\\nodely\\node_modules\\.bin\\coffee.CMD')

And if you want to run it, for example with the --version flag:


In [6]:
nodely.call('coffee', ['--version'])


Out[6]:
0

For the case that you want to get rid of the package again, just nodely.uninstall('coffee-script') it

require_node_modules in setup.py

Instead of installing Node.js packages during runtime, you can also define them as dependencies of your Python package:

from setuptools import setup

setup(
    ...
    setup_requires=['nodely', ...],
    require_node_modules=['coffee-script', ...],
    ...
)

So they get implicitly installed during the installation of the Python package, just like the Python dependencies defined in install_requires

Run installed Node.js tools from Python

The nodely.call function additionally supports subprocess.call options:


In [7]:
from subprocess import DEVNULL

nodely.call('coffee', ['--version'], stdout=DEVNULL)


Out[7]:
0

And instead of a simple nodely.call, you can also create a process instance, and give any subprocess.Popen options to it:


In [8]:
from subprocess import PIPE

process = nodely.Popen('coffee', ['--version'], stdout=PIPE,
                       universal_newlines=True)

In [9]:
process.communicate()[0].split()[-1]


Out[9]:
'1.12.7'

A more object-oriented approach is provided by:


In [10]:
import nodely.bin

It lets you introspect all installed executables with interactive auto-completion and creates nodely.bin.Command instances:


In [11]:
coffee = nodely.bin.coffee

nodely.bin['coffee'] returns the same. And that nodely.bin.Command instance provides its own .call and a .Popen methods, and can also be called directly instead of using its .call method:


In [12]:
coffee(['--version'])


Out[12]:
0