freva-client 2404.0.0__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.
Potentially problematic release.
This version of freva-client might be problematic. Click here for more details.
- freva_client-2404.0.0/MANIFEST.in +2 -0
- freva_client-2404.0.0/PKG-INFO +57 -0
- freva_client-2404.0.0/README.md +26 -0
- freva_client-2404.0.0/assets/share/freva/freva.toml +19 -0
- freva_client-2404.0.0/pyproject.toml +48 -0
- freva_client-2404.0.0/src/freva_client/__init__.py +20 -0
- freva_client-2404.0.0/src/freva_client/__main__.py +10 -0
- freva_client-2404.0.0/src/freva_client/cli/__init__.py +6 -0
- freva_client-2404.0.0/src/freva_client/cli/cli_app.py +22 -0
- freva_client-2404.0.0/src/freva_client/cli/cli_utils.py +165 -0
- freva_client-2404.0.0/src/freva_client/cli/databrowser_cli.py +454 -0
- freva_client-2404.0.0/src/freva_client/py.typed +0 -0
- freva_client-2404.0.0/src/freva_client/query.py +616 -0
- freva_client-2404.0.0/src/freva_client/utils/__init__.py +33 -0
- freva_client-2404.0.0/src/freva_client/utils/databrowser_utils.py +162 -0
- freva_client-2404.0.0/src/freva_client/utils/logger.py +91 -0
- freva_client-2404.0.0/src/tests/__init__.py +0 -0
- freva_client-2404.0.0/src/tests/conftest.py +90 -0
- freva_client-2404.0.0/src/tests/test_cli.py +136 -0
- freva_client-2404.0.0/src/tests/test_databrowser.py +116 -0
- freva_client-2404.0.0/src/tests/test_url.py +63 -0
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: freva-client
|
|
3
|
+
Version: 2404.0.0
|
|
4
|
+
Summary: Search for climate data based on key-value pairs
|
|
5
|
+
Author-email: "DKRZ, Clint" <freva@dkrz.de>
|
|
6
|
+
Requires-Python: >=3.8
|
|
7
|
+
Description-Content-Type: text/markdown
|
|
8
|
+
Classifier: Development Status :: 3 - Alpha
|
|
9
|
+
Classifier: Environment :: Console
|
|
10
|
+
Classifier: Intended Audience :: Developers
|
|
11
|
+
Classifier: Intended Audience :: Science/Research
|
|
12
|
+
Classifier: License :: OSI Approved :: BSD License
|
|
13
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Requires-Dist: appdirs
|
|
20
|
+
Requires-Dist: pyyaml
|
|
21
|
+
Requires-Dist: requests
|
|
22
|
+
Requires-Dist: rich
|
|
23
|
+
Requires-Dist: tomli
|
|
24
|
+
Requires-Dist: typer
|
|
25
|
+
Requires-Dist: tox ; extra == "dev"
|
|
26
|
+
Project-URL: Documentation, https://freva-clint.github.io/freva-nextgen
|
|
27
|
+
Project-URL: Issues, https://github.com/FREVA-CLINT/freva-nextgen/issues
|
|
28
|
+
Project-URL: Source, https://github.com/FREVA-CLINT/freva-nextgen/
|
|
29
|
+
Provides-Extra: dev
|
|
30
|
+
|
|
31
|
+
# A REST API for the freva databrowser
|
|
32
|
+
|
|
33
|
+
[](LICENSE)
|
|
34
|
+
[](https://www.python.org/downloads/release/python-312/)
|
|
35
|
+
[](https://freva-clint.github.io/freva-nextgen)
|
|
36
|
+
[](https://github.com/FREVA-CLINT/freva-nextgen/actions)
|
|
37
|
+
[](https://codecov.io/github/FREVA-CLINT/freva-nextgen)
|
|
38
|
+
|
|
39
|
+
The freva-client library is a small library that makes connections to the freva
|
|
40
|
+
server. The client library currently supports the following services:
|
|
41
|
+
|
|
42
|
+
- Freva databrowser: Search for climate and environmental datasets by sending
|
|
43
|
+
`key=value` pair search requests to the freva databrowser API.
|
|
44
|
+
|
|
45
|
+
## Installation
|
|
46
|
+
|
|
47
|
+
Installing the freva-client library is straight forward an can be achieved via:
|
|
48
|
+
|
|
49
|
+
```console
|
|
50
|
+
python3 -m pip install freva-client
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
For a basic usage consult the official documentation page.
|
|
54
|
+
## License
|
|
55
|
+
|
|
56
|
+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
|
57
|
+
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# A REST API for the freva databrowser
|
|
2
|
+
|
|
3
|
+
[](LICENSE)
|
|
4
|
+
[](https://www.python.org/downloads/release/python-312/)
|
|
5
|
+
[](https://freva-clint.github.io/freva-nextgen)
|
|
6
|
+
[](https://github.com/FREVA-CLINT/freva-nextgen/actions)
|
|
7
|
+
[](https://codecov.io/github/FREVA-CLINT/freva-nextgen)
|
|
8
|
+
|
|
9
|
+
The freva-client library is a small library that makes connections to the freva
|
|
10
|
+
server. The client library currently supports the following services:
|
|
11
|
+
|
|
12
|
+
- Freva databrowser: Search for climate and environmental datasets by sending
|
|
13
|
+
`key=value` pair search requests to the freva databrowser API.
|
|
14
|
+
|
|
15
|
+
## Installation
|
|
16
|
+
|
|
17
|
+
Installing the freva-client library is straight forward an can be achieved via:
|
|
18
|
+
|
|
19
|
+
```console
|
|
20
|
+
python3 -m pip install freva-client
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
For a basic usage consult the official documentation page.
|
|
24
|
+
## License
|
|
25
|
+
|
|
26
|
+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
## The new freva configuration file.
|
|
2
|
+
## This configuration files follows toml (https://toml.io) syntax and replaces
|
|
3
|
+
## the old evaluation_system.conf file.
|
|
4
|
+
#
|
|
5
|
+
[freva]
|
|
6
|
+
## This section configures the freva client. All settings related to freva
|
|
7
|
+
## are set here.
|
|
8
|
+
##
|
|
9
|
+
## The name of the specific freva instance. If you use multiple configurations
|
|
10
|
+
## for different freva instances the `project_name` entry allows you to
|
|
11
|
+
## later identify which configuration you were using.
|
|
12
|
+
# project_name = "freva"
|
|
13
|
+
|
|
14
|
+
##
|
|
15
|
+
## The host that runs the freva api system. In most cases this is just the
|
|
16
|
+
## url of the freva webpage, such as https://www.freva.dkrz.de.
|
|
17
|
+
## You can set a port by separating <hostname:port>
|
|
18
|
+
## for example freva.example.org:7777
|
|
19
|
+
# host = ""
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["flit_core >=3.2", "appdirs"]
|
|
3
|
+
build-backend = "flit_core.buildapi"
|
|
4
|
+
[project]
|
|
5
|
+
name = "freva-client"
|
|
6
|
+
dynamic = ["version"]
|
|
7
|
+
description = "Search for climate data based on key-value pairs"
|
|
8
|
+
authors = [{name = "DKRZ, Clint", email = "freva@dkrz.de"}]
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
classifiers = [
|
|
11
|
+
"Development Status :: 3 - Alpha",
|
|
12
|
+
"Environment :: Console",
|
|
13
|
+
"Intended Audience :: Developers",
|
|
14
|
+
"Intended Audience :: Science/Research",
|
|
15
|
+
"License :: OSI Approved :: BSD License",
|
|
16
|
+
"Operating System :: POSIX :: Linux",
|
|
17
|
+
"Programming Language :: Python :: 3",
|
|
18
|
+
"Programming Language :: Python :: 3.9",
|
|
19
|
+
"Programming Language :: Python :: 3.10",
|
|
20
|
+
"Programming Language :: Python :: 3.11",
|
|
21
|
+
"Programming Language :: Python :: 3.12",
|
|
22
|
+
]
|
|
23
|
+
requires-python = ">=3.8"
|
|
24
|
+
dependencies = [
|
|
25
|
+
"appdirs",
|
|
26
|
+
"pyyaml",
|
|
27
|
+
"requests",
|
|
28
|
+
"rich",
|
|
29
|
+
"tomli",
|
|
30
|
+
"typer",
|
|
31
|
+
]
|
|
32
|
+
[project.scripts]
|
|
33
|
+
freva-client = "freva_client:cli.app"
|
|
34
|
+
[project.urls]
|
|
35
|
+
Documentation = "https://freva-clint.github.io/freva-nextgen"
|
|
36
|
+
Issues = "https://github.com/FREVA-CLINT/freva-nextgen/issues"
|
|
37
|
+
Source = "https://github.com/FREVA-CLINT/freva-nextgen/"
|
|
38
|
+
|
|
39
|
+
[project.optional-dependencies]
|
|
40
|
+
dev = ["tox"]
|
|
41
|
+
|
|
42
|
+
[tool.flit.sdist]
|
|
43
|
+
include = ["assets/*"]
|
|
44
|
+
|
|
45
|
+
[tool.flit.external-data]
|
|
46
|
+
directory = "assets"
|
|
47
|
+
[package-data]
|
|
48
|
+
freva_deployment = ["py.typed"]
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"""Client software freva evaluation system framework (freva):
|
|
2
|
+
|
|
3
|
+
Freva, the free evaluation system framework, is a data search and analysis
|
|
4
|
+
platform developed by the atmospheric science community for the atmospheric
|
|
5
|
+
science community. With help of Freva researchers can:
|
|
6
|
+
|
|
7
|
+
- quickly and intuitively search for data stored at typical data centers that
|
|
8
|
+
host many datasets.
|
|
9
|
+
- create a common interface for user defined data analysis tools.
|
|
10
|
+
- apply data analysis tools in a reproducible manner.
|
|
11
|
+
|
|
12
|
+
The code described here is currently in testing phase. The client and server
|
|
13
|
+
library described in the documentation only support searching for data. If you
|
|
14
|
+
need to apply data analysis plugins, please visit the
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
from .query import databrowser
|
|
18
|
+
|
|
19
|
+
__version__ = "2404.0.0"
|
|
20
|
+
__all__ = ["databrowser", "__version__"]
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"""Freva the Free Evaluation System command line interface."""
|
|
2
|
+
|
|
3
|
+
import typer
|
|
4
|
+
from freva_client import __version__
|
|
5
|
+
from freva_client.utils import logger
|
|
6
|
+
from rich import print as pprint
|
|
7
|
+
|
|
8
|
+
APP_NAME: str = "freva-client"
|
|
9
|
+
|
|
10
|
+
app = typer.Typer(
|
|
11
|
+
name=APP_NAME,
|
|
12
|
+
help=__doc__,
|
|
13
|
+
add_completion=False,
|
|
14
|
+
callback=logger.set_cli,
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def version_callback(version: bool) -> None:
|
|
19
|
+
"""Print the version and exit."""
|
|
20
|
+
if version:
|
|
21
|
+
pprint(f"{APP_NAME}: {__version__}")
|
|
22
|
+
raise typer.Exit()
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
"""Utilities for the command line interface."""
|
|
2
|
+
|
|
3
|
+
import argparse
|
|
4
|
+
import inspect
|
|
5
|
+
from typing import Any, Callable, Dict, List, Optional, Tuple, cast
|
|
6
|
+
|
|
7
|
+
from freva_client import databrowser
|
|
8
|
+
from freva_client.cli.cli_app import app
|
|
9
|
+
from freva_client.utils import logger
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def parse_cli_args(cli_args: List[str]) -> Dict[str, List[str]]:
|
|
13
|
+
"""Convert the cli arguments to a dictionary."""
|
|
14
|
+
logger.debug("parsing command line arguments.")
|
|
15
|
+
kwargs = {}
|
|
16
|
+
for entry in cli_args:
|
|
17
|
+
key, _, value = entry.partition("=")
|
|
18
|
+
if value and key not in kwargs:
|
|
19
|
+
kwargs[key] = [value]
|
|
20
|
+
elif value:
|
|
21
|
+
kwargs[key].append(value)
|
|
22
|
+
logger.debug(kwargs)
|
|
23
|
+
return kwargs
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class Completer:
|
|
27
|
+
"""Base class for command line argument completers."""
|
|
28
|
+
|
|
29
|
+
def __init__(
|
|
30
|
+
self,
|
|
31
|
+
argv: List[str],
|
|
32
|
+
choices: Optional[Dict[str, Tuple[str, str]]] = None,
|
|
33
|
+
shell: str = "bash",
|
|
34
|
+
strip: bool = False,
|
|
35
|
+
flags_only: bool = False,
|
|
36
|
+
):
|
|
37
|
+
self.choices = choices or {}
|
|
38
|
+
self.strip = strip
|
|
39
|
+
self.argv = argv
|
|
40
|
+
self.flags_only = flags_only
|
|
41
|
+
if shell == "zsh":
|
|
42
|
+
self.get_print = self._print_zsh
|
|
43
|
+
elif shell == "fish":
|
|
44
|
+
self.get_print = self._print_fish
|
|
45
|
+
else:
|
|
46
|
+
self.get_print = self._print_default
|
|
47
|
+
|
|
48
|
+
def _print_zsh(self, choices: Dict[str, Tuple[str, str]]) -> List[str]:
|
|
49
|
+
out = []
|
|
50
|
+
for key, _help in choices.items():
|
|
51
|
+
if key.startswith("-"):
|
|
52
|
+
out.append(f"{key}[{_help}]")
|
|
53
|
+
else:
|
|
54
|
+
out.append(f"{key}: {_help}")
|
|
55
|
+
return out
|
|
56
|
+
|
|
57
|
+
def _print_fish(self, choices: Dict[str, Tuple[str, str]]) -> List[str]:
|
|
58
|
+
out = []
|
|
59
|
+
for key, _help in choices.items():
|
|
60
|
+
out.append(f"{key}: {_help}")
|
|
61
|
+
return out
|
|
62
|
+
|
|
63
|
+
def _print_default(self, choices: Dict[str, Tuple[str, str]]) -> List[str]:
|
|
64
|
+
out = []
|
|
65
|
+
for key, _help in choices.items():
|
|
66
|
+
if not key.startswith("-"):
|
|
67
|
+
out.append(f"{key}: {_help}")
|
|
68
|
+
else:
|
|
69
|
+
out.append(key)
|
|
70
|
+
return out
|
|
71
|
+
|
|
72
|
+
def _get_choices(self) -> Dict[str, Tuple[str, str]]:
|
|
73
|
+
"""Get the choices for databrowser command."""
|
|
74
|
+
|
|
75
|
+
facet_args = []
|
|
76
|
+
for arg in self.argv:
|
|
77
|
+
if len(arg.split("=")) == 2:
|
|
78
|
+
facet_args.append(arg)
|
|
79
|
+
search_keys = parse_cli_args(facet_args)
|
|
80
|
+
search = databrowser.metadata_search(
|
|
81
|
+
flavour="freva",
|
|
82
|
+
time=None,
|
|
83
|
+
host=None,
|
|
84
|
+
time_select="flexible",
|
|
85
|
+
multiversion=False,
|
|
86
|
+
extended_search=True,
|
|
87
|
+
fail_on_error=False,
|
|
88
|
+
**search_keys,
|
|
89
|
+
)
|
|
90
|
+
choices = {}
|
|
91
|
+
for att, values in search.items():
|
|
92
|
+
if att not in search_keys:
|
|
93
|
+
keys = ",".join([v for n, v in enumerate(values)])
|
|
94
|
+
choices[att] = (keys, "")
|
|
95
|
+
return choices
|
|
96
|
+
|
|
97
|
+
@property
|
|
98
|
+
def command_choices(self) -> Dict[str, Tuple[str, str]]:
|
|
99
|
+
"""Get the command line arguments for all sub commands."""
|
|
100
|
+
|
|
101
|
+
if self.flags_only:
|
|
102
|
+
return self.choices
|
|
103
|
+
choices = self._get_choices()
|
|
104
|
+
return {**self.choices, **choices}
|
|
105
|
+
|
|
106
|
+
def formated_print(self) -> None:
|
|
107
|
+
"""Print all choices to be processed by the shell completion function."""
|
|
108
|
+
|
|
109
|
+
out = self.get_print(self.command_choices)
|
|
110
|
+
for line in out:
|
|
111
|
+
if line.startswith("-") and self.strip and not self.flags_only:
|
|
112
|
+
continue
|
|
113
|
+
if not line.startswith("-") and self.flags_only:
|
|
114
|
+
continue
|
|
115
|
+
print(line)
|
|
116
|
+
|
|
117
|
+
@classmethod
|
|
118
|
+
def parse_choices(cls, argv: list[str]) -> "Completer":
|
|
119
|
+
"""Create the completion choices from given cmd arguments."""
|
|
120
|
+
parser = argparse.ArgumentParser(
|
|
121
|
+
description="Get choices for command line arguments"
|
|
122
|
+
)
|
|
123
|
+
parser.add_argument(
|
|
124
|
+
"--strip",
|
|
125
|
+
help="Do not print options starting with -",
|
|
126
|
+
default=False,
|
|
127
|
+
action="store_true",
|
|
128
|
+
)
|
|
129
|
+
parser.add_argument(
|
|
130
|
+
"--shell",
|
|
131
|
+
help="Set the target shell type.",
|
|
132
|
+
default=False,
|
|
133
|
+
)
|
|
134
|
+
parser.add_argument(
|
|
135
|
+
"--flags-only",
|
|
136
|
+
help="Only print options starting with -",
|
|
137
|
+
default=False,
|
|
138
|
+
action="store_true",
|
|
139
|
+
)
|
|
140
|
+
cli_app, args = parser.parse_known_args(argv)
|
|
141
|
+
main_choices = {c.name: (c, c.help) for c in app.registered_commands}
|
|
142
|
+
choices = {}
|
|
143
|
+
if args and args[0] == "freva-databrowser":
|
|
144
|
+
_ = args.pop(0)
|
|
145
|
+
if args[0] in main_choices:
|
|
146
|
+
signature = inspect.signature(
|
|
147
|
+
cast(Callable[..., Any], main_choices[args[0]][0].callback)
|
|
148
|
+
)
|
|
149
|
+
for param, value in signature.parameters.items():
|
|
150
|
+
if param in args or param == "search_keys":
|
|
151
|
+
continue
|
|
152
|
+
if hasattr(value.annotation, "__metadata__"):
|
|
153
|
+
option = value.annotation.__metadata__
|
|
154
|
+
else:
|
|
155
|
+
option = value.default
|
|
156
|
+
choices[option.param_decls[-1]] = option.help
|
|
157
|
+
else:
|
|
158
|
+
choices = {k: v[1] for k, v in main_choices.items()}
|
|
159
|
+
return cls(
|
|
160
|
+
args,
|
|
161
|
+
choices,
|
|
162
|
+
shell=cli_app.shell,
|
|
163
|
+
strip=cli_app.strip,
|
|
164
|
+
flags_only=cli_app.flags_only,
|
|
165
|
+
)
|