nodejs-pypi
nodejs-pypi copied to clipboard
Planned Python API, request for feedback.
The current planned Python API for nodejs-bin would be very limited.
Because nodejs-bin versions are tied to Node.js versions exactly we have to fix this api for the forceable future and will be unable to iterate on it once nodejs-bin goes stable.
For node
itself and other included comments such as npm
, npx
etc there would be a run()
and start()
function:
from nodejs import node, npm, npx
# Run Node.js and return the exit code.
node.run(['script.js', 'arg1', ...], **kwargs)
# Run npm and return the exit code.
npm.run(['command', 'arg1', ...], **kwargs)
# Run npx and return the exit code.
npx.run(['command', 'arg1', ...], **kwargs)
The run(args, **kwargs)
functions wrap subprocess.call()
, passes though all kwargs
and returns the exit code of the process.
Additionally, to start a Node.js process and return a subprocess.Popen
object, you can use the start(args, **kwargs)
functions:
from nodejs import node, npm, npx
# Start Node.js and return the Popen object.
node_process = node.start(['script.js', 'arg1', ...], **kwargs)
# Start npm and return the Popen object.
npm_process = npm.start(['command', 'arg1', ...], **kwargs)
# Start npx and return the Popen object.
npx_process = npx.start(['command', 'arg1', ...], **kwargs)
The start(args, **kwargs)
functions wrap subprocess.Popen()
, passes though all kwargs
and returns a Popen
object.
It would also be possible to do just:
import nodejs
nodejs.run(['script.js', 'arg1', ...], **kwargs)
node_process = nodejs.start(['script.js', 'arg1', ...], **kwargs)
Finally, there will be:
import nodejs
nodejs.__version__
# The version of the nodejs-bin package, it will always start with the version of node itself
# However for an alpha release it would have an 'aN' suffix
# or a 'build' for post release, such as '-1' (useful if find a problem with the packaging of a release)
nodejs.node_version
# The version of node itself
nodejs.path
# The path (str) to the node binary that has been installed
See PEP 440 for details of the version string: https://peps.python.org/pep-0440/
My two cents:
Change the API to be of the form:
node.run("script.js", "argument 1", **kwargs)
There's less scope for getting the wrong data type in the arguments, enforces explicitness for all the keyword arguments (something you seem to want already) and requires less typing on the user's end. This is similar to what nox's Session object does, which is where I'm pulling this suggestion from. :)
Unlike Popen, you likely don't want to take a string with already-escaped arguments that you'd pass with shell=True
-- so args don't need to be a dedicated argument and can instead be a *args
Thanks Pradyun,
That was my original plan, however as it's such a thin wrapper around subprocess.call()
(and subprocess.Popen()
), really just setting the first args, I'm cautious of deveating too far from the signature of the original functions.
I now realise run()
should probably wrap the newer subprocess.run()
and also have a call()
wrapping subprocess.call()
, and while I'm at it change start()
to Popen()
so it indicates it wraps subprocess.Popen()
.
Also just to note; while for node
these are just setting the first arg to the path to the installed node binary. For npm
and npx
they actually differ between Windows and Mac/Posix. On Windows there are npm.cmd
and npx.cmd
binaries, whereas on the others they call node /path/to/np[n,x]/script.js
.
My thinking/hope is that someone will create an elegant api that wraps node in a much more Pythonic way, however I think it's best to keep node-bin super simple.
Update:
New version "a2" released doing this.