Skip to content

Commit 5d64659

Browse files
committed
Update CLI.
1 parent 6a4cce3 commit 5d64659

File tree

5 files changed

+323
-82
lines changed

5 files changed

+323
-82
lines changed

src/lovd/__init__.py

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
21
"""
32
LOVD Querying Interfaces
43
========================
@@ -7,14 +6,15 @@
76
Variants Database (LOVD).
87
98
"""
10-
from . import client, config, constants
9+
10+
from . import cli, client, config, constants
1111

1212
from .client import (
1313
LOVD_RATE_LIMIT,
1414
LOVDClient,
15-
get_lovd_variants,
15+
get_variants,
1616
get_variants_from_config,
17-
variants_to_dataframe
17+
variants_to_dataframe,
1818
)
1919
from .config import load_acquisition_config, options
2020
from .constants import (
@@ -25,18 +25,18 @@
2525
LOVDTOOLS_DATA_PATH,
2626
LOVDTOOLS_ROOT_PATH,
2727
LOVDTOOLS_STATE_PATH,
28+
LOVDTOOLS_VERSION,
2829
LOVD_EMAIL,
2930
NCBI_EMAIL,
3031
TARGET_GENE_SYMBOLS,
31-
USER_AGENT_STRING
32-
32+
USER_AGENT_STRING,
3333
)
3434

3535

3636
# : package metadata
37-
__author__ = "Caleb Rice"
37+
__author__ = "Caleb R."
3838
__email__ = "hyletic@proton.me"
39-
__version__ = "0.1.0-dev8"
39+
__version__ = "0.1.0-dev28"
4040

4141

4242
__all__ = [
@@ -48,26 +48,24 @@
4848
"LOVDTOOLS_DATA_PATH",
4949
"LOVDTOOLS_ROOT_PATH",
5050
"LOVDTOOLS_STATE_PATH",
51+
"LOVDTOOLS_VERSION",
5152
"LOVD_EMAIL",
5253
"LOVD_RATE_LIMIT",
5354
"NCBI_EMAIL",
5455
"TARGET_GENE_SYMBOLS",
5556
"USER_AGENT_STRING",
56-
5757
# : modules
58+
"cli",
5859
"client",
5960
"config",
6061
"constants",
61-
6262
# : classes
6363
"LOVDClient",
64-
6564
# : functions
6665
"get_variants_from_config",
67-
"get_lovd_variants",
66+
"get_variants",
6867
"load_acquisition_config",
6968
"variants_to_dataframe",
70-
7169
# : objects
72-
"options"
70+
"options",
7371
]

src/lovd/cli.py

Lines changed: 203 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,203 @@
1+
"""
2+
LOVDTools CLI
3+
=============
4+
5+
This module provides a command-line interface for the LOVDTools API client.
6+
7+
"""
8+
9+
from __future__ import annotations
10+
11+
import logging
12+
13+
import click
14+
15+
from .client import LOVDClient
16+
from .config import options
17+
from .constants import ACQUISITION_CONFIG_PATH, LOVDTOOLS_VERSION
18+
19+
20+
# : API client initialization
21+
#
22+
client = LOVDClient()
23+
24+
25+
# : command-line interface
26+
#
27+
@click.group(invoke_without_command=True)
28+
@click.option(
29+
"--version",
30+
"-V",
31+
is_flag=True,
32+
help="Show `lovdtools`'s version string and exit."
33+
)
34+
@click.pass_context
35+
def cli(ctx, version):
36+
"""LOVDTools – An API client for the global–shared LOVD instance.
37+
38+
This is a command-line interface for the LOVD API client, which
39+
provides various utilities for querying the global–shared instance
40+
of the Leiden Open Variants Database (LOVD).
41+
42+
"""
43+
logging.basicConfig(level="INFO", format="%(name)s – %(levelname)s: %(message)s")
44+
ctx.logger = logging.getLogger(__name__)
45+
46+
ctx.logger.debug("Logger setup complete.")
47+
48+
if version:
49+
click.echo(f"lovdtools, v{LOVDTOOLS_VERSION}")
50+
51+
if not ctx.invoked_subcommand and not version:
52+
click.echo(ctx.get_help())
53+
54+
55+
@cli.group()
56+
def config():
57+
pass
58+
59+
60+
@config.command(name="show")
61+
def show_config():
62+
"""List all configuration options, along with their current values."""
63+
print()
64+
print("LOVDTools Configuration")
65+
print("─" * 70)
66+
67+
for k, v in options.items():
68+
print(f"o {k}: {v}")
69+
70+
print("─" * 70 + "\n")
71+
72+
73+
@config.command(name="get")
74+
@click.argument("key", metavar="KEY", required=True)
75+
def get_config_option(key: str):
76+
"""Get the current value of a specific configuration option."""
77+
print(f"\n{key.lower()}: {options[key]}\n")
78+
79+
80+
@config.command(name="set")
81+
@click.argument("key", metavar="KEY", required=True)
82+
@click.argument("value", nargs=-1, metavar="VALUE", required=True)
83+
def set_config_option(key: str, value: tuple[str]):
84+
"""Set the current value of a specific configuration option."""
85+
try:
86+
# Join the tuple elements into a single string
87+
value_str = " ".join(value)
88+
89+
# Determine if this key should be a list or string
90+
# target_gene_symbols and search_terms should be lists
91+
# email and user_agent should be strings
92+
if key in ["target_gene_symbols", "search_terms"]:
93+
# Split by spaces to create a list
94+
values = value_str.split()
95+
options[key] = values
96+
else:
97+
# Keep as a single string (don't split)
98+
options[key] = value_str
99+
100+
with open(ACQUISITION_CONFIG_PATH, "w") as f:
101+
import yaml
102+
yaml.safe_dump(options, f)
103+
104+
click.echo(f"Set configuration option `{key}` to `{value_str}`.")
105+
except Exception as e:
106+
raise e
107+
108+
109+
@cli.command(name="query")
110+
@click.argument("symbols", nargs=-1, metavar="SYMBOLS")
111+
@click.option(
112+
"--search-terms",
113+
"-S",
114+
multiple=True,
115+
help="A search term or array of search terms by which to filter results."
116+
)
117+
@click.option(
118+
"--filters",
119+
"-F",
120+
multiple=True,
121+
help="An array of [KEY]:[VALUE] pairs to pass as parameters to the LOVD API call."
122+
)
123+
@click.option(
124+
"--out",
125+
"-o",
126+
help="The directory to which results are output."
127+
)
128+
@click.option(
129+
"--include-effect",
130+
"-E",
131+
is_flag=True,
132+
help="Includes variants' reported effects in results."
133+
)
134+
@click.option(
135+
"--verbose",
136+
"-v",
137+
is_flag=True,
138+
help="Enables verbose output."
139+
)
140+
@click.option(
141+
"--progressive",
142+
"-p",
143+
is_flag=True,
144+
help="Enables a progress bar indicator for the query."
145+
)
146+
def query(
147+
symbols: tuple[str],
148+
search_terms: tuple[str] | None,
149+
filters: tuple[str] | None,
150+
out: str | None,
151+
include_effect: bool | None,
152+
verbose: bool | None,
153+
progressive: bool | None
154+
):
155+
"""Query LOVD for the given gene symbol(s).
156+
157+
Retrieves records for variants reported on the given gene symbols,
158+
according to the provided filters.
159+
160+
"""
161+
if progressive:
162+
client.with_progress()
163+
164+
symbols = symbols or options["target_gene_symbols"]
165+
166+
if verbose:
167+
click.echo("Getting variants reported on the following gene(s):")
168+
169+
for s in symbols:
170+
if s in "email target_gene_symbols user_agent":
171+
raise click.BadArgumentUsage(
172+
"It looks like you're trying to get the current value of a\n"
173+
"configuration option, but you used `lovdtools get [KEY]`, which is\n"
174+
"for querying LOVD for variants on one or more gene symbols.\n"
175+
"\nInstead, you should use `lovdtools config get [KEY]`."
176+
)
177+
178+
else:
179+
if verbose:
180+
click.echo(f" o {s}")
181+
182+
try:
183+
variants = client.get_variants_for_genes(
184+
symbols,
185+
out or "./output",
186+
search_terms,
187+
include_effect or True,
188+
list({k:v for k, v in [f.split(sep=":") for f in filters]}),
189+
)
190+
except click.BadArgumentUsage as e:
191+
e("Improper argument usage.")
192+
except click.BadOptionUsage as e:
193+
e("Improper option usage.")
194+
except click.BadParameter as e:
195+
e("Bad parameter usage.")
196+
except Exception as e:
197+
e("LOVDTools encountered an unhandled exception. Double-check your inputs.")
198+
199+
if verbose:
200+
click.echo("Requisition complete.")
201+
202+
return variants
203+

0 commit comments

Comments
 (0)