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
8e5d0caf
Kaydet (Commit)
8e5d0caf
authored
Mar 19, 2014
tarafından
Kristján Valur Jónsson
Dosyalara gözat
Seçenekler
Dosyalara Gözat
İndir
Eposta Yamaları
Sade Fark
Issue #19009
Enhance HTTPResponse.readline() performance
üst
4278b2d7
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
121 additions
and
57 deletions
+121
-57
client.py
Lib/http/client.py
+121
-57
test_httplib.py
Lib/test/test_httplib.py
+0
-0
No files found.
Lib/http/client.py
Dosyayı görüntüle @
8e5d0caf
...
@@ -271,7 +271,7 @@ def parse_headers(fp, _class=HTTPMessage):
...
@@ -271,7 +271,7 @@ def parse_headers(fp, _class=HTTPMessage):
return
email
.
parser
.
Parser
(
_class
=
_class
)
.
parsestr
(
hstring
)
return
email
.
parser
.
Parser
(
_class
=
_class
)
.
parsestr
(
hstring
)
class
HTTPResponse
(
io
.
Raw
IOBase
):
class
HTTPResponse
(
io
.
Buffered
IOBase
):
# See RFC 2616 sec 19.6 and RFC 1945 sec 6 for details.
# See RFC 2616 sec 19.6 and RFC 1945 sec 6 for details.
...
@@ -496,9 +496,10 @@ class HTTPResponse(io.RawIOBase):
...
@@ -496,9 +496,10 @@ class HTTPResponse(io.RawIOBase):
return
b
""
return
b
""
if
amt
is
not
None
:
if
amt
is
not
None
:
# Amount is given, so call base class version
# Amount is given, implement using readinto
# (which is implemented in terms of self.readinto)
b
=
bytearray
(
amt
)
return
super
(
HTTPResponse
,
self
)
.
read
(
amt
)
n
=
self
.
readinto
(
b
)
return
memoryview
(
b
)[:
n
]
.
tobytes
()
else
:
else
:
# Amount is not given (unbounded read) so we must check self.length
# Amount is not given (unbounded read) so we must check self.length
# and self.chunked
# and self.chunked
...
@@ -578,71 +579,67 @@ class HTTPResponse(io.RawIOBase):
...
@@ -578,71 +579,67 @@ class HTTPResponse(io.RawIOBase):
if
line
in
(
b
'
\r\n
'
,
b
'
\n
'
,
b
''
):
if
line
in
(
b
'
\r\n
'
,
b
'
\n
'
,
b
''
):
break
break
def
_get_chunk_left
(
self
):
# return self.chunk_left, reading a new chunk if necessary.
# chunk_left == 0: at the end of the current chunk, need to close it
# chunk_left == None: No current chunk, should read next.
# This function returns non-zero or None if the last chunk has
# been read.
chunk_left
=
self
.
chunk_left
if
not
chunk_left
:
# Can be 0 or None
if
chunk_left
is
not
None
:
# We are at the end of chunk. dicard chunk end
self
.
_safe_read
(
2
)
# toss the CRLF at the end of the chunk
try
:
chunk_left
=
self
.
_read_next_chunk_size
()
except
ValueError
:
raise
IncompleteRead
(
b
''
)
if
chunk_left
==
0
:
# last chunk: 1*("0") [ chunk-extension ] CRLF
self
.
_read_and_discard_trailer
()
# we read everything; close the "file"
self
.
_close_conn
()
chunk_left
=
None
self
.
chunk_left
=
chunk_left
return
chunk_left
def
_readall_chunked
(
self
):
def
_readall_chunked
(
self
):
assert
self
.
chunked
!=
_UNKNOWN
assert
self
.
chunked
!=
_UNKNOWN
chunk_left
=
self
.
chunk_left
value
=
[]
value
=
[]
while
True
:
try
:
if
chunk_left
is
None
:
while
True
:
try
:
chunk_left
=
self
.
_get_chunk_left
()
chunk_left
=
self
.
_read_next_chunk_size
()
if
chunk_left
is
None
:
if
chunk_left
==
0
:
break
break
value
.
append
(
self
.
_safe_read
(
chunk_left
))
except
ValueError
:
self
.
chunk_left
=
0
raise
IncompleteRead
(
b
''
.
join
(
value
))
return
b
''
.
join
(
value
)
value
.
append
(
self
.
_safe_read
(
chunk_left
))
except
IncompleteRead
:
raise
IncompleteRead
(
b
''
.
join
(
value
))
# we read the whole chunk, get another
self
.
_safe_read
(
2
)
# toss the CRLF at the end of the chunk
chunk_left
=
None
self
.
_read_and_discard_trailer
()
# we read everything; close the "file"
self
.
_close_conn
()
return
b
''
.
join
(
value
)
def
_readinto_chunked
(
self
,
b
):
def
_readinto_chunked
(
self
,
b
):
assert
self
.
chunked
!=
_UNKNOWN
assert
self
.
chunked
!=
_UNKNOWN
chunk_left
=
self
.
chunk_left
total_bytes
=
0
total_bytes
=
0
mvb
=
memoryview
(
b
)
mvb
=
memoryview
(
b
)
while
True
:
try
:
if
chunk_left
is
None
:
while
True
:
try
:
chunk_left
=
self
.
_get_chunk_left
()
chunk_left
=
self
.
_read_next_chunk_size
()
if
chunk_left
is
None
:
if
chunk_left
==
0
:
return
total_bytes
break
except
ValueError
:
if
len
(
mvb
)
<=
chunk_left
:
raise
IncompleteRead
(
bytes
(
b
[
0
:
total_bytes
]))
n
=
self
.
_safe_readinto
(
mvb
)
self
.
chunk_left
=
chunk_left
-
n
if
len
(
mvb
)
<
chunk_left
:
return
total_bytes
+
n
n
=
self
.
_safe_readinto
(
mvb
)
self
.
chunk_left
=
chunk_left
-
n
temp_mvb
=
mvb
[:
chunk_left
]
return
total_bytes
+
n
elif
len
(
mvb
)
==
chunk_left
:
n
=
self
.
_safe_readinto
(
mvb
)
self
.
_safe_read
(
2
)
# toss the CRLF at the end of the chunk
self
.
chunk_left
=
None
return
total_bytes
+
n
else
:
temp_mvb
=
mvb
[
0
:
chunk_left
]
n
=
self
.
_safe_readinto
(
temp_mvb
)
n
=
self
.
_safe_readinto
(
temp_mvb
)
mvb
=
mvb
[
n
:]
mvb
=
mvb
[
n
:]
total_bytes
+=
n
total_bytes
+=
n
self
.
chunk_left
=
0
# we read the whole chunk, get another
except
IncompleteRead
:
self
.
_safe_read
(
2
)
# toss the CRLF at the end of the chunk
raise
IncompleteRead
(
bytes
(
b
[
0
:
total_bytes
]))
chunk_left
=
None
self
.
_read_and_discard_trailer
()
# we read everything; close the "file"
self
.
_close_conn
()
return
total_bytes
def
_safe_read
(
self
,
amt
):
def
_safe_read
(
self
,
amt
):
"""Read the number of bytes requested, compensating for partial reads.
"""Read the number of bytes requested, compensating for partial reads.
...
@@ -683,6 +680,73 @@ class HTTPResponse(io.RawIOBase):
...
@@ -683,6 +680,73 @@ class HTTPResponse(io.RawIOBase):
total_bytes
+=
n
total_bytes
+=
n
return
total_bytes
return
total_bytes
def
read1
(
self
,
n
=-
1
):
"""Read with at most one underlying system call. If at least one
byte is buffered, return that instead.
"""
if
self
.
fp
is
None
or
self
.
_method
==
"HEAD"
:
return
b
""
if
self
.
chunked
:
return
self
.
_read1_chunked
(
n
)
try
:
result
=
self
.
fp
.
read1
(
n
)
except
ValueError
:
if
n
>=
0
:
raise
# some implementations, like BufferedReader, don't support -1
# Read an arbitrarily selected largeish chunk.
result
=
self
.
fp
.
read1
(
16
*
1024
)
if
not
result
and
n
:
self
.
_close_conn
()
return
result
def
peek
(
self
,
n
=-
1
):
# Having this enables IOBase.readline() to read more than one
# byte at a time
if
self
.
fp
is
None
or
self
.
_method
==
"HEAD"
:
return
b
""
if
self
.
chunked
:
return
self
.
_peek_chunked
(
n
)
return
self
.
fp
.
peek
(
n
)
def
readline
(
self
,
limit
=-
1
):
if
self
.
fp
is
None
or
self
.
_method
==
"HEAD"
:
return
b
""
if
self
.
chunked
:
# Fallback to IOBase readline which uses peek() and read()
return
super
()
.
readline
(
limit
)
result
=
self
.
fp
.
readline
(
limit
)
if
not
result
and
limit
:
self
.
_close_conn
()
return
result
def
_read1_chunked
(
self
,
n
):
# Strictly speaking, _get_chunk_left() may cause more than one read,
# but that is ok, since that is to satisfy the chunked protocol.
chunk_left
=
self
.
_get_chunk_left
()
if
chunk_left
is
None
or
n
==
0
:
return
b
''
if
not
(
0
<=
n
<=
chunk_left
):
n
=
chunk_left
# if n is negative or larger than chunk_left
read
=
self
.
fp
.
read1
(
n
)
self
.
chunk_left
-=
len
(
read
)
if
not
read
:
raise
IncompleteRead
(
b
""
)
return
read
def
_peek_chunked
(
self
,
n
):
# Strictly speaking, _get_chunk_left() may cause more than one read,
# but that is ok, since that is to satisfy the chunked protocol.
try
:
chunk_left
=
self
.
_get_chunk_left
()
except
IncompleteRead
:
return
b
''
# peek doesn't worry about protocol
if
chunk_left
is
None
:
return
b
''
# eof
# peek is allowed to return more than requested. Just request the
# entire chunk, and truncate what we get.
return
self
.
fp
.
peek
(
chunk_left
)[:
chunk_left
]
def
fileno
(
self
):
def
fileno
(
self
):
return
self
.
fp
.
fileno
()
return
self
.
fp
.
fileno
()
...
...
Lib/test/test_httplib.py
Dosyayı görüntüle @
8e5d0caf
This diff is collapsed.
Click to expand it.
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