22Module for creating the cli interface for the path interface
33"""
44
5- import asyncio
5+ import logging
66import pathlib
77import sys
8- from typing import Optional
98
109import typer
11- from typing_extensions import Annotated
1210from rich .console import Console
1311from rich .table import Table
1412
15- from biothings .cli .commands import operations
13+ from biothings .cli .commands .decorators import cli_system_path , operation_mode
14+
1615
1716SHORT_HELP = "[green]CLI tool for viewing the python system path and adding external parsers to the system path[/green]"
1817FULL_HELP = (
2625 rich_markup_mode = "rich" ,
2726)
2827
28+ logger = logging .getLogger (name = "biothings-cli" )
29+
2930
3031@path_application .command (name = "view" )
3132def view_system_path () -> None :
3233 """
3334 View the system paths current discovered by python, along with potential hub parsers of interest
3435 that the user may wish to add to the system path for usage in data plugin testing
3536 """
37+ display_system_paths ()
38+
39+
40+ @path_application .command (name = "add-hub-parsers" )
41+ def add_parser_to_system_path () -> None :
42+ """
43+ Add discovered file parsers paths to the python system path for aiding in testing various data plugins
44+
45+ Creates the file "bt_custom.pth", in the same file extension used by the `site` module
46+ provided by python. It will create this file in the biothings_hub, and if found when running any
47+ command, it will add the files to the system path
48+ """
49+ update_system_paths ()
50+ display_system_paths ()
51+
52+
53+ @path_application .command (name = "remove-hub-parsers" )
54+ def remove_parser_from_system_path () -> None :
55+ """
56+ Remove the hub parsers discovered from the python system path
57+
58+ Simply removes the bt_custom.pth file from the biothings-cli directory
59+ """
60+ remove_system_paths ()
61+ display_system_paths ()
62+
63+
64+ @cli_system_path
65+ @operation_mode
66+ def display_system_paths () -> None :
67+ """
68+ Method for displaying the system path information used for the
69+ biothing-cli application
70+
71+ External method so we can call it from multiple typer commands
72+ """
3673 path_table = Table (title = "Python System Path(s)" )
3774
3875 path_table .add_column ("Index" , style = "cyan" )
@@ -50,27 +87,53 @@ def view_system_path() -> None:
5087
5188 hub_parser_paths = find_hub_parsers ()
5289 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 ))
90+ parser_table .add_row (str (index ), str (parser_path ), str (str ( parser_path ) in system_paths ))
5491
5592 console = Console ()
5693 console .print (path_table )
5794 console .print (parser_table )
5895
5996
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
97+ @cli_system_path
98+ @operation_mode
99+ def update_system_paths () -> None :
100+ from biothings import config
101+
102+ discovery_path = pathlib .Path (config .BIOTHINGS_CLI_PATH ).resolve ().absolute ()
103+ discovery_path .mkdir (parents = True , exist_ok = True )
104+
105+ hub_parser_paths = find_hub_parsers ()
106+
107+ path_file = discovery_path .joinpath (".biothings_cli.pth" )
108+ with open (path_file , "w" , encoding = "utf-8" ) as path_handle :
109+ for parser_path in hub_parser_paths :
110+ logger .info ("Adding %s -> %s" , parser_path , path_file )
111+ path_handle .write (f"{ parser_path } \n " )
112+
113+
114+ @cli_system_path
115+ @operation_mode
116+ def remove_system_paths () -> None :
117+ from biothings import config
118+
119+ discovery_path = pathlib .Path (config .BIOTHINGS_CLI_PATH ).resolve ().absolute ()
120+ path_file = discovery_path .joinpath (".biothings_cli.pth" )
121+ path_file .unlink (missing_ok = True )
122+
123+ hub_parser_paths = find_hub_parsers ()
124+ for parser_path in hub_parser_paths :
125+ try :
126+ sys .path .remove (str (parser_path ))
127+ except ValueError :
128+ pass
66129
67130
68- def find_hub_parsers () -> list [pathlib .Path ]:
131+ def find_hub_parsers (upward_depth : int = 2 ) -> list [pathlib .Path ]:
69132 """
70133 Attempts to locate any potential hub-based parsers that are use across different plugins
71134 within a shared hub instance
72135
73- Will attempt to traverse recursively at most 3 levels above the present working directory
136+ Will attempt to traverse recursively by <upward_depth> levels (defaults to 2 levels) above the present working directory
74137 The typical hub structure has the plugins directory at the same level as the hub directory
75138
76139 pending.api structure:
@@ -86,7 +149,7 @@ def find_hub_parsers() -> list[pathlib.Path]:
86149
87150 In either structure, the user is expected to be operating within the directory of a specific
88151 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
152+ Either case we should be able to find the shared parsers within 2 upper levels
90153 """
91154 directory_pointer = pathlib .Path .cwd ()
92155
@@ -96,11 +159,11 @@ def find_hub_parsers() -> list[pathlib.Path]:
96159 # Match any path ending explicitly in hub. The bracket "[a]" matches the character literal
97160 # enclosed in the bracket, so [h][u][b] matches the literal hub
98161 match_expr = "**/[h][u][b]"
99- while traversal_counter < 2 :
162+ while traversal_counter < upward_depth :
100163 directory_pointer = directory_pointer .parent
101164 for hub_path in directory_pointer .glob (match_expr ):
102165 hub_dataload = hub_path .joinpath ("dataload" )
103166 if hub_dataload .exists ():
104- external_parser_paths .append (hub_dataload .resolve ().absolute ())
167+ external_parser_paths .append (hub_path .resolve ().absolute ())
105168 traversal_counter += 1
106169 return external_parser_paths
0 commit comments