├── .editorconfig ├── .gitignore ├── .travis.yml ├── LICENSE.txt ├── README.md ├── README.rst ├── githubtrending ├── __init__.py ├── trending.py ├── utils.py └── writers.py ├── requirements.txt ├── setup.cfg ├── setup.py └── test ├── __init__.py ├── data.py └── test_github_trending.py /.editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org 2 | 3 | root = true 4 | 5 | [*] 6 | charset = utf-8 7 | end_of_line = lf 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | 11 | [*.{py,rst,ini}] 12 | indent_style = space 13 | indent_size = 4 14 | 15 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Python byte compiled files 2 | *.py[co] 3 | 4 | # Virtual Env 5 | pyenv*/* 6 | py*/* 7 | 8 | *.egg-info/ 9 | dist/* 10 | 11 | # Coverage files 12 | htmlcov/* -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: python 2 | python: 3 | - "2.7" 4 | - "3.4" 5 | install: 6 | - "pip install ." 7 | - "pip install flake8" 8 | - "pip install lxml" 9 | - "pip install coveralls" 10 | script: 11 | - "flake8 githubtrending" 12 | - "flake8 test" 13 | - "coverage run --source=githubtrending -m test.test_github_trending" 14 | after_script: 15 | - coveralls -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Taranjeet Singh 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Github Trending Cli 2 | =================== 3 | 4 | [![PyPI version](https://badge.fury.io/py/github-trending.svg)](https://badge.fury.io/py/github-trending) [![Build Status](https://travis-ci.org/TroJan/github-trending-cli.svg?branch=master)](https://travis-ci.org/TroJan/github-trending-cli) [![Coverage Status](https://coveralls.io/repos/github/TroJan/github-trending-cli/badge.svg?branch=master)](https://coveralls.io/github/TroJan/github-trending-cli?branch=master) 5 | 6 | A cli which lists the trending repositories and developers from Github. 7 | 8 | Install 9 | ======= 10 | 11 | * Using `pip` 12 | ``` 13 | $ pip install github-trending 14 | ``` 15 | 16 | * From source 17 | 18 | ``` 19 | $ git clone https://github.com/TroJan/github-trending-cli 20 | $ cd github-trending-cli 21 | $ python setup.py install 22 | ``` 23 | 24 | Usage 25 | ===== 26 | 27 | ``` 28 | $ githubtrending # list 25 trending repositories on github 29 | $ githubtrending --repo or -r # list 25 trending repositories on github 30 | $ githubtrending --dev or -d # list 25 trending developers on github 31 | $ githubtrending --lang=python or -l=python 32 | # list 25 trending repositories for a particular language on github 33 | $ githubtrending --week # list 25 trending repositories on github since a week 34 | $ githubtrending --month # list 25 trending repositories on github since a month 35 | 36 | ``` 37 | 38 | Examples 39 | ========= 40 | 41 | ``` 42 | $ githubtrending --repo --lang=python --week # lists 25 trending repositories of python since a week 43 | $ githubtrending --dev --lang=javascript --month # lists 25 trending developers of javascript since a month 44 | $ githubtrending --repo --week # lists 25 repositories since a week 45 | ``` 46 | 47 | Available Options 48 | ================= 49 | 50 | ``` 51 | 52 | --help Lists the help and option available 53 | -r, --repo Lists 25 trending repositories 54 | -d, --dev Lists 25 trending developers 55 | -l, --lang Takes language as a parameter and lists repo of that language 56 | --week Lists trending repos/devs since a week 57 | --month Lists trending repos/devs since a month 58 | 59 | ``` 60 | 61 | Licence 62 | ==== 63 | Open sourced under [MIT License](LICENSE.txt) 64 | 65 | Package Link 66 | ============ 67 | 68 | Pypi [link](https://pypi.python.org/pypi/github-trending) 69 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | Github Trending Cli 2 | =================== 3 | 4 | [![PyPI version](https://badge.fury.io/py/github-trending.svg)](https://badge.fury.io/py/github-trending) [![Build Status](https://travis-ci.org/staranjeet/github-trending-cli.svg?branch=master)](https://travis-ci.org/staranjeet/github-trending-cli) [![Coverage Status](https://coveralls.io/repos/github/staranjeet/github-trending-cli/badge.svg?branch=master)](https://coveralls.io/github/staranjeet/github-trending-cli?branch=master) 5 | 6 | 7 | A cli which lists the trending repositories and developers from Github. 8 | 9 | Install 10 | ======= 11 | 12 | * Using `pip` 13 | ``` 14 | $ pip install github-trending 15 | ``` 16 | 17 | * From source 18 | 19 | ``` 20 | $ git clone https://github.com/staranjeet/github-trending-cli 21 | $ cd github-trending-cli 22 | $ python setup.py install 23 | ``` 24 | 25 | Usage 26 | ===== 27 | 28 | ``` 29 | $ githubtrending # list 25 trending repositories on github 30 | $ githubtrending --repo or -r # list 25 trending repositories on github 31 | $ githubtrending --dev or -d # list 25 trending developers on github 32 | $ githubtrending --lang=python or -l=python 33 | # list 25 trending repositories for a particular language on github 34 | $ githubtrending --week # list 25 trending repositories on github since a week 35 | $ githubtrending --month # list 25 trending repositories on github since a month 36 | 37 | ``` 38 | 39 | Examples 40 | ========= 41 | 42 | ``` 43 | $ githubtrending --repo --lang=python --week # lists 25 trending repositories of python since a week 44 | $ githubtrending --dev --lang=javascript --month # lists 25 trending developers of javascript since a month 45 | $ githubtrending --repo --week # lists 25 repositories since a week 46 | ``` 47 | 48 | Available Options 49 | ================= 50 | 51 | ``` 52 | 53 | --help Lists the help and option available 54 | -r, --repo Lists 25 trending repositories 55 | -d, --dev Lists 25 trending developers 56 | -l, --lang Takes language as a parameter and lists repo of that language 57 | --week Lists trending repos/devs since a week 58 | --month Lists trending repos/devs since a month 59 | 60 | ``` 61 | -------------------------------------------------------------------------------- /githubtrending/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/taranjeet/github-trending-cli/2566d19e5dcd420b78360b70da977b6f5a61be41/githubtrending/__init__.py -------------------------------------------------------------------------------- /githubtrending/trending.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import click 3 | import requests 4 | import webbrowser 5 | from lxml import etree 6 | 7 | from . import writers 8 | 9 | TRENDING_REPO_URL = 'http://github.com/trending' 10 | TRENDING_DEV_URL = 'http://github.com/trending/developers' 11 | HOME_PAGE = 'https://github.com' 12 | 13 | requests.packages.urllib3.disable_warnings() 14 | 15 | 16 | def replace_new_lines_and_strip(s): 17 | return s.strip() 18 | 19 | 20 | def replace_new_lines_and_multiple_spaces(s): 21 | return ' '.join(s.replace('\n', '').split()) 22 | 23 | 24 | def read_page(url, timeout=5): 25 | 26 | headers = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.7; rv:11.0) Gecko/20100101 Firefox/11.0'} 27 | try: 28 | response = requests.get(url, timeout=timeout, headers=headers) 29 | except requests.exceptions.ConnectionError as e: # noqa 30 | return(None, False) 31 | 32 | return(response, response.status_code) 33 | 34 | 35 | def make_etree(url): 36 | response, status_code = read_page(url) 37 | if status_code == 200: 38 | response = etree.HTML(response.text) 39 | return (response, status_code) 40 | 41 | 42 | def get_trending_repo_names(tree): 43 | repos = tree.xpath('//h3[@class="repo-list-name"]/a/@href') 44 | return repos 45 | 46 | 47 | def get_trending_repo_description(tree): 48 | repo_desc = tree.xpath('//p[@class="repo-list-description"]') 49 | repo_desc = [" ".join([x for x in each.itertext()]) for each in repo_desc] 50 | repo_desc = [replace_new_lines_and_strip(each) for each in repo_desc] 51 | return repo_desc 52 | 53 | 54 | def get_trending_repo_meta(tree): 55 | repo_meta = tree.xpath('//p[@class="repo-list-meta"]') 56 | return repo_meta 57 | 58 | 59 | def get_trending_repo_stars_and_languages(repo_meta): 60 | dot = u'•'.encode('utf8') 61 | repo_stars_and_langauges = [] 62 | for each in repo_meta: 63 | meta = each.text.strip().encode('utf8') 64 | stars, language = '', 'unknown' 65 | if dot in meta: 66 | temp = meta.split(dot) 67 | for each_option in temp: 68 | if b"stars" in each_option: 69 | stars = replace_new_lines_and_strip(each_option).decode('utf8') 70 | elif b"built by" not in each_option.lower() and b"stars" not in each_option.lower(): 71 | language = replace_new_lines_and_strip(each_option).decode('utf8') 72 | repo_stars_and_langauges.append([stars, language]) 73 | return repo_stars_and_langauges 74 | 75 | 76 | def get_trending_repos(**kwargs): 77 | repos = [] 78 | language = kwargs.get('language', None) 79 | timespan = kwargs.get('timespan', None) 80 | url = TRENDING_REPO_URL 81 | if language: 82 | url = url + '/' + language 83 | if timespan: 84 | url = url + '?since={}'.format(timespan) 85 | tree, status_code = make_etree(url) 86 | if status_code == 200: 87 | repo_names = get_trending_repo_names(tree) 88 | repo_desc = get_trending_repo_description(tree) 89 | repo_meta = get_trending_repo_meta(tree) 90 | repo_stars_and_languages = get_trending_repo_stars_and_languages(repo_meta) 91 | repos = list(zip(repo_names, repo_desc, repo_stars_and_languages)) 92 | repos = [{'repo_name': repo_name, 93 | 'description': description, 94 | 'stars': stars, 95 | 'language': lang, 96 | 'url': HOME_PAGE + str(repo_name)} 97 | for repo_name, description, [stars, lang] in repos] 98 | return repos 99 | 100 | 101 | def get_trending_dev_names(tree): 102 | devs = tree.xpath('//h2[@class="user-leaderboard-list-name"]') 103 | devs = [" ".join([x for x in each.itertext()]) for each in devs] 104 | devs = [replace_new_lines_and_multiple_spaces(replace_new_lines_and_strip(each)) for each in devs] 105 | return devs 106 | 107 | 108 | def get_trending_dev_repo_names(tree): 109 | dev_repo_names = tree.xpath('//span[@class="repo"]') 110 | dev_repo_names = [" ".join([x for x in each.itertext()]) for each in dev_repo_names] 111 | dev_repo_names = [replace_new_lines_and_strip(each) for each in dev_repo_names] 112 | return dev_repo_names 113 | 114 | 115 | def get_trending_dev_repo_desc(tree): 116 | dev_repo_desc = tree.xpath('//span[@class="repo-snipit-description css-truncate-target"]') 117 | dev_repo_desc = [" ".join([x for x in each.itertext()]) for each in dev_repo_desc] 118 | dev_repo_desc = [replace_new_lines_and_strip(each) for each in dev_repo_desc] 119 | return dev_repo_desc 120 | 121 | 122 | def get_trending_devs(**kwargs): 123 | devs = [] 124 | language = kwargs.get('language', None) 125 | timespan = kwargs.get('timespan', None) 126 | url = TRENDING_DEV_URL 127 | if language: 128 | url = url + '/' + language 129 | if timespan: 130 | url = url + '?since={}'.format(timespan) 131 | tree, status_code = make_etree(url) 132 | if status_code == 200: 133 | dev_names = get_trending_dev_names(tree) 134 | dev_repo_names = get_trending_dev_repo_names(tree) 135 | dev_repo_desc = get_trending_dev_repo_desc(tree) 136 | devs = list(zip(dev_names, dev_repo_names, dev_repo_desc)) 137 | devs = [{'dev_name': dev_name, 138 | 'repo_name': repo_name, 139 | 'description': description, 140 | 'url': HOME_PAGE + '/' + dev_name.split(' ')[0]} 141 | for dev_name, repo_name, description in devs] 142 | return devs 143 | 144 | 145 | @click.command() 146 | @click.option( 147 | '--repo', '-r', is_flag=True, 148 | help="Lists the trending repositories.") 149 | @click.option( 150 | '--dev', '-d', is_flag=True, 151 | help="Lists the trending developers.") 152 | @click.option('--lang', '-l', help='Specify the language') 153 | @click.option('--week', 'timespan', flag_value='weekly') 154 | @click.option('--month', 'timespan', flag_value='monthly') 155 | @click.argument('goto', nargs=1, required=False, type=click.INT) 156 | def main(repo, dev, lang, timespan, goto): 157 | ''' 158 | A command line utility to see the trending repositories 159 | and developers on Github 160 | ''' 161 | language = None 162 | if lang: 163 | language = str(lang) 164 | opts = { 165 | 'language': language, 166 | 'timespan': timespan, 167 | } 168 | try: 169 | if repo: 170 | repos = get_trending_repos(**opts) 171 | if goto: 172 | webbrowser.open(repos[goto-1]['url'], new=2) 173 | return 174 | else: 175 | writers.print_trending_repos(repos) 176 | if dev: 177 | devs = get_trending_devs(**opts) 178 | if goto: 179 | webbrowser.open(devs[goto-1]['url'], new=2) 180 | return 181 | else: 182 | writers.print_trending_devs(devs) 183 | # if the user does not passes any argument then list the trending repo 184 | if not repo and not dev: 185 | repos = get_trending_repos(**opts) 186 | if goto: 187 | webbrowser.open(repos[goto-1]['url'], new=2) 188 | return 189 | else: 190 | writers.print_trending_repos(repos) 191 | return 192 | except Exception as e: 193 | click.secho(e.message, fg="red", bold=True) 194 | 195 | if __name__ == '__main__': 196 | main() 197 | -------------------------------------------------------------------------------- /githubtrending/utils.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | 4 | def get_console_size(): 5 | ''' 6 | returns no of rows, no of cols 7 | ''' 8 | with os.popen('stty size', 'r') as f: 9 | size = map(int, f.read().split()) 10 | return size 11 | 12 | 13 | def get_print_size_for_repo(data): 14 | name, lang, star = [0]*3 15 | for each in data: 16 | repo_name = each.get('repo_name') 17 | stars = each.get('stars') 18 | language = each.get('language') 19 | name = max(len(repo_name), name) 20 | lang = max(len(language), lang) 21 | star = max(len(stars), star) 22 | 23 | return { 24 | "NAME": name+1, 25 | "LANG": lang+1, 26 | "STAR": star+1, 27 | "IDX": 3, 28 | } 29 | 30 | 31 | def get_print_size_for_dev(data): 32 | dev, repo = [0]*2 33 | for each in data: 34 | dev_name = each.get('dev_name') 35 | repo_name = each.get('repo_name') 36 | dev = max(len(dev_name), dev) 37 | repo = max(len(repo_name), repo) 38 | 39 | return { 40 | "DEV": dev+1, 41 | "REPO": repo+1, 42 | "IDX": 3, 43 | } 44 | 45 | 46 | def get_color_code(): 47 | return { 48 | "IDX": "white", 49 | "NAME": "yellow", 50 | "LANG": "red", 51 | "STARS": "green", 52 | "DESC": "blue", 53 | "REPO": "green", 54 | } 55 | -------------------------------------------------------------------------------- /githubtrending/writers.py: -------------------------------------------------------------------------------- 1 | import click 2 | 3 | from . import utils 4 | 5 | 6 | def print_title(is_repo=True): 7 | rows, cols = utils.get_console_size() 8 | title = "TRENDING {} ON GITHUB".format("REPOSITORIES" if is_repo else "DEVELOPERS") 9 | click.echo() 10 | click.secho("%s" % ('#'*cols), bold=True) 11 | click.secho("%*s" % (cols//2, title), bold=True) 12 | click.secho("%s" % ('#'*cols), bold=True) 13 | 14 | 15 | def print_headers(print_size, is_repo=True): 16 | 17 | print_title(is_repo) 18 | click.echo() 19 | 20 | if is_repo: 21 | click.secho( 22 | "%*s" % (print_size["IDX"], '#'), 23 | nl=False, bold=True) 24 | click.secho( 25 | "%*s" % (print_size["NAME"], "USER/REPO"), 26 | nl=False, bold=True) 27 | click.secho( 28 | "%*s" % (print_size["LANG"], "LANG"), 29 | nl=False, bold=True) 30 | click.secho( 31 | "%*s" % (print_size["STAR"], "STAR"), 32 | nl=False, bold=True) 33 | click.secho( 34 | " %s" % ("DESCRIPTION"), 35 | nl=False, bold=True) 36 | else: 37 | click.secho("%*s" % (print_size["IDX"], '#'), nl=False, bold=True) 38 | click.secho("%*s" % (print_size["DEV"], "DEV"), nl=False, bold=True) 39 | click.secho("%*s" % (print_size["REPO"], "REPO"), nl=False, bold=True) 40 | click.secho(" %s" % ("DESCRIPTION"), nl=False, bold=True) 41 | 42 | 43 | def print_trending_repos(data): 44 | 45 | print_size = utils.get_print_size_for_repo(data) 46 | COLOR = utils.get_color_code() 47 | 48 | print_headers(print_size) 49 | 50 | for idx, each in enumerate(data): 51 | repo_name = each.get('repo_name') 52 | description = each.get('description') 53 | stars = each.get('stars') 54 | language = each.get('language') 55 | click.echo() 56 | click.secho( 57 | "%*s" % (print_size["IDX"], str(idx+1)), 58 | nl=False, bold=True, fg=COLOR['IDX']) 59 | click.secho( 60 | "%*s" % (print_size["NAME"], repo_name), 61 | nl=False, bold=True, fg=COLOR['NAME']) 62 | click.secho( 63 | "%*s" % (print_size["LANG"], language), 64 | nl=False, bold=True, fg=COLOR['LANG']) 65 | click.secho( 66 | "%*s" % (print_size["STAR"], stars), 67 | nl=False, bold=True, fg=COLOR['STARS']) 68 | click.secho( 69 | " %s" % (description), 70 | nl=False, bold=True, fg=COLOR['DESC']) 71 | print('') 72 | 73 | 74 | def print_trending_devs(data): 75 | 76 | print_size = utils.get_print_size_for_dev(data) 77 | COLOR = utils.get_color_code() 78 | 79 | print_headers(print_size, is_repo=False) 80 | 81 | for idx, each in enumerate(data): 82 | click.echo() 83 | dev_name = each.get('dev_name') 84 | repo_name = each.get('repo_name') 85 | description = each.get('description') 86 | click.secho( 87 | "%*s" % (print_size["IDX"], str(idx+1)), 88 | nl=False, bold=True, fg=COLOR['IDX']) 89 | click.secho( 90 | "%*s" % (print_size["DEV"], dev_name), 91 | nl=False, bold=True, fg=COLOR['NAME']) 92 | click.secho( 93 | "%*s" % (print_size["REPO"], repo_name), 94 | nl=False, bold=True, fg=COLOR['REPO']) 95 | click.secho( 96 | " %s" % (description), 97 | nl=False, bold=True, fg=COLOR['DESC']) 98 | print('') 99 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | click==5.1 2 | requests==2.7.0 3 | wsgiref==0.1.2 4 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [metadata] 2 | description-file = README.md 3 | 4 | [flake8] 5 | max-line-length = 120 6 | exclude = .git,py* -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from setuptools import setup 4 | import sys 5 | 6 | setup( 7 | name='github-trending', 8 | version='1.0.6', 9 | description='Trending repositories and developers on Github', 10 | long_description='''This python packages lists the trending repositories 11 | and developers on Github on the console. It is available as a command line 12 | utility.''', 13 | author='Taranjeet Singh', 14 | license='MIT', 15 | classifiers=[ 16 | # How mature is this project? Common values are 17 | # 3 - Alpha 18 | # 4 - Beta 19 | # 5 - Production/Stablegit 20 | 'Development Status :: 3 - Alpha', 21 | 'Environment :: Console', 22 | 'Intended Audience :: Developers', 23 | 'Intended Audience :: Information Technology', 24 | 'Natural Language :: English', 25 | 'Topic :: Software Development :: Build Tools', 26 | 'License :: OSI Approved :: MIT License', 27 | 'Programming Language :: Python :: 2', 28 | 'Programming Language :: Python :: 2.6', 29 | 'Programming Language :: Python :: 2.7', 30 | 'Programming Language :: Python :: 3', 31 | 'Programming Language :: Python :: 3.0', 32 | 'Programming Language :: Python :: 3.1', 33 | 'Programming Language :: Python :: 3.2', 34 | 'Programming Language :: Python :: 3.3', 35 | 'Programming Language :: Python :: 3.4', 36 | 'Programming Language :: Python :: 3.5' 37 | ], 38 | keywords="github trending repo developers trending-repo", 39 | author_email='reachtotj@gmail.com', 40 | url='https://github.com/staranjeet/github-trending-cli', 41 | packages=['githubtrending'], 42 | install_requires=[ 43 | 'requests==2.7.0', 44 | "click>=5.0", 45 | 'lxml>=3.3' 46 | ] + (["colorama==0.3.3"] if "win" in sys.platform else []), 47 | entry_points={ 48 | 'console_scripts': [ 49 | 'githubtrending = githubtrending.trending:main' 50 | ], 51 | } 52 | ) 53 | -------------------------------------------------------------------------------- /test/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/taranjeet/github-trending-cli/2566d19e5dcd420b78360b70da977b6f5a61be41/test/__init__.py -------------------------------------------------------------------------------- /test/data.py: -------------------------------------------------------------------------------- 1 | TRENDING_REPO_URL = 'http://github.com/trending' 2 | TRENDING_DEV_URL = 'http://github.com/trending/developers' 3 | 4 | TRENDING_REPO_COUNT = 25 5 | 6 | READ_PAGE_DATA = [ 7 | { 8 | 'url': TRENDING_REPO_URL, 9 | 'status_code': 200, 10 | 'title': 'repositories' 11 | }, 12 | { 13 | 'url': TRENDING_DEV_URL, 14 | 'status_code': 200, 15 | 'title': 'developers' 16 | }, 17 | ] 18 | -------------------------------------------------------------------------------- /test/test_github_trending.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | 3 | from click.testing import CliRunner 4 | 5 | from githubtrending import trending as githubtrending 6 | 7 | from . import data 8 | 9 | 10 | class TestGithubTrending(unittest.TestCase): 11 | 12 | def test_read_page(self): 13 | for each in data.READ_PAGE_DATA: 14 | url = each.get('url') 15 | expected_status_code = each.get('status_code') 16 | response, status_code = githubtrending.read_page(url) 17 | self.assertEqual(status_code, expected_status_code) 18 | 19 | def test_make_etree(self): 20 | for each in data.READ_PAGE_DATA: 21 | url = each.get('url') 22 | expected_status_code = each.get('status_code') 23 | expected_title = each.get('title').encode('utf8') 24 | response, status_code = githubtrending.make_etree(url) 25 | self.assertEqual(status_code, expected_status_code) 26 | page_title = response.xpath('//title')[0].text.encode('utf8') 27 | self.assertIn(expected_title, page_title) 28 | 29 | def test_get_trending_repo_names(self): 30 | tree, status_code = githubtrending.make_etree(data.TRENDING_REPO_URL) 31 | self.assertEqual(status_code, 200) 32 | repos = githubtrending.get_trending_repo_names(tree) 33 | self.assertEqual(data.TRENDING_REPO_COUNT, len(repos)) 34 | 35 | def test_get_trending_repo_description(self): 36 | tree, status_code = githubtrending.make_etree(data.TRENDING_REPO_URL) 37 | self.assertEqual(status_code, 200) 38 | repo_desc = githubtrending.get_trending_repo_description(tree) 39 | self.assertEqual(data.TRENDING_REPO_COUNT, len(repo_desc)) 40 | 41 | def test_get_trending_repo_meta(self): 42 | tree, status_code = githubtrending.make_etree(data.TRENDING_REPO_URL) 43 | self.assertEqual(status_code, 200) 44 | repo_meta = githubtrending.get_trending_repo_meta(tree) 45 | self.assertEqual(data.TRENDING_REPO_COUNT, len(repo_meta)) 46 | 47 | def test_get_trending_repo_stars_and_languages(self): 48 | tree, status_code = githubtrending.make_etree(data.TRENDING_REPO_URL) 49 | self.assertEqual(status_code, 200) 50 | repo_meta = githubtrending.get_trending_repo_meta(tree) 51 | repo_stars_and_langauges = githubtrending.get_trending_repo_stars_and_languages(repo_meta) 52 | self.assertEqual(data.TRENDING_REPO_COUNT, len(repo_stars_and_langauges)) 53 | 54 | def test_get_trending_repos(self): 55 | repos = githubtrending.get_trending_repos() 56 | self.assertEqual(data.TRENDING_REPO_COUNT, len(repos)) 57 | 58 | def test_get_trending_dev_names(self): 59 | tree, status_code = githubtrending.make_etree(data.TRENDING_DEV_URL) 60 | self.assertEqual(status_code, 200) 61 | repos = githubtrending.get_trending_dev_names(tree) 62 | self.assertEqual(data.TRENDING_REPO_COUNT, len(repos)) 63 | 64 | def test_get_trending_dev_repo_names(self): 65 | tree, status_code = githubtrending.make_etree(data.TRENDING_DEV_URL) 66 | self.assertEqual(status_code, 200) 67 | repos = githubtrending.get_trending_dev_repo_names(tree) 68 | self.assertEqual(data.TRENDING_REPO_COUNT, len(repos)) 69 | 70 | def test_get_trending_dev_repo_desc(self): 71 | tree, status_code = githubtrending.make_etree(data.TRENDING_DEV_URL) 72 | self.assertEqual(status_code, 200) 73 | repos = githubtrending.get_trending_dev_repo_desc(tree) 74 | self.assertEqual(data.TRENDING_REPO_COUNT, len(repos)) 75 | 76 | def test_get_trending_devs(self): 77 | devs = githubtrending.get_trending_devs() 78 | self.assertEqual(data.TRENDING_REPO_COUNT, len(devs)) 79 | 80 | 81 | class GithubTrendingCliTest(unittest.TestCase): 82 | 83 | def __init__(self, *args, **kwargs): 84 | self.runner = CliRunner() 85 | super(GithubTrendingCliTest, self).__init__(*args, **kwargs) 86 | 87 | def test_github_trending_with_no_args(self): 88 | result = self.runner.invoke(githubtrending.main, []) 89 | assert result.exit_code == 0 90 | 91 | def test_github_trending_with_repo_as_args(self): 92 | result = self.runner.invoke(githubtrending.main, ['--repo']) 93 | assert result.exit_code == 0 94 | 95 | def test_github_trending_with_dev_as_args(self): 96 | result = self.runner.invoke(githubtrending.main, ['--dev']) 97 | assert result.exit_code == 0 98 | 99 | def test_github_trending_with_repo_and_lang_as_args(self): 100 | result = self.runner.invoke(githubtrending.main, ['--repo', '--lang=python']) 101 | assert result.exit_code == 0 102 | 103 | def test_github_trending_with_dev_and_timespan_as_args(self): 104 | result = self.runner.invoke(githubtrending.main, ['--dev', '--week']) 105 | assert result.exit_code == 0 106 | 107 | def test_github_trending_with_open_first_repo_in_browser(self): 108 | self.runner.invoke(githubtrending.main, ['--repo', '1']) 109 | 110 | def test_github_trending_with_open_third_dev_in_browser(self): 111 | self.runner.invoke(githubtrending.main, ['--dev', '3']) 112 | 113 | def test_github_trending_with_open_fifth_repo_in_browser_and_no_args(self): 114 | self.runner.invoke(githubtrending.main, ['3']) 115 | 116 | if __name__ == '__main__': 117 | unittest.main() 118 | --------------------------------------------------------------------------------