##// END OF EJS Templates
tests: fix deprecation warning in test-url.py
Augie Fackler -
r37974:d088810c default
parent child Browse files
Show More
@@ -1,423 +1,424 b''
1 # coding=utf-8
1 # coding=utf-8
2 from __future__ import absolute_import, print_function
2 from __future__ import absolute_import, print_function
3
3
4 import doctest
4 import doctest
5 import os
5 import os
6
6
7 def check(a, b):
7 def check(a, b):
8 if a != b:
8 if a != b:
9 print((a, b))
9 print((a, b))
10
10
11 def cert(cn):
11 def cert(cn):
12 return {'subject': ((('commonName', cn),),)}
12 return {'subject': ((('commonName', cn),),)}
13
13
14 from mercurial import (
14 from mercurial import (
15 sslutil,
15 sslutil,
16 )
16 )
17
17
18 _verifycert = sslutil._verifycert
18 _verifycert = sslutil._verifycert
19 # Test non-wildcard certificates
19 # Test non-wildcard certificates
20 check(_verifycert(cert('example.com'), 'example.com'),
20 check(_verifycert(cert('example.com'), 'example.com'),
21 None)
21 None)
22 check(_verifycert(cert('example.com'), 'www.example.com'),
22 check(_verifycert(cert('example.com'), 'www.example.com'),
23 b'certificate is for example.com')
23 b'certificate is for example.com')
24 check(_verifycert(cert('www.example.com'), 'example.com'),
24 check(_verifycert(cert('www.example.com'), 'example.com'),
25 b'certificate is for www.example.com')
25 b'certificate is for www.example.com')
26
26
27 # Test wildcard certificates
27 # Test wildcard certificates
28 check(_verifycert(cert('*.example.com'), 'www.example.com'),
28 check(_verifycert(cert('*.example.com'), 'www.example.com'),
29 None)
29 None)
30 check(_verifycert(cert('*.example.com'), 'example.com'),
30 check(_verifycert(cert('*.example.com'), 'example.com'),
31 b'certificate is for *.example.com')
31 b'certificate is for *.example.com')
32 check(_verifycert(cert('*.example.com'), 'w.w.example.com'),
32 check(_verifycert(cert('*.example.com'), 'w.w.example.com'),
33 b'certificate is for *.example.com')
33 b'certificate is for *.example.com')
34
34
35 # Test subjectAltName
35 # Test subjectAltName
36 san_cert = {'subject': ((('commonName', 'example.com'),),),
36 san_cert = {'subject': ((('commonName', 'example.com'),),),
37 'subjectAltName': (('DNS', '*.example.net'),
37 'subjectAltName': (('DNS', '*.example.net'),
38 ('DNS', 'example.net'))}
38 ('DNS', 'example.net'))}
39 check(_verifycert(san_cert, 'example.net'),
39 check(_verifycert(san_cert, 'example.net'),
40 None)
40 None)
41 check(_verifycert(san_cert, 'foo.example.net'),
41 check(_verifycert(san_cert, 'foo.example.net'),
42 None)
42 None)
43 # no fallback to subject commonName when subjectAltName has DNS
43 # no fallback to subject commonName when subjectAltName has DNS
44 check(_verifycert(san_cert, 'example.com'),
44 check(_verifycert(san_cert, 'example.com'),
45 b'certificate is for *.example.net, example.net')
45 b'certificate is for *.example.net, example.net')
46 # fallback to subject commonName when no DNS in subjectAltName
46 # fallback to subject commonName when no DNS in subjectAltName
47 san_cert = {'subject': ((('commonName', 'example.com'),),),
47 san_cert = {'subject': ((('commonName', 'example.com'),),),
48 'subjectAltName': (('IP Address', '8.8.8.8'),)}
48 'subjectAltName': (('IP Address', '8.8.8.8'),)}
49 check(_verifycert(san_cert, 'example.com'), None)
49 check(_verifycert(san_cert, 'example.com'), None)
50
50
51 # Avoid some pitfalls
51 # Avoid some pitfalls
52 check(_verifycert(cert('*.foo'), 'foo'),
52 check(_verifycert(cert('*.foo'), 'foo'),
53 b'certificate is for *.foo')
53 b'certificate is for *.foo')
54 check(_verifycert(cert('*o'), 'foo'), None)
54 check(_verifycert(cert('*o'), 'foo'), None)
55
55
56 check(_verifycert({'subject': ()},
56 check(_verifycert({'subject': ()},
57 'example.com'),
57 'example.com'),
58 b'no commonName or subjectAltName found in certificate')
58 b'no commonName or subjectAltName found in certificate')
59 check(_verifycert(None, 'example.com'),
59 check(_verifycert(None, 'example.com'),
60 b'no certificate received')
60 b'no certificate received')
61
61
62 # Unicode (IDN) certname isn't supported
62 # Unicode (IDN) certname isn't supported
63 check(_verifycert(cert(u'\u4f8b.jp'), 'example.jp'),
63 check(_verifycert(cert(u'\u4f8b.jp'), 'example.jp'),
64 b'IDN in certificate not supported')
64 b'IDN in certificate not supported')
65
65
66 # The following tests are from CPython's test_ssl.py.
66 # The following tests are from CPython's test_ssl.py.
67 check(_verifycert(cert('example.com'), 'example.com'), None)
67 check(_verifycert(cert('example.com'), 'example.com'), None)
68 check(_verifycert(cert('example.com'), 'ExAmple.cOm'), None)
68 check(_verifycert(cert('example.com'), 'ExAmple.cOm'), None)
69 check(_verifycert(cert('example.com'), 'www.example.com'),
69 check(_verifycert(cert('example.com'), 'www.example.com'),
70 b'certificate is for example.com')
70 b'certificate is for example.com')
71 check(_verifycert(cert('example.com'), '.example.com'),
71 check(_verifycert(cert('example.com'), '.example.com'),
72 b'certificate is for example.com')
72 b'certificate is for example.com')
73 check(_verifycert(cert('example.com'), 'example.org'),
73 check(_verifycert(cert('example.com'), 'example.org'),
74 b'certificate is for example.com')
74 b'certificate is for example.com')
75 check(_verifycert(cert('example.com'), 'exampleXcom'),
75 check(_verifycert(cert('example.com'), 'exampleXcom'),
76 b'certificate is for example.com')
76 b'certificate is for example.com')
77 check(_verifycert(cert('*.a.com'), 'foo.a.com'), None)
77 check(_verifycert(cert('*.a.com'), 'foo.a.com'), None)
78 check(_verifycert(cert('*.a.com'), 'bar.foo.a.com'),
78 check(_verifycert(cert('*.a.com'), 'bar.foo.a.com'),
79 b'certificate is for *.a.com')
79 b'certificate is for *.a.com')
80 check(_verifycert(cert('*.a.com'), 'a.com'),
80 check(_verifycert(cert('*.a.com'), 'a.com'),
81 b'certificate is for *.a.com')
81 b'certificate is for *.a.com')
82 check(_verifycert(cert('*.a.com'), 'Xa.com'),
82 check(_verifycert(cert('*.a.com'), 'Xa.com'),
83 b'certificate is for *.a.com')
83 b'certificate is for *.a.com')
84 check(_verifycert(cert('*.a.com'), '.a.com'),
84 check(_verifycert(cert('*.a.com'), '.a.com'),
85 b'certificate is for *.a.com')
85 b'certificate is for *.a.com')
86
86
87 # only match one left-most wildcard
87 # only match one left-most wildcard
88 check(_verifycert(cert('f*.com'), 'foo.com'), None)
88 check(_verifycert(cert('f*.com'), 'foo.com'), None)
89 check(_verifycert(cert('f*.com'), 'f.com'), None)
89 check(_verifycert(cert('f*.com'), 'f.com'), None)
90 check(_verifycert(cert('f*.com'), 'bar.com'),
90 check(_verifycert(cert('f*.com'), 'bar.com'),
91 b'certificate is for f*.com')
91 b'certificate is for f*.com')
92 check(_verifycert(cert('f*.com'), 'foo.a.com'),
92 check(_verifycert(cert('f*.com'), 'foo.a.com'),
93 b'certificate is for f*.com')
93 b'certificate is for f*.com')
94 check(_verifycert(cert('f*.com'), 'bar.foo.com'),
94 check(_verifycert(cert('f*.com'), 'bar.foo.com'),
95 b'certificate is for f*.com')
95 b'certificate is for f*.com')
96
96
97 # NULL bytes are bad, CVE-2013-4073
97 # NULL bytes are bad, CVE-2013-4073
98 check(_verifycert(cert('null.python.org\x00example.org'),
98 check(_verifycert(cert('null.python.org\x00example.org'),
99 'null.python.org\x00example.org'), None)
99 'null.python.org\x00example.org'), None)
100 check(_verifycert(cert('null.python.org\x00example.org'),
100 check(_verifycert(cert('null.python.org\x00example.org'),
101 'example.org'),
101 'example.org'),
102 b'certificate is for null.python.org\x00example.org')
102 b'certificate is for null.python.org\x00example.org')
103 check(_verifycert(cert('null.python.org\x00example.org'),
103 check(_verifycert(cert('null.python.org\x00example.org'),
104 'null.python.org'),
104 'null.python.org'),
105 b'certificate is for null.python.org\x00example.org')
105 b'certificate is for null.python.org\x00example.org')
106
106
107 # error cases with wildcards
107 # error cases with wildcards
108 check(_verifycert(cert('*.*.a.com'), 'bar.foo.a.com'),
108 check(_verifycert(cert('*.*.a.com'), 'bar.foo.a.com'),
109 b'certificate is for *.*.a.com')
109 b'certificate is for *.*.a.com')
110 check(_verifycert(cert('*.*.a.com'), 'a.com'),
110 check(_verifycert(cert('*.*.a.com'), 'a.com'),
111 b'certificate is for *.*.a.com')
111 b'certificate is for *.*.a.com')
112 check(_verifycert(cert('*.*.a.com'), 'Xa.com'),
112 check(_verifycert(cert('*.*.a.com'), 'Xa.com'),
113 b'certificate is for *.*.a.com')
113 b'certificate is for *.*.a.com')
114 check(_verifycert(cert('*.*.a.com'), '.a.com'),
114 check(_verifycert(cert('*.*.a.com'), '.a.com'),
115 b'certificate is for *.*.a.com')
115 b'certificate is for *.*.a.com')
116
116
117 check(_verifycert(cert('a.*.com'), 'a.foo.com'),
117 check(_verifycert(cert('a.*.com'), 'a.foo.com'),
118 b'certificate is for a.*.com')
118 b'certificate is for a.*.com')
119 check(_verifycert(cert('a.*.com'), 'a..com'),
119 check(_verifycert(cert('a.*.com'), 'a..com'),
120 b'certificate is for a.*.com')
120 b'certificate is for a.*.com')
121 check(_verifycert(cert('a.*.com'), 'a.com'),
121 check(_verifycert(cert('a.*.com'), 'a.com'),
122 b'certificate is for a.*.com')
122 b'certificate is for a.*.com')
123
123
124 # wildcard doesn't match IDNA prefix 'xn--'
124 # wildcard doesn't match IDNA prefix 'xn--'
125 idna = u'pΓΌthon.python.org'.encode('idna').decode('ascii')
125 idna = u'pΓΌthon.python.org'.encode('idna').decode('ascii')
126 check(_verifycert(cert(idna), idna), None)
126 check(_verifycert(cert(idna), idna), None)
127 check(_verifycert(cert('x*.python.org'), idna),
127 check(_verifycert(cert('x*.python.org'), idna),
128 b'certificate is for x*.python.org')
128 b'certificate is for x*.python.org')
129 check(_verifycert(cert('xn--p*.python.org'), idna),
129 check(_verifycert(cert('xn--p*.python.org'), idna),
130 b'certificate is for xn--p*.python.org')
130 b'certificate is for xn--p*.python.org')
131
131
132 # wildcard in first fragment and IDNA A-labels in sequent fragments
132 # wildcard in first fragment and IDNA A-labels in sequent fragments
133 # are supported.
133 # are supported.
134 idna = u'www*.pythΓΆn.org'.encode('idna').decode('ascii')
134 idna = u'www*.pythΓΆn.org'.encode('idna').decode('ascii')
135 check(_verifycert(cert(idna),
135 check(_verifycert(cert(idna),
136 u'www.pythΓΆn.org'.encode('idna').decode('ascii')),
136 u'www.pythΓΆn.org'.encode('idna').decode('ascii')),
137 None)
137 None)
138 check(_verifycert(cert(idna),
138 check(_verifycert(cert(idna),
139 u'www1.pythΓΆn.org'.encode('idna').decode('ascii')),
139 u'www1.pythΓΆn.org'.encode('idna').decode('ascii')),
140 None)
140 None)
141 check(_verifycert(cert(idna),
141 check(_verifycert(cert(idna),
142 u'ftp.pythΓΆn.org'.encode('idna').decode('ascii')),
142 u'ftp.pythΓΆn.org'.encode('idna').decode('ascii')),
143 b'certificate is for www*.xn--pythn-mua.org')
143 b'certificate is for www*.xn--pythn-mua.org')
144 check(_verifycert(cert(idna),
144 check(_verifycert(cert(idna),
145 u'pythΓΆn.org'.encode('idna').decode('ascii')),
145 u'pythΓΆn.org'.encode('idna').decode('ascii')),
146 b'certificate is for www*.xn--pythn-mua.org')
146 b'certificate is for www*.xn--pythn-mua.org')
147
147
148 c = {
148 c = {
149 'notAfter': 'Jun 26 21:41:46 2011 GMT',
149 'notAfter': 'Jun 26 21:41:46 2011 GMT',
150 'subject': (((u'commonName', u'linuxfrz.org'),),),
150 'subject': (((u'commonName', u'linuxfrz.org'),),),
151 'subjectAltName': (
151 'subjectAltName': (
152 ('DNS', 'linuxfr.org'),
152 ('DNS', 'linuxfr.org'),
153 ('DNS', 'linuxfr.com'),
153 ('DNS', 'linuxfr.com'),
154 ('othername', '<unsupported>'),
154 ('othername', '<unsupported>'),
155 )
155 )
156 }
156 }
157 check(_verifycert(c, 'linuxfr.org'), None)
157 check(_verifycert(c, 'linuxfr.org'), None)
158 check(_verifycert(c, 'linuxfr.com'), None)
158 check(_verifycert(c, 'linuxfr.com'), None)
159 # Not a "DNS" entry
159 # Not a "DNS" entry
160 check(_verifycert(c, '<unsupported>'),
160 check(_verifycert(c, '<unsupported>'),
161 b'certificate is for linuxfr.org, linuxfr.com')
161 b'certificate is for linuxfr.org, linuxfr.com')
162 # When there is a subjectAltName, commonName isn't used
162 # When there is a subjectAltName, commonName isn't used
163 check(_verifycert(c, 'linuxfrz.org'),
163 check(_verifycert(c, 'linuxfrz.org'),
164 b'certificate is for linuxfr.org, linuxfr.com')
164 b'certificate is for linuxfr.org, linuxfr.com')
165
165
166 # A pristine real-world example
166 # A pristine real-world example
167 c = {
167 c = {
168 'notAfter': 'Dec 18 23:59:59 2011 GMT',
168 'notAfter': 'Dec 18 23:59:59 2011 GMT',
169 'subject': (
169 'subject': (
170 ((u'countryName', u'US'),),
170 ((u'countryName', u'US'),),
171 ((u'stateOrProvinceName', u'California'),),
171 ((u'stateOrProvinceName', u'California'),),
172 ((u'localityName', u'Mountain View'),),
172 ((u'localityName', u'Mountain View'),),
173 ((u'organizationName', u'Google Inc'),),
173 ((u'organizationName', u'Google Inc'),),
174 ((u'commonName', u'mail.google.com'),),
174 ((u'commonName', u'mail.google.com'),),
175 ),
175 ),
176 }
176 }
177 check(_verifycert(c, 'mail.google.com'), None)
177 check(_verifycert(c, 'mail.google.com'), None)
178 check(_verifycert(c, 'gmail.com'), b'certificate is for mail.google.com')
178 check(_verifycert(c, 'gmail.com'), b'certificate is for mail.google.com')
179
179
180 # Only commonName is considered
180 # Only commonName is considered
181 check(_verifycert(c, 'California'), b'certificate is for mail.google.com')
181 check(_verifycert(c, 'California'), b'certificate is for mail.google.com')
182
182
183 # Neither commonName nor subjectAltName
183 # Neither commonName nor subjectAltName
184 c = {
184 c = {
185 'notAfter': 'Dec 18 23:59:59 2011 GMT',
185 'notAfter': 'Dec 18 23:59:59 2011 GMT',
186 'subject': (
186 'subject': (
187 ((u'countryName', u'US'),),
187 ((u'countryName', u'US'),),
188 ((u'stateOrProvinceName', u'California'),),
188 ((u'stateOrProvinceName', u'California'),),
189 ((u'localityName', u'Mountain View'),),
189 ((u'localityName', u'Mountain View'),),
190 ((u'organizationName', u'Google Inc'),),
190 ((u'organizationName', u'Google Inc'),),
191 ),
191 ),
192 }
192 }
193 check(_verifycert(c, 'mail.google.com'),
193 check(_verifycert(c, 'mail.google.com'),
194 b'no commonName or subjectAltName found in certificate')
194 b'no commonName or subjectAltName found in certificate')
195
195
196 # No DNS entry in subjectAltName but a commonName
196 # No DNS entry in subjectAltName but a commonName
197 c = {
197 c = {
198 'notAfter': 'Dec 18 23:59:59 2099 GMT',
198 'notAfter': 'Dec 18 23:59:59 2099 GMT',
199 'subject': (
199 'subject': (
200 ((u'countryName', u'US'),),
200 ((u'countryName', u'US'),),
201 ((u'stateOrProvinceName', u'California'),),
201 ((u'stateOrProvinceName', u'California'),),
202 ((u'localityName', u'Mountain View'),),
202 ((u'localityName', u'Mountain View'),),
203 ((u'commonName', u'mail.google.com'),),
203 ((u'commonName', u'mail.google.com'),),
204 ),
204 ),
205 'subjectAltName': (('othername', 'blabla'),),
205 'subjectAltName': (('othername', 'blabla'),),
206 }
206 }
207 check(_verifycert(c, 'mail.google.com'), None)
207 check(_verifycert(c, 'mail.google.com'), None)
208
208
209 # No DNS entry subjectAltName and no commonName
209 # No DNS entry subjectAltName and no commonName
210 c = {
210 c = {
211 'notAfter': 'Dec 18 23:59:59 2099 GMT',
211 'notAfter': 'Dec 18 23:59:59 2099 GMT',
212 'subject': (
212 'subject': (
213 ((u'countryName', u'US'),),
213 ((u'countryName', u'US'),),
214 ((u'stateOrProvinceName', u'California'),),
214 ((u'stateOrProvinceName', u'California'),),
215 ((u'localityName', u'Mountain View'),),
215 ((u'localityName', u'Mountain View'),),
216 ((u'organizationName', u'Google Inc'),),
216 ((u'organizationName', u'Google Inc'),),
217 ),
217 ),
218 'subjectAltName': (('othername', 'blabla'),),
218 'subjectAltName': (('othername', 'blabla'),),
219 }
219 }
220 check(_verifycert(c, 'google.com'),
220 check(_verifycert(c, 'google.com'),
221 b'no commonName or subjectAltName found in certificate')
221 b'no commonName or subjectAltName found in certificate')
222
222
223 # Empty cert / no cert
223 # Empty cert / no cert
224 check(_verifycert(None, 'example.com'), b'no certificate received')
224 check(_verifycert(None, 'example.com'), b'no certificate received')
225 check(_verifycert({}, 'example.com'), b'no certificate received')
225 check(_verifycert({}, 'example.com'), b'no certificate received')
226
226
227 # avoid denials of service by refusing more than one
227 # avoid denials of service by refusing more than one
228 # wildcard per fragment.
228 # wildcard per fragment.
229 check(_verifycert({'subject': (((u'commonName', u'a*b.com'),),)},
229 check(_verifycert({'subject': (((u'commonName', u'a*b.com'),),)},
230 'axxb.com'), None)
230 'axxb.com'), None)
231 check(_verifycert({'subject': (((u'commonName', u'a*b.co*'),),)},
231 check(_verifycert({'subject': (((u'commonName', u'a*b.co*'),),)},
232 'axxb.com'), b'certificate is for a*b.co*')
232 'axxb.com'), b'certificate is for a*b.co*')
233 check(_verifycert({'subject': (((u'commonName', u'a*b*.com'),),)},
233 check(_verifycert({'subject': (((u'commonName', u'a*b*.com'),),)},
234 'axxbxxc.com'),
234 'axxbxxc.com'),
235 b'too many wildcards in certificate DNS name: a*b*.com')
235 b'too many wildcards in certificate DNS name: a*b*.com')
236
236
237 def test_url():
237 def test_url():
238 """
238 """
239 >>> from mercurial import error, pycompat
239 >>> from mercurial import error, pycompat
240 >>> from mercurial.util import forcebytestr, url
240 >>> from mercurial.util import url
241 >>> from mercurial.utils.stringutil import forcebytestr
241
242
242 This tests for edge cases in url.URL's parsing algorithm. Most of
243 This tests for edge cases in url.URL's parsing algorithm. Most of
243 these aren't useful for documentation purposes, so they aren't
244 these aren't useful for documentation purposes, so they aren't
244 part of the class's doc tests.
245 part of the class's doc tests.
245
246
246 Query strings and fragments:
247 Query strings and fragments:
247
248
248 >>> url(b'http://host/a?b#c')
249 >>> url(b'http://host/a?b#c')
249 <url scheme: 'http', host: 'host', path: 'a', query: 'b', fragment: 'c'>
250 <url scheme: 'http', host: 'host', path: 'a', query: 'b', fragment: 'c'>
250 >>> url(b'http://host/a?')
251 >>> url(b'http://host/a?')
251 <url scheme: 'http', host: 'host', path: 'a'>
252 <url scheme: 'http', host: 'host', path: 'a'>
252 >>> url(b'http://host/a#b#c')
253 >>> url(b'http://host/a#b#c')
253 <url scheme: 'http', host: 'host', path: 'a', fragment: 'b#c'>
254 <url scheme: 'http', host: 'host', path: 'a', fragment: 'b#c'>
254 >>> url(b'http://host/a#b?c')
255 >>> url(b'http://host/a#b?c')
255 <url scheme: 'http', host: 'host', path: 'a', fragment: 'b?c'>
256 <url scheme: 'http', host: 'host', path: 'a', fragment: 'b?c'>
256 >>> url(b'http://host/?a#b')
257 >>> url(b'http://host/?a#b')
257 <url scheme: 'http', host: 'host', path: '', query: 'a', fragment: 'b'>
258 <url scheme: 'http', host: 'host', path: '', query: 'a', fragment: 'b'>
258 >>> url(b'http://host/?a#b', parsequery=False)
259 >>> url(b'http://host/?a#b', parsequery=False)
259 <url scheme: 'http', host: 'host', path: '?a', fragment: 'b'>
260 <url scheme: 'http', host: 'host', path: '?a', fragment: 'b'>
260 >>> url(b'http://host/?a#b', parsefragment=False)
261 >>> url(b'http://host/?a#b', parsefragment=False)
261 <url scheme: 'http', host: 'host', path: '', query: 'a#b'>
262 <url scheme: 'http', host: 'host', path: '', query: 'a#b'>
262 >>> url(b'http://host/?a#b', parsequery=False, parsefragment=False)
263 >>> url(b'http://host/?a#b', parsequery=False, parsefragment=False)
263 <url scheme: 'http', host: 'host', path: '?a#b'>
264 <url scheme: 'http', host: 'host', path: '?a#b'>
264
265
265 IPv6 addresses:
266 IPv6 addresses:
266
267
267 >>> url(b'ldap://[2001:db8::7]/c=GB?objectClass?one')
268 >>> url(b'ldap://[2001:db8::7]/c=GB?objectClass?one')
268 <url scheme: 'ldap', host: '[2001:db8::7]', path: 'c=GB',
269 <url scheme: 'ldap', host: '[2001:db8::7]', path: 'c=GB',
269 query: 'objectClass?one'>
270 query: 'objectClass?one'>
270 >>> url(b'ldap://joe:xxx@[2001:db8::7]:80/c=GB?objectClass?one')
271 >>> url(b'ldap://joe:xxx@[2001:db8::7]:80/c=GB?objectClass?one')
271 <url scheme: 'ldap', user: 'joe', passwd: 'xxx', host: '[2001:db8::7]',
272 <url scheme: 'ldap', user: 'joe', passwd: 'xxx', host: '[2001:db8::7]',
272 port: '80', path: 'c=GB', query: 'objectClass?one'>
273 port: '80', path: 'c=GB', query: 'objectClass?one'>
273
274
274 Missing scheme, host, etc.:
275 Missing scheme, host, etc.:
275
276
276 >>> url(b'://192.0.2.16:80/')
277 >>> url(b'://192.0.2.16:80/')
277 <url path: '://192.0.2.16:80/'>
278 <url path: '://192.0.2.16:80/'>
278 >>> url(b'https://mercurial-scm.org')
279 >>> url(b'https://mercurial-scm.org')
279 <url scheme: 'https', host: 'mercurial-scm.org'>
280 <url scheme: 'https', host: 'mercurial-scm.org'>
280 >>> url(b'/foo')
281 >>> url(b'/foo')
281 <url path: '/foo'>
282 <url path: '/foo'>
282 >>> url(b'bundle:/foo')
283 >>> url(b'bundle:/foo')
283 <url scheme: 'bundle', path: '/foo'>
284 <url scheme: 'bundle', path: '/foo'>
284 >>> url(b'a?b#c')
285 >>> url(b'a?b#c')
285 <url path: 'a?b', fragment: 'c'>
286 <url path: 'a?b', fragment: 'c'>
286 >>> url(b'http://x.com?arg=/foo')
287 >>> url(b'http://x.com?arg=/foo')
287 <url scheme: 'http', host: 'x.com', query: 'arg=/foo'>
288 <url scheme: 'http', host: 'x.com', query: 'arg=/foo'>
288 >>> url(b'http://joe:xxx@/foo')
289 >>> url(b'http://joe:xxx@/foo')
289 <url scheme: 'http', user: 'joe', passwd: 'xxx', path: 'foo'>
290 <url scheme: 'http', user: 'joe', passwd: 'xxx', path: 'foo'>
290
291
291 Just a scheme and a path:
292 Just a scheme and a path:
292
293
293 >>> url(b'mailto:John.Doe@example.com')
294 >>> url(b'mailto:John.Doe@example.com')
294 <url scheme: 'mailto', path: 'John.Doe@example.com'>
295 <url scheme: 'mailto', path: 'John.Doe@example.com'>
295 >>> url(b'a:b:c:d')
296 >>> url(b'a:b:c:d')
296 <url path: 'a:b:c:d'>
297 <url path: 'a:b:c:d'>
297 >>> url(b'aa:bb:cc:dd')
298 >>> url(b'aa:bb:cc:dd')
298 <url scheme: 'aa', path: 'bb:cc:dd'>
299 <url scheme: 'aa', path: 'bb:cc:dd'>
299
300
300 SSH examples:
301 SSH examples:
301
302
302 >>> url(b'ssh://joe@host//home/joe')
303 >>> url(b'ssh://joe@host//home/joe')
303 <url scheme: 'ssh', user: 'joe', host: 'host', path: '/home/joe'>
304 <url scheme: 'ssh', user: 'joe', host: 'host', path: '/home/joe'>
304 >>> url(b'ssh://joe:xxx@host/src')
305 >>> url(b'ssh://joe:xxx@host/src')
305 <url scheme: 'ssh', user: 'joe', passwd: 'xxx', host: 'host', path: 'src'>
306 <url scheme: 'ssh', user: 'joe', passwd: 'xxx', host: 'host', path: 'src'>
306 >>> url(b'ssh://joe:xxx@host')
307 >>> url(b'ssh://joe:xxx@host')
307 <url scheme: 'ssh', user: 'joe', passwd: 'xxx', host: 'host'>
308 <url scheme: 'ssh', user: 'joe', passwd: 'xxx', host: 'host'>
308 >>> url(b'ssh://joe@host')
309 >>> url(b'ssh://joe@host')
309 <url scheme: 'ssh', user: 'joe', host: 'host'>
310 <url scheme: 'ssh', user: 'joe', host: 'host'>
310 >>> url(b'ssh://host')
311 >>> url(b'ssh://host')
311 <url scheme: 'ssh', host: 'host'>
312 <url scheme: 'ssh', host: 'host'>
312 >>> url(b'ssh://')
313 >>> url(b'ssh://')
313 <url scheme: 'ssh'>
314 <url scheme: 'ssh'>
314 >>> url(b'ssh:')
315 >>> url(b'ssh:')
315 <url scheme: 'ssh'>
316 <url scheme: 'ssh'>
316
317
317 Non-numeric port:
318 Non-numeric port:
318
319
319 >>> url(b'http://example.com:dd')
320 >>> url(b'http://example.com:dd')
320 <url scheme: 'http', host: 'example.com', port: 'dd'>
321 <url scheme: 'http', host: 'example.com', port: 'dd'>
321 >>> url(b'ssh://joe:xxx@host:ssh/foo')
322 >>> url(b'ssh://joe:xxx@host:ssh/foo')
322 <url scheme: 'ssh', user: 'joe', passwd: 'xxx', host: 'host', port: 'ssh',
323 <url scheme: 'ssh', user: 'joe', passwd: 'xxx', host: 'host', port: 'ssh',
323 path: 'foo'>
324 path: 'foo'>
324
325
325 Bad authentication credentials:
326 Bad authentication credentials:
326
327
327 >>> url(b'http://joe@joeville:123@4:@host/a?b#c')
328 >>> url(b'http://joe@joeville:123@4:@host/a?b#c')
328 <url scheme: 'http', user: 'joe@joeville', passwd: '123@4:',
329 <url scheme: 'http', user: 'joe@joeville', passwd: '123@4:',
329 host: 'host', path: 'a', query: 'b', fragment: 'c'>
330 host: 'host', path: 'a', query: 'b', fragment: 'c'>
330 >>> url(b'http://!*#?/@!*#?/:@host/a?b#c')
331 >>> url(b'http://!*#?/@!*#?/:@host/a?b#c')
331 <url scheme: 'http', host: '!*', fragment: '?/@!*#?/:@host/a?b#c'>
332 <url scheme: 'http', host: '!*', fragment: '?/@!*#?/:@host/a?b#c'>
332 >>> url(b'http://!*#?@!*#?:@host/a?b#c')
333 >>> url(b'http://!*#?@!*#?:@host/a?b#c')
333 <url scheme: 'http', host: '!*', fragment: '?@!*#?:@host/a?b#c'>
334 <url scheme: 'http', host: '!*', fragment: '?@!*#?:@host/a?b#c'>
334 >>> url(b'http://!*@:!*@@host/a?b#c')
335 >>> url(b'http://!*@:!*@@host/a?b#c')
335 <url scheme: 'http', user: '!*@', passwd: '!*@', host: 'host',
336 <url scheme: 'http', user: '!*@', passwd: '!*@', host: 'host',
336 path: 'a', query: 'b', fragment: 'c'>
337 path: 'a', query: 'b', fragment: 'c'>
337
338
338 File paths:
339 File paths:
339
340
340 >>> url(b'a/b/c/d.g.f')
341 >>> url(b'a/b/c/d.g.f')
341 <url path: 'a/b/c/d.g.f'>
342 <url path: 'a/b/c/d.g.f'>
342 >>> url(b'/x///z/y/')
343 >>> url(b'/x///z/y/')
343 <url path: '/x///z/y/'>
344 <url path: '/x///z/y/'>
344 >>> url(b'/foo:bar')
345 >>> url(b'/foo:bar')
345 <url path: '/foo:bar'>
346 <url path: '/foo:bar'>
346 >>> url(b'\\\\foo:bar')
347 >>> url(b'\\\\foo:bar')
347 <url path: '\\\\foo:bar'>
348 <url path: '\\\\foo:bar'>
348 >>> url(b'./foo:bar')
349 >>> url(b'./foo:bar')
349 <url path: './foo:bar'>
350 <url path: './foo:bar'>
350
351
351 Non-localhost file URL:
352 Non-localhost file URL:
352
353
353 >>> try:
354 >>> try:
354 ... u = url(b'file://mercurial-scm.org/foo')
355 ... u = url(b'file://mercurial-scm.org/foo')
355 ... except error.Abort as e:
356 ... except error.Abort as e:
356 ... forcebytestr(e)
357 ... forcebytestr(e)
357 'file:// URLs can only refer to localhost'
358 'file:// URLs can only refer to localhost'
358
359
359 Empty URL:
360 Empty URL:
360
361
361 >>> u = url(b'')
362 >>> u = url(b'')
362 >>> u
363 >>> u
363 <url path: ''>
364 <url path: ''>
364 >>> str(u)
365 >>> str(u)
365 ''
366 ''
366
367
367 Empty path with query string:
368 Empty path with query string:
368
369
369 >>> str(url(b'http://foo/?bar'))
370 >>> str(url(b'http://foo/?bar'))
370 'http://foo/?bar'
371 'http://foo/?bar'
371
372
372 Invalid path:
373 Invalid path:
373
374
374 >>> u = url(b'http://foo/bar')
375 >>> u = url(b'http://foo/bar')
375 >>> u.path = b'bar'
376 >>> u.path = b'bar'
376 >>> str(u)
377 >>> str(u)
377 'http://foo/bar'
378 'http://foo/bar'
378
379
379 >>> u = url(b'file:/foo/bar/baz')
380 >>> u = url(b'file:/foo/bar/baz')
380 >>> u
381 >>> u
381 <url scheme: 'file', path: '/foo/bar/baz'>
382 <url scheme: 'file', path: '/foo/bar/baz'>
382 >>> str(u)
383 >>> str(u)
383 'file:///foo/bar/baz'
384 'file:///foo/bar/baz'
384 >>> pycompat.bytestr(u.localpath())
385 >>> pycompat.bytestr(u.localpath())
385 '/foo/bar/baz'
386 '/foo/bar/baz'
386
387
387 >>> u = url(b'file:///foo/bar/baz')
388 >>> u = url(b'file:///foo/bar/baz')
388 >>> u
389 >>> u
389 <url scheme: 'file', path: '/foo/bar/baz'>
390 <url scheme: 'file', path: '/foo/bar/baz'>
390 >>> str(u)
391 >>> str(u)
391 'file:///foo/bar/baz'
392 'file:///foo/bar/baz'
392 >>> pycompat.bytestr(u.localpath())
393 >>> pycompat.bytestr(u.localpath())
393 '/foo/bar/baz'
394 '/foo/bar/baz'
394
395
395 >>> u = url(b'file:///f:oo/bar/baz')
396 >>> u = url(b'file:///f:oo/bar/baz')
396 >>> u
397 >>> u
397 <url scheme: 'file', path: 'f:oo/bar/baz'>
398 <url scheme: 'file', path: 'f:oo/bar/baz'>
398 >>> str(u)
399 >>> str(u)
399 'file:///f:oo/bar/baz'
400 'file:///f:oo/bar/baz'
400 >>> pycompat.bytestr(u.localpath())
401 >>> pycompat.bytestr(u.localpath())
401 'f:oo/bar/baz'
402 'f:oo/bar/baz'
402
403
403 >>> u = url(b'file://localhost/f:oo/bar/baz')
404 >>> u = url(b'file://localhost/f:oo/bar/baz')
404 >>> u
405 >>> u
405 <url scheme: 'file', host: 'localhost', path: 'f:oo/bar/baz'>
406 <url scheme: 'file', host: 'localhost', path: 'f:oo/bar/baz'>
406 >>> str(u)
407 >>> str(u)
407 'file://localhost/f:oo/bar/baz'
408 'file://localhost/f:oo/bar/baz'
408 >>> pycompat.bytestr(u.localpath())
409 >>> pycompat.bytestr(u.localpath())
409 'f:oo/bar/baz'
410 'f:oo/bar/baz'
410
411
411 >>> u = url(b'file:foo/bar/baz')
412 >>> u = url(b'file:foo/bar/baz')
412 >>> u
413 >>> u
413 <url scheme: 'file', path: 'foo/bar/baz'>
414 <url scheme: 'file', path: 'foo/bar/baz'>
414 >>> str(u)
415 >>> str(u)
415 'file:foo/bar/baz'
416 'file:foo/bar/baz'
416 >>> pycompat.bytestr(u.localpath())
417 >>> pycompat.bytestr(u.localpath())
417 'foo/bar/baz'
418 'foo/bar/baz'
418 """
419 """
419
420
420 if 'TERM' in os.environ:
421 if 'TERM' in os.environ:
421 del os.environ['TERM']
422 del os.environ['TERM']
422
423
423 doctest.testmod(optionflags=doctest.NORMALIZE_WHITESPACE)
424 doctest.testmod(optionflags=doctest.NORMALIZE_WHITESPACE)
General Comments 0
You need to be logged in to leave comments. Login now