Example #1
0
def do_one(tasks_v2_session, t1: Task_v1) -> Optional[Task_v2]:
    try:
        if t1.parent:
            return None

        t2 = _do_one(tasks_v2_session, t1)

    except ValueError as e:
        print(e)
        print(json.dumps(t1.as_json(), indent=2))
        raise

    try:
        tasks_v2_session.commit()
    except StatementError as e:
        tasks_v2_session.rollback()
        print(f"ERROR: Hit exception while parsing {t1}, skipping")
        print()
        print(e)
        print()
        print(json.dumps(t1.as_json(), indent=2))
        raise
    except IntegrityError as e:
        session.rollback()
        print(f"ERROR: Hit exception while parsing {t1}, skipping")
        print()
        print(e)
        print()
        print(json.dumps(t1.as_json(), indent=2))
        raise

    return t2
Example #2
0
def test_orphan_properties(task_v1_session):
    task = Task(desc="orphan", first_scope="2021-ww24.5")
    task_v1_session.add(task)
    task_v1_session.commit()

    assert not task.parent
    assert not task.children

    json_dict = task.as_json(include_parents=True, include_children=True)
    assert 'parent_id' not in json_dict
    assert 'children' not in json_dict
Example #3
0
def test_to_json_legacy():
    TEST_DESC = "sample descr aheou;lq"
    TEST_CATEGORY = "test cat g'l.',.p"
    TEST_SCOPE = "2011-ww38.3"

    t = Task(desc=TEST_DESC, category=TEST_CATEGORY, first_scope=TEST_SCOPE)
    json_dict = t.to_json_dict()

    assert json_dict['desc'] == TEST_DESC
    assert json_dict['category'] == TEST_CATEGORY
    assert json_dict['first_scope'] == TEST_SCOPE
    assert 'created_at' not in json_dict
Example #4
0
def from_csv(csv_entry) -> Task:
    t = Task(desc=csv_entry['desc'])
    if 'created_at' in csv_entry and csv_entry['created_at']:
        t.created_at = parser.parse(csv_entry['created_at'])
    for field in [
            "first_scope", "category", "resolution", "parent_id",
            "time_estimate", "time_actual"
    ]:
        value = csv_entry.get(field)
        setattr(t, field, value if value else None)

    return t
Example #5
0
def test_as_json(task_v1_session):
    TEST_DESC = "sample desc hchcoernn1 c"
    TEST_CATEGORY = "NqMxWNCBthIYp2e9aWrfeX8"
    TEST_SCOPE = "2021-ww24.5"

    t = Task(desc=TEST_DESC, category=TEST_CATEGORY, first_scope=TEST_SCOPE)
    task_v1_session.add(t)
    task_v1_session.flush()
    json_dict = t.as_json()

    assert json_dict['task_id']
    assert json_dict['desc'] == TEST_DESC
    assert json_dict['first_scope'] == TEST_SCOPE
    assert 'parent_id' not in json_dict
Example #6
0
def test_two_generation_properties(task_v1_session):
    parent_task = Task(desc="parent", first_scope="2021-ww24.5")
    task_v1_session.add(parent_task)
    task_v1_session.flush()

    child_task = Task(desc="child", first_scope="2021-ww24.6")
    child_task.parent_id = parent_task.task_id
    task_v1_session.add(child_task)
    task_v1_session.commit()

    assert not parent_task.parent
    assert parent_task.children == [child_task]

    assert child_task.parent == parent_task
    assert not child_task.children
Example #7
0
def test_create_python(task_v1_session):
    task = Task(desc="test task for database", first_scope="2020-ww02.2")
    assert task.task_id is None

    task_v1_session.add(task)
    task_v1_session.flush()
    assert task.task_id is not None
Example #8
0
def test_create_and_read_python(task_v1_session):
    task = Task(desc="injected test task", first_scope="2016-ww27.4")
    task_v1_session.add(task)
    task_v1_session.commit()

    query = Task.query.filter_by(task_id=task.task_id)
    task_out = query.one()
    assert task_out.task_id == task.task_id
Example #9
0
def test_one_scope(task_v1_session):
    t = Task(desc="aoetuhnano", first_scope="2000-ww22.2")
    task_v1_session.add(t)
    task_v1_session.flush()

    tts = TaskTimeScope(task_id=t.task_id, time_scope_id=t.first_scope)
    task_v1_session.add(tts)
    task_v1_session.commit()

    assert len(t.scopes) == 1
    assert t.scopes[0] == tts
    assert tts.task == t
Example #10
0
def add_from_cli(session):
    # Read description for the task
    desc = input(f"Enter description: {Color.RED}")
    print(Color.END, end='', flush=True)

    # Read relevant scopes
    requested_scopes = sorted(_read_validated_scopes())
    if not len(requested_scopes):
        requested_scopes = [TimeScope(datetime.now().strftime("%G-ww%V.%u"))]
        print(f"   => defaulting to {requested_scopes}")
    if len(requested_scopes) > 1:
        print(f"   => parsed as {requested_scopes}")

    # Create a Task, now that we have all required fields
    t = Task(desc=desc,
             first_scope=requested_scopes[0],
             created_at=datetime.now())

    # And a category
    category = input(f"Enter category: {Color.RED}")
    if category is not None and category != "":
        t.category = category
    print(Color.END, end='', flush=True)

    # And a time_estimate
    time_estimate = input(f"Enter time_estimate: {Color.RED}")
    if time_estimate is not None and time_estimate != "":
        if not re.fullmatch(r"\d+\.\d", time_estimate):
            print(Color.END, end='')
            print(
                "time_estimate must be in format like `12.0` (\"\\d+\\.\\d\"), exiting"
            )
            print()
            return
        t.time_estimate = time_estimate
    print(Color.END, end='', flush=True)

    # Try committing the Task
    try:
        session.add(t)
        session.commit()
    except StatementError as e:
        print()
        print("Hit exception when parsing:")
        print(json.dumps(t.to_json_dict(), indent=4))
        session.rollback()
        return

    # Try creating the TaskTimeScopes
    for requested_scope in requested_scopes:
        session.add(
            TaskTimeScope(task_id=t.task_id, time_scope_id=requested_scope))
    session.commit()

    print()
    print(f"Created task {t.task_id}")
    print(json.dumps(t.to_json_dict(), indent=4))
Example #11
0
def _migrate_simple(session, t1: Task_v1) -> Task_v2:
    """
    Migrate an orphan task

    Task_v1 only has a few fields that will turn into linkages:

    - for first_scope, we can add the `created_at` field,
      and possibly an `as_json()` dump
    - for the last scope, we set `resolution` + `time_elapsed`
    - every other linkage has no info, a `roll => wwXX.Y` resolution at most

    Note that first_scope isn't guaranteed to be the _earliest_ scope,
    it's intended to be the one where the task was created.
    """
    t2 = Task_v2(desc=t1.desc,
                 category=t1.category,
                 time_estimate=t1.time_estimate)
    session.add(t2)
    session.flush()
    #print(f"DEBUG: {t2} <= _migrate_simple({t1})")

    created_at_linkage = None
    prior_linkage = None
    for scope_id in _get_scopes(t1):
        linkage = TaskLinkage(task_id=t2.task_id, time_scope_id=scope_id)
        linkage.created_at = datetime.now()
        session.add(linkage)

        # Touch up created_at_linkage
        if scope_id == _force_day_scope(t1.first_scope):
            created_at_linkage = linkage
            created_at_linkage.created_at = t1.created_at if t1.created_at else datetime.now(
            )
            created_at_linkage.detailed_resolution = json.dumps(t1.as_json(),
                                                                indent=4)

        # For "ordinary" linkages, append `roll => wwXX.Y` resolution
        if prior_linkage:
            min_scope_id = TimeScope(t1.first_scope).minimize(scope_id)
            prior_linkage.resolution = f"roll => {min_scope_id}"

        prior_linkage = linkage

    # For the final linkage, inherit any/all Task_v1 fields
    final_linkage = prior_linkage if prior_linkage else created_at_linkage
    final_linkage.resolution = t1.resolution
    final_linkage.time_elapsed = t1.time_actual

    return t2
Example #12
0
def to_details_html(task: Task):
    # keep parameters to a minimum, to avoid hitting slow DB accesses
    as_json = task.as_json(False, False, False)
    if 'time_scopes' in as_json:
        # make linked TimeScopes clickable
        clickable_scopes = []
        for s in as_json['time_scopes']:
            clickable_scopes.append(f'<a href=/report-tasks/{s}>{s}</a>')
        as_json['time_scopes'] = clickable_scopes

    as_text = json.dumps(as_json, indent=4, ensure_ascii=False)
    # make task_ids clickable
    as_text = re.sub(r'"task_id": (\d*),',
                     r'<a href="/task/\1">"task_id": \1</a>,', as_text)
    # make first_scopes clickable
    as_text = re.sub(r'"first_scope": "(.*)",',
                     r'<a href="/report-tasks/\1">"first_scope": "\1"</a>,',
                     as_text)
    return as_text
Example #13
0
def test_multi_scope(task_v1_session):
    t = Task(desc="hhhhhhhhhh", first_scope="2020-ww20.1")
    task_v1_session.add(t)
    task_v1_session.flush()

    task_v1_session.add(
        TaskTimeScope(task_id=t.task_id, time_scope_id=t.first_scope))
    task_v1_session.add(
        TaskTimeScope(task_id=t.task_id, time_scope_id="2020-ww20.2"))
    task_v1_session.add(
        TaskTimeScope(task_id=t.task_id, time_scope_id="2020-ww20.3"))
    task_v1_session.add(
        TaskTimeScope(task_id=t.task_id, time_scope_id="2020-ww20.4"))
    task_v1_session.add(
        TaskTimeScope(task_id=t.task_id, time_scope_id="2020-ww20.5"))
    task_v1_session.commit()

    assert len(t.scopes) == 5
    assert t.scopes[0]
Example #14
0
def test_2g_sqlalchemy_relationships(task_v1_session):
    parent_task = Task(desc="parent", first_scope="2021-ww24.5")
    task_v1_session.add(parent_task)
    task_v1_session.flush()

    child_task = Task(desc="child", first_scope="2021-ww24.6")
    child_task.parent_id = parent_task.task_id
    task_v1_session.add(child_task)
    task_v1_session.commit()

    bystander = Task(desc="completely unrelated task",
                     first_scope="2021-ww02.1")
    task_v1_session.add(bystander)

    bystander2 = Task(desc="totally unrelated task", first_scope="2021-ww03.1")
    task_v1_session.add(bystander2)
    task_v1_session.commit()

    assert not parent_task.parent
    assert parent_task.children == [child_task]

    assert child_task.parent == parent_task
    assert not child_task.children
Example #15
0
def test_task_constructor():
    task = Task(desc="test task for test_task_constructor",
                first_scope="2020-ww02.1")
    assert task
Example #16
0
def test_create_quarterly(task_v1_session):
    task = Task(desc="아니아", first_scope="2020—Q4")
    time = TimeScope(task.first_scope)
    assert time.type == TimeScope.Type.quarter