squared 0.6.9 → 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 +74 -2
- data/README.md +239 -200
- data/lib/squared/common/format.rb +7 -10
- data/lib/squared/common/prompt.rb +23 -24
- data/lib/squared/common/shell.rb +16 -17
- data/lib/squared/common/system.rb +29 -20
- data/lib/squared/common/utils.rb +43 -54
- data/lib/squared/config.rb +17 -16
- data/lib/squared/version.rb +1 -1
- data/lib/squared/workspace/application.rb +290 -175
- data/lib/squared/workspace/project/base.rb +542 -442
- data/lib/squared/workspace/project/docker.rb +151 -131
- data/lib/squared/workspace/project/git.rb +178 -144
- data/lib/squared/workspace/project/node.rb +89 -87
- data/lib/squared/workspace/project/python.rb +236 -139
- data/lib/squared/workspace/project/ruby.rb +395 -281
- data/lib/squared/workspace/project/support/class.rb +12 -6
- data/lib/squared/workspace/project/support/optionpartition.rb +58 -41
- data/lib/squared/workspace/project/support/utils.rb +68 -0
- data/lib/squared/workspace/project.rb +0 -7
- data/lib/squared/workspace/repo.rb +234 -169
- data/lib/squared/workspace/series.rb +91 -86
- data/lib/squared/workspace/support/base.rb +15 -1
- metadata +2 -1
|
@@ -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
|
|
@@ -43,7 +48,9 @@ module Squared
|
|
|
43
48
|
wheel: %w[no-verify w|wheel-dir=p].freeze
|
|
44
49
|
}.freeze
|
|
45
50
|
OPT_POETRY = {
|
|
46
|
-
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,
|
|
47
54
|
build: %w[clean config-settings=qq f|format=b o|output=p].freeze,
|
|
48
55
|
publish: %w[build dry-run skip-existing cert=p client-cert=p dist-dir=p p|password=q r|repository=q
|
|
49
56
|
u|username=qq].freeze
|
|
@@ -67,6 +74,17 @@ module Squared
|
|
|
67
74
|
client-cert=p c|comment=q config-file=p i|identity=b p|password=q r|repository=b repository-url=q
|
|
68
75
|
sign-with=b u|username=qq].freeze
|
|
69
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
|
|
70
88
|
PASS_PYTHON = {
|
|
71
89
|
python: %w[c v V].freeze,
|
|
72
90
|
pip: {
|
|
@@ -85,7 +103,7 @@ module Squared
|
|
|
85
103
|
end
|
|
86
104
|
|
|
87
105
|
def bannerargs
|
|
88
|
-
%i[dependfile venv].freeze
|
|
106
|
+
%i[version dependfile venv].freeze
|
|
89
107
|
end
|
|
90
108
|
|
|
91
109
|
def venv?
|
|
@@ -105,7 +123,7 @@ module Squared
|
|
|
105
123
|
super
|
|
106
124
|
if @pass.include?(Python.ref)
|
|
107
125
|
initialize_ref Python.ref
|
|
108
|
-
initialize_logger
|
|
126
|
+
initialize_logger kwargs[:log]
|
|
109
127
|
else
|
|
110
128
|
initialize_build(Python.ref, **kwargs)
|
|
111
129
|
initialize_env(**kwargs)
|
|
@@ -118,14 +136,18 @@ module Squared
|
|
|
118
136
|
subtasks({
|
|
119
137
|
'venv' => %i[exec create remove show].freeze,
|
|
120
138
|
'pip' => %i[upgrade uninstall wheel reinstall freeze].freeze,
|
|
121
|
-
'install' => %i[
|
|
139
|
+
'install' => %i[requirement target upgrade editable poetry].freeze,
|
|
122
140
|
'outdated' => %i[major minor patch].freeze,
|
|
123
|
-
'build' => %i[poetry pdm hatch python].freeze,
|
|
141
|
+
'build' => %i[poetry pdm hatch meson python].freeze,
|
|
124
142
|
'publish' => %i[poetry pdm hatch twine].freeze,
|
|
125
143
|
'run' => nil,
|
|
126
144
|
'exec' => nil
|
|
127
145
|
})
|
|
128
146
|
|
|
147
|
+
def project=(val)
|
|
148
|
+
@project = val.dup
|
|
149
|
+
end
|
|
150
|
+
|
|
129
151
|
def verbose=(val)
|
|
130
152
|
case val
|
|
131
153
|
when /\Av+\z/
|
|
@@ -214,7 +236,8 @@ module Squared
|
|
|
214
236
|
elsif i || args.empty?
|
|
215
237
|
readline('Enter command', force: true)
|
|
216
238
|
else
|
|
217
|
-
|
|
239
|
+
command_args(args, min: 1, prefix: 'python')
|
|
240
|
+
args.join(' ')
|
|
218
241
|
end
|
|
219
242
|
shell(cmd, name: :exec, chdir: path)
|
|
220
243
|
end
|
|
@@ -248,7 +271,7 @@ module Squared
|
|
|
248
271
|
args = args.to_a
|
|
249
272
|
if args.empty?
|
|
250
273
|
args = readline('Enter command', force: true).split(' ', 2)
|
|
251
|
-
elsif args.size == 1 &&
|
|
274
|
+
elsif args.size == 1 && option('interactive', notequals: '0', prefix: ref)
|
|
252
275
|
args << readline('Enter arguments', force: false)
|
|
253
276
|
end
|
|
254
277
|
venv_init
|
|
@@ -271,9 +294,9 @@ module Squared
|
|
|
271
294
|
when :freeze
|
|
272
295
|
format_desc action, flag, "file?=#{DEP_PYTHON[4]},opts*"
|
|
273
296
|
task flag do |_, args|
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
297
|
+
next unless (file = pip(flag, opts: args.to_a, banner: true)) && !silent?
|
|
298
|
+
|
|
299
|
+
puts File.read(file)
|
|
277
300
|
end
|
|
278
301
|
when :uninstall
|
|
279
302
|
format_desc action, flag, 'package+,opts*'
|
|
@@ -297,15 +320,12 @@ module Squared
|
|
|
297
320
|
end
|
|
298
321
|
when 'install'
|
|
299
322
|
format_desc(action, flag, 'opts*', before: case flag
|
|
300
|
-
when :
|
|
301
|
-
when :
|
|
302
|
-
when :
|
|
323
|
+
when :editable then 'path/url?'
|
|
324
|
+
when :upgrade then 'strategy?,package+'
|
|
325
|
+
when :requirement, :target then 'path'
|
|
326
|
+
else 'package+'
|
|
303
327
|
end)
|
|
304
328
|
case flag
|
|
305
|
-
when :editable
|
|
306
|
-
task flag do |_, args|
|
|
307
|
-
install flag, args.to_a
|
|
308
|
-
end
|
|
309
329
|
when :upgrade
|
|
310
330
|
task flag, [:strategy] do |_, args|
|
|
311
331
|
install flag, (case args.strategy
|
|
@@ -321,14 +341,16 @@ module Squared
|
|
|
321
341
|
end
|
|
322
342
|
end)
|
|
323
343
|
end
|
|
324
|
-
when :target
|
|
325
|
-
task flag, [:
|
|
326
|
-
|
|
327
|
-
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)
|
|
328
348
|
end
|
|
329
349
|
else
|
|
350
|
+
next if flag == :poetry && !poetry?
|
|
351
|
+
|
|
330
352
|
task flag do |_, args|
|
|
331
|
-
|
|
353
|
+
install flag, args.to_a
|
|
332
354
|
end
|
|
333
355
|
end
|
|
334
356
|
when 'outdated'
|
|
@@ -386,22 +408,24 @@ module Squared
|
|
|
386
408
|
cmd << '--no-root' if option('no-root')
|
|
387
409
|
else
|
|
388
410
|
cmd = pip_session 'install'
|
|
389
|
-
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')
|
|
390
413
|
if flag
|
|
391
|
-
case flag
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
end
|
|
399
|
-
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)
|
|
400
421
|
op.clear
|
|
401
422
|
else
|
|
402
423
|
append_global
|
|
403
424
|
end
|
|
404
|
-
|
|
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
|
|
405
429
|
append_editable
|
|
406
430
|
end
|
|
407
431
|
run(sync: sync, from: :depend)
|
|
@@ -433,7 +457,7 @@ module Squared
|
|
|
433
457
|
:patch
|
|
434
458
|
end
|
|
435
459
|
end
|
|
436
|
-
'--not-required'
|
|
460
|
+
'--not-required' if option('not-required', notequals: '0') && !env('PYTHON_DEFAULT')
|
|
437
461
|
end
|
|
438
462
|
cmd << '--local' if option('l', 'local')
|
|
439
463
|
append_global
|
|
@@ -443,7 +467,7 @@ module Squared
|
|
|
443
467
|
on :first, :outdated
|
|
444
468
|
banner = format_banner cmd
|
|
445
469
|
print_item banner if sync
|
|
446
|
-
pwd_set(
|
|
470
|
+
pwd_set(cmd, dryrun: dryrun) do
|
|
447
471
|
tc = theme[:current]
|
|
448
472
|
start = 0
|
|
449
473
|
found = 0
|
|
@@ -457,7 +481,8 @@ module Squared
|
|
|
457
481
|
(venv ? command(runenv, cmd) : `#{cmd}`).lines(chomp: true)
|
|
458
482
|
else
|
|
459
483
|
IO.popen(runenv || {}, cmd).readlines(chomp: true)
|
|
460
|
-
end
|
|
484
|
+
end
|
|
485
|
+
.each do |line|
|
|
461
486
|
next if line.match?(/^[ -]+$/)
|
|
462
487
|
|
|
463
488
|
if start > 0
|
|
@@ -520,7 +545,7 @@ module Squared
|
|
|
520
545
|
if found > 0
|
|
521
546
|
items = if se
|
|
522
547
|
choice('Select a package', items.map(&:first),
|
|
523
|
-
multiple: true, force: false, index: true, border: true).map
|
|
548
|
+
multiple: true, force: false, index: true, border: true).map { |n| items[n.pred].last }
|
|
524
549
|
elsif ia
|
|
525
550
|
items.map(&:last)
|
|
526
551
|
else
|
|
@@ -536,10 +561,9 @@ module Squared
|
|
|
536
561
|
if up && !items.empty?
|
|
537
562
|
base = %w[eager no-deps]
|
|
538
563
|
base << 'user' unless venv
|
|
539
|
-
opts = (base & opts).map
|
|
564
|
+
opts = (base & opts).map { |val| val == 'eager' ? "upgrade-strategy=#{val}" : val }
|
|
540
565
|
if dryrun
|
|
541
|
-
opts.map
|
|
542
|
-
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
|
|
543
567
|
else
|
|
544
568
|
install(:upgrade, opts, packages: items, banner: false)
|
|
545
569
|
end
|
|
@@ -552,8 +576,13 @@ module Squared
|
|
|
552
576
|
on :last, :outdated
|
|
553
577
|
end
|
|
554
578
|
|
|
555
|
-
def install(flag, opts = [], packages: [], banner:
|
|
556
|
-
|
|
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
|
|
557
586
|
case flag
|
|
558
587
|
when :editable
|
|
559
588
|
op << quote_option('e', op.pop || editable || '.')
|
|
@@ -568,7 +597,7 @@ module Squared
|
|
|
568
597
|
run(banner: banner, from: :install)
|
|
569
598
|
end
|
|
570
599
|
|
|
571
|
-
def build!(flag, opts = [])
|
|
600
|
+
def build!(flag, opts = [], outdir: nil, srcdir: nil)
|
|
572
601
|
list = case flag
|
|
573
602
|
when :poetry
|
|
574
603
|
cmd = poetry_session 'build'
|
|
@@ -579,6 +608,9 @@ module Squared
|
|
|
579
608
|
when :hatch
|
|
580
609
|
cmd, opts = hatch_session('build', opts: opts)
|
|
581
610
|
OPT_HATCH[:build]
|
|
611
|
+
when :meson
|
|
612
|
+
cmd = session 'meson', 'setup'
|
|
613
|
+
OPT_MESON[:build]
|
|
582
614
|
else
|
|
583
615
|
cmd, opts = python_session('-m build', opts: opts)
|
|
584
616
|
OPT_PYTHON[:build]
|
|
@@ -586,26 +618,45 @@ module Squared
|
|
|
586
618
|
op = OptionPartition.new(opts, list, cmd, project: self, single: singleopt(flag))
|
|
587
619
|
case flag
|
|
588
620
|
when :hatch
|
|
589
|
-
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
|
|
590
625
|
op.add_path(outdir)
|
|
626
|
+
else
|
|
627
|
+
outdir = op.first
|
|
628
|
+
op.add_first(path: true, expect: 'outdir not specified')
|
|
591
629
|
end
|
|
592
630
|
else
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
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)
|
|
604
649
|
end
|
|
605
650
|
end
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
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
|
|
609
660
|
end
|
|
610
661
|
|
|
611
662
|
def publish(flag, opts = [], test: false)
|
|
@@ -652,12 +703,12 @@ module Squared
|
|
|
652
703
|
op.add_path
|
|
653
704
|
end
|
|
654
705
|
end
|
|
655
|
-
run(from:
|
|
706
|
+
run(from: symjoin(flag, 'publish'), interactive: ['Publish', 'N', project])
|
|
656
707
|
end
|
|
657
708
|
|
|
658
709
|
def python(*args, sync: true, banner: verbose?, with: nil, pass: PASS_PYTHON[:python], **kwargs)
|
|
659
710
|
op = OptionPartition.new(session_opts(with, args: args, kwargs: kwargs, pass: pass), OPT_PYTHON[:common],
|
|
660
|
-
session('python', path: venv
|
|
711
|
+
session('python', path: !venv?),
|
|
661
712
|
project: self, multiple: [/^-c/], single: singleopt(:python), args: true,
|
|
662
713
|
stdin: true)
|
|
663
714
|
op.concat(args)
|
|
@@ -673,7 +724,7 @@ module Squared
|
|
|
673
724
|
end
|
|
674
725
|
end
|
|
675
726
|
print_run(op, banner, **kwargs)
|
|
676
|
-
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)
|
|
677
728
|
end
|
|
678
729
|
|
|
679
730
|
def pip(flag, *args, sync: true, banner: verbose?, with: nil, pass: nil, **kwargs)
|
|
@@ -684,7 +735,7 @@ module Squared
|
|
|
684
735
|
when :freeze, :inspect, :list, :check, :completion, :debug
|
|
685
736
|
opts.concat(args)
|
|
686
737
|
end
|
|
687
|
-
op = append_pip(flag, opts,
|
|
738
|
+
op = append_pip(flag, opts, pipopts(flag), target: pip_session(flag))
|
|
688
739
|
case flag
|
|
689
740
|
when :install, :uninstall, :show, :index
|
|
690
741
|
op.concat(args)
|
|
@@ -749,14 +800,24 @@ module Squared
|
|
|
749
800
|
op.clear
|
|
750
801
|
end
|
|
751
802
|
print_run(op, banner, **kwargs)
|
|
752
|
-
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))
|
|
753
804
|
.yield_self { |val| ret || val }
|
|
754
805
|
end
|
|
755
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
|
+
|
|
756
817
|
def variable_set(key, *args, **, &blk)
|
|
757
818
|
if block_given?
|
|
758
819
|
case key
|
|
759
|
-
when :dependfile, :
|
|
820
|
+
when :dependfile, :editable, :venv
|
|
760
821
|
args = block_args args, &blk
|
|
761
822
|
end
|
|
762
823
|
end
|
|
@@ -770,7 +831,7 @@ module Squared
|
|
|
770
831
|
@dependindex = index
|
|
771
832
|
@dependfile = val
|
|
772
833
|
else
|
|
773
|
-
log.warn "variable_set:
|
|
834
|
+
log.warn "variable_set: @dependfile=#{val}".subhint('not supported')
|
|
774
835
|
end
|
|
775
836
|
end
|
|
776
837
|
when :editable
|
|
@@ -790,60 +851,51 @@ module Squared
|
|
|
790
851
|
dependtype > 0 && !task_pass?('outdated')
|
|
791
852
|
end
|
|
792
853
|
|
|
854
|
+
def venv?
|
|
855
|
+
!venv.nil?
|
|
856
|
+
end
|
|
857
|
+
|
|
793
858
|
private
|
|
794
859
|
|
|
795
860
|
def pip_session(*cmd)
|
|
796
|
-
session('pip', *cmd, *preopts, path: venv
|
|
861
|
+
session('pip', *cmd, *preopts, path: !venv?)
|
|
797
862
|
end
|
|
798
863
|
|
|
799
864
|
def pip_output(*cmd)
|
|
800
|
-
session_output('pip', *cmd, *preopts, path: venv
|
|
865
|
+
session_output('pip', *cmd, *preopts, path: !venv?)
|
|
801
866
|
end
|
|
802
867
|
|
|
803
868
|
def python_session(*cmd, opts: nil)
|
|
804
|
-
|
|
805
|
-
return session('python', *pre, *cmd, path: venv.nil?) unless opts
|
|
806
|
-
|
|
807
|
-
op = OptionPartition.new(opts, OPT_PYTHON[:common], project: self, single: singleopt(:python))
|
|
808
|
-
[session('python', *pre, *op.to_a, *cmd, path: venv.nil?), op.extras]
|
|
809
|
-
end
|
|
810
|
-
|
|
811
|
-
def poetry_session(*cmd)
|
|
812
|
-
ret = session('poetry', *cmd, *preopts)
|
|
813
|
-
option('project', ignore: false) { |val| ret << quote_option('project', basepath(val)) }
|
|
814
|
-
ret
|
|
869
|
+
create_session('python', *cmd, common: OPT_PYTHON[:common], opts: opts, quiet: false)
|
|
815
870
|
end
|
|
816
871
|
|
|
817
872
|
def pdm_session(*cmd, opts: nil)
|
|
818
|
-
create_session(
|
|
873
|
+
create_session('pdm', *cmd, common: OPT_PDM[:common], opts: opts)
|
|
819
874
|
end
|
|
820
875
|
|
|
821
876
|
def hatch_session(*cmd, opts: nil)
|
|
822
|
-
|
|
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)
|
|
823
881
|
end
|
|
824
882
|
|
|
825
|
-
def
|
|
826
|
-
|
|
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
|
|
889
|
+
|
|
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
|
|
827
893
|
|
|
828
894
|
op = OptionPartition.new(opts, common, project: self, single: singleopt(name.to_sym))
|
|
829
|
-
[session(name, *
|
|
895
|
+
[session(name, *pre, *op.to_a, *cmd, path: !venv?), op.extras]
|
|
830
896
|
end
|
|
831
897
|
|
|
832
|
-
def append_pip(flag, opts, target: @session
|
|
833
|
-
list = OPT_PIP.fetch(from, []) + OPT_PIP[:common]
|
|
834
|
-
if pip_install?(flag) || from == :install
|
|
835
|
-
list.concat(OPT_PIP[:install_a])
|
|
836
|
-
list.concat(OPT_PIP[:install_b]) unless flag == :index
|
|
837
|
-
case flag
|
|
838
|
-
when :install, :editable, :upgrade
|
|
839
|
-
list.concat(OPT_PIP[:install_c] + OPT_PIP[:debug])
|
|
840
|
-
when :lock, :wheel
|
|
841
|
-
list.concat(OPT_PIP[:install_c])
|
|
842
|
-
when :download, :index
|
|
843
|
-
list.concat(OPT_PIP[:debug])
|
|
844
|
-
end
|
|
845
|
-
opts << 'no-build-isolation' if option('build-isolation', equals: '0')
|
|
846
|
-
end
|
|
898
|
+
def append_pip(flag, opts, list, target: @session)
|
|
847
899
|
op = OptionPartition.new(opts, list, target, project: self, single: singleopt)
|
|
848
900
|
append_global(target: target)
|
|
849
901
|
case flag
|
|
@@ -864,7 +916,7 @@ module Squared
|
|
|
864
916
|
end
|
|
865
917
|
op.swap
|
|
866
918
|
if edit
|
|
867
|
-
edit = basepath(edit) unless %r{\A[a-z]+(
|
|
919
|
+
edit = basepath(edit) unless %r{\A[a-z]+(\+[a-z]+)?://}i.match?(edit)
|
|
868
920
|
if flag == :editable
|
|
869
921
|
op.push(edit)
|
|
870
922
|
else
|
|
@@ -895,18 +947,16 @@ module Squared
|
|
|
895
947
|
end
|
|
896
948
|
|
|
897
949
|
def append_global(target: @session)
|
|
898
|
-
target
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
option('python', target: target) { |val| quote_option('python', basepath(val)) }
|
|
909
|
-
])
|
|
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)
|
|
910
960
|
append_nocolor(target: target)
|
|
911
961
|
end
|
|
912
962
|
|
|
@@ -917,14 +967,18 @@ module Squared
|
|
|
917
967
|
def read_pyproject(table, key = nil)
|
|
918
968
|
return [] unless (file = pyprojectfile)
|
|
919
969
|
|
|
920
|
-
|
|
970
|
+
ret = (@pyproject ||= {})[table]
|
|
971
|
+
unless ret
|
|
921
972
|
ret = []
|
|
973
|
+
found = false
|
|
922
974
|
start = /^\s*\[#{Regexp.escape(table)}\]\s*$/
|
|
923
975
|
ch = nil
|
|
924
|
-
found = false
|
|
925
976
|
File.foreach(file) do |line|
|
|
977
|
+
next if line.start_with?(/\s*#/)
|
|
978
|
+
|
|
926
979
|
if found
|
|
927
|
-
|
|
980
|
+
line.chomp!($1) if line =~ /(?<=[\d"'{}\[\]]|true|false)(\s*#.*)$/
|
|
981
|
+
break if line.match?(/^\s*\[(?:[\w.\-" ]+|".+"|'.+')\]\s*$/)
|
|
928
982
|
|
|
929
983
|
if ch
|
|
930
984
|
val = line.rstrip
|
|
@@ -940,9 +994,9 @@ module Squared
|
|
|
940
994
|
end
|
|
941
995
|
end
|
|
942
996
|
ret.last[1] += val
|
|
943
|
-
elsif
|
|
944
|
-
if (val =
|
|
945
|
-
case (ch =
|
|
997
|
+
elsif line.strip =~ /^(\S+)\s*=\s*([+-]?[\d.]+|true|false|("""|'''|["'\[{])(.*))$/
|
|
998
|
+
if (val = $4)
|
|
999
|
+
case (ch = $3)
|
|
946
1000
|
when '{', '['
|
|
947
1001
|
val = "#{ch}#{val}"
|
|
948
1002
|
ch = ch == '{' ? '}' : ']'
|
|
@@ -955,7 +1009,7 @@ module Squared
|
|
|
955
1009
|
end
|
|
956
1010
|
end
|
|
957
1011
|
else
|
|
958
|
-
val = case (ch =
|
|
1012
|
+
val = case (ch = $2)
|
|
959
1013
|
when 'true'
|
|
960
1014
|
true
|
|
961
1015
|
when 'false'
|
|
@@ -964,7 +1018,10 @@ module Squared
|
|
|
964
1018
|
ch.include?('.') ? ch.to_f : ch.to_i
|
|
965
1019
|
end
|
|
966
1020
|
end
|
|
967
|
-
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
|
|
968
1025
|
end
|
|
969
1026
|
else
|
|
970
1027
|
found = line.match?(start)
|
|
@@ -972,9 +1029,7 @@ module Squared
|
|
|
972
1029
|
end
|
|
973
1030
|
@pyproject[table] = ret
|
|
974
1031
|
end
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
ret
|
|
1032
|
+
key ? ret.find { |val| val.first == key }&.last : ret
|
|
978
1033
|
end
|
|
979
1034
|
|
|
980
1035
|
def pyprojectfile
|
|
@@ -986,9 +1041,9 @@ module Squared
|
|
|
986
1041
|
case flag
|
|
987
1042
|
when :python
|
|
988
1043
|
/\A(?:v+|q+|b+|V+|O+)\z/
|
|
989
|
-
when :pdm
|
|
1044
|
+
when :pdm, :poetry
|
|
990
1045
|
/\Av+\z/
|
|
991
|
-
when :twine
|
|
1046
|
+
when :twine, :meson
|
|
992
1047
|
nil
|
|
993
1048
|
else
|
|
994
1049
|
/\A(?:v+|q+)\z/
|
|
@@ -998,7 +1053,7 @@ module Squared
|
|
|
998
1053
|
def preopts(quiet: true)
|
|
999
1054
|
ret = []
|
|
1000
1055
|
case verbose
|
|
1001
|
-
when
|
|
1056
|
+
when false
|
|
1002
1057
|
ret << '--quiet' if quiet
|
|
1003
1058
|
when Numeric
|
|
1004
1059
|
ret << "-#{'v' * verbose}" if verbose > 0
|
|
@@ -1006,6 +1061,23 @@ module Squared
|
|
|
1006
1061
|
ret
|
|
1007
1062
|
end
|
|
1008
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
|
+
|
|
1009
1081
|
def variables
|
|
1010
1082
|
(super + %i[venv editable]).freeze
|
|
1011
1083
|
end
|
|
@@ -1034,11 +1106,16 @@ module Squared
|
|
|
1034
1106
|
end
|
|
1035
1107
|
|
|
1036
1108
|
def venv_set(val)
|
|
1109
|
+
@venv = nil
|
|
1037
1110
|
return unless val
|
|
1038
1111
|
|
|
1039
|
-
write = ->(level, hint) { log.add(level, "venv: #{@venv}".subhint(hint)) }
|
|
1112
|
+
write = ->(level, hint) { log.add(level, "#{virtualenv? ? 'virtualenv' : 'venv'}: #{@venv}".subhint(hint)) }
|
|
1040
1113
|
if val.is_a?(Array)
|
|
1041
1114
|
val, *opts = val
|
|
1115
|
+
if opts.first == 'virtualenv'
|
|
1116
|
+
@virtualenv = true
|
|
1117
|
+
opts.shift
|
|
1118
|
+
end
|
|
1042
1119
|
@venvopts = opts
|
|
1043
1120
|
end
|
|
1044
1121
|
@venv = basepath val
|
|
@@ -1058,21 +1135,35 @@ module Squared
|
|
|
1058
1135
|
def venv_init
|
|
1059
1136
|
return if !venv || (venvbin.directory? && !venvbin.empty?)
|
|
1060
1137
|
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
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?
|
|
1065
1143
|
end
|
|
1066
1144
|
|
|
1067
1145
|
def venv_create(dir, opts = [], env: nil, banner: banner?)
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
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/)
|
|
1073
1157
|
ret = run(op, env, exception: true, banner: banner)
|
|
1074
|
-
|
|
1075
|
-
|
|
1158
|
+
args = []
|
|
1159
|
+
requires = read_pyproject 'build-system', 'requires'
|
|
1160
|
+
args.concat(requires) if requires.is_a?(Array)
|
|
1161
|
+
if poetry?
|
|
1162
|
+
requires = read_pyproject 'tool.poetry', 'requires-poetry'
|
|
1163
|
+
args << "poetry#{requires}"
|
|
1164
|
+
end
|
|
1165
|
+
pip(:install, *args, banner: false) unless args.empty?
|
|
1166
|
+
success?(ret, banner, !status) { |ret| puts(ret && dir.directory? ? "Success: #{dir}" : 'Failed') }
|
|
1076
1167
|
end
|
|
1077
1168
|
|
|
1078
1169
|
def pip_install?(flag)
|
|
@@ -1089,6 +1180,8 @@ module Squared
|
|
|
1089
1180
|
build_backend == 'hatchling.build'
|
|
1090
1181
|
when :setuptools
|
|
1091
1182
|
build_backend == 'setuptools.build_meta'
|
|
1183
|
+
when :meson
|
|
1184
|
+
build_backend != 'mesonpy' && exist?('meson.build')
|
|
1092
1185
|
end
|
|
1093
1186
|
end
|
|
1094
1187
|
|
|
@@ -1104,6 +1197,10 @@ module Squared
|
|
|
1104
1197
|
dependtype == 1
|
|
1105
1198
|
end
|
|
1106
1199
|
|
|
1200
|
+
def virtualenv?
|
|
1201
|
+
@virtualenv ||= exist?('virtualenv.ini') || !ENV['VIRTUALENV_PYTHON'].nil?
|
|
1202
|
+
end
|
|
1203
|
+
|
|
1107
1204
|
def requirements?
|
|
1108
1205
|
dependtype == 5
|
|
1109
1206
|
end
|