Coverage for python/lsst/daf/butler/cli/opt/options.py: 84%

Shortcuts 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

36 statements  

1# This file is part of daf_butler. 

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/>. 

21 

22 

23import click 

24from functools import partial 

25 

26from ..utils import MWOptionDecorator, MWPath, split_commas, split_kv, unwrap, yaml_presets 

27from lsst.daf.butler.registry import CollectionType 

28 

29 

30class CollectionTypeCallback: 

31 

32 collectionTypes = tuple(collectionType.name for collectionType in CollectionType.all()) 

33 

34 @staticmethod 

35 def makeCollectionTypes(context, param, value): 

36 if not value: 

37 # Click seems to demand that the default be an empty tuple, rather 

38 # than a sentinal like None. The behavior that we want is that 

39 # not passing this option at all passes all collection types, while 

40 # passing it uses only the passed collection types. That works 

41 # fine for now, since there's no command-line option to subtract 

42 # collection types, and hence the only way to get an empty tuple 

43 # is as the default. 

44 return tuple(CollectionType.all()) 

45 

46 return tuple(CollectionType.from_name(item) for item in split_commas(context, param, value)) 

47 

48 

49collection_type_option = MWOptionDecorator("--collection-type", 

50 callback=CollectionTypeCallback.makeCollectionTypes, 

51 multiple=True, 

52 help="If provided, only list collections of this type.", 

53 type=click.Choice(CollectionTypeCallback.collectionTypes, 

54 case_sensitive=False)) 

55 

56 

57collections_option = MWOptionDecorator("--collections", 

58 help=unwrap("""One or more expressions that fully or partially identify 

59 the collections to search for datasets. If not provided all 

60 datasets are returned."""), 

61 multiple=True, 

62 callback=split_commas) 

63 

64 

65components_option = MWOptionDecorator("--components/--no-components", 

66 default=None, 

67 help=unwrap("""For --components, apply all expression patterns to 

68 component dataset type names as well. For --no-components, 

69 never apply patterns to components. Default (where neither 

70 is specified) is to apply patterns to components only if 

71 their parent datasets were not matched by the expression. 

72 Fully-specified component datasets (`str` or `DatasetType` 

73 instances) are always included.""")) 

74 

75 

76config_option = MWOptionDecorator("-c", "--config", 

77 callback=split_kv, 

78 help="Config override, as a key-value pair.", 

79 metavar="TEXT=TEXT", 

80 multiple=True) 

81 

82 

83config_file_option = MWOptionDecorator("-C", "--config-file", 

84 help=unwrap("""Path to a pex config override to be included after the 

85 Instrument config overrides are applied.""")) 

86 

87 

88confirm_option = MWOptionDecorator( 

89 "--confirm/--no-confirm", 

90 default=True, 

91 help="Print expected action and a confirmation prompt before executing. Default is --confirm." 

92) 

93 

94 

95dataset_type_option = MWOptionDecorator("-d", "--dataset-type", 

96 callback=split_commas, 

97 help="Specific DatasetType(s) to validate.", 

98 multiple=True) 

99 

100 

101datasets_option = MWOptionDecorator("--datasets") 

102 

103 

104logLevelChoices = ["CRITICAL", "ERROR", "WARNING", "INFO", "VERBOSE", "DEBUG"] 

105log_level_option = MWOptionDecorator("--log-level", 

106 callback=partial(split_kv, 

107 choice=click.Choice(logLevelChoices, 

108 case_sensitive=False), 

109 normalize=True, 

110 unseparated_okay=True, 

111 add_to_default=True), 

112 help="The logging level. " 

113 f"Supported levels are [{'|'.join(logLevelChoices)}]", 

114 is_eager=True, 

115 metavar="LEVEL|COMPONENT=LEVEL", 

116 multiple=True) 

117 

118 

119long_log_option = MWOptionDecorator("--long-log", 

120 help="Make log messages appear in long format.", 

121 is_flag=True) 

122 

123log_file_option = MWOptionDecorator("--log-file", 

124 default=None, 

125 multiple=True, 

126 callback=split_commas, 

127 type=MWPath(file_okay=True, dir_okay=False, writable=True), 

128 help="File(s) to write log messages. If the path ends with '.json' then" 

129 " JSON log records will be written, else formatted text log records" 

130 " will be written. This file can exist and records will be appended.") 

131 

132log_label_option = MWOptionDecorator("--log-label", 

133 default=None, 

134 multiple=True, 

135 callback=split_kv, 

136 type=str, 

137 help="Keyword=value pairs to add to MDC of log records.") 

138 

139log_tty_option = MWOptionDecorator("--log-tty/--no-log-tty", 

140 default=True, 

141 help="Log to terminal (default). If false logging to terminal is" 

142 " disabled.") 

143 

144options_file_option = MWOptionDecorator("--options-file", "-@", 

145 expose_value=False, # This option should not be forwarded 

146 help=unwrap("""URI to YAML file containing overrides 

147 of command line options. The YAML should be organized 

148 as a hierarchy with subcommand names at the top 

149 level options for that subcommand below."""), 

150 callback=yaml_presets) 

151 

152 

153processes_option = MWOptionDecorator("-j", "--processes", 

154 default=1, 

155 help="Number of processes to use.", 

156 type=click.IntRange(min=1)) 

157 

158 

159regex_option = MWOptionDecorator("--regex") 

160 

161 

162register_dataset_types_option = MWOptionDecorator("--register-dataset-types", 

163 help=unwrap("""Register DatasetTypes that do not already 

164 exist in the Registry."""), 

165 is_flag=True) 

166 

167run_option = MWOptionDecorator("--output-run", 

168 help="The name of the run datasets should be output to.") 

169 

170 

171transfer_option = MWOptionDecorator("-t", "--transfer", 

172 default="auto", # set to `None` if using `required=True` 

173 help="The external data transfer mode.", 

174 type=click.Choice(["auto", "link", "symlink", "hardlink", "copy", "move", 

175 "relsymlink", "direct"], 

176 case_sensitive=False)) 

177 

178 

179verbose_option = MWOptionDecorator("-v", "--verbose", 

180 help="Increase verbosity.", 

181 is_flag=True) 

182 

183 

184where_option = MWOptionDecorator("--where", 

185 help="A string expression similar to a SQL WHERE clause.") 

186 

187 

188order_by_option = MWOptionDecorator( 

189 "--order-by", 

190 help=unwrap("""One or more comma-separated names used to order records. Names can be dimension names, 

191 metadata names optionally prefixed by a dimension name and dot, or 

192 timestamp_begin/timestamp_end (with optional dimension name). To reverse ordering for a name 

193 prefix it with a minus sign."""), 

194 multiple=True, 

195 callback=split_commas 

196) 

197 

198 

199limit_option = MWOptionDecorator( 

200 "--limit", 

201 help=unwrap("Limit the number of records, by default all records are shown."), 

202 type=int, 

203 default=0 

204) 

205 

206offset_option = MWOptionDecorator( 

207 "--offset", 

208 help=unwrap("Skip initial number of records, only used when --limit is specified."), 

209 type=int, 

210 default=0 

211)