squared 0.1.3 → 0.2.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.
@@ -5,21 +5,29 @@ module Squared
5
5
  module Project
6
6
  class Python < Git
7
7
  REQUIREMENTS = %w[requirements.txt pyproject.toml setup.py].freeze
8
- OPT_USER = %w[pre dry-run].freeze
9
- OPT_FORCE = (OPT_USER + ['user']).freeze
10
- OPT_GENERAL = %w{venv isolated no-cache-dir [v]erbose}.freeze
11
- private_constant :REQUIREMENTS, :OPT_USER, :OPT_FORCE, :OPT_GENERAL
8
+ OPT_INSTALL = %w[I U break-system-packages check-build-dependencies compile dry-run force-reinstall
9
+ ignore-installed ignore-requires-python no-build-isolation no-clean no-compile no-deps
10
+ no-index no-warn-conflicts no-warn-script-location pre prefer-binary require-hashes upgrade
11
+ use-pep517 user abi=s config-settings=s c=s constraint=s e=s editable=s extra-index-url=s
12
+ f=s find-links=s global-option=s implementation=s i=s index-url=s no-binary=s only-binary=s
13
+ platform=s prefix=s progress-bar=s python-version=s report=s r=s requirement=s
14
+ root-user-action=s root=s src=s t=s target=s upgrade-strategy=s].freeze
15
+ OPT_GENERAL = %w[debug disable-pip-version-check isolated q quiet require-virtualenv v verbose
16
+ no-cache-dir no-color no-input no-python-version-warning
17
+ cache-dir=s cert=s client-cert=s exists-action=s log=s proxy=s python=s retries=i timeout=i
18
+ trusted-host=s use-deprecated=s use-feature=s].freeze
19
+ private_constant :REQUIREMENTS, :OPT_INSTALL, :OPT_GENERAL
12
20
 
13
21
  class << self
14
22
  def populate(*); end
15
23
  def batchargs(*); end
16
24
 
17
25
  def tasks
18
- %i[outdated].freeze
26
+ [:outdated].freeze
19
27
  end
20
28
 
21
29
  def bannerargs
22
- %i[dependfile].freeze
30
+ [:dependfile].freeze
23
31
  end
24
32
 
25
33
  def venv?
@@ -47,40 +55,38 @@ module Squared
47
55
  end
48
56
 
49
57
  @@tasks[ref] = {
50
- install: %i[user target upgrade force].freeze
58
+ 'install' => %i[user upgrade force target].freeze
51
59
  }.freeze
52
60
 
53
61
  def ref
54
62
  Python.ref
55
63
  end
56
64
 
57
- def populate(*)
65
+ def populate(*, **)
58
66
  super
59
67
  return unless outdated? && ref?(Python.ref)
60
68
 
61
69
  namespace name do
62
70
  @@tasks[Python.ref].each do |action, flags|
71
+ next if @pass.include?(action)
72
+
63
73
  namespace action do
64
74
  flags.each do |flag|
65
75
  case action
66
- when :install
67
- list = case flag
68
- when :target
69
- req = 'dir'
70
- OPT_USER + %w[upgrade eager]
71
- when :upgrade
72
- OPT_FORCE + ['eager']
73
- when :force
74
- OPT_FORCE
75
- else
76
- OPT_USER
77
- end
78
- list += OPT_GENERAL
79
- desc format_desc(action, flag, list, req: req)
80
- if flag == :target
81
- task flag, [:dir, :opts] do |_, args|
82
- dir = guard_params(action, flag, args: args, key: :dir)
83
- depend(flag, dir: dir, opts: args.to_a.drop(1))
76
+ when 'install'
77
+ if @@task_desc
78
+ format_desc(action, flag, OPT_INSTALL + OPT_GENERAL, before: case flag
79
+ when :target
80
+ 'dir'
81
+ when :upgrade
82
+ 'strategy'
83
+ end)
84
+ end
85
+ case flag
86
+ when :target, :upgrade
87
+ task flag, [:param] do |_, args|
88
+ param = param_guard(action, flag, args: args, key: :param)
89
+ depend(flag, param: param, opts: args.extras)
84
90
  end
85
91
  else
86
92
  task flag do |_, args|
@@ -94,7 +100,7 @@ module Squared
94
100
  end
95
101
  end
96
102
 
97
- def depend(flag = nil, dir: nil, opts: [], sync: invoked_sync?('depend', flag))
103
+ def depend(flag = nil, sync: invoked_sync?('depend', flag), param: nil, opts: [])
98
104
  if @depend && !flag
99
105
  super
100
106
  elsif outdated?
@@ -104,33 +110,117 @@ module Squared
104
110
  case flag
105
111
  when :user
106
112
  cmd << '--user'
107
- append_pip opts, OPT_USER
108
- when :target
109
- cmd << shell_option('target', basepath(dir), quote: true)
110
- append_pip opts, OPT_USER + ['upgrade']
111
- append_eager opts
112
113
  when :upgrade
113
114
  cmd << '--upgrade'
114
- append_pip opts, OPT_FORCE
115
- append_eager opts
115
+ case param
116
+ when 'eager', 'only-if-needed'
117
+ cmd << basic_option('upgrade-strategy', param)
118
+ else
119
+ opts << param
120
+ end
116
121
  when :force
117
122
  cmd << '--force-reinstall'
118
- append_pip opts, OPT_FORCE
123
+ when :target
124
+ cmd << shell_option('target', basepath(param), quote: true)
119
125
  else
120
- append_pip
126
+ append_global
127
+ end
128
+ append_pip opts if flag
129
+ if type == 2
130
+ cmd << '.'
131
+ elsif !cmd.find { |val| val =~ /^(?:-r|--requirement)/ }
132
+ cmd << '-r requirements.txt'
121
133
  end
122
- cmd << (type == 1 ? '-r requirements.txt' : '.')
123
- run(sync: sync)
124
134
  when 3
125
- run_s('python setup.py install', sync: sync)
135
+ cmd = python_session 'setup.py', 'install'
136
+ case flag
137
+ when :user
138
+ cmd << '--user'
139
+ when :target
140
+ cmd << quote_option('build-base', basepath(dir))
141
+ end
142
+ if option('user')
143
+ cmd << '--user'
144
+ else
145
+ append_first(%w[home prefix], equals: true, escape: false, quote: true, ignore: false)
146
+ end
147
+ cmd.delete('--user') if workspace.windows?
126
148
  end
149
+ run(from: :depend, sync: sync)
127
150
  end
128
151
  end
129
152
 
130
153
  def outdated(*, sync: invoked_sync?('outdated'))
131
- pip_session 'list', '--outdated'
132
- append_pip
133
- run(sync: sync)
154
+ cmd = pip_session 'list', '--outdated'
155
+ append_global
156
+ cmd = session_done(cmd)
157
+ log.info cmd
158
+ on :first, :outdated
159
+ banner = format_banner(cmd)
160
+ print_item banner if sync
161
+ start = 0
162
+ found = 0
163
+ major = 0
164
+ pwd_set(from: :outdated) do
165
+ buffer = []
166
+ out = ->(val) { sync ? puts(val) : buffer << val }
167
+ IO.popen(cmd).each do |line|
168
+ next if line =~ /^[\s-]+$/
169
+
170
+ if start > 0
171
+ unless stdin?
172
+ data = line.scan(SEM_VER)
173
+ next unless (cur = data.shift) && (lat = data.shift)
174
+
175
+ latest = lat.join
176
+ current = cur.join
177
+ semver(cur)
178
+ semver(lat)
179
+ if semmajor?(cur, lat)
180
+ type = 2
181
+ major += 1
182
+ else
183
+ type = cur[2] == lat[2] ? 0 : 1
184
+ end
185
+ if type == 0
186
+ styles = color(:yellow)
187
+ else
188
+ styles = color(:green)
189
+ line = sub_style(line, pat: /^(\S+)(.+)$/, styles: if type == 2
190
+ styles << :bold
191
+ theme[:major]
192
+ else
193
+ theme[:active]
194
+ end)
195
+ end
196
+ if theme[:current]
197
+ line = sub_style(line, pat: /^(.+)(#{Regexp.escape(current)})(.+)$/, styles: theme[:current],
198
+ index: 2)
199
+ end
200
+ line = sub_style(line, pat: /^(.+)(#{Regexp.escape(latest)})(.+)$/, styles: styles, index: 2)
201
+ found += 1
202
+ end
203
+ out.("#{start.to_s.rjust(2)}. #{line}")
204
+ start += 1
205
+ elsif line =~ /^Package /
206
+ unless stdin?
207
+ sub = { pat: /^(.*)(?<!\dm)(Package|Latest)(.+)$/, styles: theme[:header], index: 2 }
208
+ out.(print_footer(" # #{line.chomp}", reverse: true, sub: [sub, sub]))
209
+ end
210
+ start += 1
211
+ end
212
+ end
213
+ unless sync
214
+ print_item banner
215
+ puts buffer
216
+ end
217
+ if found > 0
218
+ puts print_footer empty_status('Updates are available', 'major', major)
219
+ elsif start == 0
220
+ puts 'No updates were found'
221
+ end
222
+ end
223
+ on :last, :outdated
134
224
  end
135
225
 
136
226
  def variable_set(key, *val, **)
@@ -162,29 +252,54 @@ module Squared
162
252
  session('pip', *cmd)
163
253
  end
164
254
 
165
- def append_pip(opts = [], list = [])
255
+ def python_session(*cmd)
256
+ session('python', *cmd)
257
+ end
258
+
259
+ def append_pip(opts, list = nil, target: @session)
260
+ append_nocolor(target: target)
261
+ return if opts.empty?
262
+
263
+ out = []
264
+ opts, pat = option_partition(opts, list || (OPT_INSTALL + OPT_GENERAL), target: target)
166
265
  opts.each do |opt|
167
- data = nil
168
- next unless list.include?(opt) || OPT_GENERAL.include?(opt) || (data = opt.match(/^verbose|(v+)$/))
169
-
170
- @session << case opt
171
- when 'venv'
172
- '--require-virtualenv'
173
- else
174
- (data && data[1] ? "-#{data[1]}" : "--#{opt}")
175
- end
266
+ if opt =~ /^(v+|q+)$/
267
+ cmd << "-#{$1}"
268
+ elsif opt =~ pat
269
+ case $1
270
+ when 'root', 'prefix', 'src', 'cert', 'client-cert', 'cache-dir', 'log', 'report',
271
+ 'r', 'requirement', 'c', 'constraint', 't', 'target'
272
+ target << quote_option($1, basepath($2))
273
+ when 'e', 'editable'
274
+ val = $2
275
+ target << quote_option($1, val =~ %r{^[a-z]+\+[a-z]+://} ? val : basepath(val))
276
+ when 'proxy', 'config-settings', 'global-option', 'extra-index-url',
277
+ 'f', 'find-links', 'i', 'index-url'
278
+ target << shell_option($1, $2, quote: true)
279
+ when 'retries', 'timeout'
280
+ target << basic_option($1, $2) if $2.to_i > 0
281
+ else
282
+ target << shell_option($1, $2)
283
+ end
284
+ else
285
+ out << opt
286
+ end
176
287
  end
177
- val = nil
178
- @session << shell_option('proxy', val, quote: true) if (val = option('proxy'))
179
- @session << shell_option('python', basepath(val), quote: true) if (val = option('python'))
180
- @session << shell_option('log', basepath(val), quote: true) if (val = option('log', ignore: false))
181
- @session << '--user' if !list.empty? && option('user')
182
- @session << '--no-input' if option('no-input')
183
- append_nocolor option('no-color')
288
+ option_clear(out, target: target)
184
289
  end
185
290
 
186
- def append_eager(opts)
187
- @session << '--upgrade-strategy=eager' if opts.include?('eager')
291
+ def append_global
292
+ if (val = option('cache-dir'))
293
+ cmd << case val
294
+ when '0', 'false'
295
+ '--no-cache-dir'
296
+ else
297
+ quote_option('cache-dir', basepath(val))
298
+ end
299
+ end
300
+ cmd << shell_option('proxy', val, quote: true) if (val = option('proxy'))
301
+ cmd << quote_option('python', basepath(val)) if (val = option('python'))
302
+ append_nocolor
188
303
  end
189
304
  end
190
305