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
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
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
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
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