adding developers

This commit is contained in:
Trilarion
2020-02-10 12:35:22 +01:00
parent eeb20a670a
commit 48ade4bc0b
13 changed files with 345 additions and 14 deletions

View File

@ -8,10 +8,10 @@ property: "- " _key ": " _value "\n"
_key: /(?! ).+?(?=:)(?<! )/ // key: everything until next ":", not beginning or ending with a space
_value: /.+(?<! )/ // everything until the end of the line, not ending with a space
name: /.+?(?= \()/ // developer name: everything until " ("
name: /.+?(?= \()/ // developer name: everything until " ("
number: /[0-9]+/
COMMENT: /^\[comment\]: #.*$\n/m // [comment]: # xxx
COMMENT: /^\[comment\]: #.*$\n/m // [comment]: # xxx
_E: /^$\n/m // empty new line
%ignore COMMENT

View File

@ -0,0 +1,129 @@
"""
Checks the entries and tries to detect additional developer content, by retrieving websites or logging information from
stored Git repositories.
"""
import os
import requests
from bs4 import BeautifulSoup
from utils import constants as c, utils, osg, osg_github
def developer_info_lookup(name):
for dev in developer_info:
if name == dev['name']:
return dev
return None
# author names in SF that aren't the author names how we have them
SF_alias_list = {'Erik Johansson (aka feneur)': 'Erik Johansson', 'Itms': 'Nicolas Auvray', 'Wraitii': 'Lancelot de Ferrière', 'Simzer': 'Simon Laszlo', 'armin bajramovic': 'Armin Bajramovic'}
if __name__ == "__main__":
# read developer info
developer_info = osg.read_developer_info()
osg.write_developer_info(developer_info)
# assemble info
entries = osg.assemble_infos()
# loop over infos
developers = ''
try:
i = 0
#active = False
for entry in entries:
#if entry['name'] == 'Aleph One':
# active = True
#if not active:
# continue
# for testing purposes
i += 1
if i > 40:
break
# print
entry_name = '{} - {}'.format(entry['file'], entry['name'])
print(entry_name)
content = ''
entry_developer = entry.get('developer', [])
# parse home
home = entry['home']
# sourceforge project site
prefix = 'https://sourceforge.net/projects/'
url = [x for x in home if x.startswith(prefix)]
if len(url) == 1:
url = url[0]
print(' sourceforge project site: {}'.format(url))
url = 'https://sourceforge.net/p/' + url[len(prefix):] + '_members/'
response = requests.get(url)
soup = BeautifulSoup(response.text, 'html.parser')
authors = soup.find('div', id='content_base').find('table').find_all('tr')
authors = [author.find_all('td') for author in authors]
authors = [author[1].a['href'] for author in authors if len(author) == 3]
for author in authors:
# sometimes author already contains the full url, sometimes not
url = 'https://sourceforge.net' + author if not author.startswith('http') else author
response = requests.get(url)
url = response.url # could be different now
if 'auth/?return_to' in url:
# for some reason authorisation is forbidden
author_name = author
nickname = author
else:
soup = BeautifulSoup(response.text, 'html.parser')
author_name = soup.h1.get_text()
author_name = SF_alias_list.get(author_name, author_name) # replace by alias if possible
nickname = soup.find('dl', class_= 'personal-data').find('dd').get_text()
nickname = nickname.replace('\n', '').strip()
dev = developer_info_lookup(author_name)
in_devs = dev and 'contact' in dev and nickname + '@SF' in dev['contact']
in_entry = author_name in entry_developer
if in_devs and in_entry:
continue # already existing in entry and devs
content += ' {} : {}@SF'.format(author_name, nickname)
if not in_devs:
content += ' (not in devs)'
if not in_entry:
content += ' (not in entry)'
content += '\n'
# parse source repository
repos = entry.get('code repository', [])
# Github
urls = [x for x in repos if x.startswith('https://github.com/')]
urls = []
for url in urls:
print(' github repo: {}'.format(url))
github_info = osg_github.retrieve_repo_info(url)
for contributor in github_info['contributors']:
name = contributor.name
dev = developer_info_lookup(name)
in_devs = dev and 'contact' in dev and contributor.login + '@GH' in dev['contact']
in_entry = name in entry_developer
if in_devs and in_entry:
continue # already existing in entry and devs
content += ' {}: {}@GH'.format(name, contributor.login)
if contributor.blog:
content += ' url: {}'.format(contributor.blog)
if not in_devs:
content += ' (not in devs)'
if not in_entry:
content += ' (not in entry)'
content += '\n'
if content:
developers += '{}\n\n{}\n'.format(entry_name, content)
except RuntimeError as e:
raise(e)
# pass
finally:
# store developer info
utils.write_text(os.path.join(c.root_path, 'collected_developer_info.txt'), developers)

View File

@ -1,2 +1,3 @@
pygithub
lark-parser
BeautifulSoup

View File

@ -15,7 +15,7 @@ class ListingTransformer(lark.Transformer):
raise lark.Discard
def property(self, x):
return (x[0].value, x[1].value)
return (x[0].value.lower(), x[1].value)
def name(self, x):
return ('name', x[0].value)
@ -71,6 +71,8 @@ code_dependencies_without_entry = {'OpenGL': 'https://www.opengl.org/',
regex_sanitize_name = re.compile(r"[^A-Za-z 0-9-+]+")
regex_sanitize_name_space_eater = re.compile(r" +")
valid_developer_fields = ('name', 'games', 'contact', 'organization', 'home')
comment_string = '[comment]: # (partly autogenerated content, edit with care, read the manual before)'
@ -378,7 +380,22 @@ def read_developer_info():
developer_file = os.path.join(c.root_path, 'developer.md')
grammar_file = os.path.join(c.code_path, 'grammar_listing.lark')
transformer = ListingTransformer()
return read_and_parse(developer_file, grammar_file, transformer)
developers = read_and_parse(developer_file, grammar_file, transformer)
# now transform a bit more
for index, dev in enumerate(developers):
for field in dev.keys():
if field not in valid_developer_fields:
raise RuntimeError('Unknown developer field "{}" for developer: {}.'.format(field, dev['name']))
for field in ('name', 'organization'):
if field in dev:
dev[field] = dev[field].strip()
for field in ('games', 'contact'):
if field in dev:
content = dev[field]
content = content.split(',')
content = [x.strip() for x in content]
dev[field] = content
return developers
def write_developer_info(developers):
@ -386,7 +403,38 @@ def write_developer_info(developers):
:return:
"""
# comment
content = '{}\n'.format(comment_string)
# number of developer
content += '# Developer ({})\n\n'.format(len(developers))
# sort by name
developers.sort(key=lambda x: str.casefold(x['name']))
# iterate over them
for dev in developers:
# developer name
content += '## {} ({})\n\n'.format(dev['name'], len(dev['games']))
# games
content += '- Games: {}\n'.format(', '.join(sorted(dev['games'], key=str.casefold)))
# all the remaining in alphabetical order
for field in sorted(dev.keys()):
if field not in ('name', 'games'):
value = dev[field]
field = field.capitalize()
if isinstance(value, str):
content += '- {}: {}\n'.format(field, value)
else:
content += '- {}: {}\n'.format(field, ', '.join(sorted(value, key=str.casefold)))
content += '\n'
# write
developer_file = os.path.join(c.root_path, 'developer.md')
utils.write_text(developer_file, content)
def read_inspirations_info():

View File

@ -5,16 +5,45 @@ Everything specific to the Github API (via PyGithub).
from github import Github
def normalize_repo_name(repo):
"""
Bring repo to style xxx/yyy
"""
prefix = 'https://github.com/'
if repo.startswith(prefix):
repo = repo[len(prefix):]
suffix = '.git'
if repo.endswith(suffix):
repo = repo[:-len(suffix)]
return repo
def repo_get_contributors(repo):
contributors = []
c = repo.get_contributors()
for i in range(c.totalCount):
contributors.append(c[i])
return contributors
def retrieve_repo_info(repos):
"""
For a list of Github repos, retrieves repo information
For a list of Github repos, retrieves repo information.
Repos must be have the style xxx/yyy example: "PyGithub/PyGithub"
"""
single_repo = isinstance(repos, str)
if single_repo:
repos = (repos,)
result = []
g = Github()
for repo in repos:
repo = normalize_repo_name(repo)
r = g.get_repo(repo)
e = {'archived': r.archived, 'description': r.description, 'language': r.language,
'last modified': r.last_modified, 'open issues count': r.open_issues_count,
e = {'archived': r.archived, 'contributors': repo_get_contributors(r), 'description': r.description,
'language': r.language, 'last modified': r.last_modified, 'open issues count': r.open_issues_count,
'stars count': r.stargazers_count, 'topics': r.topics, 'repo': repo}
result.append(e)
if single_repo:
result = result[0]
return result

View File

@ -79,6 +79,7 @@
## Ari Mustonen (1)
- Games: Hex-a-hop
- Contact: amuzen@SF
## Arne Reiners (1)
@ -137,6 +138,12 @@
- Games: XBill
## Ben Brian (1)
- Games: 0 A.D.
- Home: https://benbrian.net/
- Contact: historic_bruno@SF, historicbruno@GH
## Bruno Ethvignot (2)
- Games: Powermanga, TecnoballZ
@ -199,6 +206,21 @@
- Games: Colobot: Gold Edition
- Organization: Epsitec
## Nicolas Auvray (1)
- Games: 0 A.D.
- Contact: itms@SF, na-Itms@GH
## Philip Taylor (1)
- Games: 0 A.D.
- Contact: philiptaylor@SF, philiptaylor@GH
## Lancelot de Ferrière (1)
- Games: 0 A.D.
- Contact: wraitii@SF, wraitii@GH
## Daniele Napolitano (1)
- Games: Gweled
@ -450,6 +472,31 @@
- Games: Fairy-Max
## Dorfdrull (1)
- Games: Advanced Strategic Command
- Contact: dorfdrull@SF
## Michael Moerz (1)
- Games: Advanced Strategic Command
- Contact: natoka@SF
## Armin Bajramovic (1)
- Games: Advanced Strategic Command
- Contact: armin906@SF
## Frederik Kesting (1)
- Games: Advanced Strategic Command
- Contact: ocl4nis@SF
## Torsten Maekler (1)
- Games: Advanced Strategic Command
- Contact: tmaekler@SF
## Harmen van der Wal (1)
- Games: Hypercube
@ -544,7 +591,7 @@
## Jason Rohrer (8)
- Games: Between, Cultivation, Gravitation, One Hour One Life, Passage, Primrose, Sleep Is Death, Transcend
- Contact: jcr13@SF
- Contact: jcr13@SF, jasonrohrer@GH
## Jay Fenlason (1)
@ -612,6 +659,12 @@
## Johan Peitz (1)
- Games: Alex the Allegator 4
- Contact: peitz@SF
## Erik Johansson (1)
- Games: 0 A.D.
- Contact: feneur@SF
## Johannes Bergmeier (1)
@ -748,6 +801,12 @@
- Games: TecnoballZ
## Laurent (1)
- Games: 2048
- Home: https://uto.io/
- Contact: marg51@GH
## legoluft (1)
- Games: Krank
@ -827,6 +886,21 @@
- Games: Holtz
## Martin Bickel (1)
- Games: Advanced Strategic Command
- Contact: valharis@SF, ValHaris@GH
## Christian Schramm (1)
- Games: Advanced Strategic Command
- Contact: Ed-von-Schleck@GH
## valuial (1)
- Games: Advanced Strategic Command
- Contact: valuial@GH
## Masanao Izumo (1)
- Games: Kobo Deluxe
@ -1033,6 +1107,7 @@
## Paul Wise (1)
- Games: Hex-a-hop
- Contact: pabs3@SF
## Pete Shinners (1)
@ -1073,6 +1148,11 @@
- Games: Trip on the Funny Boat
## Pureon (1)
- Games: 0 A.D.
- Contact: ipureon@SF
## PyMike (1)
- Games: Mrfuze
@ -1193,6 +1273,11 @@
- Games: Freya Game Engine
- Contact: pond@SF
## Kayl (1)
- Games: 2H4U
- Contact: kaylnet@SF
## Shard (1)
- Games: Anagramarama
@ -1217,6 +1302,33 @@
## Simon Laszlo (1)
- Games: 4D-TRIS
- Contact: simzer@SF
## s0600204 (1)
- Games: 0 A.D.
- Contact: s0600204@GH
## Hilarious001 (1)
- Games: 2Moons Browsergame Engine
- Contact: Hilarious001@GH
## Ozan Kurt (1)
- Games: 2Moons Browsergame Engine
- Contact: OzanKurt@GH
## leper (1)
- Games: 0 A.D.
- Contact: leper@GH
## Kieran Pilkington (1)
- Games: 0 A.D.
- Home: https://k776.tumblr.com/
- Contact: KieranP@GH
## Simon Peter (1)
@ -1384,6 +1496,16 @@
- Games: Qonk
## Alex Clark (1)
- Games: Abe's Amazing Adventure
- Contact: jazkat@SF
## Pedro Izecksohn (1)
- Games: Abe's Amazing Adventure
- Contact: izecksohn@SF
## Tuscan Knox (1)
- Games: Shotgun Debugger

View File

@ -13,6 +13,7 @@ _0 A.D. is a free, open-source, cross-platform real-time strategy game._
- Code license: GPL-2.0
- Code dependencies: libogg, libvorbis, libxml2, OpenAL, SDL2, zlib
- Assets license: CC-BY-SA-3.0
- Developer: Erik Johansson, Ben Brian, Nicolas Auvray, Philip Taylor, Lancelot de Ferrière, s0600204, Kieran Pilkington, leper, Pureon
Engine part is called Pyrogenesis.

View File

@ -11,7 +11,7 @@ _Sliding block puzzle game._
- Code language: JavaScript
- Code license: MIT
- Assets license: MIT (very few assets)
- Developer: Gabriele Cirulli, Jerry Jiang (Android port)
- Developer: Gabriele Cirulli, Laurent, Jerry Jiang (Android port)
Port to Android: https://github.com/tpcstld/2048

View File

@ -10,6 +10,6 @@ _Mix between a Tetris-like game and a wall breaker._
- Code language: C++
- Code license: GPL-2.0
- Code dependencies: SDL
- Developer: Piwai
- Developer: Piwai, Kayl
## Building

View File

@ -10,7 +10,7 @@ _Space browsergame framework._
- Code repository: https://github.com/jkroepke/2Moons.git (archived), https://github.com/steemnova/steemnova.git (+)
- Code language: PHP, JavaScript
- Code license: MIT
- Developer: Jan-Otto Kröpke
- Developer: Jan-Otto Kröpke, Ozan Kurt
## Building

View File

@ -11,7 +11,7 @@ _Side scrolling platform game._
- Code language: C
- Code license: GPL-2.0
- Code dependencies: SDL
- Developer: Gabor Torok
- Developer: Gabor Torok, Pedro Izecksohn, Alex Clark
## Building

View File

@ -9,6 +9,7 @@ _Turn based strategy game._
- Code repository: https://github.com/ValHaris/asc-hq.git
- Code language: C++
- Code license: GPL-2.0
- Developer: Martin Bickel, Christian Schramm, valuial, Armin Bajramovic, Dorfdrull, Michael Moerz, Frederik Kesting, Torsten Maekler
## Building

View File

@ -12,7 +12,7 @@ _Retro-style platformer._
- Code license: GPL-2.0
- Code dependencies: Allegro
- Assets license: GPL-2.0
- Developer: Johan Peitz (design source code and graphics), Anders Svensson (music and sound effects)
- Developer: Johan Peitz (design source code and graphics), Anders Svensson (music and sound effects), Paul Wise
## Building