Browse Source

netbox -ASYNC update and API fixes

master
Julian Noble 3 weeks ago
parent
commit
e6bfb30ded
  1. 3
      src/modules/punk/args-999999.0a1.0.tm
  2. 1022
      src/modules/punk/netbox-999999.0a1.0.tm
  3. 305
      src/modules/punk/netbox/man-999999.0a1.0.tm
  4. 33
      src/modules/punk/ns-999999.0a1.0.tm
  5. 3
      src/project_layouts/custom/_project/punk.project-0.1/src/bootsupport/modules/punk/args-0.2.1.tm
  6. 33
      src/project_layouts/custom/_project/punk.project-0.1/src/bootsupport/modules/punk/ns-0.1.0.tm
  7. 3
      src/project_layouts/custom/_project/punk.shell-0.1/src/bootsupport/modules/punk/args-0.2.1.tm
  8. 33
      src/project_layouts/custom/_project/punk.shell-0.1/src/bootsupport/modules/punk/ns-0.1.0.tm
  9. 3
      src/vfs/_vfscommon.vfs/modules/punk/args-0.2.1.tm
  10. 1022
      src/vfs/_vfscommon.vfs/modules/punk/netbox-0.1.0.tm
  11. 305
      src/vfs/_vfscommon.vfs/modules/punk/netbox/man-0.1.0.tm
  12. 33
      src/vfs/_vfscommon.vfs/modules/punk/ns-0.1.0.tm

3
src/modules/punk/args-999999.0a1.0.tm

@ -6481,7 +6481,7 @@ tcl::namespace::eval punk::args {
}
if {[dict exists $thisarg_checks -maxsize]} {
set maxsize [dict get $thisarg_checks -maxsize]
if {$checkval ne "-1"} {
if {$maxsize ne "-1"} {
if {[tcl::string::length $e_check] > $maxsize} {
set msg "$argclass '$argname' for %caller% requires string with -maxsize $maxsize. Received len:[tcl::string::length $e_check] value:'$e_check'"
#return -options [list -code error -errorcode [list PUNKARGS VALIDATION [list sizeviolation $type] -badarg $argname -argspecs $argspecs]] $msg
@ -6679,6 +6679,7 @@ tcl::namespace::eval punk::args {
upper -
wordchar -
xdigit {
#todo - combined types xdigit && lower ?? set-theoretic types? how?
if {![tcl::string::is $type -strict $e_check]} {
set msg "$argclass $argname for %caller% requires type '$type'. Received: '$e'"
lset clause_results $c_idx $a_idx [list err [list typemismatch $type] msg $msg]

1022
src/modules/punk/netbox-999999.0a1.0.tm

File diff suppressed because it is too large Load Diff

305
src/modules/punk/netbox/man-999999.0a1.0.tm

@ -66,38 +66,6 @@ package require rest
#*** !doctools
#[section API]
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
# oo::class namespace
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
#tcl::namespace::eval punk::netbox::man::class {
#*** !doctools
#[subsection {Namespace punk::netbox::man::class}]
#[para] class definitions
#if {[tcl::info::commands [tcl::namespace::current]::interface_sample1] eq ""} {
#*** !doctools
#[list_begin enumerated]
# oo::class create interface_sample1 {
# #*** !doctools
# #[enum] CLASS [class interface_sample1]
# #[list_begin definitions]
# method test {arg1} {
# #*** !doctools
# #[call class::interface_sample1 [method test] [arg arg1]]
# #[para] test method
# puts "test: $arg1"
# }
# #*** !doctools
# #[list_end] [comment {-- end definitions interface_sample1}]
# }
#*** !doctools
#[list_end] [comment {--- end class enumeration ---}]
#}
#}
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
tcl::namespace::eval punk::netbox::man {
variable PUNKARGS
@ -926,6 +894,277 @@ tcl::namespace::eval punk::netbox::man::virtualization {
}
tcl::namespace::eval punk::netbox::man::extras {
namespace export {[a-z]*}
namespace ensemble create -parameters {apicontextid}
variable PUNKARGS
tcl::namespace::eval tags {
namespace export {[a-z]*}
namespace ensemble create -parameters {apicontextid}
variable PUNKARGS
namespace eval argdoc {
variable PUNKARGS
set DYN_CONTEXTNAMES {${[punk::netbox::api_context_names]}}
}
namespace eval argdoc {
lappend PUNKARGS [list\
{@dynamic}\
{
@id -id ::punk::netbox::man::extras::tags::create
@cmd -name punk::netbox::man::extras::tags::create -help\
"extras_tags_create
POST request for endpoint /extras/tags/"
@leaders -min 1 -max 1
apicontextid -help\
"The name of the stored api context to use.
A contextid can be created in-memory using
api_context_create, or loaded from a .toml
file using api_context_load."\
-choices {${$DYN_CONTEXTNAMES}}
@opts
-name -type string -minsize 1 -maxsize 100 -optional 0
-slug -type string -minsize 1 -maxsize 100 -optional 1
#todo - combined xdigit and lower??
-color -type xdigit -maxsize 6 -optional 1 -help\
"Default will be assigned by netbox.
e.g 9e9e9e"
-description -type string -maxsize 200 -default ""
}\
{-RETURN -default table -choices {table tableobject list linelist}}\
{
@values -min 0 -max 0
}
]
}
#example body
# color must be a lower-cased hex string (6 digits)
# e.g a red tag
# {
# "name": "my_tag",
# "slug": "my_tag",
# "color": "ff0000",
# "description": "testing tag creation"
# }
#example 201 response
#{
# "id": 14,
# "url": "https://www.netbox1.intx.com.au/api/extras/tags/14/",
# "display": "jjj",
# "name": "jjj",
# "slug": "jjj",
# "color": "ff0000",
# "description": "j testing",
# "created": "2025-11-11T16:33:17.461484Z",
# "last_updated": "2025-11-11T16:33:17.461500Z"
#}
#example 400 response
#{
# "name": [
# "tag with this name already exists."
# ],
# "slug": [
# "tag with this slug already exists."
# ]
#}
proc create {args} {
set argd [punk::args::parse $args withid "::punk::netbox::man::extras::tags::create"]
lassign [dict values $argd] leaders opts values received
set token [dict get $argd leaders apicontextid]
set map [::list \" "\\\"" \\ \\\\ \r \\r \n \\n \t \\t \b \\b \f \\f] ;#review - unicode? tcllib?
set name [dict get $argd opts -name]
if {[dict exists $received -slug]} {
set slug [dict get $opts -slug]
} else {
set slug $name
}
set description [dict get $argd opts -description]
#Escape for JSON
set name [string map $map $name]
set slug [string map $map $slug]
set description [string map $map $description]
set body "\{\n"
append body " \"name\": \"$name\"," \n
append body " \"slug\": \"$slug\"," \n
if {[dict exists $received -color]} {
append body " \"color\": \"[dict get $opts -color]\"," \n
}
append body " \"description\": \"$description\"" \n
append body "\}" \n
puts "Post body JSON:"
puts $body
#todo RETURN
set resultd [punk::netbox::extras::tags_create $token -RETURN dict $body]
}
namespace eval argdoc {
lappend PUNKARGS [list\
{@dynamic}\
{
@id -id ::punk::netbox::man::extras::tags::delete
@cmd -name punk::netbox::man::extras::tags::delete\
-summary\
"Delete one tag by id."\
-help\
"extras_tags_delete
DELETE request for endpoint /extras/tags/{id}
Delete a single tag by id."
@leaders -min 1 -max 1
apicontextid -help\
"The name of the stored api context to use.
A contextid can be created in-memory using
api_context_create, or loaded from a .toml
file using api_context_load."\
-choices {${$DYN_CONTEXTNAMES}}
@opts
@values -min 1 -max 1
id -type integer -range {0 ""}
}
]
}
proc delete {args} {
set argd [punk::args::parse $args withid "::punk::netbox::man::extras::tags::delete"]
lassign [dict values $argd] leaders opts values received
set token [dict get $argd leaders apicontextid]
set id [dict get $argd values id]
punk::netbox::extras::tags_delete $token -RETURN dict $id
return done
}
namespace eval argdoc {
lappend PUNKARGS [::list\
{@dynamic}\
[punk::args::resolved_def\
-antiglobs {@leaders @values -RETURN}\
-override {
@id {-id "::punk::netbox::man::extras::tags::list" }
apicontextid {-choices {${$DYN_CONTEXTNAMES}} }
}\
::punk::netbox::extras::tags_list\
]\
{-RETURN -default table -choices {table tableobject list linelist}}\
{-MAXRESULTS -type integer -default -1}\
{@values -min 0 -max 0}\
]
}
proc list {args} {
set argd [punk::args::parse $args withid "::punk::netbox::man::extras::tags::list"]
set urlnext ""
set requests_allowed 1000 ;#Sanity check - consider making an option - review
set resultlist [::list]
set token [dict get $argd leaders apicontextid]
set opts [dict get $argd opts]
set vals [dict get $argd values]
set multis [dict get $argd multis]
set outer_return [dict get $opts -RETURN]
set opts [dict remove $opts -RETURN] ;#opts from punk::args::parse is a dict (no dup keys) - can use 'dict remove' safely
set maxresults [dict get $opts -MAXRESULTS]
set opts [dict remove $opts -MAXRESULTS]
set initial_pagelimit [dict get $opts -limit]
#we can't just pass through 'multi' opts even if only one was supplied - list level is wrong
set nextopts [::list]
dict for {opt val} $opts {
if {$opt ni $multis} {
lappend nextopts $opt $val
} else {
foreach v $val {
lappend nextopts $opt $v
}
}
}
#Now opts is a list with possible repeated options! (for flags that have -multiple true)
if {$maxresults == -1} {
set maxresults $initial_pagelimit
}
if {$maxresults < $initial_pagelimit} {
punk::netbox::man::system::dupkeylist_setfirst nextopts -limit $maxresults
}
set to_go [expr {$maxresults - [llength $resultlist]}]
while {$urlnext ne "null"} {
if {$urlnext ne ""} {
set urlnext_params [punk::netbox::man::system::uri_get_querystring_as_keyval_list $urlnext]
if {[punk::netbox::man::system::dupkeylist_getfirst $nextopts -limit] > $to_go} {
punk::netbox::man::system::dupkeylist_setfirst urlnext_params limit $to_go
}
punk::netbox::man::system::optionlistvar_sync_from_urlparams nextopts $urlnext_params
}
puts "-->next:$urlnext nextopts:$nextopts vals:$vals"
set resultd [punk::netbox::extras::tags_list $token {*}$nextopts -RETURN dict {*}$vals]
set urlnext [dict get $resultd next]
set batch [dict get $resultd results]
lappend resultlist {*}$batch
set to_go [expr {$maxresults - [llength $resultlist]}]
if {$to_go <= 0} {break}
incr requests_allowed -1
if {$requests_allowed < 1} {break}
}
if {$outer_return in {table tableobject}} {
package require textblock
set t [textblock::list_as_table -return tableobject -colheaders {id name slug color sample description}]
foreach tag $resultlist {
set name [dict get $tag name]
set rgb [dict get $tag color]
if {[string length $rgb] && [string length $rgb] == 6} {
set sample "[a+ Rgb#$rgb rgb#$rgb-contrasting] $name [a]"
} else {
set sample ""
}
set r [::list\
[dict get $tag id]\
[dict get $tag name]\
[dict get $tag slug]\
$rgb\
$sample\
[dict get $tag description]\
]
$t add_row $r
}
}
switch -- $outer_return {
table {
set result [$t print]
$t destroy
return $result
}
tableobject {
return $t
}
linelist {
set ret ""
foreach r $resultlist {
append ret $r \n
}
return $ret
}
default {
return $resultlist
}
}
}
}
}
tcl::namespace::eval punk::netbox::man::ip-addresses {
namespace export {[a-z]*}
@ -1308,6 +1547,8 @@ namespace eval ::punk::args::register {
::punk::netbox::man::tenancy::tenants\
::punk::netbox::man::virtualization\
::punk::netbox::man::virtualization::virtual-machines\
::punk::netbox::man::extras\
::punk::netbox::man::extras::tags\
}
# -----------------------------------------------------------------------------

33
src/modules/punk/ns-999999.0a1.0.tm

@ -2581,9 +2581,10 @@ y" {return quirkykeyscript}
#eval_base has been set by previous source or proc
#It can also be set by previous eval - *if* a non default offset was returned by _cmdtrace_get_eval_offset
set eval_base [dict get $linedict $target eval_base]
set eval_offset [dict get $linedict $target eval_offset]
set line [expr {$prevline + ($eval_offset-1) + ($traceline-1)}]
#puts "stack-- $callinfo"
set line [expr {$eval_base + ($eval_offset-1) + ($traceline-1)}]
puts "stack-- $callinfo"
puts " step type: eval traceline: $traceline -- "
if {[dict exists $callinfo cmd]} {
#set cmd [string trim [dict get $callinfo cmd]]
@ -2653,9 +2654,11 @@ y" {return quirkykeyscript}
}
#puts "-- $callinfo"
} else {
puts ">>step type: $type (nontargeted proc)>> $callinfo"
::tcl::dict::incr tinfo($target) subcmds
#puts ">>step type: $type (nontargeted proc)>> $callinfo"
}
} else {
::tcl::dict::incr tinfo($target) subcmds
#todo - handle type 'source' and type 'eval' with keys 'method' 'class' (oo)
#puts -------------------------
#puts ">[dict get $callinfo cmd]"
@ -2708,7 +2711,6 @@ y" {return quirkykeyscript}
variable tinfo
array unset tinfo
variable _cmdtrace_disabled
set _cmdtrace_disabled false
set argd [punk::args::parse $args -cache 1 withid ::punk::ns::cmdtrace]
lassign [dict values $argd] leaders opts values received
@ -2718,6 +2720,8 @@ y" {return quirkykeyscript}
set cinfo [uplevel 1 [list ::punk::ns::cmdinfo {*}$cmdargs]]
set origin [dict get $cinfo origin]
set arglist [dict get $cinfo args_remaining]
set origin_nscmd [nstail $origin]
set origin_ns [nsprefix $origin]
if {[dict exists $received -target]} {
set targets [dict get $opts -target]
@ -2740,15 +2744,16 @@ y" {return quirkykeyscript}
}
#don't raise the error when no -target supplied - as our launch command can contain extra arguments
}
lappend resolved_targets $tgt_cmd
set nscmd [nstail $tgt_cmd]
set ns [nsprefix $tgt_cmd]
lappend resolved_targets $tgt_cmd $ns $nscmd
::tcl::dict::set ::punk::ns::linedict $tgt_cmd [::tcl::dict::create eval_base 1 eval_offset 1 lines {} cmdtype $tgt_type successcalls 0 errorcalls 0]
}
#if the target command has a leading colon (e.g expr alternative :) we can't put a trace directly on a fully qualified name with a triple colon such as :::
#we will need to evaluate in the namespace
foreach tgt_cmd $resolved_targets {
set nscmd [nstail $tgt_cmd]
set ns [nsprefix $tgt_cmd]
foreach {tgt_cmd ns nscmd} $resolved_targets {
puts "tracing target: $tgt_cmd whilst running: $origin $arglist"
::tcl::namespace::eval $ns [list ::trace add execution $nscmd enter [list ::punk::ns::_cmdtrace_enter ::punk::ns::linedict $tgt_cmd]]
@ -2758,17 +2763,17 @@ y" {return quirkykeyscript}
try {
set origin_nscmd [nstail $origin]
set origin_ns [nsprefix $origin]
#uplevel 1 [list $origin {*}$arglist]
set _cmdtrace_disabled false
::tcl::namespace::eval $origin_ns [list $origin_nscmd {*}$arglist]
} trap {} {errMsg errOptions} {
set _cmdtrace_disabled true
#(even a puts can involve function calls - e.g in contexts where there are stacked channels)
puts stderr "command error $errMsg"
} finally {
foreach tgt_cmd $resolved_targets {
set nscmd [nstail $tgt_cmd]
set ns [nsprefix $tgt_cmd]
set _cmdtrace_disabled true
foreach {tgt_cmd ns nscmd} $resolved_targets {
::tcl::namespace::eval $ns [list ::trace remove execution $nscmd enterstep [list ::punk::ns::_cmdtrace_enterstep ::punk::ns::linedict $tgt_cmd]]
::tcl::namespace::eval $ns [list ::trace remove execution $nscmd enter [list ::punk::ns::_cmdtrace_enter ::punk::ns::linedict $tgt_cmd]]
::tcl::namespace::eval $ns [list ::trace remove execution $nscmd leave [list ::punk::ns::_cmdtrace_leave ::punk::ns::linedict $tgt_cmd]]
@ -2780,7 +2785,7 @@ y" {return quirkykeyscript}
append final_display \n
#todo - foreach tgt_cmd in resolved_targets?
foreach tgt_cmd $resolved_targets {
foreach {tgt_cmd _ _} $resolved_targets {
set lines [dict get $linedict $tgt_cmd lines]
if {[llength $lines]} {
set procbody [punk::ns::corp -n $tgt_cmd]

3
src/project_layouts/custom/_project/punk.project-0.1/src/bootsupport/modules/punk/args-0.2.1.tm

@ -6481,7 +6481,7 @@ tcl::namespace::eval punk::args {
}
if {[dict exists $thisarg_checks -maxsize]} {
set maxsize [dict get $thisarg_checks -maxsize]
if {$checkval ne "-1"} {
if {$maxsize ne "-1"} {
if {[tcl::string::length $e_check] > $maxsize} {
set msg "$argclass '$argname' for %caller% requires string with -maxsize $maxsize. Received len:[tcl::string::length $e_check] value:'$e_check'"
#return -options [list -code error -errorcode [list PUNKARGS VALIDATION [list sizeviolation $type] -badarg $argname -argspecs $argspecs]] $msg
@ -6679,6 +6679,7 @@ tcl::namespace::eval punk::args {
upper -
wordchar -
xdigit {
#todo - combined types xdigit && lower ?? set-theoretic types? how?
if {![tcl::string::is $type -strict $e_check]} {
set msg "$argclass $argname for %caller% requires type '$type'. Received: '$e'"
lset clause_results $c_idx $a_idx [list err [list typemismatch $type] msg $msg]

33
src/project_layouts/custom/_project/punk.project-0.1/src/bootsupport/modules/punk/ns-0.1.0.tm

@ -2581,9 +2581,10 @@ y" {return quirkykeyscript}
#eval_base has been set by previous source or proc
#It can also be set by previous eval - *if* a non default offset was returned by _cmdtrace_get_eval_offset
set eval_base [dict get $linedict $target eval_base]
set eval_offset [dict get $linedict $target eval_offset]
set line [expr {$prevline + ($eval_offset-1) + ($traceline-1)}]
#puts "stack-- $callinfo"
set line [expr {$eval_base + ($eval_offset-1) + ($traceline-1)}]
puts "stack-- $callinfo"
puts " step type: eval traceline: $traceline -- "
if {[dict exists $callinfo cmd]} {
#set cmd [string trim [dict get $callinfo cmd]]
@ -2653,9 +2654,11 @@ y" {return quirkykeyscript}
}
#puts "-- $callinfo"
} else {
puts ">>step type: $type (nontargeted proc)>> $callinfo"
::tcl::dict::incr tinfo($target) subcmds
#puts ">>step type: $type (nontargeted proc)>> $callinfo"
}
} else {
::tcl::dict::incr tinfo($target) subcmds
#todo - handle type 'source' and type 'eval' with keys 'method' 'class' (oo)
#puts -------------------------
#puts ">[dict get $callinfo cmd]"
@ -2708,7 +2711,6 @@ y" {return quirkykeyscript}
variable tinfo
array unset tinfo
variable _cmdtrace_disabled
set _cmdtrace_disabled false
set argd [punk::args::parse $args -cache 1 withid ::punk::ns::cmdtrace]
lassign [dict values $argd] leaders opts values received
@ -2718,6 +2720,8 @@ y" {return quirkykeyscript}
set cinfo [uplevel 1 [list ::punk::ns::cmdinfo {*}$cmdargs]]
set origin [dict get $cinfo origin]
set arglist [dict get $cinfo args_remaining]
set origin_nscmd [nstail $origin]
set origin_ns [nsprefix $origin]
if {[dict exists $received -target]} {
set targets [dict get $opts -target]
@ -2740,15 +2744,16 @@ y" {return quirkykeyscript}
}
#don't raise the error when no -target supplied - as our launch command can contain extra arguments
}
lappend resolved_targets $tgt_cmd
set nscmd [nstail $tgt_cmd]
set ns [nsprefix $tgt_cmd]
lappend resolved_targets $tgt_cmd $ns $nscmd
::tcl::dict::set ::punk::ns::linedict $tgt_cmd [::tcl::dict::create eval_base 1 eval_offset 1 lines {} cmdtype $tgt_type successcalls 0 errorcalls 0]
}
#if the target command has a leading colon (e.g expr alternative :) we can't put a trace directly on a fully qualified name with a triple colon such as :::
#we will need to evaluate in the namespace
foreach tgt_cmd $resolved_targets {
set nscmd [nstail $tgt_cmd]
set ns [nsprefix $tgt_cmd]
foreach {tgt_cmd ns nscmd} $resolved_targets {
puts "tracing target: $tgt_cmd whilst running: $origin $arglist"
::tcl::namespace::eval $ns [list ::trace add execution $nscmd enter [list ::punk::ns::_cmdtrace_enter ::punk::ns::linedict $tgt_cmd]]
@ -2758,17 +2763,17 @@ y" {return quirkykeyscript}
try {
set origin_nscmd [nstail $origin]
set origin_ns [nsprefix $origin]
#uplevel 1 [list $origin {*}$arglist]
set _cmdtrace_disabled false
::tcl::namespace::eval $origin_ns [list $origin_nscmd {*}$arglist]
} trap {} {errMsg errOptions} {
set _cmdtrace_disabled true
#(even a puts can involve function calls - e.g in contexts where there are stacked channels)
puts stderr "command error $errMsg"
} finally {
foreach tgt_cmd $resolved_targets {
set nscmd [nstail $tgt_cmd]
set ns [nsprefix $tgt_cmd]
set _cmdtrace_disabled true
foreach {tgt_cmd ns nscmd} $resolved_targets {
::tcl::namespace::eval $ns [list ::trace remove execution $nscmd enterstep [list ::punk::ns::_cmdtrace_enterstep ::punk::ns::linedict $tgt_cmd]]
::tcl::namespace::eval $ns [list ::trace remove execution $nscmd enter [list ::punk::ns::_cmdtrace_enter ::punk::ns::linedict $tgt_cmd]]
::tcl::namespace::eval $ns [list ::trace remove execution $nscmd leave [list ::punk::ns::_cmdtrace_leave ::punk::ns::linedict $tgt_cmd]]
@ -2780,7 +2785,7 @@ y" {return quirkykeyscript}
append final_display \n
#todo - foreach tgt_cmd in resolved_targets?
foreach tgt_cmd $resolved_targets {
foreach {tgt_cmd _ _} $resolved_targets {
set lines [dict get $linedict $tgt_cmd lines]
if {[llength $lines]} {
set procbody [punk::ns::corp -n $tgt_cmd]

3
src/project_layouts/custom/_project/punk.shell-0.1/src/bootsupport/modules/punk/args-0.2.1.tm

@ -6481,7 +6481,7 @@ tcl::namespace::eval punk::args {
}
if {[dict exists $thisarg_checks -maxsize]} {
set maxsize [dict get $thisarg_checks -maxsize]
if {$checkval ne "-1"} {
if {$maxsize ne "-1"} {
if {[tcl::string::length $e_check] > $maxsize} {
set msg "$argclass '$argname' for %caller% requires string with -maxsize $maxsize. Received len:[tcl::string::length $e_check] value:'$e_check'"
#return -options [list -code error -errorcode [list PUNKARGS VALIDATION [list sizeviolation $type] -badarg $argname -argspecs $argspecs]] $msg
@ -6679,6 +6679,7 @@ tcl::namespace::eval punk::args {
upper -
wordchar -
xdigit {
#todo - combined types xdigit && lower ?? set-theoretic types? how?
if {![tcl::string::is $type -strict $e_check]} {
set msg "$argclass $argname for %caller% requires type '$type'. Received: '$e'"
lset clause_results $c_idx $a_idx [list err [list typemismatch $type] msg $msg]

33
src/project_layouts/custom/_project/punk.shell-0.1/src/bootsupport/modules/punk/ns-0.1.0.tm

@ -2581,9 +2581,10 @@ y" {return quirkykeyscript}
#eval_base has been set by previous source or proc
#It can also be set by previous eval - *if* a non default offset was returned by _cmdtrace_get_eval_offset
set eval_base [dict get $linedict $target eval_base]
set eval_offset [dict get $linedict $target eval_offset]
set line [expr {$prevline + ($eval_offset-1) + ($traceline-1)}]
#puts "stack-- $callinfo"
set line [expr {$eval_base + ($eval_offset-1) + ($traceline-1)}]
puts "stack-- $callinfo"
puts " step type: eval traceline: $traceline -- "
if {[dict exists $callinfo cmd]} {
#set cmd [string trim [dict get $callinfo cmd]]
@ -2653,9 +2654,11 @@ y" {return quirkykeyscript}
}
#puts "-- $callinfo"
} else {
puts ">>step type: $type (nontargeted proc)>> $callinfo"
::tcl::dict::incr tinfo($target) subcmds
#puts ">>step type: $type (nontargeted proc)>> $callinfo"
}
} else {
::tcl::dict::incr tinfo($target) subcmds
#todo - handle type 'source' and type 'eval' with keys 'method' 'class' (oo)
#puts -------------------------
#puts ">[dict get $callinfo cmd]"
@ -2708,7 +2711,6 @@ y" {return quirkykeyscript}
variable tinfo
array unset tinfo
variable _cmdtrace_disabled
set _cmdtrace_disabled false
set argd [punk::args::parse $args -cache 1 withid ::punk::ns::cmdtrace]
lassign [dict values $argd] leaders opts values received
@ -2718,6 +2720,8 @@ y" {return quirkykeyscript}
set cinfo [uplevel 1 [list ::punk::ns::cmdinfo {*}$cmdargs]]
set origin [dict get $cinfo origin]
set arglist [dict get $cinfo args_remaining]
set origin_nscmd [nstail $origin]
set origin_ns [nsprefix $origin]
if {[dict exists $received -target]} {
set targets [dict get $opts -target]
@ -2740,15 +2744,16 @@ y" {return quirkykeyscript}
}
#don't raise the error when no -target supplied - as our launch command can contain extra arguments
}
lappend resolved_targets $tgt_cmd
set nscmd [nstail $tgt_cmd]
set ns [nsprefix $tgt_cmd]
lappend resolved_targets $tgt_cmd $ns $nscmd
::tcl::dict::set ::punk::ns::linedict $tgt_cmd [::tcl::dict::create eval_base 1 eval_offset 1 lines {} cmdtype $tgt_type successcalls 0 errorcalls 0]
}
#if the target command has a leading colon (e.g expr alternative :) we can't put a trace directly on a fully qualified name with a triple colon such as :::
#we will need to evaluate in the namespace
foreach tgt_cmd $resolved_targets {
set nscmd [nstail $tgt_cmd]
set ns [nsprefix $tgt_cmd]
foreach {tgt_cmd ns nscmd} $resolved_targets {
puts "tracing target: $tgt_cmd whilst running: $origin $arglist"
::tcl::namespace::eval $ns [list ::trace add execution $nscmd enter [list ::punk::ns::_cmdtrace_enter ::punk::ns::linedict $tgt_cmd]]
@ -2758,17 +2763,17 @@ y" {return quirkykeyscript}
try {
set origin_nscmd [nstail $origin]
set origin_ns [nsprefix $origin]
#uplevel 1 [list $origin {*}$arglist]
set _cmdtrace_disabled false
::tcl::namespace::eval $origin_ns [list $origin_nscmd {*}$arglist]
} trap {} {errMsg errOptions} {
set _cmdtrace_disabled true
#(even a puts can involve function calls - e.g in contexts where there are stacked channels)
puts stderr "command error $errMsg"
} finally {
foreach tgt_cmd $resolved_targets {
set nscmd [nstail $tgt_cmd]
set ns [nsprefix $tgt_cmd]
set _cmdtrace_disabled true
foreach {tgt_cmd ns nscmd} $resolved_targets {
::tcl::namespace::eval $ns [list ::trace remove execution $nscmd enterstep [list ::punk::ns::_cmdtrace_enterstep ::punk::ns::linedict $tgt_cmd]]
::tcl::namespace::eval $ns [list ::trace remove execution $nscmd enter [list ::punk::ns::_cmdtrace_enter ::punk::ns::linedict $tgt_cmd]]
::tcl::namespace::eval $ns [list ::trace remove execution $nscmd leave [list ::punk::ns::_cmdtrace_leave ::punk::ns::linedict $tgt_cmd]]
@ -2780,7 +2785,7 @@ y" {return quirkykeyscript}
append final_display \n
#todo - foreach tgt_cmd in resolved_targets?
foreach tgt_cmd $resolved_targets {
foreach {tgt_cmd _ _} $resolved_targets {
set lines [dict get $linedict $tgt_cmd lines]
if {[llength $lines]} {
set procbody [punk::ns::corp -n $tgt_cmd]

3
src/vfs/_vfscommon.vfs/modules/punk/args-0.2.1.tm

@ -6481,7 +6481,7 @@ tcl::namespace::eval punk::args {
}
if {[dict exists $thisarg_checks -maxsize]} {
set maxsize [dict get $thisarg_checks -maxsize]
if {$checkval ne "-1"} {
if {$maxsize ne "-1"} {
if {[tcl::string::length $e_check] > $maxsize} {
set msg "$argclass '$argname' for %caller% requires string with -maxsize $maxsize. Received len:[tcl::string::length $e_check] value:'$e_check'"
#return -options [list -code error -errorcode [list PUNKARGS VALIDATION [list sizeviolation $type] -badarg $argname -argspecs $argspecs]] $msg
@ -6679,6 +6679,7 @@ tcl::namespace::eval punk::args {
upper -
wordchar -
xdigit {
#todo - combined types xdigit && lower ?? set-theoretic types? how?
if {![tcl::string::is $type -strict $e_check]} {
set msg "$argclass $argname for %caller% requires type '$type'. Received: '$e'"
lset clause_results $c_idx $a_idx [list err [list typemismatch $type] msg $msg]

1022
src/vfs/_vfscommon.vfs/modules/punk/netbox-0.1.0.tm

File diff suppressed because it is too large Load Diff

305
src/vfs/_vfscommon.vfs/modules/punk/netbox/man-0.1.0.tm

@ -66,38 +66,6 @@ package require rest
#*** !doctools
#[section API]
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
# oo::class namespace
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
#tcl::namespace::eval punk::netbox::man::class {
#*** !doctools
#[subsection {Namespace punk::netbox::man::class}]
#[para] class definitions
#if {[tcl::info::commands [tcl::namespace::current]::interface_sample1] eq ""} {
#*** !doctools
#[list_begin enumerated]
# oo::class create interface_sample1 {
# #*** !doctools
# #[enum] CLASS [class interface_sample1]
# #[list_begin definitions]
# method test {arg1} {
# #*** !doctools
# #[call class::interface_sample1 [method test] [arg arg1]]
# #[para] test method
# puts "test: $arg1"
# }
# #*** !doctools
# #[list_end] [comment {-- end definitions interface_sample1}]
# }
#*** !doctools
#[list_end] [comment {--- end class enumeration ---}]
#}
#}
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
tcl::namespace::eval punk::netbox::man {
variable PUNKARGS
@ -926,6 +894,277 @@ tcl::namespace::eval punk::netbox::man::virtualization {
}
tcl::namespace::eval punk::netbox::man::extras {
namespace export {[a-z]*}
namespace ensemble create -parameters {apicontextid}
variable PUNKARGS
tcl::namespace::eval tags {
namespace export {[a-z]*}
namespace ensemble create -parameters {apicontextid}
variable PUNKARGS
namespace eval argdoc {
variable PUNKARGS
set DYN_CONTEXTNAMES {${[punk::netbox::api_context_names]}}
}
namespace eval argdoc {
lappend PUNKARGS [list\
{@dynamic}\
{
@id -id ::punk::netbox::man::extras::tags::create
@cmd -name punk::netbox::man::extras::tags::create -help\
"extras_tags_create
POST request for endpoint /extras/tags/"
@leaders -min 1 -max 1
apicontextid -help\
"The name of the stored api context to use.
A contextid can be created in-memory using
api_context_create, or loaded from a .toml
file using api_context_load."\
-choices {${$DYN_CONTEXTNAMES}}
@opts
-name -type string -minsize 1 -maxsize 100 -optional 0
-slug -type string -minsize 1 -maxsize 100 -optional 1
#todo - combined xdigit and lower??
-color -type xdigit -maxsize 6 -optional 1 -help\
"Default will be assigned by netbox.
e.g 9e9e9e"
-description -type string -maxsize 200 -default ""
}\
{-RETURN -default table -choices {table tableobject list linelist}}\
{
@values -min 0 -max 0
}
]
}
#example body
# color must be a lower-cased hex string (6 digits)
# e.g a red tag
# {
# "name": "my_tag",
# "slug": "my_tag",
# "color": "ff0000",
# "description": "testing tag creation"
# }
#example 201 response
#{
# "id": 14,
# "url": "https://www.netbox1.intx.com.au/api/extras/tags/14/",
# "display": "jjj",
# "name": "jjj",
# "slug": "jjj",
# "color": "ff0000",
# "description": "j testing",
# "created": "2025-11-11T16:33:17.461484Z",
# "last_updated": "2025-11-11T16:33:17.461500Z"
#}
#example 400 response
#{
# "name": [
# "tag with this name already exists."
# ],
# "slug": [
# "tag with this slug already exists."
# ]
#}
proc create {args} {
set argd [punk::args::parse $args withid "::punk::netbox::man::extras::tags::create"]
lassign [dict values $argd] leaders opts values received
set token [dict get $argd leaders apicontextid]
set map [::list \" "\\\"" \\ \\\\ \r \\r \n \\n \t \\t \b \\b \f \\f] ;#review - unicode? tcllib?
set name [dict get $argd opts -name]
if {[dict exists $received -slug]} {
set slug [dict get $opts -slug]
} else {
set slug $name
}
set description [dict get $argd opts -description]
#Escape for JSON
set name [string map $map $name]
set slug [string map $map $slug]
set description [string map $map $description]
set body "\{\n"
append body " \"name\": \"$name\"," \n
append body " \"slug\": \"$slug\"," \n
if {[dict exists $received -color]} {
append body " \"color\": \"[dict get $opts -color]\"," \n
}
append body " \"description\": \"$description\"" \n
append body "\}" \n
puts "Post body JSON:"
puts $body
#todo RETURN
set resultd [punk::netbox::extras::tags_create $token -RETURN dict $body]
}
namespace eval argdoc {
lappend PUNKARGS [list\
{@dynamic}\
{
@id -id ::punk::netbox::man::extras::tags::delete
@cmd -name punk::netbox::man::extras::tags::delete\
-summary\
"Delete one tag by id."\
-help\
"extras_tags_delete
DELETE request for endpoint /extras/tags/{id}
Delete a single tag by id."
@leaders -min 1 -max 1
apicontextid -help\
"The name of the stored api context to use.
A contextid can be created in-memory using
api_context_create, or loaded from a .toml
file using api_context_load."\
-choices {${$DYN_CONTEXTNAMES}}
@opts
@values -min 1 -max 1
id -type integer -range {0 ""}
}
]
}
proc delete {args} {
set argd [punk::args::parse $args withid "::punk::netbox::man::extras::tags::delete"]
lassign [dict values $argd] leaders opts values received
set token [dict get $argd leaders apicontextid]
set id [dict get $argd values id]
punk::netbox::extras::tags_delete $token -RETURN dict $id
return done
}
namespace eval argdoc {
lappend PUNKARGS [::list\
{@dynamic}\
[punk::args::resolved_def\
-antiglobs {@leaders @values -RETURN}\
-override {
@id {-id "::punk::netbox::man::extras::tags::list" }
apicontextid {-choices {${$DYN_CONTEXTNAMES}} }
}\
::punk::netbox::extras::tags_list\
]\
{-RETURN -default table -choices {table tableobject list linelist}}\
{-MAXRESULTS -type integer -default -1}\
{@values -min 0 -max 0}\
]
}
proc list {args} {
set argd [punk::args::parse $args withid "::punk::netbox::man::extras::tags::list"]
set urlnext ""
set requests_allowed 1000 ;#Sanity check - consider making an option - review
set resultlist [::list]
set token [dict get $argd leaders apicontextid]
set opts [dict get $argd opts]
set vals [dict get $argd values]
set multis [dict get $argd multis]
set outer_return [dict get $opts -RETURN]
set opts [dict remove $opts -RETURN] ;#opts from punk::args::parse is a dict (no dup keys) - can use 'dict remove' safely
set maxresults [dict get $opts -MAXRESULTS]
set opts [dict remove $opts -MAXRESULTS]
set initial_pagelimit [dict get $opts -limit]
#we can't just pass through 'multi' opts even if only one was supplied - list level is wrong
set nextopts [::list]
dict for {opt val} $opts {
if {$opt ni $multis} {
lappend nextopts $opt $val
} else {
foreach v $val {
lappend nextopts $opt $v
}
}
}
#Now opts is a list with possible repeated options! (for flags that have -multiple true)
if {$maxresults == -1} {
set maxresults $initial_pagelimit
}
if {$maxresults < $initial_pagelimit} {
punk::netbox::man::system::dupkeylist_setfirst nextopts -limit $maxresults
}
set to_go [expr {$maxresults - [llength $resultlist]}]
while {$urlnext ne "null"} {
if {$urlnext ne ""} {
set urlnext_params [punk::netbox::man::system::uri_get_querystring_as_keyval_list $urlnext]
if {[punk::netbox::man::system::dupkeylist_getfirst $nextopts -limit] > $to_go} {
punk::netbox::man::system::dupkeylist_setfirst urlnext_params limit $to_go
}
punk::netbox::man::system::optionlistvar_sync_from_urlparams nextopts $urlnext_params
}
puts "-->next:$urlnext nextopts:$nextopts vals:$vals"
set resultd [punk::netbox::extras::tags_list $token {*}$nextopts -RETURN dict {*}$vals]
set urlnext [dict get $resultd next]
set batch [dict get $resultd results]
lappend resultlist {*}$batch
set to_go [expr {$maxresults - [llength $resultlist]}]
if {$to_go <= 0} {break}
incr requests_allowed -1
if {$requests_allowed < 1} {break}
}
if {$outer_return in {table tableobject}} {
package require textblock
set t [textblock::list_as_table -return tableobject -colheaders {id name slug color sample description}]
foreach tag $resultlist {
set name [dict get $tag name]
set rgb [dict get $tag color]
if {[string length $rgb] && [string length $rgb] == 6} {
set sample "[a+ Rgb#$rgb rgb#$rgb-contrasting] $name [a]"
} else {
set sample ""
}
set r [::list\
[dict get $tag id]\
[dict get $tag name]\
[dict get $tag slug]\
$rgb\
$sample\
[dict get $tag description]\
]
$t add_row $r
}
}
switch -- $outer_return {
table {
set result [$t print]
$t destroy
return $result
}
tableobject {
return $t
}
linelist {
set ret ""
foreach r $resultlist {
append ret $r \n
}
return $ret
}
default {
return $resultlist
}
}
}
}
}
tcl::namespace::eval punk::netbox::man::ip-addresses {
namespace export {[a-z]*}
@ -1308,6 +1547,8 @@ namespace eval ::punk::args::register {
::punk::netbox::man::tenancy::tenants\
::punk::netbox::man::virtualization\
::punk::netbox::man::virtualization::virtual-machines\
::punk::netbox::man::extras\
::punk::netbox::man::extras::tags\
}
# -----------------------------------------------------------------------------

33
src/vfs/_vfscommon.vfs/modules/punk/ns-0.1.0.tm

@ -2581,9 +2581,10 @@ y" {return quirkykeyscript}
#eval_base has been set by previous source or proc
#It can also be set by previous eval - *if* a non default offset was returned by _cmdtrace_get_eval_offset
set eval_base [dict get $linedict $target eval_base]
set eval_offset [dict get $linedict $target eval_offset]
set line [expr {$prevline + ($eval_offset-1) + ($traceline-1)}]
#puts "stack-- $callinfo"
set line [expr {$eval_base + ($eval_offset-1) + ($traceline-1)}]
puts "stack-- $callinfo"
puts " step type: eval traceline: $traceline -- "
if {[dict exists $callinfo cmd]} {
#set cmd [string trim [dict get $callinfo cmd]]
@ -2653,9 +2654,11 @@ y" {return quirkykeyscript}
}
#puts "-- $callinfo"
} else {
puts ">>step type: $type (nontargeted proc)>> $callinfo"
::tcl::dict::incr tinfo($target) subcmds
#puts ">>step type: $type (nontargeted proc)>> $callinfo"
}
} else {
::tcl::dict::incr tinfo($target) subcmds
#todo - handle type 'source' and type 'eval' with keys 'method' 'class' (oo)
#puts -------------------------
#puts ">[dict get $callinfo cmd]"
@ -2708,7 +2711,6 @@ y" {return quirkykeyscript}
variable tinfo
array unset tinfo
variable _cmdtrace_disabled
set _cmdtrace_disabled false
set argd [punk::args::parse $args -cache 1 withid ::punk::ns::cmdtrace]
lassign [dict values $argd] leaders opts values received
@ -2718,6 +2720,8 @@ y" {return quirkykeyscript}
set cinfo [uplevel 1 [list ::punk::ns::cmdinfo {*}$cmdargs]]
set origin [dict get $cinfo origin]
set arglist [dict get $cinfo args_remaining]
set origin_nscmd [nstail $origin]
set origin_ns [nsprefix $origin]
if {[dict exists $received -target]} {
set targets [dict get $opts -target]
@ -2740,15 +2744,16 @@ y" {return quirkykeyscript}
}
#don't raise the error when no -target supplied - as our launch command can contain extra arguments
}
lappend resolved_targets $tgt_cmd
set nscmd [nstail $tgt_cmd]
set ns [nsprefix $tgt_cmd]
lappend resolved_targets $tgt_cmd $ns $nscmd
::tcl::dict::set ::punk::ns::linedict $tgt_cmd [::tcl::dict::create eval_base 1 eval_offset 1 lines {} cmdtype $tgt_type successcalls 0 errorcalls 0]
}
#if the target command has a leading colon (e.g expr alternative :) we can't put a trace directly on a fully qualified name with a triple colon such as :::
#we will need to evaluate in the namespace
foreach tgt_cmd $resolved_targets {
set nscmd [nstail $tgt_cmd]
set ns [nsprefix $tgt_cmd]
foreach {tgt_cmd ns nscmd} $resolved_targets {
puts "tracing target: $tgt_cmd whilst running: $origin $arglist"
::tcl::namespace::eval $ns [list ::trace add execution $nscmd enter [list ::punk::ns::_cmdtrace_enter ::punk::ns::linedict $tgt_cmd]]
@ -2758,17 +2763,17 @@ y" {return quirkykeyscript}
try {
set origin_nscmd [nstail $origin]
set origin_ns [nsprefix $origin]
#uplevel 1 [list $origin {*}$arglist]
set _cmdtrace_disabled false
::tcl::namespace::eval $origin_ns [list $origin_nscmd {*}$arglist]
} trap {} {errMsg errOptions} {
set _cmdtrace_disabled true
#(even a puts can involve function calls - e.g in contexts where there are stacked channels)
puts stderr "command error $errMsg"
} finally {
foreach tgt_cmd $resolved_targets {
set nscmd [nstail $tgt_cmd]
set ns [nsprefix $tgt_cmd]
set _cmdtrace_disabled true
foreach {tgt_cmd ns nscmd} $resolved_targets {
::tcl::namespace::eval $ns [list ::trace remove execution $nscmd enterstep [list ::punk::ns::_cmdtrace_enterstep ::punk::ns::linedict $tgt_cmd]]
::tcl::namespace::eval $ns [list ::trace remove execution $nscmd enter [list ::punk::ns::_cmdtrace_enter ::punk::ns::linedict $tgt_cmd]]
::tcl::namespace::eval $ns [list ::trace remove execution $nscmd leave [list ::punk::ns::_cmdtrace_leave ::punk::ns::linedict $tgt_cmd]]
@ -2780,7 +2785,7 @@ y" {return quirkykeyscript}
append final_display \n
#todo - foreach tgt_cmd in resolved_targets?
foreach tgt_cmd $resolved_targets {
foreach {tgt_cmd _ _} $resolved_targets {
set lines [dict get $linedict $tgt_cmd lines]
if {[llength $lines]} {
set procbody [punk::ns::corp -n $tgt_cmd]

Loading…
Cancel
Save