def edit_and_validate_board_settings(board_settings_file): subprocess.run([get_settings()[EDITOR], board_settings_file]) try: get_board_settings() except Exception as e: print(e) return False return check_defaults() and test_sorting()
def render_kanban(issues): # generator can only be traversed once issues = list(issues) issues.sort(key=lambda issue: -get_sort_value(issue)) box_rows = get_settings()[BOX_ROWS] box_width = get_settings()[BOX_WIDTH] statuses = get_board_settings()[STATUS_COLUMNS] rows = defaultdict(list) status_counter = Counter() for issue in issues: if STATUS in issue.keys() and issue[STATUS] in statuses: rows[issue[STATUS]].append(render_issue(issue, box_width, box_rows)) status_counter[issue[STATUS]] += 1 hline = (1 + len(statuses) * (3 + box_width)) * '-' lines = [hline] status_line = '| ' + ' | '.join( [render_text(status, box_width) for status in statuses]) + ' |' lines.append(status_line) lines.append(hline) if len(status_counter) == 0: return lines board_height = max(status_counter.values()) for height in range(min(board_height, get_settings()[MAX_BOARD_ROWS])): for sub_row in range(box_rows): line = '| ' + ' | '.join([ fill_missing(rows[status], height, box_width, sub_row) for status in statuses ]) + ' |' lines.append(line) lines.append(hline) if board_height > get_settings()[MAX_BOARD_ROWS]: lines.append(' ...') lines.append(' ...') return lines
def _input_user_issue(path): subprocess.run([get_settings()[EDITOR], path]) with open(path, 'r') as fin: edited_contents = fin.read() if not edited_contents.isspace(): try: user_json = json.loads(edited_contents) except Exception as e: print("Not valid json, please try again.") input("Press ENTER to continue.") return _input_user_issue(path) if TITLE not in user_json or not isinstance( user_json[TITLE], str) or user_json[TITLE] == '': print("Must use non-empty string value for attribute title.") input("Press ENTER to continue.") return _input_user_issue(path) if STATUS not in user_json or user_json[ STATUS] not in get_board_settings()[STATUS_COLUMNS]: print( f"Must have status with a value in {get_board_settings()[STATUS_COLUMNS]}." ) input("Press ENTER to continue.") return _input_user_issue(path) return user_json else: return None
def transition_cmd(args): if args.new_status not in get_board_settings()[STATUS_COLUMNS]: print( f"Must use status with a value in {get_board_settings()[STATUS_COLUMNS]}." ) return for issue in matching_issues(args): issue[STATUS] = args.new_status save_issue(issue)
def check_defaults(): board_settings = get_board_settings() FIELD = r'[a-zA-Z_][a-zA-Z0-9_]*' used_fields = set(re.findall(FIELD, board_settings[BACKLOG_SORTING])) fields_with_defaults = set(board_settings[CUSTOM_FIELDS]) missing_defaults = used_fields - fields_with_defaults - {CREATED} if len(missing_defaults) > 0: print( f"Fields {list(missing_defaults)} in {BACKLOG_SORTING} do not have defaults in {CUSTOM_FIELDS}." ) return False return True
def __init__(self, issue): self.names = {} self.issue = issue settings = get_board_settings() self.custom_fields = settings[CUSTOM_FIELDS] self.sorting_expr = settings[BACKLOG_SORTING]