rename of entries fields to get only singular field names
This commit is contained in:
@ -28,9 +28,6 @@ http://icculus.org/jugglemaster/
|
||||
http://icculus.org/pyddr/
|
||||
http://icculus.org/toby/
|
||||
http://iichantra.ru/en/
|
||||
https://github.com/armory3d/iron
|
||||
https://github.com/AxioDL/urde
|
||||
https://github.com/Gramps/GodotSteam
|
||||
http://insideastarfilledsky.net/
|
||||
http://lazerbears.wixsite.com/lazerbears/cr-editor
|
||||
http://libagar.org/agar/index.html.en
|
||||
@ -51,7 +48,6 @@ http://roguebasin.roguelikedevelopment.org/index.php?title=Main_Page
|
||||
http://sam.zoy.org/monsterz/
|
||||
http://senseis.xmp.net/?GoPlayingPrograms
|
||||
http://sio2interactive.com/
|
||||
https://github.com/EasyRPG/Editor-Qt
|
||||
http://slick.ninjacave.com/
|
||||
http://snowstorm.sourceforge.net/cgi-bin/site.cgi
|
||||
http://sol.gfxile.net/ambrose3d/index.html
|
||||
@ -208,6 +204,7 @@ https://github.com/adriengivry/Overload
|
||||
https://github.com/aloisdeniel/awesome-monogame
|
||||
https://github.com/Alzter/TuxBuilder
|
||||
https://github.com/amerkoleci/Vortice.Windows
|
||||
https://github.com/armory3d/iron
|
||||
https://github.com/arturkot/the-house-game
|
||||
https://github.com/asweigart/PythonStdioGames
|
||||
https://github.com/AtomicGameEngine/AtomicGameEngine
|
||||
@ -275,6 +272,7 @@ https://github.com/GNOME/quadrapassel
|
||||
https://github.com/godot-extended-libraries/godot-next
|
||||
https://github.com/godot-mega-man/Mega-Man-Engine
|
||||
https://github.com/godotengine/godot-design
|
||||
https://github.com/Gramps/GodotSteam
|
||||
https://github.com/grantjenks/free-python-games (check all)
|
||||
https://github.com/guillaumechereau/goxel
|
||||
https://github.com/H-uru/Plasma
|
||||
|
@ -7,29 +7,28 @@ Uses Jinja2 (see https://jinja.palletsprojects.com/en/2.11.x/)
|
||||
# TODO index.html tiles, content
|
||||
# TODO index.html image (maybe downloaded and assembled from osgameclones)
|
||||
# TODO index.html only count games
|
||||
# TODO Font awesome 5 (icons for OS, for Github, Gitlab and maybe others)
|
||||
# TODO contribute.html tiles? content
|
||||
# TODO games pages links to licenses (wikipedia)
|
||||
# TODO Font awesome 4 or others (icons for OS, for Github, Gitlab and maybe others like external link)
|
||||
# TODO contribute.html tiles? content?
|
||||
# TODO games: links to licenses (wikipedia)
|
||||
# TODO indexes: make categories bold that have a certain amount of entries!
|
||||
# TODO everywhere: style URLs (Github, Wikipedia, Internet archive, SourceForge, ...)
|
||||
# TODO developers pages links to games and more information, styles
|
||||
# TODO inspirations pages, add link to games and more information, styles
|
||||
# TODO navbar add is active
|
||||
# TODO developers: links to games and more information, styles
|
||||
# TODO inspirations: add link to games and more information, styles
|
||||
# TODO statistics page: better and more statistics with links where possible
|
||||
# TODO meaningful information (links, license, last updated with lower precision)
|
||||
# TODO singular, plural everywhere (game, entries, items)
|
||||
# TODO background and shadow for the boxes
|
||||
# TODO line breaks and spaces in html source and output
|
||||
# TODO rename fields (Home to Homepage, Inspirations to Inspiration)
|
||||
# TODO developers contact expand to links to Github, Sourceforge
|
||||
# TODO games keywords as labels (some as links)
|
||||
# TODO games links to licenses and languages
|
||||
# TODO platforms as labels and with links
|
||||
# TODO split games in libraries/tools/frameworks and real games
|
||||
# TODO developers: contact expand to links to Github, Sourceforge
|
||||
# TODO games: keywords as labels (some as links)
|
||||
# TODO games: links languages
|
||||
# TODO games: platforms as labels and with links
|
||||
# TODO split games in libraries/tools/frameworks and real games, add menu
|
||||
# TODO statistics with nice graphics (pie charts in SVG) with matplotlib, seaborn, plotly?
|
||||
# TODO statistics, get it from common statistics generator
|
||||
# TODO optimize jinja for line breaks and indention
|
||||
# TODO @notices in entries
|
||||
# TODO optimize jinja for line breaks and indention and minimal amount of spaces
|
||||
# TODO replace or remove @notices in entries (maybe different entries format)
|
||||
# TODO icons: for the main categories (devs, games, statistics, home, ...)
|
||||
# TODO SEO optimizations, google search ...
|
||||
|
||||
import os
|
||||
import shutil
|
||||
@ -49,7 +48,7 @@ inspirations_path = 'inspirations'
|
||||
developers_path = 'developers'
|
||||
|
||||
plurals = {k: k+'s' for k in ('Assets license', 'Contact', 'Code language', 'Code license', 'Developer', 'Download', 'Inspiration', 'Game', 'Home', 'Organization', 'Platform')}
|
||||
for k in ('Media', 'Play', 'Keywords'):
|
||||
for k in ('Media', 'Play', 'Keyword'):
|
||||
plurals[k] = k
|
||||
for k in ('Code repository', 'Code dependency'):
|
||||
plurals[k] = k[:-1] + 'ies'
|
||||
@ -308,10 +307,10 @@ def convert_entries(entries, inspirations, developers):
|
||||
developer_references = {developer['Name']: developer['href'] for developer in developers}
|
||||
for entry in entries:
|
||||
fields = []
|
||||
for field in ('Home', 'Inspirations', 'Media', 'Download', 'Play', 'Developer', 'Keywords'):
|
||||
for field in ('Home', 'Inspiration', 'Media', 'Download', 'Play', 'Developer', 'Keyword'):
|
||||
if field in entry:
|
||||
e = entry[field]
|
||||
if field == 'Inspirations':
|
||||
if field == 'Inspiration':
|
||||
field = 'Inspiration' # TODO this is a bug, rename in entries
|
||||
if isinstance(e[0], osg.osg_parse.ValueWithComment):
|
||||
e = [x.value for x in e]
|
||||
@ -331,12 +330,12 @@ def convert_entries(entries, inspirations, developers):
|
||||
if 'Note' in entry:
|
||||
fields.append({'entries': [{'href': '', 'name': entry['Note']}]})
|
||||
fields.append({'title': 'Technical info', 'entries': []})
|
||||
for field in ('Platform', 'Code language', 'Code license', 'Code repository', 'Code dependencies', 'Assets license'):
|
||||
for field in ('Platform', 'Code language', 'Code license', 'Code repository', 'Code dependency', 'Assets license'):
|
||||
if field in entry:
|
||||
e = entry[field]
|
||||
if not e:
|
||||
continue
|
||||
if field == 'Code dependencies':
|
||||
if field == 'Code dependency':
|
||||
field = 'Code dependency' # bug, rename field
|
||||
if isinstance(e[0], osg.osg_parse.ValueWithComment):
|
||||
e = [x.value for x in e]
|
||||
@ -386,7 +385,7 @@ def generate(entries, inspirations, developers):
|
||||
developers_by_alphabet = sort_into_categories(developers, extended_alphabet, lambda item, category: category == item['letter'])
|
||||
|
||||
genres = [keyword.capitalize() for keyword in c.recommended_keywords]
|
||||
games_by_genre = sort_into_categories(entries, genres, lambda item, category: category.lower() in item['Keywords'])
|
||||
games_by_genre = sort_into_categories(entries, genres, lambda item, category: category.lower() in item['Keyword'])
|
||||
games_by_platform = sort_into_categories(entries, c.valid_platforms, lambda item, category: category in item.get('Platform', []), 'Unspecified')
|
||||
games_by_language = sort_into_categories(entries, c.known_languages, lambda item, category: category in item['Code language'])
|
||||
|
||||
|
@ -122,8 +122,8 @@ class EntriesMaintainer:
|
||||
# get all keywords and print similar keywords
|
||||
keywords = []
|
||||
for entry in self.entries:
|
||||
keywords.extend(entry['Keywords'])
|
||||
if b'first\xe2\x80\x90person'.decode() in entry['Keywords']:
|
||||
keywords.extend(entry['Keyword'])
|
||||
if b'first\xe2\x80\x90person'.decode() in entry['Keyword']:
|
||||
print(entry['File'])
|
||||
keywords = [x.value for x in keywords]
|
||||
|
||||
@ -142,7 +142,7 @@ class EntriesMaintainer:
|
||||
# get all names of frameworks and library also using osg.code_dependencies_aliases
|
||||
valid_dependencies = list(c.general_code_dependencies_without_entry.keys())
|
||||
for entry in self.entries:
|
||||
if any((x in ('framework', 'library', 'game engine') for x in entry['Keywords'])):
|
||||
if any((x in ('framework', 'library', 'game engine') for x in entry['Keyword'])):
|
||||
name = entry['Title']
|
||||
if name in c.code_dependencies_aliases:
|
||||
valid_dependencies.extend(c.code_dependencies_aliases[name])
|
||||
@ -152,7 +152,7 @@ class EntriesMaintainer:
|
||||
# get all referenced code dependencies
|
||||
referenced_dependencies = {}
|
||||
for entry in self.entries:
|
||||
deps = entry.get('Code dependencies', [])
|
||||
deps = entry.get('Code dependency', [])
|
||||
for dependency in deps:
|
||||
dependency = dependency.value
|
||||
if dependency in referenced_dependencies:
|
||||
@ -376,10 +376,10 @@ class EntriesMaintainer:
|
||||
tocs_text = ''
|
||||
|
||||
# split into games, tools, frameworks, libraries
|
||||
games = [x for x in self.entries if not any([y in x['Keywords'] for y in ('tool', 'framework', 'library')])]
|
||||
tools = [x for x in self.entries if 'tool' in x['Keywords']]
|
||||
frameworks = [x for x in self.entries if 'framework' in x['Keywords']]
|
||||
libraries = [x for x in self.entries if 'library' in x['Keywords']]
|
||||
games = [x for x in self.entries if not any([y in x['Keyword'] for y in ('tool', 'framework', 'library')])]
|
||||
tools = [x for x in self.entries if 'tool' in x['Keyword']]
|
||||
frameworks = [x for x in self.entries if 'framework' in x['Keyword']]
|
||||
libraries = [x for x in self.entries if 'library' in x['Keyword']]
|
||||
|
||||
# create games, tools, frameworks, libraries tocs
|
||||
title = 'Games'
|
||||
@ -405,7 +405,7 @@ class EntriesMaintainer:
|
||||
# create by category
|
||||
categories_text = []
|
||||
for keyword in c.recommended_keywords:
|
||||
filtered = [x for x in self.entries if keyword in x['Keywords']]
|
||||
filtered = [x for x in self.entries if keyword in x['Keyword']]
|
||||
title = keyword.capitalize()
|
||||
name = keyword.replace(' ', '-')
|
||||
file = '_{}.md'.format(name)
|
||||
@ -506,7 +506,7 @@ class EntriesMaintainer:
|
||||
|
||||
# Keywords
|
||||
statistics += '## Keywords\n\n'
|
||||
field = 'Keywords'
|
||||
field = 'Keyword'
|
||||
|
||||
# get all keywords together
|
||||
keywords = []
|
||||
@ -556,7 +556,7 @@ class EntriesMaintainer:
|
||||
|
||||
# Code dependencies
|
||||
statistics += '## Code dependencies\n\n'
|
||||
field = 'Code dependencies'
|
||||
field = 'Code dependency'
|
||||
|
||||
# get all code dependencies together
|
||||
code_dependencies = []
|
||||
@ -653,7 +653,7 @@ class EntriesMaintainer:
|
||||
return
|
||||
|
||||
# make database out of it
|
||||
db = {'headings': ['Game', 'Description', 'Download', 'State', 'Keywords', 'Source']}
|
||||
db = {'headings': ['Game', 'Description', 'Download', 'State', 'Keyword', 'Source']}
|
||||
|
||||
entries = []
|
||||
for info in self.entries:
|
||||
@ -676,7 +676,7 @@ class EntriesMaintainer:
|
||||
'inactive since {}'.format(osg.extract_inactive_year(info)) if osg.is_inactive(info) else 'active'))
|
||||
|
||||
# keywords
|
||||
keywords = info['Keywords']
|
||||
keywords = info['Keyword']
|
||||
keywords = [x.value for x in keywords]
|
||||
entry.append(', '.join(keywords))
|
||||
|
||||
|
@ -64,7 +64,7 @@ class InspirationMaintainer:
|
||||
print('Entry "{}" listed in inspiration "{}" but this entry does not exist'.format(entry_name, inspiration_name))
|
||||
else:
|
||||
entry = x[0]
|
||||
if 'Inspirations' not in entry or inspiration_name not in entry['Inspirations']:
|
||||
if 'Inspiration' not in entry or inspiration_name not in entry['Inspiration']:
|
||||
print('Entry "{}" listed in inspiration "{}" but not listed in this entry'.format(entry_name, inspiration_name))
|
||||
print('missed inspirations checked')
|
||||
|
||||
@ -90,7 +90,7 @@ class InspirationMaintainer:
|
||||
# loop over all entries and add to inspirations of entry
|
||||
for entry in self.entries:
|
||||
entry_name = entry['Title']
|
||||
for inspiration in entry.get('Inspirations', []):
|
||||
for inspiration in entry.get('Inspiration', []):
|
||||
inspiration = inspiration.value
|
||||
if inspiration in self.inspirations:
|
||||
self.inspirations[inspiration]['Inspired entries'].append(entry_name)
|
||||
|
@ -42,12 +42,12 @@ def get_config(key):
|
||||
generic_comment_string = '[comment]: # (partly autogenerated content, edit with care, read the manual before)'
|
||||
|
||||
# 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')
|
||||
|
||||
valid_properties = ('Home', 'Media', 'Inspirations', 'State', 'Play', 'Download', 'Platform', 'Keywords', 'Code repository', 'Code language',
|
||||
'Code license', 'Code dependencies', 'Assets license', 'Developer')
|
||||
essential_fields = ('File', 'Title', 'Home', 'State', 'Keyword', 'Code repository', 'Code language', 'Code license')
|
||||
|
||||
# only these fields can be used currently (in this order)
|
||||
valid_properties = ('Home', 'Media', 'Inspiration', 'State', 'Play', 'Download', 'Platform', 'Keyword', 'Code repository', 'Code language',
|
||||
'Code license', 'Code dependency', 'Assets license', 'Developer')
|
||||
|
||||
valid_fields = ('File', 'Title') + valid_properties + ('Note', 'Building')
|
||||
|
||||
url_fields = ('Home', 'Media', 'Play', 'Download', 'Code repository')
|
||||
@ -55,7 +55,7 @@ url_fields = ('Home', 'Media', 'Play', 'Download', 'Code repository')
|
||||
valid_url_prefixes = ('http://', 'https://', 'git://', 'svn://', 'ftp://', 'bzr://')
|
||||
extended_valid_url_prefixes = valid_url_prefixes + ('@see-', '@not-', '?')
|
||||
|
||||
valid_building_properties = ('Build system', 'Build instructions')
|
||||
valid_building_properties = ('Build system', 'Build instruction')
|
||||
valid_building_fields = valid_building_properties + ('Note',)
|
||||
|
||||
# these are the only valid platforms currently (and must be given in this order)
|
||||
|
@ -3,9 +3,9 @@ Specific functions working on the games.
|
||||
"""
|
||||
|
||||
import re
|
||||
import os
|
||||
from difflib import SequenceMatcher
|
||||
from utils import utils, osg_parse
|
||||
from utils.constants import *
|
||||
from utils import utils, osg_parse, constants as c
|
||||
|
||||
regex_sanitize_name = re.compile(r"[^A-Za-z 0-9-+]+")
|
||||
regex_sanitize_name_space_eater = re.compile(r" +")
|
||||
@ -21,11 +21,11 @@ def entry_iterator():
|
||||
"""
|
||||
|
||||
# get all entries (ignore everything starting with underscore)
|
||||
entries = os.listdir(entries_path)
|
||||
entries = os.listdir(c.entries_path)
|
||||
|
||||
# iterate over all entries
|
||||
for entry in entries:
|
||||
entry_path = os.path.join(entries_path, entry)
|
||||
entry_path = os.path.join(c.entries_path, entry)
|
||||
|
||||
# ignore directories ("tocs" for example)
|
||||
if os.path.isdir(entry_path):
|
||||
@ -57,8 +57,8 @@ def read_developers():
|
||||
|
||||
:return:
|
||||
"""
|
||||
grammar_file = os.path.join(code_path, 'grammar_listing.lark')
|
||||
developers = osg_parse.read_and_parse(developer_file, grammar_file, osg_parse.ListingTransformer)
|
||||
grammar_file = os.path.join(c.code_path, 'grammar_listing.lark')
|
||||
developers = osg_parse.read_and_parse(c.developer_file, grammar_file, osg_parse.ListingTransformer)
|
||||
|
||||
# now developers is a list of dictionaries for every entry with some properties
|
||||
|
||||
@ -72,15 +72,15 @@ def read_developers():
|
||||
# check for essential, valid fields
|
||||
for dev in developers:
|
||||
# check that essential fields are existing
|
||||
for field in essential_developer_fields:
|
||||
for field in c.essential_developer_fields:
|
||||
if field not in dev:
|
||||
raise RuntimeError('Essential field "{}" missing in developer {}'.format(field, dev['Name']))
|
||||
# check that all fields are valid fields
|
||||
for field in dev.keys():
|
||||
if field not in valid_developer_fields:
|
||||
if field not in c.valid_developer_fields:
|
||||
raise RuntimeError('Invalid field "{}" in developer {}.'.format(field, dev['Name']))
|
||||
# url fields
|
||||
for field in url_developer_fields:
|
||||
for field in c.url_developer_fields:
|
||||
if field in dev:
|
||||
content = dev[field]
|
||||
if any(not (x.startswith('http://') or x.startswith('https://')) for x in content):
|
||||
@ -101,7 +101,7 @@ def write_developers(developers):
|
||||
developers = list(developers.values())
|
||||
|
||||
# comment
|
||||
content = '{}\n'.format(generic_comment_string)
|
||||
content = '{}\n'.format(c.generic_comment_string)
|
||||
|
||||
# number of developer
|
||||
content += '# Developer [{}]\n\n'.format(len(developers))
|
||||
@ -131,7 +131,7 @@ def write_developers(developers):
|
||||
content += '\n'
|
||||
|
||||
# write
|
||||
utils.write_text(developer_file, content)
|
||||
utils.write_text(c.developer_file, content)
|
||||
|
||||
|
||||
def read_inspirations():
|
||||
@ -143,8 +143,8 @@ def read_inspirations():
|
||||
# read inspirations
|
||||
|
||||
# read and parse inspirations
|
||||
grammar_file = os.path.join(code_path, 'grammar_listing.lark')
|
||||
inspirations = osg_parse.read_and_parse(inspirations_file, grammar_file, osg_parse.ListingTransformer)
|
||||
grammar_file = os.path.join(c.code_path, 'grammar_listing.lark')
|
||||
inspirations = osg_parse.read_and_parse(c.inspirations_file, grammar_file, osg_parse.ListingTransformer)
|
||||
|
||||
# now inspirations is a list of dictionaries for every entry with some properties
|
||||
|
||||
@ -158,15 +158,15 @@ def read_inspirations():
|
||||
# check for essential, valid fields
|
||||
for inspiration in inspirations:
|
||||
# check that essential fields are existing
|
||||
for field in essential_inspiration_fields:
|
||||
for field in c.essential_inspiration_fields:
|
||||
if field not in inspiration:
|
||||
raise RuntimeError('Essential field "{}" missing in inspiration {}'.format(field, inspiration['Name']))
|
||||
# check that all fields are valid fields
|
||||
for field in inspiration.keys():
|
||||
if field not in valid_inspiration_fields:
|
||||
if field not in c.valid_inspiration_fields:
|
||||
raise RuntimeError('Invalid field "{}" in inspiration {}.'.format(field, inspiration['Name']))
|
||||
# url fields
|
||||
for field in url_inspiration_fields:
|
||||
for field in c.url_inspiration_fields:
|
||||
if field in inspiration:
|
||||
content = inspiration[field]
|
||||
if any(not (x.startswith('http://') or x.startswith('https://')) for x in content):
|
||||
@ -188,7 +188,7 @@ def write_inspirations(inspirations):
|
||||
inspirations = list(inspirations.values())
|
||||
|
||||
# comment
|
||||
content = '{}\n'.format(generic_comment_string)
|
||||
content = '{}\n'.format(c.generic_comment_string)
|
||||
|
||||
# updated number of inspirations
|
||||
content += '# Inspirations [{}]\n\n'.format(len(inspirations))
|
||||
@ -218,7 +218,7 @@ def write_inspirations(inspirations):
|
||||
content += '\n'
|
||||
|
||||
# write
|
||||
utils.write_text(inspirations_file, content)
|
||||
utils.write_text(c.inspirations_file, content)
|
||||
|
||||
|
||||
def read_entries():
|
||||
@ -227,7 +227,7 @@ def read_entries():
|
||||
"""
|
||||
|
||||
# setup parser and transformer
|
||||
grammar_file = os.path.join(code_path, 'grammar_entries.lark')
|
||||
grammar_file = os.path.join(c.code_path, 'grammar_entries.lark')
|
||||
grammar = utils.read_text(grammar_file)
|
||||
parse = osg_parse.create(grammar, osg_parse.EntryTransformer)
|
||||
|
||||
@ -267,9 +267,9 @@ def check_and_process_entry(entry):
|
||||
index = 0
|
||||
for e in entry:
|
||||
field = e[0]
|
||||
while index < len(valid_fields) and field != valid_fields[index]:
|
||||
while index < len(c.valid_fields) and field != c.valid_fields[index]:
|
||||
index += 1
|
||||
if index == len(valid_fields): # must be valid fields and must be in the right order
|
||||
if index == len(c.valid_fields): # must be valid fields and must be in the right order
|
||||
message += 'Field "{}" either misspelled or in wrong order\n'.format(field)
|
||||
|
||||
# order is fine we can convert to dictionary
|
||||
@ -281,7 +281,7 @@ def check_and_process_entry(entry):
|
||||
entry = d
|
||||
|
||||
# check for essential fields
|
||||
for field in essential_fields:
|
||||
for field in c.essential_fields:
|
||||
if field not in entry:
|
||||
message += 'Essential property "{}" missing\n'.format(field)
|
||||
|
||||
@ -296,7 +296,7 @@ def check_and_process_entry(entry):
|
||||
|
||||
# check valid fields in building TODO should also check order
|
||||
for field in building.keys():
|
||||
if field not in valid_building_fields:
|
||||
if field not in c.valid_building_fields:
|
||||
message += 'Building field "{}" invalid\n'.format(field)
|
||||
entry['Building'] = building
|
||||
|
||||
@ -316,12 +316,12 @@ def check_and_process_entry(entry):
|
||||
message += 'State must be one of <"beta", "mature">'
|
||||
|
||||
# check urls
|
||||
for field in url_fields:
|
||||
for field in c.url_fields:
|
||||
values = entry.get(field, [])
|
||||
for value in values:
|
||||
if value.value.startswith('<') and value.value.endswith('>'):
|
||||
value.value = value.value[1:-1]
|
||||
if not any(value.startswith(x) for x in extended_valid_url_prefixes):
|
||||
if not any(value.startswith(x) for x in c.extended_valid_url_prefixes):
|
||||
message += 'URL "{}" in field "{}" does not start with a valid prefix'.format(value, field)
|
||||
|
||||
# github/gitlab repositories should end on .git and should start with https
|
||||
@ -339,30 +339,30 @@ def check_and_process_entry(entry):
|
||||
if 'Platform' in entry:
|
||||
index = 0
|
||||
for platform in entry['Platform']:
|
||||
while index < len(valid_platforms) and platform != valid_platforms[index]:
|
||||
while index < len(c.valid_platforms) and platform != c.valid_platforms[index]:
|
||||
index += 1
|
||||
if index == len(valid_platforms): # must be valid platforms and must be in that order
|
||||
if index == len(c.valid_platforms): # must be valid platforms and must be in that order
|
||||
message += 'Platform tag "{}" either misspelled or in wrong order'.format(platform)
|
||||
|
||||
# there must be at least one keyword
|
||||
if not entry['Keywords']:
|
||||
if not entry['Keyword']:
|
||||
message += 'Need at least one keyword'
|
||||
|
||||
# check for existence of at least one recommended keywords
|
||||
keywords = entry['Keywords']
|
||||
if not any(keyword in keywords for keyword in recommended_keywords):
|
||||
keywords = entry['Keyword']
|
||||
if not any(keyword in keywords for keyword in c.recommended_keywords):
|
||||
message += 'Entry contains no recommended keywords'
|
||||
|
||||
# languages should be known
|
||||
languages = entry['Code language']
|
||||
for language in languages:
|
||||
if language not in known_languages:
|
||||
if language not in c.known_languages:
|
||||
message += 'Language "{}" is not a known code language. Misspelled or new?'.format(language)
|
||||
|
||||
# licenses should be known
|
||||
licenses = entry['Code license']
|
||||
for license in licenses:
|
||||
if license not in known_licenses:
|
||||
if license not in c.known_licenses:
|
||||
message += 'License "{}" is not a known license. Misspelled or new?'.format(license)
|
||||
|
||||
if message:
|
||||
@ -370,6 +370,7 @@ def check_and_process_entry(entry):
|
||||
|
||||
return entry
|
||||
|
||||
|
||||
def is_inactive(entry):
|
||||
state = entry['State']
|
||||
phrase = 'inactive since '
|
||||
@ -386,6 +387,7 @@ def extract_inactive_year(entry):
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
def write_entries(entries):
|
||||
"""
|
||||
|
||||
@ -406,7 +408,7 @@ def write_entry(entry):
|
||||
# TODO check entry
|
||||
|
||||
# get path
|
||||
entry_path = os.path.join(entries_path, entry['File'])
|
||||
entry_path = os.path.join(c.entries_path, entry['File'])
|
||||
|
||||
# create output content
|
||||
content = create_entry_content(entry)
|
||||
@ -427,23 +429,23 @@ def create_entry_content(entry):
|
||||
|
||||
# we automatically sort some fields
|
||||
sort_fun = lambda x: str.casefold(x.value)
|
||||
for field in ('Media', 'Inspirations', 'Code Language'):
|
||||
for field in ('Media', 'Inspiration', 'Code Language'):
|
||||
if field in entry:
|
||||
values = entry[field]
|
||||
entry[field] = sorted(values, key=sort_fun)
|
||||
# we also sort keywords, but first the recommend ones and then other ones
|
||||
keywords = entry['Keywords']
|
||||
a = [x for x in keywords if x in recommended_keywords]
|
||||
b = [x for x in keywords if x not in recommended_keywords]
|
||||
entry['Keywords'] = sorted(a, key=sort_fun) + sorted(b, key=sort_fun)
|
||||
keywords = entry['Keyword']
|
||||
a = [x for x in keywords if x in c.recommended_keywords]
|
||||
b = [x for x in keywords if x not in c.recommended_keywords]
|
||||
entry['Keyword'] = sorted(a, key=sort_fun) + sorted(b, key=sort_fun)
|
||||
|
||||
# now properties in the recommended order
|
||||
for field in valid_properties:
|
||||
# now all properties in the recommended order
|
||||
for field in c.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))
|
||||
e = entry[field]
|
||||
e = ['"{}"'.format(x) if any(y in x.value for y in (',', ' (')) else x for x in e]
|
||||
e = [str(x) for x in e]
|
||||
content += '- {}: {}\n'.format(field, ', '.join(e))
|
||||
content += '\n'
|
||||
|
||||
# if there is a note, insert it
|
||||
@ -455,15 +457,15 @@ def create_entry_content(entry):
|
||||
|
||||
# building properties if present
|
||||
has_properties = False
|
||||
for field in valid_building_properties:
|
||||
for field in c.valid_building_properties:
|
||||
if field in entry['Building']:
|
||||
if not has_properties:
|
||||
has_properties = True
|
||||
content += '\n'
|
||||
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))
|
||||
e = entry['Building'][field]
|
||||
e = ['"{}"'.format(x) if ',' in x else x for x in e]
|
||||
e = [str(x) for x in e]
|
||||
content += '- {}: {}\n'.format(field, ', '.join(e))
|
||||
|
||||
# if there is a note, insert it
|
||||
if 'Note' in entry['Building']:
|
||||
@ -479,7 +481,7 @@ def is_url(str):
|
||||
:param str:
|
||||
:return:
|
||||
"""
|
||||
if any(str.startswith(x) for x in valid_url_prefixes) and not ' ' in str:
|
||||
if any(str.startswith(x) for x in c.valid_url_prefixes) and not ' ' in str:
|
||||
return True
|
||||
return False
|
||||
|
||||
@ -494,7 +496,7 @@ def all_urls(entries):
|
||||
# iterate over entries
|
||||
for entry in entries:
|
||||
file = entry['File']
|
||||
for field in url_fields: # TODO there are other fields, maybe just regex on the whole content
|
||||
for field in c.url_fields: # TODO there are other fields, maybe just regex on the whole content
|
||||
for value in entry.get(field, []):
|
||||
if value.comment:
|
||||
value = value.value + ' ' + value.comment
|
||||
|
Reference in New Issue
Block a user