summaryrefslogtreecommitdiff
blob: adb43f4241dff8ec324d94be6e24915439df7fcc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
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>[{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<weekday>(?:{wdy}|{weekday}),[ ])?
             (?P<day>{day})
@@ -230,11 +230,17 @@ class Definitions(object):
             (?P<year2>\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<expires>%s)" % DATE
+    EXPIRES_AV = "Expires=(?P<expires>%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")