Coverage for /Users/rik/github/cgse/libs/cgse-common/src/egse/env.py: 26%

1"""

2 This module provides functionality to work with and check your environment variables.

3

4 The module provides functions to get/set the location of the data storage, the configuration data, and the log files.

5 The locations are determined from the environment variables that are set for the project.

6

7 Two important and mandatory environment variables are PROJECT and SITE_ID. The PROJECT environment variable is

8 used to construct the names of the other environment variables that are specific to the project. The SITE_ID

9 environment variable is used in the value that is returned for some the of project specific environment variables.

10

11 Mandatory environment variables:

12

13- PROJECT: the name of the project, e.g. PLATO, ARIEL. [shall be UPPER case]

14- SITE_ID: the site identifier, e.g. the lab name or organisation acronym. [shall be UPPER case]

15

16 The following environment variables are used by the project:

17

18- `<PROJECT>_DATA_STORAGE_LOCATION`: the root of the data storage location.

19- `<PROJECT>_CONF_DATA_LOCATION`: the location of the configuration data.

20- `<PROJECT>_CONF_REPO_LOCATION`: the location of the configuration data GitHub repository.

21- `<PROJECT>_LOG_FILE_LOCATION`: the location of the log files.

22- `<PROJECT>_LOCAL_SETTINGS`: the YAML file that contains site specific local settings.

23

24 Do not use the environment variables directly in your code, but use the functions provided by this module to get the

25 locations and settings.

26

27- `get_data_storage_location()`: returns the full path of the data storage location.

28- `get_conf_data_location()`: returns the full path of the location of the configuration data.

29- `get_conf_repo_location()`: returns the full path of the location of the configuration data repository.

30- `get_log_file_location()`: returns the full path of the location of the log files.

31- `get_local_settings()`: returns the fully qualified filename of the local settings YAML file.

32

33!!! warning

34

35 These environment variables shall not be changed outside the processes that use them and also not using the

36 `os.environ` within the code. For the known environment variables, use the dedicated 'setters' that are provided

37 by this module. If there is a need to change the environment variables, e.g. in unit tests, make sure to call the

38 `egse.env.initialize()` to reset the proper state.

39

40"""

41

42 from __future__ import annotations

43

44 __all__ = [

45 "env_var",

46 "get_conf_data_location",

47 "get_conf_data_location_env_name",

48 "get_conf_repo_location",

49 "get_conf_repo_location_env_name",

50 "get_data_storage_location",

51 "get_data_storage_location_env_name",

52 "get_local_settings_path",

53 "get_local_settings_env_name",

54 "get_log_file_location",

55 "get_log_file_location_env_name",

56 "get_project_name",

57 "get_site_id",

58 "set_conf_data_location",

59 "set_conf_repo_location",

60 "set_data_storage_location",

61 "set_local_settings",

62 "set_log_file_location",

63]

64

65 import contextlib

66 import os

67 import warnings

68 from pathlib import Path

69

70 from egse.log import logger

71 from egse.system import all_logging_disabled

72 from egse.system import get_caller_info

73 from egse.system import ignore_m_warning

74

75 from rich.console import Console

76

77 console = Console(width=100)

78

79# Every project shall have a PROJECT and a SITE_ID environment variable set. This variable will be used to

80# create the other environment variables that are specific to the project.

81

82 MANDATORY_ENVIRONMENT_VARIABLES = [

83 "PROJECT",

84 "SITE_ID",

85]

86

87# The environment variables that are known to be used by the project. These environment variables shall be set

88# as ${PROJECT}_<variable name>, e.g. PLATO_DATA_STORAGE_LOCATION. For each of these variables, there is a

89# corresponding function that will return the value of the environment variable. The environment variable is not

90# mandatory and if not set, a LookupError will be raised.

91

92 KNOWN_PROJECT_ENVIRONMENT_VARIABLES = [

93 "DATA_STORAGE_LOCATION",

94 "CONF_DATA_LOCATION",

95 "CONF_REPO_LOCATION",

96 "LOG_FILE_LOCATION",

97 "LOCAL_SETTINGS",

98]

99

100

101 def initialize():

102 """

103 Initialize the environment variables that are required for the CGSE to function properly.

104 This function will print a warning if any of the mandatory environment variables is not set.

105

106 This function is automatically called on import and can be called whenever the environment

107 variables have been changed, e.g. in unit tests.

108 """

109

110 global _env

111

112 for name in MANDATORY_ENVIRONMENT_VARIABLES:

113 try:

114 _env.set(name, os.environ[name])

115 except KeyError:

116 logger.warning(

117 f"The environment variable {name} is not set. {name} is required to define the project settings and "

118 f"environment variables. Please set the environment variable {name} before proceeding."

119 )

120 _env.set(name, NoValue())

121

122 project = _env.get("PROJECT")

123

124 for gen_var_name in KNOWN_PROJECT_ENVIRONMENT_VARIABLES:

125 env_var = f"{project}_{gen_var_name}"

126 _env.set(gen_var_name, os.environ.get(env_var, NoValue()))

127

128

129 class _Env:

130 """Internal class that keeps track of the environment variables."""

131

132 def __init__(self):

133 self._env = {}

134

135 def set(self, key, value):

136 if value is None: 136 ↛ 137line 136 didn't jump to line 137 because the condition on line 136 was never true

137 if key in self._env:

138 del self._env[key]

139 else:

140 self._env[key] = value

141

142 def get(self, key) -> str:

143 return self._env.get(key, NoValue())

144

145 def __rich__(self):

146 return self._env

147

148

149 _env = _Env()

150

151

152 class NoValue:

153 """

154 Represents a no value object, an environment variable that was not set.

155

156 The truth value of this object is always False, and it is equal to any other NoValue object.

157 """

158

159 def __eq__(self, other):

160 if isinstance(other, NoValue):

161 return True

162 return False

163

164 def __bool__(self):

165 return False

166

167 def __repr__(self):

168 return f"{self.__class__.__name__}"

169

170

171# The module needs to be initialized before it can be used.

172 initialize()

173

174

175 def _check_no_value(var_name, value):

176 """Raise a ValueError when the value for the variable is NoValue."""

177 if value == NoValue():

178 project = _env.get("PROJECT")

179 env_name = var_name if var_name in ("PROJECT", "SITE_ID") else f"{project}_{var_name}"

180 raise ValueError(

181 f"The environment variable {env_name} is not set. Please set the environment variable before proceeding."

182 )

183

184

185 def set_default_environment(

186 project: str,

187 site_id: str,

188 data_storage_location: str | Path,

189 conf_data_location: str | Path | None = None,

190 conf_repo_location: str | Path | None = None,

191 log_file_location: str | Path | None = None,

192 local_settings: str | Path | None = None,

193):

194 set_project_name(project)

195 set_site_id(site_id)

196 set_data_storage_location(data_storage_location)

197 set_conf_data_location(conf_data_location)

198 set_conf_repo_location(conf_repo_location)

199 set_log_file_location(log_file_location)

200 set_local_settings(local_settings)

201

202

203 def get_project_name() -> str:

204 """Get the PROJECT name. Return None when the PROJECT is not set."""

205 return _env.get("PROJECT") or None

206

207

208 def set_project_name(name: str):

209 """Set the environment variable PROJECT and its internal representation."""

210 os.environ["PROJECT"] = name

211 _env.set("PROJECT", name)

212

213

214 def get_site_id() -> str:

215 """Get the SITE_ID. Return None if the SITE_ID is not set."""

216 return _env.get("SITE_ID") or None

217

218

219 def set_site_id(name: str):

220 """Set the environment variable SITE_ID and its internal representation."""

221 os.environ["SITE_ID"] = name

222 _env.set("SITE_ID", name)

223

224

225 def get_data_storage_location_env_name() -> str:

226 """Returns the name of the environment variable for the project."""

227 project = _env.get("PROJECT")

228 return f"{project}_DATA_STORAGE_LOCATION"

229

230

231 def set_data_storage_location(location: str | Path | None):

232 """

233 Sets the environment variable and the internal representation to the given value.

234

235 Warning:

236 Issues a warning when the given location doesn't exist.

237 """

238 env_name = get_data_storage_location_env_name()

239

240 if location is None:

241 if env_name in os.environ:

242 del os.environ[env_name]

243 _env.set("DATA_STORAGE_LOCATION", None)

244 return

245

246 if not Path(location).exists():

247 warnings.warn(f"The location you provided for the environment variable {env_name} doesn't exist: {location}.")

248

249 os.environ[env_name] = str(location)

250 _env.set("DATA_STORAGE_LOCATION", str(location))

251

252

253 def get_data_storage_location(site_id: str = None) -> str:

254 """

255 Returns the full path of the data storage location for the given site_id.

256

257 If the site_id is None, it is determined from the environment variable SITE_ID.

258

259 If the `${PROJECT}_DATA_STORAGE_LOCATION` environment variable does not end with

260 the site_id, the site_id will be appended to the path on return. That means

261 the actual data storage location will always be site specific.

262

263 Note:

264 when you specify the `site_id` as an argument, it takes precedence

265 over the SITE_ID environment variable.

266

267 Args:

268 site_id: the site identifier (to be used instead of the SITE_ID environment variable)

269

270 Returns:

271 The full path of data storage location as a string.

272

273 Raises:

274 ValueError: when the SITE_ID or the ${PROJECT}_DATA_STORAGE_LOCATION is not set.

275 """

276 global _env

277

278 project = _env.get("PROJECT")

279 _check_no_value("PROJECT", project)

280

281 site_id = site_id or _env.get("SITE_ID")

282 _check_no_value("SITE_ID", site_id)

283

284 data_root = _env.get("DATA_STORAGE_LOCATION")

285 _check_no_value("DATA_STORAGE_LOCATION", data_root)

286

287 data_root = data_root.rstrip("/")

288

289 return data_root if data_root.endswith(site_id) else f"{data_root}/{site_id}"

290

291

292 def get_conf_data_location_env_name() -> str:

293 """Returns the name of the environment variable for the project."""

294 project = _env.get("PROJECT")

295 return f"{project}_CONF_DATA_LOCATION"

296

297

298 def set_conf_data_location(location: str | Path | None):

299 """

300 Sets the environment variable and the internal representation to the given value.

301

302 Warning:

303 Issues a warning when the given location doesn't exist.

304 """

305

306 env_name = get_conf_data_location_env_name()

307

308 if location is None:

309 if env_name in os.environ:

310 del os.environ[env_name]

311 _env.set("CONF_DATA_LOCATION", None)

312 return

313

314 if not Path(location).exists():

315 warnings.warn(f"The location you provided for the environment variable {env_name} doesn't exist: {location}.")

316

317 os.environ[env_name] = location

318 _env.set("CONF_DATA_LOCATION", location)

319

320

321 def get_conf_data_location(site_id: str = None) -> str:

322 """

323 Returns the full path of the location of the configuration data for the site id.

324

325 If the site_id is None, it is determined from the environment variable SITE_ID.

326

327 When the `${PROJECT}_CONF_DATA_LOCATION` environment variable is not set, the configuration data

328 location will be the `${PROJECT}_DATA_STORAGE_LOCATION + '/conf'`.

329

330 Args:

331 site_id: the site identifier (to be used instead of the SITE_ID environment variable)

332

333 Returns:

334 The full path of location of the configuration data as a string.

335

336 Raises:

337 ValueError: when the SITE_ID or the `${PROJECT}_DATA_STORAGE_LOCATION` is not set.

338 """

339

340 conf_data_root = _env.get("CONF_DATA_LOCATION")

341

342 if not conf_data_root:

343 try:

344 data_root = get_data_storage_location(site_id=site_id)

345 except ValueError:

346 raise ValueError(

347 f"Could not determine the location of the configuration files. "

348 f"The environment variable {get_conf_data_location_env_name()} is not set and also the "

349 f"data storage location is unknown."

350 )

351

352 data_root = data_root.rstrip("/")

353 conf_data_root = f"{data_root}/conf"

354

355 return conf_data_root

356

357

358 def get_log_file_location_env_name():

359 """Returns the name of the environment variable for the project."""

360 project = _env.get("PROJECT")

361 return f"{project}_LOG_FILE_LOCATION"

362

363

364 def set_log_file_location(location: str | Path | None):

365 """

366 Sets the environment variable and the internal representation to the given value.

367

368 Warning:

369 Issues a warning when the given location doesn't exist.

370 """

371

372 env_name = get_log_file_location_env_name()

373

374 if location is None:

375 if env_name in os.environ:

376 del os.environ[env_name]

377 _env.set("LOG_FILE_LOCATION", None)

378 return

379

380 if not Path(location).exists():

381 warnings.warn(f"The location you provided for the environment variable {env_name} doesn't exist: {location}.")

382

383 os.environ[env_name] = location

384 _env.set("LOG_FILE_LOCATION", location)

385

386

387 def get_log_file_location(site_id: str = None) -> str:

388 """

389 Returns the full path of the location of the log files. The log file location is read from the environment

390 variable `${PROJECT}_LOG_FILE_LOCATION`. The location shall be independent of any setting that is subject to change.

391

392 If the environment variable is not set, a default log file location is created from the data storage location as

393 follows: `<PROJECT>_DATA_STORAGE_LOCATION/<SITE_ID>/log`.

394

395 Args:

396 site_id: the site identifier

397

398 Returns:

399 The full path of location of the log files as a string.

400

401 Raises:

402 ValueError: when the SITE_ID or the ${PROJECT}_DATA_STORAGE_LOCATION is not set.

403

404 """

405

406 log_data_root = _env.get("LOG_FILE_LOCATION")

407

408 if not log_data_root:

409 try:

410 data_root = get_data_storage_location(site_id=site_id)

411 except ValueError:

412 raise ValueError(

413 f"Could not determine the location of the log files. "

414 f"The environment variable {get_log_file_location_env_name()} is not set and also the "

415 f"data storage location is unknown."

416 )

417 data_root = data_root.rstrip("/")

418 log_data_root = f"{data_root}/log"

419

420 return log_data_root

421

422

423 def get_local_settings_env_name() -> str:

424 """Returns the name of the environment variable for the project."""

425 project = _env.get("PROJECT")

426 return f"{project}_LOCAL_SETTINGS"

427

428

429 def set_local_settings(path: str | Path | None):

430 """

431 Sets the environment variable and the internal representation to the given value.

432

433 When the path is set to None, the environment variable will be unset.

434

435 Warning:

436 Issues a warning when the given path doesn't exist.

437 """

438

439 env_name = get_local_settings_env_name()

440

441 if path is None:

442 if env_name in os.environ:

443 del os.environ[env_name]

444 _env.set("LOCAL_SETTINGS", None)

445 return

446

447 if not Path(path).exists():

448 warnings.warn(f"The location you provided for the environment variable {env_name} doesn't exist: {path}.")

449

450 os.environ[env_name] = path

451 _env.set("LOCAL_SETTINGS", path)

452

453

454 def get_local_settings_path() -> str or None:

455 """

456 Returns the fully qualified filename of the local settings YAML file. When the local settings environment

457 variable is not defined or is an empty string, None is returned.

458

459 Warning:

460 The function will generate a warning when

461

462 - When the local settings environment variable is not defined, or

463 - when the path defined by the environment variable doesn't exist.

464 """

465

466 local_settings = _env.get("LOCAL_SETTINGS")

467

468 if not local_settings: 468 ↛ 469line 468 didn't jump to line 469 because the condition on line 468 was never true

469 warnings.warn(

470 f"The local settings environment variable '{get_local_settings_env_name()}' "

471 f"is not defined or is an empty string."

472 )

473 return None

474

475 if not Path(local_settings).exists(): 475 ↛ 476line 475 didn't jump to line 476 because the condition on line 475 was never true

476 warnings.warn(

477 f"The local settings path '{local_settings}' doesn't exist. As a result, "

478 f"the local settings for your project will not be loaded."

479 )

480

481 return local_settings

482

483

484 def has_conf_repo_location() -> bool:

485 location = _env.get("CONF_REPO_LOCATION")

486 return True if location in (None, NoValue) else False

487

488

489 def get_conf_repo_location_env_name() -> str:

490 """Returns the name of the environment variable for the project."""

491 project = _env.get("PROJECT")

492 return f"{project}_CONF_REPO_LOCATION"

493

494

495 def get_conf_repo_location() -> str | None:

496 """

497 Returns the fully qualified name of the location of the repository with

498 configuration and calibration data.

499

500 Returns None if no environment variable was defined or if the location doesn't exist.

501 In both cases a Warning is issued.

502 """

503

504 location = _env.get("CONF_REPO_LOCATION")

505

506 if location in (None, NoValue()):

507 warnings.warn(

508 f"The environment variable for the configuration data repository is "

509 f"not defined ({get_conf_repo_location_env_name()})."

510 )

511 return None

512

513 if not Path(location).exists():

514 warnings.warn(f"The location of the configuration data repository doesn't exist: {location}.")

515 return None

516

517 return location

518

519

520 def set_conf_repo_location(location: str | Path | None):

521 """

522 Sets the environment variable and the internal representation to the given value.

523

524 When the location is None, the environment variable will be unset and its internal

525 representation will be NoValue().

526

527 Warning:

528 Issues a warning when the given location doesn't exist.

529 """

530

531 env_name = get_conf_repo_location_env_name()

532

533 if location is None:

534 if env_name in os.environ:

535 del os.environ[env_name]

536 _env.set("CONF_REPO_LOCATION", None)

537 return

538

539 if not Path(location).exists():

540 warnings.warn(f"The location you provided for the environment variable {env_name} doesn't exist: {location}.")

541

542 os.environ[env_name] = location

543 _env.set("CONF_REPO_LOCATION", location)

544

545

546 def print_env():

547 """

548 Prints out the mandatory and known environment variables at the time of the

549 function call. The function and lineno is also printed for information.

550 """

551 col_width = 30

552

553 console = Console(width=200)

554

555 with warnings.catch_warnings():

556 warnings.simplefilter("ignore")

557 caller_info = get_caller_info(level=2)

558 console.print(f"[b]Environment as in {caller_info.filename}:{caller_info.lineno}[/]")

559 console.print(f" {'PROJECT':{col_width}s}: {get_project_name()}")

560 console.print(f" {'SITE_ID':{col_width}s}: {get_site_id()}")

561 console.print(f" {get_data_storage_location_env_name():{col_width}s}: {get_data_storage_location()}")

562 console.print(f" {get_log_file_location_env_name():{col_width}s}: {get_log_file_location()}")

563 console.print(f" {get_conf_data_location_env_name():{col_width}s}: {get_conf_data_location()}")

564 console.print(f" {get_conf_repo_location_env_name():{col_width}s}: {get_conf_repo_location()}")

565 console.print(f" {get_local_settings_env_name():{col_width}s}: {get_local_settings_path()}")

566

567

568@contextlib.contextmanager

569 def env_var(**kwargs: str | int | float | bool | None):

570 """

571 Context manager to run some code that need alternate settings for environment variables.

572 This will automatically initialize the CGSE environment upon entry and re-initialize upon exit.

573

574 Note:

575 This context manager is different from the one in `egse.system` because of the CGSE environment changes.

576

577 Args:

578 **kwargs: dictionary with environment variables that are needed

579

580 Example:

581 ```python

582 from egse.env import env_var

583 with env_var(PLATO_DATA_STORAGE_LOCATION="/Users/rik/data"):

584 # do stuff that needs these alternate setting

585 ...

586 ```

587

588 """

589 saved_env = {}

590

591 for k, v in kwargs.items():

592 saved_env[k] = os.environ.get(k)

593 if v is None:

594 if k in os.environ:

595 del os.environ[k]

596 else:

597 os.environ[k] = v

598

599 initialize()

600

601 yield

602

603 for k, v in saved_env.items():

604 if v is None:

605 if k in os.environ:

606 del os.environ[k]

607 else:

608 os.environ[k] = v

609

610 initialize()

611

612

613 def main(args: list | None = None): # pragma: no cover

614 import argparse

615 import sys

616 import rich

617

618 parser = argparse.ArgumentParser()

619 parser.add_argument(

620 "--full",

621 default=False,

622 action="store_true",

623 help="Print a full report on environment variables and paths.",

624 )

625 parser.add_argument(

626 "--doc",

627 default=False,

628 action="store_true",

629 help="Print help on the environment variables and paths.",

630 )

631 parser.add_argument(

632 "--mkdir",

633 default=False,

634 action="store_true",

635 help="Create directory that doesn't exist.",

636 )

637

638 args = parser.parse_args(args or [])

639

640 def check_env_dir(env_var: str):

641 value = _env.get(env_var)

642

643 if value == NoValue():

644 value = "[bold red]not set"

645 elif not value.startswith("/"):

646 value = f"[default]{value} [bold orange3](this is a relative path!)"

647 elif not os.path.exists(value):

648 value = f"[default]{value} [bold red](location doesn't exist!)"

649 elif not os.path.isdir(value):

650 value = f"[default]{value} [bold red](location is not a directory!)"

651 else:

652 value = f"[default]{value}"

653 return value

654

655 def check_env_file(env_var: str):

656 value = _env.get(env_var)

657

658 if not value:

659 value = "[bold red]not set"

660 elif not os.path.exists(value):

661 value = f"[default]{value} [bold red](location doesn't exist!)"

662 else:

663 value = f"[default]{value}"

664 return value

665

666 rich.print("Environment variables:")

667

668 project = _env.get("PROJECT")

669

670 for var in MANDATORY_ENVIRONMENT_VARIABLES:

671 rich.print(f" {var} = {_env.get(var)}")

672 for var in KNOWN_PROJECT_ENVIRONMENT_VARIABLES:

673 if var.endswith("_SETTINGS"):

674 rich.print(f" {project}_{var} = {check_env_file(var)}")

675 else:

676 rich.print(f" {project}_{var} = {check_env_dir(var)}")

677

678 rich.print()

679 rich.print("Generated locations and filenames")

680

681 with all_logging_disabled():

682 warnings.filterwarnings("ignore", category=UserWarning)

683 try:

684 rich.print(f" {get_data_storage_location() = }", flush=True, end="")

685 location = get_data_storage_location()

686 if not Path(location).exists():

687 if args.mkdir:

688 rich.print(f" [green]⟶ Creating data storage location: {location} (+ daily + obs)[/]")

689 Path(location).mkdir(parents=True)

690 (Path(location) / "daily").mkdir()

691 (Path(location) / "obs").mkdir()

692 else:

693 rich.print(" [red]⟶ ERROR: The data storage location doesn't exist![/]")

694 else:

695 rich.print()

696 except ValueError as exc:

697 rich.print(f" get_data_storage_location() = [red]{exc}[/]")

698

699 try:

700 rich.print(f" {get_conf_data_location() = }", flush=True, end="")

701 location = get_conf_data_location()

702 if not Path(location).exists():

703 if args.mkdir:

704 rich.print(f" [green]⟶ Creating configuration data location: {location}[/]")

705 Path(location).mkdir(parents=True)

706 else:

707 rich.print(" [red]⟶ ERROR: The configuration data location doesn't exist![/]")

708 else:

709 rich.print()

710 except ValueError as exc:

711 rich.print(f" get_conf_data_location() = [red]{exc}[/]")

712

713 try:

714 rich.print(f" {get_conf_repo_location() = }", flush=True, end="")

715 location = get_conf_repo_location()

716 if location is None or not Path(location).exists():

717 rich.print(" [red]⟶ ERROR: The configuration repository location doesn't exist![/]")

718 else:

719 rich.print()

720 except ValueError as exc:

721 rich.print(f" get_conf_repo_location() = [red]{exc}[/]")

722

723 try:

724 rich.print(f" {get_log_file_location() = }", flush=True, end="")

725 location = get_log_file_location()

726 if not Path(location).exists():

727 if args.mkdir:

728 rich.print(f" [green]⟶ Creating log files location: {location}[/]")

729 Path(location).mkdir(parents=True)

730 else:

731 rich.print(" [red]⟶ ERROR: The log files location doesn't exist![/]")

732 else:

733 rich.print()

734 except ValueError as exc:

735 rich.print(f" get_log_file_location() = [red]{exc}[/]")

736

737 try:

738 rich.print(f" {get_local_settings_path() = }", flush=True, end="")

739 location = get_local_settings_path()

740 if location is None or not Path(location).exists():

741 rich.print(" [red]⟶ ERROR: The local settings file is not defined or doesn't exist![/]")

742 else:

743 rich.print()

744 except ValueError as exc:

745 rich.print(f" get_local_settings() = [red]{exc}[/]")

746

747 if args.full:

748 rich.print()

749 rich.print(f" PYTHONPATH=[default]{os.environ.get('PYTHONPATH')}")

750 rich.print(f" PYTHONSTARTUP=[default]{os.environ.get('PYTHONSTARTUP')}")

751 rich.print()

752 python_path_msg = "\n ".join(sys.path)

753 rich.print(f" sys.path=[\n {python_path_msg}\n ]")

754 path_msg = "\n ".join(os.environ.get("PATH").split(":"))

755 rich.print(f" PATH=[\n {path_msg}\n ]")

756

757 help_msg = """

758[bold]PROJECT_INSTALL_LOCATION[/bold]:

759 This variable shall point to the location where the CGSE will be installed and is

760 usually set to `/cgse`. The variable is used by the [blue]update_cgse[/blue] script.

761

762[bold]PROJECT_CONF_DATA_LOCATION[/bold]:

763 This directory is the root folder for all the Setups of the site, the site is part

764 of the name. By default, this directory is located in the overall data storage folder.

765

766[bold]PROJECT_CONF_REPO_LOCATION[/bold]:

767 This variable is the root of the working copy of the 'plato-cgse-conf' project.

768 The value is usually set to `~/git/plato-cgse-conf`.

769

770[bold]PROJECT_DATA_STORAGE_LOCATION[/bold]:

771 This directory contains all the data files from the control servers and other

772 components. This folder is the root folder for all data from all cameras and

773 all sites. Below this folder shall be a folder for each of the cameras and in

774 there a sub-folder for each of the sites where that camera was tested. The

775 hierarchy is therefore: `$PLATO_DATA_STORAGE_LOCATION/<camera name>/<site id>.

776 Each of those folder shall contain at least the sub-folder [blue]daily[/blue], and [blue]obs[/blue].

777

778 There is also a file called [blue]obsid-table-<site id>.txt[/blue] which is maintained by

779 the configuration manager and contains information about the observations that

780 were run and the commands to start those observation.

781

782[bold]PROJECT_LOG_FILE_LOCATION[/bold]:

783 This directory contains the log files with all messages that were sent to the

784 logger control server. The log files are rotated on a daily basis at midnight UTC.

785 By default, this directory is also located in the overall data storage folder.

786

787[bold]PROJECT_LOCAL_SETTINGS[/bold]:

788 This file is used for local site-specific settings. When the environment

789 variable is not set, no local settings will be loaded. By default, this variable

790 is assumed to be '/cgse/local_settings.yaml'.

791"""

792

793 if args.doc:

794 rich.print(help_msg)

795

796 if not args.full:

797 rich.print()

798 rich.print("use the '--full' flag to get a more detailed report, '--doc' for help on the variables.")

799

800 # Do we still use these environment variables?

801 #

802 # PLATO_WORKDIR

803 # PLATO_COMMON_EGSE_PATH - YES

804

805

806 ignore_m_warning("egse.env")

807

808

809 if __name__ == "__main__": 809 ↛ 810line 809 didn't jump to line 810 because the condition on line 809 was never true

810 import sys

811

812 main(sys.argv[1:])