squared 0.8.2 → 0.8.4

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.
@@ -18,6 +18,7 @@ module Squared
18
18
  pack: %w[ignore-scripts=!? json=!? pack-destination=p].freeze,
19
19
  rebuild: %w[bin-links=! foreground-scripts=!? global=!? ignore-scripts=!? install-links=!?].freeze,
20
20
  'approve-scripts': %w[a|all allow-scripts-pending allow-scripts-pin=!? no-allow-scripts-pin json].freeze,
21
+ 'deny-scripts': %w[a|all json].freeze,
21
22
  no: {
22
23
  install: %w[audit bin-links fund package-lock].freeze
23
24
  }.freeze
@@ -254,7 +255,8 @@ module Squared
254
255
  when 'exec'
255
256
  format_desc action, nil, 'pkg/cmd,opts*,args*'
256
257
  task action, [:package] do |_, args|
257
- if (package = args.package)
258
+ package = args.package
259
+ if package
258
260
  args = args.extras
259
261
  cmd = if pnpm?
260
262
  pre = ->(ch) { "-#{ch}" if args.delete(ch) }
@@ -267,9 +269,10 @@ module Squared
267
269
  op = OptionPartition.new(args, list, cmd, project: self, strict: strict?)
268
270
  if op.empty?
269
271
  op << package
270
- if (args = readline('Enter arguments', force: false))
272
+ s = readline('Enter arguments', force: false)
273
+ if s
271
274
  op.delim unless pnpm?
272
- op << args
275
+ op << s
273
276
  end
274
277
  else
275
278
  op.delim unless pnpm?
@@ -281,20 +284,21 @@ module Squared
281
284
  run(from: :exec)
282
285
  end
283
286
  when 'nvm'
284
- next unless ENV['NVM_DIR'] && !workspace.windows?
287
+ next unless ENV['NVM_DIR'] && !windows?
285
288
 
286
289
  format_desc action, nil, 'version?,args*'
287
290
  task action, [:version] do |_, args|
288
- path = ->(s) { File.join(ENV['NVM_DIR'], s) }
289
- unless (version = args.version)
290
- cmd = ". #{path.call('nvm.sh')} && nvm list --no-colors --no-alias"
291
+ version = args.version
292
+ args = args.extras
293
+ append = ->(s) { shell_quote(File.join(ENV['NVM_DIR'], s)) }
294
+ unless version
295
+ cmd = ". #{append.call('nvm.sh')} && nvm list --no-colors --no-alias"
291
296
  version = pwd_set(from: :nvm) do
292
297
  choice_index('Select a version', IO.popen(cmd).map { |line| line[/\s(v\S+)/, 1] }, series: true)
293
298
  end
294
299
  end
295
- args = args.extras
296
300
  args << readline('Enter command', force: true) if args.empty?
297
- args.unshift(path.call('nvm-exec'))
301
+ args.unshift(append.call('nvm-exec'))
298
302
  run(args.join(' '), { 'NODE_VERSION' => version }, banner: false, from: :nvm)
299
303
  end
300
304
  when 'bump'
@@ -325,20 +329,48 @@ module Squared
325
329
  outdated flag, args.to_a
326
330
  end
327
331
  when 'package'
328
- format_desc(action, flag, 'opts*', before: case flag
329
- when :dedupe, :rebuild then nil
330
- when :reinstall then 'f/orce?'
331
- else 'name*'
332
- end)
333
- task flag do |_, args|
334
- package flag, args.to_a
332
+ case flag
333
+ when :approve, :deny
334
+ format_desc action, flag, 'name*|:,opts*'
335
+ task flag do |_, args|
336
+ args = args.to_a
337
+ if choice!(args)
338
+ pwd_set do
339
+ pad = 0
340
+ list = IO.popen(npm_output('approve-scripts --allow-scripts-pending').to_s)
341
+ .each_with_object([]) do |line, out|
342
+ next unless line =~ /^\s+([a-z\d@][^@]*)@(\S+)/
343
+
344
+ pad = [pad, $1.size].max
345
+ out << [$1, $2]
346
+ end
347
+ .map { |name, ver| name.ljust(pad + 4) + ver }
348
+ if list.empty?
349
+ puts log_message('no packages to review', subject: name, hint: "#{flag}-scripts")
350
+ exit 0
351
+ end
352
+ args.concat(choice_index('Select packages', list, multiple: true, column: /^(\S+)/))
353
+ end
354
+ end
355
+ package flag, args
356
+ end
357
+ else
358
+ format_desc(action, flag, 'opts*', before: case flag
359
+ when :dedupe, :rebuild then nil
360
+ when :reinstall then 'f/orce?'
361
+ else 'name*'
362
+ end)
363
+ task flag do |_, args|
364
+ package flag, args.to_a
365
+ end
335
366
  end
336
367
  when 'publish'
337
368
  if flag == :verify
338
369
  format_desc action, flag, 'version?,ext*'
339
370
  task flag, [:version] do |_, args|
371
+ version = args.version
340
372
  ext = args.extras
341
- if (version = args.version)&.match?(/^\.?[a-z]+$/i)
373
+ if version&.match?(/^\.?[a-z]+$/i)
342
374
  ext.unshift(version)
343
375
  version = nil
344
376
  end
@@ -1529,8 +1561,7 @@ module Squared
1529
1561
  next if yarntype(exist: true) == 0
1530
1562
  when /^pnpm/
1531
1563
  next if pnpmtype(exist: true) == 0
1532
- when /^npm/
1533
- nil
1564
+ when /^npm/ then nil
1534
1565
  else
1535
1566
  next
1536
1567
  end
@@ -1584,8 +1615,8 @@ module Squared
1584
1615
  end
1585
1616
 
1586
1617
  def remove_modules(prefix: dependbin)
1587
- modules = basepath 'node_modules'
1588
- return false unless modules.directory? && confirm_basic('Remove?', modules, prefix: prefix)
1618
+ modules = basepath!('node_modules', type: 'd')
1619
+ return false unless modules && confirm_basic('Remove?', modules, prefix: prefix)
1589
1620
 
1590
1621
  modules.rmtree
1591
1622
  rescue Timeout::Error => e
@@ -1640,7 +1671,7 @@ module Squared
1640
1671
  end
1641
1672
 
1642
1673
  def quotepath(name, val)
1643
- if $2.include?(File::SEPARATOR) || (workspace.windows? && val.match?(%r{[\\/]}))
1674
+ if $2.include?(File::SEPARATOR) || (windows? && val.match?(%r{[\\/]}))
1644
1675
  quote_option name, basepath(val)
1645
1676
  else
1646
1677
  shell_option name, val
@@ -36,9 +36,9 @@ module Squared
36
36
  root-user-action=b t|target=p upgrade-strategy=b].freeze,
37
37
  install_a: %w[no-index pre prefer-binary all-releases=b extra-index-url=q f|find-links=q i|index-url=q
38
38
  no-binary=q only-binary=q only-final=b].freeze,
39
- install_b: %w[build-constraint check-build-dependencies no-build-isolation no-clean no-deps require-hashes
40
- use-pep517 c|constraint=p group=q progress-bar=b r|requirement=p requirements-from-script=p
41
- src=p].freeze,
39
+ install_b: %w[check-build-dependencies no-build-isolation no-clean no-deps require-hashes use-pep517
40
+ build-constraint=p c|constraint=p group=q progress-bar=b r|requirement=p
41
+ requirements-from-script=p src=p].freeze,
42
42
  install_c: %w[C|config-settings=q e|editable=v].freeze,
43
43
  install_d: %w[ignore-requires-python uploaded-prior-to=q].freeze,
44
44
  hash: %w[a|algorithm].freeze,
@@ -181,8 +181,8 @@ module Squared
181
181
  format_desc action, nil, "script+|#{indexchar}index+|#,pattern*"
182
182
  task action, [:command] do |_, args|
183
183
  found = 0
184
- %w[tool.poetry.scripts tool.pdm.scripts project.scripts].each_with_index do |table, i|
185
- next if (list = read_pyproject(table)).empty?
184
+ %w[tool.poetry tool.pdm project].each_with_index do |table, i|
185
+ next if (list = read_pyproject("#{table}.scripts")).empty?
186
186
 
187
187
  if args.command == '#'
188
188
  format_list(list, "run[#{indexchar}N]", 'scripts', grep: args.extras, from: pyprojectfile)
@@ -208,7 +208,7 @@ module Squared
208
208
  log.warn "run script #{n} of #{list.size}".subhint('out of range')
209
209
  end
210
210
  else
211
- case i
211
+ case (i > 1 && poetry? ? 0 : i)
212
212
  when 0
213
213
  found |= 1
214
214
  run(session_output('poetry', 'run', val), from: :run)
@@ -236,7 +236,7 @@ module Squared
236
236
  format_desc action, nil, 'command|:,args*'
237
237
  task action do |_, args|
238
238
  args = args.to_a
239
- cmd = if (i = args.delete(':')) && !workspace.windows?
239
+ cmd = if (i = args.delete(':')) && !windows?
240
240
  readline('Enter script', force: true, multiline: %w[## ;])
241
241
  elsif i || args.empty?
242
242
  readline('Enter command', force: true)
@@ -297,7 +297,7 @@ module Squared
297
297
  install flag, ['upgrade', *args.to_a, 'pip']
298
298
  end
299
299
  when :freeze
300
- format_desc action, flag, "file?=#{DEP_PYTHON[4]},u/uninstall,opts*"
300
+ format_desc action, flag, "file?=#{DEP_PYTHON[4]},u/ninstall?,opts*"
301
301
  task flag do |_, args|
302
302
  opts = args.to_a
303
303
  if has_value!(opts, 'u', 'uninstall')
@@ -312,7 +312,7 @@ module Squared
312
312
  end
313
313
  file = pip(flag, opts: opts, banner: requirement.nil?, requirement: requirement)
314
314
  puts File.read(file) unless silent?
315
- if requirement && confirm_basic('Uninstall?', file)
315
+ if requirement && confirm_basic('Uninstall?', file, prefix: 'pip')
316
316
  pip(:uninstall, opts: ['y', "r=#{shell_quote(file)}"])
317
317
  end
318
318
  end
@@ -482,7 +482,7 @@ module Squared
482
482
  :patch
483
483
  end
484
484
  end
485
- '--not-required' if option('not-required', notequals: '0') && !env('PYTHON_DEFAULT')
485
+ '--not-required' if option('not-required', notequals: '0')
486
486
  end
487
487
  cmd << '--local' if option('l', 'local')
488
488
  append_global
@@ -502,7 +502,7 @@ module Squared
502
502
  patch = []
503
503
  buffer = []
504
504
  out = ->(val) { sync ? puts(val) : buffer << val }
505
- if workspace.windows?
505
+ if windows?
506
506
  (venv ? command(runenv, cmd) : `#{cmd}`).lines(chomp: true)
507
507
  else
508
508
  IO.popen(runenv || {}, cmd).readlines(chomp: true)
@@ -607,18 +607,18 @@ module Squared
607
607
  project: self, strict: strict?, single: singleopt(flag))
608
608
  else
609
609
  op = append_pip(flag, opts, pipopts(:install), target: pip_session('install'))
610
- end
611
- case flag
612
- when :editable
613
- op << quote_option('e', op.pop || editable || '.')
614
- op.clear
615
- when :user, :upgrade
616
- op.concat(packages)
617
- raise ArgumentError, message('no packages listed', hint: flag) if op.empty?
610
+ case flag
611
+ when :editable
612
+ op << quote_option('e', op.pop || editable || '.')
613
+ op.clear
614
+ when :user, :upgrade
615
+ op.concat(packages)
616
+ raise ArgumentError, message('no packages listed', hint: flag) if op.empty?
618
617
 
619
- op << "--#{flag}"
620
- op.append
621
- python_session('-m pip', *op.to_a.drop(1)) if workspace.windows?
618
+ op << "--#{flag}"
619
+ op.append
620
+ python_session('-m pip', *op.to_a.drop(1)) if windows?
621
+ end
622
622
  end
623
623
  run(banner: banner, from: :install)
624
624
  end
@@ -723,7 +723,7 @@ module Squared
723
723
  op.clear(pass: false)
724
724
  else
725
725
  if op.empty?
726
- op << "#{dist.call}/*"
726
+ op.add_path(dist.call, '*')
727
727
  else
728
728
  op.add_path
729
729
  end
@@ -796,8 +796,7 @@ module Squared
796
796
 
797
797
  op << (action = op.shift)
798
798
  case action
799
- when 'dir', 'info', 'purge'
800
- nil
799
+ when 'dir', 'info', 'purge' then nil
801
800
  when 'list', 'remove'
802
801
  op.add_first(quote: true)
803
802
  else
@@ -811,8 +810,7 @@ module Squared
811
810
  action = op.shift
812
811
  op << action
813
812
  case action
814
- when 'list', 'edit', 'debug'
815
- nil
813
+ when 'list', 'edit', 'debug' then nil
816
814
  when 'get', 'unset', 'set'
817
815
  op.add_first
818
816
  op.add_first(quote: true, expect: true) if action == 'set'
@@ -923,6 +921,7 @@ module Squared
923
921
  if (target = append_nocolor('no-color', target: [], prefix: 'hatch'))
924
922
  (opts ||= []).concat(target)
925
923
  end
924
+ ENV['HATCH_ENV_TYPE_VIRTUAL_PATH'] ||= venv if venv?
926
925
  create_session('hatch', *cmd, common: OPT_HATCH[:common], opts: opts)
927
926
  end
928
927
 
@@ -1010,7 +1009,7 @@ module Squared
1010
1009
  @build_backend ||= read_pyproject('build-system', 'build-backend') || ''
1011
1010
  end
1012
1011
 
1013
- def read_pyproject(table, key = nil)
1012
+ def read_pyproject(table, *keys)
1014
1013
  return [] unless (file = pyprojectfile)
1015
1014
 
1016
1015
  ret = (@pyproject ||= {})[table]
@@ -1075,7 +1074,11 @@ module Squared
1075
1074
  end
1076
1075
  @pyproject[table] = ret
1077
1076
  end
1078
- key ? ret.find { |val| val.first == key }&.last : ret
1077
+ unless keys.empty?
1078
+ ret.select! { |key,| keys.include?(key) }
1079
+ return ret.first&.last if keys.size == 1
1080
+ end
1081
+ ret
1079
1082
  end
1080
1083
 
1081
1084
  def pyprojectfile
@@ -1089,8 +1092,7 @@ module Squared
1089
1092
  /\A(?:v+|q+|b+|V+|O+)\z/
1090
1093
  when :pdm, :poetry
1091
1094
  /\Av+\z/
1092
- when :twine, :meson
1093
- nil
1095
+ when :twine, :meson then nil
1094
1096
  else
1095
1097
  /\A(?:v+|q+)\z/
1096
1098
  end
@@ -1134,15 +1136,15 @@ module Squared
1134
1136
  def runenv
1135
1137
  return unless venv
1136
1138
 
1137
- if workspace.windows?
1138
- shell_quote(venvbin.join(workspace.powershell? ? 'Activate.ps1' : 'activate.bat'), option: false)
1139
+ if windows?
1140
+ shell_quote(venvbin.join(powershell? ? 'Activate.ps1' : 'activate.bat'), option: false)
1139
1141
  else
1140
1142
  { 'VIRTUAL_ENV' => venv.to_s, 'PATH' => "#{venvbin}:#{ENV['PATH']}" }
1141
1143
  end
1142
1144
  end
1143
1145
 
1144
1146
  def venvbin
1145
- @venv&.join(workspace.windows? ? 'Scripts' : 'bin')
1147
+ @venv&.join(windows? ? 'Scripts' : 'bin')
1146
1148
  end
1147
1149
 
1148
1150
  def editable_set(val)
@@ -1214,7 +1216,22 @@ module Squared
1214
1216
  args << 'setuptools' << 'wheel'
1215
1217
  end
1216
1218
  pip(:install, *args, banner: false) unless args.empty?
1217
- success?(ret, banner, !status) { |out| puts(out && dir.directory? ? "Success: #{dir}" : 'Failed') }
1219
+ success?(ret, banner, !status) do |out|
1220
+ if out && dir.directory?
1221
+ if poetry?
1222
+ dir += (windows? ? 'Scripts/python.exe' : 'bin/python')
1223
+ cmd = poetry_session 'env use'
1224
+ else
1225
+ puts "Success: #{dir}"
1226
+ return
1227
+ end
1228
+ cmd << shell_quote(dir)
1229
+ print_run cmd, silent?
1230
+ run(banner: false)
1231
+ else
1232
+ puts 'Failed'
1233
+ end
1234
+ end
1218
1235
  end
1219
1236
 
1220
1237
  def venv_package?(val)
@@ -26,14 +26,14 @@ module Squared
26
26
  rbs: %w[I=pm r=bm no-collection no-stdlib collection=p log-level=b log-output=p repo=p].freeze,
27
27
  rubocop: %w[D P r=bm auto-gen-config a|autocorrect A|autocorrect-all d|debug disable-pending-cops
28
28
  display-only-correctable display-only-fail-level-offenses display-only-failed
29
- display-only-safe-correctable S|display-style-guide display-time editor-mode enable-pending-cops
30
- E|extra-details F|fail-fast force-default-config force-exclusion x|fix-layout
29
+ display-only-safe-correctable S|display-style-guide display-time disable-uncorrectable editor-mode
30
+ enable-pending-cops E|extra-details F|fail-fast force-default-config force-exclusion x|fix-layout
31
31
  ignore-disable-comments ignore-parent-exclusion ignore-unrecognized-cops init l|lint
32
- L|list-target-files lsp memory no-detach only-guide-cops only-recognized-file-types
33
- no-exclude-limit profile raise-cop-error regenerate-todo restart-server safe server-status
34
- start-server stderr stop-server C|cache=b cache-root=p config=p exclude-limit=i fail-level=b
35
- f|format=b except=q only=q o|out=p plugin=p require=p show-cops=q show-docs-url=q
36
- s|stdin=p].freeze,
32
+ list-enabled-cops-for=p L|list-target-files lsp memory no-detach only-guide-cops
33
+ only-recognized-file-types no-exclude-limit profile raise-cop-error regenerate-todo
34
+ restart-server safe server-status start-server stderr stop-server C|cache=b cache-root=p config=p
35
+ exclude-limit=i fail-level=b f|format=b except=q only=q o|out=p plugin=p require=p show-cops=q
36
+ show-docs-url=q s|stdin=p].freeze,
37
37
  pry: %w[f e=q I=pm no-color no-history no-multiline no-pager no-plugins simple-prompt c|context=q
38
38
  d|disable-plugin=q gem=b r|require=bm s|select-plugin=q].freeze,
39
39
  no: {
@@ -511,8 +511,7 @@ module Squared
511
511
  opts << 'redownload' if has_value!(opts, 'f', 'force')
512
512
  if (lock = basepath!('Gemfile.lock'))
513
513
  case (val = ENV['BUNDLE_FROZEN'])
514
- when '0', 'false'
515
- nil
514
+ when '0', 'false' then nil
516
515
  else
517
516
  if val
518
517
  print_error("BUNDLE_FROZEN: #{val}", loglevel: Logger::INFO, subject: name, hint: flag)
@@ -542,8 +541,9 @@ module Squared
542
541
  when :file
543
542
  format_desc action, flag, 'path,opts*,args*'
544
543
  task flag, [:rb] do |_, args|
544
+ file = args.rb
545
545
  opts = args.extras
546
- args = Array(if (file = args.rb) && !file.include?('*')
546
+ args = Array(if file && !file.include?('*')
547
547
  ENV['RUBY_ARGS']
548
548
  else
549
549
  a, b, c = choice_index('Select a file', Dir.glob(file || '*.rb', base: path),
@@ -651,7 +651,7 @@ module Squared
651
651
  ver = nil
652
652
  `ruby --version`
653
653
  end)
654
- unless workspace.windows?
654
+ unless windows?
655
655
  if vm
656
656
  out << trim.call(case vm
657
657
  when 'chruby'
@@ -783,8 +783,7 @@ module Squared
783
783
  next if val == '0' || val == 'false'
784
784
 
785
785
  run(bundle_output('binstubs --all', case val
786
- when '1', 'true'
787
- nil
786
+ when '1', 'true' then nil
788
787
  else
789
788
  if val.start_with?('~')
790
789
  val = File.join(Dir.home, val == '~' ? '.bundle' : val[1..-1])
@@ -1076,6 +1075,7 @@ module Squared
1076
1075
  filter = kwargs.fetch(:filter, {})
1077
1076
  semver = filter[:semver]
1078
1077
  equals = filter[:equals]
1078
+ dryrun = filter[:dryrun] || dryrun?(prefix: 'gem')
1079
1079
  update = if sync && filter[:select]
1080
1080
  semver ||= 'major'
1081
1081
  items = []
@@ -1232,7 +1232,7 @@ module Squared
1232
1232
  'user-install'
1233
1233
  end
1234
1234
  end
1235
- if filter[:dryrun]
1235
+ if dryrun
1236
1236
  print_run gem_output('update -f', *update.quote!(escape: true)), false
1237
1237
  else
1238
1238
  gem(:update, *update, opts: opts)
@@ -1275,9 +1275,9 @@ module Squared
1275
1275
  .clear(pass: false)
1276
1276
  end
1277
1277
  when :push
1278
- target = gemname
1279
- if op.empty? || (n = op.index(':'))
1280
- file = basepath(if !n && (spec = gemspec)
1278
+ target = nil
1279
+ if op.empty? || ia
1280
+ file = basepath(if !ia && (spec = gemspec)
1281
1281
  "#{spec.name}-#{spec.version}.gem"
1282
1282
  else
1283
1283
  choice_index 'Select a file', Dir.glob('*.gem', base: path)
@@ -1296,7 +1296,7 @@ module Squared
1296
1296
 
1297
1297
  op.add_path(file)
1298
1298
  end
1299
- return run(from: from, interactive: ['Push', 'N', target]) unless with || !banner
1299
+ return run(from: from, interactive: ['Push', 'N', target || gemname]) unless with || !banner
1300
1300
  when :exec
1301
1301
  min = if op.arg?('g', 'gem')
1302
1302
  1
@@ -1582,12 +1582,12 @@ module Squared
1582
1582
  def rdbg(*args, banner: verbose?, with: nil, pass: PASS_RUBY[:rdbg], **kwargs)
1583
1583
  opts = session_opts(with, args: args, kwargs: kwargs, pass: pass)
1584
1584
  cmd = session 'rdbg'
1585
- args.each_with_index do |val, index|
1585
+ args.each_with_index do |val, i|
1586
1586
  break if val == '--'
1587
1587
  next unless exist?(val, type: 'f')
1588
1588
 
1589
- args[index] = shell_quote basepath(val)
1590
- cmd.merge(args.slice!(0, index + 1))
1589
+ args[i] = shell_quote basepath(val)
1590
+ cmd.merge(args.slice!(0, i.succ))
1591
1591
  break
1592
1592
  end
1593
1593
  op = OptionPartition.new(opts, OPT_RUBY[:rdbg], cmd, project: self, strict: strict?, first: [/\.rb$/])
@@ -1686,11 +1686,11 @@ module Squared
1686
1686
 
1687
1687
  def vmname(bin: false)
1688
1688
  order = { 'rbenv' => -1, 'rvm' => -1, 'chruby' => -1, 'asdf' => -1, 'mise' => -1 }
1689
- ENV.fetch('PATH', '').split(':').each_with_index do |val, index|
1689
+ ENV.fetch('PATH', '').split(':').each_with_index do |val, i|
1690
1690
  order.each_key do |key|
1691
1691
  next unless val.match?(%r{[/.]#{key}/})
1692
1692
 
1693
- order[key] = index
1693
+ order[key] = i
1694
1694
  break
1695
1695
  end
1696
1696
  end
@@ -1939,8 +1939,7 @@ module Squared
1939
1939
  val = case (val = $2)
1940
1940
  when 'true'
1941
1941
  true
1942
- when '', '[]'
1943
- nil
1942
+ when '', '[]' then nil
1944
1943
  else
1945
1944
  if val =~ /\A\[:(.+)\]\z/
1946
1945
  $1.split(', :').map { |s| (s[/\A"(.+)"\z/, 1] || s).to_sym }