Skip to content

Commit

Permalink
Updates thanks to focus on project and a projects funding links (#20)
Browse files Browse the repository at this point in the history
  • Loading branch information
tomdottom authored May 20, 2018
2 parents ebc3a75 + d040d0e commit 1737fe0
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 74 deletions.
4 changes: 3 additions & 1 deletion thanks/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@
@click.option('--debug', is_flag=True, help='Set debug mode')
def main(requirements, debug):
"""Console script for thanks."""
Thanks(debug=debug).find_package_roles(requirements)
with open(requirements, 'r') as fh:
requirements = fh.read().strip().split()
Thanks(debug=debug).find_project_details(requirements)
return 0


Expand Down
21 changes: 10 additions & 11 deletions thanks/thanks.json
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
{
"amoffat": "http://formconstantdance.org/donate",
"brosner": "https://earn.com/brosner/",
"django": "https://www.djangoproject.com/fundraising/",
"freakboy3742": "https://pybee.org/contributing/membership/",
"jezdez": "https://www.paypal.me/jezdez",
"kennethreitz": "https://paypal.me/kennethreitz42",
"lamby": "https://www.paypal.me/lambyuk",
"nedbatchelder": "https://www.paypal.me/nedbat",
"phildini": "https://patreon.com/phildini",
"singingwolfboy": "https://earn.com/singingwolfboy/",
"untitaker": "https://www.paypal.me/untitaker"
"coverage": {
"url": "https://www.paypal.me/nedbat",
"authors": ["Ned Batchelder"]
},
"django": {"url": "https://www.djangoproject.com/fundraising/"},
"virtualenv": {"url": "https://www.paypal.me/untitaker"},
"thanks": {
"url": "https://patreon.com/phildini",
"authors": ["Philip James", "Tom Marks"]
}
}
139 changes: 77 additions & 62 deletions thanks/thanks.py
Original file line number Diff line number Diff line change
@@ -1,82 +1,97 @@
# -*- coding: utf-8 -*-

from collections import namedtuple
from humanfriendly.tables import format_pretty_table
import json
import os
try:
import pip._internal as pip
except ImportError:
import pip
import requirements
import requests
from termcolor import colored, cprint
try:
import xmlrpclib
except ImportError:
import xmlrpc.client as xmlrpclib


json_file = ("{}/thanks.json".format(os.path.dirname(os.path.realpath(__file__))))
client = xmlrpclib.ServerProxy('https://pypi.python.org/pypi')
JSON_FILE = ("{}/thanks.json".format(os.path.dirname(os.path.realpath(__file__))))

ProjectData = namedtuple('ProjectData', ['name', 'funding_link', 'authors'])


class Thanks():
def __init__(self, debug=False):
self.debug = debug
self.data = {}
with open(json_file, 'r') as j:
print('Loading data about {}'.format(colored('contributors...', 'cyan')))
self.data = json.load(j)
self.data = self.load_local_project_data()
self.give_thanks_to = {}
self.local_installs = {}
for package in pip.get_installed_distributions():
self.local_installs[package.key] = package

def find_package_roles(self, requirements_file):
with open(requirements_file, 'r') as reqs:
print('Scanning your {} file...'.format(colored('requirements', 'red')))
for req in requirements.parse(reqs):
self.update_give_thanks(req.name)
if req.name in self.local_installs:
for package in self.local_installs[req.name].requires():
self.update_give_thanks(package.key)
if self.give_thanks_to:
cprint(
'You depend on {} who would {}'.format(
colored('{} authors'.format(len(self.give_thanks_to)), 'cyan'),
colored('enjoy donations!', 'green'),
), attrs=['bold'])
table_data = []
for contributor in self.give_thanks_to:
table_data.append(
[
colored(contributor, 'cyan'),
colored(self.give_thanks_to[contributor]['url'], 'green'),
colored(", ".join(set(self.give_thanks_to[contributor]['packages'])), 'red'),
]
)
print(format_pretty_table(
data=table_data,
column_names=['Author', 'Where to thank', 'Packages'],
horizontal_bar=' ',
vertical_bar=' ',
))
def load_local_project_data(self):
print('Loading data about {}'.format(colored('contributors...', 'cyan')))
with open(JSON_FILE, 'r') as fh:
data = json.load(fh)
for project_name in data.keys():
authors = ', '.join(data[project_name].get('authors', []))
data[project_name]['authors'] = authors
return data

def find_project_details(self, requirements_list):
print('Scanning your {} file...'.format(colored('requirements', 'red')))
reqs = [
next(requirements.parse(r))
for r in requirements_list
]
for req in reqs:
self.update_give_thanks(req.name)
self._display_thanks()

def _display_thanks(self):
if self.give_thanks_to:
cprint(
'You depend on {} who would {}'.format(
colored('{} authors'.format(len(self.give_thanks_to)), 'cyan'),
colored('enjoy donations!', 'green'),
), attrs=['bold'])
colorized_data = [
ProjectData(
name=colored(pd.name, 'cyan'),
funding_link=colored(pd.funding_link, 'green'),
authors=colored(pd.authors, 'yellow'),
)
for pd in self.give_thanks_to.values()
]

print(format_pretty_table(
data=colorized_data,
column_names=['Project', 'Where to thank', 'Authors'],
horizontal_bar=' ',
vertical_bar=' ',
))

def get_local_data(self, project_name):
if project_name in self.data:
data = ProjectData(
name=project_name,
funding_link=self.data[project_name]['url'],
authors=self.data[project_name]['authors']
)
else:
data = None
return data

def get_remote_data(self, project_name):
url_format = 'https://pypi.org/pypi/{}/json'.format
try:
resp = requests.get(url_format(project_name))
project_data = resp.json()
data = ProjectData(
name=project_name,
funding_link=project_data['info'].get('funding_url', ''),
authors=project_data['info'].get('author', '')
)
except requests.exceptions.ConnectionError:
data = None
except json.decoder.JSONDecodeError:
data = None
return data

def update_give_thanks(self, package_name):
if self.debug:
print('Checking ', package_name)
try:
roles = client.package_roles(package_name)
role_names = set(role[1] for role in roles)
if self.debug:
print('Checking role names: ', role_names)
for name in role_names:
if name in self.give_thanks_to:
self.give_thanks_to[name]['packages'].append(package_name)
else:
if name in self.data:
self.give_thanks_to[name] = {
'url': self.data[name],
'packages': [package_name],
}
except TypeError:
pass
package_data = self.get_local_data(package_name) or self.get_remote_data(package_name)
if package_data:
self.give_thanks_to[package_name] = package_data

0 comments on commit 1737fe0

Please sign in to comment.