rubypython-raspi 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
@@ -0,0 +1,10 @@
1
+ module RubyPython
2
+ # A subclass of ::Array that will convert to a Python Tuple automatically.
3
+ class Tuple < ::Array
4
+ def self.tuple(array)
5
+ value = self.new
6
+ value.replace(array.dup)
7
+ value
8
+ end
9
+ end
10
+ 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.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