pycall 0.1.0.alpha.20170224b → 0.1.0.alpha.20170226

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d2a6e3735f767731679b29028417f1c65fd29a34
4
- data.tar.gz: 479fa94df217c1db443950c73e5457fd910a0568
3
+ metadata.gz: ab504049d683e34fa1e325340601d6577a40cd5e
4
+ data.tar.gz: c477cf5937dd0499e50512a4829ad3688d8e34e5
5
5
  SHA512:
6
- metadata.gz: e14d7ebbd21f597a9d9b439532b30a5466d46df36af207ad07151e839ecb5e768eca30dac5c85a717b612facea30a6ad89094bfc168501cd70117e3af443162d
7
- data.tar.gz: 616be33cc87bfae9291dd6ebccb875a41c0c33b97e2a1255d14a9250b3a50540449b37e3e132136171aaa8ad586893367f812dccf43c2a8b73808cbf2fbff718
6
+ metadata.gz: 041fda79cb71ccb7653e442c1831f97b489058adb48159cef581d49174182350047e736192eb5568c6d2c4b61d6e2691e917ccb28f578c2dd5b340d90dca41d3
7
+ data.tar.gz: eb6af8382a0531729aa8ac151d0880e1c7c613441550490fad77e924b26012723833b5ea1aaab75e6ef9a9f1d9d4e99e416ac4c244c155f7c5a2f7b42c4c5d3c
@@ -2,8 +2,6 @@ require 'pycall/import'
2
2
  include PyCall::Import
3
3
 
4
4
  pyimport 'numpy', as: :np
5
- pyimport 'matplotlib.pyplot', as: :plt
6
- pyimport 'matplotlib.colors', as: :mplc
7
5
  pyfrom 'sklearn.cross_validation', import: :train_test_split
8
6
  pyfrom 'sklearn.preprocessing', import: :StandardScaler
9
7
  pyfrom 'sklearn.datasets', import: %i(make_moons make_circles make_classification)
@@ -14,6 +12,13 @@ pyfrom 'sklearn.ensemble', import: %i(RandomForestClassifier AdaBoostClassifier)
14
12
  pyfrom 'sklearn.naive_bayes', import: :GaussianNB
15
13
  pyfrom 'sklearn.discriminant_analysis', import: %i(LinearDiscriminantAnalysis QuadraticDiscriminantAnalysis)
16
14
 
15
+ # FIXME: MacOSX backend is not usable through pycall. I want to fix this issue but the reason is unclear.
16
+ pyimport 'matplotlib', as: :mp
17
+ mp.rcParams[:backend] = 'TkAgg' if mp.rcParams[:backend] == 'MacOSX'
18
+
19
+ pyimport 'matplotlib.pyplot', as: :plt
20
+ pyimport 'matplotlib.colors', as: :mplc
21
+
17
22
  h = 0.02 # step size in the mesh
18
23
 
19
24
  names = [
data/examples/hist.rb CHANGED
@@ -2,6 +2,11 @@ require 'pycall/import'
2
2
  include PyCall::Import
3
3
 
4
4
  pyimport 'numpy', as: 'np'
5
+
6
+ # FIXME: MacOSX backend is not usable through pycall. I want to fix this issue but the reason is unclear.
7
+ pyimport 'matplotlib', as: :mp
8
+ mp.rcParams[:backend] = 'TkAgg' if mp.rcParams[:backend] == 'MacOSX'
9
+
5
10
  pyimport 'matplotlib.mlab', as: 'mlab'
6
11
  pyimport 'matplotlib.pyplot', as: 'plt'
7
12
 
@@ -3,6 +3,11 @@ require 'pycall/import'
3
3
  include PyCall::Import
4
4
 
5
5
  pyimport 'numpy', as: 'np'
6
+
7
+ # FIXME: MacOSX backend is not usable through pycall. I want to fix this issue but the reason is unclear.
8
+ pyimport 'matplotlib', as: :mp
9
+ mp.rcParams[:backend] = 'TkAgg' if mp.rcParams[:backend] == 'MacOSX'
10
+
6
11
  pyimport 'matplotlib.pyplot', as: 'plt'
7
12
 
8
13
  pyfrom 'sklearn.datasets', import: 'fetch_olivetti_faces'
@@ -3,6 +3,11 @@ include PyCall::Import
3
3
 
4
4
  require 'benchmark'
5
5
  pyimport :pandas, as: :pd
6
+
7
+ # FIXME: MacOSX backend is not usable through pycall. I want to fix this issue but the reason is unclear.
8
+ pyimport 'matplotlib', as: :mp
9
+ mp.rcParams[:backend] = 'TkAgg' if mp.rcParams[:backend] == 'MacOSX'
10
+
6
11
  pyimport :seaborn, as: :sns
7
12
  pyimport 'matplotlib.pyplot', as: :plt
8
13
 
@@ -1,5 +1,41 @@
1
1
  module PyCall
2
2
  module Conversions
3
+ @python_type_map = []
4
+
5
+ class TypePair < Struct.new(:pytype, :rbtype)
6
+ def to_a
7
+ [pytype, rbtype]
8
+ end
9
+ end
10
+
11
+ def self.python_type_mapping(pytype, rbtype)
12
+ @python_type_map.each_with_index do |type_pair, index|
13
+ next unless pytype == type_pair.pytype
14
+ type_pair.rbtype = rbtype
15
+ return
16
+ end
17
+ @python_type_map << TypePair.new(pytype, rbtype)
18
+ end
19
+
20
+ def self.to_ruby(pyobj)
21
+ unless pyobj.kind_of? PyObject
22
+ raise
23
+ end
24
+ @python_type_map.each do |tp|
25
+ pytype, rbtype = tp.to_a
26
+ next unless pyobj.kind_of?(pytype)
27
+ case
28
+ when rbtype.kind_of?(Proc)
29
+ return rbtype.(pyobj)
30
+ when rbtype.respond_to?(:from_python)
31
+ return rbtype.from_python(pyobj)
32
+ else
33
+ return rbtype.new(pyobj)
34
+ end
35
+ end
36
+ pyobj
37
+ end
38
+
3
39
  def self.from_ruby(obj)
4
40
  case obj
5
41
  when PyObject
@@ -102,7 +138,7 @@ module PyCall
102
138
  return Conversions.convert_to_string(py_str_ptr).force_encoding(Encoding::UTF_8)
103
139
 
104
140
  when LibPython.PyList_Type
105
- return Conversions.convert_to_array(self)
141
+ return PyCall::List.new(self)
106
142
 
107
143
  when LibPython.PyTuple_Type
108
144
  return Conversions.convert_to_tuple(self)
@@ -114,7 +150,7 @@ module PyCall
114
150
  return PyCall::Set.new(self)
115
151
  end
116
152
 
117
- self
153
+ Conversions.to_ruby(self)
118
154
  end
119
155
  end
120
156
  end
data/lib/pycall/dict.rb CHANGED
@@ -68,7 +68,10 @@ module PyCall
68
68
  end
69
69
 
70
70
  def has_key?(key)
71
- 1 == LibPython.PyDict_Contains(__pyobj__, key).to_ruby
71
+ key = Conversions.from_ruby(key)
72
+ value = LibPython.PyDict_Contains(__pyobj__, key)
73
+ raise PyError.fetch if value == -1
74
+ 1 == value
72
75
  end
73
76
 
74
77
  def default=(val)
data/lib/pycall/eval.rb CHANGED
@@ -7,6 +7,7 @@ module PyCall
7
7
  locals_ptr = maindict_ptr
8
8
  defer_sigint do
9
9
  py_code_ptr = LibPython.Py_CompileString(str, filename, Py_eval_input)
10
+ raise PyError.fetch if py_code_ptr.null?
10
11
  LibPython.PyEval_EvalCode(py_code_ptr, globals_ptr, locals_ptr)
11
12
  end
12
13
  end
@@ -14,8 +15,12 @@ module PyCall
14
15
  class << self
15
16
  private
16
17
 
18
+ def main_module
19
+ @main_module ||= PyCall.import_module("__main__")
20
+ end
21
+
17
22
  def maindict_ptr
18
- LibPython.PyModule_GetDict(PyCall.import_module("__main__"))
23
+ @maindict_ptr ||= LibPython.PyModule_GetDict(main_module)
19
24
  end
20
25
 
21
26
  def defer_sigint
@@ -0,0 +1,40 @@
1
+ require 'pycall'
2
+ require 'iruby'
3
+
4
+ module PyCall
5
+ module IRubyHelper
6
+ private
7
+
8
+ def check_pyobject_respond_to_format_method(obj, method_name)
9
+ return false unless obj.kind_of? PyObject
10
+ return false unless PyCall.hasattr?(obj, method_name)
11
+ PyCall.getattr(obj, method_name).kind_of? PyCall::LibPython.PyMethod_Type
12
+ end
13
+
14
+ def register_pyobject_formatter(format_name, mime, priority_value=0)
15
+ method_name = :"_repr_#{format_name}_"
16
+ match do |obj|
17
+ check_pyobject_respond_to_format_method(obj, method_name)
18
+ end
19
+ priority priority_value
20
+ format mime do |obj|
21
+ PyCall.getattr(obj, method_name).()
22
+ end
23
+ end
24
+ end
25
+ end
26
+
27
+ ::IRuby::Display::Registry.module_eval do
28
+ extend PyCall::IRubyHelper
29
+
30
+ register_pyobject_formatter :html, 'text/html'
31
+ register_pyobject_formatter :markdown, 'text/markdown'
32
+ register_pyobject_formatter :svg, 'image/svg+xml'
33
+ register_pyobject_formatter :png, 'image/png'
34
+ register_pyobject_formatter :jpeg, 'image/jpeg'
35
+ register_pyobject_formatter :latex, 'text/latex'
36
+ register_pyobject_formatter :json, 'application/json'
37
+ register_pyobject_formatter :javascript, 'application/javascript'
38
+ register_pyobject_formatter :pdf, 'application/pdf'
39
+ register_pyobject_formatter :pretty, 'text/plain', -1000
40
+ end
@@ -129,6 +129,7 @@ module PyCall
129
129
  attach_variable :PySet_Type, PyTypeObject
130
130
 
131
131
  attach_variable :PyFunction_Type, PyTypeObject
132
+ attach_variable :PyMethod_Type, PyTypeObject
132
133
 
133
134
  # --- functions ---
134
135
 
@@ -146,8 +147,11 @@ module PyCall
146
147
  attach_function :PyObject_SetItem, [PyObject.by_ref, PyObject.by_ref, PyObject.by_ref], :int
147
148
  attach_function :PyObject_DelItem, [PyObject.by_ref, PyObject.by_ref], :int
148
149
  attach_function :PyObject_Call, [PyObject.by_ref, PyObject.by_ref, PyObject.by_ref], PyObject.by_ref
149
- attach_function :PyObject_IsInstance, [PyObject.by_ref, PyTypeObject.by_ref], :int
150
+ attach_function :PyObject_IsInstance, [PyObject.by_ref, PyObject.by_ref], :int
150
151
  attach_function :PyObject_Dir, [PyObject.by_ref], PyObject.by_ref
152
+ attach_function :PyObject_Repr, [PyObject.by_ref], PyObject.by_ref
153
+ attach_function :PyObject_Str, [PyObject.by_ref], PyObject.by_ref
154
+ attach_function :PyObject_Type, [PyObject.by_ref], PyTypeObject.by_ref
151
155
 
152
156
  # Bool
153
157
 
@@ -237,6 +241,7 @@ module PyCall
237
241
 
238
242
  attach_function :PySequence_Size, [PyObject.by_ref], :ssize_t
239
243
  attach_function :PySequence_GetItem, [PyObject.by_ref, :ssize_t], PyObject.by_ref
244
+ attach_function :PySequence_Contains, [PyObject.by_ref, PyObject.by_ref], :int
240
245
 
241
246
  # Dict
242
247
 
@@ -282,6 +287,7 @@ module PyCall
282
287
 
283
288
  # Error
284
289
 
290
+ attach_function :PyErr_Clear, [], :void
285
291
  attach_function :PyErr_Print, [], :void
286
292
  attach_function :PyErr_Occurred, [], PyObject.by_ref
287
293
  attach_function :PyErr_Fetch, [:pointer, :pointer, :pointer], :void
data/lib/pycall/list.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  module PyCall
2
2
  class List
3
3
  include PyObjectWrapper
4
+ include Enumerable
4
5
 
5
6
  def self.new(init=nil)
6
7
  case init
@@ -47,7 +48,28 @@ module PyCall
47
48
 
48
49
  def include?(value)
49
50
  value = Conversions.from_ruby(value)
50
- LibPython.PyList_Contains(__pyobj__, value).to_ruby
51
+ value = LibPython.PySequence_Contains(__pyobj__, value)
52
+ raise PyError.fetch if value == -1
53
+ 1 == value
54
+ end
55
+
56
+ def ==(other)
57
+ case other
58
+ when Array
59
+ self.to_a == other
60
+ else
61
+ super
62
+ end
63
+ end
64
+
65
+ def each
66
+ return enum_for unless block_given?
67
+ i, n = 0, size
68
+ while i < n
69
+ yield self[i]
70
+ i += 1
71
+ end
72
+ self
51
73
  end
52
74
 
53
75
  def to_a
@@ -17,9 +17,19 @@ module PyCall
17
17
  @type = type
18
18
  @value = value
19
19
  @traceback = traceback
20
- super("#{@type.inspect}: #{PyCall.eval('str').(@value)}")
20
+ super("Error occurred in Python")
21
21
  end
22
22
 
23
23
  attr_reader :type, :value, :traceback
24
+
25
+ def message
26
+ "#{PyObject.new(type.to_ptr)}: #{value}".tap do |msg|
27
+ unless traceback.null?
28
+ if (o = PyCall.format_traceback(traceback))
29
+ msg.concat("\n", *o)
30
+ end
31
+ end
32
+ end
33
+ end
24
34
  end
25
35
  end
@@ -39,7 +39,7 @@ module PyCall
39
39
 
40
40
  def kind_of?(klass)
41
41
  case klass
42
- when PyTypeObject
42
+ when PyObject, PyTypeObject
43
43
  Types.pyisinstance(self, klass)
44
44
  else
45
45
  super
@@ -122,7 +122,16 @@ module PyCall
122
122
  end
123
123
 
124
124
  def to_s
125
- PyCall.str(self)
125
+ s = LibPython.PyObject_Repr(self)
126
+ if s.null?
127
+ LibPython.PyErr_Clear()
128
+ s = LibPython.PyObject_Str(self)
129
+ if s.null?
130
+ LibPython.PyErr_Clear()
131
+ return super
132
+ end
133
+ end
134
+ s.to_ruby
126
135
  end
127
136
 
128
137
  alias inspect to_s
@@ -1,7 +1,8 @@
1
1
  module PyCall
2
2
  module PyObjectWrapper
3
- def initialize(pyobj, pytype)
3
+ def initialize(pyobj, pytype=nil)
4
4
  check_type pyobj, pytype
5
+ pytype ||= LibPython.PyObject_Type(pyobj)
5
6
  @__pyobj__ = pyobj
6
7
  end
7
8
 
@@ -41,7 +42,8 @@ module PyCall
41
42
  private
42
43
 
43
44
  def check_type(pyobj, pytype)
44
- return if pyobj.kind_of?(PyObject) && pyobj.kind_of?(pytype)
45
+ return if pyobj.kind_of?(PyObject)
46
+ return if pytype.nil? || pyobj.kind_of?(pytype)
45
47
  raise TypeError, "the argument must be a PyObject of #{pytype}"
46
48
  end
47
49
  end
data/lib/pycall/types.rb CHANGED
@@ -2,8 +2,8 @@ module PyCall
2
2
  module Types
3
3
  def self.pyisinstance(pyobj, pytype)
4
4
  check_pyobject(pyobj)
5
- pyobj_ptr = pyobj # TODO: fix after introducing PyObject class
6
- LibPython.PyObject_IsInstance(pyobj_ptr, pytype) == 1
5
+ pytype = PyObject.new(pytype.to_ptr) if pytype.kind_of?(PyTypeObject)
6
+ LibPython.PyObject_IsInstance(pyobj, pytype) == 1
7
7
  end
8
8
 
9
9
  class << self
data/lib/pycall/utils.rb CHANGED
@@ -33,6 +33,11 @@ module PyCall
33
33
  @type ||= PyCall.eval('type')
34
34
  @type.(pyobj)
35
35
  end
36
+
37
+ def format_traceback(pyobj)
38
+ @format_tb ||= import_module('traceback').format_tb
39
+ @format_tb.(pyobj)
40
+ end
36
41
  end
37
42
 
38
43
  extend Utils
@@ -1,3 +1,3 @@
1
1
  module PyCall
2
- VERSION = "0.1.0.alpha.20170224b"
2
+ VERSION = "0.1.0.alpha.20170226"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pycall
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0.alpha.20170224b
4
+ version: 0.1.0.alpha.20170226
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kenta Murata
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-02-24 00:00:00.000000000 Z
11
+ date: 2017-02-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ffi
@@ -96,6 +96,7 @@ files:
96
96
  - lib/pycall/eval.rb
97
97
  - lib/pycall/import.rb
98
98
  - lib/pycall/init.rb
99
+ - lib/pycall/iruby_helper.rb
99
100
  - lib/pycall/libpython.rb
100
101
  - lib/pycall/list.rb
101
102
  - lib/pycall/pyerror.rb