Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

# This file is part of verify. 

# 

# 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__ = ['MetadataQuery'] 

 

from .jsonmixin import JsonSerializationMixin 

 

 

class MetadataQuery(JsonSerializationMixin): 

"""Query of `lsst.verify.Job.meta` metadata. 

 

Parameters 

---------- 

terms : `dict`, optional 

A mapping of key-value query terms. In the default query mode, the 

user-provided job metadata must have all these terms, and matching 

values, to pass the query. 

 

Examples 

-------- 

A MetadataQuery returns `True` if all key-value terms found in 

`MetadataQuery.terms` are equal to key-value metadata items. 

 

>>> metadata = {'filter': 'r', 'camera': 'MegaCam'} 

 

An example of a query with a conflicting term: 

 

>>> query1 = MetadataQuery({'filter': 'r', 'camera': 'SDSS'}) 

>>> query1(metadata) 

False 

 

A query with matching terms (albeit, a subset of the metadata): 

 

>>> query2 = MetadataQuery({'filter': 'r'}) 

>>> query2(metadata) 

True 

 

A query that overconstrains the available metadata: 

 

>>> query3 = MetadataQuery({'filter': 'r', 'camera': 'MegaCam', 

... 'photometric': True}) 

>>> query3(metadata) 

False 

 

The ``arg_driven=True`` mode reverses the matching logic so that all terms 

in the user-provided metadata must be in the MetadataQuery: 

 

>>> query3(metadata, arg_driven=True) 

True 

>>> query2(metadata, arg_driven=True) 

False 

""" 

 

terms = None 

"""Term mapping (`dict`). Metadata must have all keys and corresponding 

values. 

""" 

 

def __init__(self, terms=None): 

self.terms = terms or dict() 

 

def __call__(self, metadata, arg_driven=False): 

"""Determine if a metadata set matches the query terms. 

 

Parameters 

---------- 

metadata : `dict` or `lsst.verify.Metadata` 

Metadata mapping. Typically this is a job's 

`lsst.verify.Job.meta`. 

 

arg_driven : `bool`, optional 

If `False` (default), ``metadata`` matches the ``MetadataQuery`` 

if ``metadata`` has all the terms defined in ``MetadataQuery``, 

and those terms match. If ``metadata`` has more terms than 

``MetadataQuery``, it can still match. 

 

If `True`, the orientation of the matching is reversed. Now 

``metadata`` matches the ``MetadataQuery`` if ``MetadataQuery`` 

has all the terms defined in ``metadata`` and those terms match. 

If ``MetadataQuery`` has more terms than ``metadata``, it can 

still match. 

 

Returns 

------- 

match : `bool` 

`True` if the metadata matches the query terms; `False` otherwise. 

""" 

if arg_driven: 

# Match if self.terms has all the terms defined in metadata 

for arg_term, arg_term_value in metadata.items(): 

if arg_term not in self.terms: 

return False 

 

# If metadata can be floats, may need to do more sophisticated 

# comparison 

if arg_term_value != self.terms[arg_term]: 

return False 

else: 

# Match if metadata has all the terms defined in this MetadataQuery 

for term_key, term_value in self.terms.items(): 

if term_key not in metadata: 

return False 

 

# If metadata can be floats, may need to do more sophisticated 

# comparison 

if term_value != metadata[term_key]: 

return False 

 

return True 

 

def __eq__(self, other): 

return self.terms == other.terms 

 

def __str__(self): 

return str(self.terms) 

 

def __repr__(self): 

template = 'MetadataQuery({0!r})' 

return template.format(self.terms) 

 

@property 

def json(self): 

"""A JSON-serializable dict. 

 

Keys are metadata keys. Values are the associated metadata values 

of the query term. 

""" 

return self.jsonify_dict(self.terms)