pycall 1.3.1 → 1.4.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.
@@ -1,8 +1,85 @@
1
- from distutils.sysconfig import get_config_var
1
+ #!/usr/bin/env python
2
+
3
+ import ctypes.util
4
+ from distutils.sysconfig import get_config_var, get_python_version
5
+ import os
2
6
  import sys
3
7
 
4
- for var in ('executable', 'exec_prefix', 'prefix'):
5
- print(var + ': ' + str(getattr(sys, var)))
6
- print('multiarch: ' + str(getattr(getattr(sys, 'implementation', sys), '_multiarch', None)))
7
- for var in ('VERSION', 'INSTSONAME', 'LIBRARY', 'LDLIBRARY', 'LIBDIR', 'PYTHONFRAMEWORKPREFIX', 'MULTIARCH'):
8
- print(var + ': ' + str(get_config_var(var)))
8
+ is_windows = os.name == "nt"
9
+
10
+ def linked_libpython():
11
+ if is_windows:
12
+ return _linked_libpython_windows()
13
+ return _linked_libpython_unix()
14
+
15
+ class Dl_info(ctypes.Structure):
16
+ _fields_ = [
17
+ ("dli_fname", ctypes.c_char_p),
18
+ ("dli_fbase", ctypes.c_void_p),
19
+ ("dli_sname", ctypes.c_char_p),
20
+ ("dli_saddr", ctypes.c_void_p),
21
+ ]
22
+
23
+ def _linked_libpython_unix():
24
+ libdl = ctypes.CDLL(ctypes.util.find_library("dl"))
25
+ libdl.dladdr.argtypes = [ctypes.c_void_p, ctypes.POINTER(Dl_info)]
26
+ libdl.dladdr.restype = ctypes.c_int
27
+
28
+ dlinfo = Dl_info()
29
+ retcode = libdl.dladdr(
30
+ ctypes.cast(ctypes.pythonapi.Py_GetVersion, ctypes.c_void_p),
31
+ ctypes.pointer(dlinfo))
32
+ if retcode == 0: # means error
33
+ return None
34
+ path = os.path.realpath(dlinfo.dli_fname.decode())
35
+ if path == os.path.realpath(sys.executable):
36
+ return None
37
+ return path
38
+
39
+ def _linked_libpython_windows():
40
+ # Based on: https://stackoverflow.com/a/16659821
41
+ from ctypes.wintypes import HANDLE, LPWSTR, DWORD
42
+
43
+ GetModuleFileName = ctypes.windll.kernel32.GetModuleFileNameW
44
+ GetModuleFileName.argtypes = [HANDLE, LPWSTR, DWORD]
45
+ GetModuleFileName.restype = DWORD
46
+
47
+ MAX_PATH = 260
48
+ try:
49
+ buf = ctypes.create_unicode_buffer(MAX_PATH)
50
+ GetModuleFileName(ctypes.pythonapi._handle, buf, MAX_PATH)
51
+ return buf.value
52
+ except (ValueError, OSError):
53
+ return None
54
+
55
+ print("linked_libpython: {val}".format(val=(linked_libpython() or "None")))
56
+
57
+ sys_keys = [ "executable", "exec_prefix", "prefix" ]
58
+
59
+ for var in sys_keys:
60
+ print("{var}: {val}".format(var=var, val=(getattr(sys, var) or "None")))
61
+
62
+ config_keys = [ "INSTSONAME", "LIBDIR", "LIBPL", "LIBRARY", "LDLIBRARY",
63
+ "MULTIARCH", "PYTHONFRAMEWORKPREFIX", "SHLIB_SUFFIX", "srcdir" ]
64
+
65
+ for var in config_keys:
66
+ print("{var}: {val}".format(var=var, val=(get_config_var(var) or "None")))
67
+
68
+ print("ABIFLAGS: {val}".format(val=get_config_var("ABIFLAGS") or get_config_var("abiflags") or "None"))
69
+
70
+ version = get_python_version() or \
71
+ "{v.major}.{v.minor}".format(v=sys.version_info) or \
72
+ get_config_var("VERSION")
73
+ print("VERSION: {val}".format(val=version))
74
+
75
+ if is_windows:
76
+ if hasattr(sys, "base_exec_prefix"):
77
+ PYTHONHOME = sys.base_exec_prefix
78
+ else:
79
+ PYTHONHOME = sys.exec_prefix
80
+ else:
81
+ if hasattr(sys, "base_exec_prefix"):
82
+ PYTHONHOME = ":".join([sys.base_prefix, sys.base_exec_prefix])
83
+ else:
84
+ PYTHONHOME = ":".join([sys.prefix, sys.exec_prefix])
85
+ print("PYTHONHOME: {val}".format(val=PYTHONHOME))
@@ -1,5 +1,5 @@
1
1
  module PyCall
2
- VERSION = "1.3.1"
2
+ VERSION = "1.4.0"
3
3
 
4
4
  module Version
5
5
  numbers, TAG = VERSION.split("-")
@@ -1,5 +1,49 @@
1
1
  module PyCall
2
2
  class WrapperObjectCache
3
+
4
+ begin
5
+ ObjectSpace::WeakMap.new[42] = Object.new
6
+ rescue
7
+ WMAP_SUPPORT_INT_KEY = false
8
+ else
9
+ WMAP_SUPPORT_INT_KEY = true
10
+ end
11
+
12
+ if WMAP_SUPPORT_INT_KEY
13
+ def self.get_key(pyptr)
14
+ pyptr.__address__
15
+ end
16
+ else
17
+ class Key
18
+ @address_key_map = {}
19
+
20
+ def self.[](address)
21
+ # An instance of Key created here is parmanently cached in @address_key_map.
22
+ # This behavior is intentional.
23
+ @address_key_map[address] ||= new(address)
24
+ end
25
+
26
+ def initialize(address)
27
+ @address = address
28
+ end
29
+
30
+ attr_reader :address
31
+
32
+ def ==(other)
33
+ case other
34
+ when Key
35
+ self.address == other.address
36
+ else
37
+ super
38
+ end
39
+ end
40
+ end
41
+
42
+ def self.get_key(pyptr)
43
+ Key[pyptr.__address__]
44
+ end
45
+ end
46
+
3
47
  def initialize(*restricted_pytypes)
4
48
  unless restricted_pytypes.empty?
5
49
  restricted_pytypes.each do |pytype|
@@ -8,9 +52,7 @@ module PyCall
8
52
  end
9
53
  end
10
54
  @restricted_pytypes = restricted_pytypes
11
- @wrapper_object_table = {}
12
- @wrapped_pyptr_table = {}
13
- @weakref_table = {}
55
+ @wrapper_object_table = ObjectSpace::WeakMap.new
14
56
  end
15
57
 
16
58
  def lookup(pyptr)
@@ -25,16 +67,14 @@ module PyCall
25
67
  end
26
68
  end
27
69
 
28
- wrapper_object_id = @wrapper_object_table[pyptr.__address__]
29
- if wrapper_object_id
30
- wrapper_object = ObjectSpace._id2ref(wrapper_object_id) rescue nil
31
- return wrapper_object if wrapper_object
70
+ key = self.class.get_key(pyptr)
71
+ wrapper_object = @wrapper_object_table[key]
72
+ unless wrapper_object
73
+ wrapper_object = yield(pyptr)
74
+ check_wrapper_object(wrapper_object)
75
+ @wrapper_object_table[key] = wrapper_object
32
76
  end
33
77
 
34
- wrapper_object = yield(pyptr)
35
- check_wrapper_object(wrapper_object)
36
- register_wrapper_object(pyptr, wrapper_object)
37
-
38
78
  wrapper_object
39
79
  end
40
80
 
@@ -43,19 +83,5 @@ module PyCall
43
83
  raise TypeError, "unexpected wrapper object (expected an object extended by PyObjectWrapper)"
44
84
  end
45
85
  end
46
-
47
- def register_wrapper_object(pyptr, wrapper_object)
48
- @wrapper_object_table[pyptr.__address__] = wrapper_object.__id__
49
- @wrapped_pyptr_table[wrapper_object.__id__] = pyptr.__address__
50
- ObjectSpace.define_finalizer(wrapper_object, &method(:unregister_wrapper_object))
51
- # TODO: weakref
52
- self
53
- end
54
-
55
- def unregister_wrapper_object(wrapper_object_id)
56
- pyptr_addr = @wrapped_pyptr_table.delete(wrapper_object_id)
57
- @wrapper_object_table.delete(pyptr_addr) if pyptr_addr
58
- self
59
- end
60
86
  end
61
87
  end
data/pycall.gemspec CHANGED
@@ -44,4 +44,5 @@ Gem::Specification.new do |spec|
44
44
  spec.add_development_dependency "launchy"
45
45
  spec.add_development_dependency "pry"
46
46
  spec.add_development_dependency "pry-byebug"
47
+ spec.add_development_dependency "test-unit"
47
48
  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: 1.3.1
4
+ version: 1.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kenta Murata
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-05-25 00:00:00.000000000 Z
11
+ date: 2021-05-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -122,6 +122,20 @@ dependencies:
122
122
  - - ">="
123
123
  - !ruby/object:Gem::Version
124
124
  version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: test-unit
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
125
139
  description: pycall
126
140
  email:
127
141
  - mrkn@mrkn.jp
@@ -131,15 +145,14 @@ extensions:
131
145
  extra_rdoc_files: []
132
146
  files:
133
147
  - ".github/workflows/ci.yml"
148
+ - ".github/workflows/windows.yml"
134
149
  - ".gitignore"
135
150
  - ".rspec"
136
- - ".travis.yml"
137
151
  - CHANGES.md
138
152
  - Gemfile
139
153
  - LICENSE.txt
140
154
  - README.md
141
155
  - Rakefile
142
- - appveyor.yml
143
156
  - bin/console
144
157
  - bin/guard
145
158
  - bin/rspec
@@ -158,6 +171,7 @@ files:
158
171
  - examples/notebooks/classifier_comparison.ipynb
159
172
  - examples/notebooks/forest_importances.ipynb
160
173
  - examples/notebooks/iruby_integration.ipynb
174
+ - examples/notebooks/leaflet.ipynb
161
175
  - examples/notebooks/lorenz_attractor.ipynb
162
176
  - examples/notebooks/polar_axes.ipynb
163
177
  - examples/notebooks/sum_benchmarking.ipynb
@@ -221,7 +235,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
221
235
  - !ruby/object:Gem::Version
222
236
  version: '0'
223
237
  requirements: []
224
- rubygems_version: 3.1.2
238
+ rubygems_version: 3.2.3
225
239
  signing_key:
226
240
  specification_version: 4
227
241
  summary: pycall
data/.travis.yml DELETED
@@ -1,82 +0,0 @@
1
- language: ruby
2
-
3
- os: linux
4
-
5
- dist: bionic
6
- sudo: required
7
-
8
- rvm:
9
- - ruby-head
10
- - 2.7
11
- - 2.6
12
- - 2.5
13
- - 2.4
14
-
15
- env:
16
- global:
17
- - PYCALL_DEBUG_FIND_LIBPYTHON=1
18
- matrix:
19
- - PYENV_VERSION=3.8.0
20
- - PYENV_VERSION=3.7.5
21
- - PYENV_VERSION=2.7.17
22
- - PYENV_VERSION=system LIBPYTHON=/usr/lib/x86_64-linux-gnu/libpython3.6m.so
23
- - PYENV_VERSION=system LIBPYTHON=/usr/lib/x86_64-linux-gnu/libpython2.7.so
24
- - PYENV_VERSION=miniconda2-4.3.30
25
- - PYENV_VERSION=miniconda3-4.3.30
26
-
27
- matrix:
28
- include:
29
- - os: osx
30
- osx_image: xcode11.2
31
- compiler: clang
32
- rvm: 2.7
33
- env: PYENV_VERSION=3.8.0
34
- - os: osx
35
- osx_image: xcode11.2
36
- compiler: clang
37
- rvm: 2.6
38
- env: PYENV_VERSION=3.8.0
39
- - os: osx
40
- osx_image: xcode11.2
41
- compiler: clang
42
- rvm: 2.5
43
- env: PYENV_VERSION=3.8.0
44
- - os: osx
45
- osx_image: xcode11.2
46
- compiler: clang
47
- rvm: 2.4
48
- env: PYENV_VERSION=3.8.0
49
- - os: osx
50
- osx_image: xcode11.2
51
- compiler: clang
52
- rvm: 2.7
53
- env: PYENV_VERSION=miniconda3-4.3.11
54
- - os: osx
55
- osx_image: xcode11.2
56
- compiler: clang
57
- rvm: 2.6
58
- env: PYENV_VERSION=miniconda3-4.3.11
59
- - os: osx
60
- osx_image: xcode11.2
61
- compiler: clang
62
- rvm: 2.5
63
- env: PYENV_VERSION=miniconda3-4.3.11
64
- - os: osx
65
- osx_image: xcode11.2
66
- compiler: clang
67
- rvm: 2.4
68
- env: PYENV_VERSION=miniconda3-4.3.11
69
- allow_failures:
70
- - os: osx
71
-
72
- before_install:
73
- - export PATH="$(pyenv root)/bin:$PATH"
74
- - eval "$(pyenv init -)"
75
-
76
- install:
77
- - ci/travis_install.sh
78
-
79
- before_script:
80
- - . ci/travis_before_script.sh
81
- - bundle exec rake clobber compile
82
- - python lib/pycall/python/investigator.py
data/appveyor.yml DELETED
@@ -1,92 +0,0 @@
1
- ---
2
- environment:
3
- matrix:
4
- # Ruby 2.4 (32bit)
5
- - ruby_version: "24"
6
- PYTHONDIR: "C:\\Python27"
7
- PYTHON: "C:\\Python27\\python.exe"
8
-
9
- - ruby_version: "24"
10
- PYTHONDIR: "C:\\Python35"
11
- PYTHON: "C:\\Python35\\python.exe"
12
-
13
- - ruby_version: "24"
14
- PYTHONDIR: "C:\\Python36"
15
- PYTHON: "C:\\Python36\\python.exe"
16
-
17
- # Ruby 2.4 (64bit)
18
- - ruby_version: "24-x64"
19
- PYTHONDIR: "C:\\Python27-x64"
20
- PYTHON: "C:\\Python27-x64\\python.exe"
21
-
22
- - ruby_version: "24-x64"
23
- PYTHONDIR: "C:\\Python35-x64"
24
- PYTHON: "C:\\Python35-x64\\python.exe"
25
-
26
- - ruby_version: "24-x64"
27
- PYTHONDIR: "C:\\Python36-x64"
28
- PYTHON: "C:\\Python36-x64\\python.exe"
29
-
30
- # Ruby 2.3 (32bit)
31
- - ruby_version: "23"
32
- PYTHONDIR: "C:\\Python27"
33
- PYTHON: "C:\\Python27\\python.exe"
34
-
35
- - ruby_version: "23"
36
- PYTHONDIR: "C:\\Python34"
37
- PYTHON: "C:\\Python34\\python.exe"
38
-
39
- - ruby_version: "23"
40
- PYTHONDIR: "C:\\Python35"
41
- PYTHON: "C:\\Python35\\python.exe"
42
-
43
- - ruby_version: "23"
44
- PYTHONDIR: "C:\\Python36"
45
- PYTHON: "C:\\Python36\\python.exe"
46
-
47
- # Ruby 2.3 (64bit)
48
- - ruby_version: "23-x64"
49
- PYTHONDIR: "C:\\Python27-x64"
50
- PYTHON: "C:\\Python27-x64\\python.exe"
51
-
52
- - ruby_version: "23-x64"
53
- PYTHONDIR: "C:\\Python35-x64"
54
- PYTHON: "C:\\Python35-x64\\python.exe"
55
-
56
- - ruby_version: "23-x64"
57
- PYTHONDIR: "C:\\Python36-x64"
58
- PYTHON: "C:\\Python36-x64\\python.exe"
59
-
60
- branches:
61
- only:
62
- - master
63
- - /release-.*/
64
-
65
- notifications:
66
- - provider: Email
67
- on_build_success: false
68
- on_build_failure: false
69
- on_build_status_changed: false
70
-
71
- deploy: off
72
- build: off
73
-
74
- install:
75
- - "SET PATH=%PYTHONDIR%;%PYTHONDIR%\\Scripts;%PATH%"
76
- - "SET PATH=C:\\Ruby%ruby_version%\\bin;%PATH%"
77
- - "bundle install"
78
- - "pip install numpy"
79
-
80
- before_test:
81
- - "bundle exec rake -rdevkit clobber compile"
82
- - ECHO "=== python investigator.py ==="
83
- - "python lib\\pycall\\python\\investigator.py"
84
-
85
- test_script:
86
- - "SET PYCALL_DEBUG_FIND_LIBPYTHON=1"
87
- - rake
88
-
89
- matrix:
90
- allow_failures:
91
- - PYTHONDIR: "C:\\Python27"
92
- - PYTHONDIR: "C:\\Python27-x64"