{"id":15546872,"url":"https://github.com/zimmermanncode/nodely","last_synced_at":"2026-04-13T22:33:45.393Z","repository":{"id":57446532,"uuid":"101510407","full_name":"zimmermanncode/nodely","owner":"zimmermanncode","description":"putMORE Node.js into Python","archived":false,"fork":false,"pushed_at":"2019-08-19T07:32:07.000Z","size":104,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-09-09T03:47:18.135Z","etag":null,"topics":["node","node-modules","nodejs","npm","npmjs","python","python-environment","python-setup"],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"lgpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/zimmermanncode.png","metadata":{"files":{"readme":"README.ipynb","changelog":"CHANGES.md","contributing":null,"funding":null,"license":"COPYING","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-08-26T20:08:37.000Z","updated_at":"2019-08-19T07:32:09.000Z","dependencies_parsed_at":"2022-09-02T23:40:50.334Z","dependency_job_id":null,"html_url":"https://github.com/zimmermanncode/nodely","commit_stats":null,"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"purl":"pkg:github/zimmermanncode/nodely","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zimmermanncode%2Fnodely","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zimmermanncode%2Fnodely/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zimmermanncode%2Fnodely/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zimmermanncode%2Fnodely/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/zimmermanncode","download_url":"https://codeload.github.com/zimmermanncode/nodely/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zimmermanncode%2Fnodely/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31774028,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-13T20:17:16.280Z","status":"ssl_error","status_checked_at":"2026-04-13T20:17:08.216Z","response_time":93,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["node","node-modules","nodejs","npm","npmjs","python","python-environment","python-setup"],"created_at":"2024-10-02T13:05:10.354Z","updated_at":"2026-04-13T22:33:45.365Z","avatar_url":"https://github.com/zimmermanncode.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"{\n \"cells\": [\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"# nodely \u003e\u003e\u003e putMORE Node.js into Python\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"[![](http://www.gnu.org/graphics/lgplv3-88x31.png)](\\n\",\n    \"  https://gnu.org/licenses/lgpl.html)\\n\",\n    \"[![](https://img.shields.io/pypi/pyversions/nodely.svg)](\\n\",\n    \"  https://python.org)\\n\",\n    \"[![](https://img.shields.io/pypi/v/nodely.svg)](\\n\",\n    \"  https://pypi.python.org/pypi/nodely)\\n\",\n    \"[![](https://img.shields.io/pypi/dd/nodely.svg)](\\n\",\n    \"  https://pypi.python.org/pypi/nodely)\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"[![](https://travis-ci.org/zimmermanncode/nodely.svg)](\\n\",\n    \"  https://travis-ci.org/zimmermanncode/nodely)\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"* [**Embed**](#Embed-node_modules/-in-Python-environments)\\n\",\n    \"  **`node_modules/` in Python environments**\\n\",\n    \"* [**`require`**](#require_node_modules-in-setup.py)**`_node_modules`\\n\",\n    \"  in setup.py** \\n\",\n    \"* [**Run**](#Run-installed-Node.js-tools-from-Python)\\n\",\n    \"  **installed Node.js tools from Python**\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"### Setup\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Use [pip](http://pip-installer.org) to install the latest [release](\\n\",\n    \"  https://pypi.python.org/pypi/nodely) from [PyPI](https://pypi.python.org):\\n\",\n    \"\\n\",\n    \"\u003e `pip install nodely`\\n\",\n    \"\\n\",\n    \"And don't forget to install [Node.js](https://nodejs.org) ;)\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"### Embed `node_modules/` in Python environments\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 1,\n   \"metadata\": {\n    \"collapsed\": true\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"import nodely\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Many great tools are written with JavaScript in [Node.js](https://nodejs.org).\\n\",\n    \"It makes sense to use them in Python instead of reinventing the wheel.\\n\",\n    \"`nodely` provides an API for managing local `node_modules/` in Python environments\\n\",\n    \"and running the installed Node.js tools from Python\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"If the root directory of the current Python environment is:\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 2,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/plain\": [\n       \"'C:\\\\\\\\Users\\\\\\\\Zimmermann\\\\\\\\Miniconda3\\\\\\\\envs\\\\\\\\nodely'\"\n      ]\n     },\n     \"execution_count\": 2,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"import sys\\n\",\n    \"\\n\",\n    \"sys.prefix\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Then `nodely` will create:\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 3,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/plain\": [\n       \"Path('C:\\\\\\\\Users\\\\\\\\Zimmermann\\\\\\\\Miniconda3\\\\\\\\envs\\\\\\\\nodely\\\\\\\\node_modules')\"\n      ]\n     },\n     \"execution_count\": 3,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"nodely.NODE_MODULES_DIR\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"_Please don't modify the above constant, except you exactly know what you are doing ;)_\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Let's say you want to use the [CoffeeScript](http://coffeescript.org) compiler...\\n\",\n    \"Just install the Node.js package:\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 4,\n   \"metadata\": {\n    \"collapsed\": true\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"nodely.install('coffee-script')\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"It provides the `coffee` executable. If you want to know its absolute path:\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 5,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/plain\": [\n       \"Path('C:\\\\\\\\Users\\\\\\\\Zimmermann\\\\\\\\Miniconda3\\\\\\\\envs\\\\\\\\nodely\\\\\\\\node_modules\\\\\\\\.bin\\\\\\\\coffee.CMD')\"\n      ]\n     },\n     \"execution_count\": 5,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"nodely.which('coffee')\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"And if you want to run it, for example with the `--version` flag:\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 6,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/plain\": [\n       \"0\"\n      ]\n     },\n     \"execution_count\": 6,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"nodely.call('coffee', ['--version'])\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"For the case that you want to get rid of the package again,\\n\",\n    \"just `nodely.uninstall('coffee-script')` it\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"### `require_node_modules` in setup.py\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Instead of installing Node.js packages during runtime,\\n\",\n    \"you can also define them as dependencies of your Python package:\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"```python\\n\",\n    \"from setuptools import setup\\n\",\n    \"\\n\",\n    \"setup(\\n\",\n    \"    ...\\n\",\n    \"    setup_requires=['nodely', ...],\\n\",\n    \"    require_node_modules=['coffee-script', ...],\\n\",\n    \"    ...\\n\",\n    \")\\n\",\n    \"```\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"So they get implicitly installed during the installation of the Python package,\\n\",\n    \"just like the Python dependencies defined in `install_requires`\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"### Run installed Node.js tools from Python\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"The `nodely.call` function additionally supports `subprocess.call` options:\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 7,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/plain\": [\n       \"0\"\n      ]\n     },\n     \"execution_count\": 7,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"from subprocess import DEVNULL\\n\",\n    \"\\n\",\n    \"nodely.call('coffee', ['--version'], stdout=DEVNULL)\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"And instead of a simple `nodely.call`,\\n\",\n    \"you can also create a process instance,\\n\",\n    \"and give any `subprocess.Popen` options to it:\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 8,\n   \"metadata\": {\n    \"collapsed\": true\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"from subprocess import PIPE\\n\",\n    \"\\n\",\n    \"process = nodely.Popen('coffee', ['--version'], stdout=PIPE,\\n\",\n    \"                       universal_newlines=True)\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 9,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/plain\": [\n       \"'1.12.7'\"\n      ]\n     },\n     \"execution_count\": 9,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"process.communicate()[0].split()[-1]\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"A more object-oriented approach is provided by:\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 10,\n   \"metadata\": {\n    \"collapsed\": true\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"import nodely.bin\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"It lets you introspect all installed executables with interactive auto-completion\\n\",\n    \"and creates `nodely.bin.Command` instances:\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 11,\n   \"metadata\": {\n    \"collapsed\": true\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"coffee = nodely.bin.coffee\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"`nodely.bin['coffee']` returns the same.\\n\",\n    \"And that `nodely.bin.Command` instance provides its own `.call` and a `.Popen` methods,\\n\",\n    \"and can also be called directly instead of using its `.call` method:\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 12,\n   \"metadata\": {},\n   \"outputs\": [\n    {\n     \"data\": {\n      \"text/plain\": [\n       \"0\"\n      ]\n     },\n     \"execution_count\": 12,\n     \"metadata\": {},\n     \"output_type\": \"execute_result\"\n    }\n   ],\n   \"source\": [\n    \"coffee(['--version'])\"\n   ]\n  }\n ],\n \"metadata\": {\n  \"kernelspec\": {\n   \"display_name\": \"Python 3\",\n   \"language\": \"python\",\n   \"name\": \"python3\"\n  },\n  \"language_info\": {\n   \"codemirror_mode\": {\n    \"name\": \"ipython\",\n    \"version\": 3\n   },\n   \"file_extension\": \".py\",\n   \"mimetype\": \"text/x-python\",\n   \"name\": \"python\",\n   \"nbconvert_exporter\": \"python\",\n   \"pygments_lexer\": \"ipython3\",\n   \"version\": \"3.6.2\"\n  }\n },\n \"nbformat\": 4,\n \"nbformat_minor\": 2\n}\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzimmermanncode%2Fnodely","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzimmermanncode%2Fnodely","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzimmermanncode%2Fnodely/lists"}