cgse-common 2024.1.1__py3-none-any.whl

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.
egse/version.py ADDED
@@ -0,0 +1,178 @@
1
+ """
2
+ This module defines the version for the Common-EGSE release. Whenever a version number
3
+ or the release number is needed, this module shall be imported. The version and release
4
+ number is then available as:
5
+
6
+ >>> import egse.version
7
+ >>> print(f"version = {egse.version.VERSION}")
8
+
9
+ The actual numbers are updated for each release in the `settings.yaml` configuration file.
10
+
11
+ """
12
+ from __future__ import annotations
13
+
14
+ # WARNING: Make sure you are not importing any `egse` packages at the module level.
15
+ # This module is magically loaded by pip to determine the VERSION number before the
16
+ # package has been installed (see pyproject.py).
17
+ # Any imports from an 'egse' package will result in a ModuleNotFound error.
18
+
19
+ import os
20
+ import subprocess
21
+ from pathlib import Path
22
+
23
+ from egse.system import get_package_location
24
+
25
+ HERE = Path(__file__).parent.resolve()
26
+
27
+ __all__ = [
28
+ "get_version_installed",
29
+ "get_version_from_git",
30
+ "get_version_from_settings",
31
+ "VERSION",
32
+ ]
33
+
34
+
35
+ def get_version_from_settings_file_raw(group_name: str, location: Path | str = None) -> str:
36
+ """
37
+ Reads the VERSION field from the `settings.yaml` file in raw mode, meaning the file
38
+ is not read using the PyYAML module, but using the `readline()` function of the file
39
+ descriptor.
40
+
41
+ Args:
42
+ group_name: major group name that contains the VERSION field, i.e. Common-EGSE or PLATO_TEST_SCRIPTS.
43
+ location: the location of the `settings.yaml` file or None in which case the location of this file is used.
44
+
45
+ Raises:
46
+ A RuntimeError when the group_name is incorrect and unknown or the VERSION field is not found.
47
+
48
+ Returns:
49
+ The version from the `settings.yaml` file as a string.
50
+ """
51
+ basedir = location or os.path.dirname(__file__)
52
+
53
+ with open(os.path.join(basedir, "settings.yaml"), mode="r") as yaml_fd:
54
+ line = yaml_fd.readline()
55
+ if not line.startswith(group_name):
56
+ raise RuntimeError(f"Incompatible format for the settings.yaml file, should start with '{group_name}'")
57
+
58
+ line = yaml_fd.readline().lstrip()
59
+ if not line.startswith("VERSION"):
60
+ raise RuntimeError("Incompatible format for the settings.yaml file, no VERSION found.")
61
+ _, version = line.split(":")
62
+
63
+ # remove possible trailing comment starting with '#'
64
+ version, *_ = version.split("#")
65
+ version = version.strip()
66
+
67
+ return version
68
+
69
+
70
+ def get_version_from_settings(group_name: str, location: Path = None):
71
+ """
72
+ Reads the VERSION field from the `settings.yaml` file. This function first tries to load the proper Settings
73
+ and Group and if that fails uses the raw method.
74
+
75
+ Args:
76
+ group_name: major group name that contains the VERSION field, i.e. Common-EGSE or PLATO_TEST_SCRIPTS.
77
+ location: the location of the `settings.yaml` file or None in which case the location of this file is used.
78
+
79
+ Raises:
80
+ A RuntimeError when the group_name is incorrect and unknown or the VERSION field is not found.
81
+
82
+ Returns:
83
+ The version from the `settings.yaml` file as a string.
84
+ """
85
+ from egse.settings import Settings, SettingsError
86
+
87
+ try:
88
+ settings = Settings.load(group_name, location=location)
89
+ version = settings.VERSION
90
+ except (ModuleNotFoundError, SettingsError):
91
+ version = get_version_from_settings_file_raw(group_name, location=location)
92
+
93
+ return version
94
+
95
+
96
+ def get_version_from_git(location: str = None):
97
+ """
98
+ Returns the Git version number for the repository at the given location.
99
+
100
+ The returned string has the following format: YYYY.X.Y+REPO.TH-N-HASH, where:
101
+
102
+ * YYYY is the year
103
+ * X is the major version number and equal to the week number of the release
104
+ * Y is the minor version patch number
105
+ * REPO is the name of the repository, i.e. CGSE or TS
106
+ * TH is the name of the test house, i.e. CSL1, CSL2, IAS, INTA, SRON
107
+ * N is the number of commits since the release
108
+ * HASH is the Git hash number of the commit
109
+
110
+ Args:
111
+ location: The absolute path of the root or a sub-folder of the repo.
112
+
113
+ Returns:
114
+ The Git version number.
115
+ """
116
+ from egse.system import chdir
117
+
118
+ location = location or Path().cwd()
119
+
120
+ with chdir(location):
121
+ try:
122
+ std_out = subprocess.check_output(
123
+ ["git", "describe", "--tags", "--long", "--always"], stderr=subprocess.PIPE
124
+ )
125
+ version = std_out.strip().decode("ascii")
126
+ if "cgse" not in version.lower() and "ts" not in version.lower():
127
+ version = None
128
+ except subprocess.CalledProcessError as exc:
129
+ version = None
130
+
131
+ return version
132
+
133
+
134
+ def get_version_installed(package_name: str) -> str:
135
+ """
136
+ Returns the version that is installed, i.e. read from the metadata in the import lib.
137
+
138
+ Args:
139
+ package_name: the name of the installed package, e.g. cgse or cgse-ts
140
+
141
+ Returns:
142
+ The version of the installed repo.
143
+ """
144
+ from egse.system import chdir
145
+
146
+ with chdir(Path(__file__).parent):
147
+ from importlib.metadata import version, PackageNotFoundError
148
+
149
+ try:
150
+ version = version(package_name)
151
+ except PackageNotFoundError as exc:
152
+ version = None
153
+
154
+ return version
155
+
156
+
157
+ VERSION = get_version_from_settings_file_raw("Common-EGSE", location=HERE)
158
+
159
+ # The __PYPI_VERSION__ is the version number that will be used for the installation.
160
+ # The version will appear in PyPI and also as the `installed version`.
161
+
162
+ __PYPI_VERSION__ = VERSION.split('+')[0]
163
+
164
+
165
+ if __name__ == "__main__":
166
+ import rich
167
+ from egse.system import get_module_location
168
+ from egse.plugin import entry_points
169
+
170
+ if VERSION:
171
+ rich.print(f"CGSE version in Settings: [bold default]{VERSION}[/]")
172
+
173
+ if git_version := get_version_from_git(os.getcwd()):
174
+ rich.print(f"git version (current project) = [bold default]{git_version}[/]")
175
+
176
+ for ep in entry_points("cgse.version"):
177
+ if installed_version := get_version_installed(ep.name):
178
+ rich.print(f"Installed version for {ep.name}= [bold default]{installed_version}[/]")
egse/zmq_ser.py ADDED
@@ -0,0 +1,69 @@
1
+ import pickle
2
+ import zlib
3
+ from enum import IntEnum
4
+
5
+
6
+ def connect_address(transport, address, port):
7
+ """Returns a properly formatted URL to connect to."""
8
+ return f"{transport}://{address}:{port}"
9
+
10
+
11
+ def bind_address(transport, port):
12
+ """Returns a properly formatted url to bind a socket to."""
13
+ return f"{transport}://*:{port}"
14
+
15
+
16
+ def set_address_port(url: str, port: int):
17
+ """Returns a url where the 'port' part is replaced with the given port."""
18
+ transport, address, old_port = split_address(url)
19
+
20
+ return f"{transport}://{address}:{port}"
21
+
22
+
23
+ def split_address(url: str):
24
+
25
+ transport, address, port = url.split(":")
26
+ if address.startswith("//"):
27
+ address = address[2:]
28
+ return transport, address, port
29
+
30
+
31
+ def send_zipped_pickle(socket, obj, flags=0, protocol=-1):
32
+ """pickle an object, and zip the pickle before sending it"""
33
+ p = pickle.dumps(obj, protocol)
34
+ z = zlib.compress(p)
35
+ return socket.send(z, flags=flags)
36
+
37
+
38
+ def recv_zipped_pickle(socket, flags=0, protocol=-1):
39
+ """inverse of send_zipped_pickle"""
40
+ z = socket.recv(flags)
41
+ p = zlib.decompress(z)
42
+ return pickle.loads(p)
43
+
44
+
45
+ class MessageIdentifier(IntEnum):
46
+ """
47
+ The first item in a multipart message that can be used to subscribe, filter and identify
48
+ messages.
49
+ """
50
+
51
+ # ALL shall not be used in the multipart message itself, but exists as an indicator for
52
+ # subscribing to all messages. The ALL shall be converted into b'' when subscribing.
53
+
54
+ ALL = 0x00
55
+
56
+ # Synchronisation to DPU Processor at time of reception
57
+
58
+ SYNC_TIMECODE = 0x80
59
+ SYNC_HK_PACKET = 0x81
60
+ SYNC_DATA_PACKET = 0x82
61
+ SYNC_ERROR_FLAGS = 0x85
62
+ SYNC_HK_DATA = 0x86
63
+
64
+ N_FEE_REGISTER_MAP = 0x83
65
+ NUM_CYCLES = 0x84
66
+
67
+ # Sending out all kinds of information
68
+
69
+ HDF5_FILENAMES = 0x90