Skip to content

Commit 5f2ea13

Browse files
committed
add pragma command to roundup-admin
Added basic pragma command. Can assign settings, list settings. Most settings are not yet implemented. Only the pragma command respects unhidden pragma settings at this point. Also added tests, doc updates for roundup-admin. CHANGES.txt not updated because currently only pragma references the unhidden settings. Also fixed a couple of long lines.
1 parent 3799ae9 commit 5f2ea13

File tree

4 files changed

+299
-12
lines changed

4 files changed

+299
-12
lines changed

doc/user_guide.txt

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -456,7 +456,7 @@ registration confirmation.
456456
If the subject line contains a prefix in ``[square brackets]`` then
457457
we're looking at case 3 or 4 above. Spaces are allowed inside the
458458
brackets and after the class item name. So ``[issue2]`` and
459-
``[ issue 2 ]`` are treted the same where any whitespace is optional.
459+
``[ issue 2 ]`` are treated the same where any white space is optional.
460460
Any "re:" or "fwd:" prefixes are stripped off the subject line before
461461
we start looking for real information.
462462

@@ -767,6 +767,8 @@ The basic usage is::
767767
-S <string> -- when outputting lists of data, string-separate them
768768
-s -- when outputting lists of data, space-separate them.
769769
Same as '-S " "'.
770+
-V -- be verbose when importing
771+
-v -- report Roundup and Python versions (and quit)
770772

771773
Only one of -s, -c or -S can be specified.
772774

@@ -780,26 +782,35 @@ The basic usage is::
780782
commit
781783
create classname property=value ...
782784
display designator[,designator]*
783-
export [class[,class]] export_dir
785+
export [[-]class[,class]] export_dir
786+
exporttables [[-]class[,class]] export_dir
787+
filter classname propname=value ...
784788
find classname propname=value ...
789+
genconfig <filename>
785790
get property designator[,designator]*
786791
help topic
787-
history designator
792+
history designator [skipquiet]
788793
import import_dir
794+
importtables export_dir
789795
initialise [adminpw]
790-
install [template [backend [admin password]]]
796+
install [template [backend [key=val[,key=val]]]]
791797
list classname [property]
798+
migrate
792799
pack period | date
793-
reindex
800+
perftest [mode] [arguments]*
801+
pragma setting=value
802+
reindex [classname|designator]*
803+
restore designator[,designator]*
794804
retire designator[,designator]*
795805
rollback
796806
security [Role name]
797807
set items property=value property=value ...
798808
specification classname
799809
table classname [property[,property]*]
800-
Commands may be abbreviated as long as the abbreviation matches only one
801-
command, e.g. l == li == lis == list.
802-
810+
templates [trace_search]
811+
updateconfig <filename>
812+
Commands may be abbreviated as long as the abbreviation
813+
matches only one command, e.g. l == li == lis == list.
803814

804815
All commands (except help) require a tracker specifier. This is just the
805816
path to the roundup tracker you're working with. A roundup tracker is

roundup/admin.py

Lines changed: 98 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,31 @@ def __init__(self):
102102
self.db = None
103103
self.db_uncommitted = False
104104
self.force = None
105+
self.settings = {
106+
'display_protected': False,
107+
'indexer_backend': "as set in config.ini",
108+
'_reopen_tracker': False,
109+
'show_retired': False,
110+
'verbose': False,
111+
'_inttest': 3,
112+
'_floattest': 3.5,
113+
}
114+
self.settings_help = {
115+
'display_protected':
116+
_("Have 'display designator' show protected fields: creator. NYI"),
117+
118+
'indexer_backend':
119+
_("Set indexer to use when running 'reindex' NYI"),
120+
121+
'_reopen_tracker':
122+
_("Force reopening of tracker when running each command."),
123+
124+
'show_retired': _("Show retired items in table, list etc. NYI"),
125+
'verbose': _("Enable verbose output: tracing, descriptions..."),
126+
127+
'_inttest': "Integer valued setting. For testing only.",
128+
'_floattest': "Float valued setting. For testing only.",
129+
}
105130

106131
def get_class(self, classname):
107132
"""Get the class - raise an exception if it doesn't exist.
@@ -440,8 +465,9 @@ def do_create(self, args):
440465
if value:
441466
props[key] = value
442467
else:
443-
value = self.my_input(_('%(propname)s (%(proptype)s): ') % {
444-
'propname': key.capitalize(), 'proptype': name})
468+
value = self.my_input(_(
469+
'%(propname)s (%(proptype)s): ') % {
470+
'propname': key.capitalize(), 'proptype': name})
445471
if value:
446472
props[key] = value
447473
else:
@@ -797,8 +823,7 @@ def do_genconfig(self, args, update=False):
797823
"old_number":
798824
config.PASSWORD_PBKDF2_DEFAULT_ROUNDS,
799825
"new_number": default_ppdr
800-
}
801-
)
826+
})
802827
config.PASSWORD_PBKDF2_DEFAULT_ROUNDS = default_ppdr
803828

804829
if config.PASSWORD_PBKDF2_DEFAULT_ROUNDS < default_ppdr:
@@ -1435,6 +1460,75 @@ def do_perftest(self, args):
14351460
{"time": toc-tic, "scheme": props['scheme'],
14361461
"rounds": rounds})
14371462

1463+
def do_pragma(self, args):
1464+
''"""Usage: pragma setting=value | 'list'
1465+
Set internal admin settings to a value. E.G.
1466+
1467+
pragma verbose=True
1468+
pragma verbose=yes
1469+
pragma verbose=on
1470+
pragma verbose=1
1471+
1472+
will turn on verbose mode for roundup-admin.
1473+
1474+
pragma list
1475+
1476+
will show all settings and their current values. If verbose
1477+
is enabled hidden settings and descriptions will be shown.
1478+
"""
1479+
1480+
if len(args) < 1:
1481+
raise UsageError(_('Not enough arguments supplied'))
1482+
1483+
try:
1484+
(setting, value) = args[0].split("=", 1)
1485+
except ValueError:
1486+
if args[0] != "list":
1487+
raise UsageError(_(
1488+
'Argument must be setting=value, was given: %s.') %
1489+
args[0])
1490+
else:
1491+
print(_("Current settings and values "
1492+
"(NYI - not yet implemented):"))
1493+
is_verbose = self.settings['verbose']
1494+
for key in sorted(list(self.settings.keys())):
1495+
if key.startswith('_') and not is_verbose:
1496+
continue
1497+
print(" %s=%s" % (key, self.settings[key]))
1498+
if is_verbose:
1499+
print(" %s" % self.settings_help[key])
1500+
1501+
return
1502+
1503+
if setting not in self.settings:
1504+
raise UsageError(_('Unknown setting %s.') % setting)
1505+
if type(self.settings[setting]) is bool:
1506+
value = value.lower()
1507+
if value in ("yes", "true", "on", "1"):
1508+
value = True
1509+
elif value in ("no", "false", "off", "0"):
1510+
value = False
1511+
else:
1512+
raise UsageError(_(
1513+
'Incorrect value for boolean setting %(setting)s: '
1514+
'%(value)s.') % {"setting": setting, "value": value})
1515+
elif type(self.settings[setting]) is int:
1516+
try:
1517+
_val = int(value)
1518+
except ValueError:
1519+
raise UsageError(_(
1520+
'Incorrect value for integer setting %(setting)s: '
1521+
'%(value)s.') % {"setting": setting, "value": value})
1522+
value = _val
1523+
elif type(self.settings[setting]) is str:
1524+
pass
1525+
else:
1526+
raise UsageError(_('Internal error: pragma can not handle '
1527+
'values of type: %s') %
1528+
type(self.settings[setting]).__name__)
1529+
1530+
self.settings[setting] = value
1531+
14381532
designator_re = re.compile('([A-Za-z]+)([0-9]+)')
14391533

14401534
def do_reindex(self, args, desre=designator_re):

share/man/man1/roundup-admin.1

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,21 @@ before a certain date.
205205
Run performance test. For example test the effect
206206
of changing password hashing parameters.
207207
.TP
208+
\fBpragma\fP \fIsetting=value\fP|\fBlist\fP
209+
Set internal settings to a value. E.G.
210+
211+
pragma verbose=True
212+
pragma verbose=yes
213+
pragma verbose=on
214+
pragma verbose=1
215+
216+
will turn on verbose mode for roundup-admin.
217+
218+
pragma list
219+
220+
will show all settings and their current values. If verbose
221+
is enabled hidden settings and descriptions will be shown.
222+
.TP
208223
\fBreindex\fP \fI[classname|designator]*\fP
209224
This will re-generate the search indexes for a tracker.
210225
.TP

test/test_admin.py

Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -803,6 +803,173 @@ def testFilter(self):
803803
print(err.getvalue().strip())
804804
self.assertEqual(out, "issue1:issue2")
805805

806+
def testPragma(self):
807+
"""Uses interactive mode since pragmas only apply when using multiple
808+
commands.
809+
"""
810+
if self.backend not in ['anydbm']:
811+
self.skipTest("For speed only run test with anydbm.")
812+
813+
orig_input = AdminTool.my_input
814+
815+
for i in ["oN", "1", "yeS", "True"]:
816+
inputs = iter(["pragma verbose=%s" % i, "pragma list", "quit"])
817+
AdminTool.my_input = lambda _self, _prompt: next(inputs)
818+
819+
self.install_init()
820+
self.admin=AdminTool()
821+
sys.argv=['main', '-i', self.dirname]
822+
823+
with captured_output() as (out, err):
824+
ret = self.admin.main()
825+
826+
out = out.getvalue().strip().split('\n')
827+
828+
print(ret)
829+
self.assertTrue(ret == 0)
830+
expected = ' verbose=True'
831+
self.assertIn(expected, out)
832+
self.assertIn('descriptions...', out[-1])
833+
834+
# -----
835+
for i in ["oFf", "0", "NO", "FalSe"]:
836+
inputs = iter(["pragma verbose=true", "pragma verbose=%s" % i,
837+
"pragma list", "quit"])
838+
AdminTool.my_input = lambda _self, _prompt: next(inputs)
839+
840+
self.install_init()
841+
self.admin=AdminTool()
842+
sys.argv=['main', '-i', self.dirname]
843+
844+
with captured_output() as (out, err):
845+
ret = self.admin.main()
846+
847+
out = out.getvalue().strip().split('\n')
848+
849+
print(ret)
850+
self.assertTrue(ret == 0)
851+
expected = ' verbose=False'
852+
self.assertIn(expected, out)
853+
854+
# ----- test syntax errors
855+
inputs = iter(["pragma", "pragma arg",
856+
"pragma foo=3","quit"])
857+
AdminTool.my_input = lambda _self, _prompt: next(inputs)
858+
859+
self.install_init()
860+
self.admin=AdminTool()
861+
sys.argv=['main', '-i', self.dirname]
862+
863+
with captured_output() as (out, err):
864+
ret = self.admin.main()
865+
866+
out = out.getvalue().strip().split('\n')
867+
868+
print(ret)
869+
self.assertTrue(ret == 0)
870+
expected = 'Error: Not enough arguments supplied'
871+
self.assertIn(expected, out)
872+
expected = 'Error: Argument must be setting=value, was given: arg.'
873+
self.assertIn(expected, out)
874+
expected = 'Error: Unknown setting foo.'
875+
self.assertIn(expected, out)
876+
877+
# -----
878+
inputs = iter(["pragma verbose=foo", "quit"])
879+
AdminTool.my_input = lambda _self, _prompt: next(inputs)
880+
881+
self.install_init()
882+
self.admin=AdminTool()
883+
sys.argv=['main', '-i', self.dirname]
884+
885+
with captured_output() as (out, err):
886+
ret = self.admin.main()
887+
888+
out = out.getvalue().strip().split('\n')
889+
890+
print(ret)
891+
self.assertTrue(ret == 0)
892+
expected = 'Error: Incorrect value for boolean setting verbose: foo.'
893+
self.assertIn(expected, out)
894+
895+
# -----
896+
inputs = iter(["pragma verbose=on", "pragma _inttest=5",
897+
"pragma list", "quit"])
898+
AdminTool.my_input = lambda _self, _prompt: next(inputs)
899+
900+
self.install_init()
901+
self.admin=AdminTool()
902+
sys.argv=['main', '-i', self.dirname]
903+
904+
with captured_output() as (out, err):
905+
ret = self.admin.main()
906+
907+
out = out.getvalue().strip().split('\n')
908+
909+
print(ret)
910+
self.assertTrue(ret == 0)
911+
expected = ' _inttest=5'
912+
self.assertIn(expected, out)
913+
self.assertIn('descriptions...', out[-1])
914+
915+
916+
# -----
917+
inputs = iter(["pragma verbose=on", "pragma _inttest=fred",
918+
"pragma list", "quit"])
919+
AdminTool.my_input = lambda _self, _prompt: next(inputs)
920+
921+
self.install_init()
922+
self.admin=AdminTool()
923+
sys.argv=['main', '-i', self.dirname]
924+
925+
with captured_output() as (out, err):
926+
ret = self.admin.main()
927+
928+
out = out.getvalue().strip().split('\n')
929+
930+
print(ret)
931+
self.assertTrue(ret == 0)
932+
expected = 'Error: Incorrect value for integer setting _inttest: fred.'
933+
self.assertIn(expected, out)
934+
self.assertIn('descriptions...', out[-1])
935+
936+
# -----
937+
inputs = iter(["pragma indexer_backend=whoosh", "pragma list",
938+
"quit"])
939+
AdminTool.my_input = lambda _self, _prompt: next(inputs)
940+
941+
self.install_init()
942+
self.admin=AdminTool()
943+
sys.argv=['main', '-i', self.dirname]
944+
945+
with captured_output() as (out, err):
946+
ret = self.admin.main()
947+
948+
out = out.getvalue().strip().split('\n')
949+
950+
print(ret)
951+
expected = ' indexer_backend=whoosh'
952+
self.assertIn(expected, out)
953+
954+
# -----
955+
inputs = iter(["pragma _floattest=4.5", "quit"])
956+
AdminTool.my_input = lambda _self, _prompt: next(inputs)
957+
958+
self.install_init()
959+
self.admin=AdminTool()
960+
sys.argv=['main', '-i', self.dirname]
961+
962+
with captured_output() as (out, err):
963+
ret = self.admin.main()
964+
965+
out = out.getvalue().strip().split('\n')
966+
967+
print(ret)
968+
expected = 'Error: Internal error: pragma can not handle values of type: float'
969+
self.assertIn(expected, out)
970+
971+
# -----
972+
AdminTool.my_input = orig_input
806973

807974
def disabletestHelpInitopts(self):
808975

0 commit comments

Comments
 (0)