<s> """<STR_LIT>""" <EOL> import math <EOL> import sys <EOL> import os <EOL> import numpy as np <EOL> import pandas as pd <EOL> import requests <EOL> from git import GitCommandError <EOL> from gitpandas . repository import Repository <EOL> __author__ = '<STR_LIT>' <EOL> class ProjectDirectory ( object ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , working_dir = None , ignore_repos = None , verbose = True ) : <EOL> if working_dir is None : <EOL> self . repo_dirs = set ( [ x [ <NUM_LIT:0> ] . split ( '<STR_LIT>' ) [ <NUM_LIT:0> ] for x in os . walk ( os . getcwd ( ) ) if '<STR_LIT>' in x [ <NUM_LIT:0> ] ] ) <EOL> elif isinstance ( working_dir , list ) : <EOL> self . repo_dirs = working_dir <EOL> else : <EOL> self . repo_dirs = set ( [ x [ <NUM_LIT:0> ] . split ( '<STR_LIT>' ) [ <NUM_LIT:0> ] for x in os . walk ( working_dir ) if '<STR_LIT>' in x [ <NUM_LIT:0> ] ] ) <EOL> self . repos = [ Repository ( r , verbose = verbose ) for r in self . repo_dirs ] <EOL> if ignore_repos is not None : <EOL> self . repos = [ x for x in self . repos if x . _repo_name not in ignore_repos ] <EOL> def _repo_name ( self ) : <EOL> """<STR_LIT>""" <EOL> ds = [ [ x . _repo_name ( ) ] for x in self . repos ] <EOL> df = pd . DataFrame ( ds , columns = [ '<STR_LIT>' ] ) <EOL> return df <EOL> def is_bare ( self ) : <EOL> """<STR_LIT>""" <EOL> ds = [ [ x . _repo_name ( ) , x . is_bare ( ) ] for x in self . repos ] <EOL> df = pd . DataFrame ( ds , columns = [ '<STR_LIT>' , '<STR_LIT>' ] ) <EOL> return df <EOL> def has_coverage ( self ) : <EOL> """<STR_LIT>""" <EOL> ds = [ [ x . _repo_name ( ) , x . has_coverage ( ) ] for x in self . repos ] <EOL> df = pd . DataFrame ( ds , columns = [ '<STR_LIT>' , '<STR_LIT>' ] ) <EOL> return df <EOL> def coverage ( self ) : <EOL> """<STR_LIT>""" <EOL> df = pd . DataFrame ( columns = [ '<STR_LIT:filename>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' ] ) <EOL> for repo in self . repos : <EOL> try : <EOL> cov = repo . coverage ( ) <EOL> cov [ '<STR_LIT>' ] = repo . _repo_name ( ) <EOL> df = df . append ( cov ) <EOL> except GitCommandError as err : <EOL> print ( '<STR_LIT>' % ( repo , ) ) <EOL> pass <EOL> df . reset_index ( ) <EOL> return df <EOL> def file_change_rates ( self , branch = '<STR_LIT>' , limit = None , extensions = None , ignore_dir = None , coverage = False , days = None ) : <EOL> """<STR_LIT>""" <EOL> columns = [ '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' ] <EOL> if coverage : <EOL> columns += [ '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' ] <EOL> df = pd . DataFrame ( columns = columns ) <EOL> for repo in self . repos : <EOL> try : <EOL> fcr = repo . file_change_rates ( <EOL> branch = branch , <EOL> limit = limit , <EOL> extensions = extensions , <EOL> ignore_dir = ignore_dir , <EOL> coverage = coverage , <EOL> days = days <EOL> ) <EOL> fcr [ '<STR_LIT>' ] = repo . _repo_name ( ) <EOL> df = df . append ( fcr ) <EOL> except GitCommandError as err : <EOL> print ( '<STR_LIT>' % ( repo , branch ) ) <EOL> pass <EOL> df . reset_index ( ) <EOL> return df <EOL> def hours_estimate ( self , branch = '<STR_LIT>' , grouping_window = <NUM_LIT:0.5> , single_commit_hours = <NUM_LIT:0.5> , limit = None , extensions = None , ignore_dir = None , days = None , committer = True , by = None ) : <EOL> """<STR_LIT>""" <EOL> if limit is not None : <EOL> limit = int ( limit / len ( self . repo_dirs ) ) <EOL> if committer : <EOL> com = '<STR_LIT>' <EOL> else : <EOL> com = '<STR_LIT>' <EOL> df = pd . DataFrame ( columns = [ com , '<STR_LIT>' , '<STR_LIT>' ] ) <EOL> for repo in self . repos : <EOL> try : <EOL> ch = repo . hours_estimate ( <EOL> branch , <EOL> grouping_window = grouping_window , <EOL> single_commit_hours = single_commit_hours , <EOL> limit = limit , <EOL> extensions = extensions , <EOL> ignore_dir = ignore_dir , <EOL> days = days , <EOL> committer = committer <EOL> ) <EOL> ch [ '<STR_LIT>' ] = repo . _repo_name ( ) <EOL> df = df . append ( ch ) <EOL> except GitCommandError as err : <EOL> print ( '<STR_LIT>' % ( repo , branch ) ) <EOL> pass <EOL> df . reset_index ( ) <EOL> if by == '<STR_LIT>' or by == '<STR_LIT>' : <EOL> df = df . groupby ( com ) . agg ( { '<STR_LIT>' : sum } ) <EOL> df = df . reset_index ( ) <EOL> elif by == '<STR_LIT>' : <EOL> df = df . groupby ( '<STR_LIT>' ) . agg ( { '<STR_LIT>' : sum } ) <EOL> df = df . reset_index ( ) <EOL> return df <EOL> def commit_history ( self , branch , limit = None , extensions = None , ignore_dir = None , days = None ) : <EOL> """<STR_LIT>""" <EOL> if limit is not None : <EOL> limit = int ( limit / len ( self . repo_dirs ) ) <EOL> df = pd . DataFrame ( columns = [ '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT:message>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' ] ) <EOL> for repo in self . repos : <EOL> try : <EOL> ch = repo . commit_history ( branch , limit = limit , extensions = extensions , ignore_dir = ignore_dir , days = days ) <EOL> ch [ '<STR_LIT>' ] = repo . _repo_name ( ) <EOL> df = df . append ( ch ) <EOL> except GitCommandError as err : <EOL> print ( '<STR_LIT>' % ( repo , branch ) ) <EOL> pass <EOL> df . reset_index ( ) <EOL> return df <EOL> def file_change_history ( self , branch = '<STR_LIT>' , limit = None , extensions = None , ignore_dir = None , days = None ) : <EOL> """<STR_LIT>""" <EOL> if limit is not None : <EOL> limit = int ( limit / len ( self . repo_dirs ) ) <EOL> df = pd . DataFrame ( columns = [ '<STR_LIT>' , '<STR_LIT:date>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT:message>' , '<STR_LIT>' , '<STR_LIT:filename>' , '<STR_LIT>' , '<STR_LIT>' ] ) <EOL> for repo in self . repos : <EOL> try : <EOL> ch = repo . file_change_history ( <EOL> branch , <EOL> limit = limit , <EOL> extensions = extensions , <EOL> ignore_dir = ignore_dir , <EOL> days = days <EOL> ) <EOL> ch [ '<STR_LIT>' ] = repo . _repo_name ( ) <EOL> df = df . append ( ch ) <EOL> except GitCommandError as err : <EOL> print ( '<STR_LIT>' % ( repo , branch ) ) <EOL> pass <EOL> df . reset_index ( ) <EOL> return df <EOL> def blame ( self , extensions = None , ignore_dir = None , committer = True , by = '<STR_LIT>' ) : <EOL> """<STR_LIT>""" <EOL> df = None <EOL> for repo in self . repos : <EOL> try : <EOL> if df is None : <EOL> df = repo . blame ( extensions = extensions , ignore_dir = ignore_dir , committer = committer , by = by ) <EOL> else : <EOL> df = df . append ( repo . blame ( extensions = extensions , ignore_dir = ignore_dir , committer = committer , by = by ) ) <EOL> except GitCommandError as err : <EOL> print ( '<STR_LIT>' % ( repo , ) ) <EOL> pass <EOL> df = df . reset_index ( level = <NUM_LIT:1> ) <EOL> df = df . reset_index ( level = <NUM_LIT:1> ) <EOL> if committer : <EOL> if by == '<STR_LIT>' : <EOL> df = df . groupby ( '<STR_LIT>' ) . agg ( { '<STR_LIT>' : np . sum } ) <EOL> elif by == '<STR_LIT:file>' : <EOL> df = df . groupby ( [ '<STR_LIT>' , '<STR_LIT:file>' ] ) . agg ( { '<STR_LIT>' : np . sum } ) <EOL> else : <EOL> if by == '<STR_LIT>' : <EOL> df = df . groupby ( '<STR_LIT>' ) . agg ( { '<STR_LIT>' : np . sum } ) <EOL> elif by == '<STR_LIT:file>' : <EOL> df = df . groupby ( [ '<STR_LIT>' , '<STR_LIT:file>' ] ) . agg ( { '<STR_LIT>' : np . sum } ) <EOL> df = df . sort_values ( by = [ '<STR_LIT>' ] , ascending = False ) <EOL> return df <EOL> def file_detail ( self , extensions = None , ignore_dir = None , rev = '<STR_LIT>' , committer = True ) : <EOL> """<STR_LIT>""" <EOL> df = None <EOL> for repo in self . repos : <EOL> try : <EOL> if df is None : <EOL> df = repo . file_detail ( extensions = extensions , ignore_dir = ignore_dir , committer = committer , rev = rev ) <EOL> df [ '<STR_LIT>' ] = repo . _repo_name ( ) <EOL> else : <EOL> chunk = repo . file_detail ( extensions = extensions , ignore_dir = ignore_dir , committer = committer , rev = rev ) <EOL> chunk [ '<STR_LIT>' ] = repo . _repo_name ( ) <EOL> df = df . append ( chunk ) <EOL> except GitCommandError as err : <EOL> print ( '<STR_LIT>' % ( repo , ) ) <EOL> pass <EOL> df = df . reset_index ( level = <NUM_LIT:1> ) <EOL> df = df . set_index ( [ '<STR_LIT:file>' , '<STR_LIT>' ] ) <EOL> return df <EOL> def branches ( self ) : <EOL> """<STR_LIT>""" <EOL> df = pd . DataFrame ( columns = [ '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' ] ) <EOL> for repo in self . repos : <EOL> try : <EOL> df = df . append ( repo . branches ( ) ) <EOL> except GitCommandError as err : <EOL> print ( '<STR_LIT>' % ( repo , ) ) <EOL> pass <EOL> df . reset_index ( ) <EOL> return df <EOL> def revs ( self , branch = '<STR_LIT>' , limit = None , skip = None , num_datapoints = None ) : <EOL> """<STR_LIT>""" <EOL> if limit is not None : <EOL> limit = math . floor ( float ( limit ) / len ( self . repos ) ) <EOL> if num_datapoints is not None : <EOL> num_datapoints = math . floor ( float ( num_datapoints ) / len ( self . repos ) ) <EOL> df = pd . DataFrame ( columns = [ '<STR_LIT>' , '<STR_LIT>' ] ) <EOL> for repo in self . repos : <EOL> try : <EOL> revs = repo . revs ( branch = branch , limit = limit , skip = skip , num_datapoints = num_datapoints ) <EOL> revs [ '<STR_LIT>' ] = repo . _repo_name ( ) <EOL> df = df . append ( revs ) <EOL> except GitCommandError as err : <EOL> print ( '<STR_LIT>' % ( repo , ) ) <EOL> pass <EOL> df . reset_index ( ) <EOL> return df <EOL> def cumulative_blame ( self , branch = '<STR_LIT>' , extensions = None , ignore_dir = None , by = '<STR_LIT>' , limit = None , skip = None , num_datapoints = None , committer = True ) : <EOL> """<STR_LIT>""" <EOL> blames = [ ] <EOL> for repo in self . repos : <EOL> try : <EOL> blame = repo . cumulative_blame ( <EOL> branch = branch , <EOL> extensions = extensions , <EOL> ignore_dir = ignore_dir , <EOL> limit = limit , <EOL> skip = skip , <EOL> num_datapoints = num_datapoints , <EOL> committer = committer <EOL> ) <EOL> blames . append ( ( repo . _repo_name ( ) , blame ) ) <EOL> except GitCommandError as err : <EOL> print ( '<STR_LIT>' % ( repo , ) ) <EOL> pass <EOL> global_blame = blames [ <NUM_LIT:0> ] [ <NUM_LIT:1> ] <EOL> global_blame . columns = [ x + '<STR_LIT>' + str ( blames [ <NUM_LIT:0> ] [ <NUM_LIT:0> ] ) for x in global_blame . columns . values ] <EOL> blames = blames [ <NUM_LIT:1> : ] <EOL> for reponame , blame in blames : <EOL> blame . columns = [ x + '<STR_LIT>' + reponame for x in blame . columns . values ] <EOL> global_blame = pd . merge ( global_blame , blame , left_index = True , right_index = True , how = '<STR_LIT>' ) <EOL> global_blame . fillna ( method = '<STR_LIT>' , inplace = True ) <EOL> global_blame . fillna ( <NUM_LIT:0.0> , inplace = True ) <EOL> if by == '<STR_LIT>' : <EOL> committers = [ ( str ( x ) . split ( '<STR_LIT>' ) [ <NUM_LIT:0> ] . lower ( ) . strip ( ) , x ) for x in global_blame . columns . values ] <EOL> if sys . version_info . major == <NUM_LIT:2> : <EOL> committer_mapping = dict ( [ ( c , [ x [ <NUM_LIT:1> ] for x in committers if x [ <NUM_LIT:0> ] == c ] ) for c in set ( [ x [ <NUM_LIT:0> ] for x in committers ] ) ] ) <EOL> else : <EOL> committer_mapping = { c : [ x [ <NUM_LIT:1> ] for x in committers if x [ <NUM_LIT:0> ] == c ] for c in { x [ <NUM_LIT:0> ] for x in committers } } <EOL> for committer in committer_mapping . keys ( ) : <EOL> global_blame [ committer ] = <NUM_LIT:0> <EOL> for col in committer_mapping . get ( committer , [ ] ) : <EOL> global_blame [ committer ] += global_blame [ col ] <EOL> global_blame = global_blame . reindex ( columns = list ( committer_mapping . keys ( ) ) ) <EOL> elif by == '<STR_LIT>' : <EOL> projects = [ ( str ( x ) . split ( '<STR_LIT>' ) [ <NUM_LIT:1> ] . lower ( ) . strip ( ) , x ) for x in global_blame . columns . values ] <EOL> if sys . version_info . major == <NUM_LIT:2> : <EOL> project_mapping = dict ( [ ( c , [ x [ <NUM_LIT:1> ] for x in projects if x [ <NUM_LIT:0> ] == c ] ) for c in set ( [ x [ <NUM_LIT:0> ] for x in projects ] ) ] ) <EOL> else : <EOL> project_mapping = { c : [ x [ <NUM_LIT:1> ] for x in projects if x [ <NUM_LIT:0> ] == c ] for c in { x [ <NUM_LIT:0> ] for x in projects } } <EOL> for project in project_mapping . keys ( ) : <EOL> global_blame [ project ] = <NUM_LIT:0> <EOL> for col in project_mapping . get ( project , [ ] ) : <EOL> global_blame [ project ] += global_blame [ col ] <EOL> global_blame = global_blame . reindex ( columns = list ( project_mapping . keys ( ) ) ) <EOL> global_blame = global_blame [ ~ global_blame . index . duplicated ( ) ] <EOL> return global_blame <EOL> def tags ( self ) : <EOL> """<STR_LIT>""" <EOL> df = pd . DataFrame ( columns = [ '<STR_LIT>' , '<STR_LIT>' ] ) <EOL> for repo in self . repos : <EOL> try : <EOL> df = df . append ( repo . tags ( ) ) <EOL> except GitCommandError as err : <EOL> print ( '<STR_LIT>' % ( repo , ) ) <EOL> pass <EOL> df . reset_index ( ) <EOL> return df <EOL> def repo_information ( self ) : <EOL> """<STR_LIT>""" <EOL> data = [ [ repo . git_dir , <EOL> repo . repo . branches , <EOL> repo . repo . bare , <EOL> repo . repo . remotes , <EOL> repo . repo . description , <EOL> repo . repo . references , <EOL> repo . repo . heads , <EOL> repo . repo . submodules , <EOL> repo . repo . tags , <EOL> repo . repo . active_branch ] for repo in self . repos ] <EOL> df = pd . DataFrame ( data , columns = [ <EOL> '<STR_LIT>' , <EOL> '<STR_LIT>' , <EOL> '<STR_LIT>' , <EOL> '<STR_LIT>' , <EOL> '<STR_LIT:description>' , <EOL> '<STR_LIT>' , <EOL> '<STR_LIT>' , <EOL> '<STR_LIT>' , <EOL> '<STR_LIT>' , <EOL> '<STR_LIT>' <EOL> ] ) <EOL> return df <EOL> def bus_factor ( self , extensions = None , ignore_dir = None , by = '<STR_LIT>' ) : <EOL> """<STR_LIT>""" <EOL> if by == '<STR_LIT:file>' : <EOL> raise NotImplementedError ( '<STR_LIT>' ) <EOL> elif by == '<STR_LIT>' : <EOL> blame = self . blame ( extensions = extensions , ignore_dir = ignore_dir , by = '<STR_LIT>' ) <EOL> blame = blame . sort_values ( by = [ '<STR_LIT>' ] , ascending = False ) <EOL> total = blame [ '<STR_LIT>' ] . sum ( ) <EOL> cumulative = <NUM_LIT:0> <EOL> tc = <NUM_LIT:0> <EOL> for idx in range ( blame . shape [ <NUM_LIT:0> ] ) : <EOL> cumulative += blame . ix [ idx , '<STR_LIT>' ] <EOL> tc += <NUM_LIT:1> <EOL> if cumulative >= total / <NUM_LIT:2> : <EOL> break <EOL> return pd . DataFrame ( [ [ '<STR_LIT>' , tc ] ] , columns = [ '<STR_LIT>' , '<STR_LIT>' ] ) <EOL> elif by == '<STR_LIT>' : <EOL> df = pd . DataFrame ( columns = [ '<STR_LIT>' , '<STR_LIT>' ] ) <EOL> for repo in self . repos : <EOL> try : <EOL> df = df . append ( repo . bus_factor ( extensions = extensions , ignore_dir = ignore_dir , by = by ) ) <EOL> except GitCommandError as err : <EOL> print ( '<STR_LIT>' % ( repo , ) ) <EOL> pass <EOL> df . reset_index ( ) <EOL> return df <EOL> def punchcard ( self , branch = '<STR_LIT>' , limit = None , extensions = None , ignore_dir = None , days = None , by = None , normalize = None ) : <EOL> """<STR_LIT>""" <EOL> df = pd . DataFrame ( ) <EOL> if by == '<STR_LIT>' : <EOL> repo_by = None <EOL> else : <EOL> repo_by = by <EOL> for repo in self . repos : <EOL> try : <EOL> chunk = repo . punchcard ( <EOL> branch = branch , <EOL> limit = limit , <EOL> extensions = extensions , <EOL> ignore_dir = ignore_dir , <EOL> days = days , <EOL> by = repo_by , <EOL> normalize = None <EOL> ) <EOL> chunk [ '<STR_LIT>' ] = repo . _repo_name ( ) <EOL> df = df . append ( chunk ) <EOL> except GitCommandError as err : <EOL> print ( '<STR_LIT>' % ( repo , ) ) <EOL> pass <EOL> df . reset_index ( ) <EOL> aggs = [ '<STR_LIT>' , '<STR_LIT>' ] <EOL> if by is not None : <EOL> aggs . append ( by ) <EOL> punch_card = df . groupby ( aggs ) . agg ( { <EOL> '<STR_LIT>' : np . sum , <EOL> '<STR_LIT>' : np . sum , <EOL> '<STR_LIT>' : np . sum , <EOL> '<STR_LIT>' : np . sum <EOL> } ) <EOL> punch_card . reset_index ( inplace = True ) <EOL> if normalize is not None : <EOL> for col in [ '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' ] : <EOL> punch_card [ col ] = ( punch_card [ col ] / punch_card [ col ] . sum ( ) ) * normalize <EOL> return punch_card <EOL> def __del__ ( self ) : <EOL> """<STR_LIT>""" <EOL> for repo in self . repos : <EOL> repo . __del__ ( ) <EOL> class GitHubProfile ( ProjectDirectory ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , username , ignore_forks = False , ignore_repos = None , verbose = False ) : <EOL> """<STR_LIT>""" <EOL> uri = '<STR_LIT>' % username <EOL> data = requests . get ( uri ) <EOL> repos = [ ] <EOL> for chunk in data . json ( ) : <EOL> if ignore_forks : <EOL> if not chunk [ '<STR_LIT>' ] : <EOL> repos . append ( chunk [ '<STR_LIT>' ] ) <EOL> else : <EOL> repos . append ( chunk [ '<STR_LIT>' ] ) <EOL> ProjectDirectory . __init__ ( self , working_dir = repos , ignore_repos = ignore_repos , verbose = verbose ) </s>
