Browse Source

argparsingtest 1.3.0: opt, cmdline and tepam are optional, not module-level requires

The module hard-required opt, cmdline and tepam at load time, so on a punkshell build
without tcllib 'package require argparsingtest' died outright with "can't find package
opt". A harness whose whole job is comparing parser libraries is useless precisely on the
runtime you wanted to measure, and the module already had the right pattern for this:
argp, parse_args and argparse degrade to a not_loaded row rather than taking the module
down with them. The three tcllib parsers were the odd ones out. Reproduced before the
change with punk module paths only and an emptied auto_path, which is where tcllib's
pkgIndex-based packages come from.

Every parser this module compares is now optional. Their roster entries become
{optional opt}, {optional cmdline} and {optional tepam}, so discover_parsers reports
not_loaded when the package is absent and nothing in the harness calls them. punk::args
and Tcl 8.6- remain hard requires - the harness itself is built on those.

The guard differs by package because the dependency does:
  cmdline is only ever called INSIDE proc bodies, so the catch-guarded require at the top
  is the whole story - the wrapper procs stay defined and are simply never invoked.
  opt and tepam are used at DEFINITION time: tcl::OptProc and tepam::procedure are the
  commands that create the wrapper procs. Their seven definition sites (four opt, across
  opts/tkstyle/tclstyle/sandwich; three tepam) are each additionally guarded, so with the
  package absent the proc does not exist at all.

Those sites test 'package present' rather than wrapping the definition in a bare catch.
Both tolerate absence, but a presence test still lets a genuine error in a spec raise
loudly on a runtime that does have the package, where a catch would swallow it. The
pre-existing argp registration site keeps its original catch idiom - working code, not
part of this change.

Pinned by module_loads_without_optional_parser_packages: a child interp with an emptied
auto_path that asserts the module loads, that each absent package's parser reports
not_loaded, and that the opt and tepam wrapper procs genuinely do not exist. Where a
runtime supplies one of the three as a .tm on a module path the test degrades to
asserting the module still loads, which is the main claim anyway.

Tests that name parsers explicitly (first_call_library_backed, first_call_positional_styles,
sandwich_strictness) now filter through a loaded_parsers helper, and the tclstyle
cmdline_typed status assertion derives its expectation from package presence: those
parsers can now legitimately be missing.

Verification: 26/26 pass under the 32-bit luck-test2 runtime with no skips, 24 pass +
2 skip under native Tcl 9.0.3. With opt and tepam hidden, the built 1.3.0 module loads,
reports both as not_loaded, and compare lists them in its "not loaded:" footer instead of
the whole module failing to load.

Claude-Session: https://claude.ai/code/session_01Q82VuBXzgeKsAwMYHrbpP1
Assisted-by: harness=claude; primary-model=claude-opus-5[1m]; api-location=anthropic.com
master
Julian Noble 3 days ago
parent
commit
03306be068
  1. 68
      src/modules/argparsingtest-999999.0a1.0.tm
  2. 5
      src/modules/argparsingtest-buildversion.txt
  3. 88
      src/tests/modules/argparsingtest/testsuites/argparsingtest/argparsingtest.test

68
src/modules/argparsingtest-999999.0a1.0.tm

@ -50,15 +50,28 @@
package require Tcl 8.6- package require Tcl 8.6-
package require punk::args package require punk::args
package require opt
package require cmdline # Every parser package this module compares is OPTIONAL, including the tcllib ones.
package require tepam # A comparison harness that cannot load at all because one of the libraries it
# compares is absent is useless on exactly the runtime you most want to measure -
# and punkshell builds do ship without tcllib. A missing library must degrade to a
# not_loaded row (see the {optional <pkg>} roster markers), never to a load failure.
# Guarded here rather than at the call sites because the guard needed differs:
# cmdline - used only INSIDE proc bodies, so the requires below are the whole story
# opt - tcl::OptProc DEFINES the wrapper procs, so each definition site is
# tepam additionally guarded by an 'is the package present' test. Those sites
# test presence rather than catching, so a genuine error in a spec still
# surfaces loudly on a runtime that does have the package.
# argp, parse_args and argparse are required further down, at their own sites.
catch {package require opt}
catch {package require cmdline}
catch {package require tepam}
#*** !doctools #*** !doctools
#[item] [package {Tcl 8.6}] #[item] [package {Tcl 8.6}]
#[item] [package {punk::args}] #[item] [package {punk::args}]
#[item] [package {opt}] #[item] [package {opt}] (optional - parser under test)
#[item] [package {cmdline}] #[item] [package {cmdline}] (optional - parser under test)
#[item] [package {tepam}] #[item] [package {tepam}] (optional - parser under test)
# #package require frobz # #package require frobz
# #*** !doctools # #*** !doctools
@ -163,13 +176,13 @@ namespace eval argparsingtest {
punkargs_by_id always punkargs_by_id always
punkargs_parsecache always punkargs_parsecache always
punkargs_validate_ansistripped always punkargs_validate_ansistripped always
opt always opt {optional opt}
cmdline_untyped always cmdline_untyped {optional cmdline}
cmdline_typed always cmdline_typed {optional cmdline}
argp {optional argp} argp {optional argp}
parse_args {optional parse_args} parse_args {optional parse_args}
argparse {optional argparse} argparse {optional argparse}
tepam always tepam {optional tepam}
} }
} }
tkstyle { tkstyle {
@ -180,8 +193,8 @@ namespace eval argparsingtest {
punkargs always punkargs always
punkargs_by_id always punkargs_by_id always
punkargs_parsecache always punkargs_parsecache always
opt always opt {optional opt}
tepam always tepam {optional tepam}
argparse {optional argparse} argparse {optional argparse}
cmdline_untyped unsupported cmdline_untyped unsupported
cmdline_typed unsupported cmdline_typed unsupported
@ -197,10 +210,10 @@ namespace eval argparsingtest {
punkargs always punkargs always
punkargs_by_id always punkargs_by_id always
punkargs_parsecache always punkargs_parsecache always
opt always opt {optional opt}
cmdline_untyped always cmdline_untyped {optional cmdline}
cmdline_typed always cmdline_typed {optional cmdline}
tepam always tepam {optional tepam}
parse_args {optional parse_args} parse_args {optional parse_args}
argparse {optional argparse} argparse {optional argparse}
argp unsupported argp unsupported
@ -214,7 +227,7 @@ namespace eval argparsingtest {
punkargs always punkargs always
punkargs_by_id always punkargs_by_id always
punkargs_parsecache always punkargs_parsecache always
opt always opt {optional opt}
argparse {optional argparse} argparse {optional argparse}
cmdline_untyped unsupported cmdline_untyped unsupported
cmdline_typed unsupported cmdline_typed unsupported
@ -1494,6 +1507,8 @@ namespace eval argparsingtest::opts {
-join -type none -multiple 1 -join -type none -multiple 1
}] }]
} }
#tcl::OptProc DEFINES this proc, so skip the definition when opt is absent - see the optional-package requires at the module top
if {![catch {package present opt}]} {
tcl::OptProc opt { tcl::OptProc opt {
{-return string "return type"} {-return string "return type"}
{-frametype \uFFEF "type of frame"} {-frametype \uFFEF "type of frame"}
@ -1513,6 +1528,7 @@ namespace eval argparsingtest::opts {
} }
return $opts return $opts
} }
}
#cmdline::getoptions is much faster than typedGetoptions #cmdline::getoptions is much faster than typedGetoptions
namespace eval argdoc { namespace eval argdoc {
@ -1736,6 +1752,8 @@ namespace eval argparsingtest::opts {
-join -type none -multiple 1 -join -type none -multiple 1
}] }]
} }
#tepam::procedure DEFINES this proc, so skip the definition when tepam is absent - see the optional-package requires at the module top
if {![catch {package present tepam}]} {
tepam::procedure {tepam} { tepam::procedure {tepam} {
-args { -args {
{-return -type string -default string} {-return -type string -default string}
@ -1753,6 +1771,7 @@ namespace eval argparsingtest::opts {
} { } {
return [dict create return $return frametype $frametype show_edge $show_edge show_seps $show_seps x $x y $y z $z 1 $1 2 $2 3 $3 join $join] return [dict create return $return frametype $frametype show_edge $show_edge show_seps $show_seps x $x y $y z $z 1 $1 2 $2 3 $3 join $join]
} }
}
#*** !doctools #*** !doctools
#[list_end] [comment {--- end definitions namespace argparsingtest::opts ---}] #[list_end] [comment {--- end definitions namespace argparsingtest::opts ---}]
@ -1967,6 +1986,8 @@ namespace eval argparsingtest::tkstyle {
-join -type none -multiple 1 -join -type none -multiple 1
}] }]
} }
#tcl::OptProc DEFINES this proc, so skip the definition when opt is absent - see the optional-package requires at the module top
if {![catch {package present opt}]} {
tcl::OptProc opt { tcl::OptProc opt {
{p1 -string "first positional argument"} {p1 -string "first positional argument"}
{p2 -string "second positional argument"} {p2 -string "second positional argument"}
@ -1990,6 +2011,7 @@ namespace eval argparsingtest::tkstyle {
} }
return [list $p1 $p2 $opts] return [list $p1 $p2 $opts]
} }
}
namespace eval argdoc { namespace eval argdoc {
lappend PUNKARGS [list { lappend PUNKARGS [list {
@ -2015,6 +2037,8 @@ namespace eval argparsingtest::tkstyle {
-join -type none -multiple 1 -join -type none -multiple 1
}] }]
} }
#tepam::procedure DEFINES this proc, so skip the definition when tepam is absent - see the optional-package requires at the module top
if {![catch {package present tepam}]} {
tepam::procedure {tepam} { tepam::procedure {tepam} {
-named_arguments_first 0 -named_arguments_first 0
-args { -args {
@ -2035,6 +2059,7 @@ namespace eval argparsingtest::tkstyle {
} { } {
return [list $p1 $p2 [dict create return $return frametype $frametype show_edge $show_edge show_seps $show_seps x $x y $y z $z 1 $1 2 $2 3 $3 join $join]] return [list $p1 $p2 [dict create return $return frametype $frametype show_edge $show_edge show_seps $show_seps x $x y $y z $z 1 $1 2 $2 3 $3 join $join]]
} }
}
namespace eval argdoc { namespace eval argdoc {
lappend PUNKARGS [list { lappend PUNKARGS [list {
@ -2296,6 +2321,8 @@ namespace eval argparsingtest::tclstyle {
p2 -type string -optional 0 p2 -type string -optional 0
}] }]
} }
#tcl::OptProc DEFINES this proc, so skip the definition when opt is absent - see the optional-package requires at the module top
if {![catch {package present opt}]} {
tcl::OptProc opt { tcl::OptProc opt {
{-return string "return type"} {-return string "return type"}
{-frametype \uFFEF "type of frame"} {-frametype \uFFEF "type of frame"}
@ -2319,6 +2346,7 @@ namespace eval argparsingtest::tclstyle {
} }
return [list $p1 $p2 $opts] return [list $p1 $p2 $opts]
} }
}
namespace eval argdoc { namespace eval argdoc {
lappend PUNKARGS [list { lappend PUNKARGS [list {
@ -2439,6 +2467,8 @@ namespace eval argparsingtest::tclstyle {
p2 -type string -optional 0 p2 -type string -optional 0
}] }]
} }
#tepam::procedure DEFINES this proc, so skip the definition when tepam is absent - see the optional-package requires at the module top
if {![catch {package present tepam}]} {
tepam::procedure {tepam} { tepam::procedure {tepam} {
-args { -args {
{-return -type string -default string} {-return -type string -default string}
@ -2458,6 +2488,7 @@ namespace eval argparsingtest::tclstyle {
} { } {
return [list $p1 $p2 [dict create return $return frametype $frametype show_edge $show_edge show_seps $show_seps x $x y $y z $z 1 $1 2 $2 3 $3 join $join]] return [list $p1 $p2 [dict create return $return frametype $frametype show_edge $show_edge show_seps $show_seps x $x y $y z $z 1 $1 2 $2 3 $3 join $join]]
} }
}
namespace eval argdoc { namespace eval argdoc {
lappend PUNKARGS [list { lappend PUNKARGS [list {
@ -2848,6 +2879,8 @@ namespace eval argparsingtest::sandwich {
p5 -type string -optional 0 p5 -type string -optional 0
}] }]
} }
#tcl::OptProc DEFINES this proc, so skip the definition when opt is absent - see the optional-package requires at the module top
if {![catch {package present opt}]} {
tcl::OptProc opt { tcl::OptProc opt {
{p1 -string "first leading positional argument"} {p1 -string "first leading positional argument"}
{p2 -string "second leading positional argument"} {p2 -string "second leading positional argument"}
@ -2874,6 +2907,7 @@ namespace eval argparsingtest::sandwich {
} }
return [list [list $p1 $p2] [list $p3 $p4 $p5] $opts] return [list [list $p1 $p2] [list $p3 $p4 $p5] $opts]
} }
}
namespace eval argdoc { namespace eval argdoc {
lappend PUNKARGS [list { lappend PUNKARGS [list {

5
src/modules/argparsingtest-buildversion.txt

@ -1,6 +1,9 @@
1.2.0 1.3.0
#First line must be a semantic version number #First line must be a semantic version number
#all other lines are ignored. #all other lines are ignored.
#1.3.0 - opt, cmdline and tepam are no longer module-level hard requires. A punkshell build without tcllib could not load the module at all ("can't find package opt"), which is useless on exactly the runtime you wanted to measure: every parser this module compares is now optional and a missing one degrades to a not_loaded row like argp/parse_args/argparse already did. Their roster entries become {optional opt} / {optional cmdline} / {optional tepam}
#1.3.0 - the guard differs by package because the dependency does: cmdline is only called inside proc bodies, so the catch-guarded require is the whole story, whereas tcl::OptProc and tepam::procedure DEFINE their wrapper procs - those 7 definition sites are additionally guarded by a 'package present' test, so the proc simply does not exist when the package is absent (and discover_parsers then never calls it). Presence test rather than catch, so a genuine spec error still raises loudly on a runtime that does have the package
#1.3.0 - regression pinned by module_loads_without_optional_parser_packages (child interp with an emptied auto_path); tests that name parsers explicitly now filter through a loaded_parsers helper
#1.2.0 - fourth calling style 'sandwich': 2 mandatory leading positionals, THEN the 10 keyed options (argvec now exercises the valueless -join flag alongside -flag value pairs), THEN 3 mandatory trailing positionals. The 2/3 split is asymmetric on purpose - an even split could be satisfied by a parser that just halves the positional block. New namespace argparsingtest::sandwich with manual_switch, punkargs, punkargs_by_id, punkargs_parsecache, opt and argparse wrappers; return contract is {{p1 p2} {p3 p4 p5} optsdict} (grouped rather than the flat {p1 p2 opts} of the other positional styles, since positionals sit on both sides of the options) #1.2.0 - fourth calling style 'sandwich': 2 mandatory leading positionals, THEN the 10 keyed options (argvec now exercises the valueless -join flag alongside -flag value pairs), THEN 3 mandatory trailing positionals. The 2/3 split is asymmetric on purpose - an even split could be satisfied by a parser that just halves the positional block. New namespace argparsingtest::sandwich with manual_switch, punkargs, punkargs_by_id, punkargs_parsecache, opt and argparse wrappers; return contract is {{p1 p2} {p3 p4 p5} optsdict} (grouped rather than the flat {p1 p2 opts} of the other positional styles, since positionals sit on both sides of the options)
#1.2.0 - sandwich style: cmdline, tepam, argp and parse_args are 'unsupported' (N/A rows) - each verified to fail on the style's argvec. cmdline is the notable one: cmdline::getoptions returns WITHOUT error having parsed nothing, leaving every option at its default and the argument list untouched #1.2.0 - sandwich style: cmdline, tepam, argp and parse_args are 'unsupported' (N/A rows) - each verified to fail on the style's argvec. cmdline is the notable one: cmdline::getoptions returns WITHOUT error having parsed nothing, leaving every option at its default and the argument list untouched
#1.2.0 - sandwich style: punk::args, opt and the manual baseline model the arrangement and reject options ahead of the leaders; argparse reaches the style only via -mixed, which permits switches anywhere and therefore parses the argvec correctly WITHOUT enforcing the arrangement (pinned by the sandwich_strictness / sandwich_argparse_is_permissive tests) #1.2.0 - sandwich style: punk::args, opt and the manual baseline model the arrangement and reject options ahead of the leaders; argparse reaches the style only via -mixed, which permits switches anywhere and therefore parses the argvec correctly WITHOUT enforcing the arrangement (pinned by the sandwich_strictness / sandwich_argparse_is_permissive tests)

88
src/tests/modules/argparsingtest/testsuites/argparsingtest/argparsingtest.test

@ -15,6 +15,20 @@ namespace eval ::testspace {
testConstraint parse_args_loaded [expr {![catch {package present parse_args}]}] testConstraint parse_args_loaded [expr {![catch {package present parse_args}]}]
testConstraint argparse_loaded [expr {![catch {package present argparse}]}] testConstraint argparse_loaded [expr {![catch {package present argparse}]}]
#added 2026-07-28 (agent) - opt, cmdline and tepam are optional too (module 1.3.0 stopped
#hard-requiring them: a comparison harness must still load on a build without tcllib), so any
#test naming parsers explicitly has to drop the ones this runtime cannot load
proc loaded_parsers {style names} {
set disco [dict get [argparsingtest::discover_parsers -style $style] $style]
set out {}
foreach n $names {
if {[dict exists $disco $n] && [dict get $disco $n] eq "loaded"} {
lappend out $n
}
}
return $out
}
#added 2026-07-18 (agent) - suite rewritten for the argparsingtest 1.0.0 restructure: #added 2026-07-18 (agent) - suite rewritten for the argparsingtest 1.0.0 restructure:
#parser procs live in per-style namespaces (opts/tkstyle/tclstyle), harness results are keyed by style #parser procs live in per-style namespaces (opts/tkstyle/tclstyle), harness results are keyed by style
#Split 2026-07-19 (G-092 - parallel-floor reduction, tests moved verbatim): this file holds #Split 2026-07-19 (G-092 - parallel-floor reduction, tests moved verbatim): this file holds
@ -91,7 +105,9 @@ namespace eval ::testspace {
if {$ok eq 1 && [dict get $r opts manual_switch] ne "loaded"} { set ok "opts manual_switch status" } if {$ok eq 1 && [dict get $r opts manual_switch] ne "loaded"} { set ok "opts manual_switch status" }
if {$ok eq 1 && [dict get $r tkstyle cmdline_typed] ne "unsupported"} { set ok "tkstyle cmdline_typed status" } if {$ok eq 1 && [dict get $r tkstyle cmdline_typed] ne "unsupported"} { set ok "tkstyle cmdline_typed status" }
if {$ok eq 1 && [dict get $r tkstyle argp] ne "unsupported"} { set ok "tkstyle argp status" } if {$ok eq 1 && [dict get $r tkstyle argp] ne "unsupported"} { set ok "tkstyle argp status" }
if {$ok eq 1 && [dict get $r tclstyle cmdline_typed] ne "loaded"} { set ok "tclstyle cmdline_typed status" } #tclstyle CAN express cmdline, so there the status tracks whether the package is installed
set expect_cmdline [expr {[catch {package present cmdline}] ? "not_loaded" : "loaded"}]
if {$ok eq 1 && [dict get $r tclstyle cmdline_typed] ne $expect_cmdline} { set ok "tclstyle cmdline_typed status" }
if {$ok eq 1 && [dict get $r tclstyle argp] ne "unsupported"} { set ok "tclstyle argp status" } if {$ok eq 1 && [dict get $r tclstyle argp] ne "unsupported"} { set ok "tclstyle argp status" }
if {$ok eq 1 && [dict exists $r opts test1_switch]} { set ok "stale test1_switch key present" } if {$ok eq 1 && [dict exists $r opts test1_switch]} { set ok "stale test1_switch key present" }
set ok set ok
@ -105,6 +121,10 @@ namespace eval ::testspace {
foreach {pkg pname styles} { foreach {pkg pname styles} {
parse_args parse_args {opts tclstyle} parse_args parse_args {opts tclstyle}
argparse argparse {opts tkstyle tclstyle sandwich} argparse argparse {opts tkstyle tclstyle sandwich}
opt opt {opts tkstyle tclstyle sandwich}
cmdline cmdline_untyped {opts tclstyle}
cmdline cmdline_typed {opts tclstyle}
tepam tepam {opts tkstyle tclstyle}
} { } {
set expected [expr {[catch {package present $pkg}] ? "not_loaded" : "loaded"}] set expected [expr {[catch {package present $pkg}] ? "not_loaded" : "loaded"}]
foreach s $styles { foreach s $styles {
@ -128,6 +148,66 @@ namespace eval ::testspace {
set ok set ok
} -result 1 } -result 1
#added 2026-07-28 (agent) - regression pin for the 1.3.0 change: the module used to hard-require
#opt, cmdline and tepam, so 'package require argparsingtest' died outright with "can't find
#package opt" on a punkshell build without tcllib - a comparison harness unloadable on exactly
#the runtime you wanted to measure. Exercised in a child interp with an emptied auto_path, which
#is where tcllib's pkgIndex-based packages come from. If a runtime provides any of the three as a
#.tm on a module path this degrades to asserting the module still loads, which is the main claim.
test module_loads_without_optional_parser_packages {Test that the module loads when opt, cmdline and tepam are unavailable} -body {
set tm_paths [tcl::tm::list]
#pin to the parent's versions - a plain require prefers a stable copy over the 999999.0a1.0 source module
set pinned ""
foreach pkg {punk::args punk::lib argparsingtest} {
if {![catch {package present $pkg} ver]} {
append pinned "package require -exact [list $pkg] [list $ver]\n"
}
}
set child [interp create]
try {
set child_tm [interp eval $child {tcl::tm::list}]
if {[llength $child_tm]} {
interp eval $child [list tcl::tm::path remove {*}$child_tm]
}
if {[llength $tm_paths]} {
interp eval $child [list tcl::tm::path add {*}$tm_paths]
}
interp eval $child [list set ::auto_path [list]]
set result [interp eval $child [string cat $pinned {
set absent {}
foreach p {opt cmdline tepam} {
if {[catch {package present $p}]} { lappend absent $p }
}
set disco [dict get [argparsingtest::discover_parsers -style opts] opts]
set statuses {}
set stillcommands {}
foreach {pname pkg} {opt opt cmdline_untyped cmdline cmdline_typed cmdline tepam tepam} {
if {$pkg in $absent} {
lappend statuses $pname [dict get $disco $pname]
}
}
#opt and tepam DEFINE their wrapper procs, so those must not exist when absent
foreach {pname pkg} {opt opt tepam tepam} {
if {$pkg in $absent && [llength [info commands ::argparsingtest::opts::$pname]]} {
lappend stillcommands $pname
}
}
list loaded [package present argparsingtest] absent $absent statuses $statuses stillcommands $stillcommands
}]]
} finally {
interp delete $child
}
set ok 1
if {[dict get $result loaded] eq ""} { set ok "child did not load argparsingtest" }
if {$ok eq 1 && [llength [dict get $result stillcommands]] } { set ok "wrapper procs defined without their package: [dict get $result stillcommands]" }
if {$ok eq 1} {
foreach {pname status} [dict get $result statuses] {
if {$status ne "not_loaded"} { set ok "$pname reported $status with its package absent" ; break }
}
}
set ok
} -result 1
#added 2026-07-26 (agent) - opts-style external wrappers agree with the hand-rolled baseline's option values #added 2026-07-26 (agent) - opts-style external wrappers agree with the hand-rolled baseline's option values
test parse_args_opts_values {Test that the parse_args opts wrapper returns the declared option values} -constraints parse_args_loaded -body { test parse_args_opts_values {Test that the parse_args opts wrapper returns the declared option values} -constraints parse_args_loaded -body {
set r [argparsingtest::opts::parse_args -return object -x hello -y world -1 1 -2 2 -3 3] set r [argparsingtest::opts::parse_args -return object -x hello -y world -1 1 -2 2 -3 3]
@ -204,7 +284,7 @@ namespace eval ::testspace {
test sandwich_strictness {Test that the modelling sandwich parsers reject options before the leaders} -body { test sandwich_strictness {Test that the modelling sandwich parsers reject options before the leaders} -body {
set badvec {-x hello -join alpha beta gamma delta epsilon} set badvec {-x hello -join alpha beta gamma delta epsilon}
set ok 1 set ok 1
foreach pname {manual_switch punkargs punkargs_by_id punkargs_parsecache opt} { foreach pname [loaded_parsers sandwich {manual_switch punkargs punkargs_by_id punkargs_parsecache opt}] {
if {![catch {argparsingtest::sandwich::$pname {*}$badvec} r]} { if {![catch {argparsingtest::sandwich::$pname {*}$badvec} r]} {
set ok "$pname accepted options-before-leaders: $r" set ok "$pname accepted options-before-leaders: $r"
break break
@ -237,7 +317,7 @@ namespace eval ::testspace {
#added 2026-07-17 (agent) #added 2026-07-17 (agent)
test first_call_library_backed {Test that first_call returns cold and warm float timings for library-backed parsers (warm-up scripts must run cleanly)} -body { test first_call_library_backed {Test that first_call returns cold and warm float timings for library-backed parsers (warm-up scripts must run cleanly)} -body {
set r [argparsingtest::first_call -style opts -parsers {punkargs punkargs_by_id opt cmdline_untyped cmdline_typed tepam}] set r [argparsingtest::first_call -style opts -parsers [loaded_parsers opts {punkargs punkargs_by_id opt cmdline_untyped cmdline_typed tepam}]]
set ok 1 set ok 1
foreach {pname sub} [dict get $r opts] { foreach {pname sub} [dict get $r opts] {
foreach mode {cold warm} { foreach mode {cold warm} {
@ -254,7 +334,7 @@ namespace eval ::testspace {
test first_call_positional_styles {Test first_call cold and warm for tkstyle, tclstyle and sandwich parsers} -body { test first_call_positional_styles {Test first_call cold and warm for tkstyle, tclstyle and sandwich parsers} -body {
set ok 1 set ok 1
foreach {s plist} {tkstyle {punkargs_by_id tepam} tclstyle {cmdline_untyped} sandwich {manual_switch punkargs_by_id opt}} { foreach {s plist} {tkstyle {punkargs_by_id tepam} tclstyle {cmdline_untyped} sandwich {manual_switch punkargs_by_id opt}} {
set r [argparsingtest::first_call -style $s -parsers $plist] set r [argparsingtest::first_call -style $s -parsers [loaded_parsers $s $plist]]
foreach {pname sub} [dict get $r $s] { foreach {pname sub} [dict get $r $s] {
foreach mode {cold warm} { foreach mode {cold warm} {
if {![dict exists $sub $mode]} { set ok "missing $mode for $s $pname" ; break } if {![dict exists $sub $mode]} { set ok "missing $mode for $s $pname" ; break }

Loading…
Cancel
Save