squared 0.4.12 → 0.4.14
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 +100 -0
- data/README.ruby.md +6 -2
- data/lib/squared/common/base.rb +5 -2
- data/lib/squared/common/format.rb +8 -2
- data/lib/squared/common/prompt.rb +1 -1
- data/lib/squared/common/shell.rb +14 -14
- data/lib/squared/common/system.rb +21 -14
- data/lib/squared/common/utils.rb +7 -3
- data/lib/squared/config.rb +6 -5
- data/lib/squared/version.rb +1 -1
- data/lib/squared/workspace/application.rb +21 -12
- data/lib/squared/workspace/project/base.rb +348 -137
- data/lib/squared/workspace/project/docker.rb +95 -52
- data/lib/squared/workspace/project/git.rb +86 -52
- data/lib/squared/workspace/project/node.rb +71 -44
- data/lib/squared/workspace/project/python.rb +360 -131
- data/lib/squared/workspace/project/ruby.rb +140 -103
- data/lib/squared/workspace/project/support/class.rb +39 -3
- data/lib/squared/workspace/repo.rb +2 -1
- data/lib/squared/workspace/support/data.rb +2 -2
- metadata +1 -1
@@ -8,7 +8,7 @@ module Squared
|
|
8
8
|
DIR_PYTHON = (DEP_PYTHON + %w[README.rst]).freeze
|
9
9
|
OPT_PYTHON = {
|
10
10
|
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,
|
11
|
-
build: %w[n|no-isolation s|sdist v|verbose w|wheel
|
11
|
+
build: %w[n|no-isolation s|sdist x|skip-dependency-check v|verbose w|wheel C|config-setting=q installer=b
|
12
12
|
o|outdir=p].freeze,
|
13
13
|
venv: %w[clear copies symlinks system-site-packages upgrade upgrade-deps without-scm-ignore-files without-pip
|
14
14
|
prompt=q].freeze
|
@@ -28,11 +28,18 @@ module Squared
|
|
28
28
|
freeze: %w[all exclude-editable l|local user exclude=b path=p r|requirement=p].freeze
|
29
29
|
}.freeze
|
30
30
|
OPT_POETRY = {
|
31
|
-
common: %w[ansi no-ansi no-cache n|no-interaction no-plugins
|
31
|
+
common: %w[ansi no-ansi no-cache n|no-interaction no-plugins q|quiet v|verbose P|project=p].freeze,
|
32
32
|
build: %w[clean config-settings=qq f|format=b o|output=p].freeze,
|
33
|
-
publish: %w[build dry-run
|
33
|
+
publish: %w[build dry-run skip-existing cert=p client-cert=p dist-dir=p p|password=b r|repository=b
|
34
34
|
u|username=b].freeze
|
35
35
|
}.freeze
|
36
|
+
OPT_PDM = {
|
37
|
+
common: %w[I|ignore-python no-cache n|non-interactive].freeze,
|
38
|
+
build: %w[C=bm no-clean no-isolation no-sdist no-wheel quiet verbose config-setting=q d|dest=p p|project=p
|
39
|
+
k|skip=b].freeze,
|
40
|
+
publish: %w[no-build no-very-ssl quiet S|sign skip-existing verbose ca-certs=p c|comment=q d|dest=p identity=b
|
41
|
+
p|password=q p|project=p r|repository=q k|skip=b u|username=b].freeze
|
42
|
+
}.freeze
|
36
43
|
OPT_HATCH = {
|
37
44
|
common: %w[color interactive no-color no-interactive cache-dir=p config=p data-dir=p e|env=b p|project=b
|
38
45
|
q|quiet v|verbose].freeze,
|
@@ -41,11 +48,11 @@ module Squared
|
|
41
48
|
p|publisher=b r|repo=b u|user=q].freeze
|
42
49
|
}.freeze
|
43
50
|
OPT_TWINE = {
|
44
|
-
publish: %w[attestations disable-progress-bar non-interactive skip-existing verbose
|
45
|
-
|
51
|
+
publish: %w[attestations disable-progress-bar non-interactive s|sign skip-existing verbose cert=p
|
52
|
+
client-cert=p c|comment=q config-file=p i|identity=b p|password=q r|repository=b repository-url=q
|
46
53
|
sign-with=b u|username=q].freeze
|
47
54
|
}.freeze
|
48
|
-
private_constant :DEP_PYTHON, :DIR_PYTHON, :OPT_PYTHON, :OPT_PIP, :OPT_POETRY, :OPT_HATCH, :OPT_TWINE
|
55
|
+
private_constant :DEP_PYTHON, :DIR_PYTHON, :OPT_PYTHON, :OPT_PIP, :OPT_POETRY, :OPT_PDM, :OPT_HATCH, :OPT_TWINE
|
49
56
|
|
50
57
|
class << self
|
51
58
|
def populate(*); end
|
@@ -71,7 +78,7 @@ module Squared
|
|
71
78
|
|
72
79
|
attr_reader :venv, :editable
|
73
80
|
|
74
|
-
def initialize(*,
|
81
|
+
def initialize(*, editable: '.', verbose: nil, **kwargs)
|
75
82
|
super
|
76
83
|
if @pass.include?(Python.ref)
|
77
84
|
initialize_ref Python.ref
|
@@ -80,24 +87,21 @@ module Squared
|
|
80
87
|
initialize_build(Python.ref, **kwargs)
|
81
88
|
initialize_env(**kwargs)
|
82
89
|
end
|
83
|
-
@dependindex = DEP_PYTHON.index { |file| basepath(file).exist? }
|
84
|
-
@dependfile = @path + DEP_PYTHON[@dependindex || 0]
|
85
90
|
@verbose = verbose.size if verbose.is_a?(String) && verbose.match?(/\Av+\z/)
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
when String
|
90
|
-
Pathname.new(editable)
|
91
|
-
end
|
92
|
-
venv_set venv if venv
|
91
|
+
dependfile_set DEP_PYTHON
|
92
|
+
editable_set editable
|
93
|
+
venv_set kwargs[:venv]
|
93
94
|
end
|
94
95
|
|
95
96
|
subtasks({
|
96
|
-
'venv' => %i[
|
97
|
+
'venv' => %i[exec create remove show].freeze,
|
97
98
|
'pip' => %i[uninstall freeze].freeze,
|
98
99
|
'install' => %i[user force upgrade target editable].freeze,
|
99
|
-
'
|
100
|
-
'
|
100
|
+
'outdated' => %i[major minor patch].freeze,
|
101
|
+
'build' => %i[python poetry pdm hatch].freeze,
|
102
|
+
'publish' => %i[poetry pdm hatch twine].freeze,
|
103
|
+
'run' => nil,
|
104
|
+
'exec' => nil
|
101
105
|
})
|
102
106
|
|
103
107
|
def ref
|
@@ -112,105 +116,202 @@ module Squared
|
|
112
116
|
Python.subtasks do |action, flags|
|
113
117
|
next if @pass.include?(action)
|
114
118
|
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
119
|
+
if flags.nil?
|
120
|
+
case action
|
121
|
+
when 'run'
|
122
|
+
next unless pyprojectfile
|
123
|
+
|
124
|
+
format_desc action, nil, "script+|#{indexchar}index+|#,pattern*"
|
125
|
+
task action, [:command] do |_, args|
|
126
|
+
found = 0
|
127
|
+
['tool.poetry.scripts', 'tool.pdm.scripts', 'project.scripts'].each_with_index do |table, index|
|
128
|
+
next if (list = read_pyproject(table)).empty?
|
129
|
+
|
130
|
+
if args.command == '#'
|
131
|
+
format_list(list, "run[#{indexchar}N]", 'scripts', grep: args.extras, from: pyprojectfile)
|
132
|
+
found |= 1
|
133
|
+
else
|
134
|
+
args.to_a.each do |val|
|
135
|
+
if (n, = indexitem(val))
|
136
|
+
if (script, = list[n - 1])
|
137
|
+
case index
|
138
|
+
when 0
|
139
|
+
script = session_output 'poetry', 'run', script
|
140
|
+
when 1
|
141
|
+
script = pdm_session 'run', script
|
142
|
+
else
|
143
|
+
venv_init
|
144
|
+
end
|
145
|
+
found |= 1
|
146
|
+
run(script, from: :run)
|
147
|
+
elsif exception
|
148
|
+
indexerror n, list
|
149
|
+
else
|
150
|
+
found |= 2
|
151
|
+
log.warn "run script #{n} of #{list.size} (out of range)"
|
152
|
+
end
|
153
|
+
else
|
154
|
+
case index
|
155
|
+
when 0
|
156
|
+
found |= 1
|
157
|
+
run(session_output('poetry', 'run', val), from: :run)
|
158
|
+
when 1
|
159
|
+
found |= 1
|
160
|
+
run(pdm_session('run', val), from: :run)
|
161
|
+
else
|
162
|
+
raise_error("script: #{val}", hint: 'unknown') if exception
|
163
|
+
found |= 2
|
164
|
+
log.warn "run script \"#{val}\" (not indexed)"
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
124
168
|
end
|
125
|
-
|
169
|
+
break
|
170
|
+
end
|
171
|
+
unless found.anybits?(1)
|
172
|
+
puts log_message(found == 0 ? Logger::INFO : Logger.WARN,
|
173
|
+
"no scripts #{found == 0 ? 'found' : 'executed'}",
|
174
|
+
subject: name, hint: pyprojectfile)
|
175
|
+
end
|
176
|
+
end
|
177
|
+
when 'exec'
|
178
|
+
format_desc action, nil, 'command|:,args*'
|
179
|
+
task action do |_, args|
|
180
|
+
i = (args = args.to_a).delete(':')
|
181
|
+
cmd = if i && !workspace.windows?
|
182
|
+
readline('Enter script', force: true, multiline: ['##', ';'])
|
183
|
+
elsif i || args.empty?
|
184
|
+
readline('Enter command', force: true)
|
185
|
+
else
|
186
|
+
if (val = command_args(args, prefix: 'python'))
|
187
|
+
args << val
|
188
|
+
end
|
189
|
+
args.join(' ')
|
190
|
+
end
|
191
|
+
shell(cmd, name: :exec, chdir: path)
|
192
|
+
end
|
193
|
+
end
|
194
|
+
else
|
195
|
+
namespace action do
|
196
|
+
flags.each do |flag|
|
197
|
+
case action
|
198
|
+
when 'venv'
|
199
|
+
if flag == :create
|
200
|
+
format_desc action, flag, 'dir,opts*'
|
201
|
+
task flag, [:dir] do |_, args|
|
202
|
+
dir = path + param_guard(action, flag, args: args, key: :dir)
|
203
|
+
venv_create dir, args.extras
|
204
|
+
end
|
205
|
+
elsif venv
|
206
|
+
case flag
|
207
|
+
when :remove
|
208
|
+
next unless projectpath?(venv)
|
209
|
+
|
210
|
+
format_desc action, flag, 'c|create?,d|depend?'
|
211
|
+
task flag do |_, args|
|
212
|
+
rm_rf(venv, verbose: true)
|
213
|
+
venv_init if has_value?(%w[c create], args.to_a)
|
214
|
+
depend if has_value?(%w[d depend], args.to_a)
|
215
|
+
end
|
216
|
+
when :exec
|
217
|
+
format_desc action, flag, 'command,args*'
|
218
|
+
task flag do |_, args|
|
219
|
+
args = args.to_a
|
220
|
+
if args.empty?
|
221
|
+
args = readline('Enter command', force: true).split(' ', 2)
|
222
|
+
elsif args.size == 1 && !option('interactive', prefix: 'venv', equals: '0')
|
223
|
+
args << readline('Enter arguments', force: false)
|
224
|
+
end
|
225
|
+
venv_init
|
226
|
+
run args.join(' ')
|
227
|
+
end
|
228
|
+
when :show
|
229
|
+
format_desc action, flag
|
230
|
+
task flag do
|
231
|
+
puts venv
|
232
|
+
end
|
233
|
+
end
|
234
|
+
end
|
235
|
+
when 'pip'
|
126
236
|
case flag
|
127
|
-
when :
|
128
|
-
|
129
|
-
|
130
|
-
format_desc action, flag, 'c|create?,d|depend?'
|
237
|
+
when :freeze
|
238
|
+
format_desc action, flag, "file?=#{DEP_PYTHON[4]},opts*"
|
131
239
|
task flag do |_, args|
|
132
|
-
|
133
|
-
|
134
|
-
|
240
|
+
if (file = pip(flag, args.to_a)) && verbose
|
241
|
+
puts File.read(file)
|
242
|
+
end
|
135
243
|
end
|
136
|
-
when :
|
137
|
-
format_desc action, flag, '
|
244
|
+
when :uninstall
|
245
|
+
format_desc action, flag, 'package+,opts*'
|
138
246
|
task flag do |_, args|
|
139
|
-
|
140
|
-
args = readline('Enter command', force: true).split(' ', 2) if args.empty?
|
141
|
-
venv_init
|
142
|
-
run session(*args, path: false)
|
143
|
-
end
|
144
|
-
when :show
|
145
|
-
format_desc action, flag
|
146
|
-
task flag do
|
147
|
-
puts venv
|
247
|
+
pip flag, args.to_a
|
148
248
|
end
|
149
249
|
end
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
250
|
+
when 'install'
|
251
|
+
format_desc(action, flag, 'opts*', before: case flag
|
252
|
+
when :target then 'dir'
|
253
|
+
when :editable then 'path/url?'
|
254
|
+
when :upgrade then 'strategy?,package+'
|
255
|
+
end)
|
256
|
+
case flag
|
257
|
+
when :editable
|
258
|
+
task flag do |_, args|
|
259
|
+
install flag, args.to_a
|
260
|
+
end
|
261
|
+
when :upgrade
|
262
|
+
task flag, [:strategy] do |_, args|
|
263
|
+
case (strategy = args.strategy)
|
264
|
+
when 'eager', 'only-if-needed'
|
265
|
+
args = args.extras
|
266
|
+
else
|
267
|
+
args = args.to_a
|
268
|
+
strategy = nil
|
269
|
+
end
|
270
|
+
install(flag, args, strategy: strategy)
|
271
|
+
end
|
272
|
+
when :target
|
273
|
+
task flag, [:dir] do |_, args|
|
274
|
+
dir = param_guard(action, flag, args: args, key: :dir)
|
275
|
+
depend(flag, args.extras, target: dir)
|
276
|
+
end
|
277
|
+
else
|
278
|
+
task flag do |_, args|
|
279
|
+
depend flag, args.to_a
|
158
280
|
end
|
159
281
|
end
|
160
|
-
when
|
161
|
-
format_desc action, flag, '
|
162
|
-
task flag do |_, args|
|
163
|
-
pip flag, args.to_a
|
164
|
-
end
|
165
|
-
end
|
166
|
-
when 'install'
|
167
|
-
format_desc(action, flag, 'opts*', before: case flag
|
168
|
-
when :target then 'dir'
|
169
|
-
when :editable then 'path/url?'
|
170
|
-
when :upgrade then 'strategy?,package+'
|
171
|
-
end)
|
172
|
-
case flag
|
173
|
-
when :editable
|
282
|
+
when 'outdated'
|
283
|
+
format_desc action, flag, 'eager?'
|
174
284
|
task flag do |_, args|
|
175
|
-
|
285
|
+
outdated flag, args.to_a
|
176
286
|
end
|
177
|
-
when
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
end
|
186
|
-
install(flag, args, strategy: strategy)
|
287
|
+
when 'build'
|
288
|
+
case flag
|
289
|
+
when :poetry
|
290
|
+
next unless build_backend == 'poetry.core.masonry.api'
|
291
|
+
when :pdm
|
292
|
+
next unless build_backend == 'pdm.backend'
|
293
|
+
when :hatch
|
294
|
+
next unless build_backend == 'hatchling.build'
|
187
295
|
end
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
296
|
+
format_desc(action, flag, 'opts*', after: case flag
|
297
|
+
when :python then 'srcdir?'
|
298
|
+
when :poetry then 'output?'
|
299
|
+
when :pdm then 'dest?'
|
300
|
+
when :hatch then 'location?'
|
301
|
+
end)
|
302
|
+
task flag do |_, args|
|
303
|
+
build! flag, args.to_a
|
192
304
|
end
|
193
|
-
|
305
|
+
break unless flag == :python
|
306
|
+
when 'publish'
|
307
|
+
format_desc(action, flag, 'opts*', after: case flag
|
308
|
+
when :hatch then 'artifacts?'
|
309
|
+
when :twine then 'dist?'
|
310
|
+
end)
|
194
311
|
task flag do |_, args|
|
195
|
-
|
312
|
+
publish flag, args.to_a
|
196
313
|
end
|
197
314
|
end
|
198
|
-
when 'build'
|
199
|
-
format_desc(action, flag, 'opts*', after: case flag
|
200
|
-
when :python then 'srcdir?'
|
201
|
-
when :hatch then 'location?'
|
202
|
-
end)
|
203
|
-
task flag do |_, args|
|
204
|
-
build! flag, args.to_a
|
205
|
-
end
|
206
|
-
when 'publish'
|
207
|
-
format_desc(action, flag, 'opts*', after: case flag
|
208
|
-
when :hatch then 'artifacts?'
|
209
|
-
when :twine then 'dist?'
|
210
|
-
end)
|
211
|
-
task flag do |_, args|
|
212
|
-
publish flag, args.to_a
|
213
|
-
end
|
214
315
|
end
|
215
316
|
end
|
216
317
|
end
|
@@ -249,7 +350,7 @@ module Squared
|
|
249
350
|
end
|
250
351
|
end
|
251
352
|
|
252
|
-
def outdated(
|
353
|
+
def outdated(flag = nil, opts = [], sync: invoked_sync?('outdated'))
|
253
354
|
cmd = pip_session 'list', '--outdated'
|
254
355
|
append_global
|
255
356
|
cmd = session_done cmd
|
@@ -259,28 +360,35 @@ module Squared
|
|
259
360
|
print_item banner if sync
|
260
361
|
start = 0
|
261
362
|
found = 0
|
262
|
-
major =
|
363
|
+
major = []
|
364
|
+
minor = []
|
365
|
+
patch = []
|
263
366
|
pwd_set(from: :outdated) do
|
264
367
|
buffer = []
|
265
368
|
out = ->(val) { sync ? puts(val) : buffer << val }
|
266
369
|
IO.popen(runenv || {}, cmd).each do |line|
|
267
|
-
next if line.match?(/^[
|
370
|
+
next if line.match?(/^[ -]+$/)
|
268
371
|
|
269
372
|
if start > 0
|
270
373
|
unless stdin?
|
271
|
-
|
272
|
-
next unless
|
374
|
+
cur, lat = line.scan(SEM_VER)
|
375
|
+
next unless cur && lat
|
273
376
|
|
274
377
|
latest = lat.join
|
275
378
|
current = cur.join
|
276
379
|
semver cur
|
277
380
|
semver lat
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
381
|
+
name = line.split(' ', 2).first
|
382
|
+
type = if semmajor?(cur, lat)
|
383
|
+
major << name
|
384
|
+
2
|
385
|
+
elsif cur[2] == lat[2]
|
386
|
+
patch << name
|
387
|
+
0
|
388
|
+
else
|
389
|
+
minor << name
|
390
|
+
1
|
391
|
+
end
|
284
392
|
if type == 0
|
285
393
|
styles = color(:yellow)
|
286
394
|
else
|
@@ -314,7 +422,16 @@ module Squared
|
|
314
422
|
puts buffer
|
315
423
|
end
|
316
424
|
if found > 0
|
317
|
-
|
425
|
+
print_status(major.size, minor.size, patch.size, from: :outdated)
|
426
|
+
pkg = case flag
|
427
|
+
when :major
|
428
|
+
major + minor + patch
|
429
|
+
when :minor
|
430
|
+
minor + patch
|
431
|
+
when :patch
|
432
|
+
patch
|
433
|
+
end
|
434
|
+
install(:upgrade, pkg, strategy: opts.include?('eager') ? 'eager' : nil) unless !pkg || pkg.empty?
|
318
435
|
elsif start == 0
|
319
436
|
puts 'No updates were found'
|
320
437
|
end
|
@@ -346,6 +463,9 @@ module Squared
|
|
346
463
|
when :poetry
|
347
464
|
cmd = poetry_session 'build'
|
348
465
|
list = OPT_POETRY[:build] + OPT_POETRY[:common]
|
466
|
+
when :pdm
|
467
|
+
cmd, opts = pdm_session('build', opts: opts)
|
468
|
+
list = OPT_PDM[:build]
|
349
469
|
when :hatch
|
350
470
|
cmd, opts = hatch_session('build', opts: opts)
|
351
471
|
list = OPT_HATCH[:build]
|
@@ -353,7 +473,7 @@ module Squared
|
|
353
473
|
srcdir = nil
|
354
474
|
op = OptionPartition.new(opts, list, cmd, project: self, single: singleopt(flag))
|
355
475
|
op.each do |opt|
|
356
|
-
if !srcdir && basepath(opt).exist? && projectpath?(opt)
|
476
|
+
if !srcdir && basepath(opt.chomp('*')).exist? && projectpath?(opt.chomp('*'))
|
357
477
|
srcdir = opt
|
358
478
|
else
|
359
479
|
op.found << opt
|
@@ -361,12 +481,13 @@ module Squared
|
|
361
481
|
end
|
362
482
|
op.swap
|
363
483
|
case flag
|
364
|
-
when :poetry
|
484
|
+
when :poetry, :pdm
|
365
485
|
if srcdir
|
366
|
-
|
486
|
+
args = flag == :pdm ? ['d', 'dest'] : ['o', 'output']
|
487
|
+
if op.arg?(*args)
|
367
488
|
op.extras << srcdir
|
368
489
|
else
|
369
|
-
op << quote_option(
|
490
|
+
op << quote_option(args.last, path + srcdir)
|
370
491
|
end
|
371
492
|
srcdir = nil
|
372
493
|
end
|
@@ -388,21 +509,35 @@ module Squared
|
|
388
509
|
when :poetry
|
389
510
|
poetry_session 'publish'
|
390
511
|
list = OPT_POETRY[:publish] + OPT_POETRY[:common]
|
391
|
-
when :
|
392
|
-
|
393
|
-
list =
|
512
|
+
when :pdm
|
513
|
+
opts = pdm_session('publish', opts: opts).last
|
514
|
+
list = OPT_PDM[:publish]
|
394
515
|
when :hatch
|
395
516
|
opts = hatch_session('publish', opts: opts).last
|
396
517
|
list = OPT_HATCH[:publish]
|
518
|
+
when :twine
|
519
|
+
session 'twine', 'upload'
|
520
|
+
list = OPT_TWINE[:publish]
|
397
521
|
end
|
398
522
|
op = OptionPartition.new(opts, list, @session, project: self, single: singleopt(flag))
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
523
|
+
dist = lambda do
|
524
|
+
(path + 'dist').tap do |dir|
|
525
|
+
raise_error('no source files found', hint: dir) unless dir.directory? && !dir.empty?
|
526
|
+
end
|
527
|
+
end
|
528
|
+
case flag
|
529
|
+
when :hatch, :twine
|
530
|
+
if op.empty?
|
531
|
+
op.extras << "#{dist.call}/*"
|
532
|
+
else
|
533
|
+
op.map! { |val| path + val }
|
534
|
+
end
|
535
|
+
op.append
|
536
|
+
else
|
537
|
+
dist.call unless op.arg?(*(flag == :poetry ? ['dist-dir'] : ['d', 'dest']))
|
538
|
+
op.clear(pass: false)
|
403
539
|
end
|
404
|
-
|
405
|
-
run(from: :"#{flag}:publish")
|
540
|
+
run(from: :"#{flag}:publish", interactive: "Publish #{sub_style(project, styles: theme[:active])}")
|
406
541
|
end
|
407
542
|
|
408
543
|
def pip(flag, opts = [])
|
@@ -432,7 +567,9 @@ module Squared
|
|
432
567
|
else
|
433
568
|
log.warn "variable_set: @#{key}=#{req} (not supported)"
|
434
569
|
end
|
435
|
-
when :
|
570
|
+
when :editable
|
571
|
+
editable_set val.first
|
572
|
+
when :venv
|
436
573
|
instance_variable_set(:"@#{key}", val.empty? ? nil : basepath(*val))
|
437
574
|
else
|
438
575
|
super
|
@@ -469,11 +606,19 @@ module Squared
|
|
469
606
|
ret
|
470
607
|
end
|
471
608
|
|
609
|
+
def pdm_session(*cmd, opts: nil)
|
610
|
+
create_session(*cmd, name: 'pdm', common: OPT_PDM[:common], opts: opts)
|
611
|
+
end
|
612
|
+
|
472
613
|
def hatch_session(*cmd, opts: nil)
|
473
|
-
|
614
|
+
create_session(*cmd, name: 'hatch', common: OPT_HATCH[:common], opts: opts)
|
615
|
+
end
|
616
|
+
|
617
|
+
def create_session(*cmd, name:, common:, opts: nil)
|
618
|
+
return session(name, *preopts, *cmd, path: venv.nil?) unless opts
|
474
619
|
|
475
|
-
op = OptionPartition.new(opts,
|
476
|
-
ret = session(
|
620
|
+
op = OptionPartition.new(opts, common, project: self, single: singleopt)
|
621
|
+
ret = session(name, *op.to_a, *cmd, path: venv.nil?)
|
477
622
|
[ret, op.extras]
|
478
623
|
end
|
479
624
|
|
@@ -551,6 +696,79 @@ module Squared
|
|
551
696
|
append_nocolor(target: target)
|
552
697
|
end
|
553
698
|
|
699
|
+
def build_backend
|
700
|
+
@build_backend ||= read_pyproject('build-system', 'build-backend') || ''
|
701
|
+
end
|
702
|
+
|
703
|
+
def read_pyproject(table, key = nil)
|
704
|
+
return [] unless (file = pyprojectfile)
|
705
|
+
|
706
|
+
unless (ret = (@pyproject ||= {})[table])
|
707
|
+
ret = []
|
708
|
+
start = /^\s*\[#{Regexp.escape(table)}\]\s*$/
|
709
|
+
ch = nil
|
710
|
+
found = false
|
711
|
+
File.foreach(file) do |line|
|
712
|
+
if found
|
713
|
+
break if line.match?(/^\s*\[[\w.-]+\]\s*$/)
|
714
|
+
|
715
|
+
if ch
|
716
|
+
val = line.rstrip
|
717
|
+
case ch
|
718
|
+
when '}', ']'
|
719
|
+
ch = nil if val.end_with?(ch)
|
720
|
+
val = "\n#{val}"
|
721
|
+
else
|
722
|
+
if val.chomp!(ch)
|
723
|
+
ch = nil
|
724
|
+
else
|
725
|
+
val = line
|
726
|
+
end
|
727
|
+
end
|
728
|
+
ret.last[1] += val
|
729
|
+
elsif (data = line.match(/^\s*(\S+)\s*=\s*([+-]?[\d.]+|true|false|("""|'''|["'\[{])(.*?))\s*$/))
|
730
|
+
if (val = data[4])
|
731
|
+
case (ch = data[3])
|
732
|
+
when '{', '['
|
733
|
+
val = "#{ch}#{val}"
|
734
|
+
ch = ch == '{' ? '}' : ']'
|
735
|
+
ch = nil if val.end_with?(ch)
|
736
|
+
else
|
737
|
+
if val.chomp!(ch)
|
738
|
+
ch = nil
|
739
|
+
elsif ch.size == 1
|
740
|
+
next
|
741
|
+
end
|
742
|
+
end
|
743
|
+
else
|
744
|
+
val = case (val = data[2])
|
745
|
+
when 'true'
|
746
|
+
true
|
747
|
+
when 'false'
|
748
|
+
false
|
749
|
+
else
|
750
|
+
val.include?('.') ? val.to_f : val.to_i
|
751
|
+
end
|
752
|
+
end
|
753
|
+
ret << [data[1], val]
|
754
|
+
end
|
755
|
+
else
|
756
|
+
found = line.match?(start)
|
757
|
+
end
|
758
|
+
end
|
759
|
+
@pyproject[table] = ret
|
760
|
+
end
|
761
|
+
return ret.find { |val| val[0] == key }&.last if key
|
762
|
+
|
763
|
+
ret
|
764
|
+
end
|
765
|
+
|
766
|
+
def pyprojectfile
|
767
|
+
return unless (ret = basepath(DEP_PYTHON[2])).exist?
|
768
|
+
|
769
|
+
ret
|
770
|
+
end
|
771
|
+
|
554
772
|
def singleopt(flag = nil)
|
555
773
|
case flag
|
556
774
|
when :python
|
@@ -591,7 +809,18 @@ module Squared
|
|
591
809
|
@venv&.join(workspace.windows? ? 'Scripts' : 'bin')
|
592
810
|
end
|
593
811
|
|
812
|
+
def editable_set(val)
|
813
|
+
@editable = case val
|
814
|
+
when '.', Pathname
|
815
|
+
val
|
816
|
+
when String
|
817
|
+
Pathname.new(editable)
|
818
|
+
end
|
819
|
+
end
|
820
|
+
|
594
821
|
def venv_set(val)
|
822
|
+
return unless val
|
823
|
+
|
595
824
|
if val.is_a?(Array)
|
596
825
|
val, *opts = val
|
597
826
|
@venvopts = opts
|