Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
F
fslpy
Manage
Activity
Members
Code
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package registry
Model registry
Operate
Environments
Terraform modules
Analyze
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Evan Edmond
fslpy
Commits
918eef73
Commit
918eef73
authored
9 years ago
by
Paul McCarthy
Browse files
Options
Downloads
Patches
Plain Diff
Removed fsl.utils.trace module (it has been moved to the props project)
parent
847515ee
No related branches found
No related tags found
No related merge requests found
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
apidoc/fsl.utils.trace.rst
+0
-9
0 additions, 9 deletions
apidoc/fsl.utils.trace.rst
fsl/__init__.py
+2
-2
2 additions, 2 deletions
fsl/__init__.py
fsl/utils/__init__.py
+0
-1
0 additions, 1 deletion
fsl/utils/__init__.py
fsl/utils/trace.py
+0
-290
0 additions, 290 deletions
fsl/utils/trace.py
with
2 additions
and
302 deletions
apidoc/fsl.utils.trace.rst
deleted
100644 → 0
+
0
−
9
View file @
847515ee
:orphan:
fsl.utils.trace module
======================
.. automodule:: fsl.utils.trace
:members:
:undoc-members:
:show-inheritance:
This diff is collapsed.
Click to expand it.
fsl/__init__.py
+
2
−
2
View file @
918eef73
...
...
@@ -511,9 +511,9 @@ def _parseTopLevelArgs(argv, allTools):
# things if its logging level has been
# set to DEBUG, so we import it now so
# it can set itself up.
traceLogger
=
logging
.
getLogger
(
'
fsl.util
s.trace
'
)
traceLogger
=
logging
.
getLogger
(
'
prop
s.trace
'
)
if
traceLogger
.
getEffectiveLevel
()
<=
logging
.
DEBUG
:
import
fsl.util
s.trace
import
prop
s.trace
fslTool
=
_loadFSLTool
(
namespace
.
tool
)
...
...
This diff is collapsed.
Click to expand it.
fsl/utils/__init__.py
+
0
−
1
View file @
918eef73
...
...
@@ -19,7 +19,6 @@ things.
~fsl.utils.dialog
~fsl.utils.runwindow
~fsl.utils.webpage
~fsl.utils.trace
~fsl.utils.status
~fsl.utils.memoize
~fsl.utils.async
...
...
This diff is collapsed.
Click to expand it.
fsl/utils/trace.py
deleted
100644 → 0
+
0
−
290
View file @
847515ee
#!/usr/bin/env python
#
# trace.py - debugging functions
#
# Author: Paul McCarthy <pauldmccarthy@gmail.com>
#
"""
This module provides some useful logging/debugging functions.
.. warning:: This module is not intended for general use - it is solely for
development/debugging purposes. Do not use it unless you know
know what you are doing.
.. warning:: When this module is imported, it monkey patches the
:class:`props.callqueue.CallQueue` class in a devious and
dangerous manner to allow for more informative debug statements.
Therefore it
'
s a bad idea to even import this module, unless
you really know what you are doing.
.. warning:: Just don
'
t import this module, ok?
The functions provided by this module are as follows:
.. autosummary::
trace
setcause
propchange
"""
import
logging
import
inspect
import
os.path
as
op
log
=
logging
.
getLogger
(
__name__
)
# If trace debugging is enabled, we're going to
# do some funky stuff to the props callqueue
# object, so we can get some extra information
# in the propchange function.
if
log
.
getEffectiveLevel
()
==
logging
.
DEBUG
:
log
.
debug
(
'
Monkey-patching props.properties_value.queue instance
'
)
import
props
import
Queue
# The problem that I am addressing here is the
# fact that, when a property value listener is
# called, the cause of the call (i.e. the point
# at which the property value was changed) does
# not necessarily exist in the stack. This is
# because when a PV instance passes all of its
# listeners to the CallQueue (CQ) to call, the
# CQ will queue them immediately, but will not
# necessarily call them - they are only called
# if the CQ is not already processing the
# listeners from another PV change.
# A single CallQueue instance is shared
# by all PropertyValue instances to queue/
# call property value listeners.
theQ
=
props
.
properties_value
.
PropertyValue
.
queue
def
tracePop
(
*
args
,
**
kwargs
):
# When the CallQueue calls its _pop
# method, it will call the returned
# function. For debugging purposes,
# we'll pop the associated cause
# (enqueued in the tracePush function
# below), so the propchange function
# can print it out.
#
# This will throw Queue.EmptyError if
# the _causes queue is empty, but
# that is what the real _pop method
# does anyway.
try
:
theQ
.
_currentCause
=
theQ
.
_causes
.
get_nowait
()
except
:
theQ
.
_currentCause
=
None
return
theQ
.
_realPop
(
*
args
,
**
kwargs
)
def
tracePush
(
*
args
,
**
kwargs
):
pushed
=
theQ
.
_realPush
(
*
args
,
**
kwargs
)
# If the real _push method returns False,
# it means that the function was not enqueued
if
not
pushed
:
return
False
frames
=
inspect
.
stack
()[
1
:]
# We search for the first frame in the stack
# which is not in the props package - this
# will be the point of the PV change which
# caused this listener to be enqueued
triggerFrame
=
None
for
frame
in
frames
:
if
'
props/props
'
not
in
frame
[
1
]:
triggerFrame
=
frame
break
# This should never happen,
# but in case it does, we
# put a dummy value into
# the causes queue, so it
# is the same length as the
# reall call queue
if
triggerFrame
is
None
:
theQ
.
_causes
.
put_nowait
(
None
)
# Store the cause of the listener
# push on the causes queue
else
:
cause
=
[
triggerFrame
[
1
],
triggerFrame
[
2
],
triggerFrame
[
3
]]
if
triggerFrame
[
4
]
is
not
None
:
cause
.
append
(
triggerFrame
[
4
][
triggerFrame
[
5
]])
else
:
cause
.
append
(
'
<input>
'
)
theQ
.
_causes
.
put_nowait
(
cause
)
return
True
# Patch the CallQueue instance with
# our push/pop implementations
theQ
.
_causes
=
Queue
.
Queue
()
theQ
.
_realPush
=
theQ
.
_CallQueue__push
theQ
.
_realPop
=
theQ
.
_CallQueue__pop
theQ
.
_CallQueue__push
=
tracePush
theQ
.
_CallQueue__pop
=
tracePop
def
trace
(
desc
):
"""
Outputs a log message containing the given description and the current
stack trace.
"""
if
log
.
getEffectiveLevel
()
!=
logging
.
DEBUG
:
return
stack
=
inspect
.
stack
()[
1
:]
lines
=
'
{}
\n
'
.
format
(
desc
)
for
i
,
frame
in
enumerate
(
stack
):
srcMod
=
frame
[
1
]
srcLineNo
=
frame
[
2
]
if
frame
[
4
]
is
not
None
:
srcLine
=
frame
[
4
][
frame
[
5
]]
else
:
srcLine
=
'
<native>
'
lines
=
lines
+
'
{}{}:{}: {}
\n
'
.
format
(
'
'
*
(
i
+
1
),
srcMod
,
srcLineNo
,
srcLine
.
strip
())
log
.
debug
(
lines
)
return
lines
def
propchange
(
*
args
):
"""
Intended to be called from a :class:`props.PropertyValue` listener
function.
If this function is called due to a change, attempts to determine the line
of code which triggered the change. Prints some informative log messages.
:arg args: The arguments that were passed to the listener function.
"""
if
log
.
getEffectiveLevel
()
!=
logging
.
DEBUG
:
return
import
props
theQ
=
props
.
properties_value
.
PropertyValue
.
queue
stack
=
inspect
.
stack
()
listenerFile
=
stack
[
1
][
1
]
listenerLine
=
stack
[
1
][
2
]
listenerFunc
=
stack
[
1
][
3
]
triggerFile
=
None
if
len
(
args
)
!=
4
:
triggerFile
=
stack
[
2
][
1
]
triggerLine
=
stack
[
2
][
2
]
triggerFunc
=
stack
[
2
][
3
]
triggerSrc
=
stack
[
2
][
4
][
stack
[
2
][
5
]]
else
:
triggerFile
=
theQ
.
_currentCause
[
0
]
triggerLine
=
theQ
.
_currentCause
[
1
]
triggerFunc
=
theQ
.
_currentCause
[
2
]
triggerSrc
=
theQ
.
_currentCause
[
3
]
if
triggerFile
is
None
:
log
.
debug
(
'
Listener {} ({}:{}) was called
'
'
due to an unknown process
'
.
format
(
listenerFunc
,
op
.
basename
(
listenerFile
),
listenerLine
))
else
:
if
len
(
args
)
!=
4
:
reason
=
'
manually called from
'
else
:
value
,
valid
,
ctx
,
name
=
args
reason
=
'
called due to a value change of {}.{} ({}) at
'
.
format
(
type
(
ctx
).
__name__
,
name
,
value
)
log
.
debug
(
'
Listener {} ({}:{}) was {}
'
'
{} ({}:{}:{})
'
.
format
(
listenerFunc
,
op
.
basename
(
listenerFile
),
listenerLine
,
reason
,
triggerFunc
,
op
.
basename
(
triggerFile
),
triggerLine
,
triggerSrc
.
strip
()))
def
setcause
(
desc
):
"""
I can
'
t quite remember the difference betwen this function and the
:func:`propchange` function.
"""
if
log
.
getEffectiveLevel
()
!=
logging
.
DEBUG
:
return
stack
=
inspect
.
stack
()[
1
:]
causeFrame
=
None
ultCauseFrame
=
None
for
i
,
frame
in
enumerate
(
stack
):
if
'
props/props
'
not
in
frame
[
1
]:
causeFrame
=
frame
break
if
causeFrame
is
not
None
:
for
i
,
frame
in
reversed
(
list
(
enumerate
(
stack
))):
if
'
props/props
'
in
frame
[
1
]:
ultCauseFrame
=
stack
[
i
+
1
]
break
if
causeFrame
is
None
:
log
.
debug
(
'
{}: Unknown cause
'
.
format
(
desc
))
else
:
causeFile
=
causeFrame
[
1
]
causeLine
=
causeFrame
[
2
]
causeFunc
=
causeFrame
[
3
]
causeSrc
=
causeFrame
[
4
][
causeFrame
[
5
]]
line
=
'
{}: Caused by {} ({}:{}:{})
'
.
format
(
desc
,
causeFunc
,
op
.
basename
(
causeFile
),
causeLine
,
causeSrc
.
strip
())
if
ultCauseFrame
is
not
None
:
causeFile
=
ultCauseFrame
[
1
]
causeLine
=
ultCauseFrame
[
2
]
causeFunc
=
ultCauseFrame
[
3
]
causeSrc
=
ultCauseFrame
[
4
][
ultCauseFrame
[
5
]]
line
=
'
{} (ultimately caused by {} ({}:{}:{})
'
.
format
(
line
,
causeFunc
,
op
.
basename
(
causeFile
),
causeLine
,
causeSrc
.
strip
())
log
.
debug
(
line
)
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment