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
c582bfca
Kaydet (Commit)
c582bfca
authored
Tem 28, 2007
tarafından
Martin v. Löwis
Dosyalara gözat
Seçenekler
Dosyalara Gözat
İndir
Eposta Yamaları
Sade Fark
Fix quopri to operate consistently on bytes.
üst
f3f0c611
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
87 additions
and
75 deletions
+87
-75
quopri.py
Lib/quopri.py
+51
-46
test_quopri.py
Lib/test/test_quopri.py
+36
-29
No files found.
Lib/quopri.py
Dosyayı görüntüle @
c582bfca
...
...
@@ -6,10 +6,10 @@
__all__
=
[
"encode"
,
"decode"
,
"encodestring"
,
"decodestring"
]
ESCAPE
=
'='
ESCAPE
=
b
'='
MAXLINESIZE
=
76
HEX
=
'0123456789ABCDEF'
EMPTYSTRING
=
''
HEX
=
b
'0123456789ABCDEF'
EMPTYSTRING
=
b
''
try
:
from
binascii
import
a2b_qp
,
b2a_qp
...
...
@@ -19,23 +19,25 @@ except ImportError:
def
needsquoting
(
c
,
quotetabs
,
header
):
"""Decide whether a particular
character
needs to be quoted.
"""Decide whether a particular
byte ordinal
needs to be quoted.
The 'quotetabs' flag indicates whether embedded tabs and spaces should be
quoted. Note that line-ending tabs and spaces are always encoded, as per
RFC 1521.
"""
if
c
in
'
\t
'
:
assert
isinstance
(
c
,
bytes
)
if
c
in
b
'
\t
'
:
return
quotetabs
# if header, we have to escape _ because _ is used to escape space
if
c
==
'_'
:
if
c
==
b
'_'
:
return
header
return
c
==
ESCAPE
or
not
(
' '
<=
c
<=
'~'
)
return
c
==
ESCAPE
or
not
(
b
' '
<=
c
<=
b
'~'
)
def
quote
(
c
):
"""Quote a single character."""
i
=
ord
(
c
)
return
ESCAPE
+
HEX
[
i
//
16
]
+
HEX
[
i
%
16
]
assert
isinstance
(
c
,
bytes
)
and
len
(
c
)
==
1
c
=
ord
(
c
)
return
ESCAPE
+
bytes
((
HEX
[
c
//
16
],
HEX
[
c
%
16
]))
...
...
@@ -56,12 +58,12 @@ def encode(input, output, quotetabs, header = 0):
output
.
write
(
odata
)
return
def
write
(
s
,
output
=
output
,
lineEnd
=
'
\n
'
):
def
write
(
s
,
output
=
output
,
lineEnd
=
b
'
\n
'
):
# RFC 1521 requires that the line ending in a space or tab must have
# that trailing character encoded.
if
s
and
s
[
-
1
:]
in
'
\t
'
:
output
.
write
(
s
[:
-
1
]
+
quote
(
s
[
-
1
])
+
lineEnd
)
elif
s
==
'.'
:
if
s
and
s
[
-
1
:]
in
b
'
\t
'
:
output
.
write
(
s
[:
-
1
]
+
quote
(
s
[
-
1
:
])
+
lineEnd
)
elif
s
==
b
'.'
:
output
.
write
(
quote
(
s
)
+
lineEnd
)
else
:
output
.
write
(
s
+
lineEnd
)
...
...
@@ -73,16 +75,17 @@ def encode(input, output, quotetabs, header = 0):
break
outline
=
[]
# Strip off any readline induced trailing newline
stripped
=
''
if
line
[
-
1
:]
==
'
\n
'
:
stripped
=
b
''
if
line
[
-
1
:]
==
b
'
\n
'
:
line
=
line
[:
-
1
]
stripped
=
'
\n
'
stripped
=
b
'
\n
'
# Calculate the un-length-limited encoded line
for
c
in
line
:
c
=
bytes
((
c
,))
if
needsquoting
(
c
,
quotetabs
,
header
):
c
=
quote
(
c
)
if
header
and
c
==
' '
:
outline
.
append
(
'_'
)
if
header
and
c
==
b
' '
:
outline
.
append
(
b
'_'
)
else
:
outline
.
append
(
c
)
# First, write out the previous line
...
...
@@ -94,7 +97,7 @@ def encode(input, output, quotetabs, header = 0):
while
len
(
thisline
)
>
MAXLINESIZE
:
# Don't forget to include the soft line break `=' sign in the
# length calculation!
write
(
thisline
[:
MAXLINESIZE
-
1
],
lineEnd
=
'=
\n
'
)
write
(
thisline
[:
MAXLINESIZE
-
1
],
lineEnd
=
b
'=
\n
'
)
thisline
=
thisline
[
MAXLINESIZE
-
1
:]
# Write out the current line
prevline
=
thisline
...
...
@@ -105,9 +108,9 @@ def encode(input, output, quotetabs, header = 0):
def
encodestring
(
s
,
quotetabs
=
0
,
header
=
0
):
if
b2a_qp
is
not
None
:
return
b2a_qp
(
s
,
quotetabs
=
quotetabs
,
header
=
header
)
from
io
import
String
IO
infp
=
String
IO
(
s
)
outfp
=
String
IO
()
from
io
import
Bytes
IO
infp
=
Bytes
IO
(
s
)
outfp
=
Bytes
IO
()
encode
(
infp
,
outfp
,
quotetabs
,
header
)
return
outfp
.
getvalue
()
...
...
@@ -124,44 +127,44 @@ def decode(input, output, header = 0):
output
.
write
(
odata
)
return
new
=
''
new
=
b
''
while
1
:
line
=
input
.
readline
()
if
not
line
:
break
i
,
n
=
0
,
len
(
line
)
if
n
>
0
and
line
[
n
-
1
]
==
'
\n
'
:
if
n
>
0
and
line
[
n
-
1
:
n
]
==
b
'
\n
'
:
partial
=
0
;
n
=
n
-
1
# Strip trailing whitespace
while
n
>
0
and
line
[
n
-
1
]
in
"
\t\r
"
:
while
n
>
0
and
line
[
n
-
1
:
n
]
in
b
"
\t\r
"
:
n
=
n
-
1
else
:
partial
=
1
while
i
<
n
:
c
=
line
[
i
]
if
c
==
'_'
and
header
:
new
=
new
+
' '
;
i
=
i
+
1
c
=
line
[
i
:
i
+
1
]
if
c
==
b
'_'
and
header
:
new
=
new
+
b
' '
;
i
=
i
+
1
elif
c
!=
ESCAPE
:
new
=
new
+
c
;
i
=
i
+
1
elif
i
+
1
==
n
and
not
partial
:
partial
=
1
;
break
elif
i
+
1
<
n
and
line
[
i
+
1
]
==
ESCAPE
:
new
=
new
+
ESCAPE
;
i
=
i
+
2
elif
i
+
2
<
n
and
ishex
(
line
[
i
+
1
])
and
ishex
(
line
[
i
+
2
]):
new
=
new
+
chr
(
unhex
(
line
[
i
+
1
:
i
+
3
]
));
i
=
i
+
3
elif
i
+
2
<
n
and
ishex
(
line
[
i
+
1
:
i
+
2
])
and
ishex
(
line
[
i
+
2
:
i
+
3
]):
new
=
new
+
bytes
((
unhex
(
line
[
i
+
1
:
i
+
3
]),
));
i
=
i
+
3
else
:
# Bad escape sequence -- leave it in
new
=
new
+
c
;
i
=
i
+
1
if
not
partial
:
output
.
write
(
new
+
'
\n
'
)
new
=
''
output
.
write
(
new
+
b
'
\n
'
)
new
=
b
''
if
new
:
output
.
write
(
new
)
def
decodestring
(
s
,
header
=
0
):
if
a2b_qp
is
not
None
:
return
a2b_qp
(
s
,
header
=
header
)
from
io
import
String
IO
infp
=
String
IO
(
s
)
outfp
=
String
IO
()
from
io
import
Bytes
IO
infp
=
Bytes
IO
(
s
)
outfp
=
Bytes
IO
()
decode
(
infp
,
outfp
,
header
=
header
)
return
outfp
.
getvalue
()
...
...
@@ -169,21 +172,23 @@ def decodestring(s, header = 0):
# Other helper functions
def
ishex
(
c
):
"""Return true if the character 'c' is a hexadecimal digit."""
return
'0'
<=
c
<=
'9'
or
'a'
<=
c
<=
'f'
or
'A'
<=
c
<=
'F'
"""Return true if the byte ordinal 'c' is a hexadecimal digit in ASCII."""
assert
isinstance
(
c
,
bytes
)
return
b
'0'
<=
c
<=
b
'9'
or
b
'a'
<=
c
<=
b
'f'
or
b
'A'
<=
c
<=
b
'F'
def
unhex
(
s
):
"""Get the integer value of a hexadecimal number."""
bits
=
0
for
c
in
s
:
if
'0'
<=
c
<=
'9'
:
c
=
bytes
((
c
,))
if
b
'0'
<=
c
<=
b
'9'
:
i
=
ord
(
'0'
)
elif
'a'
<=
c
<=
'f'
:
elif
b
'a'
<=
c
<=
b
'f'
:
i
=
ord
(
'a'
)
-
10
elif
'A'
<=
c
<=
'F'
:
i
=
ord
(
'A'
)
-
10
elif
b
'A'
<=
c
<=
b
'F'
:
i
=
ord
(
b
'A'
)
-
10
else
:
break
assert
False
,
"non-hex digit "
+
repr
(
c
)
bits
=
bits
*
16
+
(
ord
(
c
)
-
i
)
return
bits
...
...
@@ -214,18 +219,18 @@ def main():
sts
=
0
for
file
in
args
:
if
file
==
'-'
:
fp
=
sys
.
stdin
fp
=
sys
.
stdin
.
buffer
else
:
try
:
fp
=
open
(
file
)
fp
=
open
(
file
,
"rb"
)
except
IOError
as
msg
:
sys
.
stderr
.
write
(
"
%
s: can't open (
%
s)
\n
"
%
(
file
,
msg
))
sts
=
1
continue
if
deco
:
decode
(
fp
,
sys
.
stdout
)
decode
(
fp
,
sys
.
stdout
.
buffer
)
else
:
encode
(
fp
,
sys
.
stdout
,
tabs
)
encode
(
fp
,
sys
.
stdout
.
buffer
,
tabs
)
if
fp
is
not
sys
.
stdin
:
fp
.
close
()
if
sts
:
...
...
Lib/test/test_quopri.py
Dosyayı görüntüle @
c582bfca
...
...
@@ -6,7 +6,7 @@ import quopri
ENCSAMPLE
=
"""
\
ENCSAMPLE
=
b
"""
\
Here's a bunch of special=20
=A1=A2=A3=A4=A5=A6=A7=A8=A9
...
...
@@ -25,8 +25,8 @@ characters... have fun!
"""
# First line ends with a space
DECSAMPLE
=
"Here's a bunch of special
\n
"
+
\
"""
\
DECSAMPLE
=
b
"Here's a bunch of special
\n
"
+
\
b
"""
\
\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9
\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3
...
...
@@ -67,48 +67,48 @@ class QuopriTestCase(unittest.TestCase):
# used in the "quotetabs=0" tests.
STRINGS
=
(
# Some normal strings
(
'hello'
,
'hello'
),
(
'''hello
(
b
'hello'
,
b
'hello'
),
(
b
'''hello
there
world'''
,
'''hello
world'''
,
b
'''hello
there
world'''
),
(
'''hello
(
b
'''hello
there
world
'''
,
'''hello
'''
,
b
'''hello
there
world
'''
),
(
'
\201\202\203
'
,
'=81=82=83'
),
(
b
'
\201\202\203
'
,
b
'=81=82=83'
),
# Add some trailing MUST QUOTE strings
(
'hello '
,
'hello=20'
),
(
'hello
\t
'
,
'hello=09'
),
(
b
'hello '
,
b
'hello=20'
),
(
b
'hello
\t
'
,
b
'hello=09'
),
# Some long lines. First, a single line of 108 characters
(
'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
,
'''xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=D8=D9=DA=DB=DC=DD=DE=DFx=
(
b
'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
,
b
'''xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=D8=D9=DA=DB=DC=DD=DE=DFx=
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'''
),
# A line of exactly 76 characters, no soft line break should be needed
(
'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy'
,
'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy'
),
(
b
'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy'
,
b
'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy'
),
# A line of 77 characters, forcing a soft line break at position 75,
# and a second line of exactly 2 characters (because the soft line
# break `=' sign counts against the line length limit).
(
'zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz'
,
'''zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz=
(
b
'zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz'
,
b
'''zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz=
zz'''
),
# A line of 151 characters, forcing a soft line break at position 75,
# with a second line of exactly 76 characters and no trailing =
(
'zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz'
,
'''zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz=
(
b
'zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz'
,
b
'''zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz=
zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz'''
),
# A string containing a hard line break, but which the first line is
# 151 characters and the second line is exactly 76 characters. This
# should leave us with three lines, the first which has a soft line
# break, and which the second and third do not.
(
'''yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
(
b
'''yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz'''
,
'''yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy=
b
'''yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy=
yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz'''
),
# Now some really complex stuff ;)
...
...
@@ -117,14 +117,14 @@ zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz''')
# These are used in the "quotetabs=1" tests.
ESTRINGS
=
(
(
'hello world'
,
'hello=20world'
),
(
'hello
\t
world'
,
'hello=09world'
),
(
b
'hello world'
,
b
'hello=20world'
),
(
b
'hello
\t
world'
,
b
'hello=09world'
),
)
# These are used in the "header=1" tests.
HSTRINGS
=
(
(
'hello world'
,
'hello_world'
),
(
'hello_world'
,
'hello=5Fworld'
),
(
b
'hello world'
,
b
'hello_world'
),
(
b
'hello_world'
,
b
'hello=5Fworld'
),
)
@withpythonimplementation
...
...
@@ -161,18 +161,18 @@ zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz''')
@withpythonimplementation
def
test_embedded_ws
(
self
):
for
p
,
e
in
self
.
ESTRINGS
:
self
.
assert
_
(
quopri
.
encodestring
(
p
,
quotetabs
=
True
)
==
e
)
self
.
assert
Equal
(
quopri
.
encodestring
(
p
,
quotetabs
=
True
),
e
)
self
.
assertEqual
(
quopri
.
decodestring
(
e
),
p
)
@withpythonimplementation
def
test_encode_header
(
self
):
for
p
,
e
in
self
.
HSTRINGS
:
self
.
assert
_
(
quopri
.
encodestring
(
p
,
header
=
True
)
==
e
)
self
.
assert
Equal
(
quopri
.
encodestring
(
p
,
header
=
True
),
e
)
@withpythonimplementation
def
test_decode_header
(
self
):
for
p
,
e
in
self
.
HSTRINGS
:
self
.
assert
_
(
quopri
.
decodestring
(
e
,
header
=
True
)
==
p
)
self
.
assert
Equal
(
quopri
.
decodestring
(
e
,
header
=
True
),
p
)
def
test_scriptencode
(
self
):
(
p
,
e
)
=
self
.
STRINGS
[
-
1
]
...
...
@@ -182,13 +182,20 @@ zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz''')
# On Windows, Python will output the result to stdout using
# CRLF, as the mode of stdout is text mode. To compare this
# with the expected result, we need to do a line-by-line comparison.
self
.
assertEqual
(
cout
.
splitlines
(),
e
.
splitlines
())
cout
=
cout
.
decode
(
'latin-1'
)
.
splitlines
()
e
=
e
.
decode
(
'latin-1'
)
.
splitlines
()
assert
len
(
cout
)
==
len
(
e
)
for
i
in
range
(
len
(
cout
)):
self
.
assertEqual
(
cout
[
i
],
e
[
i
])
self
.
assertEqual
(
cout
,
e
)
def
test_scriptdecode
(
self
):
(
p
,
e
)
=
self
.
STRINGS
[
-
1
]
process
=
subprocess
.
Popen
([
sys
.
executable
,
"-mquopri"
,
"-d"
],
stdin
=
subprocess
.
PIPE
,
stdout
=
subprocess
.
PIPE
)
cout
,
cerr
=
process
.
communicate
(
e
)
cout
=
cout
.
decode
(
'latin-1'
)
p
=
p
.
decode
(
'latin-1'
)
self
.
assertEqual
(
cout
.
splitlines
(),
p
.
splitlines
())
def
test_main
():
...
...
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