Skip to content

Commit 8501609

Browse files
author
Ian C
committed
Merge pull request #156 from GrappigPanda/issue-124
Fixes #124: Added docstrings to everything.
2 parents b4973cd + 54ca651 commit 8501609

File tree

3 files changed

+150
-16
lines changed

3 files changed

+150
-16
lines changed

pyg/Pygemony.py

+74-16
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88

99

1010
class Pygemony(object):
11+
"""
12+
The main driver of pygemony, pulls the seperate pieces together.
13+
"""
1114
def __init__(self, user=None, token=None, owner=None, repo=None):
1215
# todo_found contains a list of the following layout:
1316
# ['file_path', 'line_number', 'todo_message', 'md5 of todo']
@@ -17,23 +20,14 @@ def __init__(self, user=None, token=None, owner=None, repo=None):
1720
# TODO(ian): Add support for parsing more than one file type
1821
self.language = self.lookup_language()
1922

20-
def find_end_comment(self, f):
21-
# TODO(ian): Remove this function as we no longer support multiline TODO
22-
todo_content = []
23-
x = f
24-
count = 0
25-
for line in x.readlines():
26-
todo_content.append(line)
27-
if self.language.multi_comment[1] in line:
28-
return todo_content
29-
30-
if count > 20:
31-
return None
32-
33-
todo_content.append(line)
34-
count += 1
35-
3623
def _sanitize_todo_line(self, lines):
24+
"""
25+
Strips tab, newline, and comment characters form the TODO line.
26+
27+
:param str lines: The found line containing a TODO
28+
:rtype: str
29+
:return: The sanitized TODO line.
30+
"""
3731
# We're mainly aiming to remove newlines and tab characters here.
3832
lines = lines.replace('\n', '')
3933
while ' ' in lines or '\t' in lines:
@@ -44,23 +38,55 @@ def _sanitize_todo_line(self, lines):
4438

4539
@staticmethod
4640
def hash_todo(todo_content, file_name):
41+
"""
42+
Hashes the TODO line with the file name
43+
44+
:param str todo_content: The line in the file containing TODO
45+
:param str file_name: The file name containing the TODO line.
46+
:rtype: str
47+
:return: The MD5 hash of the `todo_content` and `file_name`
48+
"""
4749
m = hashlib.md5()
4850
m.update('{0}-{1}'.format(todo_content, file_name))
4951
return str(m.hexdigest())
5052

5153
def parse_for_todo(self, f, file_):
54+
"""
55+
Searches (line-by-line) through a file's content and and looks for
56+
lines containing TODO.
57+
58+
:param file_handle f: The handle to the file that is currently being
59+
searched
60+
:param str file_: The name of the file currently being searched
61+
"""
5262
for i, line in enumerate(f.readlines()):
5363
if "TODO" in line and self._starts_with_comment(line):
5464
line = self._sanitize_todo_line(line)
5565
self.todo_found.append([file_, i, line, self.hash_todo(line, file_)])
5666

5767
def parse_by_extension(self, files):
68+
"""
69+
Parses the list of the directory for files with an acceptable
70+
extension. The extension is determined by data returned from github on
71+
the languages used in the project.
72+
73+
:param list files: The list of all files in the current repository
74+
:rtype: generator(str)
75+
:return: Generates a list of acceptable-to-parse files.
76+
"""
5877
for lang in self.language:
5978
for ext in lang.file_exts:
6079
for file_ in fn_filter(files, ext):
6180
yield file_
6281

6382
def find_all_files(self, root):
83+
"""
84+
Walks the current repository directory and determines viable files
85+
86+
:param str root: The root directory
87+
:rtype: list
88+
:return: The list of files found and determined to be viable.
89+
"""
6490
files_found = []
6591

6692
for roots, _, files in walk(root):
@@ -73,6 +99,12 @@ def find_all_files(self, root):
7399
return files_found
74100

75101
def file_handler(self):
102+
"""
103+
Handles IO with the file
104+
105+
:rtype: list
106+
:return: The list of files found
107+
"""
76108
# First we need to remove any non-text files
77109
files_found = self.find_all_files('./')
78110
# TODO(ian): filter() over files to parse out by mimetype
@@ -96,10 +128,20 @@ def file_handler(self):
96128
return files_found
97129

98130
def run(self):
131+
"""
132+
Starts the process of finding TODOs
133+
"""
99134
self.file_handler()
100135
self.github.commit(self.todo_found)
101136

102137
def lookup_language(self):
138+
"""
139+
Constructs langauge classes based on what is found in github data.
140+
141+
:rtype: list
142+
:return: A list of language classes that will be found in a github
143+
repo.
144+
"""
103145
lang_map = {'cpp': LanguageCPP,
104146
'python': LanguagePython,
105147
'javascript': LanguageJavascript,
@@ -114,12 +156,28 @@ def lookup_language(self):
114156
return [lang_map[str(langs[0][0]).lower()]()]
115157

116158
def _starts_with_comment(self, line):
159+
"""
160+
Verifies a line (containing the word TODO) starts with a comment, if it
161+
does, we deem it to be commit-viable.
162+
163+
:param str line: The line that contains "TODO"
164+
165+
:rtype: bool
166+
:return: True if line starts with a comment (is a valid TODO statement)
167+
"""
117168
comments = self._create_comment_start_list()
118169
for comment in comments:
119170
if line.startswith(comment):
120171
return True
121172

122173
def _create_comment_start_list(self):
174+
"""
175+
Create a list of comments from each language class associated with the
176+
current repo.
177+
178+
:rtype: list
179+
:return: A list of strings containing all line-start comments.
180+
"""
123181
comments = []
124182
for lang in self.language:
125183
comments.append(lang.single_comment)

pyg/github.py

+61
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@
33

44

55
class GithubAPIManager(object):
6+
"""
7+
Handles authorization and everything else done with the github api.
8+
"""
9+
610
# repo_location = grappigpanda/pygemony.py
711
def __init__(self, user, token, owner, repo):
812
self.is_authed = False
@@ -27,13 +31,27 @@ def __init__(self, user, token, owner, repo):
2731

2832

2933
def login(self):
34+
"""
35+
Logs the user in.
36+
37+
:rtype: gh.repository
38+
:return: github3.login()
39+
"""
3040
try:
3141
return github3.login(self.user, self.token)
3242
except github3.models.GitHubError as e:
3343
print "Failed to login due to {}".format(e)
3444
return None
3545

3646
def _save_submitted_todo(self, issue):
47+
"""
48+
Writes the TODO issue information (the hashed info) to the
49+
`.pyg-submitted` file.
50+
51+
:param list issue: A list containing info about the found TODO
52+
:rtype: bool
53+
:return: True on successful write, False if the issue exists already.
54+
"""
3755
if not path.isfile('./.pyg-submitted'):
3856
with open('./.pyg-submitted', 'a+') as f:
3957
f.write("""
@@ -53,6 +71,13 @@ def _save_submitted_todo(self, issue):
5371
return True
5472

5573
def commit(self, todo_found):
74+
"""
75+
Creates a github issue per TODO found.
76+
77+
78+
:param list todo_found: A list containing information about the found
79+
TODO
80+
"""
5681
# TODO(ian): Assign issues if () in line. (ian), for example
5782
for issue in todo_found:
5883
if self._save_submitted_todo(issue):
@@ -61,31 +86,67 @@ def commit(self, todo_found):
6186
body=self._construct_issue_body(issue))
6287

6388
def get_languages(self):
89+
"""
90+
Iterates through the languages used in the project and yields the
91+
language.
92+
93+
:rtype: generator(str)
94+
:return: A generator for the languages used in the project
95+
"""
6496
for i in self.curr_repo.iter_languages():
6597
yield i
6698

6799
def _get_repo_owner(self):
100+
"""
101+
Gets the repo owner from the gitconfig.
102+
103+
:rtype: tuple
104+
:return: The (repo, owner) of the repo from the git config.
105+
"""
68106
# TODO(ian): Remove the magic directory!
69107
with open('./.git/config', 'r+') as f:
70108
for line in f.readlines():
71109
if 'url = ' in line:
72110
return line.split('github.com/')[-1].split('/')
73111

74112
def get_repo(self):
113+
"""
114+
Reads the repo name from the git config
115+
116+
:rtype: str
117+
:return: The repo's name
118+
"""
75119
return self._get_repo_owner()[1]
76120

77121
def get_owner(self):
122+
"""
123+
Reads the repo owner's name from the git config
124+
125+
:rtype: str
126+
:return: The repo owner's name
127+
"""
78128
return self._get_repo_owner()[0]
79129

80130
@staticmethod
81131
def _construct_issue_body(issue):
132+
"""
133+
Constructs the issue body that is posted in the github issue.
134+
135+
:rtype: str
136+
:return: The issue body, html formatted.
137+
"""
82138
# TODO(ian): Move all @staticmethods to a seperate class
83139
sz = 'File Location: {}<br>Line Number: {}'.format(issue[0], issue[1])
84140
sz += '<br> This message was auto-generated by Pygemony: '
85141
sz += '<a href="http://github.com/GrappigPanda/pygemony">Github</a>'
86142
return sz
87143

88144
def _pprint(self, issue):
145+
"""
146+
Prints information to the screen about creating commits
147+
148+
:param list issue: A list of information about the found TODO.
149+
"""
89150
msg = "Committing to repo: {}"
90151
msg += "\n\tFile Name: {}:{}\n\tTodo Message:{}"
91152
print msg.format(self.repo, issue[0], issue[1], issue[2])

pyg/utils.py

+15
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
11
from mimetypes import guess_type
22

33
def get_git_info():
4+
"""
5+
Parses the git info and returns a tuple containg the owner and repo
6+
7+
:deprecated:
8+
:rtype: tuple
9+
:return: (owner name, repo name)
10+
"""
411
repo = ''
512
with open('.git/config') as f:
613
for line in f.readlines():
@@ -12,4 +19,12 @@ def get_git_info():
1219

1320

1421
def detect_mimetype(file_):
22+
"""
23+
Detects the provided file's mimetype. Used to determine if we should read
24+
the file line-by-line.
25+
26+
:param str file_: The name of the file to guess the mimetype of
27+
:rtype: str
28+
:return: The mimetype of the file provided
29+
"""
1530
return guess_type(file_)

0 commit comments

Comments
 (0)