1*8a52c783SCole Faustimport json 2*8a52c783SCole Faustimport os 3*8a52c783SCole Faustfrom datetime import date 4*8a52c783SCole Faust 5*8a52c783SCole Faustfrom changelog.model import ReleaseChanges, ChangelogEntry, Version 6*8a52c783SCole Faust 7*8a52c783SCole Faust 8*8a52c783SCole Faustdef version_cmp(a,b): 9*8a52c783SCole Faust aa = [a.major, a.minor, a.patch, a.prerelease_version_number()] 10*8a52c783SCole Faust bb = [b.major, b.minor, b.patch, b.prerelease_version_number()] 11*8a52c783SCole Faust return cmp(bb,aa) 12*8a52c783SCole Faust 13*8a52c783SCole Faustdef load_all_released_changes(d): 14*8a52c783SCole Faust if not os.path.isdir(d): 15*8a52c783SCole Faust return [] 16*8a52c783SCole Faust return [load_release_changes(os.path.join(d, fn)) for fn in os.listdir(d) if fn.endswith('.json')] 17*8a52c783SCole Faust 18*8a52c783SCole Faustdef load_release_changes(fn): 19*8a52c783SCole Faust with open(fn) as f: 20*8a52c783SCole Faust return parse_release_changes(json.loads(f.read())) 21*8a52c783SCole Faust 22*8a52c783SCole Faustdef load_unreleased_changes(d): 23*8a52c783SCole Faust if not os.path.exists(d): 24*8a52c783SCole Faust return None 25*8a52c783SCole Faust return ReleaseChanges(None, date.today().isoformat(), load_unreleased_entries(d)) 26*8a52c783SCole Faust 27*8a52c783SCole Faustdef load_unreleased_entries(d): 28*8a52c783SCole Faust entries = [] 29*8a52c783SCole Faust for f in [f for f in os.listdir(d) if f.endswith('.json')]: 30*8a52c783SCole Faust with open(os.path.join(d,f)) as e: 31*8a52c783SCole Faust entries.append(parse_changelog_entry(json.loads(e.read()))) 32*8a52c783SCole Faust return entries 33*8a52c783SCole Faust 34*8a52c783SCole Faustdef parse_release_changes(changes_json): 35*8a52c783SCole Faust version = parse_version_string(changes_json['version']) 36*8a52c783SCole Faust date = changes_json['date'] 37*8a52c783SCole Faust entries = [parse_changelog_entry(e) for e in changes_json['entries']] 38*8a52c783SCole Faust return ReleaseChanges(version, date, entries) 39*8a52c783SCole Faust 40*8a52c783SCole Faustdef parse_changelog_entry(entry_json): 41*8a52c783SCole Faust return ChangelogEntry(entry_json['type'], entry_json['category'], entry_json['description'], 42*8a52c783SCole Faust entry_json.get('contributor')) 43*8a52c783SCole Faust 44*8a52c783SCole Faustdef parse_version_string(s): 45*8a52c783SCole Faust version_parts = [s for s in s.split('.')] 46*8a52c783SCole Faust prerelease = "" 47*8a52c783SCole Faust hyphen_index = version_parts[2].find('-') 48*8a52c783SCole Faust if hyphen_index != -1: 49*8a52c783SCole Faust p = version_parts[2] 50*8a52c783SCole Faust version_parts[2] = p[0:hyphen_index] 51*8a52c783SCole Faust prerelease = p[hyphen_index + 1:] 52*8a52c783SCole Faust return Version(int(version_parts[0]), int(version_parts[1]), int(version_parts[2]), prerelease) 53*8a52c783SCole Faust 54*8a52c783SCole Faustclass ReleaseChangesEncoder(json.JSONEncoder): 55*8a52c783SCole Faust def default(self, o): 56*8a52c783SCole Faust if type(o) is Version: 57*8a52c783SCole Faust # store as a "MAJOR.MINOR.PATCH" string so it's a little easier to 58*8a52c783SCole Faust # read the raw JSON 59*8a52c783SCole Faust return o.__str__() 60*8a52c783SCole Faust return o.__dict__ 61*8a52c783SCole Faust 62*8a52c783SCole Faustdef marshall_release_changes(changes): 63*8a52c783SCole Faust return json.dumps(changes, indent=4, separators=(',', ': '), cls=ReleaseChangesEncoder) 64