Skip to content
Projeler
Gruplar
Parçacıklar
Yardım
Yükleniyor...
Oturum aç / Kaydol
Gezinmeyi değiştir
C
cpython
Proje
Proje
Ayrıntılar
Etkinlik
Cycle Analytics
Depo (repository)
Depo (repository)
Dosyalar
Kayıtlar (commit)
Dallar (branch)
Etiketler
Katkıda bulunanlar
Grafik
Karşılaştır
Grafikler
Konular (issue)
0
Konular (issue)
0
Liste
Pano
Etiketler
Kilometre Taşları
Birleştirme (merge) Talepleri
0
Birleştirme (merge) Talepleri
0
CI / CD
CI / CD
İş akışları (pipeline)
İşler
Zamanlamalar
Grafikler
Paketler
Paketler
Wiki
Wiki
Parçacıklar
Parçacıklar
Üyeler
Üyeler
Collapse sidebar
Close sidebar
Etkinlik
Grafik
Grafikler
Yeni bir konu (issue) oluştur
İşler
Kayıtlar (commit)
Konu (issue) Panoları
Kenar çubuğunu aç
Batuhan Osman TASKAYA
cpython
Commits
4d770172
Kaydet (Commit)
4d770172
authored
Eyl 13, 2010
tarafından
Alexander Belopolsky
Dosyalara gözat
Seçenekler
Dosyalara Gözat
İndir
Eposta Yamaları
Sade Fark
Issue #9315: Fix for the trace module to record correct class name
when tracing methods. Unit tests. Patch by Eli Bendersky.
üst
dc69e721
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
291 additions
and
14 deletions
+291
-14
test_trace.py
Lib/test/test_trace.py
+282
-6
trace.py
Lib/trace.py
+4
-8
NEWS
Misc/NEWS
+5
-0
No files found.
Lib/test/test_trace.py
Dosyayı görüntüle @
4d770172
# Testing the trace module
from
test.support
import
run_unittest
,
TESTFN
,
rmtree
,
unlink
,
captured_stdout
import
os
import
sys
from
test.support
import
(
run_unittest
,
TESTFN
,
rmtree
,
unlink
,
captured_stdout
)
import
unittest
import
trace
import
os
,
sys
from
trace
import
CoverageResults
,
Trace
from
test.tracedmodules
import
testmod
#------------------------------- Utilities -----------------------------------#
def
fix_ext_py
(
filename
):
"""Given a .pyc/.pyo filename converts it to the appropriate .py"""
if
filename
.
endswith
((
'.pyc'
,
'.pyo'
)):
filename
=
filename
[:
-
1
]
return
filename
def
my_file_and_modname
():
"""The .py file and module name of this file (__file__)"""
modname
=
os
.
path
.
splitext
(
os
.
path
.
basename
(
__file__
))[
0
]
return
fix_ext_py
(
__file__
),
modname
def
get_firstlineno
(
func
):
return
func
.
__code__
.
co_firstlineno
#-------------------- Target functions for tracing ---------------------------#
#
# The relative line numbers of lines in these functions matter for verifying
# tracing. Please modify the appropriate tests if you change one of the
# functions. Absolute line numbers don't matter.
#
def
traced_func_linear
(
x
,
y
):
a
=
x
b
=
y
c
=
a
+
b
return
c
def
traced_func_loop
(
x
,
y
):
c
=
x
for
i
in
range
(
5
):
c
+=
y
return
c
def
traced_func_importing
(
x
,
y
):
return
x
+
y
+
testmod
.
func
(
1
)
def
traced_func_simple_caller
(
x
):
c
=
traced_func_linear
(
x
,
x
)
return
c
+
x
def
traced_func_importing_caller
(
x
):
k
=
traced_func_simple_caller
(
x
)
k
+=
traced_func_importing
(
k
,
x
)
return
k
def
traced_func_generator
(
num
):
c
=
5
# executed once
for
i
in
range
(
num
):
yield
i
+
c
def
traced_func_calling_generator
():
k
=
0
for
i
in
traced_func_generator
(
10
):
k
+=
i
def
traced_doubler
(
num
):
return
num
*
2
def
traced_caller_list_comprehension
():
k
=
10
mylist
=
[
traced_doubler
(
i
)
for
i
in
range
(
k
)]
return
mylist
class
TracedClass
(
object
):
def
__init__
(
self
,
x
):
self
.
a
=
x
def
inst_method_linear
(
self
,
y
):
return
self
.
a
+
y
def
inst_method_calling
(
self
,
x
):
c
=
self
.
inst_method_linear
(
x
)
return
c
+
traced_func_linear
(
x
,
c
)
@classmethod
def
class_method_linear
(
cls
,
y
):
return
y
*
2
@staticmethod
def
static_method_linear
(
y
):
return
y
*
2
#------------------------------ Test cases -----------------------------------#
class
TestLineCounts
(
unittest
.
TestCase
):
"""White-box testing of line-counting, via runfunc"""
def
setUp
(
self
):
self
.
tracer
=
Trace
(
count
=
1
,
trace
=
0
,
countfuncs
=
0
,
countcallers
=
0
)
self
.
my_py_filename
=
fix_ext_py
(
__file__
)
self
.
maxDiff
=
None
def
test_traced_func_linear
(
self
):
result
=
self
.
tracer
.
runfunc
(
traced_func_linear
,
2
,
5
)
self
.
assertEqual
(
result
,
7
)
# all lines are executed once
expected
=
{}
firstlineno
=
get_firstlineno
(
traced_func_linear
)
for
i
in
range
(
1
,
5
):
expected
[(
self
.
my_py_filename
,
firstlineno
+
i
)]
=
1
self
.
assertEqual
(
self
.
tracer
.
results
()
.
counts
,
expected
)
def
test_traced_func_loop
(
self
):
self
.
tracer
.
runfunc
(
traced_func_loop
,
2
,
3
)
firstlineno
=
get_firstlineno
(
traced_func_loop
)
expected
=
{
(
self
.
my_py_filename
,
firstlineno
+
1
):
1
,
(
self
.
my_py_filename
,
firstlineno
+
2
):
6
,
(
self
.
my_py_filename
,
firstlineno
+
3
):
5
,
(
self
.
my_py_filename
,
firstlineno
+
4
):
1
,
}
self
.
assertEqual
(
self
.
tracer
.
results
()
.
counts
,
expected
)
def
test_traced_func_importing
(
self
):
self
.
tracer
.
runfunc
(
traced_func_importing
,
2
,
5
)
firstlineno
=
get_firstlineno
(
traced_func_importing
)
expected
=
{
(
self
.
my_py_filename
,
firstlineno
+
1
):
1
,
(
fix_ext_py
(
testmod
.
__file__
),
2
):
1
,
(
fix_ext_py
(
testmod
.
__file__
),
3
):
1
,
}
self
.
assertEqual
(
self
.
tracer
.
results
()
.
counts
,
expected
)
def
test_trace_func_generator
(
self
):
self
.
tracer
.
runfunc
(
traced_func_calling_generator
)
firstlineno_calling
=
get_firstlineno
(
traced_func_calling_generator
)
firstlineno_gen
=
get_firstlineno
(
traced_func_generator
)
expected
=
{
(
self
.
my_py_filename
,
firstlineno_calling
+
1
):
1
,
(
self
.
my_py_filename
,
firstlineno_calling
+
2
):
11
,
(
self
.
my_py_filename
,
firstlineno_calling
+
3
):
10
,
(
self
.
my_py_filename
,
firstlineno_gen
+
1
):
1
,
(
self
.
my_py_filename
,
firstlineno_gen
+
2
):
11
,
(
self
.
my_py_filename
,
firstlineno_gen
+
3
):
10
,
}
self
.
assertEqual
(
self
.
tracer
.
results
()
.
counts
,
expected
)
def
test_trace_list_comprehension
(
self
):
self
.
tracer
.
runfunc
(
traced_caller_list_comprehension
)
firstlineno_calling
=
get_firstlineno
(
traced_caller_list_comprehension
)
firstlineno_called
=
get_firstlineno
(
traced_doubler
)
expected
=
{
(
self
.
my_py_filename
,
firstlineno_calling
+
1
):
1
,
# List compehentions work differently in 3.x, so the count
# below changed compared to 2.x.
(
self
.
my_py_filename
,
firstlineno_calling
+
2
):
12
,
(
self
.
my_py_filename
,
firstlineno_calling
+
3
):
1
,
(
self
.
my_py_filename
,
firstlineno_called
+
1
):
10
,
}
self
.
assertEqual
(
self
.
tracer
.
results
()
.
counts
,
expected
)
def
test_linear_methods
(
self
):
# XXX todo: later add 'static_method_linear' and 'class_method_linear'
# here, once issue1764286 is resolved
#
for
methname
in
[
'inst_method_linear'
,]:
tracer
=
Trace
(
count
=
1
,
trace
=
0
,
countfuncs
=
0
,
countcallers
=
0
)
traced_obj
=
TracedClass
(
25
)
method
=
getattr
(
traced_obj
,
methname
)
tracer
.
runfunc
(
method
,
20
)
firstlineno
=
get_firstlineno
(
method
)
expected
=
{
(
self
.
my_py_filename
,
firstlineno
+
1
):
1
,
}
self
.
assertEqual
(
tracer
.
results
()
.
counts
,
expected
)
class
TestRunExecCounts
(
unittest
.
TestCase
):
"""A simple sanity test of line-counting, via runctx (exec)"""
def
setUp
(
self
):
self
.
my_py_filename
=
fix_ext_py
(
__file__
)
def
test_exec_counts
(
self
):
self
.
tracer
=
Trace
(
count
=
1
,
trace
=
0
,
countfuncs
=
0
,
countcallers
=
0
)
code
=
r'''traced_func_loop(2, 5)'''
code
=
compile
(
code
,
__file__
,
'exec'
)
self
.
tracer
.
runctx
(
code
,
globals
(),
vars
())
firstlineno
=
get_firstlineno
(
traced_func_loop
)
expected
=
{
(
self
.
my_py_filename
,
firstlineno
+
1
):
1
,
(
self
.
my_py_filename
,
firstlineno
+
2
):
6
,
(
self
.
my_py_filename
,
firstlineno
+
3
):
5
,
(
self
.
my_py_filename
,
firstlineno
+
4
):
1
,
}
# When used through 'run', some other spurios counts are produced, like
# the settrace of threading, which we ignore, just making sure that the
# counts fo traced_func_loop were right.
#
for
k
in
expected
.
keys
():
self
.
assertEqual
(
self
.
tracer
.
results
()
.
counts
[
k
],
expected
[
k
])
class
TestFuncs
(
unittest
.
TestCase
):
"""White-box testing of funcs tracing"""
def
setUp
(
self
):
self
.
tracer
=
Trace
(
count
=
0
,
trace
=
0
,
countfuncs
=
1
)
self
.
filemod
=
my_file_and_modname
()
def
test_simple_caller
(
self
):
self
.
tracer
.
runfunc
(
traced_func_simple_caller
,
1
)
expected
=
{
self
.
filemod
+
(
'traced_func_simple_caller'
,):
1
,
self
.
filemod
+
(
'traced_func_linear'
,):
1
,
}
self
.
assertEqual
(
self
.
tracer
.
results
()
.
calledfuncs
,
expected
)
def
test_loop_caller_importing
(
self
):
self
.
tracer
.
runfunc
(
traced_func_importing_caller
,
1
)
expected
=
{
self
.
filemod
+
(
'traced_func_simple_caller'
,):
1
,
self
.
filemod
+
(
'traced_func_linear'
,):
1
,
self
.
filemod
+
(
'traced_func_importing_caller'
,):
1
,
self
.
filemod
+
(
'traced_func_importing'
,):
1
,
(
fix_ext_py
(
testmod
.
__file__
),
'testmod'
,
'func'
):
1
,
}
self
.
assertEqual
(
self
.
tracer
.
results
()
.
calledfuncs
,
expected
)
def
test_inst_method_calling
(
self
):
obj
=
TracedClass
(
20
)
self
.
tracer
.
runfunc
(
obj
.
inst_method_calling
,
1
)
expected
=
{
self
.
filemod
+
(
'TracedClass.inst_method_calling'
,):
1
,
self
.
filemod
+
(
'TracedClass.inst_method_linear'
,):
1
,
self
.
filemod
+
(
'traced_func_linear'
,):
1
,
}
self
.
assertEqual
(
self
.
tracer
.
results
()
.
calledfuncs
,
expected
)
class
TestCallers
(
unittest
.
TestCase
):
"""White-box testing of callers tracing"""
def
setUp
(
self
):
self
.
tracer
=
Trace
(
count
=
0
,
trace
=
0
,
countcallers
=
1
)
self
.
filemod
=
my_file_and_modname
()
def
test_loop_caller_importing
(
self
):
self
.
tracer
.
runfunc
(
traced_func_importing_caller
,
1
)
expected
=
{
((
os
.
path
.
splitext
(
trace
.
__file__
)[
0
]
+
'.py'
,
'trace'
,
'Trace.runfunc'
),
(
self
.
filemod
+
(
'traced_func_importing_caller'
,))):
1
,
((
self
.
filemod
+
(
'traced_func_simple_caller'
,)),
(
self
.
filemod
+
(
'traced_func_linear'
,))):
1
,
((
self
.
filemod
+
(
'traced_func_importing_caller'
,)),
(
self
.
filemod
+
(
'traced_func_simple_caller'
,))):
1
,
((
self
.
filemod
+
(
'traced_func_importing_caller'
,)),
(
self
.
filemod
+
(
'traced_func_importing'
,))):
1
,
((
self
.
filemod
+
(
'traced_func_importing'
,)),
(
fix_ext_py
(
testmod
.
__file__
),
'testmod'
,
'func'
)):
1
,
}
self
.
assertEqual
(
self
.
tracer
.
results
()
.
callers
,
expected
)
# Created separately for issue #3821
class
TestCoverage
(
unittest
.
TestCase
):
def
tearDown
(
self
):
rmtree
(
TESTFN
)
...
...
@@ -34,7 +310,6 @@ class TestCoverage(unittest.TestCase):
trace
=
0
,
count
=
1
)
with
captured_stdout
()
as
stdout
:
self
.
_coverage
(
tracer
)
self
.
assertEquals
(
stdout
.
getvalue
(),
""
)
if
os
.
path
.
exists
(
TESTFN
):
files
=
os
.
listdir
(
TESTFN
)
self
.
assertEquals
(
files
,
[])
...
...
@@ -43,5 +318,6 @@ class TestCoverage(unittest.TestCase):
def
test_main
():
run_unittest
(
__name__
)
if
__name__
==
"__main__"
:
if
__name__
==
'__main__'
:
test_main
()
Lib/trace.py
Dosyayı görüntüle @
4d770172
...
...
@@ -57,7 +57,7 @@ import threading
import
time
import
token
import
tokenize
import
types
import
inspect
import
gc
import
pickle
...
...
@@ -395,7 +395,7 @@ def find_lines(code, strs):
# and check the constants for references to other code objects
for
c
in
code
.
co_consts
:
if
i
sinstance
(
c
,
types
.
CodeType
):
if
i
nspect
.
iscode
(
c
):
# find another code object, so recurse into it
linenos
.
update
(
find_lines
(
c
,
strs
))
return
linenos
...
...
@@ -544,7 +544,7 @@ class Trace:
## use of gc.get_referrers() was suggested by Michael Hudson
# all functions which refer to this code object
funcs
=
[
f
for
f
in
gc
.
get_referrers
(
code
)
if
hasattr
(
f
,
"__doc__"
)]
if
inspect
.
isfunction
(
f
)]
# require len(func) == 1 to avoid ambiguity caused by calls to
# new.function(): "In the face of ambiguity, refuse the
# temptation to guess."
...
...
@@ -556,17 +556,13 @@ class Trace:
if
hasattr
(
c
,
"__bases__"
)]
if
len
(
classes
)
==
1
:
# ditto for new.classobj()
clsname
=
str
(
classes
[
0
])
clsname
=
classes
[
0
]
.
__name__
# cache the result - assumption is that new.* is
# not called later to disturb this relationship
# _caller_cache could be flushed if functions in
# the new module get called.
self
.
_caller_cache
[
code
]
=
clsname
if
clsname
is
not
None
:
# final hack - module name shows up in str(cls), but we've already
# computed module name, so remove it
clsname
=
clsname
.
split
(
"."
)[
1
:]
clsname
=
"."
.
join
(
clsname
)
funcname
=
"
%
s.
%
s"
%
(
clsname
,
funcname
)
return
filename
,
modulename
,
funcname
...
...
Misc/NEWS
Dosyayı görüntüle @
4d770172
...
...
@@ -145,6 +145,8 @@ Tools/Demos
Tests
-----
- Issue #9315: Added tests for the trace module. Patch by Eli Bendersky.
- Issue #9323: Make test.regrtest.__file__ absolute, this was not always the
case when running profile or trace, for example.
...
...
@@ -2070,6 +2072,9 @@ Library
- Issue #8235: _socket: Add the constant ``SO_SETFIB``. SO_SETFIB is a socket
option available on FreeBSD 7.1 and newer.
- Issue #9315: Fix for the trace module to record correct class name
for tracing methods.
Extension Modules
-----------------
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment