└── bib-yaml.py /bib-yaml.py: -------------------------------------------------------------------------------- 1 | # Requires Python 3 2 | 3 | import argparse 4 | import yaml 5 | import codecs 6 | 7 | 8 | class ConversionException(Exception): 9 | def __init__(self, value): 10 | self.value = value 11 | def __str__(self): 12 | return repr(self.value) 13 | 14 | 15 | def required_fields(): 16 | return { 17 | "book": [["author","authors"], "title", "year", "publisher"], 18 | "journal": [["author","authors"], "title", "journal", "year"], 19 | "conference": [["author","authors"], "title", "booktitle", "year"], 20 | "collection": [["author","authors"], "title", "booktitle", "year", "publisher"], 21 | "masters thesis": [["author","authors"], "title", "school", "year"], 22 | "phd thesis": [["author","authors"], "title", "school", "year"], 23 | "tech report": [["author","authors"], "title", "year", "institution", "number"] 24 | } 25 | 26 | def type_identifiers(): 27 | return { 28 | "book": "@book", 29 | "journal": "@article", 30 | "conference": "@inproceedings", 31 | "collection": "@incollection", 32 | "masters thesis": "@mastersthesis", 33 | "phd thesis": "@phdthesis", 34 | "tech report": "@techreport" 35 | } 36 | 37 | def check_required_fields(item): 38 | typ = item['type'] 39 | try: 40 | req_fields = required_fields()[typ] 41 | except KeyError: 42 | req_fields = [] 43 | 44 | for field in req_fields: 45 | if type(field) is list: 46 | ok = False 47 | for option in field: 48 | if option in item: 49 | ok = True 50 | break 51 | if not ok: 52 | msg = "Missing required field:" 53 | for option in field: 54 | msg += " '" + option + "'" 55 | if (option != field.last): 56 | msg += " or" 57 | raise ConversionException(msg) 58 | else: 59 | if not field in item: 60 | raise ConversionException("Missing required field: '" + field + "'") 61 | 62 | 63 | def process_item(key, item, out_file): 64 | print("processing " + str(key)) 65 | 66 | try: 67 | typ = item['type'] 68 | except KeyError: 69 | raise ConversionException("Missing type") 70 | 71 | try: 72 | out_file.write( type_identifiers()[typ] ) 73 | except KeyError: 74 | raise ConversionException("Unknown type: " + str(typ)) 75 | 76 | out_file.write("{") 77 | 78 | try: 79 | authors = item['authors'] 80 | except KeyError: 81 | try: 82 | authors = [item['author']] 83 | except KeyError: 84 | raise ConversionException("Missing author") 85 | 86 | try: 87 | year = item['year'] 88 | except KeyError: 89 | raise ConversionException("Missing year") 90 | 91 | check_required_fields(item) 92 | 93 | print("writing: " + key) 94 | 95 | out_file.write(key + " ,\n") 96 | 97 | out_file.write(" author = {") 98 | for a in range(len(authors)): 99 | out_file.write(authors[a]) 100 | if a < len(authors)-1: 101 | out_file.write(" and ") 102 | out_file.write("},\n") 103 | 104 | for field in ['type', 'author', 'authors']: 105 | try: 106 | del item[field] 107 | except KeyError: 108 | pass 109 | 110 | for key, value in item.items(): 111 | out_file.write(" " + key + " = {") 112 | if isinstance(value,list): 113 | for v in range(len(value)): 114 | out_file.write(value[v]) 115 | if v < len(value)-1: 116 | out_file.write(" and ") 117 | else: 118 | out_file.write(str(value)) 119 | out_file.write("},\n") 120 | 121 | out_file.write("}\n\n") 122 | 123 | def main(): 124 | parser = argparse.ArgumentParser(description='Translate bibliography from YAML to BIB.') 125 | parser.add_argument('input', nargs=1) 126 | parser.add_argument('output', nargs='?') 127 | a = parser.parse_args() 128 | 129 | in_file_name = a.input[0] 130 | out_file_name = None 131 | 132 | if a.output != None: 133 | out_file_name = a.output 134 | else: 135 | out_file_name = in_file_name.split('/')[-1].rpartition('.')[0] + ".bib" 136 | 137 | print("input = " + in_file_name) 138 | print("output = " + out_file_name) 139 | 140 | in_file = codecs.open(in_file_name, encoding='utf-8', mode='r') 141 | out_file = codecs.open(out_file_name, encoding='utf-8', mode='w') 142 | 143 | yaml_string = in_file.read(); 144 | data = yaml.load(yaml_string); 145 | 146 | items = {} 147 | for key, item in data.items(): 148 | try: 149 | if key in items: 150 | raise ConversionException("Duplicate key: " + str(key)) 151 | items[key] = item 152 | process_item(key, item, out_file) 153 | except ConversionException as e: 154 | print("*** Error while processing an item: " + str(e)) 155 | 156 | main() 157 | --------------------------------------------------------------------------------