kospex 0.0.14__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- kgit.py +329 -0
- kospex-0.0.14.dist-info/LICENSE +21 -0
- kospex-0.0.14.dist-info/METADATA +61 -0
- kospex-0.0.14.dist-info/RECORD +53 -0
- kospex-0.0.14.dist-info/WHEEL +5 -0
- kospex-0.0.14.dist-info/entry_points.txt +7 -0
- kospex-0.0.14.dist-info/top_level.txt +18 -0
- kospex.py +949 -0
- kospex_bitbucket.py +97 -0
- kospex_core.py +1125 -0
- kospex_dependencies.py +887 -0
- kospex_git.py +346 -0
- kospex_github.py +208 -0
- kospex_mergestat.py +154 -0
- kospex_query.py +1517 -0
- kospex_schema.py +360 -0
- kospex_utils.py +1270 -0
- kospex_web.py +60 -0
- kreaper.py +80 -0
- krunner.py +344 -0
- krunner_utils.py +257 -0
- kwatch.py +29 -0
- kweb.py +734 -0
- templates/404.html +30 -0
- templates/_bootstrap_html_head.html +9 -0
- templates/_datatable_scripts.html +2 -0
- templates/_footer_scripts.html +5 -0
- templates/_id_header_macro.html +6 -0
- templates/_radar_macro.html +46 -0
- templates/_single_radar.html +41 -0
- templates/bubble.html +615 -0
- templates/commits.html +46 -0
- templates/developer_view.html +98 -0
- templates/developers.html +93 -0
- templates/graph.html +651 -0
- templates/graph2.html +696 -0
- templates/header.html +31 -0
- templates/hotspots.html +58 -0
- templates/landscape.html +88 -0
- templates/meta-author-domains.html +44 -0
- templates/metadata.html +107 -0
- templates/observations.html +47 -0
- templates/observations_repo.html +48 -0
- templates/observations_repo_key.html +49 -0
- templates/orgs.html +67 -0
- templates/osi.html +19 -0
- templates/repo_files.html +53 -0
- templates/repo_view.html +154 -0
- templates/repos.html +152 -0
- templates/servers.html +55 -0
- templates/summary.html +191 -0
- templates/tech-change.html +78 -0
- templates/treemap.html +641 -0
kgit.py
ADDED
|
@@ -0,0 +1,329 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""This is the kospex git CLI helper tool."""
|
|
3
|
+
import time
|
|
4
|
+
import os
|
|
5
|
+
import json
|
|
6
|
+
import subprocess
|
|
7
|
+
import click
|
|
8
|
+
from prettytable import PrettyTable
|
|
9
|
+
from kospex_core import GitRepo, Kospex
|
|
10
|
+
import kospex_utils as KospexUtils
|
|
11
|
+
from kospex_git import KospexGit
|
|
12
|
+
from kospex_github import KospexGithub
|
|
13
|
+
from kospex_bitbucket import KospexBitbucket
|
|
14
|
+
|
|
15
|
+
KospexUtils.init()
|
|
16
|
+
kgit = KospexGit()
|
|
17
|
+
kospex = Kospex()
|
|
18
|
+
|
|
19
|
+
@click.group()
|
|
20
|
+
def cli():
|
|
21
|
+
"""kgit (Kospex Git) is a utility for doing git things with kospex use cases.
|
|
22
|
+
|
|
23
|
+
For documentation on how commands run `kgit COMMAND --help`.
|
|
24
|
+
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
@cli.command("status")
|
|
28
|
+
@click.argument('repo', type=GitRepo())
|
|
29
|
+
# pylint: disable=unused-argument
|
|
30
|
+
def status(repo):
|
|
31
|
+
"""Date and commit metadata for the given repo."""
|
|
32
|
+
print(f"\nRepo status for path: {repo}")
|
|
33
|
+
st = time.time()
|
|
34
|
+
|
|
35
|
+
stats = KospexUtils.get_git_stats(repo, 90)
|
|
36
|
+
table = PrettyTable()
|
|
37
|
+
table.field_names = ["Subject", "Value"]
|
|
38
|
+
table.align["Subject"] = "l"
|
|
39
|
+
table.align["Value"] = "r"
|
|
40
|
+
for subject, details in stats.items():
|
|
41
|
+
table.add_row([subject, details])
|
|
42
|
+
print(table)
|
|
43
|
+
print("Notes:")
|
|
44
|
+
print("\tdirectory sizes are in KB.")
|
|
45
|
+
print("\tunique authors are the number of unique authors in the last 90 days.")
|
|
46
|
+
et = time.time()
|
|
47
|
+
elapsed_time = et - st
|
|
48
|
+
print('\nExecution time:', elapsed_time, 'seconds', "\n")
|
|
49
|
+
|
|
50
|
+
#@cli.command("mailmap")
|
|
51
|
+
@click.option('-sync', is_flag=True, default=False, help="Sync .mailmap to the database (Default)")
|
|
52
|
+
@click.argument('filename', required=False, type=click.Path(exists=True))
|
|
53
|
+
def mailmap(sync, filename):
|
|
54
|
+
"""
|
|
55
|
+
Parse a .mailmap file and disply
|
|
56
|
+
If the -sync is passed, sync the mailmap file to the kospex database.
|
|
57
|
+
"""
|
|
58
|
+
mmap = KospexUtils.parse_mailmap(filename)
|
|
59
|
+
for entry in mmap:
|
|
60
|
+
print(entry)
|
|
61
|
+
|
|
62
|
+
#@cli.command("branches")
|
|
63
|
+
@click.option('-sync', is_flag=True, default=False, help="Sync branches to the database")
|
|
64
|
+
@click.argument('repo', type=GitRepo())
|
|
65
|
+
def branches(sync, repo):
|
|
66
|
+
"""
|
|
67
|
+
Show the branches for a given repo
|
|
68
|
+
If the -sync is passed, sync the branches to the kospex database.
|
|
69
|
+
"""
|
|
70
|
+
kgit.set_repo(repo)
|
|
71
|
+
os.chdir(repo)
|
|
72
|
+
cmd = ['git', 'branch', '--all']
|
|
73
|
+
result = subprocess.run(cmd, capture_output=True, text=True).stdout.split('\n')
|
|
74
|
+
bob = []
|
|
75
|
+
for i in result:
|
|
76
|
+
if i.lstrip():
|
|
77
|
+
bob.append(i.lstrip()) # remove leading spaces
|
|
78
|
+
print(bob)
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
@cli.command("clone")
|
|
82
|
+
@click.option('-sync', is_flag=True, default=True, help="Sync the repo to the database (Default)")
|
|
83
|
+
@click.option('-filename', type=click.Path(exists=True), help="File with HTTP git clone URLs")
|
|
84
|
+
@click.argument('repo',type=click.STRING, required=False)
|
|
85
|
+
def clone(sync, filename,repo):
|
|
86
|
+
"""
|
|
87
|
+
Clone the given repo into our KOSPEX_CODE directory.
|
|
88
|
+
Example:
|
|
89
|
+
kgit clone https://github.com/ORG/REPO
|
|
90
|
+
"""
|
|
91
|
+
# We're going to shell out to git to do the clone
|
|
92
|
+
kospex = Kospex()
|
|
93
|
+
|
|
94
|
+
if repo and filename:
|
|
95
|
+
exit("You can't specify both a repo and a filename. Please choose one.")
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
if repo:
|
|
99
|
+
repo_path = kgit.clone_repo(repo)
|
|
100
|
+
if sync and repo_path:
|
|
101
|
+
print("Syncing repo: " + repo_path)
|
|
102
|
+
kospex.sync_repo(repo_path)
|
|
103
|
+
|
|
104
|
+
elif filename:
|
|
105
|
+
with open(filename, "r", encoding='utf-8') as file:
|
|
106
|
+
for line in file:
|
|
107
|
+
repo = line.strip()
|
|
108
|
+
if repo.startswith("#"):
|
|
109
|
+
print(f"\n\nSkipping commented line: {repo}\n\n")
|
|
110
|
+
else:
|
|
111
|
+
repo_path = kgit.clone_repo(repo)
|
|
112
|
+
if not repo_path:
|
|
113
|
+
print(f"\n\nERROR with {repo}\n\n")
|
|
114
|
+
|
|
115
|
+
if sync and repo_path:
|
|
116
|
+
print("Syncing: " + repo)
|
|
117
|
+
kospex = Kospex()
|
|
118
|
+
kospex.sync_repo(repo_path)
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
@cli.command("pull")
|
|
122
|
+
@click.option('-sync', is_flag=True, default=True, help="Sync the repo to the database (Default)")
|
|
123
|
+
def pull(sync):
|
|
124
|
+
"""
|
|
125
|
+
Check if we're in a git repo, do a git pull,
|
|
126
|
+
and sync to the kospex DB.
|
|
127
|
+
"""
|
|
128
|
+
current = os.getcwd()
|
|
129
|
+
git_base = KospexUtils.find_git_base(current)
|
|
130
|
+
if git_base:
|
|
131
|
+
os.chdir(git_base)
|
|
132
|
+
os.system("git pull")
|
|
133
|
+
if sync:
|
|
134
|
+
print("Syncing to kospex DB ...")
|
|
135
|
+
kospex.sync_repo(git_base)
|
|
136
|
+
os.chdir(current)
|
|
137
|
+
else:
|
|
138
|
+
print(f"{current} does not appear to be in a git repo")
|
|
139
|
+
|
|
140
|
+
@cli.command("github")
|
|
141
|
+
@click.option('-org', type=click.STRING)
|
|
142
|
+
@click.option('-user', type=click.STRING)
|
|
143
|
+
@click.option('-no-auth', is_flag=True, help="Access the Github API unauthenticated.")
|
|
144
|
+
@click.option('-list-repos', is_flag=True, type=click.STRING)
|
|
145
|
+
@click.option('-sync', is_flag=True)
|
|
146
|
+
@click.option('-test-auth', is_flag=True, default=False, help="Test GITHUB_AUTH_TOKEN can authenticate.")
|
|
147
|
+
@click.option('-out-repo-list', type=click.Path(), help="File to write clone URLs to.")
|
|
148
|
+
@click.option('-ssh-clone-url',is_flag=True, help="Write SSH clone urls to file instead of HTTPS")
|
|
149
|
+
def github(org, user, no_auth, list_repos, sync, test_auth, out_repo_list,ssh_clone_url):
|
|
150
|
+
"""
|
|
151
|
+
Interact with the GitHub API.
|
|
152
|
+
|
|
153
|
+
For authenticated access, you must set the GITHUB_AUTH_TOKEN environment variable.
|
|
154
|
+
This is a Personal Access Token (PAT) with the necessary permissions.
|
|
155
|
+
|
|
156
|
+
"""
|
|
157
|
+
|
|
158
|
+
gh = KospexGithub()
|
|
159
|
+
repos = []
|
|
160
|
+
|
|
161
|
+
if test_auth:
|
|
162
|
+
|
|
163
|
+
found = gh.get_env_credentials()
|
|
164
|
+
if found:
|
|
165
|
+
print("Found Github GITHUB_AUTH_TOKEN in the environment.")
|
|
166
|
+
else:
|
|
167
|
+
print("Could not find Github GITHUB_AUTH_TOKEN in the environment.")
|
|
168
|
+
print("Please set GITHUB_AUTH_TOKEN.")
|
|
169
|
+
exit(1)
|
|
170
|
+
|
|
171
|
+
if gh.test_auth():
|
|
172
|
+
print("Authentication successful.")
|
|
173
|
+
else:
|
|
174
|
+
print("Authentication failed. Check your GITHUB_AUTH_TOKEN")
|
|
175
|
+
exit(0)
|
|
176
|
+
|
|
177
|
+
if not org and not user:
|
|
178
|
+
print("You must specify either an organization or a user.")
|
|
179
|
+
exit(1)
|
|
180
|
+
|
|
181
|
+
gh.get_env_credentials()
|
|
182
|
+
|
|
183
|
+
auth = False
|
|
184
|
+
if not no_auth:
|
|
185
|
+
gh.get_env_credentials()
|
|
186
|
+
#gh.set_access_token(os.environ.get("GITHUB_PAT"))
|
|
187
|
+
auth = True
|
|
188
|
+
|
|
189
|
+
owner = org or user
|
|
190
|
+
account_type = gh.get_account_type(owner)
|
|
191
|
+
kospex = Kospex()
|
|
192
|
+
|
|
193
|
+
if not account_type:
|
|
194
|
+
print(f"Could not find account type for {owner}.")
|
|
195
|
+
print(f"Most likely {owner} does not exist or has a typo.")
|
|
196
|
+
exit(1)
|
|
197
|
+
|
|
198
|
+
if org:
|
|
199
|
+
repos = gh.get_org_repos(org)
|
|
200
|
+
elif user:
|
|
201
|
+
repos = gh.get_user_repos(user)
|
|
202
|
+
else:
|
|
203
|
+
print("You must specify either an organization or a user.")
|
|
204
|
+
|
|
205
|
+
details = []
|
|
206
|
+
|
|
207
|
+
print(f"\nFinding repos for: {owner} ({account_type})\n")
|
|
208
|
+
|
|
209
|
+
if repos:
|
|
210
|
+
for repo in repos:
|
|
211
|
+
record = {}
|
|
212
|
+
record['name'] = repo.get('name')
|
|
213
|
+
record['fork'] = repo.get('fork')
|
|
214
|
+
record['updated_at'] = repo.get('updated_at')
|
|
215
|
+
record['pushed_at'] = repo.get('pushed_at')
|
|
216
|
+
#if record.get("fork"):
|
|
217
|
+
# full_repo = gh.get_repo(owner=")
|
|
218
|
+
# record['parent'] = repo.get('parent').get('full_name')
|
|
219
|
+
|
|
220
|
+
record['private'] = repo.get('private')
|
|
221
|
+
|
|
222
|
+
if ssh_clone_url:
|
|
223
|
+
# If the boolean is set set the ssh_url instead
|
|
224
|
+
record['clone_url'] = repo.get('ssh_url')
|
|
225
|
+
else:
|
|
226
|
+
record['clone_url'] = repo.get('clone_url')
|
|
227
|
+
print(f"Found repo: {repo['name']}")
|
|
228
|
+
details.append(record)
|
|
229
|
+
|
|
230
|
+
if sync:
|
|
231
|
+
clone_url = repo.get('clone_url')
|
|
232
|
+
repo_path = kgit.clone_repo(clone_url)
|
|
233
|
+
print(f"Syncing repo: {clone_url} in directorty {repo_path}")
|
|
234
|
+
kospex.sync_repo(repo_path)
|
|
235
|
+
|
|
236
|
+
table = PrettyTable()
|
|
237
|
+
table.field_names = ["Name", "fork", "private", "owner", "clone_url", "pushed_at", "status"]
|
|
238
|
+
table.align["Name"] = "l"
|
|
239
|
+
table.align["clone_url"] = "l"
|
|
240
|
+
table.align["status"] = "l"
|
|
241
|
+
|
|
242
|
+
for detail in details:
|
|
243
|
+
#print(detail)
|
|
244
|
+
days_ago = KospexUtils.days_ago(detail.get("pushed_at"))
|
|
245
|
+
status = "Unknown"
|
|
246
|
+
if days_ago:
|
|
247
|
+
status = KospexUtils.development_status(days_ago)
|
|
248
|
+
table.add_row([detail.get("name"), detail.get("fork"),
|
|
249
|
+
detail.get("private"), owner, detail.get("clone_url"),
|
|
250
|
+
detail.get("pushed_at"), status])
|
|
251
|
+
|
|
252
|
+
print(table)
|
|
253
|
+
|
|
254
|
+
# Write out the repo list to a file
|
|
255
|
+
if out_repo_list:
|
|
256
|
+
with open(out_repo_list, "w", encoding='utf-8') as file:
|
|
257
|
+
for detail in details:
|
|
258
|
+
file.write(detail['clone_url'] + "\n")
|
|
259
|
+
|
|
260
|
+
@cli.command("bitbucket")
|
|
261
|
+
@click.option('-workspace', type=click.STRING, help="Workspace to query (Mandatory)")
|
|
262
|
+
#@click.option('-no-auth', is_flag=True, help="Access the Github API unauthenticated.")
|
|
263
|
+
#@click.option('-list-repos', is_flag=True, type=click.STRING)
|
|
264
|
+
#@click.option('-sync', is_flag=True)
|
|
265
|
+
@click.option('-out-repo-list', type=click.Path(), help="File to write clone URLs to.")
|
|
266
|
+
@click.option('-test-auth', is_flag=True, default=False, help="Test BitBucket credentials can authenticate.")
|
|
267
|
+
@click.option('-out-raw', type=click.Path(), help="Output raw JSON results to the specified filename")
|
|
268
|
+
def bitbucket(workspace, out_repo_list, test_auth, out_raw):
|
|
269
|
+
"""
|
|
270
|
+
Interact with the BitBucket API to query repos in a workspace.
|
|
271
|
+
|
|
272
|
+
This command requires the following environment variables to be set:
|
|
273
|
+
BITBUCKET_USERNAME and
|
|
274
|
+
BITBUCKET_APP_PASSWORD
|
|
275
|
+
|
|
276
|
+
The bitbucket username is in the "account settings" section of your bitbucket account.
|
|
277
|
+
This is NOT your email address.
|
|
278
|
+
|
|
279
|
+
"""
|
|
280
|
+
|
|
281
|
+
bb = KospexBitbucket()
|
|
282
|
+
click.echo()
|
|
283
|
+
if bb.get_env_credentials():
|
|
284
|
+
print("Found bitbucket credentials in the environment.")
|
|
285
|
+
else:
|
|
286
|
+
print("Could not find bitbucket credentials in the environment.")
|
|
287
|
+
print("Please set BITBUCKET_USERNAME and BITBUCKET_APP_PASSWORD.\n")
|
|
288
|
+
exit(1)
|
|
289
|
+
|
|
290
|
+
if test_auth:
|
|
291
|
+
if bb.test_auth():
|
|
292
|
+
print("Authentication successful.\n")
|
|
293
|
+
else:
|
|
294
|
+
print("\nAuthentication FAILED!.",
|
|
295
|
+
"\nCheck your BITBUCKET_USERNAME and BITBUCKET_APP_PASSWORD\n")
|
|
296
|
+
exit(0)
|
|
297
|
+
|
|
298
|
+
if not workspace:
|
|
299
|
+
print("\nERROR: You MUST specify a workspace.\n")
|
|
300
|
+
exit(1)
|
|
301
|
+
|
|
302
|
+
table = PrettyTable()
|
|
303
|
+
table.field_names = ["Name", "clone_url", "is_private"]
|
|
304
|
+
table.align["Name"] = "l"
|
|
305
|
+
table.align["clone_url"] = "l"
|
|
306
|
+
table.align["is_private"] = "c"
|
|
307
|
+
|
|
308
|
+
repos = bb.get_repos(workspace)
|
|
309
|
+
|
|
310
|
+
# TODO - provide an option to write this table to a CSV
|
|
311
|
+
# TODO - add extra metadata like created, last updated and repo status
|
|
312
|
+
for r in repos:
|
|
313
|
+
#print(r.get("full_name"), bb.get_https_clone_url(r))
|
|
314
|
+
table.add_row([r.get("slug"), bb.get_https_clone_url(r), r.get("is_private")])
|
|
315
|
+
|
|
316
|
+
print(table)
|
|
317
|
+
|
|
318
|
+
if out_repo_list:
|
|
319
|
+
with open(out_repo_list, "w", encoding='utf-8') as file:
|
|
320
|
+
for r in repos:
|
|
321
|
+
file.write(bb.get_https_clone_url(r) + "\n")
|
|
322
|
+
|
|
323
|
+
if out_raw:
|
|
324
|
+
with open(out_raw, "w", encoding='utf-8') as raw_file:
|
|
325
|
+
raw_file.write(json.dumps(repos))
|
|
326
|
+
|
|
327
|
+
|
|
328
|
+
if __name__ == '__main__':
|
|
329
|
+
cli()
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2023 Peter Freiberg
|
|
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.
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
|
+
Name: kospex
|
|
3
|
+
Version: 0.0.14
|
|
4
|
+
Summary: The kospex CLI tool.
|
|
5
|
+
Author-email: Peter Freiberg <peter.freiberg@gmail.com>
|
|
6
|
+
License: MIT License
|
|
7
|
+
|
|
8
|
+
Copyright (c) 2023 Peter Freiberg
|
|
9
|
+
|
|
10
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
11
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
12
|
+
in the Software without restriction, including without limitation the rights
|
|
13
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
14
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
15
|
+
furnished to do so, subject to the following conditions:
|
|
16
|
+
|
|
17
|
+
The above copyright notice and this permission notice shall be included in all
|
|
18
|
+
copies or substantial portions of the Software.
|
|
19
|
+
|
|
20
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
21
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
22
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
23
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
24
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
25
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
26
|
+
SOFTWARE.
|
|
27
|
+
|
|
28
|
+
Project-URL: Homepage, https://kospex.io
|
|
29
|
+
Project-URL: Issues, https://github.com/kospex/kospex/issues
|
|
30
|
+
Project-URL: Repository, https://github.com/kospex/kospex
|
|
31
|
+
Keywords: analytics,git,code analytics,predictive maintenance
|
|
32
|
+
Requires-Python: >=3.11
|
|
33
|
+
Description-Content-Type: text/markdown
|
|
34
|
+
License-File: LICENSE
|
|
35
|
+
Requires-Dist: Click
|
|
36
|
+
Requires-Dist: flask
|
|
37
|
+
Requires-Dist: prettytable
|
|
38
|
+
Requires-Dist: dateutils
|
|
39
|
+
Requires-Dist: panopticas
|
|
40
|
+
Requires-Dist: python-dotenv
|
|
41
|
+
Requires-Dist: sqlite_utils
|
|
42
|
+
Requires-Dist: requests
|
|
43
|
+
Requires-Dist: PyYAML
|
|
44
|
+
|
|
45
|
+
# kospex
|
|
46
|
+
|
|
47
|
+
Kospex is a CLI which aims to _"look at the guts of your code"_ to help gain insights into your developers and technology landscape.
|
|
48
|
+
It uses database structure from the excellent [Mergestat lite](https://github.com/mergestat/mergestat-lite) to model data from git repositories.
|
|
49
|
+
|
|
50
|
+
For details on changes, see the [changelog](https://github.com/kospex/kospex/blob/main/CHANGELOG.md)
|
|
51
|
+
|
|
52
|
+
## Installation, setup and usage
|
|
53
|
+
|
|
54
|
+
See the official [installation documentation](https://kospex.io/getting-started)
|
|
55
|
+
|
|
56
|
+
## What is a kospex?
|
|
57
|
+
|
|
58
|
+
We're aiming to [k]now your c[o]de by in[spe]cting the haruspe[x].
|
|
59
|
+
From Wikipedia, _The Latin terms haruspex and haruspicina are from an archaic word, hīra = "entrails, intestines"_
|
|
60
|
+
|
|
61
|
+
So we're going to help look at the "guts of your code" to gain an understanding of the applications, technology landscape (sprawl?) and developers.
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
kgit.py,sha256=229F3X9KAMfqEgfQVcaQogTmXm2nHSBaXFINDG9psVY,11177
|
|
2
|
+
kospex.py,sha256=kb194MtcrgY0xDoyxFzYuE_cNvKghgzKglUrpTRv7Sw,34501
|
|
3
|
+
kospex_bitbucket.py,sha256=vZc7J7kvrIQrDkNSpNcyEXVrunq9oEA5xKmvKYB8kao,2720
|
|
4
|
+
kospex_core.py,sha256=H5yWX2MpEj_sibWEdnU95DeTUgfaQrPc5Cg-7OgM2Wo,43125
|
|
5
|
+
kospex_dependencies.py,sha256=P-FY56oAUtNS0sTs-e-baM-RBO-mBokxsH6FhTOa-xs,35367
|
|
6
|
+
kospex_git.py,sha256=rvp_WGV2K566_yQLUzUTTK5BZYKcXI2PzWAQHibTBbk,12465
|
|
7
|
+
kospex_github.py,sha256=zQDVc2I8WQFY3YyfeyR7Q2NRqTbd8MGLe2PTcPUGX4s,6380
|
|
8
|
+
kospex_mergestat.py,sha256=dcTVb6s9UhTbdEKp4X2QafnAUpmrKFdAdT18uWxdWkw,6038
|
|
9
|
+
kospex_query.py,sha256=5NhI1cgqh1jEUVwsp-vQdKbUOUu6A2fzgxhUrYm5_hg,54435
|
|
10
|
+
kospex_schema.py,sha256=lUp2FvFrJPaUEgucI71F6isdx-ZwqySi__PsM8BVpMU,14569
|
|
11
|
+
kospex_utils.py,sha256=wiYuJvbXya9cUrB55WHVd34FBnTMLWX9I9baIps08M8,40235
|
|
12
|
+
kospex_web.py,sha256=kxRHzBa8_Fj2VH-tQ4qWhc60I-BV_vGCT1gxN5pa9iY,1831
|
|
13
|
+
kreaper.py,sha256=D-vmJUyqTLlOG-BXm7OVt09TGG8iZUSJ4x4u8V7b6YE,2506
|
|
14
|
+
krunner.py,sha256=jKmKVSomfzXtRstdV45B0vH9dwDW9Ys9-GFN-vOzexY,12354
|
|
15
|
+
krunner_utils.py,sha256=xqOL-RMRkkkjpU_TuP79Rhj1WXyB1D8Wj7bvrkZw0Zc,8530
|
|
16
|
+
kwatch.py,sha256=Ax9zvO_G9iosNF83g-5RYi8I1fpaW67cT2hzz2fsh9E,646
|
|
17
|
+
kweb.py,sha256=WRn4HOfsIOySlodHAUp4p96x6O7DCbGkFK09CuIh86k,24368
|
|
18
|
+
templates/404.html,sha256=IWqaVQXncJeQjb8fPIR1GO5GFn0ky6EmxdXxiPYLA4o,783
|
|
19
|
+
templates/_bootstrap_html_head.html,sha256=JMmE26b2akc7oan_M_54VVo0uFEaqHWOcW3E92npQnA,289
|
|
20
|
+
templates/_datatable_scripts.html,sha256=GxN_rPZIjx6oiOhfW5xE3fqdWUU9u2DOGbIMOIp80oc,215
|
|
21
|
+
templates/_footer_scripts.html,sha256=wG-wPHlpf_LgvSGbt-IgD3nXChdT4haOoRMEfEBePq4,233
|
|
22
|
+
templates/_id_header_macro.html,sha256=BJ2unCmTmGEOr8pWQzZtDDbVUoTRmnMOun0pPACBun0,220
|
|
23
|
+
templates/_radar_macro.html,sha256=W1NWyerB9Tcl3gjC5QRJ-ZLsacM6qif78gZFg5iaYls,1316
|
|
24
|
+
templates/_single_radar.html,sha256=D0uSF4Pb7keh04UaJGIEfyGYq9H-CromsKfrHaqa-DI,1193
|
|
25
|
+
templates/bubble.html,sha256=_VAHF3qWqZRa2Pj4HLTgsThLG2AyAsk531TeIsYXDPc,23086
|
|
26
|
+
templates/commits.html,sha256=7NG8BNTv_96sd83l1LAcG8jMQaXvzKU7jepaNyiNy7k,1499
|
|
27
|
+
templates/developer_view.html,sha256=qiE3M4jedhxsnaJNT_fiwbAXidlPmfpI4XbbNiym1sY,2445
|
|
28
|
+
templates/developers.html,sha256=5eqc6mrd9SzLpHYqtMwin9HDbtPCcBARON5a1CCy_cU,2520
|
|
29
|
+
templates/graph.html,sha256=DbiJhc2I1jCEANIXkqkFbWBObSbxuGt_12MaijnR308,23860
|
|
30
|
+
templates/graph2.html,sha256=0Tc9RttCwM8vgDou-6RXSRfoa-hFiXEVlKuhxvGABOI,25604
|
|
31
|
+
templates/header.html,sha256=QjolaPeJuJFXT1iQj522DOAKMQug93wN67iNuS2ncnk,1120
|
|
32
|
+
templates/hotspots.html,sha256=L2OH3mZE5ckRieqwEzhOyfkkckJL_IdmQIDGBjDgspg,1403
|
|
33
|
+
templates/landscape.html,sha256=57liFllc2zW2YtnL2no3ynEPizyECkYqEOy1e-seQTY,3124
|
|
34
|
+
templates/meta-author-domains.html,sha256=rG3ULaoP6S3NuW16JeS3_qaq0cvmuEg1qQL8FyC2crA,1324
|
|
35
|
+
templates/metadata.html,sha256=-JazS-tXXNtCe39Tbs8Mr3afvqUk2rb8_bB81lG4y3c,3601
|
|
36
|
+
templates/observations.html,sha256=pXV1ct8LY4EIHuyYGTGzV7fgqOWvAKwhQOZbOfMTM-U,1177
|
|
37
|
+
templates/observations_repo.html,sha256=zJllC1r4A4RNYQ3Z7b1gAL_QYZ1o_BEXGo0qgVH5Itg,1264
|
|
38
|
+
templates/observations_repo_key.html,sha256=k8scGlpByrBpAYWJcggvS9U4EPBYjKxEzm9zcwJPbbo,1200
|
|
39
|
+
templates/orgs.html,sha256=HDGjGOzd3vppMmH5CxArmMrJ1SByHYQ75-yXH1QkD5Y,2343
|
|
40
|
+
templates/osi.html,sha256=PHtkBN58nWsCVF_r3Y8H4c7b4wBmptDMliBgWnM7JNw,520
|
|
41
|
+
templates/repo_files.html,sha256=0uF6AX_6dJBdZFtC2bbAK3QtL-wiXnMwhrbx72CJg-Y,1335
|
|
42
|
+
templates/repo_view.html,sha256=QbJHqTAzlyx02USA88ovTtdbxqZGvduZqnWv5gXN7uY,4127
|
|
43
|
+
templates/repos.html,sha256=8e5sTPt7fFj08zrGA4A7AjBb3JWcJpA75TDalJHb7So,4691
|
|
44
|
+
templates/servers.html,sha256=eG0rRNBgQbKt8FysaLeC-ETx_vkoFthrciEIiQ9hBX4,1749
|
|
45
|
+
templates/summary.html,sha256=XpkjCaPAcC2kOfBZzdDy3ZuSFeEyaM8UU99l-sYNDFc,8577
|
|
46
|
+
templates/tech-change.html,sha256=B3d8TMilsDb7kUIOmrAwDIMR4FzfsdDFR5A299fe158,2201
|
|
47
|
+
templates/treemap.html,sha256=R4PhbwLJBIlOMdRC_Nr5_6asG0ye_jS4degxLqszkK4,23770
|
|
48
|
+
kospex-0.0.14.dist-info/LICENSE,sha256=vd-xuOrW1JSPudp9cHxM66rJXGEYTMOihjpKvafBiQU,1071
|
|
49
|
+
kospex-0.0.14.dist-info/METADATA,sha256=TP2Od0ah8YtDgZEdQKjojS9WlKtUU2X8ZB7LHeKZOUs,2780
|
|
50
|
+
kospex-0.0.14.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
|
|
51
|
+
kospex-0.0.14.dist-info/entry_points.txt,sha256=NVl5Sr-L2m1VS_7xdNGcqxplM0VrTK3d63zXfSB6fcI,135
|
|
52
|
+
kospex-0.0.14.dist-info/top_level.txt,sha256=6ooM3xXHoWPqgNiNFDqFyO7JWRdu0Y9fGTHY_xDzqMw,206
|
|
53
|
+
kospex-0.0.14.dist-info/RECORD,,
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
kgit
|
|
2
|
+
kospex
|
|
3
|
+
kospex_bitbucket
|
|
4
|
+
kospex_core
|
|
5
|
+
kospex_dependencies
|
|
6
|
+
kospex_git
|
|
7
|
+
kospex_github
|
|
8
|
+
kospex_mergestat
|
|
9
|
+
kospex_query
|
|
10
|
+
kospex_schema
|
|
11
|
+
kospex_utils
|
|
12
|
+
kospex_web
|
|
13
|
+
kreaper
|
|
14
|
+
krunner
|
|
15
|
+
krunner_utils
|
|
16
|
+
kwatch
|
|
17
|
+
kweb
|
|
18
|
+
templates
|