pycall 1.3.1 → 1.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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"