Coverage for python/lsst/pipe/base/_datasetQueryConstraints.py: 50%
68 statements
« prev ^ index » next coverage.py v7.3.2, created at 2023-11-18 10:50 +0000
« prev ^ index » next coverage.py v7.3.2, created at 2023-11-18 10:50 +0000
1# This file is part of pipe_base.
2#
3# Developed for the LSST Data Management System.
4# This product includes software developed by the LSST Project
5# (http://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 software is dual licensed under the GNU General Public License and also
10# under a 3-clause BSD license. Recipients may choose which of these licenses
11# to use; please see the files gpl-3.0.txt and/or bsd_license.txt,
12# respectively. If you choose the GPL option then the following text applies
13# (but note that there is still no warranty even if you opt for BSD instead):
14#
15# This program is free software: you can redistribute it and/or modify
16# it under the terms of the GNU General Public License as published by
17# the Free Software Foundation, either version 3 of the License, or
18# (at your option) any later version.
19#
20# This program is distributed in the hope that it will be useful,
21# but WITHOUT ANY WARRANTY; without even the implied warranty of
22# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23# GNU General Public License for more details.
24#
25# You should have received a copy of the GNU General Public License
26# along with this program. If not, see <http://www.gnu.org/licenses/>.
28"""Module Defining variants for valid values used to constrain datasets in a
29graph building query.
30"""
32from __future__ import annotations
34__all__ = ("DatasetQueryConstraintVariant",)
36import warnings
37from collections.abc import Iterable, Iterator
38from typing import Protocol
40from lsst.utils.introspection import find_outside_stacklevel
43class DatasetQueryConstraintVariant(Iterable, Protocol):
44 """Base for all the valid variants for controlling
45 constraining graph building queries based on dataset type existence.
47 ALL variant corresponds to using all input dataset types to constrain
48 a query.
50 OFF variant corresponds to not using any dataset types to constrain a
51 graph building query.
53 LIST variant should be used when one or more specific names should be used
54 in constraining a graph building query.
56 Normally the ALL and OFF variants are used as as Singletons, attempting to
57 instantiate them (i.e. ALL()) will return in singleton class itself.
59 LIST is used as a constructor to the contents (i.e. List(['a', 'b'])).
60 Using the LIST variant directly as a singleton will behave the same as if
61 it were an empty instance.
63 Variants can be directly used, or automatically be selected by using the
64 `fromExpression` class method given a valid string.
65 """
67 ALL: "type[_ALL]"
68 OFF: "type[_OFF]"
69 LIST: "type[_LIST]"
71 @classmethod
72 def __subclasshook__(cls, subclass):
73 if subclass == cls.ALL or subclass == cls.OFF or subclass == cls.LIST:
74 return True
75 return False
77 @classmethod
78 def fromExpression(cls, expression: str) -> "DatasetQueryConstraintVariant":
79 """Select and return the correct Variant that corresponds to the input
80 expression.
82 Valid values are ``all`` for all inputs dataset types in pipeline,
83 ``off`` to not consider dataset type existence as a constraint, single
84 or comma-separated list of dataset type names.
85 """
86 if not isinstance(expression, str):
87 raise ValueError("Expression must be a string")
88 elif expression == "all":
89 return cls.ALL
90 elif expression == "off":
91 return cls.OFF
92 else:
93 if " " in expression:
94 warnings.warn(
95 "Whitespace found in expression will be trimmed",
96 RuntimeWarning,
97 stacklevel=find_outside_stacklevel("lsst.pipe.base"),
98 )
99 expression = expression.replace(" ", "")
100 members = expression.split(",")
101 return cls.LIST(members)
104class _ALLMETA(DatasetQueryConstraintVariant, type(Protocol)):
105 def __iter__(self) -> Iterator: # noqa: N804
106 raise NotImplementedError("This variant cannot be iterated")
109class _ALL(metaclass=_ALLMETA):
110 def __new__(cls):
111 return cls
114class _OFFMETA(DatasetQueryConstraintVariant, type(Protocol)):
115 def __iter__(self) -> Iterator: # noqa: N804
116 raise NotImplementedError("This variant cannot be iterated")
119class _OFF(metaclass=_OFFMETA):
120 def __new__(cls):
121 return cls
124class _LISTMETA(type(Protocol)):
125 def __iter__(self): # noqa: N804
126 return iter(tuple())
128 def __len__(self): # noqa: N804
129 return 0
131 def __eq__(self, o: object) -> bool: # noqa: N804
132 if isinstance(o, self):
133 return True
134 return super().__eq__(o)
137class _LIST(DatasetQueryConstraintVariant, metaclass=_LISTMETA):
138 def __init__(self, members: Iterable[str]):
139 self.members = list(members)
141 def __len__(self) -> int:
142 return len(self.members)
144 def __iter__(self) -> Iterable[str]:
145 return iter(self.members)
147 def __repr__(self) -> str:
148 return repr(self.members)
150 def __str__(self) -> str:
151 return str(self.members)
153 def __eq__(self, o: object) -> bool:
154 if isinstance(o, type(self)):
155 return self.members == o.members
156 return super().__eq__(o)
159def suppressInit(self):
160 raise NotImplementedError(
161 "DatasetQueryConstraintVariants cannot be directly instantiated. "
162 "Please use the variants or the fromExpression class method"
163 )
166DatasetQueryConstraintVariant.__init__ = suppressInit
167DatasetQueryConstraintVariant.ALL = _ALL
168DatasetQueryConstraintVariant.OFF = _OFF
169DatasetQueryConstraintVariant.LIST = _LIST