squared 0.8.6 → 0.8.7

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d49aff6b1cd9bedf0f0057bd7f9afe30cee588a2d86224f59585f53f16003ac6
4
- data.tar.gz: 445bcbd6ae09304dc4797404de44819600abae31b5f41f8bc61ce1951428a25c
3
+ metadata.gz: 671df38fde0cf8e19a5edf52d76aedba0d3eb294e7eaeed1bc32e63ca50b5e37
4
+ data.tar.gz: 1f87dfbe1fb9881d0d5a2ae023a4e4f14e353bd30368afcc0b45e6cd7e5c3beb
5
5
  SHA512:
6
- metadata.gz: 66c420cde0388bbb2c284fc83b365014bdd770cf30d9edb4a5c5b903b9c95752a87a3c8d951acd1c9b73473d2ce5b1167c6bff63fa582d75f79418ed80e468a5
7
- data.tar.gz: 0b89a2327e97e8f26e077134dfa228bfb1234a09cc6e499a96cd042d23d9e004aea623c63f8b34e3251b198b9f9806b6d191db9978f251c0d52608d1b4e452dd
6
+ metadata.gz: ea1eda6ca2addd9593a414c453eaa7450e31309f91ce56077732e0bc24297d23901a177ec8fd3740ccbdf92e19ec0c4473720e344508ba365fb44a745deda65f
7
+ data.tar.gz: bf9ac431a644fa2fd532bf33aff3bba1a1b9a52a0e8e2ec7b724df2bcfec41760aa00378034a099e0da60a47b21778581bae5a31700c9a5c9d7e0a816d715a6d
data/CHANGELOG.md CHANGED
@@ -1,5 +1,33 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.8.7] - 2026-10-22
4
+
5
+ ### Added
6
+
7
+ - OptionPartition can be initialized with enum and pattern options.
8
+
9
+ ### Fixed
10
+
11
+ - Python venv creation did not run post-install for package managers.
12
+
13
+ ## [0.7.14]
14
+
15
+ ### Changed
16
+
17
+ - Python program meson prefix options use local path resolution.
18
+ - Bundle exec wrapper can be configured per application.
19
+
20
+ ### Fixed
21
+
22
+ - Bundle exec wrapper did not accept boolean values.
23
+
24
+ ## [0.6.21]
25
+
26
+ ### Fixed
27
+
28
+ - RuboCop did not resolve config to project directory.
29
+ - Python program did not use correct separator for double dash options.
30
+
3
31
  ## [0.8.6] - 2026-10-01
4
32
 
5
33
  ### Added
@@ -18,7 +46,7 @@
18
46
 
19
47
  - OptionPartition did not parse quoted option values.
20
48
 
21
- ## [0.6.20] - 2026-09-25
49
+ ## [0.6.20]
22
50
 
23
51
  ### Added
24
52
 
@@ -2153,6 +2181,7 @@
2153
2181
 
2154
2182
  - Changelog was created.
2155
2183
 
2184
+ [0.8.7]: https://github.com/anpham6/squared-ruby/releases/tag/v0.8.7
2156
2185
  [0.8.6]: https://github.com/anpham6/squared-ruby/releases/tag/v0.8.6
2157
2186
  [0.8.5]: https://github.com/anpham6/squared-ruby/releases/tag/v0.8.5
2158
2187
  [0.8.4]: https://github.com/anpham6/squared-ruby/releases/tag/v0.8.4
@@ -2160,6 +2189,7 @@
2160
2189
  [0.8.2]: https://github.com/anpham6/squared-ruby/releases/tag/v0.8.2
2161
2190
  [0.8.1]: https://github.com/anpham6/squared-ruby/releases/tag/v0.8.1
2162
2191
  [0.8.0]: https://github.com/anpham6/squared-ruby/releases/tag/v0.8.0
2192
+ [0.7.14]: https://github.com/anpham6/squared-ruby/releases/tag/v0.7.14
2163
2193
  [0.7.13]: https://github.com/anpham6/squared-ruby/releases/tag/v0.7.13
2164
2194
  [0.7.12]: https://github.com/anpham6/squared-ruby/releases/tag/v0.7.12
2165
2195
  [0.7.11]: https://github.com/anpham6/squared-ruby/releases/tag/v0.7.11
@@ -2174,6 +2204,7 @@
2174
2204
  [0.7.2]: https://github.com/anpham6/squared-ruby/releases/tag/v0.7.2
2175
2205
  [0.7.1]: https://github.com/anpham6/squared-ruby/releases/tag/v0.7.1
2176
2206
  [0.7.0]: https://github.com/anpham6/squared-ruby/releases/tag/v0.7.0
2207
+ [0.6.21]: https://github.com/anpham6/squared-ruby/releases/tag/v0.6.21
2177
2208
  [0.6.20]: https://github.com/anpham6/squared-ruby/releases/tag/v0.6.20
2178
2209
  [0.6.19]: https://github.com/anpham6/squared-ruby/releases/tag/v0.6.19
2179
2210
  [0.6.18]: https://github.com/anpham6/squared-ruby/releases/tag/v0.6.18
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Squared
4
- VERSION = '0.8.6'
4
+ VERSION = '0.8.7'
5
5
  end
@@ -645,16 +645,24 @@ module Squared
645
645
  val = val.split(':') if val.is_a?(String)
646
646
  if before || after || opts
647
647
  pos = []
648
- pos << (before.is_a?(Array) ? before.join(',') : before) if before
649
- if opts
650
- pos << if opts.is_a?(Array)
651
- arg ? "#{arg}=#{opts.join(',')}" : opts.join('|')
648
+ append = lambda do |data|
649
+ pos << case data
650
+ when Array
651
+ data.join(',')
652
+ when Hash
653
+ data.keys.join('|')
652
654
  else
653
- opts
655
+ data
654
656
  end
655
657
  end
656
- pos << (after.is_a?(Array) ? after.join(',') : after) if after
657
- val << "#{val.pop}[#{pos.join(',')}]"
658
+ append.call(before)
659
+ pos << if opts.is_a?(Array)
660
+ arg ? "#{arg}=#{opts.join(',')}" : opts.join('|')
661
+ else
662
+ opts
663
+ end
664
+ append.call(after)
665
+ val << "#{val.pop}[#{pos.compact.join(',')}]"
658
666
  end
659
667
  out ? message(*val) : task_desc(*val)
660
668
  end
@@ -1911,7 +1911,7 @@ module Squared
1911
1911
  out << ''
1912
1912
  end
1913
1913
  if from
1914
- out << from
1914
+ out << (from = from.to_s)
1915
1915
  /\A(#{Regexp.escape(from)})(.*)\z/
1916
1916
  end
1917
1917
  else
@@ -181,7 +181,7 @@ module Squared
181
181
  if flags.nil?
182
182
  case action
183
183
  when 'ls'
184
- format_desc(action, nil, VAL_DOCKER[:ls].keys, after: 'a/ll?,s/tandard?,range*', arg: nil)
184
+ format_desc(action, nil, 'a/ll?,s/tandard?,range*', before: VAL_DOCKER[:ls])
185
185
  task action, [:command] do |_, args|
186
186
  command = param_guard(action, 'command', args: args, key: :command)
187
187
  args = args.extras
@@ -1106,7 +1106,7 @@ module Squared
1106
1106
  git(:remote, args.extras, extras: [name, url])
1107
1107
  end
1108
1108
  else
1109
- format_desc action, flag, "#{OPT_GIT[:remote].keys.join('|')},opts*" if TASK_METADATA
1109
+ format_desc(action, flag, 'opts*', before: OPT_GIT[:remote])
1110
1110
  task flag, [:command] do |_, args|
1111
1111
  command = param_guard(action, flag, args: args, key: :command)
1112
1112
  cmd, opts = git_session('remote', opts: args.extras)
@@ -69,7 +69,7 @@ module Squared
69
69
  install: %w[check-cache check-resolutions immutable immutable-cache inline-builds json refresh-lockfile
70
70
  mode=b].freeze,
71
71
  add: %w[cached D|dev json O|optional P|peer prefer-dev].freeze,
72
- add_a: %w[C|caret E|exact F|fixed interactive T|tilde mode=b].freeze,
72
+ add_a: %w[C|caret E|exact F|fixed i|interactive no-time-gate T|tilde mode=b].freeze,
73
73
  update: %w[R|recursive].freeze,
74
74
  dedupe: %w[check json mode=b strategy=b].freeze,
75
75
  run: %w[B|binaries-only inspect inspect-brk T|top-level require=q].freeze,
@@ -305,13 +305,11 @@ module Squared
305
305
  format_desc action, nil, 'version|pre?{major,minor,patch}|prerelease'
306
306
  task action, [:version] do |_, args|
307
307
  version = param_guard(action, 'to', args: args, key: :version)
308
- if version.match?(/^((pre)?(major|minor|patch))|prerelease$/)
309
- flag = version.to_sym
310
- version = nil
308
+ if version.match?(/^(pre)?(major|minor|patch)|prerelease$/)
309
+ bump version.to_sym
311
310
  else
312
- flag = :version
311
+ bump :version, version
313
312
  end
314
- bump flag, version
315
313
  end
316
314
  when 'pack'
317
315
  format_desc action, nil, 'opts*'
@@ -662,7 +660,7 @@ module Squared
662
660
  end
663
661
  if nolockfile?(prefix: 'yarn')
664
662
  cmd << '--no-lockfile'
665
- elsif option('ci') || (ci? && exist?('yarn.lock'))
663
+ elsif option('ci') || (ci? && exist?(yarnlock))
666
664
  if yarn == 1
667
665
  cmd << '--frozen-lockfile'
668
666
  elsif !flag
@@ -698,13 +696,13 @@ module Squared
698
696
  '--force'
699
697
  elsif nolockfile?(prefix: 'pnpm')
700
698
  '--no-lockfile'
701
- elsif option('ci') || (ci? && exist?('pnpm-lock.yaml'))
699
+ elsif option('ci') || (ci? && exist?(pnpmlock))
702
700
  '--frozen-lockfile'
703
701
  end
704
702
  cmd << '--ignore-scripts' if option('ignore-scripts')
705
703
  cmd << '--dangerously-allow-all-builds' if option('approve-builds')
706
704
  else
707
- ci = option('ci', prefix: 'npm') || (ci? && exist?('package-lock.json'))
705
+ ci = option('ci', prefix: 'npm') || (ci? && exist?(npmlock))
708
706
  cmd = session('npm', ci ? 'ci' : 'install')
709
707
  option('approve-scripts') do |val|
710
708
  cmd = npm_output 'approve-scripts'
@@ -758,7 +756,7 @@ module Squared
758
756
  append_platform
759
757
  end
760
758
  end
761
- cmd << '--package-lock=false' << 'save=false' if nolockfile?(prefix: 'npm')
759
+ cmd << '--package-lock=false' << '--save=false' if nolockfile?(prefix: 'npm')
762
760
  cmd << '--ignore-scripts' if option('ignore-scripts')
763
761
  end
764
762
  if add
@@ -771,7 +769,7 @@ module Squared
771
769
  end
772
770
 
773
771
  def outdated(flag = nil, opts = [], sync: invoked_sync?('outdated', flag))
774
- cmd = session(pnpm? && exist?('pnpm-lock.yaml') ? 'pnpm' : 'npm', 'outdated')
772
+ cmd = session(pnpm? && exist?(pnpmlock) ? 'pnpm' : 'npm', 'outdated')
775
773
  dryrun = has_value?(opts, 'd', 'dry-run') || dryrun?
776
774
  unless dryrun
777
775
  log.info cmd.to_s
@@ -1452,7 +1450,7 @@ module Squared
1452
1450
  end
1453
1451
 
1454
1452
  def yarn?
1455
- (@pm[:yarn] ||= if rootpath('yarn.lock', ascend: dependroot).exist?
1453
+ (@pm[:yarn] ||= if rootpath(yarnlock, ascend: dependroot).exist?
1456
1454
  yarntype
1457
1455
  elsif (ver = read_package || read_install)
1458
1456
  if ver =~ /^yarn(?:@(\d)|$)/
@@ -1473,7 +1471,7 @@ module Squared
1473
1471
  end
1474
1472
 
1475
1473
  def pnpm?
1476
- (@pm[:pnpm] ||= if rootpath('pnpm-lock.yaml', ascend: dependroot).exist?
1474
+ (@pm[:pnpm] ||= if rootpath(pnpmlock, ascend: dependroot).exist?
1477
1475
  pnpmtype
1478
1476
  elsif (ver = read_package || read_install)
1479
1477
  ver.start_with?('pnpm') ? pnpmtype : 0
@@ -1582,7 +1580,7 @@ module Squared
1582
1580
  require 'yaml'
1583
1581
  doc = YAML.load_file(rc)
1584
1582
  doc.nodeLinker == 'node-modules' ? 2 : 3
1585
- elsif exist && !exist?('yarn.lock')
1583
+ elsif exist && !exist?(yarnlock)
1586
1584
  0
1587
1585
  else
1588
1586
  1
@@ -1594,6 +1592,10 @@ module Squared
1594
1592
  3
1595
1593
  end
1596
1594
 
1595
+ def yarnlock
1596
+ 'yarn.lock'
1597
+ end
1598
+
1597
1599
  def pnpmtype(exist: false)
1598
1600
  require 'yaml'
1599
1601
  doc = YAML.load_file(basepath('node_modules/.modules.yaml', ascend: dependroot))
@@ -1608,13 +1610,21 @@ module Squared
1608
1610
  end
1609
1611
  rescue => e
1610
1612
  if exist
1611
- %w[pnpm-lock.yaml pnpm-workspace.yaml].any? { |val| exist?(val) } ? 4 : 0
1613
+ %W[#{pnpmlock} pnpm-workspace.yaml].any? { |val| exist?(val) } ? 4 : 0
1612
1614
  else
1613
1615
  log.debug e
1614
1616
  4
1615
1617
  end
1616
1618
  end
1617
1619
 
1620
+ def pnpmlock
1621
+ 'pnpm-lock.yaml'
1622
+ end
1623
+
1624
+ def pnpmopts(*args)
1625
+ OPT_PNPM[:common] + args.flat_map { |name| OPT_PNPM.fetch(name, []) }
1626
+ end
1627
+
1618
1628
  def remove_modules(prefix: dependbin)
1619
1629
  modules = basepath!('node_modules', type: 'd')
1620
1630
  return false unless modules && confirm_basic('Remove?', modules, prefix: prefix)
@@ -1696,16 +1706,16 @@ module Squared
1696
1706
  ].concat(args)
1697
1707
  end
1698
1708
 
1699
- def npmopts(*args)
1700
- OPT_NPM[:common] + args.flat_map { |name| OPT_NPM.fetch(name, []) }
1709
+ def npmlock
1710
+ 'package-lock.json'
1701
1711
  end
1702
1712
 
1703
- def pnpmopts(*args)
1704
- OPT_PNPM[:common] + args.flat_map { |name| OPT_PNPM.fetch(name, []) }
1713
+ def npmopts(*args)
1714
+ OPT_NPM[:common] + args.flat_map { |name| OPT_NPM.fetch(name, []) }
1705
1715
  end
1706
1716
 
1707
1717
  def lockfile(delete = false)
1708
- ret = basepath(yarn? ? 'yarn.lock' : pnpm? ? 'pnpm-lock.yaml' : 'package-lock.json')
1718
+ ret = basepath(yarn? ? yarnlock : pnpm? ? pnpmlock : npmlock)
1709
1719
  if ret.exist?
1710
1720
  if delete
1711
1721
  ret.delete
@@ -7,16 +7,18 @@ 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[meson.build README.rst]).freeze
9
9
  OPT_PYTHON = {
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,
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
11
+ check-hash-based-pycs={always,default,never}].freeze,
11
12
  build: %w[C=bm n|no-isolation s|sdist x|skip-dependency-check v|verbose w|wheel config-json=q config-setting=q
12
13
  installer=b o|outdir=p].freeze,
13
14
  venv: %w[clear copies symlinks system-site-packages upgrade upgrade-deps without-scm-ignore-files without-pip
14
15
  prompt=q].freeze,
15
16
  virtualenv: %w[always-copy clear copies download never-download no-download no-periodic-update no-pip no-seed
16
- no-setuptools no-vcs-ignore q|quiet read-only-app-data reset-app-data symlink-app-data symlinks
17
- system-site-packages with-traceback without-pip upgrade-embed-wheels v|verbose=+ activators=q
18
- app-data=p creator=b discovery=b extra-search-dir=p pip=b prompt=q p|python=q seeder=b
19
- setuptools=b try-first-with=q].freeze
17
+ no-setuptools no-vcs-ignore no-venv-redirect q|quiet read-only-app-data reset-app-data
18
+ symlink-app-data symlinks system-site-packages with-traceback without-pip upgrade-embed-wheels
19
+ venv-redirect v|verbose=+ activators={bash,batch,cshell,fish,nushell,powershell,python,xonsh}
20
+ app-data=p creator=b discovery={builtin} extra-search-dir=p pip=b prompt=q p|python=q
21
+ seeder={app-data,pip} setuptools=b try-first-with=q].freeze
20
22
  }.freeze
21
23
  OPT_PIP = {
22
24
  common: %w[debug disable-pip-version-check isolated no-cache-dir no-color no-input no-proxy-env
@@ -77,15 +79,20 @@ module Squared
77
79
  sign-with=b u|username=qq].freeze
78
80
  }.freeze
79
81
  OPT_MESON = {
80
- build: %w[D=q clearcache debug errorlogs fatal-meson-warnings pkgconfig.relocatable prefer-static
81
- python.allow-limited-api reconfigure stdsplit strip vsenv werror wipe auto-features=b backend=b
82
- bindir=p build.cmake-prefix-path=p build.pkg-config-path=p buildtype=b cmake-prefix-path=p
83
- cross-file=p datadir=p default-library=b default-both-libraries=b force-fallback-for=q genvslite=b
84
- includedir=p infodir=p install-umask=b layout=b libdir=p libexecdir=p licensedir=p localedir=p
85
- localstatedir=p mandir=p native-file=p optimization=b pkg-config-path=p prefix=p
86
- python.bytecompile=i python.platlibdir=p python.purelibdir=p python.install-env=b sbindir=p
87
- sharedstatedir=p sysconfdir=p unity=b unity-size=i warnlevel=b wrap-mode=b].freeze,
88
- compile: %w[clean v|verbose j|jobs=i l|load-average=b ninja-args=q vs-args=q xcode-args=q].freeze
82
+ build: %w[D=q clearcache debug errorlogs fatal-meson-warnings os2-emxomf pkgconfig.relocatable prefer-static
83
+ python.allow-limited-api reconfigure stdsplit strip vsenv werror wipe auto-features=b
84
+ backend={ninja,vs,vs2010,vs2012,vs2013,vs2015,vs2017,vs2019,vs2022,vs2026,xcode,none}
85
+ bindir=q build.cmake-prefix-path=p build.pkg-config-path=p
86
+ buildtype={plain,debug,debugoptimized,release,minsize,custom} cmake-prefix-path=p cross-file=p
87
+ datadir=q default-library={shared,static,both} default-both-libraries={shared,static,auto}
88
+ force-fallback-for=q genvslite={vs2022,vs2026} includedir=q infodir=q install-umask=b
89
+ layout={mirror,flat} libdir=q libexecdir=q licensedir=q localedir=q localstatedir=q mandir=q
90
+ namingscheme={platform,classic} native-file=p optimization={plain,0,g,1,2,3,s} pkg-config-path=p
91
+ prefix=p python.build-config=p python.bytecompile=b python.platlibdir=p python.purelibdir=p
92
+ python.install-env={auto,prefix,system,venv} sbindir=q sharedstatedir=q sysconfdir=q
93
+ unity={on,off,subprojects} unity-size=i warnlevel={0,1,2,3,everything}
94
+ wrap-mode={default,nofallback,nodownload,forcefallback,nopromote}].freeze,
95
+ compile: %w[C=p clean v|verbose j|jobs=i l|load-average=b ninja-args=q vs-args=q xcode-args=q].freeze
89
96
  }.freeze
90
97
  PASS_PYTHON = {
91
98
  python: %w[c v V].freeze,
@@ -276,7 +283,7 @@ module Squared
276
283
  args = args.to_a
277
284
  if args.empty?
278
285
  args = readline('Enter command', force: true).split(' ', 2)
279
- elsif args.size == 1 && option('interactive', notequals: '0', prefix: ref)
286
+ elsif args.size == 1 && option('interactive', notequals: '0', prefix: 'python')
280
287
  args << readline('Enter arguments', force: false) unless args.first.include?(' ')
281
288
  end
282
289
  venv_init
@@ -346,18 +353,18 @@ module Squared
346
353
  case flag
347
354
  when :upgrade
348
355
  task flag, [:strategy] do |_, args|
349
- install flag, (case args.strategy
350
- when 'eager'
351
- 'eager'
352
- when /^only-if|needed$/
353
- 'only-if-needed'
354
- end.yield_self do |val|
355
- if val
356
- args.extras << "upgrade-strategy=#{val}"
357
- else
358
- args.to_a
359
- end
360
- end)
356
+ val = case args.strategy
357
+ when 'eager'
358
+ 'eager'
359
+ when /^only-if/, /needed$/
360
+ 'only-if-needed'
361
+ end
362
+ args = if val
363
+ args.extras << "upgrade-strategy=#{val}"
364
+ else
365
+ args.to_a
366
+ end
367
+ install flag, args
361
368
  end
362
369
  when :requirement, :target
363
370
  task flag, [:path] do |_, args|
@@ -735,7 +742,7 @@ module Squared
735
742
  op = OptionPartition.new(session_opts(with, args: args, kwargs: kwargs, pass: pass), OPT_PYTHON[:common],
736
743
  session('python', path: !venv?),
737
744
  project: self, strict: strict?, multiple: [/^-c/], single: singleopt(:python),
738
- args: true, stdin: true)
745
+ sep: ' ', args: true, stdin: true)
739
746
  op.concat(args)
740
747
  if op.include?('-')
741
748
  op.exist?(add: true)
@@ -936,7 +943,8 @@ module Squared
936
943
  pre = preopts(quiet: quiet)
937
944
  return session(name, *pre, *cmd, path: !venv?) unless opts
938
945
 
939
- op = OptionPartition.new(opts, common, project: self, strict: strict?, single: singleopt(name.to_sym))
946
+ op = OptionPartition.new(opts, common, project: self, strict: strict?, sep: name == 'python' ? ' ' : '=',
947
+ single: singleopt(name.to_sym))
940
948
  [session(name, *pre, *op.to_a, *cmd, path: !venv?), op.extras]
941
949
  end
942
950
 
@@ -1197,6 +1205,7 @@ module Squared
1197
1205
  status = true
1198
1206
  :virtualenv
1199
1207
  else
1208
+ status = !banner
1200
1209
  :venv
1201
1210
  end
1202
1211
  cmd, opts = python_session('-m', flag, opts: opts)
@@ -1204,32 +1213,31 @@ module Squared
1204
1213
  op.append(dir, delim: true)
1205
1214
  .clear(pass: false)
1206
1215
  status ||= op.arg?(/\A-v+\z/)
1207
- ret = run(op, env, exception: true, banner: banner)
1208
- args = []
1209
- requires = read_pyproject 'build-system', 'requires'
1210
- args.concat(requires) if requires.is_a?(Array)
1211
- if poetry?
1212
- requires = read_pyproject 'tool.poetry', 'requires-poetry'
1213
- args << "poetry#{requires}"
1214
- elsif setuptools? && !virtualenv?
1215
- args << 'setuptools' << 'wheel'
1216
- end
1217
- pip(:install, *args, banner: false) unless args.empty?
1218
- success?(ret, banner, !status) do |out|
1219
- if out && dir.directory?
1220
- if poetry?
1221
- dir += (windows? ? 'Scripts/python.exe' : 'bin/python')
1222
- cmd = poetry_session 'env use'
1223
- else
1224
- puts "Success: #{dir}"
1225
- return
1226
- end
1227
- cmd << shell_quote(dir)
1228
- print_run cmd, silent?
1229
- run(banner: false)
1216
+ if run(op, env, exception: true, banner: banner) && dir.directory?
1217
+ args = []
1218
+ requires = read_pyproject 'build-system', 'requires'
1219
+ args.concat(requires) if requires.is_a?(Array)
1220
+ if poetry?
1221
+ requires = read_pyproject 'tool.poetry', 'requires-poetry'
1222
+ args << "poetry#{requires}"
1223
+ elsif setuptools? && !virtualenv?
1224
+ args << 'setuptools' << 'wheel'
1225
+ end
1226
+ pip(:install, *args, banner: false) unless args.empty?
1227
+ if poetry?
1228
+ dir += (windows? ? 'Scripts/python.exe' : 'bin/python')
1229
+ poetry_session 'env use'
1230
+ elsif pdm?
1231
+ pdm_session 'use -f'
1230
1232
  else
1231
- puts 'Failed'
1233
+ puts "Success: #{dir}" unless status
1234
+ return
1232
1235
  end
1236
+ cmd << shell_quote(dir)
1237
+ print_run cmd, silent?
1238
+ run(banner: false)
1239
+ elsif !status
1240
+ puts 'Failed'
1233
1241
  end
1234
1242
  end
1235
1243
 
@@ -227,7 +227,7 @@ module Squared
227
227
  serve_set kwargs[:serve]
228
228
  gemfile_set kwargs[:gemspec]
229
229
  self.autodetect = autodetect
230
- @bundle = { exec: exec.is_a?(String) ? basepath!(exec) : exec }
230
+ @bundle = { exec: exec }
231
231
  @steepfile = basepath! steep if steep
232
232
  rubocop = rootpath('.rubocop.yml', ascend: Dir.home) if rubocop == true
233
233
  @rubocopfile = basepath! rubocop if rubocop
@@ -1583,7 +1583,7 @@ module Squared
1583
1583
 
1584
1584
  def rdbg(*args, banner: verbose?, with: nil, pass: PASS_RUBY[:rdbg], **kwargs)
1585
1585
  opts = session_opts(with, args: args, kwargs: kwargs, pass: pass)
1586
- cmd = session 'rdbg'
1586
+ cmd = session(*bundle_args('rdbg'))
1587
1587
  args.each_with_index do |val, i|
1588
1588
  break if val == '--'
1589
1589
  next unless exist?(val, type: 'f')
@@ -1866,7 +1866,7 @@ module Squared
1866
1866
  end
1867
1867
 
1868
1868
  def ruby_session(*cmd, **kwargs)
1869
- session('ruby', *preopts, *cmd, **kwargs)
1869
+ session(*bundle_args('ruby'), *preopts, *cmd, **kwargs)
1870
1870
  end
1871
1871
 
1872
1872
  def gem_session(*cmd, **kwargs)
@@ -1884,11 +1884,10 @@ module Squared
1884
1884
  end
1885
1885
 
1886
1886
  def rbs_session(*cmd, opts: nil)
1887
- args = bundle_args 'rbs'
1888
- return session(*args, *cmd) unless opts
1887
+ return session(*bundle_args('rbs'), *cmd) unless opts
1889
1888
 
1890
1889
  op = OptionPartition.new(opts, OPT_RUBY[:rbs], project: self, strict: strict?)
1891
- [session(*args, *op.to_a, *cmd), op.extras]
1890
+ [session(*bundle_args('rbs'), *op.to_a, *cmd), op.extras]
1892
1891
  end
1893
1892
 
1894
1893
  def gem_output(*cmd, **kwargs)
@@ -1896,7 +1895,7 @@ module Squared
1896
1895
  end
1897
1896
 
1898
1897
  def ruby_output(*cmd, **kwargs)
1899
- session_output('ruby', *cmd, **kwargs)
1898
+ session_output(*bundle_args('ruby'), *cmd, **kwargs)
1900
1899
  end
1901
1900
 
1902
1901
  def bundle_output(*cmd, **kwargs)
@@ -1909,7 +1908,20 @@ module Squared
1909
1908
 
1910
1909
  def bundle_args(*args)
1911
1910
  if (val = @bundle[:exec])
1912
- args.unshift(quote_option('gemfile', val)) unless val == true
1911
+ app = args.first
1912
+ if val.is_a?(Hash)
1913
+ env = val[app.to_s] || val[app.to_sym]
1914
+ return args unless env
1915
+
1916
+ val = env.is_a?(String) ? basepath!(env) : true
1917
+ elsif app == 'ruby'
1918
+ return args
1919
+ end
1920
+ if val.is_a?(String)
1921
+ return args unless (val = basepath!(val))
1922
+
1923
+ args.unshift("--gemfile=#{shell_escape(val.relative_path_from(path), quote: true)}")
1924
+ end
1913
1925
  args.unshift('bundle', 'exec')
1914
1926
  end
1915
1927
  args
@@ -247,7 +247,7 @@ module Squared
247
247
  end
248
248
 
249
249
  def parse(list, opts = extras, no: nil, single: nil, args: false, multiple: nil, first: nil, underscore: nil,
250
- explicit: false, bool: %w[true false], auto: [], stdin: false, &blk)
250
+ explicit: false, bool: %w[true false], auto: [], regexp: {}, enum: {}, stdin: false, &blk)
251
251
  @extras = []
252
252
  @values = []
253
253
  bare = []
@@ -264,8 +264,6 @@ module Squared
264
264
  bl = []
265
265
  ex = []
266
266
  ml = []
267
- re = {}
268
- ar = {}
269
267
  sw = {}
270
268
  se = {}
271
269
  list.flat_map do |val|
@@ -287,10 +285,10 @@ module Squared
287
285
  end
288
286
  if (n = val.index('='))
289
287
  flag = val[0, n]
290
- enum = flag.split(':')
291
- mod = if enum.size > 1
292
- pre = enum.shift
293
- enum.map { |s| "#{pre}:#{s}" }
288
+ opt = flag.split(':')
289
+ mod = if opt.size > 1
290
+ pre = opt.shift
291
+ opt.map { |s| "#{pre}:#{s}" }
294
292
  else
295
293
  [flag]
296
294
  end
@@ -325,14 +323,14 @@ module Squared
325
323
  pat = eval(val)
326
324
  raise SyntaxError unless pat.is_a?(Regexp)
327
325
 
328
- mod.each { |key| re[key] = pat }
326
+ mod.each { |key| regexp[key] = pat }
329
327
  rescue SyntaxError
330
328
  warn "#{self.class}: invalid pattern (#{val})"
331
329
  end
332
330
  when '{'
333
331
  group = val[(n + 2)..-1].chomp!('}')&.split(',')
334
332
  if group
335
- mod.each { |key| ar[key] = group }
333
+ mod.each { |key| enum[key] = group }
336
334
  else
337
335
  warn "#{self.class}: invalid group (#{val})"
338
336
  end
@@ -439,8 +437,8 @@ module Squared
439
437
  else
440
438
  push opt
441
439
  end
442
- elsif !ar.empty? && has.call(ar.keys, key)
443
- group = get.call(ar)
440
+ elsif !enum.empty? && has.call(enum.keys, key)
441
+ group = get.call(enum)
444
442
  if group.include?(val)
445
443
  add shell_option(key, val, force: false, **kwargs)
446
444
  elsif @strict
@@ -448,10 +446,10 @@ module Squared
448
446
  else
449
447
  push opt
450
448
  end
451
- elsif !re.empty? && has.call(re.keys, key)
452
- pat = get.call(re)
449
+ elsif !regexp.empty? && has.call(regexp.keys, key)
450
+ pat = get.call(regexp)
453
451
  if val.match?(pat)
454
- add quote_option(key, val, **kwargs)
452
+ add __send__(kwargs[:merge] ? :basic_option : :quote_option, key, val, **kwargs)
455
453
  elsif @strict
456
454
  clear([opt], hint: "match != /#{pat.source}/")
457
455
  else
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: squared
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.6
4
+ version: 0.8.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - An Pham
@@ -126,7 +126,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
126
126
  - !ruby/object:Gem::Version
127
127
  version: '0'
128
128
  requirements: []
129
- rubygems_version: 4.0.20
129
+ rubygems_version: 4.0.23
130
130
  specification_version: 4
131
131
  summary: Rake task generator for managing multi-language workspaces.
132
132
  test_files: []