lib/rubypython.rb in rubypython-0.5.3 vs lib/rubypython.rb in rubypython-0.6.0
- old
+ new
@@ -13,43 +13,38 @@
# RubyPython.start
# cPickle = RubyPython.import "cPickle"
# puts cPickle.dumps("RubyPython is awesome!").rubify
# RubyPython.stop
module RubyPython
- VERSION = '0.5.3' #:nodoc:
-
- # Do not load the FFI interface by default. Wait until the user asks for
- # it.
- @load_ffi = false
-
- # Indicates whether the \Python DLL has been loaded. For internal use
- # only.
- def self.load_ffi? #:nodoc:
- @load_ffi
- end
+ VERSION = '0.6.0'
end
require 'rubypython/blankobject'
-require 'rubypython/options'
+require 'rubypython/interpreter'
require 'rubypython/python'
require 'rubypython/pythonerror'
require 'rubypython/pyobject'
require 'rubypython/rubypyproxy'
require 'rubypython/pymainclass'
require 'rubypython/pygenerator'
+require 'rubypython/tuple'
+require 'thread'
module RubyPython
class << self
- # Controls whether RubyPython is operating in <em>Normal Mode</em> or
- # <em>Legacy Mode</em>.
+ ##
+ # :attr_accessor:
+ # Controls whether RubyPython is operating in <em>Proxy Mode</em> or
+ # <em>Legacy Mode</em>. This behavioural difference is deprecated as of
+ # RubyPython 0.6 and will be removed in a subsequent release.
#
- # === Normal Mode
+ # === Proxy Mode
# By default, +legacy_mode+ is +false+, meaning that any object returned
- # from a \Python function call will be wrapped in an instance of
- # +RubyPyProxy+ or one of its subclasses. This allows \Python method
- # calls to be forwarded to the \Python object, even if it would otherwise
- # be a native Ruby object.
+ # from a \Python function call will be wrapped in a Ruby-Python proxy
+ # (an instance of +RubyPyProxy+ or one of its subclasses). This allows
+ # \Python method calls to be forwarded to the \Python object, even if it
+ # would otherwise be a native Ruby object.
#
# RubyPython.session do
# string = RubyPython.import 'string'
# ascii_letters = string.ascii_letters
# puts ascii_letters.isalpha # => True
@@ -58,23 +53,45 @@
#
# === Legacy Mode
# If +legacy_mode+ is +true+, RubyPython automatically tries to convert
# returned objects to native Ruby object types. If there is no such
# conversion, the object remains wrapped in +RubyPyProxy+. This
- # behaviour is the same as RubyPython 0.2 and earlier. This mode is not
- # recommended and may be phased out for RubyPython 1.0.
+ # behaviour is the same as RubyPython 0.2 and earlier. This mode is
+ # deprecated as of RubyPython 0.6 and will be removed.
#
# RubyPython.legacy_mode = true
# RubyPython.session do
# string = RubyPython.import 'string'
# ascii_letters = string.ascii_letters
# puts ascii_letters.isalpha # throws NoMethodError
# end
- attr_accessor :legacy_mode
+ def legacy_mode=(value)
+ warn_legacy_mode_deprecation unless defined? @legacy_mode
+ @legacy_mode = value
+ end
- # Starts the \Python interpreter. Either +RubyPython.start+,
- # +RubyPython.session+, or +RubyPython.run+ must be run before using any
+ def legacy_mode
+ unless defined? @legacy_mode
+ warn_legacy_mode_deprecation
+ @legacy_mode = nil
+ end
+ @legacy_mode
+ end
+
+ def legacy_mode?
+ @legacy_mode = nil unless defined? @legacy_mode
+ @legacy_mode
+ end
+ private :legacy_mode?
+
+ def warn_legacy_mode_deprecation
+ warn "RubyPython's Legacy Mode is deprecated and will be removed after version #{VERSION}."
+ end
+ private :warn_legacy_mode_deprecation
+
+ ## Starts the \Python interpreter. One of +RubyPython.start+,
+ # RubyPython.session+, or +RubyPython.run+ must be run before using any
# \Python code. Returns +true+ if the interpreter was started; +false+
# otherwise.
#
# [options] Configures the interpreter prior to starting it. Principally
# used to provide an alternative \Python interpreter to start.
@@ -88,31 +105,34 @@
# With an alternative \Python executable:
# RubyPython.start(:python_exe => 'python2.7')
# sys = RubyPython.import 'sys'
# p sys.version # => "2.7.1"
# RubyPython.stop
- #
- # *NOTE*: In the current version of RubyPython, it _is_ possible to
- # change \Python interpreters in a single Ruby process execution, but it
- # is *strongly* discouraged as this may lead to segmentation faults.
- # This feature is highly experimental and may be disabled in the future.
def start(options = {})
- RubyPython.configure(options)
+ Mutex.new.synchronize do
+ # Has the Runtime interpreter been defined?
+ if self.const_defined?(:Runtime)
+ # If this constant is defined, then yes it is. Since it is, let's
+ # see if we should print a warning to the user.
+ unless Runtime == options
+ warn "The Python interpreter has already been loaded from #{Runtime.python} and cannot be changed in this process. Continuing with the current runtime."
+ end
+ else
+ interp = RubyPython::Interpreter.new(options)
+ if interp.valid?
+ self.const_set(:Runtime, interp)
+ else
+ raise RubyPython::InvalidInterpreter, "An invalid interpreter was specified."
+ end
+ end
- unless @load_ffi
- @load_ffi = true
- @reload = false
- reload_library
+ unless defined? RubyPython::Python.ffi_libraries
+ Runtime.__send__(:infect!, RubyPython::Python)
+ end
end
return false if RubyPython::Python.Py_IsInitialized != 0
-
- if @reload
- reload_library
- @reload = false
- end
-
RubyPython::Python.Py_Initialize
notify :start
true
end
@@ -193,11 +213,11 @@
#
# :call-seq:
# run(options = {}) { block to execute in RubyPython context }
def run(options = {}, &block)
start(options)
- module_eval(&block)
+ self.module_eval(&block)
ensure
stop
end
# Starts the \Python interpreter for a
@@ -216,27 +236,32 @@
# change \Python interpreters in a single Ruby process execution, but it
# is *strongly* discouraged as this may lead to segmentation faults.
# This feature is highly experimental and may be disabled in the future.
def start_from_virtualenv(virtualenv)
result = start(:python_exe => File.join(virtualenv, "bin", "python"))
- activate
+ activate_virtualenv
result
end
- # Returns an object describing the currently active Python interpreter.
+ # Returns an object describing the active Python interpreter. Returns
+ # +nil+ if there is no active interpreter.
def python
- RubyPython::Python::EXEC
+ if self.const_defined? :Runtime
+ self::Runtime
+ else
+ nil
+ end
end
# Used to activate the virtualenv.
- def activate
+ def activate_virtualenv
imp = import("imp")
imp.load_source("activate_this",
- File.join(File.dirname(RubyPython::Python::EXEC.python),
+ File.join(File.dirname(RubyPython::Runtime.python),
"activate_this.py"))
end
- private :activate
+ private :activate_virtualenv
def add_observer(object)
@observers ||= []
@observers << object
true
@@ -245,24 +270,13 @@
def notify(status)
@observers ||= []
@observers.each do |o|
next if nil === o
- o.update status
+ o.__send__ :python_interpreter_update, status
end
end
private :notify
-
- def reload_library
- # Invalidate the current Python instance, if defined.
- if defined? RubyPython::Python::EXEC and RubyPython::Python::EXEC
- RubyPython::Python::EXEC.instance_eval { invalidate! }
- end
- remove_const :Python
- load RubyPython::PYTHON_RB
- true
- end
- private :reload_library
end
add_observer PyMain
add_observer Operators
add_observer PyObject::AutoPyPointer