Coverage for python/lsst/pipe/base/_datasetQueryConstraints.py: 47%
67 statements
« prev ^ index » next coverage.py v7.2.7, created at 2023-07-12 11:14 -0700
« prev ^ index » next coverage.py v7.2.7, created at 2023-07-12 11:14 -0700
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 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 <http://www.gnu.org/licenses/>.
22"""Module Defining variants for valid values used to constrain datasets in a
23graph building query.
24"""
26from __future__ import annotations
28__all__ = ("DatasetQueryConstraintVariant",)
30import warnings
31from collections.abc import Iterable, Iterator
32from typing import Protocol
35class DatasetQueryConstraintVariant(Iterable, Protocol):
36 """Base for all the valid variants for controlling
37 constraining graph building queries based on dataset type existence.
39 ALL variant corresponds to using all input dataset types to constrain
40 a query.
42 OFF variant corresponds to not using any dataset types to constrain a
43 graph building query.
45 LIST variant should be used when one or more specific names should be used
46 in constraining a graph building query.
48 Normally the ALL and OFF variants are used as as Singletons, attempting to
49 instantiate them (i.e. ALL()) will return in singleton class itself.
51 LIST is used as a constructor to the contents (i.e. List(['a', 'b'])).
52 Using the LIST variant directly as a singleton will behave the same as if
53 it were an empty instance.
55 Variants can be directly used, or automatically be selected by using the
56 `fromExpression` class method given a valid string.
57 """
59 ALL: "type[_ALL]"
60 OFF: "type[_OFF]"
61 LIST: "type[_LIST]"
63 @classmethod
64 def __subclasshook__(cls, subclass):
65 if subclass == cls.ALL or subclass == cls.OFF or subclass == cls.LIST:
66 return True
67 return False
69 @classmethod
70 def fromExpression(cls, expression: str) -> "DatasetQueryConstraintVariant":
71 """Select and return the correct Variant that corresponds to the input
72 expression.
74 Valid values are ``all`` for all inputs dataset types in pipeline,
75 ``off`` to not consider dataset type existence as a constraint, single
76 or comma-separated list of dataset type names.
77 """
78 if not isinstance(expression, str):
79 raise ValueError("Expression must be a string")
80 elif expression == "all":
81 return cls.ALL
82 elif expression == "off":
83 return cls.OFF
84 else:
85 if " " in expression:
86 warnings.warn("Whitespace found in expression will be trimmed", RuntimeWarning)
87 expression = expression.replace(" ", "")
88 members = expression.split(",")
89 return cls.LIST(members)
92class _ALLMETA(DatasetQueryConstraintVariant, type(Protocol)):
93 def __iter__(self) -> Iterator: # noqa: N804
94 raise NotImplementedError("This variant cannot be iterated")
97class _ALL(metaclass=_ALLMETA):
98 def __new__(cls):
99 return cls
102class _OFFMETA(DatasetQueryConstraintVariant, type(Protocol)):
103 def __iter__(self) -> Iterator: # noqa: N804
104 raise NotImplementedError("This variant cannot be iterated")
107class _OFF(metaclass=_OFFMETA):
108 def __new__(cls):
109 return cls
112class _LISTMETA(type(Protocol)):
113 def __iter__(self): # noqa: N804
114 return iter(tuple())
116 def __len__(self): # noqa: N804
117 return 0
119 def __eq__(self, o: object) -> bool: # noqa: N804
120 if isinstance(o, self):
121 return True
122 return super().__eq__(o)
125class _LIST(DatasetQueryConstraintVariant, metaclass=_LISTMETA):
126 def __init__(self, members: Iterable[str]):
127 self.members = list(members)
129 def __len__(self) -> int:
130 return len(self.members)
132 def __iter__(self) -> Iterable[str]:
133 return iter(self.members)
135 def __repr__(self) -> str:
136 return repr(self.members)
138 def __str__(self) -> str:
139 return str(self.members)
141 def __eq__(self, o: object) -> bool:
142 if isinstance(o, type(self)):
143 return self.members == o.members
144 return super().__eq__(o)
147def suppressInit(self):
148 raise NotImplementedError(
149 "DatasetQueryConstraintVariants cannot be directly instantiated. "
150 "Please use the variants or the fromExpression class method"
151 )
154DatasetQueryConstraintVariant.__init__ = suppressInit
155DatasetQueryConstraintVariant.ALL = _ALL
156DatasetQueryConstraintVariant.OFF = _OFF
157DatasetQueryConstraintVariant.LIST = _LIST