diff --git a/.travis.yml b/.travis.yml
index b4129d7..0949de8 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,36 +1,30 @@
dist: trusty
language: python
+addons:
+ firefox: "latest"
+
python:
- "2.7"
- "3.3"
- "3.4"
- "3.5"
+ - "3.6"
env:
global:
- - "SLIMERJSLAUNCHER=$(which firefox)"
- - "DISPLAY=:99.0"
- - "PATH=$TRAVIS_BUILD_DIR/slimerjs:$PATH"
- "JDK=oracle8"
jdk:
- oraclejdk8
install:
- - "sh -e /etc/init.d/xvfb start"
- - "echo 'Installing Slimer'"
- - "wget http://download.slimerjs.org/releases/0.9.6/slimerjs-0.9.6-linux-x86_64.tar.bz2"
- - "tar xvf slimerjs-*.tar.bz2"
- - "rm slimerjs-*.tar.bz2"
- - "mv slimerjs-* slimerjs"
- "sudo apt-get install -y oracle-java8-installer phantomjs libmozjs-24-bin"
- "sudo ln -s /usr/bin/js24 /usr/bin/js"
- "./install_development.sh"
- "python setup.py install"
script:
- - "slimerjs --version"
- "jjs -v < /dev/null"
- "js --help"
- "node --version && node --help"
diff --git a/README.md b/README.md
index c820530..e89124c 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,16 @@
-PyExecJS
-========
+PyExecJS (EOL)
+==============
[](https://travis-ci.org/doloopwhile/PyExecJS)
+# End of life
+
+This library is no longer maintananced ([Reason](https://gist.github.com/doloopwhile/8c6ec7dd4703e8a44e559411cb2ea221)).
+Bugs are not be fixed (even if they are trivial or essential).
+
+We suggest to use other library or to make a fork.
+
+---
+
Run JavaScript code from Python.
PyExecJS is a porting of ExecJS from Ruby.
@@ -22,14 +31,19 @@ A short example:
# Supported runtimes
+## First-class support (runtime class is provided and tested)
+
* [PyV8](http://code.google.com/p/pyv8/) - A python wrapper for Google V8 engine,
* [Node.js](http://nodejs.org/)
+* [PhantomJS](http://phantomjs.org/)
+* [Nashorn](http://docs.oracle.com/javase/8/docs/technotes/guides/scripting/nashorn/intro.html#sthref16) - Included with Oracle Java 8
+
+## Second-class support (runtime class is privided but not tested)
+
* Apple JavaScriptCore - Included with Mac OS X
-* [Mozilla SpiderMonkey](http://www.mozilla.org/js/spidermonkey/)
* [Microsoft Windows Script Host](http://msdn.microsoft.com/en-us/library/9bbdkx3k.aspx) (JScript)
* [SlimerJS](http://slimerjs.org/)
-* [PhantomJS](http://phantomjs.org/)
-* [Nashorn](http://docs.oracle.com/javase/8/docs/technotes/guides/scripting/nashorn/intro.html#sthref16) - Included with Oracle Java 8
+* [Mozilla SpiderMonkey](http://www.mozilla.org/js/spidermonkey/)
# Installation
@@ -79,6 +93,14 @@ Released under the MIT license. See `LICENSE` for details.
# Changelog
+## 1.5.0
+- Eased version requirement for six.
+
+## 1.4.1
+- Fixed arguments of module-level functions.
+- Fixed bug of execution with pipe.
+- Fixed wrong excption is raised.
+
## 1.4.0
- Fixed required libraries.
- Fixed order of output of `--print-available-runtimes`.
diff --git a/README.rst b/README.rst
index e84efa9..e3a5e83 100644
--- a/README.rst
+++ b/README.rst
@@ -1,5 +1,15 @@
-PyExecJS
-========
+PyExecJS (EOL)
+==============
+
+End of life
+===========
+
+This library is no longer maintananced. Bugs are not be fixed (even if
+they are trivial or essential).
+
+We suggest to use other library or to make a fork.
+
+--------------
Run JavaScript code from Python.
@@ -24,18 +34,25 @@ A short example:
Supported runtimes
==================
+First-class support (runtime class is provided and tested)
+----------------------------------------------------------
+
- `PyV8 `__ - A python wrapper for
Google V8 engine,
- `Node.js `__
+- `PhantomJS `__
+- `Nashorn `__
+ - Included with Oracle Java 8
+
+Second-class support (runtime class is privided but not tested)
+---------------------------------------------------------------
+
- Apple JavaScriptCore - Included with Mac OS X
-- `Mozilla SpiderMonkey `__
- `Microsoft Windows Script
Host `__
(JScript)
- `SlimerJS `__
-- `PhantomJS `__
-- `Nashorn `__
- - Included with Oracle Java 8
+- `Mozilla SpiderMonkey `__
Installation
============
@@ -101,6 +118,18 @@ Released under the MIT license. See ``LICENSE`` for details.
Changelog
=========
+1.5.0
+-----
+
+- Eased version requirement for six.
+
+1.4.1
+-----
+
+- Fixed arguments of module-level functions.
+- Fixed bug of execution with pipe.
+- Fixed wrong excption is raised.
+
1.4.0
-----
diff --git a/execjs/__init__.py b/execjs/__init__.py
index 394a357..98a4bea 100755
--- a/execjs/__init__.py
+++ b/execjs/__init__.py
@@ -22,7 +22,13 @@
'''
from __future__ import unicode_literals, division, with_statement
-from execjs._exceptions import Error, RuntimeError, ProgramError, RuntimeUnavailableError
+from execjs._exceptions import (
+ Error,
+ RuntimeError,
+ ProgramError,
+ RuntimeUnavailableError,
+)
+
import execjs._runtimes
from execjs._external_runtime import ExternalRuntime
from execjs._abstract_runtime import AbstractRuntime
@@ -41,16 +47,16 @@
get_from_environment = execjs._runtimes.get_from_environment
-def eval(source):
- return get().eval(source)
-eval.__doc__= AbstractRuntime.eval.__doc__
+def eval(source, cwd=None):
+ return get().eval(source, cwd)
+eval.__doc__ = AbstractRuntime.eval.__doc__
-def exec_(source):
- return get().exec_(source)
-exec_.__doc__= AbstractRuntime.exec_.__doc__
+def exec_(source, cwd=None):
+ return get().exec_(source, cwd)
+exec_.__doc__ = AbstractRuntime.exec_.__doc__
-def compile(source):
- return get().compile(source)
-compile.__doc__= AbstractRuntime.compile.__doc__
+def compile(source, cwd=None):
+ return get().compile(source, cwd)
+compile.__doc__ = AbstractRuntime.compile.__doc__
diff --git a/execjs/_exceptions.py b/execjs/_exceptions.py
index 876cb22..0723550 100644
--- a/execjs/_exceptions.py
+++ b/execjs/_exceptions.py
@@ -1,14 +1,24 @@
+# Abstract base error classes
class Error(Exception):
pass
-
+# Abstract class that represents errors of runtime engine.
+# ex. Specified runtime engine is not installed, runtime engine aborted (by its bugs).
+# By the way "RuntimeError" is bad name because it is confusing with the standard exception.
class RuntimeError(Error):
pass
+# Concrete runtime error classes
+class RuntimeUnavailableError(RuntimeError): pass
-class ProgramError(Error):
- pass
+class ProcessExitedWithNonZeroStatus(RuntimeError):
+ def __init__(self, status, stdout, stderr):
+ RuntimeError.__init__(self, status, stdout, stderr)
+ self.status = status
+ self.stdout = stdout
+ self.stderr = stderr
-
-class RuntimeUnavailableError(RuntimeError):
+# Errors due to JS script.
+# ex. Script has syntax error, executed and raised exception.
+class ProgramError(Error):
pass
diff --git a/execjs/_external_runtime.py b/execjs/_external_runtime.py
index dceec83..2b05c16 100644
--- a/execjs/_external_runtime.py
+++ b/execjs/_external_runtime.py
@@ -11,7 +11,12 @@
import six
import execjs._json2 as _json2
import execjs._runner_sources as _runner_sources
-import execjs._exceptions as exceptions
+
+from execjs._exceptions import (
+ ProcessExitedWithNonZeroStatus,
+ ProgramError
+)
+
from execjs._abstract_runtime import AbstractRuntime
from execjs._abstract_runtime_context import AbstractRuntimeContext
from execjs._misc import encode_unicode_codepoints
@@ -44,7 +49,7 @@ def is_available(self):
return self._available
def _compile(self, source, cwd=None):
- return self.Context(self, source, cwd=cwd, tempfile=tempfile)
+ return self.Context(self, source, cwd=cwd, tempfile=self._tempfile)
def _binary(self):
if not hasattr(self, "_binary_cache"):
@@ -92,7 +97,10 @@ def _exec_with_pipe(self, source):
p = None
try:
p = Popen(cmd, stdin=PIPE, stdout=PIPE, stderr=PIPE, cwd=self._cwd, universal_newlines=True)
- stdoutdata, stderrdata = p.communicate(input=source)
+ input = self._compile(source)
+ if six.PY2:
+ input = input.encode(sys.getfilesystemencoding())
+ stdoutdata, stderrdata = p.communicate(input=input)
ret = p.wait()
finally:
del p
@@ -110,7 +118,7 @@ def _exec_with_tempfile(self, source):
p = None
try:
- p = Popen(cmd, stdout=PIPE, stderr=PIPE, cwd=self._cwd)
+ p = Popen(cmd, stdout=PIPE, stderr=PIPE, cwd=self._cwd, universal_newlines=True)
stdoutdata, stderrdata = p.communicate()
ret = p.wait()
finally:
@@ -123,7 +131,7 @@ def _exec_with_tempfile(self, source):
def _fail_on_non_zero_status(self, status, stdoutdata, stderrdata):
if status != 0:
- raise exceptions.RuntimeError("stdout: {}, stderr: {}".format(repr(stdoutdata), repr(stderrdata)))
+ raise ProcessExitedWithNonZeroStatus(status=status, stdout=stdoutdata, stderr=stderrdata)
def _compile(self, source):
runner_source = self._runtime._runner_source
@@ -145,24 +153,18 @@ def _compile(self, source):
return runner_source
def _extract_result(self, output):
- output = output.decode(self._runtime._encoding)
output = output.replace("\r\n", "\n").replace("\r", "\n")
output_last_line = output.split("\n")[-2]
- if not output_last_line:
- status = value = None
- else:
- ret = json.loads(output_last_line)
- if len(ret) == 1:
- ret = [ret[0], None]
- status, value = ret
+ ret = json.loads(output_last_line)
+ if len(ret) == 1:
+ ret = [ret[0], None]
+ status, value = ret
if status == "ok":
return value
- elif value.startswith('SyntaxError:'):
- raise exceptions.RuntimeError(value)
else:
- raise exceptions.ProgramError(value)
+ raise ProgramError(value)
def _is_windows():
@@ -241,7 +243,8 @@ def jsc():
return ExternalRuntime(
name="JavaScriptCore",
command=["/System/Library/Frameworks/JavaScriptCore.framework/Versions/A/Resources/jsc"],
- runner_source=_runner_sources.JavaScriptCore
+ runner_source=_runner_sources.JavaScriptCore,
+ tempfile=True
)
@@ -249,7 +252,8 @@ def spidermonkey():
return ExternalRuntime(
name="SpiderMonkey",
command=["js"],
- runner_source=_runner_sources.SpiderMonkey
+ runner_source=_runner_sources.SpiderMonkey,
+ tempfile=True
)
@@ -267,7 +271,8 @@ def phantomjs():
return ExternalRuntime(
name="PhantomJS",
command=["phantomjs"],
- runner_source=_runner_sources.PhantomJS
+ runner_source=_runner_sources.PhantomJS,
+ tempfile=True
)
@@ -275,7 +280,8 @@ def slimerjs():
return ExternalRuntime(
name="SlimerJS",
command=["slimerjs"],
- runner_source=_runner_sources.SlimerJS
+ runner_source=_runner_sources.SlimerJS,
+ tempfile=True
)
@@ -283,5 +289,6 @@ def nashorn():
return ExternalRuntime(
name="Nashorn",
command=["jjs"],
- runner_source=_runner_sources.Nashorn
+ runner_source=_runner_sources.Nashorn,
+ tempfile=True
)
diff --git a/execjs/_pyv8runtime.py b/execjs/_pyv8runtime.py
index c5edcff..06ddcb7 100644
--- a/execjs/_pyv8runtime.py
+++ b/execjs/_pyv8runtime.py
@@ -1,5 +1,4 @@
import json
-import contextlib
import execjs._exceptions as exceptions
from execjs._abstract_runtime import AbstractRuntime
@@ -48,12 +47,12 @@ def _exec_(self, source):
source = str(source)
# backward compatibility
- with contextlib.nested(PyV8.JSContext(), PyV8.JSEngine()) as (ctxt, engine):
+ with PyV8.JSContext() as ctxt, PyV8.JSEngine() as engine:
js_errors = (PyV8.JSError, IndexError, ReferenceError, SyntaxError, TypeError)
try:
script = engine.compile(source)
except js_errors as e:
- raise exceptions.RuntimeError(e)
+ raise exceptions.ProgramError(e)
try:
value = script.run()
except js_errors as e:
diff --git a/setup.py b/setup.py
index f09e310..68689ea 100755
--- a/setup.py
+++ b/setup.py
@@ -5,7 +5,7 @@
import sys
import io
-version = '1.4.0'
+version = '1.5.1'
author = "Omoto Kenji"
license = "MIT License"
author_email = 'doloopwhile@gmail.com'
@@ -39,6 +39,6 @@
'Programming Language :: Python :: 3.5',
'Programming Language :: JavaScript',
],
- install_requires=["six==1.10.0"],
+ install_requires=["six >= 1.10.0"],
test_suite="test_execjs",
)
diff --git a/test_execjs.py b/test_execjs.py
index 5e7f815..146865a 100755
--- a/test_execjs.py
+++ b/test_execjs.py
@@ -25,7 +25,7 @@ def test_nested_context_call(self):
def test_context_call_missing_function(self):
context = self.runtime.compile("")
- with self.assertRaises(execjs.ProgramError):
+ with self.assertRaises(execjs.Error):
context.call("missing")
def test_exec(self):
@@ -75,11 +75,11 @@ def test_compile_large_scripts(self):
self.assertTrue(self.runtime.exec_(code))
def test_syntax_error(self):
- with self.assertRaises(execjs.RuntimeError):
+ with self.assertRaises(execjs.Error):
self.runtime.exec_(")")
def test_thrown_exception(self):
- with self.assertRaises(execjs.ProgramError):
+ with self.assertRaises(execjs.Error):
self.runtime.exec_("throw 'hello'")
def test_broken_substitutions(self):
@@ -91,20 +91,17 @@ class DefaultRuntimeTest(unittest.TestCase, RuntimeTestBase):
def setUp(self):
self.runtime = execjs
+class NodeRuntimeTest(unittest.TestCase, RuntimeTestBase):
+ def setUp(self):
+ self.runtime = execjs.get('Node')
-for name, runtime in execjs.runtimes().items():
- if not runtime.is_available():
- continue
- class_name = name.capitalize() + "RuntimeTest"
-
- def f(runtime=runtime):
- class RuntimeTest(unittest.TestCase, RuntimeTestBase):
- def setUp(self):
- self.runtime = runtime
- RuntimeTest.__name__ = str(class_name) # 2.x compatibility
- return RuntimeTest
- exec("{class_name} = f()".format(class_name=class_name))
+class NashornRuntimeTest(unittest.TestCase, RuntimeTestBase):
+ def setUp(self):
+ self.runtime = execjs.get('Nashorn')
+class PhantomJSRuntimeTest(unittest.TestCase, RuntimeTestBase):
+ def setUp(self):
+ self.runtime = execjs.get('PhantomJS')
class CommonTest(unittest.TestCase):
def test_empty_path_environ(self):