squared 0.6.4 → 0.6.6

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.
@@ -7,9 +7,9 @@ module Squared
7
7
  DEP_PYTHON = %w[poetry.lock setup.cfg pyproject.toml setup.py requirements.txt].freeze
8
8
  DIR_PYTHON = (DEP_PYTHON + %w[README.rst]).freeze
9
9
  OPT_PYTHON = {
10
- common: %w[b=+ B d E h i I O P q=+ s S u v=+ x c=q m=b W=b X=q check-hash-based-pycs=b].freeze,
11
- build: %w[n|no-isolation s|sdist x|skip-dependency-check v|verbose w|wheel C|config-setting=q installer=b
12
- o|outdir=p].freeze,
10
+ common: %w[b=+ B d E h i I O P q=+ s S u v=+ V=+ x c=q m=b W=b X=q check-hash-based-pycs=b].freeze,
11
+ build: %w[C=bm n|no-isolation s|sdist x|skip-dependency-check v|verbose w|wheel config-json=q config-setting=q
12
+ installer=b o|outdir=p].freeze,
13
13
  venv: %w[clear copies symlinks system-site-packages upgrade upgrade-deps without-scm-ignore-files without-pip
14
14
  prompt=q].freeze
15
15
  }.freeze
@@ -68,6 +68,7 @@ module Squared
68
68
  sign-with=b u|username=q].freeze
69
69
  }.freeze
70
70
  PASS_PYTHON = {
71
+ python: %w[c v V].freeze,
71
72
  pip: {
72
73
  debug: %w[platform].freeze,
73
74
  install: %w[C config-settings c constraint extra-index-url no-binary only-binary platform
@@ -178,7 +179,7 @@ module Squared
178
179
  indexerror n, list
179
180
  else
180
181
  found |= 2
181
- log.warn "run script #{n} of #{list.size} (out of range)"
182
+ log.warn "run script #{n} of #{list.size}".subhint('out of range')
182
183
  end
183
184
  else
184
185
  case i
@@ -191,18 +192,18 @@ module Squared
191
192
  else
192
193
  raise_error "script: #{val}" if exception
193
194
  found |= 2
194
- log.warn "run script \"#{val}\" (not indexed)"
195
+ log.warn "run script \"#{val}\"".subhint('not indexed')
195
196
  end
196
197
  end
197
198
  end
198
199
  end
199
200
  break
200
201
  end
201
- unless found.anybits?(1)
202
- puts log_message(found == 0 ? Logger::INFO : Logger.WARN,
203
- "no scripts #{found == 0 ? 'found' : 'executed'}",
204
- subject: name, hint: pyprojectfile)
205
- end
202
+ next if found.anybits?(1)
203
+
204
+ puts log_message(found == 0 ? Logger::INFO : Logger.WARN,
205
+ "no scripts #{found == 0 ? 'found' : 'executed'}",
206
+ subject: name, hint: pyprojectfile)
206
207
  end
207
208
  when 'exec'
208
209
  format_desc action, nil, ':|command,args*'
@@ -234,11 +235,12 @@ module Squared
234
235
  when :remove
235
236
  next unless projectpath?(venv)
236
237
 
237
- format_desc action, flag, 'c/reate?,d/epend?'
238
+ format_desc action, flag, 'c/reate?,d/epend?,opts*'
238
239
  task flag do |_, args|
240
+ args = args.to_a
239
241
  rm_rf(venv, verbose: true)
240
- venv_init if has_value?(args = args.to_a, 'c', 'create')
241
- depend if has_value?(args, 'd', 'depend')
242
+ venv_init if has_value!(args, 'c', 'create')
243
+ depend :force, args if has_value!(args, 'd', 'depend')
242
244
  end
243
245
  when :exec
244
246
  format_desc action, flag, 'command,args*'
@@ -286,11 +288,11 @@ module Squared
286
288
  pip(flag, opts: args.to_a, banner: true)
287
289
  end
288
290
  when :reinstall
289
- if venv && projectpath?(venv)
290
- format_desc action, flag
291
- task flag do
292
- ns['venv:remove'].invoke('depend')
293
- end
291
+ next unless venv && projectpath?(venv)
292
+
293
+ format_desc action, flag
294
+ task flag do
295
+ ns['venv:remove'].invoke('depend')
294
296
  end
295
297
  end
296
298
  when 'install'
@@ -309,7 +311,7 @@ module Squared
309
311
  install flag, (case args.strategy
310
312
  when 'eager'
311
313
  'eager'
312
- when /(?:\Aonly-if|needed\z)/
314
+ when /^only-if|needed$/
313
315
  'only-if-needed'
314
316
  end.yield_self do |val|
315
317
  if val
@@ -330,7 +332,7 @@ module Squared
330
332
  end
331
333
  end
332
334
  when 'outdated'
333
- format_desc(action, flag, "eager?,no-deps?,#{shortname('h', 'i', 's', 'd')}",
335
+ format_desc(action, flag, "eager?,no-deps?,#{shortname('h', 'i', 's', 'u', 'd')}",
334
336
  before: ('user?' unless venv))
335
337
  task flag do |_, args|
336
338
  outdated flag, args.to_a
@@ -408,18 +410,28 @@ module Squared
408
410
  def outdated(flag = nil, opts = [], sync: invoked_sync?('outdated', flag))
409
411
  cmd = pip_session 'list --outdated'
410
412
  cmd << if flag
411
- se = has_value!(opts, 's', 'select')
413
+ se = has_value! opts, 's', 'select'
412
414
  ia = has_value!(opts, 'i', 'interactive') && !se
415
+ up = has_value! opts, 'u', 'update'
413
416
  hide = has_value! opts, 'h', 'hide'
414
417
  dryrun = has_value! opts, 'd', 'dry-run'
415
418
  if !sync || stdin?
416
419
  se = false
417
420
  ia = false
418
421
  elsif se || ia
422
+ up = true
419
423
  items = []
420
424
  end
421
425
  '--not-required' if opts.include?('no-deps')
422
426
  else
427
+ if (up = option('u', 'update'))
428
+ flag = case up
429
+ when 'major', 'minor'
430
+ up.to_sym
431
+ else
432
+ :patch
433
+ end
434
+ end
423
435
  '--not-required' unless option('not-required', equals: '0')
424
436
  end
425
437
  cmd << '--local' if option('l', 'local')
@@ -441,11 +453,10 @@ module Squared
441
453
  buffer = []
442
454
  out = ->(val) { sync ? puts(val) : buffer << val }
443
455
  if workspace.windows?
444
- (venv ? command(runenv, cmd) : `#{cmd}`).lines
456
+ (venv ? command(runenv, cmd) : `#{cmd}`).lines(chomp: true)
445
457
  else
446
- IO.popen(runenv || {}, cmd)
458
+ IO.popen(runenv || {}, cmd).readlines(chomp: true)
447
459
  end.each do |line|
448
- line.chomp!
449
460
  next if line.match?(/^[ -]+$/)
450
461
 
451
462
  if start > 0
@@ -506,34 +517,33 @@ module Squared
506
517
  puts buffer
507
518
  end
508
519
  if found > 0
509
- if se
510
- choice('Select a package', items.map(&:first),
511
- multiple: true, force: false, index: true, border: true).map! { |n| items[n.pred].last }
512
- elsif ia
513
- items.map(&:last)
514
- else
515
- case flag
516
- when :major
517
- major + minor + patch
518
- when :minor
519
- minor + patch
520
+ items = if se
521
+ choice('Select a package', items.map(&:first),
522
+ multiple: true, force: false, index: true, border: true).map! { |n| items[n.pred].last }
523
+ elsif ia
524
+ items.map(&:last)
525
+ else
526
+ case flag
527
+ when :major
528
+ major + minor + patch
529
+ when :minor
530
+ minor + patch
531
+ else
532
+ patch
533
+ end
534
+ end
535
+ if up && !items.empty?
536
+ base = %w[eager no-deps]
537
+ base << 'user' unless venv
538
+ opts = (base & opts).map! { |val| val == 'eager' ? "upgrade-strategy=#{val}" : val }
539
+ if dryrun
540
+ opts.map! { |val| fill_option(val) }
541
+ print_run pip_output('install --upgrade', *opts, *items.quote!), false
520
542
  else
521
- patch
543
+ install(:upgrade, opts, packages: items, banner: false)
522
544
  end
523
- end.tap do |packages|
524
- unless packages.empty?
525
- base = %w[eager no-deps]
526
- base << 'user' unless venv
527
- opts = (base & opts).map! { |val| val == 'eager' ? "upgrade-strategy=#{val}" : val }
528
- if dryrun
529
- opts.map! { |val| fill_option(val) }
530
- print_run pip_output('install --upgrade', *opts, *packages.quote!), false
531
- else
532
- install(:upgrade, opts, packages: packages, banner: false)
533
- end
534
- end
535
- print_status(major.size, minor.size, patch.size, from: :outdated)
536
545
  end
546
+ print_status(major.size, minor.size, patch.size, from: :outdated)
537
547
  elsif start == 0 || hide
538
548
  puts 'No updates were found'
539
549
  end
@@ -653,6 +663,27 @@ module Squared
653
663
  run(from: :"#{flag}:publish", interactive: ['Publish', 'N', project])
654
664
  end
655
665
 
666
+ def python(*args, sync: true, banner: verbose?, with: nil, pass: PASS_PYTHON[:python], **kwargs)
667
+ op = OptionPartition.new(session_opts(with, args: args, kwargs: kwargs, pass: pass), OPT_PYTHON[:common],
668
+ session('python', path: venv.nil?),
669
+ project: self, multiple: [/^-c/], single: singleopt(:python), args: true,
670
+ stdin: true)
671
+ op.concat(args)
672
+ if op.include?('-')
673
+ op.exist?(add: true)
674
+ else
675
+ op.append_any { |val| OptionPartition.parse_arg!('c', val) }
676
+ if op.arg?('c')
677
+ op.clear
678
+ else
679
+ op.exist?(add: true, first: true) unless op.arg?('m')
680
+ op.append(escape: kwargs.fetch(:escape, false), quote: kwargs.fetch(:quote, false))
681
+ end
682
+ end
683
+ print_run(op, banner, **kwargs)
684
+ run(sync: sync, banner: banner, exception: kwargs.fetch(:exception, exception), from: :python)
685
+ end
686
+
656
687
  def pip(flag, *args, sync: true, banner: verbose?, with: nil, pass: nil, **kwargs)
657
688
  flag = flag.to_sym
658
689
  pass = PASS_PYTHON[:pip].fetch(pip_install?(flag) ? :install : flag, []) + %w[v verbose] if pass.nil?
@@ -726,29 +757,30 @@ module Squared
726
757
  op.clear
727
758
  end
728
759
  print_run(op, banner, **kwargs)
729
- run(sync: sync, banner: banner, from: :"pip:#{flag}").yield_self { |val| ret || val }
760
+ run(sync: sync, banner: banner, exception: kwargs.fetch(:exception, exception), from: :"pip:#{flag}")
761
+ .yield_self { |val| ret || val }
730
762
  end
731
763
 
732
- def variable_set(key, *val, **, &blk)
764
+ def variable_set(key, *args, **, &blk)
733
765
  if block_given?
734
766
  case key
735
767
  when :dependfile, :venv, :editable
736
- val = block_args val, &blk
768
+ args = block_args args, &blk
737
769
  end
738
770
  end
739
771
  case key
740
772
  when :dependfile
741
- req = basepath(*val)
742
- if (index = DEP_PYTHON.index(req.basename.to_s))
773
+ val = basepath(*args)
774
+ if (index = DEP_PYTHON.index(val.basename.to_s))
743
775
  @dependindex = index
744
- @dependfile = req
776
+ @dependfile = val
745
777
  else
746
- log.warn "variable_set: @#{key}=#{req} (not supported)"
778
+ log.warn "variable_set: @#{key}=#{val} (not supported)"
747
779
  end
748
780
  when :editable
749
- editable_set val.first
781
+ editable_set args.first
750
782
  when :venv
751
- instance_variable_set(:"@#{key}", (basepath(*val) unless val.empty?))
783
+ instance_variable_set(:"@#{key}", (basepath(*args) unless args.empty?))
752
784
  else
753
785
  super
754
786
  end
@@ -775,14 +807,14 @@ module Squared
775
807
  def python_session(*cmd, opts: nil)
776
808
  return session('python', *preopts(quiet: false), *cmd, path: venv.nil?) unless opts
777
809
 
778
- op = OptionPartition.new(opts, OPT_PYTHON[:common], project: self, single: /\A(?:v+|OO)\z/)
810
+ op = OptionPartition.new(opts, OPT_PYTHON[:common], project: self, single: singleopt(:python))
779
811
  [session('python', *op.to_a, *cmd, path: venv.nil?), op.extras]
780
812
  end
781
813
 
782
814
  def poetry_session(*cmd)
783
- session('poetry', *cmd, *preopts).tap do |ret|
784
- option('project', ignore: false) { |val| ret << quote_option('project', basepath(val)) }
785
- end
815
+ ret = session('poetry', *cmd, *preopts)
816
+ option('project', ignore: false) { |val| ret << quote_option('project', basepath(val)) }
817
+ ret
786
818
  end
787
819
 
788
820
  def pdm_session(*cmd, opts: nil)
@@ -849,7 +881,7 @@ module Squared
849
881
  def append_editable(target: @session)
850
882
  return if requirements? && editable == '.'
851
883
 
852
- if (val = option('editable', 'e', target: target, ignore: false))
884
+ if (val = option('e', 'editable', target: target, ignore: false))
853
885
  OptionPartition.delete_key(target, 'e', 'editable')
854
886
  case val
855
887
  when '0', 'false'
@@ -873,7 +905,7 @@ module Squared
873
905
  quote_option 'cache-dir', basepath(val)
874
906
  end
875
907
  end,
876
- option('proxy', target: target) { |val| shell_option('proxy', val) },
908
+ option('proxy', target: target) { |val| quote_option('proxy', val) },
877
909
  option('python', target: target) { |val| quote_option('python', basepath(val)) }
878
910
  ])
879
911
  append_nocolor(target: target)
@@ -947,15 +979,14 @@ module Squared
947
979
  end
948
980
 
949
981
  def pyprojectfile
950
- return @pyprojectfile || nil unless @pyprojectfile.nil?
951
-
952
- @pyprojectfile = (file = basepath(DEP_PYTHON[2])).exist? ? file : false
982
+ @pyprojectfile = basepath!(DEP_PYTHON[2]) || false if @pyprojectfile.nil?
983
+ @pyprojectfile || nil
953
984
  end
954
985
 
955
986
  def singleopt(flag = nil)
956
987
  case flag
957
988
  when :python
958
- /\A(?:v+|q+|b+)\z/
989
+ /\A(?:v+|q+|b+|V+|O+)\z/
959
990
  when :pdm
960
991
  /\Av+\z/
961
992
  when :twine
@@ -966,14 +997,14 @@ module Squared
966
997
  end
967
998
 
968
999
  def preopts(quiet: true)
969
- [].tap do |ret|
970
- case verbose
971
- when FalseClass
972
- ret << '--quiet' if quiet
973
- when Numeric
974
- ret << "-#{'v' * verbose}" if verbose > 0
975
- end
1000
+ ret = []
1001
+ case verbose
1002
+ when FalseClass
1003
+ ret << '--quiet' if quiet
1004
+ when Numeric
1005
+ ret << "-#{'v' * verbose}" if verbose > 0
976
1006
  end
1007
+ ret
977
1008
  end
978
1009
 
979
1010
  def variables
@@ -1006,20 +1037,21 @@ module Squared
1006
1037
  def venv_set(val)
1007
1038
  return unless val
1008
1039
 
1040
+ write = ->(level, hint) { log.add(level, "venv: #{@venv}".subhint(hint)) }
1009
1041
  if val.is_a?(Array)
1010
1042
  val, *opts = val
1011
1043
  @venvopts = opts
1012
1044
  end
1013
- @venv = basepath(val)
1045
+ @venv = basepath val
1014
1046
  if projectpath?(@venv)
1015
1047
  if @venv.exist?
1016
- log.debug "venv found: #{@venv}"
1017
- elsif @path.directory? && !@path.empty?
1048
+ write.call(Logger::DEBUG, 'found')
1049
+ elsif path.directory? && !path.empty?
1018
1050
  @venv.mkpath
1019
- log.info "venv mkdir: #{@venv}"
1051
+ write.call(Logger::INFO, 'mkdir')
1020
1052
  end
1021
1053
  elsif !@venv.directory?
1022
- log.warn "venv invalid: #{@venv}"
1054
+ write.call(Logger::WARN, 'invalid')
1023
1055
  @venv = nil
1024
1056
  end
1025
1057
  end
@@ -1027,20 +1059,21 @@ module Squared
1027
1059
  def venv_init
1028
1060
  return if !venv || (venvbin.directory? && !venvbin.empty?)
1029
1061
 
1030
- puts log_message(venv, subject: 'venv', hint: 'init')
1062
+ puts log_message(venv, subject: 'venv', hint: 'init') unless silent?
1031
1063
  opts = @venvopts&.map { |val| OptionPartition.strip(val) }&.flatten
1032
1064
  venv_create(venv, opts || ["prompt=#{name}", 'upgrade-deps'], env: false, banner: false)
1033
- puts log_message(venv, subject: 'venv', hint: 'created')
1065
+ puts log_message(venv, subject: 'venv', hint: 'created') unless silent?
1034
1066
  end
1035
1067
 
1036
- def venv_create(dir, opts = [], env: nil, banner: true)
1068
+ def venv_create(dir, opts = [], env: nil, banner: banner?)
1037
1069
  cmd, opts = python_session('-m venv', opts: opts)
1038
1070
  op = OptionPartition.new(opts, OPT_PYTHON[:venv], cmd, project: self)
1039
1071
  status = op.append(dir, delim: true)
1040
1072
  .clear(pass: false)
1041
1073
  .arg?(/\A-v+\z/)
1042
- run(op, env, exception: true, banner: banner)
1043
- puts(dir.directory? ? "Success: #{dir}" : 'Failed') if banner && !status
1074
+ success?(run(op, env, exception: true, banner: banner), banner, !status) do |ret|
1075
+ puts(ret && dir.directory? ? "Success: #{dir}" : 'Failed')
1076
+ end
1044
1077
  end
1045
1078
 
1046
1079
  def pip_install?(flag)
@@ -1061,7 +1094,7 @@ module Squared
1061
1094
  end
1062
1095
 
1063
1096
  def installable?
1064
- setuptools? || !pyprojectfile.nil?
1097
+ setuptools? || !!pyprojectfile
1065
1098
  end
1066
1099
 
1067
1100
  def setuptools?