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