rubypython-raspi 0.1.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.
@@ -0,0 +1,18 @@
1
+ require 'rubypython'
2
+
3
+ # A quick way to activate <em>Legacy Mode</em> for a project. Requiring
4
+ # +'rubypython/legacy' automatically activates +RubyPython.legacy_mode+ on
5
+ # the project. This mode is deprecated and will be removed.
6
+ module RubyPython::LegacyMode
7
+ # Enables +RubyPython.legacy_mode+.
8
+ def self.setup_legacy
9
+ RubyPython.legacy_mode = true
10
+ end
11
+
12
+ # Disables +RubyPython.legacy_mode+.
13
+ def self.teardown_legacy
14
+ RubyPython.legacy_mode = false
15
+ end
16
+ end
17
+
18
+ RubyPython::LegacyMode.setup_legacy
@@ -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,124 @@
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. The result of the
13
+ # operation will follow the conversion rules appropriate to the current
14
+ # mode of operation as set by {RubyPython.legacy_mode}.
15
+ # [rname] The name of the Ruby method for this operation. Can be either a
16
+ # Symbol or a String.
17
+ # [pname] The name of the \Python magic method to which this method should
18
+ # be delegated.
19
+ def self.bin_op(rname, pname)
20
+ define_method rname.to_sym do |other|
21
+ self.__send__(pname, other)
22
+ end
23
+ end
24
+
25
+ # Creates a method to delegate a relational operator. The result of the
26
+ # delegated method will always be converted to a Ruby type so that simple
27
+ # boolean testing may occur. These methods are implemented with calls the
28
+ # _operator_ module.
29
+ #
30
+ # [rname] The name of the Ruby method for this operation. Can be a Symbol
31
+ # or a String.
32
+ # [pname] The name of the \Python magic method to which this method should
33
+ # be delegated.
34
+ def self.rel_op(rname, pname)
35
+ define_method rname.to_sym do |other|
36
+ RubyPython::Operators.operator_.__send__(pname, self, other).rubify
37
+ end
38
+ end
39
+
40
+ # Creates a method to delegate a relational operator. The result of the
41
+ # operation will follow the conversion rules appropriate to the current
42
+ # mode of operation as set by {RubyPython.legacy_mode}. These methods are
43
+ # implemented with calls the _operator_ module.
44
+ # [rname] The name of the Ruby method for this operation. Can be a Symbol
45
+ # or a String.
46
+ # [pname] The name of the \Python magic method to which this method should
47
+ # be delegated.
48
+ def self.unary_op(rname, pname)
49
+ define_method rname.to_sym do
50
+ RubyPython::Operators.operator_.__send__(pname, self)
51
+ end
52
+ end
53
+
54
+ [
55
+ [:+, '__add__'],
56
+ [:-, '__sub__'],
57
+ [:*, '__mul__'],
58
+ [:/, '__div__'],
59
+ [:&, '__and__'],
60
+ [:^, '__xor__'],
61
+ [:%, '__mod__'],
62
+ [:**, '__pow__'],
63
+ [:>>, '__rshift__'],
64
+ [:<<, '__lshift__'],
65
+ [:|, '__or__']
66
+ ].each do |args|
67
+ bin_op *args
68
+ end
69
+
70
+ [
71
+ [:~, :__invert__],
72
+ [:+@, :__pos__],
73
+ [:-@, :__neg__]
74
+ ].each do |args|
75
+ unary_op *args
76
+ end
77
+
78
+ [
79
+ [:==, 'eq'],
80
+ [:<, 'lt'],
81
+ [:<=, 'le'],
82
+ [:>, 'gt'],
83
+ [:>=, 'ge'],
84
+ [:equal?, 'is_']
85
+ ].each do |args|
86
+ rel_op *args
87
+ end
88
+
89
+ # Delegates object indexed access to the wrapped \Python object.
90
+ def [](index)
91
+ self.__getitem__ index
92
+ end
93
+
94
+ # Delegates setting of various indices to the wrapped \Python object.
95
+ def []=(index, value)
96
+ self.__setitem__ index, value
97
+ end
98
+
99
+ # Delegates membership testing to \Python.
100
+ def include?(item)
101
+ self.__contains__(item).rubify
102
+ end
103
+
104
+ # Delegates Comparison to \Python.
105
+ def <=>(other)
106
+ RubyPython::PyMain.cmp(self, other)
107
+ end
108
+
109
+ class << self
110
+ # Called by RubyPython when the interpreter is started or stopped so
111
+ # that the necessary preparation or cleanup can be done. For internal
112
+ # use only.
113
+ def python_interpreter_update(status)
114
+ case status
115
+ when :stop
116
+ @@operator = nil
117
+ end
118
+ end
119
+ private :python_interpreter_update
120
+ end
121
+
122
+ # Aliases eql? to == for Python objects.
123
+ alias_method :eql?, :==
124
+ 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
@@ -0,0 +1,232 @@
1
+ require 'rubypython/python'
2
+ require 'rubypython/macros'
3
+ require 'rubypython/conversion'
4
+ require 'ffi'
5
+
6
+ # This object is an opaque wrapper around the C Py…Object types used by the
7
+ # \Python C API.
8
+ #
9
+ # This class is *only* for RubyPython internal use.
10
+ class RubyPython::PyObject # :nodoc: all
11
+ # This class wraps C <tt>Py…Object</tt>s so that the RubyPython::Python
12
+ # reference count is automatically decreased when the Ruby object
13
+ # referencing them goes out of scope.
14
+ class AutoPyPointer < FFI::AutoPointer # :nodoc:
15
+ class << self
16
+ # Keeps track of which objects are associated with the currently
17
+ # running RubyPython::Python interpreter, so that RubyPython knows not
18
+ # to try to decrease the reference counts of the others when garbage
19
+ # collecting.
20
+ attr_accessor :current_pointers
21
+
22
+ # When used along with the FFI Library method is executed whenever a
23
+ # pointer is garbage collected so that cleanup can be done. In our
24
+ # case we decrease the reference count of the held pointer as long as
25
+ # the object is still good. There is really no reason the end-user
26
+ # would need to the use this method directly.
27
+ def release(pointer)
28
+ obj_id = pointer.object_id
29
+ deleted = @current_pointers.delete(obj_id)
30
+ if deleted and (RubyPython::Python.Py_IsInitialized != 0)
31
+ RubyPython::Python.Py_DecRef pointer
32
+ end
33
+ end
34
+
35
+ # Called by RubyPython when the interpreter is started or stopped so
36
+ # that the necessary preparation or cleanup can be done. For internal
37
+ # use only.
38
+ def python_interpreter_update(status)
39
+ case status
40
+ when :stop
41
+ current_pointers.clear
42
+ end
43
+ end
44
+ private :python_interpreter_update
45
+ end
46
+
47
+ self.current_pointers = {}
48
+ end
49
+
50
+ # The AutoPyPointer object which represents the RubyPython::Python
51
+ # Py…Object.
52
+ attr_reader :pointer
53
+
54
+ # [rObject] FFI Pointer objects passed into the constructor are wrapped in
55
+ # an AutoPyPointer and assigned to the +#pointer+ attribute. Other objects
56
+ # are converted, if possible, from their Ruby types to their \Python types
57
+ # and wrapped in an AutoPyPointer. The conversion is done with
58
+ # +RubyPython::Conversion.rtopObject+.
59
+ def initialize(rObject)
60
+ if rObject.kind_of? FFI::AutoPointer
61
+ new_pointer = FFI::Pointer.new rObject
62
+ @pointer = AutoPyPointer.new new_pointer
63
+ xIncref
64
+ elsif rObject.kind_of? FFI::Pointer
65
+ @pointer = AutoPyPointer.new rObject
66
+ else
67
+ @pointer = AutoPyPointer.new RubyPython::Conversion.rtopObject(rObject)
68
+ end
69
+ AutoPyPointer.current_pointers[@pointer.object_id] = true
70
+ end
71
+
72
+ # Attempts to convert the wrapped object to a native ruby type. Returns
73
+ # either the Ruby object or the unmodified \Python object.
74
+ def rubify
75
+ RubyPython::Conversion.ptorObject @pointer
76
+ end
77
+
78
+ # Tests whether the wrapped \Python object has a given attribute. Returns
79
+ # +true+ if the attribute exists.
80
+ # [attrName] The name of the attribute to look up.
81
+ def hasAttr(attrName)
82
+ RubyPython::Python.PyObject_HasAttrString(@pointer, attrName) == 1
83
+ end
84
+
85
+ # Retrieves an object from the wrapped \Python object.
86
+ # [attrName] The name of the attribute to fetch.
87
+ def getAttr(attrName)
88
+ pyAttr = RubyPython::Python.PyObject_GetAttrString(@pointer, attrName)
89
+ self.class.new pyAttr
90
+ end
91
+
92
+ # Sets an attribute of the wrapped \Python object. Returns +true+ if the
93
+ # attribute was successfully set.
94
+ # [attrName] The name of the attribute to set.
95
+ # [rbPyAttr] A PyObject wrapper around the value that we wish to set the
96
+ # attribute to.
97
+ def setAttr(attrName, rbPyAttr)
98
+ RubyPython::Python.PyObject_SetAttrString(@pointer, attrName, rbPyAttr.pointer) != -1
99
+ end
100
+
101
+ # Calls the wrapped \Python object with the supplied arguments and keyword
102
+ # arguments. Returns a PyObject wrapper around the returned object, which
103
+ # may be +NULL+.
104
+ # [rbPyArgs] A PyObject wrapping a Tuple of the supplied arguments.
105
+ # [rbPyKeywords] A PyObject wrapping a Dict of keyword arguments.
106
+ def callObjectKeywords(rbPyArgs, rbPyKeywords)
107
+ pyReturn = RubyPython::Python.PyObject_Call(@pointer, rbPyArgs.pointer, rbPyKeywords.pointer)
108
+ self.class.new pyReturn
109
+ end
110
+
111
+ # Calls the wrapped \Python object with the supplied arguments. Returns a
112
+ # PyObject wrapper around the returned object, which may be +NULL+.
113
+ # [rbPyArgs] A PyObject wrapping a Tuple of the supplied arguments.
114
+ def callObject(rbPyArgs)
115
+ pyReturn = RubyPython::Python.PyObject_CallObject(@pointer, rbPyArgs.pointer)
116
+ self.class.new pyReturn
117
+ end
118
+
119
+ # Decrease the reference count of the wrapped object.
120
+ def xDecref
121
+ AutoPyPointer.release(@pointer)
122
+ @pointer.free
123
+ nil
124
+ end
125
+
126
+ # Increase the reference count of the wrapped object
127
+ def xIncref
128
+ RubyPython::Python.Py_IncRef @pointer
129
+ nil
130
+ end
131
+
132
+ # Tests whether the wrapped object is +NULL+.
133
+ def null?
134
+ @pointer.null?
135
+ end
136
+
137
+ # Performs a compare on two Python objects. Returns a value similar to
138
+ # that of the spaceship operator (<=>).
139
+ def cmp(other)
140
+ RubyPython::Python.PyObject_Compare @pointer, other.pointer
141
+ end
142
+
143
+ # Tests whether the wrapped object is a function or a method. This is not
144
+ # the same as #callable? as many other \Python objects are callable.
145
+ def function_or_method?
146
+ check = RubyPython::Macros.PyObject_TypeCheck(@pointer, [
147
+ RubyPython::Python.PyFunction_Type.to_ptr,
148
+ RubyPython::Python.PyCFunction_Type.to_ptr,
149
+ RubyPython::Python.PyMethod_Type.to_ptr
150
+ ])
151
+ check != 0
152
+ end
153
+
154
+ # Is the wrapped object callable?
155
+ def callable?
156
+ RubyPython::Python.PyCallable_Check(@pointer) != 0
157
+ end
158
+
159
+ # Returns the 'directory' of the RubyPython::Python object; similar to #methods in
160
+ # Ruby.
161
+ def dir
162
+ return self.class.new(RubyPython::Python.PyObject_Dir(@pointer)).rubify.map do |x|
163
+ x.to_sym
164
+ end
165
+ end
166
+
167
+ # Tests whether the wrapped object is a RubyPython::Python class (both new
168
+ # and old style).
169
+ def class?
170
+ check = RubyPython::Macros.PyObject_TypeCheck(@pointer, [
171
+ RubyPython::Python.PyClass_Type.to_ptr,
172
+ RubyPython::Python.PyType_Type.to_ptr
173
+ ])
174
+ check != 0
175
+ end
176
+
177
+ # Manipulates the supplied PyObject instance such that it is suitable to
178
+ # passed to #callObject or #callObjectKeywords. If +rbObject+ is a tuple
179
+ # then the argument passed in is returned. If it is a list then the list
180
+ # is converted to a tuple. Otherwise returns a tuple with one element:
181
+ # +rbObject+.
182
+ # [rbObject] The argument to be turned into a Tuple.
183
+ def self.makeTuple(rbObject)
184
+ pTuple = nil
185
+
186
+ if RubyPython::Macros.PyObject_TypeCheck(rbObject.pointer, RubyPython::Python.PyList_Type.to_ptr) != 0
187
+ pTuple = RubyPython::Python.PySequence_Tuple(rbObject.pointer)
188
+ elsif RubyPython::Macros.PyObject_TypeCheck(rbObject.pointer, RubyPython::Python.PyTuple_Type.to_ptr) != 0
189
+ pTuple = rbObject.pointer
190
+ else
191
+ pTuple = RubyPython::Python.PyTuple_Pack(1, :pointer, rbObject.pointer)
192
+ end
193
+
194
+ self.new pTuple
195
+ end
196
+
197
+ # Wraps up the supplied arguments in a \Python List.
198
+ def self.newList(*args)
199
+ rbList = self.new RubyPython::Python.PyList_New(args.length)
200
+
201
+ args.each_with_index do |el, i|
202
+ el.xIncref # PyList_SetItem steals references!
203
+ RubyPython::Python.PyList_SetItem rbList.pointer, i, el.pointer
204
+ end
205
+
206
+ rbList
207
+ end
208
+
209
+ # Converts the supplied arguments to PyObject instances.
210
+ def self.convert(*args)
211
+ args.map do |arg|
212
+ if arg.kind_of? RubyPython::PyObject
213
+ arg
214
+ elsif arg.kind_of? RubyPython::RubyPyProxy
215
+ arg.pObject
216
+ else
217
+ RubyPython::PyObject.new arg
218
+ end
219
+ end
220
+ end
221
+
222
+ # Takes an array of wrapped \Python objects and wraps them in a Tuple such
223
+ # that they may be passed to #callObject.
224
+ # [args] An array of PyObjects; the arguments to be inserted into the
225
+ # Tuple.
226
+ def self.buildArgTuple(*args)
227
+ pList = newList(*args)
228
+ pTuple = makeTuple(pList)
229
+ pList.xDecref
230
+ pTuple
231
+ end
232
+ end