require 'rubypython/blankobject' require 'singleton' module RubyPython # A singleton object providing access to the \Python __main__ and # __builtin__ modules. This can be conveniently accessed through # +PyMain+. The __main__ namespace is searched before the # __builtin__ namespace. As such, naming clashes will be resolved # in that order. # # RubyPython::PyMain.dir("dir") # => ['__add__', '__class__', … ] # # === Block Syntax # PyMainClass provides experimental block support for called methods. A # block may be passed to a method call and the object returned by the # function call will be passed as an argument to the block. # # RubyPython::PyMain.dir("dir") { |a| a.rubify.map { |e| e.to_sym } } # # => [:__add__, :__class__, :__contains__, … ] class PyMainClass < RubyPython::BlankObject include Singleton # Returns a proxy object wrapping the \Python __main__ namespace. def main @main ||= RubyPython.import "__main__" end # Returns a proxy object wrapping the \Python __builtin__ # namespace. def builtin @builtin ||= RubyPython.import "__builtin__" end # Delegates any method calls on this object to the \Python # __main__ or __builtin__ namespaces, in that order. If # a block is provided, the result of calling the \Python method will be # yielded as an argument to the block. # # [name] The name of the \Python method or function to call. # [args] The arguments to pass to the \Python method. # [block] A block to execute with the result of calling the \Python # method. If a block is provided, the result of the block is returned, # not the result of the \Python method. def method_missing(name, *args, &block) proxy = if main.respond_to?(name) main elsif builtin.respond_to?(name) builtin else super(name, *args) end result = if proxy.is_real_method?(name) proxy.__send__(name, *args) else proxy.__send__(:method_missing, name, *args) end if block block.call(result) else result end end # Called by RubyPython when the interpreter is started or stopped so # that the neccesary preparation or cleanup can be done. For internal # use only. def python_interpreter_update(status) case status when :stop @main = nil @builtin = nil end end private :python_interpreter_update end # The accessible instance of PyMainClass. PyMain = RubyPython::PyMainClass.instance end