elapi 2.0.0__tar.gz → 2.0.1__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.
Files changed (69) hide show
  1. {elapi-2.0.0 → elapi-2.0.1}/PKG-INFO +18 -13
  2. {elapi-2.0.0 → elapi-2.0.1}/README.md +17 -12
  3. {elapi-2.0.0 → elapi-2.0.1}/pyproject.toml +1 -1
  4. elapi-2.0.1/src/elapi/VERSION +1 -0
  5. {elapi-2.0.0 → elapi-2.0.1}/src/elapi/cli/_plugin_handler.py +25 -3
  6. {elapi-2.0.0 → elapi-2.0.1}/src/elapi/cli/_venv_state_manager.py +2 -2
  7. {elapi-2.0.0 → elapi-2.0.1}/src/elapi/cli/elapi.py +17 -24
  8. {elapi-2.0.0 → elapi-2.0.1}/src/elapi/configuration/__init__.py +1 -0
  9. {elapi-2.0.0 → elapi-2.0.1}/src/elapi/configuration/config.py +1 -1
  10. elapi-2.0.0/src/elapi/VERSION +0 -1
  11. {elapi-2.0.0 → elapi-2.0.1}/LICENSE +0 -0
  12. {elapi-2.0.0 → elapi-2.0.1}/src/elapi/__init__.py +0 -0
  13. {elapi-2.0.0 → elapi-2.0.1}/src/elapi/_names.py +0 -0
  14. {elapi-2.0.0 → elapi-2.0.1}/src/elapi/api/__init__.py +0 -0
  15. {elapi-2.0.0 → elapi-2.0.1}/src/elapi/api/api.py +0 -0
  16. {elapi-2.0.0 → elapi-2.0.1}/src/elapi/api/endpoint.py +0 -0
  17. {elapi-2.0.0 → elapi-2.0.1}/src/elapi/api/validators.py +0 -0
  18. {elapi-2.0.0 → elapi-2.0.1}/src/elapi/cli/__init__.py +0 -0
  19. {elapi-2.0.0 → elapi-2.0.1}/src/elapi/cli/__main__.py +0 -0
  20. {elapi-2.0.0 → elapi-2.0.1}/src/elapi/cli/doc.py +0 -0
  21. {elapi-2.0.0 → elapi-2.0.1}/src/elapi/configuration/_config_history.py +0 -0
  22. {elapi-2.0.0 → elapi-2.0.1}/src/elapi/configuration/_overload_history.py +0 -0
  23. {elapi-2.0.0 → elapi-2.0.1}/src/elapi/configuration/log_file.py +0 -0
  24. {elapi-2.0.0 → elapi-2.0.1}/src/elapi/configuration/overridable_vars.py +0 -0
  25. {elapi-2.0.0 → elapi-2.0.1}/src/elapi/configuration/validators.py +0 -0
  26. {elapi-2.0.0 → elapi-2.0.1}/src/elapi/core_validators/__init__.py +0 -0
  27. {elapi-2.0.0 → elapi-2.0.1}/src/elapi/core_validators/base.py +0 -0
  28. {elapi-2.0.0 → elapi-2.0.1}/src/elapi/core_validators/path.py +0 -0
  29. {elapi-2.0.0 → elapi-2.0.1}/src/elapi/loggers/__init__.py +0 -0
  30. {elapi-2.0.0 → elapi-2.0.1}/src/elapi/loggers/base.py +0 -0
  31. {elapi-2.0.0 → elapi-2.0.1}/src/elapi/loggers/handlers/__init__.py +0 -0
  32. {elapi-2.0.0 → elapi-2.0.1}/src/elapi/loggers/handlers/file.py +0 -0
  33. {elapi-2.0.0 → elapi-2.0.1}/src/elapi/loggers/handlers/stderr.py +0 -0
  34. {elapi-2.0.0 → elapi-2.0.1}/src/elapi/path.py +0 -0
  35. {elapi-2.0.0 → elapi-2.0.1}/src/elapi/plugins/__init__.py +0 -0
  36. {elapi-2.0.0 → elapi-2.0.1}/src/elapi/plugins/bill_teams/__init__.py +0 -0
  37. {elapi-2.0.0 → elapi-2.0.1}/src/elapi/plugins/bill_teams/_doc.py +0 -0
  38. {elapi-2.0.0 → elapi-2.0.1}/src/elapi/plugins/bill_teams/bill_teams.py +0 -0
  39. {elapi-2.0.0 → elapi-2.0.1}/src/elapi/plugins/bill_teams/cli.py +0 -0
  40. {elapi-2.0.0 → elapi-2.0.1}/src/elapi/plugins/bill_teams/format.py +0 -0
  41. {elapi-2.0.0 → elapi-2.0.1}/src/elapi/plugins/bill_teams/generate_table.py +0 -0
  42. {elapi-2.0.0 → elapi-2.0.1}/src/elapi/plugins/bill_teams/invoice.py +0 -0
  43. {elapi-2.0.0 → elapi-2.0.1}/src/elapi/plugins/bill_teams/specification.py +0 -0
  44. {elapi-2.0.0 → elapi-2.0.1}/src/elapi/plugins/bill_teams/validators.py +0 -0
  45. {elapi-2.0.0 → elapi-2.0.1}/src/elapi/plugins/commons/__init__.py +0 -0
  46. {elapi-2.0.0 → elapi-2.0.1}/src/elapi/plugins/commons/cli_helpers.py +0 -0
  47. {elapi-2.0.0 → elapi-2.0.1}/src/elapi/plugins/commons/export.py +0 -0
  48. {elapi-2.0.0 → elapi-2.0.1}/src/elapi/plugins/commons/get_data_from_input_or_path.py +0 -0
  49. {elapi-2.0.0 → elapi-2.0.1}/src/elapi/plugins/commons/get_information.py +0 -0
  50. {elapi-2.0.0 → elapi-2.0.1}/src/elapi/plugins/commons/get_location_from_headers.py +0 -0
  51. {elapi-2.0.0 → elapi-2.0.1}/src/elapi/plugins/experiments/__init__.py +0 -0
  52. {elapi-2.0.0 → elapi-2.0.1}/src/elapi/plugins/experiments/_doc.py +0 -0
  53. {elapi-2.0.0 → elapi-2.0.1}/src/elapi/plugins/experiments/cli.py +0 -0
  54. {elapi-2.0.0 → elapi-2.0.1}/src/elapi/plugins/experiments/experiments.py +0 -0
  55. {elapi-2.0.0 → elapi-2.0.1}/src/elapi/plugins/experiments/formats.py +0 -0
  56. {elapi-2.0.0 → elapi-2.0.1}/src/elapi/plugins/show_config.py +0 -0
  57. {elapi-2.0.0 → elapi-2.0.1}/src/elapi/plugins/version.py +0 -0
  58. {elapi-2.0.0 → elapi-2.0.1}/src/elapi/styles/__init__.py +0 -0
  59. {elapi-2.0.0 → elapi-2.0.1}/src/elapi/styles/_markdown_doc.py +0 -0
  60. {elapi-2.0.0 → elapi-2.0.1}/src/elapi/styles/_missing.py +0 -0
  61. {elapi-2.0.0 → elapi-2.0.1}/src/elapi/styles/base.py +0 -0
  62. {elapi-2.0.0 → elapi-2.0.1}/src/elapi/styles/colors.py +0 -0
  63. {elapi-2.0.0 → elapi-2.0.1}/src/elapi/styles/format.py +0 -0
  64. {elapi-2.0.0 → elapi-2.0.1}/src/elapi/styles/highlight.py +0 -0
  65. {elapi-2.0.0 → elapi-2.0.1}/src/elapi/styles/rich_utils.py +0 -0
  66. {elapi-2.0.0 → elapi-2.0.1}/src/elapi/utils/__init__.py +0 -0
  67. {elapi-2.0.0 → elapi-2.0.1}/src/elapi/utils/messages.py +0 -0
  68. {elapi-2.0.0 → elapi-2.0.1}/src/elapi/utils/utils.py +0 -0
  69. {elapi-2.0.0 → elapi-2.0.1}/src/elapi/validators.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: elapi
3
- Version: 2.0.0
3
+ Version: 2.0.1
4
4
  Summary: elAPI is a powerful, extensible API client for eLabFTW.
5
5
  Home-page: https://www.urz.uni-heidelberg.de/en/service-catalogue/software-and-applications/elabftw
6
6
  License: AGPL-3.0-only
@@ -41,16 +41,16 @@ Description-Content-Type: text/markdown
41
41
 
42
42
  # elAPI
43
43
 
44
- <a href="https://pypi.org/project/elapi/">
45
- <img src="https://badge.fury.io/py/elapi.svg" alt="Package version">
46
- </a>
47
- <br />
48
- <br />
44
+ [![Package version](https://badge.fury.io/py/elapi.svg/?branch=main)](https://pypi.org/project/elapi)
45
+
49
46
  elAPI is a powerful, extensible API client for eLabFTW developed at
50
- the [University Computing Centre](https://www.urz.uni-heidelberg.de/en) (
51
- URZ, [FIRE](https://www.urz.uni-heidelberg.de/en/node/64/organisation/future-it-research-education) division) of
47
+ the [University Computing Centre](https://www.urz.uni-heidelberg.de/en)
48
+ (URZ, [FIRE](https://www.urz.uni-heidelberg.de/en/node/64/organisation/future-it-research-education) division) of
52
49
  [University of Heidelberg](https://www.uni-heidelberg.de/en). It supports serving all kinds of requests documented on
53
- [eLabFTW API documentation](https://doc.elabftw.net/api/v2/) with ease.
50
+ [eLabFTW API documentation](https://doc.elabftw.net/api/v2/) with ease. elAPI provides a simple interface via its CLI
51
+ executable, and numerous advanced APIs when it is used directly as a Python package.
52
+
53
+ ![elAPI features in a nutshell](./.assets/elapi_features.svg)
54
54
 
55
55
  **Example:**
56
56
 
@@ -60,9 +60,14 @@ From [the documentation](https://doc.elabftw.net/api/v2/#/Users/read-user):
60
60
  With elAPI you can do the following:
61
61
 
62
62
  ```sh
63
- $ elapi get users --id <id>
63
+ $ elapi get experiments -f csv --export ~/Downloads/
64
64
  ```
65
65
 
66
+ Once the command is run, in the background, elAPI will read host (eLab server) address, API key and various other
67
+ settings (see [configuration](#configuration)) from the configuration file `elapi.yml`, perform validation (e.g.,
68
+ whether the server address is valid), fetch all _experiments_ list, convert them to `CSV`, and export them to your
69
+ local `~/Downloads/` folder.
70
+
66
71
  ## Installation
67
72
 
68
73
  elAPI can be used both as a CLI tool and as a Python library. If you are interested in simply using elAPI's
@@ -128,7 +133,7 @@ host: <host API url>
128
133
  # Example: https://demo.elabftw.net/api/v2/
129
134
  # Note the host URL ends with the API endpoint
130
135
  api_token: <token with at least read-access>
131
- # You can generate an API token from eLabFTW user panel -> API keys tab.
136
+ # "A.k.a API key". You can generate an API token from eLabFTW user panel -> API keys tab.
132
137
  export_dir: ~/Downloads/elAPI
133
138
  unsafe_api_token_warning: true
134
139
  enable_http2: false
@@ -279,8 +284,8 @@ $ elapi experiments upload-attachment --id <experiment ID> --path <path to attac
279
284
  elAPI has seamless support with tight-integration for third-party plugins. A simple third-party plugin can be created in
280
285
  a few easy steps:
281
286
 
282
- 1. Create a new subfolder under `~/.local/share/elapi/plugins` with the name for your new plugin (e.g, a folder named "
283
- test")
287
+ 1. Create a new subfolder under `~/.local/share/elapi/plugins` with the name for your new plugin (e.g, a folder named
288
+ "test")
284
289
  2. Create a `cli.py` in the subfolder with the following snippet:
285
290
 
286
291
  ```python
@@ -1,15 +1,15 @@
1
1
  # elAPI
2
2
 
3
- <a href="https://pypi.org/project/elapi/">
4
- <img src="https://badge.fury.io/py/elapi.svg" alt="Package version">
5
- </a>
6
- <br />
7
- <br />
3
+ [![Package version](https://badge.fury.io/py/elapi.svg/?branch=main)](https://pypi.org/project/elapi)
4
+
8
5
  elAPI is a powerful, extensible API client for eLabFTW developed at
9
- the [University Computing Centre](https://www.urz.uni-heidelberg.de/en) (
10
- URZ, [FIRE](https://www.urz.uni-heidelberg.de/en/node/64/organisation/future-it-research-education) division) of
6
+ the [University Computing Centre](https://www.urz.uni-heidelberg.de/en)
7
+ (URZ, [FIRE](https://www.urz.uni-heidelberg.de/en/node/64/organisation/future-it-research-education) division) of
11
8
  [University of Heidelberg](https://www.uni-heidelberg.de/en). It supports serving all kinds of requests documented on
12
- [eLabFTW API documentation](https://doc.elabftw.net/api/v2/) with ease.
9
+ [eLabFTW API documentation](https://doc.elabftw.net/api/v2/) with ease. elAPI provides a simple interface via its CLI
10
+ executable, and numerous advanced APIs when it is used directly as a Python package.
11
+
12
+ ![elAPI features in a nutshell](./.assets/elapi_features.svg)
13
13
 
14
14
  **Example:**
15
15
 
@@ -19,9 +19,14 @@ From [the documentation](https://doc.elabftw.net/api/v2/#/Users/read-user):
19
19
  With elAPI you can do the following:
20
20
 
21
21
  ```sh
22
- $ elapi get users --id <id>
22
+ $ elapi get experiments -f csv --export ~/Downloads/
23
23
  ```
24
24
 
25
+ Once the command is run, in the background, elAPI will read host (eLab server) address, API key and various other
26
+ settings (see [configuration](#configuration)) from the configuration file `elapi.yml`, perform validation (e.g.,
27
+ whether the server address is valid), fetch all _experiments_ list, convert them to `CSV`, and export them to your
28
+ local `~/Downloads/` folder.
29
+
25
30
  ## Installation
26
31
 
27
32
  elAPI can be used both as a CLI tool and as a Python library. If you are interested in simply using elAPI's
@@ -87,7 +92,7 @@ host: <host API url>
87
92
  # Example: https://demo.elabftw.net/api/v2/
88
93
  # Note the host URL ends with the API endpoint
89
94
  api_token: <token with at least read-access>
90
- # You can generate an API token from eLabFTW user panel -> API keys tab.
95
+ # "A.k.a API key". You can generate an API token from eLabFTW user panel -> API keys tab.
91
96
  export_dir: ~/Downloads/elAPI
92
97
  unsafe_api_token_warning: true
93
98
  enable_http2: false
@@ -238,8 +243,8 @@ $ elapi experiments upload-attachment --id <experiment ID> --path <path to attac
238
243
  elAPI has seamless support with tight-integration for third-party plugins. A simple third-party plugin can be created in
239
244
  a few easy steps:
240
245
 
241
- 1. Create a new subfolder under `~/.local/share/elapi/plugins` with the name for your new plugin (e.g, a folder named "
242
- test")
246
+ 1. Create a new subfolder under `~/.local/share/elapi/plugins` with the name for your new plugin (e.g, a folder named
247
+ "test")
243
248
  2. Create a `cli.py` in the subfolder with the following snippet:
244
249
 
245
250
  ```python
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "elapi"
3
- version = "2.0.0"
3
+ version = "2.0.1"
4
4
  description = "elAPI is a powerful, extensible API client for eLabFTW."
5
5
  authors = [
6
6
  "Alexander Haller, Mahadi Xion <elabftw@uni-heidelberg.de>",
@@ -0,0 +1 @@
1
+ 2.0.1
@@ -82,25 +82,47 @@ class ExternalPluginLocationValidator(Validator):
82
82
  import os
83
83
  import yaml
84
84
  from ..configuration import (
85
+ APP_BRAND_NAME,
85
86
  EXTERNAL_LOCAL_PLUGIN_METADATA_FILE_NAME,
86
87
  EXTERNAL_LOCAL_PLUGIN_TYPER_APP_FILE_NAME,
87
88
  EXTERNAL_LOCAL_PLUGIN_METADATA_FILE_KEY_FILE_EXISTS,
88
89
  EXTERNAL_LOCAL_PLUGIN_METADATA_FILE_KEY_CLI_SCRIPT_PATH,
89
90
  EXTERNAL_LOCAL_PLUGIN_METADATA_FILE_KEY_VENV_PATH,
90
91
  EXTERNAL_LOCAL_PLUGIN_METADATA_FILE_KEY_PLUGIN_NAME,
92
+ EXTERNAL_LOCAL_PLUGIN_METADATA_FILE_NAME_PREFIX,
91
93
  CANON_YAML_EXTENSION,
94
+ CONFIG_FILE_EXTENSION,
92
95
  )
93
96
 
97
+ _CANON_PLUGIN_METADATA_FILE_NAME: str = (
98
+ f"{EXTERNAL_LOCAL_PLUGIN_METADATA_FILE_NAME_PREFIX}.{CANON_YAML_EXTENSION}"
99
+ )
94
100
  parsed_metadata: dict = {
95
101
  EXTERNAL_LOCAL_PLUGIN_METADATA_FILE_KEY_FILE_EXISTS: None,
96
102
  EXTERNAL_LOCAL_PLUGIN_METADATA_FILE_KEY_CLI_SCRIPT_PATH: None,
97
- # EXTERNAL_LOCAL_PLUGIN_METADATA_FILE_KEY_VENV_PATH: None,
98
103
  EXTERNAL_LOCAL_PLUGIN_METADATA_FILE_KEY_PLUGIN_NAME: None,
99
104
  }
100
105
 
101
106
  if self.location.is_dir():
102
107
  actual_cwd = Path.cwd()
103
108
  os.chdir(self.location)
109
+ if (
110
+ _canon_plugin_metadata_file := (
111
+ self.location / _CANON_PLUGIN_METADATA_FILE_NAME
112
+ )
113
+ ).exists():
114
+ import logging
115
+
116
+ message = (
117
+ f"File '{_canon_plugin_metadata_file.name}' detected in location {_canon_plugin_metadata_file}. "
118
+ f"If it is meant to be an {APP_BRAND_NAME} plugin metadata file, "
119
+ f"please rename the file extension from '{CANON_YAML_EXTENSION}' "
120
+ f"to '{CONFIG_FILE_EXTENSION}'. "
121
+ f"{APP_BRAND_NAME} only supports '{CONFIG_FILE_EXTENSION}' "
122
+ f"as file extension for plugin metadata files."
123
+ )
124
+ add_message(message, logging.INFO)
125
+
104
126
  if (
105
127
  plugin_metadata_file := (
106
128
  self.location / EXTERNAL_LOCAL_PLUGIN_METADATA_FILE_NAME
@@ -136,7 +158,7 @@ class ExternalPluginLocationValidator(Validator):
136
158
  else:
137
159
  try:
138
160
  CLI_SCRIPT_PATH = ProperPath(CLI_SCRIPT_PATH)
139
- except ValueError:
161
+ except (TypeError, ValueError):
140
162
  raise ValidationError(
141
163
  f"Key '{EXTERNAL_LOCAL_PLUGIN_METADATA_FILE_KEY_CLI_SCRIPT_PATH}' "
142
164
  f"exists in {plugin_metadata_file}, but its assigned "
@@ -164,7 +186,7 @@ class ExternalPluginLocationValidator(Validator):
164
186
  else:
165
187
  try:
166
188
  VENV_PATH = ProperPath(VENV_PATH)
167
- except ValueError:
189
+ except (TypeError, ValueError):
168
190
  raise ValidationError(
169
191
  f"Key '{EXTERNAL_LOCAL_PLUGIN_METADATA_FILE_KEY_VENV_PATH}' "
170
192
  f"exists in {plugin_metadata_file}, but its assigned "
@@ -6,7 +6,7 @@ from ..path import ProperPath
6
6
  VENV_INDICATOR_DIR_NAME: str = "site-packages"
7
7
 
8
8
 
9
- def switch_venv_state(status: bool, /, venv_dir: Union[Path, ProperPath]):
9
+ def switch_venv_state(state: bool, /, venv_dir: Union[Path, ProperPath]):
10
10
  import sys
11
11
 
12
12
  site_packages = sorted(
@@ -20,7 +20,7 @@ def switch_venv_state(status: bool, /, venv_dir: Union[Path, ProperPath]):
20
20
  )
21
21
  for unique_dir in site_packages:
22
22
  unique_dir = str(unique_dir)
23
- if status is True:
23
+ if state is True:
24
24
  sys.path.insert(1, unique_dir)
25
25
  return
26
26
  else:
@@ -135,6 +135,21 @@ def cli_startup(
135
135
  reinitiate_config(ignore_essential_validation=True)
136
136
 
137
137
 
138
+ def cli_switch_venv_state(state: bool, /) -> None:
139
+ import click
140
+ from ._venv_state_manager import switch_venv_state
141
+
142
+ try:
143
+ venv_dir = EXTERNAL_LOCAL_PLUGIN_NAME_REGISTRY[
144
+ click.get_current_context().command.name
145
+ ].venv
146
+ except KeyError:
147
+ ...
148
+ else:
149
+ if venv_dir is not None:
150
+ switch_venv_state(state, venv_dir)
151
+
152
+
138
153
  def cli_startup_for_plugins(
139
154
  override_config: Annotated[
140
155
  Optional[str],
@@ -147,21 +162,10 @@ def cli_startup_for_plugins(
147
162
  ),
148
163
  ] = None,
149
164
  ):
150
- import click
151
165
  from ..styles import print_typer_error
152
166
  from ..validators import Exit
153
- from ._venv_state_manager import switch_venv_state
154
-
155
- try:
156
- switch_venv_state(
157
- True,
158
- EXTERNAL_LOCAL_PLUGIN_NAME_REGISTRY[
159
- click.get_current_context().command.name
160
- ].venv,
161
- )
162
- except KeyError:
163
- ...
164
167
 
168
+ cli_switch_venv_state(True)
165
169
  if override_config is not None:
166
170
  print_typer_error(
167
171
  f"--override-config/--OC can only be passed after "
@@ -172,18 +176,7 @@ def cli_startup_for_plugins(
172
176
 
173
177
 
174
178
  def cli_cleanup_for_third_party_plugins(*args, override_config=None):
175
- import click
176
- from ._venv_state_manager import switch_venv_state
177
-
178
- try:
179
- switch_venv_state(
180
- False,
181
- EXTERNAL_LOCAL_PLUGIN_NAME_REGISTRY[
182
- click.get_current_context().command.name
183
- ].venv,
184
- )
185
- except KeyError:
186
- ...
179
+ cli_switch_venv_state(False)
187
180
 
188
181
 
189
182
  for _app in internal_plugin_typer_apps:
@@ -30,6 +30,7 @@ from .config import (
30
30
  ENABLE_HTTP2,
31
31
  DEVELOPMENT_MODE,
32
32
  TMP_DIR,
33
+ CONFIG_FILE_EXTENSION,
33
34
  CANON_YAML_EXTENSION,
34
35
  EXTERNAL_LOCAL_PLUGIN_DIRECTORY_NAME,
35
36
  EXTERNAL_LOCAL_PLUGIN_DIR,
@@ -65,7 +65,7 @@ for path in [
65
65
  if path.exists():
66
66
  message = (
67
67
  f"File '{_CANON_CONFIG_FILE_NAME}' detected in location {path}. "
68
- f"If it is meant to be {APP_NAME} configuration file, "
68
+ f"If it is meant to be an {APP_NAME} configuration file, "
69
69
  f"please rename the file extension from '{CANON_YAML_EXTENSION}' "
70
70
  f"to '{CONFIG_FILE_EXTENSION}'. {APP_NAME} only supports '{CONFIG_FILE_EXTENSION}' "
71
71
  f"as file extension for configuration files."
@@ -1 +0,0 @@
1
- 2.0.0
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes