Source code for pygrade.init

#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""Initialize student repositories. Create one repo per student. Also create one team per student consisting of that student. Each repo is made private to that team.

usage:
    pygrade init --org <name> --user <username> --pass <passwd> --remote <uri> [--students <file>] [--workdir <file>]

Options
    -h, --help
    -o, --org <string>          Name of the GitHub Organization for the course.
    -p, --pass <file>           GitHub password
    -r, --remote <uri>          URL of remote github repo used for starter code.
    -s, --students <file>       Students TSV file [default: students.tsv]
    -u, --user <file>           GitHub username
    -w, --workdir <file>        Temporary directory for storing assignments [default: students]
"""
from docopt import docopt
from git import Repo
from github3 import login
import os
import time
import traceback
from . import clone_repo, get_local_repo, pull_repo, read_students


[docs]def lookup_team(existing_teams, name): for t in existing_teams: if t.name == name: return t
[docs]def search_for_user(github, userid): try: return github.user(userid) except: print('>>>cannot find github user with login %s. skipping...' % userid) return None
[docs]def get_team(team_name, existing_teams, org, user): team = lookup_team(existing_teams, team_name) if not team: try: print('creating team for %s' % team_name) team = org.create_team(team_name, permission='push') print(' created new team %s' % team.name) team.invite(user.login) except Exception as e: print(str(e)) traceback.print_exc() else: print(' found existing team %s' % team.name) return team
[docs]def lookup_repo(existing_repos, name): for t in existing_repos: if t.name == name: return t
[docs]def get_repo(repo_name, existing_repos, org, team): repo = lookup_repo(existing_repos, repo_name) if not repo: try: repo = org.create_repository(repo_name, team_id=team.id, private=True, auto_init=False) print(' created new repo %s' % repo.name) except Exception as e: print(str(e)) traceback.print_exc() else: print(' found existing remote repo %s' % repo.name) return repo
[docs]def add_to_org(user, org): org.add_to_members(user, role='member')
[docs]def create_repos_and_teams(students, org_name, github, path, remote_repo): try: org = [o for o in github.me().organizations() if os.path.basename(o.url) == org_name][0] print('found org %s' % org.url) except Exception as e: print('>>>cannot find org named %s' % org_name) print(str(e)) traceback.print_exc() return existing_teams = [t for t in org.teams()] existing_repos = [r for r in org.repositories()] for s in students: print('initializing repo %s for %s' % (s['github_repo'], s['github_id'])) user = search_for_user(github, s['github_id']) if not user: continue team_name = os.path.basename(s['github_repo']) team = get_team(team_name, existing_teams, org, user) if not team: continue repo = get_repo(team_name, existing_repos, org, team) time.sleep(1) if not repo: print('cannot getrepo for %s' % s['github_repo']) continue local_repo = get_local_repo(s, path) if os.path.exists(local_repo): print(' found existing local repo at %s' % local_repo) pull_repo(local_repo) else: clone_repo(s, path) write_readme(s, local_repo) push_readme(local_repo) add_remote(local_repo, remote_repo)
[docs]def write_readme(student, local_repo): reamde_file = os.path.join(local_repo, 'Info.md') outf = open(reamde_file, 'wt') outf.write('\n'.join('%s=%s ' % (k, v) for k, v in student.items())) outf.close()
[docs]def push_readme(repo): repo_obj = Repo(repo) index = repo_obj.index index.add(['Info.md']) index.commit('Info') repo_obj.remotes[0].push() print(' pushed Info.md')
[docs]def add_remote(local_repo, remote_repo): repo_obj = Repo(local_repo) try: repo_obj.create_remote('template', remote_repo) except: # remote already exists pass repo_obj.git.fetch('template') repo_obj.git.merge('template/master', allow_unrelated_histories=True) repo_obj.remotes[0].push() print(' pushed template from remote %s' % remote_repo)
[docs]def main(): args = docopt(__doc__) path = args['--workdir'] students = read_students(args['--students']) github = login(args['--user'], args['--pass']) create_repos_and_teams(students, args['--org'], github, path, args['--remote'])
if __name__ == '__main__': main()