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.
@@ -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