Coverage for professional_python_exercises_2_githubcli\github_cli.py: 31%
113 statements
« prev ^ index » next coverage.py v6.5.0, created at 2022-11-05 16:48 +0100
« prev ^ index » next coverage.py v6.5.0, created at 2022-11-05 16:48 +0100
1import os
2import sys
3import json
4from typing import Optional
5import dotenv
6from github import Github
7from github.NamedUser import NamedUser
8import typer
9import requests
11app = typer.Typer()
14def get_user_form_input() -> NamedUser:
15 """
16 Method used in the app commands to get the user from user input:
18 Returns:
19 user : NamedUser
20 """
21 name = input("User: ")
22 if name == "":
23 typer.echo("Empty Value inputted, try again")
24 sys.exit("Failed to get user input")
25 token = get_github_token()
26 github_session = Github(token)
27 if github_session.search_users(name).totalCount == 0:
28 typer.echo("User not found, please try again.")
29 sys.exit("Failed to find user.")
30 user = github_session.get_user(name)
31 return user
34@app.command()
35def countstars(json_format: Optional[bool] = False) -> int:
36 """
37 Counts the stars of a specified user and gives a nice comment to the user
39 Parameters:
40 json_format : Optional[bool] = False
41 decides wether json or plain text format is required
43 Returns:
44 starCount : int
45 number of stars
46 """
47 typer.echo("Enter user to count stars for.")
48 user = get_user_form_input()
49 name = user.name
51 repositories = user.get_repos()
52 star_count = 0
53 for repo in repositories:
54 stars = repo.stargazers_count
55 star_count += stars
56 if json_format:
57 output = {}
58 output["username"] = name
59 output["stars"] = star_count
60 print(json.dumps(output))
61 else:
62 typer.echo(f"User: {name} has {star_count}⭐ in {repositories.totalCount} repositories.")
63 typer.echo(_rate_stars_to_repos(star_count, repositories.totalCount))
64 return star_count
67def _rate_stars_to_repos(star_count: int, repository_count: int) -> str:
68 """
69 Rates the star to repository count, a little fun never killed nobody.
71 Parameters:
72 star_count : int
73 the number of stars for the user
74 repository_count : int
75 the number of repositories for the user
77 Returns:
78 message : str
79 A message reflecting the rating
80 """
82 if star_count == 0 or repository_count == 0:
83 return "This poor fellar. Work harder!"
84 if star_count / repository_count > 100:
85 return "Greetings, Mr. Starlord"
86 if star_count / repository_count < 1:
87 return "Keep doing what you're doing. But do more!"
88 return "Not bad ey, not bad."
91@app.command()
92def getdetails(json_format: Optional[bool] = False) -> json:
93 """
94 Gets the details for a specified user.
96 Parameters:
97 json_format: Optional[bool] = False
98 Decides wether nomal text output or json is required
100 Returns:
101 raw : json
102 Raw details in json format fron the get details request
103 """
105 typer.echo("Enter user to get details for.")
106 user = get_user_form_input()
107 name = user.name
108 typer.echo(f"Getting the detials for: {name}")
110 bio = user.bio
111 repocount = user.get_repos().totalCount
112 star_count = 0
113 for repo in user.get_repos():
114 stars = repo.stargazers_count
115 star_count += stars
116 followers = user.get_followers()
117 following = user.get_following()
118 blog = user.blog
119 company = user.company
120 contributions = user.contributions
121 created = user.created_at
122 email = user.email
123 organizations = user.get_orgs()
124 avatar_url = user.avatar_url
125 starred = user.get_starred()
126 subs = user.get_subscriptions()
127 watched = user.get_watched()
128 location = user.location
129 hireable = user.hireable
131 raw = user.raw_data
133 if json_format:
134 print(raw)
135 else:
136 typer.echo(f"Details about user:{user}, created at {created}, bio: {bio}")
137 typer.echo(
138 f"Stars: {star_count}, repos: {repocount}, followers: {followers.totalCount}"
139 f", following: {following.totalCount}"
140 )
141 typer.echo(
142 f"Contributions: {contributions}, orgs: {organizations.totalCount},"
143 f" starred: {starred.totalCount}, subs: {subs.totalCount},"
144 f" watched: {watched.totalCount}"
145 )
146 typer.echo(f"Get a visual impression at:{avatar_url}")
147 typer.echo(f"The blog: {blog}")
148 typer.echo(f"Mail: {email}, hireable: {hireable}, location: {location}, company: {company}")
149 return raw
152@app.command()
153def setstatus() -> bool:
154 """
155 Sets the status to something related to this repository: Drinking tea.
156 Returns:
157 success : bool
158 success if successful status change could be accomplished
159 """
161 mutation = """mutation {
162 changeUserStatus(input:{emoji:":tea:", message:"Drinking tea"}) {
163 status{
164 emoji
165 message
166 }
167 }
168 }
169 """
170 headers = {"Authorization": f"token {get_github_token()}"}
171 request = requests.post(
172 "https://api.github.com/graphql", json={"query": mutation}, headers=headers, timeout=30
173 )
174 if request.status_code == 200:
175 typer.echo("Success")
176 return True
177 typer.echo(f"Mutation failed to run by returning code of {request.status_code}. {mutation}")
178 return False
181def get_github_token() -> str:
182 """
183 Checks, if API Key is set as an environment variable. If not, the user is
184 asked to input it in the console. Length checks enabled for the API key. If
185 key has non-valid length (!=32) the user is asked again to enter a valid key.
186 The key is saved into a local .env file.
187 Returns:
188 github_token : str
189 API Key for the Open Weather Map
190 """
192 dotenv_file = dotenv.find_dotenv()
193 if dotenv_file == "":
194 with open(os.getcwd() + "\\.env", mode="w", encoding="utf-8").close():
195 pass
196 dotenv_file = dotenv.find_dotenv()
197 dotenv.load_dotenv(dotenv_file)
199 if "TNT_EX2_GITHUB_TOKEN" not in os.environ:
200 print(
201 "No API Key found in your environment variables. \nPlease look at "
202 "https://github.com/settings/tokens for getting an API key and enter "
203 "it in the following line:",
204 file=sys.stderr,
205 )
206 os.environ["TNT_EX2_GITHUB_TOKEN"] = input("Please enter your API Key now: \n-->").strip()
207 api_key = os.environ["TNT_EX2_GITHUB_TOKEN"]
208 if len(api_key) != 40:
209 print(
210 "Wrong sized GitHub Accoss Token inputted (correct length: 40), "
211 f"key found: {api_key}, \nplease look at https://github.com/settings/tokens "
212 "for getting an API key and enter it in the following line:",
213 file=sys.stderr,
214 )
215 os.environ["TNT_EX2_GITHUB_TOKEN"] = input("Please enter your API Key now:\n-->").strip()
216 return get_github_token()
218 dotenv.set_key(dotenv_file, "TNT_EX2_GITHUB_TOKEN", api_key) # save the API key to .env file
219 return api_key
222if __name__ == "__main__":
223 app()