sl-shared-assets 4.0.1__py3-none-any.whl → 5.0.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.

Potentially problematic release.


This version of sl-shared-assets might be problematic. Click here for more details.

Files changed (39) hide show
  1. sl_shared_assets/__init__.py +48 -41
  2. sl_shared_assets/command_line_interfaces/__init__.py +3 -0
  3. sl_shared_assets/command_line_interfaces/configure.py +173 -0
  4. sl_shared_assets/command_line_interfaces/manage.py +226 -0
  5. sl_shared_assets/data_classes/__init__.py +33 -32
  6. sl_shared_assets/data_classes/configuration_data.py +267 -79
  7. sl_shared_assets/data_classes/session_data.py +226 -289
  8. sl_shared_assets/server/__init__.py +24 -4
  9. sl_shared_assets/server/job.py +6 -7
  10. sl_shared_assets/server/pipeline.py +585 -0
  11. sl_shared_assets/server/server.py +57 -25
  12. sl_shared_assets/tools/__init__.py +9 -8
  13. sl_shared_assets/tools/packaging_tools.py +14 -25
  14. sl_shared_assets/tools/project_management_tools.py +602 -523
  15. sl_shared_assets/tools/transfer_tools.py +88 -23
  16. {sl_shared_assets-4.0.1.dist-info → sl_shared_assets-5.0.1.dist-info}/METADATA +46 -203
  17. sl_shared_assets-5.0.1.dist-info/RECORD +23 -0
  18. sl_shared_assets-5.0.1.dist-info/entry_points.txt +3 -0
  19. sl_shared_assets/__init__.pyi +0 -91
  20. sl_shared_assets/cli.py +0 -501
  21. sl_shared_assets/cli.pyi +0 -106
  22. sl_shared_assets/data_classes/__init__.pyi +0 -75
  23. sl_shared_assets/data_classes/configuration_data.pyi +0 -235
  24. sl_shared_assets/data_classes/runtime_data.pyi +0 -157
  25. sl_shared_assets/data_classes/session_data.pyi +0 -379
  26. sl_shared_assets/data_classes/surgery_data.pyi +0 -89
  27. sl_shared_assets/server/__init__.pyi +0 -11
  28. sl_shared_assets/server/job.pyi +0 -205
  29. sl_shared_assets/server/server.pyi +0 -298
  30. sl_shared_assets/tools/__init__.pyi +0 -19
  31. sl_shared_assets/tools/ascension_tools.py +0 -265
  32. sl_shared_assets/tools/ascension_tools.pyi +0 -68
  33. sl_shared_assets/tools/packaging_tools.pyi +0 -58
  34. sl_shared_assets/tools/project_management_tools.pyi +0 -239
  35. sl_shared_assets/tools/transfer_tools.pyi +0 -53
  36. sl_shared_assets-4.0.1.dist-info/RECORD +0 -36
  37. sl_shared_assets-4.0.1.dist-info/entry_points.txt +0 -7
  38. {sl_shared_assets-4.0.1.dist-info → sl_shared_assets-5.0.1.dist-info}/WHEEL +0 -0
  39. {sl_shared_assets-4.0.1.dist-info → sl_shared_assets-5.0.1.dist-info}/licenses/LICENSE +0 -0
@@ -1,6 +1,6 @@
1
- """This module provides classes used to configure data acquisition and processing runtimes in the Sun lab. All lab
2
- projects use classes from this module to configure experiment runtimes and determine how to interact with the
3
- particular data acquisition and runtime management system (hardware) they run on."""
1
+ """This module provides classes used to configure data acquisition and processing runtimes in the Sun lab. The assets
2
+ exposed by this module are used to configure specific hardware components used to acquire data and interface
3
+ with the remote hardware (servers) used to store, process, and analyze data."""
4
4
 
5
5
  import copy
6
6
  from enum import StrEnum
@@ -11,6 +11,8 @@ import appdirs
11
11
  from ataraxis_base_utilities import LogLevel, console, ensure_directory_exists
12
12
  from ataraxis_data_structures import YamlConfig
13
13
 
14
+ from ..server import ServerCredentials
15
+
14
16
 
15
17
  class AcquisitionSystems(StrEnum):
16
18
  """Defines the set of data acquisition systems used in the Sun lab and supported by all data-related libraries."""
@@ -180,14 +182,6 @@ class MesoscopeExperimentConfiguration(YamlConfig):
180
182
  class MesoscopePaths:
181
183
  """Stores the filesystem configuration parameters for the Mesoscope-VR data acquisition system."""
182
184
 
183
- server_credentials_path: Path = Path("/media/Data/Experiments/server_credentials.yaml")
184
- """
185
- The path to the locally stored .YAML file that contains the credentials for accessing the BioHPC server machine.
186
- While the filesystem of the server machine should already be mounted to the local machine via SMB or equivalent
187
- protocol, this data is used to establish SSH connection to the server and start newly acquired data processing
188
- after it is transferred to the server. This allows data acquisition, preprocessing, and processing to be controlled
189
- by the same runtime and prevents unprocessed data from piling up on the server.
190
- """
191
185
  google_credentials_path: Path = Path("/media/Data/Experiments/sl-surgery-log-0f651e492767.json")
192
186
  """
193
187
  The path to the locally stored .JSON file that contains the service account credentials used to read and write
@@ -276,7 +270,7 @@ class MesoscopeMicroControllers:
276
270
  at maximum voltage (break is fully engaged)."""
277
271
  wheel_diameter_cm: float = 15.0333
278
272
  """The diameter of the running wheel connected to the break and torque sensor, in centimeters."""
279
- lick_threshold_adc: int = 850
273
+ lick_threshold_adc: int = 400
280
274
  """The threshold voltage, in raw analog units recorded by a 12-bit Analog-to-Digital-Converter (ADC), interpreted
281
275
  as the animal's tongue contacting the sensor. Note, 12-bit ADC only supports values between 0 and 4095, so setting
282
276
  the threshold above 4095 will result in no licks being reported to Unity."""
@@ -409,7 +403,6 @@ class MesoscopeSystemConfiguration(YamlConfig):
409
403
  upon class instantiation."""
410
404
 
411
405
  # Converts all paths loaded as strings to Path objects used inside the library
412
- self.paths.server_credentials_path = Path(self.paths.server_credentials_path)
413
406
  self.paths.google_credentials_path = Path(self.paths.google_credentials_path)
414
407
  self.paths.root_directory = Path(self.paths.root_directory)
415
408
  self.paths.server_storage_directory = Path(self.paths.server_storage_directory)
@@ -429,8 +422,8 @@ class MesoscopeSystemConfiguration(YamlConfig):
429
422
  if not all(
430
423
  isinstance(item, tuple)
431
424
  and len(item) == 2
432
- and isinstance(item[0], (int, float))
433
- and isinstance(item[1], (int, float))
425
+ and isinstance(item[0], (int | float))
426
+ and isinstance(item[1], (int | float))
434
427
  for item in valve_calibration_data
435
428
  ):
436
429
  message = (
@@ -457,7 +450,6 @@ class MesoscopeSystemConfiguration(YamlConfig):
457
450
 
458
451
  # Converts all Path objects to strings before dumping the data, as .yaml encoder does not properly recognize
459
452
  # Path objects
460
- original.paths.server_credentials_path = str(original.paths.server_credentials_path) # type: ignore
461
453
  original.paths.google_credentials_path = str(original.paths.google_credentials_path) # type: ignore
462
454
  original.paths.root_directory = str(original.paths.root_directory) # type: ignore
463
455
  original.paths.server_storage_directory = str(original.paths.server_storage_directory) # type: ignore
@@ -476,59 +468,40 @@ class MesoscopeSystemConfiguration(YamlConfig):
476
468
  original.to_yaml(file_path=path)
477
469
 
478
470
 
479
- # A dictionary that maps the file names for supported data acquisition systems to their configuration classes. This
480
- # dictionary always contains all data acquisition systems used in the lab.
481
- _supported_configuration_files = {"mesoscope_system_configuration.yaml": MesoscopeSystemConfiguration}
482
-
471
+ def set_working_directory(path: Path) -> None:
472
+ """Sets the specified directory as the Sun lab working directory for the local machine (PC).
483
473
 
484
- def set_system_configuration_file(path: Path) -> None:
485
- """Sets the system configuration .yaml file specified by the input path as the default system configuration file for
486
- the managed machine (PC).
487
-
488
- This function is used to initially configure or override the existing configuration of any data acquisition system
489
- used in the lab. The path to the configuration file is stored inside the user's data directory so that all
490
- Sun lab libraries can automatically access that information during every runtime. Since the storage directory is
491
- typically hidden and varies between OSes and machines, this function provides a convenient way for setting that
492
- path without manually editing the storage cache.
474
+ This function is used as the first step for configuring any machine to work with the data stored on the remote
475
+ compute server(s). All lab libraries use this directory for caching configuration data and runtime working
476
+ (intermediate) data.
493
477
 
494
478
  Notes:
495
- If the input path does not point to an existing file, but the file name and extension are correct, the function
496
- will automatically generate a default SystemConfiguration class instance and save it under the specified path.
479
+ The path to the working directory is stored inside the user's data directory so that all Sun lab libraries can
480
+ automatically access and use the same working directory.
497
481
 
498
- A data acquisition system can include multiple machines (PCs). However, the configuration file is typically
499
- only present on the 'main' machine that manages all runtimes.
482
+ If the input path does not point to an existing directory, the function will automatically generate the
483
+ requested directory.
500
484
 
501
- Args:
502
- path: The path to the new system configuration file to be used by the local data acquisition system (PC).
485
+ After setting up the working directory, the user should use other commands from the 'sl-configure' CLI to
486
+ generate the remote compute server access credentials and / or acquisition system configuration files.
503
487
 
504
- Raises:
505
- ValueError: If the input path is not a valid system configuration file or does not use a supported data
506
- acquisition system name.
488
+ Args:
489
+ path: The path to the directory to set as the local Sun lab working directory.
507
490
  """
508
491
 
509
- # Prevents setting the path to an invalid file.
510
- if path.name not in _supported_configuration_files.keys():
511
- message = (
512
- f"Unable to set the input path {path} as the default system configuration file path. The input path has "
513
- f"to point to a configuration file ending with a '.yaml' extension and using one of the supported system "
514
- f"names: {', '.join(_supported_configuration_files.keys())}."
515
- )
516
- console.error(message=message, error=ValueError)
517
-
518
- # If the configuration file specified by the 'path' does not exist, generates a default SystemConfiguration instance
519
- # and saves it to the specified path.
492
+ # If the directory specified by the 'path' does not exist, generates the specified directory tree. As part of this
493
+ # process, also generate the precursor server_credentials.yaml file to use for accessing the remote server used to
494
+ # store project data.
520
495
  if not path.exists():
521
- precursor = _supported_configuration_files[path.name]() # Instantiates default class instance
522
- precursor.save(path=path)
523
496
  message = (
524
- f"The file specified by the input system configuration path {path} does not exist. Generating and saving "
525
- f"the default system configuration class instance to the specified path."
497
+ f"The specified working directory ({path}) does not exist. Generating the directory at the "
498
+ f"specified path..."
526
499
  )
527
- console.echo(message=message, level=LogLevel.WARNING)
500
+ console.echo(message=message, level=LogLevel.INFO)
528
501
 
529
502
  # Resolves the path to the static .txt file used to store the path to the system configuration file
530
503
  app_dir = Path(appdirs.user_data_dir(appname="sun_lab_data", appauthor="sun_lab"))
531
- path_file = app_dir.joinpath("configuration_path.txt")
504
+ path_file = app_dir.joinpath("working_directory_path.txt")
532
505
 
533
506
  # In case this function is called before the app directory is created, ensures the app directory exists
534
507
  ensure_directory_exists(path_file)
@@ -536,53 +509,268 @@ def set_system_configuration_file(path: Path) -> None:
536
509
  # Ensures that the input path's directory exists
537
510
  ensure_directory_exists(path)
538
511
 
539
- # Replaces the contents of the configuration_path.txt file with the provided path
540
- with open(path_file, "w") as f:
512
+ # Replaces the contents of the working_directory_path.txt file with the provided path
513
+ with path_file.open("w") as f:
541
514
  f.write(str(path))
542
515
 
516
+ if not path.joinpath("user_credentials.yaml").exists():
517
+ message = (
518
+ f"Unable to locate the 'user_credentials.yaml' file in the Sun lab working directory {path}. Call the "
519
+ f"'sl-configure server' CLI command to create the user server access credentials file. Note, all users "
520
+ f"need to have a valid user credentials file to work with the data stored on the remote server."
521
+ )
522
+ console.echo(message=message, level=LogLevel.WARNING)
543
523
 
544
- def get_system_configuration_data() -> MesoscopeSystemConfiguration:
545
- """Resolves the path to the local system configuration file and loads the system configuration data.
524
+ if not path.joinpath("service_credentials.yaml").exists():
525
+ message = (
526
+ f"Unable to locate the 'service_credentials.yaml' file in the Sun lab working directory {path}. If you "
527
+ f"intend to work with the remote compute server in the 'service' mode, use the 'sl-configure server -s' "
528
+ f"CLI command to create the service server access credentials file. Note, most lab users should skip this "
529
+ f"step, all intended interactions with teh server can be carried out via the user access mode."
530
+ )
531
+ console.echo(message=message, level=LogLevel.WARNING)
546
532
 
547
- This service function is used by all Sun lab data acquisition runtimes to load the system configuration data from
548
- the shared configuration file. It supports resolving and returning the data for all data acquisition systems used
549
- in the lab.
533
+
534
+ def get_working_directory() -> Path:
535
+ """Resolves and returns the path to the local Sun lab working directory.
536
+
537
+ This service function is primarily used when working with Sun lab data stored on remote compute server(s) to
538
+ establish local working directories for various jobs and pipelines.
550
539
 
551
540
  Returns:
552
- The initialized SystemConfiguration class instance for the local acquisition system that stores the loaded
553
- configuration parameters.
541
+ The path to the local working directory.
554
542
 
555
543
  Raises:
556
- FileNotFoundError: If the local machine does not have the Sun lab data directory, or the system configuration
557
- file does not exist.
544
+ FileNotFoundError: If the local machine does not have the Sun lab data directory, or the local working
545
+ directory does not exist (has not been configured).
558
546
  """
559
547
  # Uses appdirs to locate the user data directory and resolve the path to the configuration file
560
548
  app_dir = Path(appdirs.user_data_dir(appname="sun_lab_data", appauthor="sun_lab"))
561
- path_file = app_dir.joinpath("configuration_path.txt")
549
+ path_file = app_dir.joinpath("working_directory_path.txt")
562
550
 
563
551
  # If the cache file or the Sun lab data directory does not exist, aborts with an error
564
552
  if not path_file.exists():
565
553
  message = (
566
- "Unable to resolve the path to the local system configuration file, as local machine does not have the "
567
- "Sun lab data directory. Generate the local configuration file and Sun lab data directory by calling the "
568
- "'sl-create-system-config' CLI command and rerun the command that produced this error."
554
+ "Unable to resolve the path to the local Sun lab working directory, as local machine does not have a "
555
+ "configured working directory. Configure the local working directory by using the 'sl-configure directory' "
556
+ "CLI command."
569
557
  )
570
558
  console.error(message=message, error=FileNotFoundError)
571
559
 
572
560
  # Once the location of the path storage file is resolved, reads the file path from the file
573
- with open(path_file, "r") as f:
574
- configuration_file = Path(f.read().strip())
561
+ with path_file.open() as f:
562
+ working_directory = Path(f.read().strip())
575
563
 
576
564
  # If the configuration file does not exist, also aborts with an error
577
- if not configuration_file.exists():
565
+ if not working_directory.exists():
566
+ message = (
567
+ "Unable to resolve the path to the local Sun lab working directory, as the directory pointed by the path "
568
+ "stored in the Sun lab data directory does not exist. Configure a new working directory by using the "
569
+ "'sl-configure directory' CLI command."
570
+ )
571
+ console.error(message=message, error=FileNotFoundError)
572
+
573
+ # Returns the path to the working directory
574
+ return working_directory
575
+
576
+
577
+ def get_credentials_file_path(service: bool = False) -> Path:
578
+ """Resolves and returns the path to the requested .yaml file that stores access credentials for the Sun lab
579
+ remote compute server.
580
+
581
+ Depending on the configuration, either returns the path to the 'user_credentials.yaml' file (default) or the
582
+ 'service_credentials.yaml' file.
583
+
584
+ Notes:
585
+ Assumes that the local working directory has been configured before calling this function.
586
+
587
+ Args:
588
+ service: Determines whether this function must evaluate and return the path to the
589
+ 'service_credentials.yaml' file (if true) or the 'user_credentials.yaml' file (if false).
590
+
591
+ Raises:
592
+ FileNotFoundError: If either the 'service_credentials.yaml' or the 'user_credentials.yaml' files do not exist
593
+ in the local Sun lab working directory.
594
+ ValueError: If both credential files exist, but the requested credentials file is not configured.
595
+ """
596
+
597
+ # Gets the path to the local working directory.
598
+ working_directory = get_working_directory()
599
+
600
+ # Resolves the paths to the credential files.
601
+ service_path = working_directory.joinpath("service_credentials.yaml")
602
+ user_path = working_directory.joinpath("user_credentials.yaml")
603
+
604
+ # If the caller requires the service account, evaluates the service credentials file.
605
+ if service:
606
+ # Ensures that the credentials' file exists.
607
+ if not service_path.exists():
608
+ message = (
609
+ f"Unable to locate the 'service_credentials.yaml' file in the Sun lab working directory "
610
+ f"{service_path}. If you intend to work with the remote compute server in the 'service' mode, use the "
611
+ f"'sl-configure server -s' CLI command to create the service server access credentials file. Note, "
612
+ f"most lab users should skip this step, all intended interactions with teh server can be carried out "
613
+ f"via the user access mode."
614
+ )
615
+ console.error(message=message, error=FileNotFoundError)
616
+ raise FileNotFoundError(message) # Fallback to appease mypy, should not be reachable
617
+
618
+ credentials: ServerCredentials = ServerCredentials.from_yaml(file_path=service_path) # type: ignore
619
+
620
+ # If the service account is not configured, aborts with an error.
621
+ if credentials.username == "YourNetID" or credentials.password == "YourPassword":
622
+ message = (
623
+ f"The 'service_credentials.yaml' file appears to be unconfigured or contains placeholder credentials. "
624
+ f"Use the 'sl-configure server -s' CLI command to reconfigure the server credentials file."
625
+ )
626
+ console.error(message=message, error=ValueError)
627
+ raise ValueError(message) # Fallback to appease mypy, should not be reachable
628
+
629
+ # If the service account is configured, returns the path to the service credentials file to caller
630
+ else:
631
+ message = f"Server access credentials: Resolved. Using the service {credentials.username} account."
632
+ console.echo(message=message, level=LogLevel.SUCCESS)
633
+ return service_path
634
+
635
+ else:
636
+ if not user_path.exists():
637
+ message = (
638
+ f"Unable to locate the 'user_credentials.yaml' file in the Sun lab working directory {user_path}. Call "
639
+ f"the 'sl-configure server' CLI command to create the user server access credentials file. Note, "
640
+ f"all users need to have a valid user credentials file to work with the data stored on the remote "
641
+ f"server."
642
+ )
643
+ console.error(message=message, error=FileNotFoundError)
644
+ raise FileNotFoundError(message) # Fallback to appease mypy, should not be reachable
645
+
646
+ # Otherwise, evaluates the user credentials file.
647
+ credentials: ServerCredentials = ServerCredentials.from_yaml(file_path=user_path) # type: ignore
648
+
649
+ # If the user account is not configured, aborts with an error.
650
+ if credentials.username == "YourNetID" or credentials.password == "YourPassword":
651
+ message = (
652
+ f"The 'user_credentials.yaml' file appears to be unconfigured or contains placeholder credentials. "
653
+ f"Use the 'sl-configure server' CLI command to reconfigure the server credentials file."
654
+ )
655
+ console.error(message=message, error=ValueError)
656
+ raise ValueError(message) # Fallback to appease mypy, should not be reachable
657
+
658
+ # Otherwise, returns the path to the user credentials file to caller
659
+ message = f"Server access credentials: Resolved. Using the {credentials.username} account."
660
+ console.echo(message=message, level=LogLevel.SUCCESS)
661
+ return user_path
662
+
663
+
664
+ # Maps supported file names to configuration classes. This is used when loading the configuration data into memory.
665
+ _supported_configuration_files = {
666
+ "mesoscope-vr_configuration.yaml": MesoscopeSystemConfiguration,
667
+ }
668
+
669
+
670
+ def create_system_configuration_file(system: AcquisitionSystems | str) -> None:
671
+ """Creates the .yaml configuration file for the requested Sun lab data acquisition system and configures the local
672
+ machine (PC) to use this file for all future acquisition-system-related calls.
673
+
674
+ This function is used to initially configure or override the existing configuration of any data acquisition system
675
+ used in the lab.
676
+
677
+ Notes:
678
+ This function creates the configuration file inside the shared Sun lab working directory on the local machine.
679
+ It assumes that the user has configured (created) the directory before calling this function.
680
+
681
+ A data acquisition system can consist of multiple machines (PCs). The configuration file is typically only
682
+ present on the 'main' machine that manages all runtimes.
683
+
684
+ Args:
685
+ system: The name (type) of the data acquisition system for which to create the configuration file. Must be one
686
+ of the following supported options: mesoscope-vr.
687
+
688
+ Raises:
689
+ ValueError: If the input acquisition system name (type) is not recognized.
690
+ """
691
+
692
+ # Resolves the path to the local Sun lab working directory.
693
+ directory = get_working_directory()
694
+
695
+ # Removes any existing configuration files to ensure only one configuration exists on each configured machine
696
+ existing_configs = tuple(directory.glob("*_configuration.yaml"))
697
+ for config_file in existing_configs:
698
+ console.echo(f"Removing existing configuration file: {config_file.name}...")
699
+ config_file.unlink()
700
+
701
+ if system == AcquisitionSystems.MESOSCOPE_VR:
702
+ # Creates the precursor configuration file for the mesoscope-vr system
703
+ configuration = MesoscopeSystemConfiguration()
704
+ configuration_path = directory.joinpath(f"{system}_configuration.yaml")
705
+ configuration.save(path=configuration_path)
706
+
707
+ # Forces the user to finish configuring the system by editing the parameters inside the configuration file
578
708
  message = (
579
- "Unable to resolve the path to the local system configuration file, as the file pointed by the path stored "
580
- "in Sun lab data directory does not exist. Generate a new local configuration file by calling the "
581
- "'sl-create-system-config' CLI command and rerun the command that produced this error."
709
+ f"Mesoscope-VR data acquisition system configuration file: Saved to {configuration_path}. Edit the "
710
+ f"default parameters inside the configuration file to finish configuring the system."
711
+ )
712
+ console.echo(message=message, level=LogLevel.SUCCESS)
713
+ input("Enter anything to continue...")
714
+
715
+ # If the input acquisition system is not recognized, raises a ValueError
716
+ else:
717
+ systems = tuple(AcquisitionSystems)
718
+ message = (
719
+ f"Unable to generate the system configuration file for the acquisition system '{system}'. The specified "
720
+ f"acquisition system is not supported (not recognized). Currently, only the following acquisition systems "
721
+ f"are supported: {', '.join(systems)}."
722
+ )
723
+ console.error(message=message, error=ValueError)
724
+
725
+
726
+ def get_system_configuration_data() -> MesoscopeSystemConfiguration:
727
+ """Resolves the path to the local data acquisition system configuration file and loads the configuration data as
728
+ a SystemConfiguration instance.
729
+
730
+ This service function is used by all Sun lab data acquisition runtimes to load the system configuration data from
731
+ the locally stored configuration file. It supports resolving and returning the data for all data acquisition
732
+ systems currently used in the lab.
733
+
734
+ Returns:
735
+ The initialized SystemConfiguration class instance for the local data acquisition system that stores the loaded
736
+ configuration parameters.
737
+
738
+ Raises:
739
+ FileNotFoundError: If the local machine does not have a valid data acquisition system configuration file.
740
+ """
741
+
742
+ # Resolves the path to the local Sun lab working directory.
743
+ directory = get_working_directory()
744
+
745
+ # Finds all configuration files stored in the local working directory
746
+ config_files = tuple(directory.glob("*_configuration.yaml"))
747
+
748
+ # Ensures exactly one configuration file exists in the working directory
749
+ if len(config_files) != 1:
750
+ file_names = [f.name for f in config_files]
751
+ message = (
752
+ f"Expected a single dta acquisition system configuration file to be found inside the local Sun lab working "
753
+ f"directory ({directory}), but found {len(config_files)} files ({', '.join(file_names)}). Use the "
754
+ f"'sl-configure system' CLI command to reconfigure the local machine to only contain a single data "
755
+ f"acquisition system configuration file."
582
756
  )
583
757
  console.error(message=message, error=FileNotFoundError)
758
+ raise FileNotFoundError(message) # Fallback to appease mypy, should not be reachable
584
759
 
585
- # Loads the data stored inside the .yaml file into the class instance that matches the file name and returns the
586
- # instantiated class to caller
760
+ # Gets the single configuration file
761
+ configuration_file = config_files[0]
587
762
  file_name = configuration_file.name
588
- return _supported_configuration_files[file_name].from_yaml(file_path=configuration_file) # type: ignore
763
+
764
+ # Ensures that the file name is supported
765
+ if file_name not in _supported_configuration_files:
766
+ message = (
767
+ f"The data acquisition system configuration file '{file_name}' stored in teh local Sun lab working "
768
+ f"directory is not recognized. Use one of the supported configuration files: "
769
+ f"{', '.join(_supported_configuration_files.keys())}."
770
+ )
771
+ console.error(message=message, error=ValueError)
772
+ raise ValueError(message) # Fallback to appease mypy, should not be reachable
773
+
774
+ # Loads and return the configuration data
775
+ configuration_class = _supported_configuration_files[file_name]
776
+ return configuration_class.from_yaml(file_path=configuration_file) # type: ignore