piknik

Unnamed repository; edit this file 'description' to name the repository.
Info | Log | Files | Refs | README | LICENSE

commit 4c163f9e788ab323537df60336f54a471b68636e
parent a8a6074d4bcda4435b6457e1e57b0816c9135ae1
Author: lash <dev@holbrook.no>
Date:   Mon,  7 Nov 2022 00:26:37 +0000

Proper handle alias in persistent tag store

Diffstat:
Mpiknik/basket.py | 42+++++++++++++++++++++++++++++++-----------
Mpiknik/runnable/add.py | 2+-
Mpiknik/runnable/list.py | 2+-
Mpiknik/runnable/mod.py | 10+++++++++-
Mpiknik/store/__init__.py | 19+++++++++++++++++--
Mtests/test_store.py | 21+++++++++++++++++++--
Mtests/test_tag.py | 1+
7 files changed, 79 insertions(+), 18 deletions(-)

diff --git a/piknik/basket.py b/piknik/basket.py @@ -1,5 +1,7 @@ +# external imports import shep +# local imports from .error import DeadIssue from .issue import Issue @@ -16,12 +18,11 @@ class Basket: self.state.add('blocked') self.state.alias('doingblocked', self.state.DOING | self.state.BLOCKED) self.state.alias('pendingblocked', self.state.PENDING | self.state.BLOCKED) - self.limit = self.state.FINISHED - self.state.sync() - self.tags = state_factory.create_tags() + self.__tags = state_factory.create_tags() + self.__tags.sync(ignore_auto=False) self.issues_rev = {} @@ -95,14 +96,33 @@ class Basket: def tag(self, issue_id, tag): v = 0 try: - v = self.tags.from_name(tag) + v = self.__tags.from_name(tag) except AttributeError: - self.tags.add(tag) - v = self.tags.from_name(tag) - + self.__tags.add(tag) + v = self.__tags.from_name(tag) + + move = False try: - self.tags.put(issue_id) - except shep.error.StateItemExists: - pass + r = self.__tags.state(issue_id) + if r == 0: + move = True + except shep.error.StateItemNotFound: + self.__tags.put(issue_id) + move = True + + if move: + self.__tags.move(issue_id, v) + else: + self.__tags.set(issue_id, v) + + + + def untag(self, issue_id, tag): + v = self.__tags.from_name(tag) + self.__tags.unset(issue_id, v, allow_base=True) + - self.tags.set(issue_id, v) + def tags(self, issue_id): + v = self.__tags.state(issue_id) + r = self.__tags.elements(v) + return shep.state.split_elements(r) diff --git a/piknik/runnable/add.py b/piknik/runnable/add.py @@ -12,7 +12,7 @@ argp.add_argument('title', type=str, nargs='*', help='issue title') arg = argp.parse_args(sys.argv[1:]) store_factory = FileStoreFactory(arg.d) -basket = Basket(store_factory.create) +basket = Basket(store_factory) def main(): diff --git a/piknik/runnable/list.py b/piknik/runnable/list.py @@ -13,7 +13,7 @@ argp.add_argument('-r', '--renderer', type=str, default='ini', help='Renderer mo arg = argp.parse_args(sys.argv[1:]) store_factory = FileStoreFactory(arg.d) -basket = Basket(store_factory.create) +basket = Basket(store_factory) def render_ini(b, r): diff --git a/piknik/runnable/mod.py b/piknik/runnable/mod.py @@ -12,11 +12,13 @@ argp.add_argument('--block', action='store_true', help='Set issue as blocked') argp.add_argument('--unblock', action='store_true', help='Set issue as unblocked') argp.add_argument('--finish', action='store_true', help='Set issue as finished (alias of -s finish)') argp.add_argument('-s', '--state', type=str, help='Move to state') +argp.add_argument('-t', '--tag', type=str, action='append', default=[], help='Add tag to issue') +argp.add_argument('-u', '--untag', type=str, action='append', default=[], help='Remove tag from issue') argp.add_argument('issue_id', type=str, help='Issue id to modify') arg = argp.parse_args(sys.argv[1:]) store_factory = FileStoreFactory(arg.d) -basket = Basket(store_factory.create) +basket = Basket(store_factory) def main(): @@ -33,6 +35,12 @@ def main(): elif arg.finish: basket.state_finish(arg.issue_id) + for v in arg.tag: + basket.tag(arg.issue_id, v) + + for v in arg.untag: + basket.untag(arg.issue_id, v) + if __name__ == '__main__': main() diff --git a/piknik/store/__init__.py b/piknik/store/__init__.py @@ -19,5 +19,20 @@ class FileStoreFactory: def create_tags(self, logger=None, default_state=None, verifier=None): directory = os.path.join(self.directory, '.tags') - factory = SimpleFileStoreFactory(directory).add - return PersistedState(factory, 0, logger=logger, check_alias=False, default_state='untagged') + os.makedirs(directory, exist_ok=True) + factory = SimpleFileStoreFactory(directory) + state = PersistedState(factory.add, 0, logger=logger, check_alias=False, default_state='untagged') + aliases = [] + for k in factory.ls(): + if k == 'UNTAGGED': + continue + elif k[0] == '_': + aliases.append(k) + continue + state.add(k) + + for v in aliases: + s = state.from_elements(v) + state.alias(v, s) + + return state diff --git a/tests/test_store.py b/tests/test_store.py @@ -38,7 +38,7 @@ class TestStore(unittest.TestCase): def tearDown(self): - shutil.rmtree(self.d) + #shutil.rmtree(self.d) pass @@ -57,9 +57,26 @@ class TestStore(unittest.TestCase): self.b.advance(va) b = Basket(self.store_factory) - print('get va {}'.format(va)) r = b.get(va) + def test_load_tag(self): + o = Issue('foo') + va = self.b.add(o) + self.b.tag(va, 'inky') + self.b.tag(va, 'pinky') + + b = Basket(self.store_factory) + r = b.tags(va) + self.assertIn('INKY', r) + self.assertIn('PINKY', r) + + self.b.untag(va, 'inky') + b = Basket(self.store_factory) + r = b.tags(va) + self.assertNotIn('INKY', r) + self.assertIn('PINKY', r) + + if __name__ == '__main__': unittest.main() diff --git a/tests/test_tag.py b/tests/test_tag.py @@ -35,6 +35,7 @@ class TestBasic(unittest.TestCase): v = self.b.add(o) self.b.tag(v, 'inky') self.b.tag(v, 'pinky') + self.b.untag(v, 'pinky') if __name__ == '__main__':