Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,6 @@
build
node_modules
.DS_Store
.cproject
.project
.settings
10 changes: 10 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
DEBUG=node-python*
PYTHONPATH=./test/support

test:
$(MAKE) DEBUG= test-debug

test-debug:
DEBUG=$(DEBUG) PYTHONPATH=$(PYTHONPATH) ./node_modules/.bin/mocha -R spec

.PHONY: test test-debug
65 changes: 64 additions & 1 deletion index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,66 @@
var binding = require('bindings')('binding.node');
var debug = require('debug')('node-python');
var warn = require('debug')('node-python:warn');
var util = require('util');

module.exports = require('bindings')('binding.node')
function PythonError (message, value) {
if (arguments[0] instanceof Error) {
var error = arguments[0];
this.message = error.message;
this.stack = error.stack;
this.value = error.value;
Error.apply(this, arguments);
} else {
Error.call(this, message, value);
}
}

util.inherits(PythonError, Error);

module.exports.PythonError = PythonError;

var finalized = false;
function pythonFinalized () {
if (finalized) {
warn('node-python\'s python interpreter has already been finalized. python code cannot be executed.');
}
return finalized;
}

module.exports.eval = function (string) {
if (pythonFinalized()) throw new PythonError('node-python\'s python interpreter has already been finalized. python code cannot be executed.');
return binding.eval(string);
}

module.exports.finalize = function () {
if ( ! pythonFinalized()) {
binding.finalize();
finalized = true;
return finalized;
}
return false;
}

var _import = module.exports.import = function (string) {
if (pythonFinalized()) throw new PythonError('node-python\'s python interpreter has already been finalized. python code cannot be executed.');

var result = null;

try {
result = binding.import(string);
} catch (e) {
e = new PythonError(e);
debug(e);
throw e;
}

return result;
}

var os = _import('os');

var pythonPath = os.environ.get('PYTHONPATH');

if (pythonPath === undefined) {
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');
}
12 changes: 9 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "node-python",
"version": "0.0.4",
"version": "v0.0.5-rc4",
"description": "Call python stuff from nodejs",
"main": "index.js",
"repository": {
Expand All @@ -24,12 +24,18 @@
}
],
"scripts": {
"test": "node test/linker.js"
"test": "make test"
},
"license": "BSD",
"gypfile": true,
"readmeFilename": "README.md",
"dependencies": {
"bindings": "~1.1.1"
"bindings": "~1.1.1",
"debug": "^1.0.4"
},
"devDependencies": {
"mocha": "^1.21.3",
"should": "^4.0.4",
"sinon": "^1.10.3"
}
}
68 changes: 59 additions & 9 deletions src/binding.cc
Original file line number Diff line number Diff line change
@@ -1,38 +1,88 @@

#include <node.h>
#include <Python.h>

#include <datetime.h>
#include "py_object_wrapper.h"
#include "utils.h"

using namespace v8;
using namespace node;
using std::string;

Handle<Value> eval(const Arguments& args) {
HandleScope scope;
if (args.Length() < 1 || !args[0]->IsString()) {
return ThrowException(
Exception::Error(String::New("A string expression must be provided."))
);
}

PyCodeObject* code = (PyCodeObject*) Py_CompileString(*String::Utf8Value(args[0]->ToString()), "eval", Py_eval_input);
PyObject* main_module = PyImport_AddModule("__main__");
PyObject* global_dict = PyModule_GetDict(main_module);
PyObject* local_dict = PyDict_New();
PyObject* obj = PyEval_EvalCode(code, global_dict, local_dict);
PyObject* result = PyObject_Str(obj);

Py_XDECREF(code);
Py_XDECREF(global_dict);
Py_XDECREF(local_dict);
Py_XDECREF(obj);

return scope.Close(PyObjectWrapper::New(result));
}

Handle<Value> finalize(const Arguments& args) {
HandleScope scope;
Py_Finalize();
return scope.Close(Undefined());
}

Handle<Value> import(const Arguments& args) {
HandleScope scope;
if(args.Length() < 1 || !args[0]->IsString()) {
if (args.Length() < 1 || !args[0]->IsString()) {
return ThrowException(
Exception::Error(String::New("I don't know how to import that."))
);
}
PyObject* module_name = PyString_FromString(*String::Utf8Value(args[0]->ToString()));
PyObject* module = PyImport_Import(module_name);
if(!module) {

PyObject* module_name;
PyObject* module;

module_name = PyUnicode_FromString(*String::Utf8Value(args[0]->ToString()));
module = PyImport_Import(module_name);

if (PyErr_Occurred()) {
return ThrowPythonException();
}

if (!module) {
return ThrowPythonException();
}
Py_XDECREF(module_name);

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


void init (Handle<Object> exports) {
HandleScope scope;
Py_Initialize();

Py_Initialize();
PyObjectWrapper::Initialize();

// how to schedule Py_Finalize(); to be called when process exits?

// module.exports.eval
exports->Set(
String::NewSymbol("eval"),
FunctionTemplate::New(eval)->GetFunction()
);

// module.exports.finalize
exports->Set(
String::NewSymbol("finalize"),
FunctionTemplate::New(finalize)->GetFunction()
);

// module.exports.import
exports->Set(
String::NewSymbol("import"),
Expand All @@ -47,4 +97,4 @@ void init (Handle<Object> exports) {

}

NODE_MODULE(binding, init)
NODE_MODULE(binding, init)
Loading