Coverage for python/lsst/ap/pipe/make_apdb.py: 25%
52 statements
« prev ^ index » next coverage.py v6.4.2, created at 2022-07-24 02:44 -0700
« prev ^ index » next coverage.py v6.4.2, created at 2022-07-24 02:44 -0700
1# This file is part of ap_pipe.
2#
3# Developed for the LSST Data Management System.
4# This product includes software developed by the LSST Project
5# (https://www.lsst.org).
6# See the COPYRIGHT file at the top-level directory of this distribution
7# for details of code ownership.
8#
9# This program is free software: you can redistribute it and/or modify
10# it under the terms of the GNU General Public License as published by
11# the Free Software Foundation, either version 3 of the License, or
12# (at your option) any later version.
13#
14# This program is distributed in the hope that it will be useful,
15# but WITHOUT ANY WARRANTY; without even the implied warranty of
16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17# GNU General Public License for more details.
18#
19# You should have received a copy of the GNU General Public License
20# along with this program. If not, see <https://www.gnu.org/licenses/>.
22__all__ = ["makeApdb"]
24import argparse
26import lsst.dax.apdb as daxApdb
27from lsst.pipe.base.configOverrides import ConfigOverrides
28from lsst.ap.association import DiaPipelineConfig
31class ConfigOnlyParser(argparse.ArgumentParser):
32 """Argument parser that knows standard config arguments.
33 """
35 def __init__(self, description=None, **kwargs):
36 if description is None:
37 # Description must be readable in both Sphinx and make_apdb.py -h
38 description = """\
39Create a Alert Production Database using config overrides for
40`lsst.dax.apdb.ApdbConfig`.
42This script takes the same ``--config`` and ``--config-file`` arguments as
43pipeline runs. However, the configs are at a lower level than the AP pipeline.
45The config overrides must define ``db_url`` to create a valid config.
46"""
48 super().__init__(description=description, **kwargs)
50 self.add_argument("-c", "--config", nargs="*", action=ConfigValueAction,
51 help="config override(s), e.g. "
52 "``-c prefix=fancy db_url=\"sqlite://\"``",
53 metavar="NAME=VALUE")
54 self.add_argument("-C", "--config-file", dest="configfile", nargs="*", action=ConfigFileAction,
55 help="config override file(s) for ApdbConfig")
57 def parse_args(self, args=None, namespace=None):
58 """Parse arguments for an `ApdbConfig`.
60 Parameters
61 ----------
62 args : `list` [`str`], optional
63 Argument list; if `None` then ``sys.argv`` is used.
64 namespace : `argparse.Namespace`, optional
65 An object to take the attributes. The default is a new empty
66 `~argparse.Namespace` object
68 Returns
69 -------
70 namespace : `argparse.Namespace`
71 A `~argparse.Namespace` instance containing fields:
72 - ``config``: the supplied config with all overrides applied,
73 validated and frozen.
74 """
75 if not namespace:
76 namespace = argparse.Namespace()
77 namespace.overrides = ConfigOverrides()
79 # ConfigFileAction and ConfigValueAction require namespace.overrides to exist
80 namespace = super().parse_args(args, namespace)
81 del namespace.configfile
82 # Make ApdbConfig as a subconfig of DiaPipelineConfig to ensure correct defaults get set
83 namespace.config = DiaPipelineConfig().apdb.value
84 try:
85 namespace.overrides.applyTo(namespace.config)
86 except Exception as e: # yes, configs really can raise anything
87 message = str(e)
88 if "diaPipe" in message:
89 message = "it looks like one of the config files uses ApPipeConfig; " \
90 "try dropping 'diaPipe.apdb'\n" + message
91 self.error(f"cannot apply config: {message}")
93 namespace.config.validate()
94 namespace.config.freeze()
96 return namespace
99def makeApdb(args=None):
100 """Create an APDB according to a config.
102 The command-line arguments should provide config values or a config file
103 for `ApdbConfig`.
105 Parameters
106 ----------
107 args : `list` [`str`], optional
108 List of command-line arguments; if `None` use `sys.argv`.
110 Returns
111 -------
112 apdb : `lsst.dax.apdb.Apdb`
113 The newly configured APDB object.
114 """
116 parser = ConfigOnlyParser()
117 parsedCmd = parser.parse_args(args=args)
119 apdb = daxApdb.make_apdb(config=parsedCmd.config)
120 apdb.makeSchema()
121 return apdb
124# --------------------------------------------------------------------
125# argparse.Actions for use with ConfigOverrides
126# ConfigOverrides is normally used with Click; there is no built-in
127# argparse support.
130class ConfigValueAction(argparse.Action):
131 """argparse action to override config parameters using
132 name=value pairs from the command-line.
133 """
135 def __call__(self, parser, namespace, values, option_string):
136 if namespace.overrides is None:
137 return
138 for nameValue in values:
139 name, sep, valueStr = nameValue.partition("=")
140 if not valueStr:
141 parser.error(f"{option_string} value {nameValue} must be in form name=value")
142 if "diaPipe.apdb" in name:
143 parser.error(f"{nameValue} looks like it uses ApPipeConfig; try dropping 'diaPipe.apdb'")
145 namespace.overrides.addValueOverride(name, valueStr)
148class ConfigFileAction(argparse.Action):
149 """argparse action to load config overrides from one or more files.
150 """
152 def __call__(self, parser, namespace, values, option_string=None):
153 if namespace.overrides is None:
154 return
155 for configfile in values:
156 namespace.overrides.addFileOverride(configfile)