commit f538f58df8c52e37511c84eedb5cd11467dcbf2d
parent 5d193d14d5afb0621c94dad47799f6fbda6b6d0a
Author: lash <dev@holbrook.no>
Date: Sun, 19 Mar 2023 10:47:31 +0000
WIP organize subcommands
Diffstat:
6 files changed, 247 insertions(+), 83 deletions(-)
diff --git a/piknik/cli/__init__.py b/piknik/cli/__init__.py
@@ -0,0 +1,18 @@
+# standard imports
+import os
+
+# local imports
+from piknik import Basket
+from piknik.store import FileStoreFactory
+
+
+class Context:
+
+ def __init__(self, arg, assembler, mode=0, gpg_home=os.environ.get('GPGHOME')):
+ self.issue_id = arg.issue_id
+ self.files_dir = arg.files_dir
+ #self.store_factory = FileStoreFactory(arg.d)
+ store_factory = FileStoreFactory(arg.d)
+ self.basket = Basket(store_factory)
+ self.gpg_home = gpg_home
+ assembler(self, arg)
diff --git a/piknik/cli/add.py b/piknik/cli/add.py
@@ -0,0 +1,30 @@
+# standard imports
+import sys
+
+# local imports
+from piknik import Issue
+
+ctx = None
+
+
+def subparser(argp):
+ arg = argp.add_parser('add')
+ arg.add_argument('title', type=str, nargs='*', help='issue title')
+ return argp
+
+
+def assembler(o, arg):
+ o.title = arg.title
+
+
+def main():
+ title = ''
+ for s in ctx.title:
+ if s == ' ':
+ continue
+ if title != '':
+ title += ' '
+ title += s
+ o = Issue(title)
+ v = ctx.basket.add(o)
+ sys.stdout.write(v + '\n')
diff --git a/piknik/cli/mod.py b/piknik/cli/mod.py
@@ -0,0 +1,77 @@
+ctx = None
+
+
+def subparser(argp):
+ arg = argp.add_parser('mod')
+ arg.add_argument('--accept', action='store_true', help='Accept proposed issue')
+ arg.add_argument('--block', action='store_true', help='Set issue as blocked')
+ arg.add_argument('--unblock', action='store_true', help='Set issue as unblocked')
+ arg.add_argument('--finish', action='store_true', help='Set issue as finished (alias of -s finish)')
+ arg.add_argument('-s', '--state', type=str, help='Move to state')
+ arg.add_argument('-t', '--tag', type=str, action='append', default=[], help='Add tag to issue')
+ arg.add_argument('-u', '--untag', type=str, action='append', default=[], help='Remove tag from issue')
+ #argp.add_argument('-f', '--file', type=str, action='append', help='Add message file part')
+ #argp.add_argument('-m', '--message', type=str, action='append', default=[], help='Add message text part')
+ arg.add_argument('-a', '--assign', type=str, action='append', default=[], help='Assign given identity to issue')
+ arg.add_argument('--unassign', type=str, action='append', default=[], help='Unassign given identity from issue')
+ arg.add_argument('-o', '--owner', type=str, help='Set given identity as owner of issue')
+ arg.add_argument('--dep', action='append', default=[], type=str, help='Set issue dependency')
+ arg.add_argument('--undep', action='append', default=[], type=str, help='Remove issue dependency')
+ return argp
+
+
+def assembler(o, arg):
+ o.owner = arg.owner
+ o.block = arg.block
+ o.unblock = arg.unblock
+ o.state = arg.state
+ o.finish = arg.finish
+ o.accept = arg.accept
+ o.tag = arg.tag
+ o.untag = arg.untag
+ o.assign = arg.assign
+ o.unassign = arg.unassign
+ o.dep = arg.dep
+ o.undep = arg.undep
+
+
+def main():
+ global ctx
+
+ o = ctx.basket.get(ctx.issue_id)
+
+ if ctx.block:
+ ctx.basket.block(ctx.issue_id)
+ elif ctx.unblock:
+ ctx.basket.unblock(ctx.issue_id)
+
+ if ctx.state != None:
+ m = getattr(ctx.basket, 'state_' + ctx.state)
+ m(ctx.issue_id)
+ elif ctx.finish:
+ ctx.basket.state_finish(ctx.issue_id)
+ elif ctx.accept:
+ if ctx.basket.get_state(ctx.issue_id) != 'PROPOSED':
+ raise ValueError('Issue already accepted')
+ ctx.basket.advance(ctx.issue_id)
+
+ for v in ctx.tag:
+ ctx.basket.tag(ctx.issue_id, v)
+
+ for v in ctx.untag:
+ ctx.basket.untag(ctx.issue_id, v)
+
+ for v in ctx.unassign:
+ ctx.basket.unassign(ctx.issue_id, v)
+
+ for v in ctx.assign:
+ ctx.basket.assign(ctx.issue_id, v)
+
+ for v in ctx.undep:
+ ctx.basket.undep(ctx.issue_id, v)
+
+ for v in ctx.dep:
+ ctx.basket.dep(ctx.issue_id, v)
+
+ if ctx.owner:
+ ctx.basket.owner(ctx.issue_id, ctx.owner)
diff --git a/piknik/cli/session.py b/piknik/cli/session.py
@@ -0,0 +1 @@
+
diff --git a/piknik/cli/show.py b/piknik/cli/show.py
@@ -0,0 +1,101 @@
+# standard imports
+import os
+import logging
+import importlib
+
+# local imports
+from piknik import Issue
+from piknik.crypto import PGPSigner
+
+ctx = None
+accumulator_f = None
+accumulator = None
+
+logg = logging.getLogger(__name__)
+
+
+
+def set_accumulator(ctx, issue_id=None):
+ global accumulator_f
+ global accumulator
+ global m
+ if ctx.files_dir != None:
+ fb = None
+ if issue_id == None:
+ fb = 'index.html'
+ else:
+ fb = issue_id + '.html'
+ fp = os.path.join(ctx.files_dir, fb)
+ accumulator_f = open(fp, 'w')
+ accumulator = m.Accumulator(w=accumulator_f)
+ return accumulator.add
+ return None
+
+
+def reset_accumulator():
+ global accumulator_f
+ global accumulator
+ if accumulator_f != None:
+ accumulator_f.close()
+ accumulator_f = None
+ issues = accumulator.issues
+ accumulator = None
+ return issues
+ return []
+
+
+def subparser(argp):
+ arg = argp.add_parser('show')
+ arg.add_argument('-r', '--renderer', type=str, default='default', help='Renderer module for output')
+ arg.add_argument('-s', '--state', type=str, action='append', default=[], help='Limit results to state(s)')
+ arg.add_argument('--show-finished', dest='show_finished', action='store_true', help='Include finished issues')
+ arg.add_argument('--reverse', action='store_true', help='Sort comments by oldest first')
+ return argp
+
+
+def assembler(o, arg):
+ o.renderer = arg.renderer
+
+
+def main():
+ global ctx
+
+ renderer_s = ctx.renderer
+ if renderer_s == 'default':
+ renderer_s = 'piknik.render.plain'
+ elif renderer_s == 'html':
+ renderer_s = 'piknik.render.html'
+
+ m = None
+ try:
+ m = importlib.import_module(renderer_s)
+ except ModuleNotFoundError:
+ renderer_s = 'piknik.render.' + renderer_s
+ m = importlib.import_module(renderer_s)
+
+ accumulator = None
+ accumulator_f = None
+
+ issues = []
+ if ctx.issue_id:
+ issues.append(ctx.issue_id)
+
+ if ctx.issue_id == None:
+ accumulator = set_accumulator(ctx)
+ renderer = m.Renderer(ctx.basket, accumulator=accumulator)
+ renderer.apply()
+ issues = reset_accumulator()
+
+ for issue_id in issues:
+ accumulator = set_accumulator(ctx, issue_id=issue_id)
+ issue = ctx.basket.get(issue_id)
+ tags = ctx.basket.tags(issue_id)
+ state = ctx.basket.get_state(issue_id)
+ verifier = PGPSigner(home_dir=ctx.gpg_home, skip_verify=False)
+ renderer = m.Renderer(ctx.basket, wrapper=verifier, accumulator=accumulator)
+
+ renderer.apply_begin()
+ renderer.apply_issue(state, issue, tags)
+ renderer.apply_end()
+
+ reset_accumulator()
diff --git a/piknik/runnable/show.py b/piknik/runnable/show.py
@@ -10,10 +10,10 @@ from email.utils import parsedate_to_datetime
import importlib
# local imports
-from piknik import Basket
-from piknik import Issue
-from piknik.store import FileStoreFactory
-from piknik.crypto import PGPSigner
+from piknik.cli import Context
+from piknik.cli.show import subparser as subparser_show
+from piknik.cli.mod import subparser as subparser_mod
+from piknik.cli.add import subparser as subparser_add
logging.basicConfig(level=logging.WARNING)
logg = logging.getLogger()
@@ -22,88 +22,25 @@ argp = argparse.ArgumentParser()
argp.add_argument('-d', type=str, help='Data directory')
argp.add_argument('-f', '--files', dest='f', action='store_true', help='Save attachments to filesystem')
argp.add_argument('-o', '--files-dir', dest='files_dir', type=str, help='Directory to output saved files to')
-argp.add_argument('-r', '--renderer', type=str, default='default', help='Renderer module for output')
-argp.add_argument('-s', '--state', type=str, action='append', default=[], help='Limit results to state(s)')
-argp.add_argument('--show-finished', dest='show_finished', action='store_true', help='Include finished issues')
-#argp.add_argument('--reverse', action='store_true', help='Sort comments by oldest first')
-argp.add_argument('issue_id', type=str, nargs='?', default=None, help='Issue id to show')
-arg = argp.parse_args(sys.argv[1:])
-
-store_factory = FileStoreFactory(arg.d)
-basket = Basket(store_factory)
-
-gpg_home = os.environ.get('GPGHOME')
+argp.add_argument('-i','--issue-id', type=str, help='Issue id to show')
-renderer_s = arg.renderer
-if renderer_s == 'default':
- renderer_s = 'piknik.render.plain'
-elif renderer_s == 'html':
- renderer_s = 'piknik.render.html'
+argsub = argp.add_subparsers(title='subcommand', dest='subcmd')
+argsub = subparser_show(argsub)
+argsub = subparser_mod(argsub)
+argsub = subparser_add(argsub)
+arg = argp.parse_args(sys.argv[1:])
m = None
-try:
- m = importlib.import_module(renderer_s)
-except ModuleNotFoundError:
- renderer_s = 'piknik.render.' + renderer_s
- m = importlib.import_module(renderer_s)
-
-accumulator = None
-accumulator_f = None
-
-def set_accumulator(issue_id=None):
- global accumulator_f
- global accumulator
- global m
- if arg.files_dir != None:
- fb = None
- if issue_id == None:
- fb = 'index.html'
- else:
- fb = issue_id + '.html'
- fp = os.path.join(arg.files_dir, fb)
- accumulator_f = open(fp, 'w')
- accumulator = m.Accumulator(w=accumulator_f)
- return accumulator.add
- return None
-
-
-def reset_accumulator():
- global accumulator_f
- global accumulator
- if accumulator_f != None:
- accumulator_f.close()
- accumulator_f = None
- issues = accumulator.issues
- accumulator = None
- return issues
- return []
-
-
-def main():
- issues = []
- if arg.issue_id:
- issues.append(arg.issue_id)
-
- if arg.issue_id == None:
- accumulator = set_accumulator()
- renderer = m.Renderer(basket, accumulator=accumulator)
- renderer.apply()
- issues = reset_accumulator()
-
- for issue_id in issues:
- accumulator = set_accumulator(issue_id=issue_id)
- issue = basket.get(issue_id)
- tags = basket.tags(issue_id)
- state = basket.get_state(issue_id)
- verifier = PGPSigner(home_dir=gpg_home, skip_verify=False)
- renderer = m.Renderer(basket, wrapper=verifier, accumulator=accumulator)
+if arg.subcmd == 'show':
+ m = importlib.import_module('piknik.cli.show')
+elif arg.subcmd == 'mod':
+ m = importlib.import_module('piknik.cli.mod')
+elif arg.subcmd == 'add':
+ m = importlib.import_module('piknik.cli.add')
+else:
+ raise ValueError('invalid subcommand: ' + arg.subcmd)
- renderer.apply_begin()
- renderer.apply_issue(state, issue, tags)
- renderer.apply_end()
-
- reset_accumulator()
-
+m.ctx = Context(arg, m.assembler)
if __name__ == '__main__':
- main()
+ m.main()