pycall 1.0.1-x86-mingw32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +13 -0
- data/.rspec +2 -0
- data/.travis.yml +41 -0
- data/CHANGES.md +39 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/README.md +91 -0
- data/Rakefile +29 -0
- data/appveyor.yml +138 -0
- data/bin/console +10 -0
- data/bin/guard +17 -0
- data/bin/rspec +17 -0
- data/bin/runner +6 -0
- data/bin/setup +8 -0
- data/config/Guardfile +30 -0
- data/docker/Dockerfile +191 -0
- data/docker/Gemfile +12 -0
- data/docker/README.md +22 -0
- data/examples/classifier_comparison.rb +135 -0
- data/examples/datascience_rb_20170519.ipynb +4836 -0
- data/examples/hist.rb +32 -0
- data/examples/notebooks/classifier_comparison.ipynb +226 -0
- data/examples/notebooks/forest_importances.ipynb +238 -0
- data/examples/notebooks/iruby_integration.ipynb +183 -0
- data/examples/notebooks/lorenz_attractor.ipynb +214 -0
- data/examples/notebooks/polar_axes.ipynb +209 -0
- data/examples/notebooks/sum_benchmarking.ipynb +374 -0
- data/examples/notebooks/xkcd_style.ipynb +149 -0
- data/examples/plot_forest_importances_faces.rb +46 -0
- data/examples/sum_benchmarking.rb +49 -0
- data/ext/pycall/extconf.rb +3 -0
- data/ext/pycall/gc.c +74 -0
- data/ext/pycall/libpython.c +217 -0
- data/ext/pycall/pycall.c +2184 -0
- data/ext/pycall/pycall_internal.h +700 -0
- data/ext/pycall/range.c +69 -0
- data/ext/pycall/ruby_wrapper.c +432 -0
- data/lib/2.1/pycall.so +0 -0
- data/lib/2.2/pycall.so +0 -0
- data/lib/2.3/pycall.so +0 -0
- data/lib/2.4/pycall.so +0 -0
- data/lib/pycall/conversion.rb +173 -0
- data/lib/pycall/dict.rb +48 -0
- data/lib/pycall/error.rb +10 -0
- data/lib/pycall/gc_guard.rb +84 -0
- data/lib/pycall/import.rb +120 -0
- data/lib/pycall/init.rb +55 -0
- data/lib/pycall/iruby_helper.rb +40 -0
- data/lib/pycall/libpython/finder.rb +170 -0
- data/lib/pycall/libpython/pyobject_struct.rb +30 -0
- data/lib/pycall/libpython/pytypeobject_struct.rb +273 -0
- data/lib/pycall/libpython.rb +12 -0
- data/lib/pycall/list.rb +45 -0
- data/lib/pycall/pretty_print.rb +9 -0
- data/lib/pycall/pyerror.rb +30 -0
- data/lib/pycall/pyobject_wrapper.rb +212 -0
- data/lib/pycall/python/PyCall/__init__.py +1 -0
- data/lib/pycall/python/PyCall/six.py +23 -0
- data/lib/pycall/python/investigator.py +7 -0
- data/lib/pycall/pytypeobject_wrapper.rb +90 -0
- data/lib/pycall/set.rb +19 -0
- data/lib/pycall/slice.rb +8 -0
- data/lib/pycall/tuple.rb +46 -0
- data/lib/pycall/version.rb +3 -0
- data/lib/pycall/wrapper_object_cache.rb +61 -0
- data/lib/pycall.rb +91 -0
- data/pycall.gemspec +40 -0
- data/tasks/docker.rake +21 -0
- data/tasks/pycall.rake +7 -0
- metadata +228 -0
data/ext/pycall/pycall.c
ADDED
@@ -0,0 +1,2184 @@
|
|
1
|
+
#include "pycall_internal.h"
|
2
|
+
|
3
|
+
#include <stdarg.h>
|
4
|
+
|
5
|
+
VALUE pycall_mPyCall;
|
6
|
+
|
7
|
+
VALUE mLibPython;
|
8
|
+
VALUE mAPI;
|
9
|
+
VALUE mHelpers;
|
10
|
+
VALUE mConversion;
|
11
|
+
VALUE mPyObjectWrapper;
|
12
|
+
VALUE mPyTypeObjectWrapper;
|
13
|
+
VALUE mGCGuard;
|
14
|
+
|
15
|
+
VALUE pycall_cPyPtr;
|
16
|
+
VALUE cPyTypePtr;
|
17
|
+
VALUE cTuple;
|
18
|
+
VALUE cPyError;
|
19
|
+
|
20
|
+
VALUE pycall_eError;
|
21
|
+
|
22
|
+
static VALUE pycall_libpython_handle;
|
23
|
+
static VALUE python_description;
|
24
|
+
static VALUE python_version_string;
|
25
|
+
static Py_ssize_t python_hexversion;
|
26
|
+
static int python_major_version;
|
27
|
+
static int python_has_stackless_extension;
|
28
|
+
static PyObject *python_builtins_module;
|
29
|
+
static VALUE python_type_mapping;
|
30
|
+
static VALUE python_type_mapping;
|
31
|
+
static ID id_python_type_mapping;
|
32
|
+
|
33
|
+
int
|
34
|
+
pycall_python_major_version(void)
|
35
|
+
{
|
36
|
+
return python_major_version;
|
37
|
+
}
|
38
|
+
|
39
|
+
Py_ssize_t
|
40
|
+
pycall_python_hexversion(void)
|
41
|
+
{
|
42
|
+
return python_hexversion;
|
43
|
+
}
|
44
|
+
|
45
|
+
#undef pycall_python_major_version
|
46
|
+
#define pycall_python_major_version() python_major_version
|
47
|
+
|
48
|
+
#undef pycall_python_hexversion
|
49
|
+
#define pycall_python_hexversion() python_hexversion
|
50
|
+
|
51
|
+
#define python_is_unicode_literals (python_major_version >= 3)
|
52
|
+
|
53
|
+
long pycall_hash_salt;
|
54
|
+
|
55
|
+
static VALUE pycall_call_python_callable(PyObject *pycallable, int argc, VALUE *argv);
|
56
|
+
|
57
|
+
#define PyType_Check(pyobj) PyType_FastSubclass(Py_TYPE(pyobj), Py_TPFLAGS_TYPE_SUBCLASS)
|
58
|
+
#define PyClass_Check(pyobj) (Py_API(PyClass_Type) && (pyobj)->ob_type == Py_API(PyClass_Type))
|
59
|
+
|
60
|
+
#define PyObject_Hash(pyobj) (pycall_python_long_hash ? Py_API(PyObject_Hash._long)(pyobj) : Py_API(PyObject_Hash._hash_t)(pyobj))
|
61
|
+
|
62
|
+
/* ==== PyCall ==== */
|
63
|
+
|
64
|
+
VALUE
|
65
|
+
pycall_after_fork(VALUE mod)
|
66
|
+
{
|
67
|
+
Py_API(PyOS_AfterFork)();
|
68
|
+
return Qnil;
|
69
|
+
}
|
70
|
+
|
71
|
+
/* ==== PyCall::PyPtr ==== */
|
72
|
+
|
73
|
+
const rb_data_type_t pycall_pyptr_data_type = {
|
74
|
+
"PyCall::PyPtr",
|
75
|
+
{ 0, pycall_pyptr_free, pycall_pyptr_memsize, },
|
76
|
+
#ifdef RUBY_TYPED_FREE_IMMEDIATELY
|
77
|
+
0, 0, RUBY_TYPED_FREE_IMMEDIATELY
|
78
|
+
#endif
|
79
|
+
};
|
80
|
+
|
81
|
+
void
|
82
|
+
pycall_pyptr_free(void *ptr)
|
83
|
+
{
|
84
|
+
PyObject *pyobj = ptr;
|
85
|
+
#ifdef PYCALL_DEBUG_DUMP_REFCNT
|
86
|
+
if (pyobj->ob_refcnt == 0) {
|
87
|
+
fprintf(stderr, "zero refcnt object %p of type %s\n", pyobj, Py_TYPE(pyobj)->tp_name);
|
88
|
+
}
|
89
|
+
#endif /* PYCALL_DEBUG_DUMP_REFCNT */
|
90
|
+
pycall_Py_DecRef(pyobj);
|
91
|
+
}
|
92
|
+
|
93
|
+
static size_t _PySys_GetSizeOf(PyObject *);
|
94
|
+
|
95
|
+
size_t
|
96
|
+
pycall_pyptr_memsize(void const *ptr)
|
97
|
+
{
|
98
|
+
if (ptr)
|
99
|
+
return _PySys_GetSizeOf((PyObject *)ptr);
|
100
|
+
|
101
|
+
return 0;
|
102
|
+
}
|
103
|
+
|
104
|
+
static size_t
|
105
|
+
_PySys_GetSizeOf(PyObject *o)
|
106
|
+
{
|
107
|
+
PyObject *res = NULL;
|
108
|
+
Py_ssize_t size;
|
109
|
+
|
110
|
+
if (Py_API(PyType_Ready)(Py_TYPE(o)) < 0)
|
111
|
+
return (size_t)-1;
|
112
|
+
|
113
|
+
res = Py_API(PyObject_CallMethod)(o, "__sizeof__", "");
|
114
|
+
if (res == NULL)
|
115
|
+
return (size_t)-1;
|
116
|
+
|
117
|
+
size = Py_API(PyLong_AsSsize_t)(res);
|
118
|
+
pycall_Py_DecRef(res);
|
119
|
+
if (size == -1 && Py_API(PyErr_Occurred)())
|
120
|
+
return (size_t)-1;
|
121
|
+
|
122
|
+
if (size < 0)
|
123
|
+
return (size_t)-1;
|
124
|
+
|
125
|
+
if (PyObject_IS_GC(o)) {
|
126
|
+
size += sizeof(PyGC_Head);
|
127
|
+
}
|
128
|
+
return (size_t)size;
|
129
|
+
}
|
130
|
+
|
131
|
+
static inline int
|
132
|
+
is_pycall_pyptr(VALUE obj)
|
133
|
+
{
|
134
|
+
return rb_typeddata_is_kind_of(obj, &pycall_pyptr_data_type);
|
135
|
+
}
|
136
|
+
|
137
|
+
static inline PyObject*
|
138
|
+
get_pyobj_ptr(VALUE obj)
|
139
|
+
{
|
140
|
+
PyObject *pyobj;
|
141
|
+
TypedData_Get_Struct(obj, PyObject, &pycall_pyptr_data_type, pyobj);
|
142
|
+
return pyobj;
|
143
|
+
}
|
144
|
+
|
145
|
+
static inline PyObject*
|
146
|
+
try_get_pyobj_ptr(VALUE obj)
|
147
|
+
{
|
148
|
+
if (!is_pycall_pyptr(obj)) return NULL;
|
149
|
+
return (PyObject*)DATA_PTR(obj);
|
150
|
+
}
|
151
|
+
|
152
|
+
static inline PyObject *
|
153
|
+
check_get_pyobj_ptr(VALUE obj, PyTypeObject *pytypeobj)
|
154
|
+
{
|
155
|
+
PyObject *pyobj;
|
156
|
+
|
157
|
+
if (!is_pycall_pyptr(obj))
|
158
|
+
rb_raise(rb_eTypeError, "unexpected type %s (expected PyCall::PyPtr)", rb_class2name(CLASS_OF(obj)));
|
159
|
+
|
160
|
+
pyobj = get_pyobj_ptr(obj);
|
161
|
+
if (pytypeobj && Py_TYPE(pyobj) != pytypeobj)
|
162
|
+
rb_raise(rb_eTypeError, "unexpected Python type %s (expected %s)", Py_TYPE(pyobj)->tp_name, pytypeobj->tp_name);
|
163
|
+
|
164
|
+
return pyobj;
|
165
|
+
}
|
166
|
+
|
167
|
+
VALUE
|
168
|
+
pycall_pyptr_incref(VALUE pyptr)
|
169
|
+
{
|
170
|
+
PyObject *pyobj;
|
171
|
+
|
172
|
+
pyobj = try_get_pyobj_ptr(pyptr);
|
173
|
+
if (pyobj)
|
174
|
+
Py_API(Py_IncRef)(pyobj);
|
175
|
+
return pyptr;
|
176
|
+
}
|
177
|
+
|
178
|
+
static VALUE
|
179
|
+
pycall_pyptr_s_incref(VALUE klass, VALUE pyptr)
|
180
|
+
{
|
181
|
+
return pycall_pyptr_incref(pyptr);
|
182
|
+
}
|
183
|
+
|
184
|
+
void
|
185
|
+
pycall_Py_DecRef(PyObject *pyobj)
|
186
|
+
{
|
187
|
+
#ifdef PYCALL_DEBUG_DUMP_REFCNT
|
188
|
+
fprintf(stderr, "decref object %p of type %s, refcnt %"PRIdSIZE"\n",
|
189
|
+
pyobj,
|
190
|
+
pyobj ? Py_TYPE(pyobj)->tp_name : "nullptr",
|
191
|
+
pyobj ? pyobj->ob_refcnt : -1);
|
192
|
+
#endif /* PYCALL_DEBUG_DUMP_REFCNT */
|
193
|
+
Py_API(Py_DecRef)(pyobj);
|
194
|
+
}
|
195
|
+
|
196
|
+
VALUE
|
197
|
+
pycall_pyptr_decref(VALUE pyptr)
|
198
|
+
{
|
199
|
+
PyObject *pyobj;
|
200
|
+
|
201
|
+
pyobj = try_get_pyobj_ptr(pyptr);
|
202
|
+
if (pyobj) {
|
203
|
+
pycall_Py_DecRef(pyobj);
|
204
|
+
DATA_PTR(pyptr) = NULL;
|
205
|
+
}
|
206
|
+
return pyptr;
|
207
|
+
}
|
208
|
+
|
209
|
+
static VALUE
|
210
|
+
pycall_pyptr_s_decref(VALUE klass, VALUE pyptr)
|
211
|
+
{
|
212
|
+
return pycall_pyptr_decref(pyptr);
|
213
|
+
}
|
214
|
+
|
215
|
+
static VALUE
|
216
|
+
pycall_pyptr_s_sizeof(VALUE klass, VALUE pyptr)
|
217
|
+
{
|
218
|
+
size_t size;
|
219
|
+
PyObject *pyobj;
|
220
|
+
|
221
|
+
pyobj = try_get_pyobj_ptr(pyptr);
|
222
|
+
if (pyobj == NULL) return Qnil;
|
223
|
+
|
224
|
+
size = _PySys_GetSizeOf(pyobj);
|
225
|
+
return SIZET2NUM(size);
|
226
|
+
}
|
227
|
+
|
228
|
+
static VALUE
|
229
|
+
pycall_pyptr_allocate(VALUE klass)
|
230
|
+
{
|
231
|
+
return TypedData_Wrap_Struct(klass, &pycall_pyptr_data_type, NULL);
|
232
|
+
}
|
233
|
+
|
234
|
+
static inline VALUE
|
235
|
+
pycall_pyptr_new_with_klass(VALUE klass, PyObject *pyobj)
|
236
|
+
{
|
237
|
+
VALUE obj = pycall_pyptr_allocate(klass);
|
238
|
+
DATA_PTR(obj) = pyobj;
|
239
|
+
#ifdef PYCALL_DEBUG_DUMP_REFCNT
|
240
|
+
fprintf(stderr, "%s: object %p of type %s, refcnt=%"PRIdSIZE" (%s:%d)\n",
|
241
|
+
rb_class2name(klass), pyobj,
|
242
|
+
(pyobj ? Py_TYPE(pyobj)->tp_name : "(nullptr)"),
|
243
|
+
(pyobj ? pyobj->ob_refcnt : -1),
|
244
|
+
rb_sourcefile(), rb_sourceline());
|
245
|
+
#endif /* PYCALL_DEBUG_DUMP_REFCNT */
|
246
|
+
return obj;
|
247
|
+
}
|
248
|
+
|
249
|
+
VALUE
|
250
|
+
pycall_pyptr_new(PyObject *pyobj)
|
251
|
+
{
|
252
|
+
return pycall_pyptr_new_with_klass(cPyPtr, pyobj);
|
253
|
+
}
|
254
|
+
|
255
|
+
static VALUE
|
256
|
+
pycall_pyptr_initialize(VALUE pyptr, VALUE val)
|
257
|
+
{
|
258
|
+
VALUE addr;
|
259
|
+
PyObject *pyobj;
|
260
|
+
|
261
|
+
addr = rb_check_to_integer(val, "to_int");
|
262
|
+
if (NIL_P(addr)) {
|
263
|
+
rb_raise(rb_eTypeError, "Invalid PyObject address: %"PRIsVALUE, val);
|
264
|
+
}
|
265
|
+
|
266
|
+
pyobj = (PyObject *)NUM2PTR(addr);
|
267
|
+
DATA_PTR(pyptr) = pyobj;
|
268
|
+
return pyptr;
|
269
|
+
}
|
270
|
+
|
271
|
+
static VALUE
|
272
|
+
pycall_pyptr_is_null(VALUE obj)
|
273
|
+
{
|
274
|
+
PyObject* pyobj = get_pyobj_ptr(obj);
|
275
|
+
return pyobj ? Qfalse : Qtrue;
|
276
|
+
}
|
277
|
+
|
278
|
+
static VALUE
|
279
|
+
pycall_pyptr_is_none(VALUE obj)
|
280
|
+
{
|
281
|
+
PyObject* pyobj = get_pyobj_ptr(obj);
|
282
|
+
return pyobj == Py_API(_Py_NoneStruct) ? Qtrue : Qfalse;
|
283
|
+
}
|
284
|
+
|
285
|
+
static VALUE
|
286
|
+
pycall_pyptr_is_nil(VALUE obj)
|
287
|
+
{
|
288
|
+
PyObject* pyobj = get_pyobj_ptr(obj);
|
289
|
+
return (pyobj == Py_API(_Py_NoneStruct)) || (pyobj == NULL) ? Qtrue : Qfalse;
|
290
|
+
}
|
291
|
+
|
292
|
+
static VALUE
|
293
|
+
pycall_pyptr_eq(VALUE obj, VALUE other)
|
294
|
+
{
|
295
|
+
PyObject* pyobj;
|
296
|
+
PyObject* pyobj_other;
|
297
|
+
|
298
|
+
if (!is_pycall_pyptr(other)) return Qfalse;
|
299
|
+
|
300
|
+
pyobj = get_pyobj_ptr(obj);
|
301
|
+
pyobj_other = get_pyobj_ptr(other);
|
302
|
+
|
303
|
+
return pyobj == pyobj_other ? Qtrue : Qfalse;
|
304
|
+
}
|
305
|
+
|
306
|
+
static VALUE
|
307
|
+
pycall_pyptr_get_ptr_address(VALUE obj)
|
308
|
+
{
|
309
|
+
PyObject* pyobj = get_pyobj_ptr(obj);
|
310
|
+
return PTR2NUM(pyobj);
|
311
|
+
}
|
312
|
+
|
313
|
+
static VALUE
|
314
|
+
pycall_pyptr_get_ob_refcnt(VALUE obj)
|
315
|
+
{
|
316
|
+
PyObject* pyobj = get_pyobj_ptr(obj);
|
317
|
+
if (pyobj)
|
318
|
+
return SSIZET2NUM(pyobj->ob_refcnt);
|
319
|
+
return Qnil;
|
320
|
+
}
|
321
|
+
|
322
|
+
VALUE pycall_pytypeptr_new(PyObject *pytype);
|
323
|
+
|
324
|
+
static VALUE
|
325
|
+
pycall_pyptr_get_ob_type(VALUE obj)
|
326
|
+
{
|
327
|
+
PyObject* pyobj = get_pyobj_ptr(obj);
|
328
|
+
if (pyobj) {
|
329
|
+
VALUE res;
|
330
|
+
if (Py_TYPE(pyobj) == Py_API(PyInstance_Type))
|
331
|
+
res = pycall_pytype_to_ruby((PyObject *)((PyInstanceObject *)pyobj)->in_class);
|
332
|
+
else
|
333
|
+
res = pycall_pytype_to_ruby((PyObject *)pyobj->ob_type);
|
334
|
+
return res;
|
335
|
+
}
|
336
|
+
return Qnil;
|
337
|
+
}
|
338
|
+
|
339
|
+
static VALUE
|
340
|
+
pycall_pyptr_object_id(VALUE obj)
|
341
|
+
{
|
342
|
+
return rb_obj_id(obj);
|
343
|
+
}
|
344
|
+
|
345
|
+
static VALUE
|
346
|
+
pycall_pyptr_class(VALUE obj)
|
347
|
+
{
|
348
|
+
return CLASS_OF(obj);
|
349
|
+
}
|
350
|
+
|
351
|
+
static VALUE
|
352
|
+
pycall_pyptr_inspect(VALUE obj)
|
353
|
+
{
|
354
|
+
VALUE cname, str;
|
355
|
+
PyObject* pyobj = get_pyobj_ptr(obj);
|
356
|
+
|
357
|
+
cname = rb_class_name(CLASS_OF(obj));
|
358
|
+
str = rb_sprintf("#<%"PRIsVALUE":%p type=%s addr=%p>", cname, (void*)obj, Py_TYPE(pyobj)->tp_name, pyobj);
|
359
|
+
OBJ_INFECT(str, obj);
|
360
|
+
|
361
|
+
return str;
|
362
|
+
}
|
363
|
+
|
364
|
+
static VALUE
|
365
|
+
class_or_module_required(VALUE klass)
|
366
|
+
{
|
367
|
+
if (SPECIAL_CONST_P(klass)) goto not_class;
|
368
|
+
switch (BUILTIN_TYPE(klass)) {
|
369
|
+
case T_MODULE:
|
370
|
+
case T_CLASS:
|
371
|
+
case T_ICLASS:
|
372
|
+
break;
|
373
|
+
|
374
|
+
default:
|
375
|
+
not_class:
|
376
|
+
rb_raise(rb_eTypeError, "class or module required");
|
377
|
+
}
|
378
|
+
return klass;
|
379
|
+
}
|
380
|
+
|
381
|
+
static VALUE
|
382
|
+
pycall_pyptr_is_kind_of(VALUE obj, VALUE klass)
|
383
|
+
{
|
384
|
+
PyObject* pyobj = get_pyobj_ptr(obj);
|
385
|
+
VALUE res;
|
386
|
+
|
387
|
+
if (is_pycall_pyptr(klass)) {
|
388
|
+
int res;
|
389
|
+
PyObject* pyobj_klass = get_pyobj_ptr(klass);
|
390
|
+
res = Py_API(PyObject_IsInstance)(pyobj, pyobj_klass);
|
391
|
+
if (res >= 0) {
|
392
|
+
return res ? Qtrue : Qfalse;
|
393
|
+
}
|
394
|
+
Py_API(PyErr_Clear)();
|
395
|
+
}
|
396
|
+
|
397
|
+
klass = class_or_module_required(klass);
|
398
|
+
res = rb_class_inherited_p(CLASS_OF(obj), klass);
|
399
|
+
return NIL_P(res) ? Qfalse : res;
|
400
|
+
}
|
401
|
+
|
402
|
+
static VALUE
|
403
|
+
pycall_pyptr_hash(VALUE obj)
|
404
|
+
{
|
405
|
+
PyObject *pyobj = get_pyobj_ptr(obj);
|
406
|
+
Py_hash_t h;
|
407
|
+
|
408
|
+
if (!pyobj)
|
409
|
+
return PTR2NUM(pyobj);
|
410
|
+
|
411
|
+
h = PyObject_Hash(pyobj);
|
412
|
+
if (h == -1) {
|
413
|
+
Py_API(PyErr_Clear)();
|
414
|
+
return PTR2NUM(pyobj);
|
415
|
+
}
|
416
|
+
|
417
|
+
return SSIZET2NUM(h);
|
418
|
+
}
|
419
|
+
|
420
|
+
/* ==== PyTypePtr ==== */
|
421
|
+
|
422
|
+
const rb_data_type_t pycall_pytypeptr_data_type = {
|
423
|
+
"PyCall::PyTypePtr",
|
424
|
+
{ 0, pycall_pyptr_free, pycall_pyptr_memsize, },
|
425
|
+
#ifdef RUBY_TYPED_FREE_IMMEDIATELY
|
426
|
+
&pycall_pyptr_data_type, 0, RUBY_TYPED_FREE_IMMEDIATELY
|
427
|
+
#endif
|
428
|
+
};
|
429
|
+
|
430
|
+
static inline int
|
431
|
+
is_pycall_pytypeptr(VALUE obj)
|
432
|
+
{
|
433
|
+
return rb_typeddata_is_kind_of(obj, &pycall_pytypeptr_data_type);
|
434
|
+
}
|
435
|
+
|
436
|
+
static inline PyTypeObject*
|
437
|
+
get_pytypeobj_ptr(VALUE obj)
|
438
|
+
{
|
439
|
+
PyTypeObject *pytype;
|
440
|
+
TypedData_Get_Struct(obj, PyTypeObject, &pycall_pytypeptr_data_type, pytype);
|
441
|
+
return pytype;
|
442
|
+
}
|
443
|
+
|
444
|
+
static inline PyTypeObject*
|
445
|
+
try_get_pytypeobj_ptr(VALUE obj)
|
446
|
+
{
|
447
|
+
if (is_pycall_pytypeptr(obj)) return NULL;
|
448
|
+
return (PyTypeObject*)DATA_PTR(obj);
|
449
|
+
}
|
450
|
+
|
451
|
+
static inline PyTypeObject *
|
452
|
+
check_get_pytypeobj_ptr(VALUE obj)
|
453
|
+
{
|
454
|
+
PyTypeObject *pytypeobj;
|
455
|
+
if (!is_pycall_pytypeptr(obj))
|
456
|
+
rb_raise(rb_eTypeError, "unexpected type %s (expected PyCall::PyTypePtr)", rb_class2name(CLASS_OF(obj)));
|
457
|
+
|
458
|
+
pytypeobj = get_pytypeobj_ptr(obj);
|
459
|
+
if (!PyType_Check(pytypeobj))
|
460
|
+
rb_raise(rb_eTypeError, "unexpected Python type %s (expected type or class)", Py_TYPE(pytypeobj)->tp_name);
|
461
|
+
|
462
|
+
return pytypeobj;
|
463
|
+
}
|
464
|
+
|
465
|
+
static VALUE
|
466
|
+
pycall_pytypeptr_allocate(VALUE klass)
|
467
|
+
{
|
468
|
+
return TypedData_Wrap_Struct(klass, &pycall_pytypeptr_data_type, NULL);
|
469
|
+
}
|
470
|
+
|
471
|
+
static inline VALUE
|
472
|
+
pycall_pytypeptr_new_with_klass(VALUE klass, PyObject *pytypeobj)
|
473
|
+
{
|
474
|
+
VALUE obj = pycall_pytypeptr_allocate(klass);
|
475
|
+
DATA_PTR(obj) = pytypeobj;
|
476
|
+
return obj;
|
477
|
+
}
|
478
|
+
|
479
|
+
VALUE
|
480
|
+
pycall_pytypeptr_new(PyObject *pytypeobj)
|
481
|
+
{
|
482
|
+
return pycall_pytypeptr_new_with_klass(cPyTypePtr, pytypeobj);
|
483
|
+
}
|
484
|
+
|
485
|
+
static VALUE
|
486
|
+
pycall_pytypeptr_get_ob_size(VALUE obj)
|
487
|
+
{
|
488
|
+
PyTypeObject* pytype = get_pytypeobj_ptr(obj);
|
489
|
+
if (pytype)
|
490
|
+
return SSIZET2NUM(pytype->ob_size);
|
491
|
+
return Qnil;
|
492
|
+
}
|
493
|
+
|
494
|
+
static VALUE
|
495
|
+
pycall_pytypeptr_get_tp_name(VALUE obj)
|
496
|
+
{
|
497
|
+
PyTypeObject* pytype = get_pytypeobj_ptr(obj);
|
498
|
+
if (pytype) {
|
499
|
+
if (Py_TYPE(pytype) == Py_API(PyType_Type))
|
500
|
+
return rb_str_new2(pytype->tp_name);
|
501
|
+
return pycall_pyobject_to_ruby(((PyClassObject *)pytype)->cl_name);
|
502
|
+
}
|
503
|
+
return Qnil;
|
504
|
+
}
|
505
|
+
|
506
|
+
static VALUE
|
507
|
+
pycall_pytypeptr_get_tp_basicsize(VALUE obj)
|
508
|
+
{
|
509
|
+
PyTypeObject* pytype = get_pytypeobj_ptr(obj);
|
510
|
+
if (pytype) {
|
511
|
+
if (Py_TYPE(pytype) == Py_API(PyType_Type))
|
512
|
+
return SSIZET2NUM(pytype->tp_basicsize);
|
513
|
+
}
|
514
|
+
return Qnil;
|
515
|
+
}
|
516
|
+
|
517
|
+
static VALUE
|
518
|
+
pycall_pytypeptr_get_tp_flags(VALUE obj)
|
519
|
+
{
|
520
|
+
PyTypeObject* pytype = get_pytypeobj_ptr(obj);
|
521
|
+
if (pytype) {
|
522
|
+
if (Py_TYPE(pytype) == Py_API(PyType_Type))
|
523
|
+
return ULONG2NUM(pytype->tp_flags);
|
524
|
+
}
|
525
|
+
return Qnil;
|
526
|
+
}
|
527
|
+
|
528
|
+
static VALUE
|
529
|
+
pycall_pytypeptr_eqq(VALUE obj, VALUE other)
|
530
|
+
{
|
531
|
+
if (is_pycall_pyptr(other))
|
532
|
+
return pycall_pyptr_is_kind_of(other, obj);
|
533
|
+
return Qfalse;
|
534
|
+
}
|
535
|
+
|
536
|
+
/* ==== PyCall::LibPython::API ==== */
|
537
|
+
|
538
|
+
static VALUE
|
539
|
+
pycall_libpython_api_get_builtins_module_ptr(VALUE mod)
|
540
|
+
{
|
541
|
+
VALUE pyptr = pycall_pyptr_new(python_builtins_module);
|
542
|
+
Py_API(Py_IncRef)(python_builtins_module);
|
543
|
+
return pyptr;
|
544
|
+
}
|
545
|
+
|
546
|
+
static VALUE
|
547
|
+
pycall_libpython_api_PyObject_Dir(VALUE mod, VALUE pyptr)
|
548
|
+
{
|
549
|
+
PyObject *dir;
|
550
|
+
PyObject *pyobj;
|
551
|
+
|
552
|
+
if (!is_pycall_pyptr(pyptr)) {
|
553
|
+
rb_raise(rb_eTypeError, "PyCall::PyPtr is required");
|
554
|
+
}
|
555
|
+
|
556
|
+
pyobj = get_pyobj_ptr(pyptr);
|
557
|
+
dir = Py_API(PyObject_Dir)(pyobj);
|
558
|
+
if (pyobj && !dir) {
|
559
|
+
pycall_pyerror_fetch_and_raise("PyObject_Dir in pycall_libpython_api_PyObject_Dir");
|
560
|
+
}
|
561
|
+
|
562
|
+
return dir ? pycall_pyptr_new(dir) : Qnil;
|
563
|
+
}
|
564
|
+
|
565
|
+
static VALUE
|
566
|
+
pycall_libpython_api_PyList_Size(VALUE mod, VALUE pyptr)
|
567
|
+
{
|
568
|
+
PyObject *pyobj;
|
569
|
+
Py_ssize_t size;
|
570
|
+
|
571
|
+
if (!is_pycall_pyptr(pyptr)) {
|
572
|
+
rb_raise(rb_eTypeError, "PyCall::PyPtr is required");
|
573
|
+
}
|
574
|
+
|
575
|
+
pyobj = get_pyobj_ptr(pyptr);
|
576
|
+
size = Py_API(PyList_Size)(pyobj);
|
577
|
+
if (size < 0) {
|
578
|
+
pycall_pyerror_fetch_and_raise("PyList_Size in pycall_libpython_api_PyList_Size");
|
579
|
+
}
|
580
|
+
|
581
|
+
return SSIZET2NUM(size);
|
582
|
+
}
|
583
|
+
|
584
|
+
static VALUE
|
585
|
+
pycall_libpython_api_PyList_GetItem(VALUE mod, VALUE pyptr, VALUE idx)
|
586
|
+
{
|
587
|
+
PyObject *pyobj;
|
588
|
+
PyObject *pyobj_item;
|
589
|
+
Py_ssize_t i;
|
590
|
+
|
591
|
+
if (!is_pycall_pyptr(pyptr)) {
|
592
|
+
rb_raise(rb_eTypeError, "PyCall::PyPtr is required");
|
593
|
+
}
|
594
|
+
|
595
|
+
pyobj = get_pyobj_ptr(pyptr);
|
596
|
+
i = NUM2SSIZET(idx);
|
597
|
+
pyobj_item = Py_API(PyList_GetItem)(pyobj, i);
|
598
|
+
if (!pyobj_item) {
|
599
|
+
pycall_pyerror_fetch_and_raise("PyList_GetItem in pycall_libpython_api_PyList_GetItem");
|
600
|
+
}
|
601
|
+
|
602
|
+
return pycall_pyptr_new(pyobj_item);
|
603
|
+
}
|
604
|
+
|
605
|
+
/* ==== PyCall::Helpers ==== */
|
606
|
+
|
607
|
+
static VALUE
|
608
|
+
pycall_libpython_helpers_m_unicode_literals_p(VALUE mod)
|
609
|
+
{
|
610
|
+
return python_is_unicode_literals ? Qtrue : Qfalse;
|
611
|
+
}
|
612
|
+
|
613
|
+
VALUE
|
614
|
+
pycall_import_module(char const *name)
|
615
|
+
{
|
616
|
+
PyObject *pymod = Py_API(PyImport_ImportModule)(name);
|
617
|
+
if (!pymod) {
|
618
|
+
pycall_pyerror_fetch_and_raise("PyImport_ImportModule in pycall_libpython_helpers_m_import_module");
|
619
|
+
}
|
620
|
+
return pycall_pyobject_to_ruby(pymod);
|
621
|
+
}
|
622
|
+
|
623
|
+
VALUE
|
624
|
+
pycall_import_module_level(char const *name, VALUE globals, VALUE locals, VALUE fromlist, int level)
|
625
|
+
{
|
626
|
+
PyObject *pyglobals = NULL, *pylocals = NULL, *pyfromlist = NULL, *pymod;
|
627
|
+
|
628
|
+
if (!NIL_P(globals)) {
|
629
|
+
pyglobals = check_get_pyobj_ptr(globals, Py_API(PyDict_Type));
|
630
|
+
}
|
631
|
+
if (!NIL_P(locals)) {
|
632
|
+
pylocals = check_get_pyobj_ptr(locals, Py_API(PyDict_Type));
|
633
|
+
}
|
634
|
+
if (!NIL_P(fromlist)) {
|
635
|
+
fromlist = rb_convert_type(fromlist, T_ARRAY, "Array", "to_ary");
|
636
|
+
pyfromlist = pycall_pyobject_from_ruby(fromlist);
|
637
|
+
}
|
638
|
+
else {
|
639
|
+
/* TODO: set the default fromlist to ['*'] */
|
640
|
+
}
|
641
|
+
|
642
|
+
pymod = Py_API(PyImport_ImportModuleLevel)(name, pyglobals, pylocals, pyfromlist, level);
|
643
|
+
if (!pymod) {
|
644
|
+
pycall_pyerror_fetch_and_raise("PyImport_ImportModuleLevel in pycall_libpython_helpers_m_import_module");
|
645
|
+
}
|
646
|
+
|
647
|
+
return pycall_pyobject_to_ruby(pymod);
|
648
|
+
}
|
649
|
+
|
650
|
+
static VALUE
|
651
|
+
pycall_libpython_helpers_m_import_module(int argc, VALUE *argv, VALUE mod)
|
652
|
+
{
|
653
|
+
VALUE name, globals, locals, fromlist, level;
|
654
|
+
char const *name_cstr;
|
655
|
+
|
656
|
+
rb_scan_args(argc, argv, "14", &name, &globals, &locals, &fromlist, &level);
|
657
|
+
|
658
|
+
if (RB_TYPE_P(name, T_SYMBOL)) {
|
659
|
+
name = rb_sym_to_s(name);
|
660
|
+
}
|
661
|
+
|
662
|
+
name_cstr = StringValueCStr(name);
|
663
|
+
|
664
|
+
if (argc == 1) {
|
665
|
+
return pycall_import_module(name_cstr);
|
666
|
+
}
|
667
|
+
|
668
|
+
if (argc == 5) {
|
669
|
+
level = rb_check_to_integer(level, "to_int");
|
670
|
+
}
|
671
|
+
else {
|
672
|
+
/* TODO: set the default level to 0 */
|
673
|
+
}
|
674
|
+
|
675
|
+
return pycall_import_module_level(name_cstr, globals, locals, fromlist, NUM2INT(level));
|
676
|
+
}
|
677
|
+
|
678
|
+
static int
|
679
|
+
pycall_rich_compare_opid(VALUE op)
|
680
|
+
{
|
681
|
+
ID rb_opid;
|
682
|
+
|
683
|
+
Check_Type(op, T_SYMBOL);
|
684
|
+
rb_opid = SYM2ID(op);
|
685
|
+
|
686
|
+
if (rb_opid == '>')
|
687
|
+
return Py_GT;
|
688
|
+
if (rb_opid == '<')
|
689
|
+
return Py_LT;
|
690
|
+
if (rb_opid == rb_intern("=="))
|
691
|
+
return Py_EQ;
|
692
|
+
if (rb_opid == rb_intern("!="))
|
693
|
+
return Py_NE;
|
694
|
+
if (rb_opid == rb_intern(">="))
|
695
|
+
return Py_GE;
|
696
|
+
if (rb_opid == rb_intern("<="))
|
697
|
+
return Py_LE;
|
698
|
+
|
699
|
+
rb_raise(rb_eArgError, "invalid compare operator: %"PRIsVALUE, op);
|
700
|
+
}
|
701
|
+
|
702
|
+
static VALUE
|
703
|
+
pycall_libpython_helpers_m_compare(VALUE mod, VALUE op, VALUE pyptr_a, VALUE pyptr_b)
|
704
|
+
{
|
705
|
+
PyObject *pyobj_a, *pyobj_b, *res;
|
706
|
+
int opid;
|
707
|
+
|
708
|
+
opid = pycall_rich_compare_opid(op);
|
709
|
+
|
710
|
+
if (!is_pycall_pyptr(pyptr_a)) {
|
711
|
+
rb_raise(rb_eTypeError, "unexpected 2nd argument type %s (expected PyCall::PyPtr)", rb_class2name(CLASS_OF(pyptr_a)));
|
712
|
+
}
|
713
|
+
if (!is_pycall_pyptr(pyptr_b)) {
|
714
|
+
rb_raise(rb_eTypeError, "unexpected 3rd argument type %s (expected PyCall::PyPtr)", rb_class2name(CLASS_OF(pyptr_b)));
|
715
|
+
}
|
716
|
+
|
717
|
+
pyobj_a = get_pyobj_ptr(pyptr_a);
|
718
|
+
pyobj_b = get_pyobj_ptr(pyptr_b);
|
719
|
+
|
720
|
+
res = Py_API(PyObject_RichCompare)(pyobj_a, pyobj_b, opid);
|
721
|
+
if (!res) {
|
722
|
+
pycall_pyerror_fetch_and_raise("PyObject_RichCompare in pycall_libpython_helpers_m_compare");
|
723
|
+
}
|
724
|
+
|
725
|
+
return pycall_pyobject_to_ruby(res);
|
726
|
+
}
|
727
|
+
|
728
|
+
static int is_pyobject_wrapper(VALUE obj);
|
729
|
+
static PyObject * pycall_pyobject_wrapper_get_pyobj_ptr(VALUE obj);
|
730
|
+
|
731
|
+
VALUE
|
732
|
+
pycall_getattr_default(VALUE obj, char const *name, VALUE default_value)
|
733
|
+
{
|
734
|
+
PyObject *pyobj, *res;
|
735
|
+
|
736
|
+
if (is_pyobject_wrapper(obj)) {
|
737
|
+
pyobj = pycall_pyobject_wrapper_get_pyobj_ptr(obj);
|
738
|
+
}
|
739
|
+
else {
|
740
|
+
pyobj = check_get_pyobj_ptr(obj, NULL);
|
741
|
+
}
|
742
|
+
|
743
|
+
res = Py_API(PyObject_GetAttrString)(pyobj, name);
|
744
|
+
if (!res && default_value == Qundef) {
|
745
|
+
pycall_pyerror_fetch_and_raise("PyObject_GetAttrString in pycall_libpython_helpers_m_getattr");
|
746
|
+
}
|
747
|
+
Py_API(PyErr_Clear)();
|
748
|
+
return res ? pycall_pyobject_to_ruby(res) : default_value;
|
749
|
+
}
|
750
|
+
|
751
|
+
VALUE
|
752
|
+
pycall_getattr(VALUE pyptr, char const *name)
|
753
|
+
{
|
754
|
+
return pycall_getattr_default(pyptr, name, Qundef);
|
755
|
+
}
|
756
|
+
|
757
|
+
static VALUE
|
758
|
+
pycall_libpython_helpers_m_getattr(int argc, VALUE *argv, VALUE mod)
|
759
|
+
{
|
760
|
+
VALUE pyptr, name, default_value;
|
761
|
+
|
762
|
+
if (rb_scan_args(argc, argv, "21", &pyptr, &name, &default_value) == 2) {
|
763
|
+
default_value = Qundef;
|
764
|
+
}
|
765
|
+
|
766
|
+
if (!is_pycall_pyptr(pyptr)) {
|
767
|
+
rb_raise(rb_eTypeError, "PyCall::PyPtr is required");
|
768
|
+
}
|
769
|
+
|
770
|
+
if (RB_TYPE_P(name, T_SYMBOL)) {
|
771
|
+
name = rb_sym_to_s(name);
|
772
|
+
}
|
773
|
+
|
774
|
+
return pycall_getattr_default(pyptr, StringValueCStr(name), default_value);
|
775
|
+
}
|
776
|
+
|
777
|
+
static VALUE
|
778
|
+
pycall_libpython_helpers_m_hasattr_p(VALUE mod, VALUE pyptr, VALUE name)
|
779
|
+
{
|
780
|
+
PyObject *pyobj;
|
781
|
+
int res;
|
782
|
+
|
783
|
+
if (!is_pycall_pyptr(pyptr)) {
|
784
|
+
rb_raise(rb_eTypeError, "PyCall::PyPtr is required");
|
785
|
+
}
|
786
|
+
|
787
|
+
pyobj = get_pyobj_ptr(pyptr);
|
788
|
+
|
789
|
+
if (RB_TYPE_P(name, T_SYMBOL)) {
|
790
|
+
name = rb_sym_to_s(name);
|
791
|
+
}
|
792
|
+
|
793
|
+
res = Py_API(PyObject_HasAttrString)(pyobj, StringValueCStr(name));
|
794
|
+
return res ? Qtrue : Qfalse;
|
795
|
+
}
|
796
|
+
|
797
|
+
static VALUE
|
798
|
+
pycall_libpython_helpers_m_callable_p(VALUE mod, VALUE pyptr)
|
799
|
+
{
|
800
|
+
PyObject *pyobj;
|
801
|
+
int res;
|
802
|
+
|
803
|
+
if (!is_pycall_pyptr(pyptr)) {
|
804
|
+
rb_raise(rb_eTypeError, "PyCall::PyPtr is required");
|
805
|
+
}
|
806
|
+
|
807
|
+
pyobj = get_pyobj_ptr(pyptr);
|
808
|
+
|
809
|
+
res = Py_API(PyCallable_Check)(pyobj);
|
810
|
+
return res ? Qtrue : Qfalse;
|
811
|
+
}
|
812
|
+
|
813
|
+
static VALUE
|
814
|
+
pycall_libpython_helpers_m_call_object(int argc, VALUE *argv, VALUE mod)
|
815
|
+
{
|
816
|
+
VALUE pyptr;
|
817
|
+
PyObject *pyobj;
|
818
|
+
|
819
|
+
if (argc < 1) {
|
820
|
+
rb_raise(rb_eArgError, "too few arguments (%d for >=1)", argc);
|
821
|
+
}
|
822
|
+
|
823
|
+
pyptr = argv[0];
|
824
|
+
if (!is_pycall_pyptr(pyptr)) {
|
825
|
+
rb_raise(rb_eTypeError, "PyCall::PyPtr is required");
|
826
|
+
}
|
827
|
+
|
828
|
+
pyobj = get_pyobj_ptr(pyptr);
|
829
|
+
if (!Py_API(PyCallable_Check)(pyobj)) {
|
830
|
+
rb_raise(rb_eTypeError, "Non-callable Python object was given");
|
831
|
+
}
|
832
|
+
|
833
|
+
if (argc == 1) {
|
834
|
+
return pycall_call_python_callable(pyobj, 0, NULL);
|
835
|
+
}
|
836
|
+
else {
|
837
|
+
return pycall_call_python_callable(pyobj, argc - 1, argv + 1);
|
838
|
+
}
|
839
|
+
}
|
840
|
+
|
841
|
+
static int
|
842
|
+
pycall_extract_kwargs_from_ruby_hash(VALUE key, VALUE value, VALUE arg)
|
843
|
+
{
|
844
|
+
PyObject *kwargs = (PyObject *)arg;
|
845
|
+
char const *key_cstr;
|
846
|
+
PyObject *pyvalue;
|
847
|
+
|
848
|
+
if (RB_TYPE_P(key, T_SYMBOL)) {
|
849
|
+
key = rb_sym_to_s(key);
|
850
|
+
}
|
851
|
+
key_cstr = StringValueCStr(key);
|
852
|
+
pyvalue = pycall_pyobject_from_ruby(value);
|
853
|
+
|
854
|
+
if (Py_API(PyDict_SetItemString)(kwargs, key_cstr, pyvalue) < 0) {
|
855
|
+
return ST_STOP;
|
856
|
+
}
|
857
|
+
return ST_CONTINUE;
|
858
|
+
}
|
859
|
+
|
860
|
+
static VALUE
|
861
|
+
pycall_call_python_callable(PyObject *pycallable, int argc, VALUE *argv)
|
862
|
+
{
|
863
|
+
PyObject *args, *res;
|
864
|
+
PyObject *kwargs = NULL;
|
865
|
+
Py_ssize_t i, n;
|
866
|
+
VALUE hash, obj;
|
867
|
+
|
868
|
+
/* TODO: Use inspect.getfullargspec */
|
869
|
+
|
870
|
+
if (argc > 0) {
|
871
|
+
n = argc - RB_TYPE_P(argv[argc - 1], T_HASH);
|
872
|
+
}
|
873
|
+
else {
|
874
|
+
n = 0;
|
875
|
+
}
|
876
|
+
|
877
|
+
args = Py_API(PyTuple_New)(n);
|
878
|
+
if (!args) {
|
879
|
+
pycall_pyerror_fetch_and_raise("PyTuple_New in pycall_call_python_callable");
|
880
|
+
}
|
881
|
+
|
882
|
+
for (i = 0; i < n; ++i) {
|
883
|
+
PyObject *pytem = pycall_pyobject_from_ruby(argv[i]);
|
884
|
+
if (Py_API(PyTuple_SetItem)(args, i, pytem) == -1) {
|
885
|
+
pycall_Py_DecRef(pytem);
|
886
|
+
pycall_Py_DecRef(args);
|
887
|
+
pycall_pyerror_fetch_and_raise("PyTuple_SetItem in pycall_call_python_callable");
|
888
|
+
}
|
889
|
+
/* NOTE: Although PyTuple_SetItem steals the item reference,
|
890
|
+
* it is unnecessary to call Py_IncRef for the item because
|
891
|
+
* pycall_pyobject_from_ruby increments the reference count
|
892
|
+
* of its result. */
|
893
|
+
}
|
894
|
+
|
895
|
+
if (n < argc) {
|
896
|
+
hash = argv[argc - 1];
|
897
|
+
kwargs = Py_API(PyDict_New)();
|
898
|
+
if (!RHASH_EMPTY_P(hash)) {
|
899
|
+
rb_hash_foreach(hash, pycall_extract_kwargs_from_ruby_hash, (VALUE)kwargs);
|
900
|
+
if (Py_API(PyErr_Occurred)() != NULL) {
|
901
|
+
pycall_Py_DecRef(args);
|
902
|
+
pycall_pyerror_fetch_and_raise("PyDict_SetItemString in pycall_extract_kwargs_from_ruby_hash");
|
903
|
+
}
|
904
|
+
}
|
905
|
+
}
|
906
|
+
|
907
|
+
res = Py_API(PyObject_Call)(pycallable, args, kwargs); /* New reference */
|
908
|
+
if (!res) {
|
909
|
+
pycall_pyerror_fetch_and_raise("PyObject_Call in pycall_call_python_callable");
|
910
|
+
}
|
911
|
+
obj = pycall_pyobject_to_ruby(res);
|
912
|
+
pycall_Py_DecRef(res);
|
913
|
+
return obj;
|
914
|
+
}
|
915
|
+
|
916
|
+
static VALUE
|
917
|
+
pycall_pyobject_wrapper_wrapper_method(int argc, VALUE *argv, VALUE wrapper)
|
918
|
+
{
|
919
|
+
VALUE pyptr, name;
|
920
|
+
char *name_cstr;
|
921
|
+
PyObject *pyobj, *attr;
|
922
|
+
|
923
|
+
pyptr = rb_attr_get(wrapper, rb_intern("@__pyptr__"));
|
924
|
+
if (NIL_P(pyptr) || !is_pycall_pyptr(pyptr)) {
|
925
|
+
rb_raise(rb_eTypeError, "Wrong wrapper object is given");
|
926
|
+
}
|
927
|
+
|
928
|
+
pyobj = get_pyobj_ptr(pyptr);
|
929
|
+
|
930
|
+
name = rb_id2str(rb_frame_this_func());
|
931
|
+
name_cstr = StringValueCStr(name);
|
932
|
+
|
933
|
+
if (name_cstr[RSTRING_LEN(name) - 1] == '=') {
|
934
|
+
int res;
|
935
|
+
VALUE val;
|
936
|
+
|
937
|
+
rb_scan_args(argc, argv, "1", &val);
|
938
|
+
|
939
|
+
attr = pycall_pyobject_from_ruby(val);
|
940
|
+
if (!attr) {
|
941
|
+
pycall_pyerror_fetch_and_raise("pycall_pyobject_from_ruby in pycall_pyobject_wrapper_wrapper_method");
|
942
|
+
}
|
943
|
+
|
944
|
+
name_cstr[RSTRING_LEN(name) - 1] = '\0';
|
945
|
+
res = Py_API(PyObject_SetAttrString)(pyobj, name_cstr, attr);
|
946
|
+
name_cstr[RSTRING_LEN(name) - 1] = '=';
|
947
|
+
if (res == -1) {
|
948
|
+
pycall_Py_DecRef(attr);
|
949
|
+
pycall_pyerror_fetch_and_raise("PyObject_SetAttrString in pycall_pyobject_wrapper_wrapper_method");
|
950
|
+
}
|
951
|
+
|
952
|
+
return val;
|
953
|
+
}
|
954
|
+
|
955
|
+
attr = Py_API(PyObject_GetAttrString)(pyobj, name_cstr);
|
956
|
+
if (!attr) {
|
957
|
+
pycall_pyerror_fetch_and_raise("PyObject_GetAttrString in pycall_pyobject_wrapper_wrapper_method");
|
958
|
+
}
|
959
|
+
|
960
|
+
if (!Py_API(PyCallable_Check)(attr))
|
961
|
+
return pycall_pyobject_to_ruby(attr);
|
962
|
+
|
963
|
+
if (PyType_Check(attr) || PyClass_Check(attr))
|
964
|
+
return pycall_pyobject_to_ruby(attr);
|
965
|
+
|
966
|
+
return pycall_call_python_callable(attr, argc, argv);
|
967
|
+
}
|
968
|
+
|
969
|
+
static VALUE
|
970
|
+
pycall_libpython_helpers_m_define_wrapper_method(VALUE mod, VALUE wrapper, VALUE name)
|
971
|
+
{
|
972
|
+
VALUE pyptr, name_sym;
|
973
|
+
PyObject *pyobj, *attr;
|
974
|
+
char *name_cstr;
|
975
|
+
|
976
|
+
pyptr = rb_attr_get(wrapper, rb_intern("@__pyptr__"));
|
977
|
+
if (NIL_P(pyptr) || !is_pycall_pyptr(pyptr)) {
|
978
|
+
rb_raise(rb_eTypeError, "Wrong wrapper object is given");
|
979
|
+
}
|
980
|
+
|
981
|
+
pyobj = get_pyobj_ptr(pyptr);
|
982
|
+
|
983
|
+
if (RB_TYPE_P(name, T_SYMBOL)) {
|
984
|
+
name_sym = name;
|
985
|
+
name = rb_sym_to_s(name);
|
986
|
+
}
|
987
|
+
else if (RB_TYPE_P(name, T_STRING)) {
|
988
|
+
name_sym = rb_str_intern(name);
|
989
|
+
}
|
990
|
+
|
991
|
+
name_cstr = StringValueCStr(name);
|
992
|
+
if (name_cstr[RSTRING_LEN(name) - 1] == '=') {
|
993
|
+
name_cstr[RSTRING_LEN(name) - 1] = '\0';
|
994
|
+
attr = Py_API(PyObject_GetAttrString)(pyobj, name_cstr);
|
995
|
+
name_cstr[RSTRING_LEN(name) - 1] = '=';
|
996
|
+
}
|
997
|
+
else {
|
998
|
+
attr = Py_API(PyObject_GetAttrString)(pyobj, name_cstr);
|
999
|
+
}
|
1000
|
+
if (!attr) {
|
1001
|
+
pycall_pyerror_fetch_and_raise("PyObject_GetAttrString in pycall_libpython_helpers_m_define_wrapper_method");
|
1002
|
+
}
|
1003
|
+
|
1004
|
+
pycall_Py_DecRef(attr);
|
1005
|
+
rb_define_singleton_method(wrapper, name_cstr, pycall_pyobject_wrapper_wrapper_method, -1);
|
1006
|
+
|
1007
|
+
return Qnil;
|
1008
|
+
}
|
1009
|
+
|
1010
|
+
static PyObject *
|
1011
|
+
pycall_convert_index(VALUE index)
|
1012
|
+
{
|
1013
|
+
PyObject *pyobj;
|
1014
|
+
|
1015
|
+
if (RB_TYPE_P(index, T_ARRAY) && RARRAY_LEN(index) == 1) {
|
1016
|
+
index = RARRAY_AREF(index, 0);
|
1017
|
+
}
|
1018
|
+
if (RB_TYPE_P(index, T_ARRAY)) {
|
1019
|
+
long i, n = RARRAY_LEN(index);
|
1020
|
+
pyobj = Py_API(PyTuple_New)(n);
|
1021
|
+
for (i = 0; i < n; ++i) {
|
1022
|
+
PyObject *pytem = pycall_convert_index(RARRAY_AREF(index, i)); /* New reference */
|
1023
|
+
Py_API(PyTuple_SetItem)(pyobj, i, pytem); /* Steal reference */
|
1024
|
+
}
|
1025
|
+
}
|
1026
|
+
else if (rb_obj_is_kind_of(index, rb_cRange)) {
|
1027
|
+
pyobj = pycall_pyslice_from_ruby(index); /* New refrence */
|
1028
|
+
}
|
1029
|
+
else if (pycall_obj_is_step_range(index)) {
|
1030
|
+
pyobj = pycall_pyslice_from_ruby(index); /* New refrence */
|
1031
|
+
}
|
1032
|
+
else {
|
1033
|
+
pyobj = pycall_pyobject_from_ruby(index); /* New reference */
|
1034
|
+
}
|
1035
|
+
|
1036
|
+
return pyobj;
|
1037
|
+
}
|
1038
|
+
|
1039
|
+
static VALUE
|
1040
|
+
pycall_libpython_helpers_m_getitem(VALUE mod, VALUE pyptr, VALUE key)
|
1041
|
+
{
|
1042
|
+
PyObject *pyobj, *pyobj_key, *pyobj_v;
|
1043
|
+
VALUE obj;
|
1044
|
+
|
1045
|
+
if (!is_pycall_pyptr(pyptr)) {
|
1046
|
+
rb_raise(rb_eTypeError, "PyCall::PyPtr is required");
|
1047
|
+
}
|
1048
|
+
|
1049
|
+
pyobj = get_pyobj_ptr(pyptr);
|
1050
|
+
|
1051
|
+
pyobj_key = pycall_convert_index(key);
|
1052
|
+
|
1053
|
+
pyobj_v = Py_API(PyObject_GetItem)(pyobj, pyobj_key);
|
1054
|
+
if (!pyobj_v) {
|
1055
|
+
pycall_pyerror_fetch_and_raise("PyObject_GetItem in pycall_libpython_helpers_m_getitem");
|
1056
|
+
}
|
1057
|
+
|
1058
|
+
obj = pycall_pyobject_to_ruby(pyobj_v);
|
1059
|
+
pycall_Py_DecRef(pyobj_v);
|
1060
|
+
return obj;
|
1061
|
+
}
|
1062
|
+
|
1063
|
+
static VALUE
|
1064
|
+
pycall_libpython_helpers_m_setitem(VALUE mod, VALUE pyptr, VALUE key, VALUE v)
|
1065
|
+
{
|
1066
|
+
PyObject *pyobj, *pyobj_key, *pyobj_value;
|
1067
|
+
int res;
|
1068
|
+
|
1069
|
+
pyobj = check_get_pyobj_ptr(pyptr, NULL);
|
1070
|
+
pyobj_key = pycall_convert_index(key);
|
1071
|
+
pyobj_value = pycall_pyobject_from_ruby(v);
|
1072
|
+
|
1073
|
+
res = Py_API(PyObject_SetItem)(pyobj, pyobj_key, pyobj_value);
|
1074
|
+
if (res == -1) {
|
1075
|
+
pycall_pyerror_fetch_and_raise("PyObject_SetItem in pycall_libpython_helpers_m_setitem");
|
1076
|
+
}
|
1077
|
+
Py_API(Py_DecRef(pyobj_key));
|
1078
|
+
Py_API(Py_DecRef(pyobj_value));
|
1079
|
+
|
1080
|
+
return v;
|
1081
|
+
}
|
1082
|
+
|
1083
|
+
static VALUE
|
1084
|
+
pycall_libpython_helpers_m_delitem(VALUE mod, VALUE pyptr, VALUE key, VALUE v)
|
1085
|
+
{
|
1086
|
+
PyObject *pyobj, *pyobj_key;
|
1087
|
+
int res;
|
1088
|
+
|
1089
|
+
pyobj = check_get_pyobj_ptr(pyptr, NULL);
|
1090
|
+
pyobj_key = pycall_convert_index(key);
|
1091
|
+
|
1092
|
+
res = Py_API(PyObject_DelItem)(pyobj, pyobj_key);
|
1093
|
+
if (res == -1) {
|
1094
|
+
pycall_pyerror_fetch_and_raise("PyObject_DelItem");
|
1095
|
+
}
|
1096
|
+
|
1097
|
+
return v;
|
1098
|
+
}
|
1099
|
+
|
1100
|
+
static VALUE
|
1101
|
+
pycall_libpython_helpers_m_str(VALUE mod, VALUE pyptr)
|
1102
|
+
{
|
1103
|
+
PyObject *pyobj, *pyobj_str;
|
1104
|
+
|
1105
|
+
pyobj = check_get_pyobj_ptr(pyptr, NULL);
|
1106
|
+
|
1107
|
+
pyobj_str = Py_API(PyObject_Str)(pyobj);
|
1108
|
+
if (!pyobj_str) {
|
1109
|
+
pycall_pyerror_fetch_and_raise("PyObject_Str");
|
1110
|
+
}
|
1111
|
+
|
1112
|
+
return pycall_pyobject_to_ruby(pyobj_str);
|
1113
|
+
}
|
1114
|
+
|
1115
|
+
static VALUE
|
1116
|
+
pycall_libpython_helpers_m_dict_contains(VALUE mod, VALUE pyptr, VALUE key)
|
1117
|
+
{
|
1118
|
+
PyObject *pyobj, *pyobj_key;
|
1119
|
+
int res;
|
1120
|
+
|
1121
|
+
pyobj = check_get_pyobj_ptr(pyptr, Py_API(PyDict_Type));
|
1122
|
+
pyobj_key = pycall_pyobject_from_ruby(key);
|
1123
|
+
res = Py_API(PyDict_Contains)(pyobj, pyobj_key);
|
1124
|
+
if (res == -1) {
|
1125
|
+
pycall_pyerror_fetch_and_raise("PyDict_Contains");
|
1126
|
+
}
|
1127
|
+
|
1128
|
+
return res ? Qtrue : Qfalse;
|
1129
|
+
}
|
1130
|
+
|
1131
|
+
static VALUE
|
1132
|
+
pycall_libpython_helpers_m_dict_each(VALUE mod, VALUE pyptr)
|
1133
|
+
{
|
1134
|
+
PyObject *pyobj, *pyobj_key, *pyobj_value;
|
1135
|
+
Py_ssize_t pos;
|
1136
|
+
|
1137
|
+
pyobj = check_get_pyobj_ptr(pyptr, Py_API(PyDict_Type));
|
1138
|
+
|
1139
|
+
pos = 0;
|
1140
|
+
while (Py_API(PyDict_Next)(pyobj, &pos, &pyobj_key, &pyobj_value)) {
|
1141
|
+
VALUE key, value;
|
1142
|
+
key = pycall_pyobject_to_ruby(pyobj_key);
|
1143
|
+
value = pycall_pyobject_to_ruby(pyobj_value);
|
1144
|
+
rb_yield(rb_assoc_new(key, value));
|
1145
|
+
}
|
1146
|
+
|
1147
|
+
return Qnil;
|
1148
|
+
}
|
1149
|
+
|
1150
|
+
static VALUE
|
1151
|
+
pycall_libpython_helpers_m_sequence_contains(VALUE mod, VALUE pyptr, VALUE key)
|
1152
|
+
{
|
1153
|
+
PyObject *pyobj, *pyobj_key;
|
1154
|
+
int res;
|
1155
|
+
|
1156
|
+
pyobj = check_get_pyobj_ptr(pyptr, NULL);
|
1157
|
+
if (!Py_API(PySequence_Check)(pyobj))
|
1158
|
+
rb_raise(rb_eTypeError, "unexpected Python type %s (expected a Python sequence object)", Py_TYPE(pyobj)->tp_name);
|
1159
|
+
|
1160
|
+
pyobj_key = pycall_pyobject_from_ruby(key);
|
1161
|
+
res = Py_API(PySequence_Contains)(pyobj, pyobj_key);
|
1162
|
+
if (res == -1) {
|
1163
|
+
pycall_pyerror_fetch_and_raise("PySequence_Contains");
|
1164
|
+
}
|
1165
|
+
|
1166
|
+
return res ? Qtrue : Qfalse;
|
1167
|
+
}
|
1168
|
+
|
1169
|
+
static VALUE
|
1170
|
+
pycall_libpython_helpers_m_sequence_each(VALUE mod, VALUE pyptr)
|
1171
|
+
{
|
1172
|
+
PyObject *pyobj, *pyobj_iter, *pyobj_item;
|
1173
|
+
|
1174
|
+
pyobj = check_get_pyobj_ptr(pyptr, NULL);
|
1175
|
+
if (!Py_API(PySequence_Check)(pyobj))
|
1176
|
+
rb_raise(rb_eTypeError, "unexpected Python type %s (expected a Python sequence object)", Py_TYPE(pyobj)->tp_name);
|
1177
|
+
|
1178
|
+
pyobj_iter = Py_API(PyObject_GetIter)(pyobj);
|
1179
|
+
if (!pyobj_iter) {
|
1180
|
+
pycall_pyerror_fetch_and_raise("PyObject_GetIter in pycall_libpython_helpers_m_sequence_each");
|
1181
|
+
}
|
1182
|
+
|
1183
|
+
while ((pyobj_item = Py_API(PyIter_Next)(pyobj_iter))) {
|
1184
|
+
rb_yield(pycall_pyobject_to_ruby(pyobj_item));
|
1185
|
+
pycall_Py_DecRef(pyobj_item);
|
1186
|
+
}
|
1187
|
+
|
1188
|
+
pycall_Py_DecRef(pyobj_iter);
|
1189
|
+
|
1190
|
+
if (Py_API(PyErr_Occurred)() != NULL) {
|
1191
|
+
pycall_pyerror_fetch_and_raise("checking error just in case at the end of pycall_libpython_helpers_m_sequence_each");
|
1192
|
+
}
|
1193
|
+
|
1194
|
+
return Qnil;
|
1195
|
+
}
|
1196
|
+
|
1197
|
+
/* ==== PyCall::PyObjectWrapper ==== */
|
1198
|
+
|
1199
|
+
static int
|
1200
|
+
is_pyobject_wrapper(VALUE obj)
|
1201
|
+
{
|
1202
|
+
return RTEST(rb_obj_is_kind_of(obj, mPyObjectWrapper));
|
1203
|
+
}
|
1204
|
+
|
1205
|
+
static VALUE
|
1206
|
+
pycall_pyobject_wrapper_get_pyptr(VALUE obj)
|
1207
|
+
{
|
1208
|
+
if (!is_pyobject_wrapper(obj)) {
|
1209
|
+
rb_raise(rb_eTypeError, "PyCal::PyObjectWrapper is required");
|
1210
|
+
}
|
1211
|
+
|
1212
|
+
return rb_funcall(obj, rb_intern("__pyptr__"), 0);
|
1213
|
+
}
|
1214
|
+
|
1215
|
+
static PyObject *
|
1216
|
+
pycall_pyobject_wrapper_get_pyobj_ptr(VALUE obj)
|
1217
|
+
{
|
1218
|
+
VALUE pyptr = pycall_pyobject_wrapper_get_pyptr(obj);
|
1219
|
+
return get_pyobj_ptr(pyptr);
|
1220
|
+
}
|
1221
|
+
|
1222
|
+
static PyObject *
|
1223
|
+
pycall_pyobject_wrapper_check_get_pyobj_ptr(VALUE obj, PyTypeObject *pytypeobj)
|
1224
|
+
{
|
1225
|
+
PyObject *pyobj;
|
1226
|
+
|
1227
|
+
pyobj = pycall_pyobject_wrapper_get_pyobj_ptr(obj);
|
1228
|
+
if (Py_TYPE(pyobj) != pytypeobj) {
|
1229
|
+
rb_raise(rb_eTypeError, "unexpected Python type %s (expected %s)", Py_TYPE(pyobj)->tp_name, pytypeobj->tp_name);
|
1230
|
+
}
|
1231
|
+
|
1232
|
+
return pyobj;
|
1233
|
+
}
|
1234
|
+
|
1235
|
+
/* ==== PyCall::Conversion ==== */
|
1236
|
+
|
1237
|
+
static VALUE
|
1238
|
+
pycall_python_type_mapping_get_mapped_class(VALUE pytypeptr)
|
1239
|
+
{
|
1240
|
+
(void)check_get_pytypeobj_ptr(pytypeptr);
|
1241
|
+
return rb_hash_lookup(python_type_mapping, pytypeptr);
|
1242
|
+
}
|
1243
|
+
|
1244
|
+
static int
|
1245
|
+
pycall_python_type_mapping_register(VALUE pytypeptr, VALUE rbcls)
|
1246
|
+
{
|
1247
|
+
(void)check_get_pytypeobj_ptr(pytypeptr);
|
1248
|
+
if (rb_hash_lookup2(python_type_mapping, pytypeptr, Qundef) != Qundef)
|
1249
|
+
return 0;
|
1250
|
+
|
1251
|
+
Check_Type(rbcls, T_CLASS);
|
1252
|
+
if (!rb_obj_is_kind_of(rbcls, mPyTypeObjectWrapper)) {
|
1253
|
+
rb_raise(rb_eTypeError, "ruby class must be extended by PyCall::PyTypeObjectWrapper");
|
1254
|
+
}
|
1255
|
+
|
1256
|
+
/* TODO: Shouldn't have to use weak reference? */
|
1257
|
+
rb_hash_aset(python_type_mapping, pytypeptr, rbcls);
|
1258
|
+
|
1259
|
+
return 1;
|
1260
|
+
}
|
1261
|
+
|
1262
|
+
static int
|
1263
|
+
pycall_python_type_mapping_unregister(VALUE pytypeptr)
|
1264
|
+
{
|
1265
|
+
(void)check_get_pytypeobj_ptr(pytypeptr);
|
1266
|
+
if (rb_hash_lookup2(python_type_mapping, pytypeptr, Qundef) == Qundef)
|
1267
|
+
return 0;
|
1268
|
+
|
1269
|
+
rb_hash_delete(python_type_mapping, pytypeptr);
|
1270
|
+
return 1;
|
1271
|
+
}
|
1272
|
+
|
1273
|
+
VALUE
|
1274
|
+
pycall_pyobject_wrapper_object_new(VALUE klass, PyObject *pyobj)
|
1275
|
+
{
|
1276
|
+
VALUE obj;
|
1277
|
+
|
1278
|
+
obj = rb_obj_alloc(klass);
|
1279
|
+
rb_ivar_set(obj, rb_intern("@__pyptr__"), pycall_pyptr_new(pyobj));
|
1280
|
+
rb_extend_object(obj, mPyObjectWrapper);
|
1281
|
+
|
1282
|
+
return obj;
|
1283
|
+
}
|
1284
|
+
|
1285
|
+
VALUE
|
1286
|
+
pycall_pyobject_to_ruby(PyObject *pyobj)
|
1287
|
+
{
|
1288
|
+
VALUE cls;
|
1289
|
+
|
1290
|
+
if (pyobj == Py_API(_Py_NoneStruct))
|
1291
|
+
return Qnil;
|
1292
|
+
|
1293
|
+
if (PyRuby_Check(pyobj))
|
1294
|
+
return PyRuby_get_ruby_object(pyobj);
|
1295
|
+
|
1296
|
+
if (PyType_Check(pyobj))
|
1297
|
+
return pycall_pytype_to_ruby(pyobj); /* Increment pyobj refcnt */
|
1298
|
+
|
1299
|
+
if (PyClass_Check(pyobj))
|
1300
|
+
return pycall_pytype_to_ruby(pyobj); /* Increment pyobj refcnt */
|
1301
|
+
|
1302
|
+
if (pyobj->ob_type == Py_API(PyModule_Type))
|
1303
|
+
return pycall_pymodule_to_ruby(pyobj); /* Increment pyobj refcnt */
|
1304
|
+
|
1305
|
+
if (pyobj->ob_type == Py_API(PyBool_Type))
|
1306
|
+
return pycall_pybool_to_ruby(pyobj);
|
1307
|
+
|
1308
|
+
if (pyobj->ob_type == Py_API(PyComplex_Type))
|
1309
|
+
return pycall_pycomplex_to_ruby(pyobj);
|
1310
|
+
|
1311
|
+
if (pyobj->ob_type == Py_API(PyFloat_Type))
|
1312
|
+
return pycall_pyfloat_to_ruby(pyobj);
|
1313
|
+
|
1314
|
+
if (pyobj->ob_type == Py_API(PyInt_Type))
|
1315
|
+
return pycall_pyint_to_ruby(pyobj);
|
1316
|
+
|
1317
|
+
if (pyobj->ob_type == Py_API(PyLong_Type))
|
1318
|
+
return pycall_pylong_to_ruby(pyobj);
|
1319
|
+
|
1320
|
+
if (pyobj->ob_type == Py_API(PyUnicode_Type) || pyobj->ob_type == Py_API(PyString_Type))
|
1321
|
+
return pycall_pystring_to_ruby(pyobj);
|
1322
|
+
|
1323
|
+
Py_API(Py_IncRef)(pyobj);
|
1324
|
+
Py_API(Py_IncRef)((PyObject *)pyobj->ob_type);
|
1325
|
+
cls = pycall_python_type_mapping_get_mapped_class(pycall_pytypeptr_new((PyObject *)pyobj->ob_type));
|
1326
|
+
if (NIL_P(cls)) {
|
1327
|
+
rb_warning("Currentry do not support to convert %s to Ruby object", Py_TYPE(pyobj)->tp_name);
|
1328
|
+
return pycall_pyobject_wrapper_object_new(rb_cObject, pyobj);
|
1329
|
+
}
|
1330
|
+
|
1331
|
+
return rb_funcall(cls, rb_intern("wrap_pyptr"), 1, pycall_pyptr_new(pyobj));
|
1332
|
+
}
|
1333
|
+
|
1334
|
+
VALUE
|
1335
|
+
pycall_pytype_to_ruby(PyObject *pyobj)
|
1336
|
+
{
|
1337
|
+
VALUE pytypeptr = Qnil, wrapper_class;
|
1338
|
+
/* TODO: should look up wrapper class table instead of directly returning PyTypePtr */
|
1339
|
+
|
1340
|
+
if (PyType_Check(pyobj))
|
1341
|
+
pytypeptr = pycall_pytypeptr_new(pyobj);
|
1342
|
+
else if (PyClass_Check(pyobj))
|
1343
|
+
pytypeptr = pycall_pytypeptr_new(pyobj);
|
1344
|
+
|
1345
|
+
if (NIL_P(pytypeptr))
|
1346
|
+
return Qnil;
|
1347
|
+
|
1348
|
+
Py_API(Py_IncRef)(pyobj);
|
1349
|
+
|
1350
|
+
wrapper_class = rb_funcall(mPyCall, rb_intern("wrap_class"), 1, pytypeptr);
|
1351
|
+
return wrapper_class;
|
1352
|
+
}
|
1353
|
+
|
1354
|
+
VALUE
|
1355
|
+
pycall_pymodule_to_ruby(PyObject *pyobj)
|
1356
|
+
{
|
1357
|
+
VALUE pymodptr = Qnil, wrapper_module;
|
1358
|
+
|
1359
|
+
if (Py_TYPE(pyobj) != Py_API(PyModule_Type))
|
1360
|
+
return Qnil;
|
1361
|
+
|
1362
|
+
pymodptr = pycall_pyptr_new(pyobj);
|
1363
|
+
Py_API(Py_IncRef)(pyobj);
|
1364
|
+
|
1365
|
+
wrapper_module = rb_funcall(mPyCall, rb_intern("wrap_module"), 1, pymodptr);
|
1366
|
+
return wrapper_module;
|
1367
|
+
}
|
1368
|
+
|
1369
|
+
VALUE
|
1370
|
+
pycall_pybool_to_ruby(PyObject *pyobj)
|
1371
|
+
{
|
1372
|
+
if (pyobj->ob_type != Py_API(PyBool_Type))
|
1373
|
+
return Qnil;
|
1374
|
+
|
1375
|
+
if (Py_API(PyInt_Type))
|
1376
|
+
return Py_API(PyInt_AsSsize_t)(pyobj) ? Qtrue : Qfalse;
|
1377
|
+
|
1378
|
+
return Py_API(PyLong_AsSsize_t)(pyobj) ? Qtrue : Qfalse;
|
1379
|
+
}
|
1380
|
+
|
1381
|
+
VALUE
|
1382
|
+
pycall_pycomplex_to_ruby(PyObject *pyobj)
|
1383
|
+
{
|
1384
|
+
double real, imag;
|
1385
|
+
|
1386
|
+
if (pyobj->ob_type != Py_API(PyComplex_Type))
|
1387
|
+
return Qnil;
|
1388
|
+
|
1389
|
+
real = Py_API(PyComplex_RealAsDouble)(pyobj);
|
1390
|
+
imag = Py_API(PyComplex_ImagAsDouble)(pyobj);
|
1391
|
+
|
1392
|
+
return rb_complex_new(DBL2NUM(real), DBL2NUM(imag));
|
1393
|
+
}
|
1394
|
+
|
1395
|
+
VALUE
|
1396
|
+
pycall_pyfloat_to_ruby(PyObject *pyobj)
|
1397
|
+
{
|
1398
|
+
double d;
|
1399
|
+
|
1400
|
+
if (pyobj->ob_type != Py_API(PyFloat_Type))
|
1401
|
+
return Qnil;
|
1402
|
+
|
1403
|
+
{
|
1404
|
+
PyObject *type, *value, *tb;
|
1405
|
+
Py_API(PyErr_Fetch)(&type, &value, &tb);
|
1406
|
+
|
1407
|
+
d = Py_API(PyFloat_AsDouble)(pyobj);
|
1408
|
+
if (d == -1.0) {
|
1409
|
+
if (Py_API(PyErr_Occurred)()) {
|
1410
|
+
pycall_pyerror_fetch_and_raise("PyFloat_AsDouble");
|
1411
|
+
}
|
1412
|
+
}
|
1413
|
+
|
1414
|
+
Py_API(PyErr_Restore)(type, value, tb);
|
1415
|
+
}
|
1416
|
+
|
1417
|
+
return DBL2NUM(d);
|
1418
|
+
}
|
1419
|
+
|
1420
|
+
VALUE
|
1421
|
+
pycall_pyint_to_ruby(PyObject *pyobj)
|
1422
|
+
{
|
1423
|
+
Py_ssize_t n;
|
1424
|
+
|
1425
|
+
if (pyobj->ob_type != Py_API(PyInt_Type))
|
1426
|
+
return Qnil;
|
1427
|
+
|
1428
|
+
n = Py_API(PyInt_AsSsize_t)(pyobj);
|
1429
|
+
return SSIZET2NUM(n);
|
1430
|
+
}
|
1431
|
+
|
1432
|
+
VALUE
|
1433
|
+
pycall_pylong_to_ruby(PyObject *pyobj)
|
1434
|
+
{
|
1435
|
+
int overflow;
|
1436
|
+
|
1437
|
+
if (pyobj->ob_type != Py_API(PyLong_Type))
|
1438
|
+
return Qnil;
|
1439
|
+
|
1440
|
+
{
|
1441
|
+
long n = Py_API(PyLong_AsLongAndOverflow)(pyobj, &overflow);
|
1442
|
+
if (overflow == 0) {
|
1443
|
+
if (Py_API(PyErr_Occurred)()) {
|
1444
|
+
pycall_pyerror_fetch_and_raise("PyLong_AsLongAndOverflow");
|
1445
|
+
}
|
1446
|
+
return LONG2FIX(n);
|
1447
|
+
}
|
1448
|
+
}
|
1449
|
+
|
1450
|
+
#if HAVE_LONG_LONG
|
1451
|
+
{
|
1452
|
+
LONG_LONG n = Py_API(PyLong_AsLongLongAndOverflow)(pyobj, &overflow);
|
1453
|
+
if (overflow == 0) {
|
1454
|
+
if (Py_API(PyErr_Occurred)()) {
|
1455
|
+
pycall_pyerror_fetch_and_raise("PyLong_AsLongLongAndOverflow");
|
1456
|
+
}
|
1457
|
+
return LL2NUM(n);
|
1458
|
+
}
|
1459
|
+
}
|
1460
|
+
#endif
|
1461
|
+
|
1462
|
+
rb_warning("Currentry do not support to convert multi-precision PyLong number to Ruby object");
|
1463
|
+
|
1464
|
+
return Qnil;
|
1465
|
+
}
|
1466
|
+
|
1467
|
+
VALUE
|
1468
|
+
pycall_pystring_to_ruby(PyObject *pyobj)
|
1469
|
+
{
|
1470
|
+
char *str = NULL;
|
1471
|
+
Py_ssize_t len = 0;
|
1472
|
+
int res = -1;
|
1473
|
+
|
1474
|
+
/* TODO: PyUnicode_Check */
|
1475
|
+
if (pyobj->ob_type == Py_API(PyUnicode_Type)) {
|
1476
|
+
pyobj = Py_API(PyUnicode_AsUTF8String)(pyobj);
|
1477
|
+
res = Py_API(PyString_AsStringAndSize)(pyobj, &str, &len);
|
1478
|
+
pycall_Py_DecRef(pyobj);
|
1479
|
+
}
|
1480
|
+
/* TODO: PyString_Check */
|
1481
|
+
else if (pyobj->ob_type == Py_API(PyString_Type)) {
|
1482
|
+
res = Py_API(PyString_AsStringAndSize)(pyobj, &str, &len);
|
1483
|
+
}
|
1484
|
+
|
1485
|
+
if (res < 0) {
|
1486
|
+
return Qnil;
|
1487
|
+
}
|
1488
|
+
|
1489
|
+
return rb_str_new(str, len);
|
1490
|
+
}
|
1491
|
+
|
1492
|
+
static VALUE
|
1493
|
+
pycall_pytuple_to_a(PyObject *pyobj)
|
1494
|
+
{
|
1495
|
+
VALUE ary;
|
1496
|
+
Py_ssize_t i, n;
|
1497
|
+
|
1498
|
+
assert(Py_TYPE(pyobj) == Py_API(PyTuple_Type));
|
1499
|
+
|
1500
|
+
n = Py_API(PyTuple_Size)(pyobj);
|
1501
|
+
ary = rb_ary_new_capa(n);
|
1502
|
+
for (i = 0; i < n; ++i) {
|
1503
|
+
PyObject *pytem = Py_API(PyTuple_GetItem)(pyobj, i);
|
1504
|
+
Py_API(Py_IncRef)(pytem);
|
1505
|
+
rb_ary_push(ary, pycall_pyobject_to_ruby(pytem));
|
1506
|
+
}
|
1507
|
+
|
1508
|
+
return ary;
|
1509
|
+
}
|
1510
|
+
|
1511
|
+
static VALUE
|
1512
|
+
pycall_pysequence_to_a(PyObject *pyobj)
|
1513
|
+
{
|
1514
|
+
Py_ssize_t n, i;
|
1515
|
+
VALUE ary;
|
1516
|
+
|
1517
|
+
assert(Py_API(PySequence_Check)(pyobj));
|
1518
|
+
|
1519
|
+
n = Py_API(PySequence_Size)(pyobj);
|
1520
|
+
ary = rb_ary_new_capa(n);
|
1521
|
+
for (i = 0; i < n; ++i) {
|
1522
|
+
PyObject *pytem = Py_API(PySequence_GetItem)(pyobj, i);
|
1523
|
+
rb_ary_push(ary, pycall_pyobject_to_ruby(pytem));
|
1524
|
+
}
|
1525
|
+
|
1526
|
+
return ary;
|
1527
|
+
}
|
1528
|
+
|
1529
|
+
VALUE
|
1530
|
+
pycall_pyobject_to_a(PyObject *pyobj)
|
1531
|
+
{
|
1532
|
+
if (Py_TYPE(pyobj) == Py_API(PyTuple_Type)) {
|
1533
|
+
return pycall_pytuple_to_a(pyobj);
|
1534
|
+
}
|
1535
|
+
|
1536
|
+
if (Py_API(PySequence_Check)(pyobj)) {
|
1537
|
+
return pycall_pysequence_to_a(pyobj);
|
1538
|
+
}
|
1539
|
+
|
1540
|
+
/* TODO: PyDict_Type to assoc array */
|
1541
|
+
|
1542
|
+
return rb_Array(pycall_pyobject_to_ruby(pyobj));
|
1543
|
+
}
|
1544
|
+
|
1545
|
+
static VALUE
|
1546
|
+
pycall_conv_m_register_python_type_mapping(VALUE mod, VALUE pytypeptr, VALUE rbcls)
|
1547
|
+
{
|
1548
|
+
return pycall_python_type_mapping_register(pytypeptr, rbcls) ? Qtrue : Qfalse;
|
1549
|
+
}
|
1550
|
+
|
1551
|
+
static VALUE
|
1552
|
+
pycall_conv_m_unregister_python_type_mapping(VALUE mod, VALUE pytypeptr)
|
1553
|
+
{
|
1554
|
+
return pycall_python_type_mapping_unregister(pytypeptr) ? Qtrue : Qfalse;
|
1555
|
+
}
|
1556
|
+
|
1557
|
+
static VALUE
|
1558
|
+
pycall_conv_m_from_ruby(VALUE mod, VALUE obj)
|
1559
|
+
{
|
1560
|
+
PyObject *pyobj = pycall_pyobject_from_ruby(obj);
|
1561
|
+
if (PyType_Check(pyobj) || PyClass_Check(pyobj))
|
1562
|
+
return pycall_pytypeptr_new(pyobj);
|
1563
|
+
if (PyRuby_Check(pyobj))
|
1564
|
+
return pycall_pyrubyptr_new(pyobj);
|
1565
|
+
return pycall_pyptr_new(pyobj);
|
1566
|
+
}
|
1567
|
+
|
1568
|
+
static VALUE
|
1569
|
+
pycall_conv_m_to_ruby(VALUE mod, VALUE pyptr)
|
1570
|
+
{
|
1571
|
+
VALUE obj, obj_pyptr;
|
1572
|
+
PyObject *pyobj = check_get_pyobj_ptr(pyptr, NULL);
|
1573
|
+
obj = obj_pyptr = pycall_pyobject_to_ruby(pyobj);
|
1574
|
+
if (is_pyobject_wrapper(obj)) {
|
1575
|
+
obj_pyptr = pycall_pyobject_wrapper_get_pyptr(obj);
|
1576
|
+
}
|
1577
|
+
if (is_pycall_pyptr(obj_pyptr) && obj_pyptr != pyptr && DATA_PTR(obj_pyptr) == pyobj) {
|
1578
|
+
Py_API(Py_IncRef)(pyobj);
|
1579
|
+
}
|
1580
|
+
return obj;
|
1581
|
+
}
|
1582
|
+
|
1583
|
+
PyObject *
|
1584
|
+
pycall_pyobject_from_ruby(VALUE obj)
|
1585
|
+
{
|
1586
|
+
if (is_pycall_pyptr(obj)) {
|
1587
|
+
PyObject *pyobj = get_pyobj_ptr(obj);
|
1588
|
+
Py_API(Py_IncRef)(pyobj);
|
1589
|
+
return pyobj;
|
1590
|
+
}
|
1591
|
+
if (is_pyobject_wrapper(obj)) {
|
1592
|
+
PyObject *pyobj = pycall_pyobject_wrapper_get_pyobj_ptr(obj);
|
1593
|
+
Py_API(Py_IncRef)(pyobj);
|
1594
|
+
return pyobj;
|
1595
|
+
}
|
1596
|
+
if (obj == Qnil) {
|
1597
|
+
Py_API(Py_IncRef)(Py_API(_Py_NoneStruct));
|
1598
|
+
return Py_API(_Py_NoneStruct);
|
1599
|
+
}
|
1600
|
+
if (obj == Qtrue || obj == Qfalse) {
|
1601
|
+
return Py_API(PyBool_FromLong)(RTEST(obj));
|
1602
|
+
}
|
1603
|
+
if (RB_INTEGER_TYPE_P(obj)) {
|
1604
|
+
if (FIXNUM_P(obj)) {
|
1605
|
+
if (Py_API(PyInt_FromLong))
|
1606
|
+
return Py_API(PyInt_FromLong)(FIX2LONG(obj));
|
1607
|
+
return Py_API(PyLong_FromLong)(FIX2LONG(obj));
|
1608
|
+
}
|
1609
|
+
#ifdef HAVE_LONG_LONG
|
1610
|
+
else {
|
1611
|
+
LONG_LONG ll;
|
1612
|
+
int state = 0;
|
1613
|
+
ll = (LONG_LONG)rb_protect((VALUE (*)(VALUE))rb_big2ll, obj, &state);
|
1614
|
+
if (!state) {
|
1615
|
+
if (Py_API(PyInt_FromSsize_t) && SSIZE_MIN <= ll && ll <= SSIZE_MAX)
|
1616
|
+
Py_API(PyInt_FromSsize_t)((Py_ssize_t)ll);
|
1617
|
+
return Py_API(PyLong_FromLongLong)(ll);
|
1618
|
+
}
|
1619
|
+
}
|
1620
|
+
#endif
|
1621
|
+
rb_warn("Currently do not support to convert large integer values to PyLong");
|
1622
|
+
Py_API(Py_IncRef)(Py_API(_Py_NoneStruct));
|
1623
|
+
return Py_API(_Py_NoneStruct); /* FIXME */
|
1624
|
+
}
|
1625
|
+
if (RB_FLOAT_TYPE_P(obj)) {
|
1626
|
+
return Py_API(PyFloat_FromDouble)(RFLOAT_VALUE(obj));
|
1627
|
+
}
|
1628
|
+
if (RB_TYPE_P(obj, T_COMPLEX)) {
|
1629
|
+
VALUE re, im;
|
1630
|
+
re = rb_funcall(obj, rb_intern("real"), 0);
|
1631
|
+
im = rb_funcall(obj, rb_intern("imag"), 0);
|
1632
|
+
return Py_API(PyComplex_FromDoubles)(NUM2DBL(re), NUM2DBL(im));
|
1633
|
+
}
|
1634
|
+
if (RB_TYPE_P(obj, T_STRING) || RB_TYPE_P(obj, T_SYMBOL)) {
|
1635
|
+
return pycall_pystring_from_ruby(obj);
|
1636
|
+
}
|
1637
|
+
if (RB_TYPE_P(obj, T_ARRAY)) {
|
1638
|
+
return pycall_pylist_from_ruby(obj);
|
1639
|
+
}
|
1640
|
+
if (RB_TYPE_P(obj, T_HASH)) {
|
1641
|
+
return pycall_pydict_from_ruby(obj);
|
1642
|
+
}
|
1643
|
+
|
1644
|
+
return PyRuby_New(obj);
|
1645
|
+
}
|
1646
|
+
|
1647
|
+
PyObject *
|
1648
|
+
pycall_pystring_from_ruby(VALUE obj)
|
1649
|
+
{
|
1650
|
+
int is_binary, is_ascii_only;
|
1651
|
+
|
1652
|
+
if (RB_TYPE_P(obj, T_SYMBOL)) {
|
1653
|
+
obj = rb_sym_to_s(obj);
|
1654
|
+
}
|
1655
|
+
|
1656
|
+
StringValue(obj);
|
1657
|
+
|
1658
|
+
is_binary = (rb_enc_get_index(obj) == rb_ascii8bit_encindex());
|
1659
|
+
is_ascii_only = (ENC_CODERANGE_7BIT == rb_enc_str_coderange(obj));
|
1660
|
+
|
1661
|
+
if (is_binary || (!python_is_unicode_literals && is_ascii_only)) {
|
1662
|
+
return Py_API(PyString_FromStringAndSize)(RSTRING_PTR(obj), RSTRING_LEN(obj));
|
1663
|
+
}
|
1664
|
+
return Py_API(PyUnicode_DecodeUTF8)(RSTRING_PTR(obj), RSTRING_LEN(obj), NULL);
|
1665
|
+
}
|
1666
|
+
|
1667
|
+
PyObject *
|
1668
|
+
pycall_pytuple_from_ruby(VALUE obj)
|
1669
|
+
{
|
1670
|
+
PyObject *pytupleobj;
|
1671
|
+
long i, n;
|
1672
|
+
|
1673
|
+
obj = rb_convert_type(obj, T_ARRAY, "Array", "to_ary");
|
1674
|
+
n = RARRAY_LEN(obj);
|
1675
|
+
pytupleobj = Py_API(PyTuple_New)(n);
|
1676
|
+
if (!pytupleobj) {
|
1677
|
+
pycall_pyerror_fetch_and_raise("PyTuple_New in pycall_pytuple_from_ruby");
|
1678
|
+
}
|
1679
|
+
|
1680
|
+
for (i = 0; i < n; ++i) {
|
1681
|
+
int res;
|
1682
|
+
PyObject *pytem;
|
1683
|
+
|
1684
|
+
pytem = pycall_pyobject_from_ruby(RARRAY_AREF(obj, i));
|
1685
|
+
res = Py_API(PyTuple_SetItem)(pytupleobj, i, pytem);
|
1686
|
+
if (res == -1) {
|
1687
|
+
pycall_Py_DecRef(pytem);
|
1688
|
+
pycall_Py_DecRef(pytupleobj);
|
1689
|
+
pycall_pyerror_fetch_and_raise("PyTuple_SetItem");
|
1690
|
+
}
|
1691
|
+
}
|
1692
|
+
|
1693
|
+
return pytupleobj;
|
1694
|
+
}
|
1695
|
+
|
1696
|
+
PyObject *
|
1697
|
+
pycall_pylist_from_ruby(VALUE obj)
|
1698
|
+
{
|
1699
|
+
PyObject *pylistobj;
|
1700
|
+
long i, n;
|
1701
|
+
|
1702
|
+
obj = rb_convert_type(obj, T_ARRAY, "Array", "to_ary");
|
1703
|
+
n = RARRAY_LEN(obj);
|
1704
|
+
pylistobj = Py_API(PyList_New)(n);
|
1705
|
+
if (!pylistobj) {
|
1706
|
+
pycall_pyerror_fetch_and_raise("PyList_New in pcall_pylist_from_ruby");
|
1707
|
+
}
|
1708
|
+
|
1709
|
+
for (i = 0; i < n; ++i) {
|
1710
|
+
int res;
|
1711
|
+
PyObject *pytem;
|
1712
|
+
|
1713
|
+
pytem = pycall_pyobject_from_ruby(RARRAY_AREF(obj, i));
|
1714
|
+
res = Py_API(PyList_SetItem)(pylistobj, i, pytem);
|
1715
|
+
|
1716
|
+
if (res == -1) {
|
1717
|
+
pycall_Py_DecRef(pytem);
|
1718
|
+
pycall_Py_DecRef(pylistobj);
|
1719
|
+
pycall_pyerror_fetch_and_raise("PyList_SetItem in pycall_pylist_from_ruby");
|
1720
|
+
}
|
1721
|
+
}
|
1722
|
+
|
1723
|
+
return pylistobj;
|
1724
|
+
}
|
1725
|
+
|
1726
|
+
static int
|
1727
|
+
pycall_pydict_from_ruby_iter(VALUE key, VALUE value, VALUE arg)
|
1728
|
+
{
|
1729
|
+
PyObject *pydictobj = (PyObject *)arg;
|
1730
|
+
PyObject *pyobj_key, *pyobj_value;
|
1731
|
+
int res;
|
1732
|
+
|
1733
|
+
pyobj_key = pycall_pyobject_from_ruby(key);
|
1734
|
+
pyobj_value = pycall_pyobject_from_ruby(value);
|
1735
|
+
res = Py_API(PyObject_SetItem)(pydictobj, pyobj_key, pyobj_value);
|
1736
|
+
if (res == -1) {
|
1737
|
+
return ST_STOP;
|
1738
|
+
}
|
1739
|
+
Py_API(Py_DecRef)(pyobj_key);
|
1740
|
+
Py_API(Py_DecRef)(pyobj_value);
|
1741
|
+
return ST_CONTINUE;
|
1742
|
+
}
|
1743
|
+
|
1744
|
+
PyObject *
|
1745
|
+
pycall_pydict_from_ruby(VALUE obj)
|
1746
|
+
{
|
1747
|
+
PyObject *pydictobj;
|
1748
|
+
|
1749
|
+
obj = rb_convert_type(obj, T_HASH, "Hash", "to_hash");
|
1750
|
+
pydictobj = Py_API(PyDict_New)();
|
1751
|
+
if (!pydictobj) {
|
1752
|
+
pycall_pyerror_fetch_and_raise("PyDict_New in pycall_pydict_from_ruby");
|
1753
|
+
}
|
1754
|
+
|
1755
|
+
rb_hash_foreach(obj, pycall_pydict_from_ruby_iter, (VALUE)pydictobj);
|
1756
|
+
if (Py_API(PyErr_Occurred)()) {
|
1757
|
+
pycall_pyerror_fetch_and_raise("PyObject_SetItem in pycall_pydict_from_ruby_iter");
|
1758
|
+
}
|
1759
|
+
|
1760
|
+
return pydictobj;
|
1761
|
+
}
|
1762
|
+
|
1763
|
+
PyObject *
|
1764
|
+
pycall_pyslice_from_ruby(VALUE obj)
|
1765
|
+
{
|
1766
|
+
VALUE begin, end, step = Qnil;
|
1767
|
+
int exclude_end;
|
1768
|
+
PyObject *pystart, *pystop, *pystep, *pyslice;
|
1769
|
+
|
1770
|
+
if (rb_obj_is_kind_of(obj, rb_cRange)) {
|
1771
|
+
pycall_extract_range(obj, &begin, &end, &exclude_end, NULL);
|
1772
|
+
}
|
1773
|
+
else if (pycall_obj_is_step_range(obj)) {
|
1774
|
+
pycall_extract_range(obj, &begin, &end, &exclude_end, &step);
|
1775
|
+
}
|
1776
|
+
else {
|
1777
|
+
rb_raise(rb_eTypeError, "unexpected argument type %s (expected Range or Enumerator generated by Range#step)", rb_class2name(CLASS_OF(obj)));
|
1778
|
+
}
|
1779
|
+
|
1780
|
+
if (!NIL_P(step) && NUM2SSIZET(step) < 0) {
|
1781
|
+
if (!NIL_P(end)) {
|
1782
|
+
if (!exclude_end) {
|
1783
|
+
ssize_t end_i = NUM2SSIZET(end);
|
1784
|
+
switch (end_i) {
|
1785
|
+
case 0:
|
1786
|
+
end = Qnil;
|
1787
|
+
break;
|
1788
|
+
|
1789
|
+
default:
|
1790
|
+
end = SSIZET2NUM(end_i - 1); /* TODO: limit check */
|
1791
|
+
break;
|
1792
|
+
}
|
1793
|
+
}
|
1794
|
+
}
|
1795
|
+
}
|
1796
|
+
else {
|
1797
|
+
if (!NIL_P(end)) {
|
1798
|
+
if (!exclude_end) {
|
1799
|
+
ssize_t end_i = NUM2SSIZET(end);
|
1800
|
+
switch (end_i) {
|
1801
|
+
case -1:
|
1802
|
+
end = Qnil;
|
1803
|
+
break;
|
1804
|
+
|
1805
|
+
default:
|
1806
|
+
end = SSIZET2NUM(end_i + 1); /* TODO: limit check */
|
1807
|
+
break;
|
1808
|
+
}
|
1809
|
+
}
|
1810
|
+
}
|
1811
|
+
}
|
1812
|
+
|
1813
|
+
pystart = pycall_pyobject_from_ruby(begin);
|
1814
|
+
pystop = pycall_pyobject_from_ruby(end);
|
1815
|
+
pystep = pycall_pyobject_from_ruby(step);
|
1816
|
+
|
1817
|
+
pyslice = Py_API(PySlice_New)(pystart, pystop, pystep);
|
1818
|
+
/* PySlice_New increments reference counts of pystart, pystop, and pystep */
|
1819
|
+
pycall_Py_DecRef(pystart);
|
1820
|
+
pycall_Py_DecRef(pystop);
|
1821
|
+
pycall_Py_DecRef(pystep);
|
1822
|
+
|
1823
|
+
return pyslice;
|
1824
|
+
}
|
1825
|
+
|
1826
|
+
VALUE
|
1827
|
+
pycall_pyerror_new(PyObject *type, PyObject *value, PyObject *traceback)
|
1828
|
+
{
|
1829
|
+
VALUE init_args[3];
|
1830
|
+
|
1831
|
+
init_args[0] = pycall_pyobject_to_ruby(type);
|
1832
|
+
init_args[1] = value ? pycall_pyobject_to_ruby(value) : Qnil;
|
1833
|
+
init_args[2] = traceback ? pycall_pyobject_to_ruby(traceback) : Qnil;
|
1834
|
+
|
1835
|
+
return rb_class_new_instance(3, init_args, cPyError);
|
1836
|
+
}
|
1837
|
+
|
1838
|
+
VALUE
|
1839
|
+
pycall_pyerror_fetch(void)
|
1840
|
+
{
|
1841
|
+
PyObject *type, *value, *traceback;
|
1842
|
+
|
1843
|
+
if (Py_API(PyErr_Occurred)() == NULL)
|
1844
|
+
return Qnil;
|
1845
|
+
|
1846
|
+
Py_API(PyErr_Fetch)(&type, &value, &traceback);
|
1847
|
+
if (type == NULL)
|
1848
|
+
return Qnil;
|
1849
|
+
|
1850
|
+
return pycall_pyerror_new(type, value, traceback);
|
1851
|
+
}
|
1852
|
+
|
1853
|
+
void
|
1854
|
+
pycall_pyerror_fetch_and_raise(char const *format, ...)
|
1855
|
+
{
|
1856
|
+
va_list args;
|
1857
|
+
VALUE pyerror, msg;
|
1858
|
+
|
1859
|
+
pyerror = pycall_pyerror_fetch();
|
1860
|
+
if (!NIL_P(pyerror))
|
1861
|
+
rb_exc_raise(pyerror);
|
1862
|
+
|
1863
|
+
va_start(args, format);
|
1864
|
+
msg = rb_vsprintf(format, args);
|
1865
|
+
va_end(args);
|
1866
|
+
|
1867
|
+
rb_exc_raise(rb_exc_new3(eError, msg));
|
1868
|
+
}
|
1869
|
+
|
1870
|
+
unsigned long
|
1871
|
+
pycall_default_tp_flags(void)
|
1872
|
+
{
|
1873
|
+
unsigned long const stackless_extension_flag = python_has_stackless_extension ? Py_TPFLAGS_HAVE_STACKLESS_EXTENSION : 0;
|
1874
|
+
|
1875
|
+
if (python_major_version >= 3) {
|
1876
|
+
return stackless_extension_flag | Py_TPFLAGS_HAVE_VERSION_TAG;
|
1877
|
+
}
|
1878
|
+
else {
|
1879
|
+
return stackless_extension_flag |
|
1880
|
+
Py_TPFLAGS_HAVE_GETCHARBUFFER |
|
1881
|
+
Py_TPFLAGS_HAVE_SEQUENCE_IN |
|
1882
|
+
Py_TPFLAGS_HAVE_INPLACEOPS |
|
1883
|
+
Py_TPFLAGS_HAVE_RICHCOMPARE |
|
1884
|
+
Py_TPFLAGS_HAVE_WEAKREFS |
|
1885
|
+
Py_TPFLAGS_HAVE_ITER |
|
1886
|
+
Py_TPFLAGS_HAVE_CLASS |
|
1887
|
+
Py_TPFLAGS_HAVE_INDEX
|
1888
|
+
;
|
1889
|
+
}
|
1890
|
+
}
|
1891
|
+
|
1892
|
+
PyObject *
|
1893
|
+
pycall_pystring_from_format(char const *format, ...)
|
1894
|
+
{
|
1895
|
+
va_list vargs;
|
1896
|
+
PyObject *res;
|
1897
|
+
|
1898
|
+
va_start(vargs, format);
|
1899
|
+
res = pycall_pystring_from_formatv(format, vargs);
|
1900
|
+
va_end(vargs);
|
1901
|
+
|
1902
|
+
return res;
|
1903
|
+
}
|
1904
|
+
|
1905
|
+
PyObject *
|
1906
|
+
pycall_pystring_from_formatv(char const *format, va_list vargs)
|
1907
|
+
{
|
1908
|
+
if (python_is_unicode_literals)
|
1909
|
+
return Py_API(PyUnicode_FromFormatV)(format, vargs);
|
1910
|
+
else
|
1911
|
+
return Py_API(PyString_FromFormatV)(format, vargs);
|
1912
|
+
}
|
1913
|
+
|
1914
|
+
/* ==== Python ==== */
|
1915
|
+
|
1916
|
+
static void
|
1917
|
+
init_python(void)
|
1918
|
+
{
|
1919
|
+
static char const *argv[1] = { "" };
|
1920
|
+
|
1921
|
+
Py_API(Py_InitializeEx)(0);
|
1922
|
+
Py_API(PySys_SetArgvEx)(0, (char **)argv, 0);
|
1923
|
+
|
1924
|
+
/* check the availability of stackless extension */
|
1925
|
+
python_has_stackless_extension = (Py_API(PyImport_ImportModule)("stackless") != NULL);
|
1926
|
+
if (!python_has_stackless_extension) {
|
1927
|
+
Py_API(PyErr_Clear)();
|
1928
|
+
}
|
1929
|
+
|
1930
|
+
/* builtins module */
|
1931
|
+
{
|
1932
|
+
char const *builtins_module_name = (python_major_version < 3) ? "__builtin__" : "builtins";
|
1933
|
+
python_builtins_module = Py_API(PyImport_ImportModule)(builtins_module_name);
|
1934
|
+
}
|
1935
|
+
|
1936
|
+
/* sys module */
|
1937
|
+
|
1938
|
+
{
|
1939
|
+
PyObject *sys, *hexversion;
|
1940
|
+
sys = Py_API(PyImport_ImportModule)("sys");
|
1941
|
+
|
1942
|
+
/* hexversion */
|
1943
|
+
|
1944
|
+
hexversion = Py_API(PyObject_GetAttrString)(sys, "hexversion");
|
1945
|
+
if (Py_API(PyInt_Type))
|
1946
|
+
python_hexversion = Py_API(PyInt_AsSsize_t)(hexversion);
|
1947
|
+
else
|
1948
|
+
python_hexversion = Py_API(PyLong_AsSsize_t)(hexversion);
|
1949
|
+
}
|
1950
|
+
|
1951
|
+
/* constants */
|
1952
|
+
|
1953
|
+
Py_API(Py_IncRef)(Py_API(_Py_NoneStruct));
|
1954
|
+
rb_define_const(mAPI, "None", pycall_pyptr_new(Py_API(_Py_NoneStruct)));
|
1955
|
+
|
1956
|
+
Py_API(Py_IncRef)((PyObject *)Py_API(PyBool_Type));
|
1957
|
+
rb_define_const(mAPI, "PyBool_Type", pycall_pytypeptr_new((PyObject *)Py_API(PyBool_Type)));
|
1958
|
+
if (Py_API(PyClass_Type)) {
|
1959
|
+
Py_API(Py_IncRef)((PyObject *)Py_API(PyClass_Type));
|
1960
|
+
rb_define_const(mAPI, "PyClass_Type", pycall_pytypeptr_new((PyObject *)Py_API(PyClass_Type)));
|
1961
|
+
}
|
1962
|
+
Py_API(Py_IncRef)((PyObject *)Py_API(PyDict_Type));
|
1963
|
+
rb_define_const(mAPI, "PyDict_Type", pycall_pytypeptr_new((PyObject *)Py_API(PyDict_Type)));
|
1964
|
+
Py_API(Py_IncRef)((PyObject *)Py_API(PyFloat_Type));
|
1965
|
+
rb_define_const(mAPI, "PyFloat_Type", pycall_pytypeptr_new((PyObject *)Py_API(PyFloat_Type)));
|
1966
|
+
Py_API(Py_IncRef)((PyObject *)Py_API(PyInt_Type));
|
1967
|
+
rb_define_const(mAPI, "PyInt_Type", pycall_pytypeptr_new((PyObject *)Py_API(PyInt_Type)));
|
1968
|
+
Py_API(Py_IncRef)((PyObject *)Py_API(PyList_Type));
|
1969
|
+
rb_define_const(mAPI, "PyList_Type", pycall_pytypeptr_new((PyObject *)Py_API(PyList_Type)));
|
1970
|
+
Py_API(Py_IncRef)((PyObject *)Py_API(PyLong_Type));
|
1971
|
+
rb_define_const(mAPI, "PyLong_Type", pycall_pytypeptr_new((PyObject *)Py_API(PyLong_Type)));
|
1972
|
+
Py_API(Py_IncRef)((PyObject *)Py_API(PyModule_Type));
|
1973
|
+
rb_define_const(mAPI, "PyModule_Type", pycall_pytypeptr_new((PyObject *)Py_API(PyModule_Type)));
|
1974
|
+
Py_API(Py_IncRef)((PyObject *)Py_API(PyString_Type));
|
1975
|
+
rb_define_const(mAPI, "PyString_Type", pycall_pytypeptr_new((PyObject *)Py_API(PyString_Type)));
|
1976
|
+
Py_API(Py_IncRef)((PyObject *)Py_API(PyType_Type));
|
1977
|
+
rb_define_const(mAPI, "PyType_Type", pycall_pytypeptr_new((PyObject *)Py_API(PyType_Type)));
|
1978
|
+
Py_API(Py_IncRef)((PyObject *)Py_API(PyUnicode_Type));
|
1979
|
+
rb_define_const(mAPI, "PyUnicode_Type", pycall_pytypeptr_new((PyObject *)Py_API(PyUnicode_Type)));
|
1980
|
+
|
1981
|
+
pycall_init_exceptions(pycall_libpython_handle);
|
1982
|
+
}
|
1983
|
+
|
1984
|
+
static VALUE
|
1985
|
+
pycall_tuple_s_new(int argc, VALUE *argv, VALUE klass)
|
1986
|
+
{
|
1987
|
+
VALUE obj;
|
1988
|
+
PyObject *pyobj;
|
1989
|
+
int i;
|
1990
|
+
|
1991
|
+
pyobj = Py_API(PyTuple_New)(argc);
|
1992
|
+
for (i = 0; i < argc; ++i) {
|
1993
|
+
Py_API(PyTuple_SetItem)(pyobj, i, pycall_pyobject_from_ruby(argv[i]));
|
1994
|
+
|
1995
|
+
/* NOTE: Although PyTuple_SetItem steals the item reference,
|
1996
|
+
* it is unnecessary to call Py_IncRef for the item because
|
1997
|
+
* pycall_pyobject_from_ruby increments the reference count
|
1998
|
+
* of its result. */
|
1999
|
+
}
|
2000
|
+
|
2001
|
+
obj = pycall_pyobject_wrapper_object_new(klass, pyobj);
|
2002
|
+
return obj;
|
2003
|
+
}
|
2004
|
+
|
2005
|
+
static VALUE
|
2006
|
+
pycall_tuple_length(VALUE obj)
|
2007
|
+
{
|
2008
|
+
PyObject *pyobj;
|
2009
|
+
Py_ssize_t n;
|
2010
|
+
|
2011
|
+
pyobj = pycall_pyobject_wrapper_check_get_pyobj_ptr(obj, Py_API(PyTuple_Type));
|
2012
|
+
|
2013
|
+
n = Py_API(PyTuple_Size)(pyobj);
|
2014
|
+
return SSIZET2NUM(n);
|
2015
|
+
}
|
2016
|
+
|
2017
|
+
static VALUE
|
2018
|
+
pycall_tuple_to_a(VALUE obj)
|
2019
|
+
{
|
2020
|
+
PyObject *pyobj;
|
2021
|
+
|
2022
|
+
pyobj = pycall_pyobject_wrapper_check_get_pyobj_ptr(obj, Py_API(PyTuple_Type));
|
2023
|
+
|
2024
|
+
return pycall_pytuple_to_a(pyobj);
|
2025
|
+
}
|
2026
|
+
|
2027
|
+
static VALUE
|
2028
|
+
pycall_pyerror_s_occurred_p(VALUE klass)
|
2029
|
+
{
|
2030
|
+
return Py_API(PyErr_Occurred)() != NULL ? Qtrue : Qfalse;
|
2031
|
+
}
|
2032
|
+
|
2033
|
+
static VALUE
|
2034
|
+
pycall_pyerror_s_fetch(VALUE klass)
|
2035
|
+
{
|
2036
|
+
return pycall_pyerror_fetch();
|
2037
|
+
}
|
2038
|
+
|
2039
|
+
static void
|
2040
|
+
init_pyerror(void)
|
2041
|
+
{
|
2042
|
+
rb_define_singleton_method(cPyError, "occurred?", pycall_pyerror_s_occurred_p, 0);
|
2043
|
+
rb_define_singleton_method(cPyError, "fetch", pycall_pyerror_s_fetch, 0);
|
2044
|
+
}
|
2045
|
+
|
2046
|
+
static void
|
2047
|
+
init_tuple(void)
|
2048
|
+
{
|
2049
|
+
cTuple = rb_funcall(mPyCall, rb_intern("wrap_class"), 1, pycall_pytypeptr_new((PyObject *)Py_API(PyTuple_Type)));
|
2050
|
+
rb_define_const(mPyCall, "Tuple", cTuple);
|
2051
|
+
rb_funcall(cTuple, rb_intern("register_python_type_mapping"), 0);
|
2052
|
+
rb_define_singleton_method(cTuple, "new", pycall_tuple_s_new, -1);
|
2053
|
+
rb_define_method(cTuple, "length", pycall_tuple_length, 0);
|
2054
|
+
rb_define_method(cTuple, "to_a", pycall_tuple_to_a, 0);
|
2055
|
+
}
|
2056
|
+
|
2057
|
+
void
|
2058
|
+
Init_pycall(void)
|
2059
|
+
{
|
2060
|
+
pycall_hash_salt = FIX2LONG(rb_hash(rb_str_new2("PyCall::PyObject")));
|
2061
|
+
|
2062
|
+
mPyCall = rb_define_module("PyCall");
|
2063
|
+
mPyObjectWrapper = rb_const_get_at(mPyCall, rb_intern("PyObjectWrapper"));
|
2064
|
+
mPyTypeObjectWrapper = rb_const_get_at(mPyCall, rb_intern("PyTypeObjectWrapper"));
|
2065
|
+
mGCGuard = rb_define_module_under(mPyCall, "GCGuard");
|
2066
|
+
eError = rb_const_get_at(mPyCall, rb_intern("Error"));
|
2067
|
+
cPyError = rb_const_get_at(mPyCall, rb_intern("PyError"));
|
2068
|
+
|
2069
|
+
/* PyCall */
|
2070
|
+
|
2071
|
+
rb_define_module_function(mPyCall, "after_fork", pycall_after_fork, 0);
|
2072
|
+
|
2073
|
+
/* PyCall::PyPtr */
|
2074
|
+
|
2075
|
+
cPyPtr = rb_define_class_under(mPyCall, "PyPtr", rb_cBasicObject);
|
2076
|
+
rb_define_singleton_method(cPyPtr, "incref", pycall_pyptr_s_incref, 1);
|
2077
|
+
rb_define_singleton_method(cPyPtr, "decref", pycall_pyptr_s_decref, 1);
|
2078
|
+
rb_define_singleton_method(cPyPtr, "sizeof", pycall_pyptr_s_sizeof, 1);
|
2079
|
+
|
2080
|
+
rb_define_alloc_func(cPyPtr, pycall_pyptr_allocate);
|
2081
|
+
rb_define_method(cPyPtr, "initialize", pycall_pyptr_initialize, 1);
|
2082
|
+
rb_define_method(cPyPtr, "null?", pycall_pyptr_is_null, 0);
|
2083
|
+
rb_define_method(cPyPtr, "none?", pycall_pyptr_is_none, 0);
|
2084
|
+
rb_define_method(cPyPtr, "nil?", pycall_pyptr_is_nil, 0);
|
2085
|
+
rb_define_method(cPyPtr, "==", pycall_pyptr_eq, 1);
|
2086
|
+
rb_define_method(cPyPtr, "===", pycall_pyptr_eq, 1);
|
2087
|
+
rb_define_method(cPyPtr, "eql?", pycall_pyptr_eq, 1);
|
2088
|
+
rb_define_method(cPyPtr, "hash", pycall_pyptr_hash, 0);
|
2089
|
+
rb_define_method(cPyPtr, "__address__", pycall_pyptr_get_ptr_address, 0);
|
2090
|
+
rb_define_method(cPyPtr, "__ob_refcnt__", pycall_pyptr_get_ob_refcnt, 0);
|
2091
|
+
rb_define_method(cPyPtr, "__ob_type__", pycall_pyptr_get_ob_type, 0);
|
2092
|
+
rb_define_method(cPyPtr, "object_id", pycall_pyptr_object_id, 0);
|
2093
|
+
rb_define_method(cPyPtr, "class", pycall_pyptr_class, 0);
|
2094
|
+
rb_define_method(cPyPtr, "inspect", pycall_pyptr_inspect, 0);
|
2095
|
+
rb_define_method(cPyPtr, "kind_of?", pycall_pyptr_is_kind_of, 1);
|
2096
|
+
rb_define_method(cPyPtr, "is_a?", pycall_pyptr_is_kind_of, 1);
|
2097
|
+
|
2098
|
+
rb_define_const(cPyPtr, "NULL", pycall_pyptr_new(NULL));
|
2099
|
+
|
2100
|
+
/* PyCall::PyTypePtr */
|
2101
|
+
|
2102
|
+
cPyTypePtr = rb_define_class_under(mPyCall, "PyTypePtr", cPyPtr);
|
2103
|
+
rb_define_alloc_func(cPyTypePtr, pycall_pytypeptr_allocate);
|
2104
|
+
rb_define_method(cPyTypePtr, "__ob_size__", pycall_pytypeptr_get_ob_size, 0);
|
2105
|
+
rb_define_method(cPyTypePtr, "__tp_name__", pycall_pytypeptr_get_tp_name, 0);
|
2106
|
+
rb_define_method(cPyTypePtr, "__tp_basicsize__", pycall_pytypeptr_get_tp_basicsize, 0);
|
2107
|
+
rb_define_method(cPyTypePtr, "__tp_flags__", pycall_pytypeptr_get_tp_flags, 0);
|
2108
|
+
rb_define_method(cPyTypePtr, "===", pycall_pytypeptr_eqq, 1);
|
2109
|
+
|
2110
|
+
/* PyCall::LibPython::API */
|
2111
|
+
|
2112
|
+
mLibPython = rb_define_module_under(mPyCall, "LibPython");
|
2113
|
+
pycall_libpython_handle = rb_funcall(mLibPython, rb_intern("handle"), 0);
|
2114
|
+
pycall_init_libpython_api_table(pycall_libpython_handle);
|
2115
|
+
|
2116
|
+
mAPI = rb_define_module_under(mLibPython, "API");
|
2117
|
+
|
2118
|
+
rb_define_module_function(mAPI, "builtins_module_ptr", pycall_libpython_api_get_builtins_module_ptr, 0);
|
2119
|
+
|
2120
|
+
rb_define_module_function(mAPI, "PyObject_Dir", pycall_libpython_api_PyObject_Dir, 1);
|
2121
|
+
rb_define_module_function(mAPI, "PyList_Size", pycall_libpython_api_PyList_Size, 1);
|
2122
|
+
rb_define_module_function(mAPI, "PyList_GetItem", pycall_libpython_api_PyList_GetItem, 2);
|
2123
|
+
|
2124
|
+
/* PyCall::LibPython::Helpers */
|
2125
|
+
|
2126
|
+
mHelpers = rb_define_module_under(mLibPython, "Helpers");
|
2127
|
+
|
2128
|
+
rb_define_module_function(mHelpers, "unicode_literals?", pycall_libpython_helpers_m_unicode_literals_p, 0);
|
2129
|
+
rb_define_module_function(mHelpers, "import_module", pycall_libpython_helpers_m_import_module, -1);
|
2130
|
+
rb_define_module_function(mHelpers, "define_wrapper_method", pycall_libpython_helpers_m_define_wrapper_method, 2);
|
2131
|
+
rb_define_module_function(mHelpers, "compare", pycall_libpython_helpers_m_compare, 3);
|
2132
|
+
rb_define_module_function(mHelpers, "getattr", pycall_libpython_helpers_m_getattr, -1);
|
2133
|
+
rb_define_module_function(mHelpers, "hasattr?", pycall_libpython_helpers_m_hasattr_p, 2);
|
2134
|
+
rb_define_module_function(mHelpers, "callable?", pycall_libpython_helpers_m_callable_p, 1);
|
2135
|
+
rb_define_module_function(mHelpers, "call_object", pycall_libpython_helpers_m_call_object, -1);
|
2136
|
+
rb_define_module_function(mHelpers, "getitem", pycall_libpython_helpers_m_getitem, 2);
|
2137
|
+
rb_define_module_function(mHelpers, "setitem", pycall_libpython_helpers_m_setitem, 3);
|
2138
|
+
rb_define_module_function(mHelpers, "delitem", pycall_libpython_helpers_m_delitem, 2);
|
2139
|
+
rb_define_module_function(mHelpers, "str", pycall_libpython_helpers_m_str, 1);
|
2140
|
+
rb_define_module_function(mHelpers, "dict_contains", pycall_libpython_helpers_m_dict_contains, 2);
|
2141
|
+
rb_define_module_function(mHelpers, "dict_each", pycall_libpython_helpers_m_dict_each, 1);
|
2142
|
+
rb_define_module_function(mHelpers, "sequence_contains", pycall_libpython_helpers_m_sequence_contains, 2);
|
2143
|
+
rb_define_module_function(mHelpers, "sequence_each", pycall_libpython_helpers_m_sequence_each, 1);
|
2144
|
+
|
2145
|
+
/* PyCall::Conversion */
|
2146
|
+
|
2147
|
+
mConversion = rb_define_module_under(mPyCall, "Conversion");
|
2148
|
+
|
2149
|
+
rb_define_module_function(mConversion, "register_python_type_mapping", pycall_conv_m_register_python_type_mapping, 2);
|
2150
|
+
rb_define_module_function(mConversion, "unregister_python_type_mapping", pycall_conv_m_unregister_python_type_mapping, 1);
|
2151
|
+
rb_define_module_function(mConversion, "from_ruby", pycall_conv_m_from_ruby, 1);
|
2152
|
+
rb_define_module_function(mConversion, "to_ruby", pycall_conv_m_to_ruby, 1);
|
2153
|
+
|
2154
|
+
python_type_mapping = rb_hash_new();
|
2155
|
+
id_python_type_mapping = rb_intern("__python_type_mapping__");
|
2156
|
+
rb_ivar_set(mConversion, id_python_type_mapping, python_type_mapping);
|
2157
|
+
|
2158
|
+
/* initialize the constat PYTHON_VERSION */
|
2159
|
+
|
2160
|
+
python_description = rb_str_new2(Py_API(Py_GetVersion)());
|
2161
|
+
rb_define_const(mLibPython, "PYTHON_DESCRIPTION", python_description);
|
2162
|
+
|
2163
|
+
{
|
2164
|
+
char *space_pos, *first_dot_pos;
|
2165
|
+
|
2166
|
+
space_pos = memchr(RSTRING_PTR(python_description), ' ', RSTRING_LEN(python_description));
|
2167
|
+
python_version_string = rb_str_subseq(python_description, 0, space_pos - RSTRING_PTR(python_description));
|
2168
|
+
|
2169
|
+
/* extract major version */
|
2170
|
+
first_dot_pos = memchr(RSTRING_PTR(python_version_string), '.', RSTRING_LEN(python_version_string));
|
2171
|
+
*first_dot_pos = '\0';
|
2172
|
+
python_major_version = (int)strtol(RSTRING_PTR(python_version_string), (char **)NULL, 10);
|
2173
|
+
*first_dot_pos = '.';
|
2174
|
+
}
|
2175
|
+
rb_define_const(mLibPython, "PYTHON_VERSION", python_version_string);
|
2176
|
+
|
2177
|
+
/* initialize Python interpreter */
|
2178
|
+
|
2179
|
+
init_python();
|
2180
|
+
init_pyerror();
|
2181
|
+
init_tuple();
|
2182
|
+
pycall_init_gcguard();
|
2183
|
+
pycall_init_ruby_wrapper();
|
2184
|
+
}
|