autoproj 2.13.0 → 2.14.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d0594abdc1c9523788d70185cef7fee0094e70aa0aad5a7c06432e78fd3f2324
4
- data.tar.gz: 7fbde174feb043143cf9d64a23517858982216bd15e33c659954085f5168af64
3
+ metadata.gz: 3f10cbf09589b7ad19d1ac9c21d4630c1f31e285a4ee7ac2db544fb6c23059e8
4
+ data.tar.gz: 3d50fe0556577a1e5ca7601417e1b8d8ebeb73f36e9ce0c4ba76853c813833b0
5
5
  SHA512:
6
- metadata.gz: 82529e41b820b90048063019025470390718393f7479dfbf9714d4898abdc6d8a327306f1b672191f48e925b1af8c2e05e94583a4f9dde8a418f6aac11a99523
7
- data.tar.gz: 9eeec00ec5b9aaaa565e85a65b2a07a22ba0701044657434d2a99c837174e0d87551a389f73d3ee55eff0f05ee2221b61c7f35e2b057c2fe5bbfbbe568015723
6
+ metadata.gz: 7306758a6842ab1175f70deeb8b69d5268a2145681cb0aff459bbd119e00292b8cd14e661ebae12964963ff2af6a0007c217cba020422b0445b873dad5f70ffd
7
+ data.tar.gz: cfaa2391a0dae4d77d41281fb6ebc7f2174c728ec532e330515a9da6b4d9235c14eb13100f35d17a863a7701a7fad338e7a40c920b9c9cf8e37f0ee2ecb78fa8
@@ -166,7 +166,12 @@ cvs:
166
166
  default: cvs
167
167
 
168
168
  pip:
169
- debian,ubuntu: python-pip
169
+ debian:
170
+ '8,jessie,9,stretch': python-pip
171
+ default: python3-pip
172
+ ubuntu:
173
+ '16.04,18.04': python-pip
174
+ default: python3-pip
170
175
  arch: python2-pip
171
176
  opensuse: python-pip
172
177
  fedora: python-pip
@@ -175,7 +180,12 @@ pip:
175
180
 
176
181
  python:
177
182
  arch: python2
178
- debian,ubuntu: python-dev
183
+ debian:
184
+ '8,jessie,9,stretch': python-dev
185
+ default: python3-dev
186
+ ubuntu:
187
+ '16.04,18.04': python-dev
188
+ default: python3-dev
179
189
  fedora: python-devel
180
190
  freebsd: python-devel
181
191
  gentoo: dev-lang/python
@@ -184,7 +194,12 @@ python:
184
194
 
185
195
  python-setuptools:
186
196
  arch: python2-distribute
187
- debian,ubuntu: python-setuptools
197
+ debian:
198
+ '8,jessie,9,stretch': python-setuptools
199
+ default: python3-setuptools
200
+ ubuntu:
201
+ '16.04,18.04': python-setuptools
202
+ default: python3-setuptools
188
203
  fedora: python-setuptools
189
204
  gentoo: dev-python/setuptools
190
205
  default: ignore # will be installed manually by the user
@@ -17,6 +17,22 @@ module Autoproj
17
17
  Autoproj.filter_out_paths_in_workspace(env)
18
18
  end
19
19
 
20
+ def env_filename(shell, *subdir)
21
+ env_filename = if shell == 'sh'
22
+ ENV_FILENAME
23
+ else
24
+ (Pathname(ENV_FILENAME).sub_ext '').to_s.concat(".#{shell}")
25
+ end
26
+
27
+ File.join(root_dir, *subdir, env_filename)
28
+ end
29
+
30
+ def each_env_filename(*subdir)
31
+ (['sh'] + Autoproj.workspace.config.user_shells).to_set.each do |shell|
32
+ yield shell, env_filename(shell, *subdir)
33
+ end
34
+ end
35
+
20
36
  def export_env_sh(subdir = nil, options = Hash.new)
21
37
  if subdir.kind_of?(Hash)
22
38
  subdir, options = nil, subdir
@@ -28,19 +44,7 @@ module Autoproj
28
44
  completion_dir = File.join(shell_dir, 'completion')
29
45
  env_updated = false
30
46
 
31
- (['sh'] + Autoproj.workspace.config.user_shells).to_set.each do |shell|
32
- env_filename = if shell == 'sh'
33
- ENV_FILENAME
34
- else
35
- (Pathname(ENV_FILENAME).sub_ext '').to_s.concat(".#{shell}")
36
- end
37
-
38
- filename = if subdir
39
- File.join(root_dir, subdir, env_filename)
40
- else
41
- File.join(root_dir, env_filename)
42
- end
43
-
47
+ each_env_filename(*[subdir].compact) do |shell, filename|
44
48
  helper = File.join(shell_dir, "autoproj_#{shell}")
45
49
  if options[:shell_helpers]
46
50
  source_after(helper, shell: shell) if File.file?(helper)
@@ -60,6 +60,11 @@ module Autoproj
60
60
  YAML.safe_load(File.read(file)) || {}
61
61
  end
62
62
 
63
+ if data["layout"]&.member?(nil)
64
+ Autoproj.warn "There is an empty entry in your layout in #{file}. All empty entries are ignored."
65
+ data["layout"] = data["layout"].compact
66
+ end
67
+
63
68
  @file = file
64
69
  initialize_from_hash(data)
65
70
  end
@@ -123,13 +123,14 @@ module Autoproj
123
123
  end
124
124
 
125
125
  def create_cache_symlink(cache_dir, bundler_cache_dir)
126
- valid = !File.exist?(bundler_cache_dir) ||
127
- File.symlink?(bundler_cache_dir)
128
-
129
- unless valid
130
- Autoproj.warn "cannot use #{cache_dir} as gem cache as "\
131
- "#{bundler_cache_dir} already exists"
132
- return
126
+ if File.exist?(bundler_cache_dir)
127
+ if !File.symlink?(bundler_cache_dir)
128
+ Autoproj.warn "cannot use #{cache_dir} as gem cache as "\
129
+ "#{bundler_cache_dir} already exists"
130
+ return
131
+ elsif File.readlink(bundler_cache_dir) == cache_dir
132
+ return
133
+ end
133
134
  end
134
135
 
135
136
  FileUtils.rm_f bundler_cache_dir
@@ -1,3 +1,5 @@
1
+ require 'autoproj/python'
2
+
1
3
  module Autoproj
2
4
  module PackageManagers
3
5
  # Using pip to install python packages
@@ -25,30 +27,40 @@ module Autoproj
25
27
  end
26
28
 
27
29
  def guess_pip_program
28
- if Autobuild.programs['pip']
29
- return Autobuild.programs['pip']
30
+ unless ws.config.has_value_for?('USE_PYTHON')
31
+ Autoproj::Python.setup_python_configuration_options(ws: ws)
32
+ end
33
+ unless ws.config.get('USE_PYTHON')
34
+ raise ConfigError, "Your current package selection" \
35
+ " requires the use of pip, but" \
36
+ " the use of python is either unspecified or has been denied, see" \
37
+ " setting of USE_PYTHON in your workspace configuration." \
38
+ " Either remove all packages depending on pip packages " \
39
+ " from the workspace layout (manifest) or " \
40
+ " call 'autoproj reconfigure' to change the setting."
41
+
30
42
  end
31
43
 
32
- Autobuild.programs['pip'] = "pip"
44
+ Autobuild.programs['pip'] = "pip" unless Autobuild.programs['pip']
45
+ Autobuild.programs['pip']
33
46
  end
34
47
 
48
+ # rubocop:disable Lint/UnusedMethodArgument
35
49
  def install(pips, filter_uptodate_packages: false, install_only: false)
36
50
  guess_pip_program
37
- if pips.is_a?(String)
38
- pips = [pips]
39
- end
51
+ pips = [pips] if pips.is_a?(String)
40
52
 
41
- base_cmdline = [Autobuild.tool('pip'), 'install','--user']
53
+ base_cmdline = [Autobuild.tool('pip'), 'install', '--user']
42
54
 
43
55
  cmdlines = [base_cmdline + pips]
44
56
 
45
- if pips_interaction(pips, cmdlines)
46
- Autoproj.message " installing/updating Python dependencies: "+
47
- "#{pips.sort.join(", ")}"
57
+ if pips_interaction(cmdlines)
58
+ Autoproj.message " installing/updating Python dependencies:" \
59
+ " #{pips.sort.join(', ')}"
48
60
 
49
61
  cmdlines.each do |c|
50
62
  Autobuild::Subprocess.run 'autoproj', 'osdeps', *c,
51
- env: ws.env.resolved_env
63
+ env: ws.env.resolved_env
52
64
  end
53
65
 
54
66
  pips.each do |p|
@@ -56,8 +68,9 @@ module Autoproj
56
68
  end
57
69
  end
58
70
  end
59
-
60
- def pips_interaction(pips, cmdlines)
71
+ # rubocop:enable Lint/UnusedMethodArgument
72
+
73
+ def pips_interaction(cmdlines)
61
74
  if OSPackageInstaller.force_osdeps
62
75
  return true
63
76
  elsif enabled?
@@ -69,24 +82,23 @@ module Autoproj
69
82
  # We're not supposed to install rubygem packages but silent is not
70
83
  # set, so display information about them anyway
71
84
  puts <<-EOMSG
72
- #{Autoproj.color("The build process and/or the packages require some Python packages to be installed", :bold)}
73
- #{Autoproj.color("and you required autoproj to not do it itself", :bold)}
85
+ #{Autoproj.color('The build process and/or the packages require some Python packages to be installed', :bold)}
86
+ #{Autoproj.color('and you required autoproj to not do it itself', :bold)}
74
87
  The following command line can be used to install them manually
75
-
76
- #{cmdlines.map { |c| c.join(" ") }.join("\n ")}
77
-
88
+ #{' '}
89
+ #{cmdlines.map { |c| c.join(' ') }.join("\n ")}
90
+ #{' '}
78
91
  Autoproj expects these Python packages to be installed in #{pip_home} This can
79
92
  be overridden by setting the AUTOPROJ_PYTHONUSERBASE environment variable manually
80
93
 
81
94
  EOMSG
82
- print " #{Autoproj.color("Press ENTER to continue ", :bold)}"
95
+ print " #{Autoproj.color('Press ENTER to continue ', :bold)}"
83
96
 
84
- STDOUT.flush
85
- STDIN.readline
97
+ $stdout.flush
98
+ $stdin.readline
86
99
  puts
87
100
  false
88
101
  end
89
102
  end
90
103
  end
91
104
  end
92
-
@@ -0,0 +1,285 @@
1
+ require 'open3'
2
+ require 'rubygems'
3
+
4
+ module Autoproj
5
+ module Python
6
+ # Get the python version for a given python executable
7
+ # @return [String] The python version as <major>.<minor>
8
+ def self.get_python_version(python_bin)
9
+ unless File.exist?(python_bin)
10
+ raise ArgumentError, "Autoproj::Python.get_python_version executable "\
11
+ "'#{python_bin}' does not exist"
12
+ end
13
+
14
+ cmd = "#{python_bin} -c \"import sys;"\
15
+ "version=sys.version_info[:3]; "\
16
+ "print('{0}.{1}'.format(*version))\"".strip
17
+
18
+ msg, status = Open3.capture2e(cmd)
19
+ if status.success?
20
+ msg.strip
21
+
22
+ else
23
+ raise "Autoproj::Python.get_python_version identification"\
24
+ " of python version for '#{python_bin}' failed: #{msg}"
25
+ end
26
+ end
27
+
28
+ def self.get_pip_version(pip_bin)
29
+ unless File.exist?(pip_bin)
30
+ raise ArgumentError, "Autoproj::Python.get_pip_version executable "\
31
+ "'#{pip_bin}' does not exist"
32
+ end
33
+
34
+ cmd = "#{pip_bin} --version"
35
+
36
+ msg, status = Open3.capture2e(cmd)
37
+ if status.success?
38
+ msg.split(" ")[1]
39
+
40
+ else
41
+ raise "Autoproj::Python.get_pip_version identification"\
42
+ " of pip version for '#{pip_bin}' failed: #{msg}"
43
+ end
44
+ end
45
+
46
+ def self.validate_version(version, version_constraint)
47
+ if !version_constraint
48
+ true
49
+ else
50
+ dependency = Gem::Dependency.new("python", version_constraint)
51
+ dependency.match?("python", version)
52
+ end
53
+ end
54
+
55
+ # Validate that a given python executable's version fulfills
56
+ # a given version constraint
57
+ # @param [String] python_bin the python executable
58
+ # @param [String] version_constraint version constraint, e.g., <3.8, >= 3.7, 3.6
59
+ # @return [String,Bool] Version and validation result, i.e.,
60
+ # True if binary fulfills the version constraint, false otherwise
61
+ def self.validate_python_version(python_bin, version_constraint)
62
+ version = get_python_version(python_bin)
63
+ [version, validate_version(version, version_constraint)]
64
+ end
65
+
66
+ # Find python given a version constraint
67
+ # @return [String,String] path to python executable and python version
68
+ def self.find_python(ws: Autoproj.workspace,
69
+ version: ws.config.get('python_version', nil))
70
+ finders = [
71
+ -> { Autobuild.programs['python'] },
72
+ -> { `which python3`.strip },
73
+ -> { `which python`.strip }
74
+ ]
75
+
76
+ finders.each do |finder|
77
+ python_bin = finder.call
78
+ if python_bin && !python_bin.empty?
79
+ python_version, valid = validate_python_version(python_bin, version)
80
+ return python_bin, python_version if valid
81
+ end
82
+ end
83
+ raise "Autoproj::Python.find_python_bin: failed to find python" \
84
+ " for version '#{version}'"
85
+ end
86
+
87
+ # Get information about the python executable from autoproj config,
88
+ # but ensure the version constraint matches
89
+ #
90
+ # @return [String, String] Return path and version if the constraints
91
+ # are fulfilled nil otherwise
92
+
93
+ def self.get_python_from_config(ws: Autoproj.workspace, version: nil)
94
+ config_bin = ws.config.get('python_executable', nil)
95
+ return unless config_bin
96
+
97
+ config_version = ws.config.get('python_version', nil)
98
+ config_version ||= get_python_version(config_bin)
99
+
100
+ # If a version constraint is given, ensure fulfillment
101
+ if validate_version(config_version, version)
102
+ [config_bin, config_version]
103
+ else
104
+ raise "python_executable in autoproj config with " \
105
+ "version '#{config_version}' does not match "\
106
+ "version constraints '#{version}'"
107
+ end
108
+ end
109
+
110
+ def self.custom_resolve_python(bin: nil,
111
+ version: nil)
112
+ version, valid = validate_python_version(bin, version)
113
+ if valid
114
+ [bin, version]
115
+ else
116
+ raise "Autoproj::Python.resolve_python: requested python"\
117
+ "executable '#{bin}' does not satisfy version"\
118
+ "constraints '#{version}'"
119
+ end
120
+ end
121
+
122
+ def self.auto_resolve_python(ws: Autoproj.workspace,
123
+ version: nil)
124
+ version_constraint = version
125
+ resolvers = [
126
+ -> { get_python_from_config(ws: ws, version: version_constraint) },
127
+ -> { find_python(ws: ws, version: version_constraint) }
128
+ ]
129
+
130
+ bin = nil
131
+ resolvers.each do |resolver|
132
+ bin, version = resolver.call
133
+ if bin && File.exist?(bin) && version
134
+ Autoproj.debug "Autoproj::Python.resolve_python: " \
135
+ "found python '#{bin}' version '#{version}'"
136
+ break
137
+ end
138
+ rescue RuntimeError => e
139
+ Autoproj.debug "Autoproj::Python.resolve_python: " \
140
+ "resolver failed: #{e}"
141
+ end
142
+
143
+ unless bin
144
+ msg = "Autoproj::Python.resolve_python: " \
145
+ "failed to find a python executable"
146
+ if version_constraint
147
+ msg += " satisfying version constraint '#{version_constraint}'"
148
+ end
149
+ raise msg
150
+ end
151
+ [bin, version]
152
+ end
153
+
154
+ # Resolve the python executable according to a given version constraint
155
+ # @param [Autoproj.workspace] ws Autoproj workspace
156
+ # @param [String] bin Path to the python executable that shall be used,
157
+ # first fallback is the python_executable set in Autoproj's configuration,
158
+ # second fallback is a full search
159
+ # @param [String] version version constraint
160
+ # @return [String,String] python path and python version
161
+ def self.resolve_python(ws: Autoproj.workspace,
162
+ bin: nil,
163
+ version: nil)
164
+ if bin
165
+ custom_resolve_python(bin: bin, version: version)
166
+ else
167
+ auto_resolve_python(ws: ws, version: version)
168
+ end
169
+ end
170
+
171
+ def self.remove_python_shims(root_dir)
172
+ shim_path = File.join(root_dir, "install", "bin", "python")
173
+ FileUtils.rm shim_path if File.exist?(shim_path)
174
+ end
175
+
176
+ def self.remove_pip_shims(root_dir)
177
+ shim_path = File.join(root_dir, "install", "bin", "pip")
178
+ FileUtils.rm shim_path if File.exist?(shim_path)
179
+ end
180
+
181
+ def self.rewrite_python_shims(python_executable, root_dir)
182
+ shim_path = File.join(root_dir, "install", "bin")
183
+ unless File.exist?(shim_path)
184
+ FileUtils.mkdir_p shim_path
185
+ Autoproj.warn "Autoproj::Python.rewrite_python_shims: creating "\
186
+ "#{shim_path} - "\
187
+ "are you operating on a valid autoproj workspace?"
188
+ end
189
+
190
+ python_path = File.join(shim_path, 'python')
191
+ File.open(python_path, 'w') do |io|
192
+ io.puts "#! /bin/sh"
193
+ io.puts "exec #{python_executable} \"$@\""
194
+ end
195
+ FileUtils.chmod 0o755, python_path
196
+ python_path
197
+ end
198
+
199
+ def self.rewrite_pip_shims(python_executable, root_dir)
200
+ shim_path = File.join(root_dir, "install", "bin")
201
+ unless File.exist?(shim_path)
202
+ FileUtils.mkdir_p shim_path
203
+ Autoproj.warn "Autoproj::Python.rewrite_pip_shims: creating "\
204
+ "#{shim_path} - "\
205
+ "are you operating on a valid autoproj workspace?"
206
+ end
207
+ pip_path = File.join(shim_path, 'pip')
208
+ File.open(pip_path, 'w') do |io|
209
+ io.puts "#! /bin/sh"
210
+ io.puts "exec #{python_executable} -m pip \"$@\""
211
+ end
212
+ FileUtils.chmod 0o755, pip_path
213
+ pip_path
214
+ end
215
+
216
+ # Activate configuration for python in the autoproj configuration
217
+ # @return [String,String] python path and python version
218
+ def self.activate_python(ws: Autoproj.workspace,
219
+ bin: nil,
220
+ version: nil)
221
+ bin, version = resolve_python(ws: ws, bin: bin, version: version)
222
+ ws.config.set('python_executable', bin, true)
223
+ ws.config.set('python_version', version, true)
224
+
225
+ ws.osdep_suffixes << "python#{$1}" if version =~ /^([0-9]+)\./
226
+
227
+ rewrite_python_shims(bin, ws.root_dir)
228
+ rewrite_pip_shims(bin, ws.root_dir)
229
+ [bin, version]
230
+ end
231
+
232
+ def self.deactivate_python(ws: Autoproj.workspace)
233
+ remove_python_shims(ws.root_dir)
234
+ remove_pip_shims(ws.root_dir)
235
+ ws.config.reset('python_executable')
236
+ ws.config.reset('python_version')
237
+ end
238
+
239
+ # Allow to update the PYTHONPATH for package if autoproj configuration
240
+ # USE_PYTHON is set to true.
241
+ # Then tries to guess the python binary from Autobuild.programs['python']
242
+ # and system's default setting
243
+ # @param [Autobuild::Package] pkg
244
+ # @param [Autoproj.workspace] ws Autoproj workspace
245
+ # @param [String] bin Path to a custom python version
246
+ # @param [String] version version constraint for python executable
247
+ # @return tuple of [executable, version, site-packages path] if set,
248
+ # otherwise nil
249
+ def self.activate_python_path(pkg,
250
+ ws: Autoproj.workspace,
251
+ bin: nil,
252
+ version: nil)
253
+ return unless ws.config.get('USE_PYTHON', nil)
254
+
255
+ bin, version = resolve_python(ws: ws, bin: bin, version: version)
256
+ path = File.join(pkg.prefix, "lib",
257
+ "python#{version}", "site-packages")
258
+ pkg.env_add_path 'PYTHONPATH', path
259
+
260
+ [bin, version, path]
261
+ end
262
+
263
+ def self.setup_python_configuration_options(ws: Autoproj.workspace)
264
+ ws.config.declare 'USE_PYTHON', 'boolean',
265
+ default: 'no',
266
+ doc: ["Do you want to activate python?"]
267
+
268
+ if ws.config.get("USE_PYTHON")
269
+ unless ws.config.has_value_for?('python_executable')
270
+ remove_python_shims(ws.root_dir)
271
+ remove_pip_shims(ws.root_dir)
272
+ python_bin, = auto_resolve_python(ws: ws)
273
+ end
274
+
275
+ ws.config.declare 'python_executable', 'string',
276
+ default: python_bin.to_s,
277
+ doc: ["Select the path to the python executable"]
278
+
279
+ activate_python(ws: ws)
280
+ else
281
+ deactivate_python(ws: ws)
282
+ end
283
+ end
284
+ end
285
+ end
@@ -1,3 +1,3 @@
1
1
  module Autoproj
2
- VERSION = "2.13.0"
2
+ VERSION = "2.14.0"
3
3
  end
@@ -348,7 +348,11 @@ module Autoproj
348
348
  osdep_suffixes << ruby_version_keyword
349
349
  end
350
350
 
351
- def setup
351
+ # Perform initial configuration load and workspace setup
352
+ #
353
+ # @param [Boolean] load_global_configuration if true, load the global
354
+ # autoprojrc file if it exists. Otherwise, ignore it.
355
+ def setup(load_global_configuration: true)
352
356
  setup_ruby_version_handling
353
357
  migrate_bundler_and_autoproj_gem_layout
354
358
  load_config
@@ -358,7 +362,7 @@ module Autoproj
358
362
  config.validate_ruby_executable
359
363
  Autobuild.programs['ruby'] = config.ruby_executable
360
364
  config.apply_autobuild_configuration
361
- load_autoprojrc
365
+ load_autoprojrc if load_global_configuration
362
366
  load_main_initrb
363
367
  config.each_reused_autoproj_installation do |p|
364
368
  manifest.reuse(p)
@@ -803,6 +807,20 @@ module Autoproj
803
807
  full_env = self.full_env
804
808
  changed = save_cached_env(full_env)
805
809
  full_env.export_env_sh(shell_helpers: shell_helpers)
810
+
811
+ build_dir = Pathname(self.build_dir)
812
+ full_env.each_env_filename do |_, filename|
813
+ basename = File.basename(filename)
814
+ File.open(File.join(prefix_dir, basename), "w") do |io|
815
+ io.puts "source \"#{filename}\""
816
+ end
817
+ if build_dir.absolute?
818
+ build_dir.mkpath
819
+ (build_dir + basename).open("w") do |io|
820
+ io.puts "source \"#{filename}\""
821
+ end
822
+ end
823
+ end
806
824
  changed
807
825
  end
808
826
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: autoproj
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.13.0
4
+ version: 2.14.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sylvain Joyeux
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-07-15 00:00:00.000000000 Z
11
+ date: 2021-09-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -394,6 +394,7 @@ files:
394
394
  - lib/autoproj/package_manifest.rb
395
395
  - lib/autoproj/package_selection.rb
396
396
  - lib/autoproj/package_set.rb
397
+ - lib/autoproj/python.rb
397
398
  - lib/autoproj/query_base.rb
398
399
  - lib/autoproj/reporter.rb
399
400
  - lib/autoproj/repository_managers/apt.rb