summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Demo/embed/Makefile2
-rw-r--r--Demo/embed/demo.c13
-rw-r--r--Demo/embed/loop.c2
-rw-r--r--Lib/http/cookies.py28
-rw-r--r--Lib/posixpath.py3
-rw-r--r--Lib/test/test_http_cookies.py30
-rw-r--r--Lib/timeit.py3
-rw-r--r--Lib/trace.py13
-rw-r--r--Misc/NEWS7
9 files changed, 81 insertions, 20 deletions
diff --git a/Demo/embed/Makefile b/Demo/embed/Makefile
index 857b5e5..711b95b 100644
--- a/Demo/embed/Makefile
+++ b/Demo/embed/Makefile
@@ -22,7 +22,7 @@ CPPFLAGS= $(INCLUDES)
LIBPYTHON= $(blddir)/libpython$(VERSION).a
# XXX edit LIBS (in particular) to match $(blddir)/Modules/Makefile
-LIBS= -lnsl -ldl -lreadline -ltermcap -lieee -lpthread -lutil
+LIBS= -lnsl -ldl -lreadline -lieee -lpthread -lutil
LDFLAGS= -Xlinker -export-dynamic
SYSLIBS= -lm
MODLIBS=
diff --git a/Demo/embed/demo.c b/Demo/embed/demo.c
index 22bfaff..99d39ca 100644
--- a/Demo/embed/demo.c
+++ b/Demo/embed/demo.c
@@ -22,8 +22,17 @@ main(int argc, char **argv)
/* Define sys.argv. It is up to the application if you
want this; you can also let it undefined (since the Python
code is generally not a main program it has no business
- touching sys.argv...) */
- PySys_SetArgv(2, args);
+ touching sys.argv...)
+
+ If the third argument is true, sys.path is modified to include
+ either the directory containing the script named by argv[0], or
+ the current working directory. This can be risky; if you run
+ an application embedding Python in a directory controlled by
+ someone else, attackers could put a Trojan-horse module in the
+ directory (say, a file named os.py) that your application would
+ then import and run.
+ */
+ PySys_SetArgvEx(2, args, 0);
/* Do some application specific code */
printf("Hello, brave new world\n\n");
diff --git a/Demo/embed/loop.c b/Demo/embed/loop.c
index 2f7fe62..4a341fd 100644
--- a/Demo/embed/loop.c
+++ b/Demo/embed/loop.c
@@ -19,7 +19,7 @@ main(int argc, char **argv)
count = atoi(argv[2]);
}
- Py_SetProgramName(argv[0]);
+ Py_SetProgramName(L"loop");
/* uncomment this if you don't want to load site.py */
/* Py_NoSiteFlag = 1; */
diff --git a/Lib/http/cookies.py b/Lib/http/cookies.py
index 9cb80b9..e584396 100644
--- a/Lib/http/cookies.py
+++ b/Lib/http/cookies.py
@@ -439,19 +439,21 @@ class Morsel(dict):
#
_LegalCharsPatt = r"[\w\d!#%&'~_`><@,:/\$\*\+\-\.\^\|\)\(\?\}\{\=]"
-_CookiePattern = re.compile(
- r"(?x)" # This is a Verbose pattern
- r"(?P<key>" # Start of group 'key'
- ""+ _LegalCharsPatt +"+?" # Any word of at least one letter, nongreedy
- r")" # End of group 'key'
- r"\s*=\s*" # Equal Sign
- r"(?P<val>" # Start of group 'val'
- r'"(?:[^\\"]|\\.)*"' # Any doublequoted string
- r"|" # or
- ""+ _LegalCharsPatt +"*" # Any word or empty string
- r")" # End of group 'val'
- r"\s*;?" # Probably ending in a semi-colon
- , re.ASCII) # May be removed if safe.
+_CookiePattern = re.compile(r"""
+ (?x) # This is a verbose pattern
+ (?P<key> # Start of group 'key'
+ """ + _LegalCharsPatt + r"""+? # Any word of at least one letter
+ ) # End of group 'key'
+ \s*=\s* # Equal Sign
+ (?P<val> # Start of group 'val'
+ "(?:[^\\"]|\\.)*" # Any doublequoted string
+ | # or
+ \w{3},\s[\w\d-]{9,11}\s[\d:]{8}\sGMT # Special case for "expires" attr
+ | # or
+ """ + _LegalCharsPatt + r"""* # Any word or empty string
+ ) # End of group 'val'
+ \s*;? # Probably ending in a semi-colon
+ """, re.ASCII) # May be removed if safe.
# At long last, here is the cookie class.
diff --git a/Lib/posixpath.py b/Lib/posixpath.py
index aace2b2..d317ceb 100644
--- a/Lib/posixpath.py
+++ b/Lib/posixpath.py
@@ -197,6 +197,9 @@ def samestat(s1, s2):
def ismount(path):
"""Test whether a path is a mount point"""
+ if islink(path):
+ # A symlink can never be a mount point
+ return False
try:
s1 = os.lstat(path)
if isinstance(path, bytes):
diff --git a/Lib/test/test_http_cookies.py b/Lib/test/test_http_cookies.py
index 158dd63..99133f7 100644
--- a/Lib/test/test_http_cookies.py
+++ b/Lib/test/test_http_cookies.py
@@ -65,6 +65,36 @@ class CookieTests(unittest.TestCase):
</script>
""")
+ def test_special_attrs(self):
+ # 'expires'
+ C = cookies.SimpleCookie('Customer="WILE_E_COYOTE"')
+ C['Customer']['expires'] = 0
+ # can't test exact output, it always depends on current date/time
+ self.assertTrue(C.output().endswith('GMT'))
+
+ # loading 'expires'
+ C = cookies.SimpleCookie()
+ C.load('Customer="W"; expires=Wed, 01-Jan-2010 00:00:00 GMT')
+ self.assertEqual(C['Customer']['expires'],
+ 'Wed, 01-Jan-2010 00:00:00 GMT')
+ C = cookies.SimpleCookie()
+ C.load('Customer="W"; expires=Wed, 01-Jan-98 00:00:00 GMT')
+ self.assertEqual(C['Customer']['expires'],
+ 'Wed, 01-Jan-98 00:00:00 GMT')
+
+ # 'max-age'
+ C = cookies.SimpleCookie('Customer="WILE_E_COYOTE"')
+ C['Customer']['max-age'] = 10
+ self.assertEqual(C.output(),
+ 'Set-Cookie: Customer="WILE_E_COYOTE"; Max-Age=10')
+
+ # others
+ C = cookies.SimpleCookie('Customer="WILE_E_COYOTE"')
+ C['Customer']['secure'] = True
+ C['Customer']['httponly'] = True
+ self.assertEqual(C.output(),
+ 'Set-Cookie: Customer="WILE_E_COYOTE"; httponly; secure')
+
def test_quoted_meta(self):
# Try cookie with quoted meta-data
C = cookies.SimpleCookie()
diff --git a/Lib/timeit.py b/Lib/timeit.py
index 7b9b72c..c3f6753 100644
--- a/Lib/timeit.py
+++ b/Lib/timeit.py
@@ -9,7 +9,7 @@ the Python Cookbook, published by O'Reilly.
Library usage: see the Timer class.
Command line usage:
- python timeit.py [-n N] [-r N] [-s S] [-t] [-c] [-h] [statement]
+ python timeit.py [-n N] [-r N] [-s S] [-t] [-c] [-h] [--] [statement]
Options:
-n/--number N: how many times to execute 'statement' (default: see below)
@@ -19,6 +19,7 @@ Options:
-c/--clock: use time.clock() (default on Windows)
-v/--verbose: print raw timing results; repeat for more digits precision
-h/--help: print this usage message and exit
+ --: separate options from statement, use when statement starts with -
statement: statement to be timed (default 'pass')
A multi-line statement may be given by specifying each line as a
diff --git a/Lib/trace.py b/Lib/trace.py
index 49ad7a8..f408705 100644
--- a/Lib/trace.py
+++ b/Lib/trace.py
@@ -192,11 +192,13 @@ def fullmodname(path):
base = path[len(longest) + 1:]
else:
base = path
+ # the drive letter is never part of the module name
+ drive, base = os.path.splitdrive(base)
base = base.replace(os.sep, ".")
if os.altsep:
base = base.replace(os.altsep, ".")
filename, ext = os.path.splitext(base)
- return filename
+ return filename.lstrip(".")
class CoverageResults:
def __init__(self, counts=None, calledfuncs=None, infile=None,
@@ -799,7 +801,14 @@ def main(argv=None):
try:
with open(progname) as fp:
code = compile(fp.read(), progname, 'exec')
- t.run(code)
+ # try to emulate __main__ namespace as much as possible
+ globs = {
+ '__file__': progname,
+ '__name__': '__main__',
+ '__package__': None,
+ '__cached__': None,
+ }
+ t.runctx(code, globs, globs)
except IOError as err:
_err_exit("Cannot run file %r because: %s" % (sys.argv[0], err))
except SystemExit:
diff --git a/Misc/NEWS b/Misc/NEWS
index 6e52ecb..3637754 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -84,6 +84,13 @@ C-API
Library
-------
+- Issue #1713: Fix os.path.ismount(), which returned true for symbolic links
+ across devices.
+
+- Issue #8826: Properly load old-style "expires" attribute in http.cookies.
+
+- Issue #1690103: Fix initial namespace for code run with trace.main().
+
- Issue #9448: Fix a leak of OS resources (mutexes or semaphores) when
re-initializing a buffered IO object by calling its ``__init__`` method.