squared 0.3.10 → 0.4.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.
@@ -4,9 +4,11 @@ module Squared
4
4
  module Workspace
5
5
  module Project
6
6
  class Node < Git
7
+ include Prompt
8
+
7
9
  OPT_NPM = {
8
- common: %w[dry-run include-workspace-root workspaces=b? w|workspace=v].freeze,
9
- install: %w[prefer-dedupe package-lock-only cpu=q libc=e os=q].freeze,
10
+ common: %w[dry-run include-workspace-root workspaces=b? w|workspace=b].freeze,
11
+ install: %w[prefer-dedupe package-lock-only cpu=b libc=b os=b].freeze,
10
12
  install_base: %w[ignore-scripts install-links strict-peer-deps include=b omit=b install-strategy=b].freeze,
11
13
  install_no: %w[audit bin-links fund package-lock].freeze,
12
14
  install_as: %w[foreground-scripts g|global no-save save save-bundle save-dev E|save-exact save-optional
@@ -37,15 +39,14 @@ module Squared
37
39
  no-node-version-check no-progress non-interactive offline pnp prefer-offline prod
38
40
  pure-lockfile skip-integrity-check strict-semver update-checksums cache-folder=p emoji=b?
39
41
  global-folder=p https-proxy=q link-folder=p modules-folder=p mutex=q network-concurrency=i
40
- network-timeout=i preferred-cache-folder=p production=e? proxy=q otp=e registry=q
41
- scripts-prepend-node-path=e?].freeze,
42
- update: %w[A|audit C|caret E|exact L|latest T|tilde P|pattern=q S|scope=e].freeze
42
+ network-timeout=i preferred-cache-folder=p production=b? proxy=q otp=b registry=q].freeze,
43
+ update: %w[A|audit C|caret E|exact L|latest T|tilde P|pattern=q S|scope=b].freeze
43
44
  }.freeze
44
45
  OPT_BERRY = {
45
46
  install: %w[check-cache check-resolutions immutable immutable-cache inline-builds json refresh-lockfile
46
- mode=e].freeze,
47
- update: %w[C|caret E|exact F|fixed interactive T|tilde R|recursive mode=e].freeze,
48
- dedupe: %w[check json mode=e strategy=b].freeze,
47
+ mode=b].freeze,
48
+ update: %w[C|caret E|exact F|fixed interactive T|tilde R|recursive mode=b].freeze,
49
+ dedupe: %w[check json mode=b strategy=b].freeze,
49
50
  pack: %w[n|dry-run install-if-needed json o|out=p].freeze
50
51
  }.freeze
51
52
  private_constant :OPT_NPM, :OPT_PNPM, :OPT_YARN, :OPT_BERRY
@@ -93,12 +94,13 @@ module Squared
93
94
  def initialize(*, **kwargs)
94
95
  super
95
96
  if @pass.include?(Node.ref)
96
- initialize_ref(Node.ref)
97
+ initialize_ref Node.ref
97
98
  initialize_logger(**kwargs)
98
99
  else
99
100
  initialize_build(Node.ref, prod: prod?, **kwargs)
100
101
  initialize_env(**kwargs)
101
102
  end
103
+ @buildtype = :run if script?
102
104
  @pm = {}
103
105
  @dependfile = basepath('package.json')
104
106
  end
@@ -218,26 +220,25 @@ module Squared
218
220
  end
219
221
  end
220
222
 
221
- def copy(from: 'build', into: 'node_modules', workspace: false, scope: nil, also: nil, create: nil,
223
+ def copy(from: 'build', into: 'node_modules', scope: nil, also: nil, create: nil, workspace: false,
222
224
  link: false, force: false, override: false, **kwargs)
223
- return if @copy == false
224
-
225
+ glob = kwargs[:include]
226
+ pass = kwargs[:exclude]
225
227
  if @copy && !override
226
- return super if runnable?(@copy)
228
+ return super unless @copy.is_a?(Hash)
227
229
 
228
230
  from = @copy[:from] if @copy.key?(:from)
229
231
  into = @copy[:into] if @copy.key?(:into)
230
232
  workspace = @copy[:workspace] if @copy.key?(:workspace)
231
233
  link = @copy[:link] if @copy.key?(:link)
232
- force = @copy[:force] if @copy.key?(:link)
233
- glob = @copy[:include]
234
- exclude = @copy[:exclude]
235
- scope = @copy[:scope]
236
- also = @copy[:also]
237
- create = @copy[:create]
238
- else
239
- glob = kwargs[:include]
240
- exclude = kwargs[:exclude]
234
+ force = @copy[:force] if @copy.key?(:force)
235
+ scope = @copy[:scope] if @copy.key?(:scope)
236
+ also = @copy[:also] if @copy.key?(:also)
237
+ create = @copy[:create] if @copy.key?(:create)
238
+ glob = @copy[:include] if @copy.key?(:include)
239
+ pass = @copy[:exclude] if @copy.key?(:exclude)
240
+ elsif @copy == false
241
+ return
241
242
  end
242
243
  items = []
243
244
  items << @workspace.home if build? && path != @workspace.home && @workspace.home?
@@ -256,8 +257,6 @@ module Squared
256
257
  dest = @workspace.find(name: dir)&.path
257
258
  log.warn message("copy project :#{dir}", hint: 'not found') unless dest
258
259
  when Hash
259
- glob = dir[:include]
260
- exclude = dir[:exclude]
261
260
  from = dir[:from] if dir.key?(:from)
262
261
  into = dir[:into] if dir.key?(:into)
263
262
  scope = dir[:scope] if dir.key?(:scope)
@@ -266,11 +265,13 @@ module Squared
266
265
  dest = dir[:target]
267
266
  create = dir[:create]
268
267
  workspace = dir[:workspace]
268
+ glob = dir[:include]
269
+ pass = dir[:exclude]
269
270
  dest = items.first unless dest && dest != true
270
271
  when Project::Base
271
272
  dest = dir.path
272
273
  else
273
- raise_error("given: #{dir}", hint: 'unknown')
274
+ raise_error "copy given: #{dir}"
274
275
  end
275
276
  next unless from && dest&.directory?
276
277
 
@@ -305,7 +306,7 @@ module Squared
305
306
  target.each do |src, to|
306
307
  glob.each { |val| log.info "cp #{from.join(val)} #{to}" }
307
308
  begin
308
- copy_dir(src, to, glob, create: create, link: link, force: force, pass: exclude, verbose: verbose)
309
+ copy_dir(src, to, glob, create: create, link: link, force: force, pass: pass, verbose: verbose)
309
310
  rescue StandardError => e
310
311
  log.error e
311
312
  ret = on(:error, :copy, e)
@@ -320,6 +321,7 @@ module Squared
320
321
  if @depend && !flag
321
322
  super
322
323
  elsif outdated?
324
+ workspace.rev_clear name
323
325
  return update if !flag && env('NODE_UPDATE')
324
326
 
325
327
  if (yarn = dependtype(:yarn)) > 0
@@ -387,7 +389,7 @@ module Squared
387
389
  ret = on(:error, :outdated, e)
388
390
  raise if exception && ret != true
389
391
  end
390
- warn log_message(Logger::WARN, e) if warning?
392
+ warn log_message(Logger::WARN, e, pass: true) if warning?
391
393
  return
392
394
  else
393
395
  dep1 = json['dependencies'] || {}
@@ -405,7 +407,7 @@ module Squared
405
407
 
406
408
  latest = val['latest']
407
409
  ch = file[0]
408
- if ch =~ /[~^]/
410
+ if ch.match?(/[~^]/)
409
411
  file = file[1..-1]
410
412
  elsif inter && rev == :major
411
413
  major = true
@@ -414,7 +416,7 @@ module Squared
414
416
  next
415
417
  end
416
418
  current = val['current'] || file
417
- want = rev == :major && (ver = latest.match(SEM_VER)) && !ver[6] ? latest : val['wanted']
419
+ want = rev == :major && !latest[SEM_VER, 6] ? latest : val['wanted']
418
420
  next unless (current != want || file != want) && (want.match?(SEM_VER) || !file.match?(SEM_VER))
419
421
 
420
422
  f = semscan(file)
@@ -540,7 +542,9 @@ module Squared
540
542
 
541
543
  def publish(flag = nil, *, sync: invoked_sync?('publish', flag), otp: nil, tag: nil, dryrun: nil, **)
542
544
  if read_packagemanager(:private)
543
- warn log_message(Logger::WARN, 'invalid task "publish"', subject: name, hint: 'private') if warning?
545
+ if warning?
546
+ warn log_message(Logger::WARN, 'invalid task "publish"', subject: name, hint: 'private', pass: true)
547
+ end
544
548
  return
545
549
  end
546
550
  return unless version
@@ -564,7 +568,7 @@ module Squared
564
568
  banner = format_banner(cmd.to_s)
565
569
  Open3.popen2e(cmd.done) do |_, out|
566
570
  write_lines(out, banner: banner, sub: npmnotice + [
567
- { pat: /^(.+)(Tarball .+)$/, styles: :blue, index: 2 }
571
+ { pat: /^(.+)(Tarball .+)$/, styles: color(:blue), index: 2 }
568
572
  ])
569
573
  end
570
574
  end
@@ -676,7 +680,7 @@ module Squared
676
680
  end
677
681
  on :last, :bump unless dryrun?
678
682
  else
679
- raise_error('not found', hint: 'version')
683
+ raise_error('version not found', hint: dependfile)
680
684
  end
681
685
  rescue StandardError => e
682
686
  log.debug e
@@ -699,26 +703,26 @@ module Squared
699
703
  run(from: :pack)
700
704
  end
701
705
 
702
- def compose(opts, flags = nil, script: false, args: nil, from: nil, **)
703
- return unless opts
706
+ def compose(target, opts = nil, script: false, args: nil, from: :run, **)
707
+ return unless target
704
708
 
705
709
  if script
706
710
  ret = session dependbin, 'run'
707
- raise_error("#{dependbin} run script: given #{opts}", hint: from) unless append_any(opts)
708
- append_any flags if flags
711
+ raise_error("#{dependbin} run: given #{target}", hint: from) unless append_any(target, build: true)
712
+ append_any opts if opts
709
713
  append_loglevel
710
714
  append_any(args, delim: true) if args
711
715
  ret
712
716
  else
713
- case opts
717
+ case target
714
718
  when String
715
- opts
719
+ target
716
720
  when Hash
717
- append_hash(opts).join(' ')
721
+ append_hash(target).join(' ')
718
722
  when Enumerable
719
- opts.to_a.join(' ')
723
+ target.to_a.join(' ')
720
724
  else
721
- raise_error("#{project}: given #{opts}", hint: from)
725
+ raise_error("compose given: #{target}", hint: from)
722
726
  end
723
727
  end
724
728
  end
@@ -727,10 +731,6 @@ module Squared
727
731
  @depend != false && (!@depend.nil? || outdated?)
728
732
  end
729
733
 
730
- def copy?
731
- super || @copy.is_a?(Hash)
732
- end
733
-
734
734
  def outdated?
735
735
  dependfile.exist?
736
736
  end
@@ -740,8 +740,8 @@ module Squared
740
740
  end
741
741
 
742
742
  def yarn?
743
- (@pm[:yarn] ||= if basepath('yarn.lock', ascend: dependext).exist?
744
- if (rc = basepath('.yarnrc.yml', ascend: dependext)).exist?
743
+ (@pm[:yarn] ||= if rootpath('yarn.lock', ascend: dependext).exist?
744
+ if (rc = rootpath('.yarnrc.yml', ascend: dependext)).exist?
745
745
  begin
746
746
  require 'yaml'
747
747
  doc = YAML.load_file(rc)
@@ -761,7 +761,7 @@ module Squared
761
761
  end
762
762
 
763
763
  def pnpm?
764
- (@pm[:pnpm] ||= if basepath('pnpm-lock.yaml', ascend: dependext).exist?
764
+ (@pm[:pnpm] ||= if rootpath('pnpm-lock.yaml', ascend: dependext).exist?
765
765
  begin
766
766
  require 'yaml'
767
767
  doc = YAML.load_file(basepath('node_modules/.modules.yaml', ascend: dependext))
@@ -913,9 +913,9 @@ module Squared
913
913
 
914
914
  def npmnotice
915
915
  [
916
- { pat: /^(npm error )(code|\d+)(.+)$/, styles: :cyan, index: 2 },
917
- { pat: /^(npm )(error)(.*)$/, styles: :red, index: 2 },
918
- { pat: /^(npm )(notice)(.*)$/, styles: :cyan, index: 2 },
916
+ { pat: /^(npm error )(code|\d+)(.+)$/, styles: color(:cyan), index: 2 },
917
+ { pat: /^(npm )(error)(.*)$/, styles: color(:red), index: 2 },
918
+ { pat: /^(npm )(notice)(.*)$/, styles: color(:cyan), index: 2 },
919
919
  { pat: /^(npm )(.+)$/, styles: :bold }
920
920
  ]
921
921
  end
@@ -4,22 +4,39 @@ module Squared
4
4
  module Workspace
5
5
  module Project
6
6
  class Python < Git
7
- REQUIREMENTS = %w[requirements.txt pyproject.toml].freeze
7
+ REQUIREMENTS = %w[requirements.txt pyproject.toml setup.cfg].freeze
8
8
  SETUPTOOLS = %w[setup.py pyproject.toml].freeze
9
9
  DIR_PYTHON = (REQUIREMENTS + SETUPTOOLS).freeze
10
+ OPT_PYTHON = {
11
+ common: %w[b B d E h i I O OO P q s S u v x c=q m=b W=b X=q check-hash-based-pycs=b].freeze,
12
+ build: %w[n|no-isolation s|sdist v|verbose w|wheel x|skip-dependency-check C|config-setting=q installer=b
13
+ o|outdir=p].freeze
14
+ }.freeze
10
15
  OPT_PIP = {
11
16
  common: %w[debug disable-pip-version-check isolated no-cache-dir no-color no-input no-python-version-warning
12
17
  q|quiet require-virtualenv v|verbose cache-dir=p cert=p client-cert=p exists-action=b log=p
13
- proxy=q python=e retries=i timeout=i trusted-host=e use-deprecated=e use-feature=e].freeze,
18
+ proxy=q python=q retries=i timeout=i trusted-host=b use-deprecated=b use-feature=b].freeze,
14
19
  install: %w[break-system-packages check-build-dependencies compile dry-run force-reinstall I|ignore-installed
15
20
  ignore-requires-python no-build-isolation no-clean no-compile no-deps no-index no-warn-conflicts
16
- no-warn-script-location pre prefer-binary require-hashes U|upgrade use-pep517 user abi=e
17
- config-settings=q c|constraint=p e|editable=v? extra-index-url=q f|find-links=q global-option=q
21
+ no-warn-script-location pre prefer-binary require-hashes U|upgrade use-pep517 user abi=b
22
+ config-settings=q c|constraint=p e|editable=b? extra-index-url=q f|find-links=q global-option=q
18
23
  implementation=b i|index-url=q no-binary=q only-binary=q platform=q prefix=p progress-bar=b
19
- python-version=q report=p r|requirement=p root=p root-user-action=e src=p t|target=p
24
+ python-version=q report=p r|requirement=p root=p root-user-action=b src=p t|target=p
20
25
  upgrade-strategy=b].freeze
21
26
  }.freeze
22
- private_constant :REQUIREMENTS, :SETUPTOOLS, :DIR_PYTHON, :OPT_PIP
27
+ OPT_HATCH = {
28
+ common: %w[color interactive no-color no-interactive cache-dir=p config=p data-dir=p e|env=b p|project=e
29
+ q|quiet v|verbose].freeze,
30
+ build: %w[clean-hooks-after ext hooks-only no-hooks c|clean t|target=b].freeze,
31
+ publish: %w[initialize-auth n|no-prompt y|yes a|auth=q ca-cert=p client-cert=p client-key=p o|option=q
32
+ p|publisher=b r|repo=b u|user=q].freeze
33
+ }.freeze
34
+ OPT_TWINE = {
35
+ publish: %w[attestations disable-progress-bar non-interactive skip-existing verbose s|sign c|comment=q
36
+ config-file=p cert=p client-cert=p i|identity=b p|password=q r|repository=b repository-url=q
37
+ sign-with=b u|username=q].freeze
38
+ }.freeze
39
+ private_constant :REQUIREMENTS, :SETUPTOOLS, :DIR_PYTHON, :OPT_PYTHON, :OPT_PIP, :OPT_HATCH, :OPT_TWINE
23
40
 
24
41
  class << self
25
42
  def populate(*); end
@@ -47,7 +64,7 @@ module Squared
47
64
  def initialize(*, **kwargs)
48
65
  super
49
66
  if @pass.include?(Python.ref)
50
- initialize_ref(Python.ref)
67
+ initialize_ref Python.ref
51
68
  initialize_logger(**kwargs)
52
69
  else
53
70
  initialize_build(Python.ref, **kwargs)
@@ -58,7 +75,9 @@ module Squared
58
75
  end
59
76
 
60
77
  @@tasks[ref] = {
61
- 'install' => %i[user force upgrade target editable].freeze
78
+ 'install' => %i[user force upgrade target editable].freeze,
79
+ 'build' => %i[python hatch].freeze,
80
+ 'publish' => %i[twine hatch].freeze
62
81
  }.freeze
63
82
 
64
83
  def ref
@@ -111,6 +130,16 @@ module Squared
111
130
  depend flag, args.to_a
112
131
  end
113
132
  end
133
+ when 'build'
134
+ format_desc(action, flag, 'opts*', after: flag == :hatch ? 'location?' : 'srcdir?')
135
+ task flag do |_, args|
136
+ buildx flag, args.to_a
137
+ end
138
+ when 'publish'
139
+ format_desc(action, flag, 'opts*', after: flag == :hatch ? 'artifacts?' : 'dist?')
140
+ task flag do |_, args|
141
+ publish flag, args.to_a
142
+ end
114
143
  end
115
144
  end
116
145
  end
@@ -122,6 +151,7 @@ module Squared
122
151
  if @depend && !flag
123
152
  super
124
153
  elsif outdated?
154
+ workspace.rev_clear name
125
155
  cmd = pip_session 'install'
126
156
  case flag
127
157
  when :user
@@ -143,21 +173,6 @@ module Squared
143
173
  end
144
174
  end
145
175
 
146
- def install(flag, opts, strategy: nil)
147
- cmd = pip_session 'install'
148
- out = append_pip(flag, opts, from: :install)
149
- case flag
150
- when :editable
151
- cmd << '--editable' << (out.pop || '.')
152
- option_clear out
153
- when :upgrade
154
- cmd << '--upgrade'
155
- cmd << basic_option('upgrade-strategy', strategy) if strategy
156
- append_value out
157
- end
158
- run(from: :install)
159
- end
160
-
161
176
  def outdated(*, sync: invoked_sync?('outdated'))
162
177
  cmd = pip_session 'list', '--outdated'
163
178
  append_global
@@ -173,7 +188,7 @@ module Squared
173
188
  buffer = []
174
189
  out = ->(val) { sync ? puts(val) : buffer << val }
175
190
  IO.popen(cmd).each do |line|
176
- next if line =~ /^[\s-]+$/
191
+ next if line.match?(/^[\s-]+$/)
177
192
 
178
193
  if start > 0
179
194
  unless stdin?
@@ -210,7 +225,7 @@ module Squared
210
225
  end
211
226
  out.("#{start.to_s.rjust(2)}. #{line}")
212
227
  start += 1
213
- elsif line =~ /^Package /
228
+ elsif line.start_with?('Package')
214
229
  unless stdin?
215
230
  sub = { pat: /^(.*)(?<!\dm)(Package|Latest)(.+)$/, styles: theme[:header], index: 2 }
216
231
  out.(print_footer(" # #{line.chomp}", reverse: true, sub: [sub, sub]))
@@ -231,6 +246,82 @@ module Squared
231
246
  on :last, :outdated
232
247
  end
233
248
 
249
+ def install(flag, opts = [], strategy: nil)
250
+ cmd = pip_session 'install'
251
+ out = append_pip(flag, opts, from: :install)
252
+ case flag
253
+ when :editable
254
+ cmd << '--editable' << (out.pop || '.')
255
+ option_clear out
256
+ when :upgrade
257
+ cmd << '--upgrade'
258
+ cmd << basic_option('upgrade-strategy', strategy) if strategy
259
+ append_value out
260
+ end
261
+ run(from: :install)
262
+ end
263
+
264
+ def buildx(flag, opts = [])
265
+ cmd = session flag
266
+ out = []
267
+ srcdir = nil
268
+ case flag
269
+ when :python
270
+ cmd << shell_option('m', 'build')
271
+ list = OPT_PYTHON[:build] + OPT_PYTHON[:common]
272
+ when :hatch
273
+ cmd << 'build'
274
+ list = OPT_HATCH[:build] + OPT_HATCH[:common]
275
+ end
276
+ option_sanitize(opts, list).first.each do |opt|
277
+ if opt =~ /^(v+|q+)$/ || (flag == :python && opt =~ /^(b+)$/)
278
+ cmd << "-#{$1}"
279
+ elsif !srcdir && basepath(opt).exist? && projectpath?(opt)
280
+ srcdir = opt
281
+ else
282
+ out << opt
283
+ end
284
+ end
285
+ if flag == :hatch
286
+ if ENV['HATCH_BUILD_LOCATION']
287
+ srcdir = nil
288
+ else
289
+ srcdir ||= path
290
+ end
291
+ cmd << basic_option('p', project) unless ENV['HATCH_PROJECT'] || session_arg?('p', 'project')
292
+ end
293
+ cmd << shell_quote(basepath(srcdir)) if srcdir
294
+ option_clear out
295
+ run(from: :"#{flag}:build")
296
+ end
297
+
298
+ def publish(flag, opts = [])
299
+ cmd = session flag
300
+ out = []
301
+ case flag
302
+ when :twine
303
+ cmd << 'upload'
304
+ list = OPT_TWINE[:publish]
305
+ when :hatch
306
+ cmd << 'publish'
307
+ list = OPT_HATCH[:publish] + OPT_HATCH[:common]
308
+ end
309
+ option_sanitize(opts, list).first.each do |opt|
310
+ if flag == :hatch && opt =~ /^(v+|q+)$/
311
+ cmd << "-#{$1}"
312
+ else
313
+ out << opt
314
+ end
315
+ end
316
+ if out.empty?
317
+ dist = basepath.join('dist')
318
+ raise_error('no source files given', hint: dist) unless dist.directory? && !dist.empty?
319
+ out << "#{dist}/*"
320
+ end
321
+ append_value out
322
+ run(from: :"#{flag}:publish")
323
+ end
324
+
234
325
  def variable_set(key, *val, **)
235
326
  case key
236
327
  when :dependfile
@@ -265,12 +356,10 @@ module Squared
265
356
  end
266
357
 
267
358
  def append_pip(flag, opts, target: @session, from: nil)
268
- if !from || opts.empty?
269
- append_global(target: target)
270
- return []
271
- end
359
+ append_nocolor(target: target)
360
+ return [] unless from && !opts.empty?
361
+
272
362
  opts, pat = option_sanitize(opts, OPT_PIP[from] + OPT_PIP[:common], target: target)
273
- append_global(target: target)
274
363
  out = []
275
364
  edit = nil
276
365
  opts.each do |opt|
@@ -304,18 +393,18 @@ module Squared
304
393
  end
305
394
  end
306
395
 
307
- def append_global(target: @session)
308
- if (val = option('cache-dir', target: target))
309
- target << case val
310
- when '0', 'false'
311
- '--no-cache-dir'
312
- else
313
- quote_option('cache-dir', basepath(val))
314
- end
396
+ def append_global
397
+ if (val = option('cache-dir'))
398
+ cmd << case val
399
+ when '0', 'false'
400
+ '--no-cache-dir'
401
+ else
402
+ quote_option('cache-dir', basepath(val))
403
+ end
315
404
  end
316
- target << shell_option('proxy', val) if (val = option('proxy', target: target))
317
- target << quote_option('python', basepath(val)) if (val = option('python', target: target))
318
- append_nocolor(target: target)
405
+ cmd << shell_option('proxy', val) if (val = option('proxy'))
406
+ cmd << quote_option('python', basepath(val)) if (val = option('python'))
407
+ append_nocolor
319
408
  end
320
409
  end
321
410