Source code for camcops_server.camcops_server_meta
"""
camcops_server/camcops_server_meta.py
===============================================================================
Copyright (C) 2012, University of Cambridge, Department of Psychiatry.
Created by Rudolf Cardinal (rnc1001@cam.ac.uk).
This file is part of CamCOPS.
CamCOPS is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
CamCOPS is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with CamCOPS. If not, see <https://www.gnu.org/licenses/>.
===============================================================================
**The CamCOPS "meta" launcher: so you can run a CamCOPS command over multiple
config files (installations).**
This has been largely superseded by the "groups" concept, since a single
CamCOPS instance is now capable of much more.
"""
import argparse
import glob
import logging
import os
import sys
from cardinal_pythonlib.logs import (
BraceStyleAdapter,
main_only_quicksetup_rootlogger,
)
from rich_argparse import RichHelpFormatter
log = BraceStyleAdapter(logging.getLogger(__name__))
THIS_DIRECTORY = os.path.dirname(os.path.abspath(__file__))
PROJECT_BASE_DIRECTORY = os.path.abspath(
os.path.join(THIS_DIRECTORY, os.pardir)
)
PYTHON_EXECUTABLE = sys.executable
if "GENERATING_CAMCOPS_DOCS" in os.environ:
PROJECT_BASE_DIRECTORY = "/path/to/camcops/server"
PYTHON_EXECUTABLE = "/path/to/python"
DEFAULT_CAMCOPS = os.path.join(PROJECT_BASE_DIRECTORY, "camcops_server.py")
[docs]def meta_main() -> None:
"""
Command-line process for ``camcops_server_meta`` tool.
"""
parser = argparse.ArgumentParser(
description="Run commands across multiple CamCOPS databases",
formatter_class=RichHelpFormatter,
)
parser.add_argument(
"cc_command", type=str, help="Main command to pass to CamCOPS"
)
parser.add_argument(
"--filespecs",
nargs="+",
required=True,
help="List of CamCOPS config files (wildcards OK)",
)
parser.add_argument(
"--ccargs",
nargs="*",
help="List of CamCOPS arguments, to which '--' will be prefixed",
)
parser.add_argument(
"--python",
default=PYTHON_EXECUTABLE,
help=f"Python interpreter (default: {PYTHON_EXECUTABLE})",
)
parser.add_argument(
"--camcops",
default=DEFAULT_CAMCOPS,
help=f"CamCOPS server executable (default: {DEFAULT_CAMCOPS})",
)
parser.add_argument(
"-d",
"--dummyrun",
action="store_true",
help="Dummy run (show filenames only)",
)
parser.add_argument("-v", "--verbose", action="store_true", help="Verbose")
args = parser.parse_args()
main_only_quicksetup_rootlogger(
level=logging.DEBUG if args.verbose else logging.INFO
)
log.debug("Arguments: {}", args)
# Delayed import so --help doesn't take ages
from camcops_server.camcops_server import (
main as camcops_main,
) # delayed import
did_something = False
# old_sys_argv = sys.argv.copy()
for filespec in args.filespecs:
for filename in glob.glob(filespec):
did_something = True
log.info("Processing: {}", filename)
sys.argv = [
"camcops_server", # dummy argv[0]
args.cc_command,
"--config",
filename,
] + [f"--{x}" for x in args.ccargs or []]
log.debug("Executing command: {}", sys.argv)
if args.dummyrun:
continue
camcops_main() # using the new sys.argv
if not did_something:
log.info("Nothing to do; no files found")
if __name__ == "__main__":
meta_main()