Created
February 18, 2016 20:19
-
-
Save jnm/ea06626ab51ce61e044a to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import requests | |
import sys | |
import xml | |
import hashlib | |
import getpass | |
import datetime | |
from collections import OrderedDict | |
from django.conf import settings | |
from django.contrib.auth.models import User | |
from reporter.models import Rendering | |
LOCAL_USER_FIELDS = ( | |
'first_name', | |
'last_name', | |
'username', | |
'date_joined', | |
'last_login', | |
'email' | |
) | |
KC_PROFILE_FIELDS = ('organization',) | |
RENDERING_FIELDS = ('created', 'submission_count()', 'template__name') | |
KC_PROFILE_ENDPOINT = '{}/api/v1/profiles'.format(settings.KC_URL) | |
KC_FORM_ENDPOINT = '{}/api/v1/forms'.format(settings.KC_URL) | |
def print_tabular(list_of_dicts): | |
# TODO: Handle data that includes tab characters | |
if not len(list_of_dicts): | |
return | |
print '\t'.join(list_of_dicts[0].keys()) | |
for r in list_of_dicts: | |
print '\t'.join(r.values()) | |
def render_field(obj, field_name): | |
if field_name.endswith('()'): | |
is_method = True | |
field_name = field_name[:-2] | |
else: | |
is_method = False | |
field = get_related_field(obj, field_name) | |
if is_method: | |
field = field() | |
if type(field) is datetime.datetime: | |
# Excel compatibility | |
return field.strftime('%Y-%m-%d %H:%M:%S') | |
else: | |
return str(field) | |
def get_related_field(obj, field_name): | |
# Is there really not a Django utility function for this? | |
path = field_name.split('__') | |
field = obj | |
for p in path: | |
field = getattr(field, p) | |
return field | |
def user_report(): | |
sys.stderr.write('Loading profiles from KC...') | |
kc_response = requests.get(KC_PROFILE_ENDPOINT) | |
kc_profiles = {p['username']: p for p in kc_response.json()} | |
sys.stderr.write(' Done!\n') | |
user_report = [] | |
for user in User.objects.all(): | |
row = OrderedDict() | |
try: | |
profile = kc_profiles[user.username] | |
except KeyError: | |
sys.stdout.write(u'No profile for {}!\n'.format(user.username)) | |
profile = None | |
for f in LOCAL_USER_FIELDS: | |
row[f] = render_field(user, f) | |
for f in KC_PROFILE_FIELDS: | |
if profile is not None: | |
row[f] = profile[f] | |
else: | |
row[f] = str(None) | |
user_report.append(row) | |
print_tabular(user_report) | |
def project_report(): | |
print 'Please log in with a KC superuser.' | |
kc_super_username = raw_input('Username: ') | |
kc_super_password = getpass.getpass() | |
project_report = [] | |
sys.stderr.write('Processing projects') | |
for rendering in Rendering.objects.all(): | |
# Get a MD5 sum of the XML body of the KC form, hopefully to ease | |
# identification. Once `Rendering` is changed to include which `Form` | |
# was used, this won't be necessary | |
parsed_url = urlparse(rendering.url) | |
numeric_id = int(parsed_url.path.split('/')[-1]) | |
xml_url = '{}/{}/form.xml'.format(KC_FORM_ENDPOINT, numeric_id) | |
kc_response = requests.get( | |
xml_url, auth=(kc_super_username, kc_super_password)) | |
if kc_response.status_code != requests.codes.ok: | |
sys.stderr.write( | |
'\nHTTP {}: Failed to get XML for form {}!\n'.format( | |
kc_response.status_code, numeric_id) | |
) | |
form_md5 = str(None) | |
form_title = str(None) | |
else: | |
root_el = xml.etree.ElementTree.fromstring(kc_response.content) | |
# Yo dawg, I heard you liked XML... | |
root_el = xml.etree.ElementTree.fromstring( | |
root_el.text.encode('utf-8')) | |
body_el = root_el.find('{http://www.w3.org/1999/xhtml}body') | |
form_md5 = hashlib.md5( | |
''.join(body_el.itertext()).encode('utf-8') | |
).hexdigest() | |
# There are better ways to get the title, but since we already have | |
# the XML... | |
title_el = root_el.find('.//{http://www.w3.org/1999/xhtml}title') | |
form_title = title_el.text | |
sys.stderr.write('.') | |
####################################################################### | |
row = OrderedDict() | |
row['md5'] = form_md5 | |
row['title'] = form_title | |
for f in RENDERING_FIELDS: | |
row[f] = render_field(rendering, f) | |
project_report.append(row) | |
sys.stderr.write('\n') | |
print_tabular(project_report) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment