pycall 1.4.0 → 1.4.1

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
  SHA256:
3
- metadata.gz: 79fa29a4fd735c0741f03e74aadce297273cd2d64c0813b9ee2e20ad5fa321b9
4
- data.tar.gz: 108942ac4b4d45324644fe90af4e56e239f7ce3b2f27fa0d98d5defa439da8db
3
+ metadata.gz: b016b6c9b12867d113713238ecc171cc4fde8965197c79c59abf66d8bb3b252e
4
+ data.tar.gz: abb36597376d37744972f7bb537ab61032387c73947d7846b9947bb622bf04ac
5
5
  SHA512:
6
- metadata.gz: eb899c3e9c353622945df3b816df4588cd3b4606f723c53973a2f8d77d8eb9edf94b7dbcf15ff4d33f65430fd6d38a8bc2ccc2fda2a1f8f274dc769b0280e42a
7
- data.tar.gz: ff84eb82b4e10d1a2f699abd32cfcdcc6159cba6b83f2258bc4100c7229bb49ca1c7593b5a6629ef2081007728bc3be5e266b65c2967c49c043fb3dfe0bf3835
6
+ metadata.gz: 18bc020ef0c1f1d82e3796ae023170ee287bbf966c3efd12dd48f730eec585b7b70e00352d316e8e524e608c70bff0348937c1afc434ba7d6ae634223f0e1fa6
7
+ data.tar.gz: 9ea69bb090386a7a280be6a7c779b406f49a3de2da5b406c64529be6a462535cbe9eefaad404e3dd1dab6bc98a5840e2825708f8d1602e1404ab4dbd83ce43b2
data/CHANGES.md CHANGED
@@ -1,5 +1,10 @@
1
1
  # The change history of PyCall
2
2
 
3
+ ## 1.4.1
4
+
5
+ * Fix SEGV occurred on Windows
6
+ * Add PyCall.iterable
7
+
3
8
  ## 1.4.0
4
9
 
5
10
  * Explicitly states that Windows is not supported yet in README
data/ext/pycall/gc.c CHANGED
@@ -1,5 +1,74 @@
1
1
  #include "pycall_internal.h"
2
2
 
3
+ struct gcguard {
4
+ st_table *guarded_objects;
5
+ };
6
+
7
+ static int
8
+ gcguard_mark_i(st_data_t key, st_data_t val, st_data_t arg)
9
+ {
10
+ VALUE obj = (VALUE)val;
11
+ rb_gc_mark(obj);
12
+ return ST_CONTINUE;
13
+ }
14
+
15
+ static void
16
+ gcguard_mark(void* ptr)
17
+ {
18
+ struct gcguard *gg = (struct gcguard *)ptr;
19
+ st_foreach(gg->guarded_objects, gcguard_mark_i, 0);
20
+ }
21
+
22
+ static void
23
+ gcguard_free(void* ptr)
24
+ {
25
+ struct gcguard *gg = (struct gcguard *)ptr;
26
+ st_free_table(gg->guarded_objects);
27
+ }
28
+
29
+ static size_t
30
+ gcguard_memsize(const void* ptr)
31
+ {
32
+ const struct gcguard *gg = (const struct gcguard *)ptr;
33
+ return st_memsize(gg->guarded_objects);
34
+ }
35
+
36
+ static rb_data_type_t gcguard_data_type = {
37
+ "PyCall::gcguard",
38
+ {
39
+ gcguard_mark,
40
+ gcguard_free,
41
+ gcguard_memsize,
42
+ },
43
+ #ifdef RUBY_TYPED_FREE_IMMEDIATELY
44
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY
45
+ #endif
46
+ };
47
+
48
+ static void
49
+ gcguard_aset(VALUE gcguard, PyObject *pyptr, VALUE rbobj)
50
+ {
51
+ struct gcguard *gg;
52
+ TypedData_Get_Struct(gcguard, struct gcguard, &gcguard_data_type, gg);
53
+
54
+ st_insert(gg->guarded_objects, (st_data_t)pyptr, (st_data_t)rbobj);
55
+ }
56
+
57
+ static void
58
+ gcguard_delete(VALUE gcguard, PyObject *pyptr)
59
+ {
60
+ if (rb_typeddata_is_kind_of(gcguard, &gcguard_data_type)) {
61
+ /* This check is necessary to avoid error on the process finalization phase */
62
+ struct gcguard *gg;
63
+ st_data_t key, val;
64
+
65
+ TypedData_Get_Struct(gcguard, struct gcguard, &gcguard_data_type, gg);
66
+
67
+ key = (st_data_t)pyptr;
68
+ st_delete(gg->guarded_objects, &key, &val);
69
+ }
70
+ }
71
+
3
72
  static ID id_gcguard_table;
4
73
  static PyObject *weakref_callback_pyobj;
5
74
  static PyObject *gcguard_weakref_destroyed(PyObject *self, PyObject *weakref);
@@ -21,15 +90,15 @@ gcguard_weakref_destroyed(PyObject *self, PyObject *weakref)
21
90
  void
22
91
  pycall_gcguard_aset(PyObject *pyobj, VALUE rbobj)
23
92
  {
24
- VALUE table = rb_ivar_get(mPyCall, id_gcguard_table);
25
- rb_hash_aset(table, PTR2NUM(pyobj), rbobj);
93
+ VALUE gcguard = rb_ivar_get(mPyCall, id_gcguard_table);
94
+ gcguard_aset(gcguard, pyobj, rbobj);
26
95
  }
27
96
 
28
97
  void
29
98
  pycall_gcguard_delete(PyObject *pyobj)
30
99
  {
31
- VALUE table = rb_ivar_get(mPyCall, id_gcguard_table);
32
- rb_hash_delete(table, PTR2NUM(pyobj));
100
+ VALUE gcguard = rb_ivar_get(mPyCall, id_gcguard_table);
101
+ gcguard_delete(gcguard, pyobj);
33
102
  }
34
103
 
35
104
  void
@@ -64,11 +133,21 @@ pycall_gcguard_register(PyObject *pyobj, VALUE obj)
64
133
  pycall_gcguard_aset(wref, obj);
65
134
  }
66
135
 
136
+ static VALUE
137
+ gcguard_new(void)
138
+ {
139
+ struct gcguard *gg;
140
+ VALUE obj = TypedData_Make_Struct(0, struct gcguard, &gcguard_data_type, gg);
141
+ gg->guarded_objects = st_init_numtable();
142
+
143
+ return obj;
144
+ }
145
+
67
146
  void
68
147
  pycall_init_gcguard(void)
69
148
  {
70
149
  id_gcguard_table = rb_intern("gcguard_table");
71
- rb_ivar_set(mPyCall, id_gcguard_table, rb_hash_new());
150
+ rb_ivar_set(mPyCall, id_gcguard_table, gcguard_new());
72
151
 
73
152
  weakref_callback_pyobj = Py_API(PyCFunction_NewEx)(&gcguard_weakref_callback_def, NULL, NULL);
74
153
  }
data/lib/pycall.rb CHANGED
@@ -5,6 +5,7 @@ module PyCall
5
5
  require 'pycall/pyobject_wrapper'
6
6
  require 'pycall/pytypeobject_wrapper'
7
7
  require 'pycall/pymodule_wrapper'
8
+ require 'pycall/iterable_wrapper'
8
9
  require 'pycall/init'
9
10
 
10
11
  module_function
@@ -73,6 +74,10 @@ module PyCall
73
74
  LibPython::Helpers.import_module(name)
74
75
  end
75
76
 
77
+ def iterable(obj)
78
+ IterableWrapper.new(obj)
79
+ end
80
+
76
81
  def len(obj)
77
82
  case obj
78
83
  when PyObjectWrapper
@@ -0,0 +1,32 @@
1
+ module PyCall
2
+ class IterableWrapper
3
+ include Enumerable
4
+
5
+ def initialize(obj)
6
+ @obj = check_iterable(obj)
7
+ end
8
+
9
+ private def check_iterable(obj)
10
+ unless PyCall.hasattr?(obj, :__iter__)
11
+ raise ArgumentError, "%p object is not iterable" % obj
12
+ end
13
+ obj
14
+ end
15
+
16
+ def each
17
+ return enum_for(__method__) unless block_given?
18
+ iter = @obj.__iter__()
19
+ while true
20
+ begin
21
+ yield iter.__next__()
22
+ rescue PyCall::PyError => err
23
+ if err.type == PyCall.builtins.StopIteration
24
+ break
25
+ else
26
+ raise err
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -1,5 +1,5 @@
1
1
  module PyCall
2
- VERSION = "1.4.0"
2
+ VERSION = "1.4.1"
3
3
 
4
4
  module Version
5
5
  numbers, TAG = VERSION.split("-")
@@ -6,7 +6,12 @@ module PyCall
6
6
  rescue
7
7
  WMAP_SUPPORT_INT_KEY = false
8
8
  else
9
- WMAP_SUPPORT_INT_KEY = true
9
+ case RUBY_PLATFORM
10
+ when /cygwin/, /mingw/, /mswin/
11
+ WMAP_SUPPORT_INT_KEY = false
12
+ else
13
+ WMAP_SUPPORT_INT_KEY = true
14
+ end
10
15
  end
11
16
 
12
17
  if WMAP_SUPPORT_INT_KEY
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: 1.4.0
4
+ version: 1.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kenta Murata
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-05-28 00:00:00.000000000 Z
11
+ date: 2021-07-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -196,6 +196,7 @@ files:
196
196
  - lib/pycall/import.rb
197
197
  - lib/pycall/init.rb
198
198
  - lib/pycall/iruby_helper.rb
199
+ - lib/pycall/iterable_wrapper.rb
199
200
  - lib/pycall/libpython.rb
200
201
  - lib/pycall/libpython/finder.rb
201
202
  - lib/pycall/libpython/pyobject_struct.rb
@@ -235,7 +236,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
235
236
  - !ruby/object:Gem::Version
236
237
  version: '0'
237
238
  requirements: []
238
- rubygems_version: 3.2.3
239
+ rubygems_version: 3.2.21
239
240
  signing_key:
240
241
  specification_version: 4
241
242
  summary: pycall