diff --git a/cookies.py b/cookies.py index d1637d22630580e25cb0b1405754dd7e195bf85f..4fd0ebbd07384e02d6f40e45a4432a2baa95fc8b 100644 --- a/cookies.py +++ b/cookies.py @@ -132,7 +132,7 @@ class Definitions(object): # attribute and extract it appropriately. # As compared with the RFC production grammar, it is must more liberal with # space characters, in order not to break on data made by barbarians. - SET_COOKIE_HEADER = """(?x) # Verbose mode + SET_COOKIE_HEADER = r"""(?x) # Verbose mode ^(?:Set-Cookie:[ ]*)? (?P[{name}:]+) [ ]*=[ ]* @@ -203,7 +203,7 @@ class Definitions(object): # Here is the overall date format; ~99% of cases fold into one generalized # syntax like RFC 1123, and many of the rest use asctime-like formats. # (see test_date_formats for a full exegesis) - DATE = """(?ix) # Case-insensitive mode, verbose mode + _DATE = """ (?: (?P(?:{wdy}|{weekday}),[ ])? (?P{day}) @@ -230,11 +230,17 @@ class Definitions(object): (?P\d\d\d\d) (?:[ ]GMT)? # GMT (Amazon) ) - """ - DATE = DATE.format(wdy=WEEKDAY_SHORT, weekday=WEEKDAY_LONG, - day=DAY_OF_MONTH, mon=MONTH_SHORT, month=MONTH_LONG) + """.format(wdy=WEEKDAY_SHORT, weekday=WEEKDAY_LONG, + day=DAY_OF_MONTH, mon=MONTH_SHORT, month=MONTH_LONG) + + # Starting in Python 3.6, embedding a regex that starts with "(?ix)" in + # the middle of another regex produces a warning (and will stop working + # altogether in some future Python version). We thus create two variables + # here: _DATE is for embedding inside other regexes (which must themselves + # begin with "(?ix)"), DATE is for standalone matching. + DATE = '(?ix)' + _DATE - EXPIRES_AV = "Expires=(?P%s)" % DATE + EXPIRES_AV = "Expires=(?P%s)" % _DATE # Now we're ready to define a regexp which can match any number of attrs # in the variable portion of the Set-Cookie header (like the unnamed latter @@ -263,7 +269,7 @@ class Definitions(object): path=PATH_AV, stuff=EXTENSION_AV) # For request data ("Cookie: ") parsing, with finditer cf. RFC 6265 4.2.1 - COOKIE = """(?x) # Verbose mode + COOKIE = r"""(?x) # Verbose mode (?: # Either something close to valid... # Match starts at start of string, or at separator. @@ -306,13 +312,13 @@ class Definitions(object): """.format(name=COOKIE_NAME, value=COOKIE_OCTET) # Precompile externally useful definitions into re objects. - COOKIE_NAME_RE = re.compile("^([%s:]+)\Z" % COOKIE_NAME) + COOKIE_NAME_RE = re.compile(r"^([%s:]+)\Z" % COOKIE_NAME) COOKIE_RE = re.compile(COOKIE) SET_COOKIE_HEADER_RE = re.compile(SET_COOKIE_HEADER) ATTR_RE = re.compile(ATTR) DATE_RE = re.compile(DATE) DOMAIN_RE = re.compile(DOMAIN) - PATH_RE = re.compile('^([%s]+)\Z' % EXTENSION_AV) + PATH_RE = re.compile(r'^([%s]+)\Z' % EXTENSION_AV) EOL = re.compile("(?:\r\n|\n)") @@ -965,7 +971,7 @@ class Cookie(object): 'path': valid_path, 'max_age': valid_max_age, 'comment': valid_value, - 'version': lambda number: re.match("^\d+\Z", str(number)), + 'version': lambda number: re.match(r"^\d+\Z", str(number)), 'secure': lambda item: item is True or item is False, 'httponly': lambda item: item is True or item is False, } diff --git a/test_cookies.py b/test_cookies.py index 2197916effae23a85e571dcb4a1acf78fbe1c71e..abc95a6346a1522556b95e03de81baaa0a478031 100644 --- a/test_cookies.py +++ b/test_cookies.py @@ -35,19 +35,19 @@ class RFC1034: digit = "[0-9]" letter = "[A-Za-z]" let_dig = "[0-9A-Za-z]" - let_dig_hyp = "[0-9A-Za-z\-]" + let_dig_hyp = r"[0-9A-Za-z\-]" assert "\\" in let_dig_hyp ldh_str = "%s+" % let_dig_hyp label = "(?:%s|%s|%s)" % ( letter, letter + let_dig, letter + ldh_str + let_dig) - subdomain = "(?:%s\.)*(?:%s)" % (label, label) + subdomain = r"(?:%s\.)*(?:%s)" % (label, label) domain = "( |%s)" % (subdomain) def test_sanity(self): "Basic smoke tests that definitions transcribed OK" - match = re.compile("^%s\Z" % self.domain).match + match = re.compile(r"^%s\Z" % self.domain).match assert match("A.ISI.EDU") assert match("XX.LCS.MIT.EDU") assert match("SRI-NIC.ARPA") @@ -74,12 +74,12 @@ class RFC1123: # n.b.: there are length limits in the real thing label = "{let_dig}(?:(?:{let_dig_hyp}+)?{let_dig})?".format( let_dig=RFC1034.let_dig, let_dig_hyp=RFC1034.let_dig_hyp) - subdomain = "(?:%s\.)*(?:%s)" % (label, label) + subdomain = r"(?:%s\.)*(?:%s)" % (label, label) domain = "( |%s)" % (subdomain) def test_sanity(self): "Basic smoke tests that definitions transcribed OK" - match = re.compile("^%s\Z" % self.domain).match + match = re.compile(r"^%s\Z" % self.domain).match assert match("A.ISI.EDU") assert match("XX.LCS.MIT.EDU") assert match("SRI-NIC.ARPA") @@ -241,7 +241,7 @@ class TestDefinitions(object): ; whitespace DQUOTE, comma, semicolon, ; and backslash """ - match = re.compile("^[%s]+\Z" % Definitions.COOKIE_OCTET).match + match = re.compile(r"^[%s]+\Z" % Definitions.COOKIE_OCTET).match for c in RFC5234.CTL: assert not match(c) assert not match("a%sb" % c) @@ -331,7 +331,7 @@ class TestDefinitions(object): ('frob', 'laz', '')] def assert_correct(s): - #naive = re.findall(" *([^;]+)=([^;]+) *(?:;|\Z)", s) + #naive = re.findall(r" *([^;]+)=([^;]+) *(?:;|\Z)", s) result = regex.findall(s) assert result == correct # normal-looking case should work normally @@ -390,7 +390,7 @@ class TestDefinitions(object): extension_av_explicit = "".join(sorted( set(RFC5234.CHAR) - set(RFC5234.CTL + ";"))) # ... that should turn out to be the same as Definitions.EXTENSION_AV - match = re.compile("^([%s]+)\Z" % Definitions.EXTENSION_AV).match + match = re.compile(r"^([%s]+)\Z" % Definitions.EXTENSION_AV).match # Verify I didn't mess up on escaping here first assert match(r']') assert match(r'[') @@ -411,7 +411,7 @@ class TestDefinitions(object): def test_max_age_av(self): "Smoke test Definitions.MAX_AGE_AV" # Not a lot to this, it's just digits - match = re.compile("^%s\Z" % Definitions.MAX_AGE_AV).match + match = re.compile(r"^%s\Z" % Definitions.MAX_AGE_AV).match assert not match("") assert not match("Whiskers") assert not match("Max-Headroom=992") @@ -424,7 +424,7 @@ class TestDefinitions(object): def test_label(self, check_unicode=False): "Test label, as used in Domain attribute" - match = re.compile("^(%s)\Z" % Definitions.LABEL).match + match = re.compile(r"^(%s)\Z" % Definitions.LABEL).match for i in range(0, 10): assert match(str(i)) assert not match(".") @@ -459,7 +459,7 @@ class TestDefinitions(object): assert match(domain) # Now same tests through DOMAIN_AV - match = re.compile("^%s\Z" % Definitions.DOMAIN_AV).match + match = re.compile(r"^%s\Z" % Definitions.DOMAIN_AV).match for domain in bad_domains: assert not match("Domain=%s" % domain) for domain in good_domains: @@ -487,7 +487,7 @@ class TestDefinitions(object): for path in good_paths: assert match(path) - match = re.compile("^%s\Z" % Definitions.PATH_AV).match + match = re.compile(r"^%s\Z" % Definitions.PATH_AV).match for path in bad_paths: assert not match("Path=%s" % path) for path in good_paths: @@ -575,7 +575,7 @@ class TestDefinitions(object): # dependencies, and odds are good that other implementations are loose. # so this parser is also loose. "liberal in what you accept, # conservative in what you produce" - match = re.compile("^%s\Z" % Definitions.EXPIRES_AV).match + match = re.compile(r"^%s\Z" % Definitions.EXPIRES_AV, flags=re.I | re.X).match assert not match("") assert not match("Expires=") @@ -610,7 +610,7 @@ class TestDefinitions(object): If this works, then ATTR should work """ - match = re.compile("^[%s]+\Z" % Definitions.EXTENSION_AV).match + match = re.compile(r"^[%s]+\Z" % Definitions.EXTENSION_AV).match assert match("Expires=Sun, 06 Nov 1994 08:49:37 GMT") assert match("Expires=Sunday, 06-Nov-94 08:49:37 GMT") assert match("Expires=Sun Nov 6 08:49:37 1994")