rubypython 0.3.2 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. data/.autotest +3 -0
  2. data/.gemtest +0 -0
  3. data/.gitignore +13 -0
  4. data/.hgignore +14 -0
  5. data/.hgtags +7 -0
  6. data/.rspec +1 -1
  7. data/Contributors.rdoc +9 -0
  8. data/History.rdoc +148 -0
  9. data/{License.txt → License.rdoc} +7 -1
  10. data/Manifest.txt +15 -10
  11. data/PostInstall.txt +11 -4
  12. data/README.rdoc +272 -0
  13. data/Rakefile +107 -22
  14. data/autotest/discover.rb +1 -0
  15. data/lib/rubypython.rb +214 -120
  16. data/lib/rubypython/blankobject.rb +16 -14
  17. data/lib/rubypython/conversion.rb +242 -173
  18. data/lib/rubypython/legacy.rb +30 -31
  19. data/lib/rubypython/macros.rb +43 -34
  20. data/lib/rubypython/operators.rb +103 -101
  21. data/lib/rubypython/options.rb +41 -44
  22. data/lib/rubypython/pygenerator.rb +61 -0
  23. data/lib/rubypython/pymainclass.rb +46 -29
  24. data/lib/rubypython/pyobject.rb +193 -177
  25. data/lib/rubypython/python.rb +189 -176
  26. data/lib/rubypython/pythonerror.rb +54 -63
  27. data/lib/rubypython/pythonexec.rb +123 -0
  28. data/lib/rubypython/rubypyproxy.rb +213 -137
  29. data/lib/rubypython/type.rb +20 -0
  30. data/spec/basic_spec.rb +50 -0
  31. data/spec/callback_spec.rb +7 -17
  32. data/spec/conversion_spec.rb +7 -21
  33. data/spec/legacy_spec.rb +1 -16
  34. data/spec/pymainclass_spec.rb +6 -15
  35. data/spec/pyobject_spec.rb +39 -64
  36. data/spec/python_helpers/basics.py +20 -0
  37. data/spec/python_helpers/objects.py +24 -20
  38. data/spec/pythonerror_spec.rb +5 -17
  39. data/spec/refcnt_spec.rb +4 -10
  40. data/spec/rubypyclass_spec.rb +1 -11
  41. data/spec/rubypyproxy_spec.rb +45 -54
  42. data/spec/rubypython_spec.rb +45 -57
  43. data/spec/spec_helper.rb +49 -33
  44. metadata +87 -63
  45. data.tar.gz.sig +0 -0
  46. data/History.markdown +0 -97
  47. data/README.markdown +0 -105
  48. data/lib/rubypython/core_ext/string.rb +0 -7
  49. data/lib/rubypython/version.rb +0 -9
  50. data/spec/python_helpers/objects.pyc +0 -0
  51. metadata.gz.sig +0 -0
@@ -1,39 +1,38 @@
1
1
  require 'rubypython'
2
2
 
3
- #A quick way to activate legacy mode for your project. Requiring
4
- #'rubypython/legacy' automatically activates legacy_mode as described
5
- #in the documentation for {RubyPython}. If you wish to run your
6
- #project in legacy mode you can require 'rubypython/legacy' instead of
7
- #'rubypython'
3
+ # A quick way to active <em>Legacy Mode</em> for a project. Requiring
4
+ # +'rubypython/legacy' automatically activates +RubyPython.legacy_mode+ on
5
+ # the project.
8
6
  #
9
- #@example Default Behavior
10
- # irb(main):001:0> require 'rubypython'
11
- # => true
12
- # irb(main):002:0> RubyPython.start
13
- # => true
14
- # irb(main):003:0> RubyPython::PyMain.float(42).is_a? RubyPython::RubyPyProxy
15
- # => true
16
- # irb(main):004:0> RubyPython.stop
17
- # => true
18
- #
19
- #@example Legacy Mode
20
- # irb(main):001:0> require 'rubypython/legacy'
21
- # => true
22
- # irb(main):002:0> RubyPython.start
23
- # => true
24
- # irb(main):003:0> RubyPython::PyMain.float(42).is_a? Float
25
- # => true
26
- # irb(main):004:0> RubyPython.stop
27
- # => true
7
+ # This mode may be phased out for RubyPython 1.0.
8
+ #
9
+ # === Default
10
+ # require 'rubypython'
11
+ #
12
+ # RubyPython.session do
13
+ # string = RubyPython.import 'string'
14
+ # ascii_letters = string.ascii_letters
15
+ # puts ascii_letters.isalpha # => True
16
+ # puts ascii_letters.rubify.isalpha # throws NoMethodError
17
+ # end
18
+ #
19
+ # === Legacy Mode
20
+ # require 'rubypython/legacy'
21
+ #
22
+ # RubyPython.session do
23
+ # string = RubyPython.import 'string'
24
+ # ascii_letters = string.ascii_letters
25
+ # puts ascii_letters.isalpha # throws NoMethodError
26
+ # end
28
27
  module RubyPython::LegacyMode
29
- class << self
30
- def setup_legacy
31
- RubyPython.legacy_mode = true
32
- end
28
+ # Enables +RubyPython.legacy_mode+.
29
+ def self.setup_legacy
30
+ RubyPython.legacy_mode = true
31
+ end
33
32
 
34
- def teardown_legacy
35
- RubyPython.legacy_mode = false
36
- end
33
+ # Disables +RubyPython.legacy_mode+.
34
+ def self.teardown_legacy
35
+ RubyPython.legacy_mode = false
37
36
  end
38
37
  end
39
38
 
@@ -1,47 +1,56 @@
1
1
  require 'ffi'
2
2
  require 'rubypython/python'
3
3
 
4
- module RubyPython
5
- #Contains Python C API macros reimplmented in Ruby. For internal use only.
6
- module Macros
7
- def self.Py_TYPE(pObjPointer)
8
- pStruct = Python::PyObjectStruct.new pObjPointer
9
- pStruct[:ob_type]
10
- end
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
11
 
12
- def self.PyObject_TypeCheck(pObject, pTypePointer)
13
- if Py_TYPE(pObject) == pTypePointer
14
- 1
15
- else
16
- 0
17
- end
18
- end
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
19
17
 
20
- def self.Py_True
21
- Python.Py_TrueStruct.to_ptr
22
- end
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)
23
22
 
24
- def self.Py_False
25
- Python.Py_ZeroStruct.to_ptr
23
+ [ pTypePointer ].flatten.each do |pointer|
24
+ return 1 if type == pointer
26
25
  end
27
26
 
28
- def self.Py_None
29
- Python.Py_NoneStruct.to_ptr
30
- end
27
+ return 0
28
+ end
31
29
 
32
- def self.Py_RETURN_FALSE
33
- Python.Py_IncRef(self.Py_False)
34
- self.Py_False
35
- end
30
+ def self.Py_True
31
+ RubyPython::Python.Py_TrueStruct.to_ptr
32
+ end
36
33
 
37
- def self.Py_RETURN_TRUE
38
- Python.Py_IncRef(self.Py_True)
39
- self.Py_True
40
- end
34
+ def self.Py_False
35
+ RubyPython::Python.Py_ZeroStruct.to_ptr
36
+ end
41
37
 
42
- def self.Py_RETURN_NONE
43
- Python.Py_IncRef(self.Py_None)
44
- self.Py_None
45
- end
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
46
55
  end
47
56
  end
@@ -1,118 +1,120 @@
1
- module RubyPython
2
- #A mixin module to provide method delegation to a proxy class. This is done
3
- #either by delegating to methods defined on the wrapped object or by using the
4
- #Python _operator_ module. A large number of the methods are dynamically
5
- #generated and so their documentation is not provided here. In general all
6
- #operators that can be overloaded are delegated.
7
- module Operators
8
- #Provides access to the Python _operator_ module.
9
- #@return[RubyPython::RubyPyModule]
10
- def self.operator_
11
- @@operator ||= RubyPython.import('operator')
12
- end
13
-
14
- #Creates a method to delegate a binary operation. The result of the
15
- #operation will follow the conversion rules appropriate to the current mode
16
- #of operation as set by {RubyPython.legacy_mode}.
17
- #@param[Symbol, String] rname The name of the Ruby method for this operation
18
- #@param[String] pname The name of the Python magic method to which this
19
- #method should be delegated.
20
- def self.bin_op rname, pname
21
- define_method rname.to_sym do |other|
22
- self.__send__ pname, other
23
- end
24
- end
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
25
11
 
26
- #Creates a method to delegate a relational operator. The result of the
27
- #delegated method will always be converted to a Ruby type so that simple
28
- #boolean testing may occur. These methods are implemented with calls the
29
- #_operator_ module.
30
- #@param[Symbol, String] rname The name of the Ruby method for this operation
31
- #@param[String] pname The name of the Python magic method to which this
32
- #method should be delegated.
33
- def self.rel_op rname, pname
34
- define_method rname.to_sym do |other|
35
- Operators.operator_.__send__(pname, self, other).rubify
36
- end
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)
37
22
  end
23
+ end
38
24
 
39
- #Creates a method to delegate a relational operator. The result of the
40
- #operation will follow the conversion rules appropriate to the current mode
41
- #of operation as set by {RubyPython.legacy_mode}. These methods are
42
- #implemented with calls the _operator_ module.
43
- #@param[Symbol, String] rname The name of the Ruby method for this operation
44
- #@param[String] pname The name of the Python magic method to which this
45
- #method should be delegated.
46
- def self.unary_op rname, pname
47
- define_method rname.to_sym do
48
- Operators.operator_.__send__(pname, self)
49
- end
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
50
37
  end
38
+ end
51
39
 
52
-
53
- [
54
- [:+, '__add__'],
55
- [:-, '__sub__'],
56
- [:*, '__mul__'],
57
- [:/, '__div__'],
58
- [:&, '__and__'],
59
- [:^, '__xor__'],
60
- [:%, '__mod__'],
61
- [:**, '__pow__'],
62
- [:>>, '__rshift__'],
63
- [:<<, '__lshift__'],
64
- [:|, '__or__']
65
- ].each do |args|
66
- bin_op *args
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)
67
51
  end
52
+ end
68
53
 
69
- [
70
- [:~, :__invert__],
71
- [:+@, :__pos__],
72
- [:-@, :__neg__]
73
- ].each do |args|
74
- unary_op *args
75
- end
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
76
69
 
77
- [
78
- [:==, 'eq'],
79
- [:<, 'lt'],
80
- [:<=, 'le'],
81
- [:>, 'gt'],
82
- [:>=, 'ge'],
83
- [:equal?, 'is_']
84
- ].each do |args|
85
- rel_op *args
86
- end
70
+ [
71
+ [:~, :__invert__],
72
+ [:+@, :__pos__],
73
+ [:-@, :__neg__]
74
+ ].each do |args|
75
+ unary_op *args
76
+ end
87
77
 
88
- alias :eql? :==
78
+ [
79
+ [:==, 'eq'],
80
+ [:<, 'lt'],
81
+ [:<=, 'le'],
82
+ [:>, 'gt'],
83
+ [:>=, 'ge'],
84
+ [:equal?, 'is_']
85
+ ].each do |args|
86
+ rel_op *args
87
+ end
89
88
 
90
- #Delegates object indexed access to the wrapped Python object.
91
- def [](index)
92
- self.__getitem__ index
93
- end
89
+ # Delegates object indexed access to the wrapped \Python object.
90
+ def [](index)
91
+ self.__getitem__ index
92
+ end
94
93
 
95
- #Delegates setting of various indices to the wrapped Python object.
96
- def []=(index, value)
97
- self.__setitem__ index, value
98
- end
94
+ # Delegates setting of various indices to the wrapped \Python object.
95
+ def []=(index, value)
96
+ self.__setitem__ index, value
97
+ end
99
98
 
100
- #Delegates membership testing to Python.
101
- def include?(item)
102
- self.__contains__(item).rubify
103
- end
99
+ # Delegates membership testing to \Python.
100
+ def include?(item)
101
+ self.__contains__(item).rubify
102
+ end
104
103
 
105
- #Delegates Comparison to Python.
106
- def <=>(other)
107
- PyMain.cmp(self, other)
108
- end
104
+ # Delegates Comparison to \Python.
105
+ def <=>(other)
106
+ RubyPython::PyMain.cmp(self, other)
107
+ end
109
108
 
110
- #For internal use only. Called by {RubyPython} when the
111
- #interpreter is started or stopped so that the neccesary
112
- #preperation or cleanup can be done.
113
- def self.update(status)
114
- @@operator = nil if status.equal? :stop
109
+ # Called by RubyPython when the interpreter is started or stopped so that the
110
+ # necessary preparation or cleanup can be done. For internal use only.
111
+ def self.update(status)
112
+ case status
113
+ when :stop
114
+ @@operator = nil
115
115
  end
116
-
117
116
  end
117
+
118
+ # Aliases eql? to == for Python objects.
119
+ alias_method :eql?, :==
118
120
  end
@@ -1,69 +1,66 @@
1
+ require 'ostruct'
2
+
1
3
  module RubyPython
2
- #A hash for storing RubyPython execution options.
4
+ # A hash for storing RubyPython execution options.
3
5
  @options = {}
4
6
 
5
- #A list of options which require the Python library to be reloaded.
6
- NEED_RELOAD = [
7
- :python_exe,
8
- :python_lib
9
- ]
7
+ # A list of options which require the \Python library to be reloaded.
8
+ NEED_RELOAD = [ :python_exe ] #:nodoc
9
+ # 20110316 AZ: This option has been removed because it isn't supported in
10
+ # the current code.
11
+ # :python_lib -> The full path to the python library you wish to load.
10
12
 
11
13
  class << self
12
- #Allows one to set options for RubyPython's execution. Parameters
13
- #may be set either by supplying a hash argument or by supplying
14
- #a block and calling setters on the provided OpenStruct.
15
- #@param [Hash] opts a hash of options to set
16
- #@option opts [String] :python_exe The python executable for
17
- # the python version you wish to use. Can be anything in your
18
- # execution path as well as a local or relative path.
19
- #@option opts [String] :python_lib The full path to the python
20
- # library you wish to load.
21
- #@return [Hash] a copy of the new options hash
14
+ # Allows one to set options for RubyPython's execution. Parameters may
15
+ # be set either by supplying a hash argument or by supplying a block and
16
+ # calling setters on the provided OpenStruct. Returns a copy of the
17
+ # updated options hash.
18
+ #
19
+ # [options] A Hash of options to set.
22
20
  #
23
- #@example
24
- # irb(main):001:0> RubyPython.run do
25
- # irb(main):002:1* RubyPython.import('sys').version.rubify.to_f
26
- # irb(main):003:1> end
27
- # => 2.7
28
- # irb(main):004:0> RubyPython.configure :python_exe => 'python2.6'
29
- # => {:python_exe=>"python2.6"}
30
- # irb(main):005:0> RubyPython.run do
31
- # irb(main):006:1* RubyPython.import('sys').version.rubify.to_f
32
- # irb(main):007:1> end
33
- # => 2.6
34
- #
35
- def configure(opts={})
36
- old_values = @options.select { |k,v| NEED_RELOAD.include? k }
21
+ # The option currently supported is:
22
+ # [:python_exe] The name of or path to the \Python executable for the
23
+ # version of \Python you wish to use.
24
+ #
25
+ # RubyPython.run do
26
+ # RubyPython.import('sys').version.rubify.to_f # => 2.7
27
+ # end
28
+ #
29
+ # RubyPython.configure :python_exe => 'python2.6'
30
+ # # => { :python_exe => "python2.6" }
31
+ # RubyPython.run do
32
+ # RubyPython.import('sys').version.rubify.to_f # => 2.6
33
+ # end
34
+ #
35
+ # The options hash can also be passed directly to +RubyPython.start+,
36
+ # +RubyPython.session+, or +RubyPython.run+.
37
+ def configure(options = {})
38
+ old_values = Hash[*@options.select { |k, v| NEED_RELOAD.include? k }]
37
39
 
38
40
  if block_given?
39
41
  ostruct = OpenStruct.new @options
40
42
  yield ostruct
41
- @options = Hash[*ostruct.instance_eval do
42
- @table.map do |k, v|
43
- [k.to_sym, v]
44
- end.flatten
45
- end]
43
+ olist = ostruct.instance_variable_get('@table').map { |k, v| [ k.to_sym, v ] }
44
+ @options = Hash[*olist]
46
45
  end
47
- @options.merge!(opts)
46
+ @options.merge!(options)
48
47
 
49
48
  @reload = true if NEED_RELOAD.any? { |k| @options[k] != old_values[k] }
50
49
  options
51
50
  end
52
51
 
53
- #Returns a copy of the hash currently being used to determine run
54
- #options. This allows the user to determine what options have been
55
- #set. Modification of options should be done via the configure
56
- #method.
57
- #@return [Hash] a copy of the current options hash
52
+ # Returns a copy of the hash currently being used to determine run
53
+ # options. This allows the user to determine what options have been set.
54
+ # Modification of options should be done via the configure method.
58
55
  def options
59
56
  @options.dup
60
57
  end
61
58
 
62
- #Reset the options hash.
63
- #@return [void]
59
+ # Reset the options hash.
60
+ # @return [void]
64
61
  def clear_options
62
+ @reload = @options.keys.any? { |k| NEED_RELOAD.include? k }
65
63
  @options.clear
66
64
  end
67
-
68
65
  end
69
66
  end