rubypython 0.2.8 → 0.2.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. data/History.txt +4 -1
  2. data/Manifest.txt +16 -1
  3. data/PostInstall.txt +1 -1
  4. data/README.txt +7 -2
  5. data/config/hoe.rb +12 -12
  6. data/ext/rubypython_bridge/cbridge.c +92 -90
  7. data/ext/rubypython_bridge/cbridge.h +6 -16
  8. data/ext/rubypython_bridge/ptor.c +110 -56
  9. data/ext/rubypython_bridge/ptor.h +9 -25
  10. data/ext/rubypython_bridge/rp_blankobject.c +42 -0
  11. data/ext/rubypython_bridge/rp_blankobject.h +10 -0
  12. data/ext/rubypython_bridge/rp_class.c +56 -0
  13. data/ext/rubypython_bridge/rp_class.h +6 -0
  14. data/ext/rubypython_bridge/rp_error.c +14 -4
  15. data/ext/rubypython_bridge/rp_error.h +3 -1
  16. data/ext/rubypython_bridge/rp_function.c +31 -0
  17. data/ext/rubypython_bridge/rp_function.h +6 -0
  18. data/ext/rubypython_bridge/rp_instance.c +165 -0
  19. data/ext/rubypython_bridge/rp_instance.h +6 -0
  20. data/ext/rubypython_bridge/rp_module.c +159 -0
  21. data/ext/rubypython_bridge/rp_module.h +7 -0
  22. data/ext/rubypython_bridge/rp_object.c +93 -427
  23. data/ext/rubypython_bridge/rp_object.h +8 -54
  24. data/ext/rubypython_bridge/rp_util.c +61 -0
  25. data/ext/rubypython_bridge/rp_util.h +11 -0
  26. data/ext/rubypython_bridge/rtop.c +103 -54
  27. data/ext/rubypython_bridge/rtop.h +11 -16
  28. data/ext/rubypython_bridge/rubypython_bridge.c +48 -20
  29. data/ext/rubypython_bridge/rubypython_bridge.h +5 -6
  30. data/lib/rubypython.rb +2 -2
  31. data/lib/rubypython/session.rb +4 -0
  32. data/lib/rubypython/version.rb +1 -1
  33. data/test/python_helpers/objects.py +12 -0
  34. data/test/python_helpers/objects.pyc +0 -0
  35. data/test/test_rubypython.rb +123 -19
  36. data/test/test_rubypython_bridge_extn.rb +52 -19
  37. data/test/test_session.rb +1 -1
  38. data/website/index.html +25 -9
  39. data/website/index.txt +26 -3
  40. metadata +20 -5
  41. data/.autotest +0 -9
@@ -1,31 +1,15 @@
1
1
  #include "config.h"
2
2
 
3
- #ifndef _RP_ERROR_H_
4
- #include "rp_error.h"
5
- #endif
6
-
7
3
  #ifndef _PTOR_H_
8
4
  #define _PTOR_H_
9
-
10
5
  //Python to Ruby Conversion
11
- VALUE ptor_string(PyObject* pString);
12
-
13
- VALUE ptor_list(PyObject* pList);
14
-
15
- VALUE ptor_obj(PyObject* pObj);
16
-
17
- VALUE ptor_int(PyObject* pNum);
18
-
19
- VALUE ptor_long(PyObject* pNum);
20
-
21
- VALUE ptor_float(PyObject* pNum);
22
-
23
- VALUE ptor_tuple(PyObject* pTuple);
24
-
25
- VALUE ptor_dict(PyObject* pDict);
26
-
27
- VALUE ptor_obj_no_destruct(PyObject *pObj);
28
-
29
-
30
-
6
+ VALUE ptorString(PyObject* pString);
7
+ VALUE ptorList(PyObject* pList);
8
+ VALUE ptorInt(PyObject* pNum);
9
+ VALUE ptorLong(PyObject* pNum);
10
+ VALUE ptorFloat(PyObject* pNum);
11
+ VALUE ptorTuple(PyObject* pTuple);
12
+ VALUE ptorDict(PyObject* pDict);
13
+ VALUE ptorObject(PyObject* pObj);
14
+ VALUE ptorObjectKeep(PyObject *pObj);
31
15
  #endif /* _PTOR_H_ */
@@ -0,0 +1,42 @@
1
+ #include "rp_blankobject.h"
2
+
3
+ RUBY_EXTERN VALUE mRubyPythonBridge;
4
+
5
+ VALUE cBlankObject;
6
+
7
+ // :nodoc:
8
+ /* This functions is used as a predicate function. Every function name
9
+ for which it returns true will be removed from the blank object
10
+ dictionary.
11
+ */
12
+ VALUE blank_undef_if(VALUE name, VALUE klass)
13
+ {
14
+ VALUE mname = rb_funcall(name, rb_intern("to_s"), 0);
15
+ VALUE methodRe = rb_str_new2("(?:^__)|(?:\\?$)|(?:^send$)|(?:^class$)");
16
+
17
+ if(rb_funcall(mname, rb_intern("match"), 1, methodRe) == Qnil)
18
+ {
19
+ rb_undef_method(klass, STR2CSTR(mname));
20
+ return Qtrue;
21
+ }
22
+ else
23
+ {
24
+ return Qfalse;
25
+ }
26
+ }
27
+
28
+ // :nodoc:
29
+ VALUE blank_obj_prep(VALUE self)
30
+ {
31
+ VALUE instance_methods = rb_funcall(self, rb_intern("instance_methods"), 0);
32
+
33
+ rb_iterate(rb_each, instance_methods, blank_undef_if, self);
34
+ return self;
35
+ }
36
+
37
+ // :nodoc:
38
+ inline void Init_BlankObject()
39
+ {
40
+ cBlankObject = rb_define_class_under(mRubyPythonBridge,"BlankObject", rb_cObject);
41
+ blank_obj_prep(cBlankObject);
42
+ }
@@ -0,0 +1,10 @@
1
+ #include "config.h"
2
+
3
+ #ifndef _RP_BLANKOBJECT_H_
4
+ #define _RP_BLANKOBJECT_H_
5
+
6
+
7
+ VALUE blank_undef_if(VALUE, VALUE);
8
+ VALUE blank_obj_prep(VALUE);
9
+
10
+ #endif
@@ -0,0 +1,56 @@
1
+ #include "rp_class.h"
2
+
3
+ #include "rp_module.h"
4
+ #include "rp_object.h"
5
+
6
+ RUBY_EXTERN VALUE mRubyPythonBridge;
7
+ RUBY_EXTERN VALUE ePythonError;
8
+ RUBY_EXTERN VALUE cRubyPyObject;
9
+ RUBY_EXTERN VALUE cBlankObject;
10
+
11
+ VALUE cRubyPyClass;
12
+
13
+ VALUE rpClassFromPyObject(PyObject *pClass)
14
+ {
15
+ PObj* self;
16
+ PyObject* pClassDict;
17
+ VALUE rDict;
18
+ VALUE rClass = rb_class_new_instance(0, NULL, cRubyPyClass);
19
+
20
+ Data_Get_Struct(rClass, PObj, self);
21
+ self->pObject = pClass;
22
+
23
+ pClassDict = PyObject_GetAttrString(pClass,"__dict__");
24
+ Py_XINCREF(pClassDict);
25
+
26
+ rDict = rpObjectFromPyObject
27
+ (pClassDict);
28
+ rb_iv_set(rClass,"@pdict", rDict);
29
+
30
+ return rClass;
31
+ }
32
+
33
+ static
34
+ VALUE rpClassNew(VALUE self, VALUE args)
35
+ {
36
+ PyObject* pSelf;
37
+
38
+ pSelf = rpObjectGetPyObject(self);
39
+
40
+ return rpCall(pSelf, args);
41
+ }
42
+
43
+ /*
44
+ A wrapper class for Python classes and instances.
45
+
46
+ This allows objects which cannot easily be converted to native Ruby types to still be accessible
47
+ from within ruby. Most users need not concern themselves with anything about this class except
48
+ its existence.
49
+
50
+ */
51
+ void Init_RubyPyClass()
52
+ {
53
+ cRubyPyClass = rb_define_class_under(mRubyPythonBridge,"RubyPyClass", cRubyPyObject);
54
+ rb_define_method(cRubyPyClass,"method_missing", rpModuleDelegate,- 2);
55
+ rb_define_method(cRubyPyClass,"new", rpClassNew,- 2);
56
+ }
@@ -0,0 +1,6 @@
1
+ #include "config.h"
2
+
3
+ #ifndef _RP_CLASS_H_
4
+ #define _RP_CLASS_H_
5
+ VALUE rpClassFromPyObject(PyObject*);
6
+ #endif
@@ -1,23 +1,33 @@
1
1
  #include "rp_error.h"
2
2
 
3
3
  VALUE ePythonError;
4
+ VALUE eRubyPyError;
4
5
 
5
- void rp_pythonerror()
6
+ void rpPythonError()
6
7
  {
7
8
  PyObject *pType,*pValue,*pTraceback;
8
9
  PyObject *pTypeName;
10
+
9
11
  PyErr_Fetch(&pType,&pValue,&pTraceback);
10
- pTypeName=PyObject_GetAttrString(pType,"__name__");
12
+
13
+ pTypeName = PyObject_GetAttrString(pType,"__name__");
11
14
  Py_XDECREF(pType);
12
- rb_raise(ePythonError,"%s:(%s)\n",STR2CSTR(ptor_obj(pTypeName)),STR2CSTR(rb_inspect(ptor_obj(pValue))));
15
+
16
+ rb_raise(ePythonError,"%s:(%s)\n", STR2CSTR(ptorObject(pTypeName)), STR2CSTR(rb_inspect(ptorObject(pValue))));
17
+
13
18
  Py_XDECREF(pTraceback);
14
19
  }
15
20
 
21
+ void rpRubyPyError(char* eString) {
22
+ rb_raise(eRubyPyError, eString);
23
+ }
24
+
16
25
  /*
17
26
  Used to pass error information back into Ruby should an error occur in the embedded Python
18
27
  interpreter.
19
28
  */
20
29
  void Init_RubyPyError()
21
30
  {
22
- ePythonError=rb_define_class("PythonError",rb_eException);
31
+ ePythonError = rb_define_class("PythonError", rb_eException);
32
+ eRubyPyError = rb_define_class("RubyPyError", rb_eException);
23
33
  }
@@ -3,6 +3,8 @@
3
3
  #ifndef _RP_ERROR_H_
4
4
  #define _RP_ERROR_H_
5
5
 
6
- void rp_pythonerror();
6
+ void rpPythonError();
7
+
8
+ void rpRubyPyError(char*);
7
9
 
8
10
  #endif /* _RP_ERROR_H_ */
@@ -0,0 +1,31 @@
1
+ #include "rp_function.h"
2
+ #include "rp_object.h"
3
+
4
+ RUBY_EXTERN VALUE mRubyPythonBridge;
5
+ RUBY_EXTERN VALUE cRubyPyObject;
6
+
7
+ VALUE cRubyPyFunction;
8
+
9
+ VALUE rpFunctionFromPyObject(PyObject *pFunc)
10
+ {
11
+ PObj* self;
12
+ VALUE rFunc = rb_class_new_instance(0, NULL, cRubyPyFunction);
13
+
14
+ Data_Get_Struct(rFunc, PObj, self);
15
+
16
+ self->pObject = pFunc;
17
+
18
+ return rFunc;
19
+ }
20
+
21
+
22
+ //
23
+ // A wrapper class for Python functions and methods.
24
+ //
25
+ // This is used internally to aid RubyPyClass in delegating method calls.
26
+ //
27
+
28
+ void Init_RubyPyFunction()
29
+ {
30
+ cRubyPyFunction = rb_define_class_under(mRubyPythonBridge,"RubyPyFunction", cRubyPyObject);
31
+ }
@@ -0,0 +1,6 @@
1
+ #include "config.h"
2
+
3
+ #ifndef _RP_FUNCTION_H_
4
+ #define _RP_FUNCTION_H_
5
+ VALUE rpFunctionFromPyObject(PyObject*);
6
+ #endif
@@ -0,0 +1,165 @@
1
+ #include "rp_instance.h"
2
+
3
+ #include "rp_object.h"
4
+ #include "rp_function.h"
5
+
6
+ RUBY_EXTERN VALUE mRubyPythonBridge;
7
+
8
+ RUBY_EXTERN VALUE cRubyPyObject;
9
+ RUBY_EXTERN VALUE cRubyPyFunction;
10
+
11
+ VALUE cRubyPyInstance;
12
+
13
+ VALUE rpInstanceFromPyObject(PyObject* pInst)
14
+ {
15
+ PObj* self;
16
+ PyObject *pClassDict,*pClass,*pInstDict;
17
+ VALUE rInstDict, rClassDict;
18
+ VALUE rInst = rb_class_new_instance(0, NULL, cRubyPyInstance);
19
+
20
+ Data_Get_Struct(rInst, PObj, self);
21
+ self->pObject = pInst;
22
+
23
+ pClass = PyObject_GetAttrString(pInst,"__class__");
24
+ pClassDict = PyObject_GetAttrString(pClass,"__dict__");
25
+ pInstDict = PyObject_GetAttrString(pInst,"__dict__");
26
+
27
+ Py_XINCREF(pClassDict);
28
+ Py_XINCREF(pInstDict);
29
+
30
+ rClassDict = rpObjectFromPyObject(pClassDict);
31
+ rInstDict = rpObjectFromPyObject(pInstDict);
32
+
33
+ rb_iv_set(rInst,"@pclassdict", rClassDict);
34
+ rb_iv_set(rInst,"@pinstdict", rInstDict);
35
+
36
+ return rInst;
37
+ }
38
+
39
+ static
40
+ VALUE rpInstanceSetAttr(VALUE self, VALUE args)
41
+ {
42
+ VALUE name, name_string, rClassDict, result, rInstDict;
43
+ VALUE ret;
44
+
45
+ int instance;
46
+ char* cname;
47
+
48
+ PObj *pClassDict,*pInstDict,*pDict;
49
+
50
+ PyObject* pName;
51
+
52
+ name = rb_ary_shift(args);
53
+ name_string = rb_funcall(name, rb_intern("to_s"), 0);
54
+
55
+ rb_funcall(name_string, rb_intern("chop!"), 0);
56
+
57
+ if(!rpHasSymbol(self, name_string))
58
+ {
59
+ int argc;
60
+ VALUE* argv;
61
+
62
+ argc = RARRAY_LEN(args);
63
+ argv = ALLOC_N(VALUE, argc);
64
+ MEMCPY(argv, RARRAY_PTR(args), VALUE, argc);
65
+ return rb_call_super(argc, argv);
66
+ }
67
+
68
+ cname = STR2CSTR(name_string);
69
+
70
+ if((NUM2INT(rb_funcall(args, rb_intern("size"), 0)) == 1))
71
+ {
72
+ args = rb_ary_entry(args, 0);
73
+ }
74
+
75
+ rClassDict = rb_iv_get(self,"@pclassdict");
76
+ rInstDict = rb_iv_get(self,"@pinstdict");
77
+
78
+ Data_Get_Struct(rClassDict, PObj, pClassDict);
79
+ Data_Get_Struct(rInstDict, PObj, pInstDict);
80
+
81
+ pName = PyString_FromString(cname);
82
+
83
+ if(PyDict_Contains(pInstDict->pObject, pName))
84
+ {
85
+ pDict = pInstDict;
86
+
87
+ }
88
+ else
89
+ {
90
+ pDict = pClassDict;
91
+
92
+ }
93
+
94
+ Py_XDECREF(pName);
95
+ PyDict_SetItemString(pDict->pObject, STR2CSTR(name_string), rtopObject(args, 0));
96
+
97
+ return Qtrue;
98
+ }
99
+
100
+ //:nodoc:
101
+ static
102
+ VALUE rpInstanceDelegate(VALUE self, VALUE args)
103
+ {
104
+ VALUE name, name_string, rClassDict, result, rInstDict;
105
+ VALUE ret;
106
+ char* cname;
107
+ PObj *pClassDict,*pInstDict;
108
+ PyObject* pCalled;
109
+
110
+ if(rpSymbolIsSetter(args))
111
+ {
112
+ return rpInstanceSetAttr(self, args);
113
+ }
114
+
115
+ if(!rpHasSymbol(self, rb_ary_entry(args, 0)))
116
+ {
117
+ int argc;
118
+ VALUE* argv;
119
+
120
+ argc = RARRAY_LEN(args);
121
+ argv = ALLOC_N(VALUE, argc);
122
+ MEMCPY(argv, RARRAY_PTR(args), VALUE, argc);
123
+ return rb_call_super(argc, argv);
124
+ }
125
+
126
+ name = rb_ary_shift(args);
127
+ name_string = rb_funcall(name, rb_intern("to_s"), 0);
128
+ cname = STR2CSTR(name_string);
129
+
130
+ rClassDict = rb_iv_get(self,"@pclassdict");
131
+ rInstDict = rb_iv_get(self,"@pinstdict");
132
+
133
+ Data_Get_Struct(rClassDict, PObj, pClassDict);
134
+ Data_Get_Struct(rInstDict, PObj, pInstDict);
135
+
136
+ pCalled = PyDict_GetItemString(pInstDict->pObject, cname);
137
+
138
+ if(!pCalled)
139
+ {
140
+ pCalled = PyDict_GetItemString(pClassDict->pObject, cname);
141
+ }
142
+
143
+ Py_XINCREF(pCalled);
144
+ result = ptorObjectKeep(pCalled);
145
+
146
+ if(rb_obj_is_instance_of(result, cRubyPyFunction))
147
+ {
148
+ Py_XINCREF(rpObjectGetPyObject(self));
149
+ rb_ary_unshift(args, self);
150
+ ret = rpCall(pCalled, args);
151
+ return ret;
152
+ }
153
+
154
+ return result;
155
+
156
+ }
157
+
158
+
159
+ void Init_RubyPyInstance()
160
+ {
161
+ cRubyPyInstance = rb_define_class_under(mRubyPythonBridge,"RubyPyInstance", cRubyPyObject);
162
+ rb_define_method(cRubyPyInstance,"method_missing", rpInstanceDelegate,- 2);
163
+ }
164
+
165
+
@@ -0,0 +1,6 @@
1
+ #include "config.h"
2
+
3
+ #ifndef _RP_INSTANCE_H_
4
+ #define _RP_INSTANCE_H_
5
+ VALUE rpInstanceFromPyObject(PyObject*);
6
+ #endif
@@ -0,0 +1,159 @@
1
+ #include "rp_module.h"
2
+
3
+ #include "rp_object.h"
4
+ #include "rp_function.h"
5
+
6
+ VALUE cRubyPyModule;
7
+
8
+ RUBY_EXTERN VALUE mRubyPythonBridge;
9
+ RUBY_EXTERN VALUE cRubyPyFunction;
10
+ RUBY_EXTERN VALUE cRubyPyClass;
11
+ RUBY_EXTERN VALUE cRubyPyObject;
12
+
13
+ static
14
+ VALUE rpModuleCallFunction(VALUE self, VALUE func_name, VALUE args)
15
+ {
16
+ PyObject *pModule,*pFunc;
17
+ VALUE rReturn;
18
+
19
+ pModule = rpObjectGetPyObject(self);
20
+
21
+ pFunc = rpGetFunctionWithModule(pModule, func_name);
22
+ rReturn = rpCall(pFunc, args);
23
+ Py_XDECREF(pFunc);
24
+
25
+ return rReturn;
26
+
27
+ }
28
+
29
+ //:nodoc:
30
+ static
31
+ VALUE rpModuleInit(VALUE self, VALUE mname)
32
+ {
33
+ PObj* cself;
34
+ VALUE rDict;
35
+ PyObject *pModuleDict;
36
+
37
+ Data_Get_Struct(self, PObj, cself);
38
+ cself->pObject = rpGetModule(mname);
39
+
40
+ pModuleDict = PyModule_GetDict(cself->pObject);
41
+ Py_XINCREF(pModuleDict);
42
+
43
+ rDict = rpObjectFromPyObject(pModuleDict);
44
+
45
+ rb_iv_set(self,"@pdict", rDict);
46
+
47
+ return self;
48
+ }
49
+
50
+ static
51
+ VALUE rpModuleSetAttr(VALUE self, VALUE args)
52
+ {
53
+ VALUE rDict;
54
+ PyObject* pDict;
55
+
56
+ VALUE mname = rb_ary_shift(args);
57
+ VALUE name_string = rb_funcall(mname, rb_intern("to_s"), 0);
58
+
59
+ //The method name ends with "=" because it is a setter.
60
+ //We must chop that off before we pass the string to python.
61
+ rb_funcall(name_string, rb_intern("chop!"), 0);
62
+
63
+ //The wrapped python object does not have method or attribute with the
64
+ //request named. Check for it in the Ruby superclass.
65
+ if(!rpHasSymbol(self, name_string))
66
+ {
67
+ int argc;
68
+
69
+ VALUE* argv;
70
+ argc = RARRAY_LEN(args);
71
+
72
+ argv = ALLOC_N(VALUE, argc);
73
+ MEMCPY(argv, RARRAY_PTR(args), VALUE, argc);
74
+
75
+ return rb_call_super(argc, argv);
76
+ }
77
+
78
+ if(NUM2INT(rb_funcall(args, rb_intern("size"), 0)) == 1)
79
+ {
80
+ args = rb_ary_entry(args, 0);
81
+ }
82
+
83
+ rDict = rb_iv_get(self,"@pdict");
84
+
85
+ pDict = rpObjectGetPyObject(rDict);
86
+
87
+ PyDict_SetItemString(pDict, STR2CSTR(name_string), rtopObject(args, 0));
88
+
89
+ return Qtrue;
90
+ }
91
+
92
+ //:nodoc:
93
+ VALUE rpModuleDelegate(VALUE self, VALUE args)
94
+ {
95
+ VALUE name, name_string, rDict, result;
96
+ VALUE ret;
97
+ PyObject *pCalled, *pDict;
98
+
99
+ if(rpSymbolIsSetter(args))
100
+ {
101
+ return rpModuleSetAttr(self, args);
102
+ }
103
+
104
+ // if(rpSymbolIsDoubleBang)
105
+ // {
106
+ // return rp_mod_attr_db(args);
107
+ // }
108
+ if(!rpHasSymbol(self, rb_ary_entry(args, 0)))
109
+ {
110
+ int argc;
111
+
112
+ VALUE *argv;
113
+ argc = RARRAY_LEN(args);
114
+ argv = ALLOC_N(VALUE, argc);
115
+ MEMCPY(argv, RARRAY_PTR(args), VALUE, argc);
116
+ return rb_call_super(argc, argv);
117
+ }
118
+ name = rb_ary_shift(args);
119
+ name_string = rb_funcall(name, rb_intern("to_s"), 0);
120
+
121
+ rDict = rb_iv_get(self,"@pdict");
122
+
123
+ pDict = rpObjectGetPyObject(rDict);
124
+
125
+ pCalled = PyDict_GetItemString(pDict, STR2CSTR(name_string));
126
+ Py_XINCREF(pCalled);
127
+
128
+ result = ptorObjectKeep(pCalled);
129
+
130
+ if(rb_obj_is_instance_of(result, cRubyPyFunction))
131
+ {
132
+ ret = rpCall(pCalled, args);
133
+ return ret;
134
+ }
135
+ else if(rb_obj_is_instance_of(result, cRubyPyClass)&&(rb_funcall(args, rb_intern("empty?"), 0) == Qfalse)&&PyCallable_Check(pCalled))
136
+ {
137
+ ret = rpCall(pCalled, args);
138
+ return ret;
139
+ }
140
+
141
+ return result;
142
+
143
+ }
144
+
145
+
146
+ /*
147
+ A wrapper class for Python Modules.
148
+
149
+ Methods calls are delegated to the equivalent Python methods / functions. Attribute references
150
+ return either the equivalent attribute converted to a native Ruby type, or wrapped reference
151
+ to a Python object. RubyPyModule instances should be created through the use of RubyPython.import.
152
+
153
+ */
154
+ void Init_RubyPyModule()
155
+ {
156
+ cRubyPyModule = rb_define_class_under(mRubyPythonBridge,"RubyPyModule", cRubyPyObject);
157
+ rb_define_method(cRubyPyModule,"initialize", rpModuleInit, 1);
158
+ rb_define_method(cRubyPyModule,"method_missing", rpModuleDelegate,- 2);
159
+ }