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 |