cgse-common 2023.1.5__tar.gz → 2024.1.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 (33) hide show
  1. cgse_common-2024.1.1/.gitignore +20 -0
  2. {cgse_common-2023.1.5 → cgse_common-2024.1.1}/PKG-INFO +29 -24
  3. {cgse_common-2023.1.5 → cgse_common-2024.1.1}/README.md +2 -2
  4. cgse_common-2024.1.1/pyproject.toml +63 -0
  5. {cgse_common-2023.1.5 → cgse_common-2024.1.1}/src/egse/config.py +7 -128
  6. {cgse_common-2023.1.5 → cgse_common-2024.1.1}/src/egse/control.py +0 -1
  7. {cgse_common-2023.1.5 → cgse_common-2024.1.1}/src/egse/decorators.py +8 -8
  8. {cgse_common-2023.1.5 → cgse_common-2024.1.1}/src/egse/env.py +0 -8
  9. {cgse_common-2023.1.5 → cgse_common-2024.1.1}/src/egse/resource.py +70 -2
  10. {cgse_common-2023.1.5 → cgse_common-2024.1.1}/src/egse/settings.yaml +2 -2
  11. cgse_common-2023.1.5/pyproject.toml +0 -51
  12. {cgse_common-2023.1.5 → cgse_common-2024.1.1}/src/egse/bits.py +0 -0
  13. {cgse_common-2023.1.5 → cgse_common-2024.1.1}/src/egse/command.py +0 -0
  14. {cgse_common-2023.1.5 → cgse_common-2024.1.1}/src/egse/device.py +0 -0
  15. {cgse_common-2023.1.5 → cgse_common-2024.1.1}/src/egse/exceptions.py +0 -0
  16. {cgse_common-2023.1.5 → cgse_common-2024.1.1}/src/egse/mixin.py +0 -0
  17. {cgse_common-2023.1.5 → cgse_common-2024.1.1}/src/egse/monitoring.py +0 -0
  18. {cgse_common-2023.1.5 → cgse_common-2024.1.1}/src/egse/observer.py +0 -0
  19. {cgse_common-2023.1.5 → cgse_common-2024.1.1}/src/egse/obsid.py +0 -0
  20. {cgse_common-2023.1.5 → cgse_common-2024.1.1}/src/egse/persistence.py +0 -0
  21. {cgse_common-2023.1.5 → cgse_common-2024.1.1}/src/egse/plugin.py +0 -0
  22. {cgse_common-2023.1.5 → cgse_common-2024.1.1}/src/egse/process.py +0 -0
  23. {cgse_common-2023.1.5 → cgse_common-2024.1.1}/src/egse/protocol.py +0 -0
  24. {cgse_common-2023.1.5 → cgse_common-2024.1.1}/src/egse/proxy.py +0 -0
  25. {cgse_common-2023.1.5 → cgse_common-2024.1.1}/src/egse/reload.py +0 -0
  26. {cgse_common-2023.1.5 → cgse_common-2024.1.1}/src/egse/services.py +0 -0
  27. {cgse_common-2023.1.5 → cgse_common-2024.1.1}/src/egse/services.yaml +0 -0
  28. {cgse_common-2023.1.5 → cgse_common-2024.1.1}/src/egse/settings.py +0 -0
  29. {cgse_common-2023.1.5 → cgse_common-2024.1.1}/src/egse/setup.py +0 -0
  30. {cgse_common-2023.1.5 → cgse_common-2024.1.1}/src/egse/state.py +0 -0
  31. {cgse_common-2023.1.5 → cgse_common-2024.1.1}/src/egse/system.py +0 -0
  32. {cgse_common-2023.1.5 → cgse_common-2024.1.1}/src/egse/version.py +0 -0
  33. {cgse_common-2023.1.5 → cgse_common-2024.1.1}/src/egse/zmq_ser.py +0 -0
@@ -0,0 +1,20 @@
1
+ .python-version
2
+ .envrc
3
+
4
+ build
5
+ dist
6
+
7
+ .DS_Store
8
+
9
+ __pycache__
10
+ .pytest_cache
11
+
12
+ .env
13
+ .venv
14
+ venv
15
+
16
+ .idea
17
+
18
+ **/*.egg-info
19
+
20
+ uv.lock
@@ -1,31 +1,37 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: cgse-common
3
- Version: 2023.1.5
4
- Summary: Software framework to support testing hardware
5
- Author: Rik Huygen
6
- Author-email: rik.huygen@kuleuven.be
7
- Requires-Python: >=3.8,<4.0
8
- Classifier: Programming Language :: Python :: 3
9
- Classifier: Programming Language :: Python :: 3.8
10
- Classifier: Programming Language :: Python :: 3.9
11
- Classifier: Programming Language :: Python :: 3.10
12
- Classifier: Programming Language :: Python :: 3.11
13
- Requires-Dist: GitPython (>=3.1.40,<4.0.0)
14
- Requires-Dist: PyYAML (>=6.0.1,<7.0.0)
15
- Requires-Dist: click (>=8.1.7,<9.0.0)
16
- Requires-Dist: deepdiff (>=6.6.1,<7.0.0)
17
- Requires-Dist: distro (>=1.8.0,<2.0.0)
18
- Requires-Dist: numpy
3
+ Version: 2024.1.1
4
+ Summary: Software framework to support hardware testing
5
+ Author: IVS KU Leuven
6
+ Maintainer-email: Rik Huygen <rik.huygen@kuleuven.be>, Sara Regibo <sara.regibo@kuleuven.be>
7
+ License-Expression: MIT
8
+ Keywords: CGSE,Common-EGSE,hardware testing,software framework
9
+ Requires-Python: >=3.9
10
+ Requires-Dist: click
11
+ Requires-Dist: deepdiff
12
+ Requires-Dist: distro
13
+ Requires-Dist: gitpython
14
+ Requires-Dist: numpy==1.22.4
19
15
  Requires-Dist: pandas
20
- Requires-Dist: prometheus-client (>=0.17.1,<0.18.0)
21
- Requires-Dist: psutil (>=5.9.6,<6.0.0)
22
- Requires-Dist: pyzmq (>=25.1.1,<26.0.0)
23
- Requires-Dist: rich (>=13.6.0,<14.0.0)
16
+ Requires-Dist: pip>=24.3.1
17
+ Requires-Dist: prometheus-client
18
+ Requires-Dist: psutil
19
+ Requires-Dist: pyyaml
20
+ Requires-Dist: pyzmq==23.2.1
21
+ Requires-Dist: rich
22
+ Provides-Extra: dev
23
+ Requires-Dist: pipdeptree; extra == 'dev'
24
+ Requires-Dist: ruff; extra == 'dev'
25
+ Requires-Dist: tomlkit; extra == 'dev'
26
+ Provides-Extra: test
27
+ Requires-Dist: pytest; extra == 'test'
28
+ Requires-Dist: pytest-cov; extra == 'test'
29
+ Requires-Dist: pytest-mock; extra == 'test'
24
30
  Description-Content-Type: text/markdown
25
31
 
26
- # Generic Functionality used in the PLATO Common-EGSE
32
+ # Generic Functionality used in the Common-EGSE
27
33
 
28
- This package 'cgse-common' contains functionality that is used by all `cgse` sub-packages, but it is designed to be a stand-alone generic package that can be used in any other project.
34
+ This package 'cgse-common' contains functionality that is used by all `cgse` sub-packages, but it is designed to be a stand-alone generic package that can be used also in any other project.
29
35
 
30
36
 
31
37
  ## Installation
@@ -56,4 +62,3 @@ A non-comprehensive list of available functionality:
56
62
  * **egse.resource**: provides convenience functions to use resources in your code without the need to specify an absolute path
57
63
  * **egse.system**: defines convenience functions that provide information on system specific functionality like, file system interactions, timing, operating system interactions, etc.
58
64
  * **egse.version**: functionality to retrieve the package version information
59
-
@@ -1,6 +1,6 @@
1
- # Generic Functionality used in the PLATO Common-EGSE
1
+ # Generic Functionality used in the Common-EGSE
2
2
 
3
- This package 'cgse-common' contains functionality that is used by all `cgse` sub-packages, but it is designed to be a stand-alone generic package that can be used in any other project.
3
+ This package 'cgse-common' contains functionality that is used by all `cgse` sub-packages, but it is designed to be a stand-alone generic package that can be used also in any other project.
4
4
 
5
5
 
6
6
  ## Installation
@@ -0,0 +1,63 @@
1
+ [project]
2
+ name = "cgse-common"
3
+ version = "2024.1.1"
4
+ description = "Software framework to support hardware testing"
5
+ authors = [
6
+ {name = "IVS KU Leuven"}
7
+ ]
8
+ maintainers = [
9
+ {name = "Rik Huygen", email = "rik.huygen@kuleuven.be"},
10
+ {name = "Sara Regibo", email = "sara.regibo@kuleuven.be"}
11
+ ]
12
+ readme = {"file" = "README.md", "content-type" = "text/markdown"}
13
+ requires-python = ">=3.9"
14
+ license = "MIT"
15
+ keywords = [
16
+ "CGSE",
17
+ "Common-EGSE",
18
+ "hardware testing",
19
+ "software framework"
20
+ ]
21
+ dependencies = [
22
+ "click",
23
+ "deepdiff",
24
+ "distro",
25
+ "gitpython",
26
+ "numpy == 1.22.4", # only used in setup
27
+ "pandas",
28
+ "pip>=24.3.1", # only used in setup
29
+ "prometheus-client",
30
+ "psutil",
31
+ "pyyaml",
32
+ "pyzmq == 23.2.1",
33
+ "rich",
34
+ ]
35
+
36
+ [project.optional-dependencies]
37
+ test = ["pytest", "pytest-mock", "pytest-cov"]
38
+ dev = ["pipdeptree", "tomlkit", "ruff"]
39
+
40
+ [project.entry-points."cgse.version"]
41
+ cgse-common = 'egse'
42
+
43
+ [tool.hatch.build.targets.sdist]
44
+ exclude = [
45
+ "/tests",
46
+ "/pytest.ini",
47
+ "/.gitignore",
48
+ "/*poetry*",
49
+ "/*setuptools*",
50
+ ]
51
+
52
+ [tool.hatch.build.targets.wheel]
53
+ packages = ["src/egse"]
54
+
55
+ [tool.ruff]
56
+ line-length = 120
57
+
58
+ [tool.ruff.lint]
59
+ extend-select = ["E501"]
60
+
61
+ [build-system]
62
+ requires = ["hatchling"]
63
+ build-backend = "hatchling.build"
@@ -4,13 +4,9 @@ and to find paths and resources.
4
4
  """
5
5
  from __future__ import annotations
6
6
 
7
- import errno
8
7
  import fnmatch
9
8
  import logging
10
9
  import os
11
- from functools import lru_cache
12
- from os.path import exists
13
- from os.path import join
14
10
  from pathlib import Path
15
11
  from pathlib import PurePath
16
12
  from typing import List
@@ -18,10 +14,8 @@ from typing import Optional
18
14
  from typing import Tuple
19
15
  from typing import Union
20
16
 
21
- import git
22
-
23
- HERE = Path(__file__).parent.resolve()
24
- MODULE_LOGGER = logging.getLogger(__name__)
17
+ _HERE = Path(__file__).parent.resolve()
18
+ _LOGGER = logging.getLogger(__name__)
25
19
 
26
20
 
27
21
  def find_first_occurrence_of_dir(pattern: str, root: Path | str = None) -> Optional[Path]:
@@ -43,7 +37,7 @@ def find_first_occurrence_of_dir(pattern: str, root: Path | str = None) -> Optio
43
37
  """
44
38
  import fnmatch
45
39
 
46
- root = Path(root).resolve() if root else HERE
40
+ root = Path(root).resolve() if root else _HERE
47
41
  if not root.is_dir():
48
42
  root = root.parent
49
43
 
@@ -171,7 +165,7 @@ def find_files(pattern: str, root: str = None, in_dir: str = None):
171
165
 
172
166
  def find_file(name: str, root: str = None, in_dir: str = None) -> Optional[Path]:
173
167
  """
174
- Find the path to the given file starting from the root directory of the Common-EGSE
168
+ Find the path to the given file starting from the root directory of the
175
169
  distribution.
176
170
 
177
171
  Note that if there are more files with the given name found in the distribution,
@@ -239,122 +233,6 @@ def find_root(
239
233
  return Path(default) if default is not None else None
240
234
 
241
235
 
242
- @lru_cache(maxsize=16)
243
- def get_common_egse_root(path: Union[str, PurePath] = None) -> Optional[PurePath]:
244
- """
245
- Returns the absolute path to the installation directory for the Common-EGSE.
246
-
247
- The algorithm first tries to determine the path from the environment variable
248
- ``PLATO_COMMON_EGSE_PATH``. If this environment variable doesn't exist, the algorithm
249
- tries to determine the path automatically from (1) the git root if it is a git repository,
250
- or (2) from the location of this module assuming the installation is done from the
251
- GitHub distribution.
252
-
253
- When the optional argument ``path`` is given, that directory will be used to start the
254
- search for the root folder.
255
-
256
- At this moment the algorithm does not cache the ``egse_path`` in order to speed up
257
- the successive calls to this function.
258
-
259
- Args:
260
- path (str or Path): a directory as a Path or str [optional]
261
-
262
- Returns:
263
- Path: the absolute path to the Common-EGSE installation directory or None
264
- """
265
- _TEST_NAMES = ("pyproject.toml", "setup.py")
266
- if path is not None:
267
- return find_root(path, tests=_TEST_NAMES)
268
-
269
- egse_path: Union[str, PurePath, None] = os.getenv("PLATO_COMMON_EGSE_PATH")
270
-
271
- if egse_path is None:
272
-
273
- # The root of the plato-common-egse installation shall be determined from the location
274
- # of this config module using git commands to find the git root folder.
275
- # This assumes the user has installed from git/GitHub (which is not always true)!
276
- #
277
- # Alternatively, the root directory can be determined from the location of this module
278
- # by going back in the directory structure until the ``setup.py`` module is found.
279
-
280
- _THIS_FILE_PATH = Path(__file__).resolve()
281
- _THIS_FILE_LOCATION = _THIS_FILE_PATH.parent
282
-
283
- try:
284
- git_repo = git.Repo(_THIS_FILE_PATH, search_parent_directories=True)
285
- git_root = git_repo.git.rev_parse("--show-toplevel")
286
- egse_path = git_root
287
- except (git.exc.InvalidGitRepositoryError, git.exc.NoSuchPathError):
288
- MODULE_LOGGER.info("no git repository found, assuming installation from distribution.")
289
- egse_path = find_root(_THIS_FILE_LOCATION, tests=_TEST_NAMES)
290
-
291
- MODULE_LOGGER.debug(f"Common-EGSE location is automatically determined: {egse_path}.")
292
-
293
- else:
294
- MODULE_LOGGER.debug(
295
- f"Common-EGSE location determined from environment variable "
296
- f"PLATO_COMMON_EGSE_PATH: {egse_path}"
297
- )
298
-
299
- return Path(egse_path)
300
-
301
-
302
- def get_resource_dirs(root_dir: Union[str, PurePath] = None) -> List[Path]:
303
- """
304
- Define directories that contain resources like images, icons, and data files.
305
-
306
- Resource directories can have the following names: `resources`, `data`, `icons`, or `images`.
307
- This function checks if any of the resource directories exist in the project root directory,
308
- in the `root_dir` that is given as an argument or in the `src/egse` sub-folder.
309
-
310
- So, the directories that are searched for the resource folders are:
311
-
312
- * `root_dir` or the project's root directory
313
- * the `src/egse` sub-folder of one of the above
314
-
315
- For all existing directories the function returns the absolute path.
316
-
317
- Args:
318
- root_dir (str): the directory to search for resource folders
319
-
320
- Returns:
321
- a list of absolute Paths.
322
- """
323
- project_dir = Path(root_dir).resolve() if root_dir else get_common_egse_root()
324
- result = []
325
- for dir_ in ["resources", "data", "icons", "images"]:
326
- if (project_dir / dir_).is_dir():
327
- result.append(Path(project_dir, dir_).resolve())
328
- if (project_dir / "src" / "egse" / dir_).is_dir():
329
- result.append(Path(project_dir, "src", "egse", dir_).resolve())
330
- return result
331
-
332
-
333
- def get_resource_path(name: str, resource_root_dir: Union[str, PurePath] = None) -> PurePath:
334
- """
335
- Searches for a data file (resource) with the given name.
336
-
337
- When `resource_root_dir` is not given, the search for resources will start at the root
338
- folder of the project (using the function `get_common_egse_root()`). Any other root
339
- directory can be given, e.g. if you want to start the search from the location of your
340
- source code file, use `Path(__file__).parent` as the `resource_root_dir` argument.
341
-
342
- Args:
343
- name (str): the name of the resource that is requested
344
- resource_root_dir (str): the root directory where the search for resources should be started
345
-
346
- Returns:
347
- the absolute path of the data file with the given name. The first name that matches
348
- is returned. If no file with the given name or path exists, a FileNotFoundError is raised.
349
-
350
- """
351
- for resource_dir in get_resource_dirs(resource_root_dir):
352
- resource_path = join(resource_dir, name)
353
- if exists(resource_path):
354
- return Path(resource_path).absolute()
355
- raise FileNotFoundError(errno.ENOENT, f"Could not locate resource '{name}'")
356
-
357
-
358
236
  def set_logger_levels(logger_levels: List[Tuple] = None):
359
237
  """
360
238
  Set the logging level for the given loggers.
@@ -368,7 +246,8 @@ def set_logger_levels(logger_levels: List[Tuple] = None):
368
246
 
369
247
 
370
248
  class WorkingDirectory:
371
- """WorkingDirectory is a context manager to temporarily change the working directory while
249
+ """
250
+ WorkingDirectory is a context manager to temporarily change the working directory while
372
251
  executing some code.
373
252
 
374
253
  This context manager has a property `path` which returns the absolute path of the
@@ -402,7 +281,7 @@ class WorkingDirectory:
402
281
  try:
403
282
  os.chdir(self._current_dir)
404
283
  except OSError as exc:
405
- MODULE_LOGGER.warning(f"Change back to previous directory failed: {exc}")
284
+ _LOGGER.warning(f"Change back to previous directory failed: {exc}")
406
285
 
407
286
  @property
408
287
  def path(self):
@@ -5,7 +5,6 @@ import abc
5
5
  import logging
6
6
  import pickle
7
7
  import threading
8
- import time
9
8
  from typing import Any
10
9
 
11
10
  import zmq
@@ -13,7 +13,7 @@ from typing import Optional
13
13
  from egse.settings import Settings
14
14
  from egse.system import get_caller_info
15
15
 
16
- MODULE_LOGGER = logging.getLogger(__name__)
16
+ _LOGGER = logging.getLogger(__name__)
17
17
 
18
18
 
19
19
  def static_vars(**kwargs):
@@ -95,7 +95,7 @@ def timer(*, level: int = logging.INFO, precision: int = 4):
95
95
  value = func(*args, **kwargs)
96
96
  end_time = time.perf_counter()
97
97
  run_time = end_time - start_time
98
- MODULE_LOGGER.log(level, f"Finished {func.__name__!r} in {run_time:.{precision}f} secs")
98
+ _LOGGER.log(level, f"Finished {func.__name__!r} in {run_time:.{precision}f} secs")
99
99
  return value
100
100
 
101
101
  return wrapper_timer
@@ -160,9 +160,9 @@ def debug(func):
160
160
  args_repr = [repr(a) for a in args]
161
161
  kwargs_repr = [f"{k}={v!r}" for k, v in kwargs.items()]
162
162
  signature = ", ".join(args_repr + kwargs_repr)
163
- MODULE_LOGGER.debug(f"Calling {func.__name__}({signature})")
163
+ _LOGGER.debug(f"Calling {func.__name__}({signature})")
164
164
  value = func(*args, **kwargs)
165
- MODULE_LOGGER.debug(f"{func.__name__!r} returned {value!r}")
165
+ _LOGGER.debug(f"{func.__name__!r} returned {value!r}")
166
166
  else:
167
167
  value = func(*args, **kwargs)
168
168
  return value
@@ -240,10 +240,10 @@ def profile(func):
240
240
  signature = ", ".join(args_repr + kwargs_repr)
241
241
  caller = get_caller_info(level=2)
242
242
  prefix = f"PROFILE[{profile.counter}]: "
243
- MODULE_LOGGER.info(f"{prefix}Calling {func.__name__}({signature})")
244
- MODULE_LOGGER.info(f"{prefix} from {caller.filename} at {caller.lineno}.")
243
+ _LOGGER.info(f"{prefix}Calling {func.__name__}({signature})")
244
+ _LOGGER.info(f"{prefix} from {caller.filename} at {caller.lineno}.")
245
245
  value = func(*args, **kwargs)
246
- MODULE_LOGGER.info(f"{prefix}{func.__name__!r} returned {value!r}")
246
+ _LOGGER.info(f"{prefix}{func.__name__!r} returned {value!r}")
247
247
  profile.counter -= 1
248
248
  else:
249
249
  value = func(*args, **kwargs)
@@ -257,7 +257,7 @@ def to_be_implemented(func):
257
257
 
258
258
  @functools.wraps(func)
259
259
  def wrapper_tbi(*args, **kwargs):
260
- MODULE_LOGGER.warning(f"The function/method {func.__name__} is not yet implemented.")
260
+ _LOGGER.warning(f"The function/method {func.__name__} is not yet implemented.")
261
261
  return func(*args, **kwargs)
262
262
 
263
263
  return wrapper_tbi
@@ -191,14 +191,6 @@ if __name__ == "__main__":
191
191
  rich.print("Generated locations and filenames")
192
192
 
193
193
  with all_logging_disabled():
194
- try:
195
- rich.print(f" {get_common_egse_root() = !s}", flush=True)
196
- location = get_common_egse_root()
197
- if not Path(location).exists():
198
- rich.print("[red]ERROR: The generated Common-EGSE location doesn't exist![/]")
199
- except ValueError as exc:
200
- rich.print(f" get_common_egse_path() = [red]{exc}[/]")
201
-
202
194
  try:
203
195
  rich.print(f" {get_data_storage_location() = }", flush=True)
204
196
  location = get_data_storage_location()
@@ -75,20 +75,25 @@ their functionality is fully replaced by this `egse.resource` module.
75
75
 
76
76
  """
77
77
 
78
+ import errno
78
79
  import logging
79
80
  import re
80
81
  from pathlib import Path
82
+ from pathlib import PurePath
81
83
  from typing import Dict
82
84
  from typing import List
83
85
  from typing import Union
84
86
 
87
+ from os.path import exists
88
+ from os.path import join
89
+
85
90
  from egse.config import find_first_occurrence_of_dir
86
91
  from egse.config import find_files
87
92
  from egse.exceptions import InternalError
88
93
  from egse.plugin import entry_points
89
94
  from egse.system import get_package_location
90
95
 
91
- LOGGER = logging.getLogger(__name__)
96
+ _LOGGER = logging.getLogger(__name__)
92
97
 
93
98
 
94
99
  class ResourceError(Exception):
@@ -106,6 +111,8 @@ class NoSuchFileError(ResourceError):
106
111
  __all__ = [
107
112
  "get_resource",
108
113
  "get_resource_locations",
114
+ "get_resource_dirs",
115
+ "get_resource_path",
109
116
  "add_resource_id",
110
117
  "initialise_resources",
111
118
  "ResourceError",
@@ -129,6 +136,8 @@ DEFAULT_RESOURCES = {
129
136
  "data": "/data",
130
137
  }
131
138
 
139
+ _RESOURCE_DIRS = ["resources", "icons", "images", "styles", "data"]
140
+
132
141
  resources = {}
133
142
 
134
143
 
@@ -180,6 +189,65 @@ def get_resource_locations() -> Dict[str, List[Path]]:
180
189
  return resources.copy()
181
190
 
182
191
 
192
+ def get_resource_dirs(root_dir: Union[str, PurePath]) -> List[Path]:
193
+ """
194
+ Define directories that contain resources like images, icons, and data files.
195
+
196
+ Resource directories can have the following names: `resources`, `data`, `icons`, or `images`.
197
+ This function checks if any of the resource directories exist in the `root_dir` that is given as an argument.
198
+
199
+ For all existing directories the function returns the absolute path.
200
+
201
+ If the argument root_dir is None, an empty list will be returned and a warning message will be issued.
202
+
203
+ Args:
204
+ root_dir (str): the directory to search for resource folders
205
+
206
+ Returns:
207
+ a list of absolute Paths.
208
+ """
209
+
210
+ if root_dir is None:
211
+ _LOGGER.warning("The argument root_dir can not be None, an empty list is returned.")
212
+ return []
213
+
214
+ root_dir = Path(root_dir).resolve()
215
+ if not root_dir.is_dir():
216
+ root_dir = root_dir.parent
217
+
218
+ result = []
219
+ for dir_ in _RESOURCE_DIRS:
220
+ if (root_dir / dir_).is_dir():
221
+ result.append(Path(root_dir, dir_).resolve())
222
+
223
+ return result
224
+
225
+
226
+ def get_resource_path(name: str, resource_root_dir: Union[str, PurePath] = None) -> PurePath:
227
+ """
228
+ Searches for a data file (resource) with the given name.
229
+
230
+ When `resource_root_dir` is not given, the search for resources will start at the root
231
+ folder of the project (using the function `get_common_egse_root()`). Any other root
232
+ directory can be given, e.g. if you want to start the search from the location of your
233
+ source code file, use `Path(__file__).parent` as the `resource_root_dir` argument.
234
+
235
+ Args:
236
+ name (str): the name of the resource that is requested
237
+ resource_root_dir (str): the root directory w_HERE the search for resources should be started
238
+
239
+ Returns:
240
+ the absolute path of the data file with the given name. The first name that matches
241
+ is returned. If no file with the given name or path exists, a FileNotFoundError is raised.
242
+
243
+ """
244
+ for resource_dir in get_resource_dirs(resource_root_dir):
245
+ resource_path = join(resource_dir, name)
246
+ if exists(resource_path):
247
+ return Path(resource_path).absolute()
248
+ raise FileNotFoundError(errno.ENOENT, f"Could not locate resource '{name}'")
249
+
250
+
183
251
  def initialise_resources(root: Union[Path, str] = Path(__file__).parent):
184
252
  """
185
253
  Initialise the default resources and any resource published by a package entry point.
@@ -215,7 +283,7 @@ def initialise_resources(root: Union[Path, str] = Path(__file__).parent):
215
283
  if location not in x:
216
284
  x.append(location)
217
285
 
218
- LOGGER.debug(f"Resources have been initialised: {resources = }")
286
+ _LOGGER.debug(f"Resources have been initialised: {resources = }")
219
287
 
220
288
 
221
289
  def print_resources():
@@ -1,6 +1,6 @@
1
1
  Common-EGSE:
2
- VERSION: 2023.38.0+CGSE # bump version here and below
3
- RELEASE: September 2023, 2023.38.0+CGSE
2
+ VERSION: 2024.1.0+CGSE # bump version here and below
3
+ RELEASE: December 2024, 2024.1.0+CGSE
4
4
 
5
5
  SITE:
6
6
  ID: XXX
@@ -1,51 +0,0 @@
1
- [tool.poetry]
2
- name = "cgse-common"
3
- version = "2023.1.5"
4
- description = "Software framework to support testing hardware"
5
- authors = [
6
- "Rik Huygen <rik.huygen@kuleuven.be>",
7
- "Sara Regibo <sara.regibo@kuleuven.be>",
8
- ]
9
- readme = "README.md"
10
- packages = [
11
- { include = "egse", from = "src" }
12
- ]
13
-
14
- [tool.poetry.dependencies]
15
- python = "^3.8"
16
- click = "^8.1.7"
17
- deepdiff = "^6.6.1"
18
- distro = "^1.8.0"
19
- GitPython = "^3.1.40"
20
- numpy = "*"
21
- pandas = "*"
22
- prometheus-client = "^0.17.1"
23
- psutil = "^5.9.6"
24
- PyYAML = "^6.0.1"
25
- pyzmq = "^25.1.1"
26
- rich = "^13.6.0"
27
-
28
- [tool.poetry.group.test.dependencies]
29
- pytest = "^7.4.2"
30
- pytest-mock = "^3.11.1"
31
- pytest-cov = "^4.1.0"
32
-
33
- [tool.poetry.group.dev.dependencies]
34
- pipdeptree = "^2.13.0"
35
- ruff = "^0.1.6"
36
-
37
- [tool.poetry.plugins."cgse.version"]
38
- cgse-common = 'egse'
39
-
40
- [tool.ruff]
41
- line-length = 120
42
-
43
- [tool.ruff.lint]
44
- # Add the `line-too-long` rule to the enforced rule set. By default, Ruff omits rules that
45
- # overlap with the use of a formatter, like Black, but we can override this behavior by
46
- # explicitly adding the rule.
47
- extend-select = ["E501"]
48
-
49
- [build-system]
50
- requires = ["poetry-core"]
51
- build-backend = "poetry.core.masonry.api"