Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
cython
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Gwenaël Samain
cython
Commits
d07e7567
Commit
d07e7567
authored
Oct 31, 2010
by
Mark Florisson
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
lots of tests
parent
1327c85b
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
301 additions
and
99 deletions
+301
-99
Cython/Compiler/Tests/TestParseTreeTransforms.py
Cython/Compiler/Tests/TestParseTreeTransforms.py
+5
-3
Cython/Debugger/Tests/TestLibCython.py
Cython/Debugger/Tests/TestLibCython.py
+48
-40
Cython/Debugger/Tests/cfuncs.c
Cython/Debugger/Tests/cfuncs.c
+8
-0
Cython/Debugger/Tests/codefile
Cython/Debugger/Tests/codefile
+36
-0
Cython/Debugger/Tests/test_libcython_in_gdb.py
Cython/Debugger/Tests/test_libcython_in_gdb.py
+137
-56
Cython/Tests/TestStringIOTree.py
Cython/Tests/TestStringIOTree.py
+67
-0
No files found.
Cython/Compiler/Tests/TestParseTreeTransforms.py
View file @
d07e7567
...
@@ -197,10 +197,12 @@ class TestDebugTransform(TestLibCython.DebuggerTestCase):
...
@@ -197,10 +197,12 @@ class TestDebugTransform(TestLibCython.DebuggerTestCase):
self
.
assertEqual
(
1
,
len
(
list
(
spam_arguments
)))
self
.
assertEqual
(
1
,
len
(
list
(
spam_arguments
)))
# test step-into functions
# test step-into functions
spam_stepinto
=
list
(
spam
.
find
(
'StepIntoFunctions'
))
step_into
=
spam
.
find
(
'StepIntoFunctions'
)
spam_stepinto
=
[
x
.
attrib
[
'name'
]
for
x
in
step_into
]
assert
spam_stepinto
assert
spam_stepinto
self
.
assertEqual
(
1
,
len
(
list
(
spam_stepinto
)))
self
.
assertEqual
(
2
,
len
(
spam_stepinto
))
self
.
assertEqual
(
'puts'
,
list
(
spam_stepinto
)[
0
].
attrib
[
'name'
])
assert
'puts'
in
spam_stepinto
assert
'some_c_function'
in
spam_stepinto
except
:
except
:
print
open
(
self
.
debug_dest
).
read
()
print
open
(
self
.
debug_dest
).
read
()
raise
raise
...
...
Cython/Debugger/Tests/TestLibCython.py
View file @
d07e7567
...
@@ -9,10 +9,16 @@ import tempfile
...
@@ -9,10 +9,16 @@ import tempfile
import
subprocess
import
subprocess
import
distutils.core
import
distutils.core
from
distutils
import
sysconfig
from
distutils
import
sysconfig
from
distutils
import
ccompiler
import
Cython.Distutils.extension
import
Cython.Distutils.extension
from
Cython.Debugger
import
Cygdb
as
cygdb
from
Cython.Debugger
import
Cygdb
as
cygdb
root
=
os
.
path
.
dirname
(
os
.
path
.
abspath
(
__file__
))
codefile
=
os
.
path
.
join
(
root
,
'codefile'
)
cfuncs_file
=
os
.
path
.
join
(
root
,
'cfuncs.c'
)
with
open
(
codefile
)
as
f
:
source_to_lineno
=
dict
((
line
.
strip
(),
i
+
1
)
for
i
,
line
in
enumerate
(
f
))
class
DebuggerTestCase
(
unittest
.
TestCase
):
class
DebuggerTestCase
(
unittest
.
TestCase
):
...
@@ -26,52 +32,26 @@ class DebuggerTestCase(unittest.TestCase):
...
@@ -26,52 +32,26 @@ class DebuggerTestCase(unittest.TestCase):
self
.
debug_dest
=
os
.
path
.
join
(
self
.
tempdir
,
self
.
debug_dest
=
os
.
path
.
join
(
self
.
tempdir
,
'cython_debug'
,
'cython_debug'
,
'cython_debug_info_codefile'
)
'cython_debug_info_codefile'
)
self
.
cfuncs_destfile
=
os
.
path
.
join
(
self
.
tempdir
,
'cfuncs'
)
code
=
textwrap
.
dedent
(
"""
cdef extern from "stdio.h":
int puts(char *s)
cdef int c_var = 0
python_var = 0
def spam(a=0):
cdef:
int b, c, d
b = c = d = 0
b = 1
c = 2
d = 3
int(10)
puts("spam")
cdef ham():
pass
cpdef eggs():
pass
cdef class SomeClass(object):
def spam(self):
pass
spam()
"""
)
self
.
cwd
=
os
.
getcwd
()
self
.
cwd
=
os
.
getcwd
()
os
.
chdir
(
self
.
tempdir
)
os
.
chdir
(
self
.
tempdir
)
open
(
self
.
destfile
,
'w'
).
write
(
code
)
shutil
.
copy
(
codefile
,
self
.
destfile
)
shutil
.
copy
(
cfuncs_file
,
self
.
cfuncs_destfile
+
'.c'
)
compiler
=
ccompiler
.
new_compiler
()
compiler
.
compile
([
'cfuncs.c'
],
debug
=
True
)
ext
=
Cython
.
Distutils
.
extension
.
Extension
(
ext
=
Cython
.
Distutils
.
extension
.
Extension
(
'codefile'
,
'codefile'
,
[
'codefile.pyx'
],
[
'codefile.pyx'
],
pyrex_debug
=
True
)
pyrex_debug
=
True
,
extra_objects
=
[
'cfuncs.o'
])
distutils
.
core
.
setup
(
distutils
.
core
.
setup
(
script_args
=
[
'build_ext'
,
'--inplace'
],
script_args
=
[
'build_ext'
,
'--inplace'
],
ext_modules
=
[
ext
],
ext_modules
=
[
ext
],
cmdclass
=
dict
(
build_ext
=
Cython
.
Distutils
.
build_ext
)
cmdclass
=
dict
(
build_ext
=
Cython
.
Distutils
.
build_ext
)
)
)
...
@@ -84,12 +64,39 @@ class GdbDebuggerTestCase(DebuggerTestCase):
...
@@ -84,12 +64,39 @@ class GdbDebuggerTestCase(DebuggerTestCase):
def
setUp
(
self
):
def
setUp
(
self
):
super
(
GdbDebuggerTestCase
,
self
).
setUp
()
super
(
GdbDebuggerTestCase
,
self
).
setUp
()
self
.
gdb_command_file
=
cygdb
.
make_command_file
(
self
.
tempdir
)
prefix_code
=
textwrap
.
dedent
(
'''
\
with
open
(
self
.
gdb_command_file
,
'a'
)
as
f
:
python
f
.
write
(
'python '
'from Cython.Debugger.Tests import test_libcython_in_gdb;'
'test_libcython_in_gdb.main()
\
n
'
)
import os
import sys
import traceback
def excepthook(type, value, tb):
traceback.print_exception(type, value, tb)
os._exit(1)
sys.excepthook = excepthook
# Have tracebacks end up on sys.stderr (gdb replaces sys.stderr
# with an object that calls gdb.write())
sys.stderr = sys.__stderr__
end
'''
)
code
=
textwrap
.
dedent
(
'''
\
python
from Cython.Debugger.Tests import test_libcython_in_gdb
test_libcython_in_gdb.main()
end
'''
)
self
.
gdb_command_file
=
cygdb
.
make_command_file
(
self
.
tempdir
,
prefix_code
)
open
(
self
.
gdb_command_file
,
'a'
).
write
(
code
)
args
=
[
'gdb'
,
'-batch'
,
'-x'
,
self
.
gdb_command_file
,
'-n'
,
'--args'
,
args
=
[
'gdb'
,
'-batch'
,
'-x'
,
self
.
gdb_command_file
,
'-n'
,
'--args'
,
sys
.
executable
,
'-c'
,
'import codefile'
]
sys
.
executable
,
'-c'
,
'import codefile'
]
...
@@ -100,6 +107,7 @@ class GdbDebuggerTestCase(DebuggerTestCase):
...
@@ -100,6 +107,7 @@ class GdbDebuggerTestCase(DebuggerTestCase):
paths
.
append
(
os
.
path
.
dirname
(
os
.
path
.
dirname
(
paths
.
append
(
os
.
path
.
dirname
(
os
.
path
.
dirname
(
os
.
path
.
abspath
(
Cython
.
__file__
))))
os
.
path
.
abspath
(
Cython
.
__file__
))))
env
=
dict
(
os
.
environ
,
PYTHONPATH
=
os
.
pathsep
.
join
(
paths
))
env
=
dict
(
os
.
environ
,
PYTHONPATH
=
os
.
pathsep
.
join
(
paths
))
self
.
p
=
subprocess
.
Popen
(
self
.
p
=
subprocess
.
Popen
(
args
,
args
,
stdout
=
open
(
os
.
devnull
,
'w'
),
stdout
=
open
(
os
.
devnull
,
'w'
),
...
...
Cython/Debugger/Tests/cfuncs.c
0 → 100644
View file @
d07e7567
void
some_c_function
(
void
)
{
int
a
,
b
,
c
;
a
=
1
;
b
=
2
;
}
\ No newline at end of file
Cython/Debugger/Tests/codefile
0 → 100644
View file @
d07e7567
cdef extern from "stdio.h":
int puts(char *s)
cdef extern:
void some_c_function()
import os
cdef int c_var = 0
python_var = 0
def spam(a=0):
cdef:
int b, c
b = c = d = 0
b = 1
c = 2
int(10)
puts("spam")
os.path.join("foo", "bar")
some_c_function()
cdef ham():
pass
cpdef eggs():
pass
cdef class SomeClass(object):
def spam(self):
pass
spam()
print "bye!"
Cython/Debugger/Tests/test_libcython_in_gdb.py
View file @
d07e7567
...
@@ -5,19 +5,9 @@ Note: debug information is already imported by the file generated by
...
@@ -5,19 +5,9 @@ Note: debug information is already imported by the file generated by
Cython.Debugger.Cygdb.make_command_file()
Cython.Debugger.Cygdb.make_command_file()
"""
"""
import
sys
# First, fix gdb's python. Make sure to do this before importing modules
# that bind output streams as default parameters
# for some reason sys.argv is missing in gdb
sys
.
argv
=
[
'gdb'
]
# Allow gdb to capture output, but have errors end up on stderr
# sys.stdout = sys.__stdout__
sys
.
stderr
=
sys
.
__stderr__
import
os
import
os
import
sys
import
trace
import
warnings
import
warnings
import
unittest
import
unittest
import
traceback
import
traceback
...
@@ -26,6 +16,12 @@ from test import test_support
...
@@ -26,6 +16,12 @@ from test import test_support
import
gdb
import
gdb
from
Cython.Debugger
import
libcython
from
Cython.Debugger
import
libcython
from
Cython.Debugger
import
libpython
from
Cython.Debugger.Tests
import
TestLibCython
as
test_libcython
# for some reason sys.argv is missing in gdb
sys
.
argv
=
[
'gdb'
]
class
DebugTestCase
(
unittest
.
TestCase
):
class
DebugTestCase
(
unittest
.
TestCase
):
...
@@ -39,14 +35,35 @@ class DebugTestCase(unittest.TestCase):
...
@@ -39,14 +35,35 @@ class DebugTestCase(unittest.TestCase):
self
.
eggs_func
=
libcython
.
cy
.
functions_by_qualified_name
[
self
.
eggs_func
=
libcython
.
cy
.
functions_by_qualified_name
[
'codefile.eggs'
]
'codefile.eggs'
]
def
read_var
(
self
,
varname
):
def
read_var
(
self
,
varname
,
cast_to
=
None
):
return
gdb
.
parse_and_eval
(
'$cy_cname("%s")'
%
varname
)
result
=
gdb
.
parse_and_eval
(
'$cy_cname("%s")'
%
varname
)
if
cast_to
:
result
=
cast_to
(
result
)
return
result
def
local_info
(
self
):
def
local_info
(
self
):
return
gdb
.
execute
(
'info locals'
,
to_string
=
True
)
return
gdb
.
execute
(
'info locals'
,
to_string
=
True
)
class
TestDebugInformationClasses
(
DebugTestCase
):
def
lineno_equals
(
self
,
source_line
=
None
,
lineno
=
None
):
if
source_line
is
not
None
:
lineno
=
test_libcython
.
source_to_lineno
[
source_line
]
frame
=
gdb
.
selected_frame
()
self
.
assertEqual
(
libcython
.
cy
.
step
.
lineno
(
frame
),
lineno
)
def
tearDown
(
self
):
gdb
.
execute
(
'delete breakpoints'
,
to_string
=
True
)
try
:
gdb
.
execute
(
'kill inferior 1'
,
to_string
=
True
)
except
RuntimeError
:
pass
def
break_and_run
(
self
,
source_line
):
break_lineno
=
test_libcython
.
source_to_lineno
[
source_line
]
gdb
.
execute
(
'cy break codefile:%d'
%
break_lineno
,
to_string
=
True
)
gdb
.
execute
(
'run'
,
to_string
=
True
)
class
TestDebugInformationClasses
(
DebugTestCase
):
def
test_CythonModule
(
self
):
def
test_CythonModule
(
self
):
"test that debug information was parsed properly into data structures"
"test that debug information was parsed properly into data structures"
...
@@ -78,9 +95,11 @@ class TestDebugInformationClasses(DebugTestCase):
...
@@ -78,9 +95,11 @@ class TestDebugInformationClasses(DebugTestCase):
self
.
assertEqual
(
self
.
ham_func
.
type
,
libcython
.
CObject
)
self
.
assertEqual
(
self
.
ham_func
.
type
,
libcython
.
CObject
)
self
.
assertEqual
(
self
.
spam_func
.
arguments
,
[
'a'
])
self
.
assertEqual
(
self
.
spam_func
.
arguments
,
[
'a'
])
self
.
assertEqual
(
self
.
spam_func
.
step_into_functions
,
set
([
'puts'
]))
self
.
assertEqual
(
self
.
spam_func
.
step_into_functions
,
set
([
'puts'
,
'some_c_function'
]))
self
.
assertEqual
(
self
.
spam_func
.
lineno
,
8
)
expected_lineno
=
test_libcython
.
source_to_lineno
[
'def spam(a=0):'
]
self
.
assertEqual
(
self
.
spam_func
.
lineno
,
expected_lineno
)
self
.
assertEqual
(
sorted
(
self
.
spam_func
.
locals
),
list
(
'abcd'
))
self
.
assertEqual
(
sorted
(
self
.
spam_func
.
locals
),
list
(
'abcd'
))
...
@@ -95,7 +114,8 @@ class TestParameters(unittest.TestCase):
...
@@ -95,7 +114,8 @@ class TestParameters(unittest.TestCase):
class
TestBreak
(
DebugTestCase
):
class
TestBreak
(
DebugTestCase
):
def
test_break
(
self
):
def
test_break
(
self
):
result
=
gdb
.
execute
(
'cy break codefile.spam'
,
to_string
=
True
)
result
=
libpython
.
_execute
(
'cy break codefile.spam'
,
to_string
=
True
)
print
>>
sys
.
stderr
,
repr
(
result
)
assert
self
.
spam_func
.
cname
in
result
assert
self
.
spam_func
.
cname
in
result
self
.
assertEqual
(
len
(
gdb
.
breakpoints
()),
1
)
self
.
assertEqual
(
len
(
gdb
.
breakpoints
()),
1
)
...
@@ -104,48 +124,109 @@ class TestBreak(DebugTestCase):
...
@@ -104,48 +124,109 @@ class TestBreak(DebugTestCase):
self
.
assertEqual
(
bp
.
location
,
self
.
spam_func
.
cname
)
self
.
assertEqual
(
bp
.
location
,
self
.
spam_func
.
cname
)
assert
bp
.
enabled
assert
bp
.
enabled
class
TestStep
(
DebugTestCase
):
class
DebugStepperTestCase
(
DebugTestCase
):
def
test_step
(
self
):
def
step
(
self
,
varnames_and_values
,
source_line
=
None
,
lineno
=
None
):
# Note: breakpoint for spam is still set
gdb
.
execute
(
self
.
command
,
to_string
=
True
)
gdb
.
execute
(
'run'
)
for
varname
,
value
in
varnames_and_values
:
self
.
assertEqual
(
self
.
read_var
(
varname
),
value
,
self
.
local_info
())
gdb
.
execute
(
'cy step'
,
to_string
=
True
)
# b = c = d = 0
self
.
lineno_equals
(
source_line
,
lineno
)
gdb
.
execute
(
'cy step'
,
to_string
=
True
)
# b = 1
self
.
assertEqual
(
self
.
read_var
(
'b'
),
1
,
self
.
local_info
())
self
.
assertRaises
(
RuntimeError
,
self
.
read_var
(
'b'
))
gdb
.
execute
(
'cont'
)
class
TestNext
(
DebugTestCase
):
class
TestStep
(
DebugStepperTestCase
):
"""
Test stepping. Stepping happens in the code found in
Cython/Debugger/Tests/codefile.
"""
def
test_cython_step
(
self
):
gdb
.
execute
(
'cy break codefile.spam'
)
libcython
.
parameters
.
step_into_c_code
.
value
=
False
gdb
.
execute
(
'run'
,
to_string
=
True
)
self
.
lineno_equals
(
'def spam(a=0):'
)
gdb
.
execute
(
'cy step'
,
to_string
=
True
)
self
.
lineno_equals
(
'b = c = d = 0'
)
self
.
command
=
'cy step'
self
.
step
([(
'b'
,
0
)],
source_line
=
'b = 1'
)
self
.
step
([(
'b'
,
1
),
(
'c'
,
0
)],
source_line
=
'c = 2'
)
self
.
step
([(
'c'
,
2
)],
source_line
=
'int(10)'
)
self
.
step
([],
source_line
=
'puts("spam")'
)
self
.
step
([],
source_line
=
'os.path.join("foo", "bar")'
)
gdb
.
execute
(
'cont'
,
to_string
=
True
)
self
.
assertEqual
(
len
(
gdb
.
inferiors
()),
1
)
self
.
assertEqual
(
gdb
.
inferiors
()[
0
].
pid
,
0
)
def
test_next
(
self
):
def
test_c_step
(
self
):
pass
libcython
.
parameters
.
step_into_c_code
.
value
=
True
self
.
break_and_run
(
'some_c_function()'
)
gdb
.
execute
(
'cy step'
,
to_string
=
True
)
self
.
assertEqual
(
gdb
.
selected_frame
().
name
(),
'some_c_function'
)
def
main
():
def
test_python_step
(
self
):
self
.
break_and_run
(
'os.path.join("foo", "bar")'
)
gdb
.
execute
(
'cy step'
,
to_string
=
True
)
curframe
=
gdb
.
selected_frame
()
self
.
assertEqual
(
curframe
.
name
(),
'PyEval_EvalFrameEx'
)
pyframe
=
libpython
.
Frame
(
curframe
).
get_pyop
()
self
.
assertEqual
(
str
(
pyframe
.
co_name
),
'join'
)
class
TestNext
(
DebugStepperTestCase
):
def
test_cython_next
(
self
):
libcython
.
parameters
.
step_into_c_code
.
value
=
True
self
.
break_and_run
(
'c = 2'
)
lines
=
(
'int(10)'
,
'puts("spam")'
,
'os.path.join("foo", "bar")'
,
'some_c_function()'
,
)
for
line
in
lines
:
gdb
.
execute
(
'cy next'
)
self
.
lineno_equals
(
line
)
def
_main
():
# unittest.main(module=__import__(__name__, fromlist=['']))
try
:
try
:
# unittest.main(module=__import__(__name__, fromlist=['']))
gdb
.
lookup_type
(
'PyModuleObject'
)
try
:
except
RuntimeError
:
gdb
.
lookup_type
(
'PyModuleObject'
)
msg
=
(
"Unable to run tests, Python was not compiled with "
except
RuntimeError
:
"debugging information. Either compile python with "
msg
=
(
"Unable to run tests, Python was not compiled with "
"-g or get a debug build (configure with --with-pydebug)."
)
"debugging information. Either compile python with "
warnings
.
warn
(
msg
)
"-g or get a debug build (configure with --with-pydebug)."
)
else
:
warnings
.
warn
(
msg
)
tests
=
(
else
:
TestDebugInformationClasses
,
tests
=
(
TestParameters
,
TestDebugInformationClasses
,
TestBreak
,
TestParameters
,
TestStep
,
TestBreak
,
TestNext
,
TestStep
)
)
# test_support.run_unittest(tests)
# test_support.run_unittest(tests)
test_loader
=
unittest
.
TestLoader
()
test_loader
=
unittest
.
TestLoader
()
suite
=
unittest
.
TestSuite
(
suite
=
unittest
.
TestSuite
(
[
test_loader
.
loadTestsFromTestCase
(
cls
)
for
cls
in
tests
])
[
test_loader
.
loadTestsFromTestCase
(
cls
)
for
cls
in
tests
])
result
=
unittest
.
TextTestRunner
(
verbosity
=
1
).
run
(
suite
)
unittest
.
TextTestRunner
(
verbosity
=
1
).
run
(
suite
)
if
not
result
.
wasSuccessful
():
except
Exception
:
os
.
_exit
(
1
)
traceback
.
print_exc
()
os
.
_exit
(
1
)
def
main
(
trace_code
=
False
):
\ No newline at end of file
if
trace_code
:
tracer
=
trace
.
Trace
(
count
=
False
,
trace
=
True
,
outfile
=
sys
.
stderr
,
ignoredirs
=
[
sys
.
prefix
,
sys
.
exec_prefix
])
tracer
.
runfunc
(
_main
)
else
:
_main
()
\ No newline at end of file
Cython/Tests/TestStringIOTree.py
0 → 100644
View file @
d07e7567
import
unittest
from
Cython
import
StringIOTree
as
stringtree
code
=
"""
cdef int spam # line 1
cdef ham():
a = 1
b = 2
c = 3
d = 4
def eggs():
pass
cpdef bacon():
print spam
print 'scotch'
print 'tea?'
print 'or coffee?' # line 16
"""
linemap
=
dict
(
enumerate
(
code
.
splitlines
()))
class
TestStringIOTree
(
unittest
.
TestCase
):
def
setUp
(
self
):
self
.
tree
=
stringtree
.
StringIOTree
()
def
test_markers
(
self
):
assert
not
self
.
tree
.
allmarkers
()
def
test_insertion
(
self
):
self
.
write_lines
((
1
,
2
,
3
))
line_4_to_6_insertion_point
=
self
.
tree
.
insertion_point
()
self
.
write_lines
((
7
,
8
))
line_9_to_13_insertion_point
=
self
.
tree
.
insertion_point
()
self
.
write_lines
((
14
,
15
,
16
))
line_4_insertion_point
=
line_4_to_6_insertion_point
.
insertion_point
()
self
.
write_lines
((
5
,
6
),
tree
=
line_4_to_6_insertion_point
)
line_9_to_12_insertion_point
=
(
line_9_to_13_insertion_point
.
insertion_point
())
self
.
write_line
(
13
,
tree
=
line_9_to_13_insertion_point
)
self
.
write_line
(
4
,
tree
=
line_4_insertion_point
)
self
.
write_line
(
9
,
tree
=
line_9_to_12_insertion_point
)
line_10_insertion_point
=
line_9_to_12_insertion_point
.
insertion_point
()
self
.
write_line
(
11
,
tree
=
line_9_to_12_insertion_point
)
self
.
write_line
(
10
,
tree
=
line_10_insertion_point
)
self
.
write_line
(
12
,
tree
=
line_9_to_12_insertion_point
)
self
.
assertEqual
(
self
.
tree
.
allmarkers
(),
range
(
1
,
17
))
self
.
assertEqual
(
code
.
strip
(),
self
.
tree
.
getvalue
().
strip
())
def
write_lines
(
self
,
linenos
,
tree
=
None
):
for
lineno
in
linenos
:
self
.
write_line
(
lineno
,
tree
=
tree
)
def
write_line
(
self
,
lineno
,
tree
=
None
):
if
tree
is
None
:
tree
=
self
.
tree
tree
.
markers
.
append
(
lineno
)
tree
.
write
(
linemap
[
lineno
]
+
'
\
n
'
)
\ No newline at end of file
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