diff --git a/gitfiti.py b/gitfiti.py index 584ddbd8c..515660664 100755 --- a/gitfiti.py +++ b/gitfiti.py @@ -1,7 +1,18 @@ #!/usr/bin/env python -import os, sys, datetime, math, itertools, urllib2, json +""" +gitfiti -title=''' +noun : Carefully crafted graffiti in a github commit history calendar + +""" + +import datetime +import math +import itertools +import urllib2 +import json + +TITLE = ''' _ __ _____ __ _ ____ _(_) /_/ __(_) /_(_) / __ `/ / __/ /_/ / __/ / @@ -10,7 +21,7 @@ title=''' /____/ ''' -kitty=[ +KITTY = [ [0,0,0,4,0,0,0,0,4,0,0,0], [0,0,4,2,4,4,4,4,2,4,0,0], [0,0,4,2,2,2,2,2,2,4,0,0], @@ -19,7 +30,7 @@ kitty=[ [2,2,4,2,2,2,2,2,2,4,2,2], [0,0,0,3,4,4,4,4,3,0,0,0]] -oneup=[ +ONEUP = [ [0,4,4,4,4,4,4,4,0], [4,3,2,2,1,2,2,3,4], [4,2,2,1,1,1,2,2,4], @@ -28,7 +39,7 @@ oneup=[ [0,4,1,1,1,1,1,4,0], [0,0,4,4,4,4,4,0,0]] -oneup2=[ +ONEUP2 = [ [0,0,4,4,4,4,4,4,4,0,0], [0,4,2,2,1,1,1,2,2,4,0], [4,3,2,2,1,1,1,2,2,3,4], @@ -37,7 +48,7 @@ oneup2=[ [0,0,4,1,1,1,1,1,4,0,0], [0,0,0,4,4,4,4,4,0,0,0]] -hackerschool=[ +HACKERSCHOOL = [ [4,4,4,4,4,4], [4,3,3,3,3,4], [4,1,3,3,1,4], @@ -46,7 +57,7 @@ hackerschool=[ [0,0,4,4,0,0], [4,4,4,4,4,4]] -octocat=[ +OCTOCAT = [ [0,0,0,4,0,0,0,4,0], [0,0,4,4,4,4,4,4,4], [0,0,4,1,3,3,3,1,4], @@ -55,7 +66,7 @@ octocat=[ [0,0,4,4,4,4,4,4,4], [0,0,4,0,4,0,4,0,4]] -octocat2=[ +OCTOCAT2 = [ [0,0,4,0,0,4,0], [0,4,4,4,4,4,4], [0,4,1,3,3,1,4], @@ -64,7 +75,7 @@ octocat2=[ [0,4,4,4,4,4,0], [0,0,0,4,4,4,0]] -hello=[ +HELLO = [ [0,1,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,4], [0,2,0,0,0,0,0,0,0,2,0,2,0,0,0,0,0,4], [0,3,3,3,0,2,3,3,0,3,0,3,0,1,3,1,0,3], @@ -73,7 +84,7 @@ hello=[ [0,2,0,2,0,2,0,0,0,2,0,2,0,2,0,2,0,0], [0,1,0,1,0,1,1,1,0,1,0,1,0,1,1,1,0,4]] -hireme=[ +HIREME = [ [1,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], [2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], [3,3,3,0,2,0,3,3,3,0,2,3,3,0,0,3,3,0,3,0,0,2,3,3], @@ -82,7 +93,7 @@ hireme=[ [2,0,2,0,2,0,2,0,0,0,2,0,0,0,0,2,0,2,0,2,0,2,0,0], [1,0,1,0,1,0,1,0,0,0,1,1,1,0,0,1,0,1,0,1,0,1,1,1]] -ascii_to_number = { +ASCII_TO_NUMBER = { '_': 0, '_': 1, '~': 2, @@ -91,24 +102,21 @@ ascii_to_number = { } def str_to_sprite(content): - # Break out lines and filter any excess - lines = content.split('\n') - def is_empty_line(line): - return len(line) != 0 - lines = filter(is_empty_line, lines) + # Break out lines and filter any excess + lines = content.split('\n') + def is_empty_line(line): + return len(line) != 0 + lines = filter(is_empty_line, lines) + # Break up lines into each character + split_lines = map(list, lines) + # Replace each character with its numeric equivalent + for line in split_lines: + for index, char in enumerate(line): + line[index] = ASCII_TO_NUMBER.get(char, 0) + # Return the formatted str + return split_lines - # Break up lines into each character - split_lines = map(list, lines) - - # Replace each character with its numeric equivalent - for line in split_lines: - for index, char in enumerate(line): - line[index] = ascii_to_number.get(char, 0) - - # Return the formatted str - return split_lines - -oneup_str = str_to_sprite(""" +ONEUP_STR = str_to_sprite(""" ******* *=~~-~~=* *~~---~~* @@ -118,164 +126,196 @@ oneup_str = str_to_sprite(""" ***** """) -images={ -'kitty':kitty, -'oneup':oneup, -'oneup2':oneup2, -'hackerschool':hackerschool, -'octocat':octocat, -'octocat2':octocat2, -'hello':hello, -'hireme':hireme, -'oneup_str':oneup_str +IMAGES = { +'kitty': KITTY, +'oneup':ONEUP, +'oneup2':ONEUP2, +'hackerschool':HACKERSCHOOL, +'octocat':OCTOCAT, +'octocat2':OCTOCAT2, +'hello':HELLO, +'hireme':HIREME, +'oneup_str':ONEUP_STR } -def load_images(imgNames): - """loads user images from given file(s)""" - if imgNames[0]=='': - return dict() - for imageName in imgNames: - img = open(imageName) - loadedImgs = {} - imgList = '' - imgLine = ' ' - name = img.readline().replace('\n', '') - name = name[1:] +def load_images(img_names): + """loads user images from given file(s)""" + if img_names[0] == '': + return dict() + for image_name in img_names: + img = open(image_name) + loaded_imgs = {} + img_list = '' + img_line = ' ' + name = img.readline().replace('\n', '') + name = name[1:] - while True: - imgLine = img.readline() - if imgLine == '': - break - imgLine.replace('\n', '') - if(imgLine[0] == ':'): - loadedImgs[name] = json.loads(imgList) - name = imgLine[1:] - imgList = '' - else: - imgList += imgLine - loadedImgs[name] = json.loads(imgList) - return loadedImgs + while True: + img_line = img.readline() + if img_line == '': + break + img_line.replace('\n', '') + if(img_line[0] == ':'): + loaded_imgs[name] = json.loads(img_list) + name = img_line[1:] + img_list = '' + else: + img_list += img_line + loaded_imgs[name] = json.loads(img_list) + return loaded_imgs -def get_calendar(username): - """retrieves the github commit calendar data for a username""" - BASEURL='https://github.com/' - url = BASEURL + 'users/' + username + '/contributions_calendar_data' - page = urllib2.urlopen(url) - return json.load(page) +def get_calendar(username, base_url='https://github.com/'): + """retrieves the github commit calendar data for a username""" + url = base_url + 'users/' + username + '/contributions_calendar_data' + try: + page = urllib2.urlopen(url) + except (urllib2.HTTPError,urllib2.URLError) as e: + print "There was a problem fetching data from {0}".format(url) + print e + raise SystemExit + return json.load(page) def max_commits(input): - """finds the highest number of commits in one day""" - output = set() - for i, j in enumerate(input): - output.add(input[i][1]) - output = list(output) - output.sort() - output.reverse() - return output[0] + """finds the highest number of commits in one day""" + output = set() + for i, j in enumerate(input): + output.add(input[i][1]) + output = list(output) + output.sort() + output.reverse() + return output[0] def multiplier(max_commits): - """calculates a multiplier to scale github colors to commit history""" - m = max_commits/4.0 - if m == 0: return 1 - m = math.ceil(m) - m = int(m) - return m + """calculates a multiplier to scale github colors to commit history""" + m = max_commits/4.0 + if m == 0: return 1 + m = math.ceil(m) + m = int(m) + return m def get_start_date(): - '''returns a datetime object for the first sunday after one year ago today at 12:00 noon''' - d = datetime.datetime.today() - date = datetime.datetime(d.year-1, d.month, d.day, 12) - weekday = datetime.datetime.weekday(date) - while weekday < 6: - date = date + datetime.timedelta(1) - weekday = datetime.datetime.weekday(date) - return date + """returns a datetime object for the first sunday after one year ago today + at 12:00 noon""" + d = datetime.datetime.today() + date = datetime.datetime(d.year-1, d.month, d.day, 12) + weekday = datetime.datetime.weekday(date) + while weekday < 6: + date = date + datetime.timedelta(1) + weekday = datetime.datetime.weekday(date) + return date def date_gen(start_date, offset=0): - '''generator that returns the next date, requires a datetime object as input. The offset is in weeks''' - start = offset * 7 - for i in itertools.count(start): - yield start_date + datetime.timedelta(i) + """generator that returns the next date, requires a datetime object as + input. The offset is in weeks""" + start = offset * 7 + for i in itertools.count(start): + yield start_date + datetime.timedelta(i) def values_in_date_order(image, multiplier=1): - height = 7 - width = len(image[0]) - for w in range(width): - for h in range(height): - yield image[h][w]*multiplier + height = 7 + width = len(image[0]) + for w in range(width): + for h in range(height): + yield image[h][w]*multiplier def commit(content, commitdate): - template = '''echo %s >> gitfiti\nGIT_AUTHOR_DATE=%s GIT_COMMITTER_DATE=%s git commit -a -m "gitfiti"\n''' - return template % (content, commitdate.isoformat(), commitdate.isoformat()) + template = ("""echo {0} >> gitfiti\n""" + """GIT_AUTHOR_DATE={1} GIT_COMMITTER_DATE={2} """ + """git commit -a -m "gitfiti" > /dev/null\n""") + return template.format(content, commitdate.isoformat(), + commitdate.isoformat()) -def fake_it(image, start_date, username, repo, offset=0, multiplier=1): - template = ('#!/bin/bash\n' - 'REPO=%s\n' - 'git init $REPO\n' - 'cd $REPO\n' - 'touch README.md\n' - 'git add README.md\n' - 'touch gitfiti\n' - 'git add gitfiti\n' - '%s\n' - 'git remote add origin git@github.com:%s/$REPO.git\n' - 'git pull\n' - 'git push -u origin master\n') - strings = [] - for value, date in zip(values_in_date_order(image, multiplier), date_gen(start_date, offset)): - for i in range(value): - strings.append(commit(i, date)) - return template % (repo, "".join(strings), username) +def fake_it(image, start_date, username, repo, offset=0, multiplier=1, + git_url='git@github.com'): + template = ('#!/bin/bash\n' + 'REPO={0}\n' + 'git init $REPO\n' + 'cd $REPO\n' + 'touch README.md\n' + 'git add README.md\n' + 'touch gitfiti\n' + 'git add gitfiti\n' + '{1}\n' + 'git remote add origin {2}:{3}/$REPO.git\n' + 'git pull\n' + 'git push -u origin master\n') + strings = [] + for value, date in zip(values_in_date_order(image, multiplier), + date_gen(start_date, offset)): + for i in range(value): + strings.append(commit(i, date)) + return template.format(repo, "".join(strings), git_url, username) def save(output, filename): - """Saves the list to a given filename""" - f = open(filename, "w") - f.write(output) - f.close() + """Saves the list to a given filename""" + f = open(filename, "w") + f.write(output) + f.close() def main(): - global images - print title - print 'Enter your github username:' - username = raw_input(">") - cal = get_calendar(username) - m = multiplier(max_commits(cal)) + print TITLE + print "Enter github url" + ghe = raw_input("Enter nothing for https://github.com/ to be used: ") + print 'Enter your github username:' + username = raw_input(">") + if ghe is None or ghe == "": + git_base = "https://github.com/" + cal = get_calendar(username) + else: + cal = get_calendar(username,base_url=ghe) + git_base = ghe + m = multiplier(max_commits(cal)) - print 'Enter name of the repo to be used by gitfiti:' - repo = raw_input(">") - - print 'Enter number of weeks to offset the image (from the left):' - offset = raw_input(">") - if offset == None: offset = 0 - else: offset = int(offset) + print 'Enter name of the repo to be used by gitfiti:' + repo = raw_input(">") - print ('By default gitfiti.py matches the darkest pixel to the highest\n' - 'number of commits found in your github commit/activity calendar,\n' - '\n' - 'Currently this is : %s commits\n' - '\n' - 'Enter the word "gitfiti" to exceed your max\n' - '(this option generates WAY more commits)\n' - 'Any other input will cause the default matching behavior') % (max_commits(cal),) - match = raw_input(">") - if match == "gitfiti": match = m - else: match = 1 + print 'Enter number of weeks to offset the image (from the left):' + offset = raw_input(">") + if offset == None: + offset = 0 + else: + offset = int(offset) - print 'enter file(s) to load images from (blank if not applicable)' - imgNames = raw_input(">").split(' ') - images = dict(images, **load_images(imgNames)) + print ('By default gitfiti.py matches the darkest pixel to the highest\n' + 'number of commits found in your github commit/activity calendar,\n' + '\n' + 'Currently this is : {0} commits\n' + '\n' + 'Enter the word "gitfiti" to exceed your max\n' + '(this option generates WAY more commits)\n' + 'Any other input will cause the default matching behavior' + ).format(max_commits(cal)) + match = raw_input(">") + if match == "gitfiti": + match = m + else: + match = 1 - print 'enter the image name to gitfiti' - print 'images: ' + ", ".join(images.keys()) - image = raw_input(">") - if image == None: image = images['kitty'] - else: - try: image = images[image] - except: image = images['kitty'] + print 'enter file(s) to load images from (blank if not applicable)' + img_names = raw_input(">").split(' ') + images = dict(IMAGES, **load_images(img_names)) - output = fake_it(image, get_start_date(), username, repo, offset, m*match) - save(output, 'gitfiti.sh') - print 'gitfiti.sh saved. Create a new(!) repo at: https://github.com/new and run it.' + print 'enter the image name to gitfiti' + print 'images: ' + ", ".join(images.keys()) + image = raw_input(">") + if image == None: + image = IMAGES['kitty'] + else: + try: + image = IMAGES[image] + except: + image = IMAGES['kitty'] + if ghe is None or ghe == "": + output = fake_it(image, get_start_date(), username, repo, offset, + m*match) + else: + git_url = raw_input("Enter git url like git@site.github.com: ") + output = fake_it(image, get_start_date(), username, repo, offset, + m*match,git_url=git_url) -if __name__=='__main__': - main() + save(output, 'gitfiti.sh') + print 'gitfiti.sh saved.' + print 'Create a new(!) repo at: {0}new and run it.'.format(git_base) + +if __name__ == '__main__': + main()