This commit is contained in:
Raymond Hettinger 2012-04-29 14:57:05 -07:00
commit a6df2ee7d0
7 changed files with 93 additions and 20 deletions

View File

@ -22,7 +22,7 @@ Public functions: Internaldate2tuple
__version__ = "2.58" __version__ = "2.58"
import binascii, errno, random, re, socket, subprocess, sys, time import binascii, errno, random, re, socket, subprocess, sys, time, calendar
try: try:
import ssl import ssl
@ -1347,19 +1347,9 @@ def Internaldate2tuple(resp):
zone = -zone zone = -zone
tt = (year, mon, day, hour, min, sec, -1, -1, -1) tt = (year, mon, day, hour, min, sec, -1, -1, -1)
utc = calendar.timegm(tt) - zone
utc = time.mktime(tt) return time.localtime(utc)
# Following is necessary because the time module has no 'mkgmtime'.
# 'mktime' assumes arg in local timezone, so adds timezone/altzone.
lt = time.localtime(utc)
if time.daylight and lt[-1]:
zone = zone + time.altzone
else:
zone = zone + time.timezone
return time.localtime(utc - zone)

View File

@ -57,7 +57,7 @@ __all__ = [
"get_attribute", "swap_item", "swap_attr", "requires_IEEE_754", "get_attribute", "swap_item", "swap_attr", "requires_IEEE_754",
"TestHandler", "Matcher", "can_symlink", "skip_unless_symlink", "TestHandler", "Matcher", "can_symlink", "skip_unless_symlink",
"import_fresh_module", "requires_zlib", "PIPE_MAX_SIZE", "failfast", "import_fresh_module", "requires_zlib", "PIPE_MAX_SIZE", "failfast",
"anticipate_failure" "anticipate_failure", "run_with_tz"
] ]
class Error(Exception): class Error(Exception):
@ -1099,6 +1099,35 @@ def run_with_locale(catstr, *locales):
return inner return inner
return decorator return decorator
#=======================================================================
# Decorator for running a function in a specific timezone, correctly
# resetting it afterwards.
def run_with_tz(tz):
def decorator(func):
def inner(*args, **kwds):
if 'TZ' in os.environ:
orig_tz = os.environ['TZ']
else:
orig_tz = None
os.environ['TZ'] = tz
time.tzset()
# now run the function, resetting the tz on exceptions
try:
return func(*args, **kwds)
finally:
if orig_tz == None:
del os.environ['TZ']
else:
os.environ['TZ'] = orig_tz
time.tzset()
inner.__name__ = func.__name__
inner.__doc__ = func.__doc__
return inner
return decorator
#======================================================================= #=======================================================================
# Big-memory-test support. Separate from 'resources' because memory use # Big-memory-test support. Separate from 'resources' because memory use
# should be configurable. # should be configurable.

View File

@ -11,7 +11,7 @@ import socketserver
import time import time
import calendar import calendar
from test.support import reap_threads, verbose, transient_internet from test.support import reap_threads, verbose, transient_internet, run_with_tz
import unittest import unittest
try: try:
@ -36,6 +36,13 @@ class TestImaplib(unittest.TestCase):
b'25 (INTERNALDATE "31-Dec-1999 12:30:00 -1130")') b'25 (INTERNALDATE "31-Dec-1999 12:30:00 -1130")')
self.assertEqual(time.mktime(tt), t0) self.assertEqual(time.mktime(tt), t0)
@run_with_tz('MST+07MDT,M4.1.0,M10.5.0')
def test_Internaldate2tuple_issue10941(self):
self.assertNotEqual(imaplib.Internaldate2tuple(
b'25 (INTERNALDATE "02-Apr-2000 02:30:00 +0000")'),
imaplib.Internaldate2tuple(
b'25 (INTERNALDATE "02-Apr-2000 03:30:00 +0000")'))
def test_that_Time2Internaldate_returns_a_result(self): def test_that_Time2Internaldate_returns_a_result(self):
# We can check only that it successfully produces a result, # We can check only that it successfully produces a result,
# not the correctness of the result itself, since the result # not the correctness of the result itself, since the result

View File

@ -61,6 +61,16 @@ class RoundtripLegalSyntaxTestCase(unittest.TestCase):
" if (yield):\n" " if (yield):\n"
" yield x\n") " yield x\n")
def test_nonlocal_statement(self):
self.check_suite("def f():\n"
" x = 0\n"
" def g():\n"
" nonlocal x\n")
self.check_suite("def f():\n"
" x = y = 0\n"
" def g():\n"
" nonlocal x, y\n")
def test_expressions(self): def test_expressions(self):
self.check_expr("foo(1)") self.check_expr("foo(1)")
self.check_expr("[1, 2, 3]") self.check_expr("[1, 2, 3]")

View File

@ -770,6 +770,7 @@ Alexandre Parenteau
Dan Parisien Dan Parisien
Harri Pasanen Harri Pasanen
Gaël Pasgrimaud Gaël Pasgrimaud
Joe Peterson
Randy Pausch Randy Pausch
Samuele Pedroni Samuele Pedroni
Marcel van der Peijl Marcel van der Peijl

View File

@ -84,6 +84,11 @@ Core and Builtins
Library Library
------- -------
- Issue #14696: Fix parser module to understand 'nonlocal' declarations.
- Issue #10941: Fix imaplib.Internaldate2tuple to produce correct result near
the DST transition. Patch by Joe Peterson.
- Issue #9154: Fix parser module to understand function annotations. - Issue #9154: Fix parser module to understand function annotations.
- Issue #6085: In http.server.py SimpleHTTPServer.address_string returns the - Issue #6085: In http.server.py SimpleHTTPServer.address_string returns the

View File

@ -956,7 +956,8 @@ VALIDATER(del_stmt);
VALIDATER(return_stmt); VALIDATER(raise_stmt); VALIDATER(return_stmt); VALIDATER(raise_stmt);
VALIDATER(import_stmt); VALIDATER(import_stmt); VALIDATER(import_stmt); VALIDATER(import_stmt);
VALIDATER(import_name); VALIDATER(yield_stmt); VALIDATER(import_name); VALIDATER(yield_stmt);
VALIDATER(global_stmt); VALIDATER(assert_stmt); VALIDATER(global_stmt); VALIDATER(nonlocal_stmt);
VALIDATER(assert_stmt);
VALIDATER(compound_stmt); VALIDATER(test_or_star_expr); VALIDATER(compound_stmt); VALIDATER(test_or_star_expr);
VALIDATER(while); VALIDATER(for); VALIDATER(while); VALIDATER(for);
VALIDATER(try); VALIDATER(except_clause); VALIDATER(try); VALIDATER(except_clause);
@ -1480,6 +1481,7 @@ validate_small_stmt(node *tree)
|| (ntype == flow_stmt) || (ntype == flow_stmt)
|| (ntype == import_stmt) || (ntype == import_stmt)
|| (ntype == global_stmt) || (ntype == global_stmt)
|| (ntype == nonlocal_stmt)
|| (ntype == assert_stmt)) || (ntype == assert_stmt))
res = validate_node(CHILD(tree, 0)); res = validate_node(CHILD(tree, 0));
else { else {
@ -1864,8 +1866,10 @@ validate_import_stmt(node *tree)
} }
/* global_stmt:
*
* 'global' NAME (',' NAME)*
*/
static int static int
validate_global_stmt(node *tree) validate_global_stmt(node *tree)
{ {
@ -1887,6 +1891,30 @@ validate_global_stmt(node *tree)
return (res); return (res);
} }
/* nonlocal_stmt:
*
* 'nonlocal' NAME (',' NAME)*
*/
static int
validate_nonlocal_stmt(node *tree)
{
int j;
int nch = NCH(tree);
int res = (validate_ntype(tree, nonlocal_stmt)
&& is_even(nch) && (nch >= 2));
if (!res && !PyErr_Occurred())
err_string("illegal nonlocal statement");
if (res)
res = (validate_name(CHILD(tree, 0), "nonlocal")
&& validate_ntype(CHILD(tree, 1), NAME));
for (j = 2; res && (j < nch); j += 2)
res = (validate_comma(CHILD(tree, j))
&& validate_ntype(CHILD(tree, j + 1), NAME));
return res;
}
/* assert_stmt: /* assert_stmt:
* *
@ -2951,8 +2979,8 @@ validate_node(node *tree)
break; break;
case small_stmt: case small_stmt:
/* /*
* expr_stmt | del_stmt | pass_stmt | flow_stmt * expr_stmt | del_stmt | pass_stmt | flow_stmt |
* | import_stmt | global_stmt | assert_stmt * import_stmt | global_stmt | nonlocal_stmt | assert_stmt
*/ */
res = validate_small_stmt(tree); res = validate_small_stmt(tree);
break; break;
@ -3019,6 +3047,9 @@ validate_node(node *tree)
case global_stmt: case global_stmt:
res = validate_global_stmt(tree); res = validate_global_stmt(tree);
break; break;
case nonlocal_stmt:
res = validate_nonlocal_stmt(tree);
break;
case assert_stmt: case assert_stmt:
res = validate_assert_stmt(tree); res = validate_assert_stmt(tree);
break; break;