rubypython 0.3.2 → 0.5.0
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.
- data/.autotest +3 -0
- data/.gemtest +0 -0
- data/.gitignore +13 -0
- data/.hgignore +14 -0
- data/.hgtags +7 -0
- data/.rspec +1 -1
- data/Contributors.rdoc +9 -0
- data/History.rdoc +148 -0
- data/{License.txt → License.rdoc} +7 -1
- data/Manifest.txt +15 -10
- data/PostInstall.txt +11 -4
- data/README.rdoc +272 -0
- data/Rakefile +107 -22
- data/autotest/discover.rb +1 -0
- data/lib/rubypython.rb +214 -120
- data/lib/rubypython/blankobject.rb +16 -14
- data/lib/rubypython/conversion.rb +242 -173
- data/lib/rubypython/legacy.rb +30 -31
- data/lib/rubypython/macros.rb +43 -34
- data/lib/rubypython/operators.rb +103 -101
- data/lib/rubypython/options.rb +41 -44
- data/lib/rubypython/pygenerator.rb +61 -0
- data/lib/rubypython/pymainclass.rb +46 -29
- data/lib/rubypython/pyobject.rb +193 -177
- data/lib/rubypython/python.rb +189 -176
- data/lib/rubypython/pythonerror.rb +54 -63
- data/lib/rubypython/pythonexec.rb +123 -0
- data/lib/rubypython/rubypyproxy.rb +213 -137
- data/lib/rubypython/type.rb +20 -0
- data/spec/basic_spec.rb +50 -0
- data/spec/callback_spec.rb +7 -17
- data/spec/conversion_spec.rb +7 -21
- data/spec/legacy_spec.rb +1 -16
- data/spec/pymainclass_spec.rb +6 -15
- data/spec/pyobject_spec.rb +39 -64
- data/spec/python_helpers/basics.py +20 -0
- data/spec/python_helpers/objects.py +24 -20
- data/spec/pythonerror_spec.rb +5 -17
- data/spec/refcnt_spec.rb +4 -10
- data/spec/rubypyclass_spec.rb +1 -11
- data/spec/rubypyproxy_spec.rb +45 -54
- data/spec/rubypython_spec.rb +45 -57
- data/spec/spec_helper.rb +49 -33
- metadata +87 -63
- data.tar.gz.sig +0 -0
- data/History.markdown +0 -97
- data/README.markdown +0 -105
- data/lib/rubypython/core_ext/string.rb +0 -7
- data/lib/rubypython/version.rb +0 -9
- data/spec/python_helpers/objects.pyc +0 -0
- metadata.gz.sig +0 -0
data/Rakefile
CHANGED
@@ -1,22 +1,107 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
1
|
+
# -*- ruby encoding: utf-8 -*-
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'hoe'
|
5
|
+
|
6
|
+
Hoe.plugin :doofus
|
7
|
+
Hoe.plugin :gemspec
|
8
|
+
Hoe.plugin :git
|
9
|
+
Hoe.plugin :hg
|
10
|
+
|
11
|
+
Hoe.spec 'rubypython' do |spec|
|
12
|
+
spec.rubyforge_name = spec.name
|
13
|
+
|
14
|
+
developer('Steeve Morin', 'swiuzzz+rubypython@gmail.com')
|
15
|
+
developer('Austin Ziegler', 'austin@rubyforge.org')
|
16
|
+
developer('Zach Raines', 'raineszm+rubypython@gmail.com')
|
17
|
+
|
18
|
+
spec.remote_rdoc_dir = 'rdoc'
|
19
|
+
spec.rsync_args << ' --exclude=statsvn/'
|
20
|
+
|
21
|
+
spec.history_file = 'History.rdoc'
|
22
|
+
spec.readme_file = 'README.rdoc'
|
23
|
+
spec.extra_rdoc_files = FileList["*.rdoc"].to_a
|
24
|
+
|
25
|
+
spec.extra_deps << ['ffi', '~> 1.0.7']
|
26
|
+
spec.extra_deps << ['blankslate', '>= 2.1.2.3']
|
27
|
+
|
28
|
+
spec.extra_dev_deps << ['rspec', '~> 2.0']
|
29
|
+
spec.extra_dev_deps << ['tilt', '~> 1.0']
|
30
|
+
|
31
|
+
spec.spec_extras[:requirements] = [ "Python, ~> 2.4" ]
|
32
|
+
end
|
33
|
+
|
34
|
+
namespace :website do
|
35
|
+
desc "Build the website files."
|
36
|
+
task :build => [ "website/index.html" ]
|
37
|
+
|
38
|
+
deps = FileList["website/**/*"].exclude { |f| File.directory? f }
|
39
|
+
deps.include(*%w(Rakefile))
|
40
|
+
deps.include(*FileList["*.rdoc"].to_a)
|
41
|
+
deps.exclude(*%w(website/index.html website/images/*))
|
42
|
+
|
43
|
+
file "website/index.html" => deps do |t|
|
44
|
+
require 'tilt'
|
45
|
+
require 'rubypython'
|
46
|
+
|
47
|
+
puts "Generating #{t.name}…"
|
48
|
+
|
49
|
+
# Let's modify the rdoc for presenation purposes.
|
50
|
+
body_rdoc = File.read("README.rdoc")
|
51
|
+
|
52
|
+
contrib = File.read("Contributors.rdoc")
|
53
|
+
body_rdoc.gsub!(/^:include: Contributors.rdoc/, contrib)
|
54
|
+
|
55
|
+
license = File.read("License.rdoc")
|
56
|
+
body_rdoc.sub!(/^:include: License.rdoc/, license)
|
57
|
+
toc_elements = body_rdoc.scan(/^(=+) (.*)$/)
|
58
|
+
toc_elements.map! { |e| [ e[0].count('='), e[1] ] }
|
59
|
+
body_rdoc.gsub!(/^(=.*)/) { "#{$1.downcase}" }
|
60
|
+
body = Tilt::RDocTemplate.new(nil) { body_rdoc }.render
|
61
|
+
|
62
|
+
title = nil
|
63
|
+
body.gsub!(%r{<h1>(.*)</h1>}) { title = $1; "" }
|
64
|
+
|
65
|
+
toc_elements = toc_elements.select { |e| e[0].between?(2, 3) }
|
66
|
+
|
67
|
+
last_level = 0
|
68
|
+
toc = ""
|
69
|
+
|
70
|
+
toc_elements.each do |element|
|
71
|
+
level, text = *element
|
72
|
+
ltext = text.downcase
|
73
|
+
id = text.downcase.gsub(/[^a-z]+/, '-')
|
74
|
+
|
75
|
+
body.gsub!(%r{<h#{level}>#{ltext}</h#{level}>}) {
|
76
|
+
%Q(<h#{level} id="#{id}">#{ltext}</h#{level}>)
|
77
|
+
}
|
78
|
+
|
79
|
+
if last_level != level
|
80
|
+
if level > last_level
|
81
|
+
toc << "<ol>"
|
82
|
+
else
|
83
|
+
toc << "</li></ol></li>"
|
84
|
+
end
|
85
|
+
|
86
|
+
last_level = level
|
87
|
+
end
|
88
|
+
|
89
|
+
toc << %Q(<li><a href="##{id}">#{text}</a>)
|
90
|
+
end
|
91
|
+
toc << "</li></ol>"
|
92
|
+
|
93
|
+
template = Tilt.new("website/index.rhtml", :trim => "<>%")
|
94
|
+
context = {
|
95
|
+
:title => title,
|
96
|
+
:toc => toc,
|
97
|
+
:body => body,
|
98
|
+
:download => "http://rubyforge.org/frs/?group_id=6737",
|
99
|
+
:version => RubyPython::VERSION,
|
100
|
+
:modified => Time.now
|
101
|
+
}
|
102
|
+
File.open(t.name, "w") { |f| f.write template.render(self, context) } end
|
103
|
+
end
|
104
|
+
|
105
|
+
task "docs" => "website:build"
|
106
|
+
|
107
|
+
# vim: syntax=ruby
|
@@ -0,0 +1 @@
|
|
1
|
+
Autotest.add_discovery { "rspec2" }
|
data/lib/rubypython.rb
CHANGED
@@ -1,176 +1,270 @@
|
|
1
|
-
|
1
|
+
# RubyPython is a bridge between the Ruby and \Python interpreters. It
|
2
|
+
# embeds a \Python interpreter in the Ruby application's process using FFI
|
3
|
+
# and provides a means for wrapping, converting, and calling \Python objects
|
4
|
+
# and methods.
|
5
|
+
#
|
6
|
+
# == Usage
|
7
|
+
# The \Python interpreter must be started before the RubyPython bridge is
|
8
|
+
# functional. The user can either manually manage the running of the
|
9
|
+
# interpreter as shown below, or use the +RubyPython.run+ or
|
10
|
+
# +RubyPython.session+ methods to automatically start and stop the
|
11
|
+
# interpreter.
|
12
|
+
#
|
13
|
+
# RubyPython.start
|
14
|
+
# cPickle = RubyPython.import "cPickle"
|
15
|
+
# puts cPickle.dumps("RubyPython is awesome!").rubify
|
16
|
+
# RubyPython.stop
|
17
|
+
module RubyPython
|
18
|
+
VERSION = '0.5.0' #:nodoc:
|
19
|
+
|
20
|
+
# Do not load the FFI interface by default. Wait until the user asks for
|
21
|
+
# it.
|
22
|
+
@load_ffi = false
|
23
|
+
|
24
|
+
# Indicates whether the \Python DLL has been loaded. For internal use
|
25
|
+
# only.
|
26
|
+
def self.load_ffi? #:nodoc:
|
27
|
+
@load_ffi
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
require 'rubypython/blankobject'
|
2
32
|
require 'rubypython/options'
|
3
33
|
require 'rubypython/python'
|
4
34
|
require 'rubypython/pythonerror'
|
5
35
|
require 'rubypython/pyobject'
|
6
36
|
require 'rubypython/rubypyproxy'
|
7
37
|
require 'rubypython/pymainclass'
|
38
|
+
require 'rubypython/pygenerator'
|
8
39
|
|
9
|
-
|
10
|
-
#This module provides the direct user interface for the RubyPython extension.
|
11
|
-
#
|
12
|
-
#RubyPython interfaces to the Python C API via the {Python} module using the
|
13
|
-
#Ruby FFI gem. However, the end user should only worry about dealing with the
|
14
|
-
#methods made avaiable via the RubyPython module.
|
15
|
-
#
|
16
|
-
#Usage
|
17
|
-
#-----
|
18
|
-
#It is important to remember that the Python Interpreter must be
|
19
|
-
#started before the bridge is functional. This will start the embedded
|
20
|
-
#interpreter. If this approach is used, the user should remember to call
|
21
|
-
#RubyPython.stop when they are finished with Python.
|
22
|
-
#@example
|
23
|
-
# RubyPython.start
|
24
|
-
# cPickle = RubyPython.import "cPickle"
|
25
|
-
# puts cPickle.dumps("RubyPython is awesome!").rubify
|
26
|
-
# RubyPython.stop
|
27
|
-
#
|
28
|
-
#Legacy Mode vs Normal Mode
|
29
|
-
#---------------------------
|
30
|
-
#By default RubyPython always returns a proxy class which refers method calls to
|
31
|
-
#the wrapped Python object. If you instead would like RubyPython to aggressively
|
32
|
-
#attempt conversion of return values, as it did in RubyPython 0.2.x, then you
|
33
|
-
#should set {RubyPython.legacy_mode} to true. In this case RubyPython will
|
34
|
-
#attempt to convert any return value from Python to a native Ruby type, and only
|
35
|
-
#return a proxy if conversion is not possible. For further examples see
|
36
|
-
#{RubyPython.legacy_mode}.
|
37
40
|
module RubyPython
|
38
|
-
|
39
|
-
|
40
41
|
class << self
|
41
|
-
|
42
|
-
#
|
43
|
-
#
|
44
|
-
#
|
45
|
-
#
|
46
|
-
#
|
47
|
-
#
|
48
|
-
#
|
49
|
-
|
50
|
-
|
51
|
-
#
|
52
|
-
#
|
53
|
-
#
|
54
|
-
#
|
55
|
-
#
|
56
|
-
#
|
57
|
-
#
|
58
|
-
|
59
|
-
#
|
60
|
-
#
|
61
|
-
#
|
62
|
-
#
|
63
|
-
#
|
64
|
-
#
|
42
|
+
# Controls whether RubyPython is operating in <em>Normal Mode</em> or
|
43
|
+
# <em>Legacy Mode</em>.
|
44
|
+
#
|
45
|
+
# === Normal Mode
|
46
|
+
# By default, +legacy_mode+ is +false+, meaning that any object returned
|
47
|
+
# from a \Python function call will be wrapped in an instance of
|
48
|
+
# +RubyPyProxy+ or one of its subclasses. This allows \Python method
|
49
|
+
# calls to be forwarded to the \Python object, even if it would otherwise
|
50
|
+
# be a native Ruby object.
|
51
|
+
#
|
52
|
+
# RubyPython.session do
|
53
|
+
# string = RubyPython.import 'string'
|
54
|
+
# ascii_letters = string.ascii_letters
|
55
|
+
# puts ascii_letters.isalpha # => True
|
56
|
+
# puts ascii_letters.rubify.isalpha # throws NoMethodError
|
57
|
+
# end
|
58
|
+
#
|
59
|
+
# === Legacy Mode
|
60
|
+
# If +legacy_mode+ is +true+, RubyPython automatically tries to convert
|
61
|
+
# returned objects to native Ruby object types. If there is no such
|
62
|
+
# conversion, the object remains wrapped in +RubyPyProxy+. This
|
63
|
+
# behaviour is the same as RubyPython 0.2 and earlier. This mode is not
|
64
|
+
# recommended and may be phased out for RubyPython 1.0.
|
65
|
+
#
|
66
|
+
# RubyPython.legacy_mode = true
|
67
|
+
# RubyPython.session do
|
68
|
+
# string = RubyPython.import 'string'
|
69
|
+
# ascii_letters = string.ascii_letters
|
70
|
+
# puts ascii_letters.isalpha # throws NoMethodError
|
71
|
+
# end
|
65
72
|
attr_accessor :legacy_mode
|
66
73
|
|
67
|
-
#Starts
|
68
|
-
#
|
69
|
-
#
|
70
|
-
#
|
71
|
-
|
72
|
-
#
|
73
|
-
|
74
|
-
|
75
|
-
|
74
|
+
# Starts the \Python interpreter. Either +RubyPython.start+,
|
75
|
+
# +RubyPython.session+, or +RubyPython.run+ must be run before using any
|
76
|
+
# \Python code. Returns +true+ if the interpreter was started; +false+
|
77
|
+
# otherwise.
|
78
|
+
#
|
79
|
+
# [options] Configures the interpreter prior to starting it. Principally
|
80
|
+
# used to provide an alternative \Python interpreter to start.
|
81
|
+
#
|
82
|
+
# With no options provided:
|
83
|
+
# RubyPython.start
|
84
|
+
# sys = RubyPython.import 'sys'
|
85
|
+
# p sys.version # => "2.6.6"
|
86
|
+
# RubyPython.stop
|
87
|
+
#
|
88
|
+
# With an alternative \Python executable:
|
89
|
+
# RubyPython.start(:python_exe => 'python2.7')
|
90
|
+
# sys = RubyPython.import 'sys'
|
91
|
+
# p sys.version # => "2.7.1"
|
92
|
+
# RubyPython.stop
|
93
|
+
#
|
94
|
+
# *NOTE*: In the current version of RubyPython, it _is_ possible to
|
95
|
+
# change \Python interpreters in a single Ruby process execution, but it
|
96
|
+
# is *strongly* discouraged as this may lead to segmentation faults.
|
97
|
+
# This feature is highly experimental and may be disabled in the future.
|
98
|
+
def start(options = {})
|
99
|
+
RubyPython.configure(options)
|
100
|
+
|
101
|
+
unless @load_ffi
|
102
|
+
@load_ffi = true
|
103
|
+
@reload = false
|
76
104
|
reload_library
|
77
105
|
end
|
78
|
-
|
79
|
-
|
80
|
-
|
106
|
+
|
107
|
+
return false if RubyPython::Python.Py_IsInitialized != 0
|
108
|
+
|
81
109
|
if @reload
|
82
110
|
reload_library
|
83
111
|
@reload = false
|
84
112
|
end
|
85
|
-
|
113
|
+
|
114
|
+
RubyPython::Python.Py_Initialize
|
86
115
|
notify :start
|
87
116
|
true
|
88
117
|
end
|
89
118
|
|
90
|
-
#Stops the Python interpreter if it is running. Returns true if the
|
91
|
-
#intepreter is stopped
|
92
|
-
#
|
93
|
-
|
94
|
-
# and false otherwise
|
119
|
+
# Stops the \Python interpreter if it is running. Returns +true+ if the
|
120
|
+
# intepreter is stopped. All wrapped \Python objects are invalid after
|
121
|
+
# invocation of this method. If you need the values within the \Python
|
122
|
+
# proxy objects, be sure to call +RubyPyProxy#rubify+ on them.
|
95
123
|
def stop
|
96
|
-
if Python.Py_IsInitialized !=0
|
124
|
+
if defined? Python.Py_IsInitialized and Python.Py_IsInitialized != 0
|
97
125
|
Python.Py_Finalize
|
98
126
|
notify :stop
|
99
|
-
|
127
|
+
true
|
128
|
+
else
|
129
|
+
false
|
100
130
|
end
|
101
|
-
false
|
102
131
|
end
|
103
132
|
|
104
|
-
#Import a Python module into the interpreter and return a proxy object
|
105
|
-
#for it.
|
106
|
-
|
107
|
-
|
108
|
-
#
|
133
|
+
# Import a \Python module into the interpreter and return a proxy object
|
134
|
+
# for it.
|
135
|
+
#
|
136
|
+
# This is the preferred way to gain access to \Python objects.
|
137
|
+
#
|
138
|
+
# [mod_name] The name of the module to import.
|
109
139
|
def import(mod_name)
|
110
|
-
|
111
|
-
|
112
|
-
raise PythonError.handle_error
|
140
|
+
if defined? Python.Py_IsInitialized and Python.Py_IsInitialized != 0
|
141
|
+
pModule = Python.PyImport_ImportModule mod_name
|
142
|
+
raise PythonError.handle_error if PythonError.error?
|
143
|
+
pymod = PyObject.new pModule
|
144
|
+
RubyPyModule.new(pymod)
|
145
|
+
else
|
146
|
+
raise "Python has not been started."
|
113
147
|
end
|
114
|
-
pymod = PyObject.new pModule
|
115
|
-
RubyPyModule.new(pymod)
|
116
148
|
end
|
117
149
|
|
118
|
-
#
|
119
|
-
#
|
120
|
-
#
|
121
|
-
#
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
150
|
+
# Starts the \Python interpreter (optionally with options) and +yields+
|
151
|
+
# to the provided block. When the block exits for any reason, the
|
152
|
+
# \Python interpreter is stopped automatically.
|
153
|
+
#
|
154
|
+
# The last executed expression of the block is returned. Be careful that
|
155
|
+
# the last expression of the block does not return a RubyPyProxy object,
|
156
|
+
# because the proxy object will be invalidated when the interpreter is
|
157
|
+
# stopped.
|
158
|
+
#
|
159
|
+
# [options] Configures the interpreter prior to starting it. Principally
|
160
|
+
# used to provide an alternative \Python interpreter to start.
|
161
|
+
#
|
162
|
+
# *NOTE*: In the current version of RubyPython, it _is_ possible to change
|
163
|
+
# \Python interpreters in a single Ruby process execution, but it is
|
164
|
+
# *strongly* discouraged as this may lead to segmentation faults. This
|
165
|
+
# feature is highly experimental and may be disabled in the future.
|
166
|
+
#
|
167
|
+
# :call-seq:
|
168
|
+
# session(options = {}) { block to execute }
|
169
|
+
def session(options = {})
|
170
|
+
start(options)
|
171
|
+
yield
|
172
|
+
ensure
|
127
173
|
stop
|
128
|
-
result
|
129
174
|
end
|
130
175
|
|
131
|
-
#
|
132
|
-
#
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
176
|
+
# Starts the \Python interpreter (optionally with options) and executes
|
177
|
+
# the provided block in the RubyPython module scope. When the block
|
178
|
+
# exits for any reason, the \Python interpreter is stopped
|
179
|
+
# automatically.
|
180
|
+
#
|
181
|
+
# The last executed expression of the block is returned. Be careful that
|
182
|
+
# the last expression of the block does not return a RubyPyProxy object,
|
183
|
+
# because the proxy object will be invalidated when the interpreter is
|
184
|
+
# stopped.
|
185
|
+
#
|
186
|
+
# [options] Configures the interpreter prior to starting it. Principally
|
187
|
+
# used to provide an alternative \Python interpreter to start.
|
188
|
+
#
|
189
|
+
# *NOTE*: In the current version of RubyPython, it _is_ possible to
|
190
|
+
# change \Python interpreters in a single Ruby process execution, but it
|
191
|
+
# is *strongly* discouraged as this may lead to segmentation faults.
|
192
|
+
# This feature is highly experimental and may be disabled in the future.
|
193
|
+
#
|
194
|
+
# :call-seq:
|
195
|
+
# run(options = {}) { block to execute in RubyPython context }
|
196
|
+
def run(options = {}, &block)
|
197
|
+
start(options)
|
198
|
+
module_eval(&block)
|
199
|
+
ensure
|
137
200
|
stop
|
201
|
+
end
|
202
|
+
|
203
|
+
# Starts the \Python interpreter for a
|
204
|
+
# {virtualenv}[http://pypi.python.org/pypi/virtualenv] virtual
|
205
|
+
# environment. Returns +true+ if the interpreter was started.
|
206
|
+
#
|
207
|
+
# [virtualenv] The root path to the virtualenv-installed \Python
|
208
|
+
# interpreter.
|
209
|
+
#
|
210
|
+
# RubyPython.start_from_virtualenv('/path/to/virtualenv')
|
211
|
+
# sys = RubyPython.import 'sys'
|
212
|
+
# p sys.version # => "2.7.1"
|
213
|
+
# RubyPython.stop
|
214
|
+
#
|
215
|
+
# *NOTE*: In the current version of RubyPython, it _is_ possible to
|
216
|
+
# change \Python interpreters in a single Ruby process execution, but it
|
217
|
+
# is *strongly* discouraged as this may lead to segmentation faults.
|
218
|
+
# This feature is highly experimental and may be disabled in the future.
|
219
|
+
def start_from_virtualenv(virtualenv)
|
220
|
+
result = start(:python => File.join(virtualenv, "bin", "python"))
|
221
|
+
activate
|
138
222
|
result
|
139
223
|
end
|
140
224
|
|
141
|
-
|
225
|
+
# Returns an object describing the currently active Python interpreter.
|
226
|
+
def python
|
227
|
+
RubyPython::Python::EXEC
|
228
|
+
end
|
229
|
+
|
230
|
+
# Used to activate the virtualenv.
|
231
|
+
def activate
|
232
|
+
imp = import("imp")
|
233
|
+
imp.load_source("activate_this",
|
234
|
+
File.join(File.dirname(RubyPython::Python::EXEC.python),
|
235
|
+
"activate_this.py"))
|
236
|
+
end
|
237
|
+
private :activate
|
142
238
|
|
143
239
|
def add_observer(object)
|
144
240
|
@observers ||= []
|
145
241
|
@observers << object
|
146
242
|
true
|
147
243
|
end
|
244
|
+
private :add_observer
|
148
245
|
|
149
246
|
def notify(status)
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
247
|
+
@observers ||= []
|
248
|
+
@observers.each do |o|
|
249
|
+
next if nil === o
|
250
|
+
o.update status
|
154
251
|
end
|
155
252
|
end
|
253
|
+
private :notify
|
156
254
|
|
157
255
|
def reload_library
|
256
|
+
# Invalidate the current Python instance, if defined.
|
257
|
+
if defined? RubyPython::Python::EXEC and RubyPython::Python::EXEC
|
258
|
+
RubyPython::Python::EXEC.instance_eval { invalidate! }
|
259
|
+
end
|
158
260
|
remove_const :Python
|
159
|
-
load
|
261
|
+
load RubyPython::PYTHON_RB
|
160
262
|
true
|
161
263
|
end
|
162
|
-
|
163
|
-
end
|
164
|
-
|
165
|
-
[
|
166
|
-
PyMain,
|
167
|
-
Operators,
|
168
|
-
PyObject::AutoPyPointer
|
169
|
-
].each do |observer|
|
170
|
-
add_observer observer
|
264
|
+
private :reload_library
|
171
265
|
end
|
172
266
|
|
173
|
-
|
267
|
+
add_observer PyMain
|
268
|
+
add_observer Operators
|
269
|
+
add_observer PyObject::AutoPyPointer
|
174
270
|
end
|
175
|
-
|
176
|
-
|