lokeshh_rubypython 0.7

Sign up to get free protection for your applications and to get access to all the features.
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