"""GitHub helper functions.

basic_auth() -> Credentials for basic authentication.
get_repos() --> Get all public repos for an organization or user.
link_url() ---> Extract link URL from HTTP header returned by GitHub API.
"""
import collections
import json
import os
import requests

#------------------------------------------------------------------------------
def basic_auth():
    """Credentials for basic authentication.

    Returns the tuple used for API calls. GitHub username and PAT are stored
    in environment variables GitHubUser and GitHubPAT.
    """
    return (os.getenv('GitHubUser'), os.getenv('GitHubPAT'))

#-------------------------------------------------------------------------------
def get_repos(org=None, user=None):
    """Get all public repos for an organization or user.

    org = organization
    user = username (ignored if an organization is provided)

    Returns a list of namedtuple objects, one per repo.
    """
    FIELDS = ['full_name', 'watchers', 'forks', 'open_issues', 'default_branch']
    if org:
        URL = 'https://api.github.com/orgs/' + org + '/repos'
    else:
        URL = 'https://api.github.com/users/' + user + '/repos'

    repolist = [] # the list that will be returned
    Repo = collections.namedtuple('Repo', ' '.join(FIELDS)) # namedtuple factory

    response = requests.get(URL, auth=basic_auth())
    if response.ok:
        thispage = json.loads(response.text)
        for repo_json in thispage:
            repo_nt = Repo(repo_json['full_name'], repo_json['watchers'],
                           repo_json['forks'], repo_json['open_issues'],
                           repo_json['default_branch'])
            repolist.append(repo_nt)
    return repolist

#------------------------------------------------------------------------------
def link_url(link_header, linktype='next'):
    """Extract link URL from the 'link' HTTP header returned by GitHub API.

    1st parameter = the 'link' HTTP header passed as a string, or a
                    response object returned by the requests module
    linktype = the desired link type (default = 'next')
    """
    if isinstance(link_header, str):
        link_string = link_header
    else:
        link_string = link_header.headers['Link']

    retval = None # default return value if linktype not found
    links = link_string.split(',') # each of these is '<url>; rel="type"'
    for link in links:
        if '"' + linktype + '"' in link:
            retval = link.split(';')[0].strip()[1:-1]
    return retval

# if running standalone, run a few simple tests --------------------------------
if __name__ == "__main__":

    print('-'*40 + '\n' + 'basic_auth() test' + '\n' + '-'*40)
    print(basic_auth())

    print('-'*40 + '\n' + 'link_url() test' + '\n' + '-'*40)
    TESTLINKS = "<https://api.github.com/organizations/6154722/" + \
        "repos?page=2>; rel=\"next\", <https://api.github.com/" + \
        "organizations/6154722/repos?page=18>; rel=\"last\""
    for reltype in ['first', 'prev', 'next', 'last']:
        URL = link_url(TESTLINKS, reltype)
        print(reltype, URL)

    print('-'*40 + '\n' + 'get_repos() test' + '\n' + '-'*40)
    ms_repos = get_repos(user='octocat')
    for repo in ms_repos:
        print(repo)
    print('Total repos: ', len(ms_repos))
@@ -738,16 +738,31 @@
 ser=None
+, verbose=False
 ):%0A    %22
@@ -897,16 +897,88 @@
 rovided)
+%0A    verbose = flag for whether to display status information to console
 %0A%0A    Re
@@ -1128,35 +1128,40 @@
 if org:%0A        
-URL
+endpoint
  = 'https://api.
@@ -1213,19 +1213,24 @@
         
-URL
+endpoint
  = 'http
@@ -1275,16 +1275,92 @@
 repos'%0A%0A
+    if verbose:%0A        print('get_repo() -%3E ', 'API endpoint:', endpoint)%0A%0A
     repo
@@ -1483,17 +1483,54 @@
 factory%0A
-%0A
+    totpages = 0%0A%0A    while True:%0A    
     resp
@@ -1549,19 +1549,24 @@
 sts.get(
-URL
+endpoint
 , auth=b
@@ -1578,16 +1578,20 @@
 auth())%0A
+    
     if r
@@ -1602,16 +1602,46 @@
 nse.ok:%0A
+            totpages += 1%0A    
         
@@ -1681,24 +1681,28 @@
 xt)%0A        
+    
 for repo_jso
@@ -1724,24 +1724,28 @@
             
+ 
+   
 repo_nt = Re
@@ -1813,32 +1813,36 @@
                 
+    
 repo_json%5B'forks
@@ -1890,32 +1890,36 @@
                 
+   
+ 
 repo_json%5B'defau
@@ -1939,24 +1939,28 @@
             
+    
 repolist.app
@@ -1972,16 +1972,472 @@
 epo_nt)%0A
+%0A        endpoint = link_url(response, 'next') # get URL for next page of results%0A        if not endpoint:%0A            break # there are no more results to process%0A%0A    if verbose:%0A        print('get_repo() -%3E ', 'pages processed:', totpages)%0A        print('get_repo() -%3E ', 'repos returned:', len(repolist))%0A        for header in %5B'X-RateLimit-Limit', 'X-RateLimit-Remaining'%5D:%0A            print('get_repo() -%3E ', header + ':', response.headers%5Bheader%5D)%0A%0A
     retu
@@ -2923,32 +2923,49 @@
 eader%0A    else:%0A
+        try:%0A    
         link_str
@@ -2997,16 +2997,111 @@
 %5B'Link'%5D
+%0A        except KeyError:%0A            return None # there is no Link HTTP header, nothing to do
 %0A%0A    re
@@ -4051,16 +4051,30 @@
 octocat'
+, verbose=True
 )%0A    fo

add pagination support to get_repos()