Module: PyCall::LibPython::Finder
- Defined in:
- lib/pycall/libpython/finder.rb
Constant Summary collapse
- LIBPREFIX =
libprefix || 'lib'
- LIBSUFFIX =
libsuffix || 'so'
- DEFAULT_PYTHON =
[ -'python3', -'python', ].freeze
Class Method Summary collapse
- .candidate_names(python_config) ⇒ Object
- .candidate_paths(python_config) {|| ... } ⇒ Object
- .find_libpython(python = nil) ⇒ Object
- .find_python_config(python = nil) ⇒ Object
- .investigate_python_config(python) ⇒ Object
- .make_libpaths(python_config) ⇒ Object
- .normalize_path(path, suffix, apple_p = apple?) ) ⇒ Object
- .python_investigator_py ⇒ Object
-
.remove_suffix_apple(path) ⇒ Object
Strip off .so or .dylib.
Class Method Details
.candidate_names(python_config) ⇒ Object
69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 |
# File 'lib/pycall/libpython/finder.rb', line 69 def candidate_names(python_config) names = [] names << python_config[:LDLIBRARY] if python_config[:LDLIBRARY] suffix = python_config[:SHLIB_SUFFIX] if python_config[:LIBRARY] ext = File.extname(python_config[:LIBRARY]) names << python_config[:LIBRARY].delete_suffix(ext) + suffix end dlprefix = if windows? then "" else "lib" end sysdata = { v_major: python_config[:version_major], VERSION: python_config[:VERSION], ABIFLAGS: python_config[:ABIFLAGS], } [ "python%{VERSION}%{ABIFLAGS}" % sysdata, "python%{VERSION}" % sysdata, "python%{v_major}" % sysdata, "python" ].each do |stem| names << "#{dlprefix}#{stem}#{suffix}" end names.compact! names.uniq! debug_report("candidate_names: #{names}") return names end |
.candidate_paths(python_config) {|| ... } ⇒ Object
99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 |
# File 'lib/pycall/libpython/finder.rb', line 99 def candidate_paths(python_config) # The candidate library that linked by executable yield python_config[:linked_libpython] lib_dirs = make_libpaths(python_config) lib_basenames = candidate_names(python_config) # candidates by absolute paths lib_dirs.each do |dir| lib_basenames.each do |name| yield File.join(dir, name) end end # library names for searching in system library paths lib_basenames.each do |name| yield name end end |
.find_libpython(python = nil) ⇒ Object
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
# File 'lib/pycall/libpython/finder.rb', line 40 def find_libpython(python = nil) debug_report("find_libpython(#{python.inspect})") python, python_config = find_python_config(python) suffix = python_config[:SHLIB_SUFFIX] use_conda = (ENV.fetch("CONDA_PREFIX", nil) == File.dirname(python_config[:executable])) python_home = if !ENV.key?("PYTHONHOME") || use_conda python_config[:PYTHONHOME] else ENV["PYTHONHOME"] end ENV["PYTHONHOME"] = python_home candidate_paths(python_config) do |path| debug_report("Candidate: #{path}") normalized = normalize_path(path, suffix) if normalized debug_report("Trying to dlopen: #{normalized}") begin return dlopen(normalized) rescue Fiddle::DLError debug_report "dlopen(#{normalized.inspect}) => #{$!.class}: #{$!.}" end else debug_report("Not found.") end end end |
.find_python_config(python = nil) ⇒ Object
28 29 30 31 32 33 34 35 36 37 38 |
# File 'lib/pycall/libpython/finder.rb', line 28 def find_python_config(python = nil) python ||= DEFAULT_PYTHON Array(python).each do |python_cmd| begin python_config = investigate_python_config(python_cmd) return [python_cmd, python_config] unless python_config.empty? rescue end end raise ::PyCall::PythonNotFound end |
.investigate_python_config(python) ⇒ Object
141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 |
# File 'lib/pycall/libpython/finder.rb', line 141 def investigate_python_config(python) python_env = { 'PYTHONIOENCODING' => 'UTF-8' } debug_report("investigate_python_config(#{python.inspect})") IO.popen(python_env, [python, python_investigator_py], 'r') do |io| {}.tap do |config| io.each_line do |line| next unless line =~ /: / key, value = line.chomp.split(': ', 2) case value when 'True', 'true', 'False', 'false' value = (value == 'True' || value == 'true') end config[key.to_sym] = value if value != 'None' end end end rescue Errno::ENOENT raise PyCall::PythonInvestigationFailed end |
.make_libpaths(python_config) ⇒ Object
165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 |
# File 'lib/pycall/libpython/finder.rb', line 165 def make_libpaths(python_config) libpaths = python_config.values_at(:LIBPL, :srcdir, :LIBDIR) if windows? libpaths << File.dirname(python_config[:executable]) else libpaths << File.('../../lib', python_config[:executable]) end if apple? libpaths << python_config[:PYTHONFRAMEWORKPREFIX] end exec_prefix = python_config[:exec_prefix] libpaths << exec_prefix libpaths << File.join(exec_prefix, 'lib') libpaths.compact! libpaths.uniq! debug_report "libpaths: #{libpaths.inspect}" return libpaths end |
.normalize_path(path, suffix, apple_p = apple?) ) ⇒ Object
119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 |
# File 'lib/pycall/libpython/finder.rb', line 119 def normalize_path(path, suffix, apple_p=apple?) return nil if path.nil? case when path.nil?, Pathname.new(path).relative? nil when File.exist?(path) File.realpath(path) when File.exist?(path + suffix) File.realpath(path + suffix) when apple_p normalize_path(remove_suffix_apple(path), ".so", false) else nil end end |
.python_investigator_py ⇒ Object
161 162 163 |
# File 'lib/pycall/libpython/finder.rb', line 161 def python_investigator_py File.('../../python/investigator.py', __FILE__) end |
.remove_suffix_apple(path) ⇒ Object
Strip off .so or .dylib
137 138 139 |
# File 'lib/pycall/libpython/finder.rb', line 137 def remove_suffix_apple(path) path.sub(/\.(?:dylib|so)\z/, '') end |