Experimental minimal installer for js modules from npmjs.org

This commit is contained in:
Alessandro Molina 2016-04-11 00:01:16 +02:00
parent ebf52caf6e
commit 42ccb3ac9d
6 changed files with 135 additions and 4 deletions

View File

@ -2,4 +2,5 @@ from .evaljs import evaljs, JSInterpreter
from ._dukpy import JSRuntimeError
from .coffee import coffee_compile
from .babel import babel_compile, jsx_compile
from .tsc import typescript_compile
from .tsc import typescript_compile
from .install import install_jspackage

View File

@ -95,7 +95,8 @@ class JSInterpreter(object):
var m = call_python('dukpy.lookup_module', id);
if (!m)
throw new Error('cannot find module: ' + id);
return m;
module.filename = m[0];
return m[1];
};
""")

80
dukpy/install.py Normal file
View File

@ -0,0 +1,80 @@
# -*- coding: utf-8 -*-
from __future__ import print_function
import json
import os
import sys
import tarfile
import tempfile
import shutil
from contextlib import closing
from io import BytesIO
try:
from urllib.request import urlopen
except ImportError:
from urllib2 import urlopen
def main():
args = sys.argv[1:]
try:
package_name = args[0]
version = args[1]
except:
print('Usage: dukpy-install package_name version')
print('')
print('Downloads a specific package version from npmjs.org. Note this is'
'a very basic script that does not support dependencies.')
return 1
install_jspackage(package_name, version, './node_modules')
def install_jspackage(package_name, version, modulesdir):
"""Installs a JavaScript package downloaded from npmjs.org.
For example to install React::
install_jspackage('react', '0.14.8', './node_modules')
"""
url = 'http://registry.npmjs.org/{}'
with closing(urlopen(url.format(package_name))) as data:
package_info = json.loads(data.read())
package_versions = package_info['versions']
version_info = package_versions.get(version)
if version_info is None:
print('Version {} not found, available versions are {}'.format(
version, ', '.join(sorted(package_versions.keys()))
))
return 2
try:
download_url = version_info['dist']['tarball']
except KeyError:
print('Unable to detect a supported download url for package')
return 3
tarball = BytesIO()
print('Downloading {}'.format(download_url))
with closing(urlopen(download_url)) as data:
chunk = data.read(1024)
while chunk:
print('.', end='')
tarball.write(chunk)
chunk = data.read(1024)
print('')
tarball.seek(0)
print('Extracting... ')
with tarfile.open(fileobj=tarball) as tb:
dest = os.path.join(modulesdir, version_info['name'])
tmpdir = tempfile.mkdtemp()
try:
tb.extractall(tmpdir)
shutil.move(os.path.join(tmpdir, 'package'),
os.path.abspath(dest))
finally:
shutil.rmtree(tmpdir)
print('Installed in {}'.format(dest))

View File

@ -40,7 +40,7 @@ class JSModuleLoader(object):
path = self.lookup(module_name)
if path:
with open(path, 'rb') as f:
return f.read().decode('utf-8')
return path, f.read().decode('utf-8')
def _lookup(self, module_path):
# Module is a plain .js file

View File

@ -40,5 +40,10 @@ setup(
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 2.6',
'Programming Language :: JavaScript',
]
],
entry_points={
'console_scripts': [
'dukpy-install = dukpy.install:main'
]
}
)

44
tests/test_installer.py Normal file
View File

@ -0,0 +1,44 @@
# -*- coding: utf-8 -*-
import shutil
import tempfile
import dukpy
class TestPackageInstaller(object):
def setup(self):
self.tmpdir = tempfile.mkdtemp()
def tearDown(self):
#shutil.rmtree(self.tmpdir)
pass
def test_install_react(self):
dukpy.install_jspackage('react', '0.14.8', self.tmpdir)
dukpy.install_jspackage('react-dom', '0.14.8', self.tmpdir)
dukpy.install_jspackage('fbjs', '0.8.0', self.tmpdir)
jsx = dukpy.jsx_compile(TEST_CODE)
jsi = dukpy.JSInterpreter()
jsi.loader.register_path(self.tmpdir)
res = jsi.evaljs(jsx, data={'id': 1, 'name': "Alessandro"})
assert res == '<div class="helloworld">Hello Alessandro</div>', res
TEST_CODE = '''
var React = require('react/react'),
ReactDOM = require('react-dom/server');
var HelloWorld = React.createClass({
render: function() {
return (
<div className="helloworld">
Hello {this.props.data.name}
</div>
);
}
});
ReactDOM.renderToStaticMarkup(<HelloWorld data={dukpy.data}/>, null);
'''