Mercurial > p > roundup > code
annotate test/test_userauditor.py @ 8168:3f0f4746dc7e
issue2551370 - prefix session cookie with __Secure- over https
Limit use of roundup session cookie to HTTPS protocol by adding
__Secure- prefix. Automatic testing includes http behavior only.
Https behavious has been manually tested only. Need to be able to spin
up an https server using wsgiref to test https behavior in CI.
issue 2551373 opened to track automatic testing of https behavior.
| author | John Rouillard <rouilj@ieee.org> |
|---|---|
| date | Tue, 26 Nov 2024 17:11:13 -0500 |
| parents | 89aa919997c0 |
| children |
| rev | line source |
|---|---|
|
3873
4d1928ce993e
more small userauditor changes and a unittest
Justus Pendleton <jpend@users.sourceforge.net>
parents:
diff
changeset
|
1 import os, unittest, shutil |
|
5036
380d8d8b30a3
Replace existing run_tests.py script with a pytest script
John Kristensen <john@jerrykan.com>
parents:
4781
diff
changeset
|
2 |
|
5388
d26921b851c3
Python 3 preparation: make relative imports explicit.
Joseph Myers <jsm@polyomino.org.uk>
parents:
5248
diff
changeset
|
3 from .db_test_base import setupTracker |
|
5036
380d8d8b30a3
Replace existing run_tests.py script with a pytest script
John Kristensen <john@jerrykan.com>
parents:
4781
diff
changeset
|
4 from .test_dates import skip_pytz |
|
380d8d8b30a3
Replace existing run_tests.py script with a pytest script
John Kristensen <john@jerrykan.com>
parents:
4781
diff
changeset
|
5 |
|
3873
4d1928ce993e
more small userauditor changes and a unittest
Justus Pendleton <jpend@users.sourceforge.net>
parents:
diff
changeset
|
6 |
|
4d1928ce993e
more small userauditor changes and a unittest
Justus Pendleton <jpend@users.sourceforge.net>
parents:
diff
changeset
|
7 class UserAuditorTest(unittest.TestCase): |
|
4d1928ce993e
more small userauditor changes and a unittest
Justus Pendleton <jpend@users.sourceforge.net>
parents:
diff
changeset
|
8 def setUp(self): |
|
4d1928ce993e
more small userauditor changes and a unittest
Justus Pendleton <jpend@users.sourceforge.net>
parents:
diff
changeset
|
9 self.dirname = '_test_user_auditor' |
|
4d1928ce993e
more small userauditor changes and a unittest
Justus Pendleton <jpend@users.sourceforge.net>
parents:
diff
changeset
|
10 self.instance = setupTracker(self.dirname) |
|
4d1928ce993e
more small userauditor changes and a unittest
Justus Pendleton <jpend@users.sourceforge.net>
parents:
diff
changeset
|
11 self.db = self.instance.open('admin') |
| 4781 | 12 self.db.tx_Source = "cli" |
|
3873
4d1928ce993e
more small userauditor changes and a unittest
Justus Pendleton <jpend@users.sourceforge.net>
parents:
diff
changeset
|
13 |
|
4d1928ce993e
more small userauditor changes and a unittest
Justus Pendleton <jpend@users.sourceforge.net>
parents:
diff
changeset
|
14 self.db.user.create(username='kyle', address='kyle@example.com', |
|
4d1928ce993e
more small userauditor changes and a unittest
Justus Pendleton <jpend@users.sourceforge.net>
parents:
diff
changeset
|
15 realname='Kyle Broflovski', roles='User') |
|
4d1928ce993e
more small userauditor changes and a unittest
Justus Pendleton <jpend@users.sourceforge.net>
parents:
diff
changeset
|
16 |
|
4d1928ce993e
more small userauditor changes and a unittest
Justus Pendleton <jpend@users.sourceforge.net>
parents:
diff
changeset
|
17 def tearDown(self): |
|
4d1928ce993e
more small userauditor changes and a unittest
Justus Pendleton <jpend@users.sourceforge.net>
parents:
diff
changeset
|
18 self.db.close() |
|
4d1928ce993e
more small userauditor changes and a unittest
Justus Pendleton <jpend@users.sourceforge.net>
parents:
diff
changeset
|
19 try: |
|
4d1928ce993e
more small userauditor changes and a unittest
Justus Pendleton <jpend@users.sourceforge.net>
parents:
diff
changeset
|
20 shutil.rmtree(self.dirname) |
|
5248
198b6e810c67
Use Python-3-compatible 'as' syntax for except statements
Eric S. Raymond <esr@thyrsus.com>
parents:
5105
diff
changeset
|
21 except OSError as error: |
|
3873
4d1928ce993e
more small userauditor changes and a unittest
Justus Pendleton <jpend@users.sourceforge.net>
parents:
diff
changeset
|
22 if error.errno not in (errno.ENOENT, errno.ESRCH): raise |
|
4d1928ce993e
more small userauditor changes and a unittest
Justus Pendleton <jpend@users.sourceforge.net>
parents:
diff
changeset
|
23 |
|
4d1928ce993e
more small userauditor changes and a unittest
Justus Pendleton <jpend@users.sourceforge.net>
parents:
diff
changeset
|
24 def testBadTimezones(self): |
|
4d1928ce993e
more small userauditor changes and a unittest
Justus Pendleton <jpend@users.sourceforge.net>
parents:
diff
changeset
|
25 self.assertRaises(ValueError, self.db.user.create, username='eric', timezone='24') |
|
4d1928ce993e
more small userauditor changes and a unittest
Justus Pendleton <jpend@users.sourceforge.net>
parents:
diff
changeset
|
26 |
|
4d1928ce993e
more small userauditor changes and a unittest
Justus Pendleton <jpend@users.sourceforge.net>
parents:
diff
changeset
|
27 userid = self.db.user.lookup('kyle') |
|
4d1928ce993e
more small userauditor changes and a unittest
Justus Pendleton <jpend@users.sourceforge.net>
parents:
diff
changeset
|
28 |
|
4d1928ce993e
more small userauditor changes and a unittest
Justus Pendleton <jpend@users.sourceforge.net>
parents:
diff
changeset
|
29 self.assertRaises(ValueError, self.db.user.set, userid, timezone='3000') |
|
4d1928ce993e
more small userauditor changes and a unittest
Justus Pendleton <jpend@users.sourceforge.net>
parents:
diff
changeset
|
30 self.assertRaises(ValueError, self.db.user.set, userid, timezone='24') |
|
4d1928ce993e
more small userauditor changes and a unittest
Justus Pendleton <jpend@users.sourceforge.net>
parents:
diff
changeset
|
31 self.assertRaises(ValueError, self.db.user.set, userid, timezone='-24') |
|
4d1928ce993e
more small userauditor changes and a unittest
Justus Pendleton <jpend@users.sourceforge.net>
parents:
diff
changeset
|
32 self.assertRaises(ValueError, self.db.user.set, userid, timezone='-3000') |
|
4d1928ce993e
more small userauditor changes and a unittest
Justus Pendleton <jpend@users.sourceforge.net>
parents:
diff
changeset
|
33 |
|
5036
380d8d8b30a3
Replace existing run_tests.py script with a pytest script
John Kristensen <john@jerrykan.com>
parents:
4781
diff
changeset
|
34 @skip_pytz |
|
380d8d8b30a3
Replace existing run_tests.py script with a pytest script
John Kristensen <john@jerrykan.com>
parents:
4781
diff
changeset
|
35 def testBadTimezonesPyTZ(self): |
|
380d8d8b30a3
Replace existing run_tests.py script with a pytest script
John Kristensen <john@jerrykan.com>
parents:
4781
diff
changeset
|
36 userid = self.db.user.lookup('kyle') |
|
380d8d8b30a3
Replace existing run_tests.py script with a pytest script
John Kristensen <john@jerrykan.com>
parents:
4781
diff
changeset
|
37 |
|
6381
89aa919997c0
ValueError replaces UnknownTimeZoneError in bad pytz timezone test
John Rouillard <rouilj@ieee.org>
parents:
6237
diff
changeset
|
38 self.assertRaises(KeyError, self.db.user.set, userid, |
|
5036
380d8d8b30a3
Replace existing run_tests.py script with a pytest script
John Kristensen <john@jerrykan.com>
parents:
4781
diff
changeset
|
39 timezone='MiddleOf/Nowhere') |
|
3873
4d1928ce993e
more small userauditor changes and a unittest
Justus Pendleton <jpend@users.sourceforge.net>
parents:
diff
changeset
|
40 |
|
4d1928ce993e
more small userauditor changes and a unittest
Justus Pendleton <jpend@users.sourceforge.net>
parents:
diff
changeset
|
41 def testGoodTimezones(self): |
|
4d1928ce993e
more small userauditor changes and a unittest
Justus Pendleton <jpend@users.sourceforge.net>
parents:
diff
changeset
|
42 self.db.user.create(username='test_user01', timezone='12') |
|
4d1928ce993e
more small userauditor changes and a unittest
Justus Pendleton <jpend@users.sourceforge.net>
parents:
diff
changeset
|
43 |
|
4d1928ce993e
more small userauditor changes and a unittest
Justus Pendleton <jpend@users.sourceforge.net>
parents:
diff
changeset
|
44 userid = self.db.user.lookup('kyle') |
|
4d1928ce993e
more small userauditor changes and a unittest
Justus Pendleton <jpend@users.sourceforge.net>
parents:
diff
changeset
|
45 |
|
4d1928ce993e
more small userauditor changes and a unittest
Justus Pendleton <jpend@users.sourceforge.net>
parents:
diff
changeset
|
46 # TODO: roundup should accept non-integer offsets since those are valid |
|
4d1928ce993e
more small userauditor changes and a unittest
Justus Pendleton <jpend@users.sourceforge.net>
parents:
diff
changeset
|
47 # this is the offset for Tehran, Iran |
|
4d1928ce993e
more small userauditor changes and a unittest
Justus Pendleton <jpend@users.sourceforge.net>
parents:
diff
changeset
|
48 #self.db.user.set(userid, timezone='3.5') |
|
4d1928ce993e
more small userauditor changes and a unittest
Justus Pendleton <jpend@users.sourceforge.net>
parents:
diff
changeset
|
49 |
|
4d1928ce993e
more small userauditor changes and a unittest
Justus Pendleton <jpend@users.sourceforge.net>
parents:
diff
changeset
|
50 self.db.user.set(userid, timezone='-23') |
|
4d1928ce993e
more small userauditor changes and a unittest
Justus Pendleton <jpend@users.sourceforge.net>
parents:
diff
changeset
|
51 self.db.user.set(userid, timezone='23') |
|
4d1928ce993e
more small userauditor changes and a unittest
Justus Pendleton <jpend@users.sourceforge.net>
parents:
diff
changeset
|
52 self.db.user.set(userid, timezone='0') |
|
4d1928ce993e
more small userauditor changes and a unittest
Justus Pendleton <jpend@users.sourceforge.net>
parents:
diff
changeset
|
53 |
|
5036
380d8d8b30a3
Replace existing run_tests.py script with a pytest script
John Kristensen <john@jerrykan.com>
parents:
4781
diff
changeset
|
54 @skip_pytz |
|
380d8d8b30a3
Replace existing run_tests.py script with a pytest script
John Kristensen <john@jerrykan.com>
parents:
4781
diff
changeset
|
55 def testGoodTimezonesPyTZ(self): |
|
380d8d8b30a3
Replace existing run_tests.py script with a pytest script
John Kristensen <john@jerrykan.com>
parents:
4781
diff
changeset
|
56 userid = self.db.user.lookup('kyle') |
|
380d8d8b30a3
Replace existing run_tests.py script with a pytest script
John Kristensen <john@jerrykan.com>
parents:
4781
diff
changeset
|
57 |
|
380d8d8b30a3
Replace existing run_tests.py script with a pytest script
John Kristensen <john@jerrykan.com>
parents:
4781
diff
changeset
|
58 self.db.user.create(username='test_user02', timezone='MST') |
|
380d8d8b30a3
Replace existing run_tests.py script with a pytest script
John Kristensen <john@jerrykan.com>
parents:
4781
diff
changeset
|
59 self.db.user.set(userid, timezone='US/Eastern') |
|
3873
4d1928ce993e
more small userauditor changes and a unittest
Justus Pendleton <jpend@users.sourceforge.net>
parents:
diff
changeset
|
60 |
|
4d1928ce993e
more small userauditor changes and a unittest
Justus Pendleton <jpend@users.sourceforge.net>
parents:
diff
changeset
|
61 def testBadEmailAddresses(self): |
|
4d1928ce993e
more small userauditor changes and a unittest
Justus Pendleton <jpend@users.sourceforge.net>
parents:
diff
changeset
|
62 userid = self.db.user.lookup('kyle') |
|
4d1928ce993e
more small userauditor changes and a unittest
Justus Pendleton <jpend@users.sourceforge.net>
parents:
diff
changeset
|
63 self.assertRaises(ValueError, self.db.user.set, userid, address='kyle @ example.com') |
|
3902
21420ba64b0d
fuller email validition (request [SF#216291])
Justus Pendleton <jpend@users.sourceforge.net>
parents:
3888
diff
changeset
|
64 self.assertRaises(ValueError, self.db.user.set, userid, address='one@example.com,two@example.com') |
|
21420ba64b0d
fuller email validition (request [SF#216291])
Justus Pendleton <jpend@users.sourceforge.net>
parents:
3888
diff
changeset
|
65 self.assertRaises(ValueError, self.db.user.set, userid, address='weird@@example.com') |
|
21420ba64b0d
fuller email validition (request [SF#216291])
Justus Pendleton <jpend@users.sourceforge.net>
parents:
3888
diff
changeset
|
66 self.assertRaises(ValueError, self.db.user.set, userid, address='embedded\nnewline@example.com') |
|
21420ba64b0d
fuller email validition (request [SF#216291])
Justus Pendleton <jpend@users.sourceforge.net>
parents:
3888
diff
changeset
|
67 # verify that we check alternates as well |
|
21420ba64b0d
fuller email validition (request [SF#216291])
Justus Pendleton <jpend@users.sourceforge.net>
parents:
3888
diff
changeset
|
68 self.assertRaises(ValueError, self.db.user.set, userid, alternate_addresses='kyle @ example.com') |
|
21420ba64b0d
fuller email validition (request [SF#216291])
Justus Pendleton <jpend@users.sourceforge.net>
parents:
3888
diff
changeset
|
69 # make sure we accept local style addresses |
|
21420ba64b0d
fuller email validition (request [SF#216291])
Justus Pendleton <jpend@users.sourceforge.net>
parents:
3888
diff
changeset
|
70 self.db.user.set(userid, address='kyle') |
|
21420ba64b0d
fuller email validition (request [SF#216291])
Justus Pendleton <jpend@users.sourceforge.net>
parents:
3888
diff
changeset
|
71 # verify we are case insensitive |
|
21420ba64b0d
fuller email validition (request [SF#216291])
Justus Pendleton <jpend@users.sourceforge.net>
parents:
3888
diff
changeset
|
72 self.db.user.set(userid, address='kyle@EXAMPLE.COM') |
|
3873
4d1928ce993e
more small userauditor changes and a unittest
Justus Pendleton <jpend@users.sourceforge.net>
parents:
diff
changeset
|
73 |
|
3888
4fcf7a52767e
fix [SF#611787]: ensure unique email addresses
Justus Pendleton <jpend@users.sourceforge.net>
parents:
3874
diff
changeset
|
74 def testUniqueEmailAddresses(self): |
|
3902
21420ba64b0d
fuller email validition (request [SF#216291])
Justus Pendleton <jpend@users.sourceforge.net>
parents:
3888
diff
changeset
|
75 self.db.user.create(username='kenny', address='kenny@example.com', alternate_addresses='sp_ken@example.com') |
|
3888
4fcf7a52767e
fix [SF#611787]: ensure unique email addresses
Justus Pendleton <jpend@users.sourceforge.net>
parents:
3874
diff
changeset
|
76 self.assertRaises(ValueError, self.db.user.create, username='test_user01', address='kenny@example.com') |
|
4fcf7a52767e
fix [SF#611787]: ensure unique email addresses
Justus Pendleton <jpend@users.sourceforge.net>
parents:
3874
diff
changeset
|
77 uid = self.db.user.create(username='eric', address='eric@example.com') |
|
4fcf7a52767e
fix [SF#611787]: ensure unique email addresses
Justus Pendleton <jpend@users.sourceforge.net>
parents:
3874
diff
changeset
|
78 self.assertRaises(ValueError, self.db.user.set, uid, address='kenny@example.com') |
|
4fcf7a52767e
fix [SF#611787]: ensure unique email addresses
Justus Pendleton <jpend@users.sourceforge.net>
parents:
3874
diff
changeset
|
79 |
|
3902
21420ba64b0d
fuller email validition (request [SF#216291])
Justus Pendleton <jpend@users.sourceforge.net>
parents:
3888
diff
changeset
|
80 # make sure we check alternates |
|
21420ba64b0d
fuller email validition (request [SF#216291])
Justus Pendleton <jpend@users.sourceforge.net>
parents:
3888
diff
changeset
|
81 self.assertRaises(ValueError, self.db.user.set, uid, address='kenny@example.com') |
|
21420ba64b0d
fuller email validition (request [SF#216291])
Justus Pendleton <jpend@users.sourceforge.net>
parents:
3888
diff
changeset
|
82 self.assertRaises(ValueError, self.db.user.set, uid, address='sp_ken@example.com') |
|
21420ba64b0d
fuller email validition (request [SF#216291])
Justus Pendleton <jpend@users.sourceforge.net>
parents:
3888
diff
changeset
|
83 self.assertRaises(ValueError, self.db.user.set, uid, alternate_addresses='kenny@example.com') |
|
21420ba64b0d
fuller email validition (request [SF#216291])
Justus Pendleton <jpend@users.sourceforge.net>
parents:
3888
diff
changeset
|
84 |
|
3873
4d1928ce993e
more small userauditor changes and a unittest
Justus Pendleton <jpend@users.sourceforge.net>
parents:
diff
changeset
|
85 def testBadRoles(self): |
|
4d1928ce993e
more small userauditor changes and a unittest
Justus Pendleton <jpend@users.sourceforge.net>
parents:
diff
changeset
|
86 userid = self.db.user.lookup('kyle') |
|
4d1928ce993e
more small userauditor changes and a unittest
Justus Pendleton <jpend@users.sourceforge.net>
parents:
diff
changeset
|
87 self.assertRaises(ValueError, self.db.user.set, userid, roles='BadRole') |
|
4d1928ce993e
more small userauditor changes and a unittest
Justus Pendleton <jpend@users.sourceforge.net>
parents:
diff
changeset
|
88 self.assertRaises(ValueError, self.db.user.set, userid, roles='User,BadRole') |
|
4d1928ce993e
more small userauditor changes and a unittest
Justus Pendleton <jpend@users.sourceforge.net>
parents:
diff
changeset
|
89 |
|
4d1928ce993e
more small userauditor changes and a unittest
Justus Pendleton <jpend@users.sourceforge.net>
parents:
diff
changeset
|
90 def testGoodRoles(self): |
|
3874
4c8d853017f2
strip rolename & fix rolename unittest
Justus Pendleton <jpend@users.sourceforge.net>
parents:
3873
diff
changeset
|
91 userid = self.db.user.lookup('kyle') |
|
3873
4d1928ce993e
more small userauditor changes and a unittest
Justus Pendleton <jpend@users.sourceforge.net>
parents:
diff
changeset
|
92 # make sure we handle commas in weird places |
|
4d1928ce993e
more small userauditor changes and a unittest
Justus Pendleton <jpend@users.sourceforge.net>
parents:
diff
changeset
|
93 self.db.user.set(userid, roles='User,') |
|
4d1928ce993e
more small userauditor changes and a unittest
Justus Pendleton <jpend@users.sourceforge.net>
parents:
diff
changeset
|
94 self.db.user.set(userid, roles=',User') |
|
4d1928ce993e
more small userauditor changes and a unittest
Justus Pendleton <jpend@users.sourceforge.net>
parents:
diff
changeset
|
95 # make sure we strip whitespace |
|
4d1928ce993e
more small userauditor changes and a unittest
Justus Pendleton <jpend@users.sourceforge.net>
parents:
diff
changeset
|
96 self.db.user.set(userid, roles=' User ') |
|
3874
4c8d853017f2
strip rolename & fix rolename unittest
Justus Pendleton <jpend@users.sourceforge.net>
parents:
3873
diff
changeset
|
97 # check for all-whitespace (treat as no role) |
|
4c8d853017f2
strip rolename & fix rolename unittest
Justus Pendleton <jpend@users.sourceforge.net>
parents:
3873
diff
changeset
|
98 self.db.user.set(userid, roles=' ') |
|
3873
4d1928ce993e
more small userauditor changes and a unittest
Justus Pendleton <jpend@users.sourceforge.net>
parents:
diff
changeset
|
99 |
|
5958
5148e46dd314
issue2550921 - prevent usernames with characters ',' and '<', '>'
John Rouillard <rouilj@ieee.org>
parents:
5388
diff
changeset
|
100 def testBadUsernames(self): |
|
5148e46dd314
issue2550921 - prevent usernames with characters ',' and '<', '>'
John Rouillard <rouilj@ieee.org>
parents:
5388
diff
changeset
|
101 ''' ky,le raises: |
|
5148e46dd314
issue2550921 - prevent usernames with characters ',' and '<', '>'
John Rouillard <rouilj@ieee.org>
parents:
5388
diff
changeset
|
102 ValueError: Username/Login Name must consist only of the letters a-z (any case), digits 0-9 and the symbols: @._-!+% |
|
5148e46dd314
issue2550921 - prevent usernames with characters ',' and '<', '>'
John Rouillard <rouilj@ieee.org>
parents:
5388
diff
changeset
|
103 ''' |
|
5148e46dd314
issue2550921 - prevent usernames with characters ',' and '<', '>'
John Rouillard <rouilj@ieee.org>
parents:
5388
diff
changeset
|
104 |
|
6237
0a37979bbd46
Verify , in username invalid; fix broken test
John Rouillard <rouilj@ieee.org>
parents:
5958
diff
changeset
|
105 for name in [ "ky'le", "ky<br>le", "ky,le" ]: |
|
5958
5148e46dd314
issue2550921 - prevent usernames with characters ',' and '<', '>'
John Rouillard <rouilj@ieee.org>
parents:
5388
diff
changeset
|
106 with self.assertRaises(ValueError) as ctx: |
|
5148e46dd314
issue2550921 - prevent usernames with characters ',' and '<', '>'
John Rouillard <rouilj@ieee.org>
parents:
5388
diff
changeset
|
107 self.db.user.create(username=name, |
|
5148e46dd314
issue2550921 - prevent usernames with characters ',' and '<', '>'
John Rouillard <rouilj@ieee.org>
parents:
5388
diff
changeset
|
108 address='kyle@example.com', |
|
5148e46dd314
issue2550921 - prevent usernames with characters ',' and '<', '>'
John Rouillard <rouilj@ieee.org>
parents:
5388
diff
changeset
|
109 realname='Kyle Broflovski', roles='User') |
|
6237
0a37979bbd46
Verify , in username invalid; fix broken test
John Rouillard <rouilj@ieee.org>
parents:
5958
diff
changeset
|
110 self.assertEqual(str(ctx.exception), "Username/Login Name must " |
|
5958
5148e46dd314
issue2550921 - prevent usernames with characters ',' and '<', '>'
John Rouillard <rouilj@ieee.org>
parents:
5388
diff
changeset
|
111 "consist only of the letters a-z (any case), " |
|
6237
0a37979bbd46
Verify , in username invalid; fix broken test
John Rouillard <rouilj@ieee.org>
parents:
5958
diff
changeset
|
112 "digits 0-9 and the symbols: @._-!+%") |
|
5958
5148e46dd314
issue2550921 - prevent usernames with characters ',' and '<', '>'
John Rouillard <rouilj@ieee.org>
parents:
5388
diff
changeset
|
113 |
|
5148e46dd314
issue2550921 - prevent usernames with characters ',' and '<', '>'
John Rouillard <rouilj@ieee.org>
parents:
5388
diff
changeset
|
114 self.db.user.create(username='rouilj-1+mya_ddr@users.example.com', |
|
5148e46dd314
issue2550921 - prevent usernames with characters ',' and '<', '>'
John Rouillard <rouilj@ieee.org>
parents:
5388
diff
changeset
|
115 address='kyle1@example.com', |
|
5148e46dd314
issue2550921 - prevent usernames with characters ',' and '<', '>'
John Rouillard <rouilj@ieee.org>
parents:
5388
diff
changeset
|
116 realname='Kyle Broflovski', roles='User') |
|
5148e46dd314
issue2550921 - prevent usernames with characters ',' and '<', '>'
John Rouillard <rouilj@ieee.org>
parents:
5388
diff
changeset
|
117 |
|
3873
4d1928ce993e
more small userauditor changes and a unittest
Justus Pendleton <jpend@users.sourceforge.net>
parents:
diff
changeset
|
118 # vim: filetype=python sts=4 sw=4 et si |
