Skip to content

Commit

Permalink
Move register-instrument from obs_base
Browse files Browse the repository at this point in the history
This includes setting up of some click infrastructure
since this is the first click command in pipe_base
  • Loading branch information
timj committed Mar 21, 2022
1 parent 07b842e commit 9737322
Show file tree
Hide file tree
Showing 12 changed files with 335 additions and 0 deletions.
61 changes: 61 additions & 0 deletions python/lsst/pipe/base/_instrument.py
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,67 @@ def fromName(name: str, registry: Registry, collection_prefix: Optional[str] = N
)
return instrument_cls(collection_prefix=collection_prefix)

@staticmethod
def from_string(
name: str, registry: Optional[Registry] = None, collection_prefix: Optional[str] = None
) -> Instrument:
"""Return an instance from the short name or class name.
If the instrument name is not qualified (does not contain a '.') and a
butler registry is provided, this will attempt to load the instrument
using `Instrument.fromName()`. Otherwise the instrument will be
imported and instantiated.
Parameters
----------
name : `str`
The name or fully-qualified class name of an instrument.
registry : `lsst.daf.butler.Registry`, optional
Butler registry to query to find information about the instrument,
by default `None`.
collection_prefix : `str`, optional
Prefix for collection names to use instead of the intrument's own
name. This is primarily for use in simulated-data repositories,
where the instrument name may not be necessary and/or sufficient
to distinguish between collections.
Returns
-------
instrument : `Instrument`
The instantiated instrument.
Raises
------
RuntimeError
Raised if the instrument can not be imported, instantiated, or
obtained from the registry.
TypeError
Raised if the instrument is not a subclass of
`~lsst.pipe.base.Instrument`.
See Also
--------
Instrument.fromName()
"""
if "." not in name and registry is not None:
try:
instr = Instrument.fromName(name, registry, collection_prefix=collection_prefix)
except Exception as err:
raise RuntimeError(
f"Could not get instrument from name: {name}. Failed with exception: {err}"
) from err
else:
try:
instr_class = doImportType(name)
except Exception as err:
raise RuntimeError(
f"Could not import instrument: {name}. Failed with exception: {err}"
) from err
instr = instr_class(collection_prefix=collection_prefix)
if not isinstance(instr, Instrument):
raise TypeError(f"{name} is not an Instrument subclass.")
return instr

@staticmethod
def importAll(registry: Registry) -> None:
"""Import all the instruments known to this registry.
Expand Down
Empty file.
24 changes: 24 additions & 0 deletions python/lsst/pipe/base/cli/cmd/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# This file is part of pipe_base.
#
# Developed for the LSST Data Management System.
# This product includes software developed by the LSST Project
# (https://www.lsst.org).
# See the COPYRIGHT file at the top-level directory of this distribution
# for details of code ownership.
#
# This program 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.
#
# This program 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 this program. If not, see <https://www.gnu.org/licenses/>.

__all__ = ["register_instrument"]

from .commands import register_instrument
36 changes: 36 additions & 0 deletions python/lsst/pipe/base/cli/cmd/commands.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# This file is part of pipe_base.
#
# Developed for the LSST Data Management System.
# This product includes software developed by the LSST Project
# (http://www.lsst.org).
# See the COPYRIGHT file at the top-level directory of this distribution
# for details of code ownership.
#
# This program 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.
#
# This program 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 this program. If not, see <http://www.gnu.org/licenses/>.

import click
from lsst.daf.butler.cli.opt import repo_argument
from lsst.daf.butler.cli.utils import ButlerCommand

from ... import script
from ..opt import instrument_argument


@click.command(short_help="Add an instrument definition to the repository", cls=ButlerCommand)
@repo_argument(required=True)
@instrument_argument(required=True, nargs=-1, help="The fully-qualified name of an Instrument subclass.")
@click.option("--update", is_flag=True)
def register_instrument(*args, **kwargs):
"""Add an instrument to the data repository."""
script.register_instrument(*args, **kwargs)
23 changes: 23 additions & 0 deletions python/lsst/pipe/base/cli/opt/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# This file is part of pipe_base.
#
# Developed for the LSST Data Management System.
# This product includes software developed by the LSST Project
# (https://www.lsst.org).
# See the COPYRIGHT file at the top-level directory of this distribution
# for details of code ownership.
#
# This program 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.
#
# This program 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 this program. If not, see <http://www.gnu.org/licenses/>.

from .arguments import *
from .options import *
26 changes: 26 additions & 0 deletions python/lsst/pipe/base/cli/opt/arguments.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# This file is part of pipe_base.
#
# Developed for the LSST Data Management System.
# This product includes software developed by the LSST Project
# (http://www.lsst.org).
# See the COPYRIGHT file at the top-level directory of this distribution
# for details of code ownership.
#
# This program 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.
#
# This program 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 this program. If not, see <http://www.gnu.org/licenses/>.

from lsst.daf.butler.cli.utils import MWArgumentDecorator

instrument_argument = MWArgumentDecorator(
"instrument", help="The name or fully-qualified class name of an instrument."
)
26 changes: 26 additions & 0 deletions python/lsst/pipe/base/cli/opt/options.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# This file is part of pipe_base.
#
# Developed for the LSST Data Management System.
# This product includes software developed by the LSST Project
# (http://www.lsst.org).
# See the COPYRIGHT file at the top-level directory of this distribution
# for details of code ownership.
#
# This program 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.
#
# This program 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 this program. If not, see <http://www.gnu.org/licenses/>.

from lsst.daf.butler.cli.utils import MWOptionDecorator

instrument_option = MWOptionDecorator(
"--instrument", help="The name or fully-qualified class name of an instrument."
)
4 changes: 4 additions & 0 deletions python/lsst/pipe/base/cli/resources.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
cmd:
import: lsst.pipe.base.cli.cmd
commands:
- register-instrument
22 changes: 22 additions & 0 deletions python/lsst/pipe/base/script/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# This file is part of pipe_base.
#
# Developed for the LSST Data Management System.
# This product includes software developed by the LSST Project
# (https://www.lsst.org).
# See the COPYRIGHT file at the top-level directory of this distribution
# for details of code ownership.
#
# This program 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.
#
# This program 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 this program. If not, see <https://www.gnu.org/licenses/>.

from .register_instrument import register_instrument
55 changes: 55 additions & 0 deletions python/lsst/pipe/base/script/register_instrument.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# This file is part of pipe_base.
#
# Developed for the LSST Data Management System.
# This product includes software developed by the LSST Project
# (http://www.lsst.org).
# See the COPYRIGHT file at the top-level directory of this distribution
# for details of code ownership.
#
# This program 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.
#
# This program 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 this program. If not, see <http://www.gnu.org/licenses/>.

__all__ = ["register_instrument"]

from typing import List

from lsst.daf.butler import Butler
from lsst.pipe.base import Instrument


def register_instrument(repo: str, instrument: List[str], update: bool = False) -> None:
"""Add an instrument to the data repository.
Parameters
----------
repo : `str`
URI to the location to create the repo.
instrument : `list` [`str`]
The fully-qualified name of an `~lsst.pipe.base.Instrument` subclass.
update : `bool`, optional
If `True` (`False` is default), update the existing instrument and
detector records if they differ from the new ones.
Raises
------
RuntimeError
Raised if the instrument can not be imported, instantiated, or obtained
from the registry.
TypeError
Raised iff the instrument is not a subclass of
`lsst.pipe.base.Instrument`.
"""
butler = Butler(repo, writeable=True)
for string in instrument:
instrument_instance = Instrument.from_string(string, butler.registry)
instrument_instance.register(butler.registry, update=update)
57 changes: 57 additions & 0 deletions tests/test_cliCmdRegisterInstrument.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# This file is part of pipe_base.
#
# Developed for the LSST Data Management System.
# This product includes software developed by the LSST Project
# (http://www.lsst.org).
# See the COPYRIGHT file at the top-level directory of this distribution
# for details of code ownership.
#
# This program 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.
#
# This program 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 this program. If not, see <http://www.gnu.org/licenses/>.

"""Unit tests for daf_butler CLI register-instrument command.
"""

import unittest

from lsst.daf.butler.tests import CliCmdTestBase
from lsst.pipe.base.cli.cmd import register_instrument


class RegisterInstrumentTest(CliCmdTestBase, unittest.TestCase):

mockFuncName = "lsst.pipe.base.cli.cmd.commands.script.register_instrument"

@staticmethod
def defaultExpected():
return dict()

@staticmethod
def command():
return register_instrument

def test_repoBasic(self):
"""Test the most basic required arguments."""
self.run_test(
["register-instrument", "here", "a.b.c"],
self.makeExpected(repo="here", instrument=("a.b.c",), update=False),
)

def test_missing(self):
"""test a missing argument"""
self.run_missing(["register-instrument"], "Missing argument ['\"]REPO['\"]")
self.run_missing(["register-instrument", "here"], "Missing argument ['\"]INSTRUMENT ...['\"]")


if __name__ == "__main__":
unittest.main()
1 change: 1 addition & 0 deletions ups/pipe_base.table
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@ setupRequired(resources)

envPrepend(PYTHONPATH, ${PRODUCT_DIR}/python)
envPrepend(MYPYPATH, ${PRODUCT_DIR}/python)
envPrepend(DAF_BUTLER_PLUGINS, ${PRODUCT_DIR}/python/lsst/pipe/base/cli/resources.yaml)

0 comments on commit 9737322

Please sign in to comment.