Skip to content

Commit 9822751

Browse files
committed
Add PyTypePtr#subclass?
1 parent 0b8b678 commit 9822751

File tree

4 files changed

+82
-0
lines changed

4 files changed

+82
-0
lines changed

ext/pycall/libpython.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ pycall_init_libpython_api_table(VALUE libpython_handle)
9494
INIT_API_TABLE_ENTRY(_PyObject_New, required);
9595
INIT_API_TABLE_ENTRY(PyCallable_Check, required);
9696
INIT_API_TABLE_ENTRY(PyObject_IsInstance, required);
97+
INIT_API_TABLE_ENTRY(PyObject_IsSubclass, required);
9798
INIT_API_TABLE_ENTRY2(PyObject_Hash._hash_t, PyObject_Hash, required);
9899
INIT_API_TABLE_ENTRY(PyObject_RichCompare, required);
99100
INIT_API_TABLE_ENTRY(PyObject_Call, required);

ext/pycall/pycall.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -526,6 +526,23 @@ pycall_pytypeptr_get_tp_flags(VALUE obj)
526526
return Qnil;
527527
}
528528

529+
static VALUE
530+
pycall_pytypeptr_subclass_p(VALUE obj, VALUE other)
531+
{
532+
PyObject *pyobj, *pyobj_other;
533+
int res;
534+
535+
pyobj = get_pytypeobj_ptr(obj);
536+
pyobj_other = check_get_pytypeobj_ptr(other);
537+
538+
res = Py_API(PyObject_IsSubclass)(pyobj, pyobj_other);
539+
if (res < 0) {
540+
pycall_pyerror_fetch_and_raise("PyObject_IsSubclass in pycall_pytypeptr_subclass_p");
541+
}
542+
543+
return res ? Qtrue : Qfalse;
544+
}
545+
529546
static VALUE
530547
pycall_pytypeptr_eqq(VALUE obj, VALUE other)
531548
{
@@ -2108,6 +2125,7 @@ Init_pycall(void)
21082125
rb_define_method(cPyTypePtr, "__tp_name__", pycall_pytypeptr_get_tp_name, 0);
21092126
rb_define_method(cPyTypePtr, "__tp_basicsize__", pycall_pytypeptr_get_tp_basicsize, 0);
21102127
rb_define_method(cPyTypePtr, "__tp_flags__", pycall_pytypeptr_get_tp_flags, 0);
2128+
rb_define_method(cPyTypePtr, "subclass?", pycall_pytypeptr_subclass_p, 1);
21112129
rb_define_method(cPyTypePtr, "===", pycall_pytypeptr_eqq, 1);
21122130

21132131
/* PyCall::LibPython::API */

ext/pycall/pycall_internal.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -525,6 +525,7 @@ typedef struct {
525525
PyObject * (* _PyObject_New)(PyTypeObject *);
526526
int (* PyCallable_Check)(PyObject *);
527527
int (* PyObject_IsInstance)(PyObject *, PyObject *);
528+
int (* PyObject_IsSubclass)(PyObject *, PyObject *);
528529
union {
529530
long (* _long)(PyObject *);
530531
Py_hash_t (* _hash_t)(PyObject *);

spec/pycall/pytypeptr_spec.rb

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
require 'spec_helper'
2+
3+
module PyCall
4+
::RSpec.describe PyTypePtr do
5+
describe '#subclass?(other)' do
6+
subject { PyCall::List.__pyptr__ }
7+
8+
context 'when the value of `other` is a PyTypePtr' do
9+
specify do
10+
expect(subject.subclass?(PyCall.builtins.object.__pyptr__)).to eq(true)
11+
expect(subject.subclass?(PyCall.builtins.dict.__pyptr__)).to eq(false)
12+
end
13+
end
14+
15+
context 'when the value of `other` is a PyPtr' do
16+
specify do
17+
expect { subject.subclass?(Conversion.from_ruby(42)) }.to raise_error(TypeError)
18+
end
19+
end
20+
21+
context 'when the value of `other` is a PyTypeObjectWrapper' do
22+
specify do
23+
expect { subject.subclass?(PyCall.builtins.object) }.to raise_error(TypeError)
24+
expect { subject.subclass?(PyCall.builtins.dict) }.to raise_error(TypeError)
25+
end
26+
end
27+
28+
context 'when the value of `other` is a Class' do
29+
specify do
30+
expect { subject.subclass?(Array) }.to raise_error(TypeError)
31+
expect { subject.subclass?(Hash) }.to raise_error(TypeError)
32+
end
33+
end
34+
35+
context 'when the value of `other` is an instance of other class' do
36+
specify do
37+
expect { subject.subclass?(12) }.to raise_error(TypeError)
38+
end
39+
end
40+
end
41+
42+
describe '#<=>' do
43+
pending
44+
end
45+
46+
describe '#<' do
47+
pending
48+
end
49+
50+
describe '#>' do
51+
pending
52+
end
53+
54+
describe '#<=' do
55+
pending
56+
end
57+
58+
describe '#>=' do
59+
pending
60+
end
61+
end
62+
end

0 commit comments

Comments
 (0)