synchronized developers and entries

This commit is contained in:
Trilarion 2020-09-07 16:39:47 +02:00
parent 8a08425e09
commit 625871062f
5 changed files with 103 additions and 16 deletions

View File

@ -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
}

View File

@ -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')

View File

@ -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']:

View File

@ -121,7 +121,6 @@ class ValueWithComment:
else:
return '{}'.format(self.value)
def parse(parser, transformer, content):
tree = parser.parse(content)
value = transformer.transform(tree)

View File

@ -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