Skip to content

Commit d4234d6

Browse files
so, we're hosting Django from within Node.js now. THIS IS A TRIUMPH
- warnings still apply: this code probably leaks enough memory to warrant a hefty pair of Depends Adult Diapers - Python objects in Javascript are still ever-so-slightly weird - but i'm pretty elated :)
1 parent a2e7ecf commit d4234d6

2 files changed

Lines changed: 63 additions & 23 deletions

File tree

binding.cc

Lines changed: 46 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ using namespace node;
2020
class PythonObject : public ObjectWrap {
2121
PyObject* _object;
2222

23-
static Persistent<ObjectTemplate> python_object_template_;
23+
static Persistent<FunctionTemplate> python_function_template_;
2424
public:
2525
PythonObject (PyObject* obj) : _object(obj) { }
2626
virtual ~PythonObject() {
@@ -31,15 +31,19 @@ class PythonObject : public ObjectWrap {
3131
static void Initialize(Handle<Object> target) {
3232
HandleScope scope;
3333

34-
python_object_template_ = Persistent<ObjectTemplate>::New(MakePythonObjectTemplate());
34+
35+
Local<FunctionTemplate> pytpl = FunctionTemplate::New();
36+
MakePythonObjectTemplate(pytpl);
37+
python_function_template_ = Persistent<FunctionTemplate>::New(pytpl);
38+
3539
Handle<FunctionTemplate> t = FunctionTemplate::New(New);
3640
target->Set(String::NewSymbol("import"), t->GetFunction());
3741

3842
};
3943

40-
static Handle<ObjectTemplate> MakePythonObjectTemplate() {
44+
static Handle<ObjectTemplate> MakePythonObjectTemplate(Local<FunctionTemplate>& t) {
4145
HandleScope scope;
42-
Handle<ObjectTemplate> result = ObjectTemplate::New();
46+
Handle<ObjectTemplate> result = t->InstanceTemplate();
4347
result->SetInternalFieldCount(1);
4448
result->SetNamedPropertyHandler(MapGet, MapSet);
4549

@@ -53,7 +57,6 @@ class PythonObject : public ObjectWrap {
5357
result->SetCallAsFunctionHandler(Call, Handle<Value>());
5458
//result->SetAccessor(String::New("getAttribute"), get_attribute->GetFunction());
5559
//result->SetAccessor(String::New("CALL_NON_FUNCTION"), call->GetFunction());
56-
return scope.Close(result);
5760
};
5861

5962
NODEPY_ACCESSOR(ToString)
@@ -91,14 +94,38 @@ class PythonObject : public ObjectWrap {
9194
};
9295

9396
PyObject* ConvertArgToPyObject(const Handle<Value>& value) {
97+
int len;
9498
if(value->IsString()) {
9599
return PyString_FromString(*String::Utf8Value(value->ToString()));
96100
} else if(value->IsNumber()) {
97101
return PyFloat_FromDouble(value->NumberValue());
98102
} else if(value->IsObject()) {
103+
Local<Object> obj = value->ToObject();
104+
if(!obj->FindInstanceInPrototypeChain(python_function_template_).IsEmpty()) {
105+
PythonObject* python_object = ObjectWrap::Unwrap<PythonObject>(value->ToObject());
106+
PyObject* pyobj = python_object->GetValue();
107+
return pyobj;
108+
} else {
109+
Local<Array> property_names = obj->GetPropertyNames();
110+
len = property_names->Length();
111+
PyObject* py_dict = PyDict_New();
112+
for(int i = 0; i < len; ++i) {
113+
Local<String> str = property_names->Get(i)->ToString();
114+
Local<Value> js_val = obj->Get(str);
115+
PyDict_SetItemString(py_dict, *String::Utf8Value(str), ConvertArgToPyObject(js_val));
116+
}
117+
return py_dict;
118+
}
99119
return NULL;
100120
} else if(value->IsArray()) {
101-
return NULL;
121+
Local<Array> array = Array::Cast(*value);
122+
len = array->Length();
123+
PyObject* py_list = PyList_New(len);
124+
for(int i = 0; i < len; ++i) {
125+
Local<Value> js_val = array->Get(i);
126+
PyList_SET_ITEM(py_list, i, ConvertArgToPyObject(js_val));
127+
}
128+
return py_list;
102129
}
103130
return NULL;
104131
}
@@ -107,20 +134,26 @@ class PythonObject : public ObjectWrap {
107134
HandleScope scope;
108135
int len = args.Length();
109136
PyObject* py_args_as_list = PyTuple_New(len);
110-
std::vector<PyObject*> py_args_to_decref(len);
137+
std::vector<PyObject*> py_args_to_decref(len);
111138
for(int i = 0; i < len; ++i) {
112139
PyObject* py_arg_n = ConvertArgToPyObject(args[i]);
113140
PyTuple_SET_ITEM(py_args_as_list, i, py_arg_n);
114141
py_args_to_decref.push_back(py_arg_n);
115142
}
116143
PyObject* py_result = PyObject_CallObject(_object, py_args_as_list);
144+
if(!py_result) {
145+
PyErr_Print();
146+
return ThrowException(
147+
Exception::TypeError(String::New("UH OH WILL ROGER"))
148+
);
149+
}
117150
/*for(std::vector<PyObject*>::iterator i = py_args_to_decref.begin(); i != py_args_to_decref.end(); ++i) {
118151
if(*i != NULL) {
119152
Py_DECREF(*i);
120153
}
121154
}*/
122155

123-
Handle<Object> result = python_object_template_->NewInstance();
156+
Handle<Object> result = python_function_template_->GetFunction()->NewInstance();
124157
result->SetInternalField(0, External::New(new PythonObject(py_result)));
125158
return scope.Close(result);
126159
}
@@ -148,9 +181,9 @@ class PythonObject : public ObjectWrap {
148181
String::Utf8Value utf_module_name(args[0]->ToString());
149182
py_module_name = PyString_FromString(*utf_module_name),
150183
py_module = PyImport_Import(py_module_name);
151-
Py_DECREF(py_module_name);
184+
Py_XDECREF(py_module_name);
152185
if(py_module != NULL) {
153-
Handle<Object> result = python_object_template_->NewInstance();
186+
Handle<Object> result = python_function_template_->GetFunction()->NewInstance();
154187
result->SetInternalField(0, External::New(new PythonObject(py_module)));
155188
return scope.Close(result);
156189
}
@@ -169,7 +202,7 @@ class PythonObject : public ObjectWrap {
169202
PyObject* attr = object->GetAttr(key_string);
170203
Handle<Object> result;
171204
if (attr) {
172-
result = python_object_template_->NewInstance();
205+
result = python_function_template_->GetFunction()->NewInstance();
173206
PythonObject* obj_out = new PythonObject(attr);
174207
result->SetInternalField(0, External::New(obj_out));
175208
return result;
@@ -193,7 +226,7 @@ class PythonObject : public ObjectWrap {
193226
PyObject* attr = object->GetAttr(key_string);
194227
Handle<Object> result;
195228
if (attr) {
196-
result = python_object_template_->NewInstance();
229+
result = python_function_template_->GetFunction()->NewInstance();
197230
PythonObject* obj_out = new PythonObject(attr);
198231
result->SetInternalField(0, External::New(obj_out));
199232
return scope.Close(result);
@@ -212,7 +245,7 @@ class PythonObject : public ObjectWrap {
212245
};
213246
};
214247

215-
Persistent<ObjectTemplate> PythonObject::python_object_template_;
248+
Persistent<FunctionTemplate> PythonObject::python_function_template_;
216249

217250
static Handle<Value>
218251
Shutdown (const Arguments& args) {

python.js

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,36 @@
11
var sys = require('sys'),
22
puts = sys.puts,
33
binding = require('./binding'),
4+
path_additions = require('./path_additions'),
45
http = require('http');
56

67
var sys = binding.import('sys');
7-
var posix = binding.import('os');
8+
var os = binding.import('os');
89

9-
sys.path.append(posix.getcwd().toString());
10-
var gary_busey = binding.import("gary_busey");
11-
var result = gary_busey.say_hey.call("man i suck");
10+
os.environ.update({
11+
'DJANGO_SETTINGS_MODULE':'project.development',
12+
});
1213

1314
/*
15+
var gary_busey = binding.import("gary_busey");
16+
var result = gary_busey.say_hey.call("man i suck");
17+
*/
1418
var django_wsgi = binding.import('django.core.handlers.wsgi');
1519

1620
var wsgi_handler = django_wsgi.WSGIHandler.call()
21+
wsgi_handler.load_middleware();
1722

1823
http.createServer(function (req, res) {
19-
var wsgi_request = django_wsgi.WSGIRequest.call({
24+
var wsgi_request = django_wsgi.WSGIRequest({
2025
'path':req.url,
26+
'REQUEST_PATH':req.url,
27+
'REQUEST_METHOD':'GET',
28+
'HTTP_HOST':'localhost:8000',
2129
});
22-
var result = wsgi_handler.get_response.call(wsgi_request);
30+
var response = wsgi_handler.get_response(wsgi_request);
2331

24-
res.writeHead(200, {'Content-Type':'text/plain'});
25-
res.write('Heyyyyy\n');
32+
res.writeHead(200, {'Content-Type':'text/html'});
33+
var content = response.content.toString();
34+
res.write(content);
2635
res.close();
2736
}).listen(8000);
28-
*/
29-
puts(result.toString());

0 commit comments

Comments
 (0)