[Activetcl] Variable scope
by Robert M Bartis other posts by this author
Oct 1 2007 7:58PM messages near this date
view in the new Beta List Site
Re: [Activetcl] HP-UX 11.11 and Oratcl
|
Re: [Activetcl] Variable scope
I have what I think is a very obvious question, but whose answer escapes
me. I have a class below which declares a private variable elapsed. The
variable is set to zero within the constructor and then within the
private method call commonLog. Its is also passed as a variable in a
number of other method calls.
I have verified the value of elapsed is set a number of times in
commonLog to a value greater than zero before its value is passed within
the method call step. The value passed within step is always zero. If I
comment out the assignment within the constructor I receive an error
indicating the variable is not set, even though I have verified its > 0
value within the commonLog method. How is it a private variable within
the class can be in scope within within some methods and yet when set
within another method operates as if it were a local variable??
#!/dtools/ActiveTcl/bin/tclsh
package require Tcl 8.4
package require Itcl 3.3
package require Results
package provide MyLogger 1.0
itcl::class myLogger {
# Declare variable user of this class can configure
public common ftype w
public common flush 1
public variable lvl notice
public variable name "Name not set"
# Provide a common file ID for all users of this class
protected common fid -1
private common loggingStart [::clock seconds]
# Provide for a per instance logging service ID
protected variable log
protected variable logMsgs
private variable elapsed
private variable lvls
private variable lvlNum
private variable resultsObj
constructor {} {
set lvls [list debug info notice warn error critical]
set lvlNum [lsearch $lvls notice]
set elapsed 0
# Create a results object for logging cmd and results
information
# via this class.
set resultsObj [results #auto]
# First check to see if a common logging file has already been
opened. If so,
# skip this step. If not, open one now with the permissions defined
by the
# variable ftype
if {$fid == -1} {
# Open file for common logging
set fid [open log.txt $ftype]
}
# Determine if we were able to open log file
if {$fid == -1} {
$log error "Failed to open common logging file"
}
# Modify the buffer descriptors for both the log file and stdout
foreach id [list $fid stdout] {
#fconfigure $id -blocking 1 -buffersize 1000 -buffering none
fconfigure $id -blocking 1 -buffersize 1000 -buffering
line
}
}
destructor {
flush $fid
flush stdout
catch {close $fid}
}
# Define common logging function to be called for all levels
private method commonLog {lvl s} {}
public method debug {s} {}
public method info {s} {}
public method notice {s} {}
public method warn {s} {}
public method error {s} {}
public method critical {s} {}
public method msgs {lvl} {}
# Hooks to ensure calls to public methods inherited from the
# results class are logged to files as appropriate
public method cmd {cmd duration} {}
public method step {cmd passfail duration} {}
public method testResult {id duration passFail expected actual}
{}
#public method history {type} {}
}
# Provide procedure that is called whenever the user who invoked the
class configures this
# variable. Ensure only supported values are used to actually set the
interval variable
#
itcl::configbody myLogger::ftype {
switch {ftype} {
a -
w {}
default {set ftype w}
}
}
# Provide procedure that is called whenever the user who invoked the
class configures this
# variable. Ensure only supported values are used to actually set the
interval variable
#
itcl::configbody myLogger::lvl {
# Set default reporting level to notice and above
switch $lvl {
debug -
info -
notice -
warn -
error -
critical {
# Determine the numeric level based on the user supplied string
set lvlNum [lsearch $lvls $lvl]
}
default {
set lvl notice
# Determine the numeric level based on the user supplied string
set lvlNum [lsearch $lvls $lvl]
}
}
}
itcl::body myLogger::commonLog {lvl s} {
if {[lsearch $lvls $lvl] < $lvlNum} {return}
puts $s
# Calculate the duration for this logging session, in
seconds
# from the start of this class creation
set sec [::clock seconds]
set elapsed [expr $sec - $loggingStart]
set ts [::clock format $sec]
set prefix "#### $elapsed - $ts - $name"
puts $fid "\n$prefix\n$s"
# Provide means to flush file buffer each time to ensure
# debug information does not get lost if required
if {$flush == 1} {
flush $fid
flush stdout
}
}
itcl::body myLogger::debug {s} {$this commonLog debug $s}
itcl::body myLogger::info {s} {$this commonLog info $s}
itcl::body myLogger::notice {s} {$this commonLog notice $s}
itcl::body myLogger::warn {s} {
$this commonLog warn $s
append logMsgs(warn) "$s\n"
}
itcl::body myLogger::error {s} {
$this commonLog error $s
append logMsgs(error) "$s\n"
}
itcl::body myLogger::critical {s} {
$this commonLog critical $s
exit -1
}
itcl::body myLogger::msgs {lvl} {
set rtn ""
switch $lvl {
warn {if {[array get logMsgs warn] != ""} {set rtn $logMsgs(warn)} }
error {if {[array get logMsgs error] != ""} {set rtn $logMsgs(error)} }
debug -
info -
notice -
critical {}
default {$this error "$this::msgs - Invalid lvl ($lvl)"}
}
return $rtn
}
itcl::body myLogger::cmd {cmd duration} {
$resultsObj cmd $cmd $duration $elapsed
$this info "$cmd $duration"
}
itcl::body myLogger::step {cmd passfail duration} {
$resultsObj step $cmd $passfail $duration $elapsed
$this info "$cmd $duration"
}
itcl::body myLogger::testResult {id duration passFail expected actual} {
set units ms
$resultsObj testResult $id $duration $elapsed $passFail
$expected $actual
# Determine appropriate interval to report duration in, ms or
sec?
if {$duration > 0} {
set sec [expr $duration/1000]
if {$sec > 0} {
# Format to hundreds of sec accuracy
set duration [format "%.2f" $sec]
set units sec
}
}
$this notice "Test Result: $id $duration$units $passFail
$expected $actual"
}
Robert M. Bartis
Stinger Quality Assurance
TEL: (908) 582-6566
EMAIL: bartis@[...].com
Thread:
Robert M Bartis
Tom SAVELL
|