Skip to content

Commit b4a83ea

Browse files
committed
add cli, blacken code
1 parent f097373 commit b4a83ea

File tree

7 files changed

+256
-86
lines changed

7 files changed

+256
-86
lines changed

README.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,22 @@
11
# obspy_github_api
22
Helper routines to interact with obspy/obspy via GitHub API
33

4+
## Quick start
5+
6+
The easiest way to use obspy_github_api is via its command line interface.
7+
8+
```shell script
9+
# Use the magic strings found in issue 101's comments to create a config file
10+
obshub make_config 101 --path obspy_config.json
11+
12+
# Read a specified option.
13+
obshub read_config_value module_list --path obspy_config.json
14+
15+
# Use a value in the config in another command line utility.
16+
export BUILDDOCS=`bshub read_config_value module_list --path obspy_config.json`
17+
some-other-command --docs $BUILDDOCS
18+
```
19+
420
## Release Versions
521

622
Release versions are done from separate branches, see https://github.com/obspy/obspy_github_api/branches.

obspy_github_api/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
# -*- coding: utf-8 -*-
22
from .obspy_github_api import *
33

4-
__version__ = '0.0.0.dev'
4+
__version__ = "0.0.0.dev"

obspy_github_api/cli.py

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
"""
2+
Command line Interface for obspy_github_api
3+
"""
4+
import json
5+
from typing import Optional
6+
7+
import typer
8+
9+
from obspy_github_api.obspy_github_api import make_ci_json_config
10+
11+
app = typer.Typer()
12+
13+
DEFAULT_CONFIG_PATH = "obspy_config/conf.json"
14+
15+
16+
@app.command()
17+
def make_config(
18+
issue_number: int, path: str = DEFAULT_CONFIG_PATH, token: Optional[str] = None
19+
):
20+
"""
21+
Create ObsPy's configuration json file for a particular issue.
22+
23+
This command parses the comments in an issue's text looking for any magic
24+
strings (defined in ObsPy's issue template) and stores the values assigned
25+
to them to a json file for later use.
26+
27+
The following names are stored in the config file:
28+
module_list - A string of requested modules separated by commas.
29+
module_list_spaces - A string of requested modules separated by spaces.
30+
docs - True if a doc build is requested.
31+
"""
32+
make_ci_json_config(issue_number, path=path, token=token)
33+
34+
35+
@app.command()
36+
def read_config_value(name: str, path: str = DEFAULT_CONFIG_PATH):
37+
"""
38+
Read a value from the configuration file.
39+
"""
40+
with open(path, "r") as fi:
41+
params = json.load(fi)
42+
value = params[name]
43+
print(value)
44+
return value
45+
46+
47+
def main():
48+
app()
49+
50+
51+
if __name__ == "__main__":
52+
main()

obspy_github_api/obspy_github_api.py

Lines changed: 94 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
# -*- coding: utf-8 -*-
22
import ast
33
import datetime
4-
import importlib.util
54
import json
65
import os
76
import re
@@ -14,9 +13,9 @@
1413

1514

1615
# regex pattern in comments for requesting a docs build
17-
PATTERN_DOCS_BUILD = r'\+DOCS'
16+
PATTERN_DOCS_BUILD = r"\+DOCS"
1817
# regex pattern in comments for requesting tests of specific submodules
19-
PATTERN_TEST_MODULES = r'\+TESTS:([a-zA-Z0-9_\.,]*)'
18+
PATTERN_TEST_MODULES = r"\+TESTS:([a-zA-Z0-9_\.,]*)"
2019

2120

2221
@lru_cache()
@@ -29,8 +28,10 @@ def get_github_client(token=None):
2928
"""
3029
token = token or os.environ.get("GITHUB_TOKEN", None)
3130
if token is None:
32-
msg = ("Could not get authorization token for ObsPy github API "
33-
"(env variable OBSPY_COMMIT_STATUS_TOKEN)")
31+
msg = (
32+
"Could not get authorization token for ObsPy github API "
33+
"(env variable OBSPY_COMMIT_STATUS_TOKEN)"
34+
)
3435
warnings.warn(msg)
3536
gh = github3.GitHub()
3637
else:
@@ -80,9 +81,7 @@ def check_specific_module_tests_requested(issue_number, token=None):
8081

8182

8283
def get_module_test_list(
83-
issue_number,
84-
token=None,
85-
module_path='./obspy/core/util/base.py',
84+
issue_number, token=None, module_path="./obspy/core/util/base.py"
8685
):
8786
"""
8887
Gets the list of modules that should be tested for the given issue number.
@@ -132,7 +131,7 @@ def get_values_from_module(node, names):
132131
node = ast.parse(open(node).read())
133132

134133
# Parse nodes, any assignments to any of requested_names is saved.
135-
if hasattr(node, 'body'):
134+
if hasattr(node, "body"):
136135
for subnode in node.body:
137136
out.update(get_values_from_module(subnode, names=requested_names))
138137
elif isinstance(node, ast.Assign):
@@ -142,7 +141,7 @@ def get_values_from_module(node, names):
142141
return out
143142

144143

145-
def check_docs_build_requested(issue_number, token):
144+
def check_docs_build_requested(issue_number, token=None):
146145
"""
147146
Check if a docs build was requested for given issue number (by magic string
148147
'+DOCS' anywhere in issue comments).
@@ -170,7 +169,7 @@ def get_pull_requests(state="open", sort="updated", direction="desc", token=None
170169
return prs
171170

172171

173-
def get_commit_status(commit, context=None, fork='obspy', token=None):
172+
def get_commit_status(commit, context=None, fork="obspy", token=None):
174173
"""
175174
Return current commit status. Either for a specific context, or overall.
176175
@@ -194,8 +193,10 @@ def get_commit_status(commit, context=None, fork='obspy', token=None):
194193
commit = repo.commit(commit)
195194
statuses = {}
196195
for status in commit.statuses():
197-
if (status.context not in statuses or
198-
status.updated_at > statuses[status.context].updated_at):
196+
if (
197+
status.context not in statuses
198+
or status.updated_at > statuses[status.context].updated_at
199+
):
199200
statuses[status.context] = status
200201

201202
# just return current status for given context
@@ -221,20 +222,23 @@ def get_commit_time(commit, fork="obspy", token=None):
221222
gh = get_github_client(token)
222223
repo = gh.repository(fork, "obspy")
223224
commit = repo.commit(commit)
224-
dt = datetime.datetime.strptime(commit.commit.committer["date"],
225-
'%Y-%m-%dT%H:%M:%SZ')
225+
dt = datetime.datetime.strptime(
226+
commit.commit.committer["date"], "%Y-%m-%dT%H:%M:%SZ"
227+
)
226228
return time.mktime(dt.timetuple())
227229

228230

229231
def get_issue_numbers_that_request_docs_build(verbose=False, token=None):
230232
"""
231233
:rtype: list of int
232234
"""
233-
open_prs = get_pull_requests(state="open", token=None)
235+
open_prs = get_pull_requests(state="open", token=token)
234236

235237
if verbose:
236-
print("Checking the following open PRs if a docs build is requested "
237-
"and needed: {}".format(str(num for num, _ in open_prs)))
238+
print(
239+
"Checking the following open PRs if a docs build is requested "
240+
"and needed: {}".format(str(num for num, _ in open_prs))
241+
)
238242

239243
todo = []
240244
for pr in open_prs:
@@ -245,7 +249,8 @@ def get_issue_numbers_that_request_docs_build(verbose=False, token=None):
245249

246250

247251
def set_pr_docs_that_need_docs_build(
248-
pr_docs_info_dir="/home/obspy/pull_request_docs", verbose=False, token=None):
252+
pr_docs_info_dir="/home/obspy/pull_request_docs", verbose=False, token=None
253+
):
249254
"""
250255
Relies on a local directory with some files to mark when PR docs have been
251256
built etc.
@@ -261,9 +266,10 @@ def set_pr_docs_that_need_docs_build(
261266
# need to figure out time of last push from commit details.. -_-
262267
time = get_commit_time(commit, fork)
263268
if verbose:
264-
print("PR #{} requests a docs build, latest commit {} at "
265-
"{}.".format(number, commit,
266-
str(datetime.fromtimestamp(time))))
269+
print(
270+
"PR #{} requests a docs build, latest commit {} at "
271+
"{}.".format(number, commit, str(datetime.fromtimestamp(time)))
272+
)
267273

268274
filename = os.path.join(pr_docs_info_dir, str(number))
269275
filename_todo = filename + ".todo"
@@ -282,9 +288,12 @@ def set_pr_docs_that_need_docs_build(
282288
time_done = os.stat(filename_done).st_atime
283289
if time_done > time:
284290
if verbose:
285-
print("PR #{} was last built at {} and does not need a "
286-
"new build.".format(
287-
number, str(datetime.fromtimestamp(time_done))))
291+
print(
292+
"PR #{} was last built at {} and does not need a "
293+
"new build.".format(
294+
number, str(datetime.fromtimestamp(time_done))
295+
)
296+
)
288297
continue
289298
# ..otherwise touch the .todo file
290299
with open(filename_todo, "wb"):
@@ -295,9 +304,18 @@ def set_pr_docs_that_need_docs_build(
295304
print("Done checking which PRs require a docs build.")
296305

297306

298-
def set_commit_status(commit, status, context, description,
299-
target_url=None, fork="obspy", only_when_changed=True,
300-
only_when_no_status_yet=False, verbose=False, token=None):
307+
def set_commit_status(
308+
commit,
309+
status,
310+
context,
311+
description,
312+
target_url=None,
313+
fork="obspy",
314+
only_when_changed=True,
315+
only_when_no_status_yet=False,
316+
verbose=False,
317+
token=None,
318+
):
301319
"""
302320
:param only_when_changed: Whether to only set a status if the commit status
303321
would change (commit statuses can not be updated or deleted and there
@@ -320,23 +338,35 @@ def set_commit_status(commit, status, context, description,
320338
if only_when_no_status_yet:
321339
if current_status is not None:
322340
if verbose:
323-
print("Commit {} already has a commit status ({}), "
324-
"skipping.".format(commit, current_status))
341+
print(
342+
"Commit {} already has a commit status ({}), "
343+
"skipping.".format(commit, current_status)
344+
)
325345
return
326346
if only_when_changed:
327347
if current_status == status:
328348
if verbose:
329-
print("Commit {} status would not change ({}), "
330-
"skipping.".format(commit, current_status))
349+
print(
350+
"Commit {} status would not change ({}), "
351+
"skipping.".format(commit, current_status)
352+
)
331353
return
332354

333355
repo = gh.repository(fork, "obspy")
334356
commit = repo.commit(commit)
335-
repo.create_status(sha=commit.sha, state=status, context=context,
336-
description=description, target_url=target_url)
357+
repo.create_status(
358+
sha=commit.sha,
359+
state=status,
360+
context=context,
361+
description=description,
362+
target_url=target_url,
363+
)
337364
if verbose:
338-
print("Set commit {} status (context '{}') to '{}'.".format(
339-
commit.sha, context, status))
365+
print(
366+
"Set commit {} status (context '{}') to '{}'.".format(
367+
commit.sha, context, status
368+
)
369+
)
340370

341371

342372
def set_all_updated_pull_requests_docker_testbot_pending(verbose=False, token=None):
@@ -347,19 +377,24 @@ def set_all_updated_pull_requests_docker_testbot_pending(verbose=False, token=No
347377

348378
open_prs = get_pull_requests(state="open", token=token)
349379
if verbose:
350-
print("Working on PRs: " + ", ".join(
351-
[str(pr.number) for pr in open_prs]))
380+
print("Working on PRs: " + ", ".join([str(pr.number) for pr in open_prs]))
352381
for pr in open_prs:
353382
set_commit_status(
354-
commit=pr.head.sha, status="pending", context="docker-testbot",
383+
commit=pr.head.sha,
384+
status="pending",
385+
context="docker-testbot",
355386
description="docker testbot results not available yet",
356387
only_when_no_status_yet=True,
357-
verbose=verbose)
388+
verbose=verbose,
389+
)
358390

359391

360392
def get_docker_build_targets(
361-
context="docker-testbot", branches=["master", "maintenance_1.0.x"],
362-
prs=True, token=None):
393+
context="docker-testbot",
394+
branches=["master", "maintenance_1.0.x"],
395+
prs=True,
396+
token=None,
397+
):
363398
"""
364399
Returns a list of build targets that need a build of a given context.
365400
@@ -384,12 +419,12 @@ def get_docker_build_targets(
384419
:rtype: string
385420
"""
386421
if not branches and not prs:
387-
return ''
422+
return ""
388423

389424
gh = get_github_client(token)
390-
status_needs_build = (None, 'pending')
425+
status_needs_build = (None, "pending")
391426
targets = []
392-
repo = gh.repository('obspy', 'obspy')
427+
repo = gh.repository("obspy", "obspy")
393428

394429
if branches:
395430
for name in branches:
@@ -400,22 +435,22 @@ def get_docker_build_targets(
400435
continue
401436
# branches don't have a PR number, use dummy placeholder 'XXX' so
402437
# that variable splitting in bash still works
403-
targets.append('XXX_obspy:{}'.format(sha))
438+
targets.append("XXX_obspy:{}".format(sha))
404439

405440
if prs:
406-
open_prs = get_pull_requests(state='open')
441+
open_prs = get_pull_requests(state="open")
407442
for pr in open_prs:
408443
fork = pr.head.user
409444
sha = pr.head.sha
410445
status = get_commit_status(sha, context=context)
411446
if status not in status_needs_build:
412447
continue
413-
targets.append('{}_{}:{}'.format(str(pr.number), fork, sha))
448+
targets.append("{}_{}:{}".format(str(pr.number), fork, sha))
414449

415-
return ' '.join(targets)
450+
return " ".join(targets)
416451

417452

418-
def make_ci_json_config(issue_number, path='obspy_ci_conf.json', token=None):
453+
def make_ci_json_config(issue_number, path="obspy_ci_conf.json", token=None):
419454
"""
420455
Make a json file for configuring additional actions in CI.
421456
@@ -427,10 +462,15 @@ def make_ci_json_config(issue_number, path='obspy_ci_conf.json', token=None):
427462
docs = check_docs_build_requested(issue_number, token=token)
428463

429464
out = dict(
430-
module_list=('obspy.' + ',obspy.').join(module_list),
431-
module_list_spaces=' '.join(module_list),
465+
module_list=("obspy." + ",obspy.").join(module_list),
466+
module_list_spaces=" ".join(module_list),
432467
docs=docs,
433468
)
434469

435-
with open(path, 'w') as fi:
436-
json.dump(out, fi)
470+
# make sure path exists
471+
path = Path(path)
472+
path_dir = path if path.is_dir() else path.parent
473+
path_dir.mkdir(exist_ok=True, parents=True)
474+
475+
with path.open("w") as fi:
476+
json.dump(out, fi, indent=4)

0 commit comments

Comments
 (0)