squared 0.6.21 → 0.7.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +70 -257
- data/README.md +242 -205
- data/lib/squared/common/base.rb +0 -8
- data/lib/squared/common/format.rb +7 -10
- data/lib/squared/common/prompt.rb +25 -30
- data/lib/squared/common/shell.rb +27 -35
- data/lib/squared/common/system.rb +29 -21
- data/lib/squared/common/utils.rb +45 -64
- data/lib/squared/config.rb +17 -16
- data/lib/squared/version.rb +1 -1
- data/lib/squared/workspace/application.rb +292 -186
- data/lib/squared/workspace/project/base.rb +570 -511
- data/lib/squared/workspace/project/docker.rb +198 -219
- data/lib/squared/workspace/project/git.rb +244 -215
- data/lib/squared/workspace/project/node.rb +126 -162
- data/lib/squared/workspace/project/python.rb +264 -178
- data/lib/squared/workspace/project/ruby.rb +409 -300
- data/lib/squared/workspace/project/support/class.rb +13 -7
- data/lib/squared/workspace/project/support/optionpartition.rb +80 -90
- data/lib/squared/workspace/project/support/utils.rb +68 -0
- data/lib/squared/workspace/project.rb +0 -7
- data/lib/squared/workspace/repo.rb +235 -170
- data/lib/squared/workspace/series.rb +93 -89
- data/lib/squared/workspace/support/base.rb +15 -1
- metadata +3 -2
|
@@ -5,13 +5,18 @@ module Squared
|
|
|
5
5
|
module Project
|
|
6
6
|
class Python < Git
|
|
7
7
|
DEP_PYTHON = %w[poetry.lock setup.cfg pyproject.toml setup.py requirements.txt].freeze
|
|
8
|
-
DIR_PYTHON = (DEP_PYTHON + %w[README.rst]).freeze
|
|
8
|
+
DIR_PYTHON = (DEP_PYTHON + %w[meson.build README.rst]).freeze
|
|
9
9
|
OPT_PYTHON = {
|
|
10
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
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
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
|
-
prompt=q].freeze
|
|
14
|
+
prompt=q].freeze,
|
|
15
|
+
virtualenv: %w[always-copy clear copies download q|quiet never-download no-download no-periodic-update no-pip
|
|
16
|
+
no-seed no-setuptools no-vcs-ignore 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
|
|
15
20
|
}.freeze
|
|
16
21
|
OPT_PIP = {
|
|
17
22
|
common: %w[debug disable-pip-version-check isolated no-cache-dir no-color no-input require-virtualenv
|
|
@@ -29,23 +34,23 @@ module Squared
|
|
|
29
34
|
install: %w[break-system-packages compile dry-run force-reinstall I|ignore-installed no-compile
|
|
30
35
|
no-warn-conflicts no-warn-script-location U|upgrade user prefix=p report=p root=p
|
|
31
36
|
root-user-action=b t|target=p upgrade-strategy=b].freeze,
|
|
32
|
-
install_a: %w[ignore-requires-python no-index pre
|
|
33
|
-
|
|
34
|
-
install_b: %w[check-build-dependencies no-build-isolation no-clean no-deps
|
|
35
|
-
|
|
36
|
-
requirements-from-script=p src=p].freeze,
|
|
37
|
+
install_a: %w[ignore-requires-python no-index pre extra-index-url=q f|find-links=q i|index-url=q no-binary=q
|
|
38
|
+
only-binary=q].freeze,
|
|
39
|
+
install_b: %w[build-constraint check-build-dependencies no-build-isolation no-clean no-deps prefer-binary
|
|
40
|
+
require-hashes use-pep517 c|constraint=p group=q progress-bar=b r|requirement=p src=p].freeze,
|
|
37
41
|
install_c: %w[C|config-settings=q e|editable=v].freeze,
|
|
38
42
|
hash: %w[a|algorithm].freeze,
|
|
39
|
-
list: %w[e|editable exclude-editable include-editable l|local no-index not-required o|outdated pre
|
|
40
|
-
|
|
41
|
-
i|index-url=q no-binary=q only-binary=q only-final=b path=p].freeze,
|
|
43
|
+
list: %w[e|editable exclude-editable include-editable l|local no-index not-required o|outdated pre u|uptodate
|
|
44
|
+
user exclude=b extra-index-url=q format=b f|find-links=q i|index-url=q path=p].freeze,
|
|
42
45
|
lock: %w[o|output=p].freeze,
|
|
43
46
|
show: %w[f|files].freeze,
|
|
44
47
|
uninstall: %w[break-system-packages y|yes r|requirement=p root-user-action=b].freeze,
|
|
45
48
|
wheel: %w[no-verify w|wheel-dir=p].freeze
|
|
46
49
|
}.freeze
|
|
47
50
|
OPT_POETRY = {
|
|
48
|
-
common: %w[ansi no-ansi no-cache n|no-interaction no-plugins q|quiet
|
|
51
|
+
common: %w[ansi no-ansi no-cache n|no-interaction no-plugins q|quiet v|verbose=+ P|project=p].freeze,
|
|
52
|
+
install: %w[all-extras all-groups compile dry-run no-directory no-root only-root E|extras=q only=q with=q
|
|
53
|
+
without=q].freeze,
|
|
49
54
|
build: %w[clean config-settings=qq f|format=b o|output=p].freeze,
|
|
50
55
|
publish: %w[build dry-run skip-existing cert=p client-cert=p dist-dir=p p|password=q r|repository=q
|
|
51
56
|
u|username=qq].freeze
|
|
@@ -69,13 +74,24 @@ module Squared
|
|
|
69
74
|
client-cert=p c|comment=q config-file=p i|identity=b p|password=q r|repository=b repository-url=q
|
|
70
75
|
sign-with=b u|username=qq].freeze
|
|
71
76
|
}.freeze
|
|
77
|
+
OPT_MESON = {
|
|
78
|
+
build: %w[D=q clearcache debug errorlogs fatal-meson-warnings pkgconfig.relocatable prefer-static
|
|
79
|
+
python.allow-limited-api reconfigure stdsplit strip vsenv werror wipe auto-features=b backend=b
|
|
80
|
+
bindir=p build.cmake-prefix-path=p build.pkg-config-path=p buildtype=b cmake-prefix-path=p
|
|
81
|
+
cross-file=p datadir=p default-library=b default-both-libraries=b force-fallback-for=q genvslite=b
|
|
82
|
+
includedir=p infodir=p install-umask=b layout=b libdir=p libexecdir=p licensedir=p localedir=p
|
|
83
|
+
localstatedir=p mandir=p native-file=p optimization=b pkg-config-path=p prefix=p
|
|
84
|
+
python.bytecompile=i python.platlibdir=p python.purelibdir=p python.install-env=b sbindir=p
|
|
85
|
+
sharedstatedir=p sysconfdir=p unity=b unity-size=i warnlevel=b wrap-mode=b].freeze,
|
|
86
|
+
compile: %w[clean v|verbose j|jobs=i l|load-average=b ninja-args=q vs-args=q xcode-args=q].freeze
|
|
87
|
+
}.freeze
|
|
72
88
|
PASS_PYTHON = {
|
|
73
89
|
python: %w[c v V].freeze,
|
|
74
90
|
pip: {
|
|
75
91
|
debug: %w[platform].freeze,
|
|
76
92
|
install: %w[C config-settings c constraint extra-index-url no-binary only-binary platform
|
|
77
93
|
r requirement].freeze,
|
|
78
|
-
list: %w[exclude extra-index-url
|
|
94
|
+
list: %w[exclude extra-index-url].freeze
|
|
79
95
|
}.freeze
|
|
80
96
|
}.freeze
|
|
81
97
|
private_constant :DEP_PYTHON, :DIR_PYTHON, :OPT_PYTHON, :OPT_PIP, :OPT_POETRY, :OPT_PDM, :OPT_HATCH, :OPT_TWINE,
|
|
@@ -87,7 +103,7 @@ module Squared
|
|
|
87
103
|
end
|
|
88
104
|
|
|
89
105
|
def bannerargs
|
|
90
|
-
%i[dependfile venv].freeze
|
|
106
|
+
%i[version dependfile venv].freeze
|
|
91
107
|
end
|
|
92
108
|
|
|
93
109
|
def venv?
|
|
@@ -101,19 +117,18 @@ module Squared
|
|
|
101
117
|
end
|
|
102
118
|
end
|
|
103
119
|
|
|
104
|
-
attr_reader :venv
|
|
105
|
-
attr_accessor :editable
|
|
120
|
+
attr_reader :venv, :editable
|
|
106
121
|
|
|
107
122
|
def initialize(*, editable: '.', asdf: 'python', **kwargs)
|
|
108
123
|
super
|
|
109
124
|
if @pass.include?(Python.ref)
|
|
110
125
|
initialize_ref Python.ref
|
|
111
|
-
initialize_logger
|
|
126
|
+
initialize_logger kwargs[:log]
|
|
112
127
|
else
|
|
113
128
|
initialize_build(Python.ref, **kwargs)
|
|
114
129
|
initialize_env(**kwargs)
|
|
115
130
|
end
|
|
116
|
-
dependfile_set
|
|
131
|
+
dependfile_set DEP_PYTHON
|
|
117
132
|
editable_set editable
|
|
118
133
|
venv_set kwargs[:venv]
|
|
119
134
|
end
|
|
@@ -121,14 +136,18 @@ module Squared
|
|
|
121
136
|
subtasks({
|
|
122
137
|
'venv' => %i[exec create remove show].freeze,
|
|
123
138
|
'pip' => %i[upgrade uninstall wheel reinstall freeze].freeze,
|
|
124
|
-
'install' => %i[
|
|
139
|
+
'install' => %i[requirement target upgrade editable poetry].freeze,
|
|
125
140
|
'outdated' => %i[major minor patch].freeze,
|
|
126
|
-
'build' => %i[poetry pdm hatch python].freeze,
|
|
141
|
+
'build' => %i[poetry pdm hatch meson python].freeze,
|
|
127
142
|
'publish' => %i[poetry pdm hatch twine].freeze,
|
|
128
143
|
'run' => nil,
|
|
129
144
|
'exec' => nil
|
|
130
145
|
})
|
|
131
146
|
|
|
147
|
+
def project=(val)
|
|
148
|
+
@project = val.dup
|
|
149
|
+
end
|
|
150
|
+
|
|
132
151
|
def verbose=(val)
|
|
133
152
|
case val
|
|
134
153
|
when /\Av+\z/
|
|
@@ -185,7 +204,7 @@ module Squared
|
|
|
185
204
|
log.warn "run script #{n} of #{list.size}".subhint('out of range')
|
|
186
205
|
end
|
|
187
206
|
else
|
|
188
|
-
case
|
|
207
|
+
case i
|
|
189
208
|
when 0
|
|
190
209
|
found |= 1
|
|
191
210
|
run(session_output('poetry', 'run', val), from: :run)
|
|
@@ -204,12 +223,12 @@ module Squared
|
|
|
204
223
|
end
|
|
205
224
|
next if found.anybits?(1)
|
|
206
225
|
|
|
207
|
-
puts log_message(found == 0 ? Logger::INFO : Logger
|
|
226
|
+
puts log_message(found == 0 ? Logger::INFO : Logger.WARN,
|
|
208
227
|
"no scripts #{found == 0 ? 'found' : 'executed'}",
|
|
209
228
|
subject: name, hint: pyprojectfile)
|
|
210
229
|
end
|
|
211
230
|
when 'exec'
|
|
212
|
-
format_desc action, nil, 'command
|
|
231
|
+
format_desc action, nil, ':|command,args*'
|
|
213
232
|
task action do |_, args|
|
|
214
233
|
args = args.to_a
|
|
215
234
|
cmd = if (i = args.delete(':')) && !workspace.windows?
|
|
@@ -217,9 +236,10 @@ module Squared
|
|
|
217
236
|
elsif i || args.empty?
|
|
218
237
|
readline('Enter command', force: true)
|
|
219
238
|
else
|
|
220
|
-
|
|
239
|
+
command_args(args, min: 1, prefix: 'python')
|
|
240
|
+
args.join(' ')
|
|
221
241
|
end
|
|
222
|
-
|
|
242
|
+
shell(cmd, name: :exec, chdir: path)
|
|
223
243
|
end
|
|
224
244
|
end
|
|
225
245
|
else
|
|
@@ -251,8 +271,8 @@ module Squared
|
|
|
251
271
|
args = args.to_a
|
|
252
272
|
if args.empty?
|
|
253
273
|
args = readline('Enter command', force: true).split(' ', 2)
|
|
254
|
-
elsif args.size == 1 &&
|
|
255
|
-
args << readline('Enter arguments', force: false)
|
|
274
|
+
elsif args.size == 1 && option('interactive', notequals: '0', prefix: ref)
|
|
275
|
+
args << readline('Enter arguments', force: false)
|
|
256
276
|
end
|
|
257
277
|
venv_init
|
|
258
278
|
run args.join(' ')
|
|
@@ -274,9 +294,9 @@ module Squared
|
|
|
274
294
|
when :freeze
|
|
275
295
|
format_desc action, flag, "file?=#{DEP_PYTHON[4]},opts*"
|
|
276
296
|
task flag do |_, args|
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
297
|
+
next unless (file = pip(flag, opts: args.to_a, banner: true)) && !silent?
|
|
298
|
+
|
|
299
|
+
puts File.read(file)
|
|
280
300
|
end
|
|
281
301
|
when :uninstall
|
|
282
302
|
format_desc action, flag, 'package+,opts*'
|
|
@@ -300,38 +320,37 @@ module Squared
|
|
|
300
320
|
end
|
|
301
321
|
when 'install'
|
|
302
322
|
format_desc(action, flag, 'opts*', before: case flag
|
|
303
|
-
when :
|
|
304
|
-
when :
|
|
305
|
-
when :
|
|
323
|
+
when :editable then 'path/url?'
|
|
324
|
+
when :upgrade then 'strategy?,package+'
|
|
325
|
+
when :requirement, :target then 'path'
|
|
326
|
+
else 'package+'
|
|
306
327
|
end)
|
|
307
328
|
case flag
|
|
308
|
-
when :editable
|
|
309
|
-
task flag do |_, args|
|
|
310
|
-
install flag, args.to_a
|
|
311
|
-
end
|
|
312
329
|
when :upgrade
|
|
313
330
|
task flag, [:strategy] do |_, args|
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
331
|
+
install flag, (case args.strategy
|
|
332
|
+
when 'eager'
|
|
333
|
+
'eager'
|
|
334
|
+
when /^only-if|needed$/
|
|
335
|
+
'only-if-needed'
|
|
336
|
+
end.yield_self do |val|
|
|
337
|
+
if val
|
|
338
|
+
args.extras << "upgrade-strategy=#{val}"
|
|
339
|
+
else
|
|
340
|
+
args.to_a
|
|
341
|
+
end
|
|
342
|
+
end)
|
|
326
343
|
end
|
|
327
|
-
when :target
|
|
328
|
-
task flag, [:
|
|
329
|
-
|
|
330
|
-
depend(flag, args.extras, target:
|
|
344
|
+
when :requirement, :target
|
|
345
|
+
task flag, [:path] do |_, args|
|
|
346
|
+
path = param_guard(action, flag, args: args, key: :path)
|
|
347
|
+
depend(flag, args.extras, target: path)
|
|
331
348
|
end
|
|
332
349
|
else
|
|
350
|
+
next if flag == :poetry && !poetry?
|
|
351
|
+
|
|
333
352
|
task flag do |_, args|
|
|
334
|
-
|
|
353
|
+
install flag, args.to_a
|
|
335
354
|
end
|
|
336
355
|
end
|
|
337
356
|
when 'outdated'
|
|
@@ -389,22 +408,24 @@ module Squared
|
|
|
389
408
|
cmd << '--no-root' if option('no-root')
|
|
390
409
|
else
|
|
391
410
|
cmd = pip_session 'install'
|
|
392
|
-
cmd << '--upgrade-strategy=eager' if env('PYTHON_UPDATE')
|
|
411
|
+
cmd << '--upgrade-strategy=eager' if env('UPDATE') || env('PYTHON_UPDATE')
|
|
412
|
+
cmd << '--no-build-isolation' if option('build-isolation', equals: '0')
|
|
393
413
|
if flag
|
|
394
|
-
case flag
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
end
|
|
402
|
-
op = append_pip(flag, opts, from: :install)
|
|
414
|
+
cmd << case flag
|
|
415
|
+
when :requirement, :target
|
|
416
|
+
quote_option(flag, basepath(target))
|
|
417
|
+
else
|
|
418
|
+
shell_option(flag)
|
|
419
|
+
end
|
|
420
|
+
op = append_pip flag, opts, pipopts(:install)
|
|
403
421
|
op.clear
|
|
404
422
|
else
|
|
405
423
|
append_global
|
|
406
424
|
end
|
|
407
|
-
|
|
425
|
+
if exist?(DEP_PYTHON[4]) && !session_arg?('r', 'requirement')
|
|
426
|
+
cmd << basic_option('r', DEP_PYTHON[4])
|
|
427
|
+
cmd << basic_option('c', 'constraints.txt') if exist?('constraints.txt')
|
|
428
|
+
end
|
|
408
429
|
append_editable
|
|
409
430
|
end
|
|
410
431
|
run(sync: sync, from: :depend)
|
|
@@ -436,7 +457,7 @@ module Squared
|
|
|
436
457
|
:patch
|
|
437
458
|
end
|
|
438
459
|
end
|
|
439
|
-
'--not-required'
|
|
460
|
+
'--not-required' if option('not-required', notequals: '0') && !env('PYTHON_DEFAULT')
|
|
440
461
|
end
|
|
441
462
|
cmd << '--local' if option('l', 'local')
|
|
442
463
|
append_global
|
|
@@ -446,7 +467,7 @@ module Squared
|
|
|
446
467
|
on :first, :outdated
|
|
447
468
|
banner = format_banner cmd
|
|
448
469
|
print_item banner if sync
|
|
449
|
-
pwd_set(
|
|
470
|
+
pwd_set(cmd, dryrun: dryrun) do
|
|
450
471
|
tc = theme[:current]
|
|
451
472
|
start = 0
|
|
452
473
|
found = 0
|
|
@@ -460,7 +481,8 @@ module Squared
|
|
|
460
481
|
(venv ? command(runenv, cmd) : `#{cmd}`).lines(chomp: true)
|
|
461
482
|
else
|
|
462
483
|
IO.popen(runenv || {}, cmd).readlines(chomp: true)
|
|
463
|
-
end
|
|
484
|
+
end
|
|
485
|
+
.each do |line|
|
|
464
486
|
next if line.match?(/^[ -]+$/)
|
|
465
487
|
|
|
466
488
|
if start > 0
|
|
@@ -523,7 +545,7 @@ module Squared
|
|
|
523
545
|
if found > 0
|
|
524
546
|
items = if se
|
|
525
547
|
choice('Select a package', items.map(&:first),
|
|
526
|
-
multiple: true, force: false, index: true, border: true).map
|
|
548
|
+
multiple: true, force: false, index: true, border: true).map { |n| items[n.pred].last }
|
|
527
549
|
elsif ia
|
|
528
550
|
items.map(&:last)
|
|
529
551
|
else
|
|
@@ -539,10 +561,9 @@ module Squared
|
|
|
539
561
|
if up && !items.empty?
|
|
540
562
|
base = %w[eager no-deps]
|
|
541
563
|
base << 'user' unless venv
|
|
542
|
-
opts = (base & opts).map
|
|
564
|
+
opts = (base & opts).map { |val| val == 'eager' ? "upgrade-strategy=#{val}" : val }
|
|
543
565
|
if dryrun
|
|
544
|
-
opts.map
|
|
545
|
-
print_run pip_output('install --upgrade', *opts, *items.quote!), false
|
|
566
|
+
print_run pip_output('install --upgrade', *opts.map { |val| fill_option(val) }, *items.quote!), false
|
|
546
567
|
else
|
|
547
568
|
install(:upgrade, opts, packages: items, banner: false)
|
|
548
569
|
end
|
|
@@ -555,8 +576,13 @@ module Squared
|
|
|
555
576
|
on :last, :outdated
|
|
556
577
|
end
|
|
557
578
|
|
|
558
|
-
def install(flag, opts = [], packages: [], banner:
|
|
559
|
-
|
|
579
|
+
def install(flag, opts = [], packages: [], banner: !silent?)
|
|
580
|
+
if flag == :poetry
|
|
581
|
+
OptionPartition.new(opts, OPT_POETRY[:install] + OPT_POETRY[:common], poetry_session('install'),
|
|
582
|
+
project: self, single: singleopt(flag))
|
|
583
|
+
else
|
|
584
|
+
op = append_pip(flag, opts, pipopts(:install), target: pip_session('install'))
|
|
585
|
+
end
|
|
560
586
|
case flag
|
|
561
587
|
when :editable
|
|
562
588
|
op << quote_option('e', op.pop || editable || '.')
|
|
@@ -571,7 +597,7 @@ module Squared
|
|
|
571
597
|
run(banner: banner, from: :install)
|
|
572
598
|
end
|
|
573
599
|
|
|
574
|
-
def build!(flag, opts = [])
|
|
600
|
+
def build!(flag, opts = [], outdir: nil, srcdir: nil)
|
|
575
601
|
list = case flag
|
|
576
602
|
when :poetry
|
|
577
603
|
cmd = poetry_session 'build'
|
|
@@ -582,6 +608,9 @@ module Squared
|
|
|
582
608
|
when :hatch
|
|
583
609
|
cmd, opts = hatch_session('build', opts: opts)
|
|
584
610
|
OPT_HATCH[:build]
|
|
611
|
+
when :meson
|
|
612
|
+
cmd = session 'meson', 'setup'
|
|
613
|
+
OPT_MESON[:build]
|
|
585
614
|
else
|
|
586
615
|
cmd, opts = python_session('-m build', opts: opts)
|
|
587
616
|
OPT_PYTHON[:build]
|
|
@@ -589,28 +618,46 @@ module Squared
|
|
|
589
618
|
op = OptionPartition.new(opts, list, cmd, project: self, single: singleopt(flag))
|
|
590
619
|
case flag
|
|
591
620
|
when :hatch
|
|
592
|
-
if !ENV['HATCH_BUILD_LOCATION'] && (outdir ||= op.shift)
|
|
621
|
+
op.add_path(outdir) if !ENV['HATCH_BUILD_LOCATION'] && (outdir ||= op.shift)
|
|
622
|
+
srcdir = false
|
|
623
|
+
when :meson
|
|
624
|
+
if outdir
|
|
593
625
|
op.add_path(outdir)
|
|
626
|
+
else
|
|
627
|
+
outdir = op.first
|
|
628
|
+
op.add_first(path: true, expect: 'outdir not specified')
|
|
594
629
|
end
|
|
595
630
|
else
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
631
|
+
args = case flag
|
|
632
|
+
when :poetry
|
|
633
|
+
srcdir = false
|
|
634
|
+
%w[o output]
|
|
635
|
+
when :pdm
|
|
636
|
+
srcdir = false
|
|
637
|
+
%w[d dest]
|
|
638
|
+
else
|
|
639
|
+
%w[o outdir]
|
|
640
|
+
end
|
|
641
|
+
outdir = op.shift unless op.arg?(*args)
|
|
642
|
+
op << quote_option(args.last, basepath(outdir)) if outdir
|
|
643
|
+
end
|
|
644
|
+
unless srcdir == false
|
|
645
|
+
if srcdir
|
|
646
|
+
op.add_path(srcdir)
|
|
647
|
+
else
|
|
648
|
+
op.exist?(add: true, first: true)
|
|
607
649
|
end
|
|
608
650
|
end
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
651
|
+
from = symjoin flag, 'build'
|
|
652
|
+
if flag == :meson
|
|
653
|
+
cmd = session_output 'meson', 'compile', quote_option('C', basepath(outdir))
|
|
654
|
+
OptionPartition.new(op.extras, OPT_MESON[:compile], cmd, project: self).append unless op.empty?
|
|
655
|
+
run_s(op, cmd.done, from: from)
|
|
656
|
+
else
|
|
657
|
+
op.clear
|
|
658
|
+
run(from: from)
|
|
659
|
+
end
|
|
612
660
|
end
|
|
613
|
-
alias build_ build!
|
|
614
661
|
|
|
615
662
|
def publish(flag, opts = [], test: false)
|
|
616
663
|
list = case flag
|
|
@@ -651,18 +698,18 @@ module Squared
|
|
|
651
698
|
op.clear(pass: false)
|
|
652
699
|
else
|
|
653
700
|
if op.empty?
|
|
654
|
-
op
|
|
701
|
+
op << "#{dist.call}/*"
|
|
655
702
|
else
|
|
656
703
|
op.add_path
|
|
657
704
|
end
|
|
658
705
|
end
|
|
659
|
-
run(from:
|
|
706
|
+
run(from: symjoin(flag, 'publish'), interactive: ['Publish', 'N', project])
|
|
660
707
|
end
|
|
661
708
|
|
|
662
709
|
def python(*args, sync: true, banner: verbose?, with: nil, pass: PASS_PYTHON[:python], **kwargs)
|
|
663
710
|
op = OptionPartition.new(session_opts(with, args: args, kwargs: kwargs, pass: pass), OPT_PYTHON[:common],
|
|
664
|
-
session('python', path: venv
|
|
665
|
-
project: self, multiple: [/^-c/], single: singleopt(:python),
|
|
711
|
+
session('python', path: !venv?),
|
|
712
|
+
project: self, multiple: [/^-c/], single: singleopt(:python), args: true,
|
|
666
713
|
stdin: true)
|
|
667
714
|
op.concat(args)
|
|
668
715
|
if op.include?('-')
|
|
@@ -677,7 +724,7 @@ module Squared
|
|
|
677
724
|
end
|
|
678
725
|
end
|
|
679
726
|
print_run(op, banner, **kwargs)
|
|
680
|
-
run(sync: sync, banner: banner, exception: kwargs.fetch(:exception, exception), from: :python)
|
|
727
|
+
run(sync: sync, banner: banner, exception: kwargs.fetch(:exception, exception?), from: :python)
|
|
681
728
|
end
|
|
682
729
|
|
|
683
730
|
def pip(flag, *args, sync: true, banner: verbose?, with: nil, pass: nil, **kwargs)
|
|
@@ -688,7 +735,7 @@ module Squared
|
|
|
688
735
|
when :freeze, :inspect, :list, :check, :completion, :debug
|
|
689
736
|
opts.concat(args)
|
|
690
737
|
end
|
|
691
|
-
op = append_pip(flag, opts,
|
|
738
|
+
op = append_pip(flag, opts, pipopts(flag), target: pip_session(flag))
|
|
692
739
|
case flag
|
|
693
740
|
when :install, :uninstall, :show, :index
|
|
694
741
|
op.concat(args)
|
|
@@ -711,9 +758,7 @@ module Squared
|
|
|
711
758
|
when :freeze
|
|
712
759
|
venv_init
|
|
713
760
|
op << '>'
|
|
714
|
-
|
|
715
|
-
op.remove(file) if file
|
|
716
|
-
op.add_quote(ret = basepath(file || DEP_PYTHON[4]))
|
|
761
|
+
op.add_quote(ret = basepath(op.detect { |val| op.exist?(val) } || DEP_PYTHON[4]))
|
|
717
762
|
.clear
|
|
718
763
|
when :cache
|
|
719
764
|
op.concat(args)
|
|
@@ -755,14 +800,24 @@ module Squared
|
|
|
755
800
|
op.clear
|
|
756
801
|
end
|
|
757
802
|
print_run(op, banner, **kwargs)
|
|
758
|
-
run(sync: sync, banner: banner, exception: kwargs.fetch(:exception, exception), from:
|
|
803
|
+
run(sync: sync, banner: banner, exception: kwargs.fetch(:exception, exception?), from: symjoin('pip', flag))
|
|
759
804
|
.yield_self { |val| ret || val }
|
|
760
805
|
end
|
|
761
806
|
|
|
807
|
+
def project
|
|
808
|
+
return @project unless @project.frozen?
|
|
809
|
+
|
|
810
|
+
@project = (read_pyproject('project', 'name') || @project).dup
|
|
811
|
+
end
|
|
812
|
+
|
|
813
|
+
def version
|
|
814
|
+
@version ||= read_pyproject('project', 'version')
|
|
815
|
+
end
|
|
816
|
+
|
|
762
817
|
def variable_set(key, *args, **, &blk)
|
|
763
818
|
if block_given?
|
|
764
819
|
case key
|
|
765
|
-
when :dependfile, :
|
|
820
|
+
when :dependfile, :editable, :venv
|
|
766
821
|
args = block_args args, &blk
|
|
767
822
|
end
|
|
768
823
|
end
|
|
@@ -776,7 +831,7 @@ module Squared
|
|
|
776
831
|
@dependindex = index
|
|
777
832
|
@dependfile = val
|
|
778
833
|
else
|
|
779
|
-
log.warn "variable_set:
|
|
834
|
+
log.warn "variable_set: @dependfile=#{val}".subhint('not supported')
|
|
780
835
|
end
|
|
781
836
|
end
|
|
782
837
|
when :editable
|
|
@@ -796,61 +851,51 @@ module Squared
|
|
|
796
851
|
dependtype > 0 && !task_pass?('outdated')
|
|
797
852
|
end
|
|
798
853
|
|
|
854
|
+
def venv?
|
|
855
|
+
!venv.nil?
|
|
856
|
+
end
|
|
857
|
+
|
|
799
858
|
private
|
|
800
859
|
|
|
801
860
|
def pip_session(*cmd)
|
|
802
|
-
session('pip', *cmd, *preopts, path: venv
|
|
861
|
+
session('pip', *cmd, *preopts, path: !venv?)
|
|
803
862
|
end
|
|
804
863
|
|
|
805
864
|
def pip_output(*cmd)
|
|
806
|
-
session_output('pip', *cmd, *preopts, path: venv
|
|
865
|
+
session_output('pip', *cmd, *preopts, path: !venv?)
|
|
807
866
|
end
|
|
808
867
|
|
|
809
868
|
def python_session(*cmd, opts: nil)
|
|
810
|
-
|
|
811
|
-
return session('python', *pre, *cmd, path: venv.nil?) unless opts
|
|
812
|
-
|
|
813
|
-
op = OptionPartition.new(opts, OPT_PYTHON[:common], project: self, single: singleopt(:python))
|
|
814
|
-
[session('python', *pre, *op.to_a, *cmd, path: venv.nil?), op.extras]
|
|
815
|
-
end
|
|
816
|
-
|
|
817
|
-
def poetry_session(*cmd)
|
|
818
|
-
ret = session('poetry', *cmd, *preopts)
|
|
819
|
-
option('project', ignore: false) { |val| ret << quote_option('project', basepath(val)) }
|
|
820
|
-
ret
|
|
869
|
+
create_session('python', *cmd, common: OPT_PYTHON[:common], opts: opts, quiet: false)
|
|
821
870
|
end
|
|
822
871
|
|
|
823
872
|
def pdm_session(*cmd, opts: nil)
|
|
824
|
-
create_session(
|
|
873
|
+
create_session('pdm', *cmd, common: OPT_PDM[:common], opts: opts)
|
|
825
874
|
end
|
|
826
875
|
|
|
827
876
|
def hatch_session(*cmd, opts: nil)
|
|
828
|
-
|
|
877
|
+
if (target = append_nocolor('no-color', target: [], prefix: 'hatch'))
|
|
878
|
+
(opts ||= []).concat(target)
|
|
879
|
+
end
|
|
880
|
+
create_session('hatch', *cmd, common: OPT_HATCH[:common], opts: opts)
|
|
829
881
|
end
|
|
830
882
|
|
|
831
|
-
def
|
|
832
|
-
|
|
883
|
+
def poetry_session(*cmd)
|
|
884
|
+
ret = session('poetry', *cmd, *preopts)
|
|
885
|
+
option('project', ignore: false, path: true)
|
|
886
|
+
append_nocolor '--no-ansi'
|
|
887
|
+
ret
|
|
888
|
+
end
|
|
833
889
|
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
890
|
+
def create_session(name, *cmd, common:, opts: nil, quiet: true)
|
|
891
|
+
pre = preopts(quiet: quiet)
|
|
892
|
+
return session(name, *pre, *cmd, path: !venv?) unless opts
|
|
893
|
+
|
|
894
|
+
op = OptionPartition.new(opts, common, project: self, single: singleopt(name.to_sym))
|
|
895
|
+
[session(name, *pre, *op.to_a, *cmd, path: !venv?), op.extras]
|
|
837
896
|
end
|
|
838
897
|
|
|
839
|
-
def append_pip(flag, opts, target: @session
|
|
840
|
-
list = OPT_PIP.fetch(from, []) + OPT_PIP[:common]
|
|
841
|
-
if pip_install?(flag) || from == :install
|
|
842
|
-
list.concat(OPT_PIP[:install_a])
|
|
843
|
-
list.concat(OPT_PIP[:install_b]) unless flag == :index
|
|
844
|
-
case flag
|
|
845
|
-
when :install, :editable, :upgrade
|
|
846
|
-
list.concat(OPT_PIP[:install_c] + OPT_PIP[:debug])
|
|
847
|
-
when :lock, :wheel
|
|
848
|
-
list.concat(OPT_PIP[:install_c])
|
|
849
|
-
when :download, :index
|
|
850
|
-
list.concat(OPT_PIP[:debug])
|
|
851
|
-
end
|
|
852
|
-
opts << 'no-build-isolation' if option('build-isolation', equals: '0')
|
|
853
|
-
end
|
|
898
|
+
def append_pip(flag, opts, list, target: @session)
|
|
854
899
|
op = OptionPartition.new(opts, list, target, project: self, single: singleopt)
|
|
855
900
|
append_global(target: target)
|
|
856
901
|
case flag
|
|
@@ -871,7 +916,7 @@ module Squared
|
|
|
871
916
|
end
|
|
872
917
|
op.swap
|
|
873
918
|
if edit
|
|
874
|
-
edit = basepath(edit) unless %r{\A[a-z]+(
|
|
919
|
+
edit = basepath(edit) unless %r{\A[a-z]+(\+[a-z]+)?://}i.match?(edit)
|
|
875
920
|
if flag == :editable
|
|
876
921
|
op.push(edit)
|
|
877
922
|
else
|
|
@@ -902,18 +947,16 @@ module Squared
|
|
|
902
947
|
end
|
|
903
948
|
|
|
904
949
|
def append_global(target: @session)
|
|
905
|
-
target
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
option('python', target: target) { |val| quote_option('python', basepath(val)) }
|
|
916
|
-
])
|
|
950
|
+
option('cache-dir', target: target) do |val|
|
|
951
|
+
target << case val
|
|
952
|
+
when '0', 'false'
|
|
953
|
+
'--no-cache-dir'
|
|
954
|
+
else
|
|
955
|
+
quote_option('cache-dir', basepath(val))
|
|
956
|
+
end
|
|
957
|
+
end
|
|
958
|
+
option('proxy', target: target, quote: true)
|
|
959
|
+
option('python', target: target, path: true)
|
|
917
960
|
append_nocolor(target: target)
|
|
918
961
|
end
|
|
919
962
|
|
|
@@ -924,14 +967,18 @@ module Squared
|
|
|
924
967
|
def read_pyproject(table, key = nil)
|
|
925
968
|
return [] unless (file = pyprojectfile)
|
|
926
969
|
|
|
927
|
-
|
|
970
|
+
ret = (@pyproject ||= {})[table]
|
|
971
|
+
unless ret
|
|
928
972
|
ret = []
|
|
973
|
+
found = false
|
|
929
974
|
start = /^\s*\[#{Regexp.escape(table)}\]\s*$/
|
|
930
975
|
ch = nil
|
|
931
|
-
found = false
|
|
932
976
|
File.foreach(file) do |line|
|
|
977
|
+
next if line.start_with?(/\s*#/)
|
|
978
|
+
|
|
933
979
|
if found
|
|
934
|
-
|
|
980
|
+
line.chomp!($1) if line =~ /(?<=[\d"'{}\[\]]|true|false)(\s*#.*)$/
|
|
981
|
+
break if line.match?(/^\s*\[(?:[\w.\-" ]+|".+"|'.+')\]\s*$/)
|
|
935
982
|
|
|
936
983
|
if ch
|
|
937
984
|
val = line.rstrip
|
|
@@ -947,9 +994,9 @@ module Squared
|
|
|
947
994
|
end
|
|
948
995
|
end
|
|
949
996
|
ret.last[1] += val
|
|
950
|
-
elsif
|
|
951
|
-
if (val =
|
|
952
|
-
case (ch =
|
|
997
|
+
elsif line.strip =~ /^(\S+)\s*=\s*([+-]?[\d.]+|true|false|("""|'''|["'\[{])(.*))$/
|
|
998
|
+
if (val = $4)
|
|
999
|
+
case (ch = $3)
|
|
953
1000
|
when '{', '['
|
|
954
1001
|
val = "#{ch}#{val}"
|
|
955
1002
|
ch = ch == '{' ? '}' : ']'
|
|
@@ -962,7 +1009,7 @@ module Squared
|
|
|
962
1009
|
end
|
|
963
1010
|
end
|
|
964
1011
|
else
|
|
965
|
-
val = case (ch =
|
|
1012
|
+
val = case (ch = $2)
|
|
966
1013
|
when 'true'
|
|
967
1014
|
true
|
|
968
1015
|
when 'false'
|
|
@@ -971,7 +1018,10 @@ module Squared
|
|
|
971
1018
|
ch.include?('.') ? ch.to_f : ch.to_i
|
|
972
1019
|
end
|
|
973
1020
|
end
|
|
974
|
-
ret << [
|
|
1021
|
+
ret << [$1, val]
|
|
1022
|
+
end
|
|
1023
|
+
if !ch && (val = ret.last[1]).is_a?(String) && (val.match?(/\A\{.+\}\z/m) || val.match?(/\A\[.+\]\z/m))
|
|
1024
|
+
ret.last[1] = JSON.parse(val) rescue nil
|
|
975
1025
|
end
|
|
976
1026
|
else
|
|
977
1027
|
found = line.match?(start)
|
|
@@ -979,9 +1029,7 @@ module Squared
|
|
|
979
1029
|
end
|
|
980
1030
|
@pyproject[table] = ret
|
|
981
1031
|
end
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
ret
|
|
1032
|
+
key ? ret.find { |val| val.first == key }&.last : ret
|
|
985
1033
|
end
|
|
986
1034
|
|
|
987
1035
|
def pyprojectfile
|
|
@@ -993,9 +1041,9 @@ module Squared
|
|
|
993
1041
|
case flag
|
|
994
1042
|
when :python
|
|
995
1043
|
/\A(?:v+|q+|b+|V+|O+)\z/
|
|
996
|
-
when :pdm
|
|
1044
|
+
when :pdm, :poetry
|
|
997
1045
|
/\Av+\z/
|
|
998
|
-
when :twine
|
|
1046
|
+
when :twine, :meson
|
|
999
1047
|
nil
|
|
1000
1048
|
else
|
|
1001
1049
|
/\A(?:v+|q+)\z/
|
|
@@ -1005,7 +1053,7 @@ module Squared
|
|
|
1005
1053
|
def preopts(quiet: true)
|
|
1006
1054
|
ret = []
|
|
1007
1055
|
case verbose
|
|
1008
|
-
when
|
|
1056
|
+
when false
|
|
1009
1057
|
ret << '--quiet' if quiet
|
|
1010
1058
|
when Numeric
|
|
1011
1059
|
ret << "-#{'v' * verbose}" if verbose > 0
|
|
@@ -1013,6 +1061,23 @@ module Squared
|
|
|
1013
1061
|
ret
|
|
1014
1062
|
end
|
|
1015
1063
|
|
|
1064
|
+
def pipopts(flag)
|
|
1065
|
+
ret = OPT_PIP.fetch(flag, []) + OPT_PIP[:common]
|
|
1066
|
+
if pip_install?(flag)
|
|
1067
|
+
ret.concat(OPT_PIP[:install_a])
|
|
1068
|
+
ret.concat(OPT_PIP[:install_b]) unless flag == :index
|
|
1069
|
+
case flag
|
|
1070
|
+
when :install
|
|
1071
|
+
ret.concat(OPT_PIP[:install_c] + OPT_PIP[:debug])
|
|
1072
|
+
when :lock, :wheel
|
|
1073
|
+
ret.concat(OPT_PIP[:install_c])
|
|
1074
|
+
when :download, :index
|
|
1075
|
+
ret.concat(OPT_PIP[:debug])
|
|
1076
|
+
end
|
|
1077
|
+
end
|
|
1078
|
+
ret
|
|
1079
|
+
end
|
|
1080
|
+
|
|
1016
1081
|
def variables
|
|
1017
1082
|
(super + %i[venv editable]).freeze
|
|
1018
1083
|
end
|
|
@@ -1041,11 +1106,16 @@ module Squared
|
|
|
1041
1106
|
end
|
|
1042
1107
|
|
|
1043
1108
|
def venv_set(val)
|
|
1109
|
+
@venv = nil
|
|
1044
1110
|
return unless val
|
|
1045
1111
|
|
|
1046
|
-
write = ->(level, hint) { log.add(level, "venv: #{@venv}".subhint(hint)) }
|
|
1112
|
+
write = ->(level, hint) { log.add(level, "#{virtualenv? ? 'virtualenv' : 'venv'}: #{@venv}".subhint(hint)) }
|
|
1047
1113
|
if val.is_a?(Array)
|
|
1048
1114
|
val, *opts = val
|
|
1115
|
+
if opts.first == 'virtualenv'
|
|
1116
|
+
@virtualenv = true
|
|
1117
|
+
opts.shift
|
|
1118
|
+
end
|
|
1049
1119
|
@venvopts = opts
|
|
1050
1120
|
end
|
|
1051
1121
|
@venv = basepath val
|
|
@@ -1065,25 +1135,35 @@ module Squared
|
|
|
1065
1135
|
def venv_init
|
|
1066
1136
|
return if !venv || (venvbin.directory? && !venvbin.empty?)
|
|
1067
1137
|
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1138
|
+
subject = virtualenv? ? 'virtualenv' : 'venv'
|
|
1139
|
+
puts log_message(venv, subject: subject, hint: 'init') unless silent?
|
|
1140
|
+
opts = @venvopts ? @venvopts.map { |val| OptionPartition.strip(val) }.flatten : [basic_option('prompt', name)]
|
|
1141
|
+
venv_create(venv, opts, env: false, banner: false)
|
|
1142
|
+
puts log_message(venv, subject: subject, hint: 'created') unless silent?
|
|
1072
1143
|
end
|
|
1073
1144
|
|
|
1074
1145
|
def venv_create(dir, opts = [], env: nil, banner: banner?)
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1146
|
+
flag = if virtualenv?
|
|
1147
|
+
status = true
|
|
1148
|
+
:virtualenv
|
|
1149
|
+
else
|
|
1150
|
+
:venv
|
|
1151
|
+
end
|
|
1152
|
+
cmd, opts = python_session('-m', flag, opts: opts)
|
|
1153
|
+
op = OptionPartition.new(opts, OPT_PYTHON[flag], cmd, project: self)
|
|
1154
|
+
op.append(dir, delim: true)
|
|
1155
|
+
.clear(pass: false)
|
|
1156
|
+
status ||= op.arg?(/\A-v+\z/)
|
|
1080
1157
|
ret = run(op, env, exception: true, banner: banner)
|
|
1158
|
+
args = []
|
|
1159
|
+
requires = read_pyproject 'build-system', 'requires'
|
|
1160
|
+
args.concat(requires) if requires.is_a?(Array)
|
|
1081
1161
|
if poetry?
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
pip(:install, 'setuptools', 'wheel', banner: false)
|
|
1162
|
+
requires = read_pyproject 'tool.poetry', 'requires-poetry'
|
|
1163
|
+
args << "poetry#{requires}"
|
|
1085
1164
|
end
|
|
1086
|
-
|
|
1165
|
+
pip(:install, *args, banner: false) unless args.empty?
|
|
1166
|
+
success?(ret, banner, !status) { |ret| puts(ret && dir.directory? ? "Success: #{dir}" : 'Failed') }
|
|
1087
1167
|
end
|
|
1088
1168
|
|
|
1089
1169
|
def pip_install?(flag)
|
|
@@ -1100,6 +1180,8 @@ module Squared
|
|
|
1100
1180
|
build_backend == 'hatchling.build'
|
|
1101
1181
|
when :setuptools
|
|
1102
1182
|
build_backend == 'setuptools.build_meta'
|
|
1183
|
+
when :meson
|
|
1184
|
+
build_backend != 'mesonpy' && exist?('meson.build')
|
|
1103
1185
|
end
|
|
1104
1186
|
end
|
|
1105
1187
|
|
|
@@ -1115,6 +1197,10 @@ module Squared
|
|
|
1115
1197
|
dependtype == 1
|
|
1116
1198
|
end
|
|
1117
1199
|
|
|
1200
|
+
def virtualenv?
|
|
1201
|
+
@virtualenv ||= exist?('virtualenv.ini') || !ENV['VIRTUALENV_PYTHON'].nil?
|
|
1202
|
+
end
|
|
1203
|
+
|
|
1118
1204
|
def requirements?
|
|
1119
1205
|
dependtype == 5
|
|
1120
1206
|
end
|