From 625871062f6de49454139dfb1d7284c5abd1dac5 Mon Sep 17 00:00:00 2001 From: Trilarion Date: Mon, 7 Sep 2020 16:39:47 +0200 Subject: [PATCH] synchronized developers and entries --- code/maintenance_developers.py | 32 ++++++++++++++++++++++++---- code/utils/constants.py | 12 ++++++----- code/utils/osg.py | 36 +++++++++++++++++++++++++++----- code/utils/osg_parse.py | 1 - developers.md | 38 +++++++++++++++++++++++++++++++++- 5 files changed, 103 insertions(+), 16 deletions(-) diff --git a/code/maintenance_developers.py b/code/maintenance_developers.py index dd889da7..4afd2642 100644 --- a/code/maintenance_developers.py +++ b/code/maintenance_developers.py @@ -186,7 +186,7 @@ class DevelopersMaintainer: if not self.developers: print('developers not yet loaded') return - developer_names = [x['Name'] for x in self.developers] + developer_names = list(self.developers.keys()) for index, name in enumerate(developer_names): for other_name in developer_names[index + 1:]: if osg.name_similarity(name, other_name) > 0.8: @@ -197,9 +197,9 @@ class DevelopersMaintainer: if not self.developers: print('developers not yet loaded') return - for dev in self.developers: + for dev in self.developers.values(): if not dev['Games']: - print(' {} has no "Games" field'.format(dev['Name'])) + print(' {} has no games'.format(dev['Name'])) print('orphanes checked') def check_for_missing_developers_in_entries(self): @@ -209,7 +209,7 @@ class DevelopersMaintainer: if not self.entries: print('entries not yet loaded') return - for dev in self.developers: + for dev in self.developers.values(): dev_name = dev['Name'] for entry_name in dev['Games']: x = [x for x in self.entries if x['Title'] == entry_name] @@ -222,6 +222,29 @@ class DevelopersMaintainer: print('Entry "{}" listed in developer "{}" but not listed in that entry'.format(entry_name, dev_name)) print('missed developer checked') + def update_developers_from_entries(self): + if not self.developers: + print('developer not yet loaded') + return + if not self.entries: + print('entries not yet loaded') + return + # loop over all developers and delete all games + for dev in self.developers.values(): + dev['Games'] = [] + # loop over all entries and add this game to all developers of this game + for entry in self.entries: + entry_name = entry['Title'] + entry_devs = entry.get('Developer', []) + for entry_dev in entry_devs: + entry_dev = entry_dev.value # ignored the comment + if entry_dev in self.developers: + self.developers[entry_dev]['Games'].append(entry_name) + else: + # completely new developer + self.developers[entry_dev] = {'Name': entry_dev, 'Games': entry_name} + print('developers updated') + def read_entries(self): self.entries = osg.read_entries() print('{} entries read'.format(len(self.entries))) @@ -237,6 +260,7 @@ if __name__ == "__main__": 'Check for duplicates': m.check_for_duplicates, 'Check for orphans': m.check_for_orphans, 'Check for games in developers not listed': m.check_for_missing_developers_in_entries, + 'Update developers from entries': m.update_developers_from_entries, 'Read entries': m.read_entries } diff --git a/code/utils/constants.py b/code/utils/constants.py index 1ff1058e..d7684b96 100644 --- a/code/utils/constants.py +++ b/code/utils/constants.py @@ -35,12 +35,14 @@ generic_comment_string = '[comment]: # (partly autogenerated content, edit with # these fields have to be present in each entry (in this order) essential_fields = ('File', 'Title', 'Home', 'State', 'Keywords', 'Code repository', 'Code language', 'Code license') -# only these fields can be used currently (in this order) -valid_fields = ( - 'File', 'Title', 'Home', 'Media', 'Inspirations', 'State', 'Play', 'Download', 'Platform', 'Keywords', 'Code repository', 'Code language', - 'Code license', 'Code dependencies', 'Assets license', 'Developer', 'Note', 'Building') +valid_properties = ('Home', 'Media', 'Inspirations', 'State', 'Play', 'Download', 'Platform', 'Keywords', 'Code repository', 'Code language', + 'Code license', 'Code dependencies', 'Assets license', 'Developer') -valid_building_fields = ('Build system', 'Build instructions') +# only these fields can be used currently (in this order) +valid_fields = ('File', 'Title') + valid_properties + ('Note', 'Building') + +valid_building_properties = ('Build system', 'Build instructions') +valid_building_fields = valid_building_properties + ('Note',) # these are the only valid platforms currently (and must be given in this order) valid_platforms = ('Windows', 'Linux', 'macOS', 'Android', 'iOS', 'Web') diff --git a/code/utils/osg.py b/code/utils/osg.py index 39081373..cb3af4b3 100644 --- a/code/utils/osg.py +++ b/code/utils/osg.py @@ -326,6 +326,9 @@ def read_developers(): if any(not (x.startswith('http://') or x.startswith('https://')) for x in content): raise RuntimeError('Invalid URL in field "{}" in developer {}.'.format(field, dev['Name'])) + # convert to dictionary + developers = {x['Name']: x for x in developers} + return developers @@ -334,6 +337,9 @@ def write_developers(developers): :return: """ + # convert dictionary to list + developers = list(developers.values()) + # comment content = '{}\n'.format(generic_comment_string) @@ -517,7 +523,23 @@ def check_and_process_entry(entry): # check for essential fields for field in essential_fields: if field not in entry: - message += 'essential property "{}" missing\n'.format(field) + message += 'Essential property "{}" missing\n'.format(field) + + # now the same treatment for building + building = entry['Building'] + d = {} + for field, value in building: + if field in d: + message += 'Field "{}" appears twice\n'.format(field) + d[field] = value + building = d + + # check valid fields TODO should also check order + for field in building.keys(): + if field not in valid_building_fields: + message += 'Building field "{}" invalid\n'.format(field) + entry['Building'] = building + # check canonical file name file = entry['File'] @@ -551,7 +573,7 @@ def write_entry(entry): # TODO check entry # get path - entry_path = os.path.join(entries_path, entry['file']) + entry_path = os.path.join(entries_path, entry['File']) # create output content content = create_entry_content(entry) @@ -571,10 +593,11 @@ def create_entry_content(entry): content = '# {}\n\n'.format(entry['Title']) # now properties in the recommended order - for field in valid_fields: + for field in valid_properties: if field in entry: c = entry[field] c = ['"{}"'.format(x) if ',' in x else x for x in c] + c = [str(x) for x in c] content += '- {}: {}\n'.format(field, ', '.join(c)) content += '\n' @@ -587,12 +610,15 @@ def create_entry_content(entry): # building properties if present has_properties = False - for field in valid_building_fields: + for field in valid_building_properties: if field in entry['Building']: if not has_properties: has_properties = True content += '\n' - content += '- {}: {}\n'.format(field, ', '.join(entry['Building'][field])) + c = entry['Building'][field] + c = ['"{}"'.format(x) if ',' in x else x for x in c] + c = [str(x) for x in c] + content += '- {}: {}\n'.format(field, ', '.join(c)) # if there is a note, insert it if 'Note' in entry['Building']: diff --git a/code/utils/osg_parse.py b/code/utils/osg_parse.py index 6a0b2535..ba58188f 100644 --- a/code/utils/osg_parse.py +++ b/code/utils/osg_parse.py @@ -121,7 +121,6 @@ class ValueWithComment: else: return '{}'.format(self.value) - def parse(parser, transformer, content): tree = parser.parse(content) value = transformer.transform(tree) diff --git a/developers.md b/developers.md index bfb8798c..22a81862 100644 --- a/developers.md +++ b/developers.md @@ -1,5 +1,5 @@ [comment]: # (partly autogenerated content, edit with care, read the manual before) -# Developer [369] +# Developer [378] ## Akira Higuchi [1] @@ -46,6 +46,10 @@ - Games: Maxit +## Amer Koleci [7] + +- Games: Vortice + ## Anders Svensson [1] - Games: Alex the Allegator 4 @@ -87,6 +91,10 @@ - Games: Advanced Strategic Command - Contact: armin906@SF +## Armin Rigo [18] + +- Games: The Bub's Brothers + ## Arne Reiners [1] - Games: GL-117 @@ -184,6 +192,10 @@ - Games: Advanced Strategic Command - Contact: Ed-von-Schleck@GH +## Chua Kong Sian [9] + +- Games: GNU Chess + ## Chuck Simmons [1] - Games: VMS Empire @@ -779,6 +791,10 @@ - Games: Trip on the Funny Boat +## Kriss [8] + +- Games: GameCake + ## krys [1] - Games: Krystal Drop @@ -848,6 +864,10 @@ - Games: Tactics Squad +## Lukas Geyer [9] + +- Games: GNU Chess + ## Lukas Löhrer [1] - Games: Amphetamine @@ -997,6 +1017,10 @@ - Games: GJID +## Mike Strobel [9] + +- Games: Supremacy + ## Mikey Lubker [1] - Games: Snowballz @@ -1353,6 +1377,10 @@ - Games: Simon Tatham's Portable Puzzle Collection +## Simon Waters [9] + +- Games: GNU Chess + ## Sixth Floor Labs [1] - Games: Project Alexandria @@ -1415,6 +1443,10 @@ - Games: Blinken +## Stuart Cracraft [9] + +- Games: GNU Chess + ## Sylvain Beucler [1] - Games: GNU FreeDink @@ -1578,3 +1610,7 @@ - Games: Necklace of the Eye +## Андрей Питько [13] + +- Games: Wizards Magic +