autoproj 2.13.0 → 2.14.0

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