Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
M
my2to3
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Labels
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Jobs
Commits
Open sidebar
nexedi
my2to3
Commits
6f0132db
Commit
6f0132db
authored
Jul 16, 2020
by
Bryton Lacquement
🚪
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
fixes: major refactoring to eliminate boilerplate code
parent
6c078a2e
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
114 additions
and
95 deletions
+114
-95
my2to3/fixes/__init__.py
my2to3/fixes/__init__.py
+63
-5
my2to3/fixes/fix_division_support.py
my2to3/fixes/fix_division_support.py
+14
-32
my2to3/fixes/fix_division_trace.py
my2to3/fixes/fix_division_trace.py
+12
-20
my2to3/fixes/fix_nested_except_trace.py
my2to3/fixes/fix_nested_except_trace.py
+6
-7
my2to3/fixes/fix_round_trace.py
my2to3/fixes/fix_round_trace.py
+13
-20
my2to3/tests/testFixNestedExceptTrace.py
my2to3/tests/testFixNestedExceptTrace.py
+2
-2
my2to3/trace.py
my2to3/trace.py
+4
-9
No files found.
my2to3/fixes/__init__.py
View file @
6f0132db
...
...
@@ -2,14 +2,28 @@ from collections import defaultdict
from
lib2to3.fixer_base
import
BaseFix
as
lib2to3_BaseFix
import
lib2to3.fixer_util
from
my2to3.trace
import
create_table
,
get_data
,
tracing_functions
class
BaseFix
(
lib2to3_BaseFix
):
def
start_tree
(
self
,
tree
,
filename
):
super
(
BaseFix
,
self
).
start_tree
(
tree
,
filename
)
pass
class
BaseStaticTraceFix
(
BaseFix
):
def
__init__
(
self
,
*
args
,
**
kwargs
):
super
(
BaseStaticTraceFix
,
self
).
__init__
(
*
args
,
**
kwargs
)
# Note: id is used to differentiate the divisions of the same line.
shared_columns
=
"filename"
,
"lineno"
,
"id"
self
.
insert_trace
=
create_table
(
self
.
basename
+
"_trace"
,
*
(
shared_columns
+
self
.
traced_information
))
self
.
insert_modified
=
create_table
(
self
.
basename
+
"_modified"
,
*
shared_columns
)
def
start_tree
(
self
,
*
args
,
**
kwargs
):
super
(
BaseStaticTraceFix
,
self
).
start_tree
(
*
args
,
**
kwargs
)
self
.
ids
=
defaultdict
(
int
)
def
traced_call
(
self
,
n
ame
,
insert_function
,
n
ode
,
children
):
def
traced_call
(
self
,
node
,
children
):
# Important: every node inside "children" should be cloned before this
# function is called.
...
...
@@ -22,7 +36,7 @@ class BaseFix(lib2to3_BaseFix):
id_
=
self
.
ids
[
lineno
]
new_node
=
lib2to3
.
fixer_util
.
Call
(
lib2to3
.
fixer_util
.
Name
(
name
),
lib2to3
.
fixer_util
.
Name
(
self
.
basename
+
"_traced"
),
args
=
[
lib2to3
.
fixer_util
.
String
(
'"%s"'
%
filename
),
lib2to3
.
fixer_util
.
Comma
(),
...
...
@@ -35,6 +49,50 @@ class BaseFix(lib2to3_BaseFix):
self
.
ids
[
lineno
]
+=
1
insert_function
(
filename
,
lineno
,
id_
)
self
.
insert_modified
(
filename
,
lineno
,
id_
)
return
new_node
class
BaseDynamicTraceFix
(
BaseStaticTraceFix
):
def
__init__
(
self
,
*
args
,
**
kwargs
):
super
(
BaseDynamicTraceFix
,
self
).
__init__
(
*
args
,
**
kwargs
)
def
f
(
filename
,
lineno
,
id_
,
*
args
,
**
kwargs
):
result
,
values
=
self
.
_dynamic_trace
(
*
args
,
**
kwargs
)
self
.
insert_trace
(
filename
,
lineno
,
id_
,
*
values
)
return
result
f
.
__name__
=
self
.
basename
+
"_traced"
tracing_functions
.
append
(
f
)
class
BaseSupportFix
(
BaseFix
):
def
__init__
(
self
,
*
args
,
**
kwargs
):
super
(
BaseSupportFix
,
self
).
__init__
(
*
args
,
**
kwargs
)
# Note: id is used to differentiate the divisions of the same line.
self
.
insert_support
=
create_table
(
self
.
basename
+
"_support"
,
"filename"
,
"lineno"
,
"id"
,
"status"
)
def
analyze_data
(
self
,
filename
,
lineno
,
id_
):
class_name
=
"Fix%sTrace"
%
self
.
basename
.
capitalize
()
traced_information
=
getattr
(
__import__
(
"my2to3.fixes.fix_%s_trace"
%
self
.
basename
,
fromlist
=
[
class_name
]),
class_name
).
traced_information
data
=
get_data
(
self
.
basename
+
"_trace"
,
traced_information
,
dict
(
filename
=
filename
,
lineno
=
lineno
,
id
=
id_
)
)
if
data
:
try
:
results
,
status
=
self
.
_analyze_data
()
except
Exception
:
results
,
status
=
False
,
"unknown"
else
:
results
,
status
=
False
,
"no data"
self
.
insert_support
(
filename
[
1
:
-
1
],
lineno
,
id_
,
status
)
return
results
my2to3/fixes/fix_division_support.py
View file @
6f0132db
...
...
@@ -3,36 +3,26 @@ from lib2to3.pygram import python_symbols as syms
from
lib2to3.pytree
import
Leaf
,
Node
import
os
from
.
import
BaseFix
from
my2to3.trace
import
create_table
,
get_data
from
.
import
Base
Support
Fix
from
my2to3.trace
import
create_table
from
my2to3.util
import
add_future
,
data2types
# id is used to differentiate the divisions of the same line.
insert_support
=
create_table
(
"division_support"
,
"filename"
,
"lineno"
,
"id"
,
"status"
)
def
analyze_data
(
data
):
if
not
data
:
return
False
,
"no data"
class
FixDivisionSupport
(
BaseSupportFix
):
"""Rewrites division_traced(n, a, b) into Py2/Py3-compatible division
"""
basename
=
"division"
try
:
@
staticmethod
def
_analyze_data
(
data
):
types
=
data2types
(
data
)
except
Exception
as
e
:
# Probably, one type is not a builtins
return
False
,
"unknown"
if
len
(
types
)
==
1
:
dividend
,
divisor
=
types
[
0
]
if
dividend
is
divisor
is
int
:
return
True
,
"automatic"
if
len
(
types
)
==
1
:
dividend
,
divisor
=
types
[
0
]
if
dividend
is
divisor
is
int
:
return
True
,
"automatic"
return
False
,
"manual"
class
FixDivisionSupport
(
BaseFix
):
"""Rewrites division_traced(n, a, b) into Py2/Py3-compatible division
"""
return
False
,
"manual"
# Inspired by https://github.com/python/cpython/blob/e42b705188271da108de42b55d9344642170aa2b/Lib/lib2to3/fixes/fix_xrange.py#L14
PATTERN
=
"""
...
...
@@ -42,15 +32,7 @@ class FixDivisionSupport(BaseFix):
def
transform
(
self
,
node
,
results
):
args
=
results
[
'args'
]
filename
,
lineno
,
id_
=
[
l
.
value
for
l
in
args
.
children
[:
-
4
:
2
]]
should_change
,
status
=
analyze_data
(
get_data
(
"division_trace"
,
[
"dividend_type"
,
"divisor_type"
],
dict
(
filename
=
filename
,
lineno
=
lineno
,
id
=
id_
)
)
)
insert_support
(
filename
[
1
:
-
1
],
lineno
,
id_
,
status
)
should_change
=
self
.
analyze_data
(
*
[
l
.
value
for
l
in
args
.
children
[:
-
4
:
2
]])
if
should_change
:
add_future
(
node
,
'division'
)
operator
=
Leaf
(
lib2to3
.
pgen2
.
token
.
DOUBLESLASH
,
"//"
)
...
...
my2to3/fixes/fix_division_trace.py
View file @
6f0132db
...
...
@@ -4,30 +4,22 @@ import lib2to3.pgen2
from
lib2to3.pygram
import
python_symbols
as
syms
from
lib2to3.pytree
import
Node
from
.
import
BaseFix
from
my2to3.trace
import
create_table
,
register_tracing_function
from
.
import
BaseDynamicTraceFix
from
my2to3.util
import
parse_type
insert_trace
=
create_table
(
"division_trace"
,
"filename"
,
"lineno"
,
"id"
,
"dividend_type"
,
"divisor_type"
)
insert_modified
=
create_table
(
"division_modified"
,
"filename"
,
"lineno"
,
"id"
)
@
register_tracing_function
def
division_traced
(
filename
,
lineno
,
id_
,
dividend
,
divisor
):
insert_trace
(
filename
,
lineno
,
id_
,
parse_type
(
type
(
dividend
)),
parse_type
(
type
(
divisor
))
)
return
dividend
/
divisor
class
FixDivisionTrace
(
BaseFix
):
class
FixDivisionTrace
(
BaseDynamicTraceFix
):
"""Rewrites a / b into division_traced(id, a, b)
"""
basename
=
"division"
traced_information
=
"dividend_type"
,
"divisor_type"
@
staticmethod
def
_dynamic_trace
(
dividend
,
divisor
):
return
(
dividend
/
divisor
,
(
parse_type
(
type
(
dividend
)),
parse_type
(
type
(
divisor
)))
)
def
match
(
self
,
node
):
if
node
.
type
==
syms
.
term
:
...
...
@@ -64,7 +56,7 @@ class FixDivisionTrace(BaseFix):
comma
.
prefix
=
children
[
1
].
prefix
children
[
1
]
=
comma
previous_node
=
self
.
traced_call
(
"division_traced"
,
insert_modified
,
node
,
children
)
previous_node
=
self
.
traced_call
(
node
,
children
)
else
:
# It's not a division operation
previous_node
=
Node
(
syms
.
term
,
children
)
...
...
my2to3/fixes/fix_nested_except_trace.py
View file @
6f0132db
from
lib2to3.pygram
import
python_symbols
as
syms
from
.
import
BaseFix
from
my2to3.trace
import
create_table
from
.
import
BaseStaticTraceFix
insert_trace
=
create_table
(
"nested_except_trace"
,
"filename"
,
"lineno_parent"
,
"lineno_child"
)
class
FixNestedExceptTrace
(
BaseFix
):
class
FixNestedExceptTrace
(
BaseStaticTraceFix
):
"""This fixer detects scope bugs which can occur due to nested except clauses
which use the same variable name.
...
...
@@ -33,6 +29,9 @@ class FixNestedExceptTrace(BaseFix):
print(e)
raise
"""
basename
=
"nested_except"
traced_information
=
"lineno_parent"
,
"lineno_child"
# https://github.com/python/cpython/blob/3549ca313a6103a3adb281ef3a849298b7d7f72c/Lib/lib2to3/fixes/fix_except.py#L39-L45
PATTERN
=
"""
try_stmt< 'try' ':' (simple_stmt | suite)
...
...
@@ -59,6 +58,6 @@ class FixNestedExceptTrace(BaseFix):
for
child
in
self
.
list_except_clause_children
(
body
):
try
:
if
except_clause
.
children
[
3
]
==
child
.
children
[
3
]:
insert_trace
(
self
.
filenam
e
,
except_clause
.
get_lineno
(),
child
.
get_lineno
())
self
.
insert_trace
(
self
.
filename
,
None
,
Non
e
,
except_clause
.
get_lineno
(),
child
.
get_lineno
())
except
Exception
:
pass
my2to3/fixes/fix_round_trace.py
View file @
6f0132db
...
...
@@ -4,30 +4,23 @@ import lib2to3.pgen2
from
lib2to3.pygram
import
python_symbols
as
syms
from
lib2to3.pytree
import
Node
from
.
import
BaseFix
from
my2to3.trace
import
create_table
,
register_tracing_function
from
.
import
BaseDynamicTraceFix
from
my2to3.util
import
parse_type
insert_trace
=
create_table
(
"round_trace"
,
"filename"
,
"lineno"
,
"id"
,
"number"
,
"ndigits"
)
insert_modified
=
create_table
(
"round_modified"
,
"filename"
,
"lineno"
,
"id"
)
@
register_tracing_function
def
round_traced
(
filename
,
lineno
,
id_
,
number
,
ndigits
=
0
):
insert_trace
(
filename
,
lineno
,
id_
,
number
,
ndigits
)
return
round
(
number
,
ndigits
)
class
FixRoundTrace
(
BaseFix
):
class
FixRoundTrace
(
BaseDynamicTraceFix
):
"""Rewrites round(a[, b]) into round_traced(id, a[, b])
"""
basename
=
"round"
traced_information
=
"number"
,
"ndigits"
@
staticmethod
def
_dynamic_trace
(
number
,
ndigits
=
0
):
return
(
round
(
number
,
ndigits
),
(
parse_type
(
type
(
number
)),
parse_type
(
type
(
ndigits
)))
)
# Inspired by https://github.com/python/cpython/blob/e42b705188271da108de42b55d9344642170aa2b/Lib/lib2to3/fixes/fix_xrange.py#L14
PATTERN
=
"""
power<'round' trailer< '(' args=any ')' >
...
...
@@ -45,4 +38,4 @@ class FixRoundTrace(BaseFix):
# e.g. round(1,23, 4)
children
=
[
leaf
.
clone
()
for
leaf
in
args
.
children
]
node
.
replace
(
self
.
traced_call
(
"division_traced"
,
insert_modified
,
node
,
children
))
node
.
replace
(
self
.
traced_call
(
node
,
children
))
my2to3/tests/testFixNestedExceptTrace.py
View file @
6f0132db
...
...
@@ -30,7 +30,7 @@ class testFixNestedExceptTrace(FixerTestCase):
3
"""
self
.
unchanged
(
a
)
self
.
assertDataEqual
(
"nested_except_trace"
,
[(
u'<string>'
,
4
,
7
)])
self
.
assertDataEqual
(
"nested_except_trace"
,
[(
u'<string>'
,
None
,
None
,
4
,
7
)])
def
test_except_2
(
self
):
a
=
"""
...
...
@@ -59,7 +59,7 @@ class testFixNestedExceptTrace(FixerTestCase):
4
"""
self
.
unchanged
(
a
)
self
.
assertDataEqual
(
"nested_except_trace"
,
[(
u'<string>'
,
7
,
10
),
(
u'<string>'
,
4
,
7
),
(
u'<string>'
,
4
,
10
)])
self
.
assertDataEqual
(
"nested_except_trace"
,
[(
u'<string>'
,
None
,
None
,
7
,
10
),
(
u'<string>'
,
None
,
None
,
4
,
7
),
(
u'<string>'
,
None
,
None
,
4
,
10
)])
def
test_else
(
self
):
a
=
"""
...
...
my2to3/trace.py
View file @
6f0132db
...
...
@@ -8,9 +8,6 @@ conn = sqlite3.connect(database)
tracing_functions
=
[]
def
register_tracing_function
(
f
):
tracing_functions
.
append
(
f
)
return
f
def
create_table
(
table
,
*
columns
):
...
...
@@ -115,11 +112,9 @@ class ModuleImporter:
def
patch_imports
(
whitelist
):
sys
.
meta_path
.
append
(
ModuleImporter
(
whitelist
))
# XXX: This makes sure that "my2to3.trace.tracing_functions" is correctly
# populated. Let's find a better way.
apply_fixers
(
""
,
"dummy"
)
for
f
in
tracing_functions
:
setattr
(
__builtin__
,
f
.
__name__
,
f
)
for
fixer
in
get_fixers
():
# Import each fixer, to make sure that "my2to3.trace.tracing_functions" is
# correctly populated.
__import__
(
fixer
)
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