| Conditions | 20 | 
| Total Lines | 92 | 
| Lines | 0 | 
| Ratio | 0 % | 
| Changes | 5 | ||
| Bugs | 0 | Features | 0 | 
Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.
For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.
Commonly applied refactorings include:
If many parameters/temporary variables are present:
Complex classes like Analyzer.fetch_data() often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
| 1 | # | ||
| 158 | def fetch_data(self, filter=None, sort=None, default_output=None): | ||
| 159 | """Fetches the requested properties from self.extract_fields() | ||
| 160 | |||
| 161 | :param list filter: The filter list from args.filter (can be None if we don't need the filter function) | ||
| 162 | :param string sort: The sort item for the sort function (this is a property - can be None if we don't | ||
| 163 | want to use the sort function) | ||
| 164 | :return dict: a dictionary with all properties and their values | ||
| 165 | """ | ||
| 166 | |||
| 167 | data = dict() | ||
| 168 | |||
| 169 | if not filter: | ||
| 170 | self.filters_matched = True | ||
| 171 | |||
| 172 | if self.fields: | ||
| 173 | # build the xpath for selecting all needed properties | ||
| 174 | xpath = "*[self::dm:" + " or self::dm:".join(self.fields) | ||
| 175 | if sort is None: | ||
| 176 | xpath += "]" | ||
| 177 | else: | ||
| 178 | # when the args.sort is set, we can append that string to our | ||
| 179 | # xpath. that's needed if we want to display 'maintainer' but | ||
| 180 | # sort | ||
| 181 | xpath += " or self::dm:" + sort + "]" | ||
| 182 | self.fields.add(sort) | ||
| 183 | |||
| 184 | # if there are invalid characters in the xpath, lxml throws an exception. | ||
| 185 | # We have to catch that. | ||
| 186 | try: | ||
| 187 |                 data = { localname(e.tag): e.text  for e in self.xmlhandler.dm.xpath(xpath, namespaces=NS) } | ||
| 188 | except etree.XPathEvalError: | ||
| 189 |                 log.error("The given XML properties in --sort/-s or --queryformat/-qf are invalid.") | ||
| 190 | sys.exit(ReturnCodes.E_INVALID_XML_PROPERTIES) | ||
| 191 | |||
| 192 | # loop over all 'properties' and fetch their values from the XML file. properties | ||
| 193 | # without values will become an empty string if the 'default-option' was not set | ||
| 194 | for f in self.fields: | ||
| 195 | data.setdefault(f, data.get(f, None)) | ||
| 196 | |||
| 197 | if not data[f]: | ||
| 198 | if not default_output: | ||
| 199 | data[f] = '' | ||
| 200 | else: | ||
| 201 | data[f] = default_output | ||
| 202 | |||
| 203 | if filter: | ||
| 204 | filters = dict() | ||
| 205 | filters_xpath = "" | ||
| 206 | |||
| 207 | for idx, f in enumerate(filter): | ||
| 208 | try: | ||
| 209 | # validate the filter syntax of any given filter | ||
| 210 | mode, prop, condition = self.validate_filter(f) | ||
| 211 | |||
| 212 | # save the details about a filter in a dictionary | ||
| 213 | filters[prop] = dict() | ||
| 214 | filters[prop]['mode'] = mode | ||
| 215 | filters[prop]['condition'] = condition | ||
| 216 | |||
| 217 | if idx == 0: | ||
| 218 | filters_xpath += "self::dm:" + prop | ||
| 219 | else: | ||
| 220 | filters_xpath += " or self::dm:" + prop | ||
| 221 | except DMAnalyzeInvalidFilterSyntax: | ||
| 222 | # syntax is wrong | ||
| 223 |                     log.error("Invalid syntax in filter: '{}'".format(f)) | ||
| 224 |                     log.error("Look into the manual page for more information about using filters.") | ||
| 225 | sys.exit(ReturnCodes.E_ANALYZE_FILTER_INVALID_SYNTAX) | ||
| 226 | |||
| 227 | # catch the values of the filter properties | ||
| 228 |             f_xpath = { localname(e.tag): e.text  for e in self.xmlhandler.dm.xpath("*[{}]".format(filters_xpath), namespaces=NS) } | ||
| 229 | |||
| 230 | for f in filters: | ||
| 231 | # if the filter property was not found in the XML file -> the filter didn't | ||
| 232 | # not match and we have to return an empty dictionary | ||
| 233 | if f not in f_xpath: | ||
| 234 | self.filters_matched = False | ||
| 235 |                     return {} | ||
| 236 | |||
| 237 | # f_xpath[f] = '' | ||
| 238 | |||
| 239 | # condition checks | ||
| 240 | if filters[f]['mode'] == '+': | ||
| 241 | if f_xpath[f] != filters[f]['condition']: | ||
| 242 | self.filters_matched = False | ||
| 243 |                         return {} | ||
| 244 | elif filters[f]['mode'] == '-': | ||
| 245 | if f_xpath[f] == filters[f]['condition']: | ||
| 246 | self.filters_matched = False | ||
| 247 |                         return {} | ||
| 248 | |||
| 249 | return data | ||
| 250 | |||
| 287 |