pycall 1.4.0 → 1.4.1

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