Skip to content

Commit c2be235

Browse files
committed
Fix PyCall.import_module for callables
1 parent 5f72214 commit c2be235

File tree

3 files changed

+26
-8
lines changed

3 files changed

+26
-8
lines changed

lib/pycall/import.rb

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,8 @@ def pyfrom(mod_name, import: nil)
5353
name, asname = import_name, import_name
5454
end
5555

56-
if mod.respond_to? name
57-
pyobj = mod.__send__ name
56+
if PyCall::LibPython::Helpers.hasattr?(mod.__pyptr__, name)
57+
pyobj = PyCall::LibPython::Helpers.getattr(mod.__pyptr__, name)
5858
define_name(asname, pyobj)
5959
next
6060
end
@@ -77,12 +77,18 @@ def pyfrom(mod_name, import: nil)
7777
private
7878

7979
def define_name(name, pyobj)
80-
if constant_name?(name)
81-
context = self
82-
context = (self == PyCall::Import.main_object) ? Object : self
83-
context.module_eval { const_set(name, pyobj) }
80+
if callable?(pyobj) && !type_object?(pyobj)
81+
define_singleton_method(name) do |*args|
82+
LibPython::Helpers.call_object(pyobj.__pyptr__, *args)
83+
end
8484
else
85-
define_singleton_method(name) { pyobj }
85+
if constant_name?(name)
86+
context = self
87+
context = (self == PyCall::Import.main_object) ? Object : self
88+
context.module_eval { const_set(name, pyobj) }
89+
else
90+
define_singleton_method(name) { pyobj }
91+
end
8692
end
8793
end
8894

@@ -102,5 +108,13 @@ def assoc_array_matcher
102108
ary.is_a?(Array) && ary.length == 2
103109
end
104110
end
111+
112+
def callable?(pyobj)
113+
LibPython::Helpers.callable?(pyobj.__pyptr__)
114+
end
115+
116+
def type_object?(pyobj)
117+
pyobj.__pyptr__.kind_of? PyTypePtr
118+
end
105119
end
106120
end

spec/pycall/import_spec.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,10 @@ module PyCall
5050
it 'defines methods with the given names in the Hash values' do
5151
expect(mod).not_to be_respond_to(:foo)
5252
expect(mod).not_to be_respond_to(:bar)
53-
mod.pyfrom 'pycall.import_test', import: { Foo: :foo, TestClass: :bar }
53+
mod.pyfrom 'pycall.import_test', import: { Foo: :foo, TestClass: :bar, to_list: :to_list }
5454
expect(mod.foo).to be_kind_of(PyTypeObjectWrapper)
5555
expect(mod.bar).to be_kind_of(PyObjectWrapper)
56+
expect(mod.to_list(42)).to eq(PyCall::List.new([42]))
5657
end
5758
end
5859

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,5 @@
11
class Foo:
22
pass
3+
4+
def to_list(x):
5+
return [x]

0 commit comments

Comments
 (0)