Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
cpython
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
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
cpython
Commits
f0daa880
Commit
f0daa880
authored
Feb 28, 2018
by
Cheryl Sabella
Committed by
Terry Jan Reedy
Feb 28, 2018
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
bpo-32940: IDLE: Simplify StringTranslatePseudoMapping in pyparse (GH-5862)
The new code also runs faster.
parent
45ab51c1
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
32 additions
and
89 deletions
+32
-89
Lib/idlelib/idle_test/test_pyparse.py
Lib/idlelib/idle_test/test_pyparse.py
+14
-42
Lib/idlelib/pyparse.py
Lib/idlelib/pyparse.py
+17
-47
Misc/NEWS.d/next/IDLE/2018-02-24-18-20-50.bpo-32940.ZaJ1Rf.rst
...NEWS.d/next/IDLE/2018-02-24-18-20-50.bpo-32940.ZaJ1Rf.rst
+1
-0
No files found.
Lib/idlelib/idle_test/test_pyparse.py
View file @
f0daa880
...
...
@@ -8,44 +8,20 @@ import unittest
from
idlelib
import
pyparse
class
StringTranslatePseudoMappingTest
(
unittest
.
TestCase
):
@
classmethod
def
setUpClass
(
cls
):
whitespace_chars
=
'
\
t
\
n
\
r
'
cls
.
preserve_dict
=
{
ord
(
c
):
ord
(
c
)
for
c
in
whitespace_chars
}
cls
.
default
=
ord
(
'x'
)
cls
.
mapping
=
pyparse
.
StringTranslatePseudoMapping
(
cls
.
preserve_dict
,
default_value
=
ord
(
'x'
))
@
classmethod
def
tearDownClass
(
cls
):
del
cls
.
preserve_dict
,
cls
.
default
,
cls
.
mapping
def
test__init__
(
self
):
m
=
self
.
mapping
self
.
assertEqual
(
m
.
_non_defaults
,
self
.
preserve_dict
)
self
.
assertEqual
(
m
.
_default_value
,
self
.
default
)
def
test__get_item__
(
self
):
self
.
assertEqual
(
self
.
mapping
[
ord
(
'
\
t
'
)],
ord
(
'
\
t
'
))
self
.
assertEqual
(
self
.
mapping
[
ord
(
'a'
)],
self
.
default
)
def
test__len__
(
self
):
self
.
assertEqual
(
len
(
self
.
mapping
),
len
(
self
.
preserve_dict
))
def
test__iter__
(
self
):
count
=
0
for
key
,
value
in
self
.
mapping
.
items
():
self
.
assertIn
(
key
,
self
.
preserve_dict
)
count
+=
1
self
.
assertEqual
(
count
,
len
(
self
.
mapping
))
def
test_get
(
self
):
self
.
assertEqual
(
self
.
mapping
.
get
(
ord
(
'
\
t
'
)),
ord
(
'
\
t
'
))
self
.
assertEqual
(
self
.
mapping
.
get
(
'a'
),
self
.
default
)
# Default is a parameter, but it isn't used.
self
.
assertEqual
(
self
.
mapping
.
get
(
'a'
,
default
=
500
),
self
.
default
)
class
ParseMapTest
(
unittest
.
TestCase
):
def
test_parsemap
(
self
):
keepwhite
=
{
ord
(
c
):
ord
(
c
)
for
c
in
'
\
t
\
n
\
r
'
}
mapping
=
pyparse
.
ParseMap
(
keepwhite
)
self
.
assertEqual
(
mapping
[
ord
(
'
\
t
'
)],
ord
(
'
\
t
'
))
self
.
assertEqual
(
mapping
[
ord
(
'a'
)],
ord
(
'x'
))
self
.
assertEqual
(
mapping
[
1000
],
ord
(
'x'
))
def
test_trans
(
self
):
# trans is the production instance of ParseMap, used in _study1
parser
=
pyparse
.
Parser
(
4
,
4
)
self
.
assertEqual
(
'
\
t
a([{b}])b"c
\
'
d
\
n
'
.
translate
(
pyparse
.
trans
),
'xxx(((x)))x"x
\
'
x
\
n
'
)
class
PyParseTest
(
unittest
.
TestCase
):
...
...
@@ -152,10 +128,6 @@ class PyParseTest(unittest.TestCase):
p
.
set_lo
(
44
)
self
.
assertEqual
(
p
.
code
,
code
[
44
:])
def
test_tran
(
self
):
self
.
assertEqual
(
'
\
t
a([{b}])b"c
\
'
d
\
n
'
.
translate
(
self
.
parser
.
_tran
),
'xxx(((x)))x"x
\
'
x
\
n
'
)
def
test_study1
(
self
):
eq
=
self
.
assertEqual
p
=
self
.
parser
...
...
Lib/idlelib/pyparse.py
View file @
f0daa880
"""Define partial Python code Parser used by editor and hyperparser.
Instances of
StringTranslatePseudoMapping
are used with str.translate.
Instances of
ParseMap
are used with str.translate.
The following bound search and match functions are defined:
_synchre - start of popular statement;
...
...
@@ -10,7 +10,6 @@ _itemre - line that may have bracket structure start;
_closere - line that must be followed by dedent.
_chew_ordinaryre - non-special characters.
"""
from
collections.abc
import
Mapping
import
re
import
sys
...
...
@@ -101,46 +100,27 @@ _chew_ordinaryre = re.compile(r"""
"""
,
re
.
VERBOSE
).
match
class
StringTranslatePseudoMapping
(
Mapping
):
r"""
Utility class to be used with str.translate()
class
ParseMap
(
dict
):
r"""
Dict subclass that maps anything not in dict to 'x'.
This Mapping class wraps a given dict. When a value for a key is
requested via __getitem__() or get(), the key is looked up in the
given dict. If found there, the value from the dict is returned.
Otherwise, the default value given upon initialization is returned.
This is designed to be used with str.translate in study1.
Anything not specifically mapped otherwise becomes 'x'.
Example: replace everything except whitespace with 'x'.
This allows using str.translate() to make some replacements, and to
replace all characters for which no replacement was specified with
a given character instead of leaving them as-is.
For example, to replace everything except whitespace with 'x':
>>> whitespace_chars = ' \t\n\r'
>>> preserve_dict = {ord(c): ord(c) for c in whitespace_chars}
>>> mapping = StringTranslatePseudoMapping(preserve_dict, ord('x'))
>>> text = "a + b\tc\nd"
>>> text.translate(mapping)
>>> keepwhite = ParseMap((ord(c), ord(c)) for c in ' \t\n\r')
>>> "a + b\tc\nd".translate(keepwhite)
'x x x\tx\nx'
"""
def
__init__
(
self
,
non_defaults
,
default_value
):
self
.
_non_defaults
=
non_defaults
self
.
_default_value
=
default_value
def
_get
(
key
,
_get
=
non_defaults
.
get
,
_default
=
default_value
):
return
_get
(
key
,
_default
)
self
.
_get
=
_get
# Calling this triples access time; see bpo-32940
def
__missing__
(
self
,
key
):
return
120
# ord('x')
def
__getitem__
(
self
,
item
):
return
self
.
_get
(
item
)
def
__len__
(
self
):
return
len
(
self
.
_non_defaults
)
def
__iter__
(
self
):
return
iter
(
self
.
_non_defaults
)
def
get
(
self
,
key
,
default
=
None
):
return
self
.
_get
(
key
)
# Map all ascii to 120 to avoid __missing__ call, then replace some.
trans
=
ParseMap
.
fromkeys
(
range
(
128
),
120
)
trans
.
update
((
ord
(
c
),
ord
(
'('
))
for
c
in
"({["
)
# open brackets => '(';
trans
.
update
((
ord
(
c
),
ord
(
')'
))
for
c
in
")}]"
)
# close brackets => ')'.
trans
.
update
((
ord
(
c
),
ord
(
c
))
for
c
in
"
\
"
'
\
\
\
n
#"
)
# Keep these.
class
Parser
:
...
...
@@ -224,16 +204,6 @@ class Parser:
if
lo
>
0
:
self
.
code
=
self
.
code
[
lo
:]
# Build a translation table to map uninteresting chars to 'x', open
# brackets to '(', close brackets to ')' while preserving quotes,
# backslashes, newlines and hashes. This is to be passed to
# str.translate() in _study1().
_tran
=
{}
_tran
.
update
((
ord
(
c
),
ord
(
'('
))
for
c
in
"({["
)
_tran
.
update
((
ord
(
c
),
ord
(
')'
))
for
c
in
")}]"
)
_tran
.
update
((
ord
(
c
),
ord
(
c
))
for
c
in
"
\
"
'
\
\
\
n
#"
)
_tran
=
StringTranslatePseudoMapping
(
_tran
,
default_value
=
ord
(
'x'
))
def
_study1
(
self
):
"""Find the line numbers of non-continuation lines.
...
...
@@ -250,7 +220,7 @@ class Parser:
# uninteresting characters. This can cut the number of chars
# by a factor of 10-40, and so greatly speed the following loop.
code
=
self
.
code
code
=
code
.
translate
(
self
.
_tran
)
code
=
code
.
translate
(
trans
)
code
=
code
.
replace
(
'xxxxxxxx'
,
'x'
)
code
=
code
.
replace
(
'xxxx'
,
'x'
)
code
=
code
.
replace
(
'xx'
,
'x'
)
...
...
Misc/NEWS.d/next/IDLE/2018-02-24-18-20-50.bpo-32940.ZaJ1Rf.rst
0 → 100644
View file @
f0daa880
Simplify and rename StringTranslatePseudoMapping in pyparse.
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