metahq-cli 0.1.1__tar.gz → 1.0.0rc1__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.
- metahq_cli-1.0.0rc1/LICENSE +28 -0
- {metahq_cli-0.1.1 → metahq_cli-1.0.0rc1}/PKG-INFO +14 -4
- {metahq_cli-0.1.1 → metahq_cli-1.0.0rc1}/README.md +6 -3
- {metahq_cli-0.1.1 → metahq_cli-1.0.0rc1}/pyproject.toml +6 -0
- metahq_cli-1.0.0rc1/src/metahq_cli/__init__.py +1 -0
- {metahq_cli-0.1.1 → metahq_cli-1.0.0rc1}/src/metahq_cli/commands/__init__.py +3 -1
- metahq_cli-1.0.0rc1/src/metahq_cli/commands/delete.py +63 -0
- {metahq_cli-0.1.1 → metahq_cli-1.0.0rc1}/src/metahq_cli/commands/retrieve.py +41 -33
- {metahq_cli-0.1.1 → metahq_cli-1.0.0rc1}/src/metahq_cli/commands/search.py +2 -1
- {metahq_cli-0.1.1 → metahq_cli-1.0.0rc1}/src/metahq_cli/commands/setup.py +25 -13
- metahq_cli-1.0.0rc1/src/metahq_cli/commands/validate.py +51 -0
- {metahq_cli-0.1.1 → metahq_cli-1.0.0rc1}/src/metahq_cli/logger.py +14 -18
- {metahq_cli-0.1.1 → metahq_cli-1.0.0rc1}/src/metahq_cli/main.py +3 -1
- {metahq_cli-0.1.1 → metahq_cli-1.0.0rc1}/src/metahq_cli/retrieval_builder.py +162 -68
- {metahq_cli-0.1.1 → metahq_cli-1.0.0rc1}/src/metahq_cli/retriever.py +83 -28
- metahq_cli-1.0.0rc1/src/metahq_cli/setup/__init__.py +0 -0
- {metahq_cli-0.1.1 → metahq_cli-1.0.0rc1}/src/metahq_cli/setup/config.py +33 -8
- {metahq_cli-0.1.1 → metahq_cli-1.0.0rc1}/src/metahq_cli/setup/downloader.py +76 -73
- metahq_cli-1.0.0rc1/src/metahq_cli/util/__init__.py +0 -0
- metahq_cli-1.0.0rc1/src/metahq_cli/util/_validate.py +66 -0
- metahq_cli-1.0.0rc1/src/metahq_cli/util/helpers.py +37 -0
- {metahq_cli-0.1.1 → metahq_cli-1.0.0rc1}/src/metahq_cli/util/supported.py +11 -10
- metahq_cli-0.1.1/src/metahq_cli/__init__.py +0 -1
- metahq_cli-0.1.1/src/metahq_cli/util/helpers.py +0 -15
- {metahq_cli-0.1.1 → metahq_cli-1.0.0rc1}/.gitignore +0 -0
- {metahq_cli-0.1.1 → metahq_cli-1.0.0rc1}/src/metahq_cli/commands/supported.py +0 -0
- {metahq_cli-0.1.1 → metahq_cli-1.0.0rc1}/src/metahq_cli/util/checkers.py +0 -0
- {metahq_cli-0.1.1 → metahq_cli-1.0.0rc1}/src/metahq_cli/util/common_args.py +0 -0
- {metahq_cli-0.1.1 → metahq_cli-1.0.0rc1}/src/metahq_cli/util/messages.py +0 -0
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
BSD 3-Clause License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025, Krishnan Lab
|
|
4
|
+
|
|
5
|
+
Redistribution and use in source and binary forms, with or without
|
|
6
|
+
modification, are permitted provided that the following conditions are met:
|
|
7
|
+
|
|
8
|
+
1. Redistributions of source code must retain the above copyright notice, this
|
|
9
|
+
list of conditions and the following disclaimer.
|
|
10
|
+
|
|
11
|
+
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
12
|
+
this list of conditions and the following disclaimer in the documentation
|
|
13
|
+
and/or other materials provided with the distribution.
|
|
14
|
+
|
|
15
|
+
3. Neither the name of the copyright holder nor the names of its
|
|
16
|
+
contributors may be used to endorse or promote products derived from
|
|
17
|
+
this software without specific prior written permission.
|
|
18
|
+
|
|
19
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
20
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
21
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
22
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
23
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
24
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
25
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
26
|
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
27
|
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
28
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: metahq-cli
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 1.0.0rc1
|
|
4
4
|
Summary: The meta-hq CLI.
|
|
5
5
|
Author-email: Parker Hicks <parker.hicks@cuanschutz.edu>, Faisal Alquaddoomi <faisal.alquaddoomi@cuanschutz.edu>
|
|
6
|
+
License-File: LICENSE
|
|
6
7
|
Keywords: CLI,Data Curation,Database,Public Biomedical Data
|
|
7
8
|
Classifier: Development Status :: 3 - Alpha
|
|
8
9
|
Classifier: Intended Audience :: Science/Research
|
|
@@ -20,23 +21,32 @@ Provides-Extra: dev
|
|
|
20
21
|
Requires-Dist: black; extra == 'dev'
|
|
21
22
|
Requires-Dist: flake8; extra == 'dev'
|
|
22
23
|
Requires-Dist: isort; extra == 'dev'
|
|
24
|
+
Requires-Dist: mkdocs-click; extra == 'dev'
|
|
25
|
+
Requires-Dist: mkdocs-material; extra == 'dev'
|
|
26
|
+
Requires-Dist: mkdocs>=1.6.1; extra == 'dev'
|
|
27
|
+
Requires-Dist: mkdocstrings[python]; extra == 'dev'
|
|
23
28
|
Requires-Dist: mypy; extra == 'dev'
|
|
29
|
+
Requires-Dist: pymdown-extensions; extra == 'dev'
|
|
24
30
|
Requires-Dist: pytest-cov; extra == 'dev'
|
|
25
31
|
Requires-Dist: pytest>=8.0; extra == 'dev'
|
|
32
|
+
Requires-Dist: vulture; extra == 'dev'
|
|
26
33
|
Provides-Extra: test
|
|
27
34
|
Requires-Dist: pytest-benchmark; extra == 'test'
|
|
28
35
|
Requires-Dist: pytest-cov; extra == 'test'
|
|
29
36
|
Requires-Dist: pytest>=8.0; extra == 'test'
|
|
30
37
|
Description-Content-Type: text/markdown
|
|
31
38
|
|
|
32
|
-
<
|
|
39
|
+
<div align="left">
|
|
40
|
+
<img src="https://raw.githubusercontent.com/krishnanlab/meta-hq/main/media/metahq_cli_logo.png" alt="CLI Logo" width="400" height="200" />
|
|
41
|
+
</div>
|
|
33
42
|
|
|
34
43
|

|
|
35
|
-

|
|
36
45
|

|
|
37
46
|

|
|
47
|
+
[](https://opensource.org/licenses/BSD-3-Clause)
|
|
38
48
|
|
|
39
|
-
A
|
|
49
|
+
A command line interface to query the MetaHQ database.
|
|
40
50
|
|
|
41
51
|
## Key features
|
|
42
52
|
|
|
@@ -1,11 +1,14 @@
|
|
|
1
|
-
<
|
|
1
|
+
<div align="left">
|
|
2
|
+
<img src="https://raw.githubusercontent.com/krishnanlab/meta-hq/main/media/metahq_cli_logo.png" alt="CLI Logo" width="400" height="200" />
|
|
3
|
+
</div>
|
|
2
4
|
|
|
3
5
|

|
|
4
|
-

|
|
5
7
|

|
|
6
8
|

|
|
9
|
+
[](https://opensource.org/licenses/BSD-3-Clause)
|
|
7
10
|
|
|
8
|
-
A
|
|
11
|
+
A command line interface to query the MetaHQ database.
|
|
9
12
|
|
|
10
13
|
## Key features
|
|
11
14
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "1.0.0-rc.1"
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
from metahq_cli.commands.delete import delete
|
|
1
2
|
from metahq_cli.commands.retrieve import retrieve_commands
|
|
2
3
|
from metahq_cli.commands.search import search
|
|
3
4
|
from metahq_cli.commands.setup import setup
|
|
4
5
|
from metahq_cli.commands.supported import supported
|
|
6
|
+
from metahq_cli.commands.validate import validate
|
|
5
7
|
|
|
6
|
-
__all__ = ["retrieve_commands", "setup", "search", "supported"]
|
|
8
|
+
__all__ = ["retrieve_commands", "setup", "search", "supported", "validate", "delete"]
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"""
|
|
2
|
+
CLI command to delete old version of MetaHQ
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import click
|
|
6
|
+
import os
|
|
7
|
+
import shutil
|
|
8
|
+
import sys
|
|
9
|
+
from metahq_core.util.progress import console
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
|
|
12
|
+
from metahq_cli.logger import setup_logger
|
|
13
|
+
from metahq_cli.util.common_args import logging_args
|
|
14
|
+
from metahq_core.util.supported import get_default_log_dir
|
|
15
|
+
from metahq_cli.util.helpers import set_verbosity
|
|
16
|
+
|
|
17
|
+
from metahq_core.util.supported import get_config, get_config_file
|
|
18
|
+
|
|
19
|
+
@click.command(name="delete", context_settings={"help_option_names": ["-h", "--help"]})
|
|
20
|
+
@click.option(
|
|
21
|
+
"-l",
|
|
22
|
+
"--log-dir",
|
|
23
|
+
type=click.Path(),
|
|
24
|
+
default="default",
|
|
25
|
+
help="Path to directory storing logs. Default is `/home/path/MetaHQ`.",
|
|
26
|
+
)
|
|
27
|
+
@click.option(
|
|
28
|
+
"--all",
|
|
29
|
+
"-a",
|
|
30
|
+
is_flag=True,
|
|
31
|
+
default=False,
|
|
32
|
+
help="Will delete everything in MetaHQ directory",
|
|
33
|
+
)
|
|
34
|
+
@logging_args
|
|
35
|
+
def delete(log_level: str, log_dir: str, quiet: bool, all: bool):
|
|
36
|
+
"""Delete old version of MetaHQ"""
|
|
37
|
+
if log_dir == "default":
|
|
38
|
+
log_dir = str(get_default_log_dir())
|
|
39
|
+
|
|
40
|
+
logger = setup_logger(__name__, level=log_level, log_dir=log_dir, console=console)
|
|
41
|
+
verbose = set_verbosity(quiet)
|
|
42
|
+
|
|
43
|
+
# read in config
|
|
44
|
+
config = get_config()
|
|
45
|
+
config_path = get_config_file()
|
|
46
|
+
logger.info(f"The path to config file is found at: {config_path}")
|
|
47
|
+
logger.info(f"Information in the config file is: {config}")
|
|
48
|
+
|
|
49
|
+
if click.confirm(
|
|
50
|
+
f"Delete MetaHQ database and config file or config directory?",
|
|
51
|
+
default=False,
|
|
52
|
+
):
|
|
53
|
+
logger.info("Deleting existing data directory...")
|
|
54
|
+
shutil.rmtree(config["data_dir"])
|
|
55
|
+
if all:
|
|
56
|
+
logger.info("Deleting existing config directory...")
|
|
57
|
+
shutil.rmtree(config_path.parent)
|
|
58
|
+
else:
|
|
59
|
+
logger.info("Deleting existing config file...")
|
|
60
|
+
os.remove(config_path)
|
|
61
|
+
else:
|
|
62
|
+
logger.info("Keeping existing data directory and config file.")
|
|
63
|
+
sys.exit("Terminating...")
|
|
@@ -4,7 +4,7 @@ CLI command to retrieve annotations and labels from meta-hq.
|
|
|
4
4
|
Author: Parker Hicks
|
|
5
5
|
Date: 2025-09-05
|
|
6
6
|
|
|
7
|
-
Last updated: 2025-
|
|
7
|
+
Last updated: 2025-12-01 by Parker Hicks
|
|
8
8
|
"""
|
|
9
9
|
|
|
10
10
|
import click
|
|
@@ -61,15 +61,17 @@ def retrieve_commands():
|
|
|
61
61
|
"""Retrieval commands for tissue, disease, sex, and age annotations."""
|
|
62
62
|
|
|
63
63
|
|
|
64
|
-
@retrieve_commands.command("
|
|
65
|
-
@
|
|
64
|
+
@retrieve_commands.command("age")
|
|
65
|
+
@click.option(
|
|
66
|
+
"--terms",
|
|
67
|
+
type=AGE_GROUP_OPT,
|
|
68
|
+
default="all",
|
|
69
|
+
help="Age groups to choose. Can combine like 'fetus,adult'.",
|
|
70
|
+
)
|
|
66
71
|
@retrieval_args
|
|
67
|
-
@
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
terms, level, mode, fmt, metadata, filters, output, log_level, quiet, direct
|
|
71
|
-
):
|
|
72
|
-
"""Retrieval command for tissue ontology terms."""
|
|
72
|
+
@logging_args
|
|
73
|
+
def retrieve_age(terms, level, fmt, metadata, filters, output, log_level, quiet):
|
|
74
|
+
"""Retrieval command for age group annotations."""
|
|
73
75
|
if metadata == "default":
|
|
74
76
|
metadata = level
|
|
75
77
|
|
|
@@ -78,17 +80,17 @@ def retrieve_tissues(
|
|
|
78
80
|
__name__, console=get_console(), level=log_level, log_dir=get_log_dir()
|
|
79
81
|
)
|
|
80
82
|
|
|
81
|
-
# hidden from user. Used to test annotation quality.
|
|
82
|
-
mode = check_direct(mode, direct, verbose, log)
|
|
83
83
|
builder = Builder(logger=log, verbose=verbose)
|
|
84
84
|
|
|
85
85
|
# parse and check filters
|
|
86
86
|
filters = builder.get_filters(filters)
|
|
87
87
|
|
|
88
88
|
# make configs
|
|
89
|
-
query_config = builder.query_config("geo", "
|
|
90
|
-
curation_config = builder.curation_config(terms,
|
|
91
|
-
output_config = builder.output_config(
|
|
89
|
+
query_config = builder.query_config("geo", "age", level, filters)
|
|
90
|
+
curation_config = builder.curation_config(terms, "direct", "age")
|
|
91
|
+
output_config = builder.output_config(
|
|
92
|
+
output, fmt, metadata, level=level, attribute="age"
|
|
93
|
+
)
|
|
92
94
|
|
|
93
95
|
# retrieve
|
|
94
96
|
retriever = Retriever(
|
|
@@ -98,10 +100,10 @@ def retrieve_tissues(
|
|
|
98
100
|
|
|
99
101
|
|
|
100
102
|
@retrieve_commands.command("diseases")
|
|
101
|
-
@
|
|
103
|
+
@click.option("--terms", type=str, default="MONDO:0004994,MONDO:0018177")
|
|
102
104
|
@retrieval_args
|
|
103
105
|
@ontology_retrieval_args
|
|
104
|
-
@
|
|
106
|
+
@logging_args
|
|
105
107
|
def retrieve_diseases(
|
|
106
108
|
terms, level, mode, fmt, metadata, filters, output, log_level, quiet, direct
|
|
107
109
|
):
|
|
@@ -124,7 +126,9 @@ def retrieve_diseases(
|
|
|
124
126
|
# make configs
|
|
125
127
|
query_config = builder.query_config("geo", "disease", level, filters)
|
|
126
128
|
curation_config = builder.curation_config(terms, mode, "mondo")
|
|
127
|
-
output_config = builder.output_config(
|
|
129
|
+
output_config = builder.output_config(
|
|
130
|
+
output, fmt, metadata, level=level, attribute="disease"
|
|
131
|
+
)
|
|
128
132
|
|
|
129
133
|
# retrieve
|
|
130
134
|
retriever = Retriever(
|
|
@@ -134,9 +138,9 @@ def retrieve_diseases(
|
|
|
134
138
|
|
|
135
139
|
|
|
136
140
|
@retrieve_commands.command("sex")
|
|
137
|
-
@logging_args
|
|
138
|
-
@retrieval_args
|
|
139
141
|
@click.option("--terms", type=str, default="male,female")
|
|
142
|
+
@retrieval_args
|
|
143
|
+
@logging_args
|
|
140
144
|
def retrieve_sex(terms, level, fmt, metadata, filters, output, log_level, quiet):
|
|
141
145
|
"""Retrieval command for sex annotations."""
|
|
142
146
|
if metadata == "default":
|
|
@@ -155,7 +159,9 @@ def retrieve_sex(terms, level, fmt, metadata, filters, output, log_level, quiet)
|
|
|
155
159
|
# make configs
|
|
156
160
|
query_config = builder.query_config("geo", "sex", level, filters)
|
|
157
161
|
curation_config = builder.curation_config(terms, "direct", "sex")
|
|
158
|
-
output_config = builder.output_config(
|
|
162
|
+
output_config = builder.output_config(
|
|
163
|
+
output, fmt, metadata, level=level, attribute="sex"
|
|
164
|
+
)
|
|
159
165
|
|
|
160
166
|
# retrieve
|
|
161
167
|
retriever = Retriever(
|
|
@@ -164,17 +170,15 @@ def retrieve_sex(terms, level, fmt, metadata, filters, output, log_level, quiet)
|
|
|
164
170
|
retriever.retrieve()
|
|
165
171
|
|
|
166
172
|
|
|
167
|
-
@retrieve_commands.command("
|
|
168
|
-
@
|
|
173
|
+
@retrieve_commands.command("tissues")
|
|
174
|
+
@click.option("--terms", type=str, default="UBERON:0000948,UBERON:0000955")
|
|
169
175
|
@retrieval_args
|
|
170
|
-
@
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
def retrieve_age(terms, level, fmt, metadata, filters, output, log_level, quiet):
|
|
177
|
-
"""Retrieval command for age group annotations."""
|
|
176
|
+
@ontology_retrieval_args
|
|
177
|
+
@logging_args
|
|
178
|
+
def retrieve_tissues(
|
|
179
|
+
terms, level, mode, fmt, metadata, filters, output, log_level, quiet, direct
|
|
180
|
+
):
|
|
181
|
+
"""Retrieval command for tissue ontology terms."""
|
|
178
182
|
if metadata == "default":
|
|
179
183
|
metadata = level
|
|
180
184
|
|
|
@@ -183,15 +187,19 @@ def retrieve_age(terms, level, fmt, metadata, filters, output, log_level, quiet)
|
|
|
183
187
|
__name__, console=get_console(), level=log_level, log_dir=get_log_dir()
|
|
184
188
|
)
|
|
185
189
|
|
|
190
|
+
# hidden from user. Used to test annotation quality.
|
|
191
|
+
mode = check_direct(mode, direct, verbose, log)
|
|
186
192
|
builder = Builder(logger=log, verbose=verbose)
|
|
187
193
|
|
|
188
194
|
# parse and check filters
|
|
189
195
|
filters = builder.get_filters(filters)
|
|
190
196
|
|
|
191
197
|
# make configs
|
|
192
|
-
query_config = builder.query_config("geo", "
|
|
193
|
-
curation_config = builder.curation_config(terms,
|
|
194
|
-
output_config = builder.output_config(
|
|
198
|
+
query_config = builder.query_config("geo", "tissue", level, filters)
|
|
199
|
+
curation_config = builder.curation_config(terms, mode, "uberon")
|
|
200
|
+
output_config = builder.output_config(
|
|
201
|
+
output, fmt, metadata, level=level, attribute="tissue"
|
|
202
|
+
)
|
|
195
203
|
|
|
196
204
|
# retrieve
|
|
197
205
|
retriever = Retriever(
|
|
@@ -22,7 +22,6 @@ DEFAULT_TOP_HITS = 3
|
|
|
22
22
|
|
|
23
23
|
|
|
24
24
|
@click.command(name="search", context_settings={"help_option_names": ["-h", "--help"]})
|
|
25
|
-
@logging_args
|
|
26
25
|
@click.option("--query", type=str, required=True, help="Search query")
|
|
27
26
|
@click.option(
|
|
28
27
|
"--db",
|
|
@@ -30,6 +29,7 @@ DEFAULT_TOP_HITS = 3
|
|
|
30
29
|
type=str,
|
|
31
30
|
default="default",
|
|
32
31
|
help="DuckDB file",
|
|
32
|
+
hidden=True,
|
|
33
33
|
)
|
|
34
34
|
@click.option(
|
|
35
35
|
"--type",
|
|
@@ -65,6 +65,7 @@ DEFAULT_TOP_HITS = 3
|
|
|
65
65
|
@click.option(
|
|
66
66
|
"--scopes", "-x", is_flag=True, default=False, help="Include scopes in synonym list"
|
|
67
67
|
)
|
|
68
|
+
@logging_args
|
|
68
69
|
def search(
|
|
69
70
|
query,
|
|
70
71
|
db,
|
|
@@ -4,15 +4,14 @@ Command to set up the meta-hq CLI.
|
|
|
4
4
|
Author: Parker Hicks
|
|
5
5
|
Date: 2025-09-05
|
|
6
6
|
|
|
7
|
-
Last updated: 2025-11-
|
|
7
|
+
Last updated: 2025-11-26 by Parker Hicks
|
|
8
8
|
"""
|
|
9
9
|
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
|
|
10
12
|
import click
|
|
11
13
|
from metahq_core.util.progress import console
|
|
12
|
-
from metahq_core.util.supported import
|
|
13
|
-
get_default_data_dir,
|
|
14
|
-
get_default_log_dir,
|
|
15
|
-
)
|
|
14
|
+
from metahq_core.util.supported import get_default_data_dir, get_default_log_dir
|
|
16
15
|
|
|
17
16
|
from metahq_cli.logger import setup_logger
|
|
18
17
|
from metahq_cli.setup.config import Config
|
|
@@ -22,18 +21,31 @@ from metahq_cli.util.helpers import set_verbosity
|
|
|
22
21
|
from metahq_cli.util.supported import LATEST_DATABASE
|
|
23
22
|
|
|
24
23
|
|
|
25
|
-
@click.command
|
|
26
|
-
@logging_args
|
|
27
|
-
@click.option("--doi", type=str, default="latest")
|
|
28
|
-
@click.option("--data-dir", type=click.Path(), default="default")
|
|
24
|
+
@click.command(name="setup", context_settings={"help_option_names": ["-h", "--help"]})
|
|
29
25
|
@click.option(
|
|
30
|
-
"
|
|
26
|
+
"-d",
|
|
27
|
+
"--doi",
|
|
31
28
|
type=str,
|
|
29
|
+
default="latest",
|
|
30
|
+
help="Zenodo DOI of the MetaHQ database. Default is `latest`.",
|
|
31
|
+
)
|
|
32
|
+
@click.option(
|
|
33
|
+
"-o",
|
|
34
|
+
"--data-dir",
|
|
35
|
+
type=click.Path(),
|
|
32
36
|
default="default",
|
|
33
|
-
help="Path to directory
|
|
37
|
+
help="Path to directory to store the database. Default is `/home/path/.metahq_data`.",
|
|
34
38
|
)
|
|
39
|
+
@click.option(
|
|
40
|
+
"-l",
|
|
41
|
+
"--log-dir",
|
|
42
|
+
type=click.Path(),
|
|
43
|
+
default="default",
|
|
44
|
+
help="Path to directory storing logs. Default is `/home/path/MetaHQ`.",
|
|
45
|
+
)
|
|
46
|
+
@logging_args
|
|
35
47
|
def setup(doi: str, data_dir: str, log_level: str, log_dir: str, quiet: bool):
|
|
36
|
-
"""
|
|
48
|
+
"""Download the MetaHQ database and configure the CLI."""
|
|
37
49
|
if log_dir == "default":
|
|
38
50
|
log_dir = str(get_default_log_dir())
|
|
39
51
|
|
|
@@ -48,7 +60,7 @@ def setup(doi: str, data_dir: str, log_level: str, log_dir: str, quiet: bool):
|
|
|
48
60
|
|
|
49
61
|
logger.info("Downloading MetaHQ database...")
|
|
50
62
|
downloader = Downloader(
|
|
51
|
-
doi, data_dir, logger=logger, logdir=log_dir, verbose=verbose
|
|
63
|
+
doi, data_dir, logger=logger, logdir=str(log_dir), verbose=verbose
|
|
52
64
|
)
|
|
53
65
|
downloader.get()
|
|
54
66
|
downloader.extract()
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"""
|
|
2
|
+
CLI command to validate data hasen't changed.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import click
|
|
6
|
+
from metahq_core.util.progress import console
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
import hashlib
|
|
9
|
+
|
|
10
|
+
from metahq_cli.logger import setup_logger
|
|
11
|
+
from metahq_cli.util.common_args import logging_args
|
|
12
|
+
from metahq_core.util.supported import get_default_log_dir
|
|
13
|
+
from metahq_cli.util.helpers import set_verbosity
|
|
14
|
+
|
|
15
|
+
from metahq_core.util.supported import get_config, get_config_file
|
|
16
|
+
from metahq_cli.util._validate import check_md5_match
|
|
17
|
+
|
|
18
|
+
@click.command(name="validate", context_settings={"help_option_names": ["-h", "--help"]})
|
|
19
|
+
@click.option(
|
|
20
|
+
"-l",
|
|
21
|
+
"--log-dir",
|
|
22
|
+
type=click.Path(),
|
|
23
|
+
default="default",
|
|
24
|
+
help="Path to directory storing logs. Default is `/home/path/MetaHQ`.",
|
|
25
|
+
)
|
|
26
|
+
@logging_args
|
|
27
|
+
def validate(log_level: str, log_dir: str, quiet: bool):
|
|
28
|
+
"""Validate files are unchanged"""
|
|
29
|
+
if log_dir == "default":
|
|
30
|
+
log_dir = str(get_default_log_dir())
|
|
31
|
+
|
|
32
|
+
logger = setup_logger(__name__, level=log_level, log_dir=log_dir, console=console)
|
|
33
|
+
verbose = set_verbosity(quiet)
|
|
34
|
+
|
|
35
|
+
# read in config
|
|
36
|
+
config = get_config()
|
|
37
|
+
config_path = get_config_file()
|
|
38
|
+
logger.info(f"The path to config file is found at: {config_path}")
|
|
39
|
+
logger.info(f"Validating the files for the config options: {config}")
|
|
40
|
+
|
|
41
|
+
changed_files = check_md5_match(config["zenodo_doi"], config["data_dir"])
|
|
42
|
+
|
|
43
|
+
if len(changed_files) == 0:
|
|
44
|
+
logger.info("Validation Passed: All files validated to be correct")
|
|
45
|
+
elif len(changed_files) > 0:
|
|
46
|
+
logger.warning(
|
|
47
|
+
f"Validation Failed: The following files are not the same as when downloaded. "
|
|
48
|
+
"Run `metahq setup` again."
|
|
49
|
+
)
|
|
50
|
+
for afile in changed_files:
|
|
51
|
+
logger.warning(afile)
|
|
@@ -4,13 +4,12 @@ Logger setup.
|
|
|
4
4
|
Author: Parker Hicks
|
|
5
5
|
Date: 2025-10-16
|
|
6
6
|
|
|
7
|
-
Last updated:
|
|
7
|
+
Last updated: 2026-02-04 by Parker Hicks
|
|
8
8
|
"""
|
|
9
9
|
|
|
10
10
|
from __future__ import annotations
|
|
11
11
|
|
|
12
12
|
import logging
|
|
13
|
-
from logging.handlers import TimedRotatingFileHandler
|
|
14
13
|
from pathlib import Path
|
|
15
14
|
from typing import TYPE_CHECKING
|
|
16
15
|
|
|
@@ -46,22 +45,22 @@ def setup_logger(
|
|
|
46
45
|
log_dir: str | Path,
|
|
47
46
|
level: int | str = logging.INFO,
|
|
48
47
|
) -> logging.Logger:
|
|
49
|
-
"""
|
|
50
|
-
|
|
48
|
+
"""Sets up a logger.
|
|
49
|
+
|
|
50
|
+
Arguments:
|
|
51
|
+
name (str):
|
|
52
|
+
Logger name.
|
|
51
53
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
name: str
|
|
55
|
-
Logger name.
|
|
54
|
+
console (rich.Console):
|
|
55
|
+
Console object to send logging information to.
|
|
56
56
|
|
|
57
|
-
|
|
58
|
-
|
|
57
|
+
log_dir (str | Path):
|
|
58
|
+
Path to logging directory.
|
|
59
59
|
|
|
60
|
-
|
|
61
|
-
|
|
60
|
+
level (int):
|
|
61
|
+
Logging level.
|
|
62
62
|
|
|
63
|
-
Returns
|
|
64
|
-
-------
|
|
63
|
+
Returns:
|
|
65
64
|
Configured logger.
|
|
66
65
|
|
|
67
66
|
"""
|
|
@@ -94,11 +93,8 @@ def setup_logger(
|
|
|
94
93
|
logger.addHandler(console_handler)
|
|
95
94
|
|
|
96
95
|
# file handler
|
|
97
|
-
file_handler =
|
|
96
|
+
file_handler = logging.FileHandler(
|
|
98
97
|
Path(log_dir) / "log.log",
|
|
99
|
-
when="midnight",
|
|
100
|
-
interval=1,
|
|
101
|
-
backupCount=30,
|
|
102
98
|
encoding="utf-8",
|
|
103
99
|
)
|
|
104
100
|
# file formatter
|
|
@@ -9,7 +9,7 @@ Last updated: 2025-09-05
|
|
|
9
9
|
|
|
10
10
|
import click
|
|
11
11
|
|
|
12
|
-
from metahq_cli.commands import retrieve_commands, search, setup, supported
|
|
12
|
+
from metahq_cli.commands import retrieve_commands, search, setup, supported, validate, delete
|
|
13
13
|
|
|
14
14
|
|
|
15
15
|
@click.group()
|
|
@@ -21,6 +21,8 @@ main.add_command(setup)
|
|
|
21
21
|
main.add_command(search)
|
|
22
22
|
main.add_command(supported)
|
|
23
23
|
main.add_command(retrieve_commands, name="retrieve")
|
|
24
|
+
main.add_command(validate)
|
|
25
|
+
main.add_command(delete)
|
|
24
26
|
|
|
25
27
|
if __name__ == "__main__":
|
|
26
28
|
main()
|