github-to-sqlite 2.8.3__tar.gz → 2.9.1__tar.gz
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.
- {github-to-sqlite-2.8.3/github_to_sqlite.egg-info → github_to_sqlite-2.9.1}/PKG-INFO +29 -14
- github-to-sqlite-2.8.3/PKG-INFO → github_to_sqlite-2.9.1/README.md +17 -19
- {github-to-sqlite-2.8.3 → github_to_sqlite-2.9.1}/github_to_sqlite/cli.py +46 -8
- {github-to-sqlite-2.8.3 → github_to_sqlite-2.9.1}/github_to_sqlite/utils.py +44 -15
- github_to_sqlite-2.9.1/pyproject.toml +39 -0
- github_to_sqlite-2.9.1/pyproject.toml.orig +37 -0
- github-to-sqlite-2.8.3/README.md +0 -248
- github-to-sqlite-2.8.3/github_to_sqlite.egg-info/SOURCES.txt +0 -12
- github-to-sqlite-2.8.3/github_to_sqlite.egg-info/dependency_links.txt +0 -1
- github-to-sqlite-2.8.3/github_to_sqlite.egg-info/entry_points.txt +0 -4
- github-to-sqlite-2.8.3/github_to_sqlite.egg-info/requires.txt +0 -8
- github-to-sqlite-2.8.3/github_to_sqlite.egg-info/top_level.txt +0 -1
- github-to-sqlite-2.8.3/setup.cfg +0 -4
- github-to-sqlite-2.8.3/setup.py +0 -32
- {github-to-sqlite-2.8.3 → github_to_sqlite-2.9.1}/LICENSE +0 -0
- {github-to-sqlite-2.8.3 → github_to_sqlite-2.9.1}/github_to_sqlite/__init__.py +0 -0
|
@@ -1,14 +1,19 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: github-to-sqlite
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.9.1
|
|
4
4
|
Summary: Save data from GitHub to a SQLite database
|
|
5
|
-
Home-page: https://github.com/dogsheep/github-to-sqlite
|
|
6
5
|
Author: Simon Willison
|
|
7
|
-
License: Apache
|
|
8
|
-
Platform: UNKNOWN
|
|
9
|
-
Description-Content-Type: text/markdown
|
|
10
|
-
Provides-Extra: test
|
|
6
|
+
License-Expression: Apache-2.0
|
|
11
7
|
License-File: LICENSE
|
|
8
|
+
Requires-Dist: sqlite-utils>4
|
|
9
|
+
Requires-Dist: requests
|
|
10
|
+
Requires-Dist: pyyaml
|
|
11
|
+
Requires-Python: >=3.10
|
|
12
|
+
Project-URL: Homepage, https://github.com/dogsheep/github-to-sqlite
|
|
13
|
+
Project-URL: Changelog, https://github.com/dogsheep/github-to-sqlite/releases
|
|
14
|
+
Project-URL: Issues, https://github.com/dogsheep/github-to-sqlite/issues
|
|
15
|
+
Project-URL: CI, https://github.com/dogsheep/github-to-sqlite/actions
|
|
16
|
+
Description-Content-Type: text/markdown
|
|
12
17
|
|
|
13
18
|
# github-to-sqlite
|
|
14
19
|
|
|
@@ -94,13 +99,25 @@ You can use the `--pull-request` option one or more times to load specific pull
|
|
|
94
99
|
|
|
95
100
|
Note that the `merged_by` column on the `pull_requests` table will only be populated for pull requests that are loaded using the `--pull-request` option - the GitHub API does not return this field for pull requests that are loaded in bulk.
|
|
96
101
|
|
|
102
|
+
You can load only pull requests in a certain state with the `--state` option:
|
|
103
|
+
|
|
104
|
+
$ github-to-sqlite pull-requests --state=open github.db simonw/datasette
|
|
105
|
+
|
|
106
|
+
Pull requests across an entire organization (or more than one) can be loaded with `--org`:
|
|
107
|
+
|
|
108
|
+
$ github-to-sqlite pull-requests --state=open --org=psf --org=python github.db
|
|
109
|
+
|
|
110
|
+
You can use a search query to find pull requests. Note that no more than 1000 will be loaded (this is a GitHub API limitation), and some data will be missing (base and head SHAs). When using searches, other filters are ignored; put all criteria into the search itself:
|
|
111
|
+
|
|
112
|
+
$ github-to-sqlite pull-requests --search='org:python defaultdict state:closed created:<2023-09-01' github.db
|
|
113
|
+
|
|
97
114
|
Example: [pull_requests table](https://github-to-sqlite.dogsheep.net/github/pull_requests)
|
|
98
115
|
|
|
99
116
|
## Fetching issue comments for a repository
|
|
100
117
|
|
|
101
118
|
The `issue-comments` command retrieves all of the comments on all of the issues in a repository.
|
|
102
119
|
|
|
103
|
-
It is recommended you run `issues` first, so that each imported comment can have a foreign key
|
|
120
|
+
It is recommended you run `issues` first, so that each imported comment can have a foreign key pointing to its issue.
|
|
104
121
|
|
|
105
122
|
$ github-to-sqlite issues github.db simonw/datasette
|
|
106
123
|
$ github-to-sqlite issue-comments github.db simonw/datasette
|
|
@@ -113,7 +130,7 @@ Example: [issue_comments table](https://github-to-sqlite.dogsheep.net/github/iss
|
|
|
113
130
|
|
|
114
131
|
## Fetching commits for a repository
|
|
115
132
|
|
|
116
|
-
The `commits` command retrieves details of all of the commits for one or more repositories. It currently fetches the
|
|
133
|
+
The `commits` command retrieves details of all of the commits for one or more repositories. It currently fetches the SHA, commit message and author and committer details; it does not retrieve the full commit body.
|
|
117
134
|
|
|
118
135
|
$ github-to-sqlite commits github.db simonw/datasette simonw/sqlite-utils
|
|
119
136
|
|
|
@@ -168,7 +185,7 @@ You can pass more than one username to fetch for multiple users or organizations
|
|
|
168
185
|
|
|
169
186
|
$ github-to-sqlite repos github.db simonw dogsheep
|
|
170
187
|
|
|
171
|
-
Add the `--readme` option to save the README for the repo in a column called `readme`. Add `--readme-html` to save the HTML rendered version of the README into a
|
|
188
|
+
Add the `--readme` option to save the README for the repo in a column called `readme`. Add `--readme-html` to save the HTML rendered version of the README into a column called `readme_html`.
|
|
172
189
|
|
|
173
190
|
Example: [repos table](https://github-to-sqlite.dogsheep.net/github/repos)
|
|
174
191
|
|
|
@@ -228,7 +245,7 @@ You can fetch a list of every emoji supported by GitHub using the `emojis` comma
|
|
|
228
245
|
|
|
229
246
|
$ github-to-sqlite emojis github.db
|
|
230
247
|
|
|
231
|
-
This will create a table
|
|
248
|
+
This will create a table called `emojis` with a primary key `name` and a `url` column.
|
|
232
249
|
|
|
233
250
|
If you add the `--fetch` option the command will also fetch the binary content of the images and place them in an `image` column:
|
|
234
251
|
|
|
@@ -247,7 +264,7 @@ The `github-to-sqlite get` command provides a convenient shortcut for making aut
|
|
|
247
264
|
|
|
248
265
|
This will make an authenticated call to the URL you provide and pretty-print the resulting JSON to the console.
|
|
249
266
|
|
|
250
|
-
You can
|
|
267
|
+
You can omit the `https://api.github.com/` prefix, for example:
|
|
251
268
|
|
|
252
269
|
$ github-to-sqlite get /gists
|
|
253
270
|
|
|
@@ -258,5 +275,3 @@ Many GitHub APIs are [paginated using the HTTP Link header](https://docs.github.
|
|
|
258
275
|
You can outline newline-delimited JSON for each item using `--nl`. This can be useful for streaming items into another tool.
|
|
259
276
|
|
|
260
277
|
$ github-to-sqlite get /users/simonw/repos --nl
|
|
261
|
-
|
|
262
|
-
|
|
@@ -1,15 +1,3 @@
|
|
|
1
|
-
Metadata-Version: 2.1
|
|
2
|
-
Name: github-to-sqlite
|
|
3
|
-
Version: 2.8.3
|
|
4
|
-
Summary: Save data from GitHub to a SQLite database
|
|
5
|
-
Home-page: https://github.com/dogsheep/github-to-sqlite
|
|
6
|
-
Author: Simon Willison
|
|
7
|
-
License: Apache License, Version 2.0
|
|
8
|
-
Platform: UNKNOWN
|
|
9
|
-
Description-Content-Type: text/markdown
|
|
10
|
-
Provides-Extra: test
|
|
11
|
-
License-File: LICENSE
|
|
12
|
-
|
|
13
1
|
# github-to-sqlite
|
|
14
2
|
|
|
15
3
|
[](https://pypi.org/project/github-to-sqlite/)
|
|
@@ -94,13 +82,25 @@ You can use the `--pull-request` option one or more times to load specific pull
|
|
|
94
82
|
|
|
95
83
|
Note that the `merged_by` column on the `pull_requests` table will only be populated for pull requests that are loaded using the `--pull-request` option - the GitHub API does not return this field for pull requests that are loaded in bulk.
|
|
96
84
|
|
|
85
|
+
You can load only pull requests in a certain state with the `--state` option:
|
|
86
|
+
|
|
87
|
+
$ github-to-sqlite pull-requests --state=open github.db simonw/datasette
|
|
88
|
+
|
|
89
|
+
Pull requests across an entire organization (or more than one) can be loaded with `--org`:
|
|
90
|
+
|
|
91
|
+
$ github-to-sqlite pull-requests --state=open --org=psf --org=python github.db
|
|
92
|
+
|
|
93
|
+
You can use a search query to find pull requests. Note that no more than 1000 will be loaded (this is a GitHub API limitation), and some data will be missing (base and head SHAs). When using searches, other filters are ignored; put all criteria into the search itself:
|
|
94
|
+
|
|
95
|
+
$ github-to-sqlite pull-requests --search='org:python defaultdict state:closed created:<2023-09-01' github.db
|
|
96
|
+
|
|
97
97
|
Example: [pull_requests table](https://github-to-sqlite.dogsheep.net/github/pull_requests)
|
|
98
98
|
|
|
99
99
|
## Fetching issue comments for a repository
|
|
100
100
|
|
|
101
101
|
The `issue-comments` command retrieves all of the comments on all of the issues in a repository.
|
|
102
102
|
|
|
103
|
-
It is recommended you run `issues` first, so that each imported comment can have a foreign key
|
|
103
|
+
It is recommended you run `issues` first, so that each imported comment can have a foreign key pointing to its issue.
|
|
104
104
|
|
|
105
105
|
$ github-to-sqlite issues github.db simonw/datasette
|
|
106
106
|
$ github-to-sqlite issue-comments github.db simonw/datasette
|
|
@@ -113,7 +113,7 @@ Example: [issue_comments table](https://github-to-sqlite.dogsheep.net/github/iss
|
|
|
113
113
|
|
|
114
114
|
## Fetching commits for a repository
|
|
115
115
|
|
|
116
|
-
The `commits` command retrieves details of all of the commits for one or more repositories. It currently fetches the
|
|
116
|
+
The `commits` command retrieves details of all of the commits for one or more repositories. It currently fetches the SHA, commit message and author and committer details; it does not retrieve the full commit body.
|
|
117
117
|
|
|
118
118
|
$ github-to-sqlite commits github.db simonw/datasette simonw/sqlite-utils
|
|
119
119
|
|
|
@@ -168,7 +168,7 @@ You can pass more than one username to fetch for multiple users or organizations
|
|
|
168
168
|
|
|
169
169
|
$ github-to-sqlite repos github.db simonw dogsheep
|
|
170
170
|
|
|
171
|
-
Add the `--readme` option to save the README for the repo in a column called `readme`. Add `--readme-html` to save the HTML rendered version of the README into a
|
|
171
|
+
Add the `--readme` option to save the README for the repo in a column called `readme`. Add `--readme-html` to save the HTML rendered version of the README into a column called `readme_html`.
|
|
172
172
|
|
|
173
173
|
Example: [repos table](https://github-to-sqlite.dogsheep.net/github/repos)
|
|
174
174
|
|
|
@@ -228,7 +228,7 @@ You can fetch a list of every emoji supported by GitHub using the `emojis` comma
|
|
|
228
228
|
|
|
229
229
|
$ github-to-sqlite emojis github.db
|
|
230
230
|
|
|
231
|
-
This will create a table
|
|
231
|
+
This will create a table called `emojis` with a primary key `name` and a `url` column.
|
|
232
232
|
|
|
233
233
|
If you add the `--fetch` option the command will also fetch the binary content of the images and place them in an `image` column:
|
|
234
234
|
|
|
@@ -247,7 +247,7 @@ The `github-to-sqlite get` command provides a convenient shortcut for making aut
|
|
|
247
247
|
|
|
248
248
|
This will make an authenticated call to the URL you provide and pretty-print the resulting JSON to the console.
|
|
249
249
|
|
|
250
|
-
You can
|
|
250
|
+
You can omit the `https://api.github.com/` prefix, for example:
|
|
251
251
|
|
|
252
252
|
$ github-to-sqlite get /gists
|
|
253
253
|
|
|
@@ -258,5 +258,3 @@ Many GitHub APIs are [paginated using the HTTP Link header](https://docs.github.
|
|
|
258
258
|
You can outline newline-delimited JSON for each item using `--nl`. This can be useful for streaming items into another tool.
|
|
259
259
|
|
|
260
260
|
$ github-to-sqlite get /users/simonw/repos --nl
|
|
261
|
-
|
|
262
|
-
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import click
|
|
2
2
|
import datetime
|
|
3
|
+
import itertools
|
|
3
4
|
import pathlib
|
|
4
5
|
import textwrap
|
|
5
6
|
import os
|
|
@@ -104,19 +105,54 @@ def issues(db_path, repo, issue_ids, auth, load):
|
|
|
104
105
|
type=click.Path(file_okay=True, dir_okay=False, allow_dash=True, exists=True),
|
|
105
106
|
help="Load pull-requests JSON from this file instead of the API",
|
|
106
107
|
)
|
|
107
|
-
|
|
108
|
+
@click.option(
|
|
109
|
+
"--org",
|
|
110
|
+
"orgs",
|
|
111
|
+
help="Fetch all pull requests from this GitHub organization",
|
|
112
|
+
multiple=True,
|
|
113
|
+
)
|
|
114
|
+
@click.option(
|
|
115
|
+
"--state",
|
|
116
|
+
help="Only fetch pull requests in this state",
|
|
117
|
+
)
|
|
118
|
+
@click.option(
|
|
119
|
+
"--search",
|
|
120
|
+
help="Find pull requests with a search query",
|
|
121
|
+
)
|
|
122
|
+
def pull_requests(db_path, repo, pull_request_ids, auth, load, orgs, state, search):
|
|
108
123
|
"Save pull_requests for a specified repository, e.g. simonw/datasette"
|
|
109
124
|
db = sqlite_utils.Database(db_path)
|
|
110
125
|
token = load_token(auth)
|
|
111
|
-
repo_full = utils.fetch_repo(repo, token)
|
|
112
|
-
utils.save_repo(db, repo_full)
|
|
113
126
|
if load:
|
|
127
|
+
repo_full = utils.fetch_repo(repo, token)
|
|
128
|
+
utils.save_repo(db, repo_full)
|
|
114
129
|
pull_requests = json.load(open(load))
|
|
130
|
+
utils.save_pull_requests(db, pull_requests, repo_full)
|
|
131
|
+
elif search:
|
|
132
|
+
repos_seen = set()
|
|
133
|
+
search += " is:pr"
|
|
134
|
+
pull_requests = utils.fetch_searched_pulls_or_issues(search, token)
|
|
135
|
+
for pull_request in pull_requests:
|
|
136
|
+
pr_repo_url = pull_request["repository_url"]
|
|
137
|
+
if pr_repo_url not in repos_seen:
|
|
138
|
+
pr_repo = utils.fetch_repo(url=pr_repo_url)
|
|
139
|
+
utils.save_repo(db, pr_repo)
|
|
140
|
+
repos_seen.add(pr_repo_url)
|
|
141
|
+
utils.save_pull_requests(db, [pull_request], pr_repo)
|
|
115
142
|
else:
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
143
|
+
if orgs:
|
|
144
|
+
repos = itertools.chain.from_iterable(
|
|
145
|
+
utils.fetch_all_repos(token=token, org=org) for org in orgs
|
|
146
|
+
)
|
|
147
|
+
else:
|
|
148
|
+
repos = [utils.fetch_repo(repo, token)]
|
|
149
|
+
for repo_full in repos:
|
|
150
|
+
utils.save_repo(db, repo_full)
|
|
151
|
+
repo = repo_full["full_name"]
|
|
152
|
+
pull_requests = utils.fetch_pull_requests(
|
|
153
|
+
repo, state, token, pull_request_ids
|
|
154
|
+
)
|
|
155
|
+
utils.save_pull_requests(db, pull_requests, repo_full)
|
|
120
156
|
utils.ensure_db_shape(db)
|
|
121
157
|
|
|
122
158
|
|
|
@@ -464,7 +500,9 @@ def scrape_dependents(db_path, repos, auth, verbose):
|
|
|
464
500
|
{
|
|
465
501
|
"repo": repo_full["id"],
|
|
466
502
|
"dependent": dependent_id,
|
|
467
|
-
"first_seen_utc": datetime.datetime.
|
|
503
|
+
"first_seen_utc": datetime.datetime.now(datetime.timezone.utc)
|
|
504
|
+
.replace(tzinfo=None)
|
|
505
|
+
.isoformat(),
|
|
468
506
|
},
|
|
469
507
|
pk=("repo", "dependent"),
|
|
470
508
|
foreign_keys=(
|
|
@@ -2,6 +2,7 @@ import base64
|
|
|
2
2
|
import requests
|
|
3
3
|
import re
|
|
4
4
|
import time
|
|
5
|
+
import urllib.parse
|
|
5
6
|
import yaml
|
|
6
7
|
|
|
7
8
|
FTS_CONFIG = {
|
|
@@ -74,16 +75,17 @@ FOREIGN_KEYS = [
|
|
|
74
75
|
|
|
75
76
|
|
|
76
77
|
class GitHubError(Exception):
|
|
77
|
-
def __init__(self, message, status_code):
|
|
78
|
+
def __init__(self, message, status_code, headers=None):
|
|
78
79
|
self.message = message
|
|
79
80
|
self.status_code = status_code
|
|
81
|
+
self.headers = headers
|
|
80
82
|
|
|
81
83
|
@classmethod
|
|
82
84
|
def from_response(cls, response):
|
|
83
85
|
message = response.json()["message"]
|
|
84
86
|
if "git repository is empty" in message.lower():
|
|
85
87
|
cls = GitHubRepositoryEmpty
|
|
86
|
-
return cls(message, response.status_code)
|
|
88
|
+
return cls(message, response.status_code, response.headers)
|
|
87
89
|
|
|
88
90
|
|
|
89
91
|
class GitHubRepositoryEmpty(GitHubError):
|
|
@@ -169,8 +171,11 @@ def save_pull_requests(db, pull_requests, repo):
|
|
|
169
171
|
# Add repo key
|
|
170
172
|
pull_request["repo"] = repo["id"]
|
|
171
173
|
# Pull request _links can be flattened to just their URL
|
|
172
|
-
|
|
173
|
-
|
|
174
|
+
if "_links" in pull_request:
|
|
175
|
+
pull_request["url"] = pull_request["_links"]["html"]["href"]
|
|
176
|
+
pull_request.pop("_links")
|
|
177
|
+
else:
|
|
178
|
+
pull_request["url"] = pull_request["pull_request"]["html_url"]
|
|
174
179
|
# Extract user
|
|
175
180
|
pull_request["user"] = save_user(db, pull_request["user"])
|
|
176
181
|
labels = pull_request.pop("labels")
|
|
@@ -178,8 +183,9 @@ def save_pull_requests(db, pull_requests, repo):
|
|
|
178
183
|
if pull_request.get("merged_by"):
|
|
179
184
|
pull_request["merged_by"] = save_user(db, pull_request["merged_by"])
|
|
180
185
|
# Head sha
|
|
181
|
-
|
|
182
|
-
|
|
186
|
+
if "head" in pull_request:
|
|
187
|
+
pull_request["head"] = pull_request["head"]["sha"]
|
|
188
|
+
pull_request["base"] = pull_request["base"]["sha"]
|
|
183
189
|
# Extract milestone
|
|
184
190
|
if pull_request["milestone"]:
|
|
185
191
|
pull_request["milestone"] = save_milestone(
|
|
@@ -223,6 +229,11 @@ def save_pull_requests(db, pull_requests, repo):
|
|
|
223
229
|
|
|
224
230
|
|
|
225
231
|
def save_user(db, user):
|
|
232
|
+
# Under some conditions, GitHub caches removed repositories with
|
|
233
|
+
# stars and ends up leaving dangling `None` user references.
|
|
234
|
+
if user is None:
|
|
235
|
+
return None
|
|
236
|
+
|
|
226
237
|
# Remove all url fields except avatar_url and html_url
|
|
227
238
|
to_save = {
|
|
228
239
|
key: value
|
|
@@ -286,12 +297,13 @@ def save_issue_comment(db, comment):
|
|
|
286
297
|
return last_pk
|
|
287
298
|
|
|
288
299
|
|
|
289
|
-
def fetch_repo(full_name, token=None):
|
|
300
|
+
def fetch_repo(full_name=None, token=None, url=None):
|
|
290
301
|
headers = make_headers(token)
|
|
291
302
|
# Get topics:
|
|
292
303
|
headers["Accept"] = "application/vnd.github.mercy-preview+json"
|
|
293
|
-
|
|
294
|
-
|
|
304
|
+
if url is None:
|
|
305
|
+
owner, slug = full_name.split("/")
|
|
306
|
+
url = "https://api.github.com/repos/{}/{}".format(owner, slug)
|
|
295
307
|
response = requests.get(url, headers=headers)
|
|
296
308
|
response.raise_for_status()
|
|
297
309
|
return response.json()
|
|
@@ -352,7 +364,7 @@ def fetch_issues(repo, token=None, issue_ids=None):
|
|
|
352
364
|
yield from issues
|
|
353
365
|
|
|
354
366
|
|
|
355
|
-
def fetch_pull_requests(repo, token=None, pull_request_ids=None):
|
|
367
|
+
def fetch_pull_requests(repo, state=None, token=None, pull_request_ids=None):
|
|
356
368
|
headers = make_headers(token)
|
|
357
369
|
headers["accept"] = "application/vnd.github.v3+json"
|
|
358
370
|
if pull_request_ids:
|
|
@@ -364,11 +376,20 @@ def fetch_pull_requests(repo, token=None, pull_request_ids=None):
|
|
|
364
376
|
response.raise_for_status()
|
|
365
377
|
yield response.json()
|
|
366
378
|
else:
|
|
367
|
-
|
|
379
|
+
state = state or "all"
|
|
380
|
+
url = f"https://api.github.com/repos/{repo}/pulls?state={state}"
|
|
368
381
|
for pull_requests in paginate(url, headers):
|
|
369
382
|
yield from pull_requests
|
|
370
383
|
|
|
371
384
|
|
|
385
|
+
def fetch_searched_pulls_or_issues(query, token=None):
|
|
386
|
+
headers = make_headers(token)
|
|
387
|
+
url = "https://api.github.com/search/issues?"
|
|
388
|
+
url += urllib.parse.urlencode({"q": query})
|
|
389
|
+
for pulls_or_issues in paginate(url, headers):
|
|
390
|
+
yield from pulls_or_issues["items"]
|
|
391
|
+
|
|
392
|
+
|
|
372
393
|
def fetch_issue_comments(repo, token=None, issue=None):
|
|
373
394
|
assert "/" in repo
|
|
374
395
|
headers = make_headers(token)
|
|
@@ -439,13 +460,17 @@ def fetch_stargazers(repo, token=None):
|
|
|
439
460
|
yield from stargazers
|
|
440
461
|
|
|
441
462
|
|
|
442
|
-
def fetch_all_repos(username=None, token=None):
|
|
443
|
-
assert
|
|
463
|
+
def fetch_all_repos(username=None, token=None, org=None):
|
|
464
|
+
assert (
|
|
465
|
+
username or token or org
|
|
466
|
+
), "Must provide username= or token= or org= or a combination"
|
|
444
467
|
headers = make_headers(token)
|
|
445
468
|
# Get topics for each repo:
|
|
446
469
|
headers["Accept"] = "application/vnd.github.mercy-preview+json"
|
|
447
470
|
if username:
|
|
448
471
|
url = "https://api.github.com/users/{}/repos".format(username)
|
|
472
|
+
elif org:
|
|
473
|
+
url = "https://api.github.com/orgs/{}/repos".format(org)
|
|
449
474
|
else:
|
|
450
475
|
url = "https://api.github.com/user/repos"
|
|
451
476
|
for repos in paginate(url, headers):
|
|
@@ -463,6 +488,7 @@ def fetch_user(username=None, token=None):
|
|
|
463
488
|
|
|
464
489
|
|
|
465
490
|
def paginate(url, headers=None):
|
|
491
|
+
url += ("&" if "?" in url else "?") + "per_page=100"
|
|
466
492
|
while url:
|
|
467
493
|
response = requests.get(url, headers=headers)
|
|
468
494
|
# For HTTP 204 no-content this yields an empty list
|
|
@@ -671,7 +697,10 @@ def ensure_foreign_keys(db):
|
|
|
671
697
|
for expected_foreign_key in FOREIGN_KEYS:
|
|
672
698
|
table, column, table2, column2 = expected_foreign_key
|
|
673
699
|
if (
|
|
674
|
-
expected_foreign_key not in
|
|
700
|
+
expected_foreign_key not in {
|
|
701
|
+
(fk.table, fk.column, fk.other_table, fk.other_column)
|
|
702
|
+
for fk in db[table].foreign_keys
|
|
703
|
+
}
|
|
675
704
|
and
|
|
676
705
|
# Ensure all tables and columns exist
|
|
677
706
|
db[table].exists()
|
|
@@ -726,7 +755,7 @@ def scrape_dependents(repo, verbose=False):
|
|
|
726
755
|
yield from repos
|
|
727
756
|
# next page?
|
|
728
757
|
try:
|
|
729
|
-
next_link = soup.select(".paginate-container")[0].find("a",
|
|
758
|
+
next_link = soup.select(".paginate-container")[0].find("a", string="Next")
|
|
730
759
|
except IndexError:
|
|
731
760
|
break
|
|
732
761
|
if next_link is not None:
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "github-to-sqlite"
|
|
3
|
+
version = "2.9.1"
|
|
4
|
+
description = "Save data from GitHub to a SQLite database"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
requires-python = ">=3.10"
|
|
7
|
+
license = "Apache-2.0"
|
|
8
|
+
license-files = ["LICENSE"]
|
|
9
|
+
dependencies = [
|
|
10
|
+
"sqlite-utils>4",
|
|
11
|
+
"requests",
|
|
12
|
+
"PyYAML",
|
|
13
|
+
]
|
|
14
|
+
|
|
15
|
+
[[project.authors]]
|
|
16
|
+
name = "Simon Willison"
|
|
17
|
+
|
|
18
|
+
[project.urls]
|
|
19
|
+
Homepage = "https://github.com/dogsheep/github-to-sqlite"
|
|
20
|
+
Changelog = "https://github.com/dogsheep/github-to-sqlite/releases"
|
|
21
|
+
Issues = "https://github.com/dogsheep/github-to-sqlite/issues"
|
|
22
|
+
CI = "https://github.com/dogsheep/github-to-sqlite/actions"
|
|
23
|
+
|
|
24
|
+
[project.scripts]
|
|
25
|
+
github-to-sqlite = "github_to_sqlite.cli:cli"
|
|
26
|
+
|
|
27
|
+
[dependency-groups]
|
|
28
|
+
dev = [
|
|
29
|
+
"pytest",
|
|
30
|
+
"requests-mock",
|
|
31
|
+
"bs4",
|
|
32
|
+
]
|
|
33
|
+
|
|
34
|
+
[build-system]
|
|
35
|
+
requires = ["uv_build>=0.9.18,<0.12.0"]
|
|
36
|
+
build-backend = "uv_build"
|
|
37
|
+
|
|
38
|
+
[tool.uv.build-backend]
|
|
39
|
+
module-root = ""
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "github-to-sqlite"
|
|
3
|
+
version = "2.9.1"
|
|
4
|
+
description = "Save data from GitHub to a SQLite database"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
requires-python = ">=3.10"
|
|
7
|
+
authors = [{name = "Simon Willison"}]
|
|
8
|
+
license = "Apache-2.0"
|
|
9
|
+
license-files = ["LICENSE"]
|
|
10
|
+
dependencies = [
|
|
11
|
+
"sqlite-utils>4",
|
|
12
|
+
"requests",
|
|
13
|
+
"PyYAML",
|
|
14
|
+
]
|
|
15
|
+
|
|
16
|
+
[project.urls]
|
|
17
|
+
Homepage = "https://github.com/dogsheep/github-to-sqlite"
|
|
18
|
+
Changelog = "https://github.com/dogsheep/github-to-sqlite/releases"
|
|
19
|
+
Issues = "https://github.com/dogsheep/github-to-sqlite/issues"
|
|
20
|
+
CI = "https://github.com/dogsheep/github-to-sqlite/actions"
|
|
21
|
+
|
|
22
|
+
[project.scripts]
|
|
23
|
+
github-to-sqlite = "github_to_sqlite.cli:cli"
|
|
24
|
+
|
|
25
|
+
[dependency-groups]
|
|
26
|
+
dev = [
|
|
27
|
+
"pytest",
|
|
28
|
+
"requests-mock",
|
|
29
|
+
"bs4",
|
|
30
|
+
]
|
|
31
|
+
|
|
32
|
+
[build-system]
|
|
33
|
+
requires = ["uv_build>=0.9.18,<0.12.0"]
|
|
34
|
+
build-backend = "uv_build"
|
|
35
|
+
|
|
36
|
+
[tool.uv.build-backend]
|
|
37
|
+
module-root = ""
|
github-to-sqlite-2.8.3/README.md
DELETED
|
@@ -1,248 +0,0 @@
|
|
|
1
|
-
# github-to-sqlite
|
|
2
|
-
|
|
3
|
-
[](https://pypi.org/project/github-to-sqlite/)
|
|
4
|
-
[](https://github.com/dogsheep/github-to-sqlite/releases)
|
|
5
|
-
[](https://github.com/dogsheep/github-to-sqlite/actions?query=workflow%3ATest)
|
|
6
|
-
[](https://github.com/dogsheep/github-to-sqlite/blob/main/LICENSE)
|
|
7
|
-
|
|
8
|
-
Save data from GitHub to a SQLite database.
|
|
9
|
-
|
|
10
|
-
<!-- toc -->
|
|
11
|
-
|
|
12
|
-
- [Demo](#demo)
|
|
13
|
-
- [How to install](#how-to-install)
|
|
14
|
-
- [Authentication](#authentication)
|
|
15
|
-
- [Fetching issues for a repository](#fetching-issues-for-a-repository)
|
|
16
|
-
- [Fetching pull requests for a repository](#fetching-pull-requests-for-a-repository)
|
|
17
|
-
- [Fetching issue comments for a repository](#fetching-issue-comments-for-a-repository)
|
|
18
|
-
- [Fetching commits for a repository](#fetching-commits-for-a-repository)
|
|
19
|
-
- [Fetching releases for a repository](#fetching-releases-for-a-repository)
|
|
20
|
-
- [Fetching tags for a repository](#fetching-tags-for-a-repository)
|
|
21
|
-
- [Fetching contributors to a repository](#fetching-contributors-to-a-repository)
|
|
22
|
-
- [Fetching repos belonging to a user or organization](#fetching-repos-belonging-to-a-user-or-organization)
|
|
23
|
-
- [Fetching specific repositories](#fetching-specific-repositories)
|
|
24
|
-
- [Fetching repos that have been starred by a user](#fetching-repos-that-have-been-starred-by-a-user)
|
|
25
|
-
- [Fetching users that have starred specific repos](#fetching-users-that-have-starred-specific-repos)
|
|
26
|
-
- [Fetching GitHub Actions workflows](#fetching-github-actions-workflows)
|
|
27
|
-
- [Scraping dependents for a repository](#scraping-dependents-for-a-repository)
|
|
28
|
-
- [Fetching emojis](#fetching-emojis)
|
|
29
|
-
- [Making authenticated API calls](#making-authenticated-api-calls)
|
|
30
|
-
|
|
31
|
-
<!-- tocstop -->
|
|
32
|
-
|
|
33
|
-
## Demo
|
|
34
|
-
|
|
35
|
-
https://github-to-sqlite.dogsheep.net/ hosts a [Datasette](https://datasette.io/) demo of a database created by [running this tool](https://github.com/dogsheep/github-to-sqlite/blob/main/.github/workflows/deploy-demo.yml#L40-L60) against all of the repositories in the [Dogsheep GitHub organization](https://github.com/dogsheep), plus the [datasette](https://github.com/simonw/datasette) and [sqlite-utils](https://github.com/simonw/sqlite-utils) repositories.
|
|
36
|
-
|
|
37
|
-
## How to install
|
|
38
|
-
|
|
39
|
-
$ pip install github-to-sqlite
|
|
40
|
-
|
|
41
|
-
## Authentication
|
|
42
|
-
|
|
43
|
-
Create a GitHub personal access token: https://github.com/settings/tokens
|
|
44
|
-
|
|
45
|
-
Run this command and paste in your new token:
|
|
46
|
-
|
|
47
|
-
$ github-to-sqlite auth
|
|
48
|
-
|
|
49
|
-
This will create a file called `auth.json` in your current directory containing the required value. To save the file at a different path or filename, use the `--auth=myauth.json` option.
|
|
50
|
-
|
|
51
|
-
As an alternative to using an `auth.json` file you can add your access token to an environment variable called `GITHUB_TOKEN`.
|
|
52
|
-
|
|
53
|
-
## Fetching issues for a repository
|
|
54
|
-
|
|
55
|
-
The `issues` command retrieves all of the issues belonging to a specified repository.
|
|
56
|
-
|
|
57
|
-
$ github-to-sqlite issues github.db simonw/datasette
|
|
58
|
-
|
|
59
|
-
If an `auth.json` file is present it will use the token from that file. It works without authentication for public repositories but you should be aware that GitHub have strict IP-based rate limits for unauthenticated requests.
|
|
60
|
-
|
|
61
|
-
You can point to a different location of `auth.json` using `-a`:
|
|
62
|
-
|
|
63
|
-
$ github-to-sqlite issues github.db simonw/datasette -a /path/to/auth.json
|
|
64
|
-
|
|
65
|
-
You can use the `--issue` option one or more times to load specific issues:
|
|
66
|
-
|
|
67
|
-
$ github-to-sqlite issues github.db simonw/datasette --issue=1
|
|
68
|
-
|
|
69
|
-
Example: [issues table](https://github-to-sqlite.dogsheep.net/github/issues)
|
|
70
|
-
|
|
71
|
-
## Fetching pull requests for a repository
|
|
72
|
-
|
|
73
|
-
While pull requests are a type of issue, you will get more information on pull requests by pulling them separately. For example, whether a pull request has been merged and when.
|
|
74
|
-
|
|
75
|
-
Following the API of issues, the `pull-requests` command retrieves all of the pull requests belonging to a specified repository.
|
|
76
|
-
|
|
77
|
-
$ github-to-sqlite pull-requests github.db simonw/datasette
|
|
78
|
-
|
|
79
|
-
You can use the `--pull-request` option one or more times to load specific pull request:
|
|
80
|
-
|
|
81
|
-
$ github-to-sqlite pull-requests github.db simonw/datasette --pull-request=81
|
|
82
|
-
|
|
83
|
-
Note that the `merged_by` column on the `pull_requests` table will only be populated for pull requests that are loaded using the `--pull-request` option - the GitHub API does not return this field for pull requests that are loaded in bulk.
|
|
84
|
-
|
|
85
|
-
Example: [pull_requests table](https://github-to-sqlite.dogsheep.net/github/pull_requests)
|
|
86
|
-
|
|
87
|
-
## Fetching issue comments for a repository
|
|
88
|
-
|
|
89
|
-
The `issue-comments` command retrieves all of the comments on all of the issues in a repository.
|
|
90
|
-
|
|
91
|
-
It is recommended you run `issues` first, so that each imported comment can have a foreign key poining to its issue.
|
|
92
|
-
|
|
93
|
-
$ github-to-sqlite issues github.db simonw/datasette
|
|
94
|
-
$ github-to-sqlite issue-comments github.db simonw/datasette
|
|
95
|
-
|
|
96
|
-
You can use the `--issue` option to only load comments for a specific issue within that repository, for example:
|
|
97
|
-
|
|
98
|
-
$ github-to-sqlite issue-comments github.db simonw/datasette --issue=1
|
|
99
|
-
|
|
100
|
-
Example: [issue_comments table](https://github-to-sqlite.dogsheep.net/github/issue_comments)
|
|
101
|
-
|
|
102
|
-
## Fetching commits for a repository
|
|
103
|
-
|
|
104
|
-
The `commits` command retrieves details of all of the commits for one or more repositories. It currently fetches the sha, commit message and author and committer details - it does no retrieve the full commit body.
|
|
105
|
-
|
|
106
|
-
$ github-to-sqlite commits github.db simonw/datasette simonw/sqlite-utils
|
|
107
|
-
|
|
108
|
-
The command accepts one or more repositories.
|
|
109
|
-
|
|
110
|
-
By default it will stop as soon as it sees a commit that has previously been retrieved. You can force it to retrieve all commits (including those that have been previously inserted) using `--all`.
|
|
111
|
-
|
|
112
|
-
Example: [commits table](https://github-to-sqlite.dogsheep.net/github/commits)
|
|
113
|
-
|
|
114
|
-
## Fetching releases for a repository
|
|
115
|
-
|
|
116
|
-
The `releases` command retrieves the releases for one or more repositories.
|
|
117
|
-
|
|
118
|
-
$ github-to-sqlite releases github.db simonw/datasette simonw/sqlite-utils
|
|
119
|
-
|
|
120
|
-
The command accepts one or more repositories.
|
|
121
|
-
|
|
122
|
-
Example: [releases table](https://github-to-sqlite.dogsheep.net/github/releases)
|
|
123
|
-
|
|
124
|
-
## Fetching tags for a repository
|
|
125
|
-
|
|
126
|
-
The `tags` command retrieves all of the tags for one or more repositories.
|
|
127
|
-
|
|
128
|
-
$ github-to-sqlite tags github.db simonw/datasette simonw/sqlite-utils
|
|
129
|
-
|
|
130
|
-
Example: [tags table](https://github-to-sqlite.dogsheep.net/github/tags)
|
|
131
|
-
|
|
132
|
-
## Fetching contributors to a repository
|
|
133
|
-
|
|
134
|
-
The `contributors` command retrieves details of all of the contributors for one or more repositories.
|
|
135
|
-
|
|
136
|
-
$ github-to-sqlite contributors github.db simonw/datasette simonw/sqlite-utils
|
|
137
|
-
|
|
138
|
-
The command accepts one or more repositories. It populates a `contributors` table, with foreign keys to `repos` and `users` and a `contributions` table listing the number of commits to that repository for each contributor.
|
|
139
|
-
|
|
140
|
-
Example: [contributors table](https://github-to-sqlite.dogsheep.net/github/contributors)
|
|
141
|
-
|
|
142
|
-
## Fetching repos belonging to a user or organization
|
|
143
|
-
|
|
144
|
-
The `repos` command fetches repos belonging to a user or organization.
|
|
145
|
-
|
|
146
|
-
Without any other arguments, this command will fetch all repos that the currently authenticated user owns, collaborates on or can access via one of their organizations:
|
|
147
|
-
|
|
148
|
-
$ github-to-sqlite repos github.db
|
|
149
|
-
|
|
150
|
-
To fetch repos belonging to a specific user or organization, provide their username as an argument:
|
|
151
|
-
|
|
152
|
-
$ github-to-sqlite repos github.db dogsheep # organization
|
|
153
|
-
$ github-to-sqlite repos github.db simonw # user
|
|
154
|
-
|
|
155
|
-
You can pass more than one username to fetch for multiple users or organizations at once:
|
|
156
|
-
|
|
157
|
-
$ github-to-sqlite repos github.db simonw dogsheep
|
|
158
|
-
|
|
159
|
-
Add the `--readme` option to save the README for the repo in a column called `readme`. Add `--readme-html` to save the HTML rendered version of the README into a collumn called `readme_html`.
|
|
160
|
-
|
|
161
|
-
Example: [repos table](https://github-to-sqlite.dogsheep.net/github/repos)
|
|
162
|
-
|
|
163
|
-
## Fetching specific repositories
|
|
164
|
-
|
|
165
|
-
You can use `-r` with the `repos` command one or more times to fetch just specific repositories.
|
|
166
|
-
|
|
167
|
-
$ github-to-sqlite repos github.db -r simonw/datasette -r dogsheep/github-to-sqlite
|
|
168
|
-
|
|
169
|
-
## Fetching repos that have been starred by a user
|
|
170
|
-
|
|
171
|
-
The `starred` command fetches the repos that have been starred by a user.
|
|
172
|
-
|
|
173
|
-
$ github-to-sqlite starred github.db simonw
|
|
174
|
-
|
|
175
|
-
If you are using an `auth.json` file you can omit the username to retrieve the starred repos for the authenticated user.
|
|
176
|
-
|
|
177
|
-
Example: [stars table](https://github-to-sqlite.dogsheep.net/github/stars)
|
|
178
|
-
|
|
179
|
-
## Fetching users that have starred specific repos
|
|
180
|
-
|
|
181
|
-
The `stargazers` command fetches the users that have starred the specified repos.
|
|
182
|
-
|
|
183
|
-
$ github-to-sqlite stargazers github.db simonw/datasette dogsheep/github-to-sqlite
|
|
184
|
-
|
|
185
|
-
You can specify one or more repository using `owner/repo` syntax.
|
|
186
|
-
|
|
187
|
-
Users fetched using this command will be inserted into the `users` table. Many-to-many records showing which repository they starred will be added to the `stars` table.
|
|
188
|
-
|
|
189
|
-
## Fetching GitHub Actions workflows
|
|
190
|
-
|
|
191
|
-
The `workflows` command fetches the YAML workflow configurations from each repository's `.github/workflows` directory and parses them to populate `workflows`, `jobs` and `steps` tables.
|
|
192
|
-
|
|
193
|
-
$ github-to-sqlite workflows github.db simonw/datasette dogsheep/github-to-sqlite
|
|
194
|
-
|
|
195
|
-
You can specify one or more repository using `owner/repo` syntax.
|
|
196
|
-
|
|
197
|
-
Example: [workflows table](https://github-to-sqlite.dogsheep.net/github/workflows), [jobs table](https://github-to-sqlite.dogsheep.net/github/jobs), [steps table](https://github-to-sqlite.dogsheep.net/github/steps)
|
|
198
|
-
|
|
199
|
-
## Scraping dependents for a repository
|
|
200
|
-
|
|
201
|
-
The GitHub dependency graph can show other GitHub projects that depend on a specific repo, for example [simonw/datasette/network/dependents](https://github.com/simonw/datasette/network/dependents).
|
|
202
|
-
|
|
203
|
-
This data is not yet available through the GitHub API. The `scrape-dependents` command scrapes those pages and uses the GitHub API to load full versions of the dependent repositories.
|
|
204
|
-
|
|
205
|
-
$ github-to-sqlite scrape-dependents github.db simonw/datasette
|
|
206
|
-
|
|
207
|
-
The command accepts one or more repositories.
|
|
208
|
-
|
|
209
|
-
Add `-v` for verbose output.
|
|
210
|
-
|
|
211
|
-
Example: [dependents table](https://github-to-sqlite.dogsheep.net/github/dependents?_sort_desc=first_seen_utc)
|
|
212
|
-
|
|
213
|
-
## Fetching emojis
|
|
214
|
-
|
|
215
|
-
You can fetch a list of every emoji supported by GitHub using the `emojis` command:
|
|
216
|
-
|
|
217
|
-
$ github-to-sqlite emojis github.db
|
|
218
|
-
|
|
219
|
-
This will create a table callad `emojis` with a primary key `name` and a `url` column.
|
|
220
|
-
|
|
221
|
-
If you add the `--fetch` option the command will also fetch the binary content of the images and place them in an `image` column:
|
|
222
|
-
|
|
223
|
-
$ github-to-sqlite emojis emojis.db -f
|
|
224
|
-
[########----------------------------] 397/1799 22% 00:03:43
|
|
225
|
-
|
|
226
|
-
You can then use the [datasette-render-images](https://github.com/simonw/datasette-render-images) plugin to browse them visually.
|
|
227
|
-
|
|
228
|
-
Example: [emojis table](https://github-to-sqlite.dogsheep.net/github/emojis)
|
|
229
|
-
|
|
230
|
-
## Making authenticated API calls
|
|
231
|
-
|
|
232
|
-
The `github-to-sqlite get` command provides a convenient shortcut for making authenticated calls to the API. Once you have created your `auth.json` file (or set a `GITHUB_TOKEN` environment variable) you can use it like this:
|
|
233
|
-
|
|
234
|
-
$ github-to-sqlite get https://api.github.com/gists
|
|
235
|
-
|
|
236
|
-
This will make an authenticated call to the URL you provide and pretty-print the resulting JSON to the console.
|
|
237
|
-
|
|
238
|
-
You can ommit the `https://api.github.com/` prefix, for example:
|
|
239
|
-
|
|
240
|
-
$ github-to-sqlite get /gists
|
|
241
|
-
|
|
242
|
-
Many GitHub APIs are [paginated using the HTTP Link header](https://docs.github.com/en/rest/guides/traversing-with-pagination). You can follow this pagination and output a list of all of the resulting items using `--paginate`:
|
|
243
|
-
|
|
244
|
-
$ github-to-sqlite get /users/simonw/repos --paginate
|
|
245
|
-
|
|
246
|
-
You can outline newline-delimited JSON for each item using `--nl`. This can be useful for streaming items into another tool.
|
|
247
|
-
|
|
248
|
-
$ github-to-sqlite get /users/simonw/repos --nl
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
LICENSE
|
|
2
|
-
README.md
|
|
3
|
-
setup.py
|
|
4
|
-
github_to_sqlite/__init__.py
|
|
5
|
-
github_to_sqlite/cli.py
|
|
6
|
-
github_to_sqlite/utils.py
|
|
7
|
-
github_to_sqlite.egg-info/PKG-INFO
|
|
8
|
-
github_to_sqlite.egg-info/SOURCES.txt
|
|
9
|
-
github_to_sqlite.egg-info/dependency_links.txt
|
|
10
|
-
github_to_sqlite.egg-info/entry_points.txt
|
|
11
|
-
github_to_sqlite.egg-info/requires.txt
|
|
12
|
-
github_to_sqlite.egg-info/top_level.txt
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
github_to_sqlite
|
github-to-sqlite-2.8.3/setup.cfg
DELETED
github-to-sqlite-2.8.3/setup.py
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
from setuptools import setup
|
|
2
|
-
import os
|
|
3
|
-
|
|
4
|
-
VERSION = "2.8.3"
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
def get_long_description():
|
|
8
|
-
with open(
|
|
9
|
-
os.path.join(os.path.dirname(os.path.abspath(__file__)), "README.md"),
|
|
10
|
-
encoding="utf8",
|
|
11
|
-
) as fp:
|
|
12
|
-
return fp.read()
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
setup(
|
|
16
|
-
name="github-to-sqlite",
|
|
17
|
-
description="Save data from GitHub to a SQLite database",
|
|
18
|
-
long_description=get_long_description(),
|
|
19
|
-
long_description_content_type="text/markdown",
|
|
20
|
-
author="Simon Willison",
|
|
21
|
-
url="https://github.com/dogsheep/github-to-sqlite",
|
|
22
|
-
license="Apache License, Version 2.0",
|
|
23
|
-
version=VERSION,
|
|
24
|
-
packages=["github_to_sqlite"],
|
|
25
|
-
entry_points="""
|
|
26
|
-
[console_scripts]
|
|
27
|
-
github-to-sqlite=github_to_sqlite.cli:cli
|
|
28
|
-
""",
|
|
29
|
-
install_requires=["sqlite-utils>=2.7.2", "requests", "PyYAML"],
|
|
30
|
-
extras_require={"test": ["pytest", "requests-mock", "bs4"]},
|
|
31
|
-
tests_require=["github-to-sqlite[test]"],
|
|
32
|
-
)
|
|
File without changes
|
|
File without changes
|