rubypython-raspi 0.1.1 → 0.1.2
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/lib/rubypython/interpreter.rb +248 -0
- data/lib/rubypython/tuple.rb +10 -0
- metadata +3 -1
|
@@ -0,0 +1,248 @@
|
|
|
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
|
+
rc, @python = runpy "import sys; print sys.executable"
|
|
44
|
+
if rc.exitstatus.nonzero?
|
|
45
|
+
raise RubyPython::InvalidInterpreter, "An invalid interpreter was specified."
|
|
46
|
+
end
|
|
47
|
+
rc, @version = runpy "import sys; print '%d.%d' % sys.version_info[:2]"
|
|
48
|
+
rc, @sys_prefix = runpy "import sys; print sys.prefix"
|
|
49
|
+
|
|
50
|
+
if FFI::Platform.windows?
|
|
51
|
+
flat_version = @version.tr('.', '')
|
|
52
|
+
basename = File.basename(@python, '.exe')
|
|
53
|
+
|
|
54
|
+
if basename =~ /(?:#{@version}|#{flat_version})$/
|
|
55
|
+
@version_name = basename
|
|
56
|
+
else
|
|
57
|
+
@version_name = "#{basename}#{flat_version}"
|
|
58
|
+
end
|
|
59
|
+
else
|
|
60
|
+
basename = File.basename(@python)
|
|
61
|
+
|
|
62
|
+
if basename =~ /#{@version}/
|
|
63
|
+
@version_name = basename
|
|
64
|
+
else
|
|
65
|
+
@version_name = "#{basename}#{@version}"
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
@library = find_python_lib
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def find_python_lib
|
|
73
|
+
# By default, the library name will be something like
|
|
74
|
+
# libpython2.6.so, but that won't always work.
|
|
75
|
+
@libbase = "#{FFI::Platform::LIBPREFIX}#{@version_name}"
|
|
76
|
+
@libext = FFI::Platform::LIBSUFFIX
|
|
77
|
+
@libname = "#{@libbase}.#{@libext}"
|
|
78
|
+
|
|
79
|
+
# We may need to look in multiple locations for Python, so let's
|
|
80
|
+
# build this as an array.
|
|
81
|
+
@locations = [ File.join(@sys_prefix, "lib", @libname) ]
|
|
82
|
+
|
|
83
|
+
if FFI::Platform.mac?
|
|
84
|
+
# On the Mac, let's add a special case that has even a different
|
|
85
|
+
# @libname. This may not be fully useful on future versions of OS
|
|
86
|
+
# X, but it should work on 10.5 and 10.6. Even if it doesn't, the
|
|
87
|
+
# next step will (/usr/lib/libpython<version>.dylib is a symlink
|
|
88
|
+
# to the correct location).
|
|
89
|
+
@locations << File.join(@sys_prefix, "Python")
|
|
90
|
+
# Let's also look in the location that was originally set in this
|
|
91
|
+
# library:
|
|
92
|
+
File.join(@sys_prefix, "lib", "#{@realname}", "config", @libname)
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
if FFI::Platform.unix?
|
|
96
|
+
# On Unixes, let's look in some standard alternative places, too.
|
|
97
|
+
# Just in case. Some Unixes don't include a .so symlink when they
|
|
98
|
+
# should, so let's look for the base case of .so.1, too.
|
|
99
|
+
[ @libname, "#{@libname}.1" ].each do |name|
|
|
100
|
+
@locations << File.join("/opt/local/lib", name)
|
|
101
|
+
@locations << File.join("/opt/lib", name)
|
|
102
|
+
@locations << File.join("/usr/local/lib", name)
|
|
103
|
+
@locations << File.join("/usr/lib", name)
|
|
104
|
+
@locations << File.join("/opt/local/lib64", name)
|
|
105
|
+
@locations << File.join("/opt/lib64", name)
|
|
106
|
+
@locations << File.join("/usr/local/lib64", name)
|
|
107
|
+
@locations << File.join("/usr/lib64", name)
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
if FFI::Platform.windows?
|
|
112
|
+
# On Windows, the appropriate DLL is usually be found in
|
|
113
|
+
# %SYSTEMROOT%\system or %SYSTEMROOT%\system32; as a fallback we'll
|
|
114
|
+
# use C:\Windows\system{,32} as well as the install directory and the
|
|
115
|
+
# install directory + libs.
|
|
116
|
+
system_root = File.expand_path(ENV['SYSTEMROOT']).gsub(/\\/, '/')
|
|
117
|
+
@locations << File.join(system_root, 'system', @libname)
|
|
118
|
+
@locations << File.join(system_root, 'system32', @libname)
|
|
119
|
+
@locations << File.join("C:/WINDOWS", "System", @libname)
|
|
120
|
+
@locations << File.join("C:/WINDOWS", "System32", @libname)
|
|
121
|
+
@locations << File.join(sys_prefix, @libname)
|
|
122
|
+
@locations << File.join(sys_prefix, 'libs', @libname)
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
# Let's add alternative extensions; again, just in case.
|
|
126
|
+
@locations.dup.each do |location|
|
|
127
|
+
path = File.dirname(location)
|
|
128
|
+
base = File.basename(location, ".#{@libext}")
|
|
129
|
+
@locations << File.join(path, "#{base}.so") # Standard Unix
|
|
130
|
+
@locations << File.join(path, "#{base}.dylib") # Mac OS X
|
|
131
|
+
@locations << File.join(path, "#{base}.dll") # Windows
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
# Remove redundant locations
|
|
135
|
+
@locations.uniq!
|
|
136
|
+
|
|
137
|
+
library = nil
|
|
138
|
+
|
|
139
|
+
@locations.each do |location|
|
|
140
|
+
if File.exists? location
|
|
141
|
+
library = location
|
|
142
|
+
break
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
library
|
|
147
|
+
end
|
|
148
|
+
private :find_python_lib
|
|
149
|
+
|
|
150
|
+
def valid?
|
|
151
|
+
if @python.nil? or @python.empty?
|
|
152
|
+
false
|
|
153
|
+
elsif @library.nil? or @library.empty?
|
|
154
|
+
false
|
|
155
|
+
else
|
|
156
|
+
true
|
|
157
|
+
end
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
##
|
|
161
|
+
# The name of the \Python executable that is used. This is the value of
|
|
162
|
+
# 'sys.executable' for the \Python interpreter provided in
|
|
163
|
+
# <tt>:python_exe</tt> or 'python' if it is not provided.
|
|
164
|
+
#
|
|
165
|
+
# On Mac OS X Lion (10.7), this value is '/usr/bin/python' for 'python'.
|
|
166
|
+
attr_reader :python
|
|
167
|
+
##
|
|
168
|
+
# The version of the \Python interpreter. This is a decimalized version of
|
|
169
|
+
# 'sys.version_info[:2]' (such that \Python 2.7.1 is reported as '2.7').
|
|
170
|
+
attr_reader :version
|
|
171
|
+
##
|
|
172
|
+
# The system prefix for the \Python interpreter. This is the value of
|
|
173
|
+
# 'sys.prefix'.
|
|
174
|
+
attr_reader :sys_prefix
|
|
175
|
+
##
|
|
176
|
+
# The basename of the \Python interpreter with a version number. This is
|
|
177
|
+
# mostly an intermediate value used to find the shared \Python library,
|
|
178
|
+
# but /usr/bin/python is often a link to /usr/bin/python2.7 so it may be
|
|
179
|
+
# of value. Note that this does *not* include the full path to the
|
|
180
|
+
# interpreter.
|
|
181
|
+
attr_reader :version_name
|
|
182
|
+
|
|
183
|
+
# The \Python library.
|
|
184
|
+
attr_reader :library
|
|
185
|
+
|
|
186
|
+
# Run a Python command-line command.
|
|
187
|
+
def runpy(command)
|
|
188
|
+
i = @python || @python_exe || 'python'
|
|
189
|
+
if FFI::Platform.windows?
|
|
190
|
+
o = %x(#{i} -c "#{command}" 2> NUL:)
|
|
191
|
+
else
|
|
192
|
+
o = %x(#{i} -c "#{command}" 2> /dev/null)
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
[ $?, o.chomp ]
|
|
196
|
+
end
|
|
197
|
+
private :runpy
|
|
198
|
+
|
|
199
|
+
def inspect(debug = false)
|
|
200
|
+
if debug
|
|
201
|
+
debug_s
|
|
202
|
+
elsif @python
|
|
203
|
+
"#<#{self.class}: #{python} v#{version} #{sys_prefix} #{version_name}>"
|
|
204
|
+
else
|
|
205
|
+
"#<#{self.class}: invalid interpreter>"
|
|
206
|
+
end
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
def debug_s(format = nil)
|
|
210
|
+
system = ""
|
|
211
|
+
system << "windows " if FFI::Platform.windows?
|
|
212
|
+
system << "mac " if FFI::Platform.mac?
|
|
213
|
+
system << "unix " if FFI::Platform.unix?
|
|
214
|
+
system << "unknown " if system.empty?
|
|
215
|
+
|
|
216
|
+
case format
|
|
217
|
+
when :report
|
|
218
|
+
s = <<-EOS
|
|
219
|
+
python_exe: #{@python_exe}
|
|
220
|
+
python: #{@python}
|
|
221
|
+
version: #{@version}
|
|
222
|
+
sys_prefix: #{@sys_prefix}
|
|
223
|
+
version_name: #{@version_name}
|
|
224
|
+
platform: #{system.chomp}
|
|
225
|
+
library: #{@library.inspect}
|
|
226
|
+
libbase: #{@libbase}
|
|
227
|
+
libext: #{@libext}
|
|
228
|
+
libname: #{@libname}
|
|
229
|
+
locations: #{@locations.inspect}
|
|
230
|
+
EOS
|
|
231
|
+
else
|
|
232
|
+
s = "#<#{self.class}: "
|
|
233
|
+
s << "python_exe=#{@python_exe.inspect} "
|
|
234
|
+
s << "python=#{@python.inspect} "
|
|
235
|
+
s << "version=#{@version.inspect} "
|
|
236
|
+
s << "sys_prefix=#{@sys_prefix.inspect} "
|
|
237
|
+
s << "version_name=#{@version_name.inspect} "
|
|
238
|
+
s << system
|
|
239
|
+
s << "library=#{@library.inspect} "
|
|
240
|
+
s << "libbase=#{@libbase.inspect} "
|
|
241
|
+
s << "libext=#{@libext.inspect} "
|
|
242
|
+
s << "libname=#{@libname.inspect} "
|
|
243
|
+
s << "locations=#{@locations.inspect}"
|
|
244
|
+
end
|
|
245
|
+
|
|
246
|
+
s
|
|
247
|
+
end
|
|
248
|
+
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: rubypython-raspi
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.2
|
|
5
5
|
prerelease:
|
|
6
6
|
platform: ruby
|
|
7
7
|
authors:
|
|
@@ -145,6 +145,7 @@ files:
|
|
|
145
145
|
- lib/rubypython.rb
|
|
146
146
|
- lib/rubypython/blankobject.rb
|
|
147
147
|
- lib/rubypython/conversion.rb
|
|
148
|
+
- lib/rubypython/interpreter.rb
|
|
148
149
|
- lib/rubypython/legacy.rb
|
|
149
150
|
- lib/rubypython/macros.rb
|
|
150
151
|
- lib/rubypython/operators.rb
|
|
@@ -155,6 +156,7 @@ files:
|
|
|
155
156
|
- lib/rubypython/pythonerror.rb
|
|
156
157
|
- lib/rubypython/rubypyproxy.rb
|
|
157
158
|
- lib/rubypython/type.rb
|
|
159
|
+
- lib/rubypython/tuple.rb
|
|
158
160
|
- spec/basic_spec.rb
|
|
159
161
|
- spec/callback_spec.rb
|
|
160
162
|
- spec/conversion_spec.rb
|