Skip to content

Commit 4d873a0

Browse files
authored
Merge pull request #268 from adafruit/find-text-script
Added find_text.py script
2 parents 8ed7e26 + 461b54d commit 4d873a0

File tree

2 files changed

+211
-0
lines changed

2 files changed

+211
-0
lines changed

tools/README.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,12 @@
11
# Tools directory. UPDATE THIS README.
2+
3+
4+
#### find_text.py
5+
6+
Script to check for text across CircuitPython repos.
7+
8+
Must be run from top-level directory (i.e. one up from this one).
9+
10+
Type:
11+
`python3 find_text.py -h`
12+
to figure out how to use it.

tools/find_text.py

Lines changed: 200 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,200 @@
1+
# The MIT License (MIT)
2+
#
3+
# Copyright (c) 2022 Eva Herrada
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
13+
# all 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
21+
# THE SOFTWARE.
22+
23+
"""
24+
Tool for searching for text across all circuitpython libraries.
25+
Intended to be used to verify patches.
26+
27+
IMPORTANT: Must be run from the top-level adabot directory (one directory up
28+
from this one)
29+
30+
Type `python3 find_text.py -h` to figure out how to use.
31+
"""
32+
33+
import datetime
34+
import getopt
35+
import json
36+
import sys
37+
38+
import requests
39+
40+
from adabot.lib.common_funcs import list_repos
41+
42+
argumentList = sys.argv[1:]
43+
44+
OPTIONS = "ht:f:o:j"
45+
46+
long_options = ["help", "text=", "file=", "outfile=", "json"]
47+
48+
HELPMSG = """Usage:
49+
python3 find_text.py [-h | -t text | -f file | -o outfile | -j]
50+
Arguments:
51+
-h --help - Displays this message
52+
-t --text - (required) Text to check, can be used multiple times
53+
-f --file - (required) File to check for text for on github
54+
-o --outfile - (optional) Output file, prints output to stdout if variable
55+
is not set
56+
-j --json - Outputs in json instead of plain text"""
57+
58+
text = []
59+
FILE = None
60+
OUTFILE = None
61+
j = False
62+
63+
URL_TEMPLATE = "https://raw.githubusercontent.com/adafruit/{}/main/{}"
64+
RELEASE_TEMPLATE = "https://api.github.com/repos/adafruit/{}/releases/latest"
65+
66+
try:
67+
arguments, values = getopt.getopt(argumentList, OPTIONS, long_options)
68+
69+
for currentArgument, currentValue in arguments:
70+
if currentArgument in ("-h", "--help"):
71+
print(HELPMSG)
72+
sys.exit()
73+
74+
if currentArgument in ("-t", "--text"):
75+
print(f"Text: {currentValue}")
76+
text.append(currentValue)
77+
print(text)
78+
79+
if currentArgument in ("-f", "--file"):
80+
print(f"File: {currentValue}")
81+
FILE = currentValue
82+
83+
if currentArgument in ("-o", "--outfile"):
84+
OUTFILE = currentValue
85+
86+
if currentArgument in ("-j", "--json"):
87+
j = True
88+
89+
except getopt.error as err:
90+
print(str(err))
91+
92+
93+
if len(text) == 0 or FILE is None:
94+
if len(text) == 0:
95+
print("Please enter text to check for")
96+
if FILE is None:
97+
print("Please enter a file to search for the text in")
98+
print(HELPMSG)
99+
sys.exit()
100+
101+
RESULTS = {
102+
"file_not_found": [],
103+
"file_has_none": [],
104+
"file_has_all": [],
105+
}
106+
for i in range(len(text)):
107+
RESULTS[f"file_has_text_{i}"] = []
108+
109+
110+
def delete_multiple_lines(n=1):
111+
"""Delete the last line in the STDOUT."""
112+
for _ in range(n):
113+
sys.stdout.write("\x1b[1A") # cursor up one line
114+
sys.stdout.write("\x1b[2K") # delete the last line
115+
116+
117+
def prettyprint(info, results):
118+
"""Prints info about current repo and result of search"""
119+
print("┌" + "─" * (len(info) + 4) + "┐")
120+
print("│ ", info, " │")
121+
for res in results:
122+
print("│ ", res, " " * (len(info) - (len(res) - 9)), "│")
123+
print("└" + "─" * (len(info) + 4) + "┘")
124+
delete_multiple_lines(3 + len(results))
125+
126+
127+
try:
128+
with open("repos.json", "r") as f:
129+
LAST_RUN = f.readline().rstrip()
130+
except FileNotFoundError:
131+
LAST_RUN = ""
132+
133+
print(f"Last run: {LAST_RUN}")
134+
if LAST_RUN != str(datetime.date.today()):
135+
with open("repos.json", "w") as f:
136+
print("Fetching Repos List")
137+
all_repos = list_repos()
138+
print("Got Repos List")
139+
f.write(str(datetime.date.today()) + "\n")
140+
f.write(json.dumps(all_repos))
141+
142+
with open("repos.json", "r") as f:
143+
all_repos = json.loads(f.read().split("\n")[1])
144+
145+
print(f"Repos found: {len(all_repos)}")
146+
147+
148+
for repo in all_repos:
149+
INFO = "getting {} for: {}".format(FILE, repo["name"])
150+
response = requests.get(URL_TEMPLATE.format(repo["name"], FILE))
151+
result = []
152+
if response.status_code == 404:
153+
RESULTS["file_not_found"].append(repo["html_url"])
154+
result.append("\033[91mFile not found\033[0m")
155+
else:
156+
tracker = [False for i in range(len(text))]
157+
for index, item in enumerate(text):
158+
if item in response.text:
159+
tracker[index] = True
160+
161+
if all(tracker):
162+
result = ["\033[92mFound all text\033[0m"]
163+
RESULTS["file_has_all"].append(repo["html_url"])
164+
elif not any(tracker):
165+
result = ["\033[91mDid not find any text\033[0m"]
166+
RESULTS["file_has_none"].append(repo["html_url"])
167+
for index, item in enumerate(tracker):
168+
if item:
169+
result.append(f"\033[93mFound text {index}\033[0m")
170+
RESULTS[f"file_has_text_{index}"].append(repo["html_url"])
171+
else:
172+
result.append(f"\033[93mDid not find text {index}\033[0m")
173+
174+
prettyprint(INFO, result)
175+
176+
if j:
177+
if OUTFILE is not None:
178+
with open(OUTFILE, "w") as F:
179+
F.write(json.dumps(RESULTS))
180+
else:
181+
print(json.dumps(RESULTS))
182+
else:
183+
if OUTFILE is not None:
184+
with open(OUTFILE, "w") as F:
185+
for k, v in RESULTS.items():
186+
F.write(k + "\n")
187+
for i in v:
188+
F.write(i + "\n")
189+
F.write("\n")
190+
else:
191+
for k, v in RESULTS.items():
192+
print(k)
193+
for i in v:
194+
print(i)
195+
196+
197+
print("┌" + "─" * 30 + "┐")
198+
for k, v in RESULTS.items():
199+
print("│ ", k, len(v), " " * (24 - (len(k) + len(str(len(v))))), " │")
200+
print("└" + "─" * 30 + "┘")

0 commit comments

Comments
 (0)