66
77import aiohttp
88import requests
9+ import uvloop
910
11+ asyncio .set_event_loop_policy (uvloop .EventLoopPolicy ()) # use uvloop
1012
1113###############################################################################
1214# Main Classes
@@ -37,17 +39,19 @@ async def query(self, generated_query: str) -> Dict:
3739 }
3840 try :
3941 async with self .semaphore :
40- r = await self .session .post ("https://api.github.com/graphql" ,
41- headers = headers ,
42- json = {"query" : generated_query })
42+ r = await self .session .post (
43+ "https://api.github.com/graphql" ,
44+ headers = headers ,
45+ json = {"query" : generated_query }
46+ )
4347 return await r .json ()
4448 except :
45- print ("aiohttp failed for GraphQL query" )
46- # Fall back on non-async requests
4749 async with self .semaphore :
48- r = requests .post ("https://api.github.com/graphql" ,
49- headers = headers ,
50- json = {"query" : generated_query })
50+ r = requests .post (
51+ "https://api.github.com/graphql" ,
52+ headers = headers ,
53+ json = {"query" : generated_query }
54+ )
5155 return r .json ()
5256
5357 async def query_rest (self , path : str , params : Optional [Dict ] = None ) -> Dict :
@@ -58,21 +62,21 @@ async def query_rest(self, path: str, params: Optional[Dict] = None) -> Dict:
5862 :return: deserialized REST JSON output
5963 """
6064
61- for _ in range (60 ):
62- headers = {
63- "Authorization" : f"token { self .access_token } " ,
65+ headers = {
66+ "Authorization" : f"token { self .access_token } " ,
6467 }
65- if params is None :
66- params = dict ()
67- if path .startswith ("/" ):
68- path = path [1 :]
68+ if params is None :
69+ params = dict ()
70+ if path .startswith ("/" ):
71+ path = path [1 :]
72+
73+ for _ in range (60 ):
6974 try :
7075 async with self .semaphore :
7176 r = await self .session .get (f"https://api.github.com/{ path } " ,
7277 headers = headers ,
7378 params = tuple (params .items ()))
7479 if r .status == 202 :
75- # print(f"{path} returned 202. Retrying...")
7680 print (f"A path returned 202. Retrying..." )
7781 await asyncio .sleep (2 )
7882 continue
@@ -466,24 +470,23 @@ async def lines_changed(self) -> Tuple[int, int]:
466470 """
467471 if self ._lines_changed is not None :
468472 return self ._lines_changed
469- additions = 0
470- deletions = 0
471- for repo in await self . all_repos :
473+
474+ async def fetch ( repo ):
475+ additions , deletions = 0 , 0
472476 r = await self .queries .query_rest (f"/repos/{ repo } /stats/contributors" )
473477 for author_obj in r :
474- # Handle malformed response from the API by skipping this repo
475- if (not isinstance (author_obj , dict )
476- or not isinstance (author_obj .get ("author" , {}), dict )):
478+ if not isinstance (author_obj , dict ) or not isinstance (author_obj .get ("author" , {}), dict ):
477479 continue
478- author = author_obj .get ("author" , {}).get ("login" , "" )
479- if author != self .username :
480+ if author_obj .get ("author" , {}).get ("login" , "" ) != self .username :
480481 continue
481-
482482 for week in author_obj .get ("weeks" , []):
483483 additions += week .get ("a" , 0 )
484484 deletions += week .get ("d" , 0 )
485+ self ._lines_changed = (additions , deletions )
486+ return additions , deletions
485487
486- self ._lines_changed = (additions , deletions )
488+ results = await asyncio .gather (* [fetch (repo ) for repo in await self .all_repos ])
489+ self ._lines_changed = (sum (r [0 ] for r in results ), sum (r [1 ] for r in results ))
487490 return self ._lines_changed
488491
489492 @property
@@ -495,15 +498,12 @@ async def views(self) -> int:
495498 if self ._views is not None :
496499 return self ._views
497500
498- total = 0
499- for repo in await self .repos :
501+ async def fetch (repo ):
500502 r = await self .queries .query_rest (f"/repos/{ repo } /traffic/views" )
501- for view in r .get ("views" , []):
502- total += view .get ("count" , 0 )
503-
504- self ._views = total
505- return total
503+ return sum (view .get ("count" , 0 ) for view in r .get ("views" , []))
506504
505+ self ._views = sum (await asyncio .gather (* [fetch (repo ) for repo in await self .repos ]))
506+ return self ._views
507507
508508###############################################################################
509509# Main Function
@@ -519,6 +519,5 @@ async def main() -> None:
519519 s = Stats (user , access_token , session )
520520 print (await s .to_str ())
521521
522-
523522if __name__ == "__main__" :
524523 asyncio .run (main ())
0 commit comments