lokeshh_rubypython 0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. checksums.yaml +7 -0
  2. data/.autotest +3 -0
  3. data/.gitignore +18 -0
  4. data/.hgignore +20 -0
  5. data/.hgtags +12 -0
  6. data/.rspec +2 -0
  7. data/Contributors.rdoc +11 -0
  8. data/History.rdoc +214 -0
  9. data/License.rdoc +26 -0
  10. data/Manifest.txt +46 -0
  11. data/PostInstall.txt +16 -0
  12. data/README.rdoc +272 -0
  13. data/Rakefile +118 -0
  14. data/autotest/discover.rb +1 -0
  15. data/lib/rubypython/blankobject.rb +23 -0
  16. data/lib/rubypython/conversion.rb +332 -0
  17. data/lib/rubypython/interpreter.rb +262 -0
  18. data/lib/rubypython/macros.rb +56 -0
  19. data/lib/rubypython/operators.rb +120 -0
  20. data/lib/rubypython/pygenerator.rb +61 -0
  21. data/lib/rubypython/pymainclass.rb +80 -0
  22. data/lib/rubypython/pyobject.rb +189 -0
  23. data/lib/rubypython/python.rb +199 -0
  24. data/lib/rubypython/pythonerror.rb +80 -0
  25. data/lib/rubypython/rubypyproxy.rb +328 -0
  26. data/lib/rubypython/tuple.rb +10 -0
  27. data/lib/rubypython/type.rb +20 -0
  28. data/lib/rubypython.rb +229 -0
  29. data/spec/basic_spec.rb +50 -0
  30. data/spec/callback_spec.rb +53 -0
  31. data/spec/conversion_spec.rb +68 -0
  32. data/spec/pymainclass_spec.rb +24 -0
  33. data/spec/pyobject_spec.rb +202 -0
  34. data/spec/python_helpers/basics.py +23 -0
  35. data/spec/python_helpers/errors.py +2 -0
  36. data/spec/python_helpers/objects.py +48 -0
  37. data/spec/pythonerror_spec.rb +52 -0
  38. data/spec/refcnt_spec.rb +98 -0
  39. data/spec/rubypyclass_spec.rb +10 -0
  40. data/spec/rubypyproxy_spec.rb +261 -0
  41. data/spec/rubypython_spec.rb +59 -0
  42. data/spec/spec_helper.rb +71 -0
  43. data/website/index.rhtml +36 -0
  44. data/website/robots.txt +5 -0
  45. data/website/stylesheets/960.css +549 -0
  46. data/website/stylesheets/border-radius.htc +143 -0
  47. data/website/stylesheets/screen.css +132 -0
  48. metadata +297 -0
@@ -0,0 +1,262 @@
1
+ # -*- ruby encoding: utf-8 -*-
2
+
3
+ class RubyPython::InvalidInterpreter < Exception
4
+ end
5
+
6
+ ##
7
+ # An instance of this class represents information about a particular
8
+ # \Python interpreter.
9
+ #
10
+ # This class represents the current Python interpreter.
11
+ # A class that represents a \Python executable.
12
+ #
13
+ # End users may get the instance that represents the current running \Python
14
+ # interpreter (from +RubyPython.python+), but should not directly
15
+ # instantiate this class.
16
+ class RubyPython::Interpreter
17
+
18
+ ##
19
+ # Compare the current Interpreter to the provided Interpreter or
20
+ # configuration hash. A configuration hash will be converted to an
21
+ # Interpreter object before being compared.
22
+ # :python_exe basename is used. If comparing against another Interpreter
23
+ # object, the Interpreter basename and version are used.
24
+ def ==(other)
25
+ other = self.class.new(other) if other.kind_of? Hash
26
+ return false unless other.kind_of? self.class
27
+ (self.version == other.version) && (self.version_name == other.version_name)
28
+ end
29
+
30
+ ##
31
+ # Create a new instance of an Interpreter instance describing a particular
32
+ # \Python executable and shared library.
33
+ #
34
+ # Expects a hash that matches the configuration options provided to
35
+ # RubyPython.start; currently only one value is recognized in that hash:
36
+ #
37
+ # * <tt>:python_exe</tt>: Specifies the name of the python executable to
38
+ # run.
39
+ def initialize(options = {})
40
+ @python_exe = options[:python_exe]
41
+ # Windows: 'C:\\Python27\python.exe'
42
+ # Mac OS X: '/usr/bin/
43
+
44
+ # The default interpreter might be python3 on some systems
45
+ rc, majorversion = runpy "import sys; print(sys.version_info[0])"
46
+ if majorversion == "3"
47
+ warn "The python interpreter is python 3, switching to python2"
48
+ @python_exe = "python2"
49
+ end
50
+
51
+ rc, @python = runpy "import sys; print sys.executable"
52
+ if rc.exitstatus.nonzero?
53
+ raise RubyPython::InvalidInterpreter, "An invalid interpreter was specified."
54
+ end
55
+ rc, @version = runpy "import sys; print '%d.%d' % sys.version_info[:2]"
56
+ rc, @sys_prefix = runpy "import sys; print sys.prefix"
57
+
58
+ if ::FFI::Platform.windows?
59
+ flat_version = @version.tr('.', '')
60
+ basename = File.basename(@python, '.exe')
61
+
62
+ if basename =~ /(?:#{@version}|#{flat_version})$/
63
+ @version_name = basename
64
+ else
65
+ @version_name = "#{basename}#{flat_version}"
66
+ end
67
+ else
68
+ basename = File.basename(@python)
69
+ if basename =~ /#{@version}/
70
+ @version_name = basename
71
+ elsif basename.end_with?("2")
72
+ @version_name = "#{basename[0..-2]}#{@version}"
73
+ else
74
+ @version_name = "#{basename}#{@version}"
75
+ end
76
+ end
77
+
78
+ @library = find_python_lib
79
+ end
80
+
81
+ def find_python_lib
82
+ # By default, the library name will be something like
83
+ # libpython2.6.so, but that won't always work.
84
+ @libbase = "#{::FFI::Platform::LIBPREFIX}#{@version_name}"
85
+ @libext = ::FFI::Platform::LIBSUFFIX
86
+ @libname = "#{@libbase}.#{@libext}"
87
+
88
+ # We may need to look in multiple locations for Python, so let's
89
+ # build this as an array.
90
+ @locations = [ File.join(@sys_prefix, "lib", @libname) ]
91
+
92
+ if ::FFI::Platform.mac?
93
+ # On the Mac, let's add a special case that has even a different
94
+ # @libname. This may not be fully useful on future versions of OS
95
+ # X, but it should work on 10.5 and 10.6. Even if it doesn't, the
96
+ # next step will (/usr/lib/libpython<version>.dylib is a symlink
97
+ # to the correct location).
98
+ @locations << File.join(@sys_prefix, "Python")
99
+ # Let's also look in the location that was originally set in this
100
+ # library:
101
+ File.join(@sys_prefix, "lib", "#{@realname}", "config", @libname)
102
+ end
103
+
104
+ if ::FFI::Platform.unix?
105
+ # On Unixes, let's look in some standard alternative places, too.
106
+ # Just in case. Some Unixes don't include a .so symlink when they
107
+ # should, so let's look for the base cases of .so.1 and .so.1.0, too.
108
+ [ @libname, "#{@libname}.1", "#{@libname}.1.0" ].each do |name|
109
+ if ::FFI::Platform::ARCH != 'i386'
110
+ @locations << File.join("/opt/local/lib64", name)
111
+ @locations << File.join("/opt/lib64", name)
112
+ @locations << File.join("/usr/local/lib64", name)
113
+ @locations << File.join("/usr/lib64", name)
114
+ @locations << File.join("/usr/lib/x86_64-linux-gnu", name)
115
+ end
116
+ @locations << File.join("/opt/local/lib", name)
117
+ @locations << File.join("/opt/lib", name)
118
+ @locations << File.join("/usr/local/lib", name)
119
+ @locations << File.join("/usr/lib", name)
120
+ end
121
+ end
122
+
123
+ if ::FFI::Platform.windows?
124
+ # On Windows, the appropriate DLL is usually be found in
125
+ # %SYSTEMROOT%\system or %SYSTEMROOT%\system32; as a fallback we'll
126
+ # use C:\Windows\system{,32} as well as the install directory and the
127
+ # install directory + libs.
128
+ system_root = File.expand_path(ENV['SYSTEMROOT']).gsub(/\\/, '/')
129
+ @locations << File.join(system_root, 'system', @libname)
130
+ @locations << File.join(system_root, 'system32', @libname)
131
+ @locations << File.join("C:/WINDOWS", "System", @libname)
132
+ @locations << File.join("C:/WINDOWS", "System32", @libname)
133
+ @locations << File.join(sys_prefix, @libname)
134
+ @locations << File.join(sys_prefix, 'libs', @libname)
135
+ @locations << File.join(system_root, "SysWOW64", @libname)
136
+ @locations << File.join("C:/WINDOWS", "SysWOW64", @libname)
137
+ end
138
+
139
+ # Let's add alternative extensions; again, just in case.
140
+ @locations.dup.each do |location|
141
+ path = File.dirname(location)
142
+ base = File.basename(location, ".#{@libext}")
143
+ @locations << File.join(path, "#{base}.so") # Standard Unix
144
+ @locations << File.join(path, "#{base}.dylib") # Mac OS X
145
+ @locations << File.join(path, "#{base}.dll") # Windows
146
+ end
147
+
148
+ # Remove redundant locations
149
+ @locations.uniq!
150
+
151
+ library = nil
152
+
153
+ @locations.each do |location|
154
+ if File.exists? location
155
+ library = location
156
+ break
157
+ end
158
+ end
159
+
160
+ library
161
+ end
162
+ private :find_python_lib
163
+
164
+ def valid?
165
+ if @python.nil? or @python.empty?
166
+ false
167
+ elsif @library.nil? or @library.empty?
168
+ false
169
+ else
170
+ true
171
+ end
172
+ end
173
+
174
+ ##
175
+ # The name of the \Python executable that is used. This is the value of
176
+ # 'sys.executable' for the \Python interpreter provided in
177
+ # <tt>:python_exe</tt> or 'python' if it is not provided.
178
+ #
179
+ # On Mac OS X Lion (10.7), this value is '/usr/bin/python' for 'python'.
180
+ attr_reader :python
181
+ ##
182
+ # The version of the \Python interpreter. This is a decimalized version of
183
+ # 'sys.version_info[:2]' (such that \Python 2.7.1 is reported as '2.7').
184
+ attr_reader :version
185
+ ##
186
+ # The system prefix for the \Python interpreter. This is the value of
187
+ # 'sys.prefix'.
188
+ attr_reader :sys_prefix
189
+ ##
190
+ # The basename of the \Python interpreter with a version number. This is
191
+ # mostly an intermediate value used to find the shared \Python library,
192
+ # but /usr/bin/python is often a link to /usr/bin/python2.7 so it may be
193
+ # of value. Note that this does *not* include the full path to the
194
+ # interpreter.
195
+ attr_reader :version_name
196
+
197
+ # The \Python library.
198
+ attr_reader :library
199
+
200
+ # Run a Python command-line command.
201
+ def runpy(command)
202
+ i = @python || @python_exe || 'python'
203
+ if ::FFI::Platform.windows?
204
+ o = %x(#{i} -c "#{command}" 2> NUL:)
205
+ else
206
+ o = %x(#{i} -c "#{command}" 2> /dev/null)
207
+ end
208
+
209
+ [ $?, o.chomp ]
210
+ end
211
+ private :runpy
212
+
213
+ def inspect(debug = false)
214
+ if debug
215
+ debug_s
216
+ elsif @python
217
+ "#<#{self.class}: #{python} v#{version} #{sys_prefix} #{version_name}>"
218
+ else
219
+ "#<#{self.class}: invalid interpreter>"
220
+ end
221
+ end
222
+
223
+ def debug_s(format = nil)
224
+ system = ""
225
+ system << "windows " if ::FFI::Platform.windows?
226
+ system << "mac " if ::FFI::Platform.mac?
227
+ system << "unix " if ::FFI::Platform.unix?
228
+ system << "unknown " if system.empty?
229
+
230
+ case format
231
+ when :report
232
+ s = <<-EOS
233
+ python_exe: #{@python_exe}
234
+ python: #{@python}
235
+ version: #{@version}
236
+ sys_prefix: #{@sys_prefix}
237
+ version_name: #{@version_name}
238
+ platform: #{system.chomp}
239
+ library: #{@library.inspect}
240
+ libbase: #{@libbase}
241
+ libext: #{@libext}
242
+ libname: #{@libname}
243
+ locations: #{@locations.inspect}
244
+ EOS
245
+ else
246
+ s = "#<#{self.class}: "
247
+ s << "python_exe=#{@python_exe.inspect} "
248
+ s << "python=#{@python.inspect} "
249
+ s << "version=#{@version.inspect} "
250
+ s << "sys_prefix=#{@sys_prefix.inspect} "
251
+ s << "version_name=#{@version_name.inspect} "
252
+ s << system
253
+ s << "library=#{@library.inspect} "
254
+ s << "libbase=#{@libbase.inspect} "
255
+ s << "libext=#{@libext.inspect} "
256
+ s << "libname=#{@libname.inspect} "
257
+ s << "locations=#{@locations.inspect}"
258
+ end
259
+
260
+ s
261
+ end
262
+ end
@@ -0,0 +1,56 @@
1
+ require 'ffi'
2
+ require 'rubypython/python'
3
+
4
+ # Contains Python C API macros reimplemented in Ruby. For internal use only.
5
+ module RubyPython::Macros #:nodoc:
6
+ # Returns the reference count for the provided pointer.
7
+ def self.Py_REFCNT(pObjPointer)
8
+ pStruct = RubyPython::Python::PyObjectStruct.new pObjPointer
9
+ pStruct[:ob_refcnt]
10
+ end
11
+
12
+ # Returns the object type for the provided pointer.
13
+ def self.Py_TYPE(pObjPointer)
14
+ pStruct = RubyPython::Python::PyObjectStruct.new pObjPointer
15
+ pStruct[:ob_type]
16
+ end
17
+
18
+ # This has been modified from the C API macro to allow for multiple
19
+ # pointer objects to be passed. It simplifies a number of checks.
20
+ def self.PyObject_TypeCheck(pObject, pTypePointer)
21
+ type = self.Py_TYPE(pObject)
22
+
23
+ [ pTypePointer ].flatten.each do |pointer|
24
+ return 1 if type == pointer
25
+ end
26
+
27
+ return 0
28
+ end
29
+
30
+ def self.Py_True
31
+ RubyPython::Python.Py_TrueStruct.to_ptr
32
+ end
33
+
34
+ def self.Py_False
35
+ RubyPython::Python.Py_ZeroStruct.to_ptr
36
+ end
37
+
38
+ def self.Py_None
39
+ RubyPython::Python.Py_NoneStruct.to_ptr
40
+ end
41
+
42
+ def self.Py_RETURN_FALSE
43
+ RubyPython::Python.Py_IncRef(self.Py_False)
44
+ self.Py_False
45
+ end
46
+
47
+ def self.Py_RETURN_TRUE
48
+ RubyPython::Python.Py_IncRef(self.Py_True)
49
+ self.Py_True
50
+ end
51
+
52
+ def self.Py_RETURN_NONE
53
+ RubyPython::Python.Py_IncRef(self.Py_None)
54
+ self.Py_None
55
+ end
56
+ end
@@ -0,0 +1,120 @@
1
+ # A mixin module to provide method delegation to a proxy class. This is done
2
+ # either by delegating to methods defined on the wrapped object or by using
3
+ # the \Python _operator_ module. A large number of the methods are
4
+ # dynamically generated and so their documentation is not provided here. In
5
+ # general all operators that can be overloaded are delegated.
6
+ module RubyPython::Operators
7
+ # Provides access to the \Python _operator_ module.
8
+ def self.operator_
9
+ @@operator ||= RubyPython.import('operator')
10
+ end
11
+
12
+ # Creates a method to delegate a binary operation.
13
+ # [rname] The name of the Ruby method for this operation. Can be either a
14
+ # Symbol or a String.
15
+ # [pname] The name of the \Python magic method to which this method should
16
+ # be delegated.
17
+ def self.bin_op(rname, pname)
18
+ define_method rname.to_sym do |other|
19
+ self.__send__(pname, other)
20
+ end
21
+ end
22
+
23
+ # Creates a method to delegate a relational operator. The result of the
24
+ # delegated method will always be converted to a Ruby type so that simple
25
+ # boolean testing may occur. These methods are implemented with calls the
26
+ # _operator_ module.
27
+ #
28
+ # [rname] The name of the Ruby method for this operation. Can be a Symbol
29
+ # or a String.
30
+ # [pname] The name of the \Python magic method to which this method should
31
+ # be delegated.
32
+ def self.rel_op(rname, pname)
33
+ define_method rname.to_sym do |other|
34
+ RubyPython::Operators.operator_.__send__(pname, self, other).rubify
35
+ end
36
+ end
37
+
38
+ # Creates a method to delegate a relational operator.
39
+ # These methods are implemented with calls the _operator_ module.
40
+ # [rname] The name of the Ruby method for this operation. Can be a Symbol
41
+ # or a String.
42
+ # [pname] The name of the \Python magic method to which this method should
43
+ # be delegated.
44
+ def self.unary_op(rname, pname)
45
+ define_method rname.to_sym do
46
+ RubyPython::Operators.operator_.__send__(pname, self)
47
+ end
48
+ end
49
+
50
+ [
51
+ [:+, '__add__'],
52
+ [:-, '__sub__'],
53
+ [:*, '__mul__'],
54
+ [:/, '__div__'],
55
+ [:&, '__and__'],
56
+ [:^, '__xor__'],
57
+ [:%, '__mod__'],
58
+ [:**, '__pow__'],
59
+ [:>>, '__rshift__'],
60
+ [:<<, '__lshift__'],
61
+ [:|, '__or__']
62
+ ].each do |args|
63
+ bin_op *args
64
+ end
65
+
66
+ [
67
+ [:~, :__invert__],
68
+ [:+@, :__pos__],
69
+ [:-@, :__neg__]
70
+ ].each do |args|
71
+ unary_op *args
72
+ end
73
+
74
+ [
75
+ [:==, 'eq'],
76
+ [:<, 'lt'],
77
+ [:<=, 'le'],
78
+ [:>, 'gt'],
79
+ [:>=, 'ge'],
80
+ [:equal?, 'is_']
81
+ ].each do |args|
82
+ rel_op *args
83
+ end
84
+
85
+ # Delegates object indexed access to the wrapped \Python object.
86
+ def [](index)
87
+ self.__getitem__ index
88
+ end
89
+
90
+ # Delegates setting of various indices to the wrapped \Python object.
91
+ def []=(index, value)
92
+ self.__setitem__ index, value
93
+ end
94
+
95
+ # Delegates membership testing to \Python.
96
+ def include?(item)
97
+ self.__contains__(item).rubify
98
+ end
99
+
100
+ # Delegates Comparison to \Python.
101
+ def <=>(other)
102
+ RubyPython::PyMain.cmp(self, other)
103
+ end
104
+
105
+ class << self
106
+ # Called by RubyPython when the interpreter is started or stopped so
107
+ # that the necessary preparation or cleanup can be done. For internal
108
+ # use only.
109
+ def python_interpreter_update(status)
110
+ case status
111
+ when :stop
112
+ @@operator = nil
113
+ end
114
+ end
115
+ private :python_interpreter_update
116
+ end
117
+
118
+ # Aliases eql? to == for Python objects.
119
+ alias_method :eql?, :==
120
+ end
@@ -0,0 +1,61 @@
1
+ require "rubypython/python"
2
+ require "rubypython/conversion"
3
+ require 'rubypython/macros'
4
+ require 'rubypython/conversion'
5
+ require 'rubypython/pyobject'
6
+ require "rubypython/pymainclass"
7
+ require "rubypython/rubypyproxy"
8
+
9
+ if defined? Fiber
10
+ module RubyPython
11
+ class << self
12
+ # Creates a \Python generator object called +rubypython_generator+
13
+ # that accepts a callback and yields to it.
14
+ #
15
+ # *Note*: This method only exists in the RubyPython if the Fiber
16
+ # exists.
17
+ def generator_type
18
+ @generator_type ||= lambda do
19
+ code = <<-EOM
20
+ def rubypython_generator(callback):
21
+ while True:
22
+ yield callback()
23
+ EOM
24
+
25
+ globals = PyObject.new({ "__builtins__" => PyMain.builtin.pObject, })
26
+ empty_hash = PyObject.new({})
27
+ ptr = Python.PyRun_String(code, Python::PY_FILE_INPUT, globals.pointer, empty_hash.pointer)
28
+ ptr = Python.PyRun_String("rubypython_generator", Python::PY_EVAL_INPUT, globals.pointer, empty_hash.pointer)
29
+ raise PythonError.handle_error if PythonError.error?
30
+ RubyPyProxy.new(PyObject.new(ptr))
31
+ end.call
32
+ end
33
+
34
+ # Creates a Ruby lambda that acts like a \Python generator. Uses
35
+ # +RubyPython.generator_type+ and Fiber to work the generator as a
36
+ # coroutine.
37
+ #
38
+ # *Note*: This method only exists in the RubyPython if the Fiber
39
+ # exists.
40
+ def generator
41
+ return lambda do |*args|
42
+ fib = Fiber.new do
43
+ yield *args
44
+ Python.PyErr_SetNone(Python.PyExc_StopIteration)
45
+ ::FFI::Pointer::NULL
46
+ end
47
+ generator_type.__call__(lambda { fib.resume })
48
+ end
49
+ end
50
+
51
+ # Performs a +Fiber.yield+ with the provided arguments, continuing the
52
+ # coroutine execution of the generator.
53
+ #
54
+ # *Note*: This method only exists in the RubyPython if the Fiber
55
+ # exists.
56
+ def yield(*args)
57
+ Fiber.yield(*args)
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,80 @@
1
+ require 'rubypython/blankobject'
2
+ require 'singleton'
3
+
4
+ module RubyPython
5
+ # A singleton object providing access to the \Python <tt>__main__</tt> and
6
+ # <tt>__builtin__</tt> modules. This can be conveniently accessed through
7
+ # +PyMain+. The <tt>__main__</tt> namespace is searched before the
8
+ # <tt>__builtin__</tt> namespace. As such, naming clashes will be resolved
9
+ # in that order.
10
+ #
11
+ # RubyPython::PyMain.dir("dir") # => ['__add__', '__class__', … ]
12
+ #
13
+ # === Block Syntax
14
+ # PyMainClass provides experimental block support for called methods. A
15
+ # block may be passed to a method call and the object returned by the
16
+ # function call will be passed as an argument to the block.
17
+ #
18
+ # RubyPython::PyMain.dir("dir") { |a| a.rubify.map { |e| e.to_sym } }
19
+ # # => [:__add__, :__class__, :__contains__, … ]
20
+ class PyMainClass < RubyPython::BlankObject
21
+ include Singleton
22
+
23
+ # Returns a proxy object wrapping the \Python <tt>__main__</tt> namespace.
24
+ def main
25
+ @main ||= RubyPython.import "__main__"
26
+ end
27
+
28
+ # Returns a proxy object wrapping the \Python <tt>__builtin__</tt>
29
+ # namespace.
30
+ def builtin
31
+ @builtin ||= RubyPython.import "__builtin__"
32
+ end
33
+
34
+ # Delegates any method calls on this object to the \Python
35
+ # <tt>__main__</tt> or <tt>__builtin__</tt> namespaces, in that order. If
36
+ # a block is provided, the result of calling the \Python method will be
37
+ # yielded as an argument to the block.
38
+ #
39
+ # [name] The name of the \Python method or function to call.
40
+ # [args] The arguments to pass to the \Python method.
41
+ # [block] A block to execute with the result of calling the \Python
42
+ # method. If a block is provided, the result of the block is returned,
43
+ # not the result of the \Python method.
44
+ def method_missing(name, *args, &block)
45
+ proxy = if main.respond_to?(name)
46
+ main
47
+ elsif builtin.respond_to?(name)
48
+ builtin
49
+ else
50
+ super(name, *args)
51
+ end
52
+ result = if proxy.is_real_method?(name)
53
+ proxy.__send__(name, *args)
54
+ else
55
+ proxy.__send__(:method_missing, name, *args)
56
+ end
57
+
58
+ if block
59
+ block.call(result)
60
+ else
61
+ result
62
+ end
63
+ end
64
+
65
+ # Called by RubyPython when the interpreter is started or stopped so
66
+ # that the neccesary preparation or cleanup can be done. For internal
67
+ # use only.
68
+ def python_interpreter_update(status)
69
+ case status
70
+ when :stop
71
+ @main = nil
72
+ @builtin = nil
73
+ end
74
+ end
75
+ private :python_interpreter_update
76
+ end
77
+
78
+ # The accessible instance of PyMainClass.
79
+ PyMain = RubyPython::PyMainClass.instance
80
+ end