Skip to content

Commit 5605138

Browse files
committed
Update lib-python to latest 2.7 revision 82552:a8047d1376d5
1 parent d707a58 commit 5605138

294 files changed

Lines changed: 8611 additions & 2580 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

lib-python/2.7/BaseHTTPServer.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -447,13 +447,13 @@ def log_message(self, format, *args):
447447
specified as subsequent arguments (it's just like
448448
printf!).
449449
450-
The client host and current date/time are prefixed to
451-
every message.
450+
The client ip address and current date/time are prefixed to every
451+
message.
452452
453453
"""
454454

455455
sys.stderr.write("%s - - [%s] %s\n" %
456-
(self.address_string(),
456+
(self.client_address[0],
457457
self.log_date_time_string(),
458458
format%args))
459459

lib-python/2.7/CGIHTTPServer.py

Lines changed: 29 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -84,9 +84,11 @@ def is_cgi(self):
8484
path begins with one of the strings in self.cgi_directories
8585
(and the next character is a '/' or the end of the string).
8686
"""
87-
splitpath = _url_collapse_path_split(self.path)
88-
if splitpath[0] in self.cgi_directories:
89-
self.cgi_info = splitpath
87+
collapsed_path = _url_collapse_path(self.path)
88+
dir_sep = collapsed_path.find('/', 1)
89+
head, tail = collapsed_path[:dir_sep], collapsed_path[dir_sep+1:]
90+
if head in self.cgi_directories:
91+
self.cgi_info = head, tail
9092
return True
9193
return False
9294

@@ -298,51 +300,46 @@ def run_cgi(self):
298300
self.log_message("CGI script exited OK")
299301

300302

301-
# TODO(gregory.p.smith): Move this into an appropriate library.
302-
def _url_collapse_path_split(path):
303+
def _url_collapse_path(path):
303304
"""
304305
Given a URL path, remove extra '/'s and '.' path elements and collapse
305-
any '..' references.
306+
any '..' references and returns a colllapsed path.
306307
307308
Implements something akin to RFC-2396 5.2 step 6 to parse relative paths.
309+
The utility of this function is limited to is_cgi method and helps
310+
preventing some security attacks.
308311
309312
Returns: A tuple of (head, tail) where tail is everything after the final /
310313
and head is everything before it. Head will always start with a '/' and,
311314
if it contains anything else, never have a trailing '/'.
312315
313316
Raises: IndexError if too many '..' occur within the path.
317+
314318
"""
315319
# Similar to os.path.split(os.path.normpath(path)) but specific to URL
316320
# path semantics rather than local operating system semantics.
317-
path_parts = []
318-
for part in path.split('/'):
319-
if part == '.':
320-
path_parts.append('')
321-
else:
322-
path_parts.append(part)
323-
# Filter out blank non trailing parts before consuming the '..'.
324-
path_parts = [part for part in path_parts[:-1] if part] + path_parts[-1:]
325-
if path_parts:
326-
# Special case for CGI's for PATH_INFO
327-
if path.startswith('/cgi-bin') or path.startswith('/htbin'):
328-
tail_part = []
329-
while path_parts[-1] not in ('cgi-bin','htbin'):
330-
tail_part.insert(0,path_parts.pop())
331-
tail_part = "/".join(tail_part)
332-
else:
333-
tail_part = path_parts.pop()
334-
else:
335-
tail_part = ''
321+
path_parts = path.split('/')
336322
head_parts = []
337-
for part in path_parts:
323+
for part in path_parts[:-1]:
338324
if part == '..':
339-
head_parts.pop()
340-
else:
341-
head_parts.append(part)
342-
if tail_part and tail_part == '..':
343-
head_parts.pop()
325+
head_parts.pop() # IndexError if more '..' than prior parts
326+
elif part and part != '.':
327+
head_parts.append( part )
328+
if path_parts:
329+
tail_part = path_parts.pop()
330+
if tail_part:
331+
if tail_part == '..':
332+
head_parts.pop()
333+
tail_part = ''
334+
elif tail_part == '.':
335+
tail_part = ''
336+
else:
344337
tail_part = ''
345-
return ('/' + '/'.join(head_parts), tail_part)
338+
339+
splitpath = ('/' + '/'.join(head_parts), tail_part)
340+
collapsed_path = "/".join(splitpath)
341+
342+
return collapsed_path
346343

347344

348345
nobody = None

lib-python/2.7/Cookie.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -390,7 +390,7 @@ def _getdate(future=0, weekdayname=_weekdayname, monthname=_monthname):
390390
from time import gmtime, time
391391
now = time()
392392
year, month, day, hh, mm, ss, wd, y, z = gmtime(now + future)
393-
return "%s, %02d-%3s-%4d %02d:%02d:%02d GMT" % \
393+
return "%s, %02d %3s %4d %02d:%02d:%02d GMT" % \
394394
(weekdayname[wd], day, monthname[month], year, hh, mm, ss)
395395

396396

@@ -539,7 +539,7 @@ def OutputString(self, attrs=None):
539539
r"(?P<val>" # Start of group 'val'
540540
r'"(?:[^\\"]|\\.)*"' # Any doublequoted string
541541
r"|" # or
542-
r"\w{3},\s[\w\d-]{9,11}\s[\d:]{8}\sGMT" # Special case for "expires" attr
542+
r"\w{3},\s[\s\w\d-]{9,11}\s[\d:]{8}\sGMT" # Special case for "expires" attr
543543
r"|" # or
544544
""+ _LegalCharsPatt +"*" # Any word or empty string
545545
r")" # End of group 'val'

lib-python/2.7/HTMLParser.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,13 @@
2222
starttagopen = re.compile('<[a-zA-Z]')
2323
piclose = re.compile('>')
2424
commentclose = re.compile(r'--\s*>')
25-
tagfind = re.compile('[a-zA-Z][-.a-zA-Z0-9:_]*')
25+
tagfind = re.compile('([a-zA-Z][-.a-zA-Z0-9:_]*)(?:\s|/(?!>))*')
2626
# see http://www.w3.org/TR/html5/tokenization.html#tag-open-state
2727
# and http://www.w3.org/TR/html5/tokenization.html#tag-name-state
2828
tagfind_tolerant = re.compile('[a-zA-Z][^\t\n\r\f />\x00]*')
2929

3030
attrfind = re.compile(
31-
r'[\s/]*((?<=[\'"\s/])[^\s/>][^\s/=>]*)(\s*=+\s*'
31+
r'((?<=[\'"\s/])[^\s/>][^\s/=>]*)(\s*=+\s*'
3232
r'(\'[^\']*\'|"[^"]*"|(?![\'"])[^>\s]*))?(?:\s|/(?!>))*')
3333

3434
locatestarttagend = re.compile(r"""
@@ -289,7 +289,7 @@ def parse_starttag(self, i):
289289
match = tagfind.match(rawdata, i+1)
290290
assert match, 'unexpected call to parse_starttag()'
291291
k = match.end()
292-
self.lasttag = tag = rawdata[i+1:k].lower()
292+
self.lasttag = tag = match.group(1).lower()
293293

294294
while k < endpos:
295295
m = attrfind.match(rawdata, k)

lib-python/2.7/SocketServer.py

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@ class will essentially render the service "deaf" while one request is
133133
import select
134134
import sys
135135
import os
136+
import errno
136137
try:
137138
import threading
138139
except ImportError:
@@ -147,6 +148,15 @@ class will essentially render the service "deaf" while one request is
147148
"ThreadingUnixStreamServer",
148149
"ThreadingUnixDatagramServer"])
149150

151+
def _eintr_retry(func, *args):
152+
"""restart a system call interrupted by EINTR"""
153+
while True:
154+
try:
155+
return func(*args)
156+
except (OSError, select.error) as e:
157+
if e.args[0] != errno.EINTR:
158+
raise
159+
150160
class BaseServer:
151161

152162
"""Base class for server classes.
@@ -222,7 +232,8 @@ def serve_forever(self, poll_interval=0.5):
222232
# connecting to the socket to wake this up instead of
223233
# polling. Polling reduces our responsiveness to a
224234
# shutdown request and wastes cpu at all other times.
225-
r, w, e = select.select([self], [], [], poll_interval)
235+
r, w, e = _eintr_retry(select.select, [self], [], [],
236+
poll_interval)
226237
if self in r:
227238
self._handle_request_noblock()
228239
finally:
@@ -262,7 +273,7 @@ def handle_request(self):
262273
timeout = self.timeout
263274
elif self.timeout is not None:
264275
timeout = min(timeout, self.timeout)
265-
fd_sets = select.select([self], [], [], timeout)
276+
fd_sets = _eintr_retry(select.select, [self], [], [], timeout)
266277
if not fd_sets[0]:
267278
self.handle_timeout()
268279
return
@@ -690,7 +701,12 @@ def setup(self):
690701

691702
def finish(self):
692703
if not self.wfile.closed:
693-
self.wfile.flush()
704+
try:
705+
self.wfile.flush()
706+
except socket.error:
707+
# An final socket error may have occurred here, such as
708+
# the local error ECONNABORTED.
709+
pass
694710
self.wfile.close()
695711
self.rfile.close()
696712

lib-python/2.7/StringIO.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ def readline(self, length=None):
158158
newpos = self.len
159159
else:
160160
newpos = i+1
161-
if length is not None and length > 0:
161+
if length is not None and length >= 0:
162162
if self.pos + length < newpos:
163163
newpos = self.pos + length
164164
r = self.buf[self.pos:newpos]

lib-python/2.7/_LWPCookieJar.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ def lwp_cookie_str(cookie):
4848

4949
class LWPCookieJar(FileCookieJar):
5050
"""
51-
The LWPCookieJar saves a sequence of"Set-Cookie3" lines.
51+
The LWPCookieJar saves a sequence of "Set-Cookie3" lines.
5252
"Set-Cookie3" is the format used by the libwww-perl libary, not known
5353
to be compatible with any browser, but which is easy to read and
5454
doesn't lose information about RFC 2965 cookies.
@@ -60,7 +60,7 @@ class LWPCookieJar(FileCookieJar):
6060
"""
6161

6262
def as_lwp_str(self, ignore_discard=True, ignore_expires=True):
63-
"""Return cookies as a string of "\n"-separated "Set-Cookie3" headers.
63+
"""Return cookies as a string of "\\n"-separated "Set-Cookie3" headers.
6464
6565
ignore_discard and ignore_expires: see docstring for FileCookieJar.save
6666

lib-python/2.7/__future__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ def __repr__(self):
112112
CO_FUTURE_DIVISION)
113113

114114
absolute_import = _Feature((2, 5, 0, "alpha", 1),
115-
(2, 7, 0, "alpha", 0),
115+
(3, 0, 0, "alpha", 0),
116116
CO_FUTURE_ABSOLUTE_IMPORT)
117117

118118
with_statement = _Feature((2, 5, 0, "alpha", 1),

lib-python/2.7/_pyio.py

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -340,8 +340,10 @@ def close(self):
340340
This method has no effect if the file is already closed.
341341
"""
342342
if not self.__closed:
343-
self.flush()
344-
self.__closed = True
343+
try:
344+
self.flush()
345+
finally:
346+
self.__closed = True
345347

346348
def __del__(self):
347349
"""Destructor. Calls close()."""
@@ -883,12 +885,18 @@ def truncate(self, pos=None):
883885
return pos
884886

885887
def readable(self):
888+
if self.closed:
889+
raise ValueError("I/O operation on closed file.")
886890
return True
887891

888892
def writable(self):
893+
if self.closed:
894+
raise ValueError("I/O operation on closed file.")
889895
return True
890896

891897
def seekable(self):
898+
if self.closed:
899+
raise ValueError("I/O operation on closed file.")
892900
return True
893901

894902

@@ -1546,6 +1554,8 @@ def buffer(self):
15461554
return self._buffer
15471555

15481556
def seekable(self):
1557+
if self.closed:
1558+
raise ValueError("I/O operation on closed file.")
15491559
return self._seekable
15501560

15511561
def readable(self):
@@ -1560,8 +1570,10 @@ def flush(self):
15601570

15611571
def close(self):
15621572
if self.buffer is not None and not self.closed:
1563-
self.flush()
1564-
self.buffer.close()
1573+
try:
1574+
self.flush()
1575+
finally:
1576+
self.buffer.close()
15651577

15661578
@property
15671579
def closed(self):

lib-python/2.7/_strptime.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -326,7 +326,8 @@ def _strptime(data_string, format="%a %b %d %H:%M:%S %Y"):
326326
if len(data_string) != found.end():
327327
raise ValueError("unconverted data remains: %s" %
328328
data_string[found.end():])
329-
year = 1900
329+
330+
year = None
330331
month = day = 1
331332
hour = minute = second = fraction = 0
332333
tz = -1
@@ -425,6 +426,12 @@ def _strptime(data_string, format="%a %b %d %H:%M:%S %Y"):
425426
else:
426427
tz = value
427428
break
429+
leap_year_fix = False
430+
if year is None and month == 2 and day == 29:
431+
year = 1904 # 1904 is first leap year of 20th century
432+
leap_year_fix = True
433+
elif year is None:
434+
year = 1900
428435
# If we know the week of the year and what day of that week, we can figure
429436
# out the Julian day of the year.
430437
if julian == -1 and week_of_year != -1 and weekday != -1:
@@ -446,6 +453,12 @@ def _strptime(data_string, format="%a %b %d %H:%M:%S %Y"):
446453
day = datetime_result.day
447454
if weekday == -1:
448455
weekday = datetime_date(year, month, day).weekday()
456+
if leap_year_fix:
457+
# the caller didn't supply a year but asked for Feb 29th. We couldn't
458+
# use the default of 1900 for computations. We set it back to ensure
459+
# that February 29th is smaller than March 1st.
460+
year = 1900
461+
449462
return (time.struct_time((year, month, day,
450463
hour, minute, second,
451464
weekday, julian, tz)), fraction)

0 commit comments

Comments
 (0)