Source code for apsbits.api.delete_instrument
#!/usr/bin/env python3
"""
Delete an instrument and its associated qserver configuration.
This script moves an instrument directory and its corresponding qserver
configuration directory to a .deleted directory in the workspace.
"""
__version__ = "1.0.0"
import argparse
import os
import re
import shutil
import sys
from datetime import datetime
from pathlib import Path
from typing import Tuple
[docs]
def validate_instrument_name(name: str) -> bool:
"""
Validate that the instrument name follows the required pattern.
:param name: The instrument name to validate.
:return: True if the name is valid, False otherwise.
"""
return re.fullmatch(r"[a-z][_a-z0-9]*", name) is not None
[docs]
def get_instrument_paths(name: str) -> Tuple[Path, Path]:
"""
Get the paths to the instrument and qserver directories.
:param name: The name of the instrument.
:return: A tuple containing the instrument directory path and qserver directory
path.
"""
main_path: Path = Path(os.getcwd()).resolve()
instrument_dir: Path = main_path / "src" / name
qserver_dir: Path = main_path / "src" / f"{name}_qserver"
return instrument_dir, qserver_dir
[docs]
def delete_instrument(instrument_dir: Path, qserver_dir: Path) -> None:
"""
Move the instrument and qserver directories to a .deleted directory.
:param instrument_dir: Path to the instrument directory.
:param qserver_dir: Path to the qserver directory.
:return: None
"""
main_path: Path = Path(os.getcwd()).resolve()
deleted_dir: Path = main_path / ".deleted"
# Create .deleted directory if it doesn't exist
if not deleted_dir.exists():
deleted_dir.mkdir(parents=True, exist_ok=True)
print(f"Created .deleted directory at '{deleted_dir}'.")
# Add timestamp to avoid name conflicts
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
if instrument_dir.exists():
# Create a new path with timestamp
new_instrument_path = deleted_dir / f"{instrument_dir.name}_{timestamp}"
shutil.move(str(instrument_dir), str(new_instrument_path))
print(
f"Instrument directory '{instrument_dir}' moved to '{new_instrument_path}'."
)
else:
print(f"Warning: Instrument directory '{instrument_dir}' does not exist.")
if qserver_dir.exists():
# Create a new path with timestamp
new_qserver_path = deleted_dir / f"{qserver_dir.name}_{timestamp}"
shutil.move(str(qserver_dir), str(new_qserver_path))
print(f"Qserver directory '{qserver_dir}' moved to '{new_qserver_path}'.")
else:
print(f"Warning: Qserver directory '{qserver_dir}' does not exist.")
[docs]
def main() -> None:
"""
Parse arguments and move the instrument to the .deleted directory.
:return: None
"""
parser = argparse.ArgumentParser(
description=(
"Move an instrument and its associated qserver configuration to "
".deleted directory."
)
)
parser.add_argument("name", type=str, help="Name of the instrument to delete.")
parser.add_argument(
"--force",
"-f",
action="store_true",
help="Skip confirmation prompt and delete immediately.",
)
args = parser.parse_args()
if not validate_instrument_name(args.name):
print(f"Error: Invalid instrument name '{args.name}'.", file=sys.stderr)
sys.exit(1)
instrument_dir, qserver_dir = get_instrument_paths(args.name)
if not instrument_dir.exists() and not qserver_dir.exists():
msg = (
f"Error: Neither instrument '{args.name}' nor its qserver "
f"configuration exist."
)
print(msg, file=sys.stderr)
sys.exit(1)
if not args.force:
prompt = (
f"Are you sure you want to move instrument '{args.name}' and its "
f"qserver configuration to .deleted directory? [y/N]: "
)
confirmation = input(prompt)
if confirmation.lower() != "y":
print("Operation cancelled.")
sys.exit(0)
try:
delete_instrument(instrument_dir, qserver_dir)
msg = (
f"Instrument '{args.name}' and its qserver configuration have been "
"moved to .deleted directory."
)
print(msg)
except Exception as exc:
print(f"Error moving instrument: {exc}", file=sys.stderr)
sys.exit(1)
if __name__ == "__main__":
main()