def main(): arg_parser = argparse.ArgumentParser( description= 'Create a pdf document from a exported csv of Pivotal Tracker', formatter_class=argparse.ArgumentDefaultsHelpFormatter) arg_parser.add_argument('csv', help='the file path to the csv file') arg_parser.add_argument('-m', '--margin', type=int, default=5, help='margin of the page in mm') arg_parser.add_argument('-o', '--output', help='file path to the generated pdf') arg_parser.add_argument('-n', '--show-number', action='store_true', help='shows the story number on the bottom left') arg_parser.add_argument('-t', '--show-tasks', action='store_true', help='shows the tasks for each story') arg_parser.add_argument( '-c', '--collate', action='store_true', help='collate stories for easier sorting after cutting all pages') arg_parser.add_argument( '-s', '--strict', action='store_true', help='fails if the csv file does not contain all required columns') args = arg_parser.parse_args() output_file = args.output if args.output is not None \ else os.path.splitext(args.csv)[0] + '.pdf' page_margin = args.margin story_width = (297 - (page_margin * 2)) / 2 story_height = (210 - (page_margin * 2)) / 2 stories = [] with open(args.csv, 'r') as csvfile: reader = csv.reader(csvfile, delimiter=',') data = list(reader) if args.strict: validate_columns(data[0]) stories = map(partial(make_pivotal_story, data[0]), enumerate(data[1:], 1)) pdf = Pdf() pdf.set_auto_page_break(False) positions = [(page_margin, page_margin), (page_margin + story_width, page_margin), (page_margin, page_margin + story_height), (page_margin + story_width, page_margin + story_height)] stories = list(iterstories(stories, include_tasks=args.show_tasks)) chunk_function = stacked_chunks if args.collate else chunks for story_chunk in chunk_function(stories, 4): pdf.add_page('Landscape') for story, position in zip(story_chunk, positions): story.draw( pdf, position[0], position[1], story_width, story_height, args.show_number, ) pdf.output(output_file) open_file(output_file) return output_file