1 | import unittest
|
---|
2 | from test import test_support, test_genericpath
|
---|
3 |
|
---|
4 | import posixpath, os
|
---|
5 | from posixpath import realpath, abspath, dirname, basename
|
---|
6 |
|
---|
7 | # An absolute path to a temporary filename for testing. We can't rely on TESTFN
|
---|
8 | # being an absolute path, so we need this.
|
---|
9 |
|
---|
10 | ABSTFN = abspath(test_support.TESTFN)
|
---|
11 |
|
---|
12 | def skip_if_ABSTFN_contains_backslash(test):
|
---|
13 | """
|
---|
14 | On Windows, posixpath.abspath still returns paths with backslashes
|
---|
15 | instead of posix forward slashes. If this is the case, several tests
|
---|
16 | fail, so skip them.
|
---|
17 | """
|
---|
18 | found_backslash = '\\' in ABSTFN
|
---|
19 | msg = "ABSTFN is not a posix path - tests fail"
|
---|
20 | return [test, unittest.skip(msg)(test)][found_backslash]
|
---|
21 |
|
---|
22 | def safe_rmdir(dirname):
|
---|
23 | try:
|
---|
24 | os.rmdir(dirname)
|
---|
25 | except OSError:
|
---|
26 | pass
|
---|
27 |
|
---|
28 | class PosixPathTest(unittest.TestCase):
|
---|
29 |
|
---|
30 | def setUp(self):
|
---|
31 | self.tearDown()
|
---|
32 |
|
---|
33 | def tearDown(self):
|
---|
34 | for suffix in ["", "1", "2"]:
|
---|
35 | test_support.unlink(test_support.TESTFN + suffix)
|
---|
36 | safe_rmdir(test_support.TESTFN + suffix)
|
---|
37 |
|
---|
38 | def test_join(self):
|
---|
39 | self.assertEqual(posixpath.join("/foo", "bar", "/bar", "baz"), "/bar/baz")
|
---|
40 | self.assertEqual(posixpath.join("/foo", "bar", "baz"), "/foo/bar/baz")
|
---|
41 | self.assertEqual(posixpath.join("/foo/", "bar/", "baz/"), "/foo/bar/baz/")
|
---|
42 |
|
---|
43 | def test_split(self):
|
---|
44 | self.assertEqual(posixpath.split("/foo/bar"), ("/foo", "bar"))
|
---|
45 | self.assertEqual(posixpath.split("/"), ("/", ""))
|
---|
46 | self.assertEqual(posixpath.split("foo"), ("", "foo"))
|
---|
47 | self.assertEqual(posixpath.split("////foo"), ("////", "foo"))
|
---|
48 | self.assertEqual(posixpath.split("//foo//bar"), ("//foo", "bar"))
|
---|
49 |
|
---|
50 | def splitextTest(self, path, filename, ext):
|
---|
51 | self.assertEqual(posixpath.splitext(path), (filename, ext))
|
---|
52 | self.assertEqual(posixpath.splitext("/" + path), ("/" + filename, ext))
|
---|
53 | self.assertEqual(posixpath.splitext("abc/" + path), ("abc/" + filename, ext))
|
---|
54 | self.assertEqual(posixpath.splitext("abc.def/" + path), ("abc.def/" + filename, ext))
|
---|
55 | self.assertEqual(posixpath.splitext("/abc.def/" + path), ("/abc.def/" + filename, ext))
|
---|
56 | self.assertEqual(posixpath.splitext(path + "/"), (filename + ext + "/", ""))
|
---|
57 |
|
---|
58 | def test_splitext(self):
|
---|
59 | self.splitextTest("foo.bar", "foo", ".bar")
|
---|
60 | self.splitextTest("foo.boo.bar", "foo.boo", ".bar")
|
---|
61 | self.splitextTest("foo.boo.biff.bar", "foo.boo.biff", ".bar")
|
---|
62 | self.splitextTest(".csh.rc", ".csh", ".rc")
|
---|
63 | self.splitextTest("nodots", "nodots", "")
|
---|
64 | self.splitextTest(".cshrc", ".cshrc", "")
|
---|
65 | self.splitextTest("...manydots", "...manydots", "")
|
---|
66 | self.splitextTest("...manydots.ext", "...manydots", ".ext")
|
---|
67 | self.splitextTest(".", ".", "")
|
---|
68 | self.splitextTest("..", "..", "")
|
---|
69 | self.splitextTest("........", "........", "")
|
---|
70 | self.splitextTest("", "", "")
|
---|
71 |
|
---|
72 | def test_isabs(self):
|
---|
73 | self.assertIs(posixpath.isabs(""), False)
|
---|
74 | self.assertIs(posixpath.isabs("/"), True)
|
---|
75 | self.assertIs(posixpath.isabs("/foo"), True)
|
---|
76 | self.assertIs(posixpath.isabs("/foo/bar"), True)
|
---|
77 | self.assertIs(posixpath.isabs("foo/bar"), False)
|
---|
78 |
|
---|
79 | def test_basename(self):
|
---|
80 | self.assertEqual(posixpath.basename("/foo/bar"), "bar")
|
---|
81 | self.assertEqual(posixpath.basename("/"), "")
|
---|
82 | self.assertEqual(posixpath.basename("foo"), "foo")
|
---|
83 | self.assertEqual(posixpath.basename("////foo"), "foo")
|
---|
84 | self.assertEqual(posixpath.basename("//foo//bar"), "bar")
|
---|
85 |
|
---|
86 | def test_dirname(self):
|
---|
87 | self.assertEqual(posixpath.dirname("/foo/bar"), "/foo")
|
---|
88 | self.assertEqual(posixpath.dirname("/"), "/")
|
---|
89 | self.assertEqual(posixpath.dirname("foo"), "")
|
---|
90 | self.assertEqual(posixpath.dirname("////foo"), "////")
|
---|
91 | self.assertEqual(posixpath.dirname("//foo//bar"), "//foo")
|
---|
92 |
|
---|
93 | def test_islink(self):
|
---|
94 | self.assertIs(posixpath.islink(test_support.TESTFN + "1"), False)
|
---|
95 | f = open(test_support.TESTFN + "1", "wb")
|
---|
96 | try:
|
---|
97 | f.write("foo")
|
---|
98 | f.close()
|
---|
99 | self.assertIs(posixpath.islink(test_support.TESTFN + "1"), False)
|
---|
100 | if hasattr(os, "symlink"):
|
---|
101 | os.symlink(test_support.TESTFN + "1", test_support.TESTFN + "2")
|
---|
102 | self.assertIs(posixpath.islink(test_support.TESTFN + "2"), True)
|
---|
103 | os.remove(test_support.TESTFN + "1")
|
---|
104 | self.assertIs(posixpath.islink(test_support.TESTFN + "2"), True)
|
---|
105 | self.assertIs(posixpath.exists(test_support.TESTFN + "2"), False)
|
---|
106 | self.assertIs(posixpath.lexists(test_support.TESTFN + "2"), True)
|
---|
107 | finally:
|
---|
108 | if not f.close():
|
---|
109 | f.close()
|
---|
110 |
|
---|
111 | def test_samefile(self):
|
---|
112 | f = open(test_support.TESTFN + "1", "wb")
|
---|
113 | try:
|
---|
114 | f.write("foo")
|
---|
115 | f.close()
|
---|
116 | self.assertIs(
|
---|
117 | posixpath.samefile(
|
---|
118 | test_support.TESTFN + "1",
|
---|
119 | test_support.TESTFN + "1"
|
---|
120 | ),
|
---|
121 | True
|
---|
122 | )
|
---|
123 |
|
---|
124 | # If we don't have links, assume that os.stat doesn't return
|
---|
125 | # reasonable inode information and thus, that samefile() doesn't
|
---|
126 | # work.
|
---|
127 | if hasattr(os, "symlink"):
|
---|
128 | os.symlink(
|
---|
129 | test_support.TESTFN + "1",
|
---|
130 | test_support.TESTFN + "2"
|
---|
131 | )
|
---|
132 | self.assertIs(
|
---|
133 | posixpath.samefile(
|
---|
134 | test_support.TESTFN + "1",
|
---|
135 | test_support.TESTFN + "2"
|
---|
136 | ),
|
---|
137 | True
|
---|
138 | )
|
---|
139 | os.remove(test_support.TESTFN + "2")
|
---|
140 | f = open(test_support.TESTFN + "2", "wb")
|
---|
141 | f.write("bar")
|
---|
142 | f.close()
|
---|
143 | self.assertIs(
|
---|
144 | posixpath.samefile(
|
---|
145 | test_support.TESTFN + "1",
|
---|
146 | test_support.TESTFN + "2"
|
---|
147 | ),
|
---|
148 | False
|
---|
149 | )
|
---|
150 | finally:
|
---|
151 | if not f.close():
|
---|
152 | f.close()
|
---|
153 |
|
---|
154 | def test_samestat(self):
|
---|
155 | f = open(test_support.TESTFN + "1", "wb")
|
---|
156 | try:
|
---|
157 | f.write("foo")
|
---|
158 | f.close()
|
---|
159 | self.assertIs(
|
---|
160 | posixpath.samestat(
|
---|
161 | os.stat(test_support.TESTFN + "1"),
|
---|
162 | os.stat(test_support.TESTFN + "1")
|
---|
163 | ),
|
---|
164 | True
|
---|
165 | )
|
---|
166 | # If we don't have links, assume that os.stat() doesn't return
|
---|
167 | # reasonable inode information and thus, that samestat() doesn't
|
---|
168 | # work.
|
---|
169 | if hasattr(os, "symlink"):
|
---|
170 | os.symlink(test_support.TESTFN + "1", test_support.TESTFN + "2")
|
---|
171 | self.assertIs(
|
---|
172 | posixpath.samestat(
|
---|
173 | os.stat(test_support.TESTFN + "1"),
|
---|
174 | os.stat(test_support.TESTFN + "2")
|
---|
175 | ),
|
---|
176 | True
|
---|
177 | )
|
---|
178 | os.remove(test_support.TESTFN + "2")
|
---|
179 | f = open(test_support.TESTFN + "2", "wb")
|
---|
180 | f.write("bar")
|
---|
181 | f.close()
|
---|
182 | self.assertIs(
|
---|
183 | posixpath.samestat(
|
---|
184 | os.stat(test_support.TESTFN + "1"),
|
---|
185 | os.stat(test_support.TESTFN + "2")
|
---|
186 | ),
|
---|
187 | False
|
---|
188 | )
|
---|
189 | finally:
|
---|
190 | if not f.close():
|
---|
191 | f.close()
|
---|
192 |
|
---|
193 | def test_ismount(self):
|
---|
194 | self.assertIs(posixpath.ismount("/"), True)
|
---|
195 |
|
---|
196 | def test_expanduser(self):
|
---|
197 | self.assertEqual(posixpath.expanduser("foo"), "foo")
|
---|
198 | try:
|
---|
199 | import pwd
|
---|
200 | except ImportError:
|
---|
201 | pass
|
---|
202 | else:
|
---|
203 | self.assertIsInstance(posixpath.expanduser("~/"), basestring)
|
---|
204 | # if home directory == root directory, this test makes no sense
|
---|
205 | if posixpath.expanduser("~") != '/':
|
---|
206 | self.assertEqual(
|
---|
207 | posixpath.expanduser("~") + "/",
|
---|
208 | posixpath.expanduser("~/")
|
---|
209 | )
|
---|
210 | self.assertIsInstance(posixpath.expanduser("~root/"), basestring)
|
---|
211 | self.assertIsInstance(posixpath.expanduser("~foo/"), basestring)
|
---|
212 |
|
---|
213 | with test_support.EnvironmentVarGuard() as env:
|
---|
214 | env['HOME'] = '/'
|
---|
215 | self.assertEqual(posixpath.expanduser("~"), "/")
|
---|
216 | self.assertEqual(posixpath.expanduser("~/foo"), "/foo")
|
---|
217 |
|
---|
218 | def test_normpath(self):
|
---|
219 | self.assertEqual(posixpath.normpath(""), ".")
|
---|
220 | self.assertEqual(posixpath.normpath("/"), "/")
|
---|
221 | self.assertEqual(posixpath.normpath("//"), "//")
|
---|
222 | self.assertEqual(posixpath.normpath("///"), "/")
|
---|
223 | self.assertEqual(posixpath.normpath("///foo/.//bar//"), "/foo/bar")
|
---|
224 | self.assertEqual(posixpath.normpath("///foo/.//bar//.//..//.//baz"), "/foo/baz")
|
---|
225 | self.assertEqual(posixpath.normpath("///..//./foo/.//bar"), "/foo/bar")
|
---|
226 |
|
---|
227 | @skip_if_ABSTFN_contains_backslash
|
---|
228 | def test_realpath_curdir(self):
|
---|
229 | self.assertEqual(realpath('.'), os.getcwd())
|
---|
230 | self.assertEqual(realpath('./.'), os.getcwd())
|
---|
231 | self.assertEqual(realpath('/'.join(['.'] * 100)), os.getcwd())
|
---|
232 |
|
---|
233 | @skip_if_ABSTFN_contains_backslash
|
---|
234 | def test_realpath_pardir(self):
|
---|
235 | self.assertEqual(realpath('..'), dirname(os.getcwd()))
|
---|
236 | self.assertEqual(realpath('../..'), dirname(dirname(os.getcwd())))
|
---|
237 | self.assertEqual(realpath('/'.join(['..'] * 100)), '/')
|
---|
238 |
|
---|
239 | if hasattr(os, "symlink"):
|
---|
240 | def test_realpath_basic(self):
|
---|
241 | # Basic operation.
|
---|
242 | try:
|
---|
243 | os.symlink(ABSTFN+"1", ABSTFN)
|
---|
244 | self.assertEqual(realpath(ABSTFN), ABSTFN+"1")
|
---|
245 | finally:
|
---|
246 | test_support.unlink(ABSTFN)
|
---|
247 |
|
---|
248 | def test_realpath_symlink_loops(self):
|
---|
249 | # Bug #930024, return the path unchanged if we get into an infinite
|
---|
250 | # symlink loop.
|
---|
251 | try:
|
---|
252 | old_path = abspath('.')
|
---|
253 | os.symlink(ABSTFN, ABSTFN)
|
---|
254 | self.assertEqual(realpath(ABSTFN), ABSTFN)
|
---|
255 |
|
---|
256 | os.symlink(ABSTFN+"1", ABSTFN+"2")
|
---|
257 | os.symlink(ABSTFN+"2", ABSTFN+"1")
|
---|
258 | self.assertEqual(realpath(ABSTFN+"1"), ABSTFN+"1")
|
---|
259 | self.assertEqual(realpath(ABSTFN+"2"), ABSTFN+"2")
|
---|
260 |
|
---|
261 | self.assertEqual(realpath(ABSTFN+"1/x"), ABSTFN+"1/x")
|
---|
262 | self.assertEqual(realpath(ABSTFN+"1/.."), dirname(ABSTFN))
|
---|
263 | self.assertEqual(realpath(ABSTFN+"1/../x"), dirname(ABSTFN) + "/x")
|
---|
264 | os.symlink(ABSTFN+"x", ABSTFN+"y")
|
---|
265 | self.assertEqual(realpath(ABSTFN+"1/../" + basename(ABSTFN) + "y"),
|
---|
266 | ABSTFN + "y")
|
---|
267 | self.assertEqual(realpath(ABSTFN+"1/../" + basename(ABSTFN) + "1"),
|
---|
268 | ABSTFN + "1")
|
---|
269 |
|
---|
270 | os.symlink(basename(ABSTFN) + "a/b", ABSTFN+"a")
|
---|
271 | self.assertEqual(realpath(ABSTFN+"a"), ABSTFN+"a/b")
|
---|
272 |
|
---|
273 | os.symlink("../" + basename(dirname(ABSTFN)) + "/" +
|
---|
274 | basename(ABSTFN) + "c", ABSTFN+"c")
|
---|
275 | self.assertEqual(realpath(ABSTFN+"c"), ABSTFN+"c")
|
---|
276 |
|
---|
277 | # Test using relative path as well.
|
---|
278 | os.chdir(dirname(ABSTFN))
|
---|
279 | self.assertEqual(realpath(basename(ABSTFN)), ABSTFN)
|
---|
280 | finally:
|
---|
281 | os.chdir(old_path)
|
---|
282 | test_support.unlink(ABSTFN)
|
---|
283 | test_support.unlink(ABSTFN+"1")
|
---|
284 | test_support.unlink(ABSTFN+"2")
|
---|
285 | test_support.unlink(ABSTFN+"y")
|
---|
286 | test_support.unlink(ABSTFN+"c")
|
---|
287 | test_support.unlink(ABSTFN+"a")
|
---|
288 |
|
---|
289 | def test_realpath_repeated_indirect_symlinks(self):
|
---|
290 | # Issue #6975.
|
---|
291 | try:
|
---|
292 | os.mkdir(ABSTFN)
|
---|
293 | os.symlink('../' + basename(ABSTFN), ABSTFN + '/self')
|
---|
294 | os.symlink('self/self/self', ABSTFN + '/link')
|
---|
295 | self.assertEqual(realpath(ABSTFN + '/link'), ABSTFN)
|
---|
296 | finally:
|
---|
297 | test_support.unlink(ABSTFN + '/self')
|
---|
298 | test_support.unlink(ABSTFN + '/link')
|
---|
299 | safe_rmdir(ABSTFN)
|
---|
300 |
|
---|
301 | def test_realpath_deep_recursion(self):
|
---|
302 | depth = 10
|
---|
303 | old_path = abspath('.')
|
---|
304 | try:
|
---|
305 | os.mkdir(ABSTFN)
|
---|
306 | for i in range(depth):
|
---|
307 | os.symlink('/'.join(['%d' % i] * 10), ABSTFN + '/%d' % (i + 1))
|
---|
308 | os.symlink('.', ABSTFN + '/0')
|
---|
309 | self.assertEqual(realpath(ABSTFN + '/%d' % depth), ABSTFN)
|
---|
310 |
|
---|
311 | # Test using relative path as well.
|
---|
312 | os.chdir(ABSTFN)
|
---|
313 | self.assertEqual(realpath('%d' % depth), ABSTFN)
|
---|
314 | finally:
|
---|
315 | os.chdir(old_path)
|
---|
316 | for i in range(depth + 1):
|
---|
317 | test_support.unlink(ABSTFN + '/%d' % i)
|
---|
318 | safe_rmdir(ABSTFN)
|
---|
319 |
|
---|
320 | def test_realpath_resolve_parents(self):
|
---|
321 | # We also need to resolve any symlinks in the parents of a relative
|
---|
322 | # path passed to realpath. E.g.: current working directory is
|
---|
323 | # /usr/doc with 'doc' being a symlink to /usr/share/doc. We call
|
---|
324 | # realpath("a"). This should return /usr/share/doc/a/.
|
---|
325 | try:
|
---|
326 | old_path = abspath('.')
|
---|
327 | os.mkdir(ABSTFN)
|
---|
328 | os.mkdir(ABSTFN + "/y")
|
---|
329 | os.symlink(ABSTFN + "/y", ABSTFN + "/k")
|
---|
330 |
|
---|
331 | os.chdir(ABSTFN + "/k")
|
---|
332 | self.assertEqual(realpath("a"), ABSTFN + "/y/a")
|
---|
333 | finally:
|
---|
334 | os.chdir(old_path)
|
---|
335 | test_support.unlink(ABSTFN + "/k")
|
---|
336 | safe_rmdir(ABSTFN + "/y")
|
---|
337 | safe_rmdir(ABSTFN)
|
---|
338 |
|
---|
339 | def test_realpath_resolve_before_normalizing(self):
|
---|
340 | # Bug #990669: Symbolic links should be resolved before we
|
---|
341 | # normalize the path. E.g.: if we have directories 'a', 'k' and 'y'
|
---|
342 | # in the following hierarchy:
|
---|
343 | # a/k/y
|
---|
344 | #
|
---|
345 | # and a symbolic link 'link-y' pointing to 'y' in directory 'a',
|
---|
346 | # then realpath("link-y/..") should return 'k', not 'a'.
|
---|
347 | try:
|
---|
348 | old_path = abspath('.')
|
---|
349 | os.mkdir(ABSTFN)
|
---|
350 | os.mkdir(ABSTFN + "/k")
|
---|
351 | os.mkdir(ABSTFN + "/k/y")
|
---|
352 | os.symlink(ABSTFN + "/k/y", ABSTFN + "/link-y")
|
---|
353 |
|
---|
354 | # Absolute path.
|
---|
355 | self.assertEqual(realpath(ABSTFN + "/link-y/.."), ABSTFN + "/k")
|
---|
356 | # Relative path.
|
---|
357 | os.chdir(dirname(ABSTFN))
|
---|
358 | self.assertEqual(realpath(basename(ABSTFN) + "/link-y/.."),
|
---|
359 | ABSTFN + "/k")
|
---|
360 | finally:
|
---|
361 | os.chdir(old_path)
|
---|
362 | test_support.unlink(ABSTFN + "/link-y")
|
---|
363 | safe_rmdir(ABSTFN + "/k/y")
|
---|
364 | safe_rmdir(ABSTFN + "/k")
|
---|
365 | safe_rmdir(ABSTFN)
|
---|
366 |
|
---|
367 | def test_realpath_resolve_first(self):
|
---|
368 | # Bug #1213894: The first component of the path, if not absolute,
|
---|
369 | # must be resolved too.
|
---|
370 |
|
---|
371 | try:
|
---|
372 | old_path = abspath('.')
|
---|
373 | os.mkdir(ABSTFN)
|
---|
374 | os.mkdir(ABSTFN + "/k")
|
---|
375 | os.symlink(ABSTFN, ABSTFN + "link")
|
---|
376 | os.chdir(dirname(ABSTFN))
|
---|
377 |
|
---|
378 | base = basename(ABSTFN)
|
---|
379 | self.assertEqual(realpath(base + "link"), ABSTFN)
|
---|
380 | self.assertEqual(realpath(base + "link/k"), ABSTFN + "/k")
|
---|
381 | finally:
|
---|
382 | os.chdir(old_path)
|
---|
383 | test_support.unlink(ABSTFN + "link")
|
---|
384 | safe_rmdir(ABSTFN + "/k")
|
---|
385 | safe_rmdir(ABSTFN)
|
---|
386 |
|
---|
387 | def test_relpath(self):
|
---|
388 | (real_getcwd, os.getcwd) = (os.getcwd, lambda: r"/home/user/bar")
|
---|
389 | try:
|
---|
390 | curdir = os.path.split(os.getcwd())[-1]
|
---|
391 | self.assertRaises(ValueError, posixpath.relpath, "")
|
---|
392 | self.assertEqual(posixpath.relpath("a"), "a")
|
---|
393 | self.assertEqual(posixpath.relpath(posixpath.abspath("a")), "a")
|
---|
394 | self.assertEqual(posixpath.relpath("a/b"), "a/b")
|
---|
395 | self.assertEqual(posixpath.relpath("../a/b"), "../a/b")
|
---|
396 | self.assertEqual(posixpath.relpath("a", "../b"), "../"+curdir+"/a")
|
---|
397 | self.assertEqual(posixpath.relpath("a/b", "../c"), "../"+curdir+"/a/b")
|
---|
398 | self.assertEqual(posixpath.relpath("a", "b/c"), "../../a")
|
---|
399 | self.assertEqual(posixpath.relpath("a", "a"), ".")
|
---|
400 | self.assertEqual(posixpath.relpath("/foo/bar/bat", "/x/y/z"), '../../../foo/bar/bat')
|
---|
401 | self.assertEqual(posixpath.relpath("/foo/bar/bat", "/foo/bar"), 'bat')
|
---|
402 | self.assertEqual(posixpath.relpath("/foo/bar/bat", "/"), 'foo/bar/bat')
|
---|
403 | self.assertEqual(posixpath.relpath("/", "/foo/bar/bat"), '../../..')
|
---|
404 | self.assertEqual(posixpath.relpath("/foo/bar/bat", "/x"), '../foo/bar/bat')
|
---|
405 | self.assertEqual(posixpath.relpath("/x", "/foo/bar/bat"), '../../../x')
|
---|
406 | self.assertEqual(posixpath.relpath("/", "/"), '.')
|
---|
407 | self.assertEqual(posixpath.relpath("/a", "/a"), '.')
|
---|
408 | self.assertEqual(posixpath.relpath("/a/b", "/a/b"), '.')
|
---|
409 | finally:
|
---|
410 | os.getcwd = real_getcwd
|
---|
411 |
|
---|
412 |
|
---|
413 | class PosixCommonTest(test_genericpath.CommonTest):
|
---|
414 | pathmodule = posixpath
|
---|
415 | attributes = ['relpath', 'samefile', 'sameopenfile', 'samestat']
|
---|
416 |
|
---|
417 |
|
---|
418 | def test_main():
|
---|
419 | test_support.run_unittest(PosixPathTest, PosixCommonTest)
|
---|
420 |
|
---|
421 |
|
---|
422 | if __name__=="__main__":
|
---|
423 | test_main()
|
---|