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');
}
42 changes: 42 additions & 0 deletions npm-debug.log
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
0 info it worked if it ends with ok
1 verbose cli [ '/usr/local/bin/node', '/usr/local/bin/npm', 'install' ]
2 info using npm@1.4.28
3 info using node@v0.10.32
4 verbose readDependencies using package.json deps
5 verbose install where, deps [ '/Users/matt/development/electronifie/node-python',
5 verbose install [ 'bindings', 'debug', 'mocha', 'should', 'sinon' ] ]
6 info preinstall node-python@0.0.5-rc3
7 verbose readDependencies using package.json deps
8 verbose already installed skipping bindings@~1.1.1 /Users/matt/development/electronifie/node-python
9 verbose already installed skipping debug@^1.0.4 /Users/matt/development/electronifie/node-python
10 verbose already installed skipping mocha@^1.21.3 /Users/matt/development/electronifie/node-python
11 verbose already installed skipping should@^4.0.4 /Users/matt/development/electronifie/node-python
12 verbose already installed skipping sinon@^1.10.3 /Users/matt/development/electronifie/node-python
13 silly resolved []
14 info build /Users/matt/development/electronifie/node-python
15 verbose linkStuff [ false, false, false, '/Users/matt/development/electronifie' ]
16 info linkStuff node-python@0.0.5-rc3
17 verbose linkBins node-python@0.0.5-rc3
18 verbose linkMans node-python@0.0.5-rc3
19 verbose rebuildBundles node-python@0.0.5-rc3
20 verbose rebuildBundles [ '.bin', 'bindings', 'debug', 'mocha', 'should', 'sinon' ]
21 info install node-python@0.0.5-rc3
22 verbose unsafe-perm in lifecycle true
23 info node-python@0.0.5-rc3 Failed to exec install script
24 error node-python@0.0.5-rc3 install: `node-gyp rebuild`
24 error Exit status 1
25 error Failed at the node-python@0.0.5-rc3 install script.
25 error This is most likely a problem with the node-python package,
25 error not with npm itself.
25 error Tell the author that this fails on your system:
25 error node-gyp rebuild
25 error You can get their info via:
25 error npm owner ls node-python
25 error There is likely additional logging output above.
26 error System Darwin 13.3.0
27 error command "/usr/local/bin/node" "/usr/local/bin/npm" "install"
28 error cwd /Users/matt/development/electronifie/node-python
29 error node -v v0.10.32
30 error npm -v 1.4.28
31 error code ELIFECYCLE
32 verbose exit [ 1, true ]
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-rc3",
"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