lib/pycall/import.rb in pycall-0.1.0.alpha.20170711 vs lib/pycall/import.rb in pycall-1.0.0
- old
+ new
@@ -1,81 +1,72 @@
require 'pycall'
module PyCall
module Import
- def self.main_object
- @main_object
+ class << self
+ attr_reader :main_object
end
end
end
-main_object = self
-PyCall::Import.class_eval { @main_object = main_object }
+PyCall::Import.instance_variable_set(:@main_object, self)
module PyCall
module Import
def pyimport(mod_name, as: nil)
- case as
- when nil
- as = mod_name
- end
-
+ as = mod_name unless as
check_valid_module_variable_name(mod_name, as)
-
mod = PyCall.import_module(mod_name)
- raise PyError.fetch unless mod
-
define_singleton_method(as) { mod }
end
# This function is implemented as a mimic of `import_from` function defined in `Python/ceval.c`.
def pyfrom(mod_name, import: nil)
- raise ArgumentError, "missing identifiers to be imported" unless import
+ raise ArgumentError, "missing identifier(s) to be imported" unless import
mod_name = mod_name.to_str if mod_name.respond_to? :to_str
mod_name = mod_name.to_s if mod_name.is_a? Symbol
import = Array(import)
- fromlist = LibPython.PyTuple_New(import.length)
- import.each_with_index do |import_name, i|
- name = case import_name
- when assoc_array_matcher
- import_name[0]
- when Symbol, String
- import_name
- end
- LibPython.PyTuple_SetItem(fromlist, i, Conversions.from_ruby(name))
+ fromlist = import.map.with_index do |import_name, i|
+ case import_name
+ when assoc_array_matcher
+ import_name[0]
+ when Symbol, String
+ import_name
+ else
+ raise ArgumentError, "wrong type of import name #{import_name.class} (expected String or Symbol)"
+ end
end
+ from_list = PyCall.tuple(from_list)
- main_dict = PyCall::Eval.__send__ :main_dict
- globals = main_dict.__pyobj__ # FIXME: this should mimic to `import_name` function defined in `Python/ceval.c`.
- locals = main_dict.__pyobj__ # FIXME: this should mimic to `import_name` function defined in `Python/ceval.c`.
+ main_dict_ptr = PyCall.import_module('__main__').__dict__.__pyptr__
+ globals = main_dict_ptr # FIXME: this should mimic to `import_name` function defined in `Python/ceval.c`.
+ locals = main_dict_ptr # FIXME: this should mimic to `import_name` function defined in `Python/ceval.c`.
level = 0 # TODO: support prefixed dots (#25)
- mod = LibPython.PyImport_ImportModuleLevel(mod_name, globals, locals, fromlist, level)
- raise PyError.fetch if mod.null?
- mod = mod.to_ruby
+ mod = LibPython::Helpers.import_module(mod_name, globals, locals, fromlist, level)
import.each do |import_name|
case import_name
when assoc_array_matcher
name, asname = *import_name
when Symbol, String
name, asname = import_name, import_name
end
- if PyCall.hasattr?(mod, name)
- pyobj = PyCall.getattr(mod, name)
+ if PyCall::LibPython::Helpers.hasattr?(mod.__pyptr__, name)
+ pyobj = PyCall::LibPython::Helpers.getattr(mod.__pyptr__, name)
define_name(asname, pyobj)
next
end
- if PyCall.hasattr?(mod, :__name__)
- pkgname = PyCall.getattr(mod, :__name__)
+ if mod.respond_to? :__name__
+ pkgname = mod.__name__
fullname = "#{pkgname}.#{name}"
- module_dict = LibPython.PyImport_GetModuleDict()
- if PyCall.getattr(module_dict, fullname)
- pyobj = PyCall.getattr(module_dict, fullname)
+ sys_modules = PyCall.import_module('sys').modules
+ if sys_modules.has_key?(fullname)
+ pyobj = module_dict[fullname]
define_name(asname, pyobj)
next
end
end
@@ -84,16 +75,22 @@
end
private
def define_name(name, pyobj)
- if constant_name?(name)
- context = self
- context = (self == PyCall::Import.main_object) ? Object : self
- context.module_eval { const_set(name, pyobj) }
+ if callable?(pyobj) && !type_object?(pyobj)
+ define_singleton_method(name) do |*args|
+ LibPython::Helpers.call_object(pyobj.__pyptr__, *args)
+ end
else
- define_singleton_method(name) { pyobj }
+ if constant_name?(name)
+ context = self
+ context = (self == PyCall::Import.main_object) ? Object : self
+ context.module_eval { const_set(name, pyobj) }
+ else
+ define_singleton_method(name) { pyobj }
+ end
end
end
def constant_name?(name)
name =~ /\A[A-Z]/
@@ -108,8 +105,16 @@
def assoc_array_matcher
@assoc_array_matcher ||= ->(ary) do
ary.is_a?(Array) && ary.length == 2
end
+ end
+
+ def callable?(pyobj)
+ LibPython::Helpers.callable?(pyobj.__pyptr__)
+ end
+
+ def type_object?(pyobj)
+ pyobj.__pyptr__.kind_of? PyTypePtr
end
end
end