Skip to content

Commit 15e4d16

Browse files
committed
2 parents f090cb1 + b32b9ec commit 15e4d16

12 files changed

Lines changed: 423 additions & 48 deletions

File tree

.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,6 @@
11
build
2+
node_modules
3+
.DS_Store
4+
.cproject
5+
.project
6+
.settings

Makefile

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
DEBUG=node-python*
2+
PYTHONPATH=./test/support
3+
4+
test:
5+
$(MAKE) DEBUG= test-debug
6+
7+
test-debug:
8+
DEBUG=$(DEBUG) PYTHONPATH=$(PYTHONPATH) ./node_modules/.bin/mocha -R spec
9+
10+
.PHONY: test test-debug

index.js

Lines changed: 64 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,66 @@
1+
var binding = require('bindings')('binding.node');
2+
var debug = require('debug')('node-python');
3+
var warn = require('debug')('node-python:warn');
4+
var util = require('util');
15

2-
module.exports = require('bindings')('binding.node')
6+
function PythonError (message, value) {
7+
if (arguments[0] instanceof Error) {
8+
var error = arguments[0];
9+
this.message = error.message;
10+
this.stack = error.stack;
11+
this.value = error.value;
12+
Error.apply(this, arguments);
13+
} else {
14+
Error.call(this, message, value);
15+
}
16+
}
317

18+
util.inherits(PythonError, Error);
19+
20+
module.exports.PythonError = PythonError;
21+
22+
var finalized = false;
23+
function pythonFinalized () {
24+
if (finalized) {
25+
warn('node-python\'s python interpreter has already been finalized. python code cannot be executed.');
26+
}
27+
return finalized;
28+
}
29+
30+
module.exports.eval = function (string) {
31+
if (pythonFinalized()) throw new PythonError('node-python\'s python interpreter has already been finalized. python code cannot be executed.');
32+
return binding.eval(string);
33+
}
34+
35+
module.exports.finalize = function () {
36+
if ( ! pythonFinalized()) {
37+
binding.finalize();
38+
finalized = true;
39+
return finalized;
40+
}
41+
return false;
42+
}
43+
44+
var _import = module.exports.import = function (string) {
45+
if (pythonFinalized()) throw new PythonError('node-python\'s python interpreter has already been finalized. python code cannot be executed.');
46+
47+
var result = null;
48+
49+
try {
50+
result = binding.import(string);
51+
} catch (e) {
52+
e = new PythonError(e);
53+
debug(e);
54+
throw e;
55+
}
56+
57+
return result;
58+
}
59+
60+
var os = _import('os');
61+
62+
var pythonPath = os.environ.get('PYTHONPATH');
63+
64+
if (pythonPath === undefined) {
65+
debug('WARNING: PYTHONPATH environment variable is undefined. This may cause problems finding python modules. see: https://docs.python.org/2/tutorial/modules.html#the-module-search-path');
66+
}

package.json

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "node-python",
3-
"version": "0.0.4",
3+
"version": "v0.0.5-rc4",
44
"description": "Call python stuff from nodejs",
55
"main": "index.js",
66
"repository": {
@@ -24,12 +24,18 @@
2424
}
2525
],
2626
"scripts": {
27-
"test": "node test/linker.js"
27+
"test": "make test"
2828
},
2929
"license": "BSD",
3030
"gypfile": true,
3131
"readmeFilename": "README.md",
3232
"dependencies": {
33-
"bindings": "~1.1.1"
33+
"bindings": "~1.1.1",
34+
"debug": "^1.0.4"
35+
},
36+
"devDependencies": {
37+
"mocha": "^1.21.3",
38+
"should": "^4.0.4",
39+
"sinon": "^1.10.3"
3440
}
3541
}

src/binding.cc

Lines changed: 59 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,88 @@
1-
21
#include <node.h>
32
#include <Python.h>
4-
3+
#include <datetime.h>
54
#include "py_object_wrapper.h"
65
#include "utils.h"
76

87
using namespace v8;
98
using namespace node;
109
using std::string;
1110

11+
Handle<Value> eval(const Arguments& args) {
12+
HandleScope scope;
13+
if (args.Length() < 1 || !args[0]->IsString()) {
14+
return ThrowException(
15+
Exception::Error(String::New("A string expression must be provided."))
16+
);
17+
}
18+
19+
PyCodeObject* code = (PyCodeObject*) Py_CompileString(*String::Utf8Value(args[0]->ToString()), "eval", Py_eval_input);
20+
PyObject* main_module = PyImport_AddModule("__main__");
21+
PyObject* global_dict = PyModule_GetDict(main_module);
22+
PyObject* local_dict = PyDict_New();
23+
PyObject* obj = PyEval_EvalCode(code, global_dict, local_dict);
24+
PyObject* result = PyObject_Str(obj);
25+
26+
Py_XDECREF(code);
27+
Py_XDECREF(global_dict);
28+
Py_XDECREF(local_dict);
29+
Py_XDECREF(obj);
30+
31+
return scope.Close(PyObjectWrapper::New(result));
32+
}
33+
34+
Handle<Value> finalize(const Arguments& args) {
35+
HandleScope scope;
36+
Py_Finalize();
37+
return scope.Close(Undefined());
38+
}
39+
1240
Handle<Value> import(const Arguments& args) {
1341
HandleScope scope;
14-
if(args.Length() < 1 || !args[0]->IsString()) {
42+
if (args.Length() < 1 || !args[0]->IsString()) {
1543
return ThrowException(
1644
Exception::Error(String::New("I don't know how to import that."))
1745
);
1846
}
19-
PyObject* module_name = PyString_FromString(*String::Utf8Value(args[0]->ToString()));
20-
PyObject* module = PyImport_Import(module_name);
21-
if(!module) {
47+
48+
PyObject* module_name;
49+
PyObject* module;
50+
51+
module_name = PyUnicode_FromString(*String::Utf8Value(args[0]->ToString()));
52+
module = PyImport_Import(module_name);
53+
54+
if (PyErr_Occurred()) {
55+
return ThrowPythonException();
56+
}
57+
58+
if (!module) {
2259
return ThrowPythonException();
2360
}
2461
Py_XDECREF(module_name);
2562

2663
return scope.Close(PyObjectWrapper::New(module));
2764
}
2865

29-
3066
void init (Handle<Object> exports) {
3167
HandleScope scope;
32-
Py_Initialize();
3368

69+
Py_Initialize();
3470
PyObjectWrapper::Initialize();
3571

72+
// how to schedule Py_Finalize(); to be called when process exits?
73+
74+
// module.exports.eval
75+
exports->Set(
76+
String::NewSymbol("eval"),
77+
FunctionTemplate::New(eval)->GetFunction()
78+
);
79+
80+
// module.exports.finalize
81+
exports->Set(
82+
String::NewSymbol("finalize"),
83+
FunctionTemplate::New(finalize)->GetFunction()
84+
);
85+
3686
// module.exports.import
3787
exports->Set(
3888
String::NewSymbol("import"),
@@ -47,4 +97,4 @@ void init (Handle<Object> exports) {
4797

4898
}
4999

50-
NODE_MODULE(binding, init)
100+
NODE_MODULE(binding, init)

0 commit comments

Comments
 (0)