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
13192361
Commit
13192361
authored
Sep 09, 2016
by
R David Murray
Browse files
Options
Browse Files
Download
Plain Diff
Merge: #14977: Make mailcap respect the order of the lines in the mailcap file.
parents
223f12c9
347dc95c
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
80 additions
and
27 deletions
+80
-27
Lib/mailcap.py
Lib/mailcap.py
+25
-3
Lib/test/mailcap.txt
Lib/test/mailcap.txt
+1
-1
Lib/test/test_mailcap.py
Lib/test/test_mailcap.py
+46
-23
Misc/ACKS
Misc/ACKS
+1
-0
Misc/NEWS
Misc/NEWS
+7
-0
No files found.
Lib/mailcap.py
View file @
13192361
"""Mailcap file handling. See RFC 1524."""
import
os
import
warnings
__all__
=
[
"getcaps"
,
"findmatch"
]
def
lineno_sort_key
(
entry
):
# Sort in ascending order, with unspecified entries at the end
if
'lineno'
in
entry
:
return
0
,
entry
[
'lineno'
]
else
:
return
1
,
0
# Part 1: top-level interface.
def
getcaps
():
...
...
@@ -17,13 +27,14 @@ def getcaps():
"""
caps
=
{}
lineno
=
0
for
mailcap
in
listmailcapfiles
():
try
:
fp
=
open
(
mailcap
,
'r'
)
except
OSError
:
continue
with
fp
:
morecaps
=
readmailcapfile
(
fp
)
morecaps
,
lineno
=
_readmailcapfile
(
fp
,
lineno
)
for
key
,
value
in
morecaps
.
items
():
if
not
key
in
caps
:
caps
[
key
]
=
value
...
...
@@ -49,8 +60,15 @@ def listmailcapfiles():
# Part 2: the parser.
def
readmailcapfile
(
fp
):
"""Read a mailcap file and return a dictionary keyed by MIME type."""
warnings
.
warn
(
'readmailcapfile is deprecated, use getcaps instead'
,
DeprecationWarning
,
2
)
caps
,
_
=
_readmailcapfile
(
fp
,
None
)
return
caps
def
_readmailcapfile
(
fp
,
lineno
):
"""Read a mailcap file and return a dictionary keyed by MIME type.
Each MIME type is mapped to an entry consisting of a list of
...
...
@@ -76,6 +94,9 @@ def readmailcapfile(fp):
key
,
fields
=
parseline
(
line
)
if
not
(
key
and
fields
):
continue
if
lineno
is
not
None
:
fields
[
'lineno'
]
=
lineno
lineno
+=
1
# Normalize the key
types
=
key
.
split
(
'/'
)
for
j
in
range
(
len
(
types
)):
...
...
@@ -86,7 +107,7 @@ def readmailcapfile(fp):
caps
[
key
].
append
(
fields
)
else
:
caps
[
key
]
=
[
fields
]
return
caps
return
caps
,
lineno
def
parseline
(
line
):
"""Parse one entry in a mailcap file and return a dictionary.
...
...
@@ -165,6 +186,7 @@ def lookup(caps, MIMEtype, key=None):
entries
=
entries
+
caps
[
MIMEtype
]
if
key
is
not
None
:
entries
=
[
e
for
e
in
entries
if
key
in
e
]
entries
=
sorted
(
entries
,
key
=
lineno_sort_key
)
return
entries
def
subst
(
field
,
MIMEtype
,
filename
,
plist
=
[]):
...
...
Lib/test/mailcap.txt
View file @
13192361
...
...
@@ -35,5 +35,5 @@ message/external-body; showexternal %s %{access-type} %{name} %{site} \
text/richtext; shownonascii iso-8859-8 -e richtext -p %s; test=test "`echo \
%{charset} | tr '[A-Z]' '[a-z]'`" = iso-8859-8; copiousoutput
video/mpeg; mpeg_play %s
video/*; animate %s
video/mpeg; mpeg_play %s
\ No newline at end of file
Lib/test/test_mailcap.py
View file @
13192361
import
mailcap
import
os
import
copy
import
test.support
import
unittest
...
...
@@ -13,43 +14,55 @@ MAILCAPDICT = {
[{
'compose'
:
'moviemaker %s'
,
'x11-bitmap'
:
'"/usr/lib/Zmail/bitmaps/movie.xbm"'
,
'description'
:
'"Movie"'
,
'view'
:
'movieplayer %s'
}],
'view'
:
'movieplayer %s'
,
'lineno'
:
4
}],
'application/*'
:
[{
'copiousoutput'
:
''
,
'view'
:
'echo "This is
\
\
"%t
\
\
" but is 50
\
\
% Greek to me"
\
\
; cat %s'
}],
'view'
:
'echo "This is
\
\
"%t
\
\
" but is 50
\
\
% Greek to me"
\
\
; cat %s'
,
'lineno'
:
5
}],
'audio/basic'
:
[{
'edit'
:
'audiocompose %s'
,
'compose'
:
'audiocompose %s'
,
'description'
:
'"An audio fragment"'
,
'view'
:
'showaudio %s'
}],
'view'
:
'showaudio %s'
,
'lineno'
:
6
}],
'video/mpeg'
:
[{
'view'
:
'mpeg_play %s'
}],
[{
'view'
:
'mpeg_play %s'
,
'lineno'
:
13
}],
'application/postscript'
:
[{
'needsterminal'
:
''
,
'view'
:
'ps-to-terminal %s'
},
{
'compose'
:
'idraw %s'
,
'view'
:
'ps-to-terminal %s'
}],
[{
'needsterminal'
:
''
,
'view'
:
'ps-to-terminal %s'
,
'lineno'
:
1
},
{
'compose'
:
'idraw %s'
,
'view'
:
'ps-to-terminal %s'
,
'lineno'
:
2
}],
'application/x-dvi'
:
[{
'view'
:
'xdvi %s'
}],
[{
'view'
:
'xdvi %s'
,
'lineno'
:
3
}],
'message/external-body'
:
[{
'composetyped'
:
'extcompose %s'
,
'description'
:
'"A reference to data stored in an external location"'
,
'needsterminal'
:
''
,
'view'
:
'showexternal %s %{access-type} %{name} %{site} %{directory} %{mode} %{server}'
}],
'view'
:
'showexternal %s %{access-type} %{name} %{site} %{directory} %{mode} %{server}'
,
'lineno'
:
10
}],
'text/richtext'
:
[{
'test'
:
'test "`echo %{charset} | tr
\
'
[A-Z]
\
'
\
'
[a-z]
\
'
`" = iso-8859-8'
,
'copiousoutput'
:
''
,
'view'
:
'shownonascii iso-8859-8 -e richtext -p %s'
}],
'view'
:
'shownonascii iso-8859-8 -e richtext -p %s'
,
'lineno'
:
11
}],
'image/x-xwindowdump'
:
[{
'view'
:
'display %s'
}],
[{
'view'
:
'display %s'
,
'lineno'
:
9
}],
'audio/*'
:
[{
'view'
:
'/usr/local/bin/showaudio %t'
}],
[{
'view'
:
'/usr/local/bin/showaudio %t'
,
'lineno'
:
7
}],
'video/*'
:
[{
'view'
:
'animate %s'
}],
[{
'view'
:
'animate %s'
,
'lineno'
:
12
}],
'application/frame'
:
[{
'print'
:
'"cat %s | lp"'
,
'view'
:
'showframe %s'
}],
[{
'print'
:
'"cat %s | lp"'
,
'view'
:
'showframe %s'
,
'lineno'
:
0
}],
'image/rgb'
:
[{
'view'
:
'display %s'
}]
[{
'view'
:
'display %s'
,
'lineno'
:
8
}]
}
# For backwards compatibility, readmailcapfile() and lookup() still support
# the old version of mailcapdict without line numbers.
MAILCAPDICT_DEPRECATED
=
copy
.
deepcopy
(
MAILCAPDICT
)
for
entry_list
in
MAILCAPDICT_DEPRECATED
.
values
():
for
entry
in
entry_list
:
entry
.
pop
(
'lineno'
)
class
HelperFunctionTest
(
unittest
.
TestCase
):
...
...
@@ -75,12 +88,14 @@ class HelperFunctionTest(unittest.TestCase):
def
test_readmailcapfile
(
self
):
# Test readmailcapfile() using test file. It should match MAILCAPDICT.
with
open
(
MAILCAPFILE
,
'r'
)
as
mcf
:
d
=
mailcap
.
readmailcapfile
(
mcf
)
self
.
assertDictEqual
(
d
,
MAILCAPDICT
)
with
self
.
assertWarns
(
DeprecationWarning
):
d
=
mailcap
.
readmailcapfile
(
mcf
)
self
.
assertDictEqual
(
d
,
MAILCAPDICT_DEPRECATED
)
def
test_lookup
(
self
):
# Test without key
expected
=
[{
'view'
:
'mpeg_play %s'
},
{
'view'
:
'animate %s'
}]
expected
=
[{
'view'
:
'animate %s'
,
'lineno'
:
12
},
{
'view'
:
'mpeg_play %s'
,
'lineno'
:
13
}]
actual
=
mailcap
.
lookup
(
MAILCAPDICT
,
'video/mpeg'
)
self
.
assertListEqual
(
expected
,
actual
)
...
...
@@ -89,10 +104,16 @@ class HelperFunctionTest(unittest.TestCase):
expected
=
[{
'edit'
:
'audiocompose %s'
,
'compose'
:
'audiocompose %s'
,
'description'
:
'"An audio fragment"'
,
'view'
:
'showaudio %s'
}]
'view'
:
'showaudio %s'
,
'lineno'
:
6
}]
actual
=
mailcap
.
lookup
(
MAILCAPDICT
,
'audio/basic'
,
key
)
self
.
assertListEqual
(
expected
,
actual
)
# Test on user-defined dicts without line numbers
expected
=
[{
'view'
:
'mpeg_play %s'
},
{
'view'
:
'animate %s'
}]
actual
=
mailcap
.
lookup
(
MAILCAPDICT_DEPRECATED
,
'video/mpeg'
)
self
.
assertListEqual
(
expected
,
actual
)
def
test_subst
(
self
):
plist
=
[
'id=1'
,
'number=2'
,
'total=3'
]
# test case: ([field, MIMEtype, filename, plist=[]], <expected string>)
...
...
@@ -151,14 +172,16 @@ class FindmatchTest(unittest.TestCase):
'edit'
:
'audiocompose %s'
,
'compose'
:
'audiocompose %s'
,
'description'
:
'"An audio fragment"'
,
'view'
:
'showaudio %s'
'view'
:
'showaudio %s'
,
'lineno'
:
6
}
audio_entry
=
{
"view"
:
"/usr/local/bin/showaudio %t"
}
video_entry
=
{
'view'
:
'animate %s'
}
audio_entry
=
{
"view"
:
"/usr/local/bin/showaudio %t"
,
'lineno'
:
7
}
video_entry
=
{
'view'
:
'animate %s'
,
'lineno'
:
12
}
message_entry
=
{
'composetyped'
:
'extcompose %s'
,
'description'
:
'"A reference to data stored in an external location"'
,
'needsterminal'
:
''
,
'view'
:
'showexternal %s %{access-type} %{name} %{site} %{directory} %{mode} %{server}'
'view'
:
'showexternal %s %{access-type} %{name} %{site} %{directory} %{mode} %{server}'
,
'lineno'
:
10
,
}
# test case: (findmatch args, findmatch keyword args, expected output)
...
...
@@ -168,7 +191,7 @@ class FindmatchTest(unittest.TestCase):
cases
=
[
([{},
"video/mpeg"
],
{},
(
None
,
None
)),
([
c
,
"foo/bar"
],
{},
(
None
,
None
)),
([
c
,
"video/mpeg"
],
{},
(
'
mpeg_play /dev/null'
,
{
'view'
:
'mpeg_play %s'
}
)),
([
c
,
"video/mpeg"
],
{},
(
'
animate /dev/null'
,
video_entry
)),
([
c
,
"audio/basic"
,
"edit"
],
{},
(
"audiocompose /dev/null"
,
audio_basic_entry
)),
([
c
,
"audio/basic"
,
"compose"
],
{},
(
"audiocompose /dev/null"
,
audio_basic_entry
)),
([
c
,
"audio/basic"
,
"description"
],
{},
(
'"An audio fragment"'
,
audio_basic_entry
)),
...
...
Misc/ACKS
View file @
13192361
...
...
@@ -843,6 +843,7 @@ Julia Lawall
Chris Lawrence
Mark Lawrence
Chris Laws
Michael Lazar
Brian Leair
Mathieu Leduc-Hamel
Amandine Lee
...
...
Misc/NEWS
View file @
13192361
...
...
@@ -122,6 +122,9 @@ Core and Builtins
Library
-------
-
Issue
#
14977
:
mailcap
now
respects
the
order
of
the
lines
in
the
mailcap
files
(
"first match"
),
as
required
by
RFC
1542.
Patch
by
Michael
Lazar
.
-
Issue
#
28025
:
Convert
all
ssl
module
constants
to
IntEnum
and
IntFlags
.
SSLContext
properties
now
return
flags
and
enums
.
...
...
@@ -145,6 +148,10 @@ Library
- Issue #24277: The new email API is no longer provisional, and the docs
have been reorganized and rewritten to emphasize the new API.
- Issue #22450: urllib now includes an "Accept: */*" header among the
default headers. This makes the results of REST API requests more
consistent and predictable especially when proxy servers are involved.
- lib2to3.pgen3.driver.load_grammar() now creates a stable cache file
between runs given the same Grammar.txt input regardless of the hash
randomization setting.
...
...
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