From d91cc1235e01061561ae017e47c448a4412f6902 Mon Sep 17 00:00:00 2001 From: Danny Robson Date: Tue, 9 Jun 2020 12:38:46 +1000 Subject: [PATCH] Add dependent tasks --- .../10459dd24d3d_add_depends_to_tasks.py | 28 ++++++++++++++++ src/pyelephant.py | 33 +++++++++++++++++-- 2 files changed, 59 insertions(+), 2 deletions(-) create mode 100644 alembic/versions/10459dd24d3d_add_depends_to_tasks.py diff --git a/alembic/versions/10459dd24d3d_add_depends_to_tasks.py b/alembic/versions/10459dd24d3d_add_depends_to_tasks.py new file mode 100644 index 0000000..e8704d4 --- /dev/null +++ b/alembic/versions/10459dd24d3d_add_depends_to_tasks.py @@ -0,0 +1,28 @@ +"""add depends to tasks + +Revision ID: 10459dd24d3d +Revises: 17946e7038d7 +Create Date: 2020-05-21 11:07:46.953781 + +""" +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = '10459dd24d3d' +down_revision = '17946e7038d7' +branch_labels = None +depends_on = None + + +def upgrade(): + op.create_table( + 'depends', + sa.Column('first_id', sa.Integer, sa.ForeignKey('tasks.id'), primary_key=True), + sa.Column('second_id', sa.Integer, sa.ForeignKey('tasks.id'), primary_key=True) + ) + + +def downgrade(): + op.drop_table('depends') diff --git a/src/pyelephant.py b/src/pyelephant.py index 1886099..57da621 100755 --- a/src/pyelephant.py +++ b/src/pyelephant.py @@ -2,13 +2,24 @@ import sqlalchemy as sa import sqlalchemy.ext.declarative.base +import sqlalchemy.orm import dateparser +from typing import List + + ############################################################################### Base = sqlalchemy.ext.declarative.declarative_base() +depends_association = sa.Table( + "depends", Base.metadata, + sa.Column('first_id', sa.Integer, sa.ForeignKey('tasks.id'), primary_key=True), + sa.Column('second_id', sa.Integer, sa.ForeignKey('tasks.id'), primary_key=True) +) + + class Task(Base): __tablename__ = "tasks" @@ -18,14 +29,26 @@ class Task(Base): due_at = sa.Column(sa.DateTime, nullable=True) active = sa.Column(sa.Boolean, server_default=sa.sql.expression.true(), nullable=False) + depends = sa.orm.relationship( + 'Task', + secondary=depends_association, + primaryjoin=id == depends_association.c.first_id, + secondaryjoin=id == depends_association.c.second_id + ) + ############################################################################### -def add(session: sa.orm.Session, title: str, due: str = None): +def add(session: sa.orm.Session, title: str, due: str = None, depends: List[int] = None): if due is not None: due = dateparser.parse(due) + if depends is None: + depends = [] + obj = Task(title=title, due_at=due) + obj.depends.extend([session.query(Task).filter(Task.id == idx).one() for idx in depends]) session.add(obj) + session.commit() show_by_obj(session, obj) @@ -46,7 +69,7 @@ def rm(session: sa.orm.Session, index: int): # ----------------------------------------------------------------------------- def show_by_obj(session: sa.orm.Session, obj: Task): - print(obj.id, obj.created_at, obj.due_at, obj.active, obj.title) + print(obj.id, obj.created_at, obj.due_at, obj.active, obj.title, [i.id for i in obj.depends]) # ----------------------------------------------------------------------------- @@ -92,6 +115,12 @@ if __name__ == '__main__': add_parser = subparsers.add_parser('add') add_parser.set_defaults(func=add, due=None) add_parser.add_argument("title", type=str) + add_parser.add_argument( + "--depends", + type=int, + nargs="*", + help="Task IDs that must be completed before this task" + ) add_parser.add_argument("--due", type=str) done_parser = subparsers.add_parser('done')