Better test/debug for svn authz generation.

* parse arguments on the invocation command: -v, --test, --templates
* provide two levels of verbosity/debug-output, and set up the
  Authorization instance to deal with that.
* remove print() calls, replacing with .verbose1() calls
* when --test, then generate files and exit
diff --git a/authz.py b/authz.py
index d8bd703..c2d5b18 100755
--- a/authz.py
+++ b/authz.py
@@ -17,6 +17,7 @@
 
 import os.path
 import time
+import argparse
 
 import asfpy.pubsub
 import asfpy.syslog
@@ -41,26 +42,29 @@
     DN_GROUPS = 'ou=groups,dc=apache,dc=org'
     DN_SERVICES = 'ou=groups,ou=services,dc=apache,dc=org'
 
-    def __init__(self, cfg, debug=False):
+    def __init__(self, cfg, verbose=0):
         self.cfg = cfg
-        self.debug = debug
+
+        def verbose1(*args):
+            if verbose >= 1: print(*args)
+        def verbose2(*args):
+            if verbose >= 2: print(*args)
+        self.verbose1 = verbose1
+        self.verbose2 = verbose2
 
         # Gather up a bunch of changes, then write new files. We want to
         # avoid writing for each change. Gather them up for a bit of time,
         # then dump the group of changes into the new authz files.
         self.delay = cfg['config']['delay']
-        if debug:
-            print('DELAY:', self.delay)
+        self.verbose1('DELAY:', self.delay)
 
         url = cfg['config']['ldap']
-        if debug:
-            print('LDAP:', url)
+        self.verbose1('LDAP:', url)
 
-        if debug:
-            print('AUTH:', cfg['special']['auth'])
-            print('GROUPS:', cfg['special']['groups'])
-            print('SERVICES:', cfg['special']['services'])
-            print('EXPLICIT:', cfg['explicit'])
+        self.verbose1('AUTH:', cfg['special']['auth'])
+        self.verbose1('GROUPS:', cfg['special']['groups'])
+        self.verbose1('SERVICES:', cfg['special']['services'])
+        self.verbose1('EXPLICIT:', cfg['explicit'])
 
         special = { a: self.DN_AUTH for a in cfg['special']['auth'] }
         special.update((g, self.DN_GROUPS) for g in cfg['special']['groups'])
@@ -74,8 +78,7 @@
 
         turl = cfg['generate']['template_url']
         odir = cfg['generate']['output_dir']
-        if debug:
-            print(f'TURL: {turl}\nODIR: {odir}')
+        self.verbose1(f'TURL: {turl}\nODIR: {odir}')
 
         self.mappings = { }
         for name in cfg['generate']:
@@ -96,8 +99,7 @@
         self.write_signal = min(self.write_signal, time.time())
 
     def handle_commit(self, commit_info):
-        if self.debug:
-            print('COMMIT FILES:', commit_info['files'])
+        self.verbose1('COMMIT FILES:', commit_info['files'])
         ### check against cfg/commit/path
 
         self.write_needed()
@@ -105,8 +107,7 @@
     def write_files(self):
         self.write_signal = FAR_FUTURE
         t0 = time.time()
-        if self.debug:
-            print('WRITE_FILES: beginning at', t0)
+        self.verbose1('WRITE_FILES: beginning at', t0)
         for t, o in self.mappings.items():
             if t.startswith('/'):
                 # File path. Just read it.
@@ -114,8 +115,7 @@
             else:
                 template = requests.get(t, auth=self.auth, timeout=30).text
             self.gen.write_file(template.splitlines(), o)
-        if self.debug:
-            print(f'  DURATION: {time.time() - t0}')
+        self.verbose1(f'  DURATION: {time.time() - t0}')
 
     def handler(self, payload):
         # If a (re)write has been signaled, then wait for a bit before
@@ -128,8 +128,7 @@
         # What kind of packet/payload arrived from PUBSUB ?
 
         if 'stillalive' in payload:
-            if self.debug:
-                print('HEARTBEAT:', payload)
+            self.verbose1('HEARTBEAT:', payload)
         elif 'commit' in payload:
             self.handle_commit(payload['commit'])
         elif 'dn' in payload:
@@ -137,8 +136,7 @@
             # be incredibly difficult to map changes against what LDAP
             # records are needed by the authz files. So, just rebuild the
             # files, regardless.
-            if self.debug:
-                print('LDAP CHANGE:', payload['dn'])
+            self.verbose1('LDAP CHANGE:', payload['dn'])
             self.write_needed()
         else:
             # unknown payload. (???)
@@ -153,9 +151,16 @@
                                       raw=True)
 
 
-def main():
+def main(args):
     cfg = yaml.safe_load(open(CONFIG_FNAME))
-    authz = Authorization(cfg, debug=True)
+    authz = Authorization(cfg, args.verbose)
+
+    ### deal with args.templates
+
+    if args.test:
+        # Generate the files, then exit. No daemon.
+        authz.write_files()
+        return
 
     username = cfg['server']['username']
     password = cfg['server']['password']
@@ -166,8 +171,7 @@
     # FUTURE: can add more topics here.
 
     url = cfg['server']['url'] + ','.join(topics)
-    if authz.debug:
-        print('URL:', url)
+    authz.verbose1('URL:', url)
 
     # Run forever
     ### FUTURE: use asfpy.pubsub.listen_forever()
@@ -175,4 +179,17 @@
 
 
 if __name__ == '__main__':
-    main()
+    parser = argparse.ArgumentParser(description='Monitor/generate svn authz files.')
+    parser.add_argument('-v', '--verbose', action='count', default=0,
+                        help='Print more information during operation.')
+    parser.add_argument('--test', action='store_true',
+                        help='Run a test generation of the authz files.')
+    parser.add_argument('--templates',
+                        help='Directory containing the (locally-modified) templates.')
+    args = parser.parse_args()
+
+    # When testing, always produce some of the basic debug output.
+    if args.test:
+        args.verbose = max(1, args.verbose)
+
+    main(args)