Skip to content

Commit 138d661

Browse files
committed
Preliminary work for adding a cli path application
1 parent 6275849 commit 138d661

File tree

3 files changed

+111
-3
lines changed

3 files changed

+111
-3
lines changed

biothings/cli/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
from biothings.cli.commands.admin import build_admin_application
1515
from biothings.cli.commands.config import config_application, load_configuration
1616
from biothings.cli.commands.dataplugin import dataplugin_application
17+
from biothings.cli.commands.pathing import path_application
1718

1819

1920
def setup_logging_configuration(logging_level: Literal[10, 20, 30, 40, 50]) -> None:
@@ -63,4 +64,5 @@ def main():
6364

6465
admin_application.add_typer(dataplugin_application, name="dataplugin")
6566
admin_application.add_typer(config_application, name="config")
67+
admin_application.add_typer(path_application, name="path")
6668
return admin_application()

biothings/cli/commands/pathing.py

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
"""
2+
Module for creating the cli interface for the path interface
3+
"""
4+
5+
import asyncio
6+
import pathlib
7+
import sys
8+
from typing import Optional
9+
10+
import typer
11+
from typing_extensions import Annotated
12+
from rich.console import Console
13+
from rich.table import Table
14+
15+
from biothings.cli.commands import operations
16+
17+
SHORT_HELP = "[green]CLI tool for viewing the python system path and adding external parsers to the system path[/green]"
18+
FULL_HELP = (
19+
SHORT_HELP
20+
+ "\n\n[magenta] :sparkles: Run from an existing data plugin folder to evaluate a singular data plugin.[/magenta]"
21+
)
22+
path_application = typer.Typer(
23+
help=FULL_HELP,
24+
short_help=SHORT_HELP,
25+
no_args_is_help=True,
26+
rich_markup_mode="rich",
27+
)
28+
29+
30+
@path_application.command(name="view")
31+
def view_system_path() -> None:
32+
"""
33+
View the system paths current discovered by python, along with potential hub parsers of interest
34+
that the user may wish to add to the system path for usage in data plugin testing
35+
"""
36+
path_table = Table(title="Python System Path(s)")
37+
38+
path_table.add_column("Index", style="cyan")
39+
path_table.add_column("Paths", style="green")
40+
41+
system_paths = sys.path
42+
for index, system_path in enumerate(system_paths):
43+
path_table.add_row(str(index), str(system_path))
44+
45+
parser_table = Table(title="External Parser Path(s)")
46+
47+
parser_table.add_column("Index", style="cyan")
48+
parser_table.add_column("Paths", style="magenta")
49+
parser_table.add_column("On System Path?", style="steel_blue1")
50+
51+
hub_parser_paths = find_hub_parsers()
52+
for index, parser_path in enumerate(hub_parser_paths):
53+
parser_table.add_row(str(index), str(parser_path), str(parser_path in system_paths))
54+
55+
console = Console()
56+
console.print(path_table)
57+
console.print(parser_table)
58+
59+
60+
@path_application.command(name="add")
61+
def add_to_system_path() -> None:
62+
"""
63+
Add file paths to the python system path for aiding in testing various data plugins
64+
"""
65+
pass
66+
67+
68+
def find_hub_parsers() -> list[pathlib.Path]:
69+
"""
70+
Attempts to locate any potential hub-based parsers that are use across different plugins
71+
within a shared hub instance
72+
73+
Will attempt to traverse recursively at most 3 levels above the present working directory
74+
The typical hub structure has the plugins directory at the same level as the hub directory
75+
76+
pending.api structure:
77+
root
78+
├── hub
79+
├── plugins
80+
81+
(mygene, mychem, myvariant, ...) structure
82+
root
83+
├── src
84+
│   ├── hub
85+
│   ├── plugins
86+
87+
In either structure, the user is expected to be operating within the directory of a specific
88+
plugin (root/plugin/plugin_directory/) or acting as a HUB within the (root/plugin) directory
89+
Either case we should be able to find the shared parsers within 3 upper levels
90+
"""
91+
directory_pointer = pathlib.Path.cwd()
92+
93+
traversal_counter = 0
94+
external_parser_paths = []
95+
96+
# Match any path ending explicitly in hub. The bracket "[a]" matches the character literal
97+
# enclosed in the bracket, so [h][u][b] matches the literal hub
98+
match_expr = "**/[h][u][b]"
99+
while traversal_counter < 2:
100+
directory_pointer = directory_pointer.parent
101+
for hub_path in directory_pointer.glob(match_expr):
102+
hub_dataload = hub_path.joinpath("dataload")
103+
if hub_dataload.exists():
104+
external_parser_paths.append(hub_dataload.resolve().absolute())
105+
traversal_counter += 1
106+
return external_parser_paths

biothings/cli/manager.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,13 @@ async def defer_to_process(self, pinfo=None, func=None, *args, **kwargs):
2929
async def defer_to_thread(self, pinfo=None, func=None, *args):
3030
"""keep the same signature as JobManager.defer_to_thread. The passed pinfo is ignored"""
3131

32-
async def run(fut, func):
32+
async def run(fut, func, *args):
3333
try:
34-
res = func()
34+
res = func(*args)
3535
fut.set_result(res)
3636
except Exception as gen_exc:
3737
fut.set_exception(gen_exc)
3838

3939
fut = self.loop.create_future()
40-
self.loop.create_task(run(fut, func))
40+
self.loop.create_task(run(fut, func, *args))
4141
return fut

0 commit comments

Comments
 (0)